1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 Change History (most recent first):
19 $Log: mDNSMacOSX.c,v $
20 Revision 1.687 2009/06/30 21:16:09 cheshire
21 <rdar://problem/7020041> Plugging and unplugging the power cable shouldn't cause a network change event
22 Additional fix: Only start and stop NetWake browses for active interfaces that are currently registered with mDNSCore
24 Revision 1.686 2009/06/25 23:36:56 cheshire
25 To facilitate testing, added command-line switch "-OfferSleepProxyService"
26 to re-enable the previously-supported mode of operation where we offer
27 sleep proxy service on desktop Macs that are set to never sleep.
29 Revision 1.685 2009/06/25 23:15:12 cheshire
30 Don't try to use private header file "IOPowerSourcesPrivate.h"
31 (it prevents external developers from being able to compile the code)
33 Revision 1.684 2009/06/24 22:14:22 cheshire
34 <rdar://problem/6911445> Plugging and unplugging the power cable shouldn't cause a network change event
36 Revision 1.683 2009/06/08 22:31:03 cheshire
37 Fixed typo in comment: Portability > 35 means nominal weight < 3kg
39 Revision 1.682 2009/05/19 23:30:31 cheshire
40 Suppressed some unnecessary debugging messages; added AppleTV to list of recognized hardware
42 Revision 1.681 2009/05/12 23:23:15 cheshire
43 Removed unnecessary "mDNSPlatformTCPConnect - connect failed ... Error 50 (Network is down)" debugging message
45 Revision 1.680 2009/05/05 01:32:50 jessic2
46 <rdar://problem/6830541> regservice_callback: instance->request is NULL 0 -- Clean up spurious logs resulting from fixing this bug.
48 Revision 1.679 2009/05/01 23:48:46 jessic2
49 <rdar://problem/6830541> regservice_callback: instance->request is NULL 0
51 Revision 1.678 2009/04/24 23:32:28 cheshire
52 To facilitate testing, put back code to be a sleep proxy when set to never sleep, compiled out by compile-time switch
54 Revision 1.677 2009/04/24 20:50:16 mcguire
55 <rdar://problem/6791775> 4 second delay in DNS response
57 Revision 1.676 2009/04/24 02:17:58 mcguire
58 <rdar://problem/5264124> uDNS: Not always respecting preference order of DNS servers
60 Revision 1.675 2009/04/23 18:51:28 mcguire
61 <rdar://problem/6729406> uDNS: PPP doesn't automatically reconnect on wake from sleep (no name resolver)
63 Revision 1.674 2009/04/23 00:58:01 jessic2
64 <rdar://problem/6802117> uDNS: DNS stops working after configd crashes
66 Revision 1.673 2009/04/22 01:19:57 jessic2
67 <rdar://problem/6814585> Daemon: mDNSResponder is logging garbage for error codes because it's using %ld for int 32
69 Revision 1.672 2009/04/21 16:34:47 mcguire
70 <rdar://problem/6810663> null deref in mDNSPlatformSetDNSConfig
72 Revision 1.671 2009/04/15 01:14:07 mcguire
73 <rdar://problem/6791775> 4 second delay in DNS response
75 Revision 1.670 2009/04/15 01:10:39 jessic2
76 <rdar://problem/6466541> BTMM: Add support for setting kDNSServiceErr_NoSuchRecord in DynamicStore
78 Revision 1.669 2009/04/11 02:02:34 mcguire
79 <rdar://problem/6780046> crash in doSSLHandshake
81 Revision 1.668 2009/04/11 00:20:08 jessic2
82 <rdar://problem/4426780> Daemon: Should be able to turn on LogOperation dynamically
84 Revision 1.667 2009/04/09 20:01:00 cheshire
85 <rdar://problem/6767122> IOPMCopyActivePMPreferences not available on Apple TV
86 At Rory's suggestion, removed unnecessary "Could not get Wake On LAN value" log message
88 Revision 1.666 2009/04/07 21:57:53 cheshire
89 <rdar://problem/6767122> IOPMCopyActivePMPreferences not available on Apple TV
90 Put previous code back
92 Revision 1.665 2009/04/03 21:48:44 mcguire
93 Back out checkin 1.664 (<rdar://problem/6755199> MessageTracer: prepend domain to make signature field unique)
95 Revision 1.663 2009/04/02 22:21:16 mcguire
96 <rdar://problem/6577409> Adopt IOPM APIs
98 Revision 1.662 2009/04/02 01:08:15 mcguire
99 <rdar://problem/6735635> Don't be a sleep proxy when set to sleep never
101 Revision 1.661 2009/04/01 17:50:14 mcguire
104 Revision 1.660 2009/04/01 01:13:10 mcguire
105 <rdar://problem/6744276> Sleep Proxy: Detect lid closed
107 Revision 1.659 2009/03/30 21:11:07 jessic2
108 <rdar://problem/6728725> Need to do some polish work on MessageTracer logging
110 Revision 1.658 2009/03/30 20:07:28 mcguire
111 <rdar://problem/6736133> BTMM: SSLHandshake threads are leaking Mach ports
113 Revision 1.657 2009/03/27 17:27:13 cheshire
114 <rdar://problem/6724859> Need to support querying IPv6 DNS servers
116 Revision 1.656 2009/03/26 05:02:48 mcguire
117 fix build error in dnsextd
119 Revision 1.655 2009/03/26 03:59:00 jessic2
120 Changes for <rdar://problem/6492552&6492593&6492609&6492613&6492628&6492640&6492699>
122 Revision 1.654 2009/03/20 20:53:26 cheshire
123 Added test code for testing with MacBook Air, using a USB dongle that doesn't actually support Wake-On-LAN
125 Revision 1.653 2009/03/20 20:52:22 cheshire
126 <rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
128 Revision 1.652 2009/03/19 23:44:47 mcguire
129 <rdar://problem/6699216> Properly handle EADDRINUSE
131 Revision 1.651 2009/03/17 19:15:24 mcguire
132 <rdar://problem/6655415> SSLHandshake deadlock issues
134 Revision 1.650 2009/03/17 01:24:22 cheshire
135 Updated to new Sleep Proxy metric ranges: 100000-999999; 1000000 means "do not use"
137 Revision 1.649 2009/03/15 01:30:29 mcguire
140 Revision 1.648 2009/03/15 01:16:08 mcguire
141 <rdar://problem/6655415> SSLHandshake deadlock issues
143 Revision 1.647 2009/03/14 01:42:56 mcguire
144 <rdar://problem/5457116> BTMM: Fix issues with multiple .Mac accounts on the same machine
146 Revision 1.646 2009/03/13 01:36:24 mcguire
147 <rdar://problem/6657640> Reachability fixes on DNS config change
149 Revision 1.645 2009/03/10 23:48:33 cheshire
150 <rdar://problem/6665739> Task scheduling failure when Sleep Proxy Server is active
152 Revision 1.644 2009/03/10 04:17:09 cheshire
153 Check for NULL answer in UpdateSPSStatus()
155 Revision 1.643 2009/03/10 01:15:55 cheshire
156 Sleep Proxies with invalid names (score 10000) need to be ignored
158 Revision 1.642 2009/03/08 04:46:51 mkrochma
159 Change Keychain LogMsg to LogInfo
161 Revision 1.641 2009/03/05 23:53:34 cheshire
162 Removed spurious "SnowLeopardPowerChanged: wake ERROR" syslog message
164 Revision 1.640 2009/03/05 21:57:13 cheshire
165 Don't close BPF fd until we have no more records we're proxying for on that interface
167 Revision 1.639 2009/03/04 01:45:01 cheshire
168 HW_MODEL information should be LogSPS, not LogMsg
170 Revision 1.638 2009/03/03 22:51:54 cheshire
171 <rdar://problem/6504236> Sleep Proxy: Waking on same network but different interface will cause conflicts
173 Revision 1.637 2009/02/26 22:58:47 cheshire
174 <rdar://problem/6616335> Crash in mDNSResponder at mDNSResponder • CloseBPF + 75
175 Fixed race condition between the kqueue thread and the CFRunLoop thread.
177 Revision 1.636 2009/02/21 01:38:39 cheshire
178 Added comment: mDNSCoreMachineSleep(m, false); // Will set m->SleepState = SleepState_Awake;
180 Revision 1.635 2009/02/17 23:29:03 cheshire
181 Throttle logging to a slower rate when running on SnowLeopard
183 Revision 1.634 2009/02/14 00:29:17 mcguire
186 Revision 1.633 2009/02/14 00:07:11 cheshire
187 Need to set up m->SystemWakeOnLANEnabled before calling UpdateInterfaceList(m, utc);
189 Revision 1.632 2009/02/13 19:40:07 cheshire
190 Improved alignment of LogSPS messages
192 Revision 1.631 2009/02/13 18:16:05 cheshire
193 Fixed some compile warnings
195 Revision 1.630 2009/02/13 06:32:43 cheshire
196 Converted LogOperation messages to LogInfo or LogSPS
198 Revision 1.629 2009/02/12 20:57:26 cheshire
199 Renamed 'LogAllOperation' switch to 'LogClientOperations'; added new 'LogSleepProxyActions' switch
201 Revision 1.628 2009/02/11 02:34:45 cheshire
202 m->p->SystemWakeForNetworkAccessEnabled renamed to m->SystemWakeOnLANEnabled
204 Revision 1.627 2009/02/10 00:19:17 cheshire
205 <rdar://problem/6107426> Sleep Proxy: Adopt SIOCGIFWAKEFLAGS ioctl to determine interface WOMP-ability
207 Revision 1.626 2009/02/10 00:15:38 cheshire
208 <rdar://problem/6551529> Sleep Proxy: "Unknown DNS packet type 8849" logs
210 Revision 1.625 2009/02/09 21:24:25 cheshire
211 Set correct bit in ifr.ifr_wake_flags (was coincidentally working because IF_WAKE_ON_MAGIC_PACKET happens to have the value 1)
213 Revision 1.624 2009/02/09 21:11:43 cheshire
214 Need to acknowledge kIOPMSystemPowerStateCapabilityCPU message
216 Revision 1.623 2009/02/09 06:20:42 cheshire
217 Upon receiving system power change notification, make sure our m->p->SystemWakeForNetworkAccessEnabled value
218 correctly reflects the current system setting
220 Revision 1.622 2009/02/07 02:57:32 cheshire
221 <rdar://problem/6084043> Sleep Proxy: Need to adopt IOPMConnection
223 Revision 1.621 2009/02/06 03:18:12 mcguire
224 <rdar://problem/6534643> BTMM: State not cleaned up on SIGTERM w/o reboot
226 Revision 1.620 2009/02/02 22:14:11 cheshire
227 Instead of repeatedly checking the Dynamic Store, use m->p->SystemWakeForNetworkAccessEnabled variable
229 Revision 1.619 2009/01/24 02:11:58 cheshire
230 Handle case where config->resolver[0]->nameserver[0] is NULL
232 Revision 1.618 2009/01/24 01:55:51 cheshire
233 Handle case where config->resolver[0]->domain is NULL
235 Revision 1.617 2009/01/24 01:48:42 cheshire
236 <rdar://problem/4786302> Implement logic to determine when to send dot-local lookups via Unicast
238 Revision 1.616 2009/01/24 00:28:43 cheshire
241 Revision 1.615 2009/01/22 02:14:26 cheshire
242 <rdar://problem/6515626> Sleep Proxy: Set correct target MAC address, instead of all zeroes
244 Revision 1.614 2009/01/21 03:43:57 mcguire
245 <rdar://problem/6511765> BTMM: Add support for setting kDNSServiceErr_NATPortMappingDisabled in DynamicStore
247 Revision 1.613 2009/01/20 02:38:41 mcguire
248 fix previous checkin comment
250 Revision 1.612 2009/01/20 02:35:15 mcguire
251 <rdar://problem/6508974> don't update BTMM & SleepProxyServers status at shutdown time
253 Revision 1.611 2009/01/17 04:15:40 cheshire
254 Updated "did sleep(5)" debugging message
256 Revision 1.610 2009/01/16 20:37:30 cheshire
257 Fixed incorrect value of EOPNOTSUPP
259 Revision 1.609 2009/01/16 03:08:13 cheshire
260 Use kernel event notifications to track KEV_DL_WAKEFLAGS_CHANGED
261 (indicates when SIOCGIFWAKEFLAGS changes for an interface, e.g. when AirPort
262 switches from a base-station that's WakeOnLAN-capable to one that isn't)
264 Revision 1.608 2009/01/16 01:27:03 cheshire
265 Initial work to adopt SIOCGIFWAKEFLAGS ioctl to determine whether an interface is WakeOnLAN-capable
267 Revision 1.607 2009/01/15 22:24:01 cheshire
268 Get rid of unnecessary ifa_name field in NetworkInterfaceInfoOSX (it just duplicates the content of ifinfo.ifname)
269 This also eliminates an unnecessary malloc, memory copy, and free
271 Revision 1.606 2009/01/15 00:22:49 mcguire
272 <rdar://problem/6437092> NAT-PMP: mDNSResponder needs to listen on 224.0.0.1:5350/UDP with REUSEPORT
274 Revision 1.605 2009/01/14 01:38:43 mcguire
275 <rdar://problem/6492710> Write out DynamicStore per-interface SleepProxyServer info
277 Revision 1.604 2009/01/13 05:31:34 mkrochma
278 <rdar://problem/6491367> Replace bzero, bcopy with mDNSPlatformMemZero, mDNSPlatformMemCopy, memset, memcpy
280 Revision 1.603 2009/01/12 22:26:13 mkrochma
281 Change DynamicStore location from BonjourSleepProxy/DiscoveredServers to SleepProxyServers
283 Revision 1.602 2008/12/19 20:23:34 mcguire
284 <rdar://problem/6459269> Lots of duplicate log messages about failure to bind to NAT-PMP Announcement port
286 Revision 1.601 2008/12/15 19:51:56 mcguire
287 <rdar://problem/6443067> Retry UDP socket creation only when randomizing ports
289 Revision 1.600 2008/12/12 21:30:14 cheshire
290 Additional defensive coding -- make sure InterfaceID is found in our list before using it
292 Revision 1.599 2008/12/12 04:36:26 cheshire
293 Make sure we don't overflow our BPF filter buffer
294 Only add addresses for records where the InterfaceID matches
296 Revision 1.598 2008/12/12 00:57:51 cheshire
297 Updated BPF filter generation to explicitly match addresses we're proxying for,
298 rather than just matching any unknown IP address
300 Revision 1.597 2008/12/10 20:37:05 cheshire
301 Don't mark interfaces like PPP as being WakeonLAN-capable
303 Revision 1.596 2008/12/10 19:34:30 cheshire
304 Use symbolic OS version names instead of literal integers
306 Revision 1.595 2008/12/10 02:25:31 cheshire
307 Minor fixes to use of LogClientOperations symbol
309 Revision 1.594 2008/12/10 02:11:45 cheshire
310 ARMv5 compiler doesn't like uncommented stuff after #endif
312 Revision 1.593 2008/12/09 23:08:55 mcguire
313 <rdar://problem/6430877> should use IP_BOUND_IF
316 Revision 1.592 2008/12/09 19:58:44 mcguire
317 <rdar://problem/6430877> should use IP_BOUND_IF
319 Revision 1.591 2008/12/09 15:39:05 cheshire
320 Workaround for bug on Leopard and earlier where Ethernet drivers report wrong link state immediately after wake from sleep
322 Revision 1.590 2008/12/09 05:21:54 cheshire
323 Should key sleep/wake handling off kIOMessageSystemWillPowerOn message -- the kIOMessageSystemHasPoweredOn
324 message is delayed by some seemingly-random amount in the range 0-15 seconds.
326 Revision 1.589 2008/12/05 02:35:25 mcguire
327 <rdar://problem/6107390> Write to the DynamicStore when a Sleep Proxy server is available on the network
329 Revision 1.588 2008/12/04 21:08:52 mcguire
330 <rdar://problem/6116863> mDNS: Provide mechanism to disable Multicast advertisements
332 Revision 1.587 2008/12/04 02:17:47 cheshire
333 Additional sleep/wake debugging messages
335 Revision 1.586 2008/11/26 20:34:55 cheshire
336 Changed some "LogOperation" debugging messages to "debugf"
338 Revision 1.585 2008/11/25 20:53:35 cheshire
339 Updated portability metrics; added Xserve and PowerBook to list
341 Revision 1.584 2008/11/25 05:07:16 cheshire
342 <rdar://problem/6374328> Advertise Sleep Proxy metrics in service name
344 Revision 1.583 2008/11/20 01:42:31 cheshire
345 For consistency with other parts of the code, changed code to only check
346 that the first 4 bytes of MAC address are zero, not the whole 6 bytes.
348 Revision 1.582 2008/11/14 22:59:09 cheshire
349 When on a network with more than one subnet overlayed on a single physical link, don't make local ARP
350 entries for hosts that are on our physical link but not on our logical subnet -- it confuses the kernel
352 Revision 1.581 2008/11/14 21:01:26 cheshire
353 Log a warning if we fail to get a MAC address for an interface
355 Revision 1.580 2008/11/14 02:16:15 cheshire
356 Clean up NetworkChanged handling
358 Revision 1.579 2008/11/12 23:15:37 cheshire
361 Revision 1.578 2008/11/06 23:41:57 cheshire
362 Refinement: Only need to create local ARP entry when sending ARP packet to broadcast address or to ourselves
364 Revision 1.577 2008/11/06 01:15:47 mcguire
365 Fix compile error that occurs when LogOperation is disabled
367 Revision 1.576 2008/11/05 21:55:21 cheshire
368 Fixed mistake in BPF filter generation
370 Revision 1.575 2008/11/04 23:54:09 cheshire
371 Added routine mDNSSetARP(), used to replace an SPS client's entry in our ARP cache with
372 a dummy one, so that IP traffic to the SPS client initiated by the SPS machine can be
373 captured by our BPF filters, and used as a trigger to wake the sleeping machine.
375 Revision 1.574 2008/11/04 00:27:58 cheshire
376 Corrected some timing anomalies in sleep/wake causing spurious name self-conflicts
378 Revision 1.573 2008/11/03 01:12:42 mkrochma
379 Fix compile error that occurs when LogOperation is disabled
381 Revision 1.572 2008/10/31 23:36:13 cheshire
382 One wakeup clear any previous power requests
384 Revision 1.571 2008/10/31 23:05:30 cheshire
385 Move logic to decide when to at as Sleep Proxy Server from daemon.c to mDNSMacOSX.c
387 Revision 1.570 2008/10/30 01:08:19 cheshire
388 After waking for network maintenance operations go back to sleep again
390 Revision 1.569 2008/10/29 21:39:43 cheshire
391 Updated syslog messages; close BPF socket on read error
393 Revision 1.568 2008/10/28 20:37:28 cheshire
394 Changed code to create its own CFSocketCreateWithNative directly, instead of
395 relying on udsSupportAddFDToEventLoop/udsSupportRemoveFDFromEventLoop
397 Revision 1.567 2008/10/27 22:31:37 cheshire
398 Can't just close BPF_fd using "close(i->BPF_fd);" -- need to call
399 "udsSupportRemoveFDFromEventLoop(i->BPF_fd);" to remove it from our event source list
401 Revision 1.566 2008/10/23 22:33:23 cheshire
402 Changed "NOTE:" to "Note:" so that BBEdit 9 stops putting those comment lines into the funtion popup menu
404 Revision 1.565 2008/10/22 23:23:55 cheshire
405 Moved definition of OSXVers from daemon.c into mDNSMacOSX.c
407 Revision 1.564 2008/10/22 22:08:46 cheshire
408 Take IP header length into account when determining how many bytes to return from BPF filter
410 Revision 1.563 2008/10/22 20:59:28 cheshire
411 BPF filter needs to capture a few more bytes so that we can examine TCP header fields
413 Revision 1.562 2008/10/22 19:48:29 cheshire
414 Improved syslog messages
416 Revision 1.561 2008/10/22 17:18:57 cheshire
417 Need to open and close BPF fds when turning Sleep Proxy Server on and off
419 Revision 1.560 2008/10/22 01:09:36 cheshire
420 Fixed build warning when not using LogClientOperations
422 Revision 1.559 2008/10/21 01:05:30 cheshire
423 Added code to receive raw packets using Berkeley Packet Filter (BPF)
425 Revision 1.558 2008/10/16 22:42:06 cheshire
426 Removed debugging messages
428 Revision 1.557 2008/10/09 22:33:14 cheshire
429 Fill in ifinfo.MAC field when fetching interface list
431 Revision 1.556 2008/10/09 21:15:23 cheshire
432 In mDNSPlatformUDPSocket(), need to create an IPv6 socket as well as IPv4
434 Revision 1.555 2008/10/09 19:05:57 cheshire
435 No longer want to inhibit all networking when going to sleep
437 Revision 1.554 2008/10/08 18:36:51 mkrochma
438 <rdar://problem/4371323> Supress Couldn't read user-specified Computer Name logs
440 Revision 1.553 2008/10/04 00:47:12 cheshire
441 If NetWake setting changes for an interface, treat it as a whole new interface (like BSSID changing)
443 Revision 1.552 2008/10/03 23:32:15 cheshire
444 Added definition of mDNSPlatformSendRawPacket
446 Revision 1.551 2008/10/03 18:25:16 cheshire
447 Instead of calling "m->MainCallback" function pointer directly, call mDNSCore routine "mDNS_ConfigChanged(m);"
449 Revision 1.550 2008/10/03 00:51:58 cheshire
450 Removed spurious "else" case that got left in by mistake
452 Revision 1.549 2008/10/03 00:50:13 cheshire
453 Minor code rearrangement; don't set up interface list until *after* we've started watching for network changes
455 Revision 1.548 2008/10/03 00:26:25 cheshire
456 Export DictionaryIsEnabled() so it's callable from other files
458 Revision 1.547 2008/10/02 23:50:07 mcguire
459 <rdar://problem/6136442> shutdown time issues
460 improve log messages when SCDynamicStoreCreate() fails
462 Revision 1.546 2008/10/02 22:26:21 cheshire
463 Moved declaration of BPF_fd from uds_daemon.c to mDNSMacOSX.c, where it really belongs
465 Revision 1.545 2008/10/01 22:01:40 cheshire
466 On Allan Nathanson's advice, add "State:/IOKit/PowerManagement/CurrentSettings"
467 to keys array instead of patterns array, for efficiency
469 Revision 1.544 2008/10/01 21:35:35 cheshire
470 Monitor "State:/IOKit/PowerManagement/CurrentSettings" to track state of "Wake for network access" setting
472 Revision 1.543 2008/09/26 23:05:56 mkrochma
473 Improve log messages by using good old UTF-8
475 Revision 1.542 2008/09/26 19:49:51 cheshire
476 Improved "failed to send packet" debugging message
478 Revision 1.541 2008/09/25 21:02:05 cheshire
479 <rdar://problem/6245044> Stop using separate m->ServiceRegistrations list
480 In TunnelServers(), need to check main m->ResourceRecords list to see
481 if we have a non-zero number of advertised AutoTunnel services
483 Revision 1.540 2008/07/30 00:55:56 mcguire
484 <rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
485 Additional fixes so that we know when a socket has been closed while in a loop reading from it
487 Revision 1.539 2008/07/24 20:23:04 cheshire
488 <rdar://problem/3988320> Should use randomized source ports and transaction IDs to avoid DNS cache poisoning
490 Revision 1.538 2008/06/02 05:39:39 mkrochma
491 <rdar://problem/5932760> Don't set TOS bits anymore
493 Revision 1.537 2008/05/01 18:30:54 mkrochma
494 <rdar://problem/5895642> Make mDNSResponder and mDNSResponderHelper shutdown at regular time
496 Revision 1.536 2008/03/25 01:27:30 mcguire
497 <rdar://problem/5810718> Status sometimes wrong when link goes down
499 Revision 1.535 2008/03/14 22:52:51 mcguire
500 <rdar://problem/5321824> write status to the DS
501 Ignore duplicate queries, which don't get established (since they're duplicates)
503 Revision 1.534 2008/03/12 22:58:15 mcguire
504 <rdar://problem/5321824> write status to the DS
505 Fixes for NO_SECURITYFRAMEWORK
507 Revision 1.533 2008/03/07 00:48:54 mcguire
508 <rdar://problem/5321824> write status to the DS
511 Revision 1.532 2008/03/06 23:44:39 mcguire
512 <rdar://problem/5321824> write status to the DS
513 cleanup function names & log messages
514 add external port numbers to dictionary
515 add defensive code in case CF*Create fails
516 don't output NAT statuses if zero
518 Revision 1.531 2008/03/06 21:27:47 cheshire
519 <rdar://problem/5500969> BTMM: Need ability to identify version of mDNSResponder client
520 To save network bandwidth, removed unnecessary redundant information from HINFO record
522 Revision 1.530 2008/03/06 03:15:48 mcguire
523 <rdar://problem/5321824> write status to the DS
524 use mStatus_* instead of kDNSServiceErr_*
526 Revision 1.529 2008/03/06 02:48:35 mcguire
527 <rdar://problem/5321824> write status to the DS
529 Revision 1.528 2008/02/29 01:33:57 mcguire
530 <rdar://problem/5611801> BTMM: Services stay registered after previously successful NAT Port mapping fails
532 Revision 1.527 2008/02/28 03:25:26 mcguire
533 <rdar://problem/5535772> config cleanup on shutdown/reboot
535 Revision 1.526 2008/02/26 21:43:54 cheshire
536 Renamed 'clockdivisor' to 'mDNSPlatformClockDivisor' (LogTimeStamps code needs to be able to access it)
538 Revision 1.525 2008/02/20 00:53:20 cheshire
539 <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
540 Removed overly alarming syslog message
542 Revision 1.524 2008/01/31 22:25:10 jgraessley
543 <rdar://problem/5715434> using default Macintosh-0016CBF62EFD.local
544 Use sysctlbyname to get hardware type for the default name.
546 Revision 1.523 2008/01/15 01:32:56 jgraessley
548 Reviewed by: Stuart Cheshire
549 Additional change to print warning message up to 1000 times to make it more visible
551 Revision 1.522 2008/01/15 01:14:02 mcguire
552 <rdar://problem/5674390> mDNSPlatformSendUDP should allow unicast queries on specific interfaces
553 removed check and log message, as they are no longer relevant
555 Revision 1.521 2007/12/14 00:58:28 cheshire
556 <rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
557 Additional fixes: When going to sleep, mDNSResponder needs to postpone sleep
558 until TLS/TCP deregistrations have completed (up to five seconds maximum)
560 Revision 1.520 2007/12/10 23:01:01 cheshire
561 Remove some unnecessary log messages
563 Revision 1.519 2007/12/06 00:22:27 mcguire
564 <rdar://problem/5604567> BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp)
566 Revision 1.518 2007/12/05 01:52:30 cheshire
567 <rdar://problem/5624763> BTMM: getaddrinfo_async_start returns EAI_NONAME when resolving BTMM hostname
568 Delay returning IPv4 address ("A") results for autotunnel names until after we've set up the tunnel (or tried to)
570 Revision 1.517 2007/12/03 18:37:26 cheshire
571 Moved mDNSPlatformWriteLogMsg & mDNSPlatformWriteDebugMsg
572 from mDNSMacOSX.c to PlatformCommon.c, so that Posix build can use them
574 Revision 1.516 2007/12/01 01:21:27 jgraessley
575 <rdar://problem/5623140> mDNSResponder unicast DNS improvements
577 Revision 1.515 2007/12/01 00:40:00 cheshire
578 Add mDNSPlatformWriteLogMsg & mDNSPlatformWriteDebugMsg abstractions, to facilitate EFI conversion
580 Revision 1.514 2007/12/01 00:38:32 cheshire
581 Fixed compile warning: declaration of 'index' shadows a global declaration
583 Revision 1.513 2007/11/27 00:08:49 jgraessley
584 <rdar://problem/5613538> Interface-specific resolvers not setup correctly
586 Revision 1.512 2007/11/16 22:09:26 cheshire
587 Added missing type information in mDNSPlatformTCPCloseConnection debugging log message
589 Revision 1.511 2007/11/14 23:06:13 cheshire
590 <rdar://problem/5585972> IP_ADD_MEMBERSHIP fails for previously-connected removable interfaces
592 Revision 1.510 2007/11/14 22:29:19 cheshire
593 Updated comments and debugging log messages
595 Revision 1.509 2007/11/14 01:07:53 cheshire
598 Revision 1.508 2007/11/02 21:59:37 cheshire
599 Added comment about locking
601 Revision 1.507 2007/11/02 20:18:13 cheshire
602 <rdar://problem/5575583> BTMM: Work around keychain notification bug <rdar://problem/5124399>
604 Revision 1.506 2007/10/30 20:46:45 cheshire
605 <rdar://problem/5496734> BTMM: Need to retry registrations after failures
607 Revision 1.505 2007/10/29 23:55:10 cheshire
608 <rdar://problem/5526791> BTMM: Changing Local Hostname doesn't update Back to My Mac registered records
609 Don't need to manually fake another AutoTunnelNATCallback if it has not yet received its first callback
610 (and indeed should not, since the result fields will not yet be set up correctly in this case)
612 Revision 1.504 2007/10/26 00:50:37 cheshire
613 <rdar://problem/5526791> BTMM: Changing Local Hostname doesn't update Back to My Mac registered records
615 Revision 1.503 2007/10/25 23:11:42 cheshire
616 Ignore IPv6 ULA addresses configured on lo0 loopback interface
618 Revision 1.502 2007/10/22 20:07:07 cheshire
619 Moved mDNSPlatformSourceAddrForDest from mDNSMacOSX.c to PlatformCommon.c so
620 Posix build can share the code (better than just pasting it into mDNSPosix.c)
622 Revision 1.501 2007/10/22 19:40:30 cheshire
623 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
624 Made subroutine mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst)
626 Revision 1.500 2007/10/17 22:49:55 cheshire
627 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
629 Revision 1.499 2007/10/17 19:47:54 cheshire
630 Improved debugging messages
632 Revision 1.498 2007/10/17 18:42:06 cheshire
633 Export SetDomainSecrets so its callable from other files
635 Revision 1.497 2007/10/16 17:03:07 cheshire
636 <rdar://problem/3557903> Performance: Core code will not work on platforms with small stacks
637 Cut SetDomainSecrets stack from 3792 to 1760 bytes
639 Revision 1.496 2007/10/04 20:33:05 mcguire
640 <rdar://problem/5518845> BTMM: Racoon configuration removed when network changes
642 Revision 1.495 2007/10/02 05:03:38 cheshire
643 Fix bogus indentation in mDNSPlatformDynDNSHostNameStatusChanged
645 Revision 1.494 2007/09/29 20:40:19 cheshire
646 <rdar://problem/5513378> Crash in ReissueBlockedQuestions
648 Revision 1.493 2007/09/29 03:16:45 cheshire
649 <rdar://problem/5513168> BTMM: mDNSResponder memory corruption in GetAuthInfoForName_internal
650 When AutoTunnel information changes, wait for record deregistrations to complete before registering new data
652 Revision 1.492 2007/09/28 23:58:35 mcguire
653 <rdar://problem/5505280> BTMM: v6 address and security policies being setup too soon
656 Revision 1.491 2007/09/27 23:28:53 mcguire
657 <rdar://problem/5508042> BTMM: Anonymous racoon configuration not always cleaned up correctly
659 Revision 1.490 2007/09/26 23:01:21 mcguire
660 <rdar://problem/5505280> BTMM: v6 address and security policies being setup too soon
662 Revision 1.489 2007/09/26 22:58:16 mcguire
663 <rdar://problem/5505092> BTMM: Client tunnels being created to ::0 via 0.0.0.0
665 Revision 1.488 2007/09/26 00:32:45 cheshire
666 Rearrange struct TCPSocket_struct so "TCPSocketFlags flags" comes first (needed for debug logging)
668 Revision 1.487 2007/09/21 17:07:41 mcguire
669 <rdar://problem/5487354> BTMM: Need to modify IPSec tunnel setup files when shared secret changes (server-role)
671 Revision 1.486 2007/09/19 23:17:38 cheshire
672 <rdar://problem/5482131> BTMM: Crash when switching .Mac accounts
674 Revision 1.485 2007/09/19 21:44:29 cheshire
675 Improved "mDNSKeychainGetSecrets failed" error message
677 Revision 1.484 2007/09/18 21:44:55 cheshire
678 <rdar://problem/5469006> Crash in GetAuthInfoForName_internal
679 Code was using n->ExtPort (now n->RequestedPort) when it should have been using n->ExternalPort
681 Revision 1.483 2007/09/17 22:19:39 mcguire
682 <rdar://problem/5482519> BTMM: Tunnel is getting configured too much which causes long delays
683 No need to configure a tunnel again if all the parameters are the same -- just remove the older duplicate tunnel from the list.
685 Revision 1.482 2007/09/14 21:16:03 cheshire
686 <rdar://problem/5413170> mDNSResponder using 100% CPU spinning in tlsReadSock
688 Revision 1.481 2007/09/14 21:14:56 mcguire
689 <rdar://problem/5481318> BTMM: Need to modify IPSec tunnel setup files when shared secret changes
691 Revision 1.480 2007/09/13 00:16:42 cheshire
692 <rdar://problem/5468706> Miscellaneous NAT Traversal improvements
694 Revision 1.479 2007/09/12 19:22:20 cheshire
695 Variable renaming in preparation for upcoming fixes e.g. priv/pub renamed to intport/extport
696 Made NAT Traversal packet handlers take typed data instead of anonymous "mDNSu8 *" byte pointers
698 Revision 1.478 2007/09/07 22:21:45 vazquez
699 <rdar://problem/5460830> BTMM: Connection stops working after connecting VPN
701 Revision 1.477 2007/09/07 21:22:30 cheshire
702 <rdar://problem/5460210> BTMM: SetupSocket 5351 failed; Can't allocate UDP multicast socket spew on wake from sleep with internet sharing on
703 Don't log failures binding to port 5351
705 Revision 1.476 2007/09/06 20:38:08 cheshire
706 <rdar://problem/5439021> Only call SetDomainSecrets() for Keychain changes that are relevant to mDNSResponder
708 Revision 1.475 2007/09/05 02:24:28 cheshire
709 <rdar://problem/5457287> mDNSResponder taking up 100% CPU in ReissueBlockedQuestions
710 In ReissueBlockedQuestions, only restart questions marked NoAnswer_Suspended, not those marked NoAnswer_Fail
712 Revision 1.474 2007/09/04 22:32:58 mcguire
713 <rdar://problem/5453633> BTMM: BTMM overwrites /etc/racoon/remote/anonymous.conf
715 Revision 1.473 2007/08/31 19:53:15 cheshire
716 <rdar://problem/5431151> BTMM: IPv6 address lookup should not succeed if autotunnel cannot be setup
717 If AutoTunnel setup fails, the code now generates a fake NXDomain error saying that the requested AAAA record does not exist
719 Revision 1.472 2007/08/31 18:49:49 vazquez
720 <rdar://problem/5393719> BTMM: Need to properly deregister when stopping BTMM
722 Revision 1.471 2007/08/31 02:05:46 cheshire
723 Need to hold mDNS_Lock when calling mDNS_AddDynDNSHostName
725 Revision 1.470 2007/08/30 22:50:04 mcguire
726 <rdar://problem/5430628> BTMM: Tunneled services are registered when autotunnel can't be setup
728 Revision 1.469 2007/08/30 19:40:51 cheshire
729 Added syslog messages to report various initialization failures
731 Revision 1.468 2007/08/30 00:12:20 cheshire
732 Check error codes and log failures during AutoTunnel setup
734 Revision 1.467 2007/08/28 00:33:04 jgraessley
735 <rdar://problem/5423932> Selective compilation options
737 Revision 1.466 2007/08/24 23:25:55 cheshire
738 Debugging messages to help track down duplicate items being read from system keychain
740 Revision 1.465 2007/08/24 00:39:12 cheshire
741 Added comment explaining why we set info->AutoTunnelService.resrec.RecordType to kDNSRecordTypeUnregistered
743 Revision 1.464 2007/08/24 00:15:21 cheshire
744 Renamed GetAuthInfoForName() to GetAuthInfoForName_internal() to make it clear that it may only be called with the lock held
746 Revision 1.463 2007/08/23 21:02:35 cheshire
747 SecKeychainSetPreferenceDomain() call should be in platform-support layer, not daemon.c
749 Revision 1.462 2007/08/18 01:02:03 mcguire
750 <rdar://problem/5415593> No Bonjour services are getting registered at boot
752 Revision 1.461 2007/08/10 22:25:57 mkrochma
753 <rdar://problem/5396302> mDNSResponder continually complains about slow UDP packet reception -- about 400 msecs
755 Revision 1.460 2007/08/08 22:34:59 mcguire
756 <rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
758 Revision 1.459 2007/08/08 21:07:48 vazquez
759 <rdar://problem/5244687> BTMM: Need to advertise model information via wide-area bonjour
761 Revision 1.458 2007/08/03 02:18:41 mcguire
762 <rdar://problem/5381687> BTMM: Use port numbers in IPsec policies & configuration files
764 Revision 1.457 2007/08/02 16:48:45 mcguire
765 <rdar://problem/5329526> BTMM: Don't try to create tunnel back to same machine
767 Revision 1.456 2007/08/02 03:28:30 vazquez
768 Make ExternalAddress and err unused to fix build warnings
770 Revision 1.455 2007/08/01 03:09:22 cheshire
771 <rdar://problem/5344587> BTMM: Create NAT port mapping for autotunnel port
773 Revision 1.454 2007/07/31 23:08:34 mcguire
774 <rdar://problem/5329542> BTMM: Make AutoTunnel mode work with multihoming
776 Revision 1.453 2007/07/31 19:13:58 mkrochma
777 No longer need to include "btmm" in hostname to avoid name conflicts
779 Revision 1.452 2007/07/27 19:30:41 cheshire
780 Changed mDNSQuestionCallback parameter from mDNSBool to QC_result,
781 to properly reflect tri-state nature of the possible responses
783 Revision 1.451 2007/07/25 22:25:45 cheshire
784 <rdar://problem/5360853> BTMM: Code not cleaning up old racoon files
786 Revision 1.450 2007/07/25 21:19:10 cheshire
787 <rdar://problem/5359507> Fails to build with NO_SECURITYFRAMEWORK: 'IsTunnelModeDomain' defined but not used
789 Revision 1.449 2007/07/25 01:36:09 mcguire
790 <rdar://problem/5345290> BTMM: Replace popen() `setkey` calls to setup/teardown ipsec policies
792 Revision 1.448 2007/07/24 21:30:09 cheshire
793 Added "AutoTunnel server listening for connections..." diagnostic message
795 Revision 1.447 2007/07/24 20:24:18 cheshire
796 Only remove AutoTunnel address if we have created it.
797 Otherwise, we get "errno 49 (Can't assign requested address)" errors on exit.
799 Revision 1.446 2007/07/24 03:00:09 cheshire
800 SetDomainSecrets() should call SetupLocalAutoTunnelInterface_internal(), not SetupLocalAutoTunnelInterface()
802 Revision 1.445 2007/07/23 20:26:26 cheshire
803 <rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
804 Move code that reads "Setup:/Network/BackToMyMac" preferences outside the check
805 for existence of "Setup:/Network/DynamicDNS" settings
807 Revision 1.444 2007/07/21 00:54:49 cheshire
808 <rdar://problem/5344576> Delay IPv6 address callback until AutoTunnel route and policy is configured
810 Revision 1.443 2007/07/20 23:23:11 cheshire
811 Rename out-of-date name "atq" (was AutoTunnelQuery) to simpler "tun"
813 Revision 1.442 2007/07/20 20:23:24 cheshire
814 <rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
815 Fixed errors reading the Setup:/Network/BackToMyMac preferences
817 Revision 1.441 2007/07/20 16:46:45 mcguire
818 <rdar://problem/5345233> BTMM: Replace system() `route` calls to setup/teardown routes
820 Revision 1.440 2007/07/20 16:22:07 mcguire
821 <rdar://problem/5344584> BTMM: Replace system() `ifconfig` calls to setup/teardown IPv6 address
823 Revision 1.439 2007/07/20 01:14:56 cheshire
824 <rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
825 Cleaned up log messages
827 Revision 1.438 2007/07/20 00:54:21 cheshire
828 <rdar://problem/4641118> Need separate SCPreferences for per-user .Mac settings
830 Revision 1.437 2007/07/19 22:01:27 cheshire
831 Added "#pragma mark" sections headings to divide code into related function groups
833 Revision 1.436 2007/07/18 03:25:25 cheshire
834 <rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
835 Bring up server-side tunnel on demand, when necessary
837 Revision 1.435 2007/07/18 01:05:08 cheshire
838 <rdar://problem/5303834> Automatically configure IPSec policy when resolving services
839 Add list of client tunnels so we can automatically reconfigure when local address changes
841 Revision 1.434 2007/07/16 20:16:00 vazquez
842 <rdar://problem/3867231> LegacyNATTraversal: Need complete rewrite
843 Remove unnecessary LNT init code
845 Revision 1.433 2007/07/14 00:36:07 cheshire
846 Remove temporary IPv4LL tunneling mode now that IPv6-over-IPv4 is working
848 Revision 1.432 2007/07/12 23:55:11 cheshire
849 <rdar://problem/5303834> Automatically configure IPSec policy when resolving services
850 Don't need two separate DNSQuestion structures when looking up tunnel endpoint
852 Revision 1.431 2007/07/12 23:34:48 cheshire
853 Removed 'LogOperation' message to reduce verbosity in syslog
855 Revision 1.430 2007/07/12 22:16:46 cheshire
856 Improved "could not convert shared secret from base64" log message so it doesn't reveal key data in syslog
858 Revision 1.429 2007/07/12 02:51:28 cheshire
859 <rdar://problem/5303834> Automatically configure IPSec policy when resolving services
861 Revision 1.428 2007/07/11 23:17:31 cheshire
862 <rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
863 Improve log message to indicate if we're starting or restarting racoon
865 Revision 1.427 2007/07/11 22:50:30 cheshire
866 <rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
867 Write /etc/racoon/remote/anonymous.conf configuration file and start up /usr/sbin/racoon
869 Revision 1.426 2007/07/11 20:40:49 cheshire
870 <rdar://problem/5304766> Register IPSec tunnel with IPv4-only hostname and create NAT port mappings
871 In mDNSPlatformGetPrimaryInterface(), prefer routable IPv4 address to IPv4LL
873 Revision 1.425 2007/07/11 19:24:19 cheshire
874 <rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for services
875 Configure internal AutoTunnel address
876 (For temporary testing we're faking up an IPv4LL address instead of IPv6 ULA, and we're
877 assigning it with "system(commandstring);" which probably isn't the most efficient way to do it)
879 Revision 1.424 2007/07/11 19:00:27 cheshire
880 Only need to set up m->AutoTunnelHostAddr first time through UpdateInterfaceList()
882 Revision 1.423 2007/07/11 03:00:59 cheshire
883 <rdar://problem/5303807> Register IPv6-only hostname and don't create port mappings for AutoTunnel services
884 Add AutoTunnel parameter to mDNS_SetSecretForDomain; Generate IPv6 ULA address for tunnel endpoint
886 Revision 1.422 2007/07/10 01:21:20 cheshire
887 Added (commented out) line for displaying key data for debugging
889 Revision 1.421 2007/06/25 20:58:11 cheshire
890 <rdar://problem/5234463> Write the Multicast DNS domains to the DynamicStore
891 Additional refinement: Add mDNS domain list new new DynamicStore entity "State:/Network/MulticastDNS"
893 Revision 1.420 2007/06/22 21:52:14 cheshire
894 <rdar://problem/5234463> Write the Multicast DNS domains to the DynamicStore
896 Revision 1.419 2007/06/22 21:32:00 cheshire
897 <rdar://problem/5239020> Use SecKeychainCopyDefault instead of SecKeychainOpen
899 Revision 1.418 2007/06/21 16:37:43 jgraessley
901 Reviewed by: Stuart Cheshire
902 Additional changes to get this compiling on the embedded platform.
904 Revision 1.417 2007/06/20 01:44:00 cheshire
905 More information in "Network Configuration Change" message
907 Revision 1.416 2007/06/20 01:10:12 cheshire
908 <rdar://problem/5280520> Sync iPhone changes into main mDNSResponder code
910 Revision 1.415 2007/06/15 19:23:38 cheshire
911 <rdar://problem/5254053> mDNSResponder renames my host without asking
912 Improve log messages, to distinguish user-initiated renames from automatic (name conflict) renames
914 Revision 1.414 2007/05/17 22:00:59 cheshire
915 <rdar://problem/5210966> Lower network change delay from two seconds to one second
917 Revision 1.413 2007/05/16 16:43:27 cheshire
918 Only log "bind" failures for our shared mDNS port and for binding to zero
919 -- other attempts to bind to a particular port may legitimately fail
921 Revision 1.412 2007/05/15 21:49:21 cheshire
922 Get rid of "#pragma unused"
924 Revision 1.411 2007/05/14 23:54:55 cheshire
925 Instead of sprintf, use safer length-limited mDNS_snprintf
927 Revision 1.410 2007/05/12 01:05:00 cheshire
928 Updated debugging messages
930 Revision 1.409 2007/05/10 22:39:48 cheshire
931 <rdar://problem/4118503> Share single socket instead of creating separate socket for each active interface
932 Only define CountMaskBits for builds with debugging messages
934 Revision 1.408 2007/05/10 22:19:00 cheshire
935 <rdar://problem/4118503> Share single socket instead of creating separate socket for each active interface
936 Don't deliver multicast packets for which we can't find an associated InterfaceID
938 Revision 1.407 2007/05/10 21:40:28 cheshire
939 Don't log unnecessary "Address already in use" errors when joining multicast groups
941 Revision 1.406 2007/05/08 00:56:17 cheshire
942 <rdar://problem/4118503> Share single socket instead of creating separate socket for each active interface
944 Revision 1.405 2007/05/04 20:21:39 cheshire
945 Improve "connect failed" error message
947 Revision 1.404 2007/05/02 19:41:53 cheshire
948 No need to alarm people with "Connection reset by peer" syslog message
950 Revision 1.403 2007/04/28 01:31:59 cheshire
951 Improve debugging support for catching memory corruption problems
953 Revision 1.402 2007/04/26 22:54:57 cheshire
954 Debugging messages to help track down <rdar://problem/5164206> mDNSResponder takes 50%+ CPU
956 Revision 1.401 2007/04/26 00:35:16 cheshire
957 <rdar://problem/5140339> uDNS: Domain discovery not working over VPN
958 Fixes to make sure results update correctly when connectivity changes (e.g. a DNS server
959 inside the firewall may give answers where a public one gives none, and vice versa.)
961 Revision 1.400 2007/04/24 21:50:27 cheshire
962 Debugging: Show list of changedKeys in NetworkChanged callback
964 Revision 1.399 2007/04/23 22:28:47 cheshire
965 Allan Nathanson informs us we should only be looking at the search list for resolver[0], not all of them
967 Revision 1.398 2007/04/23 04:57:00 cheshire
968 Log messages for debugging <rdar://problem/4570952> IPv6 multicast not working properly
970 Revision 1.397 2007/04/22 06:02:03 cheshire
971 <rdar://problem/4615977> Query should immediately return failure when no server
973 Revision 1.396 2007/04/21 21:47:47 cheshire
974 <rdar://problem/4376383> Daemon: Add watchdog timer
976 Revision 1.395 2007/04/18 20:58:34 cheshire
977 <rdar://problem/5140339> Domain discovery not working over VPN
978 Needed different code to handle the case where there's only a single search domain
980 Revision 1.394 2007/04/17 23:05:50 cheshire
981 <rdar://problem/3957358> Shouldn't send domain queries when we have 169.254 or loopback address
983 Revision 1.393 2007/04/17 19:21:29 cheshire
984 <rdar://problem/5140339> Domain discovery not working over VPN
986 Revision 1.392 2007/04/17 17:15:09 cheshire
987 Change NO_CFUSERNOTIFICATION code so it still logs to syslog
989 Revision 1.391 2007/04/07 01:01:48 cheshire
990 <rdar://problem/5095167> mDNSResponder periodically blocks in SSLRead
992 Revision 1.390 2007/04/06 18:45:02 cheshire
993 Fix SetupActiveInterfaces() -- accidentally changed SetupSocket parameter
995 Revision 1.389 2007/04/05 21:39:49 cheshire
996 Debugging messages to help diagnose <rdar://problem/5095167> mDNSResponder periodically blocks in SSLRead
998 Revision 1.388 2007/04/05 21:09:52 cheshire
999 Condense sprawling code
1001 Revision 1.387 2007/04/05 20:40:37 cheshire
1002 Remove unused mDNSPlatformTCPGetFlags()
1004 Revision 1.386 2007/04/05 19:50:56 cheshire
1005 Fixed memory leak: GetCertChain() was not releasing cert returned by SecIdentityCopyCertificate()
1007 Revision 1.385 2007/04/03 19:39:19 cheshire
1008 Fixed intel byte order bug in mDNSPlatformSetDNSServers()
1010 Revision 1.384 2007/03/31 01:10:53 cheshire
1013 Revision 1.383 2007/03/31 00:13:48 cheshire
1016 Revision 1.382 2007/03/28 21:01:29 cheshire
1017 <rdar://problem/4743285> Remove inappropriate use of IsPrivateV4Addr()
1019 Revision 1.381 2007/03/28 15:56:37 cheshire
1020 <rdar://problem/5085774> Add listing of NAT port mapping and GetAddrInfo requests in SIGINFO output
1022 Revision 1.380 2007/03/26 22:54:46 cheshire
1025 Revision 1.379 2007/03/22 18:31:48 cheshire
1026 Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
1028 Revision 1.378 2007/03/22 00:49:20 cheshire
1029 <rdar://problem/4848295> Advertise model information via Bonjour
1031 Revision 1.377 2007/03/21 00:30:05 cheshire
1032 <rdar://problem/4789455> Multiple errors in DNameList-related code
1034 Revision 1.376 2007/03/20 17:07:15 cheshire
1035 Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket"
1037 Revision 1.375 2007/03/20 00:50:57 cheshire
1038 <rdar://problem/4530644> Remove logic to disable IPv6 discovery on interfaces which have a routable IPv4 address
1040 Revision 1.374 2007/03/06 23:29:50 cheshire
1041 <rdar://problem/4331696> Need to call IONotificationPortDestroy on shutdown
1043 Revision 1.373 2007/02/28 01:51:20 cheshire
1044 Added comment about reverse-order IP address
1046 Revision 1.372 2007/02/28 01:06:48 cheshire
1047 Use %#a format code instead of %d.%d.%d.%d
1049 Revision 1.371 2007/02/08 21:12:28 cheshire
1050 <rdar://problem/4386497> Stop reading /etc/mDNSResponder.conf on every sleep/wake
1052 Revision 1.370 2007/01/16 22:59:58 cheshire
1053 Error code ioErr is from wrong conceptual namespace; use errSSLClosedAbort instead
1055 Revision 1.369 2007/01/10 02:09:32 cheshire
1056 Better LogOperation record of keys read from System Keychain
1058 Revision 1.368 2007/01/10 01:25:31 cheshire
1059 Use symbol kDNSServiceCompPrivateDNS instead of fixed string "State:/Network/PrivateDNS"
1061 Revision 1.367 2007/01/10 01:22:01 cheshire
1062 Make sure c1, c2, c3 are initialized
1064 Revision 1.366 2007/01/09 22:37:20 cheshire
1065 Provide ten-second grace period for deleted keys, to give mDNSResponder
1066 time to delete host name before it gives up access to the required key.
1068 Revision 1.365 2007/01/09 21:09:20 cheshire
1069 Need locking in KeychainChanged()
1071 Revision 1.364 2007/01/09 20:17:04 cheshire
1072 mDNSPlatformGetDNSConfig() needs to initialize fields even when no "Setup:/Network/DynamicDNS" entity exists
1074 Revision 1.363 2007/01/09 02:41:18 cheshire
1075 uDNS_SetupDNSConfig() shouldn't be called from mDNSMacOSX.c (platform support layer);
1076 moved it to mDNS_Init() in mDNS.c (core code)
1078 Revision 1.362 2007/01/08 23:54:01 cheshire
1079 Made mDNSPlatformGetDNSConfig() more selective -- only reads prefs for non-null parameters
1081 Revision 1.361 2007/01/05 08:30:48 cheshire
1082 Trim excessive "$Log" checkin history from before 2006
1083 (checkin history still available via "cvs log ..." of course)
1085 Revision 1.360 2007/01/04 00:12:24 cheshire
1086 <rdar://problem/4742742> Read *all* DNS keys from keychain,
1087 not just key for the system-wide default registration domain
1089 Revision 1.359 2006/12/22 21:14:37 cheshire
1090 Added comment explaining why we allow both "ddns" and "sndd" as valid item types
1091 The Keychain APIs on Intel appear to store the four-character item type backwards (at least some of the time)
1093 Revision 1.358 2006/12/22 20:59:50 cheshire
1094 <rdar://problem/4742742> Read *all* DNS keys from keychain,
1095 not just key for the system-wide default registration domain
1097 Revision 1.357 2006/12/21 00:09:45 cheshire
1098 Use mDNSPlatformMemZero instead of bzero
1100 Revision 1.356 2006/12/20 23:15:53 mkrochma
1101 Fix the private domain list code so that it actually works
1103 Revision 1.355 2006/12/20 23:04:36 mkrochma
1104 Fix crash when adding private domain list to Dynamic Store
1106 Revision 1.354 2006/12/19 22:43:55 cheshire
1107 Fix compiler warnings
1109 Revision 1.353 2006/12/14 22:08:29 cheshire
1110 Fixed memory leak: need to call SecKeychainItemFreeAttributesAndData()
1111 to release data allocated by SecKeychainItemCopyAttributesAndData()
1113 Revision 1.352 2006/12/14 02:33:26 cheshire
1114 <rdar://problem/4841422> uDNS: Wide-area registrations sometimes fail
1116 Revision 1.351 2006/11/28 21:37:51 mkrochma
1117 Tweak where the private DNS data is written
1119 Revision 1.350 2006/11/28 07:55:02 herscher
1120 <rdar://problem/4742743> dnsextd has a slow memory leak
1122 Revision 1.349 2006/11/28 07:45:58 herscher
1123 <rdar://problem/4787010> Daemon: Need to write list of private domain names to the DynamicStore
1125 Revision 1.348 2006/11/16 21:47:20 mkrochma
1126 <rdar://problem/4841422> uDNS: Wide-area registrations sometimes fail
1128 Revision 1.347 2006/11/10 00:54:16 cheshire
1129 <rdar://problem/4816598> Changing case of Computer Name doesn't work
1131 Revision 1.346 2006/10/31 02:34:58 cheshire
1132 <rdar://problem/4692130> Stop creating HINFO records
1134 Revision 1.345 2006/09/21 20:04:38 mkrochma
1135 Accidently changed function name while checking in previous fix
1137 Revision 1.344 2006/09/21 19:04:13 mkrochma
1138 <rdar://problem/4733803> uDNS: Update keychain format of DNS key to include prefix
1140 Revision 1.343 2006/09/15 21:20:16 cheshire
1141 Remove uDNS_info substructure from mDNS_struct
1143 Revision 1.342 2006/08/16 00:31:50 mkrochma
1144 <rdar://problem/4386944> Get rid of NotAnInteger references
1146 Revision 1.341 2006/08/14 23:24:40 cheshire
1147 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
1149 Revision 1.340 2006/07/29 19:11:13 mkrochma
1150 Change GetUserSpecifiedDDNSConfig LogMsg to debugf
1152 Revision 1.339 2006/07/27 03:24:35 cheshire
1153 <rdar://problem/4049048> Convert mDNSResponder to use kqueue
1154 Further refinement: Declare KQueueEntry parameter "const"
1156 Revision 1.338 2006/07/27 02:59:25 cheshire
1157 <rdar://problem/4049048> Convert mDNSResponder to use kqueue
1158 Further refinements: CFRunLoop thread needs to explicitly wake the kqueue thread
1159 after releasing BigMutex, in case actions it took have resulted in new work for the
1160 kqueue thread (e.g. NetworkChanged events may result in the kqueue thread having to
1161 add new active interfaces to its list, and consequently schedule queries to be sent).
1163 Revision 1.337 2006/07/22 06:11:37 cheshire
1164 <rdar://problem/4049048> Convert mDNSResponder to use kqueue
1166 Revision 1.336 2006/07/15 02:01:32 cheshire
1167 <rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
1168 Fix broken "empty string" browsing
1170 Revision 1.335 2006/07/14 05:25:11 cheshire
1171 <rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
1172 Fixed crash in mDNSPlatformGetDNSConfig() reading BrowseDomains array
1174 Revision 1.334 2006/07/05 23:42:00 cheshire
1175 <rdar://problem/4472014> Add Private DNS client functionality to mDNSResponder
1177 Revision 1.333 2006/06/29 05:33:30 cheshire
1178 <rdar://problem/4607043> mDNSResponder conditional compilation options
1180 Revision 1.332 2006/06/28 09:10:36 cheshire
1181 Extra debugging messages
1183 Revision 1.331 2006/06/21 22:29:42 cheshire
1184 Make _CFCopySystemVersionDictionary() call more defensive on systems that have no build information set
1186 Revision 1.330 2006/06/20 23:06:00 cheshire
1187 Fix some keychain API type mismatches (was mDNSu32 instead of UInt32)
1189 Revision 1.329 2006/06/08 23:22:33 cheshire
1192 Revision 1.328 2006/03/19 03:27:49 cheshire
1193 <rdar://problem/4118624> Suppress "interface flapping" logic for loopback
1195 Revision 1.327 2006/03/19 02:00:09 cheshire
1196 <rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
1198 Revision 1.326 2006/03/08 22:42:23 cheshire
1199 Fix spelling mistake: LocalReverseMapomain -> LocalReverseMapDomain
1201 Revision 1.325 2006/01/10 00:39:17 cheshire
1202 Add comments explaining how IPv6 link-local addresses sometimes have an embedded scope_id
1204 Revision 1.324 2006/01/09 19:28:59 cheshire
1205 <rdar://problem/4403128> Cap number of "sendto failed" messages we allow mDNSResponder to log
1207 Revision 1.323 2006/01/05 21:45:27 cheshire
1208 <rdar://problem/4400118> Fix uninitialized structure member in IPv6 code
1210 Revision 1.322 2006/01/05 21:41:50 cheshire
1211 <rdar://problem/4108164> Reword "mach_absolute_time went backwards" dialog
1213 Revision 1.321 2006/01/05 21:35:06 cheshire
1214 Add (commented out) trigger value for testing "mach_absolute_time went backwards" notice
1218 // ***************************************************************************
1220 // Supporting routines to run mDNS on a CFRunLoop platform
1221 // ***************************************************************************
1223 // For debugging, set LIST_ALL_INTERFACES to 1 to display all found interfaces,
1224 // including ones that mDNSResponder chooses not to use.
1225 #define LIST_ALL_INTERFACES 0
1227 // For enabling AAAA records over IPv4. Setting this to 0 sends only
1228 // A records over IPv4 and AAAA over IPv6. Setting this to 1 sends both
1229 // AAAA and A records over both IPv4 and IPv6.
1230 #define AAAA_OVER_V4 1
1232 // In Mac OS X 10.4 and earlier, to reduce traffic, we would send and receive using IPv6 only on interfaces that had no routable
1233 // IPv4 address. Having a routable IPv4 address assigned is a reasonable indicator of being on a large configured network,
1234 // which means there's a good chance that most or all the other devices on that network should also have IPv4.
1235 // By doing this we lost the ability to talk to true IPv6-only devices on that link, but we cut the packet rate in half.
1236 // At that time, reducing the packet rate was more important than v6-only devices on a large configured network,
1237 // so were willing to make that sacrifice.
1238 // In Mac OS X 10.5, in 2007, two things have changed:
1239 // 1. IPv6-only devices are starting to become more common, so we can't ignore them.
1240 // 2. Other efficiency improvements in the code mean that crude hacks like this should no longer be necessary.
1242 #define USE_V6_ONLY_WHEN_NO_ROUTABLE_V4 0
1244 #include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
1245 #include "DNSCommon.h"
1247 #include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform
1248 #include "dns_sd.h" // For mDNSInterface_LocalOnly etc.
1249 #include "PlatformCommon.h"
1252 #include <stdarg.h> // For va_list support
1253 #include <stdlib.h> // For arc4random
1255 #include <net/if_types.h> // For IFT_ETHER
1256 #include <net/if_dl.h>
1257 #include <net/bpf.h> // For BIOCSETIF etc.
1258 #include <sys/uio.h>
1259 #include <sys/param.h>
1260 #include <sys/socket.h>
1261 #include <sys/sysctl.h>
1262 #include <sys/event.h>
1264 #include <sys/ioctl.h>
1265 #include <time.h> // platform support for UTC time
1266 #include <arpa/inet.h> // for inet_aton
1267 #include <pthread.h>
1269 #include <netinet/in.h> // For IP_RECVTTL
1271 #define IP_RECVTTL 24 // bool; receive reception TTL w/dgram
1274 #include <netinet/in_systm.h> // For n_long, required by <netinet/ip.h> below
1275 #include <netinet/ip.h> // For IPTOS_LOWDELAY etc.
1276 #include <netinet6/in6_var.h> // For IN6_IFF_NOTREADY etc.
1277 #include <netinet6/nd6.h> // For ND6_INFINITE_LIFETIME etc.
1279 #if TARGET_OS_EMBEDDED
1280 #define NO_SECURITYFRAMEWORK 1
1281 #define NO_CFUSERNOTIFICATION 1
1284 #ifndef NO_SECURITYFRAMEWORK
1285 #include <Security/SecureTransport.h>
1286 #include <Security/Security.h>
1287 #endif /* NO_SECURITYFRAMEWORK */
1289 #include <DebugServices.h>
1290 #include "dnsinfo.h"
1292 // Code contributed by Dave Heller:
1293 // Define RUN_ON_PUMA_WITHOUT_IFADDRS to compile code that will
1294 // work on Mac OS X 10.1, which does not have the getifaddrs call.
1295 #define RUN_ON_PUMA_WITHOUT_IFADDRS 0
1296 #if RUN_ON_PUMA_WITHOUT_IFADDRS
1297 #include "mDNSMacOSXPuma.c"
1299 #include <ifaddrs.h>
1302 #include <IOKit/IOKitLib.h>
1303 #include <IOKit/IOMessage.h>
1305 #if USE_IOPMCOPYACTIVEPMPREFERENCES
1306 #include <IOKit/ps/IOPowerSources.h>
1307 #include <IOKit/ps/IOPowerSourcesPrivate.h>
1310 #include <mach/mach_error.h>
1311 #include <mach/mach_port.h>
1312 #include <mach/mach_time.h>
1317 #define kInterfaceSpecificOption "interface="
1319 // ***************************************************************************
1322 #if COMPILER_LIKES_PRAGMA_MARK
1323 #pragma mark - Globals
1326 // By default we don't offer sleep proxy service
1327 // If OfferSleepProxyService is set non-zero (typically via command-line switch),
1328 // then we'll offer sleep proxy service on desktop Macs that are set to never sleep.
1329 // We currently do not offer sleep proxy service on laptops, or on machines that are set to go to sleep.
1330 mDNSexport
int OfferSleepProxyService
= 0;
1332 mDNSexport
int OSXVers
;
1333 mDNSexport
int KQueueFD
;
1335 #ifndef NO_SECURITYFRAMEWORK
1336 static CFArrayRef ServerCerts
;
1337 #endif /* NO_SECURITYFRAMEWORK */
1339 static CFStringRef NetworkChangedKey_IPv4
;
1340 static CFStringRef NetworkChangedKey_IPv6
;
1341 static CFStringRef NetworkChangedKey_Hostnames
;
1342 static CFStringRef NetworkChangedKey_Computername
;
1343 static CFStringRef NetworkChangedKey_DNS
;
1344 static CFStringRef NetworkChangedKey_DynamicDNS
= CFSTR("Setup:/Network/DynamicDNS");
1345 static CFStringRef NetworkChangedKey_BackToMyMac
= CFSTR("Setup:/Network/BackToMyMac");
1347 static char HINFO_HWstring_buffer
[32];
1348 static char *HINFO_HWstring
= "Device";
1349 static int HINFO_HWstring_prefixlen
= 6;
1351 mDNSexport
int WatchDogReportingThreshold
= 250;
1353 #if APPLE_OSX_mDNSResponder
1354 static mDNSu8 SPMetricPortability
= 99;
1355 static mDNSu8 SPMetricMarginalPower
= 99;
1356 static mDNSu8 SPMetricTotalPower
= 99;
1357 mDNSexport domainname ActiveDirectoryPrimaryDomain
;
1358 mDNSexport
int ActiveDirectoryPrimaryDomainLabelCount
;
1359 mDNSexport mDNSAddr ActiveDirectoryPrimaryDomainServer
;
1360 #endif // APPLE_OSX_mDNSResponder
1362 // ***************************************************************************
1365 #if COMPILER_LIKES_PRAGMA_MARK
1367 #pragma mark - Utility Functions
1370 // We only attempt to send and receive multicast packets on interfaces that are
1371 // (a) flagged as multicast-capable
1372 // (b) *not* flagged as point-to-point (e.g. modem)
1373 // Typically point-to-point interfaces are modems (including mobile-phone pseudo-modems), and we don't want
1374 // to run up the user's bill sending multicast traffic over a link where there's only a single device at the
1375 // other end, and that device (e.g. a modem bank) is probably not answering Multicast DNS queries anyway.
1376 #define MulticastInterface(i) (((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT))
1378 mDNSexport
void NotifyOfElusiveBug(const char *title
, const char *msg
) // Both strings are UTF-8 text
1380 static int notifyCount
= 0;
1381 if (notifyCount
) return;
1383 // If we display our alert early in the boot process, then it vanishes once the desktop appears.
1384 // To avoid this, we don't try to display alerts in the first three minutes after boot.
1385 if ((mDNSu32
)(mDNSPlatformRawTime()) < (mDNSu32
)(mDNSPlatformOneSecond
* 180)) return;
1387 // Unless ForceAlerts is defined, we only show these bug report alerts on machines that have a 17.x.x.x address
1390 // Determine if we're at Apple (17.*.*.*)
1391 extern mDNS mDNSStorage
;
1392 NetworkInterfaceInfoOSX
*i
;
1393 for (i
= mDNSStorage
.p
->InterfaceList
; i
; i
= i
->next
)
1394 if (i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
&& i
->ifinfo
.ip
.ip
.v4
.b
[0] == 17)
1396 if (!i
) return; // If not at Apple, don't show the alert
1400 LogMsg("%s", title
);
1402 // Display a notification to the user
1405 #ifndef NO_CFUSERNOTIFICATION
1406 mDNSNotify(title
, msg
);
1407 #endif /* NO_CFUSERNOTIFICATION */
1410 mDNSlocal
struct ifaddrs
*myGetIfAddrs(int refresh
)
1412 static struct ifaddrs
*ifa
= NULL
;
1420 if (ifa
== NULL
) getifaddrs(&ifa
);
1425 // To match *either* a v4 or v6 instance of this interface name, pass AF_UNSPEC for type
1426 mDNSlocal NetworkInterfaceInfoOSX
*SearchForInterfaceByName(mDNS
*const m
, const char *ifname
, int type
)
1428 NetworkInterfaceInfoOSX
*i
;
1429 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1430 if (i
->Exists
&& !strcmp(i
->ifinfo
.ifname
, ifname
) &&
1431 ((type
== AF_UNSPEC
) ||
1432 (type
== AF_INET
&& i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
) ||
1433 (type
== AF_INET6
&& i
->ifinfo
.ip
.type
== mDNSAddrType_IPv6
))) return(i
);
1437 mDNSlocal
int myIfIndexToName(u_short ifindex
, char *name
)
1439 struct ifaddrs
*ifa
;
1440 for (ifa
= myGetIfAddrs(0); ifa
; ifa
= ifa
->ifa_next
)
1441 if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
1442 if (((struct sockaddr_dl
*)ifa
->ifa_addr
)->sdl_index
== ifindex
)
1443 { strlcpy(name
, ifa
->ifa_name
, IF_NAMESIZE
); return 0; }
1447 mDNSexport mDNSInterfaceID
mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS
*const m
, mDNSu32 ifindex
)
1449 NetworkInterfaceInfoOSX
*i
;
1450 if (ifindex
== kDNSServiceInterfaceIndexLocalOnly
) return(mDNSInterface_LocalOnly
);
1451 if (ifindex
== kDNSServiceInterfaceIndexAny
) return(mDNSNULL
);
1453 // Don't get tricked by inactive interfaces with no InterfaceID set
1454 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1455 if (i
->ifinfo
.InterfaceID
&& i
->scope_id
== ifindex
) return(i
->ifinfo
.InterfaceID
);
1457 // Not found. Make sure our interface list is up to date, then try again.
1458 LogInfo("InterfaceID for interface index %d not found; Updating interface list", ifindex
);
1459 mDNSMacOSXNetworkChanged(m
);
1460 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1461 if (i
->ifinfo
.InterfaceID
&& i
->scope_id
== ifindex
) return(i
->ifinfo
.InterfaceID
);
1466 mDNSexport mDNSu32
mDNSPlatformInterfaceIndexfromInterfaceID(mDNS
*const m
, mDNSInterfaceID id
)
1468 NetworkInterfaceInfoOSX
*i
;
1469 if (id
== mDNSInterface_LocalOnly
) return(kDNSServiceInterfaceIndexLocalOnly
);
1470 if (id
== mDNSInterface_Any
) return(0);
1472 // Don't use i->ifinfo.InterfaceID here, because we DO want to find inactive interfaces, which have no InterfaceID set
1473 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1474 if ((mDNSInterfaceID
)i
== id
) return(i
->scope_id
);
1476 // Not found. Make sure our interface list is up to date, then try again.
1477 LogInfo("Interface index for InterfaceID %p not found; Updating interface list", id
);
1478 mDNSMacOSXNetworkChanged(m
);
1479 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1480 if ((mDNSInterfaceID
)i
== id
) return(i
->scope_id
);
1485 #if APPLE_OSX_mDNSResponder
1486 mDNSexport
void mDNSASLLog(uuid_t
*uuid
, const char *subdomain
, const char *result
, const char *signature
, const char *fmt
, ...)
1488 if (OSXVers
< OSXVers_10_6_SnowLeopard
) return;
1490 static char buffer
[512];
1491 aslmsg asl_msg
= asl_new(ASL_TYPE_MSG
);
1493 if (!asl_msg
) { LogMsg("mDNSASLLog: asl_new failed"); return; }
1497 uuid_unparse(*uuid
, uuidStr
);
1498 asl_set (asl_msg
, "com.apple.message.uuid", uuidStr
);
1501 static char domainBase
[] = "com.apple.mDNSResponder.%s";
1502 mDNS_snprintf (buffer
, sizeof(buffer
), domainBase
, subdomain
);
1503 asl_set (asl_msg
, "com.apple.message.domain", buffer
);
1505 if (result
) asl_set(asl_msg
, "com.apple.message.result", result
);
1506 if (signature
) asl_set(asl_msg
, "com.apple.message.signature", signature
);
1510 mDNS_vsnprintf(buffer
, sizeof(buffer
), fmt
, ptr
);
1513 int old_filter
= asl_set_filter(NULL
,ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG
));
1514 asl_log(NULL
, asl_msg
, ASL_LEVEL_DEBUG
, "%s", buffer
);
1515 asl_set_filter(NULL
, old_filter
);
1520 #if COMPILER_LIKES_PRAGMA_MARK
1522 #pragma mark - UDP & TCP send & receive
1525 mDNSlocal mDNSBool
AddrRequiresPPPConnection(const struct sockaddr
*addr
)
1527 mDNSBool result
= mDNSfalse
;
1528 SCNetworkConnectionFlags flags
;
1529 SCNetworkReachabilityRef ReachRef
= NULL
;
1531 ReachRef
= SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault
, addr
);
1532 if (!ReachRef
) { LogMsg("ERROR: RequiresConnection - SCNetworkReachabilityCreateWithAddress"); goto end
; }
1533 if (!SCNetworkReachabilityGetFlags(ReachRef
, &flags
)) { LogMsg("ERROR: AddrRequiresPPPConnection - SCNetworkReachabilityGetFlags"); goto end
; }
1534 result
= flags
& kSCNetworkFlagsConnectionRequired
;
1537 if (ReachRef
) CFRelease(ReachRef
);
1541 // Note: If InterfaceID is NULL, it means, "send this packet through our anonymous unicast socket"
1542 // Note: If InterfaceID is non-NULL it means, "send this packet through our port 5353 socket on the specified interface"
1543 // OR send via our primary v4 unicast socket
1544 // UPDATE: The UDPSocket *src parameter now allows the caller to specify the source socket
1545 mDNSexport mStatus
mDNSPlatformSendUDP(const mDNS
*const m
, const void *const msg
, const mDNSu8
*const end
,
1546 mDNSInterfaceID InterfaceID
, UDPSocket
*src
, const mDNSAddr
*dst
, mDNSIPPort dstPort
)
1548 // Note: For this platform we've adopted the convention that InterfaceIDs are secretly pointers
1549 // to the NetworkInterfaceInfoOSX structure that holds the active sockets. The mDNSCore code
1550 // doesn't know that and doesn't need to know that -- it just treats InterfaceIDs as opaque identifiers.
1551 NetworkInterfaceInfoOSX
*info
= (NetworkInterfaceInfoOSX
*)InterfaceID
;
1552 char *ifa_name
= info
? info
->ifinfo
.ifname
: "unicast";
1553 struct sockaddr_storage to
;
1555 mStatus result
= mStatus_NoError
;
1557 if (dst
->type
== mDNSAddrType_IPv4
)
1559 struct sockaddr_in
*sin_to
= (struct sockaddr_in
*)&to
;
1560 sin_to
->sin_len
= sizeof(*sin_to
);
1561 sin_to
->sin_family
= AF_INET
;
1562 sin_to
->sin_port
= dstPort
.NotAnInteger
;
1563 sin_to
->sin_addr
.s_addr
= dst
->ip
.v4
.NotAnInteger
;
1564 s
= (src
? src
->ss
: m
->p
->permanentsockets
).sktv4
;
1566 if (info
) // Specify outgoing interface
1568 if (!mDNSAddrIsDNSMulticast(dst
))
1571 if (info
->scope_id
== 0)
1572 LogInfo("IP_BOUND_IF socket option not set -- info %p (%s) scope_id is zero", info
, ifa_name
);
1574 setsockopt(s
, IPPROTO_IP
, IP_BOUND_IF
, &info
->scope_id
, sizeof(info
->scope_id
));
1577 static int displayed
= 0;
1578 if (displayed
< 1000)
1581 LogInfo("IP_BOUND_IF socket option not defined -- cannot specify interface for unicast packets");
1588 err
= setsockopt(s
, IPPROTO_IP
, IP_MULTICAST_IF
, &info
->ifa_v4addr
, sizeof(info
->ifa_v4addr
));
1589 if (err
< 0 && !m
->p
->NetworkChanged
)
1590 LogMsg("setsockopt - IP_MULTICAST_IF error %.4a %d errno %d (%s)", &info
->ifa_v4addr
, err
, errno
, strerror(errno
));
1594 else if (dst
->type
== mDNSAddrType_IPv6
)
1596 struct sockaddr_in6
*sin6_to
= (struct sockaddr_in6
*)&to
;
1597 sin6_to
->sin6_len
= sizeof(*sin6_to
);
1598 sin6_to
->sin6_family
= AF_INET6
;
1599 sin6_to
->sin6_port
= dstPort
.NotAnInteger
;
1600 sin6_to
->sin6_flowinfo
= 0;
1601 sin6_to
->sin6_addr
= *(struct in6_addr
*)&dst
->ip
.v6
;
1602 sin6_to
->sin6_scope_id
= info
? info
->scope_id
: 0;
1603 s
= (src
? src
->ss
: m
->p
->permanentsockets
).sktv6
;
1604 if (info
&& mDNSAddrIsDNSMulticast(dst
)) // Specify outgoing interface
1606 err
= setsockopt(s
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
, &info
->scope_id
, sizeof(info
->scope_id
));
1607 if (err
< 0) LogMsg("setsockopt - IPV6_MULTICAST_IF error %d errno %d (%s)", err
, errno
, strerror(errno
));
1612 LogMsg("mDNSPlatformSendUDP: dst is not an IPv4 or IPv6 address!");
1616 return mStatus_BadParamErr
;
1620 verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %p %5s/%ld to %#a:%d skt %d",
1621 InterfaceID
, ifa_name
, dst
->type
, dst
, mDNSVal16(dstPort
), s
);
1623 verbosedebugf("mDNSPlatformSendUDP: NOT sending on InterfaceID %p %5s/%ld (socket of this type not available)",
1624 InterfaceID
, ifa_name
, dst
->type
, dst
, mDNSVal16(dstPort
));
1626 // Note: When sending, mDNSCore may often ask us to send both a v4 multicast packet and then a v6 multicast packet
1627 // If we don't have the corresponding type of socket available, then return mStatus_Invalid
1628 if (s
< 0) return(mStatus_Invalid
);
1630 err
= sendto(s
, msg
, (UInt8
*)end
- (UInt8
*)msg
, 0, (struct sockaddr
*)&to
, to
.ss_len
);
1633 static int MessageCount
= 0;
1634 // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
1635 if (!mDNSAddressIsAllDNSLinkGroup(dst
))
1636 if (errno
== EHOSTDOWN
|| errno
== ENETDOWN
|| errno
== EHOSTUNREACH
|| errno
== ENETUNREACH
) return(mStatus_TransientErr
);
1637 // Don't report EHOSTUNREACH in the first three minutes after boot
1638 // This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
1639 // but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
1640 if (errno
== EHOSTUNREACH
&& (mDNSu32
)(mDNSPlatformRawTime()) < (mDNSu32
)(mDNSPlatformOneSecond
* 180)) return(mStatus_TransientErr
);
1641 // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change
1642 if (errno
== EADDRNOTAVAIL
&& m
->p
->NetworkChanged
) return(mStatus_TransientErr
);
1643 if (MessageCount
< 1000)
1646 if (errno
== EHOSTUNREACH
|| errno
== EADDRNOTAVAIL
|| errno
== ENETDOWN
)
1647 LogInfo("mDNSPlatformSendUDP sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu",
1648 s
, InterfaceID
, ifa_name
, dst
->type
, dst
, mDNSVal16(dstPort
), s
, err
, errno
, strerror(errno
), (mDNSu32
)(m
->timenow
));
1650 LogMsg("mDNSPlatformSendUDP sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu",
1651 s
, InterfaceID
, ifa_name
, dst
->type
, dst
, mDNSVal16(dstPort
), s
, err
, errno
, strerror(errno
), (mDNSu32
)(m
->timenow
));
1653 result
= mStatus_UnknownErr
;
1657 if (dst
->type
== mDNSAddrType_IPv4
&& info
&& !mDNSAddrIsDNSMulticast(dst
))
1659 static const mDNSu32 ifindex
= 0;
1660 setsockopt(s
, IPPROTO_IP
, IP_BOUND_IF
, &ifindex
, sizeof(ifindex
));
1667 mDNSlocal ssize_t
myrecvfrom(const int s
, void *const buffer
, const size_t max
,
1668 struct sockaddr
*const from
, size_t *const fromlen
, mDNSAddr
*dstaddr
, char ifname
[IF_NAMESIZE
], mDNSu8
*ttl
)
1670 static unsigned int numLogMessages
= 0;
1671 struct iovec databuffers
= { (char *)buffer
, max
};
1674 struct cmsghdr
*cmPtr
;
1675 char ancillary
[1024];
1677 *ttl
= 255; // If kernel fails to provide TTL data (e.g. Jaguar doesn't) then assume the TTL was 255 as it should be
1679 // Set up the message
1680 msg
.msg_name
= (caddr_t
)from
;
1681 msg
.msg_namelen
= *fromlen
;
1682 msg
.msg_iov
= &databuffers
;
1684 msg
.msg_control
= (caddr_t
)&ancillary
;
1685 msg
.msg_controllen
= sizeof(ancillary
);
1689 n
= recvmsg(s
, &msg
, 0);
1692 if (errno
!= EWOULDBLOCK
&& numLogMessages
++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned error %d errno %d", s
, n
, errno
);
1695 if (msg
.msg_controllen
< (int)sizeof(struct cmsghdr
))
1697 if (numLogMessages
++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned %d msg.msg_controllen %d < sizeof(struct cmsghdr) %lu",
1698 s
, n
, msg
.msg_controllen
, sizeof(struct cmsghdr
));
1701 if (msg
.msg_flags
& MSG_CTRUNC
)
1703 if (numLogMessages
++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s
);
1707 *fromlen
= msg
.msg_namelen
;
1709 // Parse each option out of the ancillary data.
1710 for (cmPtr
= CMSG_FIRSTHDR(&msg
); cmPtr
; cmPtr
= CMSG_NXTHDR(&msg
, cmPtr
))
1712 // debugf("myrecvfrom cmsg_level %d cmsg_type %d", cmPtr->cmsg_level, cmPtr->cmsg_type);
1713 if (cmPtr
->cmsg_level
== IPPROTO_IP
&& cmPtr
->cmsg_type
== IP_RECVDSTADDR
)
1715 dstaddr
->type
= mDNSAddrType_IPv4
;
1716 dstaddr
->ip
.v4
= *(mDNSv4Addr
*)CMSG_DATA(cmPtr
);
1717 //LogMsg("mDNSMacOSX.c: recvmsg IP_RECVDSTADDR %.4a", &dstaddr->ip.v4);
1719 if (cmPtr
->cmsg_level
== IPPROTO_IP
&& cmPtr
->cmsg_type
== IP_RECVIF
)
1721 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)CMSG_DATA(cmPtr
);
1722 if (sdl
->sdl_nlen
< IF_NAMESIZE
)
1724 mDNSPlatformMemCopy(ifname
, sdl
->sdl_data
, sdl
->sdl_nlen
);
1725 ifname
[sdl
->sdl_nlen
] = 0;
1726 // debugf("IP_RECVIF sdl_index %d, sdl_data %s len %d", sdl->sdl_index, ifname, sdl->sdl_nlen);
1729 if (cmPtr
->cmsg_level
== IPPROTO_IP
&& cmPtr
->cmsg_type
== IP_RECVTTL
)
1730 *ttl
= *(u_char
*)CMSG_DATA(cmPtr
);
1731 if (cmPtr
->cmsg_level
== IPPROTO_IPV6
&& cmPtr
->cmsg_type
== IPV6_PKTINFO
)
1733 struct in6_pktinfo
*ip6_info
= (struct in6_pktinfo
*)CMSG_DATA(cmPtr
);
1734 dstaddr
->type
= mDNSAddrType_IPv6
;
1735 dstaddr
->ip
.v6
= *(mDNSv6Addr
*)&ip6_info
->ipi6_addr
;
1736 myIfIndexToName(ip6_info
->ipi6_ifindex
, ifname
);
1738 if (cmPtr
->cmsg_level
== IPPROTO_IPV6
&& cmPtr
->cmsg_type
== IPV6_HOPLIMIT
)
1739 *ttl
= *(int*)CMSG_DATA(cmPtr
);
1745 mDNSlocal
void myKQSocketCallBack(int s1
, short filter
, void *context
)
1747 KQSocketSet
*const ss
= (KQSocketSet
*)context
;
1748 mDNS
*const m
= ss
->m
;
1749 int err
= 0, count
= 0, closed
= 0;
1751 if (filter
!= EVFILT_READ
)
1752 LogMsg("myKQSocketCallBack: Why is filter %d not EVFILT_READ (%d)?", filter
, EVFILT_READ
);
1754 if (s1
!= ss
->sktv4
&& s1
!= ss
->sktv6
)
1756 LogMsg("myKQSocketCallBack: native socket %d", s1
);
1757 LogMsg("myKQSocketCallBack: sktv4 %d", ss
->sktv4
);
1758 LogMsg("myKQSocketCallBack: sktv6 %d", ss
->sktv6
);
1763 mDNSAddr senderAddr
, destAddr
;
1764 mDNSIPPort senderPort
;
1765 struct sockaddr_storage from
;
1766 size_t fromlen
= sizeof(from
);
1767 char packetifname
[IF_NAMESIZE
] = "";
1769 err
= myrecvfrom(s1
, &m
->imsg
, sizeof(m
->imsg
), (struct sockaddr
*)&from
, &fromlen
, &destAddr
, packetifname
, &ttl
);
1773 if (from
.ss_family
== AF_INET
)
1775 struct sockaddr_in
*s
= (struct sockaddr_in
*)&from
;
1776 senderAddr
.type
= mDNSAddrType_IPv4
;
1777 senderAddr
.ip
.v4
.NotAnInteger
= s
->sin_addr
.s_addr
;
1778 senderPort
.NotAnInteger
= s
->sin_port
;
1779 //LogInfo("myKQSocketCallBack received IPv4 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
1781 else if (from
.ss_family
== AF_INET6
)
1783 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)&from
;
1784 senderAddr
.type
= mDNSAddrType_IPv6
;
1785 senderAddr
.ip
.v6
= *(mDNSv6Addr
*)&sin6
->sin6_addr
;
1786 senderPort
.NotAnInteger
= sin6
->sin6_port
;
1787 //LogInfo("myKQSocketCallBack received IPv6 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
1791 LogMsg("myKQSocketCallBack from is unknown address family %d", from
.ss_family
);
1795 // Note: When handling multiple packets in a batch, MUST reset InterfaceID before handling each packet
1796 mDNSInterfaceID InterfaceID
= mDNSNULL
;
1797 NetworkInterfaceInfo
*intf
= m
->HostInterfaces
;
1798 while (intf
&& strcmp(intf
->ifname
, packetifname
)) intf
= intf
->next
;
1799 // When going to sleep we deregister all our interfaces, but if the machine
1800 // takes a few seconds to sleep we may continue to receive multicasts
1801 // during that time, which would confuse mDNSCoreReceive, because as far
1802 // as it's concerned, we should have no active interfaces any more.
1803 // Hence we ignore multicasts for which we can find no matching InterfaceID.
1804 if (intf
) InterfaceID
= intf
->InterfaceID
;
1805 else if (mDNSAddrIsDNSMulticast(&destAddr
)) continue;
1807 // LogMsg("myKQSocketCallBack got packet from %#a to %#a on interface %#a/%s",
1808 // &senderAddr, &destAddr, &ss->info->ifinfo.ip, ss->info->ifinfo.ifname);
1810 // mDNSCoreReceive may close the socket we're reading from. We must break out of our
1811 // loop when that happens, or we may try to read from an invalid FD. We do this by
1812 // setting the closeFlag pointer in the socketset, so CloseSocketSet can inform us
1813 // if it closes the socketset.
1814 ss
->closeFlag
= &closed
;
1816 mDNSCoreReceive(m
, &m
->imsg
, (unsigned char*)&m
->imsg
+ err
, &senderAddr
, senderPort
, &destAddr
, ss
->port
, InterfaceID
);
1818 // if we didn't close, we can safely dereference the socketset, and should to
1819 // reset the closeFlag, since it points to something on the stack
1820 if (!closed
) ss
->closeFlag
= mDNSNULL
;
1823 if (err
< 0 && (errno
!= EWOULDBLOCK
|| count
== 0))
1825 // Something is busted here.
1826 // kqueue says there is a packet, but myrecvfrom says there is not.
1827 // Try calling select() to get another opinion.
1828 // Find out about other socket parameter that can help understand why select() says the socket is ready for read
1829 // All of this is racy, as data may have arrived after the call to select()
1830 static unsigned int numLogMessages
= 0;
1831 int save_errno
= errno
;
1835 socklen_t solen
= sizeof(int);
1837 struct timeval timeout
;
1840 FD_SET(s1
, &readfds
);
1842 timeout
.tv_usec
= 0;
1843 selectresult
= select(s1
+1, &readfds
, NULL
, NULL
, &timeout
);
1844 if (getsockopt(s1
, SOL_SOCKET
, SO_ERROR
, &so_error
, &solen
) == -1)
1845 LogMsg("myKQSocketCallBack getsockopt(SO_ERROR) error %d", errno
);
1846 if (getsockopt(s1
, SOL_SOCKET
, SO_NREAD
, &so_nread
, &solen
) == -1)
1847 LogMsg("myKQSocketCallBack getsockopt(SO_NREAD) error %d", errno
);
1848 if (ioctl(s1
, FIONREAD
, &fionread
) == -1)
1849 LogMsg("myKQSocketCallBack ioctl(FIONREAD) error %d", errno
);
1850 if (numLogMessages
++ < 100)
1851 LogMsg("myKQSocketCallBack recvfrom skt %d error %d errno %d (%s) select %d (%spackets waiting) so_error %d so_nread %d fionread %d count %d",
1852 s1
, err
, save_errno
, strerror(save_errno
), selectresult
, FD_ISSET(s1
, &readfds
) ? "" : "*NO* ", so_error
, so_nread
, fionread
, count
);
1853 if (numLogMessages
> 5)
1854 NotifyOfElusiveBug("Flaw in Kernel (select/recvfrom mismatch)",
1855 "Congratulations, you've reproduced an elusive bug.\r"
1856 "Please contact the current assignee of <rdar://problem/3375328>.\r"
1857 "Alternatively, you can send email to radar-3387020@group.apple.com. (Note number is different.)\r"
1858 "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
1860 sleep(1); // After logging this error, rate limit so we don't flood syslog
1864 // TCP socket support
1869 handshake_in_progress
,
1870 handshake_completed
,
1871 handshake_to_be_closed
1874 struct TCPSocket_struct
1876 TCPSocketFlags flags
; // MUST BE FIRST FIELD -- mDNSCore expects every TCPSocket_struct to begin with TCPSocketFlags flags
1877 TCPConnectionCallback callback
;
1879 KQueueEntry kqEntry
;
1880 #ifndef NO_SECURITYFRAMEWORK
1881 SSLContextRef tlsContext
;
1882 pthread_t handshake_thread
;
1883 #endif /* NO_SECURITYFRAMEWORK */
1887 handshakeStatus handshake
;
1888 mDNS
*m
; // So we can call KQueueLock from the SSLHandshake thread
1892 mDNSlocal
void doTcpSocketCallback(TCPSocket
*sock
)
1894 mDNSBool c
= !sock
->connected
;
1895 sock
->connected
= mDNStrue
;
1896 sock
->callback(sock
, sock
->context
, c
, sock
->err
);
1897 // Note: the callback may call CloseConnection here, which frees the context structure!
1900 #ifndef NO_SECURITYFRAMEWORK
1902 mDNSlocal OSStatus
tlsWriteSock(SSLConnectionRef connection
, const void *data
, size_t *dataLength
)
1904 int ret
= send(((TCPSocket
*)connection
)->fd
, data
, *dataLength
, 0);
1905 if (ret
>= 0 && (size_t)ret
< *dataLength
) { *dataLength
= ret
; return(errSSLWouldBlock
); }
1906 if (ret
>= 0) { *dataLength
= ret
; return(noErr
); }
1908 if (errno
== EAGAIN
) return(errSSLWouldBlock
);
1909 if (errno
== ENOENT
) return(errSSLClosedGraceful
);
1910 if (errno
== EPIPE
|| errno
== ECONNRESET
) return(errSSLClosedAbort
);
1911 LogMsg("ERROR: tlsWriteSock: %d error %d (%s)\n", ((TCPSocket
*)connection
)->fd
, errno
, strerror(errno
));
1912 return(errSSLClosedAbort
);
1915 mDNSlocal OSStatus
tlsReadSock(SSLConnectionRef connection
, void *data
, size_t *dataLength
)
1917 int ret
= recv(((TCPSocket
*)connection
)->fd
, data
, *dataLength
, 0);
1918 if (ret
> 0 && (size_t)ret
< *dataLength
) { *dataLength
= ret
; return(errSSLWouldBlock
); }
1919 if (ret
> 0) { *dataLength
= ret
; return(noErr
); }
1921 if (ret
== 0 || errno
== ENOENT
) return(errSSLClosedGraceful
);
1922 if ( errno
== EAGAIN
) return(errSSLWouldBlock
);
1923 if ( errno
== ECONNRESET
) return(errSSLClosedAbort
);
1924 LogMsg("ERROR: tlsSockRead: error %d (%s)\n", errno
, strerror(errno
));
1925 return(errSSLClosedAbort
);
1928 mDNSlocal OSStatus
tlsSetupSock(TCPSocket
*sock
, mDNSBool server
)
1930 mStatus err
= SSLNewContext(server
, &sock
->tlsContext
);
1931 if (err
) { LogMsg("ERROR: tlsSetupSock: SSLNewContext failed with error code: %d", err
); return(err
); }
1933 err
= SSLSetIOFuncs(sock
->tlsContext
, tlsReadSock
, tlsWriteSock
);
1934 if (err
) { LogMsg("ERROR: tlsSetupSock: SSLSetIOFuncs failed with error code: %d", err
); return(err
); }
1936 err
= SSLSetConnection(sock
->tlsContext
, (SSLConnectionRef
) sock
);
1937 if (err
) { LogMsg("ERROR: tlsSetupSock: SSLSetConnection failed with error code: %d", err
); return(err
); }
1942 mDNSlocal
void *doSSLHandshake(void *ctx
)
1944 // Warning: Touching sock without the kqueue lock!
1945 // We're protected because sock->handshake == handshake_in_progress
1946 TCPSocket
*sock
= (TCPSocket
*)ctx
;
1947 mDNS
* const m
= sock
->m
; // Get m now, as we may free sock if marked to be closed while we're waiting on SSLHandshake
1948 mStatus err
= SSLHandshake(sock
->tlsContext
);
1951 LogInfo("doSSLHandshake %p: got lock", sock
); // Log *after* we get the lock
1953 if (sock
->handshake
== handshake_to_be_closed
)
1955 LogInfo("SSLHandshake completed after close");
1956 mDNSPlatformTCPCloseConnection(sock
);
1960 if (sock
->fd
!= -1) KQueueSet(sock
->fd
, EV_ADD
, EVFILT_READ
, &sock
->kqEntry
);
1961 else LogMsg("doSSLHandshake: sock->fd is -1");
1963 if (err
== errSSLWouldBlock
)
1964 sock
->handshake
= handshake_required
;
1969 LogMsg("SSLHandshake failed: %d", err
);
1970 SSLDisposeContext(sock
->tlsContext
);
1971 sock
->tlsContext
= NULL
;
1975 sock
->handshake
= handshake_completed
;
1977 LogInfo("doSSLHandshake: %p calling doTcpSocketCallback", sock
);
1978 doTcpSocketCallback(sock
);
1982 LogInfo("SSLHandshake %p: dropping lock", sock
);
1983 KQueueUnlock(m
, "doSSLHandshake");
1987 mDNSlocal mStatus
spawnSSLHandshake(TCPSocket
* sock
)
1989 LogInfo("spawnSSLHandshake %p: entry", sock
);
1990 if (sock
->handshake
!= handshake_required
) LogMsg("spawnSSLHandshake: handshake status not required: %d", sock
->handshake
);
1991 sock
->handshake
= handshake_in_progress
;
1992 KQueueSet(sock
->fd
, EV_DELETE
, EVFILT_READ
, &sock
->kqEntry
);
1993 pthread_attr_t attr
;
1994 pthread_attr_init(&attr
);
1995 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
1996 mStatus err
= pthread_create(&sock
->handshake_thread
, &attr
, doSSLHandshake
, sock
);
1997 pthread_attr_destroy(&attr
);
2000 LogMsg("Could not start SSLHandshake thread: (%d) %s", err
, strerror(err
));
2001 sock
->handshake
= handshake_completed
;
2003 KQueueSet(sock
->fd
, EV_ADD
, EVFILT_READ
, &sock
->kqEntry
);
2005 LogInfo("spawnSSLHandshake %p: done", sock
);
2009 mDNSlocal mDNSBool
IsTunnelModeDomain(const domainname
*d
)
2011 static const domainname
*mmc
= (const domainname
*) "\x7" "members" "\x3" "mac" "\x3" "com";
2012 const domainname
*d1
= mDNSNULL
; // TLD
2013 const domainname
*d2
= mDNSNULL
; // SLD
2014 const domainname
*d3
= mDNSNULL
;
2015 while (d
->c
[0]) { d3
= d2
; d2
= d1
; d1
= d
; d
= (const domainname
*)(d
->c
+ 1 + d
->c
[0]); }
2016 return(d3
&& SameDomainName(d3
, mmc
));
2019 #endif /* NO_SECURITYFRAMEWORK */
2021 mDNSlocal
void tcpKQSocketCallback(__unused
int fd
, short filter
, void *context
)
2023 TCPSocket
*sock
= context
;
2024 sock
->err
= mStatus_NoError
;
2026 //if (filter == EVFILT_READ ) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_READ", filter);
2027 //if (filter == EVFILT_WRITE) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_WRITE", filter);
2028 // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it here with EV_DELETE
2029 if (filter
== EVFILT_WRITE
) KQueueSet(sock
->fd
, EV_DELETE
, EVFILT_WRITE
, &sock
->kqEntry
);
2031 if (sock
->flags
& kTCPSocketFlags_UseTLS
)
2033 #ifndef NO_SECURITYFRAMEWORK
2034 if (!sock
->setup
) { sock
->setup
= mDNStrue
; tlsSetupSock(sock
, mDNSfalse
); }
2036 if (sock
->handshake
== handshake_required
) { if (spawnSSLHandshake(sock
) == 0) return; }
2037 else if (sock
->handshake
== handshake_in_progress
|| sock
->handshake
== handshake_to_be_closed
) return;
2038 else if (sock
->handshake
!= handshake_completed
)
2040 if (!sock
->err
) sock
->err
= mStatus_UnknownErr
;
2041 LogMsg("tcpKQSocketCallback called with unexpected SSLHandshake status: %d", sock
->handshake
);
2044 sock
->err
= mStatus_UnsupportedErr
;
2045 #endif /* NO_SECURITYFRAMEWORK */
2048 doTcpSocketCallback(sock
);
2051 mDNSexport
int KQueueSet(int fd
, u_short flags
, short filter
, const KQueueEntry
*const entryRef
)
2053 struct kevent new_event
;
2054 EV_SET(&new_event
, fd
, filter
, flags
, 0, 0, (void*)entryRef
);
2055 return (kevent(KQueueFD
, &new_event
, 1, NULL
, 0, NULL
) < 0) ? errno
: 0;
2058 mDNSexport
void KQueueLock(mDNS
*const m
)
2060 pthread_mutex_lock(&m
->p
->BigMutex
);
2061 m
->p
->BigMutexStartTime
= mDNSPlatformRawTime();
2064 mDNSexport
void KQueueUnlock(mDNS
*const m
, const char const *task
)
2066 mDNSs32 end
= mDNSPlatformRawTime();
2068 if (end
- m
->p
->BigMutexStartTime
>= WatchDogReportingThreshold
)
2069 LogInfo("WARNING: %s took %dms to complete", task
, end
- m
->p
->BigMutexStartTime
);
2071 pthread_mutex_unlock(&m
->p
->BigMutex
);
2074 if (send(m
->p
->WakeKQueueLoopFD
, &wake
, sizeof(wake
), 0) == -1)
2075 LogMsg("ERROR: KQueueWake: send failed with error code: %d (%s)", errno
, strerror(errno
));
2078 mDNSexport TCPSocket
*mDNSPlatformTCPSocket(mDNS
*const m
, TCPSocketFlags flags
, mDNSIPPort
*port
)
2082 TCPSocket
*sock
= mallocL("TCPSocket/mDNSPlatformTCPSocket", sizeof(TCPSocket
));
2083 if (!sock
) { LogMsg("mDNSPlatformTCPSocket: memory allocation failure"); return(mDNSNULL
); }
2085 mDNSPlatformMemZero(sock
, sizeof(TCPSocket
));
2086 sock
->callback
= mDNSNULL
;
2087 sock
->fd
= socket(AF_INET
, SOCK_STREAM
, 0);
2088 sock
->kqEntry
.KQcallback
= tcpKQSocketCallback
;
2089 sock
->kqEntry
.KQcontext
= sock
;
2090 sock
->kqEntry
.KQtask
= "mDNSPlatformTCPSocket";
2091 sock
->flags
= flags
;
2092 sock
->context
= mDNSNULL
;
2093 sock
->setup
= mDNSfalse
;
2094 sock
->connected
= mDNSfalse
;
2095 sock
->handshake
= handshake_required
;
2097 sock
->err
= mStatus_NoError
;
2101 LogMsg("mDNSPlatformTCPSocket: socket error %d errno %d (%s)", sock
->fd
, errno
, strerror(errno
));
2102 freeL("TCPSocket/mDNSPlatformTCPSocket", sock
);
2107 struct sockaddr_in addr
;
2108 mDNSPlatformMemZero(&addr
, sizeof(addr
));
2109 addr
.sin_family
= AF_INET
;
2110 addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
2111 addr
.sin_port
= port
->NotAnInteger
;
2112 if (bind(sock
->fd
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0)
2113 { LogMsg("ERROR: bind %s", strerror(errno
)); goto error
; }
2115 // Receive interface identifiers
2116 const int on
= 1; // "on" for setsockopt
2117 if (setsockopt(sock
->fd
, IPPROTO_IP
, IP_RECVIF
, &on
, sizeof(on
)) < 0)
2118 { LogMsg("setsockopt IP_RECVIF - %s", strerror(errno
)); goto error
; }
2120 mDNSPlatformMemZero(&addr
, sizeof(addr
));
2121 socklen_t len
= sizeof(addr
);
2122 if (getsockname(sock
->fd
, (struct sockaddr
*) &addr
, &len
) < 0)
2123 { LogMsg("getsockname - %s", strerror(errno
)); goto error
; }
2125 port
->NotAnInteger
= addr
.sin_port
;
2130 freeL("TCPSocket/mDNSPlatformTCPSocket", sock
);
2134 mDNSexport mStatus
mDNSPlatformTCPConnect(TCPSocket
*sock
, const mDNSAddr
*dst
, mDNSOpaque16 dstport
, mDNSInterfaceID InterfaceID
,
2135 TCPConnectionCallback callback
, void *context
)
2137 struct sockaddr_in saddr
;
2138 mStatus err
= mStatus_NoError
;
2140 sock
->callback
= callback
;
2141 sock
->context
= context
;
2142 sock
->setup
= mDNSfalse
;
2143 sock
->connected
= mDNSfalse
;
2144 sock
->handshake
= handshake_required
;
2145 sock
->err
= mStatus_NoError
;
2147 (void) InterfaceID
; //!!!KRS use this if non-zero!!!
2149 if (dst
->type
!= mDNSAddrType_IPv4
)
2151 LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: opperation not supported");
2152 return mStatus_UnknownErr
;
2155 mDNSPlatformMemZero(&saddr
, sizeof(saddr
));
2156 saddr
.sin_family
= AF_INET
;
2157 saddr
.sin_port
= dstport
.NotAnInteger
;
2158 saddr
.sin_len
= sizeof(saddr
);
2159 saddr
.sin_addr
.s_addr
= dst
->ip
.v4
.NotAnInteger
;
2161 sock
->kqEntry
.KQcallback
= tcpKQSocketCallback
;
2162 sock
->kqEntry
.KQcontext
= sock
;
2163 sock
->kqEntry
.KQtask
= "Outgoing TCP";
2165 // Watch for connect complete (write is ready)
2166 // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it in tcpKQSocketCallback using EV_DELETE
2167 if (KQueueSet(sock
->fd
, EV_ADD
/* | EV_ONESHOT */, EVFILT_WRITE
, &sock
->kqEntry
))
2169 LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
2174 // Watch for incoming data
2175 if (KQueueSet(sock
->fd
, EV_ADD
, EVFILT_READ
, &sock
->kqEntry
))
2177 LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
2178 close(sock
->fd
); // Closing the descriptor removes all filters from the kqueue
2182 if (fcntl(sock
->fd
, F_SETFL
, fcntl(sock
->fd
, F_GETFL
, 0) | O_NONBLOCK
) < 0) // set non-blocking
2184 LogMsg("ERROR: setsockopt O_NONBLOCK - %s", strerror(errno
));
2185 return mStatus_UnknownErr
;
2188 // initiate connection wth peer
2189 if (connect(sock
->fd
, (struct sockaddr
*)&saddr
, sizeof(saddr
)) < 0)
2191 if (errno
== EINPROGRESS
) return mStatus_ConnPending
;
2192 if (errno
== EHOSTUNREACH
|| errno
== EADDRNOTAVAIL
|| errno
== ENETDOWN
)
2193 LogInfo("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s)", sock
->fd
, errno
, strerror(errno
));
2195 LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s)", sock
->fd
, errno
, strerror(errno
));
2197 return mStatus_ConnFailed
;
2200 LogMsg("NOTE: mDNSPlatformTCPConnect completed synchronously");
2201 // kQueue should notify us, but this LogMsg is to help track down if it doesn't
2205 // Why doesn't mDNSPlatformTCPAccept actually call accept() ?
2206 mDNSexport TCPSocket
*mDNSPlatformTCPAccept(TCPSocketFlags flags
, int fd
)
2208 mStatus err
= mStatus_NoError
;
2210 TCPSocket
*sock
= mallocL("TCPSocket/mDNSPlatformTCPAccept", sizeof(TCPSocket
));
2211 if (!sock
) return(mDNSNULL
);
2213 mDNSPlatformMemZero(sock
, sizeof(*sock
));
2215 sock
->flags
= flags
;
2217 if (flags
& kTCPSocketFlags_UseTLS
)
2219 #ifndef NO_SECURITYFRAMEWORK
2220 if (!ServerCerts
) { LogMsg("ERROR: mDNSPlatformTCPAccept: unable to find TLS certificates"); err
= mStatus_UnknownErr
; goto exit
; }
2222 err
= tlsSetupSock(sock
, mDNStrue
);
2223 if (err
) { LogMsg("ERROR: mDNSPlatformTCPAccept: tlsSetupSock failed with error code: %d", err
); goto exit
; }
2225 err
= SSLSetCertificate(sock
->tlsContext
, ServerCerts
);
2226 if (err
) { LogMsg("ERROR: mDNSPlatformTCPAccept: SSLSetCertificate failed with error code: %d", err
); goto exit
; }
2228 err
= mStatus_UnsupportedErr
;
2229 #endif /* NO_SECURITYFRAMEWORK */
2231 #ifndef NO_SECURITYFRAMEWORK
2235 if (err
) { freeL("TCPSocket/mDNSPlatformTCPAccept", sock
); return(mDNSNULL
); }
2239 mDNSexport
void mDNSPlatformTCPCloseConnection(TCPSocket
*sock
)
2243 #ifndef NO_SECURITYFRAMEWORK
2244 if (sock
->tlsContext
)
2246 if (sock
->handshake
== handshake_in_progress
) // SSLHandshake thread using this sock (esp. tlsContext)
2248 LogInfo("mDNSPlatformTCPCloseConnection: called while handshake in progress");
2249 sock
->handshake
= handshake_to_be_closed
;
2251 if (sock
->handshake
== handshake_to_be_closed
)
2254 SSLClose(sock
->tlsContext
);
2255 SSLDisposeContext(sock
->tlsContext
);
2256 sock
->tlsContext
= NULL
;
2258 #endif /* NO_SECURITYFRAMEWORK */
2261 shutdown(sock
->fd
, 2);
2266 freeL("TCPSocket/mDNSPlatformTCPCloseConnection", sock
);
2270 mDNSexport
long mDNSPlatformReadTCP(TCPSocket
*sock
, void *buf
, unsigned long buflen
, mDNSBool
*closed
)
2273 *closed
= mDNSfalse
;
2275 if (sock
->flags
& kTCPSocketFlags_UseTLS
)
2277 #ifndef NO_SECURITYFRAMEWORK
2278 if (sock
->handshake
== handshake_required
) { LogMsg("mDNSPlatformReadTCP called while handshake required"); return 0; }
2279 else if (sock
->handshake
== handshake_in_progress
) return 0;
2280 else if (sock
->handshake
!= handshake_completed
) LogMsg("mDNSPlatformReadTCP called with unexpected SSLHandshake status: %d", sock
->handshake
);
2282 //LogMsg("Starting SSLRead %d %X", sock->fd, fcntl(sock->fd, F_GETFL, 0));
2283 mStatus err
= SSLRead(sock
->tlsContext
, buf
, buflen
, (size_t*)&nread
);
2284 //LogMsg("SSLRead returned %d (%d) nread %d buflen %d", err, errSSLWouldBlock, nread, buflen);
2285 if (err
== errSSLClosedGraceful
) { nread
= 0; *closed
= mDNStrue
; }
2286 else if (err
&& err
!= errSSLWouldBlock
)
2287 { LogMsg("ERROR: mDNSPlatformReadTCP - SSLRead: %d", err
); nread
= -1; *closed
= mDNStrue
; }
2291 #endif /* NO_SECURITYFRAMEWORK */
2295 static int CLOSEDcount
= 0;
2296 static int EAGAINcount
= 0;
2297 nread
= recv(sock
->fd
, buf
, buflen
, 0);
2299 if (nread
> 0) { CLOSEDcount
= 0; EAGAINcount
= 0; } // On success, clear our error counters
2300 else if (nread
== 0)
2303 if ((++CLOSEDcount
% 1000) == 0) { LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got CLOSED %d times", sock
->fd
, CLOSEDcount
); sleep(1); }
2305 // else nread is negative -- see what kind of error we got
2306 else if (errno
== ECONNRESET
) { nread
= 0; *closed
= mDNStrue
; }
2307 else if (errno
!= EAGAIN
) { LogMsg("ERROR: mDNSPlatformReadTCP - recv: %d (%s)", errno
, strerror(errno
)); nread
= -1; }
2308 else // errno is EAGAIN (EWOULDBLOCK) -- no data available
2311 if ((++EAGAINcount
% 1000) == 0) { LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got EAGAIN %d times", sock
->fd
, EAGAINcount
); sleep(1); }
2318 mDNSexport
long mDNSPlatformWriteTCP(TCPSocket
*sock
, const char *msg
, unsigned long len
)
2322 if (sock
->flags
& kTCPSocketFlags_UseTLS
)
2324 #ifndef NO_SECURITYFRAMEWORK
2326 if (sock
->handshake
== handshake_required
) { LogMsg("mDNSPlatformWriteTCP called while handshake required"); return 0; }
2327 if (sock
->handshake
== handshake_in_progress
) return 0;
2328 else if (sock
->handshake
!= handshake_completed
) LogMsg("mDNSPlatformWriteTCP called with unexpected SSLHandshake status: %d", sock
->handshake
);
2330 mStatus err
= SSLWrite(sock
->tlsContext
, msg
, len
, &processed
);
2332 if (!err
) nsent
= (int) processed
;
2333 else if (err
== errSSLWouldBlock
) nsent
= 0;
2334 else { LogMsg("ERROR: mDNSPlatformWriteTCP - SSLWrite returned %d", err
); nsent
= -1; }
2337 #endif /* NO_SECURITYFRAMEWORK */
2341 nsent
= send(sock
->fd
, msg
, len
, 0);
2344 if (errno
== EAGAIN
) nsent
= 0;
2345 else { LogMsg("ERROR: mDNSPlatformWriteTCP - send %s", strerror(errno
)); nsent
= -1; }
2352 mDNSexport
int mDNSPlatformTCPGetFD(TCPSocket
*sock
)
2357 // If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
2358 // If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
2359 mDNSlocal mStatus
SetupSocket(KQSocketSet
*cp
, const mDNSIPPort port
, u_short sa_family
, mDNSIPPort
*const outport
)
2361 int *s
= (sa_family
== AF_INET
) ? &cp
->sktv4
: &cp
->sktv6
;
2362 KQueueEntry
*k
= (sa_family
== AF_INET
) ? &cp
->kqsv4
: &cp
->kqsv6
;
2364 const int twofivefive
= 255;
2365 mStatus err
= mStatus_NoError
;
2366 char *errstr
= mDNSNULL
;
2368 cp
->closeFlag
= mDNSNULL
;
2370 int skt
= socket(sa_family
, SOCK_DGRAM
, IPPROTO_UDP
);
2371 if (skt
< 3) { if (errno
!= EAFNOSUPPORT
) LogMsg("SetupSocket: socket error %d errno %d (%s)", skt
, errno
, strerror(errno
)); return(skt
); }
2373 // ... with a shared UDP port, if it's for multicast receiving
2374 if (mDNSSameIPPort(port
, MulticastDNSPort
) || mDNSSameIPPort(port
, NATPMPAnnouncementPort
)) err
= setsockopt(skt
, SOL_SOCKET
, SO_REUSEPORT
, &on
, sizeof(on
));
2375 if (err
< 0) { errstr
= "setsockopt - SO_REUSEPORT"; goto fail
; }
2377 if (sa_family
== AF_INET
)
2379 // We want to receive destination addresses
2380 err
= setsockopt(skt
, IPPROTO_IP
, IP_RECVDSTADDR
, &on
, sizeof(on
));
2381 if (err
< 0) { errstr
= "setsockopt - IP_RECVDSTADDR"; goto fail
; }
2383 // We want to receive interface identifiers
2384 err
= setsockopt(skt
, IPPROTO_IP
, IP_RECVIF
, &on
, sizeof(on
));
2385 if (err
< 0) { errstr
= "setsockopt - IP_RECVIF"; goto fail
; }
2387 // We want to receive packet TTL value so we can check it
2388 err
= setsockopt(skt
, IPPROTO_IP
, IP_RECVTTL
, &on
, sizeof(on
));
2389 // We ignore errors here -- we already know Jaguar doesn't support this, but we can get by without it
2391 // Send unicast packets with TTL 255
2392 err
= setsockopt(skt
, IPPROTO_IP
, IP_TTL
, &twofivefive
, sizeof(twofivefive
));
2393 if (err
< 0) { errstr
= "setsockopt - IP_TTL"; goto fail
; }
2395 // And multicast packets with TTL 255 too
2396 err
= setsockopt(skt
, IPPROTO_IP
, IP_MULTICAST_TTL
, &twofivefive
, sizeof(twofivefive
));
2397 if (err
< 0) { errstr
= "setsockopt - IP_MULTICAST_TTL"; goto fail
; }
2399 // And start listening for packets
2400 struct sockaddr_in listening_sockaddr
;
2401 listening_sockaddr
.sin_family
= AF_INET
;
2402 listening_sockaddr
.sin_port
= port
.NotAnInteger
; // Pass in opaque ID without any byte swapping
2403 listening_sockaddr
.sin_addr
.s_addr
= mDNSSameIPPort(port
, NATPMPAnnouncementPort
) ? AllSystemsMcast
.NotAnInteger
: 0;
2404 err
= bind(skt
, (struct sockaddr
*) &listening_sockaddr
, sizeof(listening_sockaddr
));
2405 if (err
) { errstr
= "bind"; goto fail
; }
2406 if (outport
) outport
->NotAnInteger
= listening_sockaddr
.sin_port
;
2408 else if (sa_family
== AF_INET6
)
2410 // NAT-PMP Announcements make no sense on IPv6, so bail early w/o error
2411 if (mDNSSameIPPort(port
, NATPMPAnnouncementPort
)) { if (outport
) *outport
= zeroIPPort
; return mStatus_NoError
; }
2413 // We want to receive destination addresses and receive interface identifiers
2414 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_PKTINFO
, &on
, sizeof(on
));
2415 if (err
< 0) { errstr
= "setsockopt - IPV6_PKTINFO"; goto fail
; }
2417 // We want to receive packet hop count value so we can check it
2418 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_HOPLIMIT
, &on
, sizeof(on
));
2419 if (err
< 0) { errstr
= "setsockopt - IPV6_HOPLIMIT"; goto fail
; }
2421 // We want to receive only IPv6 packets. Without this option we get IPv4 packets too,
2422 // with mapped addresses of the form 0:0:0:0:0:FFFF:xxxx:xxxx, where xxxx:xxxx is the IPv4 address
2423 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_V6ONLY
, &on
, sizeof(on
));
2424 if (err
< 0) { errstr
= "setsockopt - IPV6_V6ONLY"; goto fail
; }
2426 // Send unicast packets with TTL 255
2427 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, &twofivefive
, sizeof(twofivefive
));
2428 if (err
< 0) { errstr
= "setsockopt - IPV6_UNICAST_HOPS"; goto fail
; }
2430 // And multicast packets with TTL 255 too
2431 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_MULTICAST_HOPS
, &twofivefive
, sizeof(twofivefive
));
2432 if (err
< 0) { errstr
= "setsockopt - IPV6_MULTICAST_HOPS"; goto fail
; }
2434 // Want to receive our own packets
2435 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_MULTICAST_LOOP
, &on
, sizeof(on
));
2436 if (err
< 0) { errstr
= "setsockopt - IPV6_MULTICAST_LOOP"; goto fail
; }
2438 // And start listening for packets
2439 struct sockaddr_in6 listening_sockaddr6
;
2440 mDNSPlatformMemZero(&listening_sockaddr6
, sizeof(listening_sockaddr6
));
2441 listening_sockaddr6
.sin6_len
= sizeof(listening_sockaddr6
);
2442 listening_sockaddr6
.sin6_family
= AF_INET6
;
2443 listening_sockaddr6
.sin6_port
= port
.NotAnInteger
; // Pass in opaque ID without any byte swapping
2444 listening_sockaddr6
.sin6_flowinfo
= 0;
2445 listening_sockaddr6
.sin6_addr
= in6addr_any
; // Want to receive multicasts AND unicasts on this socket
2446 listening_sockaddr6
.sin6_scope_id
= 0;
2447 err
= bind(skt
, (struct sockaddr
*) &listening_sockaddr6
, sizeof(listening_sockaddr6
));
2448 if (err
) { errstr
= "bind"; goto fail
; }
2449 if (outport
) outport
->NotAnInteger
= listening_sockaddr6
.sin6_port
;
2452 fcntl(skt
, F_SETFL
, fcntl(skt
, F_GETFL
, 0) | O_NONBLOCK
); // set non-blocking
2453 fcntl(skt
, F_SETFD
, 1); // set close-on-exec
2455 k
->KQcallback
= myKQSocketCallBack
;
2457 k
->KQtask
= "UDP packet reception";
2458 KQueueSet(*s
, EV_ADD
, EVFILT_READ
, k
);
2463 // For "bind" failures, only write log messages for our shared mDNS port, or for binding to zero
2464 if (strcmp(errstr
, "bind") || mDNSSameIPPort(port
, MulticastDNSPort
) || mDNSIPPortIsZero(port
))
2465 LogMsg("%s skt %d port %d error %d errno %d (%s)", errstr
, skt
, mDNSVal16(port
), err
, errno
, strerror(errno
));
2467 // If we got a "bind" failure of EADDRINUSE, inform the caller as it might need to try another random port
2468 if (!strcmp(errstr
, "bind") && errno
== EADDRINUSE
)
2471 if (mDNSSameIPPort(port
, MulticastDNSPort
))
2472 NotifyOfElusiveBug("Setsockopt SO_REUSEPORT failed",
2473 "Congratulations, you've reproduced an elusive bug.\r"
2474 "Please contact the current assignee of <rdar://problem/3814904>.\r"
2475 "Alternatively, you can send email to radar-3387020@group.apple.com. (Note number is different.)\r"
2476 "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
2483 mDNSexport UDPSocket
*mDNSPlatformUDPSocket(mDNS
*const m
, const mDNSIPPort requestedport
)
2486 mDNSIPPort port
= requestedport
;
2487 mDNSBool randomizePort
= mDNSIPPortIsZero(requestedport
);
2488 int i
= 10000; // Try at most 10000 times to get a unique random port
2489 UDPSocket
*p
= mallocL("UDPSocket", sizeof(UDPSocket
));
2490 if (!p
) { LogMsg("mDNSPlatformUDPSocket: memory exhausted"); return(mDNSNULL
); }
2491 mDNSPlatformMemZero(p
, sizeof(UDPSocket
));
2492 p
->ss
.port
= zeroIPPort
;
2499 // The kernel doesn't do cryptographically strong random port allocation, so we do it ourselves here
2500 if (randomizePort
) port
= mDNSOpaque16fromIntVal(0xC000 + mDNSRandom(0x3FFF));
2501 err
= SetupSocket(&p
->ss
, port
, AF_INET
, &p
->ss
.port
);
2504 err
= SetupSocket(&p
->ss
, port
, AF_INET6
, &p
->ss
.port
);
2505 if (err
) { close(p
->ss
.sktv4
); p
->ss
.sktv4
= -1; }
2508 } while (err
== EADDRINUSE
&& randomizePort
&& i
);
2512 // In customer builds we don't want to log failures with port 5351, because this is a known issue
2513 // of failing to bind to this port when Internet Sharing has already bound to it
2514 // We also don't want to log about port 5350, due to a known bug when some other
2515 // process is bound to it.
2516 if (mDNSSameIPPort(requestedport
, NATPMPPort
) || mDNSSameIPPort(requestedport
, NATPMPAnnouncementPort
))
2517 LogInfo("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport
), err
, errno
, strerror(errno
));
2518 else LogMsg("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport
), err
, errno
, strerror(errno
));
2519 freeL("UDPSocket", p
);
2525 mDNSlocal
void CloseSocketSet(KQSocketSet
*ss
)
2527 if (ss
->sktv4
!= -1)
2532 if (ss
->sktv6
!= -1)
2537 if (ss
->closeFlag
) *ss
->closeFlag
= 1;
2540 mDNSexport
void mDNSPlatformUDPClose(UDPSocket
*sock
)
2542 CloseSocketSet(&sock
->ss
);
2543 freeL("UDPSocket", sock
);
2546 #if COMPILER_LIKES_PRAGMA_MARK
2548 #pragma mark - BPF Raw packet sending/receiving
2551 #if APPLE_OSX_mDNSResponder
2553 mDNSexport
void mDNSPlatformSendRawPacket(const void *const msg
, const mDNSu8
*const end
, mDNSInterfaceID InterfaceID
)
2555 if (!InterfaceID
) { LogMsg("mDNSPlatformSendRawPacket: No InterfaceID specified"); return; }
2556 NetworkInterfaceInfoOSX
*info
= (NetworkInterfaceInfoOSX
*)InterfaceID
;
2557 if (info
->BPF_fd
< 0)
2558 LogMsg("mDNSPlatformSendRawPacket: %s BPF_fd %d not ready", info
->ifinfo
.ifname
, info
->BPF_fd
);
2561 //LogMsg("mDNSPlatformSendRawPacket %d bytes on %s", end - (mDNSu8 *)msg, info->ifinfo.ifname);
2562 if (write(info
->BPF_fd
, msg
, end
- (mDNSu8
*)msg
) < 0)
2563 LogMsg("mDNSPlatformSendRawPacket: BPF write(%d) failed %d (%s)", info
->BPF_fd
, errno
, strerror(errno
));
2567 mDNSexport
void mDNSPlatformSetLocalARP(const mDNSv4Addr
*const tpa
, const mDNSEthAddr
*const tha
, mDNSInterfaceID InterfaceID
)
2569 if (!InterfaceID
) { LogMsg("mDNSPlatformSetLocalARP: No InterfaceID specified"); return; }
2570 NetworkInterfaceInfoOSX
*info
= (NetworkInterfaceInfoOSX
*)InterfaceID
;
2571 // Manually inject an entry into our local ARP cache.
2572 // (We can't do this by sending an ARP broadcast, because the kernel only pays attention to incoming ARP packets, not outgoing.)
2573 mDNSBool makearp
= mDNSv4AddressIsLinkLocal(tpa
);
2576 NetworkInterfaceInfoOSX
*i
;
2577 for (i
= info
->m
->p
->InterfaceList
; i
; i
= i
->next
)
2578 if (i
->Exists
&& i
->ifinfo
.InterfaceID
== InterfaceID
&& i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
)
2579 if (((i
->ifinfo
.ip
.ip
.v4
.NotAnInteger
^ tpa
->NotAnInteger
) & i
->ifinfo
.mask
.ip
.v4
.NotAnInteger
) == 0)
2583 LogInfo("Don't need ARP entry for %s %.4a %.6a", info
->ifinfo
.ifname
, tpa
, tha
);
2586 int result
= mDNSSetARP(info
->scope_id
, tpa
->b
, tha
->b
);
2587 if (result
) LogMsg("Set local ARP entry for %s %.4a %.6a failed: %d", info
->ifinfo
.ifname
, tpa
, tha
, result
);
2588 else debugf ("Set local ARP entry for %s %.4a %.6a", info
->ifinfo
.ifname
, tpa
, tha
);
2592 mDNSlocal
void CloseBPF(NetworkInterfaceInfoOSX
*const i
)
2594 LogSPS("%s closing BPF fd %d", i
->ifinfo
.ifname
, i
->BPF_fd
);
2596 // Note: MUST NOT close() the underlying native BSD sockets.
2597 // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately, because
2598 // it first has to unhook the sockets from its select() call on its other thread, before it can safely close them.
2599 CFRunLoopRemoveSource(i
->m
->p
->CFRunLoop
, i
->BPF_rls
, kCFRunLoopDefaultMode
);
2600 CFRelease(i
->BPF_rls
);
2601 CFSocketInvalidate(i
->BPF_cfs
);
2602 CFRelease(i
->BPF_cfs
);
2606 mDNSlocal
void bpf_callback(const CFSocketRef cfs
, const CFSocketCallBackType CallBackType
, const CFDataRef address
, const void *const data
, void *const context
)
2613 NetworkInterfaceInfoOSX
*const info
= (NetworkInterfaceInfoOSX
*)context
;
2614 KQueueLock(info
->m
);
2616 // Now we've got the lock, make sure the kqueue thread didn't close the fd out from under us (will not be a problem once the OS X
2617 // kernel has a mechanism for dispatching all events to a single thread, but for now we have to guard against this race condition).
2618 if (info
->BPF_fd
< 0) goto exit
;
2620 ssize_t n
= read(info
->BPF_fd
, &info
->m
->imsg
, info
->BPF_len
);
2621 const mDNSu8
*ptr
= (const mDNSu8
*)&info
->m
->imsg
;
2622 const mDNSu8
*end
= (const mDNSu8
*)&info
->m
->imsg
+ n
;
2623 debugf("%3d: bpf_callback got %d bytes on %s", info
->BPF_fd
, n
, info
->ifinfo
.ifname
);
2627 LogMsg("Closing %s BPF fd %d due to error %d (%s)", info
->ifinfo
.ifname
, info
->BPF_fd
, errno
, strerror(errno
));
2634 const struct bpf_hdr
*bh
= (const struct bpf_hdr
*)ptr
;
2635 debugf("%3d: bpf_callback bh_caplen %4d bh_datalen %4d remaining %4d", info
->BPF_fd
, bh
->bh_caplen
, bh
->bh_datalen
, end
- (ptr
+ BPF_WORDALIGN(bh
->bh_hdrlen
+ bh
->bh_caplen
)));
2636 mDNSCoreReceiveRawPacket(info
->m
, ptr
+ bh
->bh_hdrlen
, ptr
+ bh
->bh_hdrlen
+ bh
->bh_caplen
, info
->ifinfo
.InterfaceID
);
2637 ptr
+= BPF_WORDALIGN(bh
->bh_hdrlen
+ bh
->bh_caplen
);
2640 KQueueUnlock(info
->m
, "bpf_callback");
2643 #define BPF_SetOffset(from, cond, to) (from)->cond = (to) - 1 - (from)
2645 mDNSlocal
int CountProxyTargets(mDNS
*const m
, NetworkInterfaceInfoOSX
*x
, int *p4
, int *p6
)
2647 int numv4
= 0, numv6
= 0;
2650 for (rr
= m
->ResourceRecords
; rr
; rr
=rr
->next
)
2651 if (rr
->resrec
.InterfaceID
== (mDNSInterfaceID
)x
&& rr
->AddressProxy
.type
== mDNSAddrType_IPv4
)
2653 if (p4
) LogSPS("mDNSPlatformUpdateProxyList: fd %d %-7s IP%2d %.4a", x
->BPF_fd
, x
->ifinfo
.ifname
, numv4
, &rr
->AddressProxy
.ip
.v4
);
2657 for (rr
= m
->ResourceRecords
; rr
; rr
=rr
->next
)
2658 if (rr
->resrec
.InterfaceID
== (mDNSInterfaceID
)x
&& rr
->AddressProxy
.type
== mDNSAddrType_IPv6
)
2660 if (p6
) LogSPS("mDNSPlatformUpdateProxyList: fd %d %-7s IP%2d %.16a", x
->BPF_fd
, x
->ifinfo
.ifname
, numv6
, &rr
->AddressProxy
.ip
.v6
);
2664 if (p4
) *p4
= numv4
;
2665 if (p6
) *p6
= numv6
;
2666 return(numv4
+ numv6
);
2669 mDNSexport
void mDNSPlatformUpdateProxyList(mDNS
*const m
, const mDNSInterfaceID InterfaceID
)
2671 NetworkInterfaceInfoOSX
*x
;
2672 for (x
= m
->p
->InterfaceList
; x
; x
= x
->next
) if (x
== (NetworkInterfaceInfoOSX
*)InterfaceID
) break;
2673 if (!x
) { LogMsg("mDNSPlatformUpdateProxyList: ERROR InterfaceID %p not found", InterfaceID
); return; }
2675 #define MAX_BPF_ADDRS 250
2676 int numv4
= 0, numv6
= 0;
2678 if (CountProxyTargets(m
, x
, &numv4
, &numv6
) > MAX_BPF_ADDRS
)
2680 LogMsg("mDNSPlatformUpdateProxyList: ERROR Too many address proxy records v4 %d v6 %d", numv4
, numv6
);
2681 if (numv4
> MAX_BPF_ADDRS
) numv4
= MAX_BPF_ADDRS
;
2682 numv6
= MAX_BPF_ADDRS
- numv4
;
2685 LogSPS("mDNSPlatformUpdateProxyList: fd %d %-7s MAC %.6a %d v4 %d v6", x
->BPF_fd
, x
->ifinfo
.ifname
, &x
->ifinfo
.MAC
, numv4
, numv6
);
2687 // Caution: This is a static structure, so we need to be careful that any modifications we make to it
2688 // are done in such a way that they work correctly when mDNSPlatformUpdateProxyList is called multiple times
2689 static struct bpf_insn filter
[17 + MAX_BPF_ADDRS
] =
2691 BPF_STMT(BPF_LD
+ BPF_H
+ BPF_ABS
, 12), // 0 Read Ethertype (bytes 12,13)
2693 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, 0x0806, 0, 1), // 1 If Ethertype == ARP goto next, else 3
2694 BPF_STMT(BPF_RET
+ BPF_K
, 42), // 2 Return 42-byte ARP
2696 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, 0x0800, 4, 0), // 3 If Ethertype == IPv4 goto 8 (IPv4 address list check) else next
2698 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, 0x86DD, 0, 9), // 4 If Ethertype == IPv6 goto next, else exit
2699 BPF_STMT(BPF_LD
+ BPF_H
+ BPF_ABS
, 20), // 5 Read Protocol and Hop Limit (bytes 20,21)
2700 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, 0x3AFF, 0, 9), // 6 If (Prot,TTL) == (3A,FF) goto next, else IPv6 address list check
2701 BPF_STMT(BPF_RET
+ BPF_K
, 78), // 7 Return 78-byte ND
2703 // Is IPv4 packet; check if it's addressed to any IPv4 address we're proxying for
2704 BPF_STMT(BPF_LD
+ BPF_W
+ BPF_ABS
, 30), // 8 Read IPv4 Dst (bytes 30,31,32,33)
2707 struct bpf_insn
*pc
= &filter
[9];
2708 struct bpf_insn
*chk6
= pc
+ numv4
+ 1; // numv4 address checks, plus a "return 0"
2709 struct bpf_insn
*fail
= chk6
+ 1 + numv6
; // Get v6 Dst LSW, plus numv6 address checks
2710 struct bpf_insn
*ret4
= fail
+ 1;
2711 struct bpf_insn
*ret6
= ret4
+ 4;
2713 static const struct bpf_insn rf
= BPF_STMT(BPF_RET
+ BPF_K
, 0); // No match: Return nothing
2715 static const struct bpf_insn g6
= BPF_STMT(BPF_LD
+ BPF_W
+ BPF_ABS
, 50); // Read IPv6 Dst LSW (bytes 50,51,52,53)
2717 static const struct bpf_insn r4a
= BPF_STMT(BPF_LDX
+ BPF_B
+ BPF_MSH
, 14); // Get IP Header length (normally 20)
2718 static const struct bpf_insn r4b
= BPF_STMT(BPF_LD
+ BPF_IMM
, 34); // A = 34 (14-byte Ethernet plus 20-byte TCP)
2719 static const struct bpf_insn r4c
= BPF_STMT(BPF_ALU
+ BPF_ADD
+ BPF_X
, 0); // A += IP Header length
2720 static const struct bpf_insn r4d
= BPF_STMT(BPF_RET
+ BPF_A
, 0); // Success: Return Ethernet + IP + TCP
2722 static const struct bpf_insn r6a
= BPF_STMT(BPF_RET
+ BPF_K
, 94); // Success: Return Eth + IPv6 + TCP + 20 bytes spare
2724 BPF_SetOffset(&filter
[4], jf
, fail
); // If Ethertype not ARP, IPv4, or IPv6, fail
2725 BPF_SetOffset(&filter
[6], jf
, chk6
); // If IPv6 but not ICMPv6, go to IPv6 address list check
2727 // BPF Byte-Order Note
2728 // The BPF API designers apparently thought that programmers would not be smart enough to use htons
2729 // and htonl correctly to convert numeric values to network byte order on little-endian machines,
2730 // so instead they chose to make the API implicitly byte-swap *ALL* values, even literal byte strings
2731 // that shouldn't be byte-swapped, like ASCII text, Ethernet addresses, IP addresses, etc.
2732 // As a result, if we put Ethernet addresses and IP addresses in the right byte order, the BPF API
2733 // will byte-swap and make them backwards, and then our filter won't work. So, we have to arrange
2734 // that on little-endian machines we deliberately put addresses in memory with the bytes backwards,
2735 // so that when the BPF API goes through and swaps them all, they end up back as they should be.
2736 // In summary, if we byte-swap all the non-numeric fields that shouldn't be swapped, and we *don't*
2737 // swap any of the numeric values that *should* be byte-swapped, then the filter will work correctly.
2740 for (rr
= m
->ResourceRecords
; rr
; rr
=rr
->next
)
2741 if (rr
->resrec
.InterfaceID
== InterfaceID
&& rr
->AddressProxy
.type
== mDNSAddrType_IPv4
)
2743 mDNSv4Addr a
= rr
->AddressProxy
.ip
.v4
;
2744 pc
->code
= BPF_JMP
+ BPF_JEQ
+ BPF_K
;
2745 BPF_SetOffset(pc
, jt
, ret4
);
2747 pc
->k
= (bpf_u_int32
)a
.b
[0] << 24 | (bpf_u_int32
)a
.b
[1] << 16 | (bpf_u_int32
)a
.b
[2] << 8 | (bpf_u_int32
)a
.b
[3];
2752 if (pc
!= chk6
) LogMsg("mDNSPlatformUpdateProxyList: pc %p != chk6 %p", pc
, chk6
);
2753 *pc
++ = g6
; // chk6 points here
2755 for (rr
= m
->ResourceRecords
; rr
; rr
=rr
->next
)
2756 if (rr
->resrec
.InterfaceID
== InterfaceID
&& rr
->AddressProxy
.type
== mDNSAddrType_IPv6
)
2758 mDNSv6Addr a
= rr
->AddressProxy
.ip
.v6
;
2759 pc
->code
= BPF_JMP
+ BPF_JEQ
+ BPF_K
;
2760 BPF_SetOffset(pc
, jt
, ret6
);
2762 pc
->k
= (bpf_u_int32
)a
.b
[12] << 24 | (bpf_u_int32
)a
.b
[13] << 16 | (bpf_u_int32
)a
.b
[14] << 8 | (bpf_u_int32
)a
.b
[15];
2766 if (pc
!= fail
) LogMsg("mDNSPlatformUpdateProxyList: pc %p != fail %p", pc
, fail
);
2767 *pc
++ = rf
; // fail points here
2769 if (pc
!= ret4
) LogMsg("mDNSPlatformUpdateProxyList: pc %p != ret4 %p", pc
, ret4
);
2770 *pc
++ = r4a
; // ret4 points here
2775 if (pc
!= ret6
) LogMsg("mDNSPlatformUpdateProxyList: pc %p != ret6 %p", pc
, ret6
);
2776 *pc
++ = r6a
; // ret6 points here
2778 struct bpf_program prog
= { pc
- filter
, filter
};
2781 // For debugging BPF filter program
2783 for (q
=0; q
<prog
.bf_len
; q
++)
2784 LogSPS("mDNSPlatformUpdateProxyList: %2d { 0x%02x, %d, %d, 0x%08x },", q
, prog
.bf_insns
[q
].code
, prog
.bf_insns
[q
].jt
, prog
.bf_insns
[q
].jf
, prog
.bf_insns
[q
].k
);
2787 if (!numv4
&& !numv6
)
2789 LogSPS("mDNSPlatformUpdateProxyList: No need for filter");
2790 if (m
->timenow
== 0) LogMsg("mDNSPlatformUpdateProxyList: m->timenow == 0");
2791 // Schedule check to see if we can close this BPF_fd now
2792 if (!m
->p
->NetworkChanged
) m
->p
->NetworkChanged
= NonZeroTime(m
->timenow
+ mDNSPlatformOneSecond
* 2);
2793 // prog.bf_len = 0; This seems to panic the kernel
2796 if (ioctl(x
->BPF_fd
, BIOCSETF
, &prog
) < 0) LogMsg("mDNSPlatformUpdateProxyList: BIOCSETF(%d) failed %d (%s)", prog
.bf_len
, errno
, strerror(errno
));
2797 else LogSPS("mDNSPlatformUpdateProxyList: BIOCSETF(%d) successful", prog
.bf_len
);
2800 mDNSexport
void mDNSPlatformReceiveBPF_fd(mDNS
*const m
, int fd
)
2804 NetworkInterfaceInfoOSX
*i
;
2805 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
) if (i
->BPF_fd
== -2) break;
2806 if (!i
) { LogSPS("mDNSPlatformReceiveBPF_fd: No Interfaces awaiting BPF fd %d; closing", fd
); close(fd
); }
2809 LogSPS("%s using BPF fd %d", i
->ifinfo
.ifname
, fd
);
2811 struct bpf_version v
;
2812 if (ioctl(fd
, BIOCVERSION
, &v
) < 0)
2813 LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCVERSION failed %d (%s)", fd
, i
->ifinfo
.ifname
, errno
, strerror(errno
));
2814 else if (BPF_MAJOR_VERSION
!= v
.bv_major
|| BPF_MINOR_VERSION
!= v
.bv_minor
)
2815 LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCVERSION header %d.%d kernel %d.%d",
2816 fd
, i
->ifinfo
.ifname
, BPF_MAJOR_VERSION
, BPF_MINOR_VERSION
, v
.bv_major
, v
.bv_minor
);
2818 if (ioctl(fd
, BIOCGBLEN
, &i
->BPF_len
) < 0)
2819 LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCGBLEN failed %d (%s)", fd
, i
->ifinfo
.ifname
, errno
, strerror(errno
));
2821 if (i
->BPF_len
> sizeof(m
->imsg
))
2823 i
->BPF_len
= sizeof(m
->imsg
);
2824 if (ioctl(fd
, BIOCSBLEN
, &i
->BPF_len
) < 0)
2825 LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCSBLEN failed %d (%s)", fd
, i
->ifinfo
.ifname
, errno
, strerror(errno
));
2826 else LogSPS("mDNSPlatformReceiveBPF_fd: %d %s BIOCSBLEN %d", i
->BPF_len
);
2829 static const u_int opt_immediate
= 1;
2830 if (ioctl(fd
, BIOCIMMEDIATE
, &opt_immediate
) < 0)
2831 LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCIMMEDIATE failed %d (%s)", fd
, i
->ifinfo
.ifname
, errno
, strerror(errno
));
2834 mDNSPlatformMemZero(&ifr
, sizeof(ifr
));
2835 strlcpy(ifr
.ifr_name
, i
->ifinfo
.ifname
, sizeof(ifr
.ifr_name
));
2836 if (ioctl(fd
, BIOCSETIF
, &ifr
) < 0)
2837 { LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCSETIF failed %d (%s)", fd
, i
->ifinfo
.ifname
, errno
, strerror(errno
)); i
->BPF_fd
= -3; }
2840 CFSocketContext myCFSocketContext
= { 0, i
, NULL
, NULL
, NULL
};
2842 i
->BPF_cfs
= CFSocketCreateWithNative(kCFAllocatorDefault
, fd
, kCFSocketReadCallBack
, bpf_callback
, &myCFSocketContext
);
2843 i
->BPF_rls
= CFSocketCreateRunLoopSource(kCFAllocatorDefault
, i
->BPF_cfs
, 0);
2844 CFRunLoopAddSource(i
->m
->p
->CFRunLoop
, i
->BPF_rls
, kCFRunLoopDefaultMode
);
2845 mDNSPlatformUpdateProxyList(m
, (mDNSInterfaceID
)i
);
2852 #endif // APPLE_OSX_mDNSResponder
2854 #if COMPILER_LIKES_PRAGMA_MARK
2856 #pragma mark - Key Management
2859 #ifndef NO_SECURITYFRAMEWORK
2860 mDNSlocal CFArrayRef
GetCertChain(SecIdentityRef identity
)
2862 CFMutableArrayRef certChain
= NULL
;
2863 if (!identity
) { LogMsg("getCertChain: identity is NULL"); return(NULL
); }
2864 SecCertificateRef cert
;
2865 OSStatus err
= SecIdentityCopyCertificate(identity
, &cert
);
2866 if (err
|| !cert
) LogMsg("getCertChain: SecIdentityCopyCertificate() returned %d", (int) err
);
2869 SecPolicySearchRef searchRef
;
2870 err
= SecPolicySearchCreate(CSSM_CERT_X_509v3
, &CSSMOID_APPLE_X509_BASIC
, NULL
, &searchRef
);
2871 if (err
|| !searchRef
) LogMsg("getCertChain: SecPolicySearchCreate() returned %d", (int) err
);
2874 SecPolicyRef policy
;
2875 err
= SecPolicySearchCopyNext(searchRef
, &policy
);
2876 if (err
|| !policy
) LogMsg("getCertChain: SecPolicySearchCopyNext() returned %d", (int) err
);
2879 CFArrayRef wrappedCert
= CFArrayCreate(NULL
, (const void**) &cert
, 1, &kCFTypeArrayCallBacks
);
2880 if (!wrappedCert
) LogMsg("getCertChain: wrappedCert is NULL");
2884 err
= SecTrustCreateWithCertificates(wrappedCert
, policy
, &trust
);
2885 if (err
|| !trust
) LogMsg("getCertChain: SecTrustCreateWithCertificates() returned %d", (int) err
);
2888 err
= SecTrustEvaluate(trust
, NULL
);
2889 if (err
) LogMsg("getCertChain: SecTrustEvaluate() returned %d", (int) err
);
2892 CFArrayRef rawCertChain
;
2893 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
= NULL
;
2894 err
= SecTrustGetResult(trust
, NULL
, &rawCertChain
, &statusChain
);
2895 if (err
|| !rawCertChain
|| !statusChain
) LogMsg("getCertChain: SecTrustGetResult() returned %d", (int) err
);
2898 certChain
= CFArrayCreateMutableCopy(NULL
, 0, rawCertChain
);
2899 if (!certChain
) LogMsg("getCertChain: certChain is NULL");
2902 // Replace the SecCertificateRef at certChain[0] with a SecIdentityRef per documentation for SSLSetCertificate:
2903 // <http://devworld.apple.com/documentation/Security/Reference/secureTransportRef/index.html>
2904 CFArraySetValueAtIndex(certChain
, 0, identity
);
2905 // Remove root from cert chain, but keep any and all intermediate certificates that have been signed by the root certificate
2906 if (CFArrayGetCount(certChain
) > 1) CFArrayRemoveValueAtIndex(certChain
, CFArrayGetCount(certChain
) - 1);
2908 CFRelease(rawCertChain
);
2909 // Do not free statusChain:
2910 // <http://developer.apple.com/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html> says:
2911 // certChain: Call the CFRelease function to release this object when you are finished with it.
2912 // statusChain: Do not attempt to free this pointer; it remains valid until the trust management object is released...
2917 CFRelease(wrappedCert
);
2921 CFRelease(searchRef
);
2927 #endif /* NO_SECURITYFRAMEWORK */
2929 mDNSexport mStatus
mDNSPlatformTLSSetupCerts(void)
2931 #ifdef NO_SECURITYFRAMEWORK
2932 return mStatus_UnsupportedErr
;
2934 SecIdentityRef identity
= nil
;
2935 SecIdentitySearchRef srchRef
= nil
;
2938 // search for "any" identity matching specified key use
2939 // In this app, we expect there to be exactly one
2940 err
= SecIdentitySearchCreate(NULL
, CSSM_KEYUSE_DECRYPT
, &srchRef
);
2941 if (err
) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCreate returned %d", (int) err
); return err
; }
2943 err
= SecIdentitySearchCopyNext(srchRef
, &identity
);
2944 if (err
) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext returned %d", (int) err
); return err
; }
2946 if (CFGetTypeID(identity
) != SecIdentityGetTypeID())
2947 { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext CFTypeID failure"); return mStatus_UnknownErr
; }
2949 // Found one. Call getCertChain to create the correct certificate chain.
2950 ServerCerts
= GetCertChain(identity
);
2951 if (ServerCerts
== nil
) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: getCertChain error"); return mStatus_UnknownErr
; }
2953 return mStatus_NoError
;
2954 #endif /* NO_SECURITYFRAMEWORK */
2957 mDNSexport
void mDNSPlatformTLSTearDownCerts(void)
2959 #ifndef NO_SECURITYFRAMEWORK
2960 if (ServerCerts
) { CFRelease(ServerCerts
); ServerCerts
= NULL
; }
2961 #endif /* NO_SECURITYFRAMEWORK */
2964 // This gets the text of the field currently labelled "Computer Name" in the Sharing Prefs Control Panel
2965 mDNSlocal
void GetUserSpecifiedFriendlyComputerName(domainlabel
*const namelabel
)
2967 CFStringEncoding encoding
= kCFStringEncodingUTF8
;
2968 CFStringRef cfs
= SCDynamicStoreCopyComputerName(NULL
, &encoding
);
2971 CFStringGetPascalString(cfs
, namelabel
->c
, sizeof(*namelabel
), kCFStringEncodingUTF8
);
2976 // This gets the text of the field currently labelled "Local Hostname" in the Sharing Prefs Control Panel
2977 mDNSlocal
void GetUserSpecifiedLocalHostName(domainlabel
*const namelabel
)
2979 CFStringRef cfs
= SCDynamicStoreCopyLocalHostName(NULL
);
2982 CFStringGetPascalString(cfs
, namelabel
->c
, sizeof(*namelabel
), kCFStringEncodingUTF8
);
2987 mDNSexport mDNSBool
DictionaryIsEnabled(CFDictionaryRef dict
)
2990 CFNumberRef state
= CFDictionaryGetValue(dict
, CFSTR("Enabled"));
2991 if (!state
) return mDNSfalse
;
2992 if (!CFNumberGetValue(state
, kCFNumberSInt32Type
, &val
))
2993 { LogMsg("ERROR: DictionaryIsEnabled - CFNumberGetValue"); return mDNSfalse
; }
2994 return val
? mDNStrue
: mDNSfalse
;
2997 mDNSlocal mStatus
SetupAddr(mDNSAddr
*ip
, const struct sockaddr
*const sa
)
2999 if (!sa
) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid
); }
3001 if (sa
->sa_family
== AF_INET
)
3003 struct sockaddr_in
*ifa_addr
= (struct sockaddr_in
*)sa
;
3004 ip
->type
= mDNSAddrType_IPv4
;
3005 ip
->ip
.v4
.NotAnInteger
= ifa_addr
->sin_addr
.s_addr
;
3006 return(mStatus_NoError
);
3009 if (sa
->sa_family
== AF_INET6
)
3011 struct sockaddr_in6
*ifa_addr
= (struct sockaddr_in6
*)sa
;
3012 // Inside the BSD kernel they use a hack where they stuff the sin6->sin6_scope_id
3013 // value into the second word of the IPv6 link-local address, so they can just
3014 // pass around IPv6 address structures instead of full sockaddr_in6 structures.
3015 // Those hacked IPv6 addresses aren't supposed to escape the kernel in that form, but they do.
3016 // To work around this we always whack the second word of any IPv6 link-local address back to zero.
3017 if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr
->sin6_addr
)) ifa_addr
->sin6_addr
.__u6_addr
.__u6_addr16
[1] = 0;
3018 ip
->type
= mDNSAddrType_IPv6
;
3019 ip
->ip
.v6
= *(mDNSv6Addr
*)&ifa_addr
->sin6_addr
;
3020 return(mStatus_NoError
);
3023 LogMsg("SetupAddr invalid sa_family %d", sa
->sa_family
);
3024 return(mStatus_Invalid
);
3027 mDNSlocal mDNSEthAddr
GetBSSID(char *ifa_name
)
3029 mDNSEthAddr eth
= zeroEthAddr
;
3030 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:GetBSSID"), NULL
, NULL
);
3032 LogMsg("GetBSSID: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
3035 CFStringRef entityname
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("State:/Network/Interface/%s/AirPort"), ifa_name
);
3038 CFDictionaryRef dict
= SCDynamicStoreCopyValue(store
, entityname
);
3041 CFRange range
= { 0, 6 }; // Offset, length
3042 CFDataRef data
= CFDictionaryGetValue(dict
, CFSTR("BSSID"));
3043 if (data
&& CFDataGetLength(data
) == 6) CFDataGetBytes(data
, range
, eth
.b
);
3046 CFRelease(entityname
);
3053 mDNSlocal
int GetMAC(mDNSEthAddr
*eth
, u_short ifindex
)
3055 struct ifaddrs
*ifa
;
3056 for (ifa
= myGetIfAddrs(0); ifa
; ifa
= ifa
->ifa_next
)
3057 if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
3059 const struct sockaddr_dl
*const sdl
= (const struct sockaddr_dl
*)ifa
->ifa_addr
;
3060 if (sdl
->sdl_index
== ifindex
)
3061 { mDNSPlatformMemCopy(eth
->b
, sdl
->sdl_data
+ sdl
->sdl_nlen
, 6); return 0; }
3067 #ifndef SIOCGIFWAKEFLAGS
3068 #define SIOCGIFWAKEFLAGS _IOWR('i', 136, struct ifreq) /* get interface wake property flags */
3071 #ifndef IF_WAKE_ON_MAGIC_PACKET
3072 #define IF_WAKE_ON_MAGIC_PACKET 0x01
3075 #ifndef ifr_wake_flags
3076 #define ifr_wake_flags ifr_ifru.ifru_intval
3079 mDNSlocal mDNSBool
NetWakeInterface(NetworkInterfaceInfoOSX
*i
)
3081 if (!MulticastInterface(i
) ) return(mDNSfalse
); // We only use Sleep Proxy Service on multicast-capable interfaces
3082 if (i
->ifa_flags
& IFF_LOOPBACK
) return(mDNSfalse
); // except loopback
3084 int s
= socket(AF_INET
, SOCK_DGRAM
, 0);
3085 if (s
< 0) { LogMsg("NetWakeInterface %s socket failed %s errno %d (%s)", i
->ifinfo
.ifname
, errno
, strerror(errno
)); return(mDNSfalse
); }
3088 strlcpy(ifr
.ifr_name
, i
->ifinfo
.ifname
, sizeof(ifr
.ifr_name
));
3089 if (ioctl(s
, SIOCGIFWAKEFLAGS
, &ifr
) < 0)
3091 // For some strange reason, in /usr/include/sys/errno.h, EOPNOTSUPP is defined to be
3092 // 102 when compiling kernel code, and 45 when compiling user-level code. Since this
3093 // error code is being returned from the kernel, we need to use the kernel version.
3094 #define KERNEL_EOPNOTSUPP 102
3095 if (errno
!= KERNEL_EOPNOTSUPP
) // "Operation not supported on socket", the expected result on Leopard and earlier
3096 LogMsg("NetWakeInterface SIOCGIFWAKEFLAGS %s errno %d (%s)", i
->ifinfo
.ifname
, errno
, strerror(errno
));
3097 // If on Leopard or earlier, we get EOPNOTSUPP, so in that case
3098 // we enable WOL if this interface is not AirPort and "Wake for Network access" is turned on.
3099 ifr
.ifr_wake_flags
= (errno
== KERNEL_EOPNOTSUPP
&& !(i
)->BSSID
.l
[0] && i
->m
->SystemWakeOnLANEnabled
) ? IF_WAKE_ON_MAGIC_PACKET
: 0;
3101 #if ASSUME_SNOWLEOPARD_INCORRECTLY_REPORTS_AIRPORT_INCAPABLE_OF_WAKE_ON_LAN
3105 // However, on SnowLeopard, it currently indicates incorrectly that AirPort is incapable of Wake-on-LAN.
3106 // Therefore, for AirPort interfaces, we just track the system-wide Wake-on-LAN setting.
3107 if ((i
)->BSSID
.l
[0]) ifr
.ifr_wake_flags
= i
->m
->SystemWakeOnLANEnabled
? IF_WAKE_ON_MAGIC_PACKET
: 0;
3113 // ifr.ifr_wake_flags = IF_WAKE_ON_MAGIC_PACKET; // For testing with MacBook Air, using a USB dongle that doesn't actually support Wake-On-LAN
3115 LogSPS("%-6s %#-14a %s WOMP", i
->ifinfo
.ifname
, &i
->ifinfo
.ip
, (ifr
.ifr_wake_flags
& IF_WAKE_ON_MAGIC_PACKET
) ? "supports" : "no");
3117 return((ifr
.ifr_wake_flags
& IF_WAKE_ON_MAGIC_PACKET
) != 0);
3120 // Returns pointer to newly created NetworkInterfaceInfoOSX object, or
3121 // pointer to already-existing NetworkInterfaceInfoOSX object found in list, or
3122 // may return NULL if out of memory (unlikely) or parameters are invalid for some reason
3123 // (e.g. sa_family not AF_INET or AF_INET6)
3124 mDNSlocal NetworkInterfaceInfoOSX
*AddInterfaceToList(mDNS
*const m
, struct ifaddrs
*ifa
, mDNSs32 utc
)
3126 mDNSu32 scope_id
= if_nametoindex(ifa
->ifa_name
);
3127 mDNSEthAddr bssid
= GetBSSID(ifa
->ifa_name
);
3130 if (SetupAddr(&ip
, ifa
->ifa_addr
) != mStatus_NoError
) return(NULL
);
3131 if (SetupAddr(&mask
, ifa
->ifa_netmask
) != mStatus_NoError
) return(NULL
);
3133 NetworkInterfaceInfoOSX
**p
;
3134 for (p
= &m
->p
->InterfaceList
; *p
; p
= &(*p
)->next
)
3135 if (scope_id
== (*p
)->scope_id
&&
3136 mDNSSameAddress(&ip
, &(*p
)->ifinfo
.ip
) &&
3137 mDNSSameEthAddress(&bssid
, &(*p
)->BSSID
))
3139 debugf("AddInterfaceToList: Found existing interface %lu %.6a with address %#a at %p", scope_id
, &bssid
, &ip
, *p
);
3140 (*p
)->Exists
= mDNStrue
;
3141 // If interface was not in getifaddrs list last time we looked, but it is now, update 'AppearanceTime' for this record
3142 if ((*p
)->LastSeen
!= utc
) (*p
)->AppearanceTime
= utc
;
3144 // If Wake-on-LAN capability of this interface has changed (e.g. because power cable on laptop has been disconnected)
3145 // we may need to start or stop or sleep proxy browse operation
3146 const mDNSBool NetWake
= NetWakeInterface(*p
);
3147 if ((*p
)->ifinfo
.NetWake
!= NetWake
)
3149 (*p
)->ifinfo
.NetWake
= NetWake
;
3150 // If this interface is already registered with mDNSCore, then we need to start or stop its NetWake browse on-the-fly.
3151 // If this interface is not already registered (i.e. it's a dormant interface we had in our list
3152 // from when we previously saw it) then we mustn't do that, because mDNSCore doesn't know about it yet.
3153 // In this case, the mDNS_RegisterInterface() call will take care of starting the NetWake browse if necessary.
3154 if ((*p
)->ifinfo
.InterfaceID
)
3157 if (NetWake
) mDNS_ActivateNetWake_internal (m
, &(*p
)->ifinfo
);
3158 else mDNS_DeactivateNetWake_internal(m
, &(*p
)->ifinfo
);
3166 NetworkInterfaceInfoOSX
*i
= (NetworkInterfaceInfoOSX
*)mallocL("NetworkInterfaceInfoOSX", sizeof(*i
));
3167 debugf("AddInterfaceToList: Making new interface %lu %.6a with address %#a at %p", scope_id
, &bssid
, &ip
, i
);
3168 if (!i
) return(mDNSNULL
);
3169 mDNSPlatformMemZero(i
, sizeof(NetworkInterfaceInfoOSX
));
3170 i
->ifinfo
.InterfaceID
= mDNSNULL
;
3172 i
->ifinfo
.mask
= mask
;
3173 strlcpy(i
->ifinfo
.ifname
, ifa
->ifa_name
, sizeof(i
->ifinfo
.ifname
));
3174 i
->ifinfo
.ifname
[sizeof(i
->ifinfo
.ifname
)-1] = 0;
3175 // We can be configured to disable multicast advertisement, but we want to to support
3176 // local-only services, which need a loopback address record.
3177 i
->ifinfo
.Advertise
= m
->DivertMulticastAdvertisements
? ((ifa
->ifa_flags
& IFF_LOOPBACK
) ? mDNStrue
: mDNSfalse
) : m
->AdvertiseLocalAddresses
;
3178 i
->ifinfo
.McastTxRx
= mDNSfalse
; // For now; will be set up later at the end of UpdateInterfaceList
3182 i
->Exists
= mDNStrue
;
3183 i
->Flashing
= mDNSfalse
;
3184 i
->Occulting
= mDNSfalse
;
3185 i
->AppearanceTime
= utc
; // Brand new interface; AppearanceTime is now
3187 i
->ifa_flags
= ifa
->ifa_flags
;
3188 i
->scope_id
= scope_id
;
3190 i
->sa_family
= ifa
->ifa_addr
->sa_family
;
3194 // Do this AFTER i->BSSID has been set up
3195 i
->ifinfo
.NetWake
= NetWakeInterface(i
);
3196 GetMAC(&i
->ifinfo
.MAC
, scope_id
);
3197 if (i
->ifinfo
.NetWake
&& !i
->ifinfo
.MAC
.l
[0])
3198 LogMsg("AddInterfaceToList: Bad MAC address %.6a for %d %s %#a", &i
->ifinfo
.MAC
, scope_id
, i
->ifinfo
.ifname
, &ip
);
3204 #if USE_V6_ONLY_WHEN_NO_ROUTABLE_V4
3205 mDNSlocal NetworkInterfaceInfoOSX
*FindRoutableIPv4(mDNS
*const m
, mDNSu32 scope_id
)
3207 NetworkInterfaceInfoOSX
*i
;
3208 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
3209 if (i
->Exists
&& i
->scope_id
== scope_id
&& i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
)
3210 if (!mDNSv4AddressIsLinkLocal(&i
->ifinfo
.ip
.ip
.v4
))
3216 #if APPLE_OSX_mDNSResponder
3218 #if COMPILER_LIKES_PRAGMA_MARK
3220 #pragma mark - AutoTunnel
3223 #define kRacoonPort 4500
3225 static DomainAuthInfo
* AnonymousRacoonConfig
= mDNSNULL
;
3227 #ifndef NO_SECURITYFRAMEWORK
3229 static CFMutableDictionaryRef domainStatusDict
= NULL
;
3231 // MUST be called with lock held
3232 mDNSlocal
void RemoveAutoTunnelDomainStatus(const mDNS
*const m
, const DomainAuthInfo
*const info
)
3237 LogInfo("RemoveAutoTunnelDomainStatus: %##s", info
->domain
.c
);
3239 if (!domainStatusDict
) { LogMsg("RemoveAutoTunnelDomainStatus: No domainStatusDict"); return; }
3241 buffer
[mDNS_snprintf(buffer
, sizeof(buffer
), "%##s", info
->domain
.c
) - 1] = 0;
3242 domain
= CFStringCreateWithCString(NULL
, buffer
, kCFStringEncodingUTF8
);
3243 if (!domain
) { LogMsg("RemoveAutoTunnelDomainStatus: Could not create CFString domain"); return; }
3245 if (CFDictionaryContainsKey(domainStatusDict
, domain
))
3247 CFDictionaryRemoveValue(domainStatusDict
, domain
);
3248 if (!m
->ShutdownTime
) mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig
, mDNSNULL
, domainStatusDict
);
3253 #endif // ndef NO_SECURITYFRAMEWORK
3255 mDNSlocal mStatus
CheckQuestionForStatus(const DNSQuestion
*const q
)
3259 if (q
->nta
|| (q
->servAddr
.type
== mDNSAddrType_IPv4
&& mDNSIPv4AddressIsOnes(q
->servAddr
.ip
.v4
)))
3260 return mStatus_NoSuchRecord
;
3261 else if (q
->state
== LLQ_Poll
)
3262 return mStatus_PollingMode
;
3263 else if (q
->state
!= LLQ_Established
&& !q
->DuplicateOf
)
3264 return mStatus_TransientErr
;
3267 return mStatus_NoError
;
3270 // MUST be called with lock held
3271 mDNSlocal
void UpdateAutoTunnelDomainStatus(const mDNS
*const m
, const DomainAuthInfo
*const info
)
3273 #ifdef NO_SECURITYFRAMEWORK
3277 const NATTraversalInfo
*const llq
= m
->LLQNAT
.clientContext
? &m
->LLQNAT
: mDNSNULL
;
3278 const NATTraversalInfo
*const tun
= info
->AutoTunnelNAT
.clientContext
? &info
->AutoTunnelNAT
: mDNSNULL
;
3280 CFMutableDictionaryRef dict
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
3281 CFStringRef domain
= NULL
;
3282 CFStringRef tmp
= NULL
;
3283 CFNumberRef num
= NULL
;
3284 mStatus status
= mStatus_NoError
;
3286 if (!domainStatusDict
)
3288 domainStatusDict
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
3289 if (!domainStatusDict
) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFDictionary domainStatusDict"); return; }
3292 if (!dict
) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFDictionary dict"); return; }
3294 buffer
[mDNS_snprintf(buffer
, sizeof(buffer
), "%##s", info
->domain
.c
) - 1] = 0;
3295 domain
= CFStringCreateWithCString(NULL
, buffer
, kCFStringEncodingUTF8
);
3296 if (!domain
) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString domain"); return; }
3298 mDNS_snprintf(buffer
, sizeof(buffer
), "%#a", &m
->Router
);
3299 tmp
= CFStringCreateWithCString(NULL
, buffer
, kCFStringEncodingUTF8
);
3301 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString RouterAddress");
3304 CFDictionarySetValue(dict
, CFSTR("RouterAddress"), tmp
);
3308 mDNS_snprintf(buffer
, sizeof(buffer
), "%.4a", &m
->ExternalAddress
);
3309 tmp
= CFStringCreateWithCString(NULL
, buffer
, kCFStringEncodingUTF8
);
3311 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString ExternalAddress");
3314 CFDictionarySetValue(dict
, CFSTR("ExternalAddress"), tmp
);
3320 mDNSu32 port
= mDNSVal16(llq
->ExternalPort
);
3322 num
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &port
);
3324 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LLQExternalPort");
3327 CFDictionarySetValue(dict
, CFSTR("LLQExternalPort"), num
);
3333 num
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &llq
->Result
);
3335 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LLQNPMStatus");
3338 CFDictionarySetValue(dict
, CFSTR("LLQNPMStatus"), num
);
3346 mDNSu32 port
= mDNSVal16(tun
->ExternalPort
);
3348 num
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &port
);
3350 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber AutoTunnelExternalPort");
3353 CFDictionarySetValue(dict
, CFSTR("AutoTunnelExternalPort"), num
);
3359 num
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &tun
->Result
);
3361 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber AutoTunnelNPMStatus");
3364 CFDictionarySetValue(dict
, CFSTR("AutoTunnelNPMStatus"), num
);
3371 mDNSu32 code
= m
->LastNATMapResultCode
;
3373 num
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &code
);
3375 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LastNATMapResultCode");
3378 CFDictionarySetValue(dict
, CFSTR("LastNATMapResultCode"), num
);
3385 status
= mStatus_NotInitializedErr
;
3386 mDNS_snprintf(buffer
, sizeof(buffer
), "Neither LLQ nor AutoTunnel NAT port mapping is currently active");
3388 else if ((llq
&& llq
->Result
== mStatus_DoubleNAT
) || (tun
&& tun
->Result
== mStatus_DoubleNAT
))
3390 status
= mStatus_DoubleNAT
;
3391 mDNS_snprintf(buffer
, sizeof(buffer
), "Double NAT: Router is reporting an external address");
3393 else if ((llq
&& llq
->Result
== mStatus_NATPortMappingDisabled
) || (tun
&& tun
->Result
== mStatus_NATPortMappingDisabled
) ||
3394 (m
->LastNATMapResultCode
== NATErr_Refused
&& ((llq
&& !llq
->Result
&& mDNSIPPortIsZero(llq
->ExternalPort
)) || (tun
&& !tun
->Result
&& mDNSIPPortIsZero(tun
->ExternalPort
)))))
3396 status
= mStatus_NATPortMappingDisabled
;
3397 mDNS_snprintf(buffer
, sizeof(buffer
), "NAT-PMP is disabled on the router");
3399 else if ((llq
&& llq
->Result
) || (tun
&& tun
->Result
))
3401 status
= mStatus_NATTraversal
;
3402 mDNS_snprintf(buffer
, sizeof(buffer
), "Error obtaining NAT port mapping from router");
3404 else if (m
->Router
.type
== mDNSAddrType_None
)
3406 status
= mStatus_NoRouter
;
3407 mDNS_snprintf(buffer
, sizeof(buffer
), "No network connection - none");
3409 else if (m
->Router
.type
== mDNSAddrType_IPv4
&& mDNSIPv4AddressIsZero(m
->Router
.ip
.v4
))
3411 status
= mStatus_NoRouter
;
3412 mDNS_snprintf(buffer
, sizeof(buffer
), "No network connection - v4 zero");
3414 else if ((llq
&& mDNSIPPortIsZero(llq
->ExternalPort
)) || (tun
&& mDNSIPPortIsZero(tun
->ExternalPort
)))
3416 status
= mStatus_NATTraversal
;
3417 mDNS_snprintf(buffer
, sizeof(buffer
), "Unable to obtain NAT port mapping from router");
3421 DNSQuestion
* q
, *worst_q
= mDNSNULL
;
3422 for (q
= m
->Questions
; q
; q
=q
->next
)
3423 if (q
->AuthInfo
== info
)
3425 mStatus newStatus
= CheckQuestionForStatus(q
);
3426 if (newStatus
== mStatus_NoSuchRecord
) { status
= newStatus
; worst_q
= q
; break; }
3427 else if (newStatus
== mStatus_PollingMode
) { status
= newStatus
; worst_q
= q
; }
3428 else if (newStatus
== mStatus_TransientErr
&& status
== mStatus_NoError
) { status
= newStatus
; worst_q
= q
; }
3431 if (status
== mStatus_NoError
) mDNS_snprintf(buffer
, sizeof(buffer
), "Success");
3432 else if (status
== mStatus_NoSuchRecord
) mDNS_snprintf(buffer
, sizeof(buffer
), "GetZoneData %s: %##s", worst_q
->nta
? "not yet complete" : "failed", worst_q
->qname
.c
);
3433 else if (status
== mStatus_PollingMode
) mDNS_snprintf(buffer
, sizeof(buffer
), "Query polling %##s", worst_q
->qname
.c
);
3434 else if (status
== mStatus_TransientErr
) mDNS_snprintf(buffer
, sizeof(buffer
), "Query not yet established %##s", worst_q
->qname
.c
);
3437 num
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &status
);
3439 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber StatusCode");
3442 CFDictionarySetValue(dict
, CFSTR("StatusCode"), num
);
3446 tmp
= CFStringCreateWithCString(NULL
, buffer
, kCFStringEncodingUTF8
);
3448 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString StatusMessage");
3451 CFDictionarySetValue(dict
, CFSTR("StatusMessage"), tmp
);
3455 if (!CFDictionaryContainsKey(domainStatusDict
, domain
) ||
3456 !CFEqual(dict
, (CFMutableDictionaryRef
)CFDictionaryGetValue(domainStatusDict
, domain
)))
3458 CFDictionarySetValue(domainStatusDict
, domain
, dict
);
3459 if (!m
->ShutdownTime
)
3461 static char statusBuf
[16];
3462 mDNS_snprintf(statusBuf
, sizeof(statusBuf
), "%d", (int)status
);
3463 mDNSASLLog((uuid_t
*)&m
->asl_uuid
, "autotunnel.domainstatus", status
? "failure" : "success", statusBuf
, "");
3464 mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig
, mDNSNULL
, domainStatusDict
);
3471 debugf("UpdateAutoTunnelDomainStatus: %s", buffer
);
3472 #endif // def NO_SECURITYFRAMEWORK
3475 // MUST be called with lock held
3476 mDNSexport
void UpdateAutoTunnelDomainStatuses(const mDNS
*const m
)
3478 #ifdef NO_SECURITYFRAMEWORK
3481 DomainAuthInfo
* info
;
3482 for (info
= m
->AuthInfoList
; info
; info
= info
->next
)
3483 if (info
->AutoTunnel
&& !info
->deltime
)
3484 UpdateAutoTunnelDomainStatus(m
, info
);
3485 #endif // def NO_SECURITYFRAMEWORK
3488 // MUST be called with lock held
3489 mDNSlocal mDNSBool
TunnelServers(mDNS
*const m
)
3491 ServiceRecordSet
*p
;
3492 for (p
= m
->ServiceRegistrations
; p
; p
= p
->uDNS_next
)
3494 DomainAuthInfo
*AuthInfo
= GetAuthInfoForName_internal(m
, p
->RR_SRV
.resrec
.name
);
3495 if (AuthInfo
&& AuthInfo
->AutoTunnel
&& !AuthInfo
->deltime
) return(mDNStrue
);
3499 for (r
= m
->ResourceRecords
; r
; r
= r
->next
)
3500 if (r
->resrec
.rrtype
== kDNSType_SRV
)
3502 DomainAuthInfo
*AuthInfo
= GetAuthInfoForName_internal(m
, r
->resrec
.name
);
3503 if (AuthInfo
&& AuthInfo
->AutoTunnel
&& !AuthInfo
->deltime
) return(mDNStrue
);
3509 // MUST be called with lock held
3510 mDNSlocal mDNSBool
TunnelClients(mDNS
*const m
)
3513 for (p
= m
->TunnelClients
; p
; p
= p
->next
)
3514 if (p
->q
.ThisQInterval
< 0)
3519 mDNSlocal
void RegisterAutoTunnelRecords(mDNS
*m
, DomainAuthInfo
*info
)
3521 if (info
->AutoTunnelNAT
.clientContext
&& !info
->AutoTunnelNAT
.Result
&& !mDNSIPPortIsZero(info
->AutoTunnelNAT
.ExternalPort
) && AutoTunnelUnregistered(info
))
3524 LogInfo("RegisterAutoTunnelRecords %##s (%#s)", info
->domain
.c
, m
->hostlabel
.c
);
3526 // 1. Set up our address record for the internal tunnel address
3527 // (User-visible user-friendly host name, used as target in AutoTunnel SRV records)
3528 info
->AutoTunnelHostRecord
.namestorage
.c
[0] = 0;
3529 AppendDomainLabel(&info
->AutoTunnelHostRecord
.namestorage
, &m
->hostlabel
);
3530 AppendDomainName (&info
->AutoTunnelHostRecord
.namestorage
, &info
->domain
);
3531 info
->AutoTunnelHostRecord
.resrec
.rdata
->u
.ipv6
= m
->AutoTunnelHostAddr
;
3532 info
->AutoTunnelHostRecord
.resrec
.RecordType
= kDNSRecordTypeKnownUnique
;
3533 err
= mDNS_Register(m
, &info
->AutoTunnelHostRecord
);
3534 if (err
) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelHostRecord %##s", err
, info
->AutoTunnelHostRecord
.namestorage
.c
);
3536 // 2. Set up device info record
3537 ConstructServiceName(&info
->AutoTunnelDeviceInfo
.namestorage
, &m
->nicelabel
, &DeviceInfoName
, &info
->domain
);
3538 mDNSu8 len
= m
->HIHardware
.c
[0] < 255 - 6 ? m
->HIHardware
.c
[0] : 255 - 6;
3539 mDNSPlatformMemCopy(info
->AutoTunnelDeviceInfo
.resrec
.rdata
->u
.data
+ 1, "model=", 6);
3540 mDNSPlatformMemCopy(info
->AutoTunnelDeviceInfo
.resrec
.rdata
->u
.data
+ 7, m
->HIHardware
.c
+ 1, len
);
3541 info
->AutoTunnelDeviceInfo
.resrec
.rdata
->u
.data
[0] = 6 + len
; // "model=" plus the device string
3542 info
->AutoTunnelDeviceInfo
.resrec
.rdlength
= 7 + len
; // One extra for the length byte at the start of the string
3543 info
->AutoTunnelDeviceInfo
.resrec
.RecordType
= kDNSRecordTypeKnownUnique
;
3544 err
= mDNS_Register(m
, &info
->AutoTunnelDeviceInfo
);
3545 if (err
) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelDeviceInfo %##s", err
, info
->AutoTunnelDeviceInfo
.namestorage
.c
);
3547 // 3. Set up our address record for the external tunnel address
3548 // (Constructed name, not generally user-visible, used as target in IKE tunnel's SRV record)
3549 info
->AutoTunnelTarget
.namestorage
.c
[0] = 0;
3550 AppendDomainLabel(&info
->AutoTunnelTarget
.namestorage
, &m
->AutoTunnelLabel
);
3551 AppendDomainName (&info
->AutoTunnelTarget
.namestorage
, &info
->domain
);
3552 info
->AutoTunnelTarget
.resrec
.RecordType
= kDNSRecordTypeKnownUnique
;
3555 mDNS_AddDynDNSHostName(m
, &info
->AutoTunnelTarget
.namestorage
, mDNSNULL
, info
);
3558 // 4. Set up IKE tunnel's SRV record: "AutoTunnelHostRecord SRV 0 0 port AutoTunnelTarget"
3559 AssignDomainName (&info
->AutoTunnelService
.namestorage
, (const domainname
*) "\x0B" "_autotunnel" "\x04" "_udp");
3560 AppendDomainLabel(&info
->AutoTunnelService
.namestorage
, &m
->hostlabel
);
3561 AppendDomainName (&info
->AutoTunnelService
.namestorage
, &info
->domain
);
3562 info
->AutoTunnelService
.resrec
.rdata
->u
.srv
.priority
= 0;
3563 info
->AutoTunnelService
.resrec
.rdata
->u
.srv
.weight
= 0;
3564 info
->AutoTunnelService
.resrec
.rdata
->u
.srv
.port
= info
->AutoTunnelNAT
.ExternalPort
;
3565 AssignDomainName(&info
->AutoTunnelService
.resrec
.rdata
->u
.srv
.target
, &info
->AutoTunnelTarget
.namestorage
);
3566 info
->AutoTunnelService
.resrec
.RecordType
= kDNSRecordTypeKnownUnique
;
3567 err
= mDNS_Register(m
, &info
->AutoTunnelService
);
3568 if (err
) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelService %##s", err
, info
->AutoTunnelService
.namestorage
.c
);
3570 LogInfo("AutoTunnel server listening for connections on %##s[%.4a]:%d:%##s[%.16a]",
3571 info
->AutoTunnelTarget
.namestorage
.c
, &m
->AdvertisedV4
.ip
.v4
, mDNSVal16(info
->AutoTunnelNAT
.IntPort
),
3572 info
->AutoTunnelHostRecord
.namestorage
.c
, &m
->AutoTunnelHostAddr
);
3576 mDNSlocal
void DeregisterAutoTunnelRecords(mDNS
*m
, DomainAuthInfo
*info
)
3578 LogInfo("DeregisterAutoTunnelRecords %##s", info
->domain
.c
);
3579 if (info
->AutoTunnelService
.resrec
.RecordType
> kDNSRecordTypeDeregistering
)
3581 mStatus err
= mDNS_Deregister(m
, &info
->AutoTunnelService
);
3584 info
->AutoTunnelService
.resrec
.RecordType
= kDNSRecordTypeUnregistered
;
3585 LogMsg("DeregisterAutoTunnelRecords error %d deregistering AutoTunnelService %##s", err
, info
->AutoTunnelService
.namestorage
.c
);
3589 mDNS_RemoveDynDNSHostName(m
, &info
->AutoTunnelTarget
.namestorage
);
3593 if (info
->AutoTunnelHostRecord
.resrec
.RecordType
> kDNSRecordTypeDeregistering
)
3595 mStatus err
= mDNS_Deregister(m
, &info
->AutoTunnelHostRecord
);
3598 info
->AutoTunnelHostRecord
.resrec
.RecordType
= kDNSRecordTypeUnregistered
;
3599 LogMsg("DeregisterAutoTunnelRecords error %d deregistering AutoTunnelHostRecord %##s", err
, info
->AutoTunnelHostRecord
.namestorage
.c
);
3603 if (info
->AutoTunnelDeviceInfo
.resrec
.RecordType
> kDNSRecordTypeDeregistering
)
3605 mStatus err
= mDNS_Deregister(m
, &info
->AutoTunnelDeviceInfo
);
3608 info
->AutoTunnelDeviceInfo
.resrec
.RecordType
= kDNSRecordTypeUnregistered
;
3609 LogMsg("DeregisterAutoTunnelRecords error %d deregistering AutoTunnelDeviceInfo %##s", err
, info
->AutoTunnelDeviceInfo
.namestorage
.c
);
3614 mDNSlocal
void AutoTunnelRecordCallback(mDNS
*const m
, AuthRecord
*const rr
, mStatus result
)
3616 DomainAuthInfo
*info
= (DomainAuthInfo
*)rr
->RecordContext
;
3617 if (result
== mStatus_MemFree
)
3619 LogInfo("AutoTunnelRecordCallback MemFree %s", ARDisplayString(m
, rr
));
3620 // Reset the host record namestorage to force high-level PTR/SRV/TXT to deregister
3621 if (rr
== &info
->AutoTunnelHostRecord
)
3623 rr
->namestorage
.c
[0] = 0;
3624 m
->NextSRVUpdate
= NonZeroTime(m
->timenow
);
3626 RegisterAutoTunnelRecords(m
,info
);
3630 // Determine whether we need racoon to accept incoming connections
3631 mDNSlocal
void UpdateConfigureServer(mDNS
*m
)
3633 DomainAuthInfo
*info
;
3635 for (info
= m
->AuthInfoList
; info
; info
= info
->next
)
3636 if (info
->AutoTunnel
&& !info
->deltime
&& !mDNSIPPortIsZero(info
->AutoTunnelNAT
.ExternalPort
))
3639 if (info
!= AnonymousRacoonConfig
)
3641 AnonymousRacoonConfig
= info
;
3642 // Create or revert configuration file, and start (or SIGHUP) Racoon
3643 (void)mDNSConfigureServer(AnonymousRacoonConfig
? kmDNSUp
: kmDNSDown
, AnonymousRacoonConfig
? &AnonymousRacoonConfig
->domain
: mDNSNULL
);
3647 mDNSlocal
void AutoTunnelNATCallback(mDNS
*m
, NATTraversalInfo
*n
)
3649 DomainAuthInfo
*info
= (DomainAuthInfo
*)n
->clientContext
;
3650 LogInfo("AutoTunnelNATCallback Result %d %.4a Internal %d External %d %#s.%##s",
3651 n
->Result
, &n
->ExternalAddress
, mDNSVal16(n
->IntPort
), mDNSVal16(n
->ExternalPort
), m
->hostlabel
.c
, info
->domain
.c
);
3653 m
->NextSRVUpdate
= NonZeroTime(m
->timenow
);
3654 DeregisterAutoTunnelRecords(m
,info
);
3655 RegisterAutoTunnelRecords(m
,info
);
3657 UpdateConfigureServer(m
);
3659 UpdateAutoTunnelDomainStatus(m
, (DomainAuthInfo
*)n
->clientContext
);
3662 mDNSlocal
void AbortDeregistration(mDNS
*const m
, AuthRecord
*rr
)
3664 if (rr
->resrec
.RecordType
== kDNSRecordTypeDeregistering
)
3666 LogInfo("Aborting deregistration of %s", ARDisplayString(m
, rr
));
3667 CompleteDeregistration(m
, rr
);
3669 else if (rr
->resrec
.RecordType
!= kDNSRecordTypeUnregistered
)
3670 LogMsg("AbortDeregistration ERROR RecordType %02X for %s", ARDisplayString(m
, rr
));
3673 // Before SetupLocalAutoTunnelInterface_internal is called,
3674 // m->AutoTunnelHostAddr.b[0] must be non-zero, and there must be at least one TunnelClient or TunnelServer
3675 // Must be called with the lock held
3676 mDNSexport
void SetupLocalAutoTunnelInterface_internal(mDNS
*const m
)
3678 LogInfo("SetupLocalAutoTunnelInterface");
3680 // 1. Configure the local IPv6 address
3681 if (!m
->AutoTunnelHostAddrActive
)
3683 m
->AutoTunnelHostAddrActive
= mDNStrue
;
3684 LogInfo("Setting up AutoTunnel address %.16a", &m
->AutoTunnelHostAddr
);
3685 (void)mDNSAutoTunnelInterfaceUpDown(kmDNSUp
, m
->AutoTunnelHostAddr
.b
);
3688 // 2. If we have at least one server (pending) listening, publish our records
3689 if (TunnelServers(m
))
3691 DomainAuthInfo
*info
;
3692 for (info
= m
->AuthInfoList
; info
; info
= info
->next
)
3694 if (info
->AutoTunnel
&& !info
->deltime
&& !info
->AutoTunnelNAT
.clientContext
)
3696 // If we just resurrected a DomainAuthInfo that is still deregistering, we need to abort the deregistration process before re-using the AuthRecord memory
3697 AbortDeregistration(m
, &info
->AutoTunnelHostRecord
);
3698 AbortDeregistration(m
, &info
->AutoTunnelDeviceInfo
);
3699 AbortDeregistration(m
, &info
->AutoTunnelService
);
3701 mDNS_SetupResourceRecord(&info
->AutoTunnelHostRecord
, mDNSNULL
, mDNSInterface_Any
, kDNSType_AAAA
, kHostNameTTL
, kDNSRecordTypeUnregistered
, AutoTunnelRecordCallback
, info
);
3702 mDNS_SetupResourceRecord(&info
->AutoTunnelDeviceInfo
, mDNSNULL
, mDNSInterface_Any
, kDNSType_TXT
, kStandardTTL
, kDNSRecordTypeUnregistered
, AutoTunnelRecordCallback
, info
);
3703 mDNS_SetupResourceRecord(&info
->AutoTunnelTarget
, mDNSNULL
, mDNSInterface_Any
, kDNSType_A
, kHostNameTTL
, kDNSRecordTypeUnregistered
, AutoTunnelRecordCallback
, info
);
3704 mDNS_SetupResourceRecord(&info
->AutoTunnelService
, mDNSNULL
, mDNSInterface_Any
, kDNSType_SRV
, kHostNameTTL
, kDNSRecordTypeUnregistered
, AutoTunnelRecordCallback
, info
);
3706 // Try to get a NAT port mapping for the AutoTunnelService
3707 info
->AutoTunnelNAT
.clientCallback
= AutoTunnelNATCallback
;
3708 info
->AutoTunnelNAT
.clientContext
= info
;
3709 info
->AutoTunnelNAT
.Protocol
= NATOp_MapUDP
;
3710 info
->AutoTunnelNAT
.IntPort
= mDNSOpaque16fromIntVal(kRacoonPort
);
3711 info
->AutoTunnelNAT
.RequestedPort
= mDNSOpaque16fromIntVal(kRacoonPort
);
3712 info
->AutoTunnelNAT
.NATLease
= 0;
3713 mStatus err
= mDNS_StartNATOperation_internal(m
, &info
->AutoTunnelNAT
);
3714 if (err
) LogMsg("SetupLocalAutoTunnelInterface_internal error %d starting NAT mapping", err
);
3720 mDNSlocal mStatus
AutoTunnelSetKeys(ClientTunnel
*tun
, mDNSBool AddNew
)
3722 return(mDNSAutoTunnelSetKeys(AddNew
? kmDNSAutoTunnelSetKeysReplace
: kmDNSAutoTunnelSetKeysDelete
, tun
->loc_inner
.b
, tun
->loc_outer
.b
, kRacoonPort
, tun
->rmt_inner
.b
, tun
->rmt_outer
.b
, mDNSVal16(tun
->rmt_outer_port
), SkipLeadingLabels(&tun
->dstname
, 1)));
3725 // If the EUI-64 part of the IPv6 ULA matches, then that means the two addresses point to the same machine
3726 #define mDNSSameClientTunnel(A,B) ((A)->l[2] == (B)->l[2] && (A)->l[3] == (B)->l[3])
3728 mDNSlocal
void ReissueBlockedQuestionWithType(mDNS
*const m
, domainname
*d
, mDNSBool success
, mDNSu16 qtype
)
3730 DNSQuestion
*q
= m
->Questions
;
3733 if (q
->NoAnswer
== NoAnswer_Suspended
&& q
->qtype
== qtype
&& q
->AuthInfo
&& q
->AuthInfo
->AutoTunnel
&& SameDomainName(&q
->qname
, d
))
3735 LogInfo("Restart %##s (%s)", q
->qname
.c
, DNSTypeName(q
->qtype
));
3736 mDNSQuestionCallback
*tmp
= q
->QuestionCallback
;
3737 q
->QuestionCallback
= AutoTunnelCallback
; // Set QuestionCallback to suppress another call back to AddNewClientTunnel
3738 mDNS_StopQuery(m
, q
);
3739 mDNS_StartQuery(m
, q
);
3740 q
->QuestionCallback
= tmp
; // Restore QuestionCallback back to the real value
3741 if (!success
) q
->NoAnswer
= NoAnswer_Fail
;
3742 // When we call mDNS_StopQuery, it's possible for other subordinate questions like the GetZoneData query to be cancelled too.
3743 // In general we have to assume that the question list might have changed in arbitrary ways.
3744 // This code is itself called from a question callback, so the m->CurrentQuestion mechanism is
3745 // already in use. The safest solution is just to go back to the start of the list and start again.
3746 // In principle this sounds like an n^2 algorithm, but in practice we almost always activate
3747 // just one suspended question, so it's really a 2n algorithm.
3755 mDNSlocal
void ReissueBlockedQuestions(mDNS
*const m
, domainname
*d
, mDNSBool success
)
3757 // 1. We deliberately restart AAAA queries before A queries, because in the common case where a BTTM host has
3758 // a v6 address but no v4 address, we prefer the caller to get the positive AAAA response before the A NXDOMAIN.
3759 // 2. In the case of AAAA queries, if our tunnel setup failed, then we return a deliberate failure indication to the caller --
3760 // even if the name does have a valid AAAA record, we don't want clients trying to connect to it without a properly encrypted tunnel.
3761 // 3. For A queries we never fabricate failures -- if a BTTM service is really using raw IPv4, then it doesn't need the IPv6 tunnel.
3762 ReissueBlockedQuestionWithType(m
, d
, success
, kDNSType_AAAA
);
3763 ReissueBlockedQuestionWithType(m
, d
, mDNStrue
, kDNSType_A
);
3766 mDNSlocal
void UnlinkAndReissueBlockedQuestions(mDNS
*const m
, ClientTunnel
*tun
, mDNSBool success
)
3768 ClientTunnel
**p
= &m
->TunnelClients
;
3769 while (*p
!= tun
&& *p
) p
= &(*p
)->next
;
3770 if (*p
) *p
= tun
->next
;
3771 ReissueBlockedQuestions(m
, &tun
->dstname
, success
);
3772 LogInfo("UnlinkAndReissueBlockedQuestions: Disposing ClientTunnel %p", tun
);
3773 freeL("ClientTunnel", tun
);
3776 mDNSexport
void AutoTunnelCallback(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
3778 ClientTunnel
*tun
= (ClientTunnel
*)question
->QuestionContext
;
3779 LogInfo("AutoTunnelCallback tun %p AddRecord %d rdlength %d qtype %d", tun
, AddRecord
, answer
->rdlength
, question
->qtype
);
3781 if (!AddRecord
) return;
3782 mDNS_StopQuery(m
, question
);
3784 if (!answer
->rdlength
)
3786 LogInfo("AutoTunnelCallback NXDOMAIN %##s (%s)", question
->qname
.c
, DNSTypeName(question
->qtype
));
3787 static char msgbuf
[16];
3788 mDNS_snprintf(msgbuf
, sizeof(msgbuf
), "%s lookup", DNSTypeName(question
->qtype
));
3789 mDNSASLLog((uuid_t
*)&m
->asl_uuid
, "autotunnel.config", "failure", msgbuf
, "");
3790 UnlinkAndReissueBlockedQuestions(m
, tun
, mDNSfalse
);
3794 if (question
->qtype
== kDNSType_AAAA
)
3796 if (mDNSSameIPv6Address(answer
->rdata
->u
.ipv6
, m
->AutoTunnelHostAddr
))
3798 LogInfo("AutoTunnelCallback: suppressing tunnel to self %.16a", &answer
->rdata
->u
.ipv6
);
3799 UnlinkAndReissueBlockedQuestions(m
, tun
, mDNStrue
);
3803 tun
->rmt_inner
= answer
->rdata
->u
.ipv6
;
3804 LogInfo("AutoTunnelCallback: dst host %.16a", &tun
->rmt_inner
);
3805 AssignDomainName(&question
->qname
, (const domainname
*) "\x0B" "_autotunnel" "\x04" "_udp");
3806 AppendDomainName(&question
->qname
, &tun
->dstname
);
3807 question
->qtype
= kDNSType_SRV
;
3808 mDNS_StartQuery(m
, &tun
->q
);
3810 else if (question
->qtype
== kDNSType_SRV
)
3812 LogInfo("AutoTunnelCallback: SRV target name %##s", answer
->rdata
->u
.srv
.target
.c
);
3813 AssignDomainName(&tun
->q
.qname
, &answer
->rdata
->u
.srv
.target
);
3814 tun
->rmt_outer_port
= answer
->rdata
->u
.srv
.port
;
3815 question
->qtype
= kDNSType_A
;
3816 mDNS_StartQuery(m
, &tun
->q
);
3818 else if (question
->qtype
== kDNSType_A
)
3820 ClientTunnel
*old
= mDNSNULL
;
3821 LogInfo("AutoTunnelCallback: SRV target addr %.4a", &answer
->rdata
->u
.ipv4
);
3822 question
->ThisQInterval
= -1; // So we know this tunnel setup has completed
3823 tun
->rmt_outer
= answer
->rdata
->u
.ipv4
;
3824 tun
->loc_inner
= m
->AutoTunnelHostAddr
;
3825 mDNSAddr tmpDst
= { mDNSAddrType_IPv4
, {{{0}}} };
3826 tmpDst
.ip
.v4
= tun
->rmt_outer
;
3827 mDNSAddr tmpSrc
= zeroAddr
;
3828 mDNSPlatformSourceAddrForDest(&tmpSrc
, &tmpDst
);
3829 if (tmpSrc
.type
== mDNSAddrType_IPv4
) tun
->loc_outer
= tmpSrc
.ip
.v4
;
3830 else tun
->loc_outer
= m
->AdvertisedV4
.ip
.v4
;
3832 ClientTunnel
**p
= &tun
->next
;
3833 mDNSBool needSetKeys
= mDNStrue
;
3836 if (!mDNSSameClientTunnel(&(*p
)->rmt_inner
, &tun
->rmt_inner
)) p
= &(*p
)->next
;
3839 LogInfo("Found existing AutoTunnel for %##s %.16a", tun
->dstname
.c
, &tun
->rmt_inner
);
3842 if (old
->q
.ThisQInterval
>= 0) mDNS_StopQuery(m
, &old
->q
);
3843 else if (!mDNSSameIPv6Address(old
->loc_inner
, tun
->loc_inner
) ||
3844 !mDNSSameIPv4Address(old
->loc_outer
, tun
->loc_outer
) ||
3845 !mDNSSameIPv6Address(old
->rmt_inner
, tun
->rmt_inner
) ||
3846 !mDNSSameIPv4Address(old
->rmt_outer
, tun
->rmt_outer
) ||
3847 !mDNSSameIPPort(old
->rmt_outer_port
, tun
->rmt_outer_port
))
3849 LogInfo("Deleting existing AutoTunnel for %##s %.16a", tun
->dstname
.c
, &tun
->rmt_inner
);
3850 AutoTunnelSetKeys(old
, mDNSfalse
);
3852 else needSetKeys
= mDNSfalse
;
3854 LogInfo("AutoTunnelCallback: Disposing ClientTunnel %p", tun
);
3855 freeL("ClientTunnel", old
);
3859 if (needSetKeys
) LogInfo("New AutoTunnel for %##s %.16a", tun
->dstname
.c
, &tun
->rmt_inner
);
3861 if (m
->AutoTunnelHostAddr
.b
[0]) { mDNS_Lock(m
); SetupLocalAutoTunnelInterface_internal(m
); mDNS_Unlock(m
); };
3863 mStatus result
= needSetKeys
? AutoTunnelSetKeys(tun
, mDNStrue
) : mStatus_NoError
;
3864 static char msgbuf
[32];
3865 mDNS_snprintf(msgbuf
, sizeof(msgbuf
), "Tunnel setup - %d", result
);
3866 mDNSASLLog((uuid_t
*)&m
->asl_uuid
, "autotunnel.config", result
? "failure" : "success", msgbuf
, "");
3867 // Kick off any questions that were held pending this tunnel setup
3868 ReissueBlockedQuestions(m
, &tun
->dstname
, (result
== mStatus_NoError
) ? mDNStrue
: mDNSfalse
);
3871 LogMsg("AutoTunnelCallback: Unknown question %p", question
);
3874 // Must be called with the lock held
3875 mDNSexport
void AddNewClientTunnel(mDNS
*const m
, DNSQuestion
*const q
)
3877 ClientTunnel
*p
= mallocL("ClientTunnel", sizeof(ClientTunnel
));
3879 AssignDomainName(&p
->dstname
, &q
->qname
);
3880 p
->MarkedForDeletion
= mDNSfalse
;
3881 p
->loc_inner
= zerov6Addr
;
3882 p
->loc_outer
= zerov4Addr
;
3883 p
->rmt_inner
= zerov6Addr
;
3884 p
->rmt_outer
= zerov4Addr
;
3885 p
->rmt_outer_port
= zeroIPPort
;
3886 p
->next
= m
->TunnelClients
;
3887 m
->TunnelClients
= p
; // We intentionally build list in reverse order
3889 p
->q
.InterfaceID
= mDNSInterface_Any
;
3890 p
->q
.Target
= zeroAddr
;
3891 AssignDomainName(&p
->q
.qname
, &q
->qname
);
3892 p
->q
.qtype
= kDNSType_AAAA
;
3893 p
->q
.qclass
= kDNSClass_IN
;
3894 p
->q
.LongLived
= mDNSfalse
;
3895 p
->q
.ExpectUnique
= mDNStrue
;
3896 p
->q
.ForceMCast
= mDNSfalse
;
3897 p
->q
.ReturnIntermed
= mDNStrue
;
3898 p
->q
.QuestionCallback
= AutoTunnelCallback
;
3899 p
->q
.QuestionContext
= p
;
3901 LogInfo("AddNewClientTunnel start tun %p %##s (%s)%s", p
, &q
->qname
.c
, DNSTypeName(q
->qtype
), q
->LongLived
? " LongLived" : "");
3902 mDNS_StartQuery_internal(m
, &p
->q
);
3905 #endif // APPLE_OSX_mDNSResponder
3907 #if COMPILER_LIKES_PRAGMA_MARK
3909 #pragma mark - Power State & Configuration Change Management
3912 mDNSlocal mStatus
UpdateInterfaceList(mDNS
*const m
, mDNSs32 utc
)
3914 mDNSBool foundav4
= mDNSfalse
;
3915 mDNSBool foundav6
= mDNSfalse
;
3916 struct ifaddrs
*ifa
= myGetIfAddrs(1);
3917 struct ifaddrs
*v4Loopback
= NULL
;
3918 struct ifaddrs
*v6Loopback
= NULL
;
3919 char defaultname
[64];
3921 int InfoSocket
= socket(AF_INET6
, SOCK_DGRAM
, 0);
3922 if (InfoSocket
< 3 && errno
!= EAFNOSUPPORT
) LogMsg("UpdateInterfaceList: InfoSocket error %d errno %d (%s)", InfoSocket
, errno
, strerror(errno
));
3924 if (m
->SleepState
== SleepState_Sleeping
) ifa
= NULL
;
3928 #if LIST_ALL_INTERFACES
3929 if (ifa
->ifa_addr
->sa_family
== AF_APPLETALK
)
3930 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_APPLETALK",
3931 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
3932 else if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
3933 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_LINK",
3934 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
3935 else if (ifa
->ifa_addr
->sa_family
!= AF_INET
&& ifa
->ifa_addr
->sa_family
!= AF_INET6
)
3936 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)",
3937 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
3938 if (!(ifa
->ifa_flags
& IFF_UP
))
3939 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_UP",
3940 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
3941 if (!(ifa
->ifa_flags
& IFF_MULTICAST
))
3942 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_MULTICAST",
3943 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
3944 if (ifa
->ifa_flags
& IFF_POINTOPOINT
)
3945 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_POINTOPOINT",
3946 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
3947 if (ifa
->ifa_flags
& IFF_LOOPBACK
)
3948 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_LOOPBACK",
3949 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
3952 if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
3954 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
3955 if (sdl
->sdl_type
== IFT_ETHER
&& sdl
->sdl_alen
== sizeof(m
->PrimaryMAC
) && mDNSSameEthAddress(&m
->PrimaryMAC
, &zeroEthAddr
))
3956 mDNSPlatformMemCopy(m
->PrimaryMAC
.b
, sdl
->sdl_data
+ sdl
->sdl_nlen
, 6);
3959 if (ifa
->ifa_flags
& IFF_UP
&& ifa
->ifa_addr
)
3960 if (ifa
->ifa_addr
->sa_family
== AF_INET
|| ifa
->ifa_addr
->sa_family
== AF_INET6
)
3962 if (!ifa
->ifa_netmask
)
3965 SetupAddr(&ip
, ifa
->ifa_addr
);
3966 LogMsg("getifaddrs: ifa_netmask is NULL for %5s(%d) Flags %04X Family %2d %#a",
3967 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
, &ip
);
3969 // Apparently it's normal for the sa_family of an ifa_netmask to sometimes be zero, so we don't complain about that
3970 // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
3971 else if (ifa
->ifa_netmask
->sa_family
!= ifa
->ifa_addr
->sa_family
&& ifa
->ifa_netmask
->sa_family
!= 0)
3974 SetupAddr(&ip
, ifa
->ifa_addr
);
3975 LogMsg("getifaddrs ifa_netmask for %5s(%d) Flags %04X Family %2d %#a has different family: %d",
3976 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
, &ip
, ifa
->ifa_netmask
->sa_family
);
3980 // Make sure ifa_netmask->sa_family is set correctly
3981 // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
3982 ifa
->ifa_netmask
->sa_family
= ifa
->ifa_addr
->sa_family
;
3983 int ifru_flags6
= 0;
3985 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
3986 if (ifa
->ifa_addr
->sa_family
== AF_INET6
&& InfoSocket
>= 0)
3988 struct in6_ifreq ifr6
;
3989 mDNSPlatformMemZero((char *)&ifr6
, sizeof(ifr6
));
3990 strlcpy(ifr6
.ifr_name
, ifa
->ifa_name
, sizeof(ifr6
.ifr_name
));
3991 ifr6
.ifr_addr
= *sin6
;
3992 if (ioctl(InfoSocket
, SIOCGIFAFLAG_IN6
, &ifr6
) != -1)
3993 ifru_flags6
= ifr6
.ifr_ifru
.ifru_flags6
;
3994 verbosedebugf("%s %.16a %04X %04X", ifa
->ifa_name
, &sin6
->sin6_addr
, ifa
->ifa_flags
, ifru_flags6
);
3997 if (!(ifru_flags6
& (IN6_IFF_NOTREADY
| IN6_IFF_DETACHED
| IN6_IFF_DEPRECATED
| IN6_IFF_TEMPORARY
)))
3999 if (ifa
->ifa_flags
& IFF_LOOPBACK
)
4001 if (ifa
->ifa_addr
->sa_family
== AF_INET
) v4Loopback
= ifa
;
4003 else if (sin6
->sin6_addr
.s6_addr
[0] != 0xFD) v6Loopback
= ifa
;
4008 NetworkInterfaceInfoOSX
*i
= AddInterfaceToList(m
, ifa
, utc
);
4009 if (i
&& MulticastInterface(i
) && i
->ifinfo
.Advertise
)
4011 if (ifa
->ifa_addr
->sa_family
== AF_INET
) foundav4
= mDNStrue
;
4012 else foundav6
= mDNStrue
;
4018 ifa
= ifa
->ifa_next
;
4021 // For efficiency, we don't register a loopback interface when other interfaces of that family are available and advertising
4022 if (!foundav4
&& v4Loopback
) AddInterfaceToList(m
, v4Loopback
, utc
);
4023 if (!foundav6
&& v6Loopback
) AddInterfaceToList(m
, v6Loopback
, utc
);
4025 // Now the list is complete, set the McastTxRx setting for each interface.
4026 NetworkInterfaceInfoOSX
*i
;
4027 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
4030 mDNSBool txrx
= MulticastInterface(i
);
4031 #if USE_V6_ONLY_WHEN_NO_ROUTABLE_V4
4032 txrx
= txrx
&& ((i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
) || !FindRoutableIPv4(m
, i
->scope_id
));
4034 if (i
->ifinfo
.McastTxRx
!= txrx
)
4036 i
->ifinfo
.McastTxRx
= txrx
;
4037 i
->Exists
= 2; // State change; need to deregister and reregister this interface
4042 if (InfoSocket
>= 0) close(InfoSocket
);
4045 // If we haven't set up AutoTunnelHostAddr yet, do it now
4046 if (!mDNSSameEthAddress(&m
->PrimaryMAC
, &zeroEthAddr
) && m
->AutoTunnelHostAddr
.b
[0] == 0)
4048 m
->AutoTunnelHostAddr
.b
[0x0] = 0xFD; // Required prefix for "locally assigned" ULA (See RFC 4193)
4049 m
->AutoTunnelHostAddr
.b
[0x1] = mDNSRandom(255);
4050 m
->AutoTunnelHostAddr
.b
[0x2] = mDNSRandom(255);
4051 m
->AutoTunnelHostAddr
.b
[0x3] = mDNSRandom(255);
4052 m
->AutoTunnelHostAddr
.b
[0x4] = mDNSRandom(255);
4053 m
->AutoTunnelHostAddr
.b
[0x5] = mDNSRandom(255);
4054 m
->AutoTunnelHostAddr
.b
[0x6] = mDNSRandom(255);
4055 m
->AutoTunnelHostAddr
.b
[0x7] = mDNSRandom(255);
4056 m
->AutoTunnelHostAddr
.b
[0x8] = m
->PrimaryMAC
.b
[0] ^ 0x02; // See RFC 3513, Appendix A for explanation
4057 m
->AutoTunnelHostAddr
.b
[0x9] = m
->PrimaryMAC
.b
[1];
4058 m
->AutoTunnelHostAddr
.b
[0xA] = m
->PrimaryMAC
.b
[2];
4059 m
->AutoTunnelHostAddr
.b
[0xB] = 0xFF;
4060 m
->AutoTunnelHostAddr
.b
[0xC] = 0xFE;
4061 m
->AutoTunnelHostAddr
.b
[0xD] = m
->PrimaryMAC
.b
[3];
4062 m
->AutoTunnelHostAddr
.b
[0xE] = m
->PrimaryMAC
.b
[4];
4063 m
->AutoTunnelHostAddr
.b
[0xF] = m
->PrimaryMAC
.b
[5];
4064 m
->AutoTunnelLabel
.c
[0] = mDNS_snprintf((char*)m
->AutoTunnelLabel
.c
+1, 254, "AutoTunnel-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
4065 m
->AutoTunnelHostAddr
.b
[0x8], m
->AutoTunnelHostAddr
.b
[0x9], m
->AutoTunnelHostAddr
.b
[0xA], m
->AutoTunnelHostAddr
.b
[0xB],
4066 m
->AutoTunnelHostAddr
.b
[0xC], m
->AutoTunnelHostAddr
.b
[0xD], m
->AutoTunnelHostAddr
.b
[0xE], m
->AutoTunnelHostAddr
.b
[0xF]);
4067 LogInfo("m->AutoTunnelLabel %#s", m
->AutoTunnelLabel
.c
);
4070 mDNS_snprintf(defaultname
, sizeof(defaultname
), "%.*s-%02X%02X%02X%02X%02X%02X", HINFO_HWstring_prefixlen
, HINFO_HWstring
,
4071 m
->PrimaryMAC
.b
[0], m
->PrimaryMAC
.b
[1], m
->PrimaryMAC
.b
[2], m
->PrimaryMAC
.b
[3], m
->PrimaryMAC
.b
[4], m
->PrimaryMAC
.b
[5]);
4073 // Set up the nice label
4074 domainlabel nicelabel
;
4076 GetUserSpecifiedFriendlyComputerName(&nicelabel
);
4077 if (nicelabel
.c
[0] == 0)
4079 debugf("Couldn’t read user-specified Computer Name; using default “%s” instead", defaultname
);
4080 MakeDomainLabelFromLiteralString(&nicelabel
, defaultname
);
4083 // Set up the RFC 1034-compliant label
4084 domainlabel hostlabel
;
4086 GetUserSpecifiedLocalHostName(&hostlabel
);
4087 if (hostlabel
.c
[0] == 0)
4089 debugf("Couldn’t read user-specified Local Hostname; using default “%s.local” instead", defaultname
);
4090 MakeDomainLabelFromLiteralString(&hostlabel
, defaultname
);
4093 mDNSBool namechange
= mDNSfalse
;
4095 // We use a case-sensitive comparison here because even though changing the capitalization
4096 // of the name alone is not significant to DNS, it's still a change from the user's point of view
4097 if (SameDomainLabelCS(m
->p
->usernicelabel
.c
, nicelabel
.c
))
4098 debugf("Usernicelabel (%#s) unchanged since last time; not changing m->nicelabel (%#s)", m
->p
->usernicelabel
.c
, m
->nicelabel
.c
);
4101 if (m
->p
->usernicelabel
.c
[0]) // Don't show message first time through, when we first read name from prefs on boot
4102 LogMsg("User updated Computer Name from “%#s” to “%#s”", m
->p
->usernicelabel
.c
, nicelabel
.c
);
4103 m
->p
->usernicelabel
= m
->nicelabel
= nicelabel
;
4104 namechange
= mDNStrue
;
4107 if (SameDomainLabelCS(m
->p
->userhostlabel
.c
, hostlabel
.c
))
4108 debugf("Userhostlabel (%#s) unchanged since last time; not changing m->hostlabel (%#s)", m
->p
->userhostlabel
.c
, m
->hostlabel
.c
);
4111 if (m
->p
->userhostlabel
.c
[0]) // Don't show message first time through, when we first read name from prefs on boot
4112 LogMsg("User updated Local Hostname from “%#s” to “%#s”", m
->p
->userhostlabel
.c
, hostlabel
.c
);
4113 m
->p
->userhostlabel
= m
->hostlabel
= hostlabel
;
4115 namechange
= mDNStrue
;
4118 #if APPLE_OSX_mDNSResponder
4119 if (namechange
) // If either name has changed, we need to tickle our AutoTunnel state machine to update its registered records
4121 DomainAuthInfo
*info
;
4122 for (info
= m
->AuthInfoList
; info
; info
= info
->next
)
4123 if (info
->AutoTunnelNAT
.clientContext
&& !mDNSIPv4AddressIsOnes(info
->AutoTunnelNAT
.ExternalAddress
))
4124 AutoTunnelNATCallback(m
, &info
->AutoTunnelNAT
);
4126 #endif // APPLE_OSX_mDNSResponder
4128 return(mStatus_NoError
);
4131 // Returns number of leading one-bits in mask: 0-32 for IPv4, 0-128 for IPv6
4132 // Returns -1 if all the one-bits are not contiguous
4133 mDNSlocal
int CountMaskBits(mDNSAddr
*mask
)
4135 int i
= 0, bits
= 0;
4136 int bytes
= mask
->type
== mDNSAddrType_IPv4
? 4 : mask
->type
== mDNSAddrType_IPv6
? 16 : 0;
4139 mDNSu8 b
= mask
->ip
.v6
.b
[i
++];
4140 while (b
& 0x80) { bits
++; b
<<= 1; }
4143 while (i
< bytes
) if (mask
->ip
.v6
.b
[i
++]) return(-1);
4147 // returns count of non-link local V4 addresses registered
4148 mDNSlocal
int SetupActiveInterfaces(mDNS
*const m
, mDNSs32 utc
)
4150 NetworkInterfaceInfoOSX
*i
;
4152 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
4155 NetworkInterfaceInfo
*const n
= &i
->ifinfo
;
4156 NetworkInterfaceInfoOSX
*primary
= SearchForInterfaceByName(m
, i
->ifinfo
.ifname
, AAAA_OVER_V4
? AF_UNSPEC
: i
->sa_family
);
4157 if (!primary
) LogMsg("SetupActiveInterfaces ERROR! SearchForInterfaceByName didn't find %s", i
->ifinfo
.ifname
);
4159 if (n
->InterfaceID
&& n
->InterfaceID
!= (mDNSInterfaceID
)primary
) // Sanity check
4161 LogMsg("SetupActiveInterfaces ERROR! n->InterfaceID %p != primary %p", n
->InterfaceID
, primary
);
4162 n
->InterfaceID
= mDNSNULL
;
4165 if (!n
->InterfaceID
)
4167 // Note: If n->InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
4168 // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
4169 // If n->InterfaceID is NOT set, then we haven't registered it and we should not try to deregister it
4170 n
->InterfaceID
= (mDNSInterfaceID
)primary
;
4172 // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away.
4173 // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds.
4174 // If the interface is an old one that went away and came back in less than a minute, then we're in a flapping scenario.
4175 i
->Occulting
= !(i
->ifa_flags
& IFF_LOOPBACK
) && (utc
- i
->LastSeen
> 0 && utc
- i
->LastSeen
< 60);
4177 mDNS_RegisterInterface(m
, n
, i
->Flashing
&& i
->Occulting
);
4178 if (!mDNSAddressIsLinkLocal(&n
->ip
)) count
++;
4179 LogInfo("SetupActiveInterfaces: Registered %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s%s",
4180 i
->ifinfo
.ifname
, i
->scope_id
, &i
->BSSID
, primary
, &n
->ip
, CountMaskBits(&n
->mask
),
4181 i
->Flashing
? " (Flashing)" : "",
4182 i
->Occulting
? " (Occulting)" : "",
4183 n
->InterfaceActive
? " (Primary)" : "");
4186 debugf("SetupActiveInterfaces: No Tx/Rx on %5s(%lu) %.6a InterfaceID %p %#a", i
->ifinfo
.ifname
, i
->scope_id
, &i
->BSSID
, primary
, &n
->ip
);
4189 if (i
->sa_family
== AF_INET
)
4192 primary
->ifa_v4addr
.s_addr
= n
->ip
.ip
.v4
.NotAnInteger
;
4193 imr
.imr_multiaddr
.s_addr
= AllDNSLinkGroup_v4
.ip
.v4
.NotAnInteger
;
4194 imr
.imr_interface
= primary
->ifa_v4addr
;
4196 // If this is our *first* IPv4 instance for this interface name, we need to do a IP_DROP_MEMBERSHIP first,
4197 // before trying to join the group, to clear out stale kernel state which may be lingering.
4198 // In particular, this happens with removable network interfaces like USB Ethernet adapters -- the kernel has stale state
4199 // from the last time the USB Ethernet adapter was connected, and part of the kernel thinks we've already joined the group
4200 // on that interface (so we get EADDRINUSE when we try to join again) but a different part of the kernel thinks we haven't
4201 // joined the group (so we receive no multicasts). Doing an IP_DROP_MEMBERSHIP before joining seems to flush the stale state.
4202 // Also, trying to make the code leave the group when the adapter is removed doesn't work either,
4203 // because by the time we get the configuration change notification, the interface is already gone,
4204 // so attempts to unsubscribe fail with EADDRNOTAVAIL (errno 49 "Can't assign requested address").
4205 // <rdar://problem/5585972> IP_ADD_MEMBERSHIP fails for previously-connected removable interfaces
4206 if (SearchForInterfaceByName(m
, i
->ifinfo
.ifname
, AF_INET
) == i
)
4208 LogInfo("SetupActiveInterfaces: %5s(%lu) Doing precautionary IP_DROP_MEMBERSHIP for %.4a on %.4a", i
->ifinfo
.ifname
, i
->scope_id
, &imr
.imr_multiaddr
, &imr
.imr_interface
);
4209 mStatus err
= setsockopt(m
->p
->permanentsockets
.sktv4
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
, &imr
, sizeof(imr
));
4210 if (err
< 0 && (errno
!= EADDRNOTAVAIL
))
4211 LogMsg("setsockopt - IP_DROP_MEMBERSHIP error %d errno %d (%s)", err
, errno
, strerror(errno
));
4214 LogInfo("SetupActiveInterfaces: %5s(%lu) joining IPv4 mcast group %.4a on %.4a", i
->ifinfo
.ifname
, i
->scope_id
, &imr
.imr_multiaddr
, &imr
.imr_interface
);
4215 mStatus err
= setsockopt(m
->p
->permanentsockets
.sktv4
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
, &imr
, sizeof(imr
));
4216 // Joining same group twice can give "Address already in use" error -- no need to report that
4217 if (err
< 0 && (errno
!= EADDRINUSE
))
4218 LogMsg("setsockopt - IP_ADD_MEMBERSHIP error %d errno %d (%s) group %.4a on %.4a", err
, errno
, strerror(errno
), &imr
.imr_multiaddr
, &imr
.imr_interface
);
4221 if (i
->sa_family
== AF_INET6
)
4223 struct ipv6_mreq i6mr
;
4224 i6mr
.ipv6mr_interface
= primary
->scope_id
;
4225 i6mr
.ipv6mr_multiaddr
= *(struct in6_addr
*)&AllDNSLinkGroup_v6
.ip
.v6
;
4227 if (SearchForInterfaceByName(m
, i
->ifinfo
.ifname
, AF_INET6
) == i
)
4229 LogInfo("SetupActiveInterfaces: %5s(%lu) Doing precautionary IPV6_LEAVE_GROUP for %.16a on %u", i
->ifinfo
.ifname
, i
->scope_id
, &i6mr
.ipv6mr_multiaddr
, i6mr
.ipv6mr_interface
);
4230 mStatus err
= setsockopt(m
->p
->permanentsockets
.sktv6
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, &i6mr
, sizeof(i6mr
));
4231 if (err
< 0 && (errno
!= EADDRNOTAVAIL
))
4232 LogMsg("setsockopt - IPV6_LEAVE_GROUP error %d errno %d (%s) group %.16a on %u", err
, errno
, strerror(errno
), &i6mr
.ipv6mr_multiaddr
, i6mr
.ipv6mr_interface
);
4235 LogInfo("SetupActiveInterfaces: %5s(%lu) joining IPv6 mcast group %.16a on %u", i
->ifinfo
.ifname
, i
->scope_id
, &i6mr
.ipv6mr_multiaddr
, i6mr
.ipv6mr_interface
);
4236 mStatus err
= setsockopt(m
->p
->permanentsockets
.sktv6
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, &i6mr
, sizeof(i6mr
));
4237 // Joining same group twice can give "Address already in use" error -- no need to report that
4238 if (err
< 0 && (errno
!= EADDRINUSE
))
4239 LogMsg("setsockopt - IPV6_JOIN_GROUP error %d errno %d (%s) group %.16a on %u", err
, errno
, strerror(errno
), &i6mr
.ipv6mr_multiaddr
, i6mr
.ipv6mr_interface
);
4249 mDNSlocal
void MarkAllInterfacesInactive(mDNS
*const m
, mDNSs32 utc
)
4251 NetworkInterfaceInfoOSX
*i
;
4252 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
4254 if (i
->Exists
) i
->LastSeen
= utc
;
4255 i
->Exists
= mDNSfalse
;
4259 // returns count of non-link local V4 addresses deregistered
4260 mDNSlocal
int ClearInactiveInterfaces(mDNS
*const m
, mDNSs32 utc
)
4263 // If an interface is going away, then deregister this from the mDNSCore.
4264 // We also have to deregister it if the primary interface that it's using for its InterfaceID is going away.
4265 // We have to do this because mDNSCore will use that InterfaceID when sending packets, and if the memory
4266 // it refers to has gone away we'll crash.
4267 NetworkInterfaceInfoOSX
*i
;
4269 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
4271 // If this interface is no longer active, or its InterfaceID is changing, deregister it
4272 NetworkInterfaceInfoOSX
*primary
= SearchForInterfaceByName(m
, i
->ifinfo
.ifname
, AAAA_OVER_V4
? AF_UNSPEC
: i
->sa_family
);
4273 if (i
->ifinfo
.InterfaceID
)
4274 if (i
->Exists
== 0 || i
->Exists
== 2 || i
->ifinfo
.InterfaceID
!= (mDNSInterfaceID
)primary
)
4276 i
->Flashing
= !(i
->ifa_flags
& IFF_LOOPBACK
) && (utc
- i
->AppearanceTime
< 60);
4277 LogInfo("ClearInactiveInterfaces: Deregistering %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s%s",
4278 i
->ifinfo
.ifname
, i
->scope_id
, &i
->BSSID
, i
->ifinfo
.InterfaceID
,
4279 &i
->ifinfo
.ip
, CountMaskBits(&i
->ifinfo
.mask
),
4280 i
->Flashing
? " (Flashing)" : "",
4281 i
->Occulting
? " (Occulting)" : "",
4282 i
->ifinfo
.InterfaceActive
? " (Primary)" : "");
4283 mDNS_DeregisterInterface(m
, &i
->ifinfo
, i
->Flashing
&& i
->Occulting
);
4284 if (!mDNSAddressIsLinkLocal(&i
->ifinfo
.ip
)) count
++;
4285 i
->ifinfo
.InterfaceID
= mDNSNULL
;
4286 // Note: If i->ifinfo.InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
4287 // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
4288 // If i->ifinfo.InterfaceID is NOT set, then it's not registered and we should not call mDNS_DeregisterInterface() on it.
4290 // Caution: If we ever decide to add code here to leave the multicast group, we need to make sure that this
4291 // is the LAST representative of this physical interface, or we'll unsubscribe from the group prematurely.
4296 // Now that everything that's going to deregister has done so, we can clean up and free the memory
4297 NetworkInterfaceInfoOSX
**p
= &m
->p
->InterfaceList
;
4301 // If no longer active, delete interface from list and free memory
4304 if (i
->LastSeen
== utc
) i
->LastSeen
= utc
- 1;
4305 mDNSBool
delete = (NumCacheRecordsForInterfaceID(m
, (mDNSInterfaceID
)i
) == 0) && (utc
- i
->LastSeen
>= 60);
4306 LogInfo("ClearInactiveInterfaces: %-13s %5s(%lu) %.6a InterfaceID %p %#a/%d Age %d%s", delete ? "Deleting" : "Holding",
4307 i
->ifinfo
.ifname
, i
->scope_id
, &i
->BSSID
, i
->ifinfo
.InterfaceID
,
4308 &i
->ifinfo
.ip
, CountMaskBits(&i
->ifinfo
.mask
), utc
- i
->LastSeen
,
4309 i
->ifinfo
.InterfaceActive
? " (Primary)" : "");
4310 #if APPLE_OSX_mDNSResponder
4311 if (i
->BPF_fd
>= 0) CloseBPF(i
);
4312 #endif // APPLE_OSX_mDNSResponder
4316 freeL("NetworkInterfaceInfoOSX", i
);
4317 continue; // After deleting this object, don't want to do the "p = &i->next;" thing at the end of the loop
4325 mDNSlocal
void AppendDNameListElem(DNameListElem
***List
, mDNSu32 uid
, domainname
*name
)
4327 DNameListElem
*dnle
= (DNameListElem
*) mallocL("DNameListElem/AppendDNameListElem", sizeof(DNameListElem
));
4328 if (!dnle
) LogMsg("ERROR: AppendDNameListElem: memory exhausted");
4331 dnle
->next
= mDNSNULL
;
4333 AssignDomainName(&dnle
->name
, name
);
4335 *List
= &dnle
->next
;
4339 mDNSlocal
int compare_dns_configs(const void *aa
, const void *bb
)
4341 dns_resolver_t
*a
= *(dns_resolver_t
**)aa
;
4342 dns_resolver_t
*b
= *(dns_resolver_t
**)bb
;
4344 return (a
->search_order
< b
->search_order
) ? -1 : (a
->search_order
== b
->search_order
) ? 0 : 1;
4347 mDNSexport
void mDNSPlatformSetDNSConfig(mDNS
*const m
, mDNSBool setservers
, mDNSBool setsearch
, domainname
*const fqdn
, DNameListElem
**RegDomains
, DNameListElem
**BrowseDomains
)
4350 char buf
[MAX_ESCAPED_DOMAIN_NAME
]; // Max legal C-string name, including terminating NUL
4353 // Need to set these here because we need to do this even if SCDynamicStoreCreate() or SCDynamicStoreCopyValue() below don't succeed
4354 if (fqdn
) fqdn
->c
[0] = 0;
4355 if (RegDomains
) *RegDomains
= NULL
;
4356 if (BrowseDomains
) *BrowseDomains
= NULL
;
4358 LogInfo("mDNSPlatformSetDNSConfig:%s%s%s%s%s",
4359 setservers
? " setservers" : "",
4360 setsearch
? " setsearch" : "",
4361 fqdn
? " fqdn" : "",
4362 RegDomains
? " RegDomains" : "",
4363 BrowseDomains
? " BrowseDomains" : "");
4365 // Add the inferred address-based configuration discovery domains
4366 // (should really be in core code I think, not platform-specific)
4369 struct ifaddrs
*ifa
= mDNSNULL
;
4370 struct sockaddr_in saddr
;
4371 mDNSPlatformMemZero(&saddr
, sizeof(saddr
));
4372 saddr
.sin_len
= sizeof(saddr
);
4373 saddr
.sin_family
= AF_INET
;
4375 saddr
.sin_addr
.s_addr
= *(in_addr_t
*)&m
->Router
.ip
.v4
;
4377 // Don't add any reverse-IP search domains if doing the WAB bootstrap queries would cause dial-on-demand connection initiation
4378 if (!AddrRequiresPPPConnection((struct sockaddr
*)&saddr
)) ifa
= myGetIfAddrs(1);
4383 if (ifa
->ifa_addr
->sa_family
== AF_INET
&&
4385 !(ifa
->ifa_flags
& IFF_LOOPBACK
) &&
4386 !SetupAddr(&a
, ifa
->ifa_addr
) &&
4387 !mDNSv4AddressIsLinkLocal(&a
.ip
.v4
) )
4389 // Apparently it's normal for the sa_family of an ifa_netmask to sometimes be incorrect, so we explicitly fix it here before calling SetupAddr
4390 // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
4391 ifa
->ifa_netmask
->sa_family
= ifa
->ifa_addr
->sa_family
; // Make sure ifa_netmask->sa_family is set correctly
4392 SetupAddr(&n
, ifa
->ifa_netmask
);
4393 // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
4394 mDNS_snprintf(buf
, sizeof(buf
), "%d.%d.%d.%d.in-addr.arpa.", a
.ip
.v4
.b
[3] & n
.ip
.v4
.b
[3],
4395 a
.ip
.v4
.b
[2] & n
.ip
.v4
.b
[2],
4396 a
.ip
.v4
.b
[1] & n
.ip
.v4
.b
[1],
4397 a
.ip
.v4
.b
[0] & n
.ip
.v4
.b
[0]);
4398 mDNS_AddSearchDomain_CString(buf
);
4400 ifa
= ifa
->ifa_next
;
4404 #ifndef MDNS_NO_DNSINFO
4405 if (setservers
|| setsearch
)
4407 dns_config_t
*config
= dns_configuration_copy();
4410 // When running on 10.3 (build 7xxx) and earlier, we don't expect dns_configuration_copy() to succeed
4411 // On 10.4, calls to dns_configuration_copy() early in the boot process often fail.
4412 // Apparently this is expected behaviour -- "not a bug".
4413 // Accordingly, we suppress syslog messages for the first three minutes after boot.
4414 // If we are still getting failures after three minutes, then we log them.
4415 if (OSXVers
> OSXVers_10_3_Panther
&& (mDNSu32
)mDNSPlatformRawTime() > (mDNSu32
)(mDNSPlatformOneSecond
* 180))
4416 LogMsg("mDNSPlatformSetDNSConfig: Error: dns_configuration_copy returned NULL");
4420 LogInfo("mDNSPlatformSetDNSConfig: config->n_resolver = %d", config
->n_resolver
);
4421 if (setsearch
&& config
->n_resolver
)
4423 // Due to the vagaries of Apple's SystemConfiguration and dnsinfo.h APIs, if there are no search domains
4424 // listed, then you're supposed to interpret the "domain" field as also being the search domain, but if
4425 // there *are* search domains listed, then you're supposed to ignore the "domain" field completely and
4426 // instead use the search domain list as the sole authority for what domains to search and in what order
4427 // (and the domain from the "domain" field will also appear somewhere in that list).
4428 // Also, all search domains get added to the search list for resolver[0], so the domains and/or
4429 // search lists for other resolvers in the list need to be ignored.
4430 if (config
->resolver
[0]->n_search
== 0) mDNS_AddSearchDomain_CString(config
->resolver
[0]->domain
);
4431 else for (i
= 0; i
< config
->resolver
[0]->n_search
; i
++) mDNS_AddSearchDomain_CString(config
->resolver
[0]->search
[i
]);
4434 #if APPLE_OSX_mDNSResponder
4435 // Record the so-called "primary" domain, which we use as a hint to tell if the user is on a network set up
4436 // by someone using Microsoft Active Directory using "local" as a private internal top-level domain
4437 if (config
->n_resolver
&& config
->resolver
[0]->domain
&& config
->resolver
[0]->n_nameserver
&& config
->resolver
[0]->nameserver
[0])
4438 MakeDomainNameFromDNSNameString(&ActiveDirectoryPrimaryDomain
, config
->resolver
[0]->domain
);
4439 else ActiveDirectoryPrimaryDomain
.c
[0] = 0;
4440 //MakeDomainNameFromDNSNameString(&ActiveDirectoryPrimaryDomain, "test.local");
4441 ActiveDirectoryPrimaryDomainLabelCount
= CountLabels(&ActiveDirectoryPrimaryDomain
);
4442 if (config
->n_resolver
&& config
->resolver
[0]->n_nameserver
&& SameDomainName(SkipLeadingLabels(&ActiveDirectoryPrimaryDomain
, ActiveDirectoryPrimaryDomainLabelCount
- 1), &localdomain
))
4443 SetupAddr(&ActiveDirectoryPrimaryDomainServer
, config
->resolver
[0]->nameserver
[0]);
4446 AssignDomainName(&ActiveDirectoryPrimaryDomain
, (const domainname
*)"");
4447 ActiveDirectoryPrimaryDomainLabelCount
= 0;
4448 ActiveDirectoryPrimaryDomainServer
= zeroAddr
;
4454 // For the "default" resolver ("resolver #1") the "domain" value is bogus and we need to ignore it.
4455 // e.g. the default resolver's "domain" value might say "apple.com", which indicates that this resolver
4456 // is only for names that fall under "apple.com", but that's not correct. Actually the default resolver is
4457 // for all names not covered by a more specific resolver (i.e. its domain should be ".", the root domain).
4458 if (config
->n_resolver
&& config
->resolver
[0]->domain
)
4459 config
->resolver
[0]->domain
[0] = 0; // don't stop pointing at the memory, just change the first byte
4461 qsort(config
->resolver
, config
->n_resolver
, sizeof(dns_resolver_t
*), compare_dns_configs
);
4463 for (i
= 0; i
< config
->n_resolver
; i
++)
4466 dns_resolver_t
*r
= config
->resolver
[i
];
4467 mDNSInterfaceID interface
= mDNSInterface_Any
;
4470 // On Tiger, dnsinfo entries for mDNS domains have port 5353, the mDNS port. Ignore them.
4471 // Note: Unlike the BSD Sockets APIs (where TCP and UDP port numbers are universally in network byte order)
4472 // in Apple's "dnsinfo.h" API the port number is declared to be a "uint16_t in host byte order"
4473 // We also don't need to do any more work if there are no nameserver addresses
4474 if (r
->port
== 5353 || r
->n_nameserver
== 0) continue;
4476 if (!r
->domain
|| !*r
->domain
) d
.c
[0] = 0;
4477 else if (!MakeDomainNameFromDNSNameString(&d
, r
->domain
)) { LogMsg("mDNSPlatformSetDNSConfig: bad domain %s", r
->domain
); continue; }
4479 // DNS server option parsing
4480 if (r
->options
!= NULL
)
4482 char *nextOption
= r
->options
;
4483 char *currentOption
= NULL
;
4484 while ((currentOption
= strsep(&nextOption
, " ")) != NULL
&& currentOption
[0] != 0)
4486 // The option may be in the form of interface=xxx where xxx is an interface name.
4487 if (strncmp(currentOption
, kInterfaceSpecificOption
, sizeof(kInterfaceSpecificOption
) - 1) == 0)
4489 NetworkInterfaceInfoOSX
*ni
;
4490 char ifname
[IF_NAMESIZE
+1];
4491 mDNSu32 ifindex
= 0;
4492 // If something goes wrong finding the interface, create the server entry anyhow but mark it as disabled.
4493 // This allows us to block these special queries from going out on the wire.
4494 strlcpy(ifname
, currentOption
+ sizeof(kInterfaceSpecificOption
)-1, sizeof(ifname
));
4495 ifindex
= if_nametoindex(ifname
);
4496 if (ifindex
== 0) { disabled
= 1; LogMsg("RegisterSplitDNS: interfaceSpecific - interface %s not found", ifname
); continue; }
4497 LogInfo("%s: Interface-specific entry: %s on %s (%d)", __FUNCTION__
, r
->domain
, ifname
, ifindex
);
4498 // Find the interface, can't use mDNSPlatformInterfaceIDFromInterfaceIndex
4499 // because that will call mDNSMacOSXNetworkChanged if the interface doesn't exist
4500 for (ni
= m
->p
->InterfaceList
; ni
; ni
= ni
->next
)
4501 if (ni
->ifinfo
.InterfaceID
&& ni
->scope_id
== ifindex
) break;
4502 if (ni
!= NULL
) interface
= ni
->ifinfo
.InterfaceID
;
4503 if (interface
== mDNSNULL
) { disabled
= 1; LogMsg("RegisterSplitDNS: interfaceSpecific - index %d (%s) not found", ifindex
, ifname
); continue; }
4508 for (n
= 0; n
< r
->n_nameserver
; n
++)
4509 if (r
->nameserver
[n
]->sa_family
== AF_INET
|| r
->nameserver
[n
]->sa_family
== AF_INET6
)
4512 // mDNSAddr saddr = { mDNSAddrType_IPv4, { { { 192, 168, 1, 1 } } } }; // for testing
4513 if (SetupAddr(&saddr
, r
->nameserver
[n
])) LogMsg("RegisterSplitDNS: bad IP address");
4516 DNSServer
*s
= mDNS_AddDNSServer(m
, &d
, interface
, &saddr
, r
->port
? mDNSOpaque16fromIntVal(r
->port
) : UnicastDNSPort
);
4519 if (disabled
) s
->teststate
= DNSServer_Disabled
;
4520 LogInfo("Added dns server %#a:%d for domain %##s from slot %d,%d", &s
->addr
, mDNSVal16(s
->port
), d
.c
, i
, n
);
4528 dns_configuration_free(config
);
4529 setservers
= mDNSfalse
; // Done these now -- no need to fetch the same data from SCDynamicStore
4530 setsearch
= mDNSfalse
;
4533 #endif // MDNS_NO_DNSINFO
4535 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:mDNSPlatformSetDNSConfig"), NULL
, NULL
);
4537 LogMsg("mDNSPlatformSetDNSConfig: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
4540 CFDictionaryRef ddnsdict
= SCDynamicStoreCopyValue(store
, NetworkChangedKey_DynamicDNS
);
4545 CFArrayRef fqdnArray
= CFDictionaryGetValue(ddnsdict
, CFSTR("HostNames"));
4546 if (fqdnArray
&& CFArrayGetCount(fqdnArray
) > 0)
4548 // for now, we only look at the first array element. if we ever support multiple configurations, we will walk the list
4549 CFDictionaryRef fqdnDict
= CFArrayGetValueAtIndex(fqdnArray
, 0);
4550 if (fqdnDict
&& DictionaryIsEnabled(fqdnDict
))
4552 CFStringRef name
= CFDictionaryGetValue(fqdnDict
, CFSTR("Domain"));
4555 if (!CFStringGetCString(name
, buf
, sizeof(buf
), kCFStringEncodingUTF8
) ||
4556 !MakeDomainNameFromDNSNameString(fqdn
, buf
) || !fqdn
->c
[0])
4557 LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS host name: %s", buf
[0] ? buf
: "(unknown)");
4558 else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS host name: %s", buf
);
4566 CFArrayRef regArray
= CFDictionaryGetValue(ddnsdict
, CFSTR("RegistrationDomains"));
4567 if (regArray
&& CFArrayGetCount(regArray
) > 0)
4569 CFDictionaryRef regDict
= CFArrayGetValueAtIndex(regArray
, 0);
4570 if (regDict
&& DictionaryIsEnabled(regDict
))
4572 CFStringRef name
= CFDictionaryGetValue(regDict
, CFSTR("Domain"));
4575 if (!CFStringGetCString(name
, buf
, sizeof(buf
), kCFStringEncodingUTF8
) ||
4576 !MakeDomainNameFromDNSNameString(&d
, buf
) || !d
.c
[0])
4577 LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS registration domain: %s", buf
[0] ? buf
: "(unknown)");
4580 debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS registration domain: %s", buf
);
4581 AppendDNameListElem(&RegDomains
, 0, &d
);
4590 CFArrayRef browseArray
= CFDictionaryGetValue(ddnsdict
, CFSTR("BrowseDomains"));
4593 for (i
= 0; i
< CFArrayGetCount(browseArray
); i
++)
4595 CFDictionaryRef browseDict
= CFArrayGetValueAtIndex(browseArray
, i
);
4596 if (browseDict
&& DictionaryIsEnabled(browseDict
))
4598 CFStringRef name
= CFDictionaryGetValue(browseDict
, CFSTR("Domain"));
4601 if (!CFStringGetCString(name
, buf
, sizeof(buf
), kCFStringEncodingUTF8
) ||
4602 !MakeDomainNameFromDNSNameString(&d
, buf
) || !d
.c
[0])
4603 LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS browsing domain: %s", buf
[0] ? buf
: "(unknown)");
4606 debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS browsing domain: %s", buf
);
4607 AppendDNameListElem(&BrowseDomains
, 0, &d
);
4614 CFRelease(ddnsdict
);
4619 CFDictionaryRef btmm
= SCDynamicStoreCopyValue(store
, NetworkChangedKey_BackToMyMac
);
4622 CFIndex size
= CFDictionaryGetCount(btmm
);
4623 const void *key
[size
];
4624 const void *val
[size
];
4625 CFDictionaryGetKeysAndValues(btmm
, key
, val
);
4626 for (i
= 0; i
< size
; i
++)
4628 LogInfo("BackToMyMac %d", i
);
4629 if (!CFStringGetCString(key
[i
], buf
, sizeof(buf
), kCFStringEncodingUTF8
))
4630 LogMsg("Can't read BackToMyMac %d key %s", i
, buf
);
4633 mDNSu32 uid
= atoi(buf
);
4634 if (!CFStringGetCString(val
[i
], buf
, sizeof(buf
), kCFStringEncodingUTF8
))
4635 LogMsg("Can't read BackToMyMac %d val %s", i
, buf
);
4636 else if (MakeDomainNameFromDNSNameString(&d
, buf
) && d
.c
[0])
4638 LogInfo("BackToMyMac %d %d %##s", i
, uid
, d
.c
);
4639 AppendDNameListElem(&RegDomains
, uid
, &d
);
4647 if (setservers
|| setsearch
)
4649 CFDictionaryRef dict
= SCDynamicStoreCopyValue(store
, NetworkChangedKey_DNS
);
4654 CFArrayRef values
= CFDictionaryGetValue(dict
, kSCPropNetDNSServerAddresses
);
4657 LogInfo("DNS Server Address values: %d", CFArrayGetCount(values
));
4658 for (i
= 0; i
< CFArrayGetCount(values
); i
++)
4660 CFStringRef s
= CFArrayGetValueAtIndex(values
, i
);
4661 mDNSAddr addr
= { mDNSAddrType_IPv4
, { { { 0 } } } };
4662 if (s
&& CFStringGetCString(s
, buf
, 256, kCFStringEncodingUTF8
) &&
4663 inet_aton(buf
, (struct in_addr
*) &addr
.ip
.v4
))
4665 LogInfo("Adding DNS server from dict: %s", buf
);
4666 mDNS_AddDNSServer(m
, mDNSNULL
, mDNSInterface_Any
, &addr
, UnicastDNSPort
);
4670 else LogInfo("No DNS Server Address values");
4674 // Add the manual and/or DHCP-dicovered search domains
4675 CFArrayRef searchDomains
= CFDictionaryGetValue(dict
, kSCPropNetDNSSearchDomains
);
4678 for (i
= 0; i
< CFArrayGetCount(searchDomains
); i
++)
4680 CFStringRef s
= CFArrayGetValueAtIndex(searchDomains
, i
);
4681 if (s
&& CFStringGetCString(s
, buf
, sizeof(buf
), kCFStringEncodingUTF8
))
4682 mDNS_AddSearchDomain_CString(buf
);
4685 else // No kSCPropNetDNSSearchDomains, so use kSCPropNetDNSDomainName
4687 // Due to the vagaries of Apple's SystemConfiguration and dnsinfo.h APIs, if there are no search domains
4688 // listed, then you're supposed to interpret the "domain" field as also being the search domain, but if
4689 // there *are* search domains listed, then you're supposed to ignore the "domain" field completely and
4690 // instead use the search domain list as the sole authority for what domains to search and in what order
4691 // (and the domain from the "domain" field will also appear somewhere in that list).
4692 CFStringRef string
= CFDictionaryGetValue(dict
, kSCPropNetDNSDomainName
);
4693 if (string
&& CFStringGetCString(string
, buf
, sizeof(buf
), kCFStringEncodingUTF8
))
4694 mDNS_AddSearchDomain_CString(buf
);
4704 mDNSexport mStatus
mDNSPlatformGetPrimaryInterface(mDNS
*const m
, mDNSAddr
*v4
, mDNSAddr
*v6
, mDNSAddr
*r
)
4710 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:mDNSPlatformGetPrimaryInterface"), NULL
, NULL
);
4712 LogMsg("mDNSPlatformGetPrimaryInterface: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
4715 CFDictionaryRef dict
= SCDynamicStoreCopyValue(store
, NetworkChangedKey_IPv4
);
4718 r
->type
= mDNSAddrType_IPv4
;
4719 r
->ip
.v4
= zerov4Addr
;
4720 CFStringRef string
= CFDictionaryGetValue(dict
, kSCPropNetIPv4Router
);
4723 if (!CFStringGetCString(string
, buf
, 256, kCFStringEncodingUTF8
))
4724 LogMsg("Could not convert router to CString");
4727 struct sockaddr_in saddr
;
4728 saddr
.sin_len
= sizeof(saddr
);
4729 saddr
.sin_family
= AF_INET
;
4731 inet_aton(buf
, &saddr
.sin_addr
);
4733 *(in_addr_t
*)&r
->ip
.v4
= saddr
.sin_addr
.s_addr
;
4737 string
= CFDictionaryGetValue(dict
, kSCDynamicStorePropNetPrimaryInterface
);
4740 mDNSBool HavePrimaryGlobalv6
= mDNSfalse
; // does the primary interface have a global v6 address?
4741 struct ifaddrs
*ifa
= myGetIfAddrs(1);
4743 *v4
= *v6
= zeroAddr
;
4745 if (!CFStringGetCString(string
, buf
, 256, kCFStringEncodingUTF8
)) { LogMsg("Could not convert router to CString"); goto exit
; }
4747 // find primary interface in list
4748 while (ifa
&& (mDNSIPv4AddressIsZero(v4
->ip
.v4
) || mDNSv4AddressIsLinkLocal(&v4
->ip
.v4
) || !HavePrimaryGlobalv6
))
4750 mDNSAddr tmp6
= zeroAddr
;
4751 if (!strcmp(buf
, ifa
->ifa_name
))
4753 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
4755 if (mDNSIPv4AddressIsZero(v4
->ip
.v4
) || mDNSv4AddressIsLinkLocal(&v4
->ip
.v4
)) SetupAddr(v4
, ifa
->ifa_addr
);
4757 else if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
4759 SetupAddr(&tmp6
, ifa
->ifa_addr
);
4760 if (tmp6
.ip
.v6
.b
[0] >> 5 == 1) // global prefix: 001
4761 { HavePrimaryGlobalv6
= mDNStrue
; *v6
= tmp6
; }
4766 // We'll take a V6 address from the non-primary interface if the primary interface doesn't have a global V6 address
4767 if (!HavePrimaryGlobalv6
&& ifa
->ifa_addr
->sa_family
== AF_INET6
&& !v6
->ip
.v6
.b
[0])
4769 SetupAddr(&tmp6
, ifa
->ifa_addr
);
4770 if (tmp6
.ip
.v6
.b
[0] >> 5 == 1) *v6
= tmp6
;
4773 ifa
= ifa
->ifa_next
;
4776 // Note that while we advertise v6, we still require v4 (possibly NAT'd, but not link-local) because we must use
4777 // V4 to communicate w/ our DNS server
4788 mDNSexport
void mDNSPlatformDynDNSHostNameStatusChanged(const domainname
*const dname
, const mStatus status
)
4790 LogInfo("mDNSPlatformDynDNSHostNameStatusChanged %d %##s", status
, dname
->c
);
4791 char uname
[MAX_ESCAPED_DOMAIN_NAME
]; // Max legal C-string name, including terminating NUL
4792 ConvertDomainNameToCString(dname
, uname
);
4798 if (!(*(p
+1)) && *p
== '.') *p
= 0; // if last character, strip trailing dot
4802 // We need to make a CFDictionary called "State:/Network/DynamicDNS" containing (at present) a single entity.
4803 // That single entity is a CFDictionary with name "HostNames".
4804 // The "HostNames" CFDictionary contains a set of name/value pairs, where the each name is the FQDN
4805 // in question, and the corresponding value is a CFDictionary giving the state for that FQDN.
4806 // (At present we only support a single FQDN, so this dictionary holds just a single name/value pair.)
4807 // The CFDictionary for each FQDN holds (at present) a single name/value pair,
4808 // where the name is "Status" and the value is a CFNumber giving an errror code (with zero meaning success).
4810 const CFStringRef StateKeys
[1] = { CFSTR("HostNames") };
4811 const CFStringRef HostKeys
[1] = { CFStringCreateWithCString(NULL
, uname
, kCFStringEncodingUTF8
) };
4812 const CFStringRef StatusKeys
[1] = { CFSTR("Status") };
4813 if (!HostKeys
[0]) LogMsg("SetDDNSNameStatus: CFStringCreateWithCString(%s) failed", uname
);
4816 const CFNumberRef StatusVals
[1] = { CFNumberCreate(NULL
, kCFNumberSInt32Type
, &status
) };
4817 if (!StatusVals
[0]) LogMsg("SetDDNSNameStatus: CFNumberCreate(%d) failed", status
);
4820 const CFDictionaryRef HostVals
[1] = { CFDictionaryCreate(NULL
, (void*)StatusKeys
, (void*)StatusVals
, 1, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
) };
4823 const CFDictionaryRef StateVals
[1] = { CFDictionaryCreate(NULL
, (void*)HostKeys
, (void*)HostVals
, 1, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
) };
4826 CFDictionaryRef StateDict
= CFDictionaryCreate(NULL
, (void*)StateKeys
, (void*)StateVals
, 1, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
4829 mDNSDynamicStoreSetConfig(kmDNSDynamicConfig
, mDNSNULL
, StateDict
);
4830 CFRelease(StateDict
);
4832 CFRelease(StateVals
[0]);
4834 CFRelease(HostVals
[0]);
4836 CFRelease(StatusVals
[0]);
4838 CFRelease(HostKeys
[0]);
4842 // MUST be called holding the lock -- this routine calls SetupLocalAutoTunnelInterface_internal()
4843 mDNSexport
void SetDomainSecrets(mDNS
*m
)
4845 #ifdef NO_SECURITYFRAMEWORK
4847 LogMsg("Note: SetDomainSecrets: no keychain support");
4849 mDNSBool haveAutoTunnels
= mDNSfalse
;
4851 LogInfo("SetDomainSecrets");
4853 // Rather than immediately deleting all keys now, we mark them for deletion in ten seconds.
4854 // In the case where the user simultaneously removes their DDNS host name and the key
4855 // for it, this gives mDNSResponder ten seconds to gracefully delete the name from the
4856 // server before it loses access to the necessary key. Otherwise, we'd leave orphaned
4857 // address records behind that we no longer have permission to delete.
4858 DomainAuthInfo
*ptr
;
4859 for (ptr
= m
->AuthInfoList
; ptr
; ptr
= ptr
->next
)
4860 ptr
->deltime
= NonZeroTime(m
->timenow
+ mDNSPlatformOneSecond
*10);
4862 #if APPLE_OSX_mDNSResponder
4864 // Mark all TunnelClients for deletion
4865 ClientTunnel
*client
;
4866 for (client
= m
->TunnelClients
; client
; client
= client
->next
)
4868 LogInfo("SetDomainSecrets: tunnel to %##s marked for deletion", client
->dstname
.c
);
4869 client
->MarkedForDeletion
= mDNStrue
;
4872 #endif // APPLE_OSX_mDNSResponder
4874 // String Array used to write list of private domains to Dynamic Store
4875 CFMutableArrayRef sa
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
4876 if (!sa
) { LogMsg("SetDomainSecrets: CFArrayCreateMutable failed"); return; }
4878 CFDataRef data
= NULL
;
4879 const int itemsPerEntry
= 3; // domain name, key name, key value
4880 CFArrayRef secrets
= NULL
;
4881 int err
= mDNSKeychainGetSecrets(&secrets
);
4882 if (err
|| !secrets
)
4883 LogMsg("SetDomainSecrets: mDNSKeychainGetSecrets failed error %d CFArrayRef %p", err
, secrets
);
4886 CFIndex ArrayCount
= CFArrayGetCount(secrets
);
4887 // Iterate through the secrets
4888 for (i
= 0; i
< ArrayCount
; ++i
)
4891 CFArrayRef entry
= CFArrayGetValueAtIndex(secrets
, i
);
4892 if (CFArrayGetTypeID() != CFGetTypeID(entry
) || itemsPerEntry
!= CFArrayGetCount(entry
))
4893 { LogMsg("SetDomainSecrets: malformed entry"); continue; }
4894 for (j
= 0; j
< CFArrayGetCount(entry
); ++j
)
4895 if (CFDataGetTypeID() != CFGetTypeID(CFArrayGetValueAtIndex(entry
, j
)))
4896 { LogMsg("SetDomainSecrets: malformed entry item"); continue; }
4898 // The names have already been vetted by the helper, but checking them again here helps humans and automated tools verify correctness
4900 // Get DNS domain this key is for
4901 char stringbuf
[MAX_ESCAPED_DOMAIN_NAME
]; // Max legal domainname as C-string, including terminating NUL
4902 data
= CFArrayGetValueAtIndex(entry
, 0);
4903 if (CFDataGetLength(data
) >= (int)sizeof(stringbuf
))
4904 { LogMsg("SetDomainSecrets: Bad kSecServiceItemAttr length %d", CFDataGetLength(data
)); continue; }
4905 CFDataGetBytes(data
, CFRangeMake(0, CFDataGetLength(data
)), (UInt8
*)stringbuf
);
4906 stringbuf
[CFDataGetLength(data
)] = '\0';
4909 if (!MakeDomainNameFromDNSNameString(&domain
, stringbuf
)) { LogMsg("SetDomainSecrets: bad key domain %s", stringbuf
); continue; }
4912 data
= CFArrayGetValueAtIndex(entry
, 1);
4913 if (CFDataGetLength(data
) >= (int)sizeof(stringbuf
))
4914 { LogMsg("SetDomainSecrets: Bad kSecAccountItemAttr length %d", CFDataGetLength(data
)); continue; }
4915 CFDataGetBytes(data
, CFRangeMake(0,CFDataGetLength(data
)), (UInt8
*)stringbuf
);
4916 stringbuf
[CFDataGetLength(data
)] = '\0';
4919 if (!MakeDomainNameFromDNSNameString(&keyname
, stringbuf
)) { LogMsg("SetDomainSecrets: bad key name %s", stringbuf
); continue; }
4922 data
= CFArrayGetValueAtIndex(entry
, 2);
4923 if (CFDataGetLength(data
) >= (int)sizeof(stringbuf
))
4924 { LogMsg("SetDomainSecrets: Shared secret too long: %d", CFDataGetLength(data
)); continue; }
4925 CFDataGetBytes(data
, CFRangeMake(0, CFDataGetLength(data
)), (UInt8
*)stringbuf
);
4926 stringbuf
[CFDataGetLength(data
)] = '\0'; // mDNS_SetSecretForDomain requires NULL-terminated C string for key
4928 DomainAuthInfo
*FoundInList
;
4929 for (FoundInList
= m
->AuthInfoList
; FoundInList
; FoundInList
= FoundInList
->next
)
4930 if (SameDomainName(&FoundInList
->domain
, &domain
)) break;
4932 #if APPLE_OSX_mDNSResponder
4935 // If any client tunnel destination is in this domain, set deletion flag to false
4936 ClientTunnel
*client
;
4937 for (client
= m
->TunnelClients
; client
; client
= client
->next
)
4938 if (FoundInList
== GetAuthInfoForName_internal(m
, &client
->dstname
))
4940 LogInfo("SetDomainSecrets: tunnel to %##s no longer marked for deletion", client
->dstname
.c
);
4941 client
->MarkedForDeletion
= mDNSfalse
;
4945 #endif // APPLE_OSX_mDNSResponder
4947 // Uncomment the line below to view the keys as they're read out of the system keychain
4948 // DO NOT SHIP CODE THIS WAY OR YOU'LL LEAK SECRET DATA INTO A PUBLICLY READABLE FILE!
4949 //LogInfo("SetDomainSecrets: %##s %##s %s", &domain.c, &keyname.c, stringbuf);
4951 // If didn't find desired domain in the list, make a new entry
4953 if (FoundInList
&& FoundInList
->AutoTunnel
&& haveAutoTunnels
== mDNSfalse
) haveAutoTunnels
= mDNStrue
;
4956 ptr
= (DomainAuthInfo
*)mallocL("DomainAuthInfo", sizeof(*ptr
));
4957 if (!ptr
) { LogMsg("SetDomainSecrets: No memory"); continue; }
4960 LogInfo("SetDomainSecrets: %d of %d %##s", i
, ArrayCount
, &domain
);
4961 if (mDNS_SetSecretForDomain(m
, ptr
, &domain
, &keyname
, stringbuf
, IsTunnelModeDomain(&domain
)) == mStatus_BadParamErr
)
4963 if (!FoundInList
) mDNSPlatformMemFree(ptr
); // If we made a new DomainAuthInfo here, and it turned out bad, dispose it immediately
4967 #if APPLE_OSX_mDNSResponder
4968 if (ptr
->AutoTunnel
) UpdateAutoTunnelDomainStatus(m
, ptr
);
4969 #endif // APPLE_OSX_mDNSResponder
4971 ConvertDomainNameToCString(&domain
, stringbuf
);
4972 CFStringRef cfs
= CFStringCreateWithCString(NULL
, stringbuf
, kCFStringEncodingUTF8
);
4973 if (cfs
) { CFArrayAppendValue(sa
, cfs
); CFRelease(cfs
); }
4977 mDNSDynamicStoreSetConfig(kmDNSPrivateConfig
, mDNSNULL
, sa
);
4980 #if APPLE_OSX_mDNSResponder
4982 // clean up ClientTunnels
4983 ClientTunnel
**pp
= &m
->TunnelClients
;
4986 if ((*pp
)->MarkedForDeletion
)
4988 ClientTunnel
*cur
= *pp
;
4989 LogInfo("SetDomainSecrets: removing client %p %##s from list", cur
, cur
->dstname
.c
);
4990 if (cur
->q
.ThisQInterval
>= 0) mDNS_StopQuery(m
, &cur
->q
);
4991 AutoTunnelSetKeys(cur
, mDNSfalse
);
4993 freeL("ClientTunnel", cur
);
4999 DomainAuthInfo
*info
= m
->AuthInfoList
;
5002 if (info
->AutoTunnel
&& info
->deltime
)
5004 if (info
->AutoTunnelNAT
.clientContext
)
5006 // stop the NAT operation
5007 mDNS_StopNATOperation_internal(m
, &info
->AutoTunnelNAT
);
5008 if (info
->AutoTunnelNAT
.clientCallback
)
5010 // Reset port and let the AutoTunnelNATCallback handle cleanup
5011 info
->AutoTunnelNAT
.ExternalAddress
= m
->ExternalAddress
;
5012 info
->AutoTunnelNAT
.ExternalPort
= zeroIPPort
;
5013 info
->AutoTunnelNAT
.Lifetime
= 0;
5014 info
->AutoTunnelNAT
.Result
= mStatus_NoError
;
5015 mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback
5016 info
->AutoTunnelNAT
.clientCallback(m
, &info
->AutoTunnelNAT
);
5017 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again
5019 info
->AutoTunnelNAT
.clientContext
= mDNSNULL
;
5021 RemoveAutoTunnelDomainStatus(m
, info
);
5026 if (!haveAutoTunnels
&& !m
->TunnelClients
&& m
->AutoTunnelHostAddrActive
)
5028 // remove interface if no autotunnel servers and no more client tunnels
5029 LogInfo("SetDomainSecrets: Bringing tunnel interface DOWN");
5030 m
->AutoTunnelHostAddrActive
= mDNSfalse
;
5031 (void)mDNSAutoTunnelInterfaceUpDown(kmDNSDown
, m
->AutoTunnelHostAddr
.b
);
5032 mDNSPlatformMemZero(m
->AutoTunnelHostAddr
.b
, sizeof(m
->AutoTunnelHostAddr
.b
));
5035 UpdateConfigureServer(m
);
5037 if (m
->AutoTunnelHostAddr
.b
[0])
5038 if (TunnelClients(m
) || TunnelServers(m
))
5039 SetupLocalAutoTunnelInterface_internal(m
);
5041 #endif // APPLE_OSX_mDNSResponder
5043 #endif /* NO_SECURITYFRAMEWORK */
5046 mDNSlocal
void SetLocalDomains(void)
5048 CFMutableArrayRef sa
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
5049 if (!sa
) { LogMsg("SetLocalDomains: CFArrayCreateMutable failed"); return; }
5051 CFArrayAppendValue(sa
, CFSTR("local"));
5052 CFArrayAppendValue(sa
, CFSTR("254.169.in-addr.arpa"));
5053 CFArrayAppendValue(sa
, CFSTR("8.e.f.ip6.arpa"));
5054 CFArrayAppendValue(sa
, CFSTR("9.e.f.ip6.arpa"));
5055 CFArrayAppendValue(sa
, CFSTR("a.e.f.ip6.arpa"));
5056 CFArrayAppendValue(sa
, CFSTR("b.e.f.ip6.arpa"));
5058 mDNSDynamicStoreSetConfig(kmDNSMulticastConfig
, mDNSNULL
, sa
);
5062 mDNSlocal
void GetCurrentPMSetting(const CFStringRef name
, mDNSs32
*val
)
5064 #if USE_IOPMCOPYACTIVEPMPREFERENCES
5065 CFTypeRef blob
= NULL
;
5066 CFStringRef str
= NULL
;
5067 CFDictionaryRef odict
= NULL
;
5068 CFDictionaryRef idict
= NULL
;
5069 CFNumberRef number
= NULL
;
5071 blob
= IOPSCopyPowerSourcesInfo();
5072 if (!blob
) { LogMsg("GetCurrentPMSetting: IOPSCopyPowerSourcesInfo failed!"); goto end
; }
5074 odict
= IOPMCopyActivePMPreferences();
5075 if (!odict
) { LogMsg("GetCurrentPMSetting: IOPMCopyActivePMPreferences failed!"); goto end
; }
5077 str
= IOPSGetProvidingPowerSourceType(blob
);
5078 if (!str
) { LogMsg("GetCurrentPMSetting: IOPSGetProvidingPowerSourceType failed!"); goto end
; }
5080 idict
= CFDictionaryGetValue(odict
, str
);
5084 if (!CFStringGetCString(str
, buf
, sizeof(buf
), kCFStringEncodingUTF8
)) buf
[0] = 0;
5085 LogMsg("GetCurrentPMSetting: CFDictionaryGetValue (%s) failed!", buf
);
5089 number
= CFDictionaryGetValue(idict
, name
);
5090 if (!number
|| CFGetTypeID(number
) != CFNumberGetTypeID() || !CFNumberGetValue(number
, kCFNumberSInt32Type
, val
))
5093 if (blob
) CFRelease(blob
);
5094 if (odict
) CFRelease(odict
);
5098 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:GetCurrentPMSetting"), NULL
, NULL
);
5099 if (!store
) LogMsg("GetCurrentPMSetting: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
5102 CFDictionaryRef dict
= SCDynamicStoreCopyValue(store
, CFSTR("State:/IOKit/PowerManagement/CurrentSettings"));
5103 if (!dict
) LogSPS("GetCurrentPMSetting: Could not get IOPM CurrentSettings dict");
5106 CFNumberRef number
= CFDictionaryGetValue(dict
, name
);
5107 if (!number
|| CFGetTypeID(number
) != CFNumberGetTypeID() || !CFNumberGetValue(number
, kCFNumberSInt32Type
, val
))
5117 #if APPLE_OSX_mDNSResponder
5119 static CFMutableDictionaryRef spsStatusDict
= NULL
;
5120 static const CFStringRef kMetricRef
= CFSTR("Metric");
5122 mDNSlocal
void SPSStatusPutNumber(CFMutableDictionaryRef dict
, const mDNSu8
* const ptr
, CFStringRef key
)
5124 mDNSu8 tmp
= (ptr
[0] - '0') * 10 + ptr
[1] - '0';
5125 CFNumberRef num
= CFNumberCreate(NULL
, kCFNumberSInt8Type
, &tmp
);
5127 LogMsg("SPSStatusPutNumber: Could not create CFNumber");
5130 CFDictionarySetValue(dict
, key
, num
);
5135 mDNSlocal CFMutableDictionaryRef
SPSCreateDict(const mDNSu8
* const ptr
)
5137 CFMutableDictionaryRef dict
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
5138 if (!dict
) { LogMsg("SPSCreateDict: Could not create CFDictionary dict"); return dict
; }
5141 buffer
[mDNS_snprintf(buffer
, sizeof(buffer
), "%##s", ptr
) - 1] = 0;
5142 CFStringRef spsname
= CFStringCreateWithCString(NULL
, buffer
, kCFStringEncodingUTF8
);
5143 if (!spsname
) { LogMsg("SPSCreateDict: Could not create CFString spsname full"); CFRelease(dict
); return NULL
; }
5144 CFDictionarySetValue(dict
, CFSTR("FullName"), spsname
);
5147 if (ptr
[0] >= 2) SPSStatusPutNumber(dict
, ptr
+ 1, CFSTR("Type"));
5148 if (ptr
[0] >= 5) SPSStatusPutNumber(dict
, ptr
+ 4, CFSTR("Portability"));
5149 if (ptr
[0] >= 8) SPSStatusPutNumber(dict
, ptr
+ 7, CFSTR("MarginalPower"));
5150 if (ptr
[0] >= 11) SPSStatusPutNumber(dict
, ptr
+10, CFSTR("TotalPower"));
5152 mDNSu32 tmp
= SPSMetric(ptr
);
5153 CFNumberRef num
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &tmp
);
5155 LogMsg("SPSCreateDict: Could not create CFNumber");
5158 CFDictionarySetValue(dict
, kMetricRef
, num
);
5164 memcpy(buffer
, ptr
+ 13, ptr
[0] - 12);
5165 buffer
[ptr
[0] - 12] = 0;
5166 spsname
= CFStringCreateWithCString(NULL
, buffer
, kCFStringEncodingUTF8
);
5167 if (!spsname
) { LogMsg("SPSCreateDict: Could not create CFString spsname"); CFRelease(dict
); return NULL
; }
5170 CFDictionarySetValue(dict
, CFSTR("PrettyName"), spsname
);
5178 mDNSlocal CFComparisonResult
CompareSPSEntries(const void *val1
, const void *val2
, void *context
)
5181 return CFNumberCompare((CFNumberRef
)CFDictionaryGetValue((CFDictionaryRef
)val1
, kMetricRef
),
5182 (CFNumberRef
)CFDictionaryGetValue((CFDictionaryRef
)val2
, kMetricRef
),
5186 mDNSlocal
void UpdateSPSStatus(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
5189 NetworkInterfaceInfo
* info
= (NetworkInterfaceInfo
*)question
->QuestionContext
;
5190 debugf("UpdateSPSStatus: %s %##s %s %s", info
->ifname
, question
->qname
.c
, AddRecord
? "Add" : "Rmv", answer
? RRDisplayString(m
, answer
) : "<null>");
5192 if (answer
&& SPSMetric(answer
->rdata
->u
.name
.c
) > 999999) return; // Ignore instances with invalid names
5196 spsStatusDict
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
5197 if (!spsStatusDict
) { LogMsg("UpdateSPSStatus: Could not create CFDictionary spsStatusDict"); return; }
5200 CFStringRef ifname
= CFStringCreateWithCString(NULL
, info
->ifname
, kCFStringEncodingUTF8
);
5201 if (!ifname
) { LogMsg("UpdateSPSStatus: Could not create CFString ifname"); return; }
5203 CFMutableArrayRef array
= NULL
;
5205 if (!CFDictionaryGetValueIfPresent(spsStatusDict
, ifname
, (const void**) &array
))
5207 array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
5208 if (!array
) { LogMsg("UpdateSPSStatus: Could not create CFMutableArray"); CFRelease(ifname
); return; }
5209 CFDictionarySetValue(spsStatusDict
, ifname
, array
);
5210 CFRelease(array
); // let go of our reference, now that the dict has one
5213 if (!array
) { LogMsg("UpdateSPSStatus: Could not get CFMutableArray for %s", info
->ifname
); CFRelease(ifname
); return; }
5215 if (!answer
) // special call that means the question has been stopped (because the interface is going away)
5216 CFArrayRemoveAllValues(array
);
5219 CFMutableDictionaryRef dict
= SPSCreateDict(answer
->rdata
->u
.name
.c
);
5220 if (!dict
) { CFRelease(ifname
); return; }
5224 if (!CFArrayContainsValue(array
, CFRangeMake(0, CFArrayGetCount(array
)), dict
))
5227 for (i
=0; i
<CFArrayGetCount(array
); i
++)
5228 if (CompareSPSEntries(CFArrayGetValueAtIndex(array
, i
), dict
, NULL
) != kCFCompareLessThan
)
5230 CFArrayInsertValueAtIndex(array
, i
, dict
);
5232 else LogMsg("UpdateSPSStatus: %s array already contains %##s", info
->ifname
, answer
->rdata
->u
.name
.c
);
5236 CFIndex i
= CFArrayGetFirstIndexOfValue(array
, CFRangeMake(0, CFArrayGetCount(array
)), dict
);
5237 if (i
!= -1) CFArrayRemoveValueAtIndex(array
, i
);
5238 else LogMsg("UpdateSPSStatus: %s array does not contain %##s", info
->ifname
, answer
->rdata
->u
.name
.c
);
5244 if (!m
->ShutdownTime
) mDNSDynamicStoreSetConfig(kmDNSSleepProxyServersState
, info
->ifname
, array
);
5249 mDNSlocal mDNSs32
GetSystemSleepTimerSetting(void)
5252 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:GetSystemSleepTimerSetting"), NULL
, NULL
);
5254 LogMsg("GetSystemSleepTimerSetting: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
5257 CFDictionaryRef dict
= SCDynamicStoreCopyValue(store
, CFSTR("State:/IOKit/PowerManagement/CurrentSettings"));
5260 CFNumberRef number
= CFDictionaryGetValue(dict
, CFSTR("System Sleep Timer"));
5261 if (number
) CFNumberGetValue(number
, kCFNumberSInt32Type
, &val
);
5269 mDNSlocal
void SetSPS(mDNS
*const m
)
5271 SCPreferencesSynchronize(m
->p
->SCPrefs
);
5272 CFDictionaryRef dict
= SCPreferencesGetValue(m
->p
->SCPrefs
, CFSTR("NAT"));
5273 mDNSBool natenabled
= (dict
&& (CFGetTypeID(dict
) == CFDictionaryGetTypeID()) && DictionaryIsEnabled(dict
));
5274 mDNSu8 sps
= natenabled
? 50 : (OfferSleepProxyService
&& GetSystemSleepTimerSetting() == 0) ? OfferSleepProxyService
: 0;
5276 // For devices that are not running NAT, but are set to never sleep, we may choose to act
5277 // as a Sleep Proxy, but only for non-portable Macs (Portability > 35 means nominal weight < 3kg)
5278 if (sps
> 50 && SPMetricPortability
> 35) sps
= 0;
5280 // If we decide to let laptops act as Sleep Proxy, we should do it only when running on AC power, not on battery
5282 // For devices that are unable to sleep at all to save power (e.g. the current Apple TV hardware)
5283 // it makes sense for them to offer low-priority Sleep Proxy service on the network.
5284 // We rate such a device as metric 70 ("Incidentally Available Hardware")
5285 if (SPMetricMarginalPower
== 10 && (!sps
|| sps
> 70)) sps
= 70;
5287 mDNSCoreBeSleepProxyServer(m
, sps
, SPMetricPortability
, SPMetricMarginalPower
, SPMetricTotalPower
);
5290 mDNSlocal
void InternetSharingChanged(SCPreferencesRef prefs
, SCPreferencesNotification notificationType
, void *context
)
5292 (void)prefs
; // Parameter not used
5293 (void)notificationType
; // Parameter not used
5294 mDNS
*const m
= (mDNS
*const)context
;
5298 // Tell platform layer to open or close its BPF fds
5299 if (!m
->p
->NetworkChanged
||
5300 m
->p
->NetworkChanged
- NonZeroTime(m
->timenow
+ mDNSPlatformOneSecond
* 2) < 0)
5302 m
->p
->NetworkChanged
= NonZeroTime(m
->timenow
+ mDNSPlatformOneSecond
* 2);
5303 LogInfo("InternetSharingChanged: Set NetworkChanged to %d (%d)", m
->p
->NetworkChanged
- m
->timenow
, m
->p
->NetworkChanged
);
5307 KQueueUnlock(m
, "InternetSharingChanged");
5310 mDNSlocal mStatus
WatchForInternetSharingChanges(mDNS
*const m
)
5312 SCPreferencesRef SCPrefs
= SCPreferencesCreate(NULL
, CFSTR("mDNSResponder:WatchForInternetSharingChanges"), CFSTR("com.apple.nat.plist"));
5313 if (!SCPrefs
) { LogMsg("SCPreferencesCreate failed: %s", SCErrorString(SCError())); return(mStatus_NoMemoryErr
); }
5315 SCPreferencesContext context
= { 0, m
, NULL
, NULL
, NULL
};
5316 if (!SCPreferencesSetCallback(SCPrefs
, InternetSharingChanged
, &context
))
5317 { LogMsg("SCPreferencesSetCallback failed: %s", SCErrorString(SCError())); CFRelease(SCPrefs
); return(mStatus_NoMemoryErr
); }
5319 if (!SCPreferencesScheduleWithRunLoop(SCPrefs
, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode
))
5320 { LogMsg("SCPreferencesScheduleWithRunLoop failed: %s", SCErrorString(SCError())); CFRelease(SCPrefs
); return(mStatus_NoMemoryErr
); }
5322 m
->p
->SCPrefs
= SCPrefs
;
5323 return(mStatus_NoError
);
5326 #endif // APPLE_OSX_mDNSResponder
5328 static io_service_t g_rootdomain
= MACH_PORT_NULL
;
5330 mDNSlocal mDNSBool
SystemWakeForNetworkAccess(void)
5333 CFBooleanRef clamshellStop
= NULL
;
5334 mDNSBool retnow
= mDNSfalse
;
5336 GetCurrentPMSetting(CFSTR("Wake On LAN"), &val
);
5337 LogSPS("SystemWakeForNetworkAccess: Wake On LAN: %d", val
);
5338 if (!val
) return mDNSfalse
;
5340 if (!g_rootdomain
) g_rootdomain
= IORegistryEntryFromPath(MACH_PORT_NULL
, kIOPowerPlane
":/IOPowerConnection/IOPMrootDomain");
5341 if (!g_rootdomain
) { LogMsg("SystemWakeForNetworkAccess: IORegistryEntryFromPath failed; assuming no clamshell so can WOMP"); return mDNStrue
; }
5343 clamshellStop
= (CFBooleanRef
)IORegistryEntryCreateCFProperty(g_rootdomain
, CFSTR(kAppleClamshellStateKey
), kCFAllocatorDefault
, 0);
5344 if (!clamshellStop
) { LogSPS("SystemWakeForNetworkAccess: kAppleClamshellStateKey does not exist; assuming no clamshell so can WOMP"); return mDNStrue
; }
5345 retnow
= clamshellStop
== kCFBooleanFalse
;
5346 CFRelease(clamshellStop
);
5347 if (retnow
) { LogSPS("SystemWakeForNetworkAccess: kAppleClamshellStateKey is false; clamshell is open so can WOMP"); return mDNStrue
; }
5349 clamshellStop
= (CFBooleanRef
)IORegistryEntryCreateCFProperty(g_rootdomain
, CFSTR(kAppleClamshellCausesSleepKey
), kCFAllocatorDefault
, 0);
5350 if (!clamshellStop
) { LogSPS("SystemWakeForNetworkAccess: kAppleClamshellCausesSleepKey does not exist; assuming no clamshell so can WOMP"); return mDNStrue
; }
5351 retnow
= clamshellStop
== kCFBooleanFalse
;
5352 CFRelease(clamshellStop
);
5353 if (retnow
) { LogSPS("SystemWakeForNetworkAccess: kAppleClamshellCausesSleepKey is false; clamshell is closed but can WOMP"); return mDNStrue
; }
5355 LogSPS("SystemWakeForNetworkAccess: clamshell is closed and can't WOMP");
5359 mDNSexport
void mDNSMacOSXNetworkChanged(mDNS
*const m
)
5361 LogInfo("*** Network Configuration Change *** (%d)%s",
5362 m
->p
->NetworkChanged
? mDNS_TimeNow(m
) - m
->p
->NetworkChanged
: 0,
5363 m
->p
->NetworkChanged
? "" : " (no scheduled configuration change)");
5364 m
->p
->NetworkChanged
= 0; // If we received a network change event and deferred processing, we're now dealing with it
5365 mDNSs32 utc
= mDNSPlatformUTC();
5366 m
->SystemWakeOnLANEnabled
= SystemWakeForNetworkAccess();
5367 MarkAllInterfacesInactive(m
, utc
);
5368 UpdateInterfaceList(m
, utc
);
5369 ClearInactiveInterfaces(m
, utc
);
5370 SetupActiveInterfaces(m
, utc
);
5372 #if APPLE_OSX_mDNSResponder
5374 if (m
->AutoTunnelHostAddr
.b
[0])
5377 if (TunnelClients(m
) || TunnelServers(m
))
5378 SetupLocalAutoTunnelInterface_internal(m
);
5382 // Scan to find client tunnels whose questions have completed,
5383 // but whose local inner/outer addresses have changed since the tunnel was set up
5385 for (p
= m
->TunnelClients
; p
; p
= p
->next
)
5386 if (p
->q
.ThisQInterval
< 0)
5388 mDNSAddr tmpSrc
= zeroAddr
;
5389 mDNSAddr tmpDst
= { mDNSAddrType_IPv4
, {{{0}}} };
5390 tmpDst
.ip
.v4
= p
->rmt_outer
;
5391 mDNSPlatformSourceAddrForDest(&tmpSrc
, &tmpDst
);
5392 if (!mDNSSameIPv6Address(p
->loc_inner
, m
->AutoTunnelHostAddr
) ||
5393 !mDNSSameIPv4Address(p
->loc_outer
, tmpSrc
.ip
.v4
))
5395 AutoTunnelSetKeys(p
, mDNSfalse
);
5396 p
->loc_inner
= m
->AutoTunnelHostAddr
;
5397 p
->loc_outer
= tmpSrc
.ip
.v4
;
5398 AutoTunnelSetKeys(p
, mDNStrue
);
5404 NetworkInterfaceInfoOSX
*i
;
5405 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
5407 if (!m
->SPSSocket
) // Not being Sleep Proxy Server; close any open BPF fds
5409 if (i
->BPF_fd
>= 0 && CountProxyTargets(m
, i
, mDNSNULL
, mDNSNULL
) == 0) CloseBPF(i
);
5411 else // else, we're Sleep Proxy Server; open BPF fds
5413 if (i
->Exists
&& i
->ifinfo
.InterfaceID
== (mDNSInterfaceID
)i
&& !(i
->ifa_flags
& IFF_LOOPBACK
) && i
->BPF_fd
== -1)
5414 { LogSPS("%s requesting BPF", i
->ifinfo
.ifname
); i
->BPF_fd
= -2; mDNSRequestBPF(); }
5418 #endif // APPLE_OSX_mDNSResponder
5420 uDNS_SetupDNSConfig(m
);
5421 mDNS_ConfigChanged(m
);
5424 // Called with KQueueLock & mDNS lock
5425 mDNSlocal
void SetNetworkChanged(mDNS
*const m
, mDNSs32 delay
)
5427 if (!m
->p
->NetworkChanged
|| m
->p
->NetworkChanged
- NonZeroTime(m
->timenow
+ delay
) < 0)
5429 m
->p
->NetworkChanged
= NonZeroTime(m
->timenow
+ delay
);
5430 LogInfo("SetNetworkChanged: setting network changed to %d (%d)", delay
, m
->p
->NetworkChanged
);
5435 mDNSlocal
void NetworkChanged(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
5437 (void)store
; // Parameter not used
5438 mDNS
*const m
= (mDNS
*const)context
;
5442 mDNSs32 delay
= mDNSPlatformOneSecond
* 2; // Start off assuming a two-second delay
5444 int c
= CFArrayGetCount(changedKeys
); // Count changes
5445 CFRange range
= { 0, c
};
5446 int c1
= (CFArrayContainsValue(changedKeys
, range
, NetworkChangedKey_Hostnames
) != 0);
5447 int c2
= (CFArrayContainsValue(changedKeys
, range
, NetworkChangedKey_Computername
) != 0);
5448 int c3
= (CFArrayContainsValue(changedKeys
, range
, NetworkChangedKey_DynamicDNS
) != 0);
5449 int c4
= (CFArrayContainsValue(changedKeys
, range
, NetworkChangedKey_DNS
) != 0);
5450 if (c
&& c
- c1
- c2
- c3
- c4
== 0) delay
= mDNSPlatformOneSecond
/10; // If these were the only changes, shorten delay
5452 if (mDNS_LoggingEnabled
)
5458 if (!CFStringGetCString(CFArrayGetValueAtIndex(changedKeys
, i
), buf
, sizeof(buf
), kCFStringEncodingUTF8
)) buf
[0] = 0;
5459 LogInfo("*** NetworkChanged SC key: %s", buf
);
5461 LogInfo("*** NetworkChanged *** %d change%s %s%s%s%sdelay %d",
5463 c1
? "(Local Hostname) " : "",
5464 c2
? "(Computer Name) " : "",
5465 c3
? "(DynamicDNS) " : "",
5470 SetNetworkChanged(m
, delay
);
5472 // KeyChain frequently fails to notify clients of change events. To work around this
5473 // we set a timer and periodically poll to detect if any changes have occurred.
5474 // Without this Back To My Mac just does't work for a large number of users.
5475 // See <rdar://problem/5124399> Not getting Keychain Changed events when enabling BTMM
5476 if (c3
|| CFArrayContainsValue(changedKeys
, range
, NetworkChangedKey_BackToMyMac
))
5478 LogInfo("*** NetworkChanged *** starting KeyChainBugTimer");
5479 m
->p
->KeyChainBugTimer
= NonZeroTime(m
->timenow
+ delay
);
5480 m
->p
->KeyChainBugInterval
= mDNSPlatformOneSecond
;
5485 // If DNS settings changed, immediately force a reconfig (esp. cache flush)
5486 if (c4
) mDNSMacOSXNetworkChanged(m
);
5488 KQueueUnlock(m
, "NetworkChanged");
5491 mDNSlocal mStatus
WatchForNetworkChanges(mDNS
*const m
)
5494 SCDynamicStoreContext context
= { 0, m
, NULL
, NULL
, NULL
};
5495 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:WatchForNetworkChanges"), NetworkChanged
, &context
);
5496 CFMutableArrayRef keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
5497 CFStringRef pattern1
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv4
);
5498 CFStringRef pattern2
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv6
);
5499 CFMutableArrayRef patterns
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
5501 if (!store
) { LogMsg("SCDynamicStoreCreate failed: %s", SCErrorString(SCError())); goto error
; }
5502 if (!keys
|| !pattern1
|| !pattern2
|| !patterns
) goto error
;
5504 CFArrayAppendValue(keys
, NetworkChangedKey_IPv4
);
5505 CFArrayAppendValue(keys
, NetworkChangedKey_IPv6
);
5506 CFArrayAppendValue(keys
, NetworkChangedKey_Hostnames
);
5507 CFArrayAppendValue(keys
, NetworkChangedKey_Computername
);
5508 CFArrayAppendValue(keys
, NetworkChangedKey_DNS
);
5509 CFArrayAppendValue(keys
, NetworkChangedKey_DynamicDNS
);
5510 CFArrayAppendValue(keys
, NetworkChangedKey_BackToMyMac
);
5511 CFArrayAppendValue(keys
, CFSTR("State:/IOKit/PowerManagement/CurrentSettings")); // should remove as part of <rdar://problem/6751656>
5512 CFArrayAppendValue(patterns
, pattern1
);
5513 CFArrayAppendValue(patterns
, pattern2
);
5514 CFArrayAppendValue(patterns
, CFSTR("State:/Network/Interface/[^/]+/AirPort"));
5515 if (!SCDynamicStoreSetNotificationKeys(store
, keys
, patterns
))
5516 { LogMsg("SCDynamicStoreSetNotificationKeys failed: %s", SCErrorString(SCError())); goto error
; }
5518 m
->p
->StoreRLS
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, 0);
5519 if (!m
->p
->StoreRLS
) { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error
; }
5521 CFRunLoopAddSource(CFRunLoopGetCurrent(), m
->p
->StoreRLS
, kCFRunLoopDefaultMode
);
5522 m
->p
->Store
= store
;
5527 if (store
) CFRelease(store
);
5530 if (patterns
) CFRelease(patterns
);
5531 if (pattern2
) CFRelease(pattern2
);
5532 if (pattern1
) CFRelease(pattern1
);
5533 if (keys
) CFRelease(keys
);
5538 #if 0 // <rdar://problem/6751656>
5539 mDNSlocal
void PMChanged(void *context
)
5541 mDNS
*const m
= (mDNS
*const)context
;
5546 LogSPS("PMChanged");
5548 SetNetworkChanged(m
, mDNSPlatformOneSecond
* 2);
5551 KQueueUnlock(m
, "PMChanged");
5554 mDNSlocal mStatus
WatchForPMChanges(mDNS
*const m
)
5556 m
->p
->PMRLS
= IOPMPrefsNotificationCreateRunLoopSource(PMChanged
, m
);
5557 if (!m
->p
->PMRLS
) { LogMsg("IOPMPrefsNotificationCreateRunLoopSource failed!"); return mStatus_UnknownErr
; }
5559 CFRunLoopAddSource(CFRunLoopGetCurrent(), m
->p
->PMRLS
, kCFRunLoopDefaultMode
);
5561 return mStatus_NoError
;
5565 #ifndef KEV_DL_WAKEFLAGS_CHANGED
5566 #define KEV_DL_WAKEFLAGS_CHANGED 17
5569 mDNSlocal
void SysEventCallBack(int s1
, short __unused filter
, void *context
)
5571 mDNS
*const m
= (mDNS
*const)context
;
5575 struct { struct kern_event_msg k
; char extra
[256]; } msg
;
5576 int bytes
= recv(s1
, &msg
, sizeof(msg
), 0);
5578 LogMsg("SysEventCallBack: recv error %d errno %d (%s)", bytes
, errno
, strerror(errno
));
5581 LogInfo("SysEventCallBack got %d bytes size %d %X %s %X %s %X %s id %d code %d %s",
5582 bytes
, msg
.k
.total_size
,
5583 msg
.k
.vendor_code
, msg
.k
.vendor_code
== KEV_VENDOR_APPLE
? "KEV_VENDOR_APPLE" : "?",
5584 msg
.k
.kev_class
, msg
.k
.kev_class
== KEV_NETWORK_CLASS
? "KEV_NETWORK_CLASS" : "?",
5585 msg
.k
.kev_subclass
, msg
.k
.kev_subclass
== KEV_DL_SUBCLASS
? "KEV_DL_SUBCLASS" : "?",
5586 msg
.k
.id
, msg
.k
.event_code
,
5587 msg
.k
.event_code
== KEV_DL_SIFFLAGS
? "KEV_DL_SIFFLAGS" :
5588 msg
.k
.event_code
== KEV_DL_SIFMETRICS
? "KEV_DL_SIFMETRICS" :
5589 msg
.k
.event_code
== KEV_DL_SIFMTU
? "KEV_DL_SIFMTU" :
5590 msg
.k
.event_code
== KEV_DL_SIFPHYS
? "KEV_DL_SIFPHYS" :
5591 msg
.k
.event_code
== KEV_DL_SIFMEDIA
? "KEV_DL_SIFMEDIA" :
5592 msg
.k
.event_code
== KEV_DL_SIFGENERIC
? "KEV_DL_SIFGENERIC" :
5593 msg
.k
.event_code
== KEV_DL_ADDMULTI
? "KEV_DL_ADDMULTI" :
5594 msg
.k
.event_code
== KEV_DL_DELMULTI
? "KEV_DL_DELMULTI" :
5595 msg
.k
.event_code
== KEV_DL_IF_ATTACHED
? "KEV_DL_IF_ATTACHED" :
5596 msg
.k
.event_code
== KEV_DL_IF_DETACHING
? "KEV_DL_IF_DETACHING" :
5597 msg
.k
.event_code
== KEV_DL_IF_DETACHED
? "KEV_DL_IF_DETACHED" :
5598 msg
.k
.event_code
== KEV_DL_LINK_OFF
? "KEV_DL_LINK_OFF" :
5599 msg
.k
.event_code
== KEV_DL_LINK_ON
? "KEV_DL_LINK_ON" :
5600 msg
.k
.event_code
== KEV_DL_PROTO_ATTACHED
? "KEV_DL_PROTO_ATTACHED" :
5601 msg
.k
.event_code
== KEV_DL_PROTO_DETACHED
? "KEV_DL_PROTO_DETACHED" :
5602 msg
.k
.event_code
== KEV_DL_LINK_ADDRESS_CHANGED
? "KEV_DL_LINK_ADDRESS_CHANGED" :
5603 msg
.k
.event_code
== KEV_DL_WAKEFLAGS_CHANGED
? "KEV_DL_WAKEFLAGS_CHANGED" : "?");
5605 if (msg
.k
.event_code
== KEV_DL_WAKEFLAGS_CHANGED
) SetNetworkChanged(m
, mDNSPlatformOneSecond
* 2);
5611 mDNSlocal mStatus
WatchForSysEvents(mDNS
*const m
)
5613 m
->p
->SysEventNotifier
= socket(PF_SYSTEM
, SOCK_RAW
, SYSPROTO_EVENT
);
5614 if (m
->p
->SysEventNotifier
< 0)
5615 { LogMsg("WatchForNetworkChanges: socket failed %s errno %d (%s)", errno
, strerror(errno
)); return(mStatus_NoMemoryErr
); }
5617 struct kev_request kev_req
= { KEV_VENDOR_APPLE
, KEV_NETWORK_CLASS
, KEV_DL_SUBCLASS
};
5618 int err
= ioctl(m
->p
->SysEventNotifier
, SIOCSKEVFILT
, &kev_req
);
5621 LogMsg("WatchForNetworkChanges: SIOCSKEVFILT failed %s errno %d (%s)", errno
, strerror(errno
));
5622 close(m
->p
->SysEventNotifier
);
5623 m
->p
->SysEventNotifier
= -1;
5624 return(mStatus_UnknownErr
);
5627 m
->p
->SysEventKQueue
.KQcallback
= SysEventCallBack
;
5628 m
->p
->SysEventKQueue
.KQcontext
= m
;
5629 m
->p
->SysEventKQueue
.KQtask
= "System Event Notifier";
5630 KQueueSet(m
->p
->SysEventNotifier
, EV_ADD
, EVFILT_READ
, &m
->p
->SysEventKQueue
);
5632 return(mStatus_NoError
);
5635 #ifndef NO_SECURITYFRAMEWORK
5636 mDNSlocal OSStatus
KeychainChanged(SecKeychainEvent keychainEvent
, SecKeychainCallbackInfo
*info
, void *context
)
5638 LogInfo("*** Keychain Changed ***");
5639 mDNS
*const m
= (mDNS
*const)context
;
5641 OSStatus err
= SecKeychainCopyDefault(&skc
);
5644 if (info
->keychain
== skc
)
5646 // For delete events, attempt to verify what item was deleted fail because the item is already gone, so we just assume they may be relevant
5647 mDNSBool relevant
= (keychainEvent
== kSecDeleteEvent
);
5650 UInt32 tags
[3] = { kSecTypeItemAttr
, kSecServiceItemAttr
, kSecAccountItemAttr
};
5651 SecKeychainAttributeInfo attrInfo
= { 3, tags
, NULL
}; // Count, array of tags, array of formats
5652 SecKeychainAttributeList
*a
= NULL
;
5653 err
= SecKeychainItemCopyAttributesAndData(info
->item
, &attrInfo
, NULL
, &a
, NULL
, NULL
);
5656 relevant
= ((a
->attr
[0].length
== 4 && (!strncasecmp(a
->attr
[0].data
, "ddns", 4) || !strncasecmp(a
->attr
[0].data
, "sndd", 4))) ||
5657 (a
->attr
[1].length
>= 4 && (!strncasecmp(a
->attr
[1].data
, "dns:", 4))));
5658 SecKeychainItemFreeAttributesAndData(a
, NULL
);
5663 LogInfo("*** Keychain Changed *** KeychainEvent=%d %s",
5665 keychainEvent
== kSecAddEvent
? "kSecAddEvent" :
5666 keychainEvent
== kSecDeleteEvent
? "kSecDeleteEvent" :
5667 keychainEvent
== kSecUpdateEvent
? "kSecUpdateEvent" : "<Unknown>");
5668 // We're running on the CFRunLoop (Mach port) thread, not the kqueue thread, so we need to grab the KQueueLock before proceeding
5671 SetDomainSecrets(m
);
5673 KQueueUnlock(m
, "KeychainChanged");
5684 mDNSlocal
void PowerOn(mDNS
*const m
)
5686 mDNSCoreMachineSleep(m
, false); // Will set m->SleepState = SleepState_Awake;
5687 if (m
->p
->WakeAtUTC
)
5689 long utc
= mDNSPlatformUTC();
5690 mDNSPowerRequest(-1,-1); // Need to explicitly clear any previous power requests -- they're not cleared automatically on wake
5691 if (m
->p
->WakeAtUTC
- utc
> 30) LogInfo("PowerChanged PowerOn %d seconds early, assuming not maintenance wake", m
->p
->WakeAtUTC
- utc
);
5692 else if (utc
- m
->p
->WakeAtUTC
> 30) LogInfo("PowerChanged PowerOn %d seconds late, assuming not maintenance wake", utc
- m
->p
->WakeAtUTC
);
5696 //int result = mDNSPowerRequest(0, i);
5697 //if (result == kIOReturnNotReady) do i += (i<20) ? 1 : ((i+3)/4); while (mDNSPowerRequest(0, i) == kIOReturnNotReady);
5698 LogMsg("PowerChanged: Waking for network maintenance operations %d seconds early; re-sleeping in %d seconds", m
->p
->WakeAtUTC
- utc
, i
);
5699 m
->p
->RequestReSleep
= mDNS_TimeNow(m
) + i
* mDNSPlatformOneSecond
;
5704 mDNSlocal
void PowerChanged(void *refcon
, io_service_t service
, natural_t messageType
, void *messageArgument
)
5706 mDNS
*const m
= (mDNS
*const)refcon
;
5708 (void)service
; // Parameter not used
5709 debugf("PowerChanged %X %lX", messageType
, messageArgument
);
5711 // Make sure our m->SystemWakeOnLANEnabled value correctly reflects the current system setting
5712 m
->SystemWakeOnLANEnabled
= SystemWakeForNetworkAccess();
5716 case kIOMessageCanSystemPowerOff
: LogInfo("PowerChanged kIOMessageCanSystemPowerOff (no action)"); break; // E0000240
5717 case kIOMessageSystemWillPowerOff
: LogInfo("PowerChanged kIOMessageSystemWillPowerOff"); // E0000250
5718 mDNSCoreMachineSleep(m
, true);
5719 if (m
->SleepState
== SleepState_Sleeping
) mDNSMacOSXNetworkChanged(m
);
5721 case kIOMessageSystemWillNotPowerOff
: LogInfo("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; // E0000260
5722 case kIOMessageCanSystemSleep
: LogInfo("PowerChanged kIOMessageCanSystemSleep (no action)"); break; // E0000270
5723 case kIOMessageSystemWillSleep
: LogInfo("PowerChanged kIOMessageSystemWillSleep"); // E0000280
5724 mDNSCoreMachineSleep(m
, true);
5726 case kIOMessageSystemWillNotSleep
: LogInfo("PowerChanged kIOMessageSystemWillNotSleep (no action)"); break; // E0000290
5727 case kIOMessageSystemHasPoweredOn
: LogInfo("PowerChanged kIOMessageSystemHasPoweredOn"); // E0000300
5728 // If still sleeping (didn't get 'WillPowerOn' message for some reason?) wake now
5731 LogMsg("PowerChanged kIOMessageSystemHasPoweredOn: ERROR m->SleepState %d", m
->SleepState
);
5734 // Just to be safe, schedule a mDNSMacOSXNetworkChanged(), in case we never received
5735 // the System Configuration Framework "network changed" event that we expect
5736 // to receive some time shortly after the kIOMessageSystemWillPowerOn message
5738 if (!m
->p
->NetworkChanged
||
5739 m
->p
->NetworkChanged
- NonZeroTime(m
->timenow
+ mDNSPlatformOneSecond
* 2) < 0)
5740 m
->p
->NetworkChanged
= NonZeroTime(m
->timenow
+ mDNSPlatformOneSecond
* 2);
5744 case kIOMessageSystemWillRestart
: LogInfo("PowerChanged kIOMessageSystemWillRestart (no action)"); break; // E0000310
5745 case kIOMessageSystemWillPowerOn
: LogInfo("PowerChanged kIOMessageSystemWillPowerOn"); // E0000320
5747 // On Leopard and earlier, on wake from sleep, instead of reporting link state down, Apple
5748 // Ethernet drivers report "hardware incapable of detecting link state", which the kernel
5749 // interprets as "should assume we have networking", which results in the first 4-5 seconds
5750 // of packets vanishing into a black hole. To work around this, on wake from sleep,
5751 // we block for five seconds to let Ethernet come up, and then resume normal operation.
5752 if (OSXVers
< OSXVers_10_6_SnowLeopard
)
5755 LogMsg("Running on Mac OS X version 10.%d earlier than 10.6; "
5756 "PowerChanged did sleep(5) to wait for Ethernet hardware", OSXVers
- OSXVers_Base
);
5759 // Make sure our interface list is cleared to the empty state, then tell mDNSCore to wake
5760 if (m
->SleepState
!= SleepState_Sleeping
)
5762 LogMsg("kIOMessageSystemWillPowerOn: ERROR m->SleepState %d", m
->SleepState
);
5763 m
->SleepState
= SleepState_Sleeping
;
5764 mDNSMacOSXNetworkChanged(m
);
5768 default: LogInfo("PowerChanged unknown message %X", messageType
); break;
5771 if (messageType
== kIOMessageSystemWillSleep
) m
->p
->SleepCookie
= (long)messageArgument
;
5772 else IOAllowPowerChange(m
->p
->PowerConnection
, (long)messageArgument
);
5774 KQueueUnlock(m
, "PowerChanged Sleep/Wake");
5777 #ifdef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
5778 mDNSlocal
void SnowLeopardPowerChanged(void *refcon
, IOPMConnection connection
, IOPMConnectionMessageToken token
, IOPMSystemPowerStateCapabilities eventDescriptor
)
5780 mDNS
*const m
= (mDNS
*const)refcon
;
5782 LogSPS("SnowLeopardPowerChanged %X %X %X%s%s%s%s%s",
5783 connection
, token
, eventDescriptor
,
5784 eventDescriptor
& kIOPMSystemPowerStateCapabilityCPU
? " CPU" : "",
5785 eventDescriptor
& kIOPMSystemPowerStateCapabilityVideo
? " Video" : "",
5786 eventDescriptor
& kIOPMSystemPowerStateCapabilityAudio
? " Audio" : "",
5787 eventDescriptor
& kIOPMSystemPowerStateCapabilityNetwork
? " Network" : "",
5788 eventDescriptor
& kIOPMSystemPowerStateCapabilityDisk
? " Disk" : "");
5790 // Make sure our m->SystemWakeOnLANEnabled value correctly reflects the current system setting
5791 m
->SystemWakeOnLANEnabled
= SystemWakeForNetworkAccess();
5793 if (eventDescriptor
& kIOPMSystemPowerStateCapabilityCPU
)
5795 // CPU Waking. Note: Can get this message repeatedly, as other subsystems power up or down.
5796 if (m
->SleepState
== SleepState_Sleeping
) PowerOn(m
);
5797 IOPMConnectionAcknowledgeEvent(connection
, token
);
5801 // CPU sleeping. Should not get this repeatedly -- once we're told that the CPU is halting
5802 // we should hear nothing more until we're told that the CPU has started executing again.
5803 if (m
->SleepState
) LogMsg("SnowLeopardPowerChanged: Sleep Error %X m->SleepState %d", eventDescriptor
, m
->SleepState
);
5805 //mDNSMacOSXNetworkChanged(m);
5806 mDNSCoreMachineSleep(m
, true);
5807 //if (m->SleepState == SleepState_Sleeping) mDNSMacOSXNetworkChanged(m);
5808 m
->p
->SleepCookie
= token
;
5811 KQueueUnlock(m
, "SnowLeopardPowerChanged Sleep/Wake");
5815 #endif /* NO_IOPOWER */
5817 #if COMPILER_LIKES_PRAGMA_MARK
5819 #pragma mark - Initialization & Teardown
5822 CF_EXPORT CFDictionaryRef
_CFCopySystemVersionDictionary(void);
5823 CF_EXPORT
const CFStringRef _kCFSystemVersionProductNameKey
;
5824 CF_EXPORT
const CFStringRef _kCFSystemVersionProductVersionKey
;
5825 CF_EXPORT
const CFStringRef _kCFSystemVersionBuildVersionKey
;
5827 // Major version 6 is 10.2.x (Jaguar)
5828 // Major version 7 is 10.3.x (Panther)
5829 // Major version 8 is 10.4.x (Tiger)
5830 // Major version 9 is 10.5.x (Leopard)
5831 // Major version 10 is 10.6.x (SnowLeopard)
5832 mDNSexport
int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring
)
5834 int major
= 0, minor
= 0;
5835 char letter
= 0, prodname
[256]="<Unknown>", prodvers
[256]="<Unknown>", buildver
[256]="<Unknown>";
5836 CFDictionaryRef vers
= _CFCopySystemVersionDictionary();
5839 CFStringRef cfprodname
= CFDictionaryGetValue(vers
, _kCFSystemVersionProductNameKey
);
5840 CFStringRef cfprodvers
= CFDictionaryGetValue(vers
, _kCFSystemVersionProductVersionKey
);
5841 CFStringRef cfbuildver
= CFDictionaryGetValue(vers
, _kCFSystemVersionBuildVersionKey
);
5842 if (cfprodname
) CFStringGetCString(cfprodname
, prodname
, sizeof(prodname
), kCFStringEncodingUTF8
);
5843 if (cfprodvers
) CFStringGetCString(cfprodvers
, prodvers
, sizeof(prodvers
), kCFStringEncodingUTF8
);
5844 if (cfbuildver
&& CFStringGetCString(cfbuildver
, buildver
, sizeof(buildver
), kCFStringEncodingUTF8
))
5845 sscanf(buildver
, "%d%c%d", &major
, &letter
, &minor
);
5848 if (!major
) { major
=8; LogMsg("Note: No Major Build Version number found; assuming 8"); }
5849 if (HINFO_SWstring
) mDNS_snprintf(HINFO_SWstring
, 256, "%s %s (%s), %s", prodname
, prodvers
, buildver
, STRINGIFY(mDNSResponderVersion
));
5853 // Test to see if we're the first client running on UDP port 5353, by trying to bind to 5353 without using SO_REUSEPORT.
5854 // If we fail, someone else got here first. That's not a big problem; we can share the port for multicast responses --
5855 // we just need to be aware that we shouldn't expect to successfully receive unicast UDP responses.
5856 mDNSlocal mDNSBool
mDNSPlatformInit_CanReceiveUnicast(void)
5859 int s
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
5861 LogMsg("mDNSPlatformInit_CanReceiveUnicast: socket error %d errno %d (%s)", s
, errno
, strerror(errno
));
5864 struct sockaddr_in s5353
;
5865 s5353
.sin_family
= AF_INET
;
5866 s5353
.sin_port
= MulticastDNSPort
.NotAnInteger
;
5867 s5353
.sin_addr
.s_addr
= 0;
5868 err
= bind(s
, (struct sockaddr
*)&s5353
, sizeof(s5353
));
5872 if (err
) LogMsg("No unicast UDP responses");
5873 else debugf("Unicast UDP responses okay");
5877 // Construction of Default Browse domain list (i.e. when clients pass NULL) is as follows:
5878 // 1) query for b._dns-sd._udp.local on LocalOnly interface
5879 // (.local manually generated via explicit callback)
5880 // 2) for each search domain (from prefs pane), query for b._dns-sd._udp.<searchdomain>.
5881 // 3) for each result from (2), register LocalOnly PTR record b._dns-sd._udp.local. -> <result>
5882 // 4) result above should generate a callback from question in (1). result added to global list
5883 // 5) global list delivered to client via GetSearchDomainList()
5884 // 6) client calls to enumerate domains now go over LocalOnly interface
5885 // (!!!KRS may add outgoing interface in addition)
5887 mDNSlocal mStatus
mDNSPlatformInit_setup(mDNS
*const m
)
5890 m
->p
->CFRunLoop
= CFRunLoopGetCurrent();
5892 char HINFO_SWstring
[256] = "";
5893 OSXVers
= mDNSMacOSXSystemBuildNumber(HINFO_SWstring
);
5895 // In 10.4, mDNSResponder is launched very early in the boot process, while other subsystems are still in the process of starting up.
5896 // If we can't read the user's preferences, then we sleep a bit and try again, for up to five seconds before we give up.
5898 for (i
=0; i
<100; i
++)
5900 domainlabel testlabel
;
5902 GetUserSpecifiedLocalHostName(&testlabel
);
5903 if (testlabel
.c
[0]) break;
5907 m
->hostlabel
.c
[0] = 0;
5909 int get_model
[2] = { CTL_HW
, HW_MODEL
};
5910 size_t len_model
= sizeof(HINFO_HWstring_buffer
);
5911 // Names that contain no commas are prototype model names, so we ignore those
5912 if (sysctl(get_model
, 2, HINFO_HWstring_buffer
, &len_model
, NULL
, 0) == 0 && strchr(HINFO_HWstring_buffer
, ','))
5913 HINFO_HWstring
= HINFO_HWstring_buffer
;
5914 HINFO_HWstring_prefixlen
= strcspn(HINFO_HWstring
, "0123456789");
5916 if (OSXVers
< OSXVers_10_3_Panther
) m
->KnownBugs
|= mDNS_KnownBug_PhantomInterfaces
;
5917 if (OSXVers
>= OSXVers_10_6_SnowLeopard
) m
->KnownBugs
|= mDNS_KnownBug_LossySyslog
;
5918 if (mDNSPlatformInit_CanReceiveUnicast()) m
->CanReceiveUnicastOn5353
= mDNStrue
;
5920 mDNSu32 hlen
= mDNSPlatformStrLen(HINFO_HWstring
);
5921 mDNSu32 slen
= mDNSPlatformStrLen(HINFO_SWstring
);
5922 if (hlen
+ slen
< 254)
5924 m
->HIHardware
.c
[0] = hlen
;
5925 m
->HISoftware
.c
[0] = slen
;
5926 mDNSPlatformMemCopy(&m
->HIHardware
.c
[1], HINFO_HWstring
, hlen
);
5927 mDNSPlatformMemCopy(&m
->HISoftware
.c
[1], HINFO_SWstring
, slen
);
5930 m
->p
->permanentsockets
.port
= MulticastDNSPort
;
5931 m
->p
->permanentsockets
.m
= m
;
5932 m
->p
->permanentsockets
.sktv4
= m
->p
->permanentsockets
.sktv6
= -1;
5933 m
->p
->permanentsockets
.kqsv4
.KQcallback
= m
->p
->permanentsockets
.kqsv6
.KQcallback
= myKQSocketCallBack
;
5934 m
->p
->permanentsockets
.kqsv4
.KQcontext
= m
->p
->permanentsockets
.kqsv6
.KQcontext
= &m
->p
->permanentsockets
;
5935 m
->p
->permanentsockets
.kqsv4
.KQtask
= m
->p
->permanentsockets
.kqsv6
.KQtask
= "UDP packet reception";
5937 err
= SetupSocket(&m
->p
->permanentsockets
, MulticastDNSPort
, AF_INET
, mDNSNULL
);
5939 err
= SetupSocket(&m
->p
->permanentsockets
, MulticastDNSPort
, AF_INET6
, mDNSNULL
);
5942 struct sockaddr_in s4
;
5943 socklen_t n4
= sizeof(s4
);
5944 if (getsockname(m
->p
->permanentsockets
.sktv4
, (struct sockaddr
*)&s4
, &n4
) < 0) LogMsg("getsockname v4 error %d (%s)", errno
, strerror(errno
));
5945 else m
->UnicastPort4
.NotAnInteger
= s4
.sin_port
;
5947 if (m
->p
->permanentsockets
.sktv6
>= 0)
5949 struct sockaddr_in6 s6
;
5950 socklen_t n6
= sizeof(s6
);
5951 if (getsockname(m
->p
->permanentsockets
.sktv6
, (struct sockaddr
*)&s6
, &n6
) < 0) LogMsg("getsockname v6 error %d (%s)", errno
, strerror(errno
));
5952 else m
->UnicastPort6
.NotAnInteger
= s6
.sin6_port
;
5956 m
->p
->InterfaceList
= mDNSNULL
;
5957 m
->p
->userhostlabel
.c
[0] = 0;
5958 m
->p
->usernicelabel
.c
[0] = 0;
5959 m
->p
->NotifyUser
= 0;
5960 m
->p
->KeyChainBugTimer
= 0;
5961 m
->p
->WakeAtUTC
= 0;
5962 m
->p
->RequestReSleep
= 0;
5964 #if APPLE_OSX_mDNSResponder
5965 uuid_generate(m
->asl_uuid
);
5968 m
->AutoTunnelHostAddr
.b
[0] = 0; // Zero out AutoTunnelHostAddr so UpdateInterfaceList() know it has to set it up
5970 NetworkChangedKey_IPv4
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
5971 NetworkChangedKey_IPv6
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv6
);
5972 NetworkChangedKey_Hostnames
= SCDynamicStoreKeyCreateHostNames(NULL
);
5973 NetworkChangedKey_Computername
= SCDynamicStoreKeyCreateComputerName(NULL
);
5974 NetworkChangedKey_DNS
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetDNS
);
5975 if (!NetworkChangedKey_IPv4
|| !NetworkChangedKey_IPv6
|| !NetworkChangedKey_Hostnames
|| !NetworkChangedKey_Computername
|| !NetworkChangedKey_DNS
)
5976 { LogMsg("SCDynamicStore string setup failed"); return(mStatus_NoMemoryErr
); }
5978 err
= WatchForNetworkChanges(m
);
5979 if (err
) { LogMsg("mDNSPlatformInit_setup: WatchForNetworkChanges failed %d", err
); return(err
); }
5981 #if 0 // <rdar://problem/6751656>
5982 err
= WatchForPMChanges(m
);
5983 if (err
) { LogMsg("mDNSPlatformInit_setup: WatchForPMChanges failed %d", err
); return(err
); }
5986 err
= WatchForSysEvents(m
);
5987 if (err
) { LogMsg("mDNSPlatformInit_setup: WatchForSysEvents failed %d", err
); return(err
); }
5989 mDNSs32 utc
= mDNSPlatformUTC();
5990 m
->SystemWakeOnLANEnabled
= SystemWakeForNetworkAccess();
5991 UpdateInterfaceList(m
, utc
);
5992 SetupActiveInterfaces(m
, utc
);
5994 // Explicitly ensure that our Keychain operations utilize the system domain.
5995 #ifndef NO_SECURITYFRAMEWORK
5996 SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem
);
6000 SetDomainSecrets(m
);
6004 #ifndef NO_SECURITYFRAMEWORK
6005 err
= SecKeychainAddCallback(KeychainChanged
, kSecAddEventMask
|kSecDeleteEventMask
|kSecUpdateEventMask
, m
);
6006 if (err
) { LogMsg("mDNSPlatformInit_setup: SecKeychainAddCallback failed %d", err
); return(err
); }
6011 #ifndef kIOPMAcknowledgmentOptionSystemCapabilityRequirements
6012 LogMsg("Note: Compiled without SnowLeopard Fine-Grained Power Management support");
6015 IOReturn iopmerr
= IOPMConnectionCreate(CFSTR("mDNSResponder"), kIOPMSystemPowerStateCapabilityCPU
, &c
);
6016 if (iopmerr
) LogMsg("IOPMConnectionCreate failed %d", iopmerr
);
6019 iopmerr
= IOPMConnectionSetNotification(c
, m
, SnowLeopardPowerChanged
);
6020 if (iopmerr
) LogMsg("IOPMConnectionSetNotification failed %d", iopmerr
);
6023 iopmerr
= IOPMConnectionScheduleWithRunLoop(c
, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode
);
6024 if (iopmerr
) LogMsg("IOPMConnectionScheduleWithRunLoop failed %d", iopmerr
);
6027 m
->p
->IOPMConnection
= iopmerr
? mDNSNULL
: c
;
6028 if (iopmerr
) // If IOPMConnectionCreate unavailable or failed, proceed with old-style power notification code below
6029 #endif // kIOPMAcknowledgmentOptionSystemCapabilityRequirements
6031 m
->p
->PowerConnection
= IORegisterForSystemPower(m
, &m
->p
->PowerPortRef
, PowerChanged
, &m
->p
->PowerNotifier
);
6032 if (!m
->p
->PowerConnection
) { LogMsg("mDNSPlatformInit_setup: IORegisterForSystemPower failed"); return(-1); }
6033 else CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m
->p
->PowerPortRef
), kCFRunLoopDefaultMode
);
6035 #endif /* NO_IOPOWER */
6037 #if APPLE_OSX_mDNSResponder
6038 // Note: We use SPMetricPortability > 35 to indicate a laptop of some kind
6039 // SPMetricPortability <= 35 means nominally a non-portable machine (i.e. Mac mini or better)
6040 // An Apple TV does not actually weigh 3kg, but we assign it a 'nominal' mass of 3kg to indicate that it's treated as being relatively less portable than a laptop
6041 if (!strncasecmp(HINFO_HWstring
, "Xserve", 6)) { SPMetricPortability
= 25 /* 30kg */; SPMetricMarginalPower
= 84 /* 250W */; SPMetricTotalPower
= 85 /* 300W */; }
6042 else if (!strncasecmp(HINFO_HWstring
, "RackMac", 7)) { SPMetricPortability
= 25 /* 30kg */; SPMetricMarginalPower
= 84 /* 250W */; SPMetricTotalPower
= 85 /* 300W */; }
6043 else if (!strncasecmp(HINFO_HWstring
, "MacPro", 6)) { SPMetricPortability
= 27 /* 20kg */; SPMetricMarginalPower
= 84 /* 250W */; SPMetricTotalPower
= 85 /* 300W */; }
6044 else if (!strncasecmp(HINFO_HWstring
, "PowerMac", 8)) { SPMetricPortability
= 27 /* 20kg */; SPMetricMarginalPower
= 82 /* 160W */; SPMetricTotalPower
= 83 /* 200W */; }
6045 else if (!strncasecmp(HINFO_HWstring
, "iMac", 4)) { SPMetricPortability
= 30 /* 10kg */; SPMetricMarginalPower
= 77 /* 50W */; SPMetricTotalPower
= 78 /* 60W */; }
6046 else if (!strncasecmp(HINFO_HWstring
, "Macmini", 7)) { SPMetricPortability
= 33 /* 5kg */; SPMetricMarginalPower
= 73 /* 20W */; SPMetricTotalPower
= 74 /* 25W */; }
6047 else if (!strncasecmp(HINFO_HWstring
, "AppleTV", 7)) { SPMetricPortability
= 35 /* 3kg */; SPMetricMarginalPower
= 10 /* 0W */; SPMetricTotalPower
= 73 /* 20W */; }
6048 else if (!strncasecmp(HINFO_HWstring
, "MacBook", 7)) { SPMetricPortability
= 37 /* 2kg */; SPMetricMarginalPower
= 71 /* 13W */; SPMetricTotalPower
= 72 /* 15W */; }
6049 else if (!strncasecmp(HINFO_HWstring
, "PowerBook",9)) { SPMetricPortability
= 37 /* 2kg */; SPMetricMarginalPower
= 71 /* 13W */; SPMetricTotalPower
= 72 /* 15W */; }
6050 LogSPS("HW_MODEL: %.*s (%s) Portability %d Marginal Power %d Total Power %d",
6051 HINFO_HWstring_prefixlen
, HINFO_HWstring
, HINFO_HWstring
, SPMetricPortability
, SPMetricMarginalPower
, SPMetricTotalPower
);
6053 err
= WatchForInternetSharingChanges(m
);
6054 if (err
) { LogMsg("WatchForInternetSharingChanges failed %d", err
); return(err
); }
6055 #endif // APPLE_OSX_mDNSResponder
6057 return(mStatus_NoError
);
6060 mDNSexport mStatus
mDNSPlatformInit(mDNS
*const m
)
6063 LogMsg("Note: Compiled without Apple-specific Split-DNS support");
6066 // Adding interfaces will use this flag, so set it now.
6067 m
->DivertMulticastAdvertisements
= !m
->AdvertiseLocalAddresses
;
6069 #if APPLE_OSX_mDNSResponder
6070 m
->SPSBrowseCallback
= UpdateSPSStatus
;
6073 mStatus result
= mDNSPlatformInit_setup(m
);
6075 // We don't do asynchronous initialization on OS X, so by the time we get here the setup will already
6076 // have succeeded or failed -- so if it succeeded, we should just call mDNSCoreInitComplete() immediately
6077 if (result
== mStatus_NoError
) mDNSCoreInitComplete(m
, mStatus_NoError
);
6081 mDNSexport
void mDNSPlatformClose(mDNS
*const m
)
6083 if (m
->p
->PowerConnection
)
6085 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m
->p
->PowerPortRef
), kCFRunLoopDefaultMode
);
6087 // According to <http://developer.apple.com/qa/qa2004/qa1340.html>, a single call
6088 // to IORegisterForSystemPower creates *three* objects that need to be disposed individually:
6089 IODeregisterForSystemPower(&m
->p
->PowerNotifier
);
6090 IOServiceClose ( m
->p
->PowerConnection
);
6091 IONotificationPortDestroy ( m
->p
->PowerPortRef
);
6092 #endif /* NO_IOPOWER */
6093 m
->p
->PowerConnection
= 0;
6098 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m
->p
->StoreRLS
, kCFRunLoopDefaultMode
);
6099 CFRunLoopSourceInvalidate(m
->p
->StoreRLS
);
6100 CFRelease(m
->p
->StoreRLS
);
6101 CFRelease(m
->p
->Store
);
6103 m
->p
->StoreRLS
= NULL
;
6108 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m
->p
->PMRLS
, kCFRunLoopDefaultMode
);
6109 CFRunLoopSourceInvalidate(m
->p
->PMRLS
);
6110 CFRelease(m
->p
->PMRLS
);
6114 if (m
->p
->SysEventNotifier
>= 0) { close(m
->p
->SysEventNotifier
); m
->p
->SysEventNotifier
= -1; }
6116 mDNSs32 utc
= mDNSPlatformUTC();
6117 MarkAllInterfacesInactive(m
, utc
);
6118 ClearInactiveInterfaces(m
, utc
);
6119 CloseSocketSet(&m
->p
->permanentsockets
);
6121 #if APPLE_OSX_mDNSResponder
6123 while (m
->TunnelClients
)
6125 ClientTunnel
*cur
= m
->TunnelClients
;
6126 LogInfo("mDNSPlatformClose: removing client tunnel %p %##s from list", cur
, cur
->dstname
.c
);
6127 if (cur
->q
.ThisQInterval
>= 0) mDNS_StopQuery(m
, &cur
->q
);
6128 AutoTunnelSetKeys(cur
, mDNSfalse
);
6129 m
->TunnelClients
= cur
->next
;
6130 freeL("ClientTunnel", cur
);
6133 if (AnonymousRacoonConfig
)
6135 AnonymousRacoonConfig
= mDNSNULL
;
6136 LogInfo("mDNSPlatformClose: Deconfiguring autotunnel");
6137 (void)mDNSConfigureServer(kmDNSDown
, mDNSNULL
);
6140 if (m
->AutoTunnelHostAddrActive
&& m
->AutoTunnelHostAddr
.b
[0])
6142 m
->AutoTunnelHostAddrActive
= mDNSfalse
;
6143 LogInfo("mDNSPlatformClose: Removing AutoTunnel address %.16a", &m
->AutoTunnelHostAddr
);
6144 (void)mDNSAutoTunnelInterfaceUpDown(kmDNSDown
, m
->AutoTunnelHostAddr
.b
);
6146 #endif // APPLE_OSX_mDNSResponder
6149 #if COMPILER_LIKES_PRAGMA_MARK
6151 #pragma mark - General Platform Support Layer functions
6154 mDNSexport mDNSu32
mDNSPlatformRandomNumber(void)
6156 return(arc4random());
6159 mDNSexport mDNSs32 mDNSPlatformOneSecond
= 1000;
6160 mDNSexport mDNSu32 mDNSPlatformClockDivisor
= 0;
6162 mDNSexport mStatus
mDNSPlatformTimeInit(void)
6164 // Notes: Typical values for mach_timebase_info:
6165 // tbi.numer = 1000 million
6166 // tbi.denom = 33 million
6167 // These are set such that (mach_absolute_time() * numer/denom) gives us nanoseconds;
6168 // numer / denom = nanoseconds per hardware clock tick (e.g. 30);
6169 // denom / numer = hardware clock ticks per nanosecond (e.g. 0.033)
6170 // (denom*1000000) / numer = hardware clock ticks per millisecond (e.g. 33333)
6171 // So: mach_absolute_time() / ((denom*1000000)/numer) = milliseconds
6173 // Arithmetic notes:
6174 // tbi.denom is at least 1, and not more than 2^32-1.
6175 // Therefore (tbi.denom * 1000000) is at least one million, but cannot overflow a uint64_t.
6176 // tbi.denom is at least 1, and not more than 2^32-1.
6177 // Therefore clockdivisor should end up being a number roughly in the range 10^3 - 10^9.
6178 // If clockdivisor is less than 10^3 then that means that the native clock frequency is less than 1MHz,
6179 // which is unlikely on any current or future Macintosh.
6180 // If clockdivisor is greater than 10^9 then that means the native clock frequency is greater than 1000GHz.
6181 // When we ship Macs with clock frequencies above 1000GHz, we may have to update this code.
6182 struct mach_timebase_info tbi
;
6183 kern_return_t result
= mach_timebase_info(&tbi
);
6184 if (result
== KERN_SUCCESS
) mDNSPlatformClockDivisor
= ((uint64_t)tbi
.denom
* 1000000) / tbi
.numer
;
6188 mDNSexport mDNSs32
mDNSPlatformRawTime(void)
6190 if (mDNSPlatformClockDivisor
== 0) { LogMsg("mDNSPlatformRawTime called before mDNSPlatformTimeInit"); return(0); }
6192 static uint64_t last_mach_absolute_time
= 0;
6193 //static uint64_t last_mach_absolute_time = 0x8000000000000000LL; // Use this value for testing the alert display
6194 uint64_t this_mach_absolute_time
= mach_absolute_time();
6195 if ((int64_t)this_mach_absolute_time
- (int64_t)last_mach_absolute_time
< 0)
6197 LogMsg("mDNSPlatformRawTime: last_mach_absolute_time %08X%08X", last_mach_absolute_time
);
6198 LogMsg("mDNSPlatformRawTime: this_mach_absolute_time %08X%08X", this_mach_absolute_time
);
6199 // Update last_mach_absolute_time *before* calling NotifyOfElusiveBug()
6200 last_mach_absolute_time
= this_mach_absolute_time
;
6201 // Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xyyy) or later.
6202 // (This bug happens all the time on 10.3, and we know that's not going to be fixed.)
6203 if (OSXVers
>= OSXVers_10_4_Tiger
)
6204 NotifyOfElusiveBug("mach_absolute_time went backwards!",
6205 "This error occurs from time to time, often on newly released hardware, "
6206 "and usually the exact cause is different in each instance.\r\r"
6207 "Please file a new Radar bug report with the title “mach_absolute_time went backwards” "
6208 "and assign it to Radar Component “Kernel” Version “X”.");
6210 last_mach_absolute_time
= this_mach_absolute_time
;
6212 return((mDNSs32
)(this_mach_absolute_time
/ mDNSPlatformClockDivisor
));
6215 mDNSexport mDNSs32
mDNSPlatformUTC(void)
6220 // Locking is a no-op here, because we're single-threaded with a CFRunLoop, so we can never interrupt ourselves
6221 mDNSexport
void mDNSPlatformLock (const mDNS
*const m
) { (void)m
; }
6222 mDNSexport
void mDNSPlatformUnlock (const mDNS
*const m
) { (void)m
; }
6223 mDNSexport
void mDNSPlatformStrCopy( void *dst
, const void *src
) { strcpy((char *)dst
, (char *)src
); }
6224 mDNSexport mDNSu32
mDNSPlatformStrLen ( const void *src
) { return(strlen((char*)src
)); }
6225 mDNSexport
void mDNSPlatformMemCopy( void *dst
, const void *src
, mDNSu32 len
) { memcpy(dst
, src
, len
); }
6226 mDNSexport mDNSBool
mDNSPlatformMemSame(const void *dst
, const void *src
, mDNSu32 len
) { return(memcmp(dst
, src
, len
) == 0); }
6227 mDNSexport
void mDNSPlatformMemZero( void *dst
, mDNSu32 len
) { memset(dst
, 0, len
); }
6228 #if !(APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING)
6229 mDNSexport
void * mDNSPlatformMemAllocate(mDNSu32 len
) { return(mallocL("mDNSPlatformMemAllocate", len
)); }
6231 mDNSexport
void mDNSPlatformMemFree (void *mem
) { freeL("mDNSPlatformMemFree", mem
); }