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 * To Do: 18 * Elimate all mDNSPlatformMemAllocate/mDNSPlatformMemFree from this code -- the core code 19 * is supposed to be malloc-free so that it runs in constant memory determined at compile-time. 20 * Any dynamic run-time requirements should be handled by the platform layer below or client layer above 21 22 Change History (most recent first): 23 24 Log: uDNS.c,v $ 25 Revision 1.617 2009/06/30 20:51:02 cheshire 26 Improved "Error! Tried to add a NAT traversal that's already in the active list" debugging message 27 28 Revision 1.616 2009/05/27 20:29:36 cheshire 29 <rdar://problem/6926465> Sleep is delayed by 10 seconds if BTMM is on 30 After receiving confirmation of LLQ deletion, need to schedule another evaluation of whether we're ready to sleep yet 31 32 Revision 1.615 2009/05/05 01:32:50 jessic2 33 <rdar://problem/6830541> regservice_callback: instance->request is NULL 0 -- Clean up spurious logs resulting from fixing this bug. 34 35 Revision 1.614 2009/04/24 02:17:57 mcguire 36 <rdar://problem/5264124> uDNS: Not always respecting preference order of DNS servers 37 38 Revision 1.613 2009/04/23 22:06:29 cheshire 39 Added CacheRecord and InterfaceID parameters to MakeNegativeCacheRecord, in preparation for: 40 <rdar://problem/3476350> Return negative answers when host knows authoritatively that no answer exists 41 42 Revision 1.612 2009/04/22 01:19:57 jessic2 43 <rdar://problem/6814585> Daemon: mDNSResponder is logging garbage for error codes because it's using %ld for int 32 44 45 Revision 1.611 2009/04/15 20:42:51 mcguire 46 <rdar://problem/6768947> uDNS: Treat RCODE 5 (Refused) responses as failures 47 48 Revision 1.610 2009/04/15 01:10:39 jessic2 49 <rdar://problem/6466541> BTMM: Add support for setting kDNSServiceErr_NoSuchRecord in DynamicStore 50 51 Revision 1.609 2009/04/11 00:19:45 jessic2 52 <rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically 53 54 Revision 1.608 2009/04/06 23:44:59 cheshire 55 <rdar://problem/6757838> mDNSResponder thrashing kernel lock in the UDP close path, hurting SPECweb performance 56 57 Revision 1.607 2009/04/02 22:36:34 jessic2 58 Fix crash when calling debugf with null opt 59 60 Revision 1.606 2009/03/26 03:59:00 jessic2 61 Changes for <rdar://problem/6492552&6492593&6492609&6492613&6492628&6492640&6492699> 62 63 Revision 1.605 2009/03/04 00:40:14 cheshire 64 Updated DNS server error codes to be more consistent with definitions at 65 <http://www.iana.org/assignments/dns-parameters> 66 67 Revision 1.604 2009/02/27 03:08:47 cheshire 68 <rdar://problem/6547720> Crash while shutting down when "local" is in the user's DNS searchlist 69 70 Revision 1.603 2009/02/27 02:56:57 cheshire 71 Moved struct SearchListElem definition from uDNS.c into mDNSEmbeddedAPI.h 72 73 Revision 1.602 2009/02/13 06:29:54 cheshire 74 Converted LogOperation messages to LogInfo 75 76 Revision 1.601 2009/02/12 20:57:25 cheshire 77 Renamed 'LogAllOperation' switch to 'LogClientOperations'; added new 'LogSleepProxyActions' switch 78 79 Revision 1.600 2009/01/31 21:05:12 cheshire 80 Improved "Failed to obtain NAT port mapping" debugging log message 81 82 Revision 1.599 2009/01/23 00:38:36 mcguire 83 <rdar://problem/5570906> BTMM: Doesn't work with Linksys WRT54GS firmware 4.71.1 84 85 Revision 1.598 2009/01/21 03:43:57 mcguire 86 <rdar://problem/6511765> BTMM: Add support for setting kDNSServiceErr_NATPortMappingDisabled in DynamicStore 87 88 Revision 1.597 2009/01/10 01:55:49 cheshire 89 Added LogOperation message showing when domains are added and removed in FoundDomain 90 91 Revision 1.596 2008/12/19 20:23:33 mcguire 92 <rdar://problem/6459269> Lots of duplicate log messages about failure to bind to NAT-PMP Announcement port 93 94 Revision 1.595 2008/12/18 23:32:19 mcguire 95 <rdar://problem/6019470> BTMM: Include the question in the LLQ notification acknowledgment 96 97 Revision 1.594 2008/12/10 02:25:31 cheshire 98 Minor fixes to use of LogClientOperations symbol 99 100 Revision 1.593 2008/12/10 02:11:42 cheshire 101 ARMv5 compiler doesn't like uncommented stuff after #endif 102 103 Revision 1.592 2008/12/06 01:42:55 mcguire 104 <rdar://problem/6418958> Need to exponentially back-off after failure to get public address 105 106 Revision 1.591 2008/12/06 00:17:11 cheshire 107 <rdar://problem/6380477> mDNS_StopNATOperation doesn't handle duplicate NAT mapping requests properly 108 Refinement: For duplicate ssh mappings we want to suppress the syslog warning message, but not the "unmap = mDNSfalse" 109 110 Revision 1.590 2008/12/04 20:57:36 mcguire 111 fix build 112 113 Revision 1.589 2008/12/04 02:24:09 cheshire 114 Improved NAT-PMP debugging messages 115 116 Revision 1.588 2008/11/26 20:38:08 cheshire 117 Changed some "LogOperation" debugging messages to "debugf" 118 119 Revision 1.587 2008/11/26 19:53:26 cheshire 120 Don't overwrite srs->NATinfo.IntPort in StartSRVNatMap() 121 122 Revision 1.586 2008/11/25 23:43:07 cheshire 123 <rdar://problem/5745355> Crashes at ServiceRegistrationGotZoneData + 397 124 Made code more defensive to guard against ServiceRegistrationGotZoneData being called with invalid ServiceRecordSet object 125 126 Revision 1.585 2008/11/25 22:46:30 cheshire 127 For ease of code searching, renamed ZoneData field of ServiceRecordSet_struct from "nta" to "srs_nta" 128 129 Revision 1.584 2008/11/24 19:46:40 cheshire 130 When sending query over TCP, don't include LLQ option when we're talking to a conventional DNS server or cache 131 132 Revision 1.583 2008/11/21 00:34:58 cheshire 133 <rdar://problem/6380477> mDNS_StopNATOperation doesn't handle duplicate NAT mapping requests properly 134 135 Revision 1.582 2008/11/20 02:23:37 mcguire 136 <rdar://problem/6041208> need to handle URLBase 137 138 Revision 1.581 2008/11/20 01:51:19 cheshire 139 Exported RecreateNATMappings so it's callable from other files 140 141 Revision 1.580 2008/11/13 19:08:45 cheshire 142 Fixed code to handle rdataOPT properly 143 144 Revision 1.579 2008/11/07 00:18:01 mcguire 145 <rdar://problem/6351068> uDNS: Supress reverse DNS query until required 146 147 Revision 1.578 2008/11/04 22:21:46 cheshire 148 Changed zone field of AuthRecord_struct from domainname to pointer, saving 252 bytes per AuthRecord 149 150 Revision 1.577 2008/10/29 21:37:01 cheshire 151 Removed some old debugging messages 152 153 Revision 1.576 2008/10/23 22:25:57 cheshire 154 Renamed field "id" to more descriptive "updateid" 155 156 Revision 1.575 2008/10/20 02:07:49 mkrochma 157 <rdar://problem/6296804> Remove Note: DNS Server <ip> for domain <d> registered more than once 158 159 Revision 1.574 2008/10/14 19:06:45 cheshire 160 In uDNS_ReceiveMsg(), only do checkUpdateResult() for uDNS records 161 162 Revision 1.573 2008/09/25 20:43:44 cheshire 163 <rdar://problem/6245044> Stop using separate m->ServiceRegistrations list 164 In UpdateSRVRecords, call mDNS_SetFQDN(m) to update AutoTarget SRV records on the main m->ResourceRecords list 165 166 Revision 1.572 2008/09/24 23:48:05 cheshire 167 Don't need to pass whole ServiceRecordSet reference to GetServiceTarget; 168 it only needs to access the embedded SRV member of the set 169 170 Revision 1.571 2008/09/23 22:56:53 cheshire 171 <rdar://problem/5298845> Remove dnsbugtest query 172 173 Revision 1.570 2008/09/23 01:30:18 cheshire 174 The putLLQ() routine was not setting the OPT record's rrclass to NormalMaxDNSMessageData 175 176 Revision 1.569 2008/07/25 22:34:11 mcguire 177 fix sizecheck issues for 64bit 178 179 Revision 1.568 2008/07/24 20:23:03 cheshire 180 <rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning 181 182 Revision 1.567 2008/07/01 01:40:00 mcguire 183 <rdar://problem/5823010> 64-bit fixes 184 185 Revision 1.566 2008/06/26 17:24:11 mkrochma 186 <rdar://problem/5450912> BTMM: Stop listening on UDP 5351 for NAT Status Announcements 187 188 Revision 1.565 2008/06/21 19:06:58 mcguire 189 <rdar://problem/4206534> Use all configured DNS servers 190 191 Revision 1.564 2008/06/19 23:42:03 mcguire 192 <rdar://problem/4206534> Use all configured DNS servers 193 194 Revision 1.563 2008/06/19 17:46:14 mcguire 195 <rdar://problem/4206534> Use all configured DNS servers 196 Don't do extra work for log messages if we're not going to log 197 198 Revision 1.562 2008/06/19 17:35:19 mcguire 199 <rdar://problem/4206534> Use all configured DNS servers 200 cleanup log messages 201 check for null pointers 202 203 Revision 1.561 2008/06/19 01:20:49 mcguire 204 <rdar://problem/4206534> Use all configured DNS servers 205 206 Revision 1.560 2008/05/31 01:51:09 mcguire 207 fixed typo in log message 208 209 Revision 1.559 2008/04/15 22:37:58 mkrochma 210 Change LogMsg to LogOperation 211 212 Revision 1.558 2008/03/17 18:02:35 mkrochma 213 Add space to log message for consistency 214 215 Revision 1.557 2008/03/14 19:58:38 mcguire 216 <rdar://problem/5500969> BTMM: Need ability to identify version of mDNSResponder client 217 Make sure we add the record when sending LLQ refreshes 218 219 Revision 1.556 2008/03/07 23:55:05 cheshire 220 <rdar://problem/5787898> LLQ refresh randomization not working properly 221 222 Revision 1.555 2008/03/07 23:25:56 cheshire 223 Improved debugging messages 224 225 Revision 1.554 2008/03/07 18:56:03 cheshire 226 <rdar://problem/5777647> dnsbugtest query every three seconds when source IP address of response doesn't match 227 228 Revision 1.553 2008/03/06 02:48:34 mcguire 229 <rdar://problem/5321824> write status to the DS 230 231 Revision 1.552 2008/03/05 01:56:42 cheshire 232 <rdar://problem/5687667> BTMM: Don't fallback to unencrypted operations when SRV lookup fails 233 234 Revision 1.551 2008/03/01 01:43:04 cheshire 235 <rdar://problem/5631565> BTMM: Lots of "Error getting external address 3" when double-NATed prevents sleep 236 Added code to suppress logging of multiple identical error results 237 238 Revision 1.550 2008/03/01 01:34:47 cheshire 239 <rdar://problem/5736313> BTMM: Double-NAT'd machines register all but AutoTunnel v4 address records 240 Further refinements 241 242 Revision 1.549 2008/02/29 01:35:37 mcguire 243 <rdar://problem/5736313> BTMM: Double-NAT'd machines register all but AutoTunnel v4 address records 244 245 Revision 1.548 2008/02/20 23:54:18 cheshire 246 <rdar://problem/5661518> "Failed to obtain NAT port mapping" syslog messages 247 Improved log message so it tells us more about what's going on 248 249 Revision 1.547 2008/02/20 00:41:09 cheshire 250 Change "PrivateQueryGotZoneData ... invoked with error code" from LogMsg to LogOperation 251 252 Revision 1.546 2008/02/19 23:26:50 cheshire 253 <rdar://problem/5661661> BTMM: Too many members.mac.com SOA queries 254 255 Revision 1.545 2007/12/22 02:25:29 cheshire 256 <rdar://problem/5661128> Records and Services sometimes not re-registering on wake from sleep 257 258 Revision 1.544 2007/12/18 00:40:11 cheshire 259 <rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown 260 Reordered code to avoid double-TSIGs in some cases 261 262 Revision 1.543 2007/12/17 23:57:43 cheshire 263 <rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown 264 Need to include TSIG signature when sending LLQ cancellations over TLS 265 266 Revision 1.542 2007/12/15 01:12:27 cheshire 267 <rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown 268 269 Revision 1.541 2007/12/15 00:18:51 cheshire 270 Renamed question->origLease to question->ReqLease 271 272 Revision 1.540 2007/12/14 23:55:28 cheshire 273 Moved "struct tcpInfo_t" definition from uDNS.c to mDNSEmbeddedAPI.h 274 275 Revision 1.539 2007/12/14 20:44:24 cheshire 276 <rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep 277 SleepRecordRegistrations/WakeRecordRegistrations should only operate on uDNS records 278 279 Revision 1.538 2007/12/14 01:13:40 cheshire 280 <rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep 281 Additional fixes (existing code to deregister private records and services didn't work at all) 282 283 Revision 1.537 2007/12/11 00:18:25 cheshire 284 <rdar://problem/5569316> BTMM: My iMac has a "ghost" ID associated with it 285 There were cases where the code was incorrectly clearing the "uselease" flag, and never resetting it. 286 287 Revision 1.536 2007/12/10 23:07:00 cheshire 288 Removed some unnecessary log messages 289 290 Revision 1.535 2007/12/06 00:22:27 mcguire 291 <rdar://problem/5604567> BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp) 292 293 Revision 1.534 2007/12/04 00:49:37 cheshire 294 <rdar://problem/5607082> BTMM: mDNSResponder taking 100 percent CPU after upgrading to 10.5.1 295 296 Revision 1.533 2007/12/01 01:21:27 jgraessley 297 <rdar://problem/5623140> mDNSResponder unicast DNS improvements 298 299 Revision 1.532 2007/11/30 20:16:44 cheshire 300 Fixed compile warning: declaration of 'end' shadows a previous local 301 302 Revision 1.531 2007/11/28 22:00:09 cheshire 303 In StartSRVNatMap, change "mDNSu8 *p" to "const mDNSu8 *p" 304 305 Revision 1.530 2007/11/16 22:19:40 cheshire 306 <rdar://problem/5547474> mDNSResponder leaks on network changes 307 The "connection failed" code path in MakeTCPConn was not disposing of the TCPSocket it had created 308 309 Revision 1.529 2007/11/15 22:52:29 cheshire 310 <rdar://problem/5589039> ERROR: mDNSPlatformWriteTCP - send Broken pipe 311 312 Revision 1.528 2007/11/02 21:32:30 cheshire 313 <rdar://problem/5575593> BTMM: Deferring deregistration of record log messages on sleep/wake 314 315 Revision 1.527 2007/11/01 16:08:51 cheshire 316 Tidy up alignment of "SetRecordRetry refresh" log messages 317 318 Revision 1.526 2007/10/31 19:26:55 cheshire 319 Don't need to log "Permanently abandoning service registration" message when we're intentionally deleting a service 320 321 Revision 1.525 2007/10/30 23:58:59 cheshire 322 <rdar://problem/5496734> BTMM: Need to retry registrations after failures 323 After failure, double retry interval up to maximum of 30 minutes 324 325 Revision 1.524 2007/10/30 20:10:47 cheshire 326 <rdar://problem/5496734> BTMM: Need to retry registrations after failures 327 328 Revision 1.523 2007/10/30 00:54:31 cheshire 329 <rdar://problem/5496734> BTMM: Need to retry registrations after failures 330 Fixed timing logic to double retry interval properly 331 332 Revision 1.522 2007/10/30 00:04:43 cheshire 333 <rdar://problem/5496734> BTMM: Need to retry registrations after failures 334 Made the code not give up and abandon the record when it gets an error in regState_UpdatePending state 335 336 Revision 1.521 2007/10/29 23:58:52 cheshire 337 <rdar://problem/5536979> BTMM: Need to create NAT port mapping for receiving LLQ events 338 Use standard "if (mDNSIPv4AddressIsOnes(....ExternalAddress))" mechanism to determine whether callback has been invoked yet 339 340 Revision 1.520 2007/10/29 21:48:36 cheshire 341 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep 342 Added 10% random variation on LLQ renewal time, to reduce unintended timing correlation between multiple machines 343 344 Revision 1.519 2007/10/29 21:37:00 cheshire 345 <rdar://problem/5496734> BTMM: Need to retry registrations after failures 346 Added 10% random variation on record refresh time, to reduce accidental timing correlation between multiple machines 347 348 Revision 1.518 2007/10/26 23:41:29 cheshire 349 <rdar://problem/5496734> BTMM: Need to retry registrations after failures 350 351 Revision 1.517 2007/10/25 23:30:12 cheshire 352 Private DNS registered records now deregistered on sleep and re-registered on wake 353 354 Revision 1.516 2007/10/25 22:53:52 cheshire 355 <rdar://problem/5496734> BTMM: Need to retry registrations after failures 356 Don't unlinkSRS and permanently give up at the first sign of trouble 357 358 Revision 1.515 2007/10/25 21:08:07 cheshire 359 Don't try to send record registrations/deletions before we have our server address 360 361 Revision 1.514 2007/10/25 20:48:47 cheshire 362 For naming consistency (with AuthRecord's UpdateServer) renamed 'ns' to 'SRSUpdateServer' 363 364 Revision 1.513 2007/10/25 20:06:13 cheshire 365 Don't try to do SOA queries using private DNS (TLS over TCP) queries 366 367 Revision 1.512 2007/10/25 18:25:15 cheshire 368 <rdar://problem/5496734> BTMM: Need to retry registrations after failures 369 Don't need a NAT mapping for autotunnel services 370 371 Revision 1.511 2007/10/25 00:16:23 cheshire 372 <rdar://problem/5496734> BTMM: Need to retry registrations after failures 373 Fixed retry timing logic; when DNS server returns an error code, we should retry later, 374 instead of just deleting our record ("UnlinkAuthRecord") and completely giving up 375 376 Revision 1.510 2007/10/24 22:40:06 cheshire 377 Renamed: RecordRegistrationCallback -> RecordRegistrationGotZoneData 378 Renamed: ServiceRegistrationZoneDataComplete -> ServiceRegistrationGotZoneData 379 380 Revision 1.509 2007/10/24 00:54:07 cheshire 381 <rdar://problem/5496734> BTMM: Need to retry registrations after failures 382 383 Revision 1.508 2007/10/24 00:05:03 cheshire 384 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep 385 When sending TLS/TCP LLQ setup request over VPN, need to set EventPort to 5353, not zero 386 387 Revision 1.507 2007/10/23 00:33:36 cheshire 388 Improved debugging messages 389 390 Revision 1.506 2007/10/22 19:54:13 cheshire 391 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep 392 Only put EventPort in LLQ request when sending from an RFC 1918 source address, not when sending over VPN 393 394 Revision 1.505 2007/10/19 22:08:49 cheshire 395 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep 396 Additional fixes and refinements 397 398 Revision 1.504 2007/10/18 23:06:43 cheshire 399 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep 400 Additional fixes and refinements 401 402 Revision 1.503 2007/10/18 20:23:17 cheshire 403 Moved SuspendLLQs into mDNS.c, since it's only called from one place 404 405 Revision 1.502 2007/10/17 22:49:54 cheshire 406 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep 407 408 Revision 1.501 2007/10/17 22:37:23 cheshire 409 <rdar://problem/5536979> BTMM: Need to create NAT port mapping for receiving LLQ events 410 411 Revision 1.500 2007/10/17 21:53:51 cheshire 412 Improved debugging messages; renamed startLLQHandshakeCallback to LLQGotZoneData 413 414 Revision 1.499 2007/10/16 21:16:50 cheshire 415 Get rid of unused uDNS_Sleep() routine 416 417 Revision 1.498 2007/10/16 20:59:41 cheshire 418 Export SuspendLLQs/SleepServiceRegistrations/SleepRecordRegistrations so they're callable from other files 419 420 Revision 1.497 2007/10/05 18:09:44 cheshire 421 <rdar://problem/5524841> Services advertised with wrong target host 422 423 Revision 1.496 2007/10/04 22:38:59 cheshire 424 Added LogOperation message showing new q->ThisQInterval after sending uDNS query packet 425 426 Revision 1.495 2007/10/03 00:16:19 cheshire 427 In PrivateQueryGotZoneData, need to grab lock before calling SetNextQueryTime 428 429 Revision 1.494 2007/10/02 21:11:08 cheshire 430 <rdar://problem/5518270> LLQ refreshes don't work, which breaks BTMM browsing 431 432 Revision 1.493 2007/10/02 19:50:23 cheshire 433 Improved debugging message 434 435 Revision 1.492 2007/09/29 03:15:43 cheshire 436 <rdar://problem/5513168> BTMM: mDNSResponder memory corruption in GetAuthInfoForName_internal 437 Use AutoTunnelUnregistered macro instead of checking record state directly 438 439 Revision 1.491 2007/09/29 01:33:45 cheshire 440 <rdar://problem/5513168> BTMM: mDNSResponder memory corruption in GetAuthInfoForName_internal 441 442 Revision 1.490 2007/09/29 01:06:17 mcguire 443 <rdar://problem/5507862> 9A564: mDNSResponder crash in mDNS_Execute 444 445 Revision 1.489 2007/09/27 22:02:33 cheshire 446 <rdar://problem/5464941> BTMM: Registered records in BTMM don't get removed from server after calling RemoveRecord 447 448 Revision 1.488 2007/09/27 21:20:17 cheshire 449 Improved debugging syslog messages 450 451 Revision 1.487 2007/09/27 18:55:11 cheshire 452 <rdar://problem/5477165> BTMM: Multiple SRV records get registered after changing Computer Name 453 454 Revision 1.486 2007/09/27 17:42:49 cheshire 455 Fix naming: for consistency, "kDNSFlag1_RC" should be "kDNSFlag1_RC_Mask" 456 457 Revision 1.485 2007/09/27 02:16:30 cheshire 458 <rdar://problem/5500111> BTMM: LLQ refreshes being sent in the clear to the wrong port 459 460 Revision 1.484 2007/09/27 00:25:39 cheshire 461 Added ttl_seconds parameter to MakeNegativeCacheRecord in preparation for: 462 <rdar://problem/4947392> uDNS: Use SOA to determine TTL for negative answers 463 464 Revision 1.483 2007/09/26 23:16:58 cheshire 465 <rdar://problem/5496399> BTMM: Leopard sending excessive LLQ registration requests to .Mac 466 467 Revision 1.482 2007/09/26 22:06:02 cheshire 468 <rdar://problem/5507399> BTMM: No immediate failure notifications for BTMM names 469 470 Revision 1.481 2007/09/26 00:49:46 cheshire 471 Improve packet logging to show sent and received packets, 472 transport protocol (UDP/TCP/TLS) and source/destination address:port 473 474 Revision 1.480 2007/09/21 21:08:52 cheshire 475 Get rid of unnecessary DumpPacket() calls -- it makes more sense 476 to do this in mDNSSendDNSMessage and mDNSCoreReceive instead 477 478 Revision 1.479 2007/09/21 20:01:17 cheshire 479 <rdar://problem/5496750> BTMM: Skip directly to member name in SOA queries to avoid sending names in the clear 480 481 Revision 1.478 2007/09/21 19:29:14 cheshire 482 Added dump of uDNS questions when in MDNS_LOG_VERBOSE_DEBUG mode 483 484 Revision 1.477 2007/09/20 02:29:37 cheshire 485 <rdar://problem/4038277> BTMM: Not getting LLQ remove events when logging out of VPN or disconnecting from network 486 487 Revision 1.476 2007/09/20 01:19:49 cheshire 488 Improve debugging messages: report startLLQHandshake errors; show state in uDNS_StopLongLivedQuery message 489 490 Revision 1.475 2007/09/19 23:51:26 cheshire 491 <rdar://problem/5480517> BTMM: Need to log a message when NAT port mapping fails 492 493 Revision 1.474 2007/09/19 20:32:09 cheshire 494 Export GetAuthInfoForName so it's callable from other files 495 496 Revision 1.473 2007/09/18 21:42:29 cheshire 497 To reduce programming mistakes, renamed ExtPort to RequestedPort 498 499 Revision 1.472 2007/09/14 21:26:08 cheshire 500 <rdar://problem/5482627> BTMM: Need to manually avoid port conflicts when using UPnP gateways 501 502 Revision 1.471 2007/09/14 01:07:10 cheshire 503 If UPnP NAT gateway returns 0.0.0.0 as external address (e.g. because it hasn't 504 got a DHCP address yet) then retry periodically until it gives us a real address. 505 506 Revision 1.470 2007/09/13 00:36:26 cheshire 507 <rdar://problem/5477360> NAT Reboot detection logic incorrect 508 509 Revision 1.469 2007/09/13 00:28:50 cheshire 510 <rdar://problem/5477354> Host records not updated on NAT address change 511 512 Revision 1.468 2007/09/13 00:16:41 cheshire 513 <rdar://problem/5468706> Miscellaneous NAT Traversal improvements 514 515 Revision 1.467 2007/09/12 23:03:08 cheshire 516 <rdar://problem/5476978> DNSServiceNATPortMappingCreate callback not giving correct interface index 517 518 Revision 1.466 2007/09/12 22:19:29 cheshire 519 <rdar://problem/5476977> Need to listen for port 5350 NAT-PMP announcements 520 521 Revision 1.465 2007/09/12 19:22:19 cheshire 522 Variable renaming in preparation for upcoming fixes e.g. priv/pub renamed to intport/extport 523 Made NAT Traversal packet handlers take typed data instead of anonymous "mDNSu8 *" byte pointers 524 525 Revision 1.464 2007/09/12 01:22:13 cheshire 526 Improve validatelists() checking to detect when 'next' pointer gets smashed to ~0 527 528 Revision 1.463 2007/09/11 20:23:28 vazquez 529 <rdar://problem/5466719> CrashTracer: 3 crashes in mDNSResponder at mDNSResponder: natTraversalHandlePortMapReply + 107 530 Make sure we clean up NATTraversals before free'ing HostnameInfo 531 532 Revision 1.462 2007/09/11 19:19:16 cheshire 533 Correct capitalization of "uPNP" to "UPnP" 534 535 Revision 1.461 2007/09/10 22:08:17 cheshire 536 Rename uptime => upseconds and LastNATUptime => LastNATupseconds to make it clear these time values are in seconds 537 538 Revision 1.460 2007/09/07 21:47:43 vazquez 539 <rdar://problem/5460210> BTMM: SetupSocket 5351 failed; Can't allocate UDP multicast socket spew on wake from sleep with internet sharing on 540 Try to allocate using port 5350 if we get a failure, and only log message if that fails too. 541 542 Revision 1.459 2007/09/07 01:01:05 cheshire 543 <rdar://problem/5464844> BTMM: Services being registered and deregistered in a loop 544 In hndlServiceUpdateReply, need to clear SRVUpdateDeferred 545 546 Revision 1.458 2007/09/06 19:14:33 cheshire 547 Fixed minor error introduced in 1.379 (an "if" statement was deleted but the "else" following it was left there) 548 549 Revision 1.457 2007/09/05 21:48:01 cheshire 550 <rdar://problem/5385864> BTMM: mDNSResponder flushes wide-area Bonjour records after an hour for a zone. 551 Now that we're respecting the TTL of uDNS records in the cache, the LLQ maintenance code needs 552 to update the cache lifetimes of all relevant records every time it successfully renews an LLQ, 553 otherwise those records will expire and vanish from the cache. 554 555 Revision 1.456 2007/09/05 21:00:17 cheshire 556 <rdar://problem/5457287> mDNSResponder taking up 100% CPU in ReissueBlockedQuestions 557 Additional refinement: ThisQInterval needs to be restored in tcpCallback, not in PrivateQueryGotZoneData 558 559 Revision 1.455 2007/09/05 20:53:06 cheshire 560 Tidied up alignment of code layout; code was clearing m->tcpAddrInfo.sock instead of m->tcpDeviceInfo.sock 561 562 Revision 1.454 2007/09/05 02:32:55 cheshire 563 Fixed posix build error (mixed declarations and code) 564 565 Revision 1.453 2007/09/05 02:26:57 cheshire 566 <rdar://problem/5457287> mDNSResponder taking up 100% CPU in ReissueBlockedQuestions 567 In PrivateQueryGotZoneData, restore q->ThisQInterval to non-zero value after GetZoneData completes 568 569 Revision 1.452 2007/08/31 22:58:22 cheshire 570 If we have an existing TCP connection we should re-use it instead of just bailing out 571 After receiving dnsbugtest response, need to set m->NextScheduledQuery to cause queries to be re-issued 572 573 Revision 1.451 2007/08/31 18:49:49 vazquez 574 <rdar://problem/5393719> BTMM: Need to properly deregister when stopping BTMM 575 576 Revision 1.450 2007/08/30 22:50:04 mcguire 577 <rdar://problem/5430628> BTMM: Tunneled services are registered when autotunnel can't be setup 578 579 Revision 1.449 2007/08/30 00:43:17 cheshire 580 Need to clear m->rec.r.resrec.RecordType before returning from uDNS_recvLLQResponse 581 582 Revision 1.448 2007/08/30 00:18:46 cheshire 583 <rdar://problem/5448804> Error messages: "SendServiceRegistration: Already have TCP connection..." 584 585 Revision 1.447 2007/08/29 01:18:33 cheshire 586 <rdar://problem/5400181> BTMM: Tunneled services do not need NAT port mappings 587 Only create NAT mappings for SRV records with AutoTarget set to Target_AutoHostAndNATMAP 588 589 Revision 1.446 2007/08/28 23:58:42 cheshire 590 Rename HostTarget -> AutoTarget 591 592 Revision 1.445 2007/08/28 23:53:21 cheshire 593 Rename serviceRegistrationCallback -> ServiceRegistrationZoneDataComplete 594 595 Revision 1.444 2007/08/27 20:29:20 cheshire 596 Additional debugging messages 597 598 Revision 1.443 2007/08/24 23:18:28 cheshire 599 mDNS_SetSecretForDomain is called with lock held; needs to use 600 GetAuthInfoForName_internal() instead of external version GetAuthInfoForName() 601 602 Revision 1.442 2007/08/24 22:43:06 cheshire 603 Tidied up coded layout 604 605 Revision 1.441 2007/08/24 01:20:55 cheshire 606 <rdar://problem/5434381> BTMM: Memory corruption in KeychainChanged event handling 607 608 Revision 1.440 2007/08/24 00:15:20 cheshire 609 Renamed GetAuthInfoForName() to GetAuthInfoForName_internal() to make it clear that it may only be called with the lock held 610 611 Revision 1.439 2007/08/23 21:47:09 vazquez 612 <rdar://problem/5427316> BTMM: mDNSResponder sends NAT-PMP packets on public network 613 make sure we clean up port mappings on base stations by sending a lease value of 0, 614 and only send NAT-PMP packets on private networks; also save some memory by 615 not using packet structs in NATTraversals. 616 617 Revision 1.438 2007/08/22 17:50:08 vazquez 618 <rdar://problem/5399276> Need to handle errors returned by NAT-PMP routers properly 619 Propagate router errors to clients, and stop logging spurious "message too short" logs. 620 621 Revision 1.437 2007/08/18 00:54:15 mcguire 622 <rdar://problem/5413147> BTMM: Should not register private addresses or zeros 623 624 Revision 1.436 2007/08/08 21:07:48 vazquez 625 <rdar://problem/5244687> BTMM: Need to advertise model information via wide-area bonjour 626 627 Revision 1.435 2007/08/03 02:04:09 vazquez 628 <rdar://problem/5371843> BTMM: Private LLQs never fall back to polling 629 Fix case where NAT-PMP returns an external address but does not support 630 port mappings. Undo previous change and now, if the router returns an 631 error in the reply packet we respect it. 632 633 Revision 1.434 2007/08/02 21:03:05 vazquez 634 Change NAT logic to fix case where base station with port mapping turned off 635 returns an external address but does not make port mappings. 636 637 Revision 1.433 2007/08/02 03:30:11 vazquez 638 <rdar://problem/5371843> BTMM: Private LLQs never fall back to polling 639 640 Revision 1.432 2007/08/01 18:15:19 cheshire 641 Fixed crash in tcpCallback; fixed some problems with LLQ setup behind NAT 642 643 Revision 1.431 2007/08/01 16:11:06 cheshire 644 Fixed "mixed declarations and code" compiler error in Posix build 645 646 Revision 1.430 2007/08/01 16:09:13 cheshire 647 Removed unused NATTraversalInfo substructure from AuthRecord; reduced structure sizecheck values accordingly 648 649 Revision 1.429 2007/08/01 03:09:22 cheshire 650 <rdar://problem/5344587> BTMM: Create NAT port mapping for autotunnel port 651 652 Revision 1.428 2007/08/01 01:43:36 cheshire 653 Need to do mDNS_DropLockBeforeCallback/ReclaimLock around invokation of NAT client callback 654 655 Revision 1.427 2007/08/01 01:31:13 cheshire 656 Need to initialize traversal->tcpInfo fields or code may crash 657 658 Revision 1.426 2007/08/01 01:15:57 cheshire 659 <rdar://problem/5375791> Need to invoke NAT client callback when not on RFC1918 private network 660 661 Revision 1.425 2007/08/01 00:04:14 cheshire 662 <rdar://problem/5261696> Crash in tcpKQSocketCallback 663 Half-open TCP connections were not being cancelled properly 664 665 Revision 1.424 2007/07/31 02:28:35 vazquez 666 <rdar://problem/3734269> NAT-PMP: Detect public IP address changes and base station reboot 667 668 Revision 1.423 2007/07/30 23:31:26 cheshire 669 Code for respecting TTL received in uDNS responses should exclude LLQ-type responses 670 671 Revision 1.422 2007/07/28 01:25:57 cheshire 672 <rdar://problem/4780038> BTMM: Add explicit UDP event port to LLQ setup request, to fix LLQs not working behind NAT 673 674 Revision 1.421 2007/07/28 00:04:14 cheshire 675 Various fixes for comments and debugging messages 676 677 Revision 1.420 2007/07/27 23:59:18 cheshire 678 Added compile-time structure size checks 679 680 Revision 1.419 2007/07/27 20:52:29 cheshire 681 Made uDNS_recvLLQResponse() return tri-state result: LLQ_Not, LLQ_First, or LLQ_Events 682 683 Revision 1.418 2007/07/27 20:32:05 vazquez 684 Flag a UPnP NAT traversal before starting a UPnP port mapping, and make sure all 685 calls to mDNS_StopNATOperation() go through the UPnP code 686 687 Revision 1.417 2007/07/27 20:19:42 cheshire 688 Use MDNS_LOG_VERBOSE_DEBUG for dumping out packets instead of MDNS_LOG_DEBUG 689 690 Revision 1.416 2007/07/27 19:59:28 cheshire 691 MUST NOT touch m->CurrentQuestion (or q) after calling AnswerCurrentQuestionWithResourceRecord() 692 693 Revision 1.415 2007/07/27 19:51:01 cheshire 694 Use symbol QC_addnocache instead of literal constant "2" 695 696 Revision 1.414 2007/07/27 19:30:39 cheshire 697 Changed mDNSQuestionCallback parameter from mDNSBool to QC_result, 698 to properly reflect tri-state nature of the possible responses 699 700 Revision 1.413 2007/07/27 18:44:01 cheshire 701 Rename "AnswerQuestionWithResourceRecord" to more informative "AnswerCurrentQuestionWithResourceRecord" 702 703 Revision 1.412 2007/07/27 18:38:56 cheshire 704 Rename "uDNS_CheckQuery" to more informative "uDNS_CheckCurrentQuestion" 705 706 Revision 1.411 2007/07/27 00:57:13 cheshire 707 Create hostname address records using standard kHostNameTTL (2 minutes) instead of 1 second 708 709 Revision 1.410 2007/07/25 21:41:00 vazquez 710 Make sure we clean up opened sockets when there are network transitions and when changing 711 port mappings 712 713 Revision 1.409 2007/07/25 03:05:02 vazquez 714 Fixes for: 715 <rdar://problem/5338913> LegacyNATTraversal: UPnP heap overflow 716 <rdar://problem/5338933> LegacyNATTraversal: UPnP stack buffer overflow 717 and a myriad of other security problems 718 719 Revision 1.408 2007/07/24 21:47:51 cheshire 720 Don't do mDNS_StopNATOperation() for operations we never started 721 722 Revision 1.407 2007/07/24 17:23:33 cheshire 723 <rdar://problem/5357133> Add list validation checks for debugging 724 725 Revision 1.406 2007/07/24 04:14:30 cheshire 726 <rdar://problem/5356281> LLQs not working in with NAT Traversal 727 728 Revision 1.405 2007/07/24 01:29:03 cheshire 729 <rdar://problem/5356026> DNSServiceNATPortMappingCreate() returns stale external address information 730 731 Revision 1.404 2007/07/20 23:10:51 cheshire 732 Fix code layout 733 734 Revision 1.403 2007/07/20 20:12:37 cheshire 735 Rename "mDNS_DomainTypeBrowseLegacy" as "mDNS_DomainTypeBrowseAutomatic" 736 737 Revision 1.402 2007/07/20 00:54:20 cheshire 738 <rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings 739 740 Revision 1.401 2007/07/18 03:23:33 cheshire 741 In GetServiceTarget, need to call SetupLocalAutoTunnelInterface_internal to bring up tunnel on demand, if necessary 742 743 Revision 1.400 2007/07/18 02:30:25 cheshire 744 Defer AutoTunnel server record advertising until we have at least one service to advertise 745 Do AutoTunnel target host selection in GetServiceTarget (instead of uDNS_RegisterService) 746 747 Revision 1.399 2007/07/18 01:02:28 cheshire 748 <rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings 749 Declare records as kDNSRecordTypeKnownUnique so we don't get name conflicts with ourselves 750 751 Revision 1.398 2007/07/16 23:54:48 cheshire 752 <rdar://problem/5338850> Crash when removing or changing DNS keys 753 754 Revision 1.397 2007/07/16 20:13:31 vazquez 755 <rdar://problem/3867231> LegacyNATTraversal: Need complete rewrite 756 757 Revision 1.396 2007/07/14 00:33:04 cheshire 758 Remove temporary IPv4LL tunneling mode now that IPv6-over-IPv4 is working 759 760 Revision 1.395 2007/07/12 23:56:23 cheshire 761 Change "GetZoneData GOT SRV" message to debugf to reduce verbosity in syslog 762 763 Revision 1.394 2007/07/12 23:36:08 cheshire 764 Changed some 'LogOperation' calls to 'debugf' to reduce verbosity in syslog 765 766 Revision 1.393 2007/07/12 22:15:10 cheshire 767 Modified mDNS_SetSecretForDomain() so it can be called to update an existing entry 768 769 Revision 1.392 2007/07/12 02:51:27 cheshire 770 <rdar://problem/5303834> Automatically configure IPSec policy when resolving services 771 772 Revision 1.391 2007/07/11 23:16:31 cheshire 773 <rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings 774 Need to prepend _autotunnel._udp to start of AutoTunnel SRV record name 775 776 Revision 1.390 2007/07/11 22:47:55 cheshire 777 <rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for services 778 In mDNS_SetSecretForDomain(), don't register records until after we've validated the parameters 779 780 Revision 1.389 2007/07/11 21:33:10 cheshire 781 <rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings 782 Set up and register AutoTunnelTarget and AutoTunnelService DNS records 783 784 Revision 1.388 2007/07/11 19:27:10 cheshire 785 <rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for services 786 For temporary testing fake up an IPv4LL address instead of IPv6 ULA 787 788 Revision 1.387 2007/07/11 03:04:08 cheshire 789 <rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services 790 Add AutoTunnel parameter to mDNS_SetSecretForDomain; Set up AutoTunnel information for domains that require it 791 792 Revision 1.386 2007/07/10 01:57:28 cheshire 793 <rdar://problem/5196524> uDNS: mDNSresponder is leaking TCP connections to DNS server 794 Turned vast chunks of replicated code into a subroutine MakeTCPConn(...); 795 Made routines hold on to the reference it returns instead of leaking it 796 797 Revision 1.385 2007/07/09 23:50:18 cheshire 798 unlinkSRS needs to call mDNS_StopNATOperation_internal(), not mDNS_StopNATOperation() 799 800 Revision 1.384 2007/07/06 21:20:21 cheshire 801 Fix scheduling error (was causing "Task Scheduling Error: Continuously busy for more than a second") 802 803 Revision 1.383 2007/07/06 18:59:59 cheshire 804 Avoid spinning in an infinite loop when uDNS_SendNATMsg() returns an error 805 806 Revision 1.382 2007/07/04 00:49:43 vazquez 807 Clean up extraneous comments 808 809 Revision 1.381 2007/07/03 00:41:14 vazquez 810 More changes for <rdar://problem/5301908> Clean up NAT state machine (necessary for 6 other fixes) 811 Safely deal with packet replies and client callbacks 812 813 Revision 1.380 2007/07/02 22:08:47 cheshire 814 Fixed crash in "Received public IP address" message 815 816 Revision 1.379 2007/06/29 00:08:49 vazquez 817 <rdar://problem/5301908> Clean up NAT state machine (necessary for 6 other fixes) 818 819 Revision 1.378 2007/06/27 20:25:10 cheshire 820 Expanded dnsbugtest comment, explaining requirement that we also need these 821 test queries to black-hole before they get to the root name servers. 822 823 Revision 1.377 2007/06/22 21:27:21 cheshire 824 Modified "could not convert shared secret from base64" log message 825 826 Revision 1.376 2007/06/20 01:10:12 cheshire 827 <rdar://problem/5280520> Sync iPhone changes into main mDNSResponder code 828 829 Revision 1.375 2007/06/15 21:54:51 cheshire 830 <rdar://problem/4883206> Add packet logging to help debugging private browsing over TLS 831 832 Revision 1.374 2007/06/12 02:15:26 cheshire 833 Fix incorrect "DNS Server passed" LogOperation message 834 835 Revision 1.373 2007/05/31 00:25:43 cheshire 836 <rdar://problem/5238688> Only send dnsbugtest query for questions where it's warranted 837 838 Revision 1.372 2007/05/25 17:03:45 cheshire 839 lenptr needs to be declared unsigned, otherwise sign extension can mess up the shifting and ORing operations 840 841 Revision 1.371 2007/05/24 00:11:44 cheshire 842 Remove unnecessary lenbuf field from tcpInfo_t 843 844 Revision 1.370 2007/05/23 00:30:59 cheshire 845 Don't change question->TargetQID when repeating query over TCP 846 847 Revision 1.369 2007/05/21 18:04:40 cheshire 848 Updated comments -- port_mapping_create_reply renamed to port_mapping_reply 849 850 Revision 1.368 2007/05/17 19:12:16 cheshire 851 Updated comment about finding matching pair of sockets 852 853 Revision 1.367 2007/05/15 23:38:00 cheshire 854 Need to grab lock before calling SendRecordRegistration(); 855 856 Revision 1.366 2007/05/15 00:43:05 cheshire 857 <rdar://problem/4983538> uDNS serviceRegistrationCallback locking failures 858 859 Revision 1.365 2007/05/10 21:19:18 cheshire 860 Rate-limit DNS test queries to at most one per three seconds 861 (useful when we have a dozen active WAB queries, and then we join a new network) 862 863 Revision 1.364 2007/05/07 20:43:45 cheshire 864 <rdar://problem/4241419> Reduce the number of queries and announcements 865 866 Revision 1.363 2007/05/04 22:12:48 cheshire 867 Work towards solving <rdar://problem/5176892> "uDNS_CheckQuery: LastQTime" log messages 868 When code gets in this invalid state, double ThisQInterval each time, to avoid excessive logging 869 870 Revision 1.362 2007/05/04 21:23:05 cheshire 871 <rdar://problem/5167263> Private DNS always returns no answers in the initial LLQ setup response 872 Preparatory work to enable us to do a four-way LLQ handshake over TCP, if we decide that's what we want 873 874 Revision 1.361 2007/05/03 23:50:48 cheshire 875 <rdar://problem/4669229> mDNSResponder ignores bogus null target in SRV record 876 In the case of negative answers for the address record, set the server address to zerov4Addr 877 878 Revision 1.360 2007/05/03 22:40:38 cheshire 879 <rdar://problem/4669229> mDNSResponder ignores bogus null target in SRV record 880 881 Revision 1.359 2007/05/02 22:21:33 cheshire 882 <rdar://problem/5167331> RegisterRecord and RegisterService need to cancel StartGetZoneData 883 884 Revision 1.358 2007/05/01 21:46:31 cheshire 885 Move GetLLQOptData/GetPktLease from uDNS.c into DNSCommon.c so that dnsextd can use them 886 887 Revision 1.357 2007/05/01 01:33:49 cheshire 888 Removed "#define LLQ_Info DNSQuestion" and manually reconciled code that was still referring to "LLQ_Info" 889 890 Revision 1.356 2007/04/30 21:51:06 cheshire 891 Updated comments 892 893 Revision 1.355 2007/04/30 21:33:38 cheshire 894 Fix crash when a callback unregisters a service while the UpdateSRVRecords() loop 895 is iterating through the m->ServiceRegistrations list 896 897 Revision 1.354 2007/04/30 01:30:04 cheshire 898 GetZoneData_QuestionCallback needs to call client callback function on error, so client knows operation is finished 899 RecordRegistrationCallback and serviceRegistrationCallback need to clear nta reference when they're invoked 900 901 Revision 1.353 2007/04/28 01:28:25 cheshire 902 Fixed memory leak on error path in FoundDomain 903 904 Revision 1.352 2007/04/27 19:49:53 cheshire 905 In uDNS_ReceiveTestQuestionResponse, also check that srcport matches 906 907 Revision 1.351 2007/04/27 19:28:02 cheshire 908 Any code that calls StartGetZoneData needs to keep a handle to the structure, so 909 it can cancel it if necessary. (First noticed as a crash in Apple Remote Desktop 910 -- it would start a query and then quickly cancel it, and then when 911 StartGetZoneData completed, it had a dangling pointer and crashed.) 912 913 Revision 1.350 2007/04/26 22:47:14 cheshire 914 Defensive coding: tcpCallback only needs to check "if (closed)", not "if (!n && closed)" 915 916 Revision 1.349 2007/04/26 16:04:06 cheshire 917 In mDNS_AddDNSServer, check whether port matches 918 In uDNS_CheckQuery, handle case where startLLQHandshake changes q->llq->state to LLQ_Poll 919 920 Revision 1.348 2007/04/26 04:01:59 cheshire 921 Copy-and-paste error: Test should be "if (result == DNSServer_Passed)" not "if (result == DNSServer_Failed)" 922 923 Revision 1.347 2007/04/26 00:35:15 cheshire 924 <rdar://problem/5140339> uDNS: Domain discovery not working over VPN 925 Fixes to make sure results update correctly when connectivity changes (e.g. a DNS server 926 inside the firewall may give answers where a public one gives none, and vice versa.) 927 928 Revision 1.346 2007/04/25 19:16:59 cheshire 929 Don't set SuppressStdPort53Queries unless we do actually send a DNS packet 930 931 Revision 1.345 2007/04/25 18:05:11 cheshire 932 Don't try to restart inactive (duplicate) queries 933 934 Revision 1.344 2007/04/25 17:54:07 cheshire 935 Don't cancel Private LLQs using a clear-text UDP packet 936 937 Revision 1.343 2007/04/25 16:40:08 cheshire 938 Add comment explaining uDNS_recvLLQResponse logic 939 940 Revision 1.342 2007/04/25 02:14:38 cheshire 941 <rdar://problem/4246187> uDNS: Identical client queries should reference a single shared core query 942 Additional fixes to make LLQs work properly 943 944 Revision 1.341 2007/04/24 02:07:42 cheshire 945 <rdar://problem/4246187> Identical client queries should reference a single shared core query 946 Deleted some more redundant code 947 948 Revision 1.340 2007/04/23 22:01:23 cheshire 949 <rdar://problem/5094009> IPv6 filtering in AirPort base station breaks Wide-Area Bonjour 950 As of March 2007, AirPort base stations now block incoming IPv6 connections by default, so there's no point 951 advertising IPv6 addresses in DNS any more -- we have to assume that most of the time a host's IPv6 address 952 probably won't work for incoming connections (but its IPv4 address probably will, using NAT-PMP). 953 954 Revision 1.339 2007/04/22 06:02:03 cheshire 955 <rdar://problem/4615977> Query should immediately return failure when no server 956 957 Revision 1.338 2007/04/21 19:44:11 cheshire 958 Improve uDNS_HandleNATPortMapReply log message 959 960 Revision 1.337 2007/04/21 02:03:00 cheshire 961 Also need to set AddressRec->resrec.RecordType in the NAT case too 962 963 Revision 1.336 2007/04/20 21:16:12 cheshire 964 Fixed bogus double-registration of host name -- was causing these warning messages in syslog: 965 Error! Tried to register AuthRecord 0181FB0C host.example.com. (Addr) that's already in the list 966 967 Revision 1.335 2007/04/19 23:57:20 cheshire 968 Temporary workaround for some AirPort base stations that don't seem to like us requesting public port zero 969 970 Revision 1.334 2007/04/19 23:21:51 cheshire 971 Fixed a couple of places where the StartGetZoneData check was backwards 972 973 Revision 1.333 2007/04/19 22:50:53 cheshire 974 <rdar://problem/4246187> Identical client queries should reference a single shared core query 975 976 Revision 1.332 2007/04/19 20:34:32 cheshire 977 Add debugging log message in uDNS_CheckQuery() 978 979 Revision 1.331 2007/04/19 20:06:41 cheshire 980 Rename field 'Private' (sounds like a boolean) to more informative 'AuthInfo' (it's a DomainAuthInfo pointer) 981 982 Revision 1.330 2007/04/19 19:51:54 cheshire 983 Get rid of unnecessary initializeQuery() routine 984 985 Revision 1.329 2007/04/19 18:03:52 cheshire 986 Improved "mDNS_AddSearchDomain" log message 987 988 Revision 1.328 2007/04/18 20:57:20 cheshire 989 Commented out "GetAuthInfoForName none found" debugging message 990 991 Revision 1.327 2007/04/17 19:21:29 cheshire 992 <rdar://problem/5140339> Domain discovery not working over VPN 993 994 Revision 1.326 2007/04/16 20:49:39 cheshire 995 Fix compile errors for mDNSPosix build 996 997 Revision 1.325 2007/04/05 22:55:35 cheshire 998 <rdar://problem/5077076> Records are ending up in Lighthouse without expiry information 999 1000 Revision 1.324 2007/04/05 20:43:30 cheshire 1001 Collapse sprawling code onto one line -- this is part of a bigger block of identical 1002 code that has been copied-and-pasted into six different places in the same file. 1003 This really needs to be turned into a subroutine. 1004 1005 Revision 1.323 2007/04/04 21:48:52 cheshire 1006 <rdar://problem/4720694> Combine unicast authoritative answer list with multicast list 1007 1008 Revision 1.322 2007/04/03 19:53:06 cheshire 1009 Use mDNSSameIPPort (and similar) instead of accessing internal fields directly 1010 1011 Revision 1.321 2007/04/02 23:44:09 cheshire 1012 Minor code tidying 1013 1014 Revision 1.320 2007/03/31 01:26:13 cheshire 1015 Take out GetAuthInfoForName syslog message 1016 1017 Revision 1.319 2007/03/31 01:10:53 cheshire 1018 Add debugging 1019 1020 Revision 1.318 2007/03/31 00:17:11 cheshire 1021 Remove some LogMsgs 1022 1023 Revision 1.317 2007/03/29 00:09:31 cheshire 1024 Improve "uDNS_InitLongLivedQuery" log message 1025 1026 Revision 1.316 2007/03/28 21:16:27 cheshire 1027 Remove DumpPacket() call now that OPT pseudo-RR rrclass bug is fixed 1028 1029 Revision 1.315 2007/03/28 21:02:18 cheshire 1030 <rdar://problem/3810563> Wide-Area Bonjour should work on multi-subnet private network 1031 1032 Revision 1.314 2007/03/28 15:56:37 cheshire 1033 <rdar://problem/5085774> Add listing of NAT port mapping and GetAddrInfo requests in SIGINFO output 1034 1035 Revision 1.313 2007/03/28 01:27:32 cheshire 1036 <rdar://problem/4996439> Unicast DNS polling server every three seconds 1037 StartLLQPolling was using INIT_UCAST_POLL_INTERVAL instead of LLQ_POLL_INTERVAL for the retry interval 1038 1039 Revision 1.312 2007/03/27 23:48:21 cheshire 1040 Use mDNS_StopGetDomains(), not mDNS_StopQuery() 1041 1042 Revision 1.311 2007/03/27 22:47:51 cheshire 1043 Remove unnecessary "*(long*)0 = 0;" to generate crash and stack trace 1044 1045 Revision 1.310 2007/03/24 01:24:13 cheshire 1046 Add validator for uDNS data structures; fixed crash in RegisterSearchDomains() 1047 1048 Revision 1.309 2007/03/24 00:47:53 cheshire 1049 <rdar://problem/4983538> serviceRegistrationCallback: Locking Failure! mDNS_busy (1) != mDNS_reentrancy (2) 1050 Locking in this file is all messed up. For now we'll just work around the issue. 1051 1052 Revision 1.308 2007/03/24 00:41:33 cheshire 1053 Minor code cleanup (move variable declarations to minimum enclosing scope) 1054 1055 Revision 1.307 2007/03/21 23:06:00 cheshire 1056 Rename uDNS_HostnameInfo to HostnameInfo; deleted some unused fields 1057 1058 Revision 1.306 2007/03/21 00:30:03 cheshire 1059 <rdar://problem/4789455> Multiple errors in DNameList-related code 1060 1061 Revision 1.305 2007/03/20 17:07:15 cheshire 1062 Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket" 1063 1064 Revision 1.304 2007/03/17 00:02:11 cheshire 1065 <rdar://problem/5067013> NAT-PMP: Lease TTL is being ignored 1066 1067 Revision 1.303 2007/03/10 03:26:44 cheshire 1068 <rdar://problem/4961667> uDNS: LLQ refresh response packet causes cached records to be removed from cache 1069 1070 Revision 1.302 2007/03/10 02:29:58 cheshire 1071 Added comments about NAT-PMP response functions 1072 1073 Revision 1.301 2007/03/10 02:02:58 cheshire 1074 <rdar://problem/4961667> uDNS: LLQ refresh response packet causes cached records to be removed from cache 1075 Eliminate unnecessary "InternalResponseHndlr responseCallback" function pointer 1076 1077 Revision 1.300 2007/03/08 18:56:00 cheshire 1078 Fixed typo: "&v4.ip.v4.b[0]" is always non-zero (ampersand should not be there) 1079 1080 Revision 1.299 2007/02/28 01:45:47 cheshire 1081 <rdar://problem/4683261> NAT-PMP: Port mapping refreshes should contain actual public port 1082 <rdar://problem/5027863> Byte order bugs in uDNS.c, uds_daemon.c, dnssd_clientstub.c 1083 1084 Revision 1.298 2007/02/14 03:16:39 cheshire 1085 <rdar://problem/4789477> Eliminate unnecessary malloc/free in mDNSCore code 1086 1087 Revision 1.297 2007/02/08 21:12:28 cheshire 1088 <rdar://problem/4386497> Stop reading /etc/mDNSResponder.conf on every sleep/wake 1089 1090 Revision 1.296 2007/01/29 16:03:22 cheshire 1091 Fix unused parameter warning 1092 1093 Revision 1.295 2007/01/27 03:34:27 cheshire 1094 Made GetZoneData use standard queries (and cached results); 1095 eliminated GetZoneData_Callback() packet response handler 1096 1097 Revision 1.294 2007/01/25 00:40:16 cheshire 1098 Unified CNAME-following functionality into cache management code (which means CNAME-following 1099 should now also work for mDNS queries too); deleted defunct pktResponseHndlr() routine. 1100 1101 Revision 1.293 2007/01/23 02:56:11 cheshire 1102 Store negative results in the cache, instead of generating them out of pktResponseHndlr() 1103 1104 Revision 1.292 2007/01/20 01:32:40 cheshire 1105 Update comments and debugging messages 1106 1107 Revision 1.291 2007/01/20 00:07:02 cheshire 1108 When we have credentials in the keychain for a domain, we attempt private queries, but 1109 if the authoritative server is not set up for private queries (i.e. no _dns-query-tls 1110 or _dns-llq-tls record) then we need to fall back to conventional non-private queries. 1111 1112 Revision 1.290 2007/01/19 23:41:45 cheshire 1113 Need to clear m->rec.r.resrec.RecordType after calling GetLLQOptData() 1114 1115 Revision 1.289 2007/01/19 23:32:07 cheshire 1116 Eliminate pointless timenow variable 1117 1118 Revision 1.288 2007/01/19 23:26:08 cheshire 1119 Right now tcpCallback does not run holding the lock, so no need to drop the lock before invoking callbacks 1120 1121 Revision 1.287 2007/01/19 22:55:41 cheshire 1122 Eliminate redundant identical parameters to GetZoneData_StartQuery() 1123 1124 Revision 1.286 2007/01/19 21:17:33 cheshire 1125 StartLLQPolling needs to call SetNextQueryTime() to cause query to be done in a timely fashion 1126 1127 Revision 1.285 2007/01/19 18:39:11 cheshire 1128 Fix a bunch of parameters that should have been declared "const" 1129 1130 Revision 1.284 2007/01/19 18:28:28 cheshire 1131 Improved debugging messages 1132 1133 Revision 1.283 2007/01/19 18:09:33 cheshire 1134 Fixed getLLQAtIndex (now called GetLLQOptData): 1135 1. It incorrectly assumed all EDNS0 OPT records are the same size (it ignored optlen) 1136 2. It used inefficient memory copying instead of just returning a pointer 1137 1138 Revision 1.282 2007/01/17 22:06:01 cheshire 1139 Replace duplicated literal constant "{ { 0 } }" with symbol "zeroIPPort" 1140 1141 Revision 1.281 2007/01/17 21:58:13 cheshire 1142 For clarity, rename ntaContext field "isPrivate" to "ntaPrivate" 1143 1144 Revision 1.280 2007/01/17 21:46:02 cheshire 1145 Remove redundant duplicated "isPrivate" field from LLQ_Info 1146 1147 Revision 1.279 2007/01/17 21:35:31 cheshire 1148 For clarity, rename zoneData_t field "isPrivate" to "zonePrivate" 1149 1150 Revision 1.278 2007/01/16 03:04:16 cheshire 1151 <rdar://problem/4917539> Add support for one-shot private queries as well as long-lived private queries 1152 Don't cache result of ntaContextSRV(context) in a local variable -- 1153 the macro evaluates to a different result after we clear "context->isPrivate" 1154 1155 Revision 1.277 2007/01/10 22:51:58 cheshire 1156 <rdar://problem/4917539> Add support for one-shot private queries as well as long-lived private queries 1157 1158 Revision 1.276 2007/01/10 02:09:30 cheshire 1159 Better LogOperation record of keys read from System Keychain 1160 1161 Revision 1.275 2007/01/09 22:37:18 cheshire 1162 Provide ten-second grace period for deleted keys, to give mDNSResponder 1163 time to delete host name before it gives up access to the required key. 1164 1165 Revision 1.274 2007/01/09 01:16:32 cheshire 1166 Improve "ERROR m->CurrentQuestion already set" debugging messages 1167 1168 Revision 1.273 2007/01/08 23:58:00 cheshire 1169 Don't request regDomain and browseDomains in uDNS_SetupDNSConfig() -- it just ignores those results 1170 1171 Revision 1.272 2007/01/05 08:30:42 cheshire 1172 Trim excessive "Log" checkin history from before 2006 1173 (checkin history still available via "cvs log ..." of course) 1174 1175 Revision 1.271 2007/01/05 06:34:03 cheshire 1176 Improve "ERROR m->CurrentQuestion already set" debugging messages 1177 1178 Revision 1.270 2007/01/05 05:44:33 cheshire 1179 Move automatic browse/registration management from uDNS.c to mDNSShared/uds_daemon.c, 1180 so that mDNSPosix embedded clients will compile again 1181 1182 Revision 1.269 2007/01/04 23:11:13 cheshire 1183 <rdar://problem/4720673> uDNS: Need to start caching unicast records 1184 When an automatic browsing domain is removed, generate appropriate "remove" events for legacy queries 1185 1186 Revision 1.268 2007/01/04 22:06:38 cheshire 1187 Fixed crash in LLQNatMapComplete() 1188 1189 Revision 1.267 2007/01/04 21:45:20 cheshire 1190 Added mDNS_DropLockBeforeCallback/mDNS_ReclaimLockAfterCallback macros, 1191 to do additional lock sanity checking around callback invocations 1192 1193 Revision 1.266 2007/01/04 21:01:20 cheshire 1194 <rdar://problem/4607042> mDNSResponder NXDOMAIN and CNAME support 1195 Only return NXDOMAIN results to clients that request them using kDNSServiceFlagsReturnIntermediates 1196 1197 Revision 1.265 2007/01/04 20:47:17 cheshire 1198 Fixed crash in CheckForUnreferencedLLQMapping() 1199 1200 Revision 1.264 2007/01/04 20:39:27 cheshire 1201 Fix locking mismatch 1202 1203 Revision 1.263 2007/01/04 02:39:53 cheshire 1204 <rdar://problem/4030599> Hostname passed into DNSServiceRegister ignored for Wide-Area service registrations 1205 1206 Revision 1.262 2007/01/04 00:29:25 cheshire 1207 Covert LogMsg() in GetAuthInfoForName to LogOperation() 1208 1209 Revision 1.261 2006/12/22 20:59:49 cheshire 1210 <rdar://problem/4742742> Read *all* DNS keys from keychain, 1211 not just key for the system-wide default registration domain 1212 1213 Revision 1.260 2006/12/21 00:06:07 cheshire 1214 Don't need to do mDNSPlatformMemZero() -- mDNS_SetupResourceRecord() does it for us 1215 1216 Revision 1.259 2006/12/20 04:07:36 cheshire 1217 Remove uDNS_info substructure from AuthRecord_struct 1218 1219 Revision 1.258 2006/12/19 22:49:24 cheshire 1220 Remove uDNS_info substructure from ServiceRecordSet_struct 1221 1222 Revision 1.257 2006/12/19 02:38:20 cheshire 1223 Get rid of unnecessary duplicate query ID field from DNSQuestion_struct 1224 1225 Revision 1.256 2006/12/19 02:18:48 cheshire 1226 Get rid of unnecessary duplicate "void *context" field from DNSQuestion_struct 1227 1228 Revision 1.255 2006/12/16 01:58:31 cheshire 1229 <rdar://problem/4720673> uDNS: Need to start caching unicast records 1230 1231 Revision 1.254 2006/12/15 19:23:39 cheshire 1232 Use new DomainNameLengthLimit() function, to be more defensive against malformed 1233 data received from the network. 1234 1235 Revision 1.253 2006/12/01 07:43:34 herscher 1236 Fix byte ordering problem for one-shot TCP queries. 1237 Iterate more intelligently over duplicates in uDNS_ReceiveMsg to avoid spin loops. 1238 1239 Revision 1.252 2006/11/30 23:07:57 herscher 1240 <rdar://problem/4765644> uDNS: Sync up with Lighthouse changes for Private DNS 1241 1242 Revision 1.251 2006/11/28 21:42:11 mkrochma 1243 Work around a crashing bug that was introduced by uDNS and mDNS code unification 1244 1245 Revision 1.250 2006/11/18 05:01:30 cheshire 1246 Preliminary support for unifying the uDNS and mDNS code, 1247 including caching of uDNS answers 1248 1249 Revision 1.249 2006/11/10 07:44:04 herscher 1250 <rdar://problem/4825493> Fix Daemon locking failures while toggling BTMM 1251 1252 Revision 1.248 2006/11/08 04:26:53 cheshire 1253 Fix typo in debugging message 1254 1255 Revision 1.247 2006/10/20 05:35:04 herscher 1256 <rdar://problem/4720713> uDNS: Merge unicast active question list with multicast list. 1257 1258 Revision 1.246 2006/10/11 19:29:41 herscher 1259 <rdar://problem/4744553> uDNS: mDNSResponder-111 using 100% CPU 1260 1261 Revision 1.245 2006/10/04 22:21:15 herscher 1262 Tidy up references to mDNS_struct introduced when the embedded uDNS_info struct was removed. 1263 1264 Revision 1.244 2006/10/04 21:51:27 herscher 1265 Replace calls to mDNSPlatformTimeNow(m) with m->timenow 1266 1267 Revision 1.243 2006/10/04 21:38:59 herscher 1268 Remove uDNS_info substructure from DNSQuestion_struct 1269 1270 Revision 1.242 2006/09/27 00:51:46 herscher 1271 Fix compile error when _LEGACY_NAT_TRAVERSAL_ is not defined 1272 1273 Revision 1.241 2006/09/26 01:54:47 herscher 1274 <rdar://problem/4245016> NAT Port Mapping API (for both NAT-PMP and UPnP Gateway Protocol) 1275 1276 Revision 1.240 2006/09/15 21:20:15 cheshire 1277 Remove uDNS_info substructure from mDNS_struct 1278 1279 Revision 1.239 2006/08/16 02:52:56 mkrochma 1280 <rdar://problem/4104154> Actually fix it this time 1281 1282 Revision 1.238 2006/08/16 00:31:50 mkrochma 1283 <rdar://problem/4386944> Get rid of NotAnInteger references 1284 1285 Revision 1.237 2006/08/15 23:38:17 mkrochma 1286 <rdar://problem/4104154> Requested Public Port field should be set to zero on mapping deletion 1287 1288 Revision 1.236 2006/08/14 23:24:23 cheshire 1289 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 1290 1291 Revision 1.235 2006/07/30 05:45:36 cheshire 1292 <rdar://problem/4304215> Eliminate MIN_UCAST_PERIODIC_EXEC 1293 1294 Revision 1.234 2006/07/22 02:58:36 cheshire 1295 Code was clearing namehash twice instead of namehash and rdatahash 1296 1297 Revision 1.233 2006/07/20 19:46:51 mkrochma 1298 <rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder 1299 Fix Private DNS 1300 1301 Revision 1.232 2006/07/15 02:01:29 cheshire 1302 <rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder 1303 Fix broken "empty string" browsing 1304 1305 Revision 1.231 2006/07/05 23:28:22 cheshire 1306 <rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder 1307 1308 Revision 1.230 2006/06/29 03:02:44 cheshire 1309 <rdar://problem/4607042> mDNSResponder NXDOMAIN and CNAME support 1310 1311 Revision 1.229 2006/03/02 22:03:41 cheshire 1312 <rdar://problem/4395331> Spurious warning "GetLargeResourceRecord: m->rec appears to be already in use" 1313 Refinement: m->rec.r.resrec.RecordType needs to be cleared *every* time around for loop, not just once at the end 1314 1315 Revision 1.228 2006/02/26 00:54:42 cheshire 1316 Fixes to avoid code generation warning/error on FreeBSD 7 1317 1318 Revision 1.227 2006/01/09 20:47:05 cheshire 1319 <rdar://problem/4395331> Spurious warning "GetLargeResourceRecord: m->rec appears to be already in use" 1320 1321 */ 1322 1323 #include "uDNS.h" 1324 1325 #if(defined(_MSC_VER)) 1326 // Disable "assignment within conditional expression". 1327 // Other compilers understand the convention that if you place the assignment expression within an extra pair 1328 // of parentheses, this signals to the compiler that you really intended an assignment and no warning is necessary. 1329 // The Microsoft compiler doesn't understand this convention, so in the absense of any other way to signal 1330 // to the compiler that the assignment is intentional, we have to just turn this warning off completely. 1331 #pragma warning(disable:4706) 1332 #endif 1333 1334 // For domain enumeration and automatic browsing 1335 // This is the user's DNS search list. 1336 // In each of these domains we search for our special pointer records (lb._dns-sd._udp.<domain>, etc.) 1337 // to discover recommended domains for domain enumeration (browse, default browse, registration, 1338 // default registration) and possibly one or more recommended automatic browsing domains. 1339 mDNSexport SearchListElem *SearchList = mDNSNULL; 1340 1341 // Temporary workaround to make ServiceRecordSet list management safe. 1342 // Ideally a ServiceRecordSet shouldn't be a special entity that's given special treatment by the uDNS code 1343 // -- it should just be a grouping of records that are treated the same as any other registered records. 1344 // In that case it may no longer be necessary to keep an explicit list of ServiceRecordSets, which in turn 1345 // would avoid the perils of modifying that list cleanly while some other piece of code is iterating through it. 1346 ServiceRecordSet *CurrentServiceRecordSet = mDNSNULL; 1347 1348 // *************************************************************************** 1349 #if COMPILER_LIKES_PRAGMA_MARK 1350 #pragma mark - General Utility Functions 1351 #endif 1352 1353 // Unlink an AuthRecord from the m->ResourceRecords list. 1354 // This seems risky. Probably some (or maybe all) of the places calling UnlinkAuthRecord to directly 1355 // remove a record from the list should actually be using mDNS_Deregister/mDNS_Deregister_internal. 1356 mDNSlocal mStatus UnlinkAuthRecord(mDNS *const m, AuthRecord *const rr) 1357 { 1358 AuthRecord **list = &m->ResourceRecords; 1359 if (m->NewLocalRecords == rr) m->NewLocalRecords = rr->next; 1360 if (m->CurrentRecord == rr) m->CurrentRecord = rr->next; 1361 while (*list && *list != rr) list = &(*list)->next; 1362 if (!*list) 1363 { 1364 list = &m->DuplicateRecords; 1365 while (*list && *list != rr) list = &(*list)->next; 1366 } 1367 if (*list) { *list = rr->next; rr->next = mDNSNULL; return(mStatus_NoError); } 1368 LogMsg("ERROR: UnlinkAuthRecord - no such active record %##s", rr->resrec.name->c); 1369 return(mStatus_NoSuchRecord); 1370 } 1371 1372 // unlinkSRS is an internal routine (i.e. must be called with the lock already held) 1373 mDNSlocal void unlinkSRS(mDNS *const m, ServiceRecordSet *srs) 1374 { 1375 ServiceRecordSet **p; 1376 1377 if (srs->NATinfo.clientContext) 1378 { 1379 mDNS_StopNATOperation_internal(m, &srs->NATinfo); 1380 srs->NATinfo.clientContext = mDNSNULL; 1381 } 1382 1383 for (p = &m->ServiceRegistrations; *p; p = &(*p)->uDNS_next) 1384 if (*p == srs) 1385 { 1386 ExtraResourceRecord *e; 1387 *p = srs->uDNS_next; 1388 if (CurrentServiceRecordSet == srs) 1389 CurrentServiceRecordSet = srs->uDNS_next; 1390 srs->uDNS_next = mDNSNULL; 1391 for (e=srs->Extras; e; e=e->next) 1392 if (UnlinkAuthRecord(m, &e->r)) 1393 LogMsg("unlinkSRS: extra record %##s not found", e->r.resrec.name->c); 1394 return; 1395 } 1396 LogMsg("ERROR: unlinkSRS - SRS not found in ServiceRegistrations list %##s", srs->RR_SRV.resrec.name->c); 1397 } 1398 1399 // set retry timestamp for record with exponential backoff 1400 // (for service record sets, use RR_SRV as representative for time checks 1401 mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mStatus SendErr) 1402 { 1403 mDNSs32 elapsed = m->timenow - rr->LastAPTime; 1404 rr->LastAPTime = m->timenow; 1405 1406 #if 0 1407 // Code for stress-testing registration renewal code 1408 if (rr->expire && rr->expire - m->timenow > mDNSPlatformOneSecond * 120) 1409 { 1410 LogInfo("Adjusting expiry from %d to 120 seconds for %s", 1411 (rr->expire - m->timenow) / mDNSPlatformOneSecond, ARDisplayString(m, rr)); 1412 rr->expire = m->timenow + mDNSPlatformOneSecond * 120; 1413 } 1414 #endif 1415 1416 if (rr->expire && rr->expire - m->timenow > mDNSPlatformOneSecond) 1417 { 1418 mDNSs32 remaining = rr->expire - m->timenow; 1419 rr->ThisAPInterval = remaining/2 + mDNSRandom(remaining/10); 1420 debugf("SetRecordRetry refresh in %4d of %4d for %s", 1421 rr->ThisAPInterval / mDNSPlatformOneSecond, (rr->expire - m->timenow) / mDNSPlatformOneSecond, ARDisplayString(m, rr)); 1422 return; 1423 } 1424 1425 rr->expire = 0; 1426 1427 // If at least half our our time interval has elapsed, it's time to double rr->ThisAPInterval 1428 // If resulting interval is too small, set to at least INIT_UCAST_POLL_INTERVAL (3 seconds) 1429 // If resulting interval is too large, set to at most 30 minutes 1430 if (rr->ThisAPInterval / 2 <= elapsed) rr->ThisAPInterval *= 2; 1431 if (rr->ThisAPInterval < INIT_UCAST_POLL_INTERVAL || SendErr == mStatus_TransientErr) 1432 rr->ThisAPInterval = INIT_UCAST_POLL_INTERVAL; 1433 rr->ThisAPInterval += mDNSRandom(rr->ThisAPInterval/20); 1434 if (rr->ThisAPInterval > 30 * 60 * mDNSPlatformOneSecond) 1435 rr->ThisAPInterval = 30 * 60 * mDNSPlatformOneSecond; 1436 1437 LogInfo("SetRecordRetry retry in %4d for %s", rr->ThisAPInterval / mDNSPlatformOneSecond, ARDisplayString(m, rr)); 1438 } 1439 1440 // *************************************************************************** 1441 #if COMPILER_LIKES_PRAGMA_MARK 1442 #pragma mark - Name Server List Management 1443 #endif 1444 1445 mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port) 1446 { 1447 DNSServer **p = &m->DNSServers; 1448 DNSServer *tmp = mDNSNULL; 1449 1450 if (!d) d = (const domainname *)""; 1451 1452 LogInfo("mDNS_AddDNSServer: Adding %#a for %##s", addr, d->c); 1453 if (m->mDNS_busy != m->mDNS_reentrancy+1) 1454 LogMsg("mDNS_AddDNSServer: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 1455 1456 while (*p) // Check if we already have this {interface,address,port,domain} tuple registered 1457 { 1458 if ((*p)->interface == interface && (*p)->teststate != DNSServer_Disabled && 1459 mDNSSameAddress(&(*p)->addr, addr) && mDNSSameIPPort((*p)->port, port) && SameDomainName(&(*p)->domain, d)) 1460 { 1461 if (!((*p)->flags & DNSServer_FlagDelete)) debugf("Note: DNS Server %#a:%d for domain %##s (%p) registered more than once", addr, mDNSVal16(port), d->c, interface); 1462 (*p)->flags &= ~DNSServer_FlagDelete; 1463 tmp = *p; 1464 *p = tmp->next; 1465 tmp->next = mDNSNULL; 1466 } 1467 else 1468 p=&(*p)->next; 1469 } 1470 1471 if (tmp) *p = tmp; // move to end of list, to ensure ordering from platform layer 1472 else 1473 { 1474 // allocate, add to list 1475 *p = mDNSPlatformMemAllocate(sizeof(**p)); 1476 if (!*p) LogMsg("Error: mDNS_AddDNSServer - malloc"); 1477 else 1478 { 1479 (*p)->interface = interface; 1480 (*p)->addr = *addr; 1481 (*p)->port = port; 1482 (*p)->flags = DNSServer_FlagNew; 1483 (*p)->teststate = /* DNSServer_Untested */ DNSServer_Passed; 1484 (*p)->lasttest = m->timenow - INIT_UCAST_POLL_INTERVAL; 1485 AssignDomainName(&(*p)->domain, d); 1486 (*p)->next = mDNSNULL; 1487 } 1488 } 1489 return(*p); 1490 } 1491 1492 mDNSexport void PushDNSServerToEnd(mDNS *const m, DNSQuestion *q) 1493 { 1494 DNSServer *orig = q->qDNSServer; 1495 DNSServer **p = &m->DNSServers; 1496 1497 if (m->mDNS_busy != m->mDNS_reentrancy+1) 1498 LogMsg("PushDNSServerToEnd: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 1499 1500 if (!q->qDNSServer) 1501 { 1502 LogMsg("PushDNSServerToEnd: Null DNS server for %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), q->unansweredQueries); 1503 goto end; 1504 } 1505 1506 LogInfo("PushDNSServerToEnd: Pushing DNS server %#a:%d (%##s) due to %d unanswered queries for %##s (%s)", 1507 &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qDNSServer->domain.c, q->unansweredQueries, q->qname.c, DNSTypeName(q->qtype)); 1508 1509 while (*p) 1510 { 1511 if (*p == q->qDNSServer) *p = q->qDNSServer->next; 1512 else p=&(*p)->next; 1513 } 1514 1515 *p = q->qDNSServer; 1516 q->qDNSServer->next = mDNSNULL; 1517 1518 end: 1519 q->qDNSServer = GetServerForName(m, &q->qname); 1520 1521 if (q->qDNSServer != orig) 1522 { 1523 if (q->qDNSServer) LogInfo("PushDNSServerToEnd: Server for %##s (%s) changed to %#a:%d (%##s)", q->qname.c, DNSTypeName(q->qtype), &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qDNSServer->domain.c); 1524 else LogInfo("PushDNSServerToEnd: Server for %##s (%s) changed to <null>", q->qname.c, DNSTypeName(q->qtype)); 1525 q->ThisQInterval = q->ThisQInterval / QuestionIntervalStep; // Decrease interval one step so we don't quickly bounce between servers for queries that will not be answered. 1526 } 1527 } 1528 1529 // *************************************************************************** 1530 #if COMPILER_LIKES_PRAGMA_MARK 1531 #pragma mark - authorization management 1532 #endif 1533 1534 mDNSlocal DomainAuthInfo *GetAuthInfoForName_direct(mDNS *m, const domainname *const name) 1535 { 1536 const domainname *n = name; 1537 while (n->c[0]) 1538 { 1539 DomainAuthInfo *ptr; 1540 for (ptr = m->AuthInfoList; ptr; ptr = ptr->next) 1541 if (SameDomainName(&ptr->domain, n)) 1542 { 1543 debugf("GetAuthInfoForName %##s Matched %##s Key name %##s", name->c, ptr->domain.c, ptr->keyname.c); 1544 return(ptr); 1545 } 1546 n = (const domainname *)(n->c + 1 + n->c[0]); 1547 } 1548 //LogInfo("GetAuthInfoForName none found for %##s", name->c); 1549 return mDNSNULL; 1550 } 1551 1552 // MUST be called with lock held 1553 mDNSexport DomainAuthInfo *GetAuthInfoForName_internal(mDNS *m, const domainname *const name) 1554 { 1555 DomainAuthInfo **p = &m->AuthInfoList; 1556 1557 if (m->mDNS_busy != m->mDNS_reentrancy+1) 1558 LogMsg("GetAuthInfoForName_internal: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 1559 1560 // First purge any dead keys from the list 1561 while (*p) 1562 { 1563 if ((*p)->deltime && m->timenow - (*p)->deltime >= 0 && AutoTunnelUnregistered(*p)) 1564 { 1565 DNSQuestion *q; 1566 DomainAuthInfo *info = *p; 1567 LogInfo("GetAuthInfoForName_internal deleting expired key %##s %##s", info->domain.c, info->keyname.c); 1568 *p = info->next; // Cut DomainAuthInfo from list *before* scanning our question list updating AuthInfo pointers 1569 for (q = m->Questions; q; q=q->next) 1570 if (q->AuthInfo == info) 1571 { 1572 q->AuthInfo = GetAuthInfoForName_direct(m, &q->qname); 1573 debugf("GetAuthInfoForName_internal updated q->AuthInfo from %##s to %##s for %##s (%s)", 1574 info->domain.c, q->AuthInfo ? q->AuthInfo->domain.c : mDNSNULL, q->qname.c, DNSTypeName(q->qtype)); 1575 } 1576 1577 // Probably not essential, but just to be safe, zero out the secret key data 1578 // so we don't leave it hanging around in memory 1579 // (where it could potentially get exposed via some other bug) 1580 mDNSPlatformMemZero(info, sizeof(*info)); 1581 mDNSPlatformMemFree(info); 1582 } 1583 else 1584 p = &(*p)->next; 1585 } 1586 1587 return(GetAuthInfoForName_direct(m, name)); 1588 } 1589 1590 mDNSexport DomainAuthInfo *GetAuthInfoForName(mDNS *m, const domainname *const name) 1591 { 1592 DomainAuthInfo *d; 1593 mDNS_Lock(m); 1594 d = GetAuthInfoForName_internal(m, name); 1595 mDNS_Unlock(m); 1596 return(d); 1597 } 1598 1599 // MUST be called with the lock held 1600 mDNSexport mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info, 1601 const domainname *domain, const domainname *keyname, const char *b64keydata, mDNSBool AutoTunnel) 1602 { 1603 DNSQuestion *q; 1604 DomainAuthInfo **p = &m->AuthInfoList; 1605 if (!info || !b64keydata) { LogMsg("mDNS_SetSecretForDomain: ERROR: info %p b64keydata %p", info, b64keydata); return(mStatus_BadParamErr); } 1606 1607 LogInfo("mDNS_SetSecretForDomain: domain %##s key %##s%s", domain->c, keyname->c, AutoTunnel ? " AutoTunnel" : ""); 1608 1609 info->AutoTunnel = AutoTunnel; 1610 AssignDomainName(&info->domain, domain); 1611 AssignDomainName(&info->keyname, keyname); 1612 mDNS_snprintf(info->b64keydata, sizeof(info->b64keydata), "%s", b64keydata); 1613 1614 if (DNSDigest_ConstructHMACKeyfromBase64(info, b64keydata) < 0) 1615 { 1616 LogMsg("mDNS_SetSecretForDomain: ERROR: Could not convert shared secret from base64: domain %##s key %##s %s", domain->c, keyname->c, mDNS_LoggingEnabled ? b64keydata : ""); 1617 return(mStatus_BadParamErr); 1618 } 1619 1620 // Don't clear deltime until after we've ascertained that b64keydata is valid 1621 info->deltime = 0; 1622 1623 while (*p && (*p) != info) p=&(*p)->next; 1624 if (*p) return(mStatus_AlreadyRegistered); 1625 1626 // Caution: Only zero AutoTunnelHostRecord.namestorage and AutoTunnelNAT.clientContext AFTER we've determined that this is a NEW DomainAuthInfo 1627 // being added to the list. Otherwise we risk smashing our AutoTunnel host records and NATOperation that are already active and in use. 1628 info->AutoTunnelHostRecord.resrec.RecordType = kDNSRecordTypeUnregistered; 1629 info->AutoTunnelHostRecord.namestorage.c[0] = 0; 1630 info->AutoTunnelTarget .resrec.RecordType = kDNSRecordTypeUnregistered; 1631 info->AutoTunnelDeviceInfo.resrec.RecordType = kDNSRecordTypeUnregistered; 1632 info->AutoTunnelService .resrec.RecordType = kDNSRecordTypeUnregistered; 1633 info->AutoTunnelNAT.clientContext = mDNSNULL; 1634 info->next = mDNSNULL; 1635 *p = info; 1636 1637 // Check to see if adding this new DomainAuthInfo has changed the credentials for any of our questions 1638 for (q = m->Questions; q; q=q->next) 1639 { 1640 DomainAuthInfo *newinfo = GetAuthInfoForQuestion(m, q); 1641 if (q->AuthInfo != newinfo) 1642 { 1643 debugf("mDNS_SetSecretForDomain updating q->AuthInfo from %##s to %##s for %##s (%s)", 1644 q->AuthInfo ? q->AuthInfo->domain.c : mDNSNULL, 1645 newinfo ? newinfo ->domain.c : mDNSNULL, q->qname.c, DNSTypeName(q->qtype)); 1646 q->AuthInfo = newinfo; 1647 } 1648 } 1649 1650 return(mStatus_NoError); 1651 } 1652 1653 // *************************************************************************** 1654 #if COMPILER_LIKES_PRAGMA_MARK 1655 #pragma mark - 1656 #pragma mark - NAT Traversal 1657 #endif 1658 1659 mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info) 1660 { 1661 mStatus err = mStatus_NoError; 1662 1663 // send msg if we have a router and it is a private address 1664 if (!mDNSIPv4AddressIsZero(m->Router.ip.v4) && mDNSv4AddrIsRFC1918(&m->Router.ip.v4)) 1665 { 1666 union { NATAddrRequest NATAddrReq; NATPortMapRequest NATPortReq; } u = { { NATMAP_VERS, NATOp_AddrRequest } } ; 1667 const mDNSu8 *end = (mDNSu8 *)&u + sizeof(NATAddrRequest); 1668 1669 if (info) // For NATOp_MapUDP and NATOp_MapTCP, fill in additional fields 1670 { 1671 mDNSu8 *p = (mDNSu8 *)&u.NATPortReq.NATReq_lease; 1672 u.NATPortReq.opcode = info->Protocol; 1673 u.NATPortReq.unused = zeroID; 1674 u.NATPortReq.intport = info->IntPort; 1675 u.NATPortReq.extport = info->RequestedPort; 1676 p[0] = (mDNSu8)((info->NATLease >> 24) & 0xFF); 1677 p[1] = (mDNSu8)((info->NATLease >> 16) & 0xFF); 1678 p[2] = (mDNSu8)((info->NATLease >> 8) & 0xFF); 1679 p[3] = (mDNSu8)( info->NATLease & 0xFF); 1680 end = (mDNSu8 *)&u + sizeof(NATPortMapRequest); 1681 } 1682 1683 err = mDNSPlatformSendUDP(m, (mDNSu8 *)&u, end, 0, mDNSNULL, &m->Router, NATPMPPort); 1684 1685 #ifdef _LEGACY_NAT_TRAVERSAL_ 1686 if (mDNSIPPortIsZero(m->UPnPRouterPort) || mDNSIPPortIsZero(m->UPnPSOAPPort)) LNT_SendDiscoveryMsg(m); 1687 else if (info) err = LNT_MapPort(m, info); 1688 else err = LNT_GetExternalAddress(m); 1689 #endif // _LEGACY_NAT_TRAVERSAL_ 1690 } 1691 return(err); 1692 } 1693 1694 mDNSexport void RecreateNATMappings(mDNS *const m) 1695 { 1696 NATTraversalInfo *n; 1697 for (n = m->NATTraversals; n; n=n->next) 1698 { 1699 n->ExpiryTime = 0; // Mark this mapping as expired 1700 n->retryInterval = NATMAP_INIT_RETRY; 1701 n->retryPortMap = m->timenow; 1702 #ifdef _LEGACY_NAT_TRAVERSAL_ 1703 if (n->tcpInfo.sock) { mDNSPlatformTCPCloseConnection(n->tcpInfo.sock); n->tcpInfo.sock = mDNSNULL; } 1704 #endif // _LEGACY_NAT_TRAVERSAL_ 1705 } 1706 1707 m->NextScheduledNATOp = m->timenow; // Need to send packets immediately 1708 } 1709 1710 mDNSexport void natTraversalHandleAddressReply(mDNS *const m, mDNSu16 err, mDNSv4Addr ExtAddr) 1711 { 1712 static mDNSu16 last_err = 0; 1713 1714 if (err) 1715 { 1716 if (err != last_err) LogMsg("Error getting external address %d", err); 1717 ExtAddr = zerov4Addr; 1718 } 1719 else 1720 { 1721 LogInfo("Received external IP address %.4a from NAT", &ExtAddr); 1722 if (mDNSv4AddrIsRFC1918(&ExtAddr)) 1723 LogMsg("Double NAT (external NAT gateway address %.4a is also a private RFC 1918 address)", &ExtAddr); 1724 if (mDNSIPv4AddressIsZero(ExtAddr)) 1725 err = NATErr_NetFail; // fake error to handle routers that pathologically report success with the zero address 1726 } 1727 1728 if (!mDNSSameIPv4Address(m->ExternalAddress, ExtAddr)) 1729 { 1730 m->ExternalAddress = ExtAddr; 1731 RecreateNATMappings(m); // Also sets NextScheduledNATOp for us 1732 } 1733 1734 if (!err) // Success, back-off to maximum interval 1735 m->retryIntervalGetAddr = NATMAP_MAX_RETRY_INTERVAL; 1736 else if (!last_err) // Failure after success, retry quickly (then back-off exponentially) 1737 m->retryIntervalGetAddr = NATMAP_INIT_RETRY; 1738 // else back-off normally in case of pathological failures 1739 1740 m->retryGetAddr = m->timenow + m->retryIntervalGetAddr; 1741 if (m->NextScheduledNATOp - m->retryIntervalGetAddr > 0) 1742 m->NextScheduledNATOp = m->retryIntervalGetAddr; 1743 1744 last_err = err; 1745 } 1746 1747 // Both places that call NATSetNextRenewalTime() update m->NextScheduledNATOp correctly afterwards 1748 mDNSlocal void NATSetNextRenewalTime(mDNS *const m, NATTraversalInfo *n) 1749 { 1750 n->retryInterval = (n->ExpiryTime - m->timenow)/2; 1751 if (n->retryInterval < NATMAP_MIN_RETRY_INTERVAL) // Min retry interval is 2 seconds 1752 n->retryInterval = NATMAP_MIN_RETRY_INTERVAL; 1753 n->retryPortMap = m->timenow + n->retryInterval; 1754 } 1755 1756 // Note: When called from handleLNTPortMappingResponse() only pkt->err, pkt->extport and pkt->NATRep_lease fields are filled in 1757 mDNSexport void natTraversalHandlePortMapReply(mDNS *const m, NATTraversalInfo *n, const mDNSInterfaceID InterfaceID, mDNSu16 err, mDNSIPPort extport, mDNSu32 lease) 1758 { 1759 const char *prot = n->Protocol == NATOp_MapUDP ? "UDP" : n->Protocol == NATOp_MapTCP ? "TCP" : "?"; 1760 (void)prot; 1761 n->NewResult = err; 1762 if (err || lease == 0 || mDNSIPPortIsZero(extport)) 1763 { 1764 LogInfo("natTraversalHandlePortMapReply: %p Response %s Port %5d External Port %5d lease %d error %d", 1765 n, prot, mDNSVal16(n->IntPort), mDNSVal16(extport), lease, err); 1766 n->retryInterval = NATMAP_MAX_RETRY_INTERVAL; 1767 n->retryPortMap = m->timenow + NATMAP_MAX_RETRY_INTERVAL; 1768 // No need to set m->NextScheduledNATOp here, since we're only ever extending the m->retryPortMap time 1769 if (err == NATErr_Refused) n->NewResult = mStatus_NATPortMappingDisabled; 1770 else if (err > NATErr_None && err <= NATErr_Opcode) n->NewResult = mStatus_NATPortMappingUnsupported; 1771 } 1772 else 1773 { 1774 if (lease > 999999999UL / mDNSPlatformOneSecond) 1775 lease = 999999999UL / mDNSPlatformOneSecond; 1776 n->ExpiryTime = NonZeroTime(m->timenow + lease * mDNSPlatformOneSecond); 1777 1778 if (!mDNSSameIPPort(n->RequestedPort, extport)) 1779 LogInfo("natTraversalHandlePortMapReply: %p Response %s Port %5d External Port %5d changed to %5d", 1780 n, prot, mDNSVal16(n->IntPort), mDNSVal16(n->RequestedPort), mDNSVal16(extport)); 1781 1782 n->InterfaceID = InterfaceID; 1783 n->RequestedPort = extport; 1784 1785 LogInfo("natTraversalHandlePortMapReply: %p Response %s Port %5d External Port %5d lease %d", 1786 n, prot, mDNSVal16(n->IntPort), mDNSVal16(extport), lease); 1787 1788 NATSetNextRenewalTime(m, n); // Got our port mapping; now set timer to renew it at halfway point 1789 m->NextScheduledNATOp = m->timenow; // May need to invoke client callback immediately 1790 } 1791 } 1792 1793 // Must be called with the mDNS_Lock held 1794 mDNSexport mStatus mDNS_StartNATOperation_internal(mDNS *const m, NATTraversalInfo *traversal) 1795 { 1796 NATTraversalInfo **n; 1797 1798 LogInfo("mDNS_StartNATOperation_internal Protocol %d IntPort %d RequestedPort %d NATLease %d", 1799 traversal->Protocol, mDNSVal16(traversal->IntPort), mDNSVal16(traversal->RequestedPort), traversal->NATLease); 1800 1801 // Note: It important that new traversal requests are appended at the *end* of the list, not prepended at the start 1802 for (n = &m->NATTraversals; *n; n=&(*n)->next) 1803 { 1804 if (traversal == *n) 1805 { 1806 LogMsg("Error! Tried to add a NAT traversal that's already in the active list: request %p Prot %d Int %d TTL %d", 1807 traversal, traversal->Protocol, mDNSVal16(traversal->IntPort), traversal->NATLease); 1808 return(mStatus_AlreadyRegistered); 1809 } 1810 if (traversal->Protocol && traversal->Protocol == (*n)->Protocol && mDNSSameIPPort(traversal->IntPort, (*n)->IntPort) && 1811 !mDNSSameIPPort(traversal->IntPort, SSHPort)) 1812 LogMsg("Warning: Created port mapping request %p Prot %d Int %d TTL %d " 1813 "duplicates existing port mapping request %p Prot %d Int %d TTL %d", 1814 traversal, traversal->Protocol, mDNSVal16(traversal->IntPort), traversal->NATLease, 1815 *n, (*n) ->Protocol, mDNSVal16((*n) ->IntPort), (*n) ->NATLease); 1816 } 1817 1818 // Initialize necessary fields 1819 traversal->next = mDNSNULL; 1820 traversal->ExpiryTime = 0; 1821 traversal->retryInterval = NATMAP_INIT_RETRY; 1822 traversal->retryPortMap = m->timenow; 1823 traversal->NewResult = mStatus_NoError; 1824 traversal->ExternalAddress = onesIPv4Addr; 1825 traversal->ExternalPort = zeroIPPort; 1826 traversal->Lifetime = 0; 1827 traversal->Result = mStatus_NoError; 1828 1829 // set default lease if necessary 1830 if (!traversal->NATLease) traversal->NATLease = NATMAP_DEFAULT_LEASE; 1831 1832 #ifdef _LEGACY_NAT_TRAVERSAL_ 1833 mDNSPlatformMemZero(&traversal->tcpInfo, sizeof(traversal->tcpInfo)); 1834 #endif // _LEGACY_NAT_TRAVERSAL_ 1835 1836 if (!m->NATTraversals) // If this is our first NAT request, kick off an address request too 1837 { 1838 m->retryGetAddr = m->timenow; 1839 m->retryIntervalGetAddr = NATMAP_INIT_RETRY; 1840 } 1841 1842 m->NextScheduledNATOp = m->timenow; // This will always trigger sending the packet ASAP, and generate client callback if necessary 1843 1844 *n = traversal; // Append new NATTraversalInfo to the end of our list 1845 1846 return(mStatus_NoError); 1847 } 1848 1849 // Must be called with the mDNS_Lock held 1850 mDNSexport mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *traversal) 1851 { 1852 mDNSBool unmap = mDNStrue; 1853 NATTraversalInfo *p; 1854 NATTraversalInfo **ptr = &m->NATTraversals; 1855 1856 while (*ptr && *ptr != traversal) ptr=&(*ptr)->next; 1857 if (*ptr) *ptr = (*ptr)->next; // If we found it, cut this NATTraversalInfo struct from our list 1858 else 1859 { 1860 LogMsg("mDNS_StopNATOperation: NATTraversalInfo %p not found in list", traversal); 1861 return(mStatus_BadReferenceErr); 1862 } 1863 1864 LogInfo("mDNS_StopNATOperation_internal %d %d %d %d", 1865 traversal->Protocol, mDNSVal16(traversal->IntPort), mDNSVal16(traversal->RequestedPort), traversal->NATLease); 1866 1867 if (m->CurrentNATTraversal == traversal) 1868 m->CurrentNATTraversal = m->CurrentNATTraversal->next; 1869 1870 if (traversal->Protocol) 1871 for (p = m->NATTraversals; p; p=p->next) 1872 if (traversal->Protocol == p->Protocol && mDNSSameIPPort(traversal->IntPort, p->IntPort)) 1873 { 1874 if (!mDNSSameIPPort(traversal->IntPort, SSHPort)) 1875 LogMsg("Warning: Removed port mapping request %p Prot %d Int %d TTL %d " 1876 "duplicates existing port mapping request %p Prot %d Int %d TTL %d", 1877 traversal, traversal->Protocol, mDNSVal16(traversal->IntPort), traversal->NATLease, 1878 p, p ->Protocol, mDNSVal16(p ->IntPort), p ->NATLease); 1879 unmap = mDNSfalse; 1880 } 1881 1882 if (traversal->ExpiryTime && unmap) 1883 { 1884 traversal->NATLease = 0; 1885 traversal->retryInterval = 0; 1886 uDNS_SendNATMsg(m, traversal); 1887 } 1888 1889 // Even if we DIDN'T make a successful UPnP mapping yet, we might still have a partially-open TCP connection we need to clean up 1890 #ifdef _LEGACY_NAT_TRAVERSAL_ 1891 { 1892 mStatus err = LNT_UnmapPort(m, traversal); 1893 if (err) LogMsg("Legacy NAT Traversal - unmap request failed with error %d", err); 1894 } 1895 #endif // _LEGACY_NAT_TRAVERSAL_ 1896 1897 return(mStatus_NoError); 1898 } 1899 1900 mDNSexport mStatus mDNS_StartNATOperation(mDNS *m, NATTraversalInfo *traversal) 1901 { 1902 mStatus status; 1903 mDNS_Lock(m); 1904 status = mDNS_StartNATOperation_internal(m, traversal); 1905 mDNS_Unlock(m); 1906 return(status); 1907 } 1908 1909 mDNSexport mStatus mDNS_StopNATOperation(mDNS *m, NATTraversalInfo *traversal) 1910 { 1911 mStatus status; 1912 mDNS_Lock(m); 1913 status = mDNS_StopNATOperation_internal(m, traversal); 1914 mDNS_Unlock(m); 1915 return(status); 1916 } 1917 1918 // *************************************************************************** 1919 #if COMPILER_LIKES_PRAGMA_MARK 1920 #pragma mark - 1921 #pragma mark - Long-Lived Queries 1922 #endif 1923 1924 // Lock must be held -- otherwise m->timenow is undefined 1925 mDNSlocal void StartLLQPolling(mDNS *const m, DNSQuestion *q) 1926 { 1927 debugf("StartLLQPolling: %##s", q->qname.c); 1928 q->state = LLQ_Poll; 1929 q->ThisQInterval = INIT_UCAST_POLL_INTERVAL; 1930 // We want to send our poll query ASAP, but the "+ 1" is because if we set the time to now, 1931 // we risk causing spurious "SendQueries didn't send all its queries" log messages 1932 q->LastQTime = m->timenow - q->ThisQInterval + 1; 1933 SetNextQueryTime(m, q); 1934 #if APPLE_OSX_mDNSResponder 1935 UpdateAutoTunnelDomainStatuses(m); 1936 #endif 1937 } 1938 1939 mDNSlocal mDNSu8 *putLLQ(DNSMessage *const msg, mDNSu8 *ptr, const DNSQuestion *const question, const LLQOptData *const data) 1940 { 1941 AuthRecord rr; 1942 ResourceRecord *opt = &rr.resrec; 1943 rdataOPT *optRD; 1944 1945 //!!!KRS when we implement multiple llqs per message, we'll need to memmove anything past the question section 1946 ptr = putQuestion(msg, ptr, msg->data + AbsoluteMaxDNSMessageData, &question->qname, question->qtype, question->qclass); 1947 if (!ptr) { LogMsg("ERROR: putLLQ - putQuestion"); return mDNSNULL; } 1948 1949 // locate OptRR if it exists, set pointer to end 1950 // !!!KRS implement me 1951 1952 // format opt rr (fields not specified are zero-valued) 1953 mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL); 1954 opt->rrclass = NormalMaxDNSMessageData; 1955 opt->rdlength = sizeof(rdataOPT); // One option in this OPT record 1956 opt->rdestimate = sizeof(rdataOPT); 1957 1958 optRD = &rr.resrec.rdata->u.opt[0]; 1959 optRD->opt = kDNSOpt_LLQ; 1960 optRD->u.llq = *data; 1961 ptr = PutResourceRecordTTLJumbo(msg, ptr, &msg->h.numAdditionals, opt, 0); 1962 if (!ptr) { LogMsg("ERROR: putLLQ - PutResourceRecordTTLJumbo"); return mDNSNULL; } 1963 1964 return ptr; 1965 } 1966 1967 // Normally we'd just request event packets be sent directly to m->LLQNAT.ExternalPort, except... 1968 // with LLQs over TLS/TCP we're doing a weird thing where instead of requesting packets be sent to ExternalAddress:ExternalPort 1969 // we're requesting that packets be sent to ExternalPort, but at the source address of our outgoing TCP connection. 1970 // Normally, after going through the NAT gateway, the source address of our outgoing TCP connection is the same as ExternalAddress, 1971 // so this is fine, except when the TCP connection ends up going over a VPN tunnel instead. 1972 // To work around this, if we find that the source address for our TCP connection is not a private address, we tell the Dot Mac 1973 // LLQ server to send events to us directly at port 5353 on that address, instead of at our mapped external NAT port. 1974 1975 mDNSlocal mDNSu16 GetLLQEventPort(const mDNS *const m, const mDNSAddr *const dst) 1976 { 1977 mDNSAddr src; 1978 mDNSPlatformSourceAddrForDest(&src, dst); 1979 //LogMsg("GetLLQEventPort: src %#a for dst %#a (%d)", &src, dst, mDNSv4AddrIsRFC1918(&src.ip.v4) ? mDNSVal16(m->LLQNAT.ExternalPort) : 0); 1980 return(mDNSv4AddrIsRFC1918(&src.ip.v4) ? mDNSVal16(m->LLQNAT.ExternalPort) : mDNSVal16(MulticastDNSPort)); 1981 } 1982 1983 // Normally called with llq set. 1984 // May be called with llq NULL, when retransmitting a lost Challenge Response 1985 mDNSlocal void sendChallengeResponse(mDNS *const m, DNSQuestion *const q, const LLQOptData *llq) 1986 { 1987 mDNSu8 *responsePtr = m->omsg.data; 1988 LLQOptData llqBuf; 1989 1990 if (q->ntries++ == kLLQ_MAX_TRIES) 1991 { 1992 LogMsg("sendChallengeResponse: %d failed attempts for LLQ %##s", kLLQ_MAX_TRIES, q->qname.c); 1993 StartLLQPolling(m,q); 1994 return; 1995 } 1996 1997 if (!llq) // Retransmission: need to make a new LLQOptData 1998 { 1999 llqBuf.vers = kLLQ_Vers; 2000 llqBuf.llqOp = kLLQOp_Setup; 2001 llqBuf.err = LLQErr_NoError; // Don't need to tell server UDP notification port when sending over UDP 2002 llqBuf.id = q->id; 2003 llqBuf.llqlease = q->ReqLease; 2004 llq = &llqBuf; 2005 } 2006 2007 q->LastQTime = m->timenow; 2008 q->ThisQInterval = q->tcp ? 0 : (kLLQ_INIT_RESEND * q->ntries * mDNSPlatformOneSecond); // If using TCP, don't need to retransmit 2009 SetNextQueryTime(m, q); 2010 2011 // To simulate loss of challenge response packet, uncomment line below 2012 //if (q->ntries == 1) return; 2013 2014 InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags); 2015 responsePtr = putLLQ(&m->omsg, responsePtr, q, llq); 2016 if (responsePtr) 2017 { 2018 mStatus err = mDNSSendDNSMessage(m, &m->omsg, responsePtr, mDNSInterface_Any, q->LocalSocket, &q->servAddr, q->servPort, q->tcp ? q->tcp->sock : mDNSNULL, q->AuthInfo); 2019 if (err) 2020 { 2021 LogMsg("sendChallengeResponse: mDNSSendDNSMessage%s failed: %d", q->tcp ? " (TCP)" : "", err); 2022 if (q->tcp) { DisposeTCPConn(q->tcp); q->tcp = mDNSNULL; } 2023 } 2024 } 2025 else StartLLQPolling(m,q); 2026 } 2027 2028 mDNSlocal void SetLLQTimer(mDNS *const m, DNSQuestion *const q, const LLQOptData *const llq) 2029 { 2030 mDNSs32 lease = (mDNSs32)llq->llqlease * mDNSPlatformOneSecond; 2031 q->ReqLease = llq->llqlease; 2032 q->LastQTime = m->timenow; 2033 q->expire = m->timenow + lease; 2034 q->ThisQInterval = lease/2 + mDNSRandom(lease/10); 2035 debugf("SetLLQTimer setting %##s (%s) to %d %d", q->qname.c, DNSTypeName(q->qtype), lease/mDNSPlatformOneSecond, q->ThisQInterval/mDNSPlatformOneSecond); 2036 SetNextQueryTime(m, q); 2037 } 2038 2039 mDNSlocal void recvSetupResponse(mDNS *const m, mDNSu8 rcode, DNSQuestion *const q, const LLQOptData *const llq) 2040 { 2041 if (rcode && rcode != kDNSFlag1_RC_NXDomain) 2042 { LogMsg("ERROR: recvSetupResponse %##s (%s) - rcode && rcode != kDNSFlag1_RC_NXDomain", q->qname.c, DNSTypeName(q->qtype)); return; } 2043 2044 if (llq->llqOp != kLLQOp_Setup) 2045 { LogMsg("ERROR: recvSetupResponse %##s (%s) - bad op %d", q->qname.c, DNSTypeName(q->qtype), llq->llqOp); return; } 2046 2047 if (llq->vers != kLLQ_Vers) 2048 { LogMsg("ERROR: recvSetupResponse %##s (%s) - bad vers %d", q->qname.c, DNSTypeName(q->qtype), llq->vers); return; } 2049 2050 if (q->state == LLQ_InitialRequest) 2051 { 2052 //LogInfo("Got LLQ_InitialRequest"); 2053 2054 if (llq->err) { LogMsg("recvSetupResponse - received llq->err %d from server", llq->err); StartLLQPolling(m,q); return; } 2055 2056 if (q->ReqLease != llq->llqlease) 2057 debugf("recvSetupResponse: requested lease %lu, granted lease %lu", q->ReqLease, llq->llqlease); 2058 2059 // cache expiration in case we go to sleep before finishing setup 2060 q->ReqLease = llq->llqlease; 2061 q->expire = m->timenow + ((mDNSs32)llq->llqlease * mDNSPlatformOneSecond); 2062 2063 // update state 2064 q->state = LLQ_SecondaryRequest; 2065 q->id = llq->id; 2066 q->ntries = 0; // first attempt to send response 2067 sendChallengeResponse(m, q, llq); 2068 } 2069 else if (q->state == LLQ_SecondaryRequest) 2070 { 2071 //LogInfo("Got LLQ_SecondaryRequest"); 2072 2073 // Fix this immediately if not sooner. Copy the id from the LLQOptData into our DNSQuestion struct. This is only 2074 // an issue for private LLQs, because we skip parts 2 and 3 of the handshake. This is related to a bigger 2075 // problem of the current implementation of TCP LLQ setup: we're not handling state transitions correctly 2076 // if the server sends back SERVFULL or STATIC. 2077 if (q->AuthInfo) 2078 { 2079 LogInfo("Private LLQ_SecondaryRequest; copying id %08X%08X", llq->id.l[0], llq->id.l[1]); 2080 q->id = llq->id; 2081 } 2082 2083 if (llq->err) { LogMsg("ERROR: recvSetupResponse %##s (%s) code %d from server", q->qname.c, DNSTypeName(q->qtype), llq->err); StartLLQPolling(m,q); return; } 2084 if (!mDNSSameOpaque64(&q->id, &llq->id)) 2085 { LogMsg("recvSetupResponse - ID changed. discarding"); return; } // this can happen rarely (on packet loss + reordering) 2086 q->state = LLQ_Established; 2087 q->ntries = 0; 2088 SetLLQTimer(m, q, llq); 2089 #if APPLE_OSX_mDNSResponder 2090 UpdateAutoTunnelDomainStatuses(m); 2091 #endif 2092 } 2093 } 2094 2095 mDNSexport uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport) 2096 { 2097 DNSQuestion pktQ, *q; 2098 if (msg->h.numQuestions && getQuestion(msg, msg->data, end, 0, &pktQ)) 2099 { 2100 const rdataOPT *opt = GetLLQOptData(m, msg, end); 2101 2102 for (q = m->Questions; q; q = q->next) 2103 { 2104 if (!mDNSOpaque16IsZero(q->TargetQID) && q->LongLived && q->qtype == pktQ.qtype && q->qnamehash == pktQ.qnamehash && SameDomainName(&q->qname, &pktQ.qname)) 2105 { 2106 debugf("uDNS_recvLLQResponse found %##s (%s) %d %#a %#a %X %X %X %X %d", 2107 q->qname.c, DNSTypeName(q->qtype), q->state, srcaddr, &q->servAddr, 2108 opt ? opt->u.llq.id.l[0] : 0, opt ? opt->u.llq.id.l[1] : 0, q->id.l[0], q->id.l[1], opt ? opt->u.llq.llqOp : 0); 2109 if (q->state == LLQ_Poll) debugf("uDNS_LLQ_Events: q->state == LLQ_Poll msg->h.id %d q->TargetQID %d", mDNSVal16(msg->h.id), mDNSVal16(q->TargetQID)); 2110 if (q->state == LLQ_Poll && mDNSSameOpaque16(msg->h.id, q->TargetQID)) 2111 { 2112 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 2113 debugf("uDNS_recvLLQResponse got poll response; moving to LLQ_InitialRequest for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 2114 q->state = LLQ_InitialRequest; 2115 q->servPort = zeroIPPort; // Clear servPort so that startLLQHandshake will retry the GetZoneData processing 2116 q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10); // Retry LLQ setup in approx 15 minutes 2117 q->LastQTime = m->timenow; 2118 SetNextQueryTime(m, q); 2119 return uDNS_LLQ_Entire; // uDNS_LLQ_Entire means flush stale records; assume a large effective TTL 2120 } 2121 // Note: In LLQ Event packets, the msg->h.id does not match our q->TargetQID, because in that case the msg->h.id nonce is selected by the server 2122 else if (opt && q->state == LLQ_Established && opt->u.llq.llqOp == kLLQOp_Event && mDNSSameOpaque64(&opt->u.llq.id, &q->id)) 2123 { 2124 mDNSu8 *ackEnd; 2125 //debugf("Sending LLQ ack for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 2126 InitializeDNSMessage(&m->omsg.h, msg->h.id, ResponseFlags); 2127 ackEnd = putLLQ(&m->omsg, m->omsg.data, q, &opt->u.llq); 2128 if (ackEnd) mDNSSendDNSMessage(m, &m->omsg, ackEnd, mDNSInterface_Any, q->LocalSocket, srcaddr, srcport, mDNSNULL, mDNSNULL); 2129 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 2130 debugf("uDNS_LLQ_Events: q->state == LLQ_Established msg->h.id %d q->TargetQID %d", mDNSVal16(msg->h.id), mDNSVal16(q->TargetQID)); 2131 return uDNS_LLQ_Events; 2132 } 2133 if (opt && mDNSSameOpaque16(msg->h.id, q->TargetQID)) 2134 { 2135 if (q->state == LLQ_Established && opt->u.llq.llqOp == kLLQOp_Refresh && mDNSSameOpaque64(&opt->u.llq.id, &q->id) && msg->h.numAdditionals && !msg->h.numAnswers) 2136 { 2137 if (opt->u.llq.err != LLQErr_NoError) LogMsg("recvRefreshReply: received error %d from server", opt->u.llq.err); 2138 else 2139 { 2140 //LogInfo("Received refresh confirmation ntries %d for %##s (%s)", q->ntries, q->qname.c, DNSTypeName(q->qtype)); 2141 // If we're waiting to go to sleep, then this LLQ deletion may have been the thing 2142 // we were waiting for, so schedule another check to see if we can sleep now. 2143 if (opt->u.llq.llqlease == 0 && m->SleepLimit) m->NextScheduledSPRetry = m->timenow; 2144 GrantCacheExtensions(m, q, opt->u.llq.llqlease); 2145 SetLLQTimer(m, q, &opt->u.llq); 2146 q->ntries = 0; 2147 } 2148 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 2149 return uDNS_LLQ_Ignore; 2150 } 2151 if (q->state < LLQ_Established && mDNSSameAddress(srcaddr, &q->servAddr)) 2152 { 2153 LLQ_State oldstate = q->state; 2154 recvSetupResponse(m, msg->h.flags.b[1] & kDNSFlag1_RC_Mask, q, &opt->u.llq); 2155 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 2156 // We have a protocol anomaly here in the LLQ definition. 2157 // Both the challenge packet from the server and the ack+answers packet have opt->u.llq.llqOp == kLLQOp_Setup. 2158 // However, we need to treat them differently: 2159 // The challenge packet has no answers in it, and tells us nothing about whether our cache entries 2160 // are still valid, so this packet should not cause us to do anything that messes with our cache. 2161 // The ack+answers packet gives us the whole truth, so we should handle it by updating our cache 2162 // to match the answers in the packet, and only the answers in the packet. 2163 return (oldstate == LLQ_SecondaryRequest ? uDNS_LLQ_Entire : uDNS_LLQ_Ignore); 2164 } 2165 } 2166 } 2167 } 2168 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 2169 } 2170 return uDNS_LLQ_Not; 2171 } 2172 2173 // Stub definition of TCPSocket_struct so we can access flags field. (Rest of TCPSocket_struct is platform-dependent.) 2174 struct TCPSocket_struct { TCPSocketFlags flags; /* ... */ }; 2175 2176 // tcpCallback is called to handle events (e.g. connection opening and data reception) on TCP connections for 2177 // Private DNS operations -- private queries, private LLQs, private record updates and private service updates 2178 mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEstablished, mStatus err) 2179 { 2180 tcpInfo_t *tcpInfo = (tcpInfo_t *)context; 2181 mDNSBool closed = mDNSfalse; 2182 mDNS *m = tcpInfo->m; 2183 DNSQuestion *const q = tcpInfo->question; 2184 tcpInfo_t **backpointer = 2185 q ? &q ->tcp : 2186 tcpInfo->srs ? &tcpInfo->srs->tcp : 2187 tcpInfo->rr ? &tcpInfo->rr ->tcp : mDNSNULL; 2188 if (backpointer && *backpointer != tcpInfo) 2189 LogMsg("tcpCallback: %d backpointer %p incorrect tcpInfo %p question %p srs %p rr %p", 2190 mDNSPlatformTCPGetFD(tcpInfo->sock), *backpointer, tcpInfo, q, tcpInfo->srs, tcpInfo->rr); 2191 2192 if (err) goto exit; 2193 2194 if (ConnectionEstablished) 2195 { 2196 mDNSu8 *end = ((mDNSu8*) &tcpInfo->request) + tcpInfo->requestLen; 2197 DomainAuthInfo *AuthInfo; 2198 2199 // Defensive coding for <rdar://problem/5546824> Crash in mDNSResponder at GetAuthInfoForName_internal + 366 2200 // Don't know yet what's causing this, but at least we can be cautious and try to avoid crashing if we find our pointers in an unexpected state 2201 if (tcpInfo->srs && tcpInfo->srs->RR_SRV.resrec.name != &tcpInfo->srs->RR_SRV.namestorage) 2202 LogMsg("tcpCallback: ERROR: tcpInfo->srs->RR_SRV.resrec.name %p != &tcpInfo->srs->RR_SRV.namestorage %p", 2203 tcpInfo->srs->RR_SRV.resrec.name, &tcpInfo->srs->RR_SRV.namestorage); 2204 if (tcpInfo->rr && tcpInfo->rr->resrec.name != &tcpInfo->rr->namestorage) 2205 LogMsg("tcpCallback: ERROR: tcpInfo->rr->resrec.name %p != &tcpInfo->rr->namestorage %p", 2206 tcpInfo->rr->resrec.name, &tcpInfo->rr->namestorage); 2207 if (tcpInfo->srs && tcpInfo->srs->RR_SRV.resrec.name != &tcpInfo->srs->RR_SRV.namestorage) return; 2208 if (tcpInfo->rr && tcpInfo->rr-> resrec.name != &tcpInfo->rr-> namestorage) return; 2209 2210 AuthInfo = tcpInfo->srs ? GetAuthInfoForName(m, tcpInfo->srs->RR_SRV.resrec.name) : 2211 tcpInfo->rr ? GetAuthInfoForName(m, tcpInfo->rr->resrec.name) : mDNSNULL; 2212 2213 // connection is established - send the message 2214 if (q && q->LongLived && q->state == LLQ_Established) 2215 { 2216 end = ((mDNSu8*) &tcpInfo->request) + tcpInfo->requestLen; 2217 } 2218 else if (q && q->LongLived && q->state != LLQ_Poll && !mDNSIPPortIsZero(m->LLQNAT.ExternalPort) && !mDNSIPPortIsZero(q->servPort)) 2219 { 2220 // Notes: 2221 // If we have a NAT port mapping, ExternalPort is the external port 2222 // If we have a routable address so we don't need a port mapping, ExternalPort is the same as our own internal port 2223 // If we need a NAT port mapping but can't get one, then ExternalPort is zero 2224 LLQOptData llqData; // set llq rdata 2225 llqData.vers = kLLQ_Vers; 2226 llqData.llqOp = kLLQOp_Setup; 2227 llqData.err = GetLLQEventPort(m, &tcpInfo->Addr); // We're using TCP; tell server what UDP port to send notifications to 2228 LogInfo("tcpCallback: eventPort %d", llqData.err); 2229 llqData.id = zeroOpaque64; 2230 llqData.llqlease = kLLQ_DefLease; 2231 InitializeDNSMessage(&tcpInfo->request.h, q->TargetQID, uQueryFlags); 2232 end = putLLQ(&tcpInfo->request, tcpInfo->request.data, q, &llqData); 2233 if (!end) { LogMsg("ERROR: tcpCallback - putLLQ"); err = mStatus_UnknownErr; goto exit; } 2234 AuthInfo = q->AuthInfo; // Need to add TSIG to this message 2235 } 2236 else if (q) 2237 { 2238 InitializeDNSMessage(&tcpInfo->request.h, q->TargetQID, uQueryFlags); 2239 end = putQuestion(&tcpInfo->request, tcpInfo->request.data, tcpInfo->request.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass); 2240 AuthInfo = q->AuthInfo; // Need to add TSIG to this message 2241 } 2242 2243 err = mDNSSendDNSMessage(m, &tcpInfo->request, end, mDNSInterface_Any, mDNSNULL, &tcpInfo->Addr, tcpInfo->Port, sock, AuthInfo); 2244 if (err) { debugf("ERROR: tcpCallback: mDNSSendDNSMessage - %d", err); err = mStatus_UnknownErr; goto exit; } 2245 2246 // Record time we sent this question 2247 if (q) 2248 { 2249 mDNS_Lock(m); 2250 q->LastQTime = m->timenow; 2251 if (q->ThisQInterval < (256 * mDNSPlatformOneSecond)) // Now we have a TCP connection open, make sure we wait at least 256 seconds before retrying 2252 q->ThisQInterval = (256 * mDNSPlatformOneSecond); 2253 SetNextQueryTime(m, q); 2254 mDNS_Unlock(m); 2255 } 2256 } 2257 else 2258 { 2259 long n; 2260 if (tcpInfo->nread < 2) // First read the two-byte length preceeding the DNS message 2261 { 2262 mDNSu8 *lenptr = (mDNSu8 *)&tcpInfo->replylen; 2263 n = mDNSPlatformReadTCP(sock, lenptr + tcpInfo->nread, 2 - tcpInfo->nread, &closed); 2264 if (n < 0) { LogMsg("ERROR: tcpCallback - attempt to read message length failed (%d)", n); err = mStatus_ConnFailed; goto exit; } 2265 else if (closed) 2266 { 2267 // It's perfectly fine for this socket to close after the first reply. The server might 2268 // be sending gratuitous replies using UDP and doesn't have a need to leave the TCP socket open. 2269 // We'll only log this event if we've never received a reply before. 2270 // BIND 9 appears to close an idle connection after 30 seconds. 2271 if (tcpInfo->numReplies == 0) LogMsg("ERROR: socket closed prematurely tcpInfo->nread = %d", tcpInfo->nread); 2272 err = mStatus_ConnFailed; 2273 goto exit; 2274 } 2275 2276 tcpInfo->nread += n; 2277 if (tcpInfo->nread < 2) goto exit; 2278 2279 tcpInfo->replylen = (mDNSu16)((mDNSu16)lenptr[0] << 8 | lenptr[1]); 2280 if (tcpInfo->replylen < sizeof(DNSMessageHeader)) 2281 { LogMsg("ERROR: tcpCallback - length too short (%d bytes)", tcpInfo->replylen); err = mStatus_UnknownErr; goto exit; } 2282 2283 tcpInfo->reply = mDNSPlatformMemAllocate(tcpInfo->replylen); 2284 if (!tcpInfo->reply) { LogMsg("ERROR: tcpCallback - malloc failed"); err = mStatus_NoMemoryErr; goto exit; } 2285 } 2286 2287 n = mDNSPlatformReadTCP(sock, ((char *)tcpInfo->reply) + (tcpInfo->nread - 2), tcpInfo->replylen - (tcpInfo->nread - 2), &closed); 2288 2289 if (n < 0) { LogMsg("ERROR: tcpCallback - read returned %d", n); err = mStatus_ConnFailed; goto exit; } 2290 else if (closed) { LogMsg("ERROR: socket closed prematurely %d", tcpInfo->nread); err = mStatus_ConnFailed; goto exit; } 2291 2292 tcpInfo->nread += n; 2293 2294 if ((tcpInfo->nread - 2) == tcpInfo->replylen) 2295 { 2296 AuthRecord *rr = tcpInfo->rr; 2297 DNSMessage *reply = tcpInfo->reply; 2298 mDNSu8 *end = (mDNSu8 *)tcpInfo->reply + tcpInfo->replylen; 2299 mDNSAddr Addr = tcpInfo->Addr; 2300 mDNSIPPort Port = tcpInfo->Port; 2301 tcpInfo->numReplies++; 2302 tcpInfo->reply = mDNSNULL; // Detach reply buffer from tcpInfo_t, to make sure client callback can't cause it to be disposed 2303 tcpInfo->nread = 0; 2304 tcpInfo->replylen = 0; 2305 2306 // If we're going to dispose this connection, do it FIRST, before calling client callback 2307 // Note: Sleep code depends on us clearing *backpointer here -- it uses the clearing of rr->tcp and srs->tcp 2308 // as the signal that the DNS deregistration operation with the server has completed, and the machine may now sleep 2309 if (backpointer) 2310 if (!q || !q->LongLived || m->SleepState) 2311 { *backpointer = mDNSNULL; DisposeTCPConn(tcpInfo); } 2312 2313 if (rr && rr->resrec.RecordType == kDNSRecordTypeDeregistering) 2314 { 2315 mDNS_Lock(m); 2316 LogInfo("tcpCallback: CompleteDeregistration %s", ARDisplayString(m, rr)); 2317 CompleteDeregistration(m, rr); // Don't touch rr after this 2318 mDNS_Unlock(m); 2319 } 2320 else 2321 mDNSCoreReceive(m, reply, end, &Addr, Port, (sock->flags & kTCPSocketFlags_UseTLS) ? (mDNSAddr *)1 : mDNSNULL, zeroIPPort, 0); 2322 // USE CAUTION HERE: Invoking mDNSCoreReceive may have caused the environment to change, including canceling this operation itself 2323 2324 mDNSPlatformMemFree(reply); 2325 return; 2326 } 2327 } 2328 2329 exit: 2330 2331 if (err) 2332 { 2333 // Clear client backpointer FIRST -- that way if one of the callbacks cancels its operation 2334 // we won't end up double-disposing our tcpInfo_t 2335 if (backpointer) *backpointer = mDNSNULL; 2336 2337 mDNS_Lock(m); // Need to grab the lock to get m->timenow 2338 2339 if (q) 2340 { 2341 if (q->ThisQInterval == 0 || q->LastQTime + q->ThisQInterval - m->timenow > MAX_UCAST_POLL_INTERVAL) 2342 { 2343 q->LastQTime = m->timenow; 2344 q->ThisQInterval = MAX_UCAST_POLL_INTERVAL; 2345 SetNextQueryTime(m, q); 2346 } 2347 // ConnFailed may be actually okay. It just means that the server closed the connection but the LLQ may still be okay. 2348 // If the error isn't ConnFailed, then the LLQ is in bad shape. 2349 if (err != mStatus_ConnFailed) 2350 { 2351 if (q->LongLived && q->state != LLQ_Poll) StartLLQPolling(m, q); 2352 } 2353 } 2354 2355 if (tcpInfo->rr) SetRecordRetry(m, tcpInfo->rr, mStatus_NoError); 2356 2357 if (tcpInfo->srs) SetRecordRetry(m, &tcpInfo->srs->RR_SRV, mStatus_NoError); 2358 2359 mDNS_Unlock(m); 2360 2361 DisposeTCPConn(tcpInfo); 2362 } 2363 } 2364 2365 mDNSlocal tcpInfo_t *MakeTCPConn(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, 2366 TCPSocketFlags flags, const mDNSAddr *const Addr, const mDNSIPPort Port, 2367 DNSQuestion *const question, ServiceRecordSet *const srs, AuthRecord *const rr) 2368 { 2369 mStatus err; 2370 mDNSIPPort srcport = zeroIPPort; 2371 tcpInfo_t *info = (tcpInfo_t *)mDNSPlatformMemAllocate(sizeof(tcpInfo_t)); 2372 if (!info) { LogMsg("ERROR: MakeTCP - memallocate failed"); return(mDNSNULL); } 2373 mDNSPlatformMemZero(info, sizeof(tcpInfo_t)); 2374 2375 info->m = m; 2376 info->sock = mDNSPlatformTCPSocket(m, flags, &srcport); 2377 info->requestLen = 0; 2378 info->question = question; 2379 info->srs = srs; 2380 info->rr = rr; 2381 info->Addr = *Addr; 2382 info->Port = Port; 2383 info->reply = mDNSNULL; 2384 info->replylen = 0; 2385 info->nread = 0; 2386 info->numReplies = 0; 2387 2388 if (msg) 2389 { 2390 info->requestLen = (int) (end - ((mDNSu8*)msg)); 2391 mDNSPlatformMemCopy(&info->request, msg, info->requestLen); 2392 } 2393 2394 if (!info->sock) { LogMsg("SendServiceRegistration: unable to create TCP socket"); mDNSPlatformMemFree(info); return(mDNSNULL); } 2395 err = mDNSPlatformTCPConnect(info->sock, Addr, Port, 0, tcpCallback, info); 2396 2397 // Probably suboptimal here. 2398 // Instead of returning mDNSNULL here on failure, we should probably invoke the callback with an error code. 2399 // That way clients can put all the error handling and retry/recovery code in one place, 2400 // instead of having to handle immediate errors in one place and async errors in another. 2401 // Also: "err == mStatus_ConnEstablished" probably never happens. 2402 2403 // Don't need to log "connection failed" in customer builds -- it happens quite often during sleep, wake, configuration changes, etc. 2404 if (err == mStatus_ConnEstablished) { tcpCallback(info->sock, info, mDNStrue, mStatus_NoError); } 2405 else if (err != mStatus_ConnPending ) { LogInfo("MakeTCPConnection: connection failed"); DisposeTCPConn(info); return(mDNSNULL); } 2406 return(info); 2407 } 2408 2409 mDNSexport void DisposeTCPConn(struct tcpInfo_t *tcp) 2410 { 2411 mDNSPlatformTCPCloseConnection(tcp->sock); 2412 if (tcp->reply) mDNSPlatformMemFree(tcp->reply); 2413 mDNSPlatformMemFree(tcp); 2414 } 2415 2416 // Lock must be held 2417 mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q) 2418 { 2419 if (mDNSIPv4AddressIsOnes(m->LLQNAT.ExternalAddress)) 2420 { 2421 LogInfo("startLLQHandshake: waiting for NAT status for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 2422 q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10); // Retry in approx 15 minutes 2423 q->LastQTime = m->timenow; 2424 SetNextQueryTime(m, q); 2425 return; 2426 } 2427 2428 if (mDNSIPPortIsZero(m->LLQNAT.ExternalPort)) 2429 { 2430 LogInfo("startLLQHandshake: Cannot receive inbound packets; will poll for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 2431 StartLLQPolling(m, q); 2432 return; 2433 } 2434 2435 if (mDNSIPPortIsZero(q->servPort)) 2436 { 2437 debugf("startLLQHandshake: StartGetZoneData for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 2438 q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10); // Retry in approx 15 minutes 2439 q->LastQTime = m->timenow; 2440 SetNextQueryTime(m, q); 2441 q->servAddr = zeroAddr; 2442 // We know q->servPort is zero because of check above 2443 if (q->nta) CancelGetZoneData(m, q->nta); 2444 q->nta = StartGetZoneData(m, &q->qname, ZoneServiceLLQ, LLQGotZoneData, q); 2445 return; 2446 } 2447 2448 if (q->AuthInfo) 2449 { 2450 if (q->tcp) LogInfo("startLLQHandshake: Disposing existing TCP connection for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 2451 if (q->tcp) DisposeTCPConn(q->tcp); 2452 q->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_UseTLS, &q->servAddr, q->servPort, q, mDNSNULL, mDNSNULL); 2453 if (!q->tcp) 2454 q->ThisQInterval = mDNSPlatformOneSecond * 5; // If TCP failed (transient networking glitch) try again in five seconds 2455 else 2456 { 2457 q->state = LLQ_SecondaryRequest; // Right now, for private DNS, we skip the four-way LLQ handshake 2458 q->ReqLease = kLLQ_DefLease; 2459 q->ThisQInterval = 0; 2460 } 2461 q->LastQTime = m->timenow; 2462 SetNextQueryTime(m, q); 2463 } 2464 else 2465 { 2466 debugf("startLLQHandshake: m->AdvertisedV4 %#a%s Server %#a:%d%s %##s (%s)", 2467 &m->AdvertisedV4, mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) ? " (RFC 1918)" : "", 2468 &q->servAddr, mDNSVal16(q->servPort), mDNSAddrIsRFC1918(&q->servAddr) ? " (RFC 1918)" : "", 2469 q->qname.c, DNSTypeName(q->qtype)); 2470 2471 if (q->ntries++ >= kLLQ_MAX_TRIES) 2472 { 2473 LogMsg("startLLQHandshake: %d failed attempts for LLQ %##s Polling.", kLLQ_MAX_TRIES, q->qname.c); 2474 StartLLQPolling(m, q); 2475 } 2476 else 2477 { 2478 mDNSu8 *end; 2479 LLQOptData llqData; 2480 2481 // set llq rdata 2482 llqData.vers = kLLQ_Vers; 2483 llqData.llqOp = kLLQOp_Setup; 2484 llqData.err = LLQErr_NoError; // Don't need to tell server UDP notification port when sending over UDP 2485 llqData.id = zeroOpaque64; 2486 llqData.llqlease = kLLQ_DefLease; 2487 2488 InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags); 2489 end = putLLQ(&m->omsg, m->omsg.data, q, &llqData); 2490 if (!end) { LogMsg("ERROR: startLLQHandshake - putLLQ"); StartLLQPolling(m,q); return; } 2491 2492 mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, q->LocalSocket, &q->servAddr, q->servPort, mDNSNULL, mDNSNULL); 2493 2494 // update question state 2495 q->state = LLQ_InitialRequest; 2496 q->ReqLease = kLLQ_DefLease; 2497 q->ThisQInterval = (kLLQ_INIT_RESEND * mDNSPlatformOneSecond); 2498 q->LastQTime = m->timenow; 2499 SetNextQueryTime(m, q); 2500 } 2501 } 2502 } 2503 2504 // forward declaration so GetServiceTarget can do reverse lookup if needed 2505 mDNSlocal void GetStaticHostname(mDNS *m); 2506 2507 mDNSexport const domainname *GetServiceTarget(mDNS *m, AuthRecord *const rr) 2508 { 2509 debugf("GetServiceTarget %##s", rr->resrec.name->c); 2510 2511 if (!rr->AutoTarget) // If not automatically tracking this host's current name, just return the existing target 2512 return(&rr->resrec.rdata->u.srv.target); 2513 else 2514 { 2515 #if APPLE_OSX_mDNSResponder 2516 DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, rr->resrec.name); 2517 if (AuthInfo && AuthInfo->AutoTunnel) 2518 { 2519 // If this AutoTunnel is not yet active, start it now (which entails activating its NAT Traversal request, 2520 // which will subsequently advertise the appropriate records when the NAT Traversal returns a result) 2521 if (!AuthInfo->AutoTunnelNAT.clientContext && m->AutoTunnelHostAddr.b[0]) 2522 SetupLocalAutoTunnelInterface_internal(m); 2523 if (AuthInfo->AutoTunnelHostRecord.namestorage.c[0] == 0) return(mDNSNULL); 2524 return(&AuthInfo->AutoTunnelHostRecord.namestorage); 2525 } 2526 else 2527 #endif // APPLE_OSX_mDNSResponder 2528 { 2529 const int srvcount = CountLabels(rr->resrec.name); 2530 HostnameInfo *besthi = mDNSNULL, *hi; 2531 int best = 0; 2532 for (hi = m->Hostnames; hi; hi = hi->next) 2533 if (hi->arv4.state == regState_Registered || hi->arv4.state == regState_Refresh || 2534 hi->arv6.state == regState_Registered || hi->arv6.state == regState_Refresh) 2535 { 2536 int x, hostcount = CountLabels(&hi->fqdn); 2537 for (x = hostcount < srvcount ? hostcount : srvcount; x > 0 && x > best; x--) 2538 if (SameDomainName(SkipLeadingLabels(rr->resrec.name, srvcount - x), SkipLeadingLabels(&hi->fqdn, hostcount - x))) 2539 { best = x; besthi = hi; } 2540 } 2541 2542 if (besthi) return(&besthi->fqdn); 2543 } 2544 if (m->StaticHostname.c[0]) return(&m->StaticHostname); 2545 else GetStaticHostname(m); // asynchronously do reverse lookup for primary IPv4 address 2546 return(mDNSNULL); 2547 } 2548 } 2549 2550 // Called with lock held 2551 mDNSlocal void SendServiceRegistration(mDNS *m, ServiceRecordSet *srs) 2552 { 2553 mDNSu8 *ptr = m->omsg.data; 2554 mDNSu8 *end = (mDNSu8 *)&m->omsg + sizeof(DNSMessage); 2555 mDNSOpaque16 id; 2556 mStatus err = mStatus_NoError; 2557 const domainname *target; 2558 mDNSu32 i; 2559 2560 if (m->mDNS_busy != m->mDNS_reentrancy+1) 2561 LogMsg("SendServiceRegistration: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 2562 2563 if (mDNSIPv4AddressIsZero(srs->SRSUpdateServer.ip.v4)) // Don't know our UpdateServer yet 2564 { 2565 srs->RR_SRV.LastAPTime = m->timenow; 2566 if (srs->RR_SRV.ThisAPInterval < mDNSPlatformOneSecond * 5) 2567 srs->RR_SRV.ThisAPInterval = mDNSPlatformOneSecond * 5; 2568 return; 2569 } 2570 2571 if (srs->state == regState_Registered) srs->state = regState_Refresh; 2572 2573 id = mDNS_NewMessageID(m); 2574 InitializeDNSMessage(&m->omsg.h, id, UpdateReqFlags); 2575 2576 // setup resource records 2577 SetNewRData(&srs->RR_PTR.resrec, mDNSNULL, 0); // Update rdlength, rdestimate, rdatahash 2578 SetNewRData(&srs->RR_TXT.resrec, mDNSNULL, 0); // Update rdlength, rdestimate, rdatahash 2579 2580 // replace port w/ NAT mapping if necessary 2581 if (srs->RR_SRV.AutoTarget == Target_AutoHostAndNATMAP && !mDNSIPPortIsZero(srs->NATinfo.ExternalPort)) 2582 srs->RR_SRV.resrec.rdata->u.srv.port = srs->NATinfo.ExternalPort; 2583 2584 // construct update packet 2585 // set zone 2586 ptr = putZone(&m->omsg, ptr, end, &srs->zone, mDNSOpaque16fromIntVal(srs->RR_SRV.resrec.rrclass)); 2587 if (!ptr) { err = mStatus_UnknownErr; goto exit; } 2588 2589 if (srs->TestForSelfConflict) 2590 { 2591 // update w/ prereq that SRV already exist to make sure previous registration was ours, and delete any stale TXT records 2592 if (!(ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numPrereqs, &srs->RR_SRV.resrec, 0))) { err = mStatus_UnknownErr; goto exit; } 2593 if (!(ptr = putDeleteRRSet(&m->omsg, ptr, srs->RR_TXT.resrec.name, srs->RR_TXT.resrec.rrtype))) { err = mStatus_UnknownErr; goto exit; } 2594 } 2595 2596 else if (srs->state != regState_Refresh && srs->state != regState_UpdatePending) 2597 { 2598 // use SRV name for prereq 2599 //ptr = putPrereqNameNotInUse(srs->RR_SRV.resrec.name, &m->omsg, ptr, end); 2600 2601 // For now, until we implement RFC 4701 (DHCID RR) to detect whether an existing record is someone else using the name, or just a 2602 // stale echo of our own previous registration before we changed our host name, we just overwrite whatever may have already been there 2603 ptr = putDeleteRRSet(&m->omsg, ptr, srs->RR_SRV.resrec.name, kDNSQType_ANY); 2604 if (!ptr) { err = mStatus_UnknownErr; goto exit; } 2605 } 2606 2607 //!!!KRS Need to do bounds checking and use TCP if it won't fit!!! 2608 if (!(ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &srs->RR_PTR.resrec, srs->RR_PTR.resrec.rroriginalttl))) { err = mStatus_UnknownErr; goto exit; } 2609 2610 for (i = 0; i < srs->NumSubTypes; i++) 2611 if (!(ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &srs->SubTypes[i].resrec, srs->SubTypes[i].resrec.rroriginalttl))) { err = mStatus_UnknownErr; goto exit; } 2612 2613 if (srs->state == regState_UpdatePending) // we're updating the txt record 2614 { 2615 AuthRecord *txt = &srs->RR_TXT; 2616 // delete old RData 2617 SetNewRData(&txt->resrec, txt->OrigRData, txt->OrigRDLen); 2618 if (!(ptr = putDeletionRecord(&m->omsg, ptr, &srs->RR_TXT.resrec))) { err = mStatus_UnknownErr; goto exit; } // delete old rdata 2619 2620 // add new RData 2621 SetNewRData(&txt->resrec, txt->InFlightRData, txt->InFlightRDLen); 2622 if (!(ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &srs->RR_TXT.resrec, srs->RR_TXT.resrec.rroriginalttl))) { err = mStatus_UnknownErr; goto exit; } 2623 } 2624 else 2625 if (!(ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &srs->RR_TXT.resrec, srs->RR_TXT.resrec.rroriginalttl))) { err = mStatus_UnknownErr; goto exit; } 2626 2627 target = GetServiceTarget(m, &srs->RR_SRV); 2628 if (!target || target->c[0] == 0) 2629 { 2630 debugf("SendServiceRegistration - no target for %##s", srs->RR_SRV.resrec.name->c); 2631 srs->state = regState_NoTarget; 2632 return; 2633 } 2634 2635 if (!SameDomainName(target, &srs->RR_SRV.resrec.rdata->u.srv.target)) 2636 { 2637 AssignDomainName(&srs->RR_SRV.resrec.rdata->u.srv.target, target); 2638 SetNewRData(&srs->RR_SRV.resrec, mDNSNULL, 0); // Update rdlength, rdestimate, rdatahash 2639 } 2640 2641 ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &srs->RR_SRV.resrec, srs->RR_SRV.resrec.rroriginalttl); 2642 if (!ptr) { err = mStatus_UnknownErr; goto exit; } 2643 2644 if (srs->srs_uselease) 2645 { ptr = putUpdateLease(&m->omsg, ptr, DEFAULT_UPDATE_LEASE); if (!ptr) { err = mStatus_UnknownErr; goto exit; } } 2646 2647 if (srs->state != regState_Refresh && srs->state != regState_DeregDeferred && srs->state != regState_UpdatePending) 2648 srs->state = regState_Pending; 2649 2650 srs->id = id; 2651 2652 if (srs->Private) 2653 { 2654 if (srs->tcp) LogInfo("SendServiceRegistration: Disposing existing TCP connection for %s", ARDisplayString(m, &srs->RR_SRV)); 2655 if (srs->tcp) DisposeTCPConn(srs->tcp); 2656 srs->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, srs, mDNSNULL); 2657 if (!srs->tcp) srs->RR_SRV.ThisAPInterval = mDNSPlatformOneSecond * 5; // If failed to make TCP connection, try again in ten seconds (5*2) 2658 else if (srs->RR_SRV.ThisAPInterval < mDNSPlatformOneSecond * 30) srs->RR_SRV.ThisAPInterval = mDNSPlatformOneSecond * 30; 2659 } 2660 else 2661 { 2662 err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, srs->RR_SRV.resrec.name)); 2663 if (err) debugf("ERROR: SendServiceRegistration - mDNSSendDNSMessage - %d", err); 2664 } 2665 2666 SetRecordRetry(m, &srs->RR_SRV, err); 2667 return; 2668 2669 exit: 2670 if (err) 2671 { 2672 LogMsg("SendServiceRegistration ERROR formatting message %d!! Permanently abandoning service registration %##s", err, srs->RR_SRV.resrec.name->c); 2673 unlinkSRS(m, srs); 2674 srs->state = regState_Unregistered; 2675 2676 mDNS_DropLockBeforeCallback(); 2677 srs->ServiceCallback(m, srs, err); 2678 mDNS_ReclaimLockAfterCallback(); 2679 // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function 2680 // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc. 2681 } 2682 } 2683 2684 mDNSlocal const domainname *PUBLIC_UPDATE_SERVICE_TYPE = (const domainname*)"\x0B_dns-update" "\x04_udp"; 2685 mDNSlocal const domainname *PUBLIC_LLQ_SERVICE_TYPE = (const domainname*)"\x08_dns-llq" "\x04_udp"; 2686 2687 mDNSlocal const domainname *PRIVATE_UPDATE_SERVICE_TYPE = (const domainname*)"\x0F_dns-update-tls" "\x04_tcp"; 2688 mDNSlocal const domainname *PRIVATE_QUERY_SERVICE_TYPE = (const domainname*)"\x0E_dns-query-tls" "\x04_tcp"; 2689 mDNSlocal const domainname *PRIVATE_LLQ_SERVICE_TYPE = (const domainname*)"\x0C_dns-llq-tls" "\x04_tcp"; 2690 2691 #define ZoneDataSRV(X) (\ 2692 (X)->ZoneService == ZoneServiceUpdate ? ((X)->ZonePrivate ? PRIVATE_UPDATE_SERVICE_TYPE : PUBLIC_UPDATE_SERVICE_TYPE) : \ 2693 (X)->ZoneService == ZoneServiceQuery ? ((X)->ZonePrivate ? PRIVATE_QUERY_SERVICE_TYPE : (const domainname*)"" ) : \ 2694 (X)->ZoneService == ZoneServiceLLQ ? ((X)->ZonePrivate ? PRIVATE_LLQ_SERVICE_TYPE : PUBLIC_LLQ_SERVICE_TYPE ) : (const domainname*)"") 2695 2696 // Forward reference: GetZoneData_StartQuery references GetZoneData_QuestionCallback, and 2697 // GetZoneData_QuestionCallback calls GetZoneData_StartQuery 2698 mDNSlocal mStatus GetZoneData_StartQuery(mDNS *const m, ZoneData *zd, mDNSu16 qtype); 2699 2700 // GetZoneData_QuestionCallback is called from normal client callback context (core API calls allowed) 2701 mDNSlocal void GetZoneData_QuestionCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) 2702 { 2703 ZoneData *zd = (ZoneData*)question->QuestionContext; 2704 2705 debugf("GetZoneData_QuestionCallback: %s %s", AddRecord ? "Add" : "Rmv", RRDisplayString(m, answer)); 2706 2707 if (!AddRecord) return; // Don't care about REMOVE events 2708 if (AddRecord == QC_addnocache && answer->rdlength == 0) return; // Don't care about transient failure indications 2709 if (answer->rrtype != question->qtype) return; // Don't care about CNAMEs 2710 2711 if (answer->rrtype == kDNSType_SOA) 2712 { 2713 debugf("GetZoneData GOT SOA %s", RRDisplayString(m, answer)); 2714 mDNS_StopQuery(m, question); 2715 if (answer->rdlength) 2716 { 2717 AssignDomainName(&zd->ZoneName, answer->name); 2718 zd->ZoneClass = answer->rrclass; 2719 AssignDomainName(&zd->question.qname, &zd->ZoneName); 2720 GetZoneData_StartQuery(m, zd, kDNSType_SRV); 2721 } 2722 else if (zd->CurrentSOA->c[0]) 2723 { 2724 zd->CurrentSOA = (domainname *)(zd->CurrentSOA->c + zd->CurrentSOA->c[0]+1); 2725 AssignDomainName(&zd->question.qname, zd->CurrentSOA); 2726 GetZoneData_StartQuery(m, zd, kDNSType_SOA); 2727 } 2728 else 2729 { 2730 LogInfo("GetZoneData recursed to root label of %##s without finding SOA", zd->ChildName.c); 2731 zd->ZoneDataCallback(m, mStatus_NoSuchNameErr, zd); 2732 mDNSPlatformMemFree(zd); 2733 } 2734 } 2735 else if (answer->rrtype == kDNSType_SRV) 2736 { 2737 debugf("GetZoneData GOT SRV %s", RRDisplayString(m, answer)); 2738 mDNS_StopQuery(m, question); 2739 // Right now we don't want to fail back to non-encrypted operations 2740 // If the AuthInfo has the AutoTunnel field set, then we want private or nothing 2741 // <rdar://problem/5687667> BTMM: Don't fallback to unencrypted operations when SRV lookup fails 2742 #if 0 2743 if (!answer->rdlength && zd->ZonePrivate && zd->ZoneService != ZoneServiceQuery) 2744 { 2745 zd->ZonePrivate = mDNSfalse; // Causes ZoneDataSRV() to yield a different SRV name when building the query 2746 GetZoneData_StartQuery(m, zd, kDNSType_SRV); // Try again, non-private this time 2747 } 2748 else 2749 #endif 2750 { 2751 if (answer->rdlength) 2752 { 2753 AssignDomainName(&zd->Host, &answer->rdata->u.srv.target); 2754 zd->Port = answer->rdata->u.srv.port; 2755 AssignDomainName(&zd->question.qname, &zd->Host); 2756 GetZoneData_StartQuery(m, zd, kDNSType_A); 2757 } 2758 else 2759 { 2760 zd->ZonePrivate = mDNSfalse; 2761 zd->Host.c[0] = 0; 2762 zd->Port = zeroIPPort; 2763 zd->Addr = zeroAddr; 2764 zd->ZoneDataCallback(m, mStatus_NoError, zd); 2765 mDNSPlatformMemFree(zd); 2766 } 2767 } 2768 } 2769 else if (answer->rrtype == kDNSType_A) 2770 { 2771 debugf("GetZoneData GOT A %s", RRDisplayString(m, answer)); 2772 mDNS_StopQuery(m, question); 2773 zd->Addr.type = mDNSAddrType_IPv4; 2774 zd->Addr.ip.v4 = (answer->rdlength == 4) ? answer->rdata->u.ipv4 : zerov4Addr; 2775 // In order to simulate firewalls blocking our outgoing TCP connections, returning immediate ICMP errors or TCP resets, 2776 // the code below will make us try to connect to loopback, resulting in an immediate "port unreachable" failure. 2777 // This helps us test to make sure we handle this case gracefully 2778 // <rdar://problem/5607082> BTMM: mDNSResponder taking 100 percent CPU after upgrading to 10.5.1 2779 #if 0 2780 zd->Addr.ip.v4.b[0] = 127; 2781 zd->Addr.ip.v4.b[1] = 0; 2782 zd->Addr.ip.v4.b[2] = 0; 2783 zd->Addr.ip.v4.b[3] = 1; 2784 #endif 2785 zd->ZoneDataCallback(m, mStatus_NoError, zd); 2786 mDNSPlatformMemFree(zd); 2787 } 2788 } 2789 2790 // GetZoneData_StartQuery is called from normal client context (lock not held, or client callback) 2791 mDNSlocal mStatus GetZoneData_StartQuery(mDNS *const m, ZoneData *zd, mDNSu16 qtype) 2792 { 2793 if (qtype == kDNSType_SRV) 2794 { 2795 AssignDomainName(&zd->question.qname, ZoneDataSRV(zd)); 2796 AppendDomainName(&zd->question.qname, &zd->ZoneName); 2797 debugf("lookupDNSPort %##s", zd->question.qname.c); 2798 } 2799 2800 zd->question.ThisQInterval = -1; // So that GetZoneData_QuestionCallback() knows whether to cancel this question (Is this necessary?) 2801 zd->question.InterfaceID = mDNSInterface_Any; 2802 zd->question.Target = zeroAddr; 2803 //zd->question.qname.c[0] = 0; // Already set 2804 zd->question.qtype = qtype; 2805 zd->question.qclass = kDNSClass_IN; 2806 zd->question.LongLived = mDNSfalse; 2807 zd->question.ExpectUnique = mDNStrue; 2808 zd->question.ForceMCast = mDNSfalse; 2809 zd->question.ReturnIntermed = mDNStrue; 2810 zd->question.QuestionCallback = GetZoneData_QuestionCallback; 2811 zd->question.QuestionContext = zd; 2812 2813 //LogMsg("GetZoneData_StartQuery %##s (%s) %p", zd->question.qname.c, DNSTypeName(zd->question.qtype), zd->question.Private); 2814 return(mDNS_StartQuery(m, &zd->question)); 2815 } 2816 2817 // StartGetZoneData is an internal routine (i.e. must be called with the lock already held) 2818 mDNSexport ZoneData *StartGetZoneData(mDNS *const m, const domainname *const name, const ZoneService target, ZoneDataCallback callback, void *ZoneDataContext) 2819 { 2820 DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, name); 2821 int initialskip = (AuthInfo && AuthInfo->AutoTunnel) ? DomainNameLength(name) - DomainNameLength(&AuthInfo->domain) : 0; 2822 ZoneData *zd = (ZoneData*)mDNSPlatformMemAllocate(sizeof(ZoneData)); 2823 if (!zd) { LogMsg("ERROR: StartGetZoneData - mDNSPlatformMemAllocate failed"); return mDNSNULL; } 2824 mDNSPlatformMemZero(zd, sizeof(ZoneData)); 2825 AssignDomainName(&zd->ChildName, name); 2826 zd->ZoneService = target; 2827 zd->CurrentSOA = (domainname *)(&zd->ChildName.c[initialskip]); 2828 zd->ZoneName.c[0] = 0; 2829 zd->ZoneClass = 0; 2830 zd->Host.c[0] = 0; 2831 zd->Port = zeroIPPort; 2832 zd->Addr = zeroAddr; 2833 zd->ZonePrivate = AuthInfo && AuthInfo->AutoTunnel ? mDNStrue : mDNSfalse; 2834 zd->ZoneDataCallback = callback; 2835 zd->ZoneDataContext = ZoneDataContext; 2836 2837 zd->question.QuestionContext = zd; 2838 AssignDomainName(&zd->question.qname, zd->CurrentSOA); 2839 2840 mDNS_DropLockBeforeCallback(); // GetZoneData_StartQuery expects to be called from a normal callback, so we emulate that here 2841 GetZoneData_StartQuery(m, zd, kDNSType_SOA); 2842 mDNS_ReclaimLockAfterCallback(); 2843 2844 return zd; 2845 } 2846 2847 // GetZoneData queries are a special case -- even if we have a key for them, we don't do them privately, 2848 // because that would result in an infinite loop (i.e. to do a private query we first need to get 2849 // the _dns-query-tls SRV record for the zone, and we can't do *that* privately because to do so 2850 // we'd need to already know the _dns-query-tls SRV record. 2851 // Also, as a general rule, we never do SOA queries privately 2852 mDNSexport DomainAuthInfo *GetAuthInfoForQuestion(mDNS *m, const DNSQuestion *const q) // Must be called with lock held 2853 { 2854 if (q->QuestionCallback == GetZoneData_QuestionCallback) return(mDNSNULL); 2855 if (q->qtype == kDNSType_SOA ) return(mDNSNULL); 2856 return(GetAuthInfoForName_internal(m, &q->qname)); 2857 } 2858 2859 // *************************************************************************** 2860 #if COMPILER_LIKES_PRAGMA_MARK 2861 #pragma mark - host name and interface management 2862 #endif 2863 2864 // Called in normal client context (lock not held) 2865 mDNSlocal void CompleteSRVNatMap(mDNS *m, NATTraversalInfo *n) 2866 { 2867 ServiceRecordSet *srs = (ServiceRecordSet *)n->clientContext; 2868 debugf("SRVNatMap complete %.4a IntPort %u ExternalPort %u NATLease %u", &n->ExternalAddress, mDNSVal16(n->IntPort), mDNSVal16(n->ExternalPort), n->NATLease); 2869 2870 if (!srs) { LogMsg("CompleteSRVNatMap called with unknown ServiceRecordSet object"); return; } 2871 if (!n->NATLease) return; 2872 2873 mDNS_Lock(m); 2874 if (!mDNSIPv4AddressIsZero(srs->SRSUpdateServer.ip.v4)) 2875 SendServiceRegistration(m, srs); // non-zero server address means we already have necessary zone data to send update 2876 else 2877 { 2878 // SHOULD NEVER HAPPEN! 2879 LogInfo("ERROR: CompleteSRVNatMap called but srs->SRSUpdateServer.ip.v4 is zero!"); 2880 srs->state = regState_FetchingZoneData; 2881 if (srs->srs_nta) CancelGetZoneData(m, srs->srs_nta); // Make sure we cancel old one before we start a new one 2882 srs->srs_nta = StartGetZoneData(m, srs->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, srs); 2883 } 2884 mDNS_Unlock(m); 2885 } 2886 2887 mDNSlocal void StartSRVNatMap(mDNS *m, ServiceRecordSet *srs) 2888 { 2889 const mDNSu8 *p = srs->RR_PTR.resrec.name->c; 2890 if (p[0]) p += 1 + p[0]; 2891 if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_tcp")) srs->NATinfo.Protocol = NATOp_MapTCP; 2892 else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp")) srs->NATinfo.Protocol = NATOp_MapUDP; 2893 else { LogMsg("StartSRVNatMap: could not determine transport protocol of service %##s", srs->RR_SRV.resrec.name->c); return; } 2894 2895 if (srs->NATinfo.clientContext) mDNS_StopNATOperation_internal(m, &srs->NATinfo); 2896 // Don't try to set IntPort here -- 2897 // SendServiceRegistration overwrites srs->RR_SRV.resrec.rdata->u.srv.port with external (mapped) port number 2898 //srs->NATinfo.IntPort = srs->RR_SRV.resrec.rdata->u.srv.port; 2899 srs->NATinfo.RequestedPort = srs->RR_SRV.resrec.rdata->u.srv.port; 2900 srs->NATinfo.NATLease = 0; // Request default lease 2901 srs->NATinfo.clientCallback = CompleteSRVNatMap; 2902 srs->NATinfo.clientContext = srs; 2903 mDNS_StartNATOperation_internal(m, &srs->NATinfo); 2904 } 2905 2906 // Called in normal callback context (i.e. mDNS_busy and mDNS_reentrancy are both 1) 2907 mDNSexport void ServiceRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData) 2908 { 2909 ServiceRecordSet *srs = (ServiceRecordSet *)zoneData->ZoneDataContext; 2910 2911 if (m->mDNS_busy != m->mDNS_reentrancy) 2912 LogMsg("ServiceRegistrationGotZoneData: mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 2913 2914 if (!srs->RR_SRV.resrec.rdata) 2915 { LogMsg("ServiceRegistrationGotZoneData: ERROR: srs->RR_SRV.resrec.rdata is NULL"); return; } 2916 2917 srs->srs_nta = mDNSNULL; 2918 2919 // Start off assuming we're going to use a lease 2920 // If we get an error from the server, and the update port as given in the SRV record is 53, then we'll retry without the lease option 2921 srs->srs_uselease = mDNStrue; 2922 2923 if (err || !zoneData) return; 2924 2925 if (mDNSIPPortIsZero(zoneData->Port) || mDNSAddressIsZero(&zoneData->Addr)) return; 2926 2927 // cache zone data 2928 AssignDomainName(&srs->zone, &zoneData->ZoneName); 2929 srs->SRSUpdateServer.type = mDNSAddrType_IPv4; 2930 srs->SRSUpdateServer = zoneData->Addr; 2931 srs->SRSUpdatePort = zoneData->Port; 2932 srs->Private = zoneData->ZonePrivate; 2933 2934 srs->RR_SRV.LastAPTime = m->timenow; 2935 srs->RR_SRV.ThisAPInterval = 0; 2936 2937 debugf("ServiceRegistrationGotZoneData My IPv4 %#a%s Server %#a:%d%s for %##s", 2938 &m->AdvertisedV4, mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) ? " (RFC1918)" : "", 2939 &srs->SRSUpdateServer, mDNSVal16(srs->SRSUpdatePort), mDNSAddrIsRFC1918(&srs->SRSUpdateServer) ? " (RFC1918)" : "", 2940 srs->RR_SRV.resrec.name->c); 2941 2942 // If we have non-zero service port (always?) 2943 // and a private address, and update server is non-private 2944 // and this service is AutoTarget 2945 // then initiate a NAT mapping request. On completion it will do SendServiceRegistration() for us 2946 if (!mDNSIPPortIsZero(srs->RR_SRV.resrec.rdata->u.srv.port) && 2947 mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) && !mDNSAddrIsRFC1918(&srs->SRSUpdateServer) && 2948 srs->RR_SRV.AutoTarget == Target_AutoHostAndNATMAP) 2949 { 2950 srs->state = regState_NATMap; 2951 debugf("ServiceRegistrationGotZoneData StartSRVNatMap"); 2952 StartSRVNatMap(m, srs); 2953 } 2954 else 2955 { 2956 mDNS_Lock(m); 2957 SendServiceRegistration(m, srs); 2958 mDNS_Unlock(m); 2959 } 2960 } 2961 2962 mDNSlocal void SendServiceDeregistration(mDNS *m, ServiceRecordSet *srs) 2963 { 2964 mDNSOpaque16 id; 2965 mDNSu8 *ptr = m->omsg.data; 2966 mDNSu8 *end = (mDNSu8 *)&m->omsg + sizeof(DNSMessage); 2967 mStatus err = mStatus_UnknownErr; 2968 mDNSu32 i; 2969 2970 if (mDNSIPv4AddressIsZero(srs->SRSUpdateServer.ip.v4)) // Don't know our UpdateServer yet 2971 { 2972 srs->RR_SRV.LastAPTime = m->timenow; 2973 if (srs->RR_SRV.ThisAPInterval < mDNSPlatformOneSecond * 5) 2974 srs->RR_SRV.ThisAPInterval = mDNSPlatformOneSecond * 5; 2975 return; 2976 } 2977 2978 id = mDNS_NewMessageID(m); 2979 InitializeDNSMessage(&m->omsg.h, id, UpdateReqFlags); 2980 2981 // put zone 2982 ptr = putZone(&m->omsg, ptr, end, &srs->zone, mDNSOpaque16fromIntVal(srs->RR_SRV.resrec.rrclass)); 2983 if (!ptr) { LogMsg("ERROR: SendServiceDeregistration - putZone"); err = mStatus_UnknownErr; goto exit; } 2984 2985 if (!(ptr = putDeleteAllRRSets(&m->omsg, ptr, srs->RR_SRV.resrec.name))) { err = mStatus_UnknownErr; goto exit; } // this deletes SRV, TXT, and Extras 2986 if (!(ptr = putDeletionRecord(&m->omsg, ptr, &srs->RR_PTR.resrec))) { err = mStatus_UnknownErr; goto exit; } 2987 for (i = 0; i < srs->NumSubTypes; i++) 2988 if (!(ptr = putDeletionRecord(&m->omsg, ptr, &srs->SubTypes[i].resrec))) { err = mStatus_UnknownErr; goto exit; } 2989 2990 srs->id = id; 2991 srs->state = regState_DeregPending; 2992 srs->RR_SRV.expire = 0; // Indicate that we have no active registration any more 2993 2994 if (srs->Private) 2995 { 2996 LogInfo("SendServiceDeregistration TCP %p %s", srs->tcp, ARDisplayString(m, &srs->RR_SRV)); 2997 if (srs->tcp) LogInfo("SendServiceDeregistration: Disposing existing TCP connection for %s", ARDisplayString(m, &srs->RR_SRV)); 2998 if (srs->tcp) DisposeTCPConn(srs->tcp); 2999 srs->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, srs, mDNSNULL); 3000 if (!srs->tcp) srs->RR_SRV.ThisAPInterval = mDNSPlatformOneSecond * 5; // If failed to make TCP connection, try again in ten seconds (5*2) 3001 else if (srs->RR_SRV.ThisAPInterval < mDNSPlatformOneSecond * 30) srs->RR_SRV.ThisAPInterval = mDNSPlatformOneSecond * 30; 3002 } 3003 else 3004 { 3005 err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, srs->RR_SRV.resrec.name)); 3006 if (err && err != mStatus_TransientErr) { debugf("ERROR: SendServiceDeregistration - mDNSSendDNSMessage - %d", err); goto exit; } 3007 } 3008 3009 SetRecordRetry(m, &srs->RR_SRV, err); 3010 return; 3011 3012 exit: 3013 if (err) 3014 { 3015 LogMsg("SendServiceDeregistration ERROR formatting message %d!! Permanently abandoning service registration %##s", err, srs->RR_SRV.resrec.name->c); 3016 unlinkSRS(m, srs); 3017 srs->state = regState_Unregistered; 3018 } 3019 } 3020 3021 // Called with lock held 3022 mDNSlocal void UpdateSRV(mDNS *m, ServiceRecordSet *srs) 3023 { 3024 ExtraResourceRecord *e; 3025 3026 // Target change if: 3027 // We have a target and were previously waiting for one, or 3028 // We had a target and no longer do, or 3029 // The target has changed 3030 3031 domainname *curtarget = &srs->RR_SRV.resrec.rdata->u.srv.target; 3032 const domainname *const nt = GetServiceTarget(m, &srs->RR_SRV); 3033 const domainname *const newtarget = nt ? nt : (domainname*)""; 3034 mDNSBool TargetChanged = (newtarget->c[0] && srs->state == regState_NoTarget) || !SameDomainName(curtarget, newtarget); 3035 mDNSBool HaveZoneData = !mDNSIPv4AddressIsZero(srs->SRSUpdateServer.ip.v4); 3036 3037 // Nat state change if: 3038 // We were behind a NAT, and now we are behind a new NAT, or 3039 // We're not behind a NAT but our port was previously mapped to a different external port 3040 // We were not behind a NAT and now we are 3041 3042 mDNSIPPort port = srs->RR_SRV.resrec.rdata->u.srv.port; 3043 mDNSBool NowNeedNATMAP = (srs->RR_SRV.AutoTarget == Target_AutoHostAndNATMAP && !mDNSIPPortIsZero(port) && mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) && !mDNSAddrIsRFC1918(&srs->SRSUpdateServer)); 3044 mDNSBool WereBehindNAT = (srs->NATinfo.clientContext != mDNSNULL); 3045 mDNSBool PortWasMapped = (srs->NATinfo.clientContext && !mDNSSameIPPort(srs->NATinfo.RequestedPort, port)); // I think this is always false -- SC Sept 07 3046 mDNSBool NATChanged = (!WereBehindNAT && NowNeedNATMAP) || (!NowNeedNATMAP && PortWasMapped); 3047 3048 debugf("UpdateSRV %##s newtarget %##s TargetChanged %d HaveZoneData %d port %d NowNeedNATMAP %d WereBehindNAT %d PortWasMapped %d NATChanged %d", 3049 srs->RR_SRV.resrec.name->c, newtarget, 3050 TargetChanged, HaveZoneData, mDNSVal16(port), NowNeedNATMAP, WereBehindNAT, PortWasMapped, NATChanged); 3051 3052 if (m->mDNS_busy != m->mDNS_reentrancy+1) 3053 LogMsg("UpdateSRV: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 3054 3055 if (!TargetChanged && !NATChanged) return; 3056 3057 switch(srs->state) 3058 { 3059 case regState_FetchingZoneData: 3060 case regState_DeregPending: 3061 case regState_DeregDeferred: 3062 case regState_Unregistered: 3063 case regState_NATMap: 3064 case regState_ExtraQueued: 3065 // In these states, the SRV has either not yet been registered (it will get up-to-date information when it is) 3066 // or is in the process of, or has already been, deregistered 3067 return; 3068 3069 case regState_Pending: 3070 case regState_Refresh: 3071 case regState_UpdatePending: 3072 // let the in-flight operation complete before updating 3073 srs->SRVUpdateDeferred = mDNStrue; 3074 return; 3075 3076 case regState_NATError: 3077 if (!NATChanged) return; 3078 // if nat changed, register if we have a target (below) 3079 3080 case regState_NoTarget: 3081 if (newtarget->c[0]) 3082 { 3083 debugf("UpdateSRV: %s service %##s", HaveZoneData ? (NATChanged && NowNeedNATMAP ? "Starting Port Map for" : "Registering") : "Getting Zone Data for", srs->RR_SRV.resrec.name->c); 3084 if (!HaveZoneData) 3085 { 3086 srs->state = regState_FetchingZoneData; 3087 if (srs->srs_nta) CancelGetZoneData(m, srs->srs_nta); // Make sure we cancel old one before we start a new one 3088 srs->srs_nta = StartGetZoneData(m, srs->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, srs); 3089 } 3090 else 3091 { 3092 if (srs->NATinfo.clientContext && (NATChanged || !NowNeedNATMAP)) 3093 { 3094 mDNS_StopNATOperation_internal(m, &srs->NATinfo); 3095 srs->NATinfo.clientContext = mDNSNULL; 3096 } 3097 if (NATChanged && NowNeedNATMAP && srs->RR_SRV.AutoTarget == Target_AutoHostAndNATMAP) 3098 { srs->state = regState_NATMap; StartSRVNatMap(m, srs); } 3099 else SendServiceRegistration(m, srs); 3100 } 3101 } 3102 return; 3103 3104 case regState_Registered: 3105 // target or nat changed. deregister service. upon completion, we'll look for a new target 3106 debugf("UpdateSRV: SRV record changed for service %##s - deregistering (will re-register with new SRV)", srs->RR_SRV.resrec.name->c); 3107 for (e = srs->Extras; e; e = e->next) e->r.state = regState_ExtraQueued; // extra will be re-registed if the service is re-registered 3108 srs->SRVChanged = mDNStrue; 3109 SendServiceDeregistration(m, srs); 3110 return; 3111 3112 default: LogMsg("UpdateSRV: Unknown state %d for %##s", srs->state, srs->RR_SRV.resrec.name->c); 3113 } 3114 } 3115 3116 // Called with lock held 3117 mDNSlocal void UpdateSRVRecords(mDNS *m) 3118 { 3119 debugf("UpdateSRVRecords%s", m->SleepState ? " (ignored due to SleepState)" : ""); 3120 if (m->SleepState) return; 3121 3122 if (CurrentServiceRecordSet) 3123 LogMsg("UpdateSRVRecords ERROR CurrentServiceRecordSet already set"); 3124 CurrentServiceRecordSet = m->ServiceRegistrations; 3125 3126 while (CurrentServiceRecordSet) 3127 { 3128 ServiceRecordSet *s = CurrentServiceRecordSet; 3129 CurrentServiceRecordSet = CurrentServiceRecordSet->uDNS_next; 3130 UpdateSRV(m, s); 3131 } 3132 3133 mDNS_DropLockBeforeCallback(); // mDNS_SetFQDN expects to be called without the lock held, so we emulate that here 3134 mDNS_SetFQDN(m); 3135 mDNS_ReclaimLockAfterCallback(); 3136 } 3137 3138 // Forward reference: AdvertiseHostname references HostnameCallback, and HostnameCallback calls AdvertiseHostname 3139 mDNSlocal void HostnameCallback(mDNS *const m, AuthRecord *const rr, mStatus result); 3140 3141 // Called in normal client context (lock not held) 3142 mDNSlocal void hostnameGetPublicAddressCallback(mDNS *m, NATTraversalInfo *n) 3143 { 3144 HostnameInfo *h = (HostnameInfo *)n->clientContext; 3145 3146 if (!h) { LogMsg("RegisterHostnameRecord: registration cancelled"); return; } 3147 3148 if (!n->Result) 3149 { 3150 if (mDNSIPv4AddressIsZero(n->ExternalAddress) || mDNSv4AddrIsRFC1918(&n->ExternalAddress)) return; 3151 3152 if (h->arv4.resrec.RecordType) 3153 { 3154 if (mDNSSameIPv4Address(h->arv4.resrec.rdata->u.ipv4, n->ExternalAddress)) return; // If address unchanged, do nothing 3155 LogInfo("Updating hostname %##s IPv4 from %.4a to %.4a (NAT gateway's external address)", 3156 h->arv4.resrec.name->c, &h->arv4.resrec.rdata->u.ipv4, &n->ExternalAddress); 3157 mDNS_Deregister(m, &h->arv4); // mStatus_MemFree callback will re-register with new address 3158 } 3159 else 3160 { 3161 LogInfo("Advertising hostname %##s IPv4 %.4a (NAT gateway's external address)", h->arv4.resrec.name->c, &n->ExternalAddress); 3162 h->arv4.resrec.RecordType = kDNSRecordTypeKnownUnique; 3163 h->arv4.resrec.rdata->u.ipv4 = n->ExternalAddress; 3164 mDNS_Register(m, &h->arv4); 3165 } 3166 } 3167 } 3168 3169 // register record or begin NAT traversal 3170 mDNSlocal void AdvertiseHostname(mDNS *m, HostnameInfo *h) 3171 { 3172 if (!mDNSIPv4AddressIsZero(m->AdvertisedV4.ip.v4) && h->arv4.resrec.RecordType == kDNSRecordTypeUnregistered) 3173 { 3174 mDNS_SetupResourceRecord(&h->arv4, mDNSNULL, mDNSInterface_Any, kDNSType_A, kHostNameTTL, kDNSRecordTypeUnregistered, HostnameCallback, h); 3175 AssignDomainName(&h->arv4.namestorage, &h->fqdn); 3176 h->arv4.resrec.rdata->u.ipv4 = m->AdvertisedV4.ip.v4; 3177 h->arv4.state = regState_Unregistered; 3178 if (mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4)) 3179 { 3180 // If we already have a NAT query active, stop it and restart it to make sure we get another callback 3181 if (h->natinfo.clientContext) mDNS_StopNATOperation_internal(m, &h->natinfo); 3182 h->natinfo.Protocol = 0; 3183 h->natinfo.IntPort = zeroIPPort; 3184 h->natinfo.RequestedPort = zeroIPPort; 3185 h->natinfo.NATLease = 0; 3186 h->natinfo.clientCallback = hostnameGetPublicAddressCallback; 3187 h->natinfo.clientContext = h; 3188 mDNS_StartNATOperation_internal(m, &h->natinfo); 3189 } 3190 else 3191 { 3192 LogInfo("Advertising hostname %##s IPv4 %.4a", h->arv4.resrec.name->c, &m->AdvertisedV4.ip.v4); 3193 h->arv4.resrec.RecordType = kDNSRecordTypeKnownUnique; 3194 mDNS_Register_internal(m, &h->arv4); 3195 } 3196 } 3197 3198 if (!mDNSIPv6AddressIsZero(m->AdvertisedV6.ip.v6) && h->arv6.resrec.RecordType == kDNSRecordTypeUnregistered) 3199 { 3200 mDNS_SetupResourceRecord(&h->arv6, mDNSNULL, mDNSInterface_Any, kDNSType_AAAA, kHostNameTTL, kDNSRecordTypeKnownUnique, HostnameCallback, h); 3201 AssignDomainName(&h->arv6.namestorage, &h->fqdn); 3202 h->arv6.resrec.rdata->u.ipv6 = m->AdvertisedV6.ip.v6; 3203 h->arv6.state = regState_Unregistered; 3204 LogInfo("Advertising hostname %##s IPv6 %.16a", h->arv6.resrec.name->c, &m->AdvertisedV6.ip.v6); 3205 mDNS_Register_internal(m, &h->arv6); 3206 } 3207 } 3208 3209 mDNSlocal void HostnameCallback(mDNS *const m, AuthRecord *const rr, mStatus result) 3210 { 3211 HostnameInfo *hi = (HostnameInfo *)rr->RecordContext; 3212 3213 if (result == mStatus_MemFree) 3214 { 3215 if (hi) 3216 { 3217 // If we're still in the Hostnames list, update to new address 3218 HostnameInfo *i; 3219 LogInfo("HostnameCallback: Got mStatus_MemFree for %p %p %s", hi, rr, ARDisplayString(m, rr)); 3220 for (i = m->Hostnames; i; i = i->next) 3221 if (rr == &i->arv4 || rr == &i->arv6) 3222 { mDNS_Lock(m); AdvertiseHostname(m, i); mDNS_Unlock(m); return; } 3223 3224 // Else, we're not still in the Hostnames list, so free the memory 3225 if (hi->arv4.resrec.RecordType == kDNSRecordTypeUnregistered && 3226 hi->arv6.resrec.RecordType == kDNSRecordTypeUnregistered) 3227 { 3228 if (hi->natinfo.clientContext) mDNS_StopNATOperation_internal(m, &hi->natinfo); 3229 hi->natinfo.clientContext = mDNSNULL; 3230 mDNSPlatformMemFree(hi); // free hi when both v4 and v6 AuthRecs deallocated 3231 } 3232 } 3233 return; 3234 } 3235 3236 if (result) 3237 { 3238 // don't unlink or free - we can retry when we get a new address/router 3239 if (rr->resrec.rrtype == kDNSType_A) 3240 LogMsg("HostnameCallback: Error %d for registration of %##s IP %.4a", result, rr->resrec.name->c, &rr->resrec.rdata->u.ipv4); 3241 else 3242 LogMsg("HostnameCallback: Error %d for registration of %##s IP %.16a", result, rr->resrec.name->c, &rr->resrec.rdata->u.ipv6); 3243 if (!hi) { mDNSPlatformMemFree(rr); return; } 3244 if (rr->state != regState_Unregistered) LogMsg("Error: HostnameCallback invoked with error code for record not in regState_Unregistered!"); 3245 3246 if (hi->arv4.state == regState_Unregistered && 3247 hi->arv6.state == regState_Unregistered) 3248 { 3249 // only deliver status if both v4 and v6 fail 3250 rr->RecordContext = (void *)hi->StatusContext; 3251 if (hi->StatusCallback) 3252 hi->StatusCallback(m, rr, result); // client may NOT make API calls here 3253 rr->RecordContext = (void *)hi; 3254 } 3255 return; 3256 } 3257 3258 // register any pending services that require a target 3259 mDNS_Lock(m); 3260 UpdateSRVRecords(m); 3261 mDNS_Unlock(m); 3262 3263 // Deliver success to client 3264 if (!hi) { LogMsg("HostnameCallback invoked with orphaned address record"); return; } 3265 if (rr->resrec.rrtype == kDNSType_A) 3266 LogInfo("Registered hostname %##s IP %.4a", rr->resrec.name->c, &rr->resrec.rdata->u.ipv4); 3267 else 3268 LogInfo("Registered hostname %##s IP %.16a", rr->resrec.name->c, &rr->resrec.rdata->u.ipv6); 3269 3270 rr->RecordContext = (void *)hi->StatusContext; 3271 if (hi->StatusCallback) 3272 hi->StatusCallback(m, rr, result); // client may NOT make API calls here 3273 rr->RecordContext = (void *)hi; 3274 } 3275 3276 mDNSlocal void FoundStaticHostname(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) 3277 { 3278 const domainname *pktname = &answer->rdata->u.name; 3279 domainname *storedname = &m->StaticHostname; 3280 HostnameInfo *h = m->Hostnames; 3281 3282 (void)question; 3283 3284 debugf("FoundStaticHostname: %##s -> %##s (%s)", question->qname.c, answer->rdata->u.name.c, AddRecord ? "added" : "removed"); 3285 if (AddRecord && !SameDomainName(pktname, storedname)) 3286 { 3287 AssignDomainName(storedname, pktname); 3288 while (h) 3289 { 3290 if (h->arv4.state == regState_FetchingZoneData || h->arv4.state == regState_Pending || h->arv4.state == regState_NATMap || 3291 h->arv6.state == regState_FetchingZoneData || h->arv6.state == regState_Pending) 3292 { 3293 // if we're in the process of registering a dynamic hostname, delay SRV update so we don't have to reregister services if the dynamic name succeeds 3294 m->NextSRVUpdate = NonZeroTime(m->timenow + 5 * mDNSPlatformOneSecond); 3295 return; 3296 } 3297 h = h->next; 3298 } 3299 mDNS_Lock(m); 3300 UpdateSRVRecords(m); 3301 mDNS_Unlock(m); 3302 } 3303 else if (!AddRecord && SameDomainName(pktname, storedname)) 3304 { 3305 mDNS_Lock(m); 3306 storedname->c[0] = 0; 3307 UpdateSRVRecords(m); 3308 mDNS_Unlock(m); 3309 } 3310 } 3311 3312 // Called with lock held 3313 mDNSlocal void GetStaticHostname(mDNS *m) 3314 { 3315 char buf[MAX_REVERSE_MAPPING_NAME_V4]; 3316 DNSQuestion *q = &m->ReverseMap; 3317 mDNSu8 *ip = m->AdvertisedV4.ip.v4.b; 3318 mStatus err; 3319 3320 if (m->ReverseMap.ThisQInterval != -1) return; // already running 3321 if (mDNSIPv4AddressIsZero(m->AdvertisedV4.ip.v4)) return; 3322 3323 mDNSPlatformMemZero(q, sizeof(*q)); 3324 // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code 3325 mDNS_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa.", ip[3], ip[2], ip[1], ip[0]); 3326 if (!MakeDomainNameFromDNSNameString(&q->qname, buf)) { LogMsg("Error: GetStaticHostname - bad name %s", buf); return; } 3327 3328 q->InterfaceID = mDNSInterface_Any; 3329 q->Target = zeroAddr; 3330 q->qtype = kDNSType_PTR; 3331 q->qclass = kDNSClass_IN; 3332 q->LongLived = mDNSfalse; 3333 q->ExpectUnique = mDNSfalse; 3334 q->ForceMCast = mDNSfalse; 3335 q->ReturnIntermed = mDNStrue; 3336 q->QuestionCallback = FoundStaticHostname; 3337 q->QuestionContext = mDNSNULL; 3338 3339 LogInfo("GetStaticHostname: %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 3340 err = mDNS_StartQuery_internal(m, q); 3341 if (err) LogMsg("Error: GetStaticHostname - StartQuery returned error %d", err); 3342 } 3343 3344 mDNSexport void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext) 3345 { 3346 HostnameInfo **ptr = &m->Hostnames; 3347 3348 LogInfo("mDNS_AddDynDNSHostName %##s", fqdn); 3349 3350 while (*ptr && !SameDomainName(fqdn, &(*ptr)->fqdn)) ptr = &(*ptr)->next; 3351 if (*ptr) { LogMsg("DynDNSHostName %##s already in list", fqdn->c); return; } 3352 3353 // allocate and format new address record 3354 *ptr = mDNSPlatformMemAllocate(sizeof(**ptr)); 3355 if (!*ptr) { LogMsg("ERROR: mDNS_AddDynDNSHostName - malloc"); return; } 3356 3357 mDNSPlatformMemZero(*ptr, sizeof(**ptr)); 3358 AssignDomainName(&(*ptr)->fqdn, fqdn); 3359 (*ptr)->arv4.state = regState_Unregistered; 3360 (*ptr)->arv6.state = regState_Unregistered; 3361 (*ptr)->StatusCallback = StatusCallback; 3362 (*ptr)->StatusContext = StatusContext; 3363 3364 AdvertiseHostname(m, *ptr); 3365 } 3366 3367 mDNSexport void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn) 3368 { 3369 HostnameInfo **ptr = &m->Hostnames; 3370 3371 LogInfo("mDNS_RemoveDynDNSHostName %##s", fqdn); 3372 3373 while (*ptr && !SameDomainName(fqdn, &(*ptr)->fqdn)) ptr = &(*ptr)->next; 3374 if (!*ptr) LogMsg("mDNS_RemoveDynDNSHostName: no such domainname %##s", fqdn->c); 3375 else 3376 { 3377 HostnameInfo *hi = *ptr; 3378 // We do it this way because, if we have no active v6 record, the "mDNS_Deregister_internal(m, &hi->arv4);" 3379 // below could free the memory, and we have to make sure we don't touch hi fields after that. 3380 mDNSBool f4 = hi->arv4.resrec.RecordType != kDNSRecordTypeUnregistered && hi->arv4.state != regState_Unregistered; 3381 mDNSBool f6 = hi->arv6.resrec.RecordType != kDNSRecordTypeUnregistered && hi->arv6.state != regState_Unregistered; 3382 if (f4) LogInfo("mDNS_RemoveDynDNSHostName removing v4 %##s", fqdn); 3383 if (f6) LogInfo("mDNS_RemoveDynDNSHostName removing v6 %##s", fqdn); 3384 *ptr = (*ptr)->next; // unlink 3385 if (f4) mDNS_Deregister_internal(m, &hi->arv4, mDNS_Dereg_normal); 3386 if (f6) mDNS_Deregister_internal(m, &hi->arv6, mDNS_Dereg_normal); 3387 // When both deregistrations complete we'll free the memory in the mStatus_MemFree callback 3388 } 3389 UpdateSRVRecords(m); 3390 } 3391 3392 // Currently called without holding the lock 3393 // Maybe we should change that? 3394 mDNSexport void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, const mDNSAddr *v6addr, const mDNSAddr *router) 3395 { 3396 mDNSBool v4Changed, v6Changed, RouterChanged; 3397 3398 if (m->mDNS_busy != m->mDNS_reentrancy) 3399 LogMsg("mDNS_SetPrimaryInterfaceInfo: mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 3400 3401 if (v4addr && v4addr->type != mDNSAddrType_IPv4) { LogMsg("mDNS_SetPrimaryInterfaceInfo v4 address - incorrect type. Discarding. %#a", v4addr); return; } 3402 if (v6addr && v6addr->type != mDNSAddrType_IPv6) { LogMsg("mDNS_SetPrimaryInterfaceInfo v6 address - incorrect type. Discarding. %#a", v6addr); return; } 3403 if (router && router->type != mDNSAddrType_IPv4) { LogMsg("mDNS_SetPrimaryInterfaceInfo passed non-v4 router. Discarding. %#a", router); return; } 3404 3405 mDNS_Lock(m); 3406 3407 if (v4addr && !mDNSv4AddressIsLinkLocal(&v4addr->ip.v4)) v6addr = mDNSNULL; 3408 3409 v4Changed = !mDNSSameIPv4Address(m->AdvertisedV4.ip.v4, v4addr ? v4addr->ip.v4 : zerov4Addr); 3410 v6Changed = !mDNSSameIPv6Address(m->AdvertisedV6.ip.v6, v6addr ? v6addr->ip.v6 : zerov6Addr); 3411 RouterChanged = !mDNSSameIPv4Address(m->Router.ip.v4, router ? router->ip.v4 : zerov4Addr); 3412 3413 if (v4addr && (v4Changed || RouterChanged)) 3414 debugf("mDNS_SetPrimaryInterfaceInfo: address changed from %#a to %#a", &m->AdvertisedV4, v4addr); 3415 3416 if (v4addr) m->AdvertisedV4 = *v4addr; else m->AdvertisedV4.ip.v4 = zerov4Addr; 3417 if (v6addr) m->AdvertisedV6 = *v6addr; else m->AdvertisedV6.ip.v6 = zerov6Addr; 3418 if (router) m->Router = *router; else m->Router .ip.v4 = zerov4Addr; 3419 // setting router to zero indicates that nat mappings must be reestablished when router is reset 3420 3421 if (v4Changed || RouterChanged || v6Changed) 3422 { 3423 HostnameInfo *i; 3424 LogInfo("mDNS_SetPrimaryInterfaceInfo: %s%s%s%#a %#a %#a", 3425 v4Changed ? "v4Changed " : "", 3426 RouterChanged ? "RouterChanged " : "", 3427 v6Changed ? "v6Changed " : "", v4addr, v6addr, router); 3428 3429 for (i = m->Hostnames; i; i = i->next) 3430 { 3431 LogInfo("mDNS_SetPrimaryInterfaceInfo updating host name registrations for %##s", i->fqdn.c); 3432 3433 if (i->arv4.resrec.RecordType > kDNSRecordTypeDeregistering && 3434 !mDNSSameIPv4Address(i->arv4.resrec.rdata->u.ipv4, m->AdvertisedV4.ip.v4)) 3435 { 3436 LogInfo("mDNS_SetPrimaryInterfaceInfo deregistering %s", ARDisplayString(m, &i->arv4)); 3437 mDNS_Deregister_internal(m, &i->arv4, mDNS_Dereg_normal); 3438 } 3439 3440 if (i->arv6.resrec.RecordType > kDNSRecordTypeDeregistering && 3441 !mDNSSameIPv6Address(i->arv6.resrec.rdata->u.ipv6, m->AdvertisedV6.ip.v6)) 3442 { 3443 LogInfo("mDNS_SetPrimaryInterfaceInfo deregistering %s", ARDisplayString(m, &i->arv6)); 3444 mDNS_Deregister_internal(m, &i->arv6, mDNS_Dereg_normal); 3445 } 3446 3447 // AdvertiseHostname will only register new address records. 3448 // For records still in the process of deregistering it will ignore them, and let the mStatus_MemFree callback handle them. 3449 AdvertiseHostname(m, i); 3450 } 3451 3452 if (v4Changed || RouterChanged) 3453 { 3454 m->ExternalAddress = zerov4Addr; 3455 m->retryIntervalGetAddr = NATMAP_INIT_RETRY; 3456 m->retryGetAddr = m->timenow; 3457 m->NextScheduledNATOp = m->timenow; 3458 m->LastNATMapResultCode = NATErr_None; 3459 #ifdef _LEGACY_NAT_TRAVERSAL_ 3460 LNT_ClearState(m); 3461 #endif // _LEGACY_NAT_TRAVERSAL_ 3462 } 3463 3464 if (m->ReverseMap.ThisQInterval != -1) mDNS_StopQuery_internal(m, &m->ReverseMap); 3465 m->StaticHostname.c[0] = 0; 3466 3467 UpdateSRVRecords(m); // Will call GetStaticHostname if needed 3468 3469 #if APPLE_OSX_mDNSResponder 3470 if (RouterChanged) uuid_generate(m->asl_uuid); 3471 UpdateAutoTunnelDomainStatuses(m); 3472 #endif 3473 } 3474 3475 mDNS_Unlock(m); 3476 } 3477 3478 // *************************************************************************** 3479 #if COMPILER_LIKES_PRAGMA_MARK 3480 #pragma mark - Incoming Message Processing 3481 #endif 3482 3483 mDNSlocal mStatus ParseTSIGError(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const domainname *const displayname) 3484 { 3485 const mDNSu8 *ptr; 3486 mStatus err = mStatus_NoError; 3487 int i; 3488 3489 ptr = LocateAdditionals(msg, end); 3490 if (!ptr) goto finish; 3491 3492 for (i = 0; i < msg->h.numAdditionals; i++) 3493 { 3494 ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec); 3495 if (!ptr) goto finish; 3496 if (m->rec.r.resrec.rrtype == kDNSType_TSIG) 3497 { 3498 mDNSu32 macsize; 3499 mDNSu8 *rd = m->rec.r.resrec.rdata->u.data; 3500 mDNSu8 *rdend = rd + m->rec.r.resrec.rdlength; 3501 int alglen = DomainNameLengthLimit(&m->rec.r.resrec.rdata->u.name, rdend); 3502 if (alglen > MAX_DOMAIN_NAME) goto finish; 3503 rd += alglen; // algorithm name 3504 if (rd + 6 > rdend) goto finish; 3505 rd += 6; // 48-bit timestamp 3506 if (rd + sizeof(mDNSOpaque16) > rdend) goto finish; 3507 rd += sizeof(mDNSOpaque16); // fudge 3508 if (rd + sizeof(mDNSOpaque16) > rdend) goto finish; 3509 macsize = mDNSVal16(*(mDNSOpaque16 *)rd); 3510 rd += sizeof(mDNSOpaque16); // MAC size 3511 if (rd + macsize > rdend) goto finish; 3512 rd += macsize; 3513 if (rd + sizeof(mDNSOpaque16) > rdend) goto finish; 3514 rd += sizeof(mDNSOpaque16); // orig id 3515 if (rd + sizeof(mDNSOpaque16) > rdend) goto finish; 3516 err = mDNSVal16(*(mDNSOpaque16 *)rd); // error code 3517 3518 if (err == TSIG_ErrBadSig) { LogMsg("%##s: bad signature", displayname->c); err = mStatus_BadSig; } 3519 else if (err == TSIG_ErrBadKey) { LogMsg("%##s: bad key", displayname->c); err = mStatus_BadKey; } 3520 else if (err == TSIG_ErrBadTime) { LogMsg("%##s: bad time", displayname->c); err = mStatus_BadTime; } 3521 else if (err) { LogMsg("%##s: unknown tsig error %d", displayname->c, err); err = mStatus_UnknownErr; } 3522 goto finish; 3523 } 3524 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 3525 } 3526 3527 finish: 3528 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 3529 return err; 3530 } 3531 3532 mDNSlocal mStatus checkUpdateResult(mDNS *const m, const domainname *const displayname, const mDNSu8 rcode, const DNSMessage *const msg, const mDNSu8 *const end) 3533 { 3534 (void)msg; // currently unused, needed for TSIG errors 3535 if (!rcode) return mStatus_NoError; 3536 else if (rcode == kDNSFlag1_RC_YXDomain) 3537 { 3538 debugf("name in use: %##s", displayname->c); 3539 return mStatus_NameConflict; 3540 } 3541 else if (rcode == kDNSFlag1_RC_Refused) 3542 { 3543 LogMsg("Update %##s refused", displayname->c); 3544 return mStatus_Refused; 3545 } 3546 else if (rcode == kDNSFlag1_RC_NXRRSet) 3547 { 3548 LogMsg("Reregister refused (NXRRSET): %##s", displayname->c); 3549 return mStatus_NoSuchRecord; 3550 } 3551 else if (rcode == kDNSFlag1_RC_NotAuth) 3552 { 3553 // TSIG errors should come with FormErr as per RFC 2845, but BIND 9 sends them with NotAuth so we look here too 3554 mStatus tsigerr = ParseTSIGError(m, msg, end, displayname); 3555 if (!tsigerr) 3556 { 3557 LogMsg("Permission denied (NOAUTH): %##s", displayname->c); 3558 return mStatus_UnknownErr; 3559 } 3560 else return tsigerr; 3561 } 3562 else if (rcode == kDNSFlag1_RC_FormErr) 3563 { 3564 mStatus tsigerr = ParseTSIGError(m, msg, end, displayname); 3565 if (!tsigerr) 3566 { 3567 LogMsg("Format Error: %##s", displayname->c); 3568 return mStatus_UnknownErr; 3569 } 3570 else return tsigerr; 3571 } 3572 else 3573 { 3574 LogMsg("Update %##s failed with rcode %d", displayname->c, rcode); 3575 return mStatus_UnknownErr; 3576 } 3577 } 3578 3579 // Called with lock held 3580 mDNSlocal void SendRecordRegistration(mDNS *const m, AuthRecord *rr) 3581 { 3582 mDNSu8 *ptr = m->omsg.data; 3583 mDNSu8 *end = (mDNSu8 *)&m->omsg + sizeof(DNSMessage); 3584 mStatus err = mStatus_UnknownErr; 3585 3586 if (m->mDNS_busy != m->mDNS_reentrancy+1) 3587 LogMsg("SendRecordRegistration: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 3588 3589 if (mDNSIPv4AddressIsZero(rr->UpdateServer.ip.v4)) // Don't know our UpdateServer yet 3590 { 3591 rr->LastAPTime = m->timenow; 3592 if (rr->ThisAPInterval < mDNSPlatformOneSecond * 5) 3593 rr->ThisAPInterval = mDNSPlatformOneSecond * 5; 3594 return; 3595 } 3596 3597 rr->RequireGoodbye = mDNStrue; 3598 rr->updateid = mDNS_NewMessageID(m); 3599 InitializeDNSMessage(&m->omsg.h, rr->updateid, UpdateReqFlags); 3600 3601 // set zone 3602 ptr = putZone(&m->omsg, ptr, end, rr->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass)); 3603 if (!ptr) { err = mStatus_UnknownErr; goto exit; } 3604 3605 if (rr->state == regState_UpdatePending) 3606 { 3607 // delete old RData 3608 SetNewRData(&rr->resrec, rr->OrigRData, rr->OrigRDLen); 3609 if (!(ptr = putDeletionRecord(&m->omsg, ptr, &rr->resrec))) { err = mStatus_UnknownErr; goto exit; } // delete old rdata 3610 3611 // add new RData 3612 SetNewRData(&rr->resrec, rr->InFlightRData, rr->InFlightRDLen); 3613 if (!(ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl))) { err = mStatus_UnknownErr; goto exit; } 3614 } 3615 3616 else 3617 { 3618 if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique) 3619 { 3620 // KnownUnique: Delete any previous value 3621 ptr = putDeleteRRSet(&m->omsg, ptr, rr->resrec.name, rr->resrec.rrtype); 3622 if (!ptr) { err = mStatus_UnknownErr; goto exit; } 3623 } 3624 3625 else if (rr->resrec.RecordType != kDNSRecordTypeShared) 3626 { 3627 // For now don't do this, until we have the logic for intelligent grouping of individual recors into logical service record sets 3628 //ptr = putPrereqNameNotInUse(rr->resrec.name, &m->omsg, ptr, end); 3629 if (!ptr) { err = mStatus_UnknownErr; goto exit; } 3630 } 3631 3632 ptr = PutResourceRecordTTLJumbo(&m->omsg, ptr, &m->omsg.h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl); 3633 if (!ptr) { err = mStatus_UnknownErr; goto exit; } 3634 } 3635 3636 if (rr->uselease) 3637 { 3638 ptr = putUpdateLease(&m->omsg, ptr, DEFAULT_UPDATE_LEASE); if (!ptr) { err = mStatus_UnknownErr; goto exit; } 3639 } 3640 3641 if (rr->Private) 3642 { 3643 LogInfo("SendRecordRegistration TCP %p %s", rr->tcp, ARDisplayString(m, rr)); 3644 if (rr->tcp) LogInfo("SendRecordRegistration: Disposing existing TCP connection for %s", ARDisplayString(m, rr)); 3645 if (rr->tcp) DisposeTCPConn(rr->tcp); 3646 rr->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &rr->UpdateServer, rr->UpdatePort, mDNSNULL, mDNSNULL, rr); 3647 if (!rr->tcp) rr->ThisAPInterval = mDNSPlatformOneSecond * 5; // If failed to make TCP connection, try again in ten seconds (5*2) 3648 else if (rr->ThisAPInterval < mDNSPlatformOneSecond * 30) rr->ThisAPInterval = mDNSPlatformOneSecond * 30; 3649 } 3650 else 3651 { 3652 err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &rr->UpdateServer, rr->UpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, rr->resrec.name)); 3653 if (err) debugf("ERROR: SendRecordRegistration - mDNSSendDNSMessage - %d", err); 3654 } 3655 3656 SetRecordRetry(m, rr, err); 3657 3658 if (rr->state != regState_Refresh && rr->state != regState_DeregDeferred && rr->state != regState_UpdatePending) 3659 rr->state = regState_Pending; 3660 3661 return; 3662 3663 exit: 3664 LogMsg("SendRecordRegistration: Error formatting message for %s", ARDisplayString(m, rr)); 3665 } 3666 3667 // Called with lock held 3668 mDNSlocal void hndlServiceUpdateReply(mDNS *const m, ServiceRecordSet *srs, mStatus err) 3669 { 3670 mDNSBool InvokeCallback = mDNSfalse; 3671 ExtraResourceRecord **e = &srs->Extras; 3672 AuthRecord *txt = &srs->RR_TXT; 3673 3674 if (m->mDNS_busy != m->mDNS_reentrancy+1) 3675 LogMsg("hndlServiceUpdateReply: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 3676 3677 debugf("hndlServiceUpdateReply: err %d state %d %##s", err, srs->state, srs->RR_SRV.resrec.name->c); 3678 3679 SetRecordRetry(m, &srs->RR_SRV, mStatus_NoError); 3680 3681 switch (srs->state) 3682 { 3683 case regState_Pending: 3684 if (err == mStatus_NameConflict && !srs->TestForSelfConflict) 3685 { 3686 srs->TestForSelfConflict = mDNStrue; 3687 debugf("checking for self-conflict of service %##s", srs->RR_SRV.resrec.name->c); 3688 SendServiceRegistration(m, srs); 3689 return; 3690 } 3691 else if (srs->TestForSelfConflict) 3692 { 3693 srs->TestForSelfConflict = mDNSfalse; 3694 if (err == mStatus_NoSuchRecord) err = mStatus_NameConflict; // NoSuchRecord implies that our prereq was not met, so we actually have a name conflict 3695 if (!err) srs->state = regState_Registered; 3696 InvokeCallback = mDNStrue; 3697 break; 3698 } 3699 else if (srs->srs_uselease && err == mStatus_UnknownErr && mDNSSameIPPort(srs->SRSUpdatePort, UnicastDNSPort)) 3700 { 3701 LogMsg("Re-trying update of service %##s without lease option", srs->RR_SRV.resrec.name->c); 3702 srs->srs_uselease = mDNSfalse; 3703 SendServiceRegistration(m, srs); 3704 return; 3705 } 3706 else 3707 { 3708 //!!!KRS make sure all structs will still get cleaned up when client calls DeregisterService with this state 3709 if (err) LogMsg("Error %d for registration of service %##s", err, srs->RR_SRV.resrec.name->c); 3710 else srs->state = regState_Registered; 3711 InvokeCallback = mDNStrue; 3712 break; 3713 } 3714 case regState_Refresh: 3715 if (err) 3716 { 3717 LogMsg("Error %d for refresh of service %##s", err, srs->RR_SRV.resrec.name->c); 3718 InvokeCallback = mDNStrue; 3719 } 3720 else srs->state = regState_Registered; 3721 break; 3722 case regState_DeregPending: 3723 if (err) LogMsg("Error %d for deregistration of service %##s", err, srs->RR_SRV.resrec.name->c); 3724 if (srs->SRVChanged) 3725 { 3726 srs->state = regState_NoTarget; // NoTarget will allow us to pick up new target OR nat traversal state 3727 break; 3728 } 3729 err = mStatus_MemFree; 3730 InvokeCallback = mDNStrue; 3731 if (srs->NATinfo.clientContext) 3732 { 3733 // deletion completed 3734 mDNS_StopNATOperation_internal(m, &srs->NATinfo); 3735 srs->NATinfo.clientContext = mDNSNULL; 3736 } 3737 srs->state = regState_Unregistered; 3738 break; 3739 case regState_DeregDeferred: 3740 if (err) 3741 { 3742 debugf("Error %d received prior to deferred deregistration of %##s", err, srs->RR_SRV.resrec.name->c); 3743 err = mStatus_MemFree; 3744 InvokeCallback = mDNStrue; 3745 srs->state = regState_Unregistered; 3746 break; 3747 } 3748 else 3749 { 3750 debugf("Performing deferred deregistration of %##s", srs->RR_SRV.resrec.name->c); 3751 srs->state = regState_Registered; 3752 SendServiceDeregistration(m, srs); 3753 return; 3754 } 3755 case regState_UpdatePending: 3756 if (err) 3757 { 3758 LogMsg("hndlServiceUpdateReply: error updating TXT record for service %##s", srs->RR_SRV.resrec.name->c); 3759 InvokeCallback = mDNStrue; 3760 } 3761 else 3762 { 3763 srs->state = regState_Registered; 3764 // deallocate old RData 3765 if (txt->UpdateCallback) txt->UpdateCallback(m, txt, txt->OrigRData); 3766 SetNewRData(&txt->resrec, txt->InFlightRData, txt->InFlightRDLen); 3767 txt->OrigRData = mDNSNULL; 3768 txt->InFlightRData = mDNSNULL; 3769 } 3770 break; 3771 case regState_NoTarget: 3772 // This state is used when using SendServiceDeregistration() when going to sleep -- no further action required 3773 return; 3774 case regState_FetchingZoneData: 3775 case regState_Registered: 3776 case regState_Unregistered: 3777 case regState_NATMap: 3778 case regState_ExtraQueued: 3779 case regState_NATError: 3780 LogMsg("hndlServiceUpdateReply called for service %##s in unexpected state %d with error %d. Unlinking.", 3781 srs->RR_SRV.resrec.name->c, srs->state, err); 3782 err = mStatus_UnknownErr; 3783 default: LogMsg("hndlServiceUpdateReply: Unknown state %d for %##s", srs->state, srs->RR_SRV.resrec.name->c); 3784 } 3785 3786 if ((srs->SRVChanged || srs->SRVUpdateDeferred) && (srs->state == regState_NoTarget || srs->state == regState_Registered)) 3787 { 3788 debugf("hndlServiceUpdateReply: SRVChanged %d SRVUpdateDeferred %d state %d", srs->SRVChanged, srs->SRVUpdateDeferred, srs->state); 3789 if (InvokeCallback) 3790 { 3791 srs->ClientCallbackDeferred = mDNStrue; 3792 srs->DeferredStatus = err; 3793 } 3794 srs->SRVChanged = srs->SRVUpdateDeferred = mDNSfalse; 3795 UpdateSRV(m, srs); 3796 return; 3797 } 3798 3799 while (*e) 3800 { 3801 if ((*e)->r.state == regState_ExtraQueued) 3802 { 3803 if (srs->state == regState_Registered && !err) 3804 { 3805 // extra resource record queued for this service - copy zone srs and register 3806 (*e)->r.zone = &srs->zone; 3807 (*e)->r.UpdateServer = srs->SRSUpdateServer; 3808 (*e)->r.UpdatePort = srs->SRSUpdatePort; 3809 (*e)->r.uselease = srs->srs_uselease; 3810 SendRecordRegistration(m, &(*e)->r); 3811 e = &(*e)->next; 3812 } 3813 else if (err && (*e)->r.state != regState_Unregistered) 3814 { 3815 // unlink extra from list 3816 (*e)->r.state = regState_Unregistered; 3817 *e = (*e)->next; 3818 } 3819 else e = &(*e)->next; 3820 } 3821 else e = &(*e)->next; 3822 } 3823 3824 if (srs->state == regState_Unregistered) 3825 { 3826 if (err != mStatus_MemFree) 3827 LogMsg("hndlServiceUpdateReply ERROR! state == regState_Unregistered but err != mStatus_MemFree. Permanently abandoning service registration %##s", 3828 srs->RR_SRV.resrec.name->c); 3829 unlinkSRS(m, srs); 3830 } 3831 else if (txt->QueuedRData && srs->state == regState_Registered) 3832 { 3833 if (InvokeCallback) 3834 { 3835 // if we were supposed to give a client callback, we'll do it after we update the primary txt record 3836 srs->ClientCallbackDeferred = mDNStrue; 3837 srs->DeferredStatus = err; 3838 } 3839 srs->state = regState_UpdatePending; 3840 txt->InFlightRData = txt->QueuedRData; 3841 txt->InFlightRDLen = txt->QueuedRDLen; 3842 txt->OrigRData = txt->resrec.rdata; 3843 txt->OrigRDLen = txt->resrec.rdlength; 3844 txt->QueuedRData = mDNSNULL; 3845 SendServiceRegistration(m, srs); 3846 return; 3847 } 3848 3849 mDNS_DropLockBeforeCallback(); 3850 if (InvokeCallback) 3851 srs->ServiceCallback(m, srs, err); 3852 else if (srs->ClientCallbackDeferred) 3853 { 3854 srs->ClientCallbackDeferred = mDNSfalse; 3855 srs->ServiceCallback(m, srs, srs->DeferredStatus); 3856 } 3857 mDNS_ReclaimLockAfterCallback(); 3858 // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function 3859 // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc. 3860 } 3861 3862 // Called with lock held 3863 mDNSlocal void hndlRecordUpdateReply(mDNS *m, AuthRecord *rr, mStatus err) 3864 { 3865 mDNSBool InvokeCallback = mDNStrue; 3866 3867 if (m->mDNS_busy != m->mDNS_reentrancy+1) 3868 LogMsg("hndlRecordUpdateReply: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 3869 3870 LogInfo("hndlRecordUpdateReply: err %d state %d %s", err, rr->state, ARDisplayString(m, rr)); 3871 3872 if (m->SleepState) return; // If we just sent a deregister on going to sleep, no further action required 3873 3874 SetRecordRetry(m, rr, mStatus_NoError); 3875 3876 if (rr->state == regState_UpdatePending) 3877 { 3878 if (err) LogMsg("Update record failed for %##s (err %d)", rr->resrec.name->c, err); 3879 rr->state = regState_Registered; 3880 // deallocate old RData 3881 if (rr->UpdateCallback) rr->UpdateCallback(m, rr, rr->OrigRData); 3882 SetNewRData(&rr->resrec, rr->InFlightRData, rr->InFlightRDLen); 3883 rr->OrigRData = mDNSNULL; 3884 rr->InFlightRData = mDNSNULL; 3885 } 3886 3887 if (rr->state == regState_DeregPending) 3888 { 3889 debugf("Received reply for deregister record %##s type %d", rr->resrec.name->c, rr->resrec.rrtype); 3890 if (err) LogMsg("ERROR: Deregistration of record %##s type %d failed with error %d", 3891 rr->resrec.name->c, rr->resrec.rrtype, err); 3892 err = mStatus_MemFree; 3893 rr->state = regState_Unregistered; 3894 } 3895 3896 if (rr->state == regState_DeregDeferred) 3897 { 3898 if (err) 3899 { 3900 LogMsg("Cancelling deferred deregistration record %##s type %d due to registration error %d", 3901 rr->resrec.name->c, rr->resrec.rrtype, err); 3902 rr->state = regState_Unregistered; 3903 } 3904 debugf("Calling deferred deregistration of record %##s type %d", rr->resrec.name->c, rr->resrec.rrtype); 3905 rr->state = regState_Registered; 3906 mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal); 3907 return; 3908 } 3909 3910 if (rr->state == regState_Pending || rr->state == regState_Refresh) 3911 { 3912 if (!err) 3913 { 3914 if (rr->state == regState_Refresh) InvokeCallback = mDNSfalse; 3915 rr->state = regState_Registered; 3916 } 3917 else 3918 { 3919 if (rr->uselease && err == mStatus_UnknownErr && mDNSSameIPPort(rr->UpdatePort, UnicastDNSPort)) 3920 { 3921 LogMsg("Re-trying update of record %##s without lease option", rr->resrec.name->c); 3922 rr->uselease = mDNSfalse; 3923 SendRecordRegistration(m, rr); 3924 return; 3925 } 3926 LogMsg("hndlRecordUpdateReply: Registration of record %##s type %d failed with error %d", rr->resrec.name->c, rr->resrec.rrtype, err); 3927 return; 3928 } 3929 } 3930 3931 if (rr->state == regState_Unregistered) // Should never happen 3932 { 3933 LogMsg("hndlRecordUpdateReply rr->state == regState_Unregistered %s", ARDisplayString(m, rr)); 3934 return; 3935 } 3936 3937 if (rr->QueuedRData && rr->state == regState_Registered) 3938 { 3939 rr->state = regState_UpdatePending; 3940 rr->InFlightRData = rr->QueuedRData; 3941 rr->InFlightRDLen = rr->QueuedRDLen; 3942 rr->OrigRData = rr->resrec.rdata; 3943 rr->OrigRDLen = rr->resrec.rdlength; 3944 rr->QueuedRData = mDNSNULL; 3945 SendRecordRegistration(m, rr); 3946 return; 3947 } 3948 3949 if (InvokeCallback && rr->RecordCallback) 3950 { 3951 mDNS_DropLockBeforeCallback(); 3952 rr->RecordCallback(m, rr, err); 3953 mDNS_ReclaimLockAfterCallback(); 3954 } 3955 // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function 3956 // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc. 3957 } 3958 3959 mDNSexport void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID InterfaceID, mDNSu8 *pkt, mDNSu16 len) 3960 { 3961 NATTraversalInfo *ptr; 3962 NATAddrReply *AddrReply = (NATAddrReply *)pkt; 3963 NATPortMapReply *PortMapReply = (NATPortMapReply *)pkt; 3964 mDNSu32 nat_elapsed, our_elapsed; 3965 3966 // Minimum packet is vers (1) opcode (1) err (2) upseconds (4) = 8 bytes 3967 if (!AddrReply->err && len < 8) { LogMsg("NAT Traversal message too short (%d bytes)", len); return; } 3968 if (AddrReply->vers != NATMAP_VERS) { LogMsg("Received NAT Traversal response with version %d (expected %d)", pkt[0], NATMAP_VERS); return; } 3969 3970 // Read multi-byte numeric values (fields are identical in a NATPortMapReply) 3971 AddrReply->err = (mDNSu16) ( (mDNSu16)pkt[2] << 8 | pkt[3]); 3972 AddrReply->upseconds = (mDNSs32) ((mDNSs32)pkt[4] << 24 | (mDNSs32)pkt[5] << 16 | (mDNSs32)pkt[6] << 8 | pkt[7]); 3973 3974 nat_elapsed = AddrReply->upseconds - m->LastNATupseconds; 3975 our_elapsed = (m->timenow - m->LastNATReplyLocalTime) / mDNSPlatformOneSecond; 3976 debugf("uDNS_ReceiveNATPMPPacket %X upseconds %u nat_elapsed %d our_elapsed %d", AddrReply->opcode, AddrReply->upseconds, nat_elapsed, our_elapsed); 3977 3978 // We compute a conservative estimate of how much the NAT gateways's clock should have advanced 3979 // 1. We subtract 12.5% from our own measured elapsed time, to allow for NAT gateways that have an inacurate clock that runs slowly 3980 // 2. We add a two-second safety margin to allow for rounding errors: 3981 // -- e.g. if NAT gateway sends a packet at t=2.00 seconds, then one at t=7.99, that's virtually 6 seconds, 3982 // but based on the values in the packet (2,7) the apparent difference is only 5 seconds 3983 // -- similarly, if we're slow handling packets and/or we have coarse clock granularity, we could over-estimate the true interval 3984 // (e.g. t=1.99 seconds rounded to 1, and t=8.01 rounded to 8, gives an apparent difference of 7 seconds) 3985 if (AddrReply->upseconds < m->LastNATupseconds || nat_elapsed + 2 < our_elapsed - our_elapsed/8) 3986 { LogMsg("NAT gateway %#a rebooted", &m->Router); RecreateNATMappings(m); } 3987 3988 m->LastNATupseconds = AddrReply->upseconds; 3989 m->LastNATReplyLocalTime = m->timenow; 3990 #ifdef _LEGACY_NAT_TRAVERSAL_ 3991 LNT_ClearState(m); 3992 #endif // _LEGACY_NAT_TRAVERSAL_ 3993 3994 if (AddrReply->opcode == NATOp_AddrResponse) 3995 { 3996 #if APPLE_OSX_mDNSResponder 3997 static char msgbuf[16]; 3998 mDNS_snprintf(msgbuf, sizeof(msgbuf), "%d", AddrReply->err); 3999 mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.natpmp.AddressRequest", AddrReply->err ? "failure" : "success", msgbuf, ""); 4000 #endif 4001 if (!AddrReply->err && len < sizeof(NATAddrReply)) { LogMsg("NAT Traversal AddrResponse message too short (%d bytes)", len); return; } 4002 natTraversalHandleAddressReply(m, AddrReply->err, AddrReply->ExtAddr); 4003 } 4004 else if (AddrReply->opcode == NATOp_MapUDPResponse || AddrReply->opcode == NATOp_MapTCPResponse) 4005 { 4006 mDNSu8 Protocol = AddrReply->opcode & 0x7F; 4007 #if APPLE_OSX_mDNSResponder 4008 static char msgbuf[16]; 4009 mDNS_snprintf(msgbuf, sizeof(msgbuf), "%s - %d", AddrReply->opcode == NATOp_MapUDPResponse ? "UDP" : "TCP", PortMapReply->err); 4010 mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.natpmp.PortMapRequest", PortMapReply->err ? "failure" : "success", msgbuf, ""); 4011 #endif 4012 if (!PortMapReply->err) 4013 { 4014 if (len < sizeof(NATPortMapReply)) { LogMsg("NAT Traversal PortMapReply message too short (%d bytes)", len); return; } 4015 PortMapReply->NATRep_lease = (mDNSu32) ((mDNSu32)pkt[12] << 24 | (mDNSu32)pkt[13] << 16 | (mDNSu32)pkt[14] << 8 | pkt[15]); 4016 } 4017 4018 // Since some NAT-PMP server implementations don't return the requested internal port in 4019 // the reply, we can't associate this reply with a particular NATTraversalInfo structure. 4020 // We globally keep track of the most recent error code for mappings. 4021 m->LastNATMapResultCode = PortMapReply->err; 4022 4023 for (ptr = m->NATTraversals; ptr; ptr=ptr->next) 4024 if (ptr->Protocol == Protocol && mDNSSameIPPort(ptr->IntPort, PortMapReply->intport)) 4025 natTraversalHandlePortMapReply(m, ptr, InterfaceID, PortMapReply->err, PortMapReply->extport, PortMapReply->NATRep_lease); 4026 } 4027 else { LogMsg("Received NAT Traversal response with version unknown opcode 0x%X", AddrReply->opcode); return; } 4028 4029 // Don't need an SSDP socket if we get a NAT-PMP packet 4030 if (m->SSDPSocket) { debugf("uDNS_ReceiveNATPMPPacket destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; } 4031 } 4032 4033 // <rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs 4034 // <rdar://problem/4288449> Add check to avoid crashing NAT gateways that have buggy DNS relay code 4035 // 4036 // We know of bugs in home NAT gateways that cause them to crash if they receive certain DNS queries. 4037 // The DNS queries that make them crash are perfectly legal DNS queries, but even if they weren't, 4038 // the gateway shouldn't crash -- in today's world of viruses and network attacks, software has to 4039 // be written assuming that a malicious attacker could send them any packet, properly-formed or not. 4040 // Still, we don't want to be crashing people's home gateways, so we go out of our way to avoid 4041 // the queries that crash them. 4042 // 4043 // Some examples: 4044 // 4045 // 1. Any query where the name ends in ".in-addr.arpa." and the text before this is 32 or more bytes. 4046 // The query type does not need to be PTR -- the gateway will crash for any query type. 4047 // e.g. "ping long-name-crashes-the-buggy-router.in-addr.arpa" will crash one of these. 4048 // 4049 // 2. Any query that results in a large response with the TC bit set. 4050 // 4051 // 3. Any PTR query that doesn't begin with four decimal numbers. 4052 // These gateways appear to assume that the only possible PTR query is a reverse-mapping query 4053 // (e.g. "1.0.168.192.in-addr.arpa") and if they ever get a PTR query where the first four 4054 // labels are not all decimal numbers in the range 0-255, they handle that by crashing. 4055 // These gateways also ignore the remainder of the name following the four decimal numbers 4056 // -- whether or not it actually says in-addr.arpa, they just make up an answer anyway. 4057 // 4058 // The challenge therefore is to craft a query that will discern whether the DNS server 4059 // is one of these buggy ones, without crashing it. Furthermore we don't want our test 4060 // queries making it all the way to the root name servers, putting extra load on those 4061 // name servers and giving Apple a bad reputation. To this end we send this query: 4062 // dig -t ptr 1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa. 4063 // 4064 // The text preceding the ".in-addr.arpa." is under 32 bytes, so it won't cause crash (1). 4065 // It will not yield a large response with the TC bit set, so it won't cause crash (2). 4066 // It starts with four decimal numbers, so it won't cause crash (3). 4067 // The name falls within the "1.0.0.127.in-addr.arpa." domain, the reverse-mapping name for the local 4068 // loopback address, and therefore the query will black-hole at the first properly-configured DNS server 4069 // it reaches, making it highly unlikely that this query will make it all the way to the root. 4070 // 4071 // Finally, the correct response to this query is NXDOMAIN or a similar error, but the 4072 // gateways that ignore the remainder of the name following the four decimal numbers 4073 // give themselves away by actually returning a result for this nonsense query. 4074 4075 mDNSlocal const domainname *DNSRelayTestQuestion = (const domainname*) 4076 "\x1" "1" "\x1" "0" "\x1" "0" "\x3" "127" "\xa" "dnsbugtest" 4077 "\x1" "1" "\x1" "0" "\x1" "0" "\x3" "127" "\x7" "in-addr" "\x4" "arpa"; 4078 4079 // See comments above for DNSRelayTestQuestion 4080 // If this is the kind of query that has the risk of crashing buggy DNS servers, we do a test question first 4081 mDNSlocal mDNSBool NoTestQuery(DNSQuestion *q) 4082 { 4083 int i; 4084 mDNSu8 *p = q->qname.c; 4085 if (q->AuthInfo) return(mDNStrue); // Don't need a test query for private queries sent directly to authoritative server over TLS/TCP 4086 if (q->qtype != kDNSType_PTR) return(mDNStrue); // Don't need a test query for any non-PTR queries 4087 for (i=0; i<4; i++) // If qname does not begin with num.num.num.num, can't skip the test query 4088 { 4089 if (p[0] < 1 || p[0] > 3) return(mDNSfalse); 4090 if ( p[1] < '0' || p[1] > '9' ) return(mDNSfalse); 4091 if (p[0] >= 2 && (p[2] < '0' || p[2] > '9')) return(mDNSfalse); 4092 if (p[0] >= 3 && (p[3] < '0' || p[3] > '9')) return(mDNSfalse); 4093 p += 1 + p[0]; 4094 } 4095 // If remainder of qname is ".in-addr.arpa.", this is a vanilla reverse-mapping query and 4096 // we can safely do it without needing a test query first, otherwise we need the test query. 4097 return(SameDomainName((domainname*)p, (const domainname*)"\x7" "in-addr" "\x4" "arpa")); 4098 } 4099 4100 // Returns mDNStrue if response was handled 4101 mDNSlocal mDNSBool uDNS_ReceiveTestQuestionResponse(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, 4102 const mDNSAddr *const srcaddr, const mDNSIPPort srcport) 4103 { 4104 const mDNSu8 *ptr = msg->data; 4105 DNSQuestion pktq; 4106 DNSServer *s; 4107 mDNSu32 result = 0; 4108 4109 // 1. Find out if this is an answer to one of our test questions 4110 if (msg->h.numQuestions != 1) return(mDNSfalse); 4111 ptr = getQuestion(msg, ptr, end, mDNSInterface_Any, &pktq); 4112 if (!ptr) return(mDNSfalse); 4113 if (pktq.qtype != kDNSType_PTR || pktq.qclass != kDNSClass_IN) return(mDNSfalse); 4114 if (!SameDomainName(&pktq.qname, DNSRelayTestQuestion)) return(mDNSfalse); 4115 4116 // 2. If the DNS relay gave us a positive response, then it's got buggy firmware 4117 // else, if the DNS relay gave us an error or no-answer response, it passed our test 4118 if ((msg->h.flags.b[1] & kDNSFlag1_RC_Mask) == kDNSFlag1_RC_NoErr && msg->h.numAnswers > 0) 4119 result = DNSServer_Failed; 4120 else 4121 result = DNSServer_Passed; 4122 4123 // 3. Find occurrences of this server in our list, and mark them appropriately 4124 for (s = m->DNSServers; s; s = s->next) 4125 { 4126 mDNSBool matchaddr = (s->teststate != result && mDNSSameAddress(srcaddr, &s->addr) && mDNSSameIPPort(srcport, s->port)); 4127 mDNSBool matchid = (s->teststate == DNSServer_Untested && mDNSSameOpaque16(msg->h.id, s->testid)); 4128 if (matchaddr || matchid) 4129 { 4130 DNSQuestion *q; 4131 s->teststate = result; 4132 if (result == DNSServer_Passed) 4133 { 4134 LogInfo("DNS Server %#a:%d (%#a:%d) %d passed%s", 4135 &s->addr, mDNSVal16(s->port), srcaddr, mDNSVal16(srcport), mDNSVal16(s->testid), 4136 matchaddr ? "" : " NOTE: Reply did not come from address to which query was sent"); 4137 } 4138 else 4139 { 4140 LogMsg("NOTE: Wide-Area Service Discovery disabled to avoid crashing defective DNS relay %#a:%d (%#a:%d) %d%s", 4141 &s->addr, mDNSVal16(s->port), srcaddr, mDNSVal16(srcport), mDNSVal16(s->testid), 4142 matchaddr ? "" : " NOTE: Reply did not come from address to which query was sent"); 4143 } 4144 4145 // If this server has just changed state from DNSServer_Untested to DNSServer_Passed, then retrigger any waiting questions. 4146 // We use the NoTestQuery() test so that we only retrigger questions that were actually blocked waiting for this test to complete. 4147 if (result == DNSServer_Passed) // Unblock any questions that were waiting for this result 4148 for (q = m->Questions; q; q=q->next) 4149 if (q->qDNSServer == s && !NoTestQuery(q)) 4150 { 4151 q->ThisQInterval = INIT_UCAST_POLL_INTERVAL / QuestionIntervalStep; 4152 q->unansweredQueries = 0; 4153 q->LastQTime = m->timenow - q->ThisQInterval; 4154 m->NextScheduledQuery = m->timenow; 4155 } 4156 } 4157 } 4158 4159 return(mDNStrue); // Return mDNStrue to tell uDNS_ReceiveMsg it doesn't need to process this packet further 4160 } 4161 4162 // Called from mDNSCoreReceive with the lock held 4163 mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport) 4164 { 4165 DNSQuestion *qptr; 4166 mStatus err = mStatus_NoError; 4167 4168 mDNSu8 StdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery; 4169 mDNSu8 UpdateR = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update; 4170 mDNSu8 QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask); 4171 mDNSu8 rcode = (mDNSu8)(msg->h.flags.b[1] & kDNSFlag1_RC_Mask); 4172 4173 (void)srcport; // Unused 4174 4175 debugf("uDNS_ReceiveMsg from %#-15a with " 4176 "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s", 4177 srcaddr, 4178 msg->h.numQuestions, msg->h.numQuestions == 1 ? ", " : "s,", 4179 msg->h.numAnswers, msg->h.numAnswers == 1 ? ", " : "s,", 4180 msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y, " : "ies,", 4181 msg->h.numAdditionals, msg->h.numAdditionals == 1 ? "" : "s"); 4182 4183 if (QR_OP == StdR) 4184 { 4185 //if (srcaddr && recvLLQResponse(m, msg, end, srcaddr, srcport)) return; 4186 if (uDNS_ReceiveTestQuestionResponse(m, msg, end, srcaddr, srcport)) return; 4187 for (qptr = m->Questions; qptr; qptr = qptr->next) 4188 if (msg->h.flags.b[0] & kDNSFlag0_TC && mDNSSameOpaque16(qptr->TargetQID, msg->h.id) && m->timenow - qptr->LastQTime < RESPONSE_WINDOW) 4189 { 4190 if (!srcaddr) LogMsg("uDNS_ReceiveMsg: TCP DNS response had TC bit set: ignoring"); 4191 else if (qptr->tcp) 4192 { 4193 // There may be a race condition here, if the server decides to drop the connection just as we decide to reuse it 4194 // For now it should not be serious because our normal retry logic (as used to handle UDP packet loss) 4195 // should take care of it but later we may want to look at handling this case explicitly 4196 LogInfo("uDNS_ReceiveMsg: Using existing TCP connection for %##s (%s)", qptr->qname.c, DNSTypeName(qptr->qtype)); 4197 mDNS_DropLockBeforeCallback(); 4198 tcpCallback(qptr->tcp->sock, qptr->tcp, mDNStrue, mStatus_NoError); 4199 mDNS_ReclaimLockAfterCallback(); 4200 } 4201 else qptr->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_Zero, srcaddr, srcport, qptr, mDNSNULL, mDNSNULL); 4202 } 4203 } 4204 4205 if (QR_OP == UpdateR) 4206 { 4207 mDNSu32 lease = GetPktLease(m, msg, end); 4208 mDNSs32 expire = m->timenow + (mDNSs32)lease * mDNSPlatformOneSecond; 4209 4210 //rcode = kDNSFlag1_RC_ServFail; // Simulate server failure (rcode 2) 4211 4212 if (CurrentServiceRecordSet) 4213 LogMsg("uDNS_ReceiveMsg ERROR CurrentServiceRecordSet already set"); 4214 CurrentServiceRecordSet = m->ServiceRegistrations; 4215 4216 while (CurrentServiceRecordSet) 4217 { 4218 ServiceRecordSet *sptr = CurrentServiceRecordSet; 4219 CurrentServiceRecordSet = CurrentServiceRecordSet->uDNS_next; 4220 4221 if (mDNSSameOpaque16(sptr->id, msg->h.id)) 4222 { 4223 err = checkUpdateResult(m, sptr->RR_SRV.resrec.name, rcode, msg, end); 4224 if (!err && sptr->srs_uselease && lease) 4225 if (sptr->RR_SRV.expire - expire >= 0 || sptr->state != regState_UpdatePending) 4226 sptr->RR_SRV.expire = expire; 4227 hndlServiceUpdateReply(m, sptr, err); 4228 CurrentServiceRecordSet = mDNSNULL; 4229 return; 4230 } 4231 } 4232 4233 if (m->CurrentRecord) 4234 LogMsg("uDNS_ReceiveMsg ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 4235 m->CurrentRecord = m->ResourceRecords; 4236 while (m->CurrentRecord) 4237 { 4238 AuthRecord *rptr = m->CurrentRecord; 4239 m->CurrentRecord = m->CurrentRecord->next; 4240 if (AuthRecord_uDNS(rptr) && mDNSSameOpaque16(rptr->updateid, msg->h.id)) 4241 { 4242 err = checkUpdateResult(m, rptr->resrec.name, rcode, msg, end); 4243 if (!err && rptr->uselease && lease) 4244 if (rptr->expire - expire >= 0 || rptr->state != regState_UpdatePending) 4245 rptr->expire = expire; 4246 hndlRecordUpdateReply(m, rptr, err); 4247 m->CurrentRecord = mDNSNULL; 4248 return; 4249 } 4250 } 4251 } 4252 debugf("Received unexpected response: ID %d matches no active records", mDNSVal16(msg->h.id)); 4253 } 4254 4255 // *************************************************************************** 4256 #if COMPILER_LIKES_PRAGMA_MARK 4257 #pragma mark - Query Routines 4258 #endif 4259 4260 mDNSexport void sendLLQRefresh(mDNS *m, DNSQuestion *q) 4261 { 4262 mDNSu8 *end; 4263 LLQOptData llq; 4264 4265 if (q->ReqLease) 4266 if ((q->state == LLQ_Established && q->ntries >= kLLQ_MAX_TRIES) || q->expire - m->timenow < 0) 4267 { 4268 LogMsg("Unable to refresh LLQ %##s (%s) - will retry in %d seconds", q->qname.c, DNSTypeName(q->qtype), LLQ_POLL_INTERVAL / mDNSPlatformOneSecond); 4269 StartLLQPolling(m,q); 4270 return; 4271 } 4272 4273 llq.vers = kLLQ_Vers; 4274 llq.llqOp = kLLQOp_Refresh; 4275 llq.err = q->tcp ? GetLLQEventPort(m, &q->servAddr) : LLQErr_NoError; // If using TCP tell server what UDP port to send notifications to 4276 llq.id = q->id; 4277 llq.llqlease = q->ReqLease; 4278 4279 InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags); 4280 end = putLLQ(&m->omsg, m->omsg.data, q, &llq); 4281 if (!end) { LogMsg("sendLLQRefresh: putLLQ failed %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); return; } 4282 4283 // Note that we (conditionally) add HINFO and TSIG here, since the question might be going away, 4284 // so we may not be able to reference it (most importantly it's AuthInfo) when we actually send the message 4285 end = putHINFO(m, &m->omsg, end, q->AuthInfo); 4286 if (!end) { LogMsg("sendLLQRefresh: putHINFO failed %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); return; } 4287 4288 if (q->AuthInfo) 4289 { 4290 DNSDigest_SignMessageHostByteOrder(&m->omsg, &end, q->AuthInfo); 4291 if (!end) { LogMsg("sendLLQRefresh: DNSDigest_SignMessage failed %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); return; } 4292 } 4293 4294 if (q->AuthInfo && !q->tcp) 4295 { 4296 LogInfo("sendLLQRefresh setting up new TLS session %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 4297 q->tcp = MakeTCPConn(m, &m->omsg, end, kTCPSocketFlags_UseTLS, &q->servAddr, q->servPort, q, mDNSNULL, mDNSNULL); 4298 } 4299 else 4300 { 4301 mStatus err = mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, q->LocalSocket, &q->servAddr, q->servPort, q->tcp ? q->tcp->sock : mDNSNULL, mDNSNULL); 4302 if (err) 4303 { 4304 LogMsg("sendLLQRefresh: mDNSSendDNSMessage%s failed: %d", q->tcp ? " (TCP)" : "", err); 4305 if (q->tcp) { DisposeTCPConn(q->tcp); q->tcp = mDNSNULL; } 4306 } 4307 } 4308 4309 q->ntries++; 4310 4311 debugf("sendLLQRefresh ntries %d %##s (%s)", q->ntries, q->qname.c, DNSTypeName(q->qtype)); 4312 4313 q->LastQTime = m->timenow; 4314 SetNextQueryTime(m, q); 4315 } 4316 4317 mDNSexport void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo) 4318 { 4319 DNSQuestion *q = (DNSQuestion *)zoneInfo->ZoneDataContext; 4320 4321 mDNS_Lock(m); 4322 4323 // If we get here it means that the GetZoneData operation has completed, and is is about to cancel 4324 // its question and free the ZoneData memory. We no longer need to hold onto our pointer (which 4325 // we use for cleaning up if our LLQ is cancelled *before* the GetZoneData operation has completes). 4326 q->nta = mDNSNULL; 4327 q->servAddr = zeroAddr; 4328 q->servPort = zeroIPPort; 4329 4330 if (!err && zoneInfo && !mDNSIPPortIsZero(zoneInfo->Port) && !mDNSAddressIsZero(&zoneInfo->Addr)) 4331 { 4332 q->servAddr = zoneInfo->Addr; 4333 q->servPort = zoneInfo->Port; 4334 q->AuthInfo = zoneInfo->ZonePrivate ? GetAuthInfoForName_internal(m, &q->qname) : mDNSNULL; 4335 q->ntries = 0; 4336 debugf("LLQGotZoneData %#a:%d", &q->servAddr, mDNSVal16(q->servPort)); 4337 startLLQHandshake(m, q); 4338 } 4339 else 4340 { 4341 StartLLQPolling(m,q); 4342 if (err == mStatus_NoSuchNameErr) 4343 { 4344 // this actually failed, so mark it by setting address to all ones 4345 q->servAddr.type = mDNSAddrType_IPv4; 4346 q->servAddr.ip.v4 = onesIPv4Addr; 4347 } 4348 } 4349 4350 mDNS_Unlock(m); 4351 } 4352 4353 // Called in normal callback context (i.e. mDNS_busy and mDNS_reentrancy are both 1) 4354 mDNSlocal void PrivateQueryGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo) 4355 { 4356 DNSQuestion *q = (DNSQuestion *) zoneInfo->ZoneDataContext; 4357 4358 LogInfo("PrivateQueryGotZoneData %##s (%s) err %d Zone %##s Private %d", q->qname.c, DNSTypeName(q->qtype), err, zoneInfo->ZoneName.c, zoneInfo->ZonePrivate); 4359 4360 // If we get here it means that the GetZoneData operation has completed, and is is about to cancel 4361 // its question and free the ZoneData memory. We no longer need to hold onto our pointer (which 4362 // we use for cleaning up if our LLQ is cancelled *before* the GetZoneData operation has completes). 4363 q->nta = mDNSNULL; 4364 4365 if (err || !zoneInfo || mDNSAddressIsZero(&zoneInfo->Addr) || mDNSIPPortIsZero(zoneInfo->Port)) 4366 { 4367 LogInfo("ERROR: PrivateQueryGotZoneData %##s (%s) invoked with error code %d %p %#a:%d", 4368 q->qname.c, DNSTypeName(q->qtype), err, zoneInfo, 4369 zoneInfo ? &zoneInfo->Addr : mDNSNULL, 4370 zoneInfo ? mDNSVal16(zoneInfo->Port) : 0); 4371 return; 4372 } 4373 4374 if (!zoneInfo->ZonePrivate) 4375 { 4376 debugf("Private port lookup failed -- retrying without TLS -- %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 4377 q->AuthInfo = mDNSNULL; // Clear AuthInfo so we try again non-private 4378 q->ThisQInterval = InitialQuestionInterval; 4379 q->LastQTime = m->timenow - q->ThisQInterval; 4380 mDNS_Lock(m); 4381 SetNextQueryTime(m, q); 4382 mDNS_Unlock(m); 4383 return; 4384 // Next call to uDNS_CheckCurrentQuestion() will do this as a non-private query 4385 } 4386 4387 if (!q->AuthInfo) 4388 { 4389 LogMsg("ERROR: PrivateQueryGotZoneData: cannot find credentials for q %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 4390 return; 4391 } 4392 4393 q->TargetQID = mDNS_NewMessageID(m); 4394 if (q->tcp) DisposeTCPConn(q->tcp); 4395 q->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_UseTLS, &zoneInfo->Addr, zoneInfo->Port, q, mDNSNULL, mDNSNULL); 4396 } 4397 4398 // *************************************************************************** 4399 #if COMPILER_LIKES_PRAGMA_MARK 4400 #pragma mark - Dynamic Updates 4401 #endif 4402 4403 // Called in normal callback context (i.e. mDNS_busy and mDNS_reentrancy are both 1) 4404 mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData) 4405 { 4406 AuthRecord *newRR = (AuthRecord*)zoneData->ZoneDataContext; 4407 AuthRecord *ptr; 4408 int c1, c2; 4409 4410 if (m->mDNS_busy != m->mDNS_reentrancy) 4411 LogMsg("RecordRegistrationGotZoneData: mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 4412 4413 newRR->nta = mDNSNULL; 4414 4415 // Start off assuming we're going to use a lease 4416 // If we get an error from the server, and the update port as given in the SRV record is 53, then we'll retry without the lease option 4417 newRR->uselease = mDNStrue; 4418 4419 // make sure record is still in list (!!!) 4420 for (ptr = m->ResourceRecords; ptr; ptr = ptr->next) if (ptr == newRR) break; 4421 if (!ptr) { LogMsg("RecordRegistrationGotZoneData - RR no longer in list. Discarding."); return; } 4422 4423 // check error/result 4424 if (err) 4425 { 4426 if (err != mStatus_NoSuchNameErr) LogMsg("RecordRegistrationGotZoneData: error %d", err); 4427 return; 4428 } 4429 4430 if (!zoneData) { LogMsg("ERROR: RecordRegistrationGotZoneData invoked with NULL result and no error"); return; } 4431 4432 if (newRR->resrec.rrclass != zoneData->ZoneClass) 4433 { 4434 LogMsg("ERROR: New resource record's class (%d) does not match zone class (%d)", newRR->resrec.rrclass, zoneData->ZoneClass); 4435 return; 4436 } 4437 4438 // Don't try to do updates to the root name server. 4439 // We might be tempted also to block updates to any single-label name server (e.g. com, edu, net, etc.) but some 4440 // organizations use their own private pseudo-TLD, like ".home", etc, and we don't want to block that. 4441 if (zoneData->ZoneName.c[0] == 0) 4442 { 4443 LogInfo("RecordRegistrationGotZoneData: No name server found claiming responsibility for \"%##s\"!", newRR->resrec.name->c); 4444 return; 4445 } 4446 4447 // Store discovered zone data 4448 c1 = CountLabels(newRR->resrec.name); 4449 c2 = CountLabels(&zoneData->ZoneName); 4450 if (c2 > c1) 4451 { 4452 LogMsg("RecordRegistrationGotZoneData: Zone \"%##s\" is longer than \"%##s\"", zoneData->ZoneName.c, newRR->resrec.name->c); 4453 return; 4454 } 4455 newRR->zone = SkipLeadingLabels(newRR->resrec.name, c1-c2); 4456 if (!SameDomainName(newRR->zone, &zoneData->ZoneName)) 4457 { 4458 LogMsg("RecordRegistrationGotZoneData: Zone \"%##s\" does not match \"%##s\" for \"%##s\"", newRR->zone->c, zoneData->ZoneName.c, newRR->resrec.name->c); 4459 return; 4460 } 4461 newRR->UpdateServer = zoneData->Addr; 4462 newRR->UpdatePort = zoneData->Port; 4463 newRR->Private = zoneData->ZonePrivate; 4464 debugf("RecordRegistrationGotZoneData: Set newRR->UpdateServer %##s %##s to %#a:%d", 4465 newRR->resrec.name->c, zoneData->ZoneName.c, &newRR->UpdateServer, mDNSVal16(newRR->UpdatePort)); 4466 4467 if (mDNSIPPortIsZero(zoneData->Port) || mDNSAddressIsZero(&zoneData->Addr)) 4468 { 4469 LogInfo("RecordRegistrationGotZoneData: No _dns-update._udp service found for \"%##s\"!", newRR->resrec.name->c); 4470 return; 4471 } 4472 4473 newRR->ThisAPInterval = 5 * mDNSPlatformOneSecond; // After doubling, first retry will happen after ten seconds 4474 4475 mDNS_Lock(m); // SendRecordRegistration expects to be called with the lock held 4476 SendRecordRegistration(m, newRR); 4477 mDNS_Unlock(m); 4478 } 4479 4480 mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr) 4481 { 4482 mDNSu8 *ptr = m->omsg.data; 4483 mDNSu8 *end = (mDNSu8 *)&m->omsg + sizeof(DNSMessage); 4484 4485 if (mDNSIPv4AddressIsZero(rr->UpdateServer.ip.v4)) // Don't know our UpdateServer yet 4486 { 4487 rr->LastAPTime = m->timenow; 4488 if (rr->ThisAPInterval < mDNSPlatformOneSecond * 5) 4489 rr->ThisAPInterval = mDNSPlatformOneSecond * 5; 4490 return; 4491 } 4492 4493 InitializeDNSMessage(&m->omsg.h, rr->updateid, UpdateReqFlags); 4494 4495 ptr = putZone(&m->omsg, ptr, end, rr->zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass)); 4496 if (ptr) ptr = putDeletionRecord(&m->omsg, ptr, &rr->resrec); 4497 if (!ptr) 4498 { 4499 LogMsg("SendRecordDeregistration Error: could not contruct deregistration packet for %s", ARDisplayString(m, rr)); 4500 if (rr->state == regState_DeregPending) CompleteDeregistration(m, rr); 4501 } 4502 else 4503 { 4504 rr->expire = 0; // Indicate that we have no active registration any more 4505 if (rr->Private) 4506 { 4507 LogInfo("SendRecordDeregistration TCP %p %s", rr->tcp, ARDisplayString(m, rr)); 4508 if (rr->tcp) LogInfo("SendRecordDeregistration: Disposing existing TCP connection for %s", ARDisplayString(m, rr)); 4509 if (rr->tcp) DisposeTCPConn(rr->tcp); 4510 rr->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &rr->UpdateServer, rr->UpdatePort, mDNSNULL, mDNSNULL, rr); 4511 if (!rr->tcp) rr->ThisAPInterval = mDNSPlatformOneSecond * 5; // If failed to make TCP connection, try again in ten seconds (5*2) 4512 else if (rr->ThisAPInterval < mDNSPlatformOneSecond * 30) rr->ThisAPInterval = mDNSPlatformOneSecond * 30; 4513 SetRecordRetry(m, rr, mStatus_NoError); 4514 } 4515 else 4516 { 4517 mStatus err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &rr->UpdateServer, rr->UpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, rr->resrec.name)); 4518 if (err) debugf("ERROR: SendRecordDeregistration - mDNSSendDNSMessage - %d", err); 4519 if (rr->state == regState_DeregPending) CompleteDeregistration(m, rr); // Don't touch rr after this 4520 } 4521 } 4522 } 4523 4524 mDNSexport mStatus uDNS_DeregisterRecord(mDNS *const m, AuthRecord *const rr) 4525 { 4526 switch (rr->state) 4527 { 4528 case regState_NATMap: LogMsg("regState_NATMap %##s type %s", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return mStatus_NoError; 4529 case regState_ExtraQueued: rr->state = regState_Unregistered; break; 4530 case regState_Refresh: 4531 case regState_Pending: 4532 case regState_UpdatePending: 4533 case regState_FetchingZoneData: 4534 case regState_Registered: break; 4535 case regState_DeregPending: break; 4536 case regState_DeregDeferred: LogMsg("regState_DeregDeferred %##s type %s", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return mStatus_NoError; 4537 case regState_Unregistered: LogMsg("regState_Unregistered %##s type %s", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return mStatus_NoError; 4538 case regState_NATError: LogMsg("regState_NATError %##s type %s", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return mStatus_NoError; 4539 case regState_NoTarget: LogMsg("regState_NoTarget %##s type %s", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return mStatus_NoError; 4540 default: LogMsg("uDNS_DeregisterRecord: State %d for %##s type %s", rr->state, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return mStatus_NoError; 4541 } 4542 4543 if (rr->state != regState_Unregistered) { rr->state = regState_DeregPending; SendRecordDeregistration(m, rr); } 4544 return mStatus_NoError; 4545 } 4546 4547 // Called with lock held 4548 mDNSexport mStatus uDNS_DeregisterService(mDNS *const m, ServiceRecordSet *srs) 4549 { 4550 char *errmsg = "Unknown State"; 4551 4552 if (m->mDNS_busy != m->mDNS_reentrancy+1) 4553 LogMsg("uDNS_DeregisterService: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 4554 4555 // don't re-register with a new target following deregistration 4556 srs->SRVChanged = srs->SRVUpdateDeferred = mDNSfalse; 4557 4558 if (srs->srs_nta) { CancelGetZoneData(m, srs->srs_nta); srs->srs_nta = mDNSNULL; } 4559 4560 if (srs->NATinfo.clientContext) 4561 { 4562 mDNS_StopNATOperation_internal(m, &srs->NATinfo); 4563 srs->NATinfo.clientContext = mDNSNULL; 4564 } 4565 4566 switch (srs->state) 4567 { 4568 case regState_Unregistered: 4569 debugf("uDNS_DeregisterService - service %##s not registered", srs->RR_SRV.resrec.name->c); 4570 return mStatus_BadReferenceErr; 4571 case regState_DeregPending: 4572 case regState_DeregDeferred: 4573 debugf("Double deregistration of service %##s", srs->RR_SRV.resrec.name->c); 4574 return mStatus_NoError; 4575 case regState_NATError: // not registered 4576 case regState_NATMap: // not registered 4577 case regState_NoTarget: // not registered 4578 unlinkSRS(m, srs); 4579 srs->state = regState_Unregistered; 4580 mDNS_DropLockBeforeCallback(); 4581 srs->ServiceCallback(m, srs, mStatus_MemFree); 4582 mDNS_ReclaimLockAfterCallback(); 4583 return mStatus_NoError; 4584 case regState_Pending: 4585 case regState_Refresh: 4586 case regState_UpdatePending: 4587 case regState_FetchingZoneData: 4588 case regState_Registered: 4589 srs->state = regState_DeregPending; 4590 SendServiceDeregistration(m, srs); 4591 return mStatus_NoError; 4592 case regState_ExtraQueued: // only for record registrations 4593 errmsg = "bad state (regState_ExtraQueued)"; 4594 goto error; 4595 default: LogMsg("uDNS_DeregisterService: Unknown state %d for %##s", srs->state, srs->RR_SRV.resrec.name->c); 4596 } 4597 4598 error: 4599 LogMsg("Error, uDNS_DeregisterService: %s", errmsg); 4600 return mStatus_BadReferenceErr; 4601 } 4602 4603 mDNSexport mStatus uDNS_UpdateRecord(mDNS *m, AuthRecord *rr) 4604 { 4605 ServiceRecordSet *parent = mDNSNULL; 4606 AuthRecord *rptr; 4607 regState_t *stateptr = mDNSNULL; 4608 4609 // find the record in registered service list 4610 for (parent = m->ServiceRegistrations; parent; parent = parent->uDNS_next) 4611 if (&parent->RR_TXT == rr) { stateptr = &parent->state; break; } 4612 4613 if (!parent) 4614 { 4615 // record not part of a service - check individual record registrations 4616 for (rptr = m->ResourceRecords; rptr; rptr = rptr->next) 4617 if (rptr == rr) { stateptr = &rr->state; break; } 4618 if (!rptr) goto unreg_error; 4619 } 4620 4621 switch(*stateptr) 4622 { 4623 case regState_DeregPending: 4624 case regState_DeregDeferred: 4625 case regState_Unregistered: 4626 // not actively registered 4627 goto unreg_error; 4628 4629 case regState_FetchingZoneData: 4630 case regState_NATMap: 4631 case regState_ExtraQueued: 4632 case regState_NoTarget: 4633 // change rdata directly since it hasn't been sent yet 4634 if (rr->UpdateCallback) rr->UpdateCallback(m, rr, rr->resrec.rdata); 4635 SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength); 4636 rr->NewRData = mDNSNULL; 4637 return mStatus_NoError; 4638 4639 case regState_Pending: 4640 case regState_Refresh: 4641 case regState_UpdatePending: 4642 // registration in-flight. queue rdata and return 4643 if (rr->QueuedRData && rr->UpdateCallback) 4644 // if unsent rdata is already queued, free it before we replace it 4645 rr->UpdateCallback(m, rr, rr->QueuedRData); 4646 rr->QueuedRData = rr->NewRData; 4647 rr->QueuedRDLen = rr->newrdlength; 4648 rr->NewRData = mDNSNULL; 4649 return mStatus_NoError; 4650 4651 case regState_Registered: 4652 rr->OrigRData = rr->resrec.rdata; 4653 rr->OrigRDLen = rr->resrec.rdlength; 4654 rr->InFlightRData = rr->NewRData; 4655 rr->InFlightRDLen = rr->newrdlength; 4656 rr->NewRData = mDNSNULL; 4657 *stateptr = regState_UpdatePending; 4658 if (parent) SendServiceRegistration(m, parent); 4659 else SendRecordRegistration(m, rr); 4660 return mStatus_NoError; 4661 4662 case regState_NATError: 4663 LogMsg("ERROR: uDNS_UpdateRecord called for record %##s with bad state regState_NATError", rr->resrec.name->c); 4664 return mStatus_UnknownErr; // states for service records only 4665 4666 default: LogMsg("uDNS_UpdateRecord: Unknown state %d for %##s", *stateptr, rr->resrec.name->c); 4667 } 4668 4669 unreg_error: 4670 LogMsg("Requested update of record %##s type %d, part of service not currently registered", 4671 rr->resrec.name->c, rr->resrec.rrtype); 4672 return mStatus_Invalid; 4673 } 4674 4675 // *************************************************************************** 4676 #if COMPILER_LIKES_PRAGMA_MARK 4677 #pragma mark - Periodic Execution Routines 4678 #endif 4679 4680 // The question to be checked is not passed in as an explicit parameter; 4681 // instead it is implicit that the question to be checked is m->CurrentQuestion. 4682 mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) 4683 { 4684 DNSQuestion *q = m->CurrentQuestion; 4685 mDNSs32 sendtime = q->LastQTime + q->ThisQInterval; 4686 // Don't allow sendtime to be earlier than SuppressStdPort53Queries 4687 if (!q->LongLived && m->SuppressStdPort53Queries && sendtime - m->SuppressStdPort53Queries < 0) 4688 sendtime = m->SuppressStdPort53Queries; 4689 if (m->timenow - sendtime < 0) return; 4690 4691 if (q->LongLived) 4692 { 4693 switch (q->state) 4694 { 4695 case LLQ_InitialRequest: startLLQHandshake(m, q); break; 4696 case LLQ_SecondaryRequest: sendChallengeResponse(m, q, mDNSNULL); break; 4697 case LLQ_Established: sendLLQRefresh(m, q); break; 4698 case LLQ_Poll: break; // Do nothing (handled below) 4699 } 4700 } 4701 4702 // We repeat the check above (rather than just making this the "else" case) because startLLQHandshake can change q->state to LLQ_Poll 4703 if (!(q->LongLived && q->state != LLQ_Poll)) 4704 { 4705 if (q->unansweredQueries >= MAX_UCAST_UNANSWERED_QUERIES) 4706 { 4707 DNSServer *orig = q->qDNSServer; 4708 if (orig) LogInfo("Sent %d unanswered queries for %##s (%s) to %#a:%d (%##s)", q->unansweredQueries, q->qname.c, DNSTypeName(q->qtype), &orig->addr, mDNSVal16(orig->port), orig->domain.c); 4709 4710 PushDNSServerToEnd(m, q); 4711 q->unansweredQueries = 0; 4712 } 4713 4714 if (q->qDNSServer && q->qDNSServer->teststate != DNSServer_Disabled) 4715 { 4716 mDNSu8 *end = m->omsg.data; 4717 mStatus err = mStatus_NoError; 4718 mDNSBool private = mDNSfalse; 4719 4720 InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags); 4721 4722 if (q->qDNSServer->teststate != DNSServer_Untested || NoTestQuery(q)) 4723 { 4724 end = putQuestion(&m->omsg, m->omsg.data, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass); 4725 private = (q->AuthInfo && q->AuthInfo->AutoTunnel); 4726 } 4727 else if (m->timenow - q->qDNSServer->lasttest >= INIT_UCAST_POLL_INTERVAL) // Make sure at least three seconds has elapsed since last test query 4728 { 4729 LogInfo("Sending DNS test query to %#a:%d", &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port)); 4730 q->ThisQInterval = INIT_UCAST_POLL_INTERVAL / QuestionIntervalStep; 4731 q->qDNSServer->lasttest = m->timenow; 4732 end = putQuestion(&m->omsg, m->omsg.data, m->omsg.data + AbsoluteMaxDNSMessageData, DNSRelayTestQuestion, kDNSType_PTR, kDNSClass_IN); 4733 q->qDNSServer->testid = m->omsg.h.id; 4734 } 4735 4736 if (end > m->omsg.data && (q->qDNSServer->teststate != DNSServer_Failed || NoTestQuery(q))) 4737 { 4738 //LogMsg("uDNS_CheckCurrentQuestion %p %d %p %##s (%s)", q, sendtime - m->timenow, private, q->qname.c, DNSTypeName(q->qtype)); 4739 if (private) 4740 { 4741 if (q->nta) CancelGetZoneData(m, q->nta); 4742 q->nta = StartGetZoneData(m, &q->qname, q->LongLived ? ZoneServiceLLQ : ZoneServiceQuery, PrivateQueryGotZoneData, q); 4743 q->ThisQInterval = (LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10)) / QuestionIntervalStep; 4744 } 4745 else 4746 { 4747 if (!q->LocalSocket) q->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort); 4748 if (!q->LocalSocket) err = mStatus_NoMemoryErr; // If failed to make socket (should be very rare), we'll try again next time 4749 else err = mDNSSendDNSMessage(m, &m->omsg, end, q->qDNSServer->interface, q->LocalSocket, &q->qDNSServer->addr, q->qDNSServer->port, mDNSNULL, mDNSNULL); 4750 m->SuppressStdPort53Queries = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+99)/100); 4751 } 4752 } 4753 4754 if (err) debugf("ERROR: uDNS_idle - mDNSSendDNSMessage - %d", err); // surpress syslog messages if we have no network 4755 else 4756 { 4757 q->ThisQInterval = q->ThisQInterval * QuestionIntervalStep; // Only increase interval if send succeeded 4758 q->unansweredQueries++; 4759 if (q->ThisQInterval > MAX_UCAST_POLL_INTERVAL) 4760 q->ThisQInterval = MAX_UCAST_POLL_INTERVAL; 4761 debugf("Increased ThisQInterval to %d for %##s (%s)", q->ThisQInterval, q->qname.c, DNSTypeName(q->qtype)); 4762 } 4763 q->LastQTime = m->timenow; 4764 SetNextQueryTime(m, q); 4765 } 4766 else 4767 { 4768 // If we have no server for this query, or the only server is a disabled one, then we deliver 4769 // a transient failure indication to the client. This is important for things like iPhone 4770 // where we want to return timely feedback to the user when no network is available. 4771 // After calling MakeNegativeCacheRecord() we store the resulting record in the 4772 // cache so that it will be visible to other clients asking the same question. 4773 // (When we have a group of identical questions, only the active representative of the group gets 4774 // passed to uDNS_CheckCurrentQuestion -- we only want one set of query packets hitting the wire -- 4775 // but we want *all* of the questions to get answer callbacks.) 4776 4777 CacheRecord *rr; 4778 const mDNSu32 slot = HashSlot(&q->qname); 4779 CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); 4780 if (cg) 4781 for (rr = cg->members; rr; rr=rr->next) 4782 if (SameNameRecordAnswersQuestion(&rr->resrec, q)) mDNS_PurgeCacheResourceRecord(m, rr); 4783 4784 if (!q->qDNSServer) debugf("uDNS_CheckCurrentQuestion no DNS server for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 4785 else LogMsg("uDNS_CheckCurrentQuestion DNS server %#a:%d for %##s is disabled", &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qname.c); 4786 4787 MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any); 4788 // Inactivate this question until the next change of DNS servers (do this before AnswerCurrentQuestionWithResourceRecord) 4789 q->ThisQInterval = 0; 4790 q->unansweredQueries = 0; 4791 CreateNewCacheEntry(m, slot, cg); 4792 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 4793 // MUST NOT touch m->CurrentQuestion (or q) after this -- client callback could have deleted it 4794 } 4795 } 4796 } 4797 4798 mDNSlocal void CheckNATMappings(mDNS *m) 4799 { 4800 mStatus err = mStatus_NoError; 4801 mDNSBool rfc1918 = mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4); 4802 mDNSBool HaveRoutable = !rfc1918 && !mDNSIPv4AddressIsZero(m->AdvertisedV4.ip.v4); 4803 m->NextScheduledNATOp = m->timenow + 0x3FFFFFFF; 4804 4805 if (HaveRoutable) m->ExternalAddress = m->AdvertisedV4.ip.v4; 4806 4807 if (m->NATTraversals && rfc1918) // Do we need to open NAT-PMP socket to receive multicast announcements from router? 4808 { 4809 if (m->NATMcastRecvskt == mDNSNULL) // If we are behind a NAT and the socket hasn't been opened yet, open it 4810 { 4811 // we need to log a message if we can't get our socket, but only the first time (after success) 4812 static mDNSBool needLog = mDNStrue; 4813 m->NATMcastRecvskt = mDNSPlatformUDPSocket(m, NATPMPAnnouncementPort); 4814 if (!m->NATMcastRecvskt) 4815 { 4816 if (needLog) 4817 { 4818 LogMsg("CheckNATMappings: Failed to allocate port 5350 UDP multicast socket for NAT-PMP announcements"); 4819 needLog = mDNSfalse; 4820 } 4821 } 4822 else 4823 needLog = mDNStrue; 4824 } 4825 } 4826 else // else, we don't want to listen for announcements, so close them if they're open 4827 { 4828 if (m->NATMcastRecvskt) { mDNSPlatformUDPClose(m->NATMcastRecvskt); m->NATMcastRecvskt = mDNSNULL; } 4829 if (m->SSDPSocket) { debugf("CheckNATMappings destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; } 4830 } 4831 4832 if (m->NATTraversals) 4833 { 4834 if (m->timenow - m->retryGetAddr >= 0) 4835 { 4836 err = uDNS_SendNATMsg(m, mDNSNULL); // Will also do UPnP discovery for us, if necessary 4837 if (!err) 4838 { 4839 if (m->retryIntervalGetAddr < NATMAP_INIT_RETRY) m->retryIntervalGetAddr = NATMAP_INIT_RETRY; 4840 else if (m->retryIntervalGetAddr < NATMAP_MAX_RETRY_INTERVAL / 2) m->retryIntervalGetAddr *= 2; 4841 else m->retryIntervalGetAddr = NATMAP_MAX_RETRY_INTERVAL; 4842 } 4843 // Always update m->retryGetAddr, even if we fail to send the packet. Otherwise in cases where we can't send the packet 4844 // (like when we have no active interfaces) we'll spin in an infinite loop repeatedly failing to send the packet 4845 m->retryGetAddr = m->timenow + m->retryIntervalGetAddr; 4846 } 4847 // Even when we didn't send the GetAddr packet, still need to make sure NextScheduledNATOp is set correctly 4848 if (m->NextScheduledNATOp - m->retryGetAddr > 0) 4849 m->NextScheduledNATOp = m->retryGetAddr; 4850 } 4851 4852 if (m->CurrentNATTraversal) LogMsg("WARNING m->CurrentNATTraversal already in use"); 4853 m->CurrentNATTraversal = m->NATTraversals; 4854 4855 while (m->CurrentNATTraversal) 4856 { 4857 NATTraversalInfo *cur = m->CurrentNATTraversal; 4858 m->CurrentNATTraversal = m->CurrentNATTraversal->next; 4859 4860 if (HaveRoutable) // If not RFC 1918 address, our own address and port are effectively our external address and port 4861 { 4862 cur->ExpiryTime = 0; 4863 cur->NewResult = mStatus_NoError; 4864 } 4865 else if (cur->Protocol) // Check if it's time to send port mapping packets 4866 { 4867 if (m->timenow - cur->retryPortMap >= 0) // Time to do something with this mapping 4868 { 4869 if (cur->ExpiryTime && cur->ExpiryTime - m->timenow < 0) // Mapping has expired 4870 { 4871 cur->ExpiryTime = 0; 4872 cur->retryInterval = NATMAP_INIT_RETRY; 4873 } 4874 4875 //LogMsg("uDNS_SendNATMsg"); 4876 err = uDNS_SendNATMsg(m, cur); 4877 4878 if (cur->ExpiryTime) // If have active mapping then set next renewal time halfway to expiry 4879 NATSetNextRenewalTime(m, cur); 4880 else // else no mapping; use exponential backoff sequence 4881 { 4882 if (cur->retryInterval < NATMAP_INIT_RETRY ) cur->retryInterval = NATMAP_INIT_RETRY; 4883 else if (cur->retryInterval < NATMAP_MAX_RETRY_INTERVAL / 2) cur->retryInterval *= 2; 4884 else cur->retryInterval = NATMAP_MAX_RETRY_INTERVAL; 4885 cur->retryPortMap = m->timenow + cur->retryInterval; 4886 } 4887 } 4888 4889 if (m->NextScheduledNATOp - cur->retryPortMap > 0) 4890 m->NextScheduledNATOp = cur->retryPortMap; 4891 } 4892 4893 // Notify the client if necessary. We invoke the callback if: 4894 // (1) we have an ExternalAddress, or we've tried and failed a couple of times to discover it 4895 // and (2) the client doesn't want a mapping, or the client won't need a mapping, or the client has a successful mapping, or we've tried and failed a couple of times 4896 // and (3) we have new data to give the client that's changed since the last callback 4897 if (!mDNSIPv4AddressIsZero(m->ExternalAddress) || m->retryIntervalGetAddr > NATMAP_INIT_RETRY * 8) 4898 { 4899 const mStatus EffectiveResult = cur->NewResult ? cur->NewResult : mDNSv4AddrIsRFC1918(&m->ExternalAddress) ? mStatus_DoubleNAT : mStatus_NoError; 4900 const mDNSIPPort ExternalPort = HaveRoutable ? cur->IntPort : 4901 !mDNSIPv4AddressIsZero(m->ExternalAddress) && cur->ExpiryTime ? cur->RequestedPort : zeroIPPort; 4902 if (!cur->Protocol || HaveRoutable || cur->ExpiryTime || cur->retryInterval > NATMAP_INIT_RETRY * 8) 4903 if (!mDNSSameIPv4Address(cur->ExternalAddress, m->ExternalAddress) || 4904 !mDNSSameIPPort (cur->ExternalPort, ExternalPort) || 4905 cur->Result != EffectiveResult) 4906 { 4907 //LogMsg("NAT callback %d %d %d", cur->Protocol, cur->ExpiryTime, cur->retryInterval); 4908 if (cur->Protocol && mDNSIPPortIsZero(ExternalPort) && !mDNSIPv4AddressIsZero(m->Router.ip.v4)) 4909 { 4910 if (!EffectiveResult) 4911 LogInfo("Failed to obtain NAT port mapping %p from router %#a external address %.4a internal port %5d interval %d error %d", 4912 cur, &m->Router, &m->ExternalAddress, mDNSVal16(cur->IntPort), cur->retryInterval, EffectiveResult); 4913 else 4914 LogMsg("Failed to obtain NAT port mapping %p from router %#a external address %.4a internal port %5d interval %d error %d", 4915 cur, &m->Router, &m->ExternalAddress, mDNSVal16(cur->IntPort), cur->retryInterval, EffectiveResult); 4916 } 4917 4918 cur->ExternalAddress = m->ExternalAddress; 4919 cur->ExternalPort = ExternalPort; 4920 cur->Lifetime = cur->ExpiryTime && !mDNSIPPortIsZero(ExternalPort) ? 4921 (cur->ExpiryTime - m->timenow + mDNSPlatformOneSecond/2) / mDNSPlatformOneSecond : 0; 4922 cur->Result = EffectiveResult; 4923 mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback 4924 if (cur->clientCallback) 4925 cur->clientCallback(m, cur); 4926 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 4927 // MUST NOT touch cur after invoking the callback 4928 } 4929 } 4930 } 4931 } 4932 4933 mDNSlocal mDNSs32 CheckRecordRegistrations(mDNS *m) 4934 { 4935 AuthRecord *rr; 4936 mDNSs32 nextevent = m->timenow + 0x3FFFFFFF; 4937 4938 for (rr = m->ResourceRecords; rr; rr = rr->next) 4939 { 4940 if (rr->state == regState_FetchingZoneData || 4941 rr->state == regState_Pending || rr->state == regState_DeregPending || rr->state == regState_UpdatePending || 4942 rr->state == regState_DeregDeferred || rr->state == regState_Refresh || rr->state == regState_Registered) 4943 { 4944 if (rr->LastAPTime + rr->ThisAPInterval - m->timenow < 0) 4945 { 4946 if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; } 4947 if (rr->state == regState_FetchingZoneData) 4948 { 4949 if (rr->nta) CancelGetZoneData(m, rr->nta); 4950 rr->nta = StartGetZoneData(m, rr->resrec.name, ZoneServiceUpdate, RecordRegistrationGotZoneData, rr); 4951 SetRecordRetry(m, rr, mStatus_NoError); 4952 } 4953 else if (rr->state == regState_DeregPending) SendRecordDeregistration(m, rr); 4954 else SendRecordRegistration(m, rr); 4955 } 4956 if (nextevent - (rr->LastAPTime + rr->ThisAPInterval) > 0) 4957 nextevent = (rr->LastAPTime + rr->ThisAPInterval); 4958 } 4959 } 4960 return nextevent; 4961 } 4962 4963 mDNSlocal mDNSs32 CheckServiceRegistrations(mDNS *m) 4964 { 4965 mDNSs32 nextevent = m->timenow + 0x3FFFFFFF; 4966 4967 if (CurrentServiceRecordSet) 4968 LogMsg("CheckServiceRegistrations ERROR CurrentServiceRecordSet already set"); 4969 CurrentServiceRecordSet = m->ServiceRegistrations; 4970 4971 // Note: ServiceRegistrations list is in the order they were created; important for in-order event delivery 4972 while (CurrentServiceRecordSet) 4973 { 4974 ServiceRecordSet *srs = CurrentServiceRecordSet; 4975 CurrentServiceRecordSet = CurrentServiceRecordSet->uDNS_next; 4976 if (srs->state == regState_FetchingZoneData || 4977 srs->state == regState_Pending || srs->state == regState_DeregPending || srs->state == regState_DeregDeferred || 4978 srs->state == regState_Refresh || srs->state == regState_UpdatePending || srs->state == regState_Registered) 4979 { 4980 if (srs->RR_SRV.LastAPTime + srs->RR_SRV.ThisAPInterval - m->timenow <= 0) 4981 { 4982 if (srs->tcp) { DisposeTCPConn(srs->tcp); srs->tcp = mDNSNULL; } 4983 if (srs->state == regState_FetchingZoneData) 4984 { 4985 if (srs->srs_nta) CancelGetZoneData(m, srs->srs_nta); 4986 srs->srs_nta = StartGetZoneData(m, srs->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, srs); 4987 SetRecordRetry(m, &srs->RR_SRV, mStatus_NoError); 4988 } 4989 else if (srs->state == regState_DeregPending) SendServiceDeregistration(m, srs); 4990 else SendServiceRegistration(m, srs); 4991 } 4992 if (nextevent - (srs->RR_SRV.LastAPTime + srs->RR_SRV.ThisAPInterval) > 0) 4993 nextevent = (srs->RR_SRV.LastAPTime + srs->RR_SRV.ThisAPInterval); 4994 } 4995 } 4996 return nextevent; 4997 } 4998 4999 mDNSexport void uDNS_Execute(mDNS *const m) 5000 { 5001 mDNSs32 nexte; 5002 5003 m->NextuDNSEvent = m->timenow + 0x3FFFFFFF; 5004 5005 if (m->NextSRVUpdate && m->NextSRVUpdate - m->timenow < 0) 5006 { m->NextSRVUpdate = 0; UpdateSRVRecords(m); } 5007 5008 CheckNATMappings(m); 5009 5010 if (m->SuppressStdPort53Queries && m->timenow - m->SuppressStdPort53Queries >= 0) 5011 m->SuppressStdPort53Queries = 0; // If suppression time has passed, clear it 5012 5013 nexte = CheckRecordRegistrations(m); 5014 if (nexte - m->NextuDNSEvent < 0) m->NextuDNSEvent = nexte; 5015 5016 nexte = CheckServiceRegistrations(m); 5017 if (nexte - m->NextuDNSEvent < 0) m->NextuDNSEvent = nexte; 5018 } 5019 5020 // *************************************************************************** 5021 #if COMPILER_LIKES_PRAGMA_MARK 5022 #pragma mark - Startup, Shutdown, and Sleep 5023 #endif 5024 5025 // simplest sleep logic - rather than having sleep states that must be dealt with explicitly in all parts of 5026 // the code, we simply send a deregistration, and put the service in Refresh state, with a timeout far enough 5027 // in the future that we'll sleep (or the sleep will be cancelled) before it is retransmitted. Then to wake, 5028 // we just move up the timers. 5029 5030 mDNSexport void SleepRecordRegistrations(mDNS *m) 5031 { 5032 AuthRecord *rr; 5033 for (rr = m->ResourceRecords; rr; rr=rr->next) 5034 if (AuthRecord_uDNS(rr)) 5035 if (rr->state == regState_Registered || 5036 rr->state == regState_Refresh) 5037 { 5038 SendRecordDeregistration(m, rr); 5039 rr->state = regState_Refresh; 5040 rr->LastAPTime = m->timenow; 5041 rr->ThisAPInterval = 300 * mDNSPlatformOneSecond; 5042 } 5043 } 5044 5045 mDNSexport void SleepServiceRegistrations(mDNS *m) 5046 { 5047 ServiceRecordSet *srs = m->ServiceRegistrations; 5048 while (srs) 5049 { 5050 LogInfo("SleepServiceRegistrations: state %d %s", srs->state, ARDisplayString(m, &srs->RR_SRV)); 5051 if (srs->srs_nta) { CancelGetZoneData(m, srs->srs_nta); srs->srs_nta = mDNSNULL; } 5052 5053 if (srs->NATinfo.clientContext) 5054 { 5055 mDNS_StopNATOperation_internal(m, &srs->NATinfo); 5056 srs->NATinfo.clientContext = mDNSNULL; 5057 } 5058 5059 if (srs->state == regState_UpdatePending) 5060 { 5061 // act as if the update succeeded, since we're about to delete the name anyway 5062 AuthRecord *txt = &srs->RR_TXT; 5063 srs->state = regState_Registered; 5064 // deallocate old RData 5065 if (txt->UpdateCallback) txt->UpdateCallback(m, txt, txt->OrigRData); 5066 SetNewRData(&txt->resrec, txt->InFlightRData, txt->InFlightRDLen); 5067 txt->OrigRData = mDNSNULL; 5068 txt->InFlightRData = mDNSNULL; 5069 } 5070 5071 if (srs->state == regState_Registered || srs->state == regState_Refresh) 5072 SendServiceDeregistration(m, srs); 5073 5074 srs->state = regState_NoTarget; // when we wake, we'll re-register (and optionally nat-map) once our address record completes 5075 srs->RR_SRV.resrec.rdata->u.srv.target.c[0] = 0; 5076 srs->SRSUpdateServer = zeroAddr; // This will cause UpdateSRV to do a new StartGetZoneData 5077 srs->RR_SRV.ThisAPInterval = 5 * mDNSPlatformOneSecond; // After doubling, first retry will happen after ten seconds 5078 5079 srs = srs->uDNS_next; 5080 } 5081 } 5082 5083 mDNSexport void mDNS_AddSearchDomain(const domainname *const domain) 5084 { 5085 SearchListElem **p; 5086 5087 // Check to see if we already have this domain in our list 5088 for (p = &SearchList; *p; p = &(*p)->next) 5089 if (SameDomainName(&(*p)->domain, domain)) 5090 { 5091 // If domain is already in list, and marked for deletion, change it to "leave alone" 5092 if ((*p)->flag == -1) (*p)->flag = 0; 5093 LogInfo("mDNS_AddSearchDomain already in list %##s", domain->c); 5094 return; 5095 } 5096 5097 // if domain not in list, add to list, mark as add (1) 5098 *p = mDNSPlatformMemAllocate(sizeof(SearchListElem)); 5099 if (!*p) { LogMsg("ERROR: mDNS_AddSearchDomain - malloc"); return; } 5100 mDNSPlatformMemZero(*p, sizeof(SearchListElem)); 5101 AssignDomainName(&(*p)->domain, domain); 5102 (*p)->flag = 1; // add 5103 (*p)->next = mDNSNULL; 5104 LogInfo("mDNS_AddSearchDomain created new %##s", domain->c); 5105 } 5106 5107 mDNSlocal void FreeARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result) 5108 { 5109 (void)m; // unused 5110 if (result == mStatus_MemFree) mDNSPlatformMemFree(rr->RecordContext); 5111 } 5112 5113 mDNSlocal void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) 5114 { 5115 SearchListElem *slElem = question->QuestionContext; 5116 mStatus err; 5117 const char *name; 5118 5119 if (answer->rrtype != kDNSType_PTR) return; 5120 if (answer->RecordType == kDNSRecordTypePacketNegative) return; 5121 if (answer->InterfaceID == mDNSInterface_LocalOnly) return; 5122 5123 if (question == &slElem->BrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowse]; 5124 else if (question == &slElem->DefBrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseDefault]; 5125 else if (question == &slElem->AutomaticBrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseAutomatic]; 5126 else if (question == &slElem->RegisterQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistration]; 5127 else if (question == &slElem->DefRegisterQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistrationDefault]; 5128 else { LogMsg("FoundDomain - unknown question"); return; } 5129 5130 LogInfo("FoundDomain: %p %s %s Q %##s A %s", answer->InterfaceID, AddRecord ? "Add" : "Rmv", name, question->qname.c, RRDisplayString(m, answer)); 5131 5132 if (AddRecord) 5133 { 5134 ARListElem *arElem = mDNSPlatformMemAllocate(sizeof(ARListElem)); 5135 if (!arElem) { LogMsg("ERROR: FoundDomain out of memory"); return; } 5136 mDNS_SetupResourceRecord(&arElem->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, FreeARElemCallback, arElem); 5137 MakeDomainNameFromDNSNameString(&arElem->ar.namestorage, name); 5138 AppendDNSNameString (&arElem->ar.namestorage, "local"); 5139 AssignDomainName(&arElem->ar.resrec.rdata->u.name, &answer->rdata->u.name); 5140 LogInfo("FoundDomain: Registering %s", ARDisplayString(m, &arElem->ar)); 5141 err = mDNS_Register(m, &arElem->ar); 5142 if (err) { LogMsg("ERROR: FoundDomain - mDNS_Register returned %d", err); mDNSPlatformMemFree(arElem); return; } 5143 arElem->next = slElem->AuthRecs; 5144 slElem->AuthRecs = arElem; 5145 } 5146 else 5147 { 5148 ARListElem **ptr = &slElem->AuthRecs; 5149 while (*ptr) 5150 { 5151 if (SameDomainName(&(*ptr)->ar.resrec.rdata->u.name, &answer->rdata->u.name)) 5152 { 5153 ARListElem *dereg = *ptr; 5154 *ptr = (*ptr)->next; 5155 LogInfo("FoundDomain: Deregistering %s", ARDisplayString(m, &dereg->ar)); 5156 err = mDNS_Deregister(m, &dereg->ar); 5157 if (err) LogMsg("ERROR: FoundDomain - mDNS_Deregister returned %d", err); 5158 // Memory will be freed in the FreeARElemCallback 5159 } 5160 else 5161 ptr = &(*ptr)->next; 5162 } 5163 } 5164 } 5165 5166 #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING 5167 mDNSexport void udns_validatelists(void *const v) 5168 { 5169 mDNS *const m = v; 5170 5171 ServiceRecordSet *s; 5172 for (s = m->ServiceRegistrations; s; s=s->uDNS_next) 5173 if (s->uDNS_next == (ServiceRecordSet*)~0) 5174 LogMemCorruption("m->ServiceRegistrations: %p is garbage (%lX)", s, s->uDNS_next); 5175 5176 NATTraversalInfo *n; 5177 for (n = m->NATTraversals; n; n=n->next) 5178 if (n->next == (NATTraversalInfo *)~0 || n->clientCallback == (NATTraversalClientCallback)~0) 5179 LogMemCorruption("m->NATTraversals: %p is garbage", n); 5180 5181 DNSServer *d; 5182 for (d = m->DNSServers; d; d=d->next) 5183 if (d->next == (DNSServer *)~0 || d->teststate > DNSServer_Disabled) 5184 LogMemCorruption("m->DNSServers: %p is garbage (%d)", d, d->teststate); 5185 5186 DomainAuthInfo *info; 5187 for (info = m->AuthInfoList; info; info = info->next) 5188 if (info->next == (DomainAuthInfo *)~0 || info->AutoTunnel == (mDNSBool)~0) 5189 LogMemCorruption("m->AuthInfoList: %p is garbage (%X)", info, info->AutoTunnel); 5190 5191 HostnameInfo *hi; 5192 for (hi = m->Hostnames; hi; hi = hi->next) 5193 if (hi->next == (HostnameInfo *)~0 || hi->StatusCallback == (mDNSRecordCallback*)~0) 5194 LogMemCorruption("m->Hostnames: %p is garbage", n); 5195 5196 SearchListElem *ptr; 5197 for (ptr = SearchList; ptr; ptr = ptr->next) 5198 if (ptr->next == (SearchListElem *)~0 || ptr->AuthRecs == (void*)~0) 5199 LogMemCorruption("SearchList: %p is garbage (%X)", ptr, ptr->AuthRecs); 5200 } 5201 #endif 5202 5203 // This should probably move to the UDS daemon -- the concept of legacy clients and automatic registration / automatic browsing 5204 // is really a UDS API issue, not something intrinsic to uDNS 5205 5206 mDNSexport mStatus uDNS_RegisterSearchDomains(mDNS *const m) 5207 { 5208 SearchListElem **p = &SearchList, *ptr; 5209 mStatus err; 5210 5211 // step 1: mark each element for removal (-1) 5212 for (ptr = SearchList; ptr; ptr = ptr->next) ptr->flag = -1; 5213 5214 // Client has requested domain enumeration or automatic browse -- time to make sure we have the search domains from the platform layer 5215 mDNS_Lock(m); 5216 m->RegisterSearchDomains = mDNStrue; 5217 mDNSPlatformSetDNSConfig(m, mDNSfalse, m->RegisterSearchDomains, mDNSNULL, mDNSNULL, mDNSNULL); 5218 mDNS_Unlock(m); 5219 5220 // delete elems marked for removal, do queries for elems marked add 5221 while (*p) 5222 { 5223 ptr = *p; 5224 LogInfo("RegisterSearchDomains %d %p %##s", ptr->flag, ptr->AuthRecs, ptr->domain.c); 5225 if (ptr->flag == -1) // remove 5226 { 5227 ARListElem *arList = ptr->AuthRecs; 5228 ptr->AuthRecs = mDNSNULL; 5229 *p = ptr->next; 5230 5231 // If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries 5232 if (!SameDomainName(&ptr->domain, &localdomain)) 5233 { 5234 mDNS_StopGetDomains(m, &ptr->BrowseQ); 5235 mDNS_StopGetDomains(m, &ptr->RegisterQ); 5236 mDNS_StopGetDomains(m, &ptr->DefBrowseQ); 5237 mDNS_StopGetDomains(m, &ptr->DefRegisterQ); 5238 mDNS_StopGetDomains(m, &ptr->AutomaticBrowseQ); 5239 } 5240 mDNSPlatformMemFree(ptr); 5241 5242 // deregister records generated from answers to the query 5243 while (arList) 5244 { 5245 ARListElem *dereg = arList; 5246 arList = arList->next; 5247 debugf("Deregistering PTR %##s -> %##s", dereg->ar.resrec.name->c, dereg->ar.resrec.rdata->u.name.c); 5248 err = mDNS_Deregister(m, &dereg->ar); 5249 if (err) LogMsg("ERROR: RegisterSearchDomains mDNS_Deregister returned %d", err); 5250 // Memory will be freed in the FreeARElemCallback 5251 } 5252 continue; 5253 } 5254 5255 if (ptr->flag == 1) // add 5256 { 5257 // If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries 5258 if (!SameDomainName(&ptr->domain, &localdomain)) 5259 { 5260 mStatus err1, err2, err3, err4, err5; 5261 err1 = mDNS_GetDomains(m, &ptr->BrowseQ, mDNS_DomainTypeBrowse, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr); 5262 err2 = mDNS_GetDomains(m, &ptr->DefBrowseQ, mDNS_DomainTypeBrowseDefault, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr); 5263 err3 = mDNS_GetDomains(m, &ptr->RegisterQ, mDNS_DomainTypeRegistration, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr); 5264 err4 = mDNS_GetDomains(m, &ptr->DefRegisterQ, mDNS_DomainTypeRegistrationDefault, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr); 5265 err5 = mDNS_GetDomains(m, &ptr->AutomaticBrowseQ, mDNS_DomainTypeBrowseAutomatic, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr); 5266 if (err1 || err2 || err3 || err4 || err5) 5267 LogMsg("GetDomains for domain %##s returned error(s):\n" 5268 "%d (mDNS_DomainTypeBrowse)\n" 5269 "%d (mDNS_DomainTypeBrowseDefault)\n" 5270 "%d (mDNS_DomainTypeRegistration)\n" 5271 "%d (mDNS_DomainTypeRegistrationDefault)" 5272 "%d (mDNS_DomainTypeBrowseAutomatic)\n", 5273 ptr->domain.c, err1, err2, err3, err4, err5); 5274 } 5275 ptr->flag = 0; 5276 } 5277 5278 if (ptr->flag) { LogMsg("RegisterSearchDomains - unknown flag %d. Skipping.", ptr->flag); } 5279 5280 p = &ptr->next; 5281 } 5282 5283 return mStatus_NoError; 5284 } 5285 5286 // Construction of Default Browse domain list (i.e. when clients pass NULL) is as follows: 5287 // 1) query for b._dns-sd._udp.local on LocalOnly interface 5288 // (.local manually generated via explicit callback) 5289 // 2) for each search domain (from prefs pane), query for b._dns-sd._udp.<searchdomain>. 5290 // 3) for each result from (2), register LocalOnly PTR record b._dns-sd._udp.local. -> <result> 5291 // 4) result above should generate a callback from question in (1). result added to global list 5292 // 5) global list delivered to client via GetSearchDomainList() 5293 // 6) client calls to enumerate domains now go over LocalOnly interface 5294 // (!!!KRS may add outgoing interface in addition) 5295 5296 struct CompileTimeAssertionChecks_uDNS 5297 { 5298 // Check our structures are reasonable sizes. Including overly-large buffers, or embedding 5299 // other overly-large structures instead of having a pointer to them, can inadvertently 5300 // cause structure sizes (and therefore memory usage) to balloon unreasonably. 5301 char sizecheck_tcpInfo_t [(sizeof(tcpInfo_t) <= 9056) ? 1 : -1]; 5302 char sizecheck_SearchListElem[(sizeof(SearchListElem) <= 3920) ? 1 : -1]; 5303 }; 5304