1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
24 Change History (most recent first):
26 $Log: mDNSMacOSX.c,v $
27 Revision 1.294 2005/01/27 21:30:23 cheshire
28 <rdar://problem/3952067> "Can't assign requested address" message after AirPort turned off
29 Don't write syslog messages for EADDRNOTAVAIL if we know network configuration changes are happening
31 Revision 1.293 2005/01/27 19:15:41 cheshire
32 Remove extraneous LogMsg() call
34 Revision 1.292 2005/01/27 17:48:38 cheshire
35 Added comment about CFSocketInvalidate closing the underlying socket
37 Revision 1.291 2005/01/27 00:10:58 cheshire
38 <rdar://problem/3967867> Name change log messages every time machine boots
40 Revision 1.290 2005/01/25 23:18:30 ksekar
41 fix for <rdar://problem/3971467> requires that local-only ".local" registration record be created
43 Revision 1.289 2005/01/25 18:08:31 ksekar
44 Removed redundant debug output
46 Revision 1.288 2005/01/25 17:42:26 ksekar
47 Renamed FoundDefBrowseDomain -> FoundLegacyBrowseDomain,
48 cleaned up duplicate log messages when adding/removing browse domains
50 Revision 1.287 2005/01/25 16:59:23 ksekar
51 <rdar://problem/3971138> sa_len not set checking reachability for TCP connections
53 Revision 1.286 2005/01/25 02:02:37 cheshire
54 <rdar://problem/3970673> mDNSResponder leaks
55 GetSearchDomains() was not calling dns_configuration_free().
57 Revision 1.285 2005/01/22 00:07:54 ksekar
58 <rdar://problem/3960546> mDNSResponder should look at all browse domains in SCPreferences
60 Revision 1.284 2005/01/21 23:07:17 ksekar
61 <rdar://problem/3960795> mDNSResponder causes Dial on Demand
63 Revision 1.283 2005/01/19 21:16:16 cheshire
64 Make sure when we set NetworkChanged that we don't set it to zero
66 Revision 1.282 2005/01/19 19:19:21 ksekar
67 <rdar://problem/3960191> Need a way to turn off domain discovery
69 Revision 1.281 2005/01/18 18:10:55 ksekar
70 <rdar://problem/3954575> Use 10.4 resolver API to get search domains
72 Revision 1.280 2005/01/17 22:48:52 ksekar
73 No longer need to call MarkSearchListElem for registration domain
75 Revision 1.279 2005/01/17 20:40:34 ksekar
76 SCPreferences changes should remove exactly one browse and one legacy browse domain for each remove event
78 Revision 1.278 2005/01/17 19:53:34 ksekar
79 Refinement to previous fix - register _legacy._browse records for SCPreference domains to achieve correct reference counting
81 Revision 1.277 2005/01/12 00:17:50 ksekar
82 <rdar://problem/3933573> Update LLQs *after* setting DNS
84 Revision 1.276 2005/01/10 17:39:10 ksekar
85 Refinement to 1.272 - avoid spurious warnings when registration and browse domains are set to same value and toggled on/off
87 Revision 1.275 2005/01/10 04:02:22 ksekar
88 Refinement to <rdar://problem/3891628> - strip trailing dot before writing hostname status to dynamic store
90 Revision 1.274 2005/01/10 03:41:36 ksekar
91 Correction to checkin 1.272 - check that registration domain is set
92 before trying to remove it as an implicit browse domain
94 Revision 1.273 2005/01/08 00:42:18 ksekar
95 <rdar://problem/3922758> Clean up syslog messages
97 Revision 1.272 2005/01/07 23:21:42 ksekar
98 <rdar://problem/3891628> Clean up SCPreferences format
100 Revision 1.271 2004/12/20 23:18:12 cheshire
101 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
102 One more refinement: When an interface with a v6LL address gets a v4 address too, that's not a flap
104 Revision 1.270 2004/12/20 21:28:14 cheshire
105 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
106 Additional refinements to handle sleep/wake better
108 Revision 1.269 2004/12/20 20:48:11 cheshire
109 Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xxx) or later
111 Revision 1.268 2004/12/18 03:19:04 cheshire
112 Show netmask in error log
114 Revision 1.267 2004/12/18 00:51:52 cheshire
115 Use symbolic constant kDNSServiceInterfaceIndexLocalOnly instead of (mDNSu32) ~0
117 Revision 1.266 2004/12/17 23:49:38 cheshire
118 <rdar://problem/3922754> Computer Name change is slow
119 Also treat changes to "Setup:/Network/DynamicDNS" the same way
121 Revision 1.265 2004/12/17 23:37:47 cheshire
122 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
123 (and other repetitive configuration changes)
125 Revision 1.264 2004/12/17 19:03:05 cheshire
126 Update debugging messages to show netmask a simple CIDR-style numeric value (0-128)
128 Revision 1.263 2004/12/17 05:25:46 cheshire
129 <rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs
131 Revision 1.262 2004/12/17 04:48:32 cheshire
132 <rdar://problem/3922754> Computer Name change is slow
134 Revision 1.261 2004/12/17 02:40:08 cheshire
135 Undo last change -- it was too strict
137 Revision 1.260 2004/12/16 22:17:16 cheshire
138 Only accept multicast packets on interfaces that have McastTxRx set
140 Revision 1.259 2004/12/16 20:13:01 cheshire
141 <rdar://problem/3324626> Cache memory management improvements
143 Revision 1.258 2004/12/14 00:18:05 cheshire
144 Don't log dns_configuration_copy() failures in the first three minutes after boot
146 Revision 1.257 2004/12/10 19:45:46 cheshire
147 <rdar://problem/3915074> Reduce egregious stack space usage
148 Reduced myCFSocketCallBack() stack frame from 9K to 512 bytes
150 Revision 1.256 2004/12/10 04:35:43 cheshire
151 <rdar://problem/3907233> Show "Note: Compiled without Apple-specific split DNS support" only once
153 Revision 1.255 2004/12/10 04:12:54 ksekar
154 <rdar://problem/3890764> Need new DefaultBrowseDomain key
156 Revision 1.254 2004/12/10 01:55:31 ksekar
157 <rdar://problem/3899067> Keychain lookups should be in lower case.
159 Revision 1.253 2004/12/09 03:15:41 ksekar
160 <rdar://problem/3806610> use _legacy instead of _default to find "empty string" browse domains
162 Revision 1.252 2004/12/07 01:32:42 cheshire
163 Don't log dns_configuration_copy() failure when running on 10.3
165 Revision 1.251 2004/12/06 22:30:31 cheshire
166 Added debugging log message
168 Revision 1.250 2004/12/06 06:59:08 ksekar
169 RegisterSplitDNS should return Unsupported error when compiled on Panther
171 Revision 1.249 2004/12/04 00:29:46 cheshire
172 Add "#ifdef MAC_OS_X_VERSION_10_4" around split-DNS code that can't be compiled on 10.3 systems
173 (When compiled on 10.3, code will not include split-DNS support.)
175 Revision 1.248 2004/12/01 20:57:20 ksekar
176 <rdar://problem/3873921> Wide Area Rendezvous must be split-DNS aware
178 Revision 1.247 2004/12/01 03:26:58 cheshire
179 Remove unused variables
181 Revision 1.246 2004/12/01 01:51:34 cheshire
182 Move ReadDDNSSettingsFromConfFile() from mDNSMacOSX.c to PlatformCommon.c
184 Revision 1.245 2004/11/30 03:24:04 cheshire
185 <rdar://problem/3854544> Defer processing network configuration changes until configuration has stabilized
187 Revision 1.244 2004/11/30 02:59:35 cheshire
188 For debugging diagnostics, added identifying strings in SCDynamicStoreCreate() calls
190 Revision 1.243 2004/11/29 19:17:29 ksekar
191 <rdar://problem/3878195> Unnecessary GetUserSpecifiedDDNSConfig log messages
193 Revision 1.242 2004/11/29 18:37:38 ksekar
194 <rdar://problem/3889341> Buffer overflow in GetConfigOption
196 Revision 1.241 2004/11/25 01:37:04 ksekar
197 <rdar://problem/3894854> Config file and SCPreferences don't play well together
199 Revision 1.240 2004/11/25 01:29:42 ksekar
200 Remove unnecessary log messages
202 Revision 1.239 2004/11/25 01:27:19 ksekar
203 <rdar://problem/3885859> Don't try to advertise link-local IP addresses via dynamic update
205 Revision 1.238 2004/11/24 22:00:59 cheshire
206 Move definition of mDNSAddressIsAllDNSLinkGroup() from mDNSMacOSX.c to mDNSEmbeddedAPI.h
208 Revision 1.237 2004/11/24 21:54:44 cheshire
209 <rdar://problem/3894475> mDNSCore not receiving unicast responses properly
211 Revision 1.236 2004/11/23 03:39:46 cheshire
212 Let interface name/index mapping capability live directly in JNISupport.c,
213 instead of having to call through to the daemon via IPC to get this information.
215 Revision 1.235 2004/11/17 01:45:35 cheshire
216 <rdar://problem/3847435> Rendezvous buddy list frequently becomes empty if you let the machine sleep
217 Refresh our interface list on receiving kIOMessageSystemHasPoweredOn,
218 in case we get no System Configuration Framework "network changed" event.
220 Revision 1.234 2004/11/17 00:32:56 ksekar
221 <rdar://problem/3880773> mDNSResponder will not discover zones contained both in Search Domains and DHCP Domain option
223 Revision 1.233 2004/11/12 03:16:45 rpantos
224 rdar://problem/3809541 Add mDNSPlatformGetInterfaceByName, mDNSPlatformGetInterfaceName
226 Revision 1.232 2004/11/10 20:40:54 ksekar
227 <rdar://problem/3868216> LLQ mobility fragile on non-primary interface
229 Revision 1.231 2004/11/06 00:59:33 ksekar
230 Don't log ENETDOWN errors for unicast destinations (pollutes log on
233 Revision 1.230 2004/11/05 01:04:10 ksekar
234 <rdar://problem/3774577> LegacyNATDestroy() called too enthusiastically
236 Revision 1.229 2004/11/03 03:45:16 cheshire
237 <rdar://problem/3863627> mDNSResponder does not inform user of Computer Name collisions
239 Revision 1.228 2004/11/02 23:47:32 cheshire
240 <rdar://problem/3863214> Default hostname and Computer Name should be unique
242 Revision 1.227 2004/11/02 04:23:03 cheshire
243 Change to more informative name "GetUserSpecifiedLocalHostName()"
245 Revision 1.226 2004/11/01 20:36:19 ksekar
246 <rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
248 Revision 1.225 2004/10/28 19:03:04 cheshire
249 Remove \n from LogMsg() calls
251 Revision 1.224 2004/10/28 17:47:34 cheshire
252 Oops. Forgot the %d in the log message.
254 Revision 1.223 2004/10/28 17:24:28 cheshire
255 Updated "bad ifa_netmask" log message to give more information
257 Revision 1.222 2004/10/28 03:36:34 cheshire
258 <rdar://problem/3856535> Share the same port for both multicast and unicast receiving
260 Revision 1.221 2004/10/28 03:24:41 cheshire
261 Rename m->CanReceiveUnicastOn as m->CanReceiveUnicastOn5353
263 Revision 1.220 2004/10/28 00:53:57 cheshire
264 Export mDNSMacOSXNetworkChanged() so it's callable from outside this mDNSMacOSX.c;
265 Add LogOperation() call to record when we get network change events
267 Revision 1.219 2004/10/27 20:42:20 cheshire
268 Clean up debugging messages
270 Revision 1.218 2004/10/27 02:03:59 cheshire
271 Update debugging messages
273 Revision 1.217 2004/10/26 20:48:21 cheshire
274 Improve logging messages
276 Revision 1.216 2004/10/26 01:02:37 cheshire
279 Revision 1.215 2004/10/25 20:09:00 ksekar
280 Cleaned up config file parsing.
282 Revision 1.214 2004/10/25 19:30:53 ksekar
283 <rdar://problem/3827956> Simplify dynamic host name structures
285 Revision 1.213 2004/10/23 01:16:01 cheshire
286 <rdar://problem/3851677> uDNS operations not always reliable on multi-homed hosts
288 Revision 1.212 2004/10/22 20:52:08 ksekar
289 <rdar://problem/3799260> Create NAT port mappings for Long Lived Queries
291 Revision 1.211 2004/10/22 01:07:11 cheshire
292 <rdar://problem/3375328> select() says data is waiting; recvfrom() says there is no data
293 Log error message if socket() ever returns file descriptors 0, 1 or 2 (stdin/stdout/stderr).
294 These are all supposed to be remapped to /dev/null
296 Revision 1.210 2004/10/20 02:19:54 cheshire
297 Eliminate "SetupAddr invalid sa_family" warning from RegisterSearchDomains()
299 Revision 1.209 2004/10/16 00:17:00 cheshire
300 <rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
302 Revision 1.208 2004/10/15 23:00:18 ksekar
303 <rdar://problem/3799242> Need to update LLQs on location changes
305 Revision 1.207 2004/10/13 22:45:23 cheshire
306 <rdar://problem/3438392> Ten-second delay before kIOMessageSystemHasPoweredOn message
308 Revision 1.206 2004/10/13 22:11:46 cheshire
309 Update debugging messages
311 Revision 1.205 2004/10/12 21:10:11 cheshire
312 <rdar://problem/3438376> mach_absolute_time() not monotonically increasing
313 Do a NotifyOfElusiveBug() if we see mach_absolute_time() go backwards
315 Revision 1.204 2004/10/12 03:20:52 ksekar
316 <rdar://problem/3835614> Incorrect LogMsg produces garbage on errors
318 Revision 1.203 2004/10/08 04:29:25 ksekar
319 <rdar://problem/3831842> Allow default search domains to be set via hint from DHCP
321 Revision 1.202 2004/10/04 05:56:04 cheshire
322 <rdar://problem/3824730> mDNSResponder doesn't respond to certain AirPort changes
324 Revision 1.201 2004/09/30 00:24:59 ksekar
325 <rdar://problem/3695802> Dynamically update default registration domains on config change
327 Revision 1.200 2004/09/26 23:20:35 ksekar
328 <rdar://problem/3813108> Allow default registrations in multiple wide-area domains
330 Revision 1.199 2004/09/24 23:54:55 cheshire
331 <rdar://problem/3787102> Don't use kCFSocketCloseOnInvalidate
333 Revision 1.198 2004/09/24 23:47:49 cheshire
334 Correct comment and error message
336 Revision 1.197 2004/09/24 23:39:27 cheshire
337 <rdar://problem/3733705> Only IPv6 loopback address advertised on laptop w/no networking
339 Revision 1.196 2004/09/24 20:53:04 cheshire
340 Revise error message to say "Setsockopt SO_REUSEPORT failed" instead of "Flaw in Kernel"
342 Revision 1.195 2004/09/24 19:21:45 cheshire
343 <rdar://problem/3671626> Report "Address already in use" errors
345 Revision 1.194 2004/09/24 19:16:54 cheshire
346 Remove "mDNS *const m" parameter from NotifyOfElusiveBug();
347 Refine error message to say "Flaw in Kernel (select/recvfrom mismatch)"
349 Revision 1.193 2004/09/22 00:41:59 cheshire
350 Move tcp connection status codes into the legal range allocated for mDNS use
352 Revision 1.192 2004/09/21 21:02:55 cheshire
353 Set up ifname before calling mDNS_RegisterInterface()
355 Revision 1.191 2004/09/21 19:19:36 cheshire
356 <rdar://problem/3760923> Combine WatchForDynDNSChanges() into WatchForNetworkChanges()
358 Revision 1.190 2004/09/21 19:04:45 cheshire
359 Strip trailing white space from the ends of lines
361 Revision 1.189 2004/09/21 00:13:28 cheshire
362 Fix build failure (io_connect_t and io_object_t are integers, not pointers)
364 Revision 1.188 2004/09/20 23:52:02 cheshire
365 CFSocket{Puma}.c renamed to mDNSMacOSX{Puma}.c
367 Revision 1.187 2004/09/18 01:37:01 cheshire
370 Revision 1.186 2004/09/18 01:11:57 ksekar
371 <rdar://problem/3806734> Add a user's default domain to empty-string browse list
373 Revision 1.185 2004/09/17 01:08:52 cheshire
374 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
375 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
376 declared in that file are ONLY appropriate to single-address-space embedded applications.
377 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
379 Revision 1.184 2004/09/17 00:19:10 cheshire
380 For consistency with AllDNSLinkGroupv6, rename AllDNSLinkGroup to AllDNSLinkGroupv4
382 Revision 1.183 2004/09/17 00:15:56 cheshire
383 Rename mDNSPlatformInit_ReceiveUnicast to mDNSPlatformInit_CanReceiveUnicast
385 Revision 1.182 2004/09/16 21:36:36 cheshire
386 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
387 Changes to add necessary locking calls around unicast DNS operations
389 Revision 1.181 2004/09/16 02:03:42 cheshire
390 <rdar://problem/3802944> Change address to notify user of kernel flaw
392 Revision 1.180 2004/09/16 01:58:22 cheshire
393 Fix compiler warnings
395 Revision 1.179 2004/09/16 00:24:49 cheshire
396 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
398 Revision 1.178 2004/09/15 21:51:34 cheshire
399 <rdar://problem/3387020> mDNSResponder should notify user of kernel flaw
400 Calling CFUserNotificationDisplayNotice too early in the boot process seems to kill
401 the machine, so make sure we don't do this until at least three minutes after boot.
403 Revision 1.177 2004/09/15 01:16:29 cheshire
404 <rdar://problem/3387020> mDNSResponder should notify user of kernel flaw
406 Revision 1.176 2004/09/14 23:42:36 cheshire
407 <rdar://problem/3801296> Need to seed random number generator from platform-layer data
409 Revision 1.175 2004/09/14 21:35:46 cheshire
410 Minor code tidying, and added comments about CFRetainCounts
412 Revision 1.174 2004/09/14 19:14:57 ksekar
413 <rdar://problem/3192531> DynDNS: Discovery of DynDNS Zones via Reverse-Map PTR
415 Revision 1.173 2004/08/25 23:35:22 ksekar
416 <rdar://problem/3770615>: Error converting shared secret from base-64 to binary
418 Revision 1.172 2004/08/25 02:01:45 cheshire
419 <rdar://problem/3774777> Need to be able to get status of Dynamic DNS Host Name Update
421 Revision 1.171 2004/08/25 01:04:42 cheshire
422 Don't need to CFRelease name and array
424 Revision 1.170 2004/08/25 00:37:28 ksekar
425 <rdar://problem/3774635>: Cleanup DynDNS hostname registration code
427 Revision 1.169 2004/08/18 17:35:41 ksekar
428 <rdar://problem/3651443>: Feature #9586: Need support for Legacy NAT gateways
430 Revision 1.168 2004/08/17 03:16:24 ksekar
431 Fixed checkin 1.166 - enumeration type changed for wrong invocation of mDNS_GetDomains
433 Revision 1.167 2004/08/17 00:52:43 ksekar
434 Fix config file parse error, make semantics match SCPreferences
437 Revision 1.166 2004/08/16 19:55:07 ksekar
438 Change enumeration type to BrowseDefault to construct empty-string
439 browse list as result of checking 1.161.
441 Revision 1.165 2004/08/16 19:52:40 ksekar
442 Pass computer name + zone for FQDN after keychain notification,
443 setting global default service registration domain to the zone.
445 Revision 1.164 2004/08/16 16:52:37 ksekar
446 Pass in zone read from keychain to mDNS_SetFQDNs.
448 Revision 1.163 2004/08/14 03:22:42 cheshire
449 <rdar://problem/3762579> Dynamic DNS UI <-> mDNSResponder glue
450 Add GetUserSpecifiedDDNSName() routine
451 Convert ServiceRegDomain to domainname instead of C string
452 Replace mDNS_GenerateFQDN/mDNS_GenerateGlobalFQDN with mDNS_SetFQDNs
454 Revision 1.162 2004/08/12 22:34:00 cheshire
455 All strings should be read as kCFStringEncodingUTF8, not kCFStringEncodingASCII
457 Revision 1.161 2004/08/11 00:17:46 ksekar
458 <rdar://problem/3757662>: 8A227: Need Lighthouse configred machines to
459 set default bit for their domains
461 Revision 1.160 2004/07/29 19:27:16 ksekar
462 NATPMP Support - minor fixes and cleanup
464 Revision 1.159 2004/07/26 22:49:31 ksekar
465 <rdar://problem/3651409>: Feature #9516: Need support for NATPMP in client
467 Revision 1.158 2004/07/13 21:24:24 rpantos
468 Fix for <rdar://problem/3701120>.
470 Revision 1.157 2004/06/08 18:54:48 ksekar
471 <rdar://problem/3681378>: mDNSResponder leaks after exploring in Printer Setup Utility
473 Revision 1.156 2004/06/05 00:04:26 cheshire
474 <rdar://problem/3668639>: wide-area domains should be returned in reg. domain enumeration
476 Revision 1.155 2004/06/04 08:58:30 ksekar
477 <rdar://problem/3668624>: Keychain integration for secure dynamic update
479 Revision 1.154 2004/05/31 22:22:28 ksekar
480 <rdar://problem/3668639>: wide-area domains should be returned in
481 reg. domain enumeration
483 Revision 1.153 2004/05/26 17:06:33 cheshire
484 <rdar://problem/3668515>: Don't rely on CFSocketInvalidate() to remove RunLoopSource
486 Revision 1.152 2004/05/18 23:51:26 cheshire
487 Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
489 Revision 1.151 2004/05/17 21:46:34 cheshire
490 <rdar://problem/3616426>: When interface is turned off, browse "remove" events are delivered with interface index zero
491 Take care to correctly update InterfaceIDs when a dormant interface comes back to life
493 Revision 1.150 2004/05/13 04:54:20 ksekar
494 Unified list copy/free code. Added symetric list for
496 Revision 1.149 2004/05/13 03:55:14 ksekar
497 Fixed list traversal bug in FoundDefSearchDomain.
499 Revision 1.148 2004/05/12 22:03:08 ksekar
500 Made GetSearchDomainList a true platform-layer call (declaration moved
501 from mDNSMacOSX.h to mDNSEmbeddedAPI.h), impelemted to return "local"
502 only on non-OSX platforms. Changed call to return a copy of the list
503 to avoid shared memory issues. Added a routine to free the list.
505 Revision 1.147 2004/05/12 02:03:25 ksekar
506 Non-local domains will only be browsed by default, and show up in
507 _browse domain enumeration, if they contain an _browse._dns-sd ptr record.
509 Revision 1.146 2004/04/27 02:49:15 cheshire
510 <rdar://problem/3634655>: mDNSResponder leaks sockets on bind() error
512 Revision 1.145 2004/04/21 03:08:03 cheshire
513 Rename 'alias' to more descriptive name 'primary'
515 Revision 1.144 2004/04/21 03:04:35 cheshire
516 Minor cleanup for clarity
518 Revision 1.143 2004/04/21 03:03:30 cheshire
519 Preparation work: AddInterfaceToList() should return pointer to structure it creates
521 Revision 1.142 2004/04/21 02:49:11 cheshire
522 To reduce future confusion, renamed 'TxAndRx' to 'McastTxRx'
524 Revision 1.141 2004/04/21 02:20:47 cheshire
525 Rename interface field 'CurrentlyActive' to more descriptive 'Exists'
527 Revision 1.140 2004/04/14 23:09:29 ksekar
528 Support for TSIG signed dynamic updates.
530 Revision 1.139 2004/04/09 17:40:26 cheshire
531 Remove unnecessary "Multicast" field -- it duplicates the semantics of the existing McastTxRx field
533 Revision 1.138 2004/04/09 16:37:16 cheshire
534 Suggestion from Bob Bradley:
535 Move NumCacheRecordsForInterfaceID() to DNSCommon.c so it's available to all platform layers
537 Revision 1.137 2004/04/08 00:59:55 cheshire
538 <rdar://problem/3609972> When interface turned off, browse "remove" events delivered with interface index zero
539 Unify use of the InterfaceID field, and make code that walks the list respect the 'Exists' flag
541 Revision 1.136 2004/04/07 01:08:57 cheshire
542 <rdar://problem/3609972> When interface turned off, browse "remove" events delivered with interface index zero
544 Revision 1.135 2004/03/19 01:01:03 ksekar
545 Fixed config file parsing to chop newline
547 Revision 1.134 2004/03/13 01:57:34 ksekar
548 <rdar://problem/3192546>: DynDNS: Dynamic update of service records
550 Revision 1.133 2004/02/02 22:46:56 cheshire
551 Move "CFRelease(dict);" inside the "if (dict)" check
553 Revision 1.132 2004/01/28 02:30:08 ksekar
554 Added default Search Domains to unicast browsing, controlled via
555 Networking sharing prefs pane. Stopped sending unicast messages on
556 every interface. Fixed unicast resolving via mach-port API.
558 Revision 1.131 2004/01/27 22:57:48 cheshire
559 <rdar://problem/3534352>: Need separate socket for issuing unicast queries
561 Revision 1.130 2004/01/27 22:28:40 cheshire
562 <rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
563 Additional lingering port 53 code deleted
565 Revision 1.129 2004/01/27 20:15:23 cheshire
566 <rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
568 Revision 1.128 2004/01/24 23:58:17 cheshire
569 Change to use mDNSVal16() instead of shifting and ORing
571 Revision 1.127 2004/01/24 04:59:16 cheshire
572 Fixes so that Posix/Linux, OS9, Windows, and VxWorks targets build again
574 Revision 1.126 2004/01/23 23:23:15 ksekar
575 Added TCP support for truncated unicast messages.
577 Revision 1.125 2004/01/22 03:43:09 cheshire
578 Export constants like mDNSInterface_LocalOnly so that the client layers can use them
580 Revision 1.124 2004/01/21 21:53:19 cheshire
581 <rdar://problem/3448144>: Don't try to receive unicast responses if we're not the first to bind to the UDP port
583 Revision 1.123 2004/01/20 03:18:25 cheshire
584 Removed "LogMsg("Hey There!");" that evidently got checked in my mistake
586 Revision 1.122 2003/12/17 20:43:59 cheshire
587 <rdar://problem/3496728>: Syslog messages saying "sendto failed"
589 Revision 1.121 2003/12/13 03:05:28 ksekar
590 <rdar://problem/3192548>: DynDNS: Unicast query of service records
592 Revision 1.120 2003/12/08 21:00:46 rpantos
593 Changes to support mDNSResponder on Linux.
595 Revision 1.119 2003/12/03 02:35:15 cheshire
596 Also report value of m->timenow when logging sendto() failure
598 Revision 1.118 2003/11/14 20:59:09 cheshire
599 Clients can't use AssignDomainName macro because mDNSPlatformMemCopy is defined in mDNSPlatformFunctions.h.
600 Best solution is just to combine mDNSEmbeddedAPI.h and mDNSPlatformFunctions.h into a single file.
602 Revision 1.117 2003/11/08 22:18:29 cheshire
603 <rdar://problem/3477870>: Don't need to show process ID in *every* mDNSResponder syslog message
605 Revision 1.116 2003/09/23 16:39:49 cheshire
606 When LogAllOperations is set, also report registration and deregistration of interfaces
608 Revision 1.115 2003/09/10 00:45:55 cheshire
609 <rdar://problem/3412328> Don't log "sendto failed" errors during the first two minutes of startup
611 Revision 1.114 2003/08/27 02:55:13 cheshire
612 <rdar://problem/3387910>: Bug: Don't report mDNSPlatformSendUDP sendto errno 64 (Host is down)
614 Revision 1.113 2003/08/19 22:20:00 cheshire
615 <rdar://problem/3376721> Don't use IPv6 on interfaces that have a routable IPv4 address configured
616 More minor refinements
618 Revision 1.112 2003/08/19 03:04:43 cheshire
619 <rdar://problem/3376721> Don't use IPv6 on interfaces that have a routable IPv4 address configured
621 Revision 1.111 2003/08/18 22:53:37 cheshire
622 <rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformRawTime()
624 Revision 1.110 2003/08/16 03:39:00 cheshire
625 <rdar://problem/3338440> InterfaceID -1 indicates "local only"
627 Revision 1.109 2003/08/15 02:19:49 cheshire
628 <rdar://problem/3375225> syslog messages: myCFSocketCallBack recvfrom skt 6 error -1 errno 35
629 Also limit number of messages to at most 100
631 Revision 1.108 2003/08/12 22:24:52 cheshire
632 <rdar://problem/3375225> syslog messages: myCFSocketCallBack recvfrom skt 6 error -1 errno 35
633 This message indicates a kernel bug, but still we don't want to flood syslog.
634 Do a sleep(1) after writing this log message, to limit the rate.
636 Revision 1.107 2003/08/12 19:56:25 cheshire
639 Revision 1.106 2003/08/12 13:48:32 cheshire
640 Add comment explaining clockdivisor calculation
642 Revision 1.105 2003/08/12 13:44:14 cheshire
643 <rdar://problem/3370229> mDNSResponder *VERY* unhappy if time goes backwards
644 Use mach_absolute_time() (which is guaranteed to always go forwards, resetting only on reboot)
645 instead of gettimeofday() (which can jump back if the user manually changes their time/date)
647 Revision 1.104 2003/08/12 13:12:07 cheshire
648 Textual search/replace: Indicate local functions using "mDNSlocal" instead of "static"
650 Revision 1.103 2003/08/08 18:36:04 cheshire
651 <rdar://problem/3344154> Only need to revalidate on interface removal on platforms that have the PhantomInterfaces bug
653 Revision 1.102 2003/08/06 00:14:52 cheshire
654 <rdar://problem/3330324> Need to check IP TTL on responses
655 Also add corresponding checks in the IPv6 code path
657 Revision 1.101 2003/08/05 22:20:16 cheshire
658 <rdar://problem/3330324> Need to check IP TTL on responses
660 Revision 1.100 2003/08/05 21:18:50 cheshire
661 <rdar://problem/3363185> mDNSResponder should ignore 6to4
662 Only use interfaces that are marked as multicast-capable (IFF_MULTICAST)
664 Revision 1.99 2003/08/05 20:13:52 cheshire
665 <rdar://problem/3294080> mDNSResponder using IPv6 interfaces before they are ready
666 Ignore interfaces with the IN6_IFF_NOTREADY flag set
668 Revision 1.98 2003/07/20 03:38:51 ksekar
669 <rdar://problem/3320722>
670 Completed support for Unix-domain socket based API.
672 Revision 1.97 2003/07/19 03:15:16 cheshire
673 Add generic MemAllocate/MemFree prototypes to mDNSPlatformFunctions.h,
674 and add the obvious trivial implementations to each platform support layer
676 Revision 1.96 2003/07/18 00:30:00 cheshire
677 <rdar://problem/3268878> Remove mDNSResponder version from packet header and use HINFO record instead
679 Revision 1.95 2003/07/12 03:15:20 cheshire
680 <rdar://problem/3324848> After SCDynamicStore notification, mDNSResponder updates
681 m->hostlabel even if user hasn't actually actually changed their dot-local hostname
683 Revision 1.94 2003/07/03 00:51:54 cheshire
684 <rdar://problem/3287213> When select() and recvmgs() disagree, get more info from kernel about the socket state
686 Revision 1.93 2003/07/03 00:09:14 cheshire
687 <rdar://problem/3286004> New APIs require a mDNSPlatformInterfaceIDfromInterfaceIndex() call
688 Additional refinement suggested by Josh: Use info->scope_id instead of if_nametoindex(info->ifa_name);
690 Revision 1.92 2003/07/02 21:19:51 cheshire
691 <rdar://problem/3313413> Update copyright notices, etc., in source code comments
693 Revision 1.91 2003/06/24 01:53:51 cheshire
694 Minor update to comments
696 Revision 1.90 2003/06/24 01:51:47 cheshire
697 <rdar://problem/3303118> Oops: Double-dispose of sockets
698 Don't need to close sockets: CFSocketInvalidate() does that for us
700 Revision 1.89 2003/06/21 18:12:47 cheshire
701 <rdar://problem/3296061> mDNSResponder cannot handle interfaces whose total name is >3 chars
702 One-line change: should say "IF_NAMESIZE", not sizeof(ifname)
704 Revision 1.88 2003/06/12 23:38:37 cheshire
705 <rdar://problem/3291162> mDNSResponder doesn't detect some configuration changes
706 Also check that scope_id matches before concluding that two interfaces are the same
708 Revision 1.87 2003/06/10 01:14:11 cheshire
709 <rdar://problem/3286004> New APIs require a mDNSPlatformInterfaceIDfromInterfaceIndex() call
711 Revision 1.86 2003/05/28 02:41:52 cheshire
712 <rdar://problem/3034346> Time to remove Mac OS 9 UDP Port 53 legacy support
714 Revision 1.85 2003/05/28 02:39:47 cheshire
715 Minor change to debugging messages
717 Revision 1.84 2003/05/27 22:29:40 cheshire
718 Remove out-dated comment
720 Revision 1.83 2003/05/26 03:21:29 cheshire
721 Tidy up address structure naming:
722 mDNSIPAddr => mDNSv4Addr (for consistency with mDNSv6Addr)
723 mDNSAddr.addr.ipv4 => mDNSAddr.ip.v4
724 mDNSAddr.addr.ipv6 => mDNSAddr.ip.v6
726 Revision 1.82 2003/05/26 03:01:27 cheshire
727 <rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
729 Revision 1.81 2003/05/24 02:06:42 cheshire
730 <rdar://problem/3268480> IPv6 Multicast Loopback doesn't work
731 Tried setting IPV6_MULTICAST_LOOP; it doesn't help.
732 However, it is probably wise to have the code explicitly set this socket
733 option anyway, in case the default changes in later versions of Unix.
735 Revision 1.80 2003/05/24 02:02:24 cheshire
736 <rdar://problem/3221880> if_indextoname consumes a lot of CPU
737 Fix error in myIfIndexToName; was returning prematurely
739 Revision 1.79 2003/05/23 23:07:44 cheshire
740 <rdar://problem/3268199> Must not write to stderr when running as daemon
742 Revision 1.78 2003/05/23 01:19:04 cheshire
743 <rdar://problem/3267085> mDNSResponder needs to signal type of service to AirPort
744 Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
746 Revision 1.77 2003/05/23 01:12:05 cheshire
749 Revision 1.76 2003/05/22 01:26:01 cheshire
752 Revision 1.75 2003/05/22 00:07:09 cheshire
753 <rdar://problem/3264366> myCFSocketCallBack recvfrom(5) error 1, errno 35
754 Extra logging to determine whether there is a bug in CFSocket
756 Revision 1.74 2003/05/21 20:20:12 cheshire
757 Fix warnings (mainly printf format string warnings, like using "%d" where
758 it should say "%lu", etc.) and improve error logging (use strerror()
759 to include textual error message as well as numeric error in log messages).
761 Revision 1.73 2003/05/21 17:56:29 ksekar
762 <rdar://problem/3191277>: mDNSResponder doesn't watch for IPv6 address changes
764 Revision 1.72 2003/05/14 18:48:41 cheshire
765 <rdar://problem/3159272> mDNSResponder should be smarter about reconfigurations
766 More minor refinements:
767 mDNSMacOSX.c needs to do *all* its mDNS_DeregisterInterface calls before freeing memory
768 mDNS_DeregisterInterface revalidates cache record when *any* representative of an interface goes away
770 Revision 1.71 2003/05/14 07:08:37 cheshire
771 <rdar://problem/3159272> mDNSResponder should be smarter about reconfigurations
772 Previously, when there was any network configuration change, mDNSResponder
773 would tear down the entire list of active interfaces and start again.
774 That was very disruptive, and caused the entire cache to be flushed,
775 and caused lots of extra network traffic. Now it only removes interfaces
776 that have really gone, and only adds new ones that weren't there before.
778 Revision 1.70 2003/05/07 18:30:24 cheshire
779 Fix signed/unsigned comparison warning
781 Revision 1.69 2003/05/06 20:14:44 cheshire
784 Revision 1.68 2003/05/06 00:00:49 cheshire
785 <rdar://problem/3248914> Rationalize naming of domainname manipulation functions
787 Revision 1.67 2003/04/29 00:43:44 cheshire
788 Fix compiler warnings
790 Revision 1.66 2003/04/26 02:41:58 cheshire
791 <rdar://problem/3241281> Change timenow from a local variable to a structure member
793 Revision 1.65 2003/04/26 02:34:01 cheshire
794 Add missing mDNSexport
796 Revision 1.64 2003/04/15 16:48:06 jgraessl
797 <rdar://problem/3228833>
798 Modified code in CFSocket notifier function to read all packets on the socket
799 instead of reading only one packet every time the notifier was called.
801 Revision 1.63 2003/04/15 16:33:50 jgraessl
802 <rdar://problem/3221880>
803 Switched to our own copy of if_indextoname to improve performance.
805 Revision 1.62 2003/03/28 01:55:44 cheshire
806 Minor improvements to debugging messages
808 Revision 1.61 2003/03/27 03:30:56 cheshire
809 <rdar://problem/3210018> Name conflicts not handled properly, resulting in memory corruption, and eventual crash
810 Problem was that HostNameCallback() was calling mDNS_DeregisterInterface(), which is not safe in a callback
812 1. Make mDNS_DeregisterInterface() safe to call from a callback
813 2. Make HostNameCallback() use mDNS_DeadvertiseInterface() instead
814 (it never really needed to deregister the interface at all)
816 Revision 1.60 2003/03/15 04:40:38 cheshire
817 Change type called "mDNSOpaqueID" to the more descriptive name "mDNSInterfaceID"
819 Revision 1.59 2003/03/11 01:23:26 cheshire
820 <rdar://problem/3194246> mDNSResponder socket problems
822 Revision 1.58 2003/03/06 01:43:04 cheshire
823 <rdar://problem/3189097> Additional debugging code in mDNSResponder
824 Improve "LIST_ALL_INTERFACES" output
826 Revision 1.57 2003/03/05 22:36:27 cheshire
827 <rdar://problem/3186338> Loopback doesn't work with mDNSResponder-27
828 Temporary workaround: Skip loopback interface *only* if we found at least one v4 interface to use
830 Revision 1.56 2003/03/05 01:50:38 cheshire
831 <rdar://problem/3189097> Additional debugging code in mDNSResponder
833 Revision 1.55 2003/02/21 01:54:09 cheshire
834 <rdar://problem/3099194> mDNSResponder needs performance improvements
835 Switched to using new "mDNS_Execute" model (see "Implementer Notes.txt")
837 Revision 1.54 2003/02/20 06:48:35 cheshire
838 <rdar://problem/3169535> Xserve RAID needs to do interface-specific registrations
839 Reviewed by: Josh Graessley, Bob Bradley
841 Revision 1.53 2003/01/29 02:21:23 cheshire
842 Return mStatus_Invalid if can't send packet because socket not available
844 Revision 1.52 2003/01/28 19:39:43 jgraessl
845 Enabling AAAA over IPv4 support.
847 Revision 1.51 2003/01/28 05:11:23 cheshire
848 Fixed backwards comparison in SearchForInterfaceByName
850 Revision 1.50 2003/01/13 23:49:44 jgraessl
851 Merged changes for the following fixes in to top of tree:
852 <rdar://problem/3086540> computer name changes not handled properly
853 <rdar://problem/3124348> service name changes are not properly handled
854 <rdar://problem/3124352> announcements sent in pairs, failing chattiness test
856 Revision 1.49 2002/12/23 22:13:30 jgraessl
857 Reviewed by: Stuart Cheshire
858 Initial IPv6 support for mDNSResponder.
860 Revision 1.48 2002/11/22 01:37:52 cheshire
861 <rdar://problem/3108426> mDNSResponder is monitoring ServiceEntities instead of InterfaceEntities
863 Revision 1.47 2002/09/21 20:44:51 zarzycki
866 Revision 1.46 2002/09/19 21:25:35 cheshire
867 mDNS_snprintf() doesn't need to be in a separate file
869 Revision 1.45 2002/09/17 01:45:13 cheshire
870 Add LIST_ALL_INTERFACES symbol for debugging
872 Revision 1.44 2002/09/17 01:36:23 cheshire
873 Move Puma support to mDNSMacOSXPuma.c
875 Revision 1.43 2002/09/17 01:05:28 cheshire
876 Change mDNS_AdvertiseLocalAddresses to be an Init parameter instead of a global
878 Revision 1.42 2002/09/16 23:13:50 cheshire
883 // ***************************************************************************
885 // Supporting routines to run mDNS on a CFRunLoop platform
886 // ***************************************************************************
888 // For debugging, set LIST_ALL_INTERFACES to 1 to display all found interfaces,
889 // including ones that mDNSResponder chooses not to use.
890 #define LIST_ALL_INTERFACES 0
892 // For enabling AAAA records over IPv4. Setting this to 0 sends only
893 // A records over IPv4 and AAAA over IPv6. Setting this to 1 sends both
894 // AAAA and A records over both IPv4 and IPv6.
895 #define AAAA_OVER_V4 1
897 #include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
898 #include "DNSCommon.h"
899 #include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform
900 #include "../mDNSShared/uds_daemon.h" // Defines communication interface from platform layer up to UDS daemon
901 #include "PlatformCommon.h"
904 #include <stdarg.h> // For va_list support
906 #include <net/if_types.h> // For IFT_ETHER
907 #include <net/if_dl.h>
909 #include <sys/param.h>
910 #include <sys/socket.h>
911 #include <sys/sysctl.h>
913 #include <sys/ioctl.h>
914 #include <time.h> // platform support for UTC time
915 #include <arpa/inet.h> // for inet_aton
917 #include <netinet/in.h> // For IP_RECVTTL
919 #define IP_RECVTTL 24 // bool; receive reception TTL w/dgram
922 #include <netinet/in_systm.h> // For n_long, required by <netinet/ip.h> below
923 #include <netinet/ip.h> // For IPTOS_LOWDELAY etc.
924 #include <netinet6/in6_var.h> // For IN6_IFF_NOTREADY etc.
926 #include <Security/Security.h>
928 #include <AvailabilityMacros.h>
929 #ifdef MAC_OS_X_VERSION_10_4
933 // Code contributed by Dave Heller:
934 // Define RUN_ON_PUMA_WITHOUT_IFADDRS to compile code that will
935 // work on Mac OS X 10.1, which does not have the getifaddrs call.
936 #define RUN_ON_PUMA_WITHOUT_IFADDRS 0
937 #if RUN_ON_PUMA_WITHOUT_IFADDRS
938 #include "mDNSMacOSXPuma.c"
943 #include <IOKit/IOKitLib.h>
944 #include <IOKit/IOMessage.h>
945 #include <mach/mach_time.h>
947 typedef struct SearchListElem
949 struct SearchListElem
*next
;
953 DNSQuestion DefBrowseQ
;
954 DNSQuestion LegacyBrowseQ
;
955 DNSQuestion RegisterQ
;
956 DNSQuestion DefRegisterQ
;
957 ARListElem
*AuthRecs
;
961 // ***************************************************************************
964 static mDNSu32 clockdivisor
= 0;
966 // for domain enumeration and default browsing/registration
967 static SearchListElem
*SearchList
= NULL
; // where we search for _browse domains
968 static DNSQuestion LegacyBrowseDomainQ
; // our local enumeration query for _legacy._browse domains
969 static DNameListElem
*DefBrowseList
= NULL
; // cache of answers to above query (where we search for empty string browses)
970 static DNameListElem
*DefRegList
= NULL
; // manually generated list of domains where we register for empty string registrations
971 static ARListElem
*SCPrefBrowseDomains
= NULL
; // manually generated local-only PTR records for browse domains we get from SCPreferences
973 static domainname DynDNSRegDomain
; // Default wide-area zone for service registration
974 static CFArrayRef DynDNSBrowseDomains
= NULL
; // Default wide-area zones for legacy ("empty string") browses
975 static domainname DynDNSHostname
;
977 static mDNSBool DomainDiscoveryDisabled
= mDNSfalse
;
979 #define CONFIG_FILE "/etc/mDNSResponder.conf"
980 #define DYNDNS_KEYCHAIN_SERVICE "DynDNS Shared Secret"
981 #define SYS_KEYCHAIN_PATH "/Library/Keychains/System.keychain"
983 // Function Prototypes
984 mDNSlocal
void SetSCPrefsBrowseDomain(mDNS
*m
, const domainname
*d
, mDNSBool add
);
986 // ***************************************************************************
989 // routines to allow access to default domain lists from daemon layer
991 mDNSexport DNameListElem
*mDNSPlatformGetSearchDomainList(void)
993 return mDNS_CopyDNameList(DefBrowseList
);
996 mDNSexport DNameListElem
*mDNSPlatformGetRegDomainList(void)
998 return mDNS_CopyDNameList(DefRegList
);
1001 // utility routines to manage registration domain lists
1003 mDNSlocal
void AddDefRegDomain(domainname
*d
)
1005 DNameListElem
*newelem
= NULL
, *ptr
;
1007 // make sure name not already in list
1008 for (ptr
= DefRegList
; ptr
; ptr
= ptr
->next
)
1010 if (SameDomainName(&ptr
->name
, d
))
1011 { debugf("duplicate addition of default reg domain %##s", d
->c
); return; }
1014 newelem
= mallocL("DNameListElem", sizeof(*newelem
));
1015 if (!newelem
) { LogMsg("Error - malloc"); return; }
1016 AssignDomainName(&newelem
->name
, d
);
1017 newelem
->next
= DefRegList
;
1018 DefRegList
= newelem
;
1020 DefaultRegDomainChanged(d
, mDNStrue
);
1021 udsserver_default_reg_domain_changed(d
, mDNStrue
);
1024 mDNSlocal
void RemoveDefRegDomain(domainname
*d
)
1026 DNameListElem
*ptr
= DefRegList
, *prev
= NULL
;
1030 if (SameDomainName(&ptr
->name
, d
))
1032 if (prev
) prev
->next
= ptr
->next
;
1033 else DefRegList
= ptr
->next
;
1034 freeL("DNameListElem", ptr
);
1035 DefaultRegDomainChanged(d
, mDNSfalse
);
1036 udsserver_default_reg_domain_changed(d
, mDNSfalse
);
1042 debugf("Requested removal of default registration domain %##s not in contained in list", d
->c
);
1045 mDNSlocal
void NotifyOfElusiveBug(const char *title
, mDNSu32 radarid
, const char *msg
)
1047 extern mDNS mDNSStorage
;
1048 NetworkInterfaceInfoOSX
*i
;
1049 static int notifyCount
= 0;
1050 if (notifyCount
) return;
1052 // If we display our alert early in the boot process, then it vanishes once the desktop appears.
1053 // To avoid this, we don't try to display alerts in the first three minutes after boot.
1054 if ((mDNSu32
)(mDNSPlatformRawTime()) < (mDNSu32
)(mDNSPlatformOneSecond
* 180)) return;
1056 // Determine if we're at Apple (17.*.*.*)
1057 for (i
= mDNSStorage
.p
->InterfaceList
; i
; i
= i
->next
)
1058 if (i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
&& i
->ifinfo
.ip
.ip
.v4
.b
[0] == 17)
1060 if (!i
) return; // If not at Apple, don't show the alert
1062 // Send a notification to the user to contact coreos-networking
1064 CFStringRef alertHeader
= CFStringCreateWithCString(NULL
, title
, kCFStringEncodingUTF8
);
1065 CFStringRef alertFormat
= CFSTR("Congratulations, you've reproduced an elusive bug. Please contact the owner of <rdar://problem/%d>. %s");
1066 CFStringRef alertMessage
= CFStringCreateWithFormat(NULL
, NULL
, alertFormat
, radarid
, msg
);
1067 CFUserNotificationDisplayNotice(0.0, kCFUserNotificationStopAlertLevel
, NULL
, NULL
, NULL
, alertHeader
, alertMessage
, NULL
);
1070 mDNSlocal
struct ifaddrs
* myGetIfAddrs(int refresh
)
1072 static struct ifaddrs
*ifa
= NULL
;
1080 if (ifa
== NULL
) getifaddrs(&ifa
);
1085 mDNSlocal NetworkInterfaceInfoOSX
*SearchForInterfaceByName(mDNS
*const m
, const char *ifname
, int type
)
1087 NetworkInterfaceInfoOSX
*i
;
1088 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1089 if (i
->Exists
&& !strcmp(i
->ifa_name
, ifname
) &&
1091 (type
== AF_INET
&& i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
) ||
1092 (type
== AF_INET6
&& i
->ifinfo
.ip
.type
== mDNSAddrType_IPv6
) )) return(i
);
1096 mDNSlocal
int myIfIndexToName(u_short index
, char* name
)
1098 struct ifaddrs
*ifa
;
1099 for (ifa
= myGetIfAddrs(0); ifa
; ifa
= ifa
->ifa_next
)
1100 if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
1101 if (((struct sockaddr_dl
*)ifa
->ifa_addr
)->sdl_index
== index
)
1102 { strncpy(name
, ifa
->ifa_name
, IF_NAMESIZE
); return 0; }
1106 mDNSexport mDNSInterfaceID
mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS
*const m
, mDNSu32 index
)
1108 NetworkInterfaceInfoOSX
*i
;
1109 if (index
== kDNSServiceInterfaceIndexLocalOnly
) return(mDNSInterface_LocalOnly
);
1111 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1112 // Don't get tricked by inactive interfaces with no InterfaceID set
1113 if (i
->ifinfo
.InterfaceID
&& i
->scope_id
== index
) return(i
->ifinfo
.InterfaceID
);
1117 mDNSexport mDNSu32
mDNSPlatformInterfaceIndexfromInterfaceID(const mDNS
*const m
, mDNSInterfaceID id
)
1119 NetworkInterfaceInfoOSX
*i
;
1120 if (id
== mDNSInterface_LocalOnly
) return(kDNSServiceInterfaceIndexLocalOnly
);
1122 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1123 // Don't use i->ifinfo.InterfaceID here, because we DO want to find inactive interfaces, which have no InterfaceID set
1124 if ((mDNSInterfaceID
)i
== id
) return(i
->scope_id
);
1128 mDNSlocal mDNSBool
AddrRequiresPPPConnection(const struct sockaddr
*addr
)
1130 mDNSBool result
= mDNSfalse
;
1131 SCNetworkConnectionFlags flags
;
1132 SCNetworkReachabilityRef ReachRef
= NULL
;
1134 ReachRef
= SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault
, addr
);
1135 if (!ReachRef
) { LogMsg("ERROR: RequiresConnection - SCNetworkReachabilityCreateWithAddress"); goto end
; }
1136 if (!SCNetworkReachabilityGetFlags(ReachRef
, &flags
)) { LogMsg("ERROR: AddrRequiresPPPConnection - SCNetworkReachabilityGetFlags"); goto end
; }
1137 result
= flags
& kSCNetworkFlagsConnectionRequired
;
1140 if (ReachRef
) CFRelease(ReachRef
);
1144 // NOTE: If InterfaceID is NULL, it means, "send this packet through our anonymous unicast socket"
1145 // NOTE: If InterfaceID is non-NULL it means, "send this packet through our port 5353 socket on the specified interface"
1146 // OR send via our primary v4 unicast socket
1147 mDNSexport mStatus
mDNSPlatformSendUDP(const mDNS
*const m
, const void *const msg
, const mDNSu8
*const end
,
1148 mDNSInterfaceID InterfaceID
, const mDNSAddr
*dst
, mDNSIPPort dstPort
)
1152 // Note: For this platform we've adopted the convention that InterfaceIDs are secretly pointers
1153 // to the NetworkInterfaceInfoOSX structure that holds the active sockets. The mDNSCore code
1154 // doesn't know that and doesn't need to know that -- it just treats InterfaceIDs as opaque identifiers.
1155 NetworkInterfaceInfoOSX
*info
= (NetworkInterfaceInfoOSX
*)InterfaceID
;
1156 char *ifa_name
= info
? info
->ifa_name
: "unicast";
1157 struct sockaddr_storage to
;
1160 // Sanity check: Make sure that if we're sending a query via unicast, we're sending it using our
1161 // anonymous socket created for this purpose, so that we'll receive the response.
1162 // If we use one of the many multicast sockets bound to port 5353 then we may not receive responses reliably.
1163 if (info
&& !mDNSAddrIsDNSMulticast(dst
))
1165 const DNSMessage
*const m
= (DNSMessage
*)msg
;
1166 if ((m
->h
.flags
.b
[0] & kDNSFlag0_QR_Mask
) == kDNSFlag0_QR_Query
)
1167 LogMsg("mDNSPlatformSendUDP: ERROR: Sending query OP from mDNS port to non-mDNS destination %#a:%d", dst
, mDNSVal16(dstPort
));
1170 if (dst
->type
== mDNSAddrType_IPv4
)
1172 struct sockaddr_in
*sin_to
= (struct sockaddr_in
*)&to
;
1173 sin_to
->sin_len
= sizeof(*sin_to
);
1174 sin_to
->sin_family
= AF_INET
;
1175 sin_to
->sin_port
= dstPort
.NotAnInteger
;
1176 sin_to
->sin_addr
.s_addr
= dst
->ip
.v4
.NotAnInteger
;
1177 s
= info
? info
->ss
.sktv4
: m
->p
->unicastsockets
.sktv4
;
1179 else if (dst
->type
== mDNSAddrType_IPv6
)
1181 struct sockaddr_in6
*sin6_to
= (struct sockaddr_in6
*)&to
;
1182 sin6_to
->sin6_len
= sizeof(*sin6_to
);
1183 sin6_to
->sin6_family
= AF_INET6
;
1184 sin6_to
->sin6_port
= dstPort
.NotAnInteger
;
1185 sin6_to
->sin6_flowinfo
= 0;
1186 sin6_to
->sin6_addr
= *(struct in6_addr
*)&dst
->ip
.v6
;
1187 sin6_to
->sin6_scope_id
= info
? info
->scope_id
: 0;
1188 s
= info
? info
->ss
.sktv6
: m
->p
->unicastsockets
.sktv6
;
1192 LogMsg("mDNSPlatformSendUDP: dst is not an IPv4 or IPv6 address!");
1193 return mStatus_BadParamErr
;
1196 // Don't send if it would cause dial on demand connection initiation. As an optimization,
1197 // don't bother consulting reachability API / routing table when sending Multicast DNS
1198 // since we ignore PPP interfaces for mDNS traffic
1199 if (!mDNSAddrIsDNSMulticast(dst
) && AddrRequiresPPPConnection((struct sockaddr
*)&to
))
1201 debugf("mDNSPlatformSendUDP: Surpressing sending to avoid dial-on-demand connection");
1202 return mStatus_NoError
;
1206 verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %p %5s/%ld to %#a:%d skt %d",
1207 InterfaceID
, ifa_name
, dst
->type
, dst
, mDNSVal16(dstPort
), s
);
1209 verbosedebugf("mDNSPlatformSendUDP: NOT sending on InterfaceID %p %5s/%ld (socket of this type not available)",
1210 InterfaceID
, ifa_name
, dst
->type
, dst
, mDNSVal16(dstPort
));
1212 // Note: When sending, mDNSCore may often ask us to send both a v4 multicast packet and then a v6 multicast packet
1213 // If we don't have the corresponding type of socket available, then return mStatus_Invalid
1214 if (s
< 0) return(mStatus_Invalid
);
1216 err
= sendto(s
, msg
, (UInt8
*)end
- (UInt8
*)msg
, 0, (struct sockaddr
*)&to
, to
.ss_len
);
1219 // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
1220 if (!mDNSAddressIsAllDNSLinkGroup(dst
) && (errno
== EHOSTDOWN
|| errno
== ENETDOWN
|| errno
== EHOSTUNREACH
)) return(err
);
1221 // Don't report EHOSTUNREACH in the first three minutes after boot
1222 // This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
1223 // but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
1224 if (errno
== EHOSTUNREACH
&& (mDNSu32
)(mDNSPlatformRawTime()) < (mDNSu32
)(mDNSPlatformOneSecond
* 180)) return(err
);
1225 // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change
1226 if (errno
== EADDRNOTAVAIL
&& m
->p
->NetworkChanged
) return(err
);
1227 LogMsg("mDNSPlatformSendUDP sendto failed to send packet on InterfaceID %p %5s/%ld to %#a:%d skt %d error %d errno %d (%s) %lu",
1228 InterfaceID
, ifa_name
, dst
->type
, dst
, mDNSVal16(dstPort
), s
, err
, errno
, strerror(errno
), (mDNSu32
)(m
->timenow
));
1232 return(mStatus_NoError
);
1235 mDNSlocal ssize_t
myrecvfrom(const int s
, void *const buffer
, const size_t max
,
1236 struct sockaddr
*const from
, size_t *const fromlen
, mDNSAddr
*dstaddr
, char ifname
[IF_NAMESIZE
], mDNSu8
*ttl
)
1238 static unsigned int numLogMessages
= 0;
1239 struct iovec databuffers
= { (char *)buffer
, max
};
1242 struct cmsghdr
*cmPtr
;
1243 char ancillary
[1024];
1245 *ttl
= 255; // If kernel fails to provide TTL data (e.g. Jaguar doesn't) then assume the TTL was 255 as it should be
1247 // Set up the message
1248 msg
.msg_name
= (caddr_t
)from
;
1249 msg
.msg_namelen
= *fromlen
;
1250 msg
.msg_iov
= &databuffers
;
1252 msg
.msg_control
= (caddr_t
)&ancillary
;
1253 msg
.msg_controllen
= sizeof(ancillary
);
1257 n
= recvmsg(s
, &msg
, 0);
1260 if (errno
!= EWOULDBLOCK
&& numLogMessages
++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned error %d errno %d", s
, n
, errno
);
1263 if (msg
.msg_controllen
< (int)sizeof(struct cmsghdr
))
1265 if (numLogMessages
++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_controllen %d < sizeof(struct cmsghdr) %lu",
1266 s
, msg
.msg_controllen
, sizeof(struct cmsghdr
));
1269 if (msg
.msg_flags
& MSG_CTRUNC
)
1271 if (numLogMessages
++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s
);
1275 *fromlen
= msg
.msg_namelen
;
1277 // Parse each option out of the ancillary data.
1278 for (cmPtr
= CMSG_FIRSTHDR(&msg
); cmPtr
; cmPtr
= CMSG_NXTHDR(&msg
, cmPtr
))
1280 // debugf("myrecvfrom cmsg_level %d cmsg_type %d", cmPtr->cmsg_level, cmPtr->cmsg_type);
1281 if (cmPtr
->cmsg_level
== IPPROTO_IP
&& cmPtr
->cmsg_type
== IP_RECVDSTADDR
)
1283 dstaddr
->type
= mDNSAddrType_IPv4
;
1284 dstaddr
->ip
.v4
.NotAnInteger
= *(u_int32_t
*)CMSG_DATA(cmPtr
);
1286 if (cmPtr
->cmsg_level
== IPPROTO_IP
&& cmPtr
->cmsg_type
== IP_RECVIF
)
1288 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)CMSG_DATA(cmPtr
);
1289 if (sdl
->sdl_nlen
< IF_NAMESIZE
)
1291 mDNSPlatformMemCopy(sdl
->sdl_data
, ifname
, sdl
->sdl_nlen
);
1292 ifname
[sdl
->sdl_nlen
] = 0;
1293 // debugf("IP_RECVIF sdl_index %d, sdl_data %s len %d", sdl->sdl_index, ifname, sdl->sdl_nlen);
1296 if (cmPtr
->cmsg_level
== IPPROTO_IP
&& cmPtr
->cmsg_type
== IP_RECVTTL
)
1298 *ttl
= *(u_char
*)CMSG_DATA(cmPtr
);
1300 if (cmPtr
->cmsg_level
== IPPROTO_IPV6
&& cmPtr
->cmsg_type
== IPV6_PKTINFO
)
1302 struct in6_pktinfo
*ip6_info
= (struct in6_pktinfo
*)CMSG_DATA(cmPtr
);
1303 dstaddr
->type
= mDNSAddrType_IPv6
;
1304 dstaddr
->ip
.v6
= *(mDNSv6Addr
*)&ip6_info
->ipi6_addr
;
1305 myIfIndexToName(ip6_info
->ipi6_ifindex
, ifname
);
1307 if (cmPtr
->cmsg_level
== IPPROTO_IPV6
&& cmPtr
->cmsg_type
== IPV6_HOPLIMIT
)
1309 *ttl
= *(int*)CMSG_DATA(cmPtr
);
1316 // On entry, context points to our CFSocketSet
1317 // If ss->info is NULL, we received this packet on our anonymous unicast socket
1318 // If ss->info is non-NULL, we received this packet on port 5353 on the indicated interface
1319 mDNSlocal
void myCFSocketCallBack(CFSocketRef cfs
, CFSocketCallBackType CallBackType
, CFDataRef address
, const void *data
, void *context
)
1321 mDNSAddr senderAddr
, destAddr
;
1322 mDNSIPPort senderPort
, destPort
= MulticastDNSPort
;
1323 const CFSocketSet
*ss
= (const CFSocketSet
*)context
;
1324 mDNS
*const m
= ss
->m
;
1325 mDNSInterfaceID InterfaceID
= ss
->info
? ss
->info
->ifinfo
.InterfaceID
: mDNSNULL
;
1326 struct sockaddr_storage from
;
1327 size_t fromlen
= sizeof(from
);
1328 char packetifname
[IF_NAMESIZE
] = "";
1329 int err
, s1
= -1, skt
= CFSocketGetNative(cfs
);
1332 (void)address
; // Parameter not used
1333 (void)data
; // Parameter not used
1335 if (CallBackType
!= kCFSocketReadCallBack
)
1336 LogMsg("myCFSocketCallBack: Why is CallBackType %d not kCFSocketReadCallBack?", CallBackType
);
1338 if (cfs
== ss
->cfsv4
) s1
= ss
->sktv4
;
1339 else if (cfs
== ss
->cfsv6
) s1
= ss
->sktv6
;
1341 if (s1
< 0 || s1
!= skt
)
1343 LogMsg("myCFSocketCallBack: s1 %d native socket %d, cfs %p", s1
, skt
, cfs
);
1344 LogMsg("myCFSocketCallBack: cfsv4 %p, sktv4 %d", ss
->cfsv4
, ss
->sktv4
);
1345 LogMsg("myCFSocketCallBack: cfsv6 %p, sktv6 %d", ss
->cfsv6
, ss
->sktv6
);
1349 while ((err
= myrecvfrom(s1
, &m
->imsg
, sizeof(m
->imsg
), (struct sockaddr
*)&from
, &fromlen
, &destAddr
, packetifname
, &ttl
)) >= 0)
1352 if (from
.ss_family
== AF_INET
)
1354 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&from
;
1355 senderAddr
.type
= mDNSAddrType_IPv4
;
1356 senderAddr
.ip
.v4
.NotAnInteger
= sin
->sin_addr
.s_addr
;
1357 senderPort
.NotAnInteger
= sin
->sin_port
;
1359 else if (from
.ss_family
== AF_INET6
)
1361 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)&from
;
1362 senderAddr
.type
= mDNSAddrType_IPv6
;
1363 senderAddr
.ip
.v6
= *(mDNSv6Addr
*)&sin6
->sin6_addr
;
1364 senderPort
.NotAnInteger
= sin6
->sin6_port
;
1368 LogMsg("myCFSocketCallBack from is unknown address family %d", from
.ss_family
);
1372 if (mDNSAddrIsDNSMulticast(&destAddr
))
1374 // Even though we indicated a specific interface in the IP_ADD_MEMBERSHIP call, a weirdness of the
1375 // sockets API means that even though this socket has only officially joined the multicast group
1376 // on one specific interface, the kernel will still deliver multicast packets to it no matter which
1377 // interface they arrive on. According to the official Unix Powers That Be, this is Not A Bug.
1378 // To work around this weirdness, we use the IP_RECVIF option to find the name of the interface
1379 // on which the packet arrived, and ignore the packet if it really arrived on some other interface.
1380 if (!ss
->info
|| !ss
->info
->Exists
)
1382 verbosedebugf("myCFSocketCallBack got multicast packet from %#a to %#a on unicast socket (Ignored)", &senderAddr
, &destAddr
);
1385 else if (!strcmp(ss
->info
->ifa_name
, packetifname
))
1386 verbosedebugf("myCFSocketCallBack got multicast packet from %#a to %#a on interface %#a/%s",
1387 &senderAddr
, &destAddr
, &ss
->info
->ifinfo
.ip
, ss
->info
->ifa_name
);
1390 verbosedebugf("myCFSocketCallBack got multicast packet from %#a to %#a on interface %#a/%s (Ignored -- really arrived on interface %s)",
1391 &senderAddr
, &destAddr
, &ss
->info
->ifinfo
.ip
, ss
->info
->ifa_name
, packetifname
);
1397 // Note: For unicast packets, try to find the matching mDNSCore interface object
1398 // (though we may not be able to, for unicast packets received over something like a PPP link)
1399 NetworkInterfaceInfo
*intf
= m
->HostInterfaces
;
1400 while (intf
&& strcmp(intf
->ifname
, packetifname
)) intf
= intf
->next
;
1401 if (intf
) InterfaceID
= intf
->InterfaceID
;
1404 mDNSCoreReceive(m
, &m
->imsg
, (unsigned char*)&m
->imsg
+ err
, &senderAddr
, senderPort
, &destAddr
, destPort
, InterfaceID
);
1407 if (err
< 0 && (errno
!= EWOULDBLOCK
|| count
== 0))
1409 // Something is busted here.
1410 // CFSocket says there is a packet, but myrecvfrom says there is not.
1411 // Try calling select() to get another opinion.
1412 // Find out about other socket parameter that can help understand why select() says the socket is ready for read
1413 // All of this is racy, as data may have arrived after the call to select()
1414 int save_errno
= errno
;
1418 int solen
= sizeof(int);
1421 FD_SET(s1
, &readfds
);
1422 struct timeval timeout
;
1424 timeout
.tv_usec
= 0;
1425 int selectresult
= select(s1
+1, &readfds
, NULL
, NULL
, &timeout
);
1426 if (getsockopt(s1
, SOL_SOCKET
, SO_ERROR
, &so_error
, &solen
) == -1)
1427 LogMsg("myCFSocketCallBack getsockopt(SO_ERROR) error %d", errno
);
1428 if (getsockopt(s1
, SOL_SOCKET
, SO_NREAD
, &so_nread
, &solen
) == -1)
1429 LogMsg("myCFSocketCallBack getsockopt(SO_NREAD) error %d", errno
);
1430 if (ioctl(s1
, FIONREAD
, &fionread
) == -1)
1431 LogMsg("myCFSocketCallBack ioctl(FIONREAD) error %d", errno
);
1432 static unsigned int numLogMessages
= 0;
1433 if (numLogMessages
++ < 100)
1434 LogMsg("myCFSocketCallBack recvfrom skt %d error %d errno %d (%s) select %d (%spackets waiting) so_error %d so_nread %d fionread %d count %d",
1435 s1
, err
, save_errno
, strerror(save_errno
), selectresult
, FD_ISSET(s1
, &readfds
) ? "" : "*NO* ", so_error
, so_nread
, fionread
, count
);
1436 if (numLogMessages
> 5)
1437 NotifyOfElusiveBug("Flaw in Kernel (select/recvfrom mismatch)", 3375328,
1438 "Alternatively, you can send email to radar-3387020@group.apple.com. "
1439 "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
1441 sleep(1); // After logging this error, rate limit so we don't flood syslog
1445 // TCP socket support for unicast DNS and Dynamic DNS Update
1449 TCPConnectionCallback callback
;
1454 mDNSlocal
void tcpCFSocketCallback(CFSocketRef cfs
, CFSocketCallBackType CallbackType
, CFDataRef address
,
1455 const void *data
, void *context
)
1457 #pragma unused(CallbackType, address, data)
1458 mDNSBool connect
= mDNSfalse
;
1460 tcpInfo_t
*info
= context
;
1461 if (!info
->connected
)
1464 info
->connected
= mDNStrue
; // prevent connected flag from being set in future callbacks
1466 info
->callback(CFSocketGetNative(cfs
), info
->context
, connect
);
1467 // NOTE: the callback may call CloseConnection here, which frees the context structure!
1470 mDNSexport mStatus
mDNSPlatformTCPConnect(const mDNSAddr
*dst
, mDNSOpaque16 dstport
, mDNSInterfaceID InterfaceID
,
1471 TCPConnectionCallback callback
, void *context
, int *descriptor
)
1473 int sd
, on
= 1; // "on" for setsockopt
1474 struct sockaddr_in saddr
;
1475 CFSocketContext cfContext
= { 0, NULL
, 0, 0, 0 };
1478 CFRunLoopSourceRef rls
;
1480 (void)InterfaceID
; //!!!KRS use this if non-zero!!!
1483 if (dst
->type
!= mDNSAddrType_IPv4
)
1485 LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: opperation not supported");
1486 return mStatus_UnknownErr
;
1489 bzero(&saddr
, sizeof(saddr
));
1490 saddr
.sin_family
= AF_INET
;
1491 saddr
.sin_port
= dstport
.NotAnInteger
;
1492 saddr
.sin_len
= sizeof(saddr
);
1493 memcpy(&saddr
.sin_addr
, &dst
->ip
.v4
.NotAnInteger
, sizeof(saddr
.sin_addr
));
1495 // Don't send if it would cause dial on demand connection initiation.
1496 if (AddrRequiresPPPConnection((struct sockaddr
*)&saddr
))
1498 debugf("mDNSPlatformTCPConnect: Surpressing sending to avoid dial-on-demand connection");
1499 return mStatus_UnknownErr
;
1502 sd
= socket(AF_INET
, SOCK_STREAM
, 0);
1503 if (sd
< 3) { LogMsg("mDNSPlatformTCPConnect: socket error %d errno %d (%s)", sd
, errno
, strerror(errno
)); return mStatus_UnknownErr
; }
1506 if (fcntl(sd
, F_SETFL
, O_NONBLOCK
) < 0)
1508 LogMsg("ERROR: setsockopt O_NONBLOCK - %s", strerror(errno
));
1509 return mStatus_UnknownErr
;
1512 // receive interface identifiers
1513 if (setsockopt(sd
, IPPROTO_IP
, IP_RECVIF
, &on
, sizeof(on
)) < 0)
1515 LogMsg("setsockopt IP_RECVIF - %s", strerror(errno
));
1516 return mStatus_UnknownErr
;
1518 // set up CF wrapper, add to Run Loop
1519 info
= mallocL("mDNSPlatformTCPConnect", sizeof(tcpInfo_t
));
1520 info
->callback
= callback
;
1521 info
->context
= context
;
1522 cfContext
.info
= info
;
1523 sr
= CFSocketCreateWithNative(kCFAllocatorDefault
, sd
, kCFSocketReadCallBack
| kCFSocketConnectCallBack
,
1524 tcpCFSocketCallback
, &cfContext
);
1527 LogMsg("ERROR: mDNSPlatformTCPConnect - CFSocketRefCreateWithNative failed");
1528 freeL("mDNSPlatformTCPConnect", info
);
1529 return mStatus_UnknownErr
;
1532 rls
= CFSocketCreateRunLoopSource(kCFAllocatorDefault
, sr
, 0);
1535 LogMsg("ERROR: mDNSPlatformTCPConnect - CFSocketCreateRunLoopSource failed");
1536 freeL("mDNSPlatformTCPConnect", info
);
1537 return mStatus_UnknownErr
;
1540 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1543 // initiate connection wth peer
1544 if (connect(sd
, (struct sockaddr
*)&saddr
, sizeof(saddr
)) < 0)
1546 if (errno
== EINPROGRESS
)
1548 info
->connected
= 0;
1550 return mStatus_ConnPending
;
1552 LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: %s", strerror(errno
));
1553 freeL("mDNSPlatformTCPConnect", info
);
1554 CFSocketInvalidate(sr
); // Note: Also closes the underlying socket
1555 return mStatus_ConnFailed
;
1557 info
->connected
= 1;
1559 return mStatus_ConnEstablished
;
1562 mDNSexport
void mDNSPlatformTCPCloseConnection(int sd
)
1564 CFSocketContext cfContext
;
1568 if (sd
< 3) LogMsg("mDNSPlatformTCPCloseConnection: ERROR sd %d < 3", sd
);
1570 // Get the CFSocket for the descriptor
1571 sr
= CFSocketCreateWithNative(kCFAllocatorDefault
, sd
, kCFSocketNoCallBack
, NULL
, NULL
);
1572 if (!sr
) { LogMsg("ERROR: mDNSPlatformTCPCloseConnection - CFSocketCreateWithNative returned NULL"); return; }
1574 CFSocketGetContext(sr
, &cfContext
);
1575 if (!cfContext
.info
)
1577 LogMsg("ERROR: mDNSPlatformTCPCloseConnection - could not retreive tcpInfo from socket context");
1581 CFRelease(sr
); // this only releases the copy we allocated with CreateWithNative above
1583 info
= cfContext
.info
;
1585 // Note: MUST NOT close the underlying native BSD socket.
1586 // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately,
1587 // because it first has to unhook the sockets from its select() call, before it can safely close them.
1588 CFSocketInvalidate(sr
);
1590 freeL("mDNSPlatformTCPCloseConnection", info
);
1593 mDNSexport
int mDNSPlatformReadTCP(int sd
, void *buf
, int buflen
)
1595 int nread
= recv(sd
, buf
, buflen
, 0);
1598 if (errno
== EAGAIN
) return 0; // no data available (call would block)
1599 LogMsg("ERROR: mDNSPlatformReadTCP - recv: %s", strerror(errno
));
1605 mDNSexport
int mDNSPlatformWriteTCP(int sd
, const char *msg
, int len
)
1607 int nsent
= send(sd
, msg
, len
, 0);
1611 if (errno
== EAGAIN
) return 0; // blocked
1612 LogMsg("ERROR: mDNSPlatformWriteTCP - sendL %s", strerror(errno
));
1618 // This gets the text of the field currently labelled "Computer Name" in the Sharing Prefs Control Panel
1619 mDNSlocal
void GetUserSpecifiedFriendlyComputerName(domainlabel
*const namelabel
)
1621 CFStringEncoding encoding
= kCFStringEncodingUTF8
;
1622 CFStringRef cfs
= SCDynamicStoreCopyComputerName(NULL
, &encoding
);
1625 CFStringGetPascalString(cfs
, namelabel
->c
, sizeof(*namelabel
), kCFStringEncodingUTF8
);
1630 // This gets the text of the field currently labelled "Local Hostname" in the Sharing Prefs Control Panel
1631 mDNSlocal
void GetUserSpecifiedLocalHostName(domainlabel
*const namelabel
)
1633 CFStringRef cfs
= SCDynamicStoreCopyLocalHostName(NULL
);
1636 CFStringGetPascalString(cfs
, namelabel
->c
, sizeof(*namelabel
), kCFStringEncodingUTF8
);
1641 mDNSlocal mDNSBool
DDNSSettingEnabled(CFDictionaryRef dict
)
1644 CFNumberRef state
= CFDictionaryGetValue(dict
, CFSTR("Enabled"));
1645 if (!state
) return mDNSfalse
;
1646 if (!CFNumberGetValue(state
, kCFNumberSInt32Type
, &val
)) { LogMsg("ERROR: DDNSSettingEnabled - CFNumberGetValue"); return mDNSfalse
; }
1647 return val
? mDNStrue
: mDNSfalse
;
1650 mDNSlocal
void GetUserSpecifiedDDNSConfig(domainname
*const fqdn
, domainname
*const regDomain
, CFArrayRef
*const browseDomains
)
1652 char buf
[MAX_ESCAPED_DOMAIN_NAME
];
1655 regDomain
->c
[0] = 0;
1657 *browseDomains
= NULL
;
1659 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:GetUserSpecifiedDDNSConfig"), NULL
, NULL
);
1662 CFDictionaryRef dict
= SCDynamicStoreCopyValue(store
, CFSTR("Setup:/Network/DynamicDNS"));
1665 CFArrayRef fqdnArray
= CFDictionaryGetValue(dict
, CFSTR("HostNames"));
1668 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
1669 if (fqdnDict
&& DDNSSettingEnabled(fqdnDict
))
1671 CFStringRef name
= CFDictionaryGetValue(fqdnDict
, CFSTR("Domain"));
1674 if (!CFStringGetCString(name
, buf
, sizeof(buf
), kCFStringEncodingUTF8
) ||
1675 !MakeDomainNameFromDNSNameString(fqdn
, buf
) || !fqdn
->c
[0])
1676 LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS host name: %s", buf
[0] ? buf
: "(unknown)");
1677 else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS host name: %s", buf
);
1682 CFArrayRef regArray
= CFDictionaryGetValue(dict
, CFSTR("RegistrationDomains"));
1685 CFDictionaryRef regDict
= CFArrayGetValueAtIndex(regArray
, 0);
1686 if (regDict
&& DDNSSettingEnabled(regDict
))
1688 CFStringRef name
= CFDictionaryGetValue(regDict
, CFSTR("Domain"));
1691 if (!CFStringGetCString(name
, buf
, sizeof(buf
), kCFStringEncodingUTF8
) ||
1692 !MakeDomainNameFromDNSNameString(regDomain
, buf
) || !regDomain
->c
[0])
1693 LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS registration domain: %s", buf
[0] ? buf
: "(unknown)");
1694 else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS registration zone: %s", buf
);
1698 CFArrayRef browseArray
= CFDictionaryGetValue(dict
, CFSTR("BrowseDomains"));
1701 CFRetain(browseArray
);
1702 *browseDomains
= browseArray
;
1710 mDNSlocal
void SetDDNSNameStatus(domainname
*const dname
, mStatus status
)
1712 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:SetDDNSNameStatus"), NULL
, NULL
);
1715 char uname
[MAX_ESCAPED_DOMAIN_NAME
];
1716 ConvertDomainNameToCString(dname
, uname
);
1722 if (!(*(p
+1)) && *p
== '.') *p
= 0; // if last character, strip trailing dot
1726 const void *StatusKey
= CFSTR("Status");
1727 const void *StatusVal
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &status
); // CFNumberRef
1728 const void *StatusDict
= CFDictionaryCreate(NULL
, &StatusKey
, &StatusVal
, 1, NULL
, NULL
);
1730 const void *HostKey
= CFStringCreateWithCString(NULL
, uname
, kCFStringEncodingUTF8
);
1731 const void *HostDict
= CFDictionaryCreate(NULL
, &HostKey
, &StatusDict
, 1, NULL
, NULL
);
1733 const void *StateKey
= CFSTR("HostNames"); // CFStringRef
1734 CFDictionaryRef StateDict
= CFDictionaryCreate(NULL
, &StateKey
, &HostDict
, 1, NULL
, NULL
);
1735 SCDynamicStoreSetValue(store
, CFSTR("State:/Network/DynamicDNS"), StateDict
);
1737 CFRelease(StateDict
);
1738 CFRelease(StateKey
);
1739 CFRelease(HostDict
);
1741 CFRelease(StatusDict
);
1742 CFRelease(StatusVal
);
1743 CFRelease(StatusKey
);
1748 // If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
1749 // If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
1750 mDNSlocal mStatus
SetupSocket(mDNS
*const m
, CFSocketSet
*cp
, mDNSBool mcast
, const mDNSAddr
*ifaddr
, u_short sa_family
)
1752 int *s
= (sa_family
== AF_INET
) ? &cp
->sktv4
: &cp
->sktv6
;
1753 CFSocketRef
*c
= (sa_family
== AF_INET
) ? &cp
->cfsv4
: &cp
->cfsv6
;
1754 CFRunLoopSourceRef
*r
= (sa_family
== AF_INET
) ? &cp
->rlsv4
: &cp
->rlsv6
;
1756 const int twofivefive
= 255;
1757 mStatus err
= mStatus_NoError
;
1758 char *errstr
= mDNSNULL
;
1760 mDNSIPPort port
= (mcast
| m
->CanReceiveUnicastOn5353
) ? MulticastDNSPort
: zeroIPPort
;
1762 if (*s
>= 0) { LogMsg("SetupSocket ERROR: socket %d is already set", *s
); return(-1); }
1763 if (*c
) { LogMsg("SetupSocket ERROR: CFSocketRef %p is already set", *c
); return(-1); }
1765 // Open the socket...
1766 int skt
= socket(sa_family
, SOCK_DGRAM
, IPPROTO_UDP
);
1767 if (skt
< 3) { LogMsg("SetupSocket: socket error %d errno %d (%s)", skt
, errno
, strerror(errno
)); return(skt
); }
1769 // ... with a shared UDP port, if it's for multicast receiving
1770 if (port
.NotAnInteger
) err
= setsockopt(skt
, SOL_SOCKET
, SO_REUSEPORT
, &on
, sizeof(on
));
1771 if (err
< 0) { errstr
= "setsockopt - SO_REUSEPORT"; goto fail
; }
1773 if (sa_family
== AF_INET
)
1775 // We want to receive destination addresses
1776 err
= setsockopt(skt
, IPPROTO_IP
, IP_RECVDSTADDR
, &on
, sizeof(on
));
1777 if (err
< 0) { errstr
= "setsockopt - IP_RECVDSTADDR"; goto fail
; }
1779 // We want to receive interface identifiers
1780 err
= setsockopt(skt
, IPPROTO_IP
, IP_RECVIF
, &on
, sizeof(on
));
1781 if (err
< 0) { errstr
= "setsockopt - IP_RECVIF"; goto fail
; }
1783 // We want to receive packet TTL value so we can check it
1784 err
= setsockopt(skt
, IPPROTO_IP
, IP_RECVTTL
, &on
, sizeof(on
));
1785 // We ignore errors here -- we already know Jaguar doesn't support this, but we can get by without it
1787 // Add multicast group membership on this interface, if it's for multicast receiving
1790 struct in_addr addr
= { ifaddr
->ip
.v4
.NotAnInteger
};
1792 imr
.imr_multiaddr
.s_addr
= AllDNSLinkGroupv4
.NotAnInteger
;
1793 imr
.imr_interface
= addr
;
1794 err
= setsockopt(skt
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
, &imr
, sizeof(imr
));
1795 if (err
< 0) { errstr
= "setsockopt - IP_ADD_MEMBERSHIP"; goto fail
; }
1797 // Specify outgoing interface too
1798 err
= setsockopt(skt
, IPPROTO_IP
, IP_MULTICAST_IF
, &addr
, sizeof(addr
));
1799 if (err
< 0) { errstr
= "setsockopt - IP_MULTICAST_IF"; goto fail
; }
1802 // Send unicast packets with TTL 255
1803 err
= setsockopt(skt
, IPPROTO_IP
, IP_TTL
, &twofivefive
, sizeof(twofivefive
));
1804 if (err
< 0) { errstr
= "setsockopt - IP_TTL"; goto fail
; }
1806 // And multicast packets with TTL 255 too
1807 err
= setsockopt(skt
, IPPROTO_IP
, IP_MULTICAST_TTL
, &twofivefive
, sizeof(twofivefive
));
1808 if (err
< 0) { errstr
= "setsockopt - IP_MULTICAST_TTL"; goto fail
; }
1810 // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
1811 const int ip_tosbits
= IPTOS_LOWDELAY
| IPTOS_THROUGHPUT
;
1812 err
= setsockopt(skt
, IPPROTO_IP
, IP_TOS
, &ip_tosbits
, sizeof(ip_tosbits
));
1813 if (err
< 0) { errstr
= "setsockopt - IP_TOS"; goto fail
; }
1815 // And start listening for packets
1816 struct sockaddr_in listening_sockaddr
;
1817 listening_sockaddr
.sin_family
= AF_INET
;
1818 listening_sockaddr
.sin_port
= port
.NotAnInteger
;
1819 listening_sockaddr
.sin_addr
.s_addr
= 0; // Want to receive multicasts AND unicasts on this socket
1820 err
= bind(skt
, (struct sockaddr
*) &listening_sockaddr
, sizeof(listening_sockaddr
));
1821 if (err
) { errstr
= "bind"; goto fail
; }
1823 else if (sa_family
== AF_INET6
)
1825 // We want to receive destination addresses and receive interface identifiers
1826 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_PKTINFO
, &on
, sizeof(on
));
1827 if (err
< 0) { errstr
= "setsockopt - IPV6_PKTINFO"; goto fail
; }
1829 // We want to receive packet hop count value so we can check it
1830 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_HOPLIMIT
, &on
, sizeof(on
));
1831 if (err
< 0) { errstr
= "setsockopt - IPV6_HOPLIMIT"; goto fail
; }
1833 // We want to receive only IPv6 packets, without this option, we may
1834 // get IPv4 addresses as mapped addresses.
1835 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_V6ONLY
, &on
, sizeof(on
));
1836 if (err
< 0) { errstr
= "setsockopt - IPV6_V6ONLY"; goto fail
; }
1840 // Add multicast group membership on this interface, if it's for multicast receiving
1841 int interface_id
= if_nametoindex(cp
->info
->ifa_name
);
1842 struct ipv6_mreq i6mr
;
1843 i6mr
.ipv6mr_interface
= interface_id
;
1844 i6mr
.ipv6mr_multiaddr
= *(struct in6_addr
*)&AllDNSLinkGroupv6
;
1845 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, &i6mr
, sizeof(i6mr
));
1846 if (err
< 0) { errstr
= "setsockopt - IPV6_JOIN_GROUP"; goto fail
; }
1848 // Specify outgoing interface too
1849 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
, &interface_id
, sizeof(interface_id
));
1850 if (err
< 0) { errstr
= "setsockopt - IPV6_MULTICAST_IF"; goto fail
; }
1853 // Send unicast packets with TTL 255
1854 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, &twofivefive
, sizeof(twofivefive
));
1855 if (err
< 0) { errstr
= "setsockopt - IPV6_UNICAST_HOPS"; goto fail
; }
1857 // And multicast packets with TTL 255 too
1858 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_MULTICAST_HOPS
, &twofivefive
, sizeof(twofivefive
));
1859 if (err
< 0) { errstr
= "setsockopt - IPV6_MULTICAST_HOPS"; goto fail
; }
1861 // Note: IPV6_TCLASS appears not to be implemented on OS X right now (or indeed on ANY version of Unix?)
1863 // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
1864 int tclass
= IPTOS_LOWDELAY
| IPTOS_THROUGHPUT
; // This may not be right (since tclass is not implemented on OS X, I can't test it)
1865 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_TCLASS
, &tclass
, sizeof(tclass
));
1866 if (err
< 0) { errstr
= "setsockopt - IPV6_TCLASS"; goto fail
; }
1869 // Want to receive our own packets
1870 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_MULTICAST_LOOP
, &on
, sizeof(on
));
1871 if (err
< 0) { errstr
= "setsockopt - IPV6_MULTICAST_LOOP"; goto fail
; }
1873 // And start listening for packets
1874 struct sockaddr_in6 listening_sockaddr6
;
1875 bzero(&listening_sockaddr6
, sizeof(listening_sockaddr6
));
1876 listening_sockaddr6
.sin6_len
= sizeof(listening_sockaddr6
);
1877 listening_sockaddr6
.sin6_family
= AF_INET6
;
1878 listening_sockaddr6
.sin6_port
= port
.NotAnInteger
;
1879 listening_sockaddr6
.sin6_flowinfo
= 0;
1880 // listening_sockaddr6.sin6_addr = IN6ADDR_ANY_INIT; // Want to receive multicasts AND unicasts on this socket
1881 listening_sockaddr6
.sin6_scope_id
= 0;
1882 err
= bind(skt
, (struct sockaddr
*) &listening_sockaddr6
, sizeof(listening_sockaddr6
));
1883 if (err
) { errstr
= "bind"; goto fail
; }
1886 fcntl(skt
, F_SETFL
, fcntl(skt
, F_GETFL
, 0) | O_NONBLOCK
); // set non-blocking
1888 CFSocketContext myCFSocketContext
= { 0, cp
, NULL
, NULL
, NULL
};
1889 *c
= CFSocketCreateWithNative(kCFAllocatorDefault
, *s
, kCFSocketReadCallBack
, myCFSocketCallBack
, &myCFSocketContext
);
1890 *r
= CFSocketCreateRunLoopSource(kCFAllocatorDefault
, *c
, 0);
1891 CFRunLoopAddSource(CFRunLoopGetCurrent(), *r
, kCFRunLoopDefaultMode
);
1896 LogMsg("%s error %ld errno %d (%s)", errstr
, err
, errno
, strerror(errno
));
1897 if (!strcmp(errstr
, "bind") && errno
== EADDRINUSE
)
1898 NotifyOfElusiveBug("Setsockopt SO_REUSEPORT failed", 3814904,
1899 "Alternatively, you can send email to radar-3387020@group.apple.com. "
1900 "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
1905 mDNSlocal mStatus
SetupAddr(mDNSAddr
*ip
, const struct sockaddr
*const sa
)
1907 if (!sa
) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid
); }
1909 if (sa
->sa_family
== AF_INET
)
1911 struct sockaddr_in
*ifa_addr
= (struct sockaddr_in
*)sa
;
1912 ip
->type
= mDNSAddrType_IPv4
;
1913 ip
->ip
.v4
.NotAnInteger
= ifa_addr
->sin_addr
.s_addr
;
1914 return(mStatus_NoError
);
1917 if (sa
->sa_family
== AF_INET6
)
1919 struct sockaddr_in6
*ifa_addr
= (struct sockaddr_in6
*)sa
;
1920 ip
->type
= mDNSAddrType_IPv6
;
1921 if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr
->sin6_addr
)) ifa_addr
->sin6_addr
.__u6_addr
.__u6_addr16
[1] = 0;
1922 ip
->ip
.v6
= *(mDNSv6Addr
*)&ifa_addr
->sin6_addr
;
1923 return(mStatus_NoError
);
1926 LogMsg("SetupAddr invalid sa_family %d", sa
->sa_family
);
1927 return(mStatus_Invalid
);
1930 mDNSlocal mDNSEthAddr
GetBSSID(char *ifa_name
)
1932 mDNSEthAddr eth
= zeroEthAddr
;
1933 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:GetBSSID"), NULL
, NULL
);
1936 CFStringRef entityname
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("State:/Network/Interface/%s/AirPort"), ifa_name
);
1939 CFDictionaryRef dict
= SCDynamicStoreCopyValue(store
, entityname
);
1942 CFRange range
= { 0, 6 }; // Offset, length
1943 CFDataRef data
= CFDictionaryGetValue(dict
, CFSTR("BSSID"));
1944 if (data
&& CFDataGetLength(data
) == 6) CFDataGetBytes(data
, range
, eth
.b
);
1947 CFRelease(entityname
);
1954 mDNSlocal NetworkInterfaceInfoOSX
*AddInterfaceToList(mDNS
*const m
, struct ifaddrs
*ifa
, mDNSs32 utc
)
1956 mDNSu32 scope_id
= if_nametoindex(ifa
->ifa_name
);
1957 mDNSEthAddr bssid
= GetBSSID(ifa
->ifa_name
);
1960 if (SetupAddr(&ip
, ifa
->ifa_addr
) != mStatus_NoError
) return(NULL
);
1961 if (SetupAddr(&mask
, ifa
->ifa_netmask
) != mStatus_NoError
) return(NULL
);
1963 NetworkInterfaceInfoOSX
**p
;
1964 for (p
= &m
->p
->InterfaceList
; *p
; p
= &(*p
)->next
)
1965 if (scope_id
== (*p
)->scope_id
&& mDNSSameAddress(&ip
, &(*p
)->ifinfo
.ip
) && mDNSSameEthAddress(&bssid
, &(*p
)->BSSID
))
1967 debugf("AddInterfaceToList: Found existing interface %lu %.6a with address %#a at %p", scope_id
, &bssid
, &ip
, *p
);
1968 (*p
)->Exists
= mDNStrue
;
1972 NetworkInterfaceInfoOSX
*i
= (NetworkInterfaceInfoOSX
*)mallocL("NetworkInterfaceInfoOSX", sizeof(*i
));
1973 debugf("AddInterfaceToList: Making new interface %lu %.6a with address %#a at %p", scope_id
, &bssid
, &ip
, i
);
1974 if (!i
) return(mDNSNULL
);
1975 bzero(i
, sizeof(NetworkInterfaceInfoOSX
));
1976 i
->ifa_name
= (char *)mallocL("NetworkInterfaceInfoOSX name", strlen(ifa
->ifa_name
) + 1);
1977 if (!i
->ifa_name
) { freeL("NetworkInterfaceInfoOSX", i
); return(mDNSNULL
); }
1978 strcpy(i
->ifa_name
, ifa
->ifa_name
);
1980 i
->ifinfo
.InterfaceID
= mDNSNULL
;
1982 i
->ifinfo
.mask
= mask
;
1983 strncpy(i
->ifinfo
.ifname
, ifa
->ifa_name
, sizeof(i
->ifinfo
.ifname
));
1984 i
->ifinfo
.ifname
[sizeof(i
->ifinfo
.ifname
)-1] = 0;
1985 i
->ifinfo
.Advertise
= m
->AdvertiseLocalAddresses
;
1986 i
->ifinfo
.McastTxRx
= mDNSfalse
; // For now; will be set up later at the end of UpdateInterfaceList
1989 i
->Exists
= mDNStrue
;
1991 i
->scope_id
= scope_id
;
1993 i
->sa_family
= ifa
->ifa_addr
->sa_family
;
1994 i
->Multicast
= (ifa
->ifa_flags
& IFF_MULTICAST
) && !(ifa
->ifa_flags
& IFF_POINTOPOINT
);
1998 i
->ss
.sktv4
= i
->ss
.sktv6
= -1;
1999 i
->ss
.cfsv4
= i
->ss
.cfsv6
= NULL
;
2000 i
->ss
.rlsv4
= i
->ss
.rlsv6
= NULL
;
2006 mDNSlocal NetworkInterfaceInfoOSX
*FindRoutableIPv4(mDNS
*const m
, mDNSu32 scope_id
)
2008 NetworkInterfaceInfoOSX
*i
;
2009 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2010 if (i
->Exists
&& i
->scope_id
== scope_id
&& i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
)
2011 if (!(i
->ifinfo
.ip
.ip
.v4
.b
[0] == 169 && i
->ifinfo
.ip
.ip
.v4
.b
[1] == 254))
2016 mDNSlocal mStatus
UpdateInterfaceList(mDNS
*const m
, mDNSs32 utc
)
2018 mDNSBool foundav4
= mDNSfalse
;
2019 mDNSBool foundav6
= mDNSfalse
;
2020 struct ifaddrs
*ifa
= myGetIfAddrs(1);
2021 struct ifaddrs
*v4Loopback
= NULL
;
2022 struct ifaddrs
*v6Loopback
= NULL
;
2023 mDNSEthAddr PrimaryMAC
= zeroEthAddr
;
2024 char defaultname
[32];
2025 int InfoSocket
= socket(AF_INET6
, SOCK_DGRAM
, 0);
2026 if (InfoSocket
< 3) LogMsg("UpdateInterfaceList: InfoSocket error %d errno %d (%s)", InfoSocket
, errno
, strerror(errno
));
2027 if (m
->SleepState
) ifa
= NULL
;
2031 #if LIST_ALL_INTERFACES
2032 if (ifa
->ifa_addr
->sa_family
== AF_APPLETALK
)
2033 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_APPLETALK",
2034 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2035 else if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
2036 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_LINK",
2037 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2038 else if (ifa
->ifa_addr
->sa_family
!= AF_INET
&& ifa
->ifa_addr
->sa_family
!= AF_INET6
)
2039 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)",
2040 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2041 if (!(ifa
->ifa_flags
& IFF_UP
))
2042 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_UP",
2043 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2044 if (!(ifa
->ifa_flags
& IFF_MULTICAST
))
2045 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_MULTICAST",
2046 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2047 if (ifa
->ifa_flags
& IFF_POINTOPOINT
)
2048 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_POINTOPOINT",
2049 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2050 if (ifa
->ifa_flags
& IFF_LOOPBACK
)
2051 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_LOOPBACK",
2052 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2055 if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
2057 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
2058 if (sdl
->sdl_type
== IFT_ETHER
&& sdl
->sdl_alen
== sizeof(PrimaryMAC
) && mDNSSameEthAddress(&PrimaryMAC
, &zeroEthAddr
))
2059 mDNSPlatformMemCopy(sdl
->sdl_data
+ sdl
->sdl_nlen
, PrimaryMAC
.b
, 6);
2062 if (ifa
->ifa_flags
& IFF_UP
&& ifa
->ifa_addr
)
2063 if (ifa
->ifa_addr
->sa_family
== AF_INET
|| ifa
->ifa_addr
->sa_family
== AF_INET6
)
2065 if (!ifa
->ifa_netmask
)
2068 SetupAddr(&ip
, ifa
->ifa_addr
);
2069 LogMsg("getifaddrs: ifa_netmask is NULL for %5s(%d) Flags %04X Family %2d %#a",
2070 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
, &ip
);
2072 else if (ifa
->ifa_addr
->sa_family
!= ifa
->ifa_netmask
->sa_family
)
2075 SetupAddr(&ip
, ifa
->ifa_addr
);
2076 LogMsg("getifaddrs ifa_netmask for %5s(%d) Flags %04X Family %2d %#a has different family: %d",
2077 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
, &ip
, ifa
->ifa_netmask
->sa_family
);
2081 int ifru_flags6
= 0;
2082 if (ifa
->ifa_addr
->sa_family
== AF_INET6
&& InfoSocket
>= 0)
2084 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
2085 struct in6_ifreq ifr6
;
2086 bzero((char *)&ifr6
, sizeof(ifr6
));
2087 strncpy(ifr6
.ifr_name
, ifa
->ifa_name
, sizeof(ifr6
.ifr_name
));
2088 ifr6
.ifr_addr
= *sin6
;
2089 if (ioctl(InfoSocket
, SIOCGIFAFLAG_IN6
, &ifr6
) != -1)
2090 ifru_flags6
= ifr6
.ifr_ifru
.ifru_flags6
;
2091 verbosedebugf("%s %.16a %04X %04X", ifa
->ifa_name
, &sin6
->sin6_addr
, ifa
->ifa_flags
, ifru_flags6
);
2093 if (!(ifru_flags6
& (IN6_IFF_NOTREADY
| IN6_IFF_DETACHED
| IN6_IFF_DEPRECATED
| IN6_IFF_TEMPORARY
)))
2095 if (ifa
->ifa_flags
& IFF_LOOPBACK
)
2096 if (ifa
->ifa_addr
->sa_family
== AF_INET
) v4Loopback
= ifa
;
2097 else v6Loopback
= ifa
;
2100 AddInterfaceToList(m
, ifa
, utc
);
2101 if (ifa
->ifa_addr
->sa_family
== AF_INET
) foundav4
= mDNStrue
;
2102 else foundav6
= mDNStrue
;
2107 ifa
= ifa
->ifa_next
;
2110 // For efficiency, we don't register a loopback interface when other interfaces of that family are available
2111 if (!foundav4
&& v4Loopback
) AddInterfaceToList(m
, v4Loopback
, utc
);
2112 if (!foundav6
&& v6Loopback
) AddInterfaceToList(m
, v6Loopback
, utc
);
2114 // Now the list is complete, set the McastTxRx setting for each interface.
2115 // We always send and receive using IPv4.
2116 // To reduce traffic, we send and receive using IPv6 only on interfaces that have no routable IPv4 address.
2117 // Having a routable IPv4 address assigned is a reasonable indicator of being on a large configured network,
2118 // which means there's a good chance that most or all the other devices on that network should also have v4.
2119 // 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.
2120 // At this time, reducing the packet rate is more important than v6-only devices on a large configured network,
2121 // so we are willing to make that sacrifice.
2122 NetworkInterfaceInfoOSX
*i
;
2123 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2126 mDNSBool txrx
= i
->Multicast
&& ((i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
) || !FindRoutableIPv4(m
, i
->scope_id
));
2127 if (i
->ifinfo
.McastTxRx
!= txrx
)
2129 i
->ifinfo
.McastTxRx
= txrx
;
2130 i
->Exists
= 2; // State change; need to deregister and reregister this interface
2133 if (InfoSocket
>= 0) close(InfoSocket
);
2135 mDNS_snprintf(defaultname
, sizeof(defaultname
), "Macintosh-%02X%02X%02X%02X%02X%02X",
2136 PrimaryMAC
.b
[0], PrimaryMAC
.b
[1], PrimaryMAC
.b
[2], PrimaryMAC
.b
[3], PrimaryMAC
.b
[4], PrimaryMAC
.b
[5]);
2138 // Set up the nice label
2139 domainlabel nicelabel
;
2141 GetUserSpecifiedFriendlyComputerName(&nicelabel
);
2142 if (nicelabel
.c
[0] == 0)
2144 LogMsg("Couldn't read user-specified Computer Name; using default “%s” instead", defaultname
);
2145 MakeDomainLabelFromLiteralString(&nicelabel
, defaultname
);
2148 // Set up the RFC 1034-compliant label
2149 domainlabel hostlabel
;
2151 GetUserSpecifiedLocalHostName(&hostlabel
);
2152 if (hostlabel
.c
[0] == 0)
2154 LogMsg("Couldn't read user-specified local hostname; using default “%s.local” instead", defaultname
);
2155 MakeDomainLabelFromLiteralString(&hostlabel
, defaultname
);
2158 if (SameDomainLabel(m
->p
->usernicelabel
.c
, nicelabel
.c
))
2159 debugf("Usernicelabel (%#s) unchanged since last time; not changing m->nicelabel (%#s)", m
->p
->usernicelabel
.c
, m
->nicelabel
.c
);
2162 debugf("Updating m->nicelabel to %#s", nicelabel
.c
);
2163 m
->p
->usernicelabel
= m
->nicelabel
= nicelabel
;
2166 if (SameDomainLabel(m
->p
->userhostlabel
.c
, hostlabel
.c
))
2167 debugf("Userhostlabel (%#s) unchanged since last time; not changing m->hostlabel (%#s)", m
->p
->userhostlabel
.c
, m
->hostlabel
.c
);
2170 debugf("Updating m->hostlabel to %#s", hostlabel
.c
);
2171 m
->p
->userhostlabel
= m
->hostlabel
= hostlabel
;
2175 return(mStatus_NoError
);
2178 mDNSlocal
int CountMaskBits(mDNSAddr
*mask
)
2180 int i
= 0, bits
= 0;
2181 int bytes
= mask
->type
== mDNSAddrType_IPv4
? 4 : mask
->type
== mDNSAddrType_IPv6
? 16 : 0;
2184 mDNSu8 b
= mask
->ip
.v6
.b
[i
++];
2185 while (b
& 0x80) { bits
++; b
<<= 1; }
2188 while (i
< bytes
) if (mask
->ip
.v6
.b
[i
++]) return(-1);
2192 // returns count of non-link local V4 addresses registered
2193 mDNSlocal
int SetupActiveInterfaces(mDNS
*const m
, mDNSs32 utc
)
2195 NetworkInterfaceInfoOSX
*i
;
2197 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2200 NetworkInterfaceInfo
*n
= &i
->ifinfo
;
2201 NetworkInterfaceInfoOSX
*primary
= SearchForInterfaceByName(m
, i
->ifa_name
, i
->sa_family
);
2202 if (!primary
) LogMsg("SetupActiveInterfaces ERROR! SearchForInterfaceByName didn't find %s", i
->ifa_name
);
2204 if (n
->InterfaceID
&& n
->InterfaceID
!= (mDNSInterfaceID
)primary
) // Sanity check
2206 LogMsg("SetupActiveInterfaces ERROR! n->InterfaceID %p != primary %p", n
->InterfaceID
, primary
);
2207 n
->InterfaceID
= mDNSNULL
;
2210 if (!n
->InterfaceID
)
2212 // NOTE: If n->InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
2213 // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
2214 // If n->InterfaceID is NOT set, then we haven't registered it and we should not try to deregister it
2215 n
->InterfaceID
= (mDNSInterfaceID
)primary
;
2216 // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away.
2217 // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds.
2218 // 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.
2219 mDNSBool flapping
= (utc
- i
->LastSeen
> 0 && utc
- i
->LastSeen
< 60);
2220 mDNS_RegisterInterface(m
, n
, flapping
? mDNSPlatformOneSecond
* 5 : 0);
2221 if (i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
&& (i
->ifinfo
.ip
.ip
.v4
.b
[0] != 169 || i
->ifinfo
.ip
.ip
.v4
.b
[1] != 254)) count
++;
2222 LogOperation("SetupActiveInterfaces: Registered %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s",
2223 i
->ifa_name
, i
->scope_id
, &i
->BSSID
, primary
, &n
->ip
, CountMaskBits(&n
->mask
),
2224 flapping
? " (Flapping)" : "", n
->InterfaceActive
? " (Primary)" : "");
2228 debugf("SetupActiveInterfaces: No Tx/Rx on %5s(%lu) %.6a InterfaceID %p %#a", i
->ifa_name
, i
->scope_id
, &i
->BSSID
, primary
, &n
->ip
);
2231 if (i
->sa_family
== AF_INET
&& primary
->ss
.sktv4
== -1)
2233 mStatus err
= SetupSocket(m
, &primary
->ss
, mDNStrue
, &i
->ifinfo
.ip
, AF_INET
);
2234 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
));
2235 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
));
2238 if (i
->sa_family
== AF_INET6
&& primary
->ss
.sktv6
== -1)
2240 mStatus err
= SetupSocket(m
, &primary
->ss
, mDNStrue
, &i
->ifinfo
.ip
, AF_INET6
);
2241 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
));
2242 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
));
2249 mDNSlocal
void MarkAllInterfacesInactive(mDNS
*const m
, mDNSs32 utc
)
2251 NetworkInterfaceInfoOSX
*i
;
2252 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2254 if (i
->Exists
) i
->LastSeen
= utc
;
2255 i
->Exists
= mDNSfalse
;
2259 mDNSlocal
void CloseRunLoopSourceSocket(CFRunLoopSourceRef rls
, CFSocketRef cfs
)
2261 // Note: CFSocketInvalidate also closes the underlying socket for us
2262 // Comments show retain counts (obtained via CFGetRetainCount()) after each call. rls 3 cfs 3
2263 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
); // rls 2 cfs 3
2264 CFRelease(rls
); // rls ? cfs 3
2265 CFSocketInvalidate(cfs
); // rls ? cfs 1
2266 CFRelease(cfs
); // rls ? cfs ?
2269 mDNSlocal
void CloseSocketSet(CFSocketSet
*ss
)
2271 // Note: MUST NOT close the underlying native BSD sockets.
2272 // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately,
2273 // because it first has to unhook the sockets from its select() call, before it can safely close them.
2274 if (ss
->cfsv4
) CloseRunLoopSourceSocket(ss
->rlsv4
, ss
->cfsv4
);
2275 if (ss
->cfsv6
) CloseRunLoopSourceSocket(ss
->rlsv6
, ss
->cfsv6
);
2276 ss
->sktv4
= ss
->sktv6
= -1;
2277 ss
->cfsv4
= ss
->cfsv6
= NULL
;
2278 ss
->rlsv4
= ss
->rlsv6
= NULL
;
2281 // returns count of non-link local V4 addresses deregistered
2282 mDNSlocal
int ClearInactiveInterfaces(mDNS
*const m
, mDNSs32 utc
)
2285 // If an interface is going away, then deregister this from the mDNSCore.
2286 // We also have to deregister it if the primary interface that it's using for its InterfaceID is going away.
2287 // We have to do this because mDNSCore will use that InterfaceID when sending packets, and if the memory
2288 // it refers to has gone away we'll crash.
2289 // Don't actually close the sockets or free the memory yet: When the last representative of an interface goes away
2290 // mDNSCore may want to send goodbye packets on that interface. (Not yet implemented, but a good idea anyway.)
2291 NetworkInterfaceInfoOSX
*i
;
2293 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2295 // 1. If this interface is no longer active, or its InterfaceID is changing, deregister it
2296 NetworkInterfaceInfoOSX
*primary
= SearchForInterfaceByName(m
, i
->ifa_name
, i
->sa_family
);
2297 if (i
->ifinfo
.InterfaceID
)
2298 if (i
->Exists
== 0 || i
->Exists
== 2 || i
->ifinfo
.InterfaceID
!= (mDNSInterfaceID
)primary
)
2300 LogOperation("ClearInactiveInterfaces: Deregistering %5s(%lu) %.6a InterfaceID %p %#a/%d%s",
2301 i
->ifa_name
, i
->scope_id
, &i
->BSSID
, i
->ifinfo
.InterfaceID
,
2302 &i
->ifinfo
.ip
, CountMaskBits(&i
->ifinfo
.mask
), i
->ifinfo
.InterfaceActive
? " (Primary)" : "");
2303 mDNS_DeregisterInterface(m
, &i
->ifinfo
);
2304 if (i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
&& (i
->ifinfo
.ip
.ip
.v4
.b
[0] != 169 || i
->ifinfo
.ip
.ip
.v4
.b
[1] != 254)) count
++;
2305 i
->ifinfo
.InterfaceID
= mDNSNULL
;
2306 // NOTE: If n->InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
2307 // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
2308 // If n->InterfaceID is NOT set, then it's not registered and we should not call mDNS_DeregisterInterface() on it.
2313 // Now that everything that's going to deregister has done so, we can close sockets and free the memory
2314 NetworkInterfaceInfoOSX
**p
= &m
->p
->InterfaceList
;
2318 // 2. Close all our CFSockets. We'll recreate them later as necessary.
2319 // (We may have previously had both v4 and v6, and we may not need both any more.)
2320 CloseSocketSet(&i
->ss
);
2321 // 3. If no longer active, delete interface from list and free memory
2324 if (i
->LastSeen
== utc
) i
->LastSeen
= utc
- 1;
2325 mDNSBool
delete = (NumCacheRecordsForInterfaceID(m
, (mDNSInterfaceID
)i
) == 0) && (utc
- i
->LastSeen
>= 60);
2326 LogOperation("ClearInactiveInterfaces: %-13s %5s(%lu) %.6a InterfaceID %p %#a/%d Age %d%s", delete ? "Deleting" : "Holding",
2327 i
->ifa_name
, i
->scope_id
, &i
->BSSID
, i
->ifinfo
.InterfaceID
,
2328 &i
->ifinfo
.ip
, CountMaskBits(&i
->ifinfo
.mask
), utc
- i
->LastSeen
,
2329 i
->ifinfo
.InterfaceActive
? " (Primary)" : "");
2333 if (i
->ifa_name
) freeL("NetworkInterfaceInfoOSX name", i
->ifa_name
);
2334 freeL("NetworkInterfaceInfoOSX", i
);
2335 continue; // After deleting this object, don't want to do the "p = &i->next;" thing at the end of the loop
2343 mDNSlocal mStatus
GetDNSConfig(void **result
)
2345 #ifndef MAC_OS_X_VERSION_10_4
2346 static int MessageShown
= 0;
2347 if (!MessageShown
) { MessageShown
= 1; LogMsg("Note: Compiled without Apple-specific split DNS support"); }
2349 return mStatus_UnsupportedErr
;
2352 *result
= dns_configuration_copy();
2356 // When running on 10.3 (build 7xxx) and earlier, we don't expect dns_configuration_copy() to succeed
2357 if (mDNSMacOSXSystemBuildNumber(NULL
) < 8) return mStatus_UnsupportedErr
;
2359 // On 10.4, calls to dns_configuration_copy() early in the boot process often fail.
2360 // Apparently this is expected behaviour -- "not a bug".
2361 // Accordingly, we suppress syslog messages for the first three minutes after boot.
2362 // If we are still getting failures after three minutes, then we log them.
2363 if ((mDNSu32
)(mDNSPlatformRawTime()) < (mDNSu32
)(mDNSPlatformOneSecond
* 180)) return mStatus_NoError
;
2365 LogMsg("GetDNSConfig: Error: dns_configuration_copy returned NULL");
2366 return mStatus_UnknownErr
;
2368 return mStatus_NoError
;
2369 #endif // MAC_OS_X_VERSION_10_4
2372 mDNSlocal mStatus
RegisterSplitDNS(mDNS
*m
)
2374 (void)m
; // unused on 10.3 systems
2376 mStatus err
= GetDNSConfig(&v
);
2379 #ifdef MAC_OS_X_VERSION_10_4
2381 dns_config_t
*config
= v
; // use void * to allow compilation on 10.3 systems
2382 mDNS_DeleteDNSServers(m
);
2384 LogOperation("RegisterSplitDNS: Registering %d resolvers", config
->n_resolver
);
2385 for (i
= 0; i
< config
->n_resolver
; i
++)
2389 dns_resolver_t
*r
= config
->resolver
[i
];
2390 if (r
->port
== MulticastDNSPort
.NotAnInteger
) continue; // ignore configurations for .local
2391 if (r
->search_order
== DEFAULT_SEARCH_ORDER
|| !r
->domain
|| !*r
->domain
) d
.c
[0] = 0; // we ignore domain for "default" resolver
2392 else if (!MakeDomainNameFromDNSNameString(&d
, r
->domain
)) { LogMsg("RegisterSplitDNS: bad domain %s", r
->domain
); continue; }
2394 // check if this is the lowest-weighted server for the domain
2395 for (j
= 0; j
< config
->n_resolver
; j
++)
2397 dns_resolver_t
*p
= config
->resolver
[j
];
2398 if (p
->port
== MulticastDNSPort
.NotAnInteger
) continue;
2399 if (p
->search_order
<= r
->search_order
)
2402 if (p
->search_order
== DEFAULT_SEARCH_ORDER
|| !p
->domain
|| !*p
->domain
) tmp
.c
[0] = '\0';
2403 else if (!MakeDomainNameFromDNSNameString(&tmp
, p
->domain
)) { LogMsg("RegisterSplitDNS: bad domain %s", p
->domain
); continue; }
2404 if (SameDomainName(&d
, &tmp
))
2405 if (p
->search_order
< r
->search_order
|| j
< i
) break; // if equal weights, pick first in list, otherwise pick lower-weight (p)
2408 if (j
< config
->n_resolver
) // found a lower-weighted resolver for this domain
2409 { debugf("Rejecting DNS server in slot %d domain %##s (slot %d outranks)", i
, d
.c
, j
); continue; }
2410 // we're using this resolver - find the first IPv4 address
2411 for (n
= 0; n
< r
->n_nameserver
; n
++)
2413 if (r
->nameserver
[n
]->sa_family
== AF_INET
&& !AddrRequiresPPPConnection(r
->nameserver
[n
]))
2416 if (SetupAddr(&saddr
, r
->nameserver
[n
])) { LogMsg("RegisterSplitDNS: bad IP address"); continue; }
2417 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
);
2418 mDNS_AddDNSServer(m
, &saddr
, &d
);
2419 break; // !!!KRS if we ever support round-robin servers, don't break here
2423 dns_configuration_free(config
);
2429 mDNSlocal mStatus
RegisterNameServers(mDNS
*const m
, CFDictionaryRef dict
)
2434 mDNSAddr saddr
= { mDNSAddrType_IPv4
, { { { 0 } } } };
2437 mDNS_DeleteDNSServers(m
); // deregister orig list
2438 values
= CFDictionaryGetValue(dict
, kSCPropNetDNSServerAddresses
);
2439 if (!values
) return mStatus_NoError
;
2441 count
= CFArrayGetCount(values
);
2442 for (i
= 0; i
< count
; i
++)
2444 s
= CFArrayGetValueAtIndex(values
, i
);
2445 if (!s
) { LogMsg("ERROR: RegisterNameServers - CFArrayGetValueAtIndex"); break; }
2446 if (!CFStringGetCString(s
, buf
, 256, kCFStringEncodingUTF8
))
2448 LogMsg("ERROR: RegisterNameServers - CFStringGetCString");
2451 if (!inet_aton(buf
, (struct in_addr
*)saddr
.ip
.v4
.b
))
2453 LogMsg("ERROR: RegisterNameServers - invalid address string %s", buf
);
2456 LogOperation("RegisterNameServers: Adding %#a", &saddr
);
2457 mDNS_AddDNSServer(m
, &saddr
, NULL
);
2459 return mStatus_NoError
;
2462 mDNSlocal
void FreeARElemCallback(mDNS
*const m
, AuthRecord
*const rr
, mStatus result
)
2465 ARListElem
*elem
= rr
->RecordContext
;
2466 if (result
== mStatus_MemFree
) freeL("FreeARElemCallback", elem
);
2469 mDNSlocal
void FoundDomain(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
2471 SearchListElem
*slElem
= question
->QuestionContext
;
2472 ARListElem
*arElem
, *ptr
, *prev
;
2479 arElem
= mallocL("FoundDomain - arElem", sizeof(ARListElem
));
2480 if (!arElem
) { LogMsg("ERROR: malloc"); return; }
2481 mDNS_SetupResourceRecord(&arElem
->ar
, mDNSNULL
, mDNSInterface_LocalOnly
, kDNSType_PTR
, 7200, kDNSRecordTypeShared
, FreeARElemCallback
, arElem
);
2482 if (question
== &slElem
->BrowseQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeBrowse
];
2483 else if (question
== &slElem
->DefBrowseQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeBrowseDefault
];
2484 else if (question
== &slElem
->LegacyBrowseQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeBrowseLegacy
];
2485 else if (question
== &slElem
->RegisterQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeRegistration
];
2486 else if (question
== &slElem
->DefRegisterQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeRegistrationDefault
];
2487 else { LogMsg("FoundDomain - unknown question"); return; }
2489 MakeDomainNameFromDNSNameString(arElem
->ar
.resrec
.name
, name
);
2490 AppendDNSNameString (arElem
->ar
.resrec
.name
, "local");
2491 AssignDomainName(&arElem
->ar
.resrec
.rdata
->u
.name
, &answer
->rdata
->u
.name
);
2492 err
= mDNS_Register(m
, &arElem
->ar
);
2495 LogMsg("ERROR: FoundDomain - mDNS_Register returned %d", err
);
2496 freeL("FoundDomain - arElem", arElem
);
2499 arElem
->next
= slElem
->AuthRecs
;
2500 slElem
->AuthRecs
= arElem
;
2504 ptr
= slElem
->AuthRecs
;
2508 if (SameDomainName(&ptr
->ar
.resrec
.rdata
->u
.name
, &answer
->rdata
->u
.name
))
2510 debugf("Deregistering PTR %s -> %s", ptr
->ar
.resrec
.name
->c
, ptr
->ar
.resrec
.rdata
->u
.name
.c
);
2512 if (prev
) prev
->next
= ptr
->next
;
2513 else slElem
->AuthRecs
= ptr
->next
;
2515 err
= mDNS_Deregister(m
, dereg
);
2516 if (err
) LogMsg("ERROR: FoundDomain - mDNS_Deregister returned %d", err
);
2527 mDNSlocal
void MarkSearchListElem(const char *d
)
2529 SearchListElem
*new, *ptr
;
2532 if (!MakeDomainNameFromDNSNameString(&domain
, d
))
2533 { LogMsg("ERROR: MarkSearchListElem - bad domain %##s", d
); return; }
2535 if (SameDomainName(&domain
, &localdomain
) || SameDomainName(&domain
, &LocalReverseMapomain
))
2536 { debugf("MarkSearchListElem - ignoring local domain %##s", domain
.c
); return; }
2538 // if domain is in list, mark as pre-existent (0)
2539 for (ptr
= SearchList
; ptr
; ptr
= ptr
->next
)
2540 if (SameDomainName(&ptr
->domain
, &domain
))
2542 if (ptr
->flag
!= 1) ptr
->flag
= 0; // gracefully handle duplicates - if it is already marked as add, don't bump down to preexistent
2546 // if domain not in list, add to list, mark as add (1)
2549 new = mallocL("MarkSearchListElem - SearchListElem", sizeof(SearchListElem
));
2550 if (!new) { LogMsg("ERROR: MarkSearchListElem - malloc"); return; }
2551 bzero(new, sizeof(SearchListElem
));
2552 AssignDomainName(&new->domain
, &domain
);
2553 new->flag
= 1; // add
2554 new->next
= SearchList
;
2559 // Get the search domains via OS X resolver routines. Returns mStatus_UnsupporterErr if compiled or run on 10.3 systems
2560 mDNSlocal mStatus
GetSearchDomains(void)
2563 mStatus err
= GetDNSConfig(&v
);
2566 #ifdef MAC_OS_X_VERSION_10_4
2568 dns_config_t
*config
= v
;
2569 if (!config
->n_resolver
) return err
;
2570 dns_resolver_t
*resolv
= config
->resolver
[0]; // use the first slot for search domains
2572 for (i
= 0; i
< resolv
->n_search
; i
++) MarkSearchListElem(resolv
->search
[i
]);
2573 if (resolv
->domain
) MarkSearchListElem(resolv
->domain
);
2574 dns_configuration_free(config
);
2580 // Get search domains from dynamic store - used as a fallback mechanism on 10.3 systems, if GetSearchDomains (above) fails.
2581 mDNSlocal
void GetDSSearchDomains(CFDictionaryRef dict
)
2583 char buf
[MAX_ESCAPED_DOMAIN_NAME
];
2588 // get all the domains from "Search Domains" field of sharing prefs
2591 CFArrayRef searchdomains
= CFDictionaryGetValue(dict
, kSCPropNetDNSSearchDomains
);
2594 count
= CFArrayGetCount(searchdomains
);
2595 for (i
= 0; i
< count
; i
++)
2597 s
= CFArrayGetValueAtIndex(searchdomains
, i
);
2598 if (!s
) { LogMsg("ERROR: GetDSSearchDomains - CFArrayGetValueAtIndex"); break; }
2599 if (!CFStringGetCString(s
, buf
, MAX_ESCAPED_DOMAIN_NAME
, kCFStringEncodingUTF8
))
2601 LogMsg("ERROR: GetDSSearchDomains - CFStringGetCString");
2604 MarkSearchListElem(buf
);
2608 // get DHCP domain field
2609 CFStringRef dname
= CFDictionaryGetValue(dict
, kSCPropNetDNSDomainName
);
2612 if (CFStringGetCString(dname
, buf
, MAX_ESCAPED_DOMAIN_NAME
, kCFStringEncodingUTF8
))
2613 MarkSearchListElem(buf
);
2614 else LogMsg("ERROR: GetDSSearchDomains - CFStringGetCString");
2619 mDNSlocal mStatus
RegisterSearchDomains(mDNS
*const m
, CFDictionaryRef dict
)
2621 struct ifaddrs
*ifa
= NULL
;
2622 SearchListElem
*ptr
, *prev
, *freeSLPtr
;
2626 if (DomainDiscoveryDisabled
) return mStatus_NoError
;
2628 // step 1: mark each elem for removal (-1), unless we aren't passed a dictionary in which case we mark as preexistent
2629 for (ptr
= SearchList
; ptr
; ptr
= ptr
->next
) ptr
->flag
= dict
? -1 : 0;
2631 // Get search domains from resolver library (available in OS X 10.4 and later), reverting to dynamic store on 10.3 systems
2632 if (GetSearchDomains() == mStatus_UnsupportedErr
) GetDSSearchDomains(dict
);
2634 // Construct reverse-map search domains
2635 ifa
= myGetIfAddrs(1);
2639 if (ifa
->ifa_addr
->sa_family
== AF_INET
&& !SetupAddr(&addr
, ifa
->ifa_addr
) && !IsPrivateV4Addr(&addr
) && !(ifa
->ifa_flags
& IFF_LOOPBACK
) && ifa
->ifa_netmask
)
2643 if (!SetupAddr(&netmask
, ifa
->ifa_netmask
))
2645 sprintf(buffer
, "%d.%d.%d.%d.in-addr.arpa.", addr
.ip
.v4
.b
[3] & netmask
.ip
.v4
.b
[3],
2646 addr
.ip
.v4
.b
[2] & netmask
.ip
.v4
.b
[2],
2647 addr
.ip
.v4
.b
[1] & netmask
.ip
.v4
.b
[1],
2648 addr
.ip
.v4
.b
[0] & netmask
.ip
.v4
.b
[0]);
2649 MarkSearchListElem(buffer
);
2652 ifa
= ifa
->ifa_next
;
2655 // delete elems marked for removal, do queries for elems marked add
2660 if (ptr
->flag
== -1) // remove
2662 mDNS_StopQuery(m
, &ptr
->BrowseQ
);
2663 mDNS_StopQuery(m
, &ptr
->RegisterQ
);
2664 mDNS_StopQuery(m
, &ptr
->DefBrowseQ
);
2665 mDNS_StopQuery(m
, &ptr
->DefRegisterQ
);
2666 mDNS_StopQuery(m
, &ptr
->LegacyBrowseQ
);
2668 // deregister records generated from answers to the query
2669 arList
= ptr
->AuthRecs
;
2670 ptr
->AuthRecs
= NULL
;
2673 AuthRecord
*dereg
= &arList
->ar
;
2674 arList
= arList
->next
;
2675 debugf("Deregistering PTR %s -> %s", dereg
->resrec
.name
->c
, dereg
->resrec
.rdata
->u
.name
.c
);
2676 err
= mDNS_Deregister(m
, dereg
);
2677 if (err
) LogMsg("ERROR: RegisterSearchDomains mDNS_Deregister returned %d", err
);
2680 // remove elem from list, delete
2681 if (prev
) prev
->next
= ptr
->next
;
2682 else SearchList
= ptr
->next
;
2685 freeL("RegisterSearchDomains - freeSLPtr", freeSLPtr
);
2689 if (ptr
->flag
== 1) // add
2691 mStatus err1
, err2
, err3
, err4
, err5
;
2692 err1
= mDNS_GetDomains(m
, &ptr
->BrowseQ
, mDNS_DomainTypeBrowse
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2693 err2
= mDNS_GetDomains(m
, &ptr
->DefBrowseQ
, mDNS_DomainTypeBrowseDefault
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2694 err3
= mDNS_GetDomains(m
, &ptr
->RegisterQ
, mDNS_DomainTypeRegistration
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2695 err4
= mDNS_GetDomains(m
, &ptr
->DefRegisterQ
, mDNS_DomainTypeRegistrationDefault
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2696 err5
= mDNS_GetDomains(m
, &ptr
->LegacyBrowseQ
, mDNS_DomainTypeBrowseLegacy
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2697 if (err1
|| err2
|| err3
|| err4
|| err5
)
2698 LogMsg("GetDomains for domain %##s returned error(s):\n"
2699 "%d (mDNS_DomainTypeBrowse)\n"
2700 "%d (mDNS_DomainTypeBrowseDefault)\n"
2701 "%d (mDNS_DomainTypeRegistration)\n"
2702 "%d (mDNS_DomainTypeRegistrationDefault)"
2703 "%d (mDNS_DomainTypeBrowseLegacy)\n",
2704 ptr
->domain
.c
, err1
, err2
, err3
, err4
, err5
);
2708 if (ptr
->flag
) { LogMsg("RegisterSearchDomains - unknown flag %d. Skipping.", ptr
->flag
); }
2714 return mStatus_NoError
;
2717 //!!!KRS here is where we will give success/failure notification to the UI
2718 mDNSlocal
void SCPrefsDynDNSCallback(mDNS
*const m
, AuthRecord
*const rr
, mStatus result
)
2721 debugf("SCPrefsDynDNSCallback: result %d for registration of name %##s", result
, rr
->resrec
.name
->c
);
2722 SetDDNSNameStatus(rr
->resrec
.name
, result
);
2725 mDNSlocal
void SetSecretForDomain(mDNS
*m
, const domainname
*domain
)
2728 SecKeychainRef SysKeychain
= NULL
;
2729 SecKeychainItemRef KeychainItem
;
2730 char dstring
[MAX_ESCAPED_DOMAIN_NAME
];
2732 void *secret
= NULL
;
2733 domainname
*d
, canon
;
2736 // canonicalize name by converting to lower case (keychain and some name servers are case sensitive)
2737 ConvertDomainNameToCString(domain
, dstring
);
2738 dlen
= strlen(dstring
);
2739 for (i
= 0; i
< dlen
; i
++) dstring
[i
] = tolower(dstring
[i
]); // canonicalize -> lower case
2740 MakeDomainNameFromDNSNameString(&canon
, dstring
);
2743 err
= SecKeychainOpen(SYS_KEYCHAIN_PATH
, &SysKeychain
);
2744 if (err
) { LogMsg("SetSecretForDomain: couldn't open system keychain (error %d)", err
); return; }
2745 // find longest-match key ("account") name, excluding last label (e.g. excluding ".com")
2746 while (d
->c
[0] && *(d
->c
+ d
->c
[0] + 1))
2748 if (!ConvertDomainNameToCString(d
, dstring
)) { LogMsg("SetSecretForDomain: bad domain %##s", d
->c
); return; }
2749 dlen
= strlen(dstring
);
2750 if (dstring
[dlen
-1] == '.') { dstring
[dlen
-1] = '\0'; dlen
--; } // chop trailing dot
2751 err
= SecKeychainFindGenericPassword(SysKeychain
, strlen(DYNDNS_KEYCHAIN_SERVICE
), DYNDNS_KEYCHAIN_SERVICE
, dlen
, dstring
, &secretlen
, &secret
, &KeychainItem
);
2754 debugf("Setting shared secret for zone %s with key %##s", dstring
, d
->c
);
2755 mDNS_SetSecretForZone(m
, d
, d
, secret
, secretlen
, mDNStrue
);
2759 if (err
== errSecItemNotFound
) d
= (domainname
*)(d
->c
+ d
->c
[0] + 1);
2762 if (err
== errSecNoSuchKeychain
) debugf("SetSecretForDomain: keychain not found");
2763 else LogMsg("SetSecretForDomain: SecKeychainFindGenericPassword returned error %d", err
);
2769 mDNSlocal
void SetSCPrefsBrowseDomainsFromCFArray(mDNS
*m
, CFArrayRef browseDomains
, mDNSBool add
)
2773 CFIndex count
= CFArrayGetCount(browseDomains
);
2774 CFDictionaryRef browseDict
;
2775 char buf
[MAX_ESCAPED_DOMAIN_NAME
];
2778 for (i
= 0; i
< count
; i
++)
2780 browseDict
= (CFDictionaryRef
)CFArrayGetValueAtIndex(browseDomains
, i
);
2781 if (browseDict
&& DDNSSettingEnabled(browseDict
))
2783 CFStringRef name
= CFDictionaryGetValue(browseDict
, CFSTR("Domain"));
2786 domainname BrowseDomain
;
2787 if (!CFStringGetCString(name
, buf
, sizeof(buf
), kCFStringEncodingUTF8
) || !MakeDomainNameFromDNSNameString(&BrowseDomain
, buf
) || !BrowseDomain
.c
[0])
2788 LogMsg("SetSCPrefsBrowseDomainsFromCFArray SCDynamicStore bad DDNS browse domain: %s", buf
[0] ? buf
: "(unknown)");
2789 else SetSCPrefsBrowseDomain(m
, &BrowseDomain
, add
);
2797 mDNSlocal
void DynDNSConfigChanged(mDNS
*const m
)
2799 static mDNSBool LegacyNATInitialized
= mDNSfalse
;
2800 uDNS_GlobalInfo
*u
= &m
->uDNS_info
;
2801 CFDictionaryRef dict
;
2803 domainname RegDomain
, fqdn
;
2804 CFArrayRef NewBrowseDomains
= NULL
;
2806 // get fqdn, zone from SCPrefs
2807 GetUserSpecifiedDDNSConfig(&fqdn
, &RegDomain
, &NewBrowseDomains
);
2808 ReadDDNSSettingsFromConfFile(m
, CONFIG_FILE
, fqdn
.c
[0] ? NULL
: &fqdn
, RegDomain
.c
[0] ? NULL
: &RegDomain
, &DomainDiscoveryDisabled
);
2810 if (!SameDomainName(&RegDomain
, &DynDNSRegDomain
))
2812 if (DynDNSRegDomain
.c
[0])
2814 RemoveDefRegDomain(&DynDNSRegDomain
);
2815 SetSCPrefsBrowseDomain(m
, &DynDNSRegDomain
, mDNSfalse
); // if we were automatically browsing in our registration domain, stop
2817 AssignDomainName(&DynDNSRegDomain
, &RegDomain
);
2818 if (DynDNSRegDomain
.c
[0])
2820 SetSecretForDomain(m
, &DynDNSRegDomain
);
2821 AddDefRegDomain(&DynDNSRegDomain
);
2822 SetSCPrefsBrowseDomain(m
, &DynDNSRegDomain
, mDNStrue
);
2826 // Add new browse domains to internal list
2827 if (NewBrowseDomains
) SetSCPrefsBrowseDomainsFromCFArray(m
, NewBrowseDomains
, mDNStrue
);
2829 // Remove old browse domains from internal list
2830 if (DynDNSBrowseDomains
)
2832 SetSCPrefsBrowseDomainsFromCFArray(m
, DynDNSBrowseDomains
, mDNSfalse
);
2833 CFRelease(DynDNSBrowseDomains
);
2836 // Replace the old browse domains array with the new array
2837 DynDNSBrowseDomains
= NewBrowseDomains
;
2839 if (!SameDomainName(&fqdn
, &DynDNSHostname
))
2841 if (DynDNSHostname
.c
[0]) mDNS_RemoveDynDNSHostName(m
, &DynDNSHostname
);
2842 AssignDomainName(&DynDNSHostname
, &fqdn
);
2843 if (DynDNSHostname
.c
[0])
2845 SetSecretForDomain(m
, &fqdn
); // no-op if "zone" secret, above, is to be used for hostname
2846 mDNS_AddDynDNSHostName(m
, &DynDNSHostname
, SCPrefsDynDNSCallback
, NULL
);
2847 SetDDNSNameStatus(&DynDNSHostname
, 1);
2852 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:DynDNSConfigChanged"), NULL
, NULL
);
2855 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetDNS
);
2856 if (!key
) { LogMsg("ERROR: DNSConfigChanged - SCDynamicStoreKeyCreateNetworkGlobalEntity"); CFRelease(store
); return; }
2857 dict
= SCDynamicStoreCopyValue(store
, key
);
2860 // handle any changes to search domains and DNS server addresses
2861 if (RegisterSplitDNS(m
) != mStatus_NoError
)
2862 if (dict
) RegisterNameServers(m
, dict
); // fall back to non-split DNS aware configuration on failure
2863 RegisterSearchDomains(m
, dict
); // note that we register name servers *before* search domains
2864 if (dict
) CFRelease(dict
);
2866 // get IPv4 settings
2867 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
,kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
2868 if (!key
) { LogMsg("ERROR: RouterChanged - SCDynamicStoreKeyCreateNetworkGlobalEntity"); CFRelease(store
); return; }
2869 dict
= SCDynamicStoreCopyValue(store
, key
);
2873 { mDNS_SetPrimaryInterfaceInfo(m
, NULL
, NULL
); return; } // lost v4
2875 // handle router changes
2878 r
.type
= mDNSAddrType_IPv4
;
2879 r
.ip
.v4
.NotAnInteger
= 0;
2880 CFStringRef router
= CFDictionaryGetValue(dict
, kSCPropNetIPv4Router
);
2883 struct sockaddr_in saddr
;
2885 if (!CFStringGetCString(router
, buf
, 256, kCFStringEncodingUTF8
))
2886 LogMsg("Could not convert router to CString");
2889 saddr
.sin_len
= sizeof(saddr
);
2890 saddr
.sin_family
= AF_INET
;
2892 inet_aton(buf
, &saddr
.sin_addr
);
2893 if (AddrRequiresPPPConnection((struct sockaddr
*)&saddr
)) { debugf("Ignoring router %s (requires PPP connection)", buf
); }
2894 else *(in_addr_t
*)&r
.ip
.v4
= saddr
.sin_addr
.s_addr
;
2898 // handle primary interface changes
2899 CFStringRef primary
= CFDictionaryGetValue(dict
, kSCDynamicStorePropNetPrimaryInterface
);
2902 struct ifaddrs
*ifa
= myGetIfAddrs(1);
2904 if (!CFStringGetCString(primary
, buf
, 256, kCFStringEncodingUTF8
))
2905 { LogMsg("Could not convert router to CString"); goto error
; }
2907 // find primary interface in list
2910 if (ifa
->ifa_addr
->sa_family
== AF_INET
&& !strcmp(buf
, ifa
->ifa_name
))
2913 SetupAddr(&ip
, ifa
->ifa_addr
);
2914 if (ip
.ip
.v4
.b
[0] == 169 && ip
.ip
.v4
.b
[1] == 254)
2915 { mDNS_SetPrimaryInterfaceInfo(m
, NULL
, NULL
); break; } // primary IP is link-local
2916 if (ip
.ip
.v4
.NotAnInteger
!= u
->PrimaryIP
.ip
.v4
.NotAnInteger
||
2917 r
.ip
.v4
.NotAnInteger
!= u
->Router
.ip
.v4
.NotAnInteger
)
2919 if (LegacyNATInitialized
) { LegacyNATDestroy(); LegacyNATInitialized
= mDNSfalse
; }
2920 if (r
.ip
.v4
.NotAnInteger
&& IsPrivateV4Addr(&ip
))
2922 mStatus err
= LegacyNATInit();
2923 if (err
) LogMsg("ERROR: LegacyNATInit");
2924 else LegacyNATInitialized
= mDNStrue
;
2926 mDNS_SetPrimaryInterfaceInfo(m
, &ip
, r
.ip
.v4
.NotAnInteger
? &r
: NULL
);
2930 ifa
= ifa
->ifa_next
;
2938 mDNSexport
void mDNSMacOSXNetworkChanged(mDNS
*const m
)
2940 LogOperation("*** Network Configuration Change ***");
2941 mDNSs32 utc
= mDNSPlatformUTC();
2942 MarkAllInterfacesInactive(m
, utc
);
2943 UpdateInterfaceList(m
, utc
);
2944 int nDeletions
= ClearInactiveInterfaces(m
, utc
);
2945 int nAdditions
= SetupActiveInterfaces(m
, utc
);
2946 DynDNSConfigChanged(m
); // note - call DynDNSConfigChanged *before* mDNS_UpdateLLQs
2947 if (nDeletions
|| nAdditions
) mDNS_UpdateLLQs(m
); // so that LLQs are restarted against the up to date name servers
2949 if (m
->MainCallback
)
2950 m
->MainCallback(m
, mStatus_ConfigChanged
);
2953 mDNSlocal
void NetworkChanged(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
2955 (void)store
; // Parameter not used
2956 (void)changedKeys
; // Parameter not used
2957 mDNS
*const m
= (mDNS
*const)context
;
2960 mDNSs32 delay
= mDNSPlatformOneSecond
* 2; // Start off assuming a two-second delay
2962 int c
= CFArrayGetCount(changedKeys
); // Count changes
2963 CFRange range
= { 0, c
};
2964 CFStringRef k1
= SCDynamicStoreKeyCreateComputerName(NULL
);
2965 CFStringRef k2
= SCDynamicStoreKeyCreateHostNames(NULL
);
2968 int c1
= (CFArrayContainsValue(changedKeys
, range
, k1
) != 0); // See if ComputerName changed
2969 int c2
= (CFArrayContainsValue(changedKeys
, range
, k2
) != 0); // See if Local Hostname changed
2970 int c3
= (CFArrayContainsValue(changedKeys
, range
, CFSTR("Setup:/Network/DynamicDNS")) != 0);
2971 if (c
&& c
- c1
- c2
- c3
== 0) delay
= mDNSPlatformOneSecond
/10; // If these were the only changes, shorten delay
2973 if (k1
) CFRelease(k1
);
2974 if (k2
) CFRelease(k2
);
2976 LogOperation("*** NetworkChanged *** %d change%s, delay %d", c
, c
>1?"s":"", delay
);
2978 if (!m
->p
->NetworkChanged
||
2979 m
->p
->NetworkChanged
- NonZeroTime(m
->timenow
+ delay
) < 0)
2980 m
->p
->NetworkChanged
= NonZeroTime(m
->timenow
+ delay
);
2982 if (!m
->SuppressSending
||
2983 m
->SuppressSending
- m
->p
->NetworkChanged
< 0)
2984 m
->SuppressSending
= m
->p
->NetworkChanged
;
2988 mDNSlocal mStatus
WatchForNetworkChanges(mDNS
*const m
)
2991 SCDynamicStoreContext context
= { 0, m
, NULL
, NULL
, NULL
};
2992 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:WatchForNetworkChanges"), NetworkChanged
, &context
);
2993 CFStringRef key1
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
2994 CFStringRef key2
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv6
);
2995 CFStringRef key3
= SCDynamicStoreKeyCreateComputerName(NULL
);
2996 CFStringRef key4
= SCDynamicStoreKeyCreateHostNames(NULL
);
2997 CFStringRef key5
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetDNS
);
2998 CFStringRef pattern1
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv4
);
2999 CFStringRef pattern2
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv6
);
3001 CFMutableArrayRef keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3002 CFMutableArrayRef patterns
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3004 if (!store
) { LogMsg("SCDynamicStoreCreate failed: %s", SCErrorString(SCError())); goto error
; }
3005 if (!key1
|| !key2
|| !key3
|| !key4
|| !keys
|| !pattern1
|| !pattern2
|| !patterns
) goto error
;
3007 CFArrayAppendValue(keys
, key1
);
3008 CFArrayAppendValue(keys
, key2
);
3009 CFArrayAppendValue(keys
, key3
);
3010 CFArrayAppendValue(keys
, key4
);
3011 CFArrayAppendValue(keys
, key5
);
3012 CFArrayAppendValue(keys
, CFSTR("Setup:/Network/DynamicDNS"));
3013 CFArrayAppendValue(patterns
, pattern1
);
3014 CFArrayAppendValue(patterns
, pattern2
);
3015 CFArrayAppendValue(patterns
, CFSTR("State:/Network/Interface/[^/]+/AirPort"));
3016 if (!SCDynamicStoreSetNotificationKeys(store
, keys
, patterns
))
3017 { LogMsg("SCDynamicStoreSetNotificationKeys failed: %s", SCErrorString(SCError())); goto error
; }
3019 m
->p
->StoreRLS
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, 0);
3020 if (!m
->p
->StoreRLS
) { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error
; }
3022 CFRunLoopAddSource(CFRunLoopGetCurrent(), m
->p
->StoreRLS
, kCFRunLoopDefaultMode
);
3023 m
->p
->Store
= store
;
3028 if (store
) CFRelease(store
);
3031 if (key1
) CFRelease(key1
);
3032 if (key2
) CFRelease(key2
);
3033 if (key3
) CFRelease(key3
);
3034 if (key4
) CFRelease(key4
);
3035 if (key5
) CFRelease(key5
);
3036 if (pattern1
) CFRelease(pattern1
);
3037 if (pattern2
) CFRelease(pattern2
);
3038 if (keys
) CFRelease(keys
);
3039 if (patterns
) CFRelease(patterns
);
3044 mDNSlocal
void PowerChanged(void *refcon
, io_service_t service
, natural_t messageType
, void *messageArgument
)
3046 mDNS
*const m
= (mDNS
*const)refcon
;
3047 (void)service
; // Parameter not used
3050 case kIOMessageCanSystemPowerOff
: debugf("PowerChanged kIOMessageCanSystemPowerOff (no action)"); break; // E0000240
3051 case kIOMessageSystemWillPowerOff
: debugf("PowerChanged kIOMessageSystemWillPowerOff");
3052 mDNSCoreMachineSleep(m
, true); mDNSMacOSXNetworkChanged(m
); break; // E0000250
3053 case kIOMessageSystemWillNotPowerOff
: debugf("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; // E0000260
3054 case kIOMessageCanSystemSleep
: debugf("PowerChanged kIOMessageCanSystemSleep (no action)"); break; // E0000270
3055 case kIOMessageSystemWillSleep
: debugf("PowerChanged kIOMessageSystemWillSleep");
3056 mDNSCoreMachineSleep(m
, true); mDNSMacOSXNetworkChanged(m
); break; // E0000280
3057 case kIOMessageSystemWillNotSleep
: debugf("PowerChanged kIOMessageSystemWillNotSleep (no action)"); break; // E0000290
3058 case kIOMessageSystemHasPoweredOn
: debugf("PowerChanged kIOMessageSystemHasPoweredOn");
3059 // If still sleeping (didn't get 'WillPowerOn' message for some reason?) wake now
3060 if (m
->SleepState
) mDNSCoreMachineSleep(m
, false);
3061 // Just to be safe, also make sure our interface list is fully up to date, in case we
3062 // haven't yet received the System Configuration Framework "network changed" event that
3063 // we expect to receive some time shortly after the kIOMessageSystemWillPowerOn message
3064 mDNSMacOSXNetworkChanged(m
); break; // E0000300
3065 case kIOMessageSystemWillRestart
: debugf("PowerChanged kIOMessageSystemWillRestart (no action)"); break; // E0000310
3066 case kIOMessageSystemWillPowerOn
: debugf("PowerChanged kIOMessageSystemWillPowerOn");
3067 // Make sure our interface list is cleared to the empty state, then tell mDNSCore to wake
3068 mDNSMacOSXNetworkChanged(m
); mDNSCoreMachineSleep(m
, false); break; // E0000320
3069 default: debugf("PowerChanged unknown message %X", messageType
); break;
3071 IOAllowPowerChange(m
->p
->PowerConnection
, (long)messageArgument
);
3074 mDNSlocal mStatus
WatchForPowerChanges(mDNS
*const m
)
3076 IONotificationPortRef thePortRef
;
3077 m
->p
->PowerConnection
= IORegisterForSystemPower(m
, &thePortRef
, PowerChanged
, &m
->p
->PowerNotifier
);
3078 if (m
->p
->PowerConnection
)
3080 m
->p
->PowerRLS
= IONotificationPortGetRunLoopSource(thePortRef
);
3081 CFRunLoopAddSource(CFRunLoopGetCurrent(), m
->p
->PowerRLS
, kCFRunLoopDefaultMode
);
3082 return(mStatus_NoError
);
3087 CF_EXPORT CFDictionaryRef
_CFCopySystemVersionDictionary(void);
3088 CF_EXPORT
const CFStringRef _kCFSystemVersionProductNameKey
;
3089 CF_EXPORT
const CFStringRef _kCFSystemVersionProductVersionKey
;
3090 CF_EXPORT
const CFStringRef _kCFSystemVersionBuildVersionKey
;
3092 mDNSexport
int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring
)
3094 int major
= 0, minor
= 0;
3095 char letter
= 0, prodname
[256]="Mac OS X", prodvers
[256]="", buildver
[256]="?";
3096 CFDictionaryRef vers
= _CFCopySystemVersionDictionary();
3099 CFStringRef cfprodname
= CFDictionaryGetValue(vers
, _kCFSystemVersionProductNameKey
);
3100 CFStringRef cfprodvers
= CFDictionaryGetValue(vers
, _kCFSystemVersionProductVersionKey
);
3101 CFStringRef cfbuildver
= CFDictionaryGetValue(vers
, _kCFSystemVersionBuildVersionKey
);
3102 if (cfprodname
) CFStringGetCString(cfprodname
, prodname
, sizeof(prodname
), kCFStringEncodingUTF8
);
3103 if (cfprodvers
) CFStringGetCString(cfprodvers
, prodvers
, sizeof(prodvers
), kCFStringEncodingUTF8
);
3104 if (cfbuildver
) CFStringGetCString(cfbuildver
, buildver
, sizeof(buildver
), kCFStringEncodingUTF8
);
3105 sscanf(buildver
, "%d%c%d", &major
, &letter
, &minor
);
3108 if (HINFO_SWstring
) mDNS_snprintf(HINFO_SWstring
, 256, "%s %s (%s), %s", prodname
, prodvers
, buildver
, mDNSResponderVersionString
);
3112 // Test to see if we're the first client running on UDP port 5353, by trying to bind to 5353 without using SO_REUSEPORT.
3113 // If we fail, someone else got here first. That's not a big problem; we can share the port for multicast responses --
3114 // we just need to be aware that we shouldn't expect to successfully receive unicast UDP responses.
3115 mDNSlocal mDNSBool
mDNSPlatformInit_CanReceiveUnicast(void)
3118 int s
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
3120 LogMsg("mDNSPlatformInit_CanReceiveUnicast: socket error %d errno %d (%s)", s
, errno
, strerror(errno
));
3123 struct sockaddr_in s5353
;
3124 s5353
.sin_family
= AF_INET
;
3125 s5353
.sin_port
= MulticastDNSPort
.NotAnInteger
;
3126 s5353
.sin_addr
.s_addr
= 0;
3127 err
= bind(s
, (struct sockaddr
*)&s5353
, sizeof(s5353
));
3131 if (err
) LogMsg("No unicast UDP responses");
3132 else debugf("Unicast UDP responses okay");
3136 // Callback for the _legacy._browse queries - add answer to list of domains to search for empty-string browses
3137 mDNSlocal
void FoundLegacyBrowseDomain(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
3139 DNameListElem
*ptr
, *prev
, *new;
3141 (void)question
; // unused
3143 LogMsg("%s browse domain %##s", AddRecord
? "Adding" : "Removing", answer
->rdata
->u
.name
.c
);
3147 new = mallocL("FoundLegacyBrowseDomain", sizeof(DNameListElem
));
3148 if (!new) { LogMsg("ERROR: malloc"); return; }
3149 AssignDomainName(&new->name
, &answer
->rdata
->u
.name
);
3150 new->next
= DefBrowseList
;
3151 DefBrowseList
= new;
3152 DefaultBrowseDomainChanged(&new->name
, mDNStrue
);
3153 udsserver_default_browse_domain_changed(&new->name
, mDNStrue
);
3158 ptr
= DefBrowseList
;
3162 if (SameDomainName(&ptr
->name
, &answer
->rdata
->u
.name
))
3164 DefaultBrowseDomainChanged(&ptr
->name
, mDNSfalse
);
3165 udsserver_default_browse_domain_changed(&ptr
->name
, mDNSfalse
);
3166 if (prev
) prev
->next
= ptr
->next
;
3167 else DefBrowseList
= ptr
->next
;
3168 freeL("FoundLegacyBrowseDomain", ptr
);
3174 LogMsg("FoundLegacyBrowseDomain: Got remove event for domain %s not in list", answer
->rdata
->u
.name
.c
);
3178 mDNSlocal
void RegisterBrowseDomainPTR(mDNS
*m
, const domainname
*d
, int type
)
3180 // allocate/register legacy and non-legacy _browse PTR record
3181 ARListElem
*browse
= mallocL("ARListElem", sizeof(*browse
));
3182 mDNS_SetupResourceRecord(&browse
->ar
, mDNSNULL
, mDNSInterface_LocalOnly
, kDNSType_PTR
, 7200, kDNSRecordTypeShared
, FreeARElemCallback
, browse
);
3183 MakeDomainNameFromDNSNameString(browse
->ar
.resrec
.name
, mDNS_DomainTypeNames
[type
]);
3184 AppendDNSNameString (browse
->ar
.resrec
.name
, "local");
3185 AssignDomainName(&browse
->ar
.resrec
.rdata
->u
.name
, d
);
3186 mStatus err
= mDNS_Register(m
, &browse
->ar
);
3189 LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err
);
3190 freeL("ARListElem", browse
);
3194 browse
->next
= SCPrefBrowseDomains
;
3195 SCPrefBrowseDomains
= browse
;
3199 mDNSlocal
void DeregisterBrowseDomainPTR(mDNS
*m
, const domainname
*d
, int type
)
3201 ARListElem
*remove
, **ptr
= &SCPrefBrowseDomains
;
3202 domainname lhs
; // left-hand side of PTR, for comparison
3204 MakeDomainNameFromDNSNameString(&lhs
, mDNS_DomainTypeNames
[type
]);
3205 AppendDNSNameString (&lhs
, "local");
3209 if (SameDomainName(&(*ptr
)->ar
.resrec
.rdata
->u
.name
, d
) && SameDomainName((*ptr
)->ar
.resrec
.name
, &lhs
))
3212 *ptr
= (*ptr
)->next
;
3213 mDNS_Deregister(m
, &remove
->ar
);
3216 else ptr
= &(*ptr
)->next
;
3220 // Add or remove a user-specified domain to the list of empty-string browse domains
3221 // Also register a non-legacy _browse PTR record so that the domain appears in enumeration lists
3222 mDNSlocal
void SetSCPrefsBrowseDomain(mDNS
*m
, const domainname
*d
, mDNSBool add
)
3224 debugf("SetSCPrefsBrowseDomain: %s default browse domain %##s", add
? "Adding" : "Removing", d
->c
);
3228 RegisterBrowseDomainPTR(m
, d
, mDNS_DomainTypeBrowse
);
3229 RegisterBrowseDomainPTR(m
, d
, mDNS_DomainTypeBrowseLegacy
);
3233 DeregisterBrowseDomainPTR(m
, d
, mDNS_DomainTypeBrowse
);
3234 DeregisterBrowseDomainPTR(m
, d
, mDNS_DomainTypeBrowseLegacy
);
3238 // Construction of Default Browse domain list (i.e. when clients pass NULL) is as follows:
3239 // 1) query for b._dns-sd._udp.local on LocalOnly interface
3240 // (.local manually generated via explicit callback)
3241 // 2) for each search domain (from prefs pane), query for b._dns-sd._udp.<searchdomain>.
3242 // 3) for each result from (2), register LocalOnly PTR record b._dns-sd._udp.local. -> <result>
3243 // 4) result above should generate a callback from question in (1). result added to global list
3244 // 5) global list delivered to client via GetSearchDomainList()
3245 // 6) client calls to enumerate domains now go over LocalOnly interface
3246 // (!!!KRS may add outgoing interface in addition)
3248 mDNSlocal mStatus
InitDNSConfig(mDNS
*const m
)
3251 static AuthRecord LocalRegPTR
;
3253 // start query for domains to be used in default (empty string domain) browses
3254 err
= mDNS_GetDomains(m
, &LegacyBrowseDomainQ
, mDNS_DomainTypeBrowseLegacy
, NULL
, mDNSInterface_LocalOnly
, FoundLegacyBrowseDomain
, NULL
);
3256 // provide browse domain "local" automatically
3257 SetSCPrefsBrowseDomain(m
, &localdomain
, mDNStrue
);
3259 // register registration domain "local"
3260 mDNS_SetupResourceRecord(&LocalRegPTR
, mDNSNULL
, mDNSInterface_LocalOnly
, kDNSType_PTR
, 7200, kDNSRecordTypeShared
, NULL
, NULL
);
3261 MakeDomainNameFromDNSNameString(LocalRegPTR
.resrec
.name
, mDNS_DomainTypeNames
[mDNS_DomainTypeRegistration
]);
3262 AppendDNSNameString (LocalRegPTR
.resrec
.name
, "local");
3263 AssignDomainName(&LocalRegPTR
.resrec
.rdata
->u
.name
, &localdomain
);
3264 err
= mDNS_Register(m
, &LocalRegPTR
);
3265 if (err
) LogMsg("ERROR: InitDNSConfig - mDNS_Register returned error %d", err
);
3267 return mStatus_NoError
;
3270 mDNSlocal mStatus
mDNSPlatformInit_setup(mDNS
*const m
)
3272 // In 10.4, mDNSResponder is launched very early in the boot process, while other subsystems are still in the process of starting up.
3273 // 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.
3275 for (i
=0; i
<100; i
++)
3277 domainlabel testlabel
;
3279 GetUserSpecifiedLocalHostName(&testlabel
);
3280 if (testlabel
.c
[0]) break;
3286 m
->hostlabel
.c
[0] = 0;
3288 char *HINFO_HWstring
= "Macintosh";
3289 char HINFO_HWstring_buffer
[256];
3290 int get_model
[2] = { CTL_HW
, HW_MODEL
};
3291 size_t len_model
= sizeof(HINFO_HWstring_buffer
);
3292 if (sysctl(get_model
, 2, HINFO_HWstring_buffer
, &len_model
, NULL
, 0) == 0)
3293 HINFO_HWstring
= HINFO_HWstring_buffer
;
3295 char HINFO_SWstring
[256] = "";
3296 if (mDNSMacOSXSystemBuildNumber(HINFO_SWstring
) < 7) m
->KnownBugs
|= mDNS_KnownBug_PhantomInterfaces
;
3297 if (mDNSPlatformInit_CanReceiveUnicast()) m
->CanReceiveUnicastOn5353
= mDNStrue
;
3299 mDNSu32 hlen
= mDNSPlatformStrLen(HINFO_HWstring
);
3300 mDNSu32 slen
= mDNSPlatformStrLen(HINFO_SWstring
);
3301 if (hlen
+ slen
< 254)
3303 m
->HIHardware
.c
[0] = hlen
;
3304 m
->HISoftware
.c
[0] = slen
;
3305 mDNSPlatformMemCopy(HINFO_HWstring
, &m
->HIHardware
.c
[1], hlen
);
3306 mDNSPlatformMemCopy(HINFO_SWstring
, &m
->HISoftware
.c
[1], slen
);
3309 m
->p
->unicastsockets
.m
= m
;
3310 m
->p
->unicastsockets
.info
= NULL
;
3311 m
->p
->unicastsockets
.sktv4
= m
->p
->unicastsockets
.sktv6
= -1;
3312 m
->p
->unicastsockets
.cfsv4
= m
->p
->unicastsockets
.cfsv6
= NULL
;
3313 m
->p
->unicastsockets
.rlsv4
= m
->p
->unicastsockets
.rlsv6
= NULL
;
3315 err
= SetupSocket(m
, &m
->p
->unicastsockets
, mDNSfalse
, &zeroAddr
, AF_INET
);
3316 err
= SetupSocket(m
, &m
->p
->unicastsockets
, mDNSfalse
, &zeroAddr
, AF_INET6
);
3318 struct sockaddr_in s4
;
3319 struct sockaddr_in6 s6
;
3320 int n4
= sizeof(s4
);
3321 int n6
= sizeof(s6
);
3322 if (getsockname(m
->p
->unicastsockets
.sktv4
, (struct sockaddr
*)&s4
, &n4
) < 0) LogMsg("getsockname v4 error %d (%s)", errno
, strerror(errno
));
3323 else m
->UnicastPort4
.NotAnInteger
= s4
.sin_port
;
3324 if (getsockname(m
->p
->unicastsockets
.sktv6
, (struct sockaddr
*)&s6
, &n6
) < 0) LogMsg("getsockname v6 error %d (%s)", errno
, strerror(errno
));
3325 else m
->UnicastPort6
.NotAnInteger
= s6
.sin6_port
;
3327 m
->p
->InterfaceList
= mDNSNULL
;
3328 m
->p
->userhostlabel
.c
[0] = 0;
3329 m
->p
->usernicelabel
.c
[0] = 0;
3330 m
->p
->NotifyUser
= 0;
3331 mDNSs32 utc
= mDNSPlatformUTC();
3332 UpdateInterfaceList(m
, utc
);
3333 SetupActiveInterfaces(m
, utc
);
3335 err
= WatchForNetworkChanges(m
);
3336 if (err
) return(err
);
3338 err
= WatchForPowerChanges(m
);
3339 if (err
) return err
;
3341 DynDNSRegDomain
.c
[0] = '\0';
3342 DynDNSConfigChanged(m
); // Get initial DNS configuration
3348 mDNSexport mStatus
mDNSPlatformInit(mDNS
*const m
)
3350 mStatus result
= mDNSPlatformInit_setup(m
);
3352 // We don't do asynchronous initialization on OS X, so by the time we get here the setup will already
3353 // have succeeded or failed -- so if it succeeded, we should just call mDNSCoreInitComplete() immediately
3354 if (result
== mStatus_NoError
) mDNSCoreInitComplete(m
, mStatus_NoError
);
3358 mDNSexport
void mDNSPlatformClose(mDNS
*const m
)
3360 if (m
->p
->PowerConnection
)
3362 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m
->p
->PowerRLS
, kCFRunLoopDefaultMode
);
3363 CFRunLoopSourceInvalidate(m
->p
->PowerRLS
);
3364 CFRelease(m
->p
->PowerRLS
);
3365 IODeregisterForSystemPower(&m
->p
->PowerNotifier
);
3366 m
->p
->PowerConnection
= 0;
3367 m
->p
->PowerNotifier
= 0;
3368 m
->p
->PowerRLS
= NULL
;
3373 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m
->p
->StoreRLS
, kCFRunLoopDefaultMode
);
3374 CFRunLoopSourceInvalidate(m
->p
->StoreRLS
);
3375 CFRelease(m
->p
->StoreRLS
);
3376 CFRelease(m
->p
->Store
);
3378 m
->p
->StoreRLS
= NULL
;
3381 mDNSs32 utc
= mDNSPlatformUTC();
3382 MarkAllInterfacesInactive(m
, utc
);
3383 ClearInactiveInterfaces(m
, utc
);
3384 CloseSocketSet(&m
->p
->unicastsockets
);
3387 mDNSexport mDNSu32
mDNSPlatformRandomSeed(void)
3389 return(mach_absolute_time());
3392 mDNSexport mDNSs32 mDNSPlatformOneSecond
= 1000;
3394 mDNSexport mStatus
mDNSPlatformTimeInit(void)
3396 // Notes: Typical values for mach_timebase_info:
3397 // tbi.numer = 1000 million
3398 // tbi.denom = 33 million
3399 // These are set such that (mach_absolute_time() * numer/denom) gives us nanoseconds;
3400 // numer / denom = nanoseconds per hardware clock tick (e.g. 30);
3401 // denom / numer = hardware clock ticks per nanosecond (e.g. 0.033)
3402 // (denom*1000000) / numer = hardware clock ticks per millisecond (e.g. 33333)
3403 // So: mach_absolute_time() / ((denom*1000000)/numer) = milliseconds
3405 // Arithmetic notes:
3406 // tbi.denom is at least 1, and not more than 2^32-1.
3407 // Therefore (tbi.denom * 1000000) is at least one million, but cannot overflow a uint64_t.
3408 // tbi.denom is at least 1, and not more than 2^32-1.
3409 // Therefore clockdivisor should end up being a number roughly in the range 10^3 - 10^9.
3410 // If clockdivisor is less than 10^3 then that means that the native clock frequency is less than 1MHz,
3411 // which is unlikely on any current or future Macintosh.
3412 // If clockdivisor is greater than 10^9 then that means the native clock frequency is greater than 1000GHz.
3413 // When we ship Macs with clock frequencies above 1000GHz, we may have to update this code.
3414 struct mach_timebase_info tbi
;
3415 kern_return_t result
= mach_timebase_info(&tbi
);
3416 if (result
== KERN_SUCCESS
) clockdivisor
= ((uint64_t)tbi
.denom
* 1000000) / tbi
.numer
;
3420 mDNSexport mDNSs32
mDNSPlatformRawTime(void)
3422 if (clockdivisor
== 0) { LogMsg("mDNSPlatformRawTime called before mDNSPlatformTimeInit"); return(0); }
3424 static uint64_t last_mach_absolute_time
= 0;
3425 uint64_t this_mach_absolute_time
= mach_absolute_time();
3426 if ((int64_t)this_mach_absolute_time
- (int64_t)last_mach_absolute_time
< 0)
3428 LogMsg("mDNSPlatformRawTime: last_mach_absolute_time %08X%08X", last_mach_absolute_time
);
3429 LogMsg("mDNSPlatformRawTime: this_mach_absolute_time %08X%08X", this_mach_absolute_time
);
3430 // Update last_mach_absolute_time *before* calling NotifyOfElusiveBug()
3431 last_mach_absolute_time
= this_mach_absolute_time
;
3432 // Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xxx) or later
3433 if (mDNSMacOSXSystemBuildNumber(NULL
) >= 8)
3434 NotifyOfElusiveBug("mach_absolute_time went backwards!", 3438376, "");
3436 last_mach_absolute_time
= this_mach_absolute_time
;
3438 return((mDNSs32
)(this_mach_absolute_time
/ clockdivisor
));
3441 mDNSexport mDNSs32
mDNSPlatformUTC(void)
3446 // Locking is a no-op here, because we're single-threaded with a CFRunLoop, so we can never interrupt ourselves
3447 mDNSexport
void mDNSPlatformLock (const mDNS
*const m
) { (void)m
; }
3448 mDNSexport
void mDNSPlatformUnlock (const mDNS
*const m
) { (void)m
; }
3449 mDNSexport
void mDNSPlatformStrCopy(const void *src
, void *dst
) { strcpy((char *)dst
, (char *)src
); }
3450 mDNSexport mDNSu32
mDNSPlatformStrLen (const void *src
) { return(strlen((char*)src
)); }
3451 mDNSexport
void mDNSPlatformMemCopy(const void *src
, void *dst
, mDNSu32 len
) { memcpy(dst
, src
, len
); }
3452 mDNSexport mDNSBool
mDNSPlatformMemSame(const void *src
, const void *dst
, mDNSu32 len
) { return(memcmp(dst
, src
, len
) == 0); }
3453 mDNSexport
void mDNSPlatformMemZero( void *dst
, mDNSu32 len
) { bzero(dst
, len
); }
3454 mDNSexport
void * mDNSPlatformMemAllocate(mDNSu32 len
) { return(mallocL("mDNSPlatformMemAllocate", len
)); }
3455 mDNSexport
void mDNSPlatformMemFree (void *mem
) { freeL("mDNSPlatformMemFree", mem
); }