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.333.2.1 2006/08/29 06:24:30 cheshire
21 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
23 Revision 1.333 2006/06/29 05:33:30 cheshire
24 <rdar://problem/4607043> mDNSResponder conditional compilation options
26 Revision 1.332 2006/06/28 09:10:36 cheshire
27 Extra debugging messages
29 Revision 1.331 2006/06/21 22:29:42 cheshire
30 Make _CFCopySystemVersionDictionary() call more defensive on systems that have no build information set
32 Revision 1.330 2006/06/20 23:06:00 cheshire
33 Fix some keychain API type mismatches (was mDNSu32 instead of UInt32)
35 Revision 1.329 2006/06/08 23:22:33 cheshire
38 Revision 1.328 2006/03/19 03:27:49 cheshire
39 <rdar://problem/4118624> Suppress "interface flapping" logic for loopback
41 Revision 1.327 2006/03/19 02:00:09 cheshire
42 <rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
44 Revision 1.326 2006/03/08 22:42:23 cheshire
45 Fix spelling mistake: LocalReverseMapomain -> LocalReverseMapDomain
47 Revision 1.325 2006/01/10 00:39:17 cheshire
48 Add comments explaining how IPv6 link-local addresses sometimes have an embedded scope_id
50 Revision 1.324 2006/01/09 19:28:59 cheshire
51 <rdar://problem/4403128> Cap number of "sendto failed" messages we allow mDNSResponder to log
53 Revision 1.323 2006/01/05 21:45:27 cheshire
54 <rdar://problem/4400118> Fix uninitialized structure member in IPv6 code
56 Revision 1.322 2006/01/05 21:41:50 cheshire
57 <rdar://problem/4108164> Reword "mach_absolute_time went backwards" dialog
59 Revision 1.321 2006/01/05 21:35:06 cheshire
60 Add (commented out) trigger value for testing "mach_absolute_time went backwards" notice
62 Revision 1.320 2005/12/03 01:39:28 cheshire
63 <rdar://problem/4363411> Improve diagnostic message to indicate that message will not appear to customers
65 Revision 1.319 2005/12/02 00:02:15 cheshire
66 Include recvmsg return value in error message
68 Revision 1.318 2005/10/20 00:10:34 cheshire
69 <rdar://problem/4290265> Add check to avoid crashing NAT gateways that have buggy DNS relay code
71 Revision 1.317 2005/09/24 01:10:26 cheshire
74 Revision 1.316 2005/07/29 18:04:22 ksekar
75 <rdar://problem/4137930> Hostname registration should register IPv6 AAAA record with DNS Update
77 Revision 1.315 2005/07/22 21:50:55 ksekar
78 Fix GCC 4.0/Intel compiler warnings
80 Revision 1.314 2005/07/11 02:12:09 cheshire
81 <rdar://problem/4147774> Be defensive against invalid UTF-8 in dynamic host names
82 Fix copy-and-paste error: "CFRelease(StatusVals[0]);" should be "CFRelease(StateVals[0]);"
84 Revision 1.313 2005/07/04 23:52:25 cheshire
85 <rdar://problem/3923098> Things are showing up with a bogus interface index
87 Revision 1.312 2005/07/04 22:24:36 cheshire
88 Export NotifyOfElusiveBug() so other files can call it
90 Revision 1.311 2005/06/15 13:20:43 cheshire
91 <rdar://problem/4147774> Be defensive against invalid UTF-8 in dynamic host names
93 Revision 1.310 2005/04/07 00:49:58 cheshire
94 <rdar://problem/4080074> PPP connection disables Bonjour ".local" lookups
96 Revision 1.309 2005/03/23 05:53:29 cheshire
97 Fix %s where it should have been %##s in debugf & LogMsg calls
99 Revision 1.308 2005/03/09 00:48:44 cheshire
100 <rdar://problem/4015157> QU packets getting sent too early on wake from sleep
101 Move "m->p->NetworkChanged = 0;" line from caller to callee
103 Revision 1.307 2005/03/03 03:12:02 cheshire
104 Add comment about mDNSMacOSXSystemBuildNumber()
106 Revision 1.306 2005/03/02 22:18:00 cheshire
107 <rdar://problem/3930171> mDNSResponder requires AppleInternal packages to build on Tiger
109 Revision 1.305 2005/02/26 05:08:28 cheshire
110 <rdar://problem/3930171> mDNSResponder requires AppleInternal packages to build on Tiger
111 Added dnsinfo.h to project directory
113 Revision 1.304 2005/02/25 23:51:22 cheshire
114 <rdar://problem/4021868> SendServiceRegistration fails on wake from sleep
115 Return mStatus_UnknownErr instead of -1
117 Revision 1.303 2005/02/25 17:47:45 ksekar
118 <rdar://problem/4021868> SendServiceRegistration fails on wake from sleep
120 Revision 1.302 2005/02/25 02:34:14 cheshire
121 <rdar://problem/4017292> Should not indicate successful dynamic update if no network connection
122 Show status as 1 (in progress) while we're trying
124 Revision 1.301 2005/02/24 21:55:57 ksekar
125 <rdar://problem/4017292> Should not indicate successful dynamic update if no network connection
127 Revision 1.300 2005/02/15 20:03:13 ksekar
128 <rdar://problem/4005868> Crash when SCPreferences contains empty array
130 Revision 1.299 2005/02/15 02:46:53 cheshire
131 <rdar://problem/3967876> Don't log ENETUNREACH errors for unicast destinations
133 Revision 1.298 2005/02/10 00:41:59 cheshire
136 Revision 1.297 2005/02/09 23:38:51 ksekar
137 <rdar://problem/3993508> Reregister hostname when DNS server changes but IP address does not
139 Revision 1.296 2005/02/01 21:06:52 ksekar
140 Avoid spurious log message
142 Revision 1.295 2005/02/01 19:33:30 ksekar
143 <rdar://problem/3985239> Keychain format too restrictive
145 Revision 1.294 2005/01/27 21:30:23 cheshire
146 <rdar://problem/3952067> "Can't assign requested address" message after AirPort turned off
147 Don't write syslog messages for EADDRNOTAVAIL if we know network configuration changes are happening
149 Revision 1.293 2005/01/27 19:15:41 cheshire
150 Remove extraneous LogMsg() call
152 Revision 1.292 2005/01/27 17:48:38 cheshire
153 Added comment about CFSocketInvalidate closing the underlying socket
155 Revision 1.291 2005/01/27 00:10:58 cheshire
156 <rdar://problem/3967867> Name change log messages every time machine boots
158 Revision 1.290 2005/01/25 23:18:30 ksekar
159 fix for <rdar://problem/3971467> requires that local-only ".local" registration record be created
161 Revision 1.289 2005/01/25 18:08:31 ksekar
162 Removed redundant debug output
164 Revision 1.288 2005/01/25 17:42:26 ksekar
165 Renamed FoundDefBrowseDomain -> FoundLegacyBrowseDomain,
166 cleaned up duplicate log messages when adding/removing browse domains
168 Revision 1.287 2005/01/25 16:59:23 ksekar
169 <rdar://problem/3971138> sa_len not set checking reachability for TCP connections
171 Revision 1.286 2005/01/25 02:02:37 cheshire
172 <rdar://problem/3970673> mDNSResponder leaks
173 GetSearchDomains() was not calling dns_configuration_free().
175 Revision 1.285 2005/01/22 00:07:54 ksekar
176 <rdar://problem/3960546> mDNSResponder should look at all browse domains in SCPreferences
178 Revision 1.284 2005/01/21 23:07:17 ksekar
179 <rdar://problem/3960795> mDNSResponder causes Dial on Demand
181 Revision 1.283 2005/01/19 21:16:16 cheshire
182 Make sure when we set NetworkChanged that we don't set it to zero
184 Revision 1.282 2005/01/19 19:19:21 ksekar
185 <rdar://problem/3960191> Need a way to turn off domain discovery
187 Revision 1.281 2005/01/18 18:10:55 ksekar
188 <rdar://problem/3954575> Use 10.4 resolver API to get search domains
190 Revision 1.280 2005/01/17 22:48:52 ksekar
191 No longer need to call MarkSearchListElem for registration domain
193 Revision 1.279 2005/01/17 20:40:34 ksekar
194 SCPreferences changes should remove exactly one browse and one legacy browse domain for each remove event
196 Revision 1.278 2005/01/17 19:53:34 ksekar
197 Refinement to previous fix - register _legacy._browse records for SCPreference domains to achieve correct reference counting
199 Revision 1.277 2005/01/12 00:17:50 ksekar
200 <rdar://problem/3933573> Update LLQs *after* setting DNS
202 Revision 1.276 2005/01/10 17:39:10 ksekar
203 Refinement to 1.272 - avoid spurious warnings when registration and browse domains are set to same value and toggled on/off
205 Revision 1.275 2005/01/10 04:02:22 ksekar
206 Refinement to <rdar://problem/3891628> - strip trailing dot before writing hostname status to dynamic store
208 Revision 1.274 2005/01/10 03:41:36 ksekar
209 Correction to checkin 1.272 - check that registration domain is set
210 before trying to remove it as an implicit browse domain
212 Revision 1.273 2005/01/08 00:42:18 ksekar
213 <rdar://problem/3922758> Clean up syslog messages
215 Revision 1.272 2005/01/07 23:21:42 ksekar
216 <rdar://problem/3891628> Clean up SCPreferences format
218 Revision 1.271 2004/12/20 23:18:12 cheshire
219 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
220 One more refinement: When an interface with a v6LL address gets a v4 address too, that's not a flap
222 Revision 1.270 2004/12/20 21:28:14 cheshire
223 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
224 Additional refinements to handle sleep/wake better
226 Revision 1.269 2004/12/20 20:48:11 cheshire
227 Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xxx) or later
229 Revision 1.268 2004/12/18 03:19:04 cheshire
230 Show netmask in error log
232 Revision 1.267 2004/12/18 00:51:52 cheshire
233 Use symbolic constant kDNSServiceInterfaceIndexLocalOnly instead of (mDNSu32) ~0
235 Revision 1.266 2004/12/17 23:49:38 cheshire
236 <rdar://problem/3922754> Computer Name change is slow
237 Also treat changes to "Setup:/Network/DynamicDNS" the same way
239 Revision 1.265 2004/12/17 23:37:47 cheshire
240 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
241 (and other repetitive configuration changes)
243 Revision 1.264 2004/12/17 19:03:05 cheshire
244 Update debugging messages to show netmask a simple CIDR-style numeric value (0-128)
246 Revision 1.263 2004/12/17 05:25:46 cheshire
247 <rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs
249 Revision 1.262 2004/12/17 04:48:32 cheshire
250 <rdar://problem/3922754> Computer Name change is slow
252 Revision 1.261 2004/12/17 02:40:08 cheshire
253 Undo last change -- it was too strict
255 Revision 1.260 2004/12/16 22:17:16 cheshire
256 Only accept multicast packets on interfaces that have McastTxRx set
258 Revision 1.259 2004/12/16 20:13:01 cheshire
259 <rdar://problem/3324626> Cache memory management improvements
261 Revision 1.258 2004/12/14 00:18:05 cheshire
262 Don't log dns_configuration_copy() failures in the first three minutes after boot
264 Revision 1.257 2004/12/10 19:45:46 cheshire
265 <rdar://problem/3915074> Reduce egregious stack space usage
266 Reduced myCFSocketCallBack() stack frame from 9K to 512 bytes
268 Revision 1.256 2004/12/10 04:35:43 cheshire
269 <rdar://problem/3907233> Show "Note: Compiled without Apple-specific split DNS support" only once
271 Revision 1.255 2004/12/10 04:12:54 ksekar
272 <rdar://problem/3890764> Need new DefaultBrowseDomain key
274 Revision 1.254 2004/12/10 01:55:31 ksekar
275 <rdar://problem/3899067> Keychain lookups should be in lower case.
277 Revision 1.253 2004/12/09 03:15:41 ksekar
278 <rdar://problem/3806610> use _legacy instead of _default to find "empty string" browse domains
280 Revision 1.252 2004/12/07 01:32:42 cheshire
281 Don't log dns_configuration_copy() failure when running on 10.3
283 Revision 1.251 2004/12/06 22:30:31 cheshire
284 Added debugging log message
286 Revision 1.250 2004/12/06 06:59:08 ksekar
287 RegisterSplitDNS should return Unsupported error when compiled on Panther
289 Revision 1.249 2004/12/04 00:29:46 cheshire
290 Add "#ifdef MAC_OS_X_VERSION_10_4" around split-DNS code that can't be compiled on 10.3 systems
291 (When compiled on 10.3, code will not include split-DNS support.)
293 Revision 1.248 2004/12/01 20:57:20 ksekar
294 <rdar://problem/3873921> Wide Area Service Discovery must be split-DNS aware
296 Revision 1.247 2004/12/01 03:26:58 cheshire
297 Remove unused variables
299 Revision 1.246 2004/12/01 01:51:34 cheshire
300 Move ReadDDNSSettingsFromConfFile() from mDNSMacOSX.c to PlatformCommon.c
302 Revision 1.245 2004/11/30 03:24:04 cheshire
303 <rdar://problem/3854544> Defer processing network configuration changes until configuration has stabilized
305 Revision 1.244 2004/11/30 02:59:35 cheshire
306 For debugging diagnostics, added identifying strings in SCDynamicStoreCreate() calls
308 Revision 1.243 2004/11/29 19:17:29 ksekar
309 <rdar://problem/3878195> Unnecessary GetUserSpecifiedDDNSConfig log messages
311 Revision 1.242 2004/11/29 18:37:38 ksekar
312 <rdar://problem/3889341> Buffer overflow in GetConfigOption
314 Revision 1.241 2004/11/25 01:37:04 ksekar
315 <rdar://problem/3894854> Config file and SCPreferences don't play well together
317 Revision 1.240 2004/11/25 01:29:42 ksekar
318 Remove unnecessary log messages
320 Revision 1.239 2004/11/25 01:27:19 ksekar
321 <rdar://problem/3885859> Don't try to advertise link-local IP addresses via dynamic update
323 Revision 1.238 2004/11/24 22:00:59 cheshire
324 Move definition of mDNSAddressIsAllDNSLinkGroup() from mDNSMacOSX.c to mDNSEmbeddedAPI.h
326 Revision 1.237 2004/11/24 21:54:44 cheshire
327 <rdar://problem/3894475> mDNSCore not receiving unicast responses properly
329 Revision 1.236 2004/11/23 03:39:46 cheshire
330 Let interface name/index mapping capability live directly in JNISupport.c,
331 instead of having to call through to the daemon via IPC to get this information.
333 Revision 1.235 2004/11/17 01:45:35 cheshire
334 <rdar://problem/3847435> mDNS buddy list frequently becomes empty if you let the machine sleep
335 Refresh our interface list on receiving kIOMessageSystemHasPoweredOn,
336 in case we get no System Configuration Framework "network changed" event.
338 Revision 1.234 2004/11/17 00:32:56 ksekar
339 <rdar://problem/3880773> mDNSResponder will not discover zones contained both in Search Domains and DHCP Domain option
341 Revision 1.233 2004/11/12 03:16:45 rpantos
342 rdar://problem/3809541 Add mDNSPlatformGetInterfaceByName, mDNSPlatformGetInterfaceName
344 Revision 1.232 2004/11/10 20:40:54 ksekar
345 <rdar://problem/3868216> LLQ mobility fragile on non-primary interface
347 Revision 1.231 2004/11/06 00:59:33 ksekar
348 Don't log ENETDOWN errors for unicast destinations (pollutes log on
351 Revision 1.230 2004/11/05 01:04:10 ksekar
352 <rdar://problem/3774577> LegacyNATDestroy() called too enthusiastically
354 Revision 1.229 2004/11/03 03:45:16 cheshire
355 <rdar://problem/3863627> mDNSResponder does not inform user of Computer Name collisions
357 Revision 1.228 2004/11/02 23:47:32 cheshire
358 <rdar://problem/3863214> Default hostname and Computer Name should be unique
360 Revision 1.227 2004/11/02 04:23:03 cheshire
361 Change to more informative name "GetUserSpecifiedLocalHostName()"
363 Revision 1.226 2004/11/01 20:36:19 ksekar
364 <rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
366 Revision 1.225 2004/10/28 19:03:04 cheshire
367 Remove \n from LogMsg() calls
369 Revision 1.224 2004/10/28 17:47:34 cheshire
370 Oops. Forgot the %d in the log message.
372 Revision 1.223 2004/10/28 17:24:28 cheshire
373 Updated "bad ifa_netmask" log message to give more information
375 Revision 1.222 2004/10/28 03:36:34 cheshire
376 <rdar://problem/3856535> Share the same port for both multicast and unicast receiving
378 Revision 1.221 2004/10/28 03:24:41 cheshire
379 Rename m->CanReceiveUnicastOn as m->CanReceiveUnicastOn5353
381 Revision 1.220 2004/10/28 00:53:57 cheshire
382 Export mDNSMacOSXNetworkChanged() so it's callable from outside this mDNSMacOSX.c;
383 Add LogOperation() call to record when we get network change events
385 Revision 1.219 2004/10/27 20:42:20 cheshire
386 Clean up debugging messages
388 Revision 1.218 2004/10/27 02:03:59 cheshire
389 Update debugging messages
391 Revision 1.217 2004/10/26 20:48:21 cheshire
392 Improve logging messages
394 Revision 1.216 2004/10/26 01:02:37 cheshire
397 Revision 1.215 2004/10/25 20:09:00 ksekar
398 Cleaned up config file parsing.
400 Revision 1.214 2004/10/25 19:30:53 ksekar
401 <rdar://problem/3827956> Simplify dynamic host name structures
403 Revision 1.213 2004/10/23 01:16:01 cheshire
404 <rdar://problem/3851677> uDNS operations not always reliable on multi-homed hosts
406 Revision 1.212 2004/10/22 20:52:08 ksekar
407 <rdar://problem/3799260> Create NAT port mappings for Long Lived Queries
409 Revision 1.211 2004/10/22 01:07:11 cheshire
410 <rdar://problem/3375328> select() says data is waiting; recvfrom() says there is no data
411 Log error message if socket() ever returns file descriptors 0, 1 or 2 (stdin/stdout/stderr).
412 These are all supposed to be remapped to /dev/null
414 Revision 1.210 2004/10/20 02:19:54 cheshire
415 Eliminate "SetupAddr invalid sa_family" warning from RegisterSearchDomains()
417 Revision 1.209 2004/10/16 00:17:00 cheshire
418 <rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
420 Revision 1.208 2004/10/15 23:00:18 ksekar
421 <rdar://problem/3799242> Need to update LLQs on location changes
423 Revision 1.207 2004/10/13 22:45:23 cheshire
424 <rdar://problem/3438392> Ten-second delay before kIOMessageSystemHasPoweredOn message
426 Revision 1.206 2004/10/13 22:11:46 cheshire
427 Update debugging messages
429 Revision 1.205 2004/10/12 21:10:11 cheshire
430 <rdar://problem/3438376> mach_absolute_time() not monotonically increasing
431 Do a NotifyOfElusiveBug() if we see mach_absolute_time() go backwards
433 Revision 1.204 2004/10/12 03:20:52 ksekar
434 <rdar://problem/3835614> Incorrect LogMsg produces garbage on errors
436 Revision 1.203 2004/10/08 04:29:25 ksekar
437 <rdar://problem/3831842> Allow default search domains to be set via hint from DHCP
439 Revision 1.202 2004/10/04 05:56:04 cheshire
440 <rdar://problem/3824730> mDNSResponder doesn't respond to certain AirPort changes
442 Revision 1.201 2004/09/30 00:24:59 ksekar
443 <rdar://problem/3695802> Dynamically update default registration domains on config change
445 Revision 1.200 2004/09/26 23:20:35 ksekar
446 <rdar://problem/3813108> Allow default registrations in multiple wide-area domains
448 Revision 1.199 2004/09/24 23:54:55 cheshire
449 <rdar://problem/3787102> Don't use kCFSocketCloseOnInvalidate
451 Revision 1.198 2004/09/24 23:47:49 cheshire
452 Correct comment and error message
454 Revision 1.197 2004/09/24 23:39:27 cheshire
455 <rdar://problem/3733705> Only IPv6 loopback address advertised on laptop w/no networking
457 Revision 1.196 2004/09/24 20:53:04 cheshire
458 Revise error message to say "Setsockopt SO_REUSEPORT failed" instead of "Flaw in Kernel"
460 Revision 1.195 2004/09/24 19:21:45 cheshire
461 <rdar://problem/3671626> Report "Address already in use" errors
463 Revision 1.194 2004/09/24 19:16:54 cheshire
464 Remove "mDNS *const m" parameter from NotifyOfElusiveBug();
465 Refine error message to say "Flaw in Kernel (select/recvfrom mismatch)"
467 Revision 1.193 2004/09/22 00:41:59 cheshire
468 Move tcp connection status codes into the legal range allocated for mDNS use
470 Revision 1.192 2004/09/21 21:02:55 cheshire
471 Set up ifname before calling mDNS_RegisterInterface()
473 Revision 1.191 2004/09/21 19:19:36 cheshire
474 <rdar://problem/3760923> Combine WatchForDynDNSChanges() into WatchForNetworkChanges()
476 Revision 1.190 2004/09/21 19:04:45 cheshire
477 Strip trailing white space from the ends of lines
479 Revision 1.189 2004/09/21 00:13:28 cheshire
480 Fix build failure (io_connect_t and io_object_t are integers, not pointers)
482 Revision 1.188 2004/09/20 23:52:02 cheshire
483 CFSocket{Puma}.c renamed to mDNSMacOSX{Puma}.c
485 Revision 1.187 2004/09/18 01:37:01 cheshire
488 Revision 1.186 2004/09/18 01:11:57 ksekar
489 <rdar://problem/3806734> Add a user's default domain to empty-string browse list
491 Revision 1.185 2004/09/17 01:08:52 cheshire
492 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
493 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
494 declared in that file are ONLY appropriate to single-address-space embedded applications.
495 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
497 Revision 1.184 2004/09/17 00:19:10 cheshire
498 For consistency with AllDNSLinkGroupv6, rename AllDNSLinkGroup to AllDNSLinkGroupv4
500 Revision 1.183 2004/09/17 00:15:56 cheshire
501 Rename mDNSPlatformInit_ReceiveUnicast to mDNSPlatformInit_CanReceiveUnicast
503 Revision 1.182 2004/09/16 21:36:36 cheshire
504 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
505 Changes to add necessary locking calls around unicast DNS operations
507 Revision 1.181 2004/09/16 02:03:42 cheshire
508 <rdar://problem/3802944> Change address to notify user of kernel flaw
510 Revision 1.180 2004/09/16 01:58:22 cheshire
511 Fix compiler warnings
513 Revision 1.179 2004/09/16 00:24:49 cheshire
514 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
516 Revision 1.178 2004/09/15 21:51:34 cheshire
517 <rdar://problem/3387020> mDNSResponder should notify user of kernel flaw
518 Calling CFUserNotificationDisplayNotice too early in the boot process seems to kill
519 the machine, so make sure we don't do this until at least three minutes after boot.
521 Revision 1.177 2004/09/15 01:16:29 cheshire
522 <rdar://problem/3387020> mDNSResponder should notify user of kernel flaw
524 Revision 1.176 2004/09/14 23:42:36 cheshire
525 <rdar://problem/3801296> Need to seed random number generator from platform-layer data
527 Revision 1.175 2004/09/14 21:35:46 cheshire
528 Minor code tidying, and added comments about CFRetainCounts
530 Revision 1.174 2004/09/14 19:14:57 ksekar
531 <rdar://problem/3192531> DynDNS: Discovery of DynDNS Zones via Reverse-Map PTR
533 Revision 1.173 2004/08/25 23:35:22 ksekar
534 <rdar://problem/3770615>: Error converting shared secret from base-64 to binary
536 Revision 1.172 2004/08/25 02:01:45 cheshire
537 <rdar://problem/3774777> Need to be able to get status of Dynamic DNS Host Name Update
539 Revision 1.171 2004/08/25 01:04:42 cheshire
540 Don't need to CFRelease name and array
542 Revision 1.170 2004/08/25 00:37:28 ksekar
543 <rdar://problem/3774635>: Cleanup DynDNS hostname registration code
545 Revision 1.169 2004/08/18 17:35:41 ksekar
546 <rdar://problem/3651443>: Feature #9586: Need support for Legacy NAT gateways
548 Revision 1.168 2004/08/17 03:16:24 ksekar
549 Fixed checkin 1.166 - enumeration type changed for wrong invocation of mDNS_GetDomains
551 Revision 1.167 2004/08/17 00:52:43 ksekar
552 Fix config file parse error, make semantics match SCPreferences
555 Revision 1.166 2004/08/16 19:55:07 ksekar
556 Change enumeration type to BrowseDefault to construct empty-string
557 browse list as result of checking 1.161.
559 Revision 1.165 2004/08/16 19:52:40 ksekar
560 Pass computer name + zone for FQDN after keychain notification,
561 setting global default service registration domain to the zone.
563 Revision 1.164 2004/08/16 16:52:37 ksekar
564 Pass in zone read from keychain to mDNS_SetFQDNs.
566 Revision 1.163 2004/08/14 03:22:42 cheshire
567 <rdar://problem/3762579> Dynamic DNS UI <-> mDNSResponder glue
568 Add GetUserSpecifiedDDNSName() routine
569 Convert ServiceRegDomain to domainname instead of C string
570 Replace mDNS_GenerateFQDN/mDNS_GenerateGlobalFQDN with mDNS_SetFQDNs
572 Revision 1.162 2004/08/12 22:34:00 cheshire
573 All strings should be read as kCFStringEncodingUTF8, not kCFStringEncodingASCII
575 Revision 1.161 2004/08/11 00:17:46 ksekar
576 <rdar://problem/3757662>: 8A227: Need Lighthouse configred machines to
577 set default bit for their domains
579 Revision 1.160 2004/07/29 19:27:16 ksekar
580 NATPMP Support - minor fixes and cleanup
582 Revision 1.159 2004/07/26 22:49:31 ksekar
583 <rdar://problem/3651409>: Feature #9516: Need support for NATPMP in client
585 Revision 1.158 2004/07/13 21:24:24 rpantos
586 Fix for <rdar://problem/3701120>.
588 Revision 1.157 2004/06/08 18:54:48 ksekar
589 <rdar://problem/3681378>: mDNSResponder leaks after exploring in Printer Setup Utility
591 Revision 1.156 2004/06/05 00:04:26 cheshire
592 <rdar://problem/3668639>: wide-area domains should be returned in reg. domain enumeration
594 Revision 1.155 2004/06/04 08:58:30 ksekar
595 <rdar://problem/3668624>: Keychain integration for secure dynamic update
597 Revision 1.154 2004/05/31 22:22:28 ksekar
598 <rdar://problem/3668639>: wide-area domains should be returned in
599 reg. domain enumeration
601 Revision 1.153 2004/05/26 17:06:33 cheshire
602 <rdar://problem/3668515>: Don't rely on CFSocketInvalidate() to remove RunLoopSource
604 Revision 1.152 2004/05/18 23:51:26 cheshire
605 Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
607 Revision 1.151 2004/05/17 21:46:34 cheshire
608 <rdar://problem/3616426>: When interface is turned off, browse "remove" events are delivered with interface index zero
609 Take care to correctly update InterfaceIDs when a dormant interface comes back to life
611 Revision 1.150 2004/05/13 04:54:20 ksekar
612 Unified list copy/free code. Added symetric list for
614 Revision 1.149 2004/05/13 03:55:14 ksekar
615 Fixed list traversal bug in FoundDefSearchDomain.
617 Revision 1.148 2004/05/12 22:03:08 ksekar
618 Made GetSearchDomainList a true platform-layer call (declaration moved
619 from mDNSMacOSX.h to mDNSEmbeddedAPI.h), impelemted to return "local"
620 only on non-OSX platforms. Changed call to return a copy of the list
621 to avoid shared memory issues. Added a routine to free the list.
623 Revision 1.147 2004/05/12 02:03:25 ksekar
624 Non-local domains will only be browsed by default, and show up in
625 _browse domain enumeration, if they contain an _browse._dns-sd ptr record.
627 Revision 1.146 2004/04/27 02:49:15 cheshire
628 <rdar://problem/3634655>: mDNSResponder leaks sockets on bind() error
630 Revision 1.145 2004/04/21 03:08:03 cheshire
631 Rename 'alias' to more descriptive name 'primary'
633 Revision 1.144 2004/04/21 03:04:35 cheshire
634 Minor cleanup for clarity
636 Revision 1.143 2004/04/21 03:03:30 cheshire
637 Preparation work: AddInterfaceToList() should return pointer to structure it creates
639 Revision 1.142 2004/04/21 02:49:11 cheshire
640 To reduce future confusion, renamed 'TxAndRx' to 'McastTxRx'
642 Revision 1.141 2004/04/21 02:20:47 cheshire
643 Rename interface field 'CurrentlyActive' to more descriptive 'Exists'
645 Revision 1.140 2004/04/14 23:09:29 ksekar
646 Support for TSIG signed dynamic updates.
648 Revision 1.139 2004/04/09 17:40:26 cheshire
649 Remove unnecessary "Multicast" field -- it duplicates the semantics of the existing McastTxRx field
651 Revision 1.138 2004/04/09 16:37:16 cheshire
652 Suggestion from Bob Bradley:
653 Move NumCacheRecordsForInterfaceID() to DNSCommon.c so it's available to all platform layers
655 Revision 1.137 2004/04/08 00:59:55 cheshire
656 <rdar://problem/3609972> When interface turned off, browse "remove" events delivered with interface index zero
657 Unify use of the InterfaceID field, and make code that walks the list respect the 'Exists' flag
659 Revision 1.136 2004/04/07 01:08:57 cheshire
660 <rdar://problem/3609972> When interface turned off, browse "remove" events delivered with interface index zero
662 Revision 1.135 2004/03/19 01:01:03 ksekar
663 Fixed config file parsing to chop newline
665 Revision 1.134 2004/03/13 01:57:34 ksekar
666 <rdar://problem/3192546>: DynDNS: Dynamic update of service records
668 Revision 1.133 2004/02/02 22:46:56 cheshire
669 Move "CFRelease(dict);" inside the "if (dict)" check
671 Revision 1.132 2004/01/28 02:30:08 ksekar
672 Added default Search Domains to unicast browsing, controlled via
673 Networking sharing prefs pane. Stopped sending unicast messages on
674 every interface. Fixed unicast resolving via mach-port API.
676 Revision 1.131 2004/01/27 22:57:48 cheshire
677 <rdar://problem/3534352>: Need separate socket for issuing unicast queries
679 Revision 1.130 2004/01/27 22:28:40 cheshire
680 <rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
681 Additional lingering port 53 code deleted
683 Revision 1.129 2004/01/27 20:15:23 cheshire
684 <rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
686 Revision 1.128 2004/01/24 23:58:17 cheshire
687 Change to use mDNSVal16() instead of shifting and ORing
689 Revision 1.127 2004/01/24 04:59:16 cheshire
690 Fixes so that Posix/Linux, OS9, Windows, and VxWorks targets build again
692 Revision 1.126 2004/01/23 23:23:15 ksekar
693 Added TCP support for truncated unicast messages.
695 Revision 1.125 2004/01/22 03:43:09 cheshire
696 Export constants like mDNSInterface_LocalOnly so that the client layers can use them
698 Revision 1.124 2004/01/21 21:53:19 cheshire
699 <rdar://problem/3448144>: Don't try to receive unicast responses if we're not the first to bind to the UDP port
701 Revision 1.123 2004/01/20 03:18:25 cheshire
702 Removed "LogMsg("Hey There!");" that evidently got checked in my mistake
704 Revision 1.122 2003/12/17 20:43:59 cheshire
705 <rdar://problem/3496728>: Syslog messages saying "sendto failed"
707 Revision 1.121 2003/12/13 03:05:28 ksekar
708 <rdar://problem/3192548>: DynDNS: Unicast query of service records
710 Revision 1.120 2003/12/08 21:00:46 rpantos
711 Changes to support mDNSResponder on Linux.
713 Revision 1.119 2003/12/03 02:35:15 cheshire
714 Also report value of m->timenow when logging sendto() failure
716 Revision 1.118 2003/11/14 20:59:09 cheshire
717 Clients can't use AssignDomainName macro because mDNSPlatformMemCopy is defined in mDNSPlatformFunctions.h.
718 Best solution is just to combine mDNSEmbeddedAPI.h and mDNSPlatformFunctions.h into a single file.
720 Revision 1.117 2003/11/08 22:18:29 cheshire
721 <rdar://problem/3477870>: Don't need to show process ID in *every* mDNSResponder syslog message
723 Revision 1.116 2003/09/23 16:39:49 cheshire
724 When LogAllOperations is set, also report registration and deregistration of interfaces
726 Revision 1.115 2003/09/10 00:45:55 cheshire
727 <rdar://problem/3412328> Don't log "sendto failed" errors during the first two minutes of startup
729 Revision 1.114 2003/08/27 02:55:13 cheshire
730 <rdar://problem/3387910>: Bug: Don't report mDNSPlatformSendUDP sendto errno 64 (Host is down)
732 Revision 1.113 2003/08/19 22:20:00 cheshire
733 <rdar://problem/3376721> Don't use IPv6 on interfaces that have a routable IPv4 address configured
734 More minor refinements
736 Revision 1.112 2003/08/19 03:04:43 cheshire
737 <rdar://problem/3376721> Don't use IPv6 on interfaces that have a routable IPv4 address configured
739 Revision 1.111 2003/08/18 22:53:37 cheshire
740 <rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformRawTime()
742 Revision 1.110 2003/08/16 03:39:00 cheshire
743 <rdar://problem/3338440> InterfaceID -1 indicates "local only"
745 Revision 1.109 2003/08/15 02:19:49 cheshire
746 <rdar://problem/3375225> syslog messages: myCFSocketCallBack recvfrom skt 6 error -1 errno 35
747 Also limit number of messages to at most 100
749 Revision 1.108 2003/08/12 22:24:52 cheshire
750 <rdar://problem/3375225> syslog messages: myCFSocketCallBack recvfrom skt 6 error -1 errno 35
751 This message indicates a kernel bug, but still we don't want to flood syslog.
752 Do a sleep(1) after writing this log message, to limit the rate.
754 Revision 1.107 2003/08/12 19:56:25 cheshire
757 Revision 1.106 2003/08/12 13:48:32 cheshire
758 Add comment explaining clockdivisor calculation
760 Revision 1.105 2003/08/12 13:44:14 cheshire
761 <rdar://problem/3370229> mDNSResponder *VERY* unhappy if time goes backwards
762 Use mach_absolute_time() (which is guaranteed to always go forwards, resetting only on reboot)
763 instead of gettimeofday() (which can jump back if the user manually changes their time/date)
765 Revision 1.104 2003/08/12 13:12:07 cheshire
766 Textual search/replace: Indicate local functions using "mDNSlocal" instead of "static"
768 Revision 1.103 2003/08/08 18:36:04 cheshire
769 <rdar://problem/3344154> Only need to revalidate on interface removal on platforms that have the PhantomInterfaces bug
771 Revision 1.102 2003/08/06 00:14:52 cheshire
772 <rdar://problem/3330324> Need to check IP TTL on responses
773 Also add corresponding checks in the IPv6 code path
775 Revision 1.101 2003/08/05 22:20:16 cheshire
776 <rdar://problem/3330324> Need to check IP TTL on responses
778 Revision 1.100 2003/08/05 21:18:50 cheshire
779 <rdar://problem/3363185> mDNSResponder should ignore 6to4
780 Only use interfaces that are marked as multicast-capable (IFF_MULTICAST)
782 Revision 1.99 2003/08/05 20:13:52 cheshire
783 <rdar://problem/3294080> mDNSResponder using IPv6 interfaces before they are ready
784 Ignore interfaces with the IN6_IFF_NOTREADY flag set
786 Revision 1.98 2003/07/20 03:38:51 ksekar
787 <rdar://problem/3320722>
788 Completed support for Unix-domain socket based API.
790 Revision 1.97 2003/07/19 03:15:16 cheshire
791 Add generic MemAllocate/MemFree prototypes to mDNSPlatformFunctions.h,
792 and add the obvious trivial implementations to each platform support layer
794 Revision 1.96 2003/07/18 00:30:00 cheshire
795 <rdar://problem/3268878> Remove mDNSResponder version from packet header and use HINFO record instead
797 Revision 1.95 2003/07/12 03:15:20 cheshire
798 <rdar://problem/3324848> After SCDynamicStore notification, mDNSResponder updates
799 m->hostlabel even if user hasn't actually actually changed their dot-local hostname
801 Revision 1.94 2003/07/03 00:51:54 cheshire
802 <rdar://problem/3287213> When select() and recvmgs() disagree, get more info from kernel about the socket state
804 Revision 1.93 2003/07/03 00:09:14 cheshire
805 <rdar://problem/3286004> New APIs require a mDNSPlatformInterfaceIDfromInterfaceIndex() call
806 Additional refinement suggested by Josh: Use info->scope_id instead of if_nametoindex(info->ifa_name);
808 Revision 1.92 2003/07/02 21:19:51 cheshire
809 <rdar://problem/3313413> Update copyright notices, etc., in source code comments
811 Revision 1.91 2003/06/24 01:53:51 cheshire
812 Minor update to comments
814 Revision 1.90 2003/06/24 01:51:47 cheshire
815 <rdar://problem/3303118> Oops: Double-dispose of sockets
816 Don't need to close sockets: CFSocketInvalidate() does that for us
818 Revision 1.89 2003/06/21 18:12:47 cheshire
819 <rdar://problem/3296061> mDNSResponder cannot handle interfaces whose total name is >3 chars
820 One-line change: should say "IF_NAMESIZE", not sizeof(ifname)
822 Revision 1.88 2003/06/12 23:38:37 cheshire
823 <rdar://problem/3291162> mDNSResponder doesn't detect some configuration changes
824 Also check that scope_id matches before concluding that two interfaces are the same
826 Revision 1.87 2003/06/10 01:14:11 cheshire
827 <rdar://problem/3286004> New APIs require a mDNSPlatformInterfaceIDfromInterfaceIndex() call
829 Revision 1.86 2003/05/28 02:41:52 cheshire
830 <rdar://problem/3034346> Time to remove Mac OS 9 UDP Port 53 legacy support
832 Revision 1.85 2003/05/28 02:39:47 cheshire
833 Minor change to debugging messages
835 Revision 1.84 2003/05/27 22:29:40 cheshire
836 Remove out-dated comment
838 Revision 1.83 2003/05/26 03:21:29 cheshire
839 Tidy up address structure naming:
840 mDNSIPAddr => mDNSv4Addr (for consistency with mDNSv6Addr)
841 mDNSAddr.addr.ipv4 => mDNSAddr.ip.v4
842 mDNSAddr.addr.ipv6 => mDNSAddr.ip.v6
844 Revision 1.82 2003/05/26 03:01:27 cheshire
845 <rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
847 Revision 1.81 2003/05/24 02:06:42 cheshire
848 <rdar://problem/3268480> IPv6 Multicast Loopback doesn't work
849 Tried setting IPV6_MULTICAST_LOOP; it doesn't help.
850 However, it is probably wise to have the code explicitly set this socket
851 option anyway, in case the default changes in later versions of Unix.
853 Revision 1.80 2003/05/24 02:02:24 cheshire
854 <rdar://problem/3221880> if_indextoname consumes a lot of CPU
855 Fix error in myIfIndexToName; was returning prematurely
857 Revision 1.79 2003/05/23 23:07:44 cheshire
858 <rdar://problem/3268199> Must not write to stderr when running as daemon
860 Revision 1.78 2003/05/23 01:19:04 cheshire
861 <rdar://problem/3267085> mDNSResponder needs to signal type of service to AirPort
862 Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
864 Revision 1.77 2003/05/23 01:12:05 cheshire
867 Revision 1.76 2003/05/22 01:26:01 cheshire
870 Revision 1.75 2003/05/22 00:07:09 cheshire
871 <rdar://problem/3264366> myCFSocketCallBack recvfrom(5) error 1, errno 35
872 Extra logging to determine whether there is a bug in CFSocket
874 Revision 1.74 2003/05/21 20:20:12 cheshire
875 Fix warnings (mainly printf format string warnings, like using "%d" where
876 it should say "%lu", etc.) and improve error logging (use strerror()
877 to include textual error message as well as numeric error in log messages).
879 Revision 1.73 2003/05/21 17:56:29 ksekar
880 <rdar://problem/3191277>: mDNSResponder doesn't watch for IPv6 address changes
882 Revision 1.72 2003/05/14 18:48:41 cheshire
883 <rdar://problem/3159272> mDNSResponder should be smarter about reconfigurations
884 More minor refinements:
885 mDNSMacOSX.c needs to do *all* its mDNS_DeregisterInterface calls before freeing memory
886 mDNS_DeregisterInterface revalidates cache record when *any* representative of an interface goes away
888 Revision 1.71 2003/05/14 07:08:37 cheshire
889 <rdar://problem/3159272> mDNSResponder should be smarter about reconfigurations
890 Previously, when there was any network configuration change, mDNSResponder
891 would tear down the entire list of active interfaces and start again.
892 That was very disruptive, and caused the entire cache to be flushed,
893 and caused lots of extra network traffic. Now it only removes interfaces
894 that have really gone, and only adds new ones that weren't there before.
896 Revision 1.70 2003/05/07 18:30:24 cheshire
897 Fix signed/unsigned comparison warning
899 Revision 1.69 2003/05/06 20:14:44 cheshire
902 Revision 1.68 2003/05/06 00:00:49 cheshire
903 <rdar://problem/3248914> Rationalize naming of domainname manipulation functions
905 Revision 1.67 2003/04/29 00:43:44 cheshire
906 Fix compiler warnings
908 Revision 1.66 2003/04/26 02:41:58 cheshire
909 <rdar://problem/3241281> Change timenow from a local variable to a structure member
911 Revision 1.65 2003/04/26 02:34:01 cheshire
912 Add missing mDNSexport
914 Revision 1.64 2003/04/15 16:48:06 jgraessl
915 <rdar://problem/3228833>
916 Modified code in CFSocket notifier function to read all packets on the socket
917 instead of reading only one packet every time the notifier was called.
919 Revision 1.63 2003/04/15 16:33:50 jgraessl
920 <rdar://problem/3221880>
921 Switched to our own copy of if_indextoname to improve performance.
923 Revision 1.62 2003/03/28 01:55:44 cheshire
924 Minor improvements to debugging messages
926 Revision 1.61 2003/03/27 03:30:56 cheshire
927 <rdar://problem/3210018> Name conflicts not handled properly, resulting in memory corruption, and eventual crash
928 Problem was that HostNameCallback() was calling mDNS_DeregisterInterface(), which is not safe in a callback
930 1. Make mDNS_DeregisterInterface() safe to call from a callback
931 2. Make HostNameCallback() use mDNS_DeadvertiseInterface() instead
932 (it never really needed to deregister the interface at all)
934 Revision 1.60 2003/03/15 04:40:38 cheshire
935 Change type called "mDNSOpaqueID" to the more descriptive name "mDNSInterfaceID"
937 Revision 1.59 2003/03/11 01:23:26 cheshire
938 <rdar://problem/3194246> mDNSResponder socket problems
940 Revision 1.58 2003/03/06 01:43:04 cheshire
941 <rdar://problem/3189097> Additional debugging code in mDNSResponder
942 Improve "LIST_ALL_INTERFACES" output
944 Revision 1.57 2003/03/05 22:36:27 cheshire
945 <rdar://problem/3186338> Loopback doesn't work with mDNSResponder-27
946 Temporary workaround: Skip loopback interface *only* if we found at least one v4 interface to use
948 Revision 1.56 2003/03/05 01:50:38 cheshire
949 <rdar://problem/3189097> Additional debugging code in mDNSResponder
951 Revision 1.55 2003/02/21 01:54:09 cheshire
952 <rdar://problem/3099194> mDNSResponder needs performance improvements
953 Switched to using new "mDNS_Execute" model (see "Implementer Notes.txt")
955 Revision 1.54 2003/02/20 06:48:35 cheshire
956 <rdar://problem/3169535> Xserve RAID needs to do interface-specific registrations
957 Reviewed by: Josh Graessley, Bob Bradley
959 Revision 1.53 2003/01/29 02:21:23 cheshire
960 Return mStatus_Invalid if can't send packet because socket not available
962 Revision 1.52 2003/01/28 19:39:43 jgraessl
963 Enabling AAAA over IPv4 support.
965 Revision 1.51 2003/01/28 05:11:23 cheshire
966 Fixed backwards comparison in SearchForInterfaceByName
968 Revision 1.50 2003/01/13 23:49:44 jgraessl
969 Merged changes for the following fixes in to top of tree:
970 <rdar://problem/3086540> computer name changes not handled properly
971 <rdar://problem/3124348> service name changes are not properly handled
972 <rdar://problem/3124352> announcements sent in pairs, failing chattiness test
974 Revision 1.49 2002/12/23 22:13:30 jgraessl
975 Reviewed by: Stuart Cheshire
976 Initial IPv6 support for mDNSResponder.
978 Revision 1.48 2002/11/22 01:37:52 cheshire
979 <rdar://problem/3108426> mDNSResponder is monitoring ServiceEntities instead of InterfaceEntities
981 Revision 1.47 2002/09/21 20:44:51 zarzycki
984 Revision 1.46 2002/09/19 21:25:35 cheshire
985 mDNS_snprintf() doesn't need to be in a separate file
987 Revision 1.45 2002/09/17 01:45:13 cheshire
988 Add LIST_ALL_INTERFACES symbol for debugging
990 Revision 1.44 2002/09/17 01:36:23 cheshire
991 Move Puma support to mDNSMacOSXPuma.c
993 Revision 1.43 2002/09/17 01:05:28 cheshire
994 Change mDNS_AdvertiseLocalAddresses to be an Init parameter instead of a global
996 Revision 1.42 2002/09/16 23:13:50 cheshire
1001 // ***************************************************************************
1003 // Supporting routines to run mDNS on a CFRunLoop platform
1004 // ***************************************************************************
1006 // For debugging, set LIST_ALL_INTERFACES to 1 to display all found interfaces,
1007 // including ones that mDNSResponder chooses not to use.
1008 #define LIST_ALL_INTERFACES 0
1010 // For enabling AAAA records over IPv4. Setting this to 0 sends only
1011 // A records over IPv4 and AAAA over IPv6. Setting this to 1 sends both
1012 // AAAA and A records over both IPv4 and IPv6.
1013 #define AAAA_OVER_V4 1
1015 #include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
1016 #include "DNSCommon.h"
1017 #include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform
1018 #include "../mDNSShared/uds_daemon.h" // Defines communication interface from platform layer up to UDS daemon
1019 #include "PlatformCommon.h"
1022 #include <stdarg.h> // For va_list support
1024 #include <net/if_types.h> // For IFT_ETHER
1025 #include <net/if_dl.h>
1026 #include <sys/uio.h>
1027 #include <sys/param.h>
1028 #include <sys/socket.h>
1029 #include <sys/sysctl.h>
1031 #include <sys/ioctl.h>
1032 #include <time.h> // platform support for UTC time
1033 #include <arpa/inet.h> // for inet_aton
1035 #include <netinet/in.h> // For IP_RECVTTL
1037 #define IP_RECVTTL 24 // bool; receive reception TTL w/dgram
1040 #include <netinet/in_systm.h> // For n_long, required by <netinet/ip.h> below
1041 #include <netinet/ip.h> // For IPTOS_LOWDELAY etc.
1042 #include <netinet6/in6_var.h> // For IN6_IFF_NOTREADY etc.
1044 #ifndef NO_SECURITYFRAMEWORK
1045 #include <Security/Security.h>
1046 #endif /* NO_SECURITYFRAMEWORK */
1048 #include "dnsinfo.h"
1050 // Code contributed by Dave Heller:
1051 // Define RUN_ON_PUMA_WITHOUT_IFADDRS to compile code that will
1052 // work on Mac OS X 10.1, which does not have the getifaddrs call.
1053 #define RUN_ON_PUMA_WITHOUT_IFADDRS 0
1054 #if RUN_ON_PUMA_WITHOUT_IFADDRS
1055 #include "mDNSMacOSXPuma.c"
1057 #include <ifaddrs.h>
1060 #include <IOKit/IOKitLib.h>
1061 #include <IOKit/IOMessage.h>
1062 #include <mach/mach_time.h>
1064 typedef struct SearchListElem
1066 struct SearchListElem
*next
;
1069 DNSQuestion BrowseQ
;
1070 DNSQuestion DefBrowseQ
;
1071 DNSQuestion LegacyBrowseQ
;
1072 DNSQuestion RegisterQ
;
1073 DNSQuestion DefRegisterQ
;
1074 ARListElem
*AuthRecs
;
1078 // ***************************************************************************
1081 static mDNSu32 clockdivisor
= 0;
1083 // for domain enumeration and default browsing/registration
1084 static SearchListElem
*SearchList
= NULL
; // where we search for _browse domains
1085 static DNSQuestion LegacyBrowseDomainQ
; // our local enumeration query for _legacy._browse domains
1086 static DNameListElem
*DefBrowseList
= NULL
; // cache of answers to above query (where we search for empty string browses)
1087 static DNameListElem
*DefRegList
= NULL
; // manually generated list of domains where we register for empty string registrations
1088 static ARListElem
*SCPrefBrowseDomains
= NULL
; // manually generated local-only PTR records for browse domains we get from SCPreferences
1090 static domainname DynDNSRegDomain
; // Default wide-area zone for service registration
1091 static CFArrayRef DynDNSBrowseDomains
= NULL
; // Default wide-area zones for legacy ("empty string") browses
1092 static domainname DynDNSHostname
;
1094 static mDNSBool DomainDiscoveryDisabled
= mDNSfalse
;
1096 #define CONFIG_FILE "/etc/mDNSResponder.conf"
1097 #define DYNDNS_KEYCHAIN_SERVICE "DynDNS Shared Secret"
1098 #define SYS_KEYCHAIN_PATH "/Library/Keychains/System.keychain"
1100 // Function Prototypes
1101 mDNSlocal
void SetSCPrefsBrowseDomain(mDNS
*m
, const domainname
*d
, mDNSBool add
);
1103 // ***************************************************************************
1106 // We only attempt to send and receive multicast packets on interfaces that are
1107 // (a) flagged as multicast-capable
1108 // (b) *not* flagged as point-to-point (e.g. modem)
1109 // Typically point-to-point interfaces are modems (including mobile-phone pseudo-modems), and we don't want
1110 // to run up the user's bill sending multicast traffic over a link where there's only a single device at the
1111 // other end, and that device (e.g. a modem bank) is probably not answering Multicast DNS queries anyway.
1112 #define MulticastInterface(i) ((i->ifa_flags & IFF_MULTICAST) && !(i->ifa_flags & IFF_POINTOPOINT))
1114 // routines to allow access to default domain lists from daemon layer
1116 mDNSexport DNameListElem
*mDNSPlatformGetSearchDomainList(void)
1118 return mDNS_CopyDNameList(DefBrowseList
);
1121 mDNSexport DNameListElem
*mDNSPlatformGetRegDomainList(void)
1123 return mDNS_CopyDNameList(DefRegList
);
1126 // utility routines to manage registration domain lists
1128 mDNSlocal
void AddDefRegDomain(domainname
*d
)
1130 DNameListElem
*newelem
= NULL
, *ptr
;
1132 // make sure name not already in list
1133 for (ptr
= DefRegList
; ptr
; ptr
= ptr
->next
)
1135 if (SameDomainName(&ptr
->name
, d
))
1136 { debugf("duplicate addition of default reg domain %##s", d
->c
); return; }
1139 newelem
= mallocL("DNameListElem", sizeof(*newelem
));
1140 if (!newelem
) { LogMsg("Error - malloc"); return; }
1141 AssignDomainName(&newelem
->name
, d
);
1142 newelem
->next
= DefRegList
;
1143 DefRegList
= newelem
;
1145 DefaultRegDomainChanged(d
, mDNStrue
);
1146 udsserver_default_reg_domain_changed(d
, mDNStrue
);
1149 mDNSlocal
void RemoveDefRegDomain(domainname
*d
)
1151 DNameListElem
*ptr
= DefRegList
, *prev
= NULL
;
1155 if (SameDomainName(&ptr
->name
, d
))
1157 if (prev
) prev
->next
= ptr
->next
;
1158 else DefRegList
= ptr
->next
;
1159 freeL("DNameListElem", ptr
);
1160 DefaultRegDomainChanged(d
, mDNSfalse
);
1161 udsserver_default_reg_domain_changed(d
, mDNSfalse
);
1167 debugf("Requested removal of default registration domain %##s not in contained in list", d
->c
);
1170 #ifndef NO_CFUSERNOTIFICATION
1171 mDNSexport
void NotifyOfElusiveBug(const char *title
, const char *msg
) // Both strings are UTF-8 text
1173 static int notifyCount
= 0;
1174 if (notifyCount
) return;
1176 // If we display our alert early in the boot process, then it vanishes once the desktop appears.
1177 // To avoid this, we don't try to display alerts in the first three minutes after boot.
1178 if ((mDNSu32
)(mDNSPlatformRawTime()) < (mDNSu32
)(mDNSPlatformOneSecond
* 180)) return;
1180 // Unless ForceAlerts is defined, we only show these bug report alerts on machines that have a 17.x.x.x address
1183 // Determine if we're at Apple (17.*.*.*)
1184 extern mDNS mDNSStorage
;
1185 NetworkInterfaceInfoOSX
*i
;
1186 for (i
= mDNSStorage
.p
->InterfaceList
; i
; i
= i
->next
)
1187 if (i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
&& i
->ifinfo
.ip
.ip
.v4
.b
[0] == 17)
1189 if (!i
) return; // If not at Apple, don't show the alert
1193 LogMsg("%s", title
);
1195 // Display a notification to the user
1197 static const char footer
[] = "(Note: This message only appears on machines with 17.x.x.x IP addresses — i.e. at Apple — not on customer machines.)";
1198 CFStringRef alertHeader
= CFStringCreateWithCString(NULL
, title
, kCFStringEncodingUTF8
);
1199 CFStringRef alertBody
= CFStringCreateWithCString(NULL
, msg
, kCFStringEncodingUTF8
);
1200 CFStringRef alertFooter
= CFStringCreateWithCString(NULL
, footer
, kCFStringEncodingUTF8
);
1201 CFStringRef alertMessage
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@\r\r%@"), alertBody
, alertFooter
);
1202 CFUserNotificationDisplayNotice(0.0, kCFUserNotificationStopAlertLevel
, NULL
, NULL
, NULL
, alertHeader
, alertMessage
, NULL
);
1205 mDNSexport
void NotifyOfElusiveBug(__unused
const char *title
, __unused
const char *msg
)
1208 #endif /* NO_CFUSERNOTIFICATION */
1210 mDNSlocal
struct ifaddrs
* myGetIfAddrs(int refresh
)
1212 static struct ifaddrs
*ifa
= NULL
;
1220 if (ifa
== NULL
) getifaddrs(&ifa
);
1225 mDNSlocal NetworkInterfaceInfoOSX
*SearchForInterfaceByName(mDNS
*const m
, const char *ifname
, int type
)
1227 NetworkInterfaceInfoOSX
*i
;
1228 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1229 if (i
->Exists
&& !strcmp(i
->ifa_name
, ifname
) &&
1231 (type
== AF_INET
&& i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
) ||
1232 (type
== AF_INET6
&& i
->ifinfo
.ip
.type
== mDNSAddrType_IPv6
) )) return(i
);
1236 mDNSlocal
int myIfIndexToName(u_short index
, char* name
)
1238 struct ifaddrs
*ifa
;
1239 for (ifa
= myGetIfAddrs(0); ifa
; ifa
= ifa
->ifa_next
)
1240 if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
1241 if (((struct sockaddr_dl
*)ifa
->ifa_addr
)->sdl_index
== index
)
1242 { strncpy(name
, ifa
->ifa_name
, IF_NAMESIZE
); return 0; }
1246 mDNSexport mDNSInterfaceID
mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS
*const m
, mDNSu32 index
)
1248 NetworkInterfaceInfoOSX
*i
;
1249 if (index
== kDNSServiceInterfaceIndexLocalOnly
) return(mDNSInterface_LocalOnly
);
1250 if (index
== kDNSServiceInterfaceIndexAny
) return(mDNSNULL
);
1252 // Don't get tricked by inactive interfaces with no InterfaceID set
1253 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1254 if (i
->ifinfo
.InterfaceID
&& i
->scope_id
== index
) return(i
->ifinfo
.InterfaceID
);
1256 // Not found. Make sure our interface list is up to date, then try again.
1257 LogOperation("InterfaceID for interface index %d not found; Updating interface list", index
);
1258 mDNSMacOSXNetworkChanged(m
);
1259 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1260 if (i
->ifinfo
.InterfaceID
&& i
->scope_id
== index
) return(i
->ifinfo
.InterfaceID
);
1265 mDNSexport mDNSu32
mDNSPlatformInterfaceIndexfromInterfaceID(mDNS
*const m
, mDNSInterfaceID id
)
1267 NetworkInterfaceInfoOSX
*i
;
1268 if (id
== mDNSInterface_LocalOnly
) return(kDNSServiceInterfaceIndexLocalOnly
);
1269 if (id
== mDNSInterface_Any
) return(0);
1271 // Don't use i->ifinfo.InterfaceID here, because we DO want to find inactive interfaces, which have no InterfaceID set
1272 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1273 if ((mDNSInterfaceID
)i
== id
) return(i
->scope_id
);
1275 // Not found. Make sure our interface list is up to date, then try again.
1276 LogOperation("Interface index for InterfaceID %p not found; Updating interface list", id
);
1277 mDNSMacOSXNetworkChanged(m
);
1278 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1279 if ((mDNSInterfaceID
)i
== id
) return(i
->scope_id
);
1284 mDNSlocal mDNSBool
AddrRequiresPPPConnection(const struct sockaddr
*addr
)
1286 mDNSBool result
= mDNSfalse
;
1287 SCNetworkConnectionFlags flags
;
1288 SCNetworkReachabilityRef ReachRef
= NULL
;
1290 ReachRef
= SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault
, addr
);
1291 if (!ReachRef
) { LogMsg("ERROR: RequiresConnection - SCNetworkReachabilityCreateWithAddress"); goto end
; }
1292 if (!SCNetworkReachabilityGetFlags(ReachRef
, &flags
)) { LogMsg("ERROR: AddrRequiresPPPConnection - SCNetworkReachabilityGetFlags"); goto end
; }
1293 result
= flags
& kSCNetworkFlagsConnectionRequired
;
1296 if (ReachRef
) CFRelease(ReachRef
);
1300 // NOTE: If InterfaceID is NULL, it means, "send this packet through our anonymous unicast socket"
1301 // NOTE: If InterfaceID is non-NULL it means, "send this packet through our port 5353 socket on the specified interface"
1302 // OR send via our primary v4 unicast socket
1303 mDNSexport mStatus
mDNSPlatformSendUDP(const mDNS
*const m
, const void *const msg
, const mDNSu8
*const end
,
1304 mDNSInterfaceID InterfaceID
, const mDNSAddr
*dst
, mDNSIPPort dstPort
)
1308 // Note: For this platform we've adopted the convention that InterfaceIDs are secretly pointers
1309 // to the NetworkInterfaceInfoOSX structure that holds the active sockets. The mDNSCore code
1310 // doesn't know that and doesn't need to know that -- it just treats InterfaceIDs as opaque identifiers.
1311 NetworkInterfaceInfoOSX
*info
= (NetworkInterfaceInfoOSX
*)InterfaceID
;
1312 char *ifa_name
= info
? info
->ifa_name
: "unicast";
1313 struct sockaddr_storage to
;
1316 // Sanity check: Make sure that if we're sending a query via unicast, we're sending it using our
1317 // anonymous socket created for this purpose, so that we'll receive the response.
1318 // If we use one of the many multicast sockets bound to port 5353 then we may not receive responses reliably.
1319 if (info
&& !mDNSAddrIsDNSMulticast(dst
))
1321 const DNSMessage
*const m
= (DNSMessage
*)msg
;
1322 if ((m
->h
.flags
.b
[0] & kDNSFlag0_QR_Mask
) == kDNSFlag0_QR_Query
)
1323 LogMsg("mDNSPlatformSendUDP: ERROR: Sending query OP from mDNS port to non-mDNS destination %#a:%d", dst
, mDNSVal16(dstPort
));
1326 if (dst
->type
== mDNSAddrType_IPv4
)
1328 struct sockaddr_in
*sin_to
= (struct sockaddr_in
*)&to
;
1329 sin_to
->sin_len
= sizeof(*sin_to
);
1330 sin_to
->sin_family
= AF_INET
;
1331 sin_to
->sin_port
= dstPort
.NotAnInteger
;
1332 sin_to
->sin_addr
.s_addr
= dst
->ip
.v4
.NotAnInteger
;
1333 s
= info
? info
->ss
.sktv4
: m
->p
->unicastsockets
.sktv4
;
1335 else if (dst
->type
== mDNSAddrType_IPv6
)
1337 struct sockaddr_in6
*sin6_to
= (struct sockaddr_in6
*)&to
;
1338 sin6_to
->sin6_len
= sizeof(*sin6_to
);
1339 sin6_to
->sin6_family
= AF_INET6
;
1340 sin6_to
->sin6_port
= dstPort
.NotAnInteger
;
1341 sin6_to
->sin6_flowinfo
= 0;
1342 sin6_to
->sin6_addr
= *(struct in6_addr
*)&dst
->ip
.v6
;
1343 sin6_to
->sin6_scope_id
= info
? info
->scope_id
: 0;
1344 s
= info
? info
->ss
.sktv6
: m
->p
->unicastsockets
.sktv6
;
1348 LogMsg("mDNSPlatformSendUDP: dst is not an IPv4 or IPv6 address!");
1349 return mStatus_BadParamErr
;
1352 // Don't send if it would cause dial-on-demand connection initiation.
1353 // As an optimization, don't bother consulting reachability API / routing
1354 // table when sending Multicast DNS since we ignore PPP interfaces for mDNS traffic.
1355 if (!mDNSAddrIsDNSMulticast(dst
) && AddrRequiresPPPConnection((struct sockaddr
*)&to
))
1357 debugf("mDNSPlatformSendUDP: Surpressing sending to avoid dial-on-demand connection");
1358 return mStatus_NoError
;
1362 verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %p %5s/%ld to %#a:%d skt %d",
1363 InterfaceID
, ifa_name
, dst
->type
, dst
, mDNSVal16(dstPort
), s
);
1365 verbosedebugf("mDNSPlatformSendUDP: NOT sending on InterfaceID %p %5s/%ld (socket of this type not available)",
1366 InterfaceID
, ifa_name
, dst
->type
, dst
, mDNSVal16(dstPort
));
1368 // Note: When sending, mDNSCore may often ask us to send both a v4 multicast packet and then a v6 multicast packet
1369 // If we don't have the corresponding type of socket available, then return mStatus_Invalid
1370 if (s
< 0) return(mStatus_Invalid
);
1372 err
= sendto(s
, msg
, (UInt8
*)end
- (UInt8
*)msg
, 0, (struct sockaddr
*)&to
, to
.ss_len
);
1375 static int MessageCount
= 0;
1376 // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
1377 if (!mDNSAddressIsAllDNSLinkGroup(dst
))
1378 if (errno
== EHOSTDOWN
|| errno
== ENETDOWN
|| errno
== EHOSTUNREACH
|| errno
== ENETUNREACH
) return(mStatus_TransientErr
);
1379 // Don't report EHOSTUNREACH in the first three minutes after boot
1380 // This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
1381 // but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
1382 if (errno
== EHOSTUNREACH
&& (mDNSu32
)(mDNSPlatformRawTime()) < (mDNSu32
)(mDNSPlatformOneSecond
* 180)) return(mStatus_TransientErr
);
1383 // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change
1384 if (errno
== EADDRNOTAVAIL
&& m
->p
->NetworkChanged
) return(mStatus_TransientErr
);
1385 if (MessageCount
< 1000)
1388 LogMsg("mDNSPlatformSendUDP sendto failed to send packet on InterfaceID %p %5s/%ld to %#a:%d skt %d error %d errno %d (%s) %lu",
1389 InterfaceID
, ifa_name
, dst
->type
, dst
, mDNSVal16(dstPort
), s
, err
, errno
, strerror(errno
), (mDNSu32
)(m
->timenow
));
1391 return(mStatus_UnknownErr
);
1394 return(mStatus_NoError
);
1397 mDNSlocal ssize_t
myrecvfrom(const int s
, void *const buffer
, const size_t max
,
1398 struct sockaddr
*const from
, size_t *const fromlen
, mDNSAddr
*dstaddr
, char ifname
[IF_NAMESIZE
], mDNSu8
*ttl
)
1400 static unsigned int numLogMessages
= 0;
1401 struct iovec databuffers
= { (char *)buffer
, max
};
1404 struct cmsghdr
*cmPtr
;
1405 char ancillary
[1024];
1407 *ttl
= 255; // If kernel fails to provide TTL data (e.g. Jaguar doesn't) then assume the TTL was 255 as it should be
1409 // Set up the message
1410 msg
.msg_name
= (caddr_t
)from
;
1411 msg
.msg_namelen
= *fromlen
;
1412 msg
.msg_iov
= &databuffers
;
1414 msg
.msg_control
= (caddr_t
)&ancillary
;
1415 msg
.msg_controllen
= sizeof(ancillary
);
1419 n
= recvmsg(s
, &msg
, 0);
1422 if (errno
!= EWOULDBLOCK
&& numLogMessages
++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned error %d errno %d", s
, n
, errno
);
1425 if (msg
.msg_controllen
< (int)sizeof(struct cmsghdr
))
1427 if (numLogMessages
++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned %d msg.msg_controllen %d < sizeof(struct cmsghdr) %lu",
1428 s
, n
, msg
.msg_controllen
, sizeof(struct cmsghdr
));
1431 if (msg
.msg_flags
& MSG_CTRUNC
)
1433 if (numLogMessages
++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s
);
1437 *fromlen
= msg
.msg_namelen
;
1439 // Parse each option out of the ancillary data.
1440 for (cmPtr
= CMSG_FIRSTHDR(&msg
); cmPtr
; cmPtr
= CMSG_NXTHDR(&msg
, cmPtr
))
1442 // debugf("myrecvfrom cmsg_level %d cmsg_type %d", cmPtr->cmsg_level, cmPtr->cmsg_type);
1443 if (cmPtr
->cmsg_level
== IPPROTO_IP
&& cmPtr
->cmsg_type
== IP_RECVDSTADDR
)
1445 dstaddr
->type
= mDNSAddrType_IPv4
;
1446 dstaddr
->ip
.v4
.NotAnInteger
= *(u_int32_t
*)CMSG_DATA(cmPtr
);
1448 if (cmPtr
->cmsg_level
== IPPROTO_IP
&& cmPtr
->cmsg_type
== IP_RECVIF
)
1450 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)CMSG_DATA(cmPtr
);
1451 if (sdl
->sdl_nlen
< IF_NAMESIZE
)
1453 mDNSPlatformMemCopy(sdl
->sdl_data
, ifname
, sdl
->sdl_nlen
);
1454 ifname
[sdl
->sdl_nlen
] = 0;
1455 // debugf("IP_RECVIF sdl_index %d, sdl_data %s len %d", sdl->sdl_index, ifname, sdl->sdl_nlen);
1458 if (cmPtr
->cmsg_level
== IPPROTO_IP
&& cmPtr
->cmsg_type
== IP_RECVTTL
)
1460 *ttl
= *(u_char
*)CMSG_DATA(cmPtr
);
1462 if (cmPtr
->cmsg_level
== IPPROTO_IPV6
&& cmPtr
->cmsg_type
== IPV6_PKTINFO
)
1464 struct in6_pktinfo
*ip6_info
= (struct in6_pktinfo
*)CMSG_DATA(cmPtr
);
1465 dstaddr
->type
= mDNSAddrType_IPv6
;
1466 dstaddr
->ip
.v6
= *(mDNSv6Addr
*)&ip6_info
->ipi6_addr
;
1467 myIfIndexToName(ip6_info
->ipi6_ifindex
, ifname
);
1469 if (cmPtr
->cmsg_level
== IPPROTO_IPV6
&& cmPtr
->cmsg_type
== IPV6_HOPLIMIT
)
1471 *ttl
= *(int*)CMSG_DATA(cmPtr
);
1478 // On entry, context points to our CFSocketSet
1479 // If ss->info is NULL, we received this packet on our anonymous unicast socket
1480 // If ss->info is non-NULL, we received this packet on port 5353 on the indicated interface
1481 mDNSlocal
void myCFSocketCallBack(const CFSocketRef cfs
, const CFSocketCallBackType CallBackType
, const CFDataRef address
, const void *const data
, void *const context
)
1483 const CFSocketSet
*const ss
= (const CFSocketSet
*)context
;
1484 mDNS
*const m
= ss
->m
;
1485 const int skt
= CFSocketGetNative(cfs
);
1486 const int s1
= (cfs
== ss
->cfsv4
) ? ss
->sktv4
: (cfs
== ss
->cfsv6
) ? ss
->sktv6
: -1;
1489 (void)address
; // Parameter not used
1490 (void)data
; // Parameter not used
1492 if (CallBackType
!= kCFSocketReadCallBack
)
1493 LogMsg("myCFSocketCallBack: Why is CallBackType %d not kCFSocketReadCallBack?", CallBackType
);
1495 if (s1
< 0 || s1
!= skt
)
1497 LogMsg("myCFSocketCallBack: s1 %d native socket %d, cfs %p", s1
, skt
, cfs
);
1498 LogMsg("myCFSocketCallBack: cfsv4 %p, sktv4 %d", ss
->cfsv4
, ss
->sktv4
);
1499 LogMsg("myCFSocketCallBack: cfsv6 %p, sktv6 %d", ss
->cfsv6
, ss
->sktv6
);
1504 // NOTE: When handling multiple packets in a batch, MUST reset InterfaceID before handling each packet
1505 mDNSInterfaceID InterfaceID
= ss
->info
? ss
->info
->ifinfo
.InterfaceID
: mDNSNULL
;
1506 mDNSAddr senderAddr
, destAddr
;
1507 mDNSIPPort senderPort
, destPort
= MulticastDNSPort
;
1508 struct sockaddr_storage from
;
1509 size_t fromlen
= sizeof(from
);
1510 char packetifname
[IF_NAMESIZE
] = "";
1512 err
= myrecvfrom(s1
, &m
->imsg
, sizeof(m
->imsg
), (struct sockaddr
*)&from
, &fromlen
, &destAddr
, packetifname
, &ttl
);
1516 if (from
.ss_family
== AF_INET
)
1518 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&from
;
1519 senderAddr
.type
= mDNSAddrType_IPv4
;
1520 senderAddr
.ip
.v4
.NotAnInteger
= sin
->sin_addr
.s_addr
;
1521 senderPort
.NotAnInteger
= sin
->sin_port
;
1523 else if (from
.ss_family
== AF_INET6
)
1525 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)&from
;
1526 senderAddr
.type
= mDNSAddrType_IPv6
;
1527 senderAddr
.ip
.v6
= *(mDNSv6Addr
*)&sin6
->sin6_addr
;
1528 senderPort
.NotAnInteger
= sin6
->sin6_port
;
1529 //LogOperation("myCFSocketCallBack received IPv6 packet from %#a to %#a", &senderAddr, &destAddr);
1533 LogMsg("myCFSocketCallBack from is unknown address family %d", from
.ss_family
);
1537 if (mDNSAddrIsDNSMulticast(&destAddr
))
1539 // Even though we indicated a specific interface in the IP_ADD_MEMBERSHIP call, a weirdness of the
1540 // sockets API means that even though this socket has only officially joined the multicast group
1541 // on one specific interface, the kernel will still deliver multicast packets to it no matter which
1542 // interface they arrive on. According to the official Unix Powers That Be, this is Not A Bug.
1543 // To work around this weirdness, we use the IP_RECVIF option to find the name of the interface
1544 // on which the packet arrived, and ignore the packet if it really arrived on some other interface.
1545 if (!ss
->info
|| !ss
->info
->Exists
)
1547 verbosedebugf("myCFSocketCallBack got multicast packet from %#a to %#a on unicast socket (Ignored)", &senderAddr
, &destAddr
);
1550 else if (strcmp(ss
->info
->ifa_name
, packetifname
))
1552 verbosedebugf("myCFSocketCallBack got multicast packet from %#a to %#a on interface %#a/%s (Ignored -- really arrived on interface %s)",
1553 &senderAddr
, &destAddr
, &ss
->info
->ifinfo
.ip
, ss
->info
->ifa_name
, packetifname
);
1557 verbosedebugf("myCFSocketCallBack got multicast packet from %#a to %#a on interface %#a/%s",
1558 &senderAddr
, &destAddr
, &ss
->info
->ifinfo
.ip
, ss
->info
->ifa_name
);
1562 // Note: Unicast packets are delivered to *one* of our listening sockets,
1563 // not necessarily the one bound to the physical interface where the packet arrived.
1564 // To sort this out we search our interface list and update InterfaceID to reference
1565 // the mDNSCore interface object for the interface where the packet was actually received.
1566 NetworkInterfaceInfo
*intf
= m
->HostInterfaces
;
1567 while (intf
&& strcmp(intf
->ifname
, packetifname
)) intf
= intf
->next
;
1568 if (intf
) InterfaceID
= intf
->InterfaceID
;
1571 mDNSCoreReceive(m
, &m
->imsg
, (unsigned char*)&m
->imsg
+ err
, &senderAddr
, senderPort
, &destAddr
, destPort
, InterfaceID
);
1574 if (err
< 0 && (errno
!= EWOULDBLOCK
|| count
== 0))
1576 // Something is busted here.
1577 // CFSocket says there is a packet, but myrecvfrom says there is not.
1578 // Try calling select() to get another opinion.
1579 // Find out about other socket parameter that can help understand why select() says the socket is ready for read
1580 // All of this is racy, as data may have arrived after the call to select()
1581 int save_errno
= errno
;
1585 socklen_t solen
= sizeof(int);
1588 FD_SET(s1
, &readfds
);
1589 struct timeval timeout
;
1591 timeout
.tv_usec
= 0;
1592 int selectresult
= select(s1
+1, &readfds
, NULL
, NULL
, &timeout
);
1593 if (getsockopt(s1
, SOL_SOCKET
, SO_ERROR
, &so_error
, &solen
) == -1)
1594 LogMsg("myCFSocketCallBack getsockopt(SO_ERROR) error %d", errno
);
1595 if (getsockopt(s1
, SOL_SOCKET
, SO_NREAD
, &so_nread
, &solen
) == -1)
1596 LogMsg("myCFSocketCallBack getsockopt(SO_NREAD) error %d", errno
);
1597 if (ioctl(s1
, FIONREAD
, &fionread
) == -1)
1598 LogMsg("myCFSocketCallBack ioctl(FIONREAD) error %d", errno
);
1599 static unsigned int numLogMessages
= 0;
1600 if (numLogMessages
++ < 100)
1601 LogMsg("myCFSocketCallBack recvfrom skt %d error %d errno %d (%s) select %d (%spackets waiting) so_error %d so_nread %d fionread %d count %d",
1602 s1
, err
, save_errno
, strerror(save_errno
), selectresult
, FD_ISSET(s1
, &readfds
) ? "" : "*NO* ", so_error
, so_nread
, fionread
, count
);
1603 if (numLogMessages
> 5)
1604 NotifyOfElusiveBug("Flaw in Kernel (select/recvfrom mismatch)",
1605 "Congratulations, you've reproduced an elusive bug.\r"
1606 "Please contact the current assignee of <rdar://problem/3375328>.\r"
1607 "Alternatively, you can send email to radar-3387020@group.apple.com. (Note number is different.)\r"
1608 "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
1610 sleep(1); // After logging this error, rate limit so we don't flood syslog
1614 // TCP socket support for unicast DNS and Dynamic DNS Update
1618 TCPConnectionCallback callback
;
1623 mDNSlocal
void tcpCFSocketCallback(CFSocketRef cfs
, CFSocketCallBackType CallbackType
, CFDataRef address
,
1624 const void *data
, void *context
)
1626 #pragma unused(CallbackType, address, data)
1627 mDNSBool connect
= mDNSfalse
;
1629 tcpInfo_t
*info
= context
;
1630 if (!info
->connected
)
1633 info
->connected
= mDNStrue
; // prevent connected flag from being set in future callbacks
1635 info
->callback(CFSocketGetNative(cfs
), info
->context
, connect
);
1636 // NOTE: the callback may call CloseConnection here, which frees the context structure!
1639 mDNSexport mStatus
mDNSPlatformTCPConnect(const mDNSAddr
*dst
, mDNSOpaque16 dstport
, mDNSInterfaceID InterfaceID
,
1640 TCPConnectionCallback callback
, void *context
, int *descriptor
)
1642 int sd
, on
= 1; // "on" for setsockopt
1643 struct sockaddr_in saddr
;
1644 CFSocketContext cfContext
= { 0, NULL
, 0, 0, 0 };
1647 CFRunLoopSourceRef rls
;
1649 (void)InterfaceID
; //!!!KRS use this if non-zero!!!
1652 if (dst
->type
!= mDNSAddrType_IPv4
)
1654 LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: opperation not supported");
1655 return mStatus_UnknownErr
;
1658 bzero(&saddr
, sizeof(saddr
));
1659 saddr
.sin_family
= AF_INET
;
1660 saddr
.sin_port
= dstport
.NotAnInteger
;
1661 saddr
.sin_len
= sizeof(saddr
);
1662 memcpy(&saddr
.sin_addr
, &dst
->ip
.v4
.NotAnInteger
, sizeof(saddr
.sin_addr
));
1664 // Don't send if it would cause dial-on-demand connection initiation.
1665 if (AddrRequiresPPPConnection((struct sockaddr
*)&saddr
))
1667 debugf("mDNSPlatformTCPConnect: Surpressing sending to avoid dial-on-demand connection");
1668 return mStatus_UnknownErr
;
1671 sd
= socket(AF_INET
, SOCK_STREAM
, 0);
1672 if (sd
< 3) { LogMsg("mDNSPlatformTCPConnect: socket error %d errno %d (%s)", sd
, errno
, strerror(errno
)); return mStatus_UnknownErr
; }
1675 if (fcntl(sd
, F_SETFL
, O_NONBLOCK
) < 0)
1677 LogMsg("ERROR: setsockopt O_NONBLOCK - %s", strerror(errno
));
1678 return mStatus_UnknownErr
;
1681 // receive interface identifiers
1682 if (setsockopt(sd
, IPPROTO_IP
, IP_RECVIF
, &on
, sizeof(on
)) < 0)
1684 LogMsg("setsockopt IP_RECVIF - %s", strerror(errno
));
1685 return mStatus_UnknownErr
;
1687 // set up CF wrapper, add to Run Loop
1688 info
= mallocL("mDNSPlatformTCPConnect", sizeof(tcpInfo_t
));
1689 info
->callback
= callback
;
1690 info
->context
= context
;
1691 cfContext
.info
= info
;
1692 sr
= CFSocketCreateWithNative(kCFAllocatorDefault
, sd
, kCFSocketReadCallBack
| kCFSocketConnectCallBack
,
1693 tcpCFSocketCallback
, &cfContext
);
1696 LogMsg("ERROR: mDNSPlatformTCPConnect - CFSocketRefCreateWithNative failed");
1697 freeL("mDNSPlatformTCPConnect", info
);
1698 return mStatus_UnknownErr
;
1701 rls
= CFSocketCreateRunLoopSource(kCFAllocatorDefault
, sr
, 0);
1704 LogMsg("ERROR: mDNSPlatformTCPConnect - CFSocketCreateRunLoopSource failed");
1705 freeL("mDNSPlatformTCPConnect", info
);
1706 return mStatus_UnknownErr
;
1709 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1712 // initiate connection wth peer
1713 if (connect(sd
, (struct sockaddr
*)&saddr
, sizeof(saddr
)) < 0)
1715 if (errno
== EINPROGRESS
)
1717 info
->connected
= 0;
1719 return mStatus_ConnPending
;
1721 LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: %s", strerror(errno
));
1722 freeL("mDNSPlatformTCPConnect", info
);
1723 CFSocketInvalidate(sr
); // Note: Also closes the underlying socket
1724 return mStatus_ConnFailed
;
1726 info
->connected
= 1;
1728 return mStatus_ConnEstablished
;
1731 mDNSexport
void mDNSPlatformTCPCloseConnection(int sd
)
1733 CFSocketContext cfContext
;
1737 if (sd
< 3) LogMsg("mDNSPlatformTCPCloseConnection: ERROR sd %d < 3", sd
);
1739 // Get the CFSocket for the descriptor
1740 sr
= CFSocketCreateWithNative(kCFAllocatorDefault
, sd
, kCFSocketNoCallBack
, NULL
, NULL
);
1741 if (!sr
) { LogMsg("ERROR: mDNSPlatformTCPCloseConnection - CFSocketCreateWithNative returned NULL"); return; }
1743 CFSocketGetContext(sr
, &cfContext
);
1744 if (!cfContext
.info
)
1746 LogMsg("ERROR: mDNSPlatformTCPCloseConnection - could not retreive tcpInfo from socket context");
1750 CFRelease(sr
); // this only releases the copy we allocated with CreateWithNative above
1752 info
= cfContext
.info
;
1754 // Note: MUST NOT close the underlying native BSD socket.
1755 // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately,
1756 // because it first has to unhook the sockets from its select() call, before it can safely close them.
1757 CFSocketInvalidate(sr
);
1759 freeL("mDNSPlatformTCPCloseConnection", info
);
1762 mDNSexport
int mDNSPlatformReadTCP(int sd
, void *buf
, int buflen
)
1764 int nread
= recv(sd
, buf
, buflen
, 0);
1767 if (errno
== EAGAIN
) return 0; // no data available (call would block)
1768 LogMsg("ERROR: mDNSPlatformReadTCP - recv: %s", strerror(errno
));
1774 mDNSexport
int mDNSPlatformWriteTCP(int sd
, const char *msg
, int len
)
1776 int nsent
= send(sd
, msg
, len
, 0);
1780 if (errno
== EAGAIN
) return 0; // blocked
1781 LogMsg("ERROR: mDNSPlatformWriteTCP - sendL %s", strerror(errno
));
1787 // This gets the text of the field currently labelled "Computer Name" in the Sharing Prefs Control Panel
1788 mDNSlocal
void GetUserSpecifiedFriendlyComputerName(domainlabel
*const namelabel
)
1790 CFStringEncoding encoding
= kCFStringEncodingUTF8
;
1791 CFStringRef cfs
= SCDynamicStoreCopyComputerName(NULL
, &encoding
);
1794 CFStringGetPascalString(cfs
, namelabel
->c
, sizeof(*namelabel
), kCFStringEncodingUTF8
);
1799 // This gets the text of the field currently labelled "Local Hostname" in the Sharing Prefs Control Panel
1800 mDNSlocal
void GetUserSpecifiedLocalHostName(domainlabel
*const namelabel
)
1802 CFStringRef cfs
= SCDynamicStoreCopyLocalHostName(NULL
);
1805 CFStringGetPascalString(cfs
, namelabel
->c
, sizeof(*namelabel
), kCFStringEncodingUTF8
);
1810 mDNSlocal mDNSBool
DDNSSettingEnabled(CFDictionaryRef dict
)
1813 CFNumberRef state
= CFDictionaryGetValue(dict
, CFSTR("Enabled"));
1814 if (!state
) return mDNSfalse
;
1815 if (!CFNumberGetValue(state
, kCFNumberSInt32Type
, &val
)) { LogMsg("ERROR: DDNSSettingEnabled - CFNumberGetValue"); return mDNSfalse
; }
1816 return val
? mDNStrue
: mDNSfalse
;
1819 mDNSlocal
void GetUserSpecifiedDDNSConfig(domainname
*const fqdn
, domainname
*const regDomain
, CFArrayRef
*const browseDomains
)
1821 char buf
[MAX_ESCAPED_DOMAIN_NAME
];
1824 regDomain
->c
[0] = 0;
1826 *browseDomains
= NULL
;
1828 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:GetUserSpecifiedDDNSConfig"), NULL
, NULL
);
1831 CFDictionaryRef dict
= SCDynamicStoreCopyValue(store
, CFSTR("Setup:/Network/DynamicDNS"));
1834 CFArrayRef fqdnArray
= CFDictionaryGetValue(dict
, CFSTR("HostNames"));
1835 if (fqdnArray
&& CFArrayGetCount(fqdnArray
) > 0)
1837 CFDictionaryRef fqdnDict
= CFArrayGetValueAtIndex(fqdnArray
, 0); // for now, we only look at the first array element. if we ever support multiple configurations, we will walk the list
1838 if (fqdnDict
&& DDNSSettingEnabled(fqdnDict
))
1840 CFStringRef name
= CFDictionaryGetValue(fqdnDict
, CFSTR("Domain"));
1843 if (!CFStringGetCString(name
, buf
, sizeof(buf
), kCFStringEncodingUTF8
) ||
1844 !MakeDomainNameFromDNSNameString(fqdn
, buf
) || !fqdn
->c
[0])
1845 LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS host name: %s", buf
[0] ? buf
: "(unknown)");
1846 else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS host name: %s", buf
);
1851 CFArrayRef regArray
= CFDictionaryGetValue(dict
, CFSTR("RegistrationDomains"));
1852 if (regArray
&& CFArrayGetCount(regArray
) > 0)
1854 CFDictionaryRef regDict
= CFArrayGetValueAtIndex(regArray
, 0);
1855 if (regDict
&& DDNSSettingEnabled(regDict
))
1857 CFStringRef name
= CFDictionaryGetValue(regDict
, CFSTR("Domain"));
1860 if (!CFStringGetCString(name
, buf
, sizeof(buf
), kCFStringEncodingUTF8
) ||
1861 !MakeDomainNameFromDNSNameString(regDomain
, buf
) || !regDomain
->c
[0])
1862 LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS registration domain: %s", buf
[0] ? buf
: "(unknown)");
1863 else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS registration zone: %s", buf
);
1867 CFArrayRef browseArray
= CFDictionaryGetValue(dict
, CFSTR("BrowseDomains"));
1868 if (browseArray
&& CFArrayGetCount(browseArray
) > 0)
1870 CFRetain(browseArray
);
1871 *browseDomains
= browseArray
;
1879 mDNSlocal
void SetDDNSNameStatus(domainname
*const dname
, mStatus status
)
1881 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:SetDDNSNameStatus"), NULL
, NULL
);
1884 char uname
[MAX_ESCAPED_DOMAIN_NAME
];
1885 ConvertDomainNameToCString(dname
, uname
);
1891 if (!(*(p
+1)) && *p
== '.') *p
= 0; // if last character, strip trailing dot
1895 // We need to make a CFDictionary called "State:/Network/DynamicDNS" containing (at present) a single entity.
1896 // That single entity is a CFDictionary with name "HostNames".
1897 // The "HostNames" CFDictionary contains a set of name/value pairs, where the each name is the FQDN
1898 // in question, and the corresponding value is a CFDictionary giving the state for that FQDN.
1899 // (At present we only support a single FQDN, so this dictionary holds just a single name/value pair.)
1900 // The CFDictionary for each FQDN holds (at present) a single name/value pair,
1901 // where the name is "Status" and the value is a CFNumber giving an errror code (with zero meaning success).
1903 const CFStringRef StateKeys
[1] = { CFSTR("HostNames") };
1904 const CFStringRef HostKeys
[1] = { CFStringCreateWithCString(NULL
, uname
, kCFStringEncodingUTF8
) };
1905 const CFStringRef StatusKeys
[1] = { CFSTR("Status") };
1906 if (!HostKeys
[0]) LogMsg("SetDDNSNameStatus: CFStringCreateWithCString(%s) failed", uname
);
1909 const CFNumberRef StatusVals
[1] = { CFNumberCreate(NULL
, kCFNumberSInt32Type
, &status
) };
1910 if (!StatusVals
[0]) LogMsg("SetDDNSNameStatus: CFNumberCreate(%ld) failed", status
);
1913 const CFDictionaryRef HostVals
[1] = { CFDictionaryCreate(NULL
, (void*)StatusKeys
, (void*)StatusVals
, 1, NULL
, NULL
) };
1916 const CFDictionaryRef StateVals
[1] = { CFDictionaryCreate(NULL
, (void*)HostKeys
, (void*)HostVals
, 1, NULL
, NULL
) };
1919 CFDictionaryRef StateDict
= CFDictionaryCreate(NULL
, (void*)StateKeys
, (void*)StateVals
, 1, NULL
, NULL
);
1922 SCDynamicStoreSetValue(store
, CFSTR("State:/Network/DynamicDNS"), StateDict
);
1923 CFRelease(StateDict
);
1925 CFRelease(StateVals
[0]);
1927 CFRelease(HostVals
[0]);
1929 CFRelease(StatusVals
[0]);
1931 CFRelease(HostKeys
[0]);
1937 // If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
1938 // If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
1939 mDNSlocal mStatus
SetupSocket(mDNS
*const m
, CFSocketSet
*cp
, mDNSBool mcast
, const mDNSAddr
*ifaddr
, u_short sa_family
)
1941 int *s
= (sa_family
== AF_INET
) ? &cp
->sktv4
: &cp
->sktv6
;
1942 CFSocketRef
*c
= (sa_family
== AF_INET
) ? &cp
->cfsv4
: &cp
->cfsv6
;
1943 CFRunLoopSourceRef
*r
= (sa_family
== AF_INET
) ? &cp
->rlsv4
: &cp
->rlsv6
;
1945 const int twofivefive
= 255;
1946 mStatus err
= mStatus_NoError
;
1947 char *errstr
= mDNSNULL
;
1949 mDNSIPPort port
= (mcast
| m
->CanReceiveUnicastOn5353
) ? MulticastDNSPort
: zeroIPPort
;
1951 if (*s
>= 0) { LogMsg("SetupSocket ERROR: socket %d is already set", *s
); return(-1); }
1952 if (*c
) { LogMsg("SetupSocket ERROR: CFSocketRef %p is already set", *c
); return(-1); }
1954 // Open the socket...
1955 int skt
= socket(sa_family
, SOCK_DGRAM
, IPPROTO_UDP
);
1956 if (skt
< 3) { LogMsg("SetupSocket: socket error %d errno %d (%s)", skt
, errno
, strerror(errno
)); return(skt
); }
1958 // ... with a shared UDP port, if it's for multicast receiving
1959 if (port
.NotAnInteger
) err
= setsockopt(skt
, SOL_SOCKET
, SO_REUSEPORT
, &on
, sizeof(on
));
1960 if (err
< 0) { errstr
= "setsockopt - SO_REUSEPORT"; goto fail
; }
1962 if (sa_family
== AF_INET
)
1964 // We want to receive destination addresses
1965 err
= setsockopt(skt
, IPPROTO_IP
, IP_RECVDSTADDR
, &on
, sizeof(on
));
1966 if (err
< 0) { errstr
= "setsockopt - IP_RECVDSTADDR"; goto fail
; }
1968 // We want to receive interface identifiers
1969 err
= setsockopt(skt
, IPPROTO_IP
, IP_RECVIF
, &on
, sizeof(on
));
1970 if (err
< 0) { errstr
= "setsockopt - IP_RECVIF"; goto fail
; }
1972 // We want to receive packet TTL value so we can check it
1973 err
= setsockopt(skt
, IPPROTO_IP
, IP_RECVTTL
, &on
, sizeof(on
));
1974 // We ignore errors here -- we already know Jaguar doesn't support this, but we can get by without it
1976 // Add multicast group membership on this interface, if it's for multicast receiving
1979 struct in_addr addr
= { ifaddr
->ip
.v4
.NotAnInteger
};
1981 imr
.imr_multiaddr
.s_addr
= AllDNSLinkGroupv4
.NotAnInteger
;
1982 imr
.imr_interface
= addr
;
1983 err
= setsockopt(skt
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
, &imr
, sizeof(imr
));
1984 if (err
< 0) { errstr
= "setsockopt - IP_ADD_MEMBERSHIP"; goto fail
; }
1986 // Specify outgoing interface too
1987 err
= setsockopt(skt
, IPPROTO_IP
, IP_MULTICAST_IF
, &addr
, sizeof(addr
));
1988 if (err
< 0) { errstr
= "setsockopt - IP_MULTICAST_IF"; goto fail
; }
1991 // Send unicast packets with TTL 255
1992 err
= setsockopt(skt
, IPPROTO_IP
, IP_TTL
, &twofivefive
, sizeof(twofivefive
));
1993 if (err
< 0) { errstr
= "setsockopt - IP_TTL"; goto fail
; }
1995 // And multicast packets with TTL 255 too
1996 err
= setsockopt(skt
, IPPROTO_IP
, IP_MULTICAST_TTL
, &twofivefive
, sizeof(twofivefive
));
1997 if (err
< 0) { errstr
= "setsockopt - IP_MULTICAST_TTL"; goto fail
; }
1999 // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
2000 const int ip_tosbits
= IPTOS_LOWDELAY
| IPTOS_THROUGHPUT
;
2001 err
= setsockopt(skt
, IPPROTO_IP
, IP_TOS
, &ip_tosbits
, sizeof(ip_tosbits
));
2002 if (err
< 0) { errstr
= "setsockopt - IP_TOS"; goto fail
; }
2004 // And start listening for packets
2005 struct sockaddr_in listening_sockaddr
;
2006 listening_sockaddr
.sin_family
= AF_INET
;
2007 listening_sockaddr
.sin_port
= port
.NotAnInteger
;
2008 listening_sockaddr
.sin_addr
.s_addr
= 0; // Want to receive multicasts AND unicasts on this socket
2009 err
= bind(skt
, (struct sockaddr
*) &listening_sockaddr
, sizeof(listening_sockaddr
));
2010 if (err
) { errstr
= "bind"; goto fail
; }
2012 else if (sa_family
== AF_INET6
)
2014 // We want to receive destination addresses and receive interface identifiers
2015 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_PKTINFO
, &on
, sizeof(on
));
2016 if (err
< 0) { errstr
= "setsockopt - IPV6_PKTINFO"; goto fail
; }
2018 // We want to receive packet hop count value so we can check it
2019 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_HOPLIMIT
, &on
, sizeof(on
));
2020 if (err
< 0) { errstr
= "setsockopt - IPV6_HOPLIMIT"; goto fail
; }
2022 // We want to receive only IPv6 packets. Without this option we get IPv4 packets too,
2023 // with mapped addresses of the form 0:0:0:0:0:FFFF:xxxx:xxxx, where xxxx:xxxx is the IPv4 address
2024 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_V6ONLY
, &on
, sizeof(on
));
2025 if (err
< 0) { errstr
= "setsockopt - IPV6_V6ONLY"; goto fail
; }
2029 // Add multicast group membership on this interface, if it's for multicast receiving
2030 int interface_id
= if_nametoindex(cp
->info
->ifa_name
);
2031 struct ipv6_mreq i6mr
;
2032 //LogOperation("SetupSocket: v6 %#a %s %d", ifaddr, cp->info->ifa_name, interface_id);
2033 i6mr
.ipv6mr_interface
= interface_id
;
2034 i6mr
.ipv6mr_multiaddr
= *(struct in6_addr
*)&AllDNSLinkGroupv6
;
2035 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, &i6mr
, sizeof(i6mr
));
2036 if (err
< 0) { errstr
= "setsockopt - IPV6_JOIN_GROUP"; goto fail
; }
2038 // Specify outgoing interface too
2039 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
, &interface_id
, sizeof(interface_id
));
2040 if (err
< 0) { errstr
= "setsockopt - IPV6_MULTICAST_IF"; goto fail
; }
2043 // Send unicast packets with TTL 255
2044 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, &twofivefive
, sizeof(twofivefive
));
2045 if (err
< 0) { errstr
= "setsockopt - IPV6_UNICAST_HOPS"; goto fail
; }
2047 // And multicast packets with TTL 255 too
2048 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_MULTICAST_HOPS
, &twofivefive
, sizeof(twofivefive
));
2049 if (err
< 0) { errstr
= "setsockopt - IPV6_MULTICAST_HOPS"; goto fail
; }
2051 // Note: IPV6_TCLASS appears not to be implemented on OS X right now (or indeed on ANY version of Unix?)
2053 // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
2054 int tclass
= IPTOS_LOWDELAY
| IPTOS_THROUGHPUT
; // This may not be right (since tclass is not implemented on OS X, I can't test it)
2055 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_TCLASS
, &tclass
, sizeof(tclass
));
2056 if (err
< 0) { errstr
= "setsockopt - IPV6_TCLASS"; goto fail
; }
2059 // Want to receive our own packets
2060 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_MULTICAST_LOOP
, &on
, sizeof(on
));
2061 if (err
< 0) { errstr
= "setsockopt - IPV6_MULTICAST_LOOP"; goto fail
; }
2063 // And start listening for packets
2064 struct sockaddr_in6 listening_sockaddr6
;
2065 bzero(&listening_sockaddr6
, sizeof(listening_sockaddr6
));
2066 listening_sockaddr6
.sin6_len
= sizeof(listening_sockaddr6
);
2067 listening_sockaddr6
.sin6_family
= AF_INET6
;
2068 listening_sockaddr6
.sin6_port
= port
.NotAnInteger
;
2069 listening_sockaddr6
.sin6_flowinfo
= 0;
2070 listening_sockaddr6
.sin6_addr
= in6addr_any
; // Want to receive multicasts AND unicasts on this socket
2071 listening_sockaddr6
.sin6_scope_id
= 0;
2072 err
= bind(skt
, (struct sockaddr
*) &listening_sockaddr6
, sizeof(listening_sockaddr6
));
2073 if (err
) { errstr
= "bind"; goto fail
; }
2076 fcntl(skt
, F_SETFL
, fcntl(skt
, F_GETFL
, 0) | O_NONBLOCK
); // set non-blocking
2078 CFSocketContext myCFSocketContext
= { 0, cp
, NULL
, NULL
, NULL
};
2079 *c
= CFSocketCreateWithNative(kCFAllocatorDefault
, *s
, kCFSocketReadCallBack
, myCFSocketCallBack
, &myCFSocketContext
);
2080 *r
= CFSocketCreateRunLoopSource(kCFAllocatorDefault
, *c
, 0);
2081 CFRunLoopAddSource(CFRunLoopGetCurrent(), *r
, kCFRunLoopDefaultMode
);
2086 LogMsg("%s error %ld errno %d (%s)", errstr
, err
, errno
, strerror(errno
));
2087 if (!strcmp(errstr
, "bind") && errno
== EADDRINUSE
)
2088 NotifyOfElusiveBug("Setsockopt SO_REUSEPORT failed",
2089 "Congratulations, you've reproduced an elusive bug.\r"
2090 "Please contact the current assignee of <rdar://problem/3814904>.\r"
2091 "Alternatively, you can send email to radar-3387020@group.apple.com. (Note number is different.)\r"
2092 "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
2097 mDNSlocal mStatus
SetupAddr(mDNSAddr
*ip
, const struct sockaddr
*const sa
)
2099 if (!sa
) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid
); }
2101 if (sa
->sa_family
== AF_INET
)
2103 struct sockaddr_in
*ifa_addr
= (struct sockaddr_in
*)sa
;
2104 ip
->type
= mDNSAddrType_IPv4
;
2105 ip
->ip
.v4
.NotAnInteger
= ifa_addr
->sin_addr
.s_addr
;
2106 return(mStatus_NoError
);
2109 if (sa
->sa_family
== AF_INET6
)
2111 struct sockaddr_in6
*ifa_addr
= (struct sockaddr_in6
*)sa
;
2112 // Inside the BSD kernel they use a hack where they stuff the sin6->sin6_scope_id
2113 // value into the second word of the IPv6 link-local address, so they can just
2114 // pass around IPv6 address structures instead of full sockaddr_in6 structures.
2115 // Those hacked IPv6 addresses aren't supposed to escape the kernel in that form, but they do.
2116 // To work around this we always whack the second word of any IPv6 link-local address back to zero.
2117 if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr
->sin6_addr
)) ifa_addr
->sin6_addr
.__u6_addr
.__u6_addr16
[1] = 0;
2118 ip
->type
= mDNSAddrType_IPv6
;
2119 ip
->ip
.v6
= *(mDNSv6Addr
*)&ifa_addr
->sin6_addr
;
2120 return(mStatus_NoError
);
2123 LogMsg("SetupAddr invalid sa_family %d", sa
->sa_family
);
2124 return(mStatus_Invalid
);
2127 mDNSlocal mDNSEthAddr
GetBSSID(char *ifa_name
)
2129 mDNSEthAddr eth
= zeroEthAddr
;
2130 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:GetBSSID"), NULL
, NULL
);
2133 CFStringRef entityname
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("State:/Network/Interface/%s/AirPort"), ifa_name
);
2136 CFDictionaryRef dict
= SCDynamicStoreCopyValue(store
, entityname
);
2139 CFRange range
= { 0, 6 }; // Offset, length
2140 CFDataRef data
= CFDictionaryGetValue(dict
, CFSTR("BSSID"));
2141 if (data
&& CFDataGetLength(data
) == 6) CFDataGetBytes(data
, range
, eth
.b
);
2144 CFRelease(entityname
);
2151 // Returns pointer to newly created NetworkInterfaceInfoOSX object, or
2152 // pointer to already-existing NetworkInterfaceInfoOSX object found in list, or
2153 // may return NULL if out of memory (unlikely) or parameters are invalid for some reason
2154 // (e.g. sa_family not AF_INET or AF_INET6)
2155 mDNSlocal NetworkInterfaceInfoOSX
*AddInterfaceToList(mDNS
*const m
, struct ifaddrs
*ifa
, mDNSs32 utc
)
2157 mDNSu32 scope_id
= if_nametoindex(ifa
->ifa_name
);
2158 mDNSEthAddr bssid
= GetBSSID(ifa
->ifa_name
);
2161 if (SetupAddr(&ip
, ifa
->ifa_addr
) != mStatus_NoError
) return(NULL
);
2162 if (SetupAddr(&mask
, ifa
->ifa_netmask
) != mStatus_NoError
) return(NULL
);
2164 NetworkInterfaceInfoOSX
**p
;
2165 for (p
= &m
->p
->InterfaceList
; *p
; p
= &(*p
)->next
)
2166 if (scope_id
== (*p
)->scope_id
&& mDNSSameAddress(&ip
, &(*p
)->ifinfo
.ip
) && mDNSSameEthAddress(&bssid
, &(*p
)->BSSID
))
2168 debugf("AddInterfaceToList: Found existing interface %lu %.6a with address %#a at %p", scope_id
, &bssid
, &ip
, *p
);
2169 (*p
)->Exists
= mDNStrue
;
2170 // If interface was not in getifaddrs list last time we looked, but it is now, update 'AppearanceTime' for this record
2171 if ((*p
)->LastSeen
!= utc
) (*p
)->AppearanceTime
= utc
;
2175 NetworkInterfaceInfoOSX
*i
= (NetworkInterfaceInfoOSX
*)mallocL("NetworkInterfaceInfoOSX", sizeof(*i
));
2176 debugf("AddInterfaceToList: Making new interface %lu %.6a with address %#a at %p", scope_id
, &bssid
, &ip
, i
);
2177 if (!i
) return(mDNSNULL
);
2178 bzero(i
, sizeof(NetworkInterfaceInfoOSX
));
2179 i
->ifa_name
= (char *)mallocL("NetworkInterfaceInfoOSX name", strlen(ifa
->ifa_name
) + 1);
2180 if (!i
->ifa_name
) { freeL("NetworkInterfaceInfoOSX", i
); return(mDNSNULL
); }
2181 strcpy(i
->ifa_name
, ifa
->ifa_name
);
2183 i
->ifinfo
.InterfaceID
= mDNSNULL
;
2185 i
->ifinfo
.mask
= mask
;
2186 strncpy(i
->ifinfo
.ifname
, ifa
->ifa_name
, sizeof(i
->ifinfo
.ifname
));
2187 i
->ifinfo
.ifname
[sizeof(i
->ifinfo
.ifname
)-1] = 0;
2188 i
->ifinfo
.Advertise
= m
->AdvertiseLocalAddresses
;
2189 i
->ifinfo
.McastTxRx
= mDNSfalse
; // For now; will be set up later at the end of UpdateInterfaceList
2192 i
->Exists
= mDNStrue
;
2193 i
->AppearanceTime
= utc
; // Brand new interface; AppearanceTime is now
2195 i
->Flashing
= mDNSfalse
;
2196 i
->Occulting
= mDNSfalse
;
2197 i
->scope_id
= scope_id
;
2199 i
->sa_family
= ifa
->ifa_addr
->sa_family
;
2200 i
->ifa_flags
= ifa
->ifa_flags
;
2204 i
->ss
.sktv4
= i
->ss
.sktv6
= -1;
2205 i
->ss
.cfsv4
= i
->ss
.cfsv6
= NULL
;
2206 i
->ss
.rlsv4
= i
->ss
.rlsv6
= NULL
;
2212 mDNSlocal NetworkInterfaceInfoOSX
*FindRoutableIPv4(mDNS
*const m
, mDNSu32 scope_id
)
2214 NetworkInterfaceInfoOSX
*i
;
2215 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2216 if (i
->Exists
&& i
->scope_id
== scope_id
&& i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
)
2217 if (!(i
->ifinfo
.ip
.ip
.v4
.b
[0] == 169 && i
->ifinfo
.ip
.ip
.v4
.b
[1] == 254))
2222 mDNSlocal mStatus
UpdateInterfaceList(mDNS
*const m
, mDNSs32 utc
)
2224 mDNSBool foundav4
= mDNSfalse
;
2225 mDNSBool foundav6
= mDNSfalse
;
2226 struct ifaddrs
*ifa
= myGetIfAddrs(1);
2227 struct ifaddrs
*v4Loopback
= NULL
;
2228 struct ifaddrs
*v6Loopback
= NULL
;
2229 mDNSEthAddr PrimaryMAC
= zeroEthAddr
;
2230 char defaultname
[32];
2232 int InfoSocket
= socket(AF_INET6
, SOCK_DGRAM
, 0);
2233 if (InfoSocket
< 3) LogMsg("UpdateInterfaceList: InfoSocket error %d errno %d (%s)", InfoSocket
, errno
, strerror(errno
));
2235 if (m
->SleepState
) ifa
= NULL
;
2239 #if LIST_ALL_INTERFACES
2240 if (ifa
->ifa_addr
->sa_family
== AF_APPLETALK
)
2241 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_APPLETALK",
2242 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2243 else if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
2244 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_LINK",
2245 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2246 else if (ifa
->ifa_addr
->sa_family
!= AF_INET
&& ifa
->ifa_addr
->sa_family
!= AF_INET6
)
2247 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)",
2248 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2249 if (!(ifa
->ifa_flags
& IFF_UP
))
2250 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_UP",
2251 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2252 if (!(ifa
->ifa_flags
& IFF_MULTICAST
))
2253 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_MULTICAST",
2254 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2255 if (ifa
->ifa_flags
& IFF_POINTOPOINT
)
2256 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_POINTOPOINT",
2257 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2258 if (ifa
->ifa_flags
& IFF_LOOPBACK
)
2259 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_LOOPBACK",
2260 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2263 if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
2265 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
2266 if (sdl
->sdl_type
== IFT_ETHER
&& sdl
->sdl_alen
== sizeof(PrimaryMAC
) && mDNSSameEthAddress(&PrimaryMAC
, &zeroEthAddr
))
2267 mDNSPlatformMemCopy(sdl
->sdl_data
+ sdl
->sdl_nlen
, PrimaryMAC
.b
, 6);
2270 if (ifa
->ifa_flags
& IFF_UP
&& ifa
->ifa_addr
)
2271 if (ifa
->ifa_addr
->sa_family
== AF_INET
|| ifa
->ifa_addr
->sa_family
== AF_INET6
)
2273 if (!ifa
->ifa_netmask
)
2276 SetupAddr(&ip
, ifa
->ifa_addr
);
2277 LogMsg("getifaddrs: ifa_netmask is NULL for %5s(%d) Flags %04X Family %2d %#a",
2278 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
, &ip
);
2280 else if (ifa
->ifa_addr
->sa_family
!= ifa
->ifa_netmask
->sa_family
)
2283 SetupAddr(&ip
, ifa
->ifa_addr
);
2284 LogMsg("getifaddrs ifa_netmask for %5s(%d) Flags %04X Family %2d %#a has different family: %d",
2285 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
, &ip
, ifa
->ifa_netmask
->sa_family
);
2289 int ifru_flags6
= 0;
2291 if (ifa
->ifa_addr
->sa_family
== AF_INET6
&& InfoSocket
>= 0)
2293 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
2294 struct in6_ifreq ifr6
;
2295 bzero((char *)&ifr6
, sizeof(ifr6
));
2296 strncpy(ifr6
.ifr_name
, ifa
->ifa_name
, sizeof(ifr6
.ifr_name
));
2297 ifr6
.ifr_addr
= *sin6
;
2298 if (ioctl(InfoSocket
, SIOCGIFAFLAG_IN6
, &ifr6
) != -1)
2299 ifru_flags6
= ifr6
.ifr_ifru
.ifru_flags6
;
2300 verbosedebugf("%s %.16a %04X %04X", ifa
->ifa_name
, &sin6
->sin6_addr
, ifa
->ifa_flags
, ifru_flags6
);
2303 if (!(ifru_flags6
& (IN6_IFF_NOTREADY
| IN6_IFF_DETACHED
| IN6_IFF_DEPRECATED
| IN6_IFF_TEMPORARY
)))
2305 if (ifa
->ifa_flags
& IFF_LOOPBACK
)
2306 if (ifa
->ifa_addr
->sa_family
== AF_INET
) v4Loopback
= ifa
;
2307 else v6Loopback
= ifa
;
2310 NetworkInterfaceInfoOSX
*i
= AddInterfaceToList(m
, ifa
, utc
);
2311 if (i
&& MulticastInterface(i
))
2313 if (ifa
->ifa_addr
->sa_family
== AF_INET
) foundav4
= mDNStrue
;
2314 else foundav6
= mDNStrue
;
2320 ifa
= ifa
->ifa_next
;
2323 // For efficiency, we don't register a loopback interface when other interfaces of that family are available
2324 if (!foundav4
&& v4Loopback
) AddInterfaceToList(m
, v4Loopback
, utc
);
2325 if (!foundav6
&& v6Loopback
) AddInterfaceToList(m
, v6Loopback
, utc
);
2327 // Now the list is complete, set the McastTxRx setting for each interface.
2328 // We always send and receive using IPv4.
2329 // To reduce traffic, we send and receive using IPv6 only on interfaces that have no routable IPv4 address.
2330 // Having a routable IPv4 address assigned is a reasonable indicator of being on a large configured network,
2331 // which means there's a good chance that most or all the other devices on that network should also have v4.
2332 // By doing this we lose the ability to talk to true v6-only devices on that link, but we cut the packet rate in half.
2333 // At this time, reducing the packet rate is more important than v6-only devices on a large configured network,
2334 // so we are willing to make that sacrifice.
2335 NetworkInterfaceInfoOSX
*i
;
2336 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2339 mDNSBool txrx
= MulticastInterface(i
) && ((i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
) || !FindRoutableIPv4(m
, i
->scope_id
));
2340 if (i
->ifinfo
.McastTxRx
!= txrx
)
2342 i
->ifinfo
.McastTxRx
= txrx
;
2343 i
->Exists
= 2; // State change; need to deregister and reregister this interface
2348 if (InfoSocket
>= 0) close(InfoSocket
);
2351 mDNS_snprintf(defaultname
, sizeof(defaultname
), "Macintosh-%02X%02X%02X%02X%02X%02X",
2352 PrimaryMAC
.b
[0], PrimaryMAC
.b
[1], PrimaryMAC
.b
[2], PrimaryMAC
.b
[3], PrimaryMAC
.b
[4], PrimaryMAC
.b
[5]);
2354 // Set up the nice label
2355 domainlabel nicelabel
;
2357 GetUserSpecifiedFriendlyComputerName(&nicelabel
);
2358 if (nicelabel
.c
[0] == 0)
2360 LogMsg("Couldn't read user-specified Computer Name; using default “%s” instead", defaultname
);
2361 MakeDomainLabelFromLiteralString(&nicelabel
, defaultname
);
2364 // Set up the RFC 1034-compliant label
2365 domainlabel hostlabel
;
2367 GetUserSpecifiedLocalHostName(&hostlabel
);
2368 if (hostlabel
.c
[0] == 0)
2370 LogMsg("Couldn't read user-specified local hostname; using default “%s.local” instead", defaultname
);
2371 MakeDomainLabelFromLiteralString(&hostlabel
, defaultname
);
2374 if (SameDomainLabel(m
->p
->usernicelabel
.c
, nicelabel
.c
))
2375 debugf("Usernicelabel (%#s) unchanged since last time; not changing m->nicelabel (%#s)", m
->p
->usernicelabel
.c
, m
->nicelabel
.c
);
2378 debugf("Updating m->nicelabel to %#s", nicelabel
.c
);
2379 m
->p
->usernicelabel
= m
->nicelabel
= nicelabel
;
2382 if (SameDomainLabel(m
->p
->userhostlabel
.c
, hostlabel
.c
))
2383 debugf("Userhostlabel (%#s) unchanged since last time; not changing m->hostlabel (%#s)", m
->p
->userhostlabel
.c
, m
->hostlabel
.c
);
2386 debugf("Updating m->hostlabel to %#s", hostlabel
.c
);
2387 m
->p
->userhostlabel
= m
->hostlabel
= hostlabel
;
2391 return(mStatus_NoError
);
2394 mDNSlocal
int CountMaskBits(mDNSAddr
*mask
)
2396 int i
= 0, bits
= 0;
2397 int bytes
= mask
->type
== mDNSAddrType_IPv4
? 4 : mask
->type
== mDNSAddrType_IPv6
? 16 : 0;
2400 mDNSu8 b
= mask
->ip
.v6
.b
[i
++];
2401 while (b
& 0x80) { bits
++; b
<<= 1; }
2404 while (i
< bytes
) if (mask
->ip
.v6
.b
[i
++]) return(-1);
2408 // returns count of non-link local V4 addresses registered
2409 mDNSlocal
int SetupActiveInterfaces(mDNS
*const m
, mDNSs32 utc
)
2411 NetworkInterfaceInfoOSX
*i
;
2413 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2416 NetworkInterfaceInfo
*n
= &i
->ifinfo
;
2417 NetworkInterfaceInfoOSX
*primary
= SearchForInterfaceByName(m
, i
->ifa_name
, i
->sa_family
);
2418 if (!primary
) LogMsg("SetupActiveInterfaces ERROR! SearchForInterfaceByName didn't find %s", i
->ifa_name
);
2420 if (n
->InterfaceID
&& n
->InterfaceID
!= (mDNSInterfaceID
)primary
) // Sanity check
2422 LogMsg("SetupActiveInterfaces ERROR! n->InterfaceID %p != primary %p", n
->InterfaceID
, primary
);
2423 n
->InterfaceID
= mDNSNULL
;
2426 if (!n
->InterfaceID
)
2428 // NOTE: If n->InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
2429 // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
2430 // If n->InterfaceID is NOT set, then we haven't registered it and we should not try to deregister it
2431 n
->InterfaceID
= (mDNSInterfaceID
)primary
;
2432 // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away.
2433 // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds.
2434 // 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.
2435 i
->Occulting
= !(i
->ifa_flags
& IFF_LOOPBACK
) && (utc
- i
->LastSeen
> 0 && utc
- i
->LastSeen
< 60);
2436 mDNS_RegisterInterface(m
, n
, i
->Flashing
&& i
->Occulting
);
2437 if (i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
&& (i
->ifinfo
.ip
.ip
.v4
.b
[0] != 169 || i
->ifinfo
.ip
.ip
.v4
.b
[1] != 254)) count
++;
2438 LogOperation("SetupActiveInterfaces: Registered %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s%s",
2439 i
->ifa_name
, i
->scope_id
, &i
->BSSID
, primary
, &n
->ip
, CountMaskBits(&n
->mask
),
2440 i
->Flashing
? " (Flashing)" : "",
2441 i
->Occulting
? " (Occulting)" : "",
2442 n
->InterfaceActive
? " (Primary)" : "");
2446 debugf("SetupActiveInterfaces: No Tx/Rx on %5s(%lu) %.6a InterfaceID %p %#a", i
->ifa_name
, i
->scope_id
, &i
->BSSID
, primary
, &n
->ip
);
2449 if (i
->sa_family
== AF_INET
&& primary
->ss
.sktv4
== -1)
2451 mStatus err
= SetupSocket(m
, &primary
->ss
, mDNStrue
, &i
->ifinfo
.ip
, AF_INET
);
2452 if (err
== 0) debugf("SetupActiveInterfaces: v4 socket%2d %5s(%lu) %.6a InterfaceID %p %#a/%d", primary
->ss
.sktv4
, i
->ifa_name
, i
->scope_id
, &i
->BSSID
, n
->InterfaceID
, &n
->ip
, CountMaskBits(&n
->mask
));
2453 else LogMsg("SetupActiveInterfaces: v4 socket%2d %5s(%lu) %.6a InterfaceID %p %#a/%d FAILED", primary
->ss
.sktv4
, i
->ifa_name
, i
->scope_id
, &i
->BSSID
, n
->InterfaceID
, &n
->ip
, CountMaskBits(&n
->mask
));
2457 if (i
->sa_family
== AF_INET6
&& primary
->ss
.sktv6
== -1)
2459 mStatus err
= SetupSocket(m
, &primary
->ss
, mDNStrue
, &i
->ifinfo
.ip
, AF_INET6
);
2460 if (err
== 0) debugf("SetupActiveInterfaces: v6 socket%2d %5s(%lu) %.6a InterfaceID %p %#a/%d", primary
->ss
.sktv6
, i
->ifa_name
, i
->scope_id
, &i
->BSSID
, n
->InterfaceID
, &n
->ip
, CountMaskBits(&n
->mask
));
2461 else LogMsg("SetupActiveInterfaces: v6 socket%2d %5s(%lu) %.6a InterfaceID %p %#a/%d FAILED", primary
->ss
.sktv6
, i
->ifa_name
, i
->scope_id
, &i
->BSSID
, n
->InterfaceID
, &n
->ip
, CountMaskBits(&n
->mask
));
2469 mDNSlocal
void MarkAllInterfacesInactive(mDNS
*const m
, mDNSs32 utc
)
2471 NetworkInterfaceInfoOSX
*i
;
2472 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2474 if (i
->Exists
) i
->LastSeen
= utc
;
2475 i
->Exists
= mDNSfalse
;
2479 mDNSlocal
void CloseRunLoopSourceSocket(CFRunLoopSourceRef rls
, CFSocketRef cfs
)
2481 // Note: CFSocketInvalidate also closes the underlying socket for us
2482 // Comments show retain counts (obtained via CFGetRetainCount()) after each call. rls 3 cfs 3
2483 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
); // rls 2 cfs 3
2484 CFRelease(rls
); // rls ? cfs 3
2485 CFSocketInvalidate(cfs
); // rls ? cfs 1
2486 CFRelease(cfs
); // rls ? cfs ?
2489 mDNSlocal
void CloseSocketSet(CFSocketSet
*ss
)
2491 // Note: MUST NOT close the underlying native BSD sockets.
2492 // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately,
2493 // because it first has to unhook the sockets from its select() call, before it can safely close them.
2494 if (ss
->cfsv4
) CloseRunLoopSourceSocket(ss
->rlsv4
, ss
->cfsv4
);
2495 if (ss
->cfsv6
) CloseRunLoopSourceSocket(ss
->rlsv6
, ss
->cfsv6
);
2496 ss
->sktv4
= ss
->sktv6
= -1;
2497 ss
->cfsv4
= ss
->cfsv6
= NULL
;
2498 ss
->rlsv4
= ss
->rlsv6
= NULL
;
2501 // returns count of non-link local V4 addresses deregistered
2502 mDNSlocal
int ClearInactiveInterfaces(mDNS
*const m
, mDNSs32 utc
)
2505 // If an interface is going away, then deregister this from the mDNSCore.
2506 // We also have to deregister it if the primary interface that it's using for its InterfaceID is going away.
2507 // We have to do this because mDNSCore will use that InterfaceID when sending packets, and if the memory
2508 // it refers to has gone away we'll crash.
2509 // Don't actually close the sockets or free the memory yet: When the last representative of an interface goes away
2510 // mDNSCore may want to send goodbye packets on that interface. (Not yet implemented, but a good idea anyway.)
2511 NetworkInterfaceInfoOSX
*i
;
2513 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2515 // 1. If this interface is no longer active, or its InterfaceID is changing, deregister it
2516 NetworkInterfaceInfoOSX
*primary
= SearchForInterfaceByName(m
, i
->ifa_name
, i
->sa_family
);
2517 if (i
->ifinfo
.InterfaceID
)
2518 if (i
->Exists
== 0 || i
->Exists
== 2 || i
->ifinfo
.InterfaceID
!= (mDNSInterfaceID
)primary
)
2520 i
->Flashing
= !(i
->ifa_flags
& IFF_LOOPBACK
) && (utc
- i
->AppearanceTime
< 60);
2521 LogOperation("ClearInactiveInterfaces: Deregistering %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s%s",
2522 i
->ifa_name
, i
->scope_id
, &i
->BSSID
, i
->ifinfo
.InterfaceID
,
2523 &i
->ifinfo
.ip
, CountMaskBits(&i
->ifinfo
.mask
),
2524 i
->Flashing
? " (Flashing)" : "",
2525 i
->Occulting
? " (Occulting)" : "",
2526 i
->ifinfo
.InterfaceActive
? " (Primary)" : "");
2527 mDNS_DeregisterInterface(m
, &i
->ifinfo
, i
->Flashing
&& i
->Occulting
);
2528 if (i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
&& (i
->ifinfo
.ip
.ip
.v4
.b
[0] != 169 || i
->ifinfo
.ip
.ip
.v4
.b
[1] != 254)) count
++;
2529 i
->ifinfo
.InterfaceID
= mDNSNULL
;
2530 // NOTE: If n->InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
2531 // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
2532 // If n->InterfaceID is NOT set, then it's not registered and we should not call mDNS_DeregisterInterface() on it.
2537 // Now that everything that's going to deregister has done so, we can close sockets and free the memory
2538 NetworkInterfaceInfoOSX
**p
= &m
->p
->InterfaceList
;
2542 // 2. Close all our CFSockets. We'll recreate them later as necessary.
2543 // (We may have previously had both v4 and v6, and we may not need both any more.)
2544 CloseSocketSet(&i
->ss
);
2545 // 3. If no longer active, delete interface from list and free memory
2548 if (i
->LastSeen
== utc
) i
->LastSeen
= utc
- 1;
2549 mDNSBool
delete = (NumCacheRecordsForInterfaceID(m
, (mDNSInterfaceID
)i
) == 0) && (utc
- i
->LastSeen
>= 60);
2550 LogOperation("ClearInactiveInterfaces: %-13s %5s(%lu) %.6a InterfaceID %p %#a/%d Age %d%s", delete ? "Deleting" : "Holding",
2551 i
->ifa_name
, i
->scope_id
, &i
->BSSID
, i
->ifinfo
.InterfaceID
,
2552 &i
->ifinfo
.ip
, CountMaskBits(&i
->ifinfo
.mask
), utc
- i
->LastSeen
,
2553 i
->ifinfo
.InterfaceActive
? " (Primary)" : "");
2557 if (i
->ifa_name
) freeL("NetworkInterfaceInfoOSX name", i
->ifa_name
);
2558 freeL("NetworkInterfaceInfoOSX", i
);
2559 continue; // After deleting this object, don't want to do the "p = &i->next;" thing at the end of the loop
2567 mDNSlocal mStatus
GetDNSConfig(void **result
)
2570 static int MessageShown
= 0;
2571 if (!MessageShown
) { MessageShown
= 1; LogMsg("Note: Compiled without Apple-specific Split-DNS support"); }
2573 return mStatus_UnsupportedErr
;
2576 *result
= dns_configuration_copy();
2580 // When running on 10.3 (build 7xxx) and earlier, we don't expect dns_configuration_copy() to succeed
2581 if (mDNSMacOSXSystemBuildNumber(NULL
) < 8) return mStatus_UnsupportedErr
;
2583 // On 10.4, calls to dns_configuration_copy() early in the boot process often fail.
2584 // Apparently this is expected behaviour -- "not a bug".
2585 // Accordingly, we suppress syslog messages for the first three minutes after boot.
2586 // If we are still getting failures after three minutes, then we log them.
2587 if ((mDNSu32
)(mDNSPlatformRawTime()) < (mDNSu32
)(mDNSPlatformOneSecond
* 180)) return mStatus_NoError
;
2589 LogMsg("GetDNSConfig: Error: dns_configuration_copy returned NULL");
2590 return mStatus_UnknownErr
;
2592 return mStatus_NoError
;
2593 #endif // MDNS_NO_DNSINFO
2596 mDNSlocal mStatus
RegisterSplitDNS(mDNS
*m
, int *nAdditions
, int *nDeletions
)
2598 (void)m
; // unused on 10.3 systems
2600 *nAdditions
= *nDeletions
= 0;
2601 mStatus err
= GetDNSConfig(&v
);
2603 #if !MDNS_NO_DNSINFO
2608 dns_config_t
*config
= v
; // use void * to allow compilation on 10.3 systems
2610 p
= m
->uDNS_info
.Servers
;
2611 while (p
) { p
->del
= mDNStrue
; p
= p
->next
; } // mark all for deletion
2613 LogOperation("RegisterSplitDNS: Registering %d resolvers", config
->n_resolver
);
2614 for (i
= 0; i
< config
->n_resolver
; i
++)
2618 dns_resolver_t
*r
= config
->resolver
[i
];
2619 if (r
->port
== MulticastDNSPort
.NotAnInteger
) continue; // ignore configurations for .local
2620 if (r
->search_order
== DEFAULT_SEARCH_ORDER
|| !r
->domain
|| !*r
->domain
) d
.c
[0] = 0; // we ignore domain for "default" resolver
2621 else if (!MakeDomainNameFromDNSNameString(&d
, r
->domain
)) { LogMsg("RegisterSplitDNS: bad domain %s", r
->domain
); continue; }
2623 // check if this is the lowest-weighted server for the domain
2624 for (j
= 0; j
< config
->n_resolver
; j
++)
2626 dns_resolver_t
*p
= config
->resolver
[j
];
2627 if (p
->port
== MulticastDNSPort
.NotAnInteger
) continue;
2628 if (p
->search_order
<= r
->search_order
)
2631 if (p
->search_order
== DEFAULT_SEARCH_ORDER
|| !p
->domain
|| !*p
->domain
) tmp
.c
[0] = '\0';
2632 else if (!MakeDomainNameFromDNSNameString(&tmp
, p
->domain
)) { LogMsg("RegisterSplitDNS: bad domain %s", p
->domain
); continue; }
2633 if (SameDomainName(&d
, &tmp
))
2634 if (p
->search_order
< r
->search_order
|| j
< i
) break; // if equal weights, pick first in list, otherwise pick lower-weight (p)
2637 if (j
< config
->n_resolver
) // found a lower-weighted resolver for this domain
2638 { debugf("Rejecting DNS server in slot %d domain %##s (slot %d outranks)", i
, d
.c
, j
); continue; }
2639 // we're using this resolver - find the first IPv4 address
2640 for (n
= 0; n
< r
->n_nameserver
; n
++)
2642 if (r
->nameserver
[n
]->sa_family
== AF_INET
&& !AddrRequiresPPPConnection(r
->nameserver
[n
]))
2644 // %%% This should use mDNS_AddDNSServer() instead of duplicating functionality here
2646 if (SetupAddr(&saddr
, r
->nameserver
[n
])) { LogMsg("RegisterSplitDNS: bad IP address"); continue; }
2647 // mDNSAddr saddr = { mDNSAddrType_IPv4, { { { 192, 168, 1, 1 } } } }; // for testing
2648 debugf("Adding dns server from slot %d %d.%d.%d.%d for domain %##s", i
, saddr
.ip
.v4
.b
[0], saddr
.ip
.v4
.b
[1], saddr
.ip
.v4
.b
[2], saddr
.ip
.v4
.b
[3], d
.c
);
2649 p
= m
->uDNS_info
.Servers
;
2652 if (mDNSSameAddress(&p
->addr
, &saddr
) && SameDomainName(&p
->domain
, &d
)) { p
->del
= mDNSfalse
; break; }
2657 p
= mallocL("DNSServer", sizeof(*p
));
2658 if (!p
) { LogMsg("Error: malloc"); mDNS_Unlock(m
); return mStatus_UnknownErr
; }
2661 p
->teststate
= DNSServer_Untested
;
2662 AssignDomainName(&p
->domain
, &d
);
2663 p
->next
= m
->uDNS_info
.Servers
;
2664 m
->uDNS_info
.Servers
= p
;
2667 break; // !!!KRS if we ever support round-robin servers, don't break here
2672 // remove all servers marked for deletion
2673 DNSServer
**s
= &m
->uDNS_info
.Servers
;
2680 freeL("DNSServer", p
);
2683 else s
= &(*s
)->next
;
2686 dns_configuration_free(config
);
2693 mDNSlocal mStatus
RegisterNameServers(mDNS
*const m
, CFDictionaryRef dict
)
2698 mDNSAddr saddr
= { mDNSAddrType_IPv4
, { { { 0 } } } };
2701 mDNS_DeleteDNSServers(m
); // deregister orig list
2702 values
= CFDictionaryGetValue(dict
, kSCPropNetDNSServerAddresses
);
2703 if (!values
) return mStatus_NoError
;
2705 count
= CFArrayGetCount(values
);
2706 for (i
= 0; i
< count
; i
++)
2708 s
= CFArrayGetValueAtIndex(values
, i
);
2709 if (!s
) { LogMsg("ERROR: RegisterNameServers - CFArrayGetValueAtIndex"); break; }
2710 if (!CFStringGetCString(s
, buf
, 256, kCFStringEncodingUTF8
))
2712 LogMsg("ERROR: RegisterNameServers - CFStringGetCString");
2715 if (!inet_aton(buf
, (struct in_addr
*)saddr
.ip
.v4
.b
))
2717 LogMsg("ERROR: RegisterNameServers - invalid address string %s", buf
);
2720 LogOperation("RegisterNameServers: Adding %#a", &saddr
);
2721 mDNS_AddDNSServer(m
, &saddr
, NULL
);
2723 return mStatus_NoError
;
2726 mDNSlocal
void FreeARElemCallback(mDNS
*const m
, AuthRecord
*const rr
, mStatus result
)
2729 ARListElem
*elem
= rr
->RecordContext
;
2730 if (result
== mStatus_MemFree
) freeL("FreeARElemCallback", elem
);
2733 mDNSlocal
void FoundDomain(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
2735 SearchListElem
*slElem
= question
->QuestionContext
;
2736 ARListElem
*arElem
, *ptr
, *prev
;
2743 arElem
= mallocL("FoundDomain - arElem", sizeof(ARListElem
));
2744 if (!arElem
) { LogMsg("ERROR: malloc"); return; }
2745 mDNS_SetupResourceRecord(&arElem
->ar
, mDNSNULL
, mDNSInterface_LocalOnly
, kDNSType_PTR
, 7200, kDNSRecordTypeShared
, FreeARElemCallback
, arElem
);
2746 if (question
== &slElem
->BrowseQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeBrowse
];
2747 else if (question
== &slElem
->DefBrowseQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeBrowseDefault
];
2748 else if (question
== &slElem
->LegacyBrowseQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeBrowseLegacy
];
2749 else if (question
== &slElem
->RegisterQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeRegistration
];
2750 else if (question
== &slElem
->DefRegisterQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeRegistrationDefault
];
2751 else { LogMsg("FoundDomain - unknown question"); return; }
2753 MakeDomainNameFromDNSNameString(arElem
->ar
.resrec
.name
, name
);
2754 AppendDNSNameString (arElem
->ar
.resrec
.name
, "local");
2755 AssignDomainName(&arElem
->ar
.resrec
.rdata
->u
.name
, &answer
->rdata
->u
.name
);
2756 err
= mDNS_Register(m
, &arElem
->ar
);
2759 LogMsg("ERROR: FoundDomain - mDNS_Register returned %d", err
);
2760 freeL("FoundDomain - arElem", arElem
);
2763 arElem
->next
= slElem
->AuthRecs
;
2764 slElem
->AuthRecs
= arElem
;
2768 ptr
= slElem
->AuthRecs
;
2772 if (SameDomainName(&ptr
->ar
.resrec
.rdata
->u
.name
, &answer
->rdata
->u
.name
))
2774 debugf("Deregistering PTR %##s -> %##s", ptr
->ar
.resrec
.name
->c
, ptr
->ar
.resrec
.rdata
->u
.name
.c
);
2776 if (prev
) prev
->next
= ptr
->next
;
2777 else slElem
->AuthRecs
= ptr
->next
;
2779 err
= mDNS_Deregister(m
, dereg
);
2780 if (err
) LogMsg("ERROR: FoundDomain - mDNS_Deregister returned %d", err
);
2791 mDNSlocal
void MarkSearchListElem(const char *d
)
2793 SearchListElem
*new, *ptr
;
2796 if (!MakeDomainNameFromDNSNameString(&domain
, d
))
2797 { LogMsg("ERROR: MarkSearchListElem - bad domain %##s", d
); return; }
2799 if (SameDomainName(&domain
, &localdomain
) || SameDomainName(&domain
, &LocalReverseMapDomain
))
2800 { debugf("MarkSearchListElem - ignoring local domain %##s", domain
.c
); return; }
2802 // if domain is in list, mark as pre-existent (0)
2803 for (ptr
= SearchList
; ptr
; ptr
= ptr
->next
)
2804 if (SameDomainName(&ptr
->domain
, &domain
))
2806 if (ptr
->flag
!= 1) ptr
->flag
= 0; // gracefully handle duplicates - if it is already marked as add, don't bump down to preexistent
2810 // if domain not in list, add to list, mark as add (1)
2813 new = mallocL("MarkSearchListElem - SearchListElem", sizeof(SearchListElem
));
2814 if (!new) { LogMsg("ERROR: MarkSearchListElem - malloc"); return; }
2815 bzero(new, sizeof(SearchListElem
));
2816 AssignDomainName(&new->domain
, &domain
);
2817 new->flag
= 1; // add
2818 new->next
= SearchList
;
2823 // Get the search domains via OS X resolver routines. Returns mStatus_UnsupporterErr if compiled or run on 10.3 systems
2824 mDNSlocal mStatus
GetSearchDomains(void)
2827 mStatus err
= GetDNSConfig(&v
);
2829 #if !MDNS_NO_DNSINFO
2833 dns_config_t
*config
= v
;
2834 if (!config
->n_resolver
) return err
;
2835 dns_resolver_t
*resolv
= config
->resolver
[0]; // use the first slot for search domains
2837 for (i
= 0; i
< resolv
->n_search
; i
++) MarkSearchListElem(resolv
->search
[i
]);
2838 if (resolv
->domain
) MarkSearchListElem(resolv
->domain
);
2839 dns_configuration_free(config
);
2846 // Get search domains from dynamic store - used as a fallback mechanism on 10.3 systems, if GetSearchDomains (above) fails.
2847 mDNSlocal
void GetDSSearchDomains(CFDictionaryRef dict
)
2849 char buf
[MAX_ESCAPED_DOMAIN_NAME
];
2854 // get all the domains from "Search Domains" field of sharing prefs
2857 CFArrayRef searchdomains
= CFDictionaryGetValue(dict
, kSCPropNetDNSSearchDomains
);
2860 count
= CFArrayGetCount(searchdomains
);
2861 for (i
= 0; i
< count
; i
++)
2863 s
= CFArrayGetValueAtIndex(searchdomains
, i
);
2864 if (!s
) { LogMsg("ERROR: GetDSSearchDomains - CFArrayGetValueAtIndex"); break; }
2865 if (!CFStringGetCString(s
, buf
, MAX_ESCAPED_DOMAIN_NAME
, kCFStringEncodingUTF8
))
2867 LogMsg("ERROR: GetDSSearchDomains - CFStringGetCString");
2870 MarkSearchListElem(buf
);
2874 // get DHCP domain field
2875 CFStringRef dname
= CFDictionaryGetValue(dict
, kSCPropNetDNSDomainName
);
2878 if (CFStringGetCString(dname
, buf
, MAX_ESCAPED_DOMAIN_NAME
, kCFStringEncodingUTF8
))
2879 MarkSearchListElem(buf
);
2880 else LogMsg("ERROR: GetDSSearchDomains - CFStringGetCString");
2885 mDNSlocal mStatus
RegisterSearchDomains(mDNS
*const m
, CFDictionaryRef dict
)
2887 struct ifaddrs
*ifa
= NULL
;
2888 SearchListElem
*ptr
, *prev
, *freeSLPtr
;
2892 if (DomainDiscoveryDisabled
) return mStatus_NoError
;
2894 // step 1: mark each elem for removal (-1), unless we aren't passed a dictionary in which case we mark as preexistent
2895 for (ptr
= SearchList
; ptr
; ptr
= ptr
->next
) ptr
->flag
= dict
? -1 : 0;
2897 // Get search domains from resolver library (available in OS X 10.4 and later), reverting to dynamic store on 10.3 systems
2898 if (GetSearchDomains() == mStatus_UnsupportedErr
) GetDSSearchDomains(dict
);
2900 // Construct reverse-map search domains
2901 ifa
= myGetIfAddrs(1);
2905 if (ifa
->ifa_addr
->sa_family
== AF_INET
&& !SetupAddr(&addr
, ifa
->ifa_addr
) && !IsPrivateV4Addr(&addr
) && !(ifa
->ifa_flags
& IFF_LOOPBACK
) && ifa
->ifa_netmask
)
2909 if (!SetupAddr(&netmask
, ifa
->ifa_netmask
))
2911 sprintf(buffer
, "%d.%d.%d.%d.in-addr.arpa.", addr
.ip
.v4
.b
[3] & netmask
.ip
.v4
.b
[3],
2912 addr
.ip
.v4
.b
[2] & netmask
.ip
.v4
.b
[2],
2913 addr
.ip
.v4
.b
[1] & netmask
.ip
.v4
.b
[1],
2914 addr
.ip
.v4
.b
[0] & netmask
.ip
.v4
.b
[0]);
2915 MarkSearchListElem(buffer
);
2918 ifa
= ifa
->ifa_next
;
2921 // delete elems marked for removal, do queries for elems marked add
2926 if (ptr
->flag
== -1) // remove
2928 mDNS_StopQuery(m
, &ptr
->BrowseQ
);
2929 mDNS_StopQuery(m
, &ptr
->RegisterQ
);
2930 mDNS_StopQuery(m
, &ptr
->DefBrowseQ
);
2931 mDNS_StopQuery(m
, &ptr
->DefRegisterQ
);
2932 mDNS_StopQuery(m
, &ptr
->LegacyBrowseQ
);
2934 // deregister records generated from answers to the query
2935 arList
= ptr
->AuthRecs
;
2936 ptr
->AuthRecs
= NULL
;
2939 AuthRecord
*dereg
= &arList
->ar
;
2940 arList
= arList
->next
;
2941 debugf("Deregistering PTR %##s -> %##s", dereg
->resrec
.name
->c
, dereg
->resrec
.rdata
->u
.name
.c
);
2942 err
= mDNS_Deregister(m
, dereg
);
2943 if (err
) LogMsg("ERROR: RegisterSearchDomains mDNS_Deregister returned %d", err
);
2946 // remove elem from list, delete
2947 if (prev
) prev
->next
= ptr
->next
;
2948 else SearchList
= ptr
->next
;
2951 freeL("RegisterSearchDomains - freeSLPtr", freeSLPtr
);
2955 if (ptr
->flag
== 1) // add
2957 mStatus err1
, err2
, err3
, err4
, err5
;
2958 err1
= mDNS_GetDomains(m
, &ptr
->BrowseQ
, mDNS_DomainTypeBrowse
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2959 err2
= mDNS_GetDomains(m
, &ptr
->DefBrowseQ
, mDNS_DomainTypeBrowseDefault
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2960 err3
= mDNS_GetDomains(m
, &ptr
->RegisterQ
, mDNS_DomainTypeRegistration
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2961 err4
= mDNS_GetDomains(m
, &ptr
->DefRegisterQ
, mDNS_DomainTypeRegistrationDefault
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2962 err5
= mDNS_GetDomains(m
, &ptr
->LegacyBrowseQ
, mDNS_DomainTypeBrowseLegacy
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2963 if (err1
|| err2
|| err3
|| err4
|| err5
)
2964 LogMsg("GetDomains for domain %##s returned error(s):\n"
2965 "%d (mDNS_DomainTypeBrowse)\n"
2966 "%d (mDNS_DomainTypeBrowseDefault)\n"
2967 "%d (mDNS_DomainTypeRegistration)\n"
2968 "%d (mDNS_DomainTypeRegistrationDefault)"
2969 "%d (mDNS_DomainTypeBrowseLegacy)\n",
2970 ptr
->domain
.c
, err1
, err2
, err3
, err4
, err5
);
2974 if (ptr
->flag
) { LogMsg("RegisterSearchDomains - unknown flag %d. Skipping.", ptr
->flag
); }
2980 return mStatus_NoError
;
2983 //!!!KRS here is where we will give success/failure notification to the UI
2984 mDNSlocal
void SCPrefsDynDNSCallback(mDNS
*const m
, AuthRecord
*const rr
, mStatus result
)
2987 debugf("SCPrefsDynDNSCallback: result %d for registration of name %##s", result
, rr
->resrec
.name
->c
);
2988 SetDDNSNameStatus(rr
->resrec
.name
, result
);
2991 mDNSlocal
void SetSecretForDomain(mDNS
*m
, const domainname
*domain
)
2993 #ifndef NO_SECURITYFRAMEWORK
2995 char dstring
[MAX_ESCAPED_DOMAIN_NAME
];
2997 void *secret
= NULL
;
2998 domainname
*d
, canon
;
3000 mDNSu32 type
= 'ddns';
3001 mDNSu32 typelen
= sizeof(type
);
3002 char *failedfn
= "(none)";
3003 SecKeychainAttributeList
*attrList
= NULL
;
3004 SecKeychainItemRef itemRef
= NULL
;
3006 err
= SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem
);
3007 if (err
) { failedfn
= "SecKeychainSetPreferenceDomain"; goto cleanup
; }
3009 // canonicalize name by converting to lower case (keychain and some name servers are case sensitive)
3010 ConvertDomainNameToCString(domain
, dstring
);
3011 dlen
= strlen(dstring
);
3012 for (i
= 0; i
< dlen
; i
++) dstring
[i
] = tolower(dstring
[i
]); // canonicalize -> lower case
3013 MakeDomainNameFromDNSNameString(&canon
, dstring
);
3016 // find longest-match key, excluding last label (e.g. excluding ".com")
3017 while (d
->c
[0] && *(d
->c
+ d
->c
[0] + 1))
3019 if (!ConvertDomainNameToCString(d
, dstring
)) { LogMsg("SetSecretForDomain: bad domain %##s", d
->c
); return; }
3020 dlen
= strlen(dstring
);
3021 if (dstring
[dlen
-1] == '.') { dstring
[dlen
-1] = '\0'; dlen
--; } // chop trailing dot
3022 SecKeychainAttribute attrs
[] = { { kSecServiceItemAttr
, strlen(dstring
), dstring
},
3023 { kSecTypeItemAttr
, typelen
, (UInt32
*)&type
} };
3024 SecKeychainAttributeList attributes
= { sizeof(attrs
) / sizeof(attrs
[0]), attrs
};
3025 SecKeychainSearchRef searchRef
;
3027 err
= SecKeychainSearchCreateFromAttributes(NULL
, kSecGenericPasswordItemClass
, &attributes
, &searchRef
);
3028 if (err
) { failedfn
= "SecKeychainSearchCreateFromAttributes"; goto cleanup
; }
3030 err
= SecKeychainSearchCopyNext(searchRef
, &itemRef
);
3034 SecKeychainAttributeInfo attrInfo
;
3036 char keybuf
[MAX_ESCAPED_DOMAIN_NAME
+1];
3039 tags
[0] = kSecAccountItemAttr
;
3041 attrInfo
.tag
= tags
;
3042 attrInfo
.format
= NULL
;
3044 err
= SecKeychainItemCopyAttributesAndData(itemRef
, &attrInfo
, NULL
, &attrList
, &secretlen
, &secret
);
3045 if (err
|| !attrList
) { failedfn
= "SecKeychainItemCopyAttributesAndData"; goto cleanup
; }
3046 if (!secretlen
|| !secret
) { LogMsg("SetSecretForDomain - bad shared secret"); return; }
3047 if (((char *)secret
)[secretlen
-1]) { LogMsg("SetSecretForDomain - Shared secret not NULL-terminated"); goto cleanup
; }
3049 for (i
= 0; i
< attrList
->count
; i
++)
3051 SecKeychainAttribute attr
= attrList
->attr
[i
];
3052 if (attr
.tag
== kSecAccountItemAttr
)
3054 if (!attr
.length
|| attr
.length
> MAX_ESCAPED_DOMAIN_NAME
) { LogMsg("SetSecretForDomain - Bad key length %d", attr
.length
); goto cleanup
; }
3055 strncpy(keybuf
, attr
.data
, attr
.length
);
3056 if (!MakeDomainNameFromDNSNameString(&keyname
, keybuf
)) { LogMsg("SetSecretForDomain - bad key %s", keybuf
); goto cleanup
; }
3057 debugf("Setting shared secret for zone %s with key %##s", dstring
, keyname
.c
);
3058 mDNS_SetSecretForZone(m
, d
, &keyname
, secret
);
3062 if (i
== attrList
->count
) LogMsg("SetSecretForDomain - no key name set");
3065 else if (err
== errSecItemNotFound
) d
= (domainname
*)(d
->c
+ d
->c
[0] + 1);
3066 else { failedfn
= "SecKeychainSearchCopyNext"; goto cleanup
; }
3070 if (err
&& err
!= errSecItemNotFound
) LogMsg("Error: SetSecretForDomain - %s failed with error code %d", failedfn
, err
);
3071 if (attrList
) SecKeychainItemFreeAttributesAndData(attrList
, secret
);
3072 if (itemRef
) CFRelease(itemRef
);
3074 (void)m
; (void)domain
;
3075 LogMsg("Error: SetSecretForDomain - no keychain support");
3076 #endif /* NO_SECURITYFRAMEWORK */
3079 mDNSlocal
void SetSCPrefsBrowseDomainsFromCFArray(mDNS
*m
, CFArrayRef browseDomains
, mDNSBool add
)
3083 CFIndex count
= CFArrayGetCount(browseDomains
);
3084 CFDictionaryRef browseDict
;
3085 char buf
[MAX_ESCAPED_DOMAIN_NAME
];
3088 for (i
= 0; i
< count
; i
++)
3090 browseDict
= (CFDictionaryRef
)CFArrayGetValueAtIndex(browseDomains
, i
);
3091 if (browseDict
&& DDNSSettingEnabled(browseDict
))
3093 CFStringRef name
= CFDictionaryGetValue(browseDict
, CFSTR("Domain"));
3096 domainname BrowseDomain
;
3097 if (!CFStringGetCString(name
, buf
, sizeof(buf
), kCFStringEncodingUTF8
) || !MakeDomainNameFromDNSNameString(&BrowseDomain
, buf
) || !BrowseDomain
.c
[0])
3098 LogMsg("SetSCPrefsBrowseDomainsFromCFArray SCDynamicStore bad DDNS browse domain: %s", buf
[0] ? buf
: "(unknown)");
3099 else SetSCPrefsBrowseDomain(m
, &BrowseDomain
, add
);
3107 mDNSlocal
void DynDNSConfigChanged(mDNS
*const m
)
3109 static mDNSBool LegacyNATInitialized
= mDNSfalse
;
3110 uDNS_GlobalInfo
*u
= &m
->uDNS_info
;
3111 CFDictionaryRef dict
;
3113 domainname RegDomain
, fqdn
;
3114 CFArrayRef NewBrowseDomains
= NULL
;
3115 int nAdditions
= 0, nDeletions
= 0;
3117 // get fqdn, zone from SCPrefs
3118 GetUserSpecifiedDDNSConfig(&fqdn
, &RegDomain
, &NewBrowseDomains
);
3119 ReadDDNSSettingsFromConfFile(m
, CONFIG_FILE
, fqdn
.c
[0] ? NULL
: &fqdn
, RegDomain
.c
[0] ? NULL
: &RegDomain
, &DomainDiscoveryDisabled
);
3121 if (!SameDomainName(&RegDomain
, &DynDNSRegDomain
))
3123 if (DynDNSRegDomain
.c
[0])
3125 RemoveDefRegDomain(&DynDNSRegDomain
);
3126 SetSCPrefsBrowseDomain(m
, &DynDNSRegDomain
, mDNSfalse
); // if we were automatically browsing in our registration domain, stop
3128 AssignDomainName(&DynDNSRegDomain
, &RegDomain
);
3129 if (DynDNSRegDomain
.c
[0])
3131 SetSecretForDomain(m
, &DynDNSRegDomain
);
3132 AddDefRegDomain(&DynDNSRegDomain
);
3133 SetSCPrefsBrowseDomain(m
, &DynDNSRegDomain
, mDNStrue
);
3137 // Add new browse domains to internal list
3138 if (NewBrowseDomains
) SetSCPrefsBrowseDomainsFromCFArray(m
, NewBrowseDomains
, mDNStrue
);
3140 // Remove old browse domains from internal list
3141 if (DynDNSBrowseDomains
)
3143 SetSCPrefsBrowseDomainsFromCFArray(m
, DynDNSBrowseDomains
, mDNSfalse
);
3144 CFRelease(DynDNSBrowseDomains
);
3147 // Replace the old browse domains array with the new array
3148 DynDNSBrowseDomains
= NewBrowseDomains
;
3150 if (!SameDomainName(&fqdn
, &DynDNSHostname
))
3152 if (DynDNSHostname
.c
[0]) mDNS_RemoveDynDNSHostName(m
, &DynDNSHostname
);
3153 AssignDomainName(&DynDNSHostname
, &fqdn
);
3154 if (DynDNSHostname
.c
[0])
3156 SetSecretForDomain(m
, &fqdn
); // no-op if "zone" secret, above, is to be used for hostname
3157 SetDDNSNameStatus(&DynDNSHostname
, 1); // Set status to 1 to indicate "in progress"
3158 mDNS_AddDynDNSHostName(m
, &DynDNSHostname
, SCPrefsDynDNSCallback
, NULL
);
3163 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:DynDNSConfigChanged"), NULL
, NULL
);
3166 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetDNS
);
3167 if (!key
) { LogMsg("ERROR: DNSConfigChanged - SCDynamicStoreKeyCreateNetworkGlobalEntity"); CFRelease(store
); return; }
3168 dict
= SCDynamicStoreCopyValue(store
, key
);
3171 // handle any changes to search domains and DNS server addresses
3172 if (RegisterSplitDNS(m
, &nAdditions
, &nDeletions
) != mStatus_NoError
)
3173 if (dict
) RegisterNameServers(m
, dict
); // fall back to non-split DNS aware configuration on failure
3174 RegisterSearchDomains(m
, dict
); // note that we register name servers *before* search domains
3175 if (dict
) CFRelease(dict
);
3177 // get IPv4 settings
3178 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
,kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
3179 if (!key
) { LogMsg("ERROR: RouterChanged - SCDynamicStoreKeyCreateNetworkGlobalEntity"); CFRelease(store
); return; }
3180 dict
= SCDynamicStoreCopyValue(store
, key
);
3183 if (!dict
) // lost v4
3185 mDNS_SetPrimaryInterfaceInfo(m
, NULL
, NULL
, NULL
);
3186 if (DynDNSHostname
.c
[0]) SetDDNSNameStatus(&DynDNSHostname
, 1); // Set status to 1 to indicate temporary failure
3190 // handle router changes
3193 r
.type
= mDNSAddrType_IPv4
;
3194 r
.ip
.v4
.NotAnInteger
= 0;
3195 CFStringRef router
= CFDictionaryGetValue(dict
, kSCPropNetIPv4Router
);
3198 struct sockaddr_in saddr
;
3200 if (!CFStringGetCString(router
, buf
, 256, kCFStringEncodingUTF8
))
3201 LogMsg("Could not convert router to CString");
3204 saddr
.sin_len
= sizeof(saddr
);
3205 saddr
.sin_family
= AF_INET
;
3207 inet_aton(buf
, &saddr
.sin_addr
);
3208 if (AddrRequiresPPPConnection((struct sockaddr
*)&saddr
)) { debugf("Ignoring router %s (requires PPP connection)", buf
); }
3209 else *(in_addr_t
*)&r
.ip
.v4
= saddr
.sin_addr
.s_addr
;
3213 // handle primary interface changes
3214 // if we gained or lost DNS servers (e.g. logged into VPN) "toggle" primary address so it gets re-registered even if it is unchanged
3215 if (nAdditions
|| nDeletions
) mDNS_SetPrimaryInterfaceInfo(m
, NULL
, NULL
, NULL
);
3216 CFStringRef primary
= CFDictionaryGetValue(dict
, kSCDynamicStorePropNetPrimaryInterface
);
3219 mDNSAddr v4
= zeroAddr
, v6
= zeroAddr
;
3220 mDNSBool HavePrimaryGlobalv6
= mDNSfalse
; // does the primary interface have a global v6 address?
3221 struct ifaddrs
*ifa
= myGetIfAddrs(1);
3223 if (!CFStringGetCString(primary
, buf
, 256, kCFStringEncodingUTF8
))
3224 { LogMsg("Could not convert router to CString"); goto error
; }
3226 // find primary interface in list
3227 while (ifa
&& (!v4
.ip
.v4
.NotAnInteger
|| !HavePrimaryGlobalv6
))
3229 mDNSAddr tmp6
= zeroAddr
;
3230 if (!strcmp(buf
, ifa
->ifa_name
))
3232 if (ifa
->ifa_addr
->sa_family
== AF_INET
) SetupAddr(&v4
, ifa
->ifa_addr
);
3233 else if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
3235 SetupAddr(&tmp6
, ifa
->ifa_addr
);
3236 if (tmp6
.ip
.v6
.b
[0] >> 5 == 1) // global prefix: 001
3237 { HavePrimaryGlobalv6
= mDNStrue
; v6
= tmp6
; }
3242 // We'll take a V6 address from the non-primary interface if the primary interface doesn't have a global V6 address
3243 if (!HavePrimaryGlobalv6
&& ifa
->ifa_addr
->sa_family
== AF_INET6
&& !v6
.ip
.v6
.b
[0])
3245 SetupAddr(&tmp6
, ifa
->ifa_addr
);
3246 if (tmp6
.ip
.v6
.b
[0] >> 5 == 1) v6
= tmp6
;
3249 ifa
= ifa
->ifa_next
;
3252 // Note that while we advertise v6, we still require v4 (possibly NAT'd, but not link-local) because we must use
3253 // V4 to communicate w/ our DNS server
3255 if (v4
.ip
.v4
.b
[0] == 169 && v4
.ip
.v4
.b
[1] == 254) mDNS_SetPrimaryInterfaceInfo(m
, NULL
, NULL
, NULL
); // primary IP is link-local
3258 if (v4
.ip
.v4
.NotAnInteger
!= u
->AdvertisedV4
.ip
.v4
.NotAnInteger
||
3259 memcmp(v6
.ip
.v6
.b
, u
->AdvertisedV6
.ip
.v6
.b
, 16) ||
3260 r
.ip
.v4
.NotAnInteger
!= u
->Router
.ip
.v4
.NotAnInteger
)
3262 if (LegacyNATInitialized
) { LegacyNATDestroy(); LegacyNATInitialized
= mDNSfalse
; }
3263 if (r
.ip
.v4
.NotAnInteger
&& IsPrivateV4Addr(&v4
))
3265 mStatus err
= LegacyNATInit();
3266 if (err
) LogMsg("ERROR: LegacyNATInit");
3267 else LegacyNATInitialized
= mDNStrue
;
3269 mDNS_SetPrimaryInterfaceInfo(m
, &v4
, v6
.ip
.v6
.b
[0] ? &v6
: NULL
, r
.ip
.v4
.NotAnInteger
? &r
: NULL
);
3277 mDNSexport
void mDNSMacOSXNetworkChanged(mDNS
*const m
)
3279 LogOperation("*** Network Configuration Change ***");
3280 m
->p
->NetworkChanged
= 0; // If we received a network change event and deferred processing, we're now dealing with it
3281 mDNSs32 utc
= mDNSPlatformUTC();
3282 MarkAllInterfacesInactive(m
, utc
);
3283 UpdateInterfaceList(m
, utc
);
3284 int nDeletions
= ClearInactiveInterfaces(m
, utc
);
3285 int nAdditions
= SetupActiveInterfaces(m
, utc
);
3286 DynDNSConfigChanged(m
); // note - call DynDNSConfigChanged *before* mDNS_UpdateLLQs
3287 if (nDeletions
|| nAdditions
) mDNS_UpdateLLQs(m
); // so that LLQs are restarted against the up to date name servers
3289 if (m
->MainCallback
)
3290 m
->MainCallback(m
, mStatus_ConfigChanged
);
3293 mDNSlocal
void NetworkChanged(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
3295 (void)store
; // Parameter not used
3296 (void)changedKeys
; // Parameter not used
3297 mDNS
*const m
= (mDNS
*const)context
;
3300 mDNSs32 delay
= mDNSPlatformOneSecond
* 2; // Start off assuming a two-second delay
3302 int c
= CFArrayGetCount(changedKeys
); // Count changes
3303 CFRange range
= { 0, c
};
3304 CFStringRef k1
= SCDynamicStoreKeyCreateComputerName(NULL
);
3305 CFStringRef k2
= SCDynamicStoreKeyCreateHostNames(NULL
);
3308 int c1
= (CFArrayContainsValue(changedKeys
, range
, k1
) != 0); // See if ComputerName changed
3309 int c2
= (CFArrayContainsValue(changedKeys
, range
, k2
) != 0); // See if Local Hostname changed
3310 int c3
= (CFArrayContainsValue(changedKeys
, range
, CFSTR("Setup:/Network/DynamicDNS")) != 0);
3311 if (c
&& c
- c1
- c2
- c3
== 0) delay
= mDNSPlatformOneSecond
/10; // If these were the only changes, shorten delay
3313 if (k1
) CFRelease(k1
);
3314 if (k2
) CFRelease(k2
);
3316 LogOperation("*** NetworkChanged *** %d change%s, delay %d", c
, c
>1?"s":"", delay
);
3318 if (!m
->p
->NetworkChanged
||
3319 m
->p
->NetworkChanged
- NonZeroTime(m
->timenow
+ delay
) < 0)
3320 m
->p
->NetworkChanged
= NonZeroTime(m
->timenow
+ delay
);
3322 if (!m
->SuppressSending
||
3323 m
->SuppressSending
- m
->p
->NetworkChanged
< 0)
3324 m
->SuppressSending
= m
->p
->NetworkChanged
;
3328 mDNSlocal mStatus
WatchForNetworkChanges(mDNS
*const m
)
3331 SCDynamicStoreContext context
= { 0, m
, NULL
, NULL
, NULL
};
3332 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:WatchForNetworkChanges"), NetworkChanged
, &context
);
3333 CFStringRef key1
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
3334 CFStringRef key2
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv6
);
3335 CFStringRef key3
= SCDynamicStoreKeyCreateComputerName(NULL
);
3336 CFStringRef key4
= SCDynamicStoreKeyCreateHostNames(NULL
);
3337 CFStringRef key5
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetDNS
);
3338 CFStringRef pattern1
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv4
);
3339 CFStringRef pattern2
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv6
);
3341 CFMutableArrayRef keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3342 CFMutableArrayRef patterns
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3344 if (!store
) { LogMsg("SCDynamicStoreCreate failed: %s", SCErrorString(SCError())); goto error
; }
3345 if (!key1
|| !key2
|| !key3
|| !key4
|| !keys
|| !pattern1
|| !pattern2
|| !patterns
) goto error
;
3347 CFArrayAppendValue(keys
, key1
);
3348 CFArrayAppendValue(keys
, key2
);
3349 CFArrayAppendValue(keys
, key3
);
3350 CFArrayAppendValue(keys
, key4
);
3351 CFArrayAppendValue(keys
, key5
);
3352 CFArrayAppendValue(keys
, CFSTR("Setup:/Network/DynamicDNS"));
3353 CFArrayAppendValue(patterns
, pattern1
);
3354 CFArrayAppendValue(patterns
, pattern2
);
3355 CFArrayAppendValue(patterns
, CFSTR("State:/Network/Interface/[^/]+/AirPort"));
3356 if (!SCDynamicStoreSetNotificationKeys(store
, keys
, patterns
))
3357 { LogMsg("SCDynamicStoreSetNotificationKeys failed: %s", SCErrorString(SCError())); goto error
; }
3359 m
->p
->StoreRLS
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, 0);
3360 if (!m
->p
->StoreRLS
) { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error
; }
3362 CFRunLoopAddSource(CFRunLoopGetCurrent(), m
->p
->StoreRLS
, kCFRunLoopDefaultMode
);
3363 m
->p
->Store
= store
;
3368 if (store
) CFRelease(store
);
3371 if (key1
) CFRelease(key1
);
3372 if (key2
) CFRelease(key2
);
3373 if (key3
) CFRelease(key3
);
3374 if (key4
) CFRelease(key4
);
3375 if (key5
) CFRelease(key5
);
3376 if (pattern1
) CFRelease(pattern1
);
3377 if (pattern2
) CFRelease(pattern2
);
3378 if (keys
) CFRelease(keys
);
3379 if (patterns
) CFRelease(patterns
);
3385 mDNSlocal
void PowerChanged(void *refcon
, io_service_t service
, natural_t messageType
, void *messageArgument
)
3387 mDNS
*const m
= (mDNS
*const)refcon
;
3388 (void)service
; // Parameter not used
3391 case kIOMessageCanSystemPowerOff
: debugf ("PowerChanged kIOMessageCanSystemPowerOff (no action)"); break; // E0000240
3392 case kIOMessageSystemWillPowerOff
: LogOperation("PowerChanged kIOMessageSystemWillPowerOff");
3393 mDNSCoreMachineSleep(m
, true); mDNSMacOSXNetworkChanged(m
); break; // E0000250
3394 case kIOMessageSystemWillNotPowerOff
: debugf ("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; // E0000260
3395 case kIOMessageCanSystemSleep
: debugf ("PowerChanged kIOMessageCanSystemSleep (no action)"); break; // E0000270
3396 case kIOMessageSystemWillSleep
: LogOperation("PowerChanged kIOMessageSystemWillSleep");
3397 mDNSCoreMachineSleep(m
, true); mDNSMacOSXNetworkChanged(m
); break; // E0000280
3398 case kIOMessageSystemWillNotSleep
: debugf ("PowerChanged kIOMessageSystemWillNotSleep (no action)"); break; // E0000290
3399 case kIOMessageSystemHasPoweredOn
: LogOperation("PowerChanged kIOMessageSystemHasPoweredOn");
3400 // If still sleeping (didn't get 'WillPowerOn' message for some reason?) wake now
3401 if (m
->SleepState
) mDNSCoreMachineSleep(m
, false);
3402 // Just to be safe, also make sure our interface list is fully up to date, in case we
3403 // haven't yet received the System Configuration Framework "network changed" event that
3404 // we expect to receive some time shortly after the kIOMessageSystemWillPowerOn message
3405 mDNSMacOSXNetworkChanged(m
); break; // E0000300
3406 case kIOMessageSystemWillRestart
: debugf ("PowerChanged kIOMessageSystemWillRestart (no action)"); break; // E0000310
3407 case kIOMessageSystemWillPowerOn
: LogOperation("PowerChanged kIOMessageSystemWillPowerOn");
3408 // Make sure our interface list is cleared to the empty state, then tell mDNSCore to wake
3409 mDNSMacOSXNetworkChanged(m
); mDNSCoreMachineSleep(m
, false); break; // E0000320
3410 default: LogOperation("PowerChanged unknown message %X", messageType
); break;
3412 IOAllowPowerChange(m
->p
->PowerConnection
, (long)messageArgument
);
3415 mDNSlocal mStatus
WatchForPowerChanges(mDNS
*const m
)
3417 IONotificationPortRef thePortRef
;
3418 m
->p
->PowerConnection
= IORegisterForSystemPower(m
, &thePortRef
, PowerChanged
, &m
->p
->PowerNotifier
);
3419 if (m
->p
->PowerConnection
)
3421 m
->p
->PowerRLS
= IONotificationPortGetRunLoopSource(thePortRef
);
3422 CFRunLoopAddSource(CFRunLoopGetCurrent(), m
->p
->PowerRLS
, kCFRunLoopDefaultMode
);
3423 return(mStatus_NoError
);
3427 #endif /* NO_IOPOWER */
3429 CF_EXPORT CFDictionaryRef
_CFCopySystemVersionDictionary(void);
3430 CF_EXPORT
const CFStringRef _kCFSystemVersionProductNameKey
;
3431 CF_EXPORT
const CFStringRef _kCFSystemVersionProductVersionKey
;
3432 CF_EXPORT
const CFStringRef _kCFSystemVersionBuildVersionKey
;
3434 // Major version 6 is 10.2.x (Jaguar)
3435 // Major version 7 is 10.3.x (Panther)
3436 // Major version 8 is 10.4.x (Tiger)
3437 mDNSexport
int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring
)
3439 int major
= 0, minor
= 0;
3440 char letter
= 0, prodname
[256]="<Unknown>", prodvers
[256]="<Unknown>", buildver
[256]="<Unknown>";
3441 CFDictionaryRef vers
= _CFCopySystemVersionDictionary();
3444 CFStringRef cfprodname
= CFDictionaryGetValue(vers
, _kCFSystemVersionProductNameKey
);
3445 CFStringRef cfprodvers
= CFDictionaryGetValue(vers
, _kCFSystemVersionProductVersionKey
);
3446 CFStringRef cfbuildver
= CFDictionaryGetValue(vers
, _kCFSystemVersionBuildVersionKey
);
3447 if (cfprodname
) CFStringGetCString(cfprodname
, prodname
, sizeof(prodname
), kCFStringEncodingUTF8
);
3448 if (cfprodvers
) CFStringGetCString(cfprodvers
, prodvers
, sizeof(prodvers
), kCFStringEncodingUTF8
);
3449 if (cfbuildver
) CFStringGetCString(cfbuildver
, buildver
, sizeof(buildver
), kCFStringEncodingUTF8
);
3450 sscanf(buildver
, "%d%c%d", &major
, &letter
, &minor
);
3453 if (!major
) { major
=8; LogMsg("Note: No Major Build Version number found; assuming 8"); }
3454 if (HINFO_SWstring
) mDNS_snprintf(HINFO_SWstring
, 256, "%s %s (%s), %s", prodname
, prodvers
, buildver
, mDNSResponderVersionString
);
3458 // Test to see if we're the first client running on UDP port 5353, by trying to bind to 5353 without using SO_REUSEPORT.
3459 // If we fail, someone else got here first. That's not a big problem; we can share the port for multicast responses --
3460 // we just need to be aware that we shouldn't expect to successfully receive unicast UDP responses.
3461 mDNSlocal mDNSBool
mDNSPlatformInit_CanReceiveUnicast(void)
3464 int s
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
3466 LogMsg("mDNSPlatformInit_CanReceiveUnicast: socket error %d errno %d (%s)", s
, errno
, strerror(errno
));
3469 struct sockaddr_in s5353
;
3470 s5353
.sin_family
= AF_INET
;
3471 s5353
.sin_port
= MulticastDNSPort
.NotAnInteger
;
3472 s5353
.sin_addr
.s_addr
= 0;
3473 err
= bind(s
, (struct sockaddr
*)&s5353
, sizeof(s5353
));
3477 if (err
) LogMsg("No unicast UDP responses");
3478 else debugf("Unicast UDP responses okay");
3482 // Callback for the _legacy._browse queries - add answer to list of domains to search for empty-string browses
3483 mDNSlocal
void FoundLegacyBrowseDomain(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
3485 DNameListElem
*ptr
, *prev
, *new;
3487 (void)question
; // unused
3489 LogMsg("%s browse domain %##s", AddRecord
? "Adding" : "Removing", answer
->rdata
->u
.name
.c
);
3493 new = mallocL("FoundLegacyBrowseDomain", sizeof(DNameListElem
));
3494 if (!new) { LogMsg("ERROR: malloc"); return; }
3495 AssignDomainName(&new->name
, &answer
->rdata
->u
.name
);
3496 new->next
= DefBrowseList
;
3497 DefBrowseList
= new;
3498 DefaultBrowseDomainChanged(&new->name
, mDNStrue
);
3499 udsserver_default_browse_domain_changed(&new->name
, mDNStrue
);
3504 ptr
= DefBrowseList
;
3508 if (SameDomainName(&ptr
->name
, &answer
->rdata
->u
.name
))
3510 DefaultBrowseDomainChanged(&ptr
->name
, mDNSfalse
);
3511 udsserver_default_browse_domain_changed(&ptr
->name
, mDNSfalse
);
3512 if (prev
) prev
->next
= ptr
->next
;
3513 else DefBrowseList
= ptr
->next
;
3514 freeL("FoundLegacyBrowseDomain", ptr
);
3520 LogMsg("FoundLegacyBrowseDomain: Got remove event for domain %##s not in list", answer
->rdata
->u
.name
.c
);
3524 mDNSlocal
void RegisterBrowseDomainPTR(mDNS
*m
, const domainname
*d
, int type
)
3526 // allocate/register legacy and non-legacy _browse PTR record
3527 ARListElem
*browse
= mallocL("ARListElem", sizeof(*browse
));
3528 mDNS_SetupResourceRecord(&browse
->ar
, mDNSNULL
, mDNSInterface_LocalOnly
, kDNSType_PTR
, 7200, kDNSRecordTypeShared
, FreeARElemCallback
, browse
);
3529 MakeDomainNameFromDNSNameString(browse
->ar
.resrec
.name
, mDNS_DomainTypeNames
[type
]);
3530 AppendDNSNameString (browse
->ar
.resrec
.name
, "local");
3531 AssignDomainName(&browse
->ar
.resrec
.rdata
->u
.name
, d
);
3532 mStatus err
= mDNS_Register(m
, &browse
->ar
);
3535 LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err
);
3536 freeL("ARListElem", browse
);
3540 browse
->next
= SCPrefBrowseDomains
;
3541 SCPrefBrowseDomains
= browse
;
3545 mDNSlocal
void DeregisterBrowseDomainPTR(mDNS
*m
, const domainname
*d
, int type
)
3547 ARListElem
*remove
, **ptr
= &SCPrefBrowseDomains
;
3548 domainname lhs
; // left-hand side of PTR, for comparison
3550 MakeDomainNameFromDNSNameString(&lhs
, mDNS_DomainTypeNames
[type
]);
3551 AppendDNSNameString (&lhs
, "local");
3555 if (SameDomainName(&(*ptr
)->ar
.resrec
.rdata
->u
.name
, d
) && SameDomainName((*ptr
)->ar
.resrec
.name
, &lhs
))
3558 *ptr
= (*ptr
)->next
;
3559 mDNS_Deregister(m
, &remove
->ar
);
3562 else ptr
= &(*ptr
)->next
;
3566 // Add or remove a user-specified domain to the list of empty-string browse domains
3567 // Also register a non-legacy _browse PTR record so that the domain appears in enumeration lists
3568 mDNSlocal
void SetSCPrefsBrowseDomain(mDNS
*m
, const domainname
*d
, mDNSBool add
)
3570 debugf("SetSCPrefsBrowseDomain: %s default browse domain %##s", add
? "Adding" : "Removing", d
->c
);
3574 RegisterBrowseDomainPTR(m
, d
, mDNS_DomainTypeBrowse
);
3575 RegisterBrowseDomainPTR(m
, d
, mDNS_DomainTypeBrowseLegacy
);
3579 DeregisterBrowseDomainPTR(m
, d
, mDNS_DomainTypeBrowse
);
3580 DeregisterBrowseDomainPTR(m
, d
, mDNS_DomainTypeBrowseLegacy
);
3584 // Construction of Default Browse domain list (i.e. when clients pass NULL) is as follows:
3585 // 1) query for b._dns-sd._udp.local on LocalOnly interface
3586 // (.local manually generated via explicit callback)
3587 // 2) for each search domain (from prefs pane), query for b._dns-sd._udp.<searchdomain>.
3588 // 3) for each result from (2), register LocalOnly PTR record b._dns-sd._udp.local. -> <result>
3589 // 4) result above should generate a callback from question in (1). result added to global list
3590 // 5) global list delivered to client via GetSearchDomainList()
3591 // 6) client calls to enumerate domains now go over LocalOnly interface
3592 // (!!!KRS may add outgoing interface in addition)
3594 mDNSlocal mStatus
InitDNSConfig(mDNS
*const m
)
3597 static AuthRecord LocalRegPTR
;
3599 // start query for domains to be used in default (empty string domain) browses
3600 err
= mDNS_GetDomains(m
, &LegacyBrowseDomainQ
, mDNS_DomainTypeBrowseLegacy
, NULL
, mDNSInterface_LocalOnly
, FoundLegacyBrowseDomain
, NULL
);
3602 // provide browse domain "local" automatically
3603 SetSCPrefsBrowseDomain(m
, &localdomain
, mDNStrue
);
3605 // register registration domain "local"
3606 mDNS_SetupResourceRecord(&LocalRegPTR
, mDNSNULL
, mDNSInterface_LocalOnly
, kDNSType_PTR
, 7200, kDNSRecordTypeShared
, NULL
, NULL
);
3607 MakeDomainNameFromDNSNameString(LocalRegPTR
.resrec
.name
, mDNS_DomainTypeNames
[mDNS_DomainTypeRegistration
]);
3608 AppendDNSNameString (LocalRegPTR
.resrec
.name
, "local");
3609 AssignDomainName(&LocalRegPTR
.resrec
.rdata
->u
.name
, &localdomain
);
3610 err
= mDNS_Register(m
, &LocalRegPTR
);
3611 if (err
) LogMsg("ERROR: InitDNSConfig - mDNS_Register returned error %d", err
);
3613 return mStatus_NoError
;
3616 mDNSlocal mStatus
mDNSPlatformInit_setup(mDNS
*const m
)
3618 // In 10.4, mDNSResponder is launched very early in the boot process, while other subsystems are still in the process of starting up.
3619 // 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.
3621 for (i
=0; i
<100; i
++)
3623 domainlabel testlabel
;
3625 GetUserSpecifiedLocalHostName(&testlabel
);
3626 if (testlabel
.c
[0]) break;
3632 m
->hostlabel
.c
[0] = 0;
3634 char *HINFO_HWstring
= "Macintosh";
3635 char HINFO_HWstring_buffer
[256];
3636 int get_model
[2] = { CTL_HW
, HW_MODEL
};
3637 size_t len_model
= sizeof(HINFO_HWstring_buffer
);
3638 if (sysctl(get_model
, 2, HINFO_HWstring_buffer
, &len_model
, NULL
, 0) == 0)
3639 HINFO_HWstring
= HINFO_HWstring_buffer
;
3641 char HINFO_SWstring
[256] = "";
3642 if (mDNSMacOSXSystemBuildNumber(HINFO_SWstring
) < 7) m
->KnownBugs
|= mDNS_KnownBug_PhantomInterfaces
;
3643 if (mDNSPlatformInit_CanReceiveUnicast()) m
->CanReceiveUnicastOn5353
= mDNStrue
;
3646 mDNSu32 hlen
= mDNSPlatformStrLen(HINFO_HWstring
);
3647 mDNSu32 slen
= mDNSPlatformStrLen(HINFO_SWstring
);
3648 if (hlen
+ slen
< 254)
3650 m
->HIHardware
.c
[0] = hlen
;
3651 m
->HISoftware
.c
[0] = slen
;
3652 mDNSPlatformMemCopy(HINFO_HWstring
, &m
->HIHardware
.c
[1], hlen
);
3653 mDNSPlatformMemCopy(HINFO_SWstring
, &m
->HISoftware
.c
[1], slen
);
3655 #endif /* NO_HINFO */
3657 m
->p
->unicastsockets
.m
= m
;
3658 m
->p
->unicastsockets
.info
= NULL
;
3659 m
->p
->unicastsockets
.sktv4
= m
->p
->unicastsockets
.sktv6
= -1;
3660 m
->p
->unicastsockets
.cfsv4
= m
->p
->unicastsockets
.cfsv6
= NULL
;
3661 m
->p
->unicastsockets
.rlsv4
= m
->p
->unicastsockets
.rlsv6
= NULL
;
3663 err
= SetupSocket(m
, &m
->p
->unicastsockets
, mDNSfalse
, &zeroAddr
, AF_INET
);
3665 err
= SetupSocket(m
, &m
->p
->unicastsockets
, mDNSfalse
, &zeroAddr
, AF_INET6
);
3668 struct sockaddr_in s4
;
3669 socklen_t n4
= sizeof(s4
);
3670 if (getsockname(m
->p
->unicastsockets
.sktv4
, (struct sockaddr
*)&s4
, &n4
) < 0) LogMsg("getsockname v4 error %d (%s)", errno
, strerror(errno
));
3671 else m
->UnicastPort4
.NotAnInteger
= s4
.sin_port
;
3673 struct sockaddr_in6 s6
;
3674 socklen_t n6
= sizeof(s6
);
3675 if (getsockname(m
->p
->unicastsockets
.sktv6
, (struct sockaddr
*)&s6
, &n6
) < 0) LogMsg("getsockname v6 error %d (%s)", errno
, strerror(errno
));
3676 else m
->UnicastPort6
.NotAnInteger
= s6
.sin6_port
;
3679 m
->p
->InterfaceList
= mDNSNULL
;
3680 m
->p
->userhostlabel
.c
[0] = 0;
3681 m
->p
->usernicelabel
.c
[0] = 0;
3682 m
->p
->NotifyUser
= 0;
3683 mDNSs32 utc
= mDNSPlatformUTC();
3684 UpdateInterfaceList(m
, utc
);
3685 SetupActiveInterfaces(m
, utc
);
3687 err
= WatchForNetworkChanges(m
);
3688 if (err
) return(err
);
3691 err
= WatchForPowerChanges(m
);
3692 if (err
) return err
;
3693 #endif /* NO_IOPOWER */
3695 DynDNSRegDomain
.c
[0] = '\0';
3696 DynDNSConfigChanged(m
); // Get initial DNS configuration
3702 mDNSexport mStatus
mDNSPlatformInit(mDNS
*const m
)
3704 mStatus result
= mDNSPlatformInit_setup(m
);
3706 // We don't do asynchronous initialization on OS X, so by the time we get here the setup will already
3707 // have succeeded or failed -- so if it succeeded, we should just call mDNSCoreInitComplete() immediately
3708 if (result
== mStatus_NoError
) mDNSCoreInitComplete(m
, mStatus_NoError
);
3712 mDNSexport
void mDNSPlatformClose(mDNS
*const m
)
3714 if (m
->p
->PowerConnection
)
3716 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m
->p
->PowerRLS
, kCFRunLoopDefaultMode
);
3717 CFRunLoopSourceInvalidate(m
->p
->PowerRLS
);
3718 CFRelease(m
->p
->PowerRLS
);
3720 IODeregisterForSystemPower(&m
->p
->PowerNotifier
);
3721 #endif /* NO_IOPOWER */
3722 m
->p
->PowerConnection
= 0;
3723 m
->p
->PowerNotifier
= 0;
3724 m
->p
->PowerRLS
= NULL
;
3729 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m
->p
->StoreRLS
, kCFRunLoopDefaultMode
);
3730 CFRunLoopSourceInvalidate(m
->p
->StoreRLS
);
3731 CFRelease(m
->p
->StoreRLS
);
3732 CFRelease(m
->p
->Store
);
3734 m
->p
->StoreRLS
= NULL
;
3737 mDNSs32 utc
= mDNSPlatformUTC();
3738 MarkAllInterfacesInactive(m
, utc
);
3739 ClearInactiveInterfaces(m
, utc
);
3740 CloseSocketSet(&m
->p
->unicastsockets
);
3743 mDNSexport mDNSu32
mDNSPlatformRandomSeed(void)
3745 return(mach_absolute_time());
3748 mDNSexport mDNSs32 mDNSPlatformOneSecond
= 1000;
3750 mDNSexport mStatus
mDNSPlatformTimeInit(void)
3752 // Notes: Typical values for mach_timebase_info:
3753 // tbi.numer = 1000 million
3754 // tbi.denom = 33 million
3755 // These are set such that (mach_absolute_time() * numer/denom) gives us nanoseconds;
3756 // numer / denom = nanoseconds per hardware clock tick (e.g. 30);
3757 // denom / numer = hardware clock ticks per nanosecond (e.g. 0.033)
3758 // (denom*1000000) / numer = hardware clock ticks per millisecond (e.g. 33333)
3759 // So: mach_absolute_time() / ((denom*1000000)/numer) = milliseconds
3761 // Arithmetic notes:
3762 // tbi.denom is at least 1, and not more than 2^32-1.
3763 // Therefore (tbi.denom * 1000000) is at least one million, but cannot overflow a uint64_t.
3764 // tbi.denom is at least 1, and not more than 2^32-1.
3765 // Therefore clockdivisor should end up being a number roughly in the range 10^3 - 10^9.
3766 // If clockdivisor is less than 10^3 then that means that the native clock frequency is less than 1MHz,
3767 // which is unlikely on any current or future Macintosh.
3768 // If clockdivisor is greater than 10^9 then that means the native clock frequency is greater than 1000GHz.
3769 // When we ship Macs with clock frequencies above 1000GHz, we may have to update this code.
3770 struct mach_timebase_info tbi
;
3771 kern_return_t result
= mach_timebase_info(&tbi
);
3772 if (result
== KERN_SUCCESS
) clockdivisor
= ((uint64_t)tbi
.denom
* 1000000) / tbi
.numer
;
3776 mDNSexport mDNSs32
mDNSPlatformRawTime(void)
3778 if (clockdivisor
== 0) { LogMsg("mDNSPlatformRawTime called before mDNSPlatformTimeInit"); return(0); }
3780 static uint64_t last_mach_absolute_time
= 0;
3781 //static uint64_t last_mach_absolute_time = 0x8000000000000000LL; // Use this value for testing the alert display
3782 uint64_t this_mach_absolute_time
= mach_absolute_time();
3783 if ((int64_t)this_mach_absolute_time
- (int64_t)last_mach_absolute_time
< 0)
3785 LogMsg("mDNSPlatformRawTime: last_mach_absolute_time %08X%08X", last_mach_absolute_time
);
3786 LogMsg("mDNSPlatformRawTime: this_mach_absolute_time %08X%08X", this_mach_absolute_time
);
3787 // Update last_mach_absolute_time *before* calling NotifyOfElusiveBug()
3788 last_mach_absolute_time
= this_mach_absolute_time
;
3789 // Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xyyy) or later.
3790 // (This bug happens all the time on 10.3, and we know that's not going to be fixed.)
3791 if (mDNSMacOSXSystemBuildNumber(NULL
) >= 8)
3792 NotifyOfElusiveBug("mach_absolute_time went backwards!",
3793 "This error occurs from time to time, often on newly released hardware, "
3794 "and usually the exact cause is different in each instance.\r\r"
3795 "Please file a new Radar bug report with the title “mach_absolute_time went backwards” "
3796 "and assign it to Radar Component “Kernel” Version “X”.");
3798 last_mach_absolute_time
= this_mach_absolute_time
;
3800 return((mDNSs32
)(this_mach_absolute_time
/ clockdivisor
));
3803 mDNSexport mDNSs32
mDNSPlatformUTC(void)
3808 // Locking is a no-op here, because we're single-threaded with a CFRunLoop, so we can never interrupt ourselves
3809 mDNSexport
void mDNSPlatformLock (const mDNS
*const m
) { (void)m
; }
3810 mDNSexport
void mDNSPlatformUnlock (const mDNS
*const m
) { (void)m
; }
3811 mDNSexport
void mDNSPlatformStrCopy(const void *src
, void *dst
) { strcpy((char *)dst
, (char *)src
); }
3812 mDNSexport mDNSu32
mDNSPlatformStrLen (const void *src
) { return(strlen((char*)src
)); }
3813 mDNSexport
void mDNSPlatformMemCopy(const void *src
, void *dst
, mDNSu32 len
) { memcpy(dst
, src
, len
); }
3814 mDNSexport mDNSBool
mDNSPlatformMemSame(const void *src
, const void *dst
, mDNSu32 len
) { return(memcmp(dst
, src
, len
) == 0); }
3815 mDNSexport
void mDNSPlatformMemZero( void *dst
, mDNSu32 len
) { bzero(dst
, len
); }
3816 mDNSexport
void * mDNSPlatformMemAllocate(mDNSu32 len
) { return(mallocL("mDNSPlatformMemAllocate", len
)); }
3817 mDNSexport
void mDNSPlatformMemFree (void *mem
) { freeL("mDNSPlatformMemFree", mem
); }