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.308 2005/03/09 00:48:44 cheshire
28 <rdar://problem/4015157> QU packets getting sent too early on wake from sleep
29 Move "m->p->NetworkChanged = 0;" line from caller to callee
31 Revision 1.307 2005/03/03 03:12:02 cheshire
32 Add comment about mDNSMacOSXSystemBuildNumber()
34 Revision 1.306 2005/03/02 22:18:00 cheshire
35 <rdar://problem/3930171> mDNSResponder requires AppleInternal packages to build on Tiger
37 Revision 1.305 2005/02/26 05:08:28 cheshire
38 <rdar://problem/3930171> mDNSResponder requires AppleInternal packages to build on Tiger
39 Added dnsinfo.h to project directory
41 Revision 1.304 2005/02/25 23:51:22 cheshire
42 <rdar://problem/4021868> SendServiceRegistration fails on wake from sleep
43 Return mStatus_UnknownErr instead of -1
45 Revision 1.303 2005/02/25 17:47:45 ksekar
46 <rdar://problem/4021868> SendServiceRegistration fails on wake from sleep
48 Revision 1.302 2005/02/25 02:34:14 cheshire
49 <rdar://problem/4017292> Should not indicate successful dynamic update if no network connection
50 Show status as 1 (in progress) while we're trying
52 Revision 1.301 2005/02/24 21:55:57 ksekar
53 <rdar://problem/4017292> Should not indicate successful dynamic update if no network connection
55 Revision 1.300 2005/02/15 20:03:13 ksekar
56 <rdar://problem/4005868> Crash when SCPreferences contains empty array
58 Revision 1.299 2005/02/15 02:46:53 cheshire
59 <rdar://problem/3967876> Don't log ENETUNREACH errors for unicast destinations
61 Revision 1.298 2005/02/10 00:41:59 cheshire
64 Revision 1.297 2005/02/09 23:38:51 ksekar
65 <rdar://problem/3993508> Reregister hostname when DNS server changes but IP address does not
67 Revision 1.296 2005/02/01 21:06:52 ksekar
68 Avoid spurious log message
70 Revision 1.295 2005/02/01 19:33:30 ksekar
71 <rdar://problem/3985239> Keychain format too restrictive
73 Revision 1.294 2005/01/27 21:30:23 cheshire
74 <rdar://problem/3952067> "Can't assign requested address" message after AirPort turned off
75 Don't write syslog messages for EADDRNOTAVAIL if we know network configuration changes are happening
77 Revision 1.293 2005/01/27 19:15:41 cheshire
78 Remove extraneous LogMsg() call
80 Revision 1.292 2005/01/27 17:48:38 cheshire
81 Added comment about CFSocketInvalidate closing the underlying socket
83 Revision 1.291 2005/01/27 00:10:58 cheshire
84 <rdar://problem/3967867> Name change log messages every time machine boots
86 Revision 1.290 2005/01/25 23:18:30 ksekar
87 fix for <rdar://problem/3971467> requires that local-only ".local" registration record be created
89 Revision 1.289 2005/01/25 18:08:31 ksekar
90 Removed redundant debug output
92 Revision 1.288 2005/01/25 17:42:26 ksekar
93 Renamed FoundDefBrowseDomain -> FoundLegacyBrowseDomain,
94 cleaned up duplicate log messages when adding/removing browse domains
96 Revision 1.287 2005/01/25 16:59:23 ksekar
97 <rdar://problem/3971138> sa_len not set checking reachability for TCP connections
99 Revision 1.286 2005/01/25 02:02:37 cheshire
100 <rdar://problem/3970673> mDNSResponder leaks
101 GetSearchDomains() was not calling dns_configuration_free().
103 Revision 1.285 2005/01/22 00:07:54 ksekar
104 <rdar://problem/3960546> mDNSResponder should look at all browse domains in SCPreferences
106 Revision 1.284 2005/01/21 23:07:17 ksekar
107 <rdar://problem/3960795> mDNSResponder causes Dial on Demand
109 Revision 1.283 2005/01/19 21:16:16 cheshire
110 Make sure when we set NetworkChanged that we don't set it to zero
112 Revision 1.282 2005/01/19 19:19:21 ksekar
113 <rdar://problem/3960191> Need a way to turn off domain discovery
115 Revision 1.281 2005/01/18 18:10:55 ksekar
116 <rdar://problem/3954575> Use 10.4 resolver API to get search domains
118 Revision 1.280 2005/01/17 22:48:52 ksekar
119 No longer need to call MarkSearchListElem for registration domain
121 Revision 1.279 2005/01/17 20:40:34 ksekar
122 SCPreferences changes should remove exactly one browse and one legacy browse domain for each remove event
124 Revision 1.278 2005/01/17 19:53:34 ksekar
125 Refinement to previous fix - register _legacy._browse records for SCPreference domains to achieve correct reference counting
127 Revision 1.277 2005/01/12 00:17:50 ksekar
128 <rdar://problem/3933573> Update LLQs *after* setting DNS
130 Revision 1.276 2005/01/10 17:39:10 ksekar
131 Refinement to 1.272 - avoid spurious warnings when registration and browse domains are set to same value and toggled on/off
133 Revision 1.275 2005/01/10 04:02:22 ksekar
134 Refinement to <rdar://problem/3891628> - strip trailing dot before writing hostname status to dynamic store
136 Revision 1.274 2005/01/10 03:41:36 ksekar
137 Correction to checkin 1.272 - check that registration domain is set
138 before trying to remove it as an implicit browse domain
140 Revision 1.273 2005/01/08 00:42:18 ksekar
141 <rdar://problem/3922758> Clean up syslog messages
143 Revision 1.272 2005/01/07 23:21:42 ksekar
144 <rdar://problem/3891628> Clean up SCPreferences format
146 Revision 1.271 2004/12/20 23:18:12 cheshire
147 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
148 One more refinement: When an interface with a v6LL address gets a v4 address too, that's not a flap
150 Revision 1.270 2004/12/20 21:28:14 cheshire
151 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
152 Additional refinements to handle sleep/wake better
154 Revision 1.269 2004/12/20 20:48:11 cheshire
155 Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xxx) or later
157 Revision 1.268 2004/12/18 03:19:04 cheshire
158 Show netmask in error log
160 Revision 1.267 2004/12/18 00:51:52 cheshire
161 Use symbolic constant kDNSServiceInterfaceIndexLocalOnly instead of (mDNSu32) ~0
163 Revision 1.266 2004/12/17 23:49:38 cheshire
164 <rdar://problem/3922754> Computer Name change is slow
165 Also treat changes to "Setup:/Network/DynamicDNS" the same way
167 Revision 1.265 2004/12/17 23:37:47 cheshire
168 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
169 (and other repetitive configuration changes)
171 Revision 1.264 2004/12/17 19:03:05 cheshire
172 Update debugging messages to show netmask a simple CIDR-style numeric value (0-128)
174 Revision 1.263 2004/12/17 05:25:46 cheshire
175 <rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs
177 Revision 1.262 2004/12/17 04:48:32 cheshire
178 <rdar://problem/3922754> Computer Name change is slow
180 Revision 1.261 2004/12/17 02:40:08 cheshire
181 Undo last change -- it was too strict
183 Revision 1.260 2004/12/16 22:17:16 cheshire
184 Only accept multicast packets on interfaces that have McastTxRx set
186 Revision 1.259 2004/12/16 20:13:01 cheshire
187 <rdar://problem/3324626> Cache memory management improvements
189 Revision 1.258 2004/12/14 00:18:05 cheshire
190 Don't log dns_configuration_copy() failures in the first three minutes after boot
192 Revision 1.257 2004/12/10 19:45:46 cheshire
193 <rdar://problem/3915074> Reduce egregious stack space usage
194 Reduced myCFSocketCallBack() stack frame from 9K to 512 bytes
196 Revision 1.256 2004/12/10 04:35:43 cheshire
197 <rdar://problem/3907233> Show "Note: Compiled without Apple-specific split DNS support" only once
199 Revision 1.255 2004/12/10 04:12:54 ksekar
200 <rdar://problem/3890764> Need new DefaultBrowseDomain key
202 Revision 1.254 2004/12/10 01:55:31 ksekar
203 <rdar://problem/3899067> Keychain lookups should be in lower case.
205 Revision 1.253 2004/12/09 03:15:41 ksekar
206 <rdar://problem/3806610> use _legacy instead of _default to find "empty string" browse domains
208 Revision 1.252 2004/12/07 01:32:42 cheshire
209 Don't log dns_configuration_copy() failure when running on 10.3
211 Revision 1.251 2004/12/06 22:30:31 cheshire
212 Added debugging log message
214 Revision 1.250 2004/12/06 06:59:08 ksekar
215 RegisterSplitDNS should return Unsupported error when compiled on Panther
217 Revision 1.249 2004/12/04 00:29:46 cheshire
218 Add "#ifdef MAC_OS_X_VERSION_10_4" around split-DNS code that can't be compiled on 10.3 systems
219 (When compiled on 10.3, code will not include split-DNS support.)
221 Revision 1.248 2004/12/01 20:57:20 ksekar
222 <rdar://problem/3873921> Wide Area Service Discovery must be split-DNS aware
224 Revision 1.247 2004/12/01 03:26:58 cheshire
225 Remove unused variables
227 Revision 1.246 2004/12/01 01:51:34 cheshire
228 Move ReadDDNSSettingsFromConfFile() from mDNSMacOSX.c to PlatformCommon.c
230 Revision 1.245 2004/11/30 03:24:04 cheshire
231 <rdar://problem/3854544> Defer processing network configuration changes until configuration has stabilized
233 Revision 1.244 2004/11/30 02:59:35 cheshire
234 For debugging diagnostics, added identifying strings in SCDynamicStoreCreate() calls
236 Revision 1.243 2004/11/29 19:17:29 ksekar
237 <rdar://problem/3878195> Unnecessary GetUserSpecifiedDDNSConfig log messages
239 Revision 1.242 2004/11/29 18:37:38 ksekar
240 <rdar://problem/3889341> Buffer overflow in GetConfigOption
242 Revision 1.241 2004/11/25 01:37:04 ksekar
243 <rdar://problem/3894854> Config file and SCPreferences don't play well together
245 Revision 1.240 2004/11/25 01:29:42 ksekar
246 Remove unnecessary log messages
248 Revision 1.239 2004/11/25 01:27:19 ksekar
249 <rdar://problem/3885859> Don't try to advertise link-local IP addresses via dynamic update
251 Revision 1.238 2004/11/24 22:00:59 cheshire
252 Move definition of mDNSAddressIsAllDNSLinkGroup() from mDNSMacOSX.c to mDNSEmbeddedAPI.h
254 Revision 1.237 2004/11/24 21:54:44 cheshire
255 <rdar://problem/3894475> mDNSCore not receiving unicast responses properly
257 Revision 1.236 2004/11/23 03:39:46 cheshire
258 Let interface name/index mapping capability live directly in JNISupport.c,
259 instead of having to call through to the daemon via IPC to get this information.
261 Revision 1.235 2004/11/17 01:45:35 cheshire
262 <rdar://problem/3847435> mDNS buddy list frequently becomes empty if you let the machine sleep
263 Refresh our interface list on receiving kIOMessageSystemHasPoweredOn,
264 in case we get no System Configuration Framework "network changed" event.
266 Revision 1.234 2004/11/17 00:32:56 ksekar
267 <rdar://problem/3880773> mDNSResponder will not discover zones contained both in Search Domains and DHCP Domain option
269 Revision 1.233 2004/11/12 03:16:45 rpantos
270 rdar://problem/3809541 Add mDNSPlatformGetInterfaceByName, mDNSPlatformGetInterfaceName
272 Revision 1.232 2004/11/10 20:40:54 ksekar
273 <rdar://problem/3868216> LLQ mobility fragile on non-primary interface
275 Revision 1.231 2004/11/06 00:59:33 ksekar
276 Don't log ENETDOWN errors for unicast destinations (pollutes log on
279 Revision 1.230 2004/11/05 01:04:10 ksekar
280 <rdar://problem/3774577> LegacyNATDestroy() called too enthusiastically
282 Revision 1.229 2004/11/03 03:45:16 cheshire
283 <rdar://problem/3863627> mDNSResponder does not inform user of Computer Name collisions
285 Revision 1.228 2004/11/02 23:47:32 cheshire
286 <rdar://problem/3863214> Default hostname and Computer Name should be unique
288 Revision 1.227 2004/11/02 04:23:03 cheshire
289 Change to more informative name "GetUserSpecifiedLocalHostName()"
291 Revision 1.226 2004/11/01 20:36:19 ksekar
292 <rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
294 Revision 1.225 2004/10/28 19:03:04 cheshire
295 Remove \n from LogMsg() calls
297 Revision 1.224 2004/10/28 17:47:34 cheshire
298 Oops. Forgot the %d in the log message.
300 Revision 1.223 2004/10/28 17:24:28 cheshire
301 Updated "bad ifa_netmask" log message to give more information
303 Revision 1.222 2004/10/28 03:36:34 cheshire
304 <rdar://problem/3856535> Share the same port for both multicast and unicast receiving
306 Revision 1.221 2004/10/28 03:24:41 cheshire
307 Rename m->CanReceiveUnicastOn as m->CanReceiveUnicastOn5353
309 Revision 1.220 2004/10/28 00:53:57 cheshire
310 Export mDNSMacOSXNetworkChanged() so it's callable from outside this mDNSMacOSX.c;
311 Add LogOperation() call to record when we get network change events
313 Revision 1.219 2004/10/27 20:42:20 cheshire
314 Clean up debugging messages
316 Revision 1.218 2004/10/27 02:03:59 cheshire
317 Update debugging messages
319 Revision 1.217 2004/10/26 20:48:21 cheshire
320 Improve logging messages
322 Revision 1.216 2004/10/26 01:02:37 cheshire
325 Revision 1.215 2004/10/25 20:09:00 ksekar
326 Cleaned up config file parsing.
328 Revision 1.214 2004/10/25 19:30:53 ksekar
329 <rdar://problem/3827956> Simplify dynamic host name structures
331 Revision 1.213 2004/10/23 01:16:01 cheshire
332 <rdar://problem/3851677> uDNS operations not always reliable on multi-homed hosts
334 Revision 1.212 2004/10/22 20:52:08 ksekar
335 <rdar://problem/3799260> Create NAT port mappings for Long Lived Queries
337 Revision 1.211 2004/10/22 01:07:11 cheshire
338 <rdar://problem/3375328> select() says data is waiting; recvfrom() says there is no data
339 Log error message if socket() ever returns file descriptors 0, 1 or 2 (stdin/stdout/stderr).
340 These are all supposed to be remapped to /dev/null
342 Revision 1.210 2004/10/20 02:19:54 cheshire
343 Eliminate "SetupAddr invalid sa_family" warning from RegisterSearchDomains()
345 Revision 1.209 2004/10/16 00:17:00 cheshire
346 <rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
348 Revision 1.208 2004/10/15 23:00:18 ksekar
349 <rdar://problem/3799242> Need to update LLQs on location changes
351 Revision 1.207 2004/10/13 22:45:23 cheshire
352 <rdar://problem/3438392> Ten-second delay before kIOMessageSystemHasPoweredOn message
354 Revision 1.206 2004/10/13 22:11:46 cheshire
355 Update debugging messages
357 Revision 1.205 2004/10/12 21:10:11 cheshire
358 <rdar://problem/3438376> mach_absolute_time() not monotonically increasing
359 Do a NotifyOfElusiveBug() if we see mach_absolute_time() go backwards
361 Revision 1.204 2004/10/12 03:20:52 ksekar
362 <rdar://problem/3835614> Incorrect LogMsg produces garbage on errors
364 Revision 1.203 2004/10/08 04:29:25 ksekar
365 <rdar://problem/3831842> Allow default search domains to be set via hint from DHCP
367 Revision 1.202 2004/10/04 05:56:04 cheshire
368 <rdar://problem/3824730> mDNSResponder doesn't respond to certain AirPort changes
370 Revision 1.201 2004/09/30 00:24:59 ksekar
371 <rdar://problem/3695802> Dynamically update default registration domains on config change
373 Revision 1.200 2004/09/26 23:20:35 ksekar
374 <rdar://problem/3813108> Allow default registrations in multiple wide-area domains
376 Revision 1.199 2004/09/24 23:54:55 cheshire
377 <rdar://problem/3787102> Don't use kCFSocketCloseOnInvalidate
379 Revision 1.198 2004/09/24 23:47:49 cheshire
380 Correct comment and error message
382 Revision 1.197 2004/09/24 23:39:27 cheshire
383 <rdar://problem/3733705> Only IPv6 loopback address advertised on laptop w/no networking
385 Revision 1.196 2004/09/24 20:53:04 cheshire
386 Revise error message to say "Setsockopt SO_REUSEPORT failed" instead of "Flaw in Kernel"
388 Revision 1.195 2004/09/24 19:21:45 cheshire
389 <rdar://problem/3671626> Report "Address already in use" errors
391 Revision 1.194 2004/09/24 19:16:54 cheshire
392 Remove "mDNS *const m" parameter from NotifyOfElusiveBug();
393 Refine error message to say "Flaw in Kernel (select/recvfrom mismatch)"
395 Revision 1.193 2004/09/22 00:41:59 cheshire
396 Move tcp connection status codes into the legal range allocated for mDNS use
398 Revision 1.192 2004/09/21 21:02:55 cheshire
399 Set up ifname before calling mDNS_RegisterInterface()
401 Revision 1.191 2004/09/21 19:19:36 cheshire
402 <rdar://problem/3760923> Combine WatchForDynDNSChanges() into WatchForNetworkChanges()
404 Revision 1.190 2004/09/21 19:04:45 cheshire
405 Strip trailing white space from the ends of lines
407 Revision 1.189 2004/09/21 00:13:28 cheshire
408 Fix build failure (io_connect_t and io_object_t are integers, not pointers)
410 Revision 1.188 2004/09/20 23:52:02 cheshire
411 CFSocket{Puma}.c renamed to mDNSMacOSX{Puma}.c
413 Revision 1.187 2004/09/18 01:37:01 cheshire
416 Revision 1.186 2004/09/18 01:11:57 ksekar
417 <rdar://problem/3806734> Add a user's default domain to empty-string browse list
419 Revision 1.185 2004/09/17 01:08:52 cheshire
420 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
421 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
422 declared in that file are ONLY appropriate to single-address-space embedded applications.
423 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
425 Revision 1.184 2004/09/17 00:19:10 cheshire
426 For consistency with AllDNSLinkGroupv6, rename AllDNSLinkGroup to AllDNSLinkGroupv4
428 Revision 1.183 2004/09/17 00:15:56 cheshire
429 Rename mDNSPlatformInit_ReceiveUnicast to mDNSPlatformInit_CanReceiveUnicast
431 Revision 1.182 2004/09/16 21:36:36 cheshire
432 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
433 Changes to add necessary locking calls around unicast DNS operations
435 Revision 1.181 2004/09/16 02:03:42 cheshire
436 <rdar://problem/3802944> Change address to notify user of kernel flaw
438 Revision 1.180 2004/09/16 01:58:22 cheshire
439 Fix compiler warnings
441 Revision 1.179 2004/09/16 00:24:49 cheshire
442 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
444 Revision 1.178 2004/09/15 21:51:34 cheshire
445 <rdar://problem/3387020> mDNSResponder should notify user of kernel flaw
446 Calling CFUserNotificationDisplayNotice too early in the boot process seems to kill
447 the machine, so make sure we don't do this until at least three minutes after boot.
449 Revision 1.177 2004/09/15 01:16:29 cheshire
450 <rdar://problem/3387020> mDNSResponder should notify user of kernel flaw
452 Revision 1.176 2004/09/14 23:42:36 cheshire
453 <rdar://problem/3801296> Need to seed random number generator from platform-layer data
455 Revision 1.175 2004/09/14 21:35:46 cheshire
456 Minor code tidying, and added comments about CFRetainCounts
458 Revision 1.174 2004/09/14 19:14:57 ksekar
459 <rdar://problem/3192531> DynDNS: Discovery of DynDNS Zones via Reverse-Map PTR
461 Revision 1.173 2004/08/25 23:35:22 ksekar
462 <rdar://problem/3770615>: Error converting shared secret from base-64 to binary
464 Revision 1.172 2004/08/25 02:01:45 cheshire
465 <rdar://problem/3774777> Need to be able to get status of Dynamic DNS Host Name Update
467 Revision 1.171 2004/08/25 01:04:42 cheshire
468 Don't need to CFRelease name and array
470 Revision 1.170 2004/08/25 00:37:28 ksekar
471 <rdar://problem/3774635>: Cleanup DynDNS hostname registration code
473 Revision 1.169 2004/08/18 17:35:41 ksekar
474 <rdar://problem/3651443>: Feature #9586: Need support for Legacy NAT gateways
476 Revision 1.168 2004/08/17 03:16:24 ksekar
477 Fixed checkin 1.166 - enumeration type changed for wrong invocation of mDNS_GetDomains
479 Revision 1.167 2004/08/17 00:52:43 ksekar
480 Fix config file parse error, make semantics match SCPreferences
483 Revision 1.166 2004/08/16 19:55:07 ksekar
484 Change enumeration type to BrowseDefault to construct empty-string
485 browse list as result of checking 1.161.
487 Revision 1.165 2004/08/16 19:52:40 ksekar
488 Pass computer name + zone for FQDN after keychain notification,
489 setting global default service registration domain to the zone.
491 Revision 1.164 2004/08/16 16:52:37 ksekar
492 Pass in zone read from keychain to mDNS_SetFQDNs.
494 Revision 1.163 2004/08/14 03:22:42 cheshire
495 <rdar://problem/3762579> Dynamic DNS UI <-> mDNSResponder glue
496 Add GetUserSpecifiedDDNSName() routine
497 Convert ServiceRegDomain to domainname instead of C string
498 Replace mDNS_GenerateFQDN/mDNS_GenerateGlobalFQDN with mDNS_SetFQDNs
500 Revision 1.162 2004/08/12 22:34:00 cheshire
501 All strings should be read as kCFStringEncodingUTF8, not kCFStringEncodingASCII
503 Revision 1.161 2004/08/11 00:17:46 ksekar
504 <rdar://problem/3757662>: 8A227: Need Lighthouse configred machines to
505 set default bit for their domains
507 Revision 1.160 2004/07/29 19:27:16 ksekar
508 NATPMP Support - minor fixes and cleanup
510 Revision 1.159 2004/07/26 22:49:31 ksekar
511 <rdar://problem/3651409>: Feature #9516: Need support for NATPMP in client
513 Revision 1.158 2004/07/13 21:24:24 rpantos
514 Fix for <rdar://problem/3701120>.
516 Revision 1.157 2004/06/08 18:54:48 ksekar
517 <rdar://problem/3681378>: mDNSResponder leaks after exploring in Printer Setup Utility
519 Revision 1.156 2004/06/05 00:04:26 cheshire
520 <rdar://problem/3668639>: wide-area domains should be returned in reg. domain enumeration
522 Revision 1.155 2004/06/04 08:58:30 ksekar
523 <rdar://problem/3668624>: Keychain integration for secure dynamic update
525 Revision 1.154 2004/05/31 22:22:28 ksekar
526 <rdar://problem/3668639>: wide-area domains should be returned in
527 reg. domain enumeration
529 Revision 1.153 2004/05/26 17:06:33 cheshire
530 <rdar://problem/3668515>: Don't rely on CFSocketInvalidate() to remove RunLoopSource
532 Revision 1.152 2004/05/18 23:51:26 cheshire
533 Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
535 Revision 1.151 2004/05/17 21:46:34 cheshire
536 <rdar://problem/3616426>: When interface is turned off, browse "remove" events are delivered with interface index zero
537 Take care to correctly update InterfaceIDs when a dormant interface comes back to life
539 Revision 1.150 2004/05/13 04:54:20 ksekar
540 Unified list copy/free code. Added symetric list for
542 Revision 1.149 2004/05/13 03:55:14 ksekar
543 Fixed list traversal bug in FoundDefSearchDomain.
545 Revision 1.148 2004/05/12 22:03:08 ksekar
546 Made GetSearchDomainList a true platform-layer call (declaration moved
547 from mDNSMacOSX.h to mDNSEmbeddedAPI.h), impelemted to return "local"
548 only on non-OSX platforms. Changed call to return a copy of the list
549 to avoid shared memory issues. Added a routine to free the list.
551 Revision 1.147 2004/05/12 02:03:25 ksekar
552 Non-local domains will only be browsed by default, and show up in
553 _browse domain enumeration, if they contain an _browse._dns-sd ptr record.
555 Revision 1.146 2004/04/27 02:49:15 cheshire
556 <rdar://problem/3634655>: mDNSResponder leaks sockets on bind() error
558 Revision 1.145 2004/04/21 03:08:03 cheshire
559 Rename 'alias' to more descriptive name 'primary'
561 Revision 1.144 2004/04/21 03:04:35 cheshire
562 Minor cleanup for clarity
564 Revision 1.143 2004/04/21 03:03:30 cheshire
565 Preparation work: AddInterfaceToList() should return pointer to structure it creates
567 Revision 1.142 2004/04/21 02:49:11 cheshire
568 To reduce future confusion, renamed 'TxAndRx' to 'McastTxRx'
570 Revision 1.141 2004/04/21 02:20:47 cheshire
571 Rename interface field 'CurrentlyActive' to more descriptive 'Exists'
573 Revision 1.140 2004/04/14 23:09:29 ksekar
574 Support for TSIG signed dynamic updates.
576 Revision 1.139 2004/04/09 17:40:26 cheshire
577 Remove unnecessary "Multicast" field -- it duplicates the semantics of the existing McastTxRx field
579 Revision 1.138 2004/04/09 16:37:16 cheshire
580 Suggestion from Bob Bradley:
581 Move NumCacheRecordsForInterfaceID() to DNSCommon.c so it's available to all platform layers
583 Revision 1.137 2004/04/08 00:59:55 cheshire
584 <rdar://problem/3609972> When interface turned off, browse "remove" events delivered with interface index zero
585 Unify use of the InterfaceID field, and make code that walks the list respect the 'Exists' flag
587 Revision 1.136 2004/04/07 01:08:57 cheshire
588 <rdar://problem/3609972> When interface turned off, browse "remove" events delivered with interface index zero
590 Revision 1.135 2004/03/19 01:01:03 ksekar
591 Fixed config file parsing to chop newline
593 Revision 1.134 2004/03/13 01:57:34 ksekar
594 <rdar://problem/3192546>: DynDNS: Dynamic update of service records
596 Revision 1.133 2004/02/02 22:46:56 cheshire
597 Move "CFRelease(dict);" inside the "if (dict)" check
599 Revision 1.132 2004/01/28 02:30:08 ksekar
600 Added default Search Domains to unicast browsing, controlled via
601 Networking sharing prefs pane. Stopped sending unicast messages on
602 every interface. Fixed unicast resolving via mach-port API.
604 Revision 1.131 2004/01/27 22:57:48 cheshire
605 <rdar://problem/3534352>: Need separate socket for issuing unicast queries
607 Revision 1.130 2004/01/27 22:28:40 cheshire
608 <rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
609 Additional lingering port 53 code deleted
611 Revision 1.129 2004/01/27 20:15:23 cheshire
612 <rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
614 Revision 1.128 2004/01/24 23:58:17 cheshire
615 Change to use mDNSVal16() instead of shifting and ORing
617 Revision 1.127 2004/01/24 04:59:16 cheshire
618 Fixes so that Posix/Linux, OS9, Windows, and VxWorks targets build again
620 Revision 1.126 2004/01/23 23:23:15 ksekar
621 Added TCP support for truncated unicast messages.
623 Revision 1.125 2004/01/22 03:43:09 cheshire
624 Export constants like mDNSInterface_LocalOnly so that the client layers can use them
626 Revision 1.124 2004/01/21 21:53:19 cheshire
627 <rdar://problem/3448144>: Don't try to receive unicast responses if we're not the first to bind to the UDP port
629 Revision 1.123 2004/01/20 03:18:25 cheshire
630 Removed "LogMsg("Hey There!");" that evidently got checked in my mistake
632 Revision 1.122 2003/12/17 20:43:59 cheshire
633 <rdar://problem/3496728>: Syslog messages saying "sendto failed"
635 Revision 1.121 2003/12/13 03:05:28 ksekar
636 <rdar://problem/3192548>: DynDNS: Unicast query of service records
638 Revision 1.120 2003/12/08 21:00:46 rpantos
639 Changes to support mDNSResponder on Linux.
641 Revision 1.119 2003/12/03 02:35:15 cheshire
642 Also report value of m->timenow when logging sendto() failure
644 Revision 1.118 2003/11/14 20:59:09 cheshire
645 Clients can't use AssignDomainName macro because mDNSPlatformMemCopy is defined in mDNSPlatformFunctions.h.
646 Best solution is just to combine mDNSEmbeddedAPI.h and mDNSPlatformFunctions.h into a single file.
648 Revision 1.117 2003/11/08 22:18:29 cheshire
649 <rdar://problem/3477870>: Don't need to show process ID in *every* mDNSResponder syslog message
651 Revision 1.116 2003/09/23 16:39:49 cheshire
652 When LogAllOperations is set, also report registration and deregistration of interfaces
654 Revision 1.115 2003/09/10 00:45:55 cheshire
655 <rdar://problem/3412328> Don't log "sendto failed" errors during the first two minutes of startup
657 Revision 1.114 2003/08/27 02:55:13 cheshire
658 <rdar://problem/3387910>: Bug: Don't report mDNSPlatformSendUDP sendto errno 64 (Host is down)
660 Revision 1.113 2003/08/19 22:20:00 cheshire
661 <rdar://problem/3376721> Don't use IPv6 on interfaces that have a routable IPv4 address configured
662 More minor refinements
664 Revision 1.112 2003/08/19 03:04:43 cheshire
665 <rdar://problem/3376721> Don't use IPv6 on interfaces that have a routable IPv4 address configured
667 Revision 1.111 2003/08/18 22:53:37 cheshire
668 <rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformRawTime()
670 Revision 1.110 2003/08/16 03:39:00 cheshire
671 <rdar://problem/3338440> InterfaceID -1 indicates "local only"
673 Revision 1.109 2003/08/15 02:19:49 cheshire
674 <rdar://problem/3375225> syslog messages: myCFSocketCallBack recvfrom skt 6 error -1 errno 35
675 Also limit number of messages to at most 100
677 Revision 1.108 2003/08/12 22:24:52 cheshire
678 <rdar://problem/3375225> syslog messages: myCFSocketCallBack recvfrom skt 6 error -1 errno 35
679 This message indicates a kernel bug, but still we don't want to flood syslog.
680 Do a sleep(1) after writing this log message, to limit the rate.
682 Revision 1.107 2003/08/12 19:56:25 cheshire
685 Revision 1.106 2003/08/12 13:48:32 cheshire
686 Add comment explaining clockdivisor calculation
688 Revision 1.105 2003/08/12 13:44:14 cheshire
689 <rdar://problem/3370229> mDNSResponder *VERY* unhappy if time goes backwards
690 Use mach_absolute_time() (which is guaranteed to always go forwards, resetting only on reboot)
691 instead of gettimeofday() (which can jump back if the user manually changes their time/date)
693 Revision 1.104 2003/08/12 13:12:07 cheshire
694 Textual search/replace: Indicate local functions using "mDNSlocal" instead of "static"
696 Revision 1.103 2003/08/08 18:36:04 cheshire
697 <rdar://problem/3344154> Only need to revalidate on interface removal on platforms that have the PhantomInterfaces bug
699 Revision 1.102 2003/08/06 00:14:52 cheshire
700 <rdar://problem/3330324> Need to check IP TTL on responses
701 Also add corresponding checks in the IPv6 code path
703 Revision 1.101 2003/08/05 22:20:16 cheshire
704 <rdar://problem/3330324> Need to check IP TTL on responses
706 Revision 1.100 2003/08/05 21:18:50 cheshire
707 <rdar://problem/3363185> mDNSResponder should ignore 6to4
708 Only use interfaces that are marked as multicast-capable (IFF_MULTICAST)
710 Revision 1.99 2003/08/05 20:13:52 cheshire
711 <rdar://problem/3294080> mDNSResponder using IPv6 interfaces before they are ready
712 Ignore interfaces with the IN6_IFF_NOTREADY flag set
714 Revision 1.98 2003/07/20 03:38:51 ksekar
715 <rdar://problem/3320722>
716 Completed support for Unix-domain socket based API.
718 Revision 1.97 2003/07/19 03:15:16 cheshire
719 Add generic MemAllocate/MemFree prototypes to mDNSPlatformFunctions.h,
720 and add the obvious trivial implementations to each platform support layer
722 Revision 1.96 2003/07/18 00:30:00 cheshire
723 <rdar://problem/3268878> Remove mDNSResponder version from packet header and use HINFO record instead
725 Revision 1.95 2003/07/12 03:15:20 cheshire
726 <rdar://problem/3324848> After SCDynamicStore notification, mDNSResponder updates
727 m->hostlabel even if user hasn't actually actually changed their dot-local hostname
729 Revision 1.94 2003/07/03 00:51:54 cheshire
730 <rdar://problem/3287213> When select() and recvmgs() disagree, get more info from kernel about the socket state
732 Revision 1.93 2003/07/03 00:09:14 cheshire
733 <rdar://problem/3286004> New APIs require a mDNSPlatformInterfaceIDfromInterfaceIndex() call
734 Additional refinement suggested by Josh: Use info->scope_id instead of if_nametoindex(info->ifa_name);
736 Revision 1.92 2003/07/02 21:19:51 cheshire
737 <rdar://problem/3313413> Update copyright notices, etc., in source code comments
739 Revision 1.91 2003/06/24 01:53:51 cheshire
740 Minor update to comments
742 Revision 1.90 2003/06/24 01:51:47 cheshire
743 <rdar://problem/3303118> Oops: Double-dispose of sockets
744 Don't need to close sockets: CFSocketInvalidate() does that for us
746 Revision 1.89 2003/06/21 18:12:47 cheshire
747 <rdar://problem/3296061> mDNSResponder cannot handle interfaces whose total name is >3 chars
748 One-line change: should say "IF_NAMESIZE", not sizeof(ifname)
750 Revision 1.88 2003/06/12 23:38:37 cheshire
751 <rdar://problem/3291162> mDNSResponder doesn't detect some configuration changes
752 Also check that scope_id matches before concluding that two interfaces are the same
754 Revision 1.87 2003/06/10 01:14:11 cheshire
755 <rdar://problem/3286004> New APIs require a mDNSPlatformInterfaceIDfromInterfaceIndex() call
757 Revision 1.86 2003/05/28 02:41:52 cheshire
758 <rdar://problem/3034346> Time to remove Mac OS 9 UDP Port 53 legacy support
760 Revision 1.85 2003/05/28 02:39:47 cheshire
761 Minor change to debugging messages
763 Revision 1.84 2003/05/27 22:29:40 cheshire
764 Remove out-dated comment
766 Revision 1.83 2003/05/26 03:21:29 cheshire
767 Tidy up address structure naming:
768 mDNSIPAddr => mDNSv4Addr (for consistency with mDNSv6Addr)
769 mDNSAddr.addr.ipv4 => mDNSAddr.ip.v4
770 mDNSAddr.addr.ipv6 => mDNSAddr.ip.v6
772 Revision 1.82 2003/05/26 03:01:27 cheshire
773 <rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
775 Revision 1.81 2003/05/24 02:06:42 cheshire
776 <rdar://problem/3268480> IPv6 Multicast Loopback doesn't work
777 Tried setting IPV6_MULTICAST_LOOP; it doesn't help.
778 However, it is probably wise to have the code explicitly set this socket
779 option anyway, in case the default changes in later versions of Unix.
781 Revision 1.80 2003/05/24 02:02:24 cheshire
782 <rdar://problem/3221880> if_indextoname consumes a lot of CPU
783 Fix error in myIfIndexToName; was returning prematurely
785 Revision 1.79 2003/05/23 23:07:44 cheshire
786 <rdar://problem/3268199> Must not write to stderr when running as daemon
788 Revision 1.78 2003/05/23 01:19:04 cheshire
789 <rdar://problem/3267085> mDNSResponder needs to signal type of service to AirPort
790 Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
792 Revision 1.77 2003/05/23 01:12:05 cheshire
795 Revision 1.76 2003/05/22 01:26:01 cheshire
798 Revision 1.75 2003/05/22 00:07:09 cheshire
799 <rdar://problem/3264366> myCFSocketCallBack recvfrom(5) error 1, errno 35
800 Extra logging to determine whether there is a bug in CFSocket
802 Revision 1.74 2003/05/21 20:20:12 cheshire
803 Fix warnings (mainly printf format string warnings, like using "%d" where
804 it should say "%lu", etc.) and improve error logging (use strerror()
805 to include textual error message as well as numeric error in log messages).
807 Revision 1.73 2003/05/21 17:56:29 ksekar
808 <rdar://problem/3191277>: mDNSResponder doesn't watch for IPv6 address changes
810 Revision 1.72 2003/05/14 18:48:41 cheshire
811 <rdar://problem/3159272> mDNSResponder should be smarter about reconfigurations
812 More minor refinements:
813 mDNSMacOSX.c needs to do *all* its mDNS_DeregisterInterface calls before freeing memory
814 mDNS_DeregisterInterface revalidates cache record when *any* representative of an interface goes away
816 Revision 1.71 2003/05/14 07:08:37 cheshire
817 <rdar://problem/3159272> mDNSResponder should be smarter about reconfigurations
818 Previously, when there was any network configuration change, mDNSResponder
819 would tear down the entire list of active interfaces and start again.
820 That was very disruptive, and caused the entire cache to be flushed,
821 and caused lots of extra network traffic. Now it only removes interfaces
822 that have really gone, and only adds new ones that weren't there before.
824 Revision 1.70 2003/05/07 18:30:24 cheshire
825 Fix signed/unsigned comparison warning
827 Revision 1.69 2003/05/06 20:14:44 cheshire
830 Revision 1.68 2003/05/06 00:00:49 cheshire
831 <rdar://problem/3248914> Rationalize naming of domainname manipulation functions
833 Revision 1.67 2003/04/29 00:43:44 cheshire
834 Fix compiler warnings
836 Revision 1.66 2003/04/26 02:41:58 cheshire
837 <rdar://problem/3241281> Change timenow from a local variable to a structure member
839 Revision 1.65 2003/04/26 02:34:01 cheshire
840 Add missing mDNSexport
842 Revision 1.64 2003/04/15 16:48:06 jgraessl
843 <rdar://problem/3228833>
844 Modified code in CFSocket notifier function to read all packets on the socket
845 instead of reading only one packet every time the notifier was called.
847 Revision 1.63 2003/04/15 16:33:50 jgraessl
848 <rdar://problem/3221880>
849 Switched to our own copy of if_indextoname to improve performance.
851 Revision 1.62 2003/03/28 01:55:44 cheshire
852 Minor improvements to debugging messages
854 Revision 1.61 2003/03/27 03:30:56 cheshire
855 <rdar://problem/3210018> Name conflicts not handled properly, resulting in memory corruption, and eventual crash
856 Problem was that HostNameCallback() was calling mDNS_DeregisterInterface(), which is not safe in a callback
858 1. Make mDNS_DeregisterInterface() safe to call from a callback
859 2. Make HostNameCallback() use mDNS_DeadvertiseInterface() instead
860 (it never really needed to deregister the interface at all)
862 Revision 1.60 2003/03/15 04:40:38 cheshire
863 Change type called "mDNSOpaqueID" to the more descriptive name "mDNSInterfaceID"
865 Revision 1.59 2003/03/11 01:23:26 cheshire
866 <rdar://problem/3194246> mDNSResponder socket problems
868 Revision 1.58 2003/03/06 01:43:04 cheshire
869 <rdar://problem/3189097> Additional debugging code in mDNSResponder
870 Improve "LIST_ALL_INTERFACES" output
872 Revision 1.57 2003/03/05 22:36:27 cheshire
873 <rdar://problem/3186338> Loopback doesn't work with mDNSResponder-27
874 Temporary workaround: Skip loopback interface *only* if we found at least one v4 interface to use
876 Revision 1.56 2003/03/05 01:50:38 cheshire
877 <rdar://problem/3189097> Additional debugging code in mDNSResponder
879 Revision 1.55 2003/02/21 01:54:09 cheshire
880 <rdar://problem/3099194> mDNSResponder needs performance improvements
881 Switched to using new "mDNS_Execute" model (see "Implementer Notes.txt")
883 Revision 1.54 2003/02/20 06:48:35 cheshire
884 <rdar://problem/3169535> Xserve RAID needs to do interface-specific registrations
885 Reviewed by: Josh Graessley, Bob Bradley
887 Revision 1.53 2003/01/29 02:21:23 cheshire
888 Return mStatus_Invalid if can't send packet because socket not available
890 Revision 1.52 2003/01/28 19:39:43 jgraessl
891 Enabling AAAA over IPv4 support.
893 Revision 1.51 2003/01/28 05:11:23 cheshire
894 Fixed backwards comparison in SearchForInterfaceByName
896 Revision 1.50 2003/01/13 23:49:44 jgraessl
897 Merged changes for the following fixes in to top of tree:
898 <rdar://problem/3086540> computer name changes not handled properly
899 <rdar://problem/3124348> service name changes are not properly handled
900 <rdar://problem/3124352> announcements sent in pairs, failing chattiness test
902 Revision 1.49 2002/12/23 22:13:30 jgraessl
903 Reviewed by: Stuart Cheshire
904 Initial IPv6 support for mDNSResponder.
906 Revision 1.48 2002/11/22 01:37:52 cheshire
907 <rdar://problem/3108426> mDNSResponder is monitoring ServiceEntities instead of InterfaceEntities
909 Revision 1.47 2002/09/21 20:44:51 zarzycki
912 Revision 1.46 2002/09/19 21:25:35 cheshire
913 mDNS_snprintf() doesn't need to be in a separate file
915 Revision 1.45 2002/09/17 01:45:13 cheshire
916 Add LIST_ALL_INTERFACES symbol for debugging
918 Revision 1.44 2002/09/17 01:36:23 cheshire
919 Move Puma support to mDNSMacOSXPuma.c
921 Revision 1.43 2002/09/17 01:05:28 cheshire
922 Change mDNS_AdvertiseLocalAddresses to be an Init parameter instead of a global
924 Revision 1.42 2002/09/16 23:13:50 cheshire
929 // ***************************************************************************
931 // Supporting routines to run mDNS on a CFRunLoop platform
932 // ***************************************************************************
934 // For debugging, set LIST_ALL_INTERFACES to 1 to display all found interfaces,
935 // including ones that mDNSResponder chooses not to use.
936 #define LIST_ALL_INTERFACES 0
938 // For enabling AAAA records over IPv4. Setting this to 0 sends only
939 // A records over IPv4 and AAAA over IPv6. Setting this to 1 sends both
940 // AAAA and A records over both IPv4 and IPv6.
941 #define AAAA_OVER_V4 1
943 #include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
944 #include "DNSCommon.h"
945 #include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform
946 #include "../mDNSShared/uds_daemon.h" // Defines communication interface from platform layer up to UDS daemon
947 #include "PlatformCommon.h"
950 #include <stdarg.h> // For va_list support
952 #include <net/if_types.h> // For IFT_ETHER
953 #include <net/if_dl.h>
955 #include <sys/param.h>
956 #include <sys/socket.h>
957 #include <sys/sysctl.h>
959 #include <sys/ioctl.h>
960 #include <time.h> // platform support for UTC time
961 #include <arpa/inet.h> // for inet_aton
963 #include <netinet/in.h> // For IP_RECVTTL
965 #define IP_RECVTTL 24 // bool; receive reception TTL w/dgram
968 #include <netinet/in_systm.h> // For n_long, required by <netinet/ip.h> below
969 #include <netinet/ip.h> // For IPTOS_LOWDELAY etc.
970 #include <netinet6/in6_var.h> // For IN6_IFF_NOTREADY etc.
972 #include <Security/Security.h>
976 // Code contributed by Dave Heller:
977 // Define RUN_ON_PUMA_WITHOUT_IFADDRS to compile code that will
978 // work on Mac OS X 10.1, which does not have the getifaddrs call.
979 #define RUN_ON_PUMA_WITHOUT_IFADDRS 0
980 #if RUN_ON_PUMA_WITHOUT_IFADDRS
981 #include "mDNSMacOSXPuma.c"
986 #include <IOKit/IOKitLib.h>
987 #include <IOKit/IOMessage.h>
988 #include <mach/mach_time.h>
990 typedef struct SearchListElem
992 struct SearchListElem
*next
;
996 DNSQuestion DefBrowseQ
;
997 DNSQuestion LegacyBrowseQ
;
998 DNSQuestion RegisterQ
;
999 DNSQuestion DefRegisterQ
;
1000 ARListElem
*AuthRecs
;
1004 // ***************************************************************************
1007 static mDNSu32 clockdivisor
= 0;
1009 // for domain enumeration and default browsing/registration
1010 static SearchListElem
*SearchList
= NULL
; // where we search for _browse domains
1011 static DNSQuestion LegacyBrowseDomainQ
; // our local enumeration query for _legacy._browse domains
1012 static DNameListElem
*DefBrowseList
= NULL
; // cache of answers to above query (where we search for empty string browses)
1013 static DNameListElem
*DefRegList
= NULL
; // manually generated list of domains where we register for empty string registrations
1014 static ARListElem
*SCPrefBrowseDomains
= NULL
; // manually generated local-only PTR records for browse domains we get from SCPreferences
1016 static domainname DynDNSRegDomain
; // Default wide-area zone for service registration
1017 static CFArrayRef DynDNSBrowseDomains
= NULL
; // Default wide-area zones for legacy ("empty string") browses
1018 static domainname DynDNSHostname
;
1020 static mDNSBool DomainDiscoveryDisabled
= mDNSfalse
;
1022 #define CONFIG_FILE "/etc/mDNSResponder.conf"
1023 #define DYNDNS_KEYCHAIN_SERVICE "DynDNS Shared Secret"
1024 #define SYS_KEYCHAIN_PATH "/Library/Keychains/System.keychain"
1026 // Function Prototypes
1027 mDNSlocal
void SetSCPrefsBrowseDomain(mDNS
*m
, const domainname
*d
, mDNSBool add
);
1029 // ***************************************************************************
1032 // routines to allow access to default domain lists from daemon layer
1034 mDNSexport DNameListElem
*mDNSPlatformGetSearchDomainList(void)
1036 return mDNS_CopyDNameList(DefBrowseList
);
1039 mDNSexport DNameListElem
*mDNSPlatformGetRegDomainList(void)
1041 return mDNS_CopyDNameList(DefRegList
);
1044 // utility routines to manage registration domain lists
1046 mDNSlocal
void AddDefRegDomain(domainname
*d
)
1048 DNameListElem
*newelem
= NULL
, *ptr
;
1050 // make sure name not already in list
1051 for (ptr
= DefRegList
; ptr
; ptr
= ptr
->next
)
1053 if (SameDomainName(&ptr
->name
, d
))
1054 { debugf("duplicate addition of default reg domain %##s", d
->c
); return; }
1057 newelem
= mallocL("DNameListElem", sizeof(*newelem
));
1058 if (!newelem
) { LogMsg("Error - malloc"); return; }
1059 AssignDomainName(&newelem
->name
, d
);
1060 newelem
->next
= DefRegList
;
1061 DefRegList
= newelem
;
1063 DefaultRegDomainChanged(d
, mDNStrue
);
1064 udsserver_default_reg_domain_changed(d
, mDNStrue
);
1067 mDNSlocal
void RemoveDefRegDomain(domainname
*d
)
1069 DNameListElem
*ptr
= DefRegList
, *prev
= NULL
;
1073 if (SameDomainName(&ptr
->name
, d
))
1075 if (prev
) prev
->next
= ptr
->next
;
1076 else DefRegList
= ptr
->next
;
1077 freeL("DNameListElem", ptr
);
1078 DefaultRegDomainChanged(d
, mDNSfalse
);
1079 udsserver_default_reg_domain_changed(d
, mDNSfalse
);
1085 debugf("Requested removal of default registration domain %##s not in contained in list", d
->c
);
1088 mDNSlocal
void NotifyOfElusiveBug(const char *title
, mDNSu32 radarid
, const char *msg
)
1090 extern mDNS mDNSStorage
;
1091 NetworkInterfaceInfoOSX
*i
;
1092 static int notifyCount
= 0;
1093 if (notifyCount
) return;
1095 // If we display our alert early in the boot process, then it vanishes once the desktop appears.
1096 // To avoid this, we don't try to display alerts in the first three minutes after boot.
1097 if ((mDNSu32
)(mDNSPlatformRawTime()) < (mDNSu32
)(mDNSPlatformOneSecond
* 180)) return;
1099 // Determine if we're at Apple (17.*.*.*)
1100 for (i
= mDNSStorage
.p
->InterfaceList
; i
; i
= i
->next
)
1101 if (i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
&& i
->ifinfo
.ip
.ip
.v4
.b
[0] == 17)
1103 if (!i
) return; // If not at Apple, don't show the alert
1105 // Send a notification to the user to contact coreos-networking
1107 CFStringRef alertHeader
= CFStringCreateWithCString(NULL
, title
, kCFStringEncodingUTF8
);
1108 CFStringRef alertFormat
= CFSTR("Congratulations, you've reproduced an elusive bug. Please contact the owner of <rdar://problem/%d>. %s");
1109 CFStringRef alertMessage
= CFStringCreateWithFormat(NULL
, NULL
, alertFormat
, radarid
, msg
);
1110 CFUserNotificationDisplayNotice(0.0, kCFUserNotificationStopAlertLevel
, NULL
, NULL
, NULL
, alertHeader
, alertMessage
, NULL
);
1113 mDNSlocal
struct ifaddrs
* myGetIfAddrs(int refresh
)
1115 static struct ifaddrs
*ifa
= NULL
;
1123 if (ifa
== NULL
) getifaddrs(&ifa
);
1128 mDNSlocal NetworkInterfaceInfoOSX
*SearchForInterfaceByName(mDNS
*const m
, const char *ifname
, int type
)
1130 NetworkInterfaceInfoOSX
*i
;
1131 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1132 if (i
->Exists
&& !strcmp(i
->ifa_name
, ifname
) &&
1134 (type
== AF_INET
&& i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
) ||
1135 (type
== AF_INET6
&& i
->ifinfo
.ip
.type
== mDNSAddrType_IPv6
) )) return(i
);
1139 mDNSlocal
int myIfIndexToName(u_short index
, char* name
)
1141 struct ifaddrs
*ifa
;
1142 for (ifa
= myGetIfAddrs(0); ifa
; ifa
= ifa
->ifa_next
)
1143 if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
1144 if (((struct sockaddr_dl
*)ifa
->ifa_addr
)->sdl_index
== index
)
1145 { strncpy(name
, ifa
->ifa_name
, IF_NAMESIZE
); return 0; }
1149 mDNSexport mDNSInterfaceID
mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS
*const m
, mDNSu32 index
)
1151 NetworkInterfaceInfoOSX
*i
;
1152 if (index
== kDNSServiceInterfaceIndexLocalOnly
) return(mDNSInterface_LocalOnly
);
1154 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1155 // Don't get tricked by inactive interfaces with no InterfaceID set
1156 if (i
->ifinfo
.InterfaceID
&& i
->scope_id
== index
) return(i
->ifinfo
.InterfaceID
);
1160 mDNSexport mDNSu32
mDNSPlatformInterfaceIndexfromInterfaceID(const mDNS
*const m
, mDNSInterfaceID id
)
1162 NetworkInterfaceInfoOSX
*i
;
1163 if (id
== mDNSInterface_LocalOnly
) return(kDNSServiceInterfaceIndexLocalOnly
);
1165 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
1166 // Don't use i->ifinfo.InterfaceID here, because we DO want to find inactive interfaces, which have no InterfaceID set
1167 if ((mDNSInterfaceID
)i
== id
) return(i
->scope_id
);
1171 mDNSlocal mDNSBool
AddrRequiresPPPConnection(const struct sockaddr
*addr
)
1173 mDNSBool result
= mDNSfalse
;
1174 SCNetworkConnectionFlags flags
;
1175 SCNetworkReachabilityRef ReachRef
= NULL
;
1177 ReachRef
= SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault
, addr
);
1178 if (!ReachRef
) { LogMsg("ERROR: RequiresConnection - SCNetworkReachabilityCreateWithAddress"); goto end
; }
1179 if (!SCNetworkReachabilityGetFlags(ReachRef
, &flags
)) { LogMsg("ERROR: AddrRequiresPPPConnection - SCNetworkReachabilityGetFlags"); goto end
; }
1180 result
= flags
& kSCNetworkFlagsConnectionRequired
;
1183 if (ReachRef
) CFRelease(ReachRef
);
1187 // NOTE: If InterfaceID is NULL, it means, "send this packet through our anonymous unicast socket"
1188 // NOTE: If InterfaceID is non-NULL it means, "send this packet through our port 5353 socket on the specified interface"
1189 // OR send via our primary v4 unicast socket
1190 mDNSexport mStatus
mDNSPlatformSendUDP(const mDNS
*const m
, const void *const msg
, const mDNSu8
*const end
,
1191 mDNSInterfaceID InterfaceID
, const mDNSAddr
*dst
, mDNSIPPort dstPort
)
1195 // Note: For this platform we've adopted the convention that InterfaceIDs are secretly pointers
1196 // to the NetworkInterfaceInfoOSX structure that holds the active sockets. The mDNSCore code
1197 // doesn't know that and doesn't need to know that -- it just treats InterfaceIDs as opaque identifiers.
1198 NetworkInterfaceInfoOSX
*info
= (NetworkInterfaceInfoOSX
*)InterfaceID
;
1199 char *ifa_name
= info
? info
->ifa_name
: "unicast";
1200 struct sockaddr_storage to
;
1203 // Sanity check: Make sure that if we're sending a query via unicast, we're sending it using our
1204 // anonymous socket created for this purpose, so that we'll receive the response.
1205 // If we use one of the many multicast sockets bound to port 5353 then we may not receive responses reliably.
1206 if (info
&& !mDNSAddrIsDNSMulticast(dst
))
1208 const DNSMessage
*const m
= (DNSMessage
*)msg
;
1209 if ((m
->h
.flags
.b
[0] & kDNSFlag0_QR_Mask
) == kDNSFlag0_QR_Query
)
1210 LogMsg("mDNSPlatformSendUDP: ERROR: Sending query OP from mDNS port to non-mDNS destination %#a:%d", dst
, mDNSVal16(dstPort
));
1213 if (dst
->type
== mDNSAddrType_IPv4
)
1215 struct sockaddr_in
*sin_to
= (struct sockaddr_in
*)&to
;
1216 sin_to
->sin_len
= sizeof(*sin_to
);
1217 sin_to
->sin_family
= AF_INET
;
1218 sin_to
->sin_port
= dstPort
.NotAnInteger
;
1219 sin_to
->sin_addr
.s_addr
= dst
->ip
.v4
.NotAnInteger
;
1220 s
= info
? info
->ss
.sktv4
: m
->p
->unicastsockets
.sktv4
;
1222 else if (dst
->type
== mDNSAddrType_IPv6
)
1224 struct sockaddr_in6
*sin6_to
= (struct sockaddr_in6
*)&to
;
1225 sin6_to
->sin6_len
= sizeof(*sin6_to
);
1226 sin6_to
->sin6_family
= AF_INET6
;
1227 sin6_to
->sin6_port
= dstPort
.NotAnInteger
;
1228 sin6_to
->sin6_flowinfo
= 0;
1229 sin6_to
->sin6_addr
= *(struct in6_addr
*)&dst
->ip
.v6
;
1230 sin6_to
->sin6_scope_id
= info
? info
->scope_id
: 0;
1231 s
= info
? info
->ss
.sktv6
: m
->p
->unicastsockets
.sktv6
;
1235 LogMsg("mDNSPlatformSendUDP: dst is not an IPv4 or IPv6 address!");
1236 return mStatus_BadParamErr
;
1239 // Don't send if it would cause dial on demand connection initiation. As an optimization,
1240 // don't bother consulting reachability API / routing table when sending Multicast DNS
1241 // since we ignore PPP interfaces for mDNS traffic
1242 if (!mDNSAddrIsDNSMulticast(dst
) && AddrRequiresPPPConnection((struct sockaddr
*)&to
))
1244 debugf("mDNSPlatformSendUDP: Surpressing sending to avoid dial-on-demand connection");
1245 return mStatus_NoError
;
1249 verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %p %5s/%ld to %#a:%d skt %d",
1250 InterfaceID
, ifa_name
, dst
->type
, dst
, mDNSVal16(dstPort
), s
);
1252 verbosedebugf("mDNSPlatformSendUDP: NOT sending on InterfaceID %p %5s/%ld (socket of this type not available)",
1253 InterfaceID
, ifa_name
, dst
->type
, dst
, mDNSVal16(dstPort
));
1255 // Note: When sending, mDNSCore may often ask us to send both a v4 multicast packet and then a v6 multicast packet
1256 // If we don't have the corresponding type of socket available, then return mStatus_Invalid
1257 if (s
< 0) return(mStatus_Invalid
);
1259 err
= sendto(s
, msg
, (UInt8
*)end
- (UInt8
*)msg
, 0, (struct sockaddr
*)&to
, to
.ss_len
);
1262 // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
1263 if (!mDNSAddressIsAllDNSLinkGroup(dst
))
1264 if (errno
== EHOSTDOWN
|| errno
== ENETDOWN
|| errno
== EHOSTUNREACH
|| errno
== ENETUNREACH
) return(mStatus_TransientErr
);
1265 // Don't report EHOSTUNREACH in the first three minutes after boot
1266 // This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
1267 // but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
1268 if (errno
== EHOSTUNREACH
&& (mDNSu32
)(mDNSPlatformRawTime()) < (mDNSu32
)(mDNSPlatformOneSecond
* 180)) return(mStatus_TransientErr
);
1269 // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change
1270 if (errno
== EADDRNOTAVAIL
&& m
->p
->NetworkChanged
) return(mStatus_TransientErr
);
1271 LogMsg("mDNSPlatformSendUDP sendto failed to send packet on InterfaceID %p %5s/%ld to %#a:%d skt %d error %d errno %d (%s) %lu",
1272 InterfaceID
, ifa_name
, dst
->type
, dst
, mDNSVal16(dstPort
), s
, err
, errno
, strerror(errno
), (mDNSu32
)(m
->timenow
));
1273 return(mStatus_UnknownErr
);
1276 return(mStatus_NoError
);
1279 mDNSlocal ssize_t
myrecvfrom(const int s
, void *const buffer
, const size_t max
,
1280 struct sockaddr
*const from
, size_t *const fromlen
, mDNSAddr
*dstaddr
, char ifname
[IF_NAMESIZE
], mDNSu8
*ttl
)
1282 static unsigned int numLogMessages
= 0;
1283 struct iovec databuffers
= { (char *)buffer
, max
};
1286 struct cmsghdr
*cmPtr
;
1287 char ancillary
[1024];
1289 *ttl
= 255; // If kernel fails to provide TTL data (e.g. Jaguar doesn't) then assume the TTL was 255 as it should be
1291 // Set up the message
1292 msg
.msg_name
= (caddr_t
)from
;
1293 msg
.msg_namelen
= *fromlen
;
1294 msg
.msg_iov
= &databuffers
;
1296 msg
.msg_control
= (caddr_t
)&ancillary
;
1297 msg
.msg_controllen
= sizeof(ancillary
);
1301 n
= recvmsg(s
, &msg
, 0);
1304 if (errno
!= EWOULDBLOCK
&& numLogMessages
++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned error %d errno %d", s
, n
, errno
);
1307 if (msg
.msg_controllen
< (int)sizeof(struct cmsghdr
))
1309 if (numLogMessages
++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_controllen %d < sizeof(struct cmsghdr) %lu",
1310 s
, msg
.msg_controllen
, sizeof(struct cmsghdr
));
1313 if (msg
.msg_flags
& MSG_CTRUNC
)
1315 if (numLogMessages
++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s
);
1319 *fromlen
= msg
.msg_namelen
;
1321 // Parse each option out of the ancillary data.
1322 for (cmPtr
= CMSG_FIRSTHDR(&msg
); cmPtr
; cmPtr
= CMSG_NXTHDR(&msg
, cmPtr
))
1324 // debugf("myrecvfrom cmsg_level %d cmsg_type %d", cmPtr->cmsg_level, cmPtr->cmsg_type);
1325 if (cmPtr
->cmsg_level
== IPPROTO_IP
&& cmPtr
->cmsg_type
== IP_RECVDSTADDR
)
1327 dstaddr
->type
= mDNSAddrType_IPv4
;
1328 dstaddr
->ip
.v4
.NotAnInteger
= *(u_int32_t
*)CMSG_DATA(cmPtr
);
1330 if (cmPtr
->cmsg_level
== IPPROTO_IP
&& cmPtr
->cmsg_type
== IP_RECVIF
)
1332 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)CMSG_DATA(cmPtr
);
1333 if (sdl
->sdl_nlen
< IF_NAMESIZE
)
1335 mDNSPlatformMemCopy(sdl
->sdl_data
, ifname
, sdl
->sdl_nlen
);
1336 ifname
[sdl
->sdl_nlen
] = 0;
1337 // debugf("IP_RECVIF sdl_index %d, sdl_data %s len %d", sdl->sdl_index, ifname, sdl->sdl_nlen);
1340 if (cmPtr
->cmsg_level
== IPPROTO_IP
&& cmPtr
->cmsg_type
== IP_RECVTTL
)
1342 *ttl
= *(u_char
*)CMSG_DATA(cmPtr
);
1344 if (cmPtr
->cmsg_level
== IPPROTO_IPV6
&& cmPtr
->cmsg_type
== IPV6_PKTINFO
)
1346 struct in6_pktinfo
*ip6_info
= (struct in6_pktinfo
*)CMSG_DATA(cmPtr
);
1347 dstaddr
->type
= mDNSAddrType_IPv6
;
1348 dstaddr
->ip
.v6
= *(mDNSv6Addr
*)&ip6_info
->ipi6_addr
;
1349 myIfIndexToName(ip6_info
->ipi6_ifindex
, ifname
);
1351 if (cmPtr
->cmsg_level
== IPPROTO_IPV6
&& cmPtr
->cmsg_type
== IPV6_HOPLIMIT
)
1353 *ttl
= *(int*)CMSG_DATA(cmPtr
);
1360 // On entry, context points to our CFSocketSet
1361 // If ss->info is NULL, we received this packet on our anonymous unicast socket
1362 // If ss->info is non-NULL, we received this packet on port 5353 on the indicated interface
1363 mDNSlocal
void myCFSocketCallBack(CFSocketRef cfs
, CFSocketCallBackType CallBackType
, CFDataRef address
, const void *data
, void *context
)
1365 mDNSAddr senderAddr
, destAddr
;
1366 mDNSIPPort senderPort
, destPort
= MulticastDNSPort
;
1367 const CFSocketSet
*ss
= (const CFSocketSet
*)context
;
1368 mDNS
*const m
= ss
->m
;
1369 mDNSInterfaceID InterfaceID
= ss
->info
? ss
->info
->ifinfo
.InterfaceID
: mDNSNULL
;
1370 struct sockaddr_storage from
;
1371 size_t fromlen
= sizeof(from
);
1372 char packetifname
[IF_NAMESIZE
] = "";
1373 int err
, s1
= -1, skt
= CFSocketGetNative(cfs
);
1376 (void)address
; // Parameter not used
1377 (void)data
; // Parameter not used
1379 if (CallBackType
!= kCFSocketReadCallBack
)
1380 LogMsg("myCFSocketCallBack: Why is CallBackType %d not kCFSocketReadCallBack?", CallBackType
);
1382 if (cfs
== ss
->cfsv4
) s1
= ss
->sktv4
;
1383 else if (cfs
== ss
->cfsv6
) s1
= ss
->sktv6
;
1385 if (s1
< 0 || s1
!= skt
)
1387 LogMsg("myCFSocketCallBack: s1 %d native socket %d, cfs %p", s1
, skt
, cfs
);
1388 LogMsg("myCFSocketCallBack: cfsv4 %p, sktv4 %d", ss
->cfsv4
, ss
->sktv4
);
1389 LogMsg("myCFSocketCallBack: cfsv6 %p, sktv6 %d", ss
->cfsv6
, ss
->sktv6
);
1393 while ((err
= myrecvfrom(s1
, &m
->imsg
, sizeof(m
->imsg
), (struct sockaddr
*)&from
, &fromlen
, &destAddr
, packetifname
, &ttl
)) >= 0)
1396 if (from
.ss_family
== AF_INET
)
1398 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&from
;
1399 senderAddr
.type
= mDNSAddrType_IPv4
;
1400 senderAddr
.ip
.v4
.NotAnInteger
= sin
->sin_addr
.s_addr
;
1401 senderPort
.NotAnInteger
= sin
->sin_port
;
1403 else if (from
.ss_family
== AF_INET6
)
1405 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)&from
;
1406 senderAddr
.type
= mDNSAddrType_IPv6
;
1407 senderAddr
.ip
.v6
= *(mDNSv6Addr
*)&sin6
->sin6_addr
;
1408 senderPort
.NotAnInteger
= sin6
->sin6_port
;
1412 LogMsg("myCFSocketCallBack from is unknown address family %d", from
.ss_family
);
1416 if (mDNSAddrIsDNSMulticast(&destAddr
))
1418 // Even though we indicated a specific interface in the IP_ADD_MEMBERSHIP call, a weirdness of the
1419 // sockets API means that even though this socket has only officially joined the multicast group
1420 // on one specific interface, the kernel will still deliver multicast packets to it no matter which
1421 // interface they arrive on. According to the official Unix Powers That Be, this is Not A Bug.
1422 // To work around this weirdness, we use the IP_RECVIF option to find the name of the interface
1423 // on which the packet arrived, and ignore the packet if it really arrived on some other interface.
1424 if (!ss
->info
|| !ss
->info
->Exists
)
1426 verbosedebugf("myCFSocketCallBack got multicast packet from %#a to %#a on unicast socket (Ignored)", &senderAddr
, &destAddr
);
1429 else if (!strcmp(ss
->info
->ifa_name
, packetifname
))
1430 verbosedebugf("myCFSocketCallBack got multicast packet from %#a to %#a on interface %#a/%s",
1431 &senderAddr
, &destAddr
, &ss
->info
->ifinfo
.ip
, ss
->info
->ifa_name
);
1434 verbosedebugf("myCFSocketCallBack got multicast packet from %#a to %#a on interface %#a/%s (Ignored -- really arrived on interface %s)",
1435 &senderAddr
, &destAddr
, &ss
->info
->ifinfo
.ip
, ss
->info
->ifa_name
, packetifname
);
1441 // Note: For unicast packets, try to find the matching mDNSCore interface object
1442 // (though we may not be able to, for unicast packets received over something like a PPP link)
1443 NetworkInterfaceInfo
*intf
= m
->HostInterfaces
;
1444 while (intf
&& strcmp(intf
->ifname
, packetifname
)) intf
= intf
->next
;
1445 if (intf
) InterfaceID
= intf
->InterfaceID
;
1448 mDNSCoreReceive(m
, &m
->imsg
, (unsigned char*)&m
->imsg
+ err
, &senderAddr
, senderPort
, &destAddr
, destPort
, InterfaceID
);
1451 if (err
< 0 && (errno
!= EWOULDBLOCK
|| count
== 0))
1453 // Something is busted here.
1454 // CFSocket says there is a packet, but myrecvfrom says there is not.
1455 // Try calling select() to get another opinion.
1456 // Find out about other socket parameter that can help understand why select() says the socket is ready for read
1457 // All of this is racy, as data may have arrived after the call to select()
1458 int save_errno
= errno
;
1462 int solen
= sizeof(int);
1465 FD_SET(s1
, &readfds
);
1466 struct timeval timeout
;
1468 timeout
.tv_usec
= 0;
1469 int selectresult
= select(s1
+1, &readfds
, NULL
, NULL
, &timeout
);
1470 if (getsockopt(s1
, SOL_SOCKET
, SO_ERROR
, &so_error
, &solen
) == -1)
1471 LogMsg("myCFSocketCallBack getsockopt(SO_ERROR) error %d", errno
);
1472 if (getsockopt(s1
, SOL_SOCKET
, SO_NREAD
, &so_nread
, &solen
) == -1)
1473 LogMsg("myCFSocketCallBack getsockopt(SO_NREAD) error %d", errno
);
1474 if (ioctl(s1
, FIONREAD
, &fionread
) == -1)
1475 LogMsg("myCFSocketCallBack ioctl(FIONREAD) error %d", errno
);
1476 static unsigned int numLogMessages
= 0;
1477 if (numLogMessages
++ < 100)
1478 LogMsg("myCFSocketCallBack recvfrom skt %d error %d errno %d (%s) select %d (%spackets waiting) so_error %d so_nread %d fionread %d count %d",
1479 s1
, err
, save_errno
, strerror(save_errno
), selectresult
, FD_ISSET(s1
, &readfds
) ? "" : "*NO* ", so_error
, so_nread
, fionread
, count
);
1480 if (numLogMessages
> 5)
1481 NotifyOfElusiveBug("Flaw in Kernel (select/recvfrom mismatch)", 3375328,
1482 "Alternatively, you can send email to radar-3387020@group.apple.com. "
1483 "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
1485 sleep(1); // After logging this error, rate limit so we don't flood syslog
1489 // TCP socket support for unicast DNS and Dynamic DNS Update
1493 TCPConnectionCallback callback
;
1498 mDNSlocal
void tcpCFSocketCallback(CFSocketRef cfs
, CFSocketCallBackType CallbackType
, CFDataRef address
,
1499 const void *data
, void *context
)
1501 #pragma unused(CallbackType, address, data)
1502 mDNSBool connect
= mDNSfalse
;
1504 tcpInfo_t
*info
= context
;
1505 if (!info
->connected
)
1508 info
->connected
= mDNStrue
; // prevent connected flag from being set in future callbacks
1510 info
->callback(CFSocketGetNative(cfs
), info
->context
, connect
);
1511 // NOTE: the callback may call CloseConnection here, which frees the context structure!
1514 mDNSexport mStatus
mDNSPlatformTCPConnect(const mDNSAddr
*dst
, mDNSOpaque16 dstport
, mDNSInterfaceID InterfaceID
,
1515 TCPConnectionCallback callback
, void *context
, int *descriptor
)
1517 int sd
, on
= 1; // "on" for setsockopt
1518 struct sockaddr_in saddr
;
1519 CFSocketContext cfContext
= { 0, NULL
, 0, 0, 0 };
1522 CFRunLoopSourceRef rls
;
1524 (void)InterfaceID
; //!!!KRS use this if non-zero!!!
1527 if (dst
->type
!= mDNSAddrType_IPv4
)
1529 LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: opperation not supported");
1530 return mStatus_UnknownErr
;
1533 bzero(&saddr
, sizeof(saddr
));
1534 saddr
.sin_family
= AF_INET
;
1535 saddr
.sin_port
= dstport
.NotAnInteger
;
1536 saddr
.sin_len
= sizeof(saddr
);
1537 memcpy(&saddr
.sin_addr
, &dst
->ip
.v4
.NotAnInteger
, sizeof(saddr
.sin_addr
));
1539 // Don't send if it would cause dial on demand connection initiation.
1540 if (AddrRequiresPPPConnection((struct sockaddr
*)&saddr
))
1542 debugf("mDNSPlatformTCPConnect: Surpressing sending to avoid dial-on-demand connection");
1543 return mStatus_UnknownErr
;
1546 sd
= socket(AF_INET
, SOCK_STREAM
, 0);
1547 if (sd
< 3) { LogMsg("mDNSPlatformTCPConnect: socket error %d errno %d (%s)", sd
, errno
, strerror(errno
)); return mStatus_UnknownErr
; }
1550 if (fcntl(sd
, F_SETFL
, O_NONBLOCK
) < 0)
1552 LogMsg("ERROR: setsockopt O_NONBLOCK - %s", strerror(errno
));
1553 return mStatus_UnknownErr
;
1556 // receive interface identifiers
1557 if (setsockopt(sd
, IPPROTO_IP
, IP_RECVIF
, &on
, sizeof(on
)) < 0)
1559 LogMsg("setsockopt IP_RECVIF - %s", strerror(errno
));
1560 return mStatus_UnknownErr
;
1562 // set up CF wrapper, add to Run Loop
1563 info
= mallocL("mDNSPlatformTCPConnect", sizeof(tcpInfo_t
));
1564 info
->callback
= callback
;
1565 info
->context
= context
;
1566 cfContext
.info
= info
;
1567 sr
= CFSocketCreateWithNative(kCFAllocatorDefault
, sd
, kCFSocketReadCallBack
| kCFSocketConnectCallBack
,
1568 tcpCFSocketCallback
, &cfContext
);
1571 LogMsg("ERROR: mDNSPlatformTCPConnect - CFSocketRefCreateWithNative failed");
1572 freeL("mDNSPlatformTCPConnect", info
);
1573 return mStatus_UnknownErr
;
1576 rls
= CFSocketCreateRunLoopSource(kCFAllocatorDefault
, sr
, 0);
1579 LogMsg("ERROR: mDNSPlatformTCPConnect - CFSocketCreateRunLoopSource failed");
1580 freeL("mDNSPlatformTCPConnect", info
);
1581 return mStatus_UnknownErr
;
1584 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
);
1587 // initiate connection wth peer
1588 if (connect(sd
, (struct sockaddr
*)&saddr
, sizeof(saddr
)) < 0)
1590 if (errno
== EINPROGRESS
)
1592 info
->connected
= 0;
1594 return mStatus_ConnPending
;
1596 LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: %s", strerror(errno
));
1597 freeL("mDNSPlatformTCPConnect", info
);
1598 CFSocketInvalidate(sr
); // Note: Also closes the underlying socket
1599 return mStatus_ConnFailed
;
1601 info
->connected
= 1;
1603 return mStatus_ConnEstablished
;
1606 mDNSexport
void mDNSPlatformTCPCloseConnection(int sd
)
1608 CFSocketContext cfContext
;
1612 if (sd
< 3) LogMsg("mDNSPlatformTCPCloseConnection: ERROR sd %d < 3", sd
);
1614 // Get the CFSocket for the descriptor
1615 sr
= CFSocketCreateWithNative(kCFAllocatorDefault
, sd
, kCFSocketNoCallBack
, NULL
, NULL
);
1616 if (!sr
) { LogMsg("ERROR: mDNSPlatformTCPCloseConnection - CFSocketCreateWithNative returned NULL"); return; }
1618 CFSocketGetContext(sr
, &cfContext
);
1619 if (!cfContext
.info
)
1621 LogMsg("ERROR: mDNSPlatformTCPCloseConnection - could not retreive tcpInfo from socket context");
1625 CFRelease(sr
); // this only releases the copy we allocated with CreateWithNative above
1627 info
= cfContext
.info
;
1629 // Note: MUST NOT close the underlying native BSD socket.
1630 // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately,
1631 // because it first has to unhook the sockets from its select() call, before it can safely close them.
1632 CFSocketInvalidate(sr
);
1634 freeL("mDNSPlatformTCPCloseConnection", info
);
1637 mDNSexport
int mDNSPlatformReadTCP(int sd
, void *buf
, int buflen
)
1639 int nread
= recv(sd
, buf
, buflen
, 0);
1642 if (errno
== EAGAIN
) return 0; // no data available (call would block)
1643 LogMsg("ERROR: mDNSPlatformReadTCP - recv: %s", strerror(errno
));
1649 mDNSexport
int mDNSPlatformWriteTCP(int sd
, const char *msg
, int len
)
1651 int nsent
= send(sd
, msg
, len
, 0);
1655 if (errno
== EAGAIN
) return 0; // blocked
1656 LogMsg("ERROR: mDNSPlatformWriteTCP - sendL %s", strerror(errno
));
1662 // This gets the text of the field currently labelled "Computer Name" in the Sharing Prefs Control Panel
1663 mDNSlocal
void GetUserSpecifiedFriendlyComputerName(domainlabel
*const namelabel
)
1665 CFStringEncoding encoding
= kCFStringEncodingUTF8
;
1666 CFStringRef cfs
= SCDynamicStoreCopyComputerName(NULL
, &encoding
);
1669 CFStringGetPascalString(cfs
, namelabel
->c
, sizeof(*namelabel
), kCFStringEncodingUTF8
);
1674 // This gets the text of the field currently labelled "Local Hostname" in the Sharing Prefs Control Panel
1675 mDNSlocal
void GetUserSpecifiedLocalHostName(domainlabel
*const namelabel
)
1677 CFStringRef cfs
= SCDynamicStoreCopyLocalHostName(NULL
);
1680 CFStringGetPascalString(cfs
, namelabel
->c
, sizeof(*namelabel
), kCFStringEncodingUTF8
);
1685 mDNSlocal mDNSBool
DDNSSettingEnabled(CFDictionaryRef dict
)
1688 CFNumberRef state
= CFDictionaryGetValue(dict
, CFSTR("Enabled"));
1689 if (!state
) return mDNSfalse
;
1690 if (!CFNumberGetValue(state
, kCFNumberSInt32Type
, &val
)) { LogMsg("ERROR: DDNSSettingEnabled - CFNumberGetValue"); return mDNSfalse
; }
1691 return val
? mDNStrue
: mDNSfalse
;
1694 mDNSlocal
void GetUserSpecifiedDDNSConfig(domainname
*const fqdn
, domainname
*const regDomain
, CFArrayRef
*const browseDomains
)
1696 char buf
[MAX_ESCAPED_DOMAIN_NAME
];
1699 regDomain
->c
[0] = 0;
1701 *browseDomains
= NULL
;
1703 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:GetUserSpecifiedDDNSConfig"), NULL
, NULL
);
1706 CFDictionaryRef dict
= SCDynamicStoreCopyValue(store
, CFSTR("Setup:/Network/DynamicDNS"));
1709 CFArrayRef fqdnArray
= CFDictionaryGetValue(dict
, CFSTR("HostNames"));
1710 if (fqdnArray
&& CFArrayGetCount(fqdnArray
) > 0)
1712 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
1713 if (fqdnDict
&& DDNSSettingEnabled(fqdnDict
))
1715 CFStringRef name
= CFDictionaryGetValue(fqdnDict
, CFSTR("Domain"));
1718 if (!CFStringGetCString(name
, buf
, sizeof(buf
), kCFStringEncodingUTF8
) ||
1719 !MakeDomainNameFromDNSNameString(fqdn
, buf
) || !fqdn
->c
[0])
1720 LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS host name: %s", buf
[0] ? buf
: "(unknown)");
1721 else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS host name: %s", buf
);
1726 CFArrayRef regArray
= CFDictionaryGetValue(dict
, CFSTR("RegistrationDomains"));
1727 if (regArray
&& CFArrayGetCount(regArray
) > 0)
1729 CFDictionaryRef regDict
= CFArrayGetValueAtIndex(regArray
, 0);
1730 if (regDict
&& DDNSSettingEnabled(regDict
))
1732 CFStringRef name
= CFDictionaryGetValue(regDict
, CFSTR("Domain"));
1735 if (!CFStringGetCString(name
, buf
, sizeof(buf
), kCFStringEncodingUTF8
) ||
1736 !MakeDomainNameFromDNSNameString(regDomain
, buf
) || !regDomain
->c
[0])
1737 LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS registration domain: %s", buf
[0] ? buf
: "(unknown)");
1738 else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS registration zone: %s", buf
);
1742 CFArrayRef browseArray
= CFDictionaryGetValue(dict
, CFSTR("BrowseDomains"));
1743 if (browseArray
&& CFArrayGetCount(browseArray
) > 0)
1745 CFRetain(browseArray
);
1746 *browseDomains
= browseArray
;
1754 mDNSlocal
void SetDDNSNameStatus(domainname
*const dname
, mStatus status
)
1756 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:SetDDNSNameStatus"), NULL
, NULL
);
1759 char uname
[MAX_ESCAPED_DOMAIN_NAME
];
1760 ConvertDomainNameToCString(dname
, uname
);
1766 if (!(*(p
+1)) && *p
== '.') *p
= 0; // if last character, strip trailing dot
1770 const void *StatusKey
= CFSTR("Status");
1771 const void *StatusVal
= CFNumberCreate(NULL
, kCFNumberSInt32Type
, &status
); // CFNumberRef
1772 const void *StatusDict
= CFDictionaryCreate(NULL
, &StatusKey
, &StatusVal
, 1, NULL
, NULL
);
1774 const void *HostKey
= CFStringCreateWithCString(NULL
, uname
, kCFStringEncodingUTF8
);
1775 const void *HostDict
= CFDictionaryCreate(NULL
, &HostKey
, &StatusDict
, 1, NULL
, NULL
);
1777 const void *StateKey
= CFSTR("HostNames"); // CFStringRef
1778 CFDictionaryRef StateDict
= CFDictionaryCreate(NULL
, &StateKey
, &HostDict
, 1, NULL
, NULL
);
1779 SCDynamicStoreSetValue(store
, CFSTR("State:/Network/DynamicDNS"), StateDict
);
1781 CFRelease(StateDict
);
1782 CFRelease(StateKey
);
1783 CFRelease(HostDict
);
1785 CFRelease(StatusDict
);
1786 CFRelease(StatusVal
);
1787 CFRelease(StatusKey
);
1792 // If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
1793 // If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
1794 mDNSlocal mStatus
SetupSocket(mDNS
*const m
, CFSocketSet
*cp
, mDNSBool mcast
, const mDNSAddr
*ifaddr
, u_short sa_family
)
1796 int *s
= (sa_family
== AF_INET
) ? &cp
->sktv4
: &cp
->sktv6
;
1797 CFSocketRef
*c
= (sa_family
== AF_INET
) ? &cp
->cfsv4
: &cp
->cfsv6
;
1798 CFRunLoopSourceRef
*r
= (sa_family
== AF_INET
) ? &cp
->rlsv4
: &cp
->rlsv6
;
1800 const int twofivefive
= 255;
1801 mStatus err
= mStatus_NoError
;
1802 char *errstr
= mDNSNULL
;
1804 mDNSIPPort port
= (mcast
| m
->CanReceiveUnicastOn5353
) ? MulticastDNSPort
: zeroIPPort
;
1806 if (*s
>= 0) { LogMsg("SetupSocket ERROR: socket %d is already set", *s
); return(-1); }
1807 if (*c
) { LogMsg("SetupSocket ERROR: CFSocketRef %p is already set", *c
); return(-1); }
1809 // Open the socket...
1810 int skt
= socket(sa_family
, SOCK_DGRAM
, IPPROTO_UDP
);
1811 if (skt
< 3) { LogMsg("SetupSocket: socket error %d errno %d (%s)", skt
, errno
, strerror(errno
)); return(skt
); }
1813 // ... with a shared UDP port, if it's for multicast receiving
1814 if (port
.NotAnInteger
) err
= setsockopt(skt
, SOL_SOCKET
, SO_REUSEPORT
, &on
, sizeof(on
));
1815 if (err
< 0) { errstr
= "setsockopt - SO_REUSEPORT"; goto fail
; }
1817 if (sa_family
== AF_INET
)
1819 // We want to receive destination addresses
1820 err
= setsockopt(skt
, IPPROTO_IP
, IP_RECVDSTADDR
, &on
, sizeof(on
));
1821 if (err
< 0) { errstr
= "setsockopt - IP_RECVDSTADDR"; goto fail
; }
1823 // We want to receive interface identifiers
1824 err
= setsockopt(skt
, IPPROTO_IP
, IP_RECVIF
, &on
, sizeof(on
));
1825 if (err
< 0) { errstr
= "setsockopt - IP_RECVIF"; goto fail
; }
1827 // We want to receive packet TTL value so we can check it
1828 err
= setsockopt(skt
, IPPROTO_IP
, IP_RECVTTL
, &on
, sizeof(on
));
1829 // We ignore errors here -- we already know Jaguar doesn't support this, but we can get by without it
1831 // Add multicast group membership on this interface, if it's for multicast receiving
1834 struct in_addr addr
= { ifaddr
->ip
.v4
.NotAnInteger
};
1836 imr
.imr_multiaddr
.s_addr
= AllDNSLinkGroupv4
.NotAnInteger
;
1837 imr
.imr_interface
= addr
;
1838 err
= setsockopt(skt
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
, &imr
, sizeof(imr
));
1839 if (err
< 0) { errstr
= "setsockopt - IP_ADD_MEMBERSHIP"; goto fail
; }
1841 // Specify outgoing interface too
1842 err
= setsockopt(skt
, IPPROTO_IP
, IP_MULTICAST_IF
, &addr
, sizeof(addr
));
1843 if (err
< 0) { errstr
= "setsockopt - IP_MULTICAST_IF"; goto fail
; }
1846 // Send unicast packets with TTL 255
1847 err
= setsockopt(skt
, IPPROTO_IP
, IP_TTL
, &twofivefive
, sizeof(twofivefive
));
1848 if (err
< 0) { errstr
= "setsockopt - IP_TTL"; goto fail
; }
1850 // And multicast packets with TTL 255 too
1851 err
= setsockopt(skt
, IPPROTO_IP
, IP_MULTICAST_TTL
, &twofivefive
, sizeof(twofivefive
));
1852 if (err
< 0) { errstr
= "setsockopt - IP_MULTICAST_TTL"; goto fail
; }
1854 // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
1855 const int ip_tosbits
= IPTOS_LOWDELAY
| IPTOS_THROUGHPUT
;
1856 err
= setsockopt(skt
, IPPROTO_IP
, IP_TOS
, &ip_tosbits
, sizeof(ip_tosbits
));
1857 if (err
< 0) { errstr
= "setsockopt - IP_TOS"; goto fail
; }
1859 // And start listening for packets
1860 struct sockaddr_in listening_sockaddr
;
1861 listening_sockaddr
.sin_family
= AF_INET
;
1862 listening_sockaddr
.sin_port
= port
.NotAnInteger
;
1863 listening_sockaddr
.sin_addr
.s_addr
= 0; // Want to receive multicasts AND unicasts on this socket
1864 err
= bind(skt
, (struct sockaddr
*) &listening_sockaddr
, sizeof(listening_sockaddr
));
1865 if (err
) { errstr
= "bind"; goto fail
; }
1867 else if (sa_family
== AF_INET6
)
1869 // We want to receive destination addresses and receive interface identifiers
1870 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_PKTINFO
, &on
, sizeof(on
));
1871 if (err
< 0) { errstr
= "setsockopt - IPV6_PKTINFO"; goto fail
; }
1873 // We want to receive packet hop count value so we can check it
1874 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_HOPLIMIT
, &on
, sizeof(on
));
1875 if (err
< 0) { errstr
= "setsockopt - IPV6_HOPLIMIT"; goto fail
; }
1877 // We want to receive only IPv6 packets, without this option, we may
1878 // get IPv4 addresses as mapped addresses.
1879 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_V6ONLY
, &on
, sizeof(on
));
1880 if (err
< 0) { errstr
= "setsockopt - IPV6_V6ONLY"; goto fail
; }
1884 // Add multicast group membership on this interface, if it's for multicast receiving
1885 int interface_id
= if_nametoindex(cp
->info
->ifa_name
);
1886 struct ipv6_mreq i6mr
;
1887 i6mr
.ipv6mr_interface
= interface_id
;
1888 i6mr
.ipv6mr_multiaddr
= *(struct in6_addr
*)&AllDNSLinkGroupv6
;
1889 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
, &i6mr
, sizeof(i6mr
));
1890 if (err
< 0) { errstr
= "setsockopt - IPV6_JOIN_GROUP"; goto fail
; }
1892 // Specify outgoing interface too
1893 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
, &interface_id
, sizeof(interface_id
));
1894 if (err
< 0) { errstr
= "setsockopt - IPV6_MULTICAST_IF"; goto fail
; }
1897 // Send unicast packets with TTL 255
1898 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, &twofivefive
, sizeof(twofivefive
));
1899 if (err
< 0) { errstr
= "setsockopt - IPV6_UNICAST_HOPS"; goto fail
; }
1901 // And multicast packets with TTL 255 too
1902 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_MULTICAST_HOPS
, &twofivefive
, sizeof(twofivefive
));
1903 if (err
< 0) { errstr
= "setsockopt - IPV6_MULTICAST_HOPS"; goto fail
; }
1905 // Note: IPV6_TCLASS appears not to be implemented on OS X right now (or indeed on ANY version of Unix?)
1907 // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
1908 int tclass
= IPTOS_LOWDELAY
| IPTOS_THROUGHPUT
; // This may not be right (since tclass is not implemented on OS X, I can't test it)
1909 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_TCLASS
, &tclass
, sizeof(tclass
));
1910 if (err
< 0) { errstr
= "setsockopt - IPV6_TCLASS"; goto fail
; }
1913 // Want to receive our own packets
1914 err
= setsockopt(skt
, IPPROTO_IPV6
, IPV6_MULTICAST_LOOP
, &on
, sizeof(on
));
1915 if (err
< 0) { errstr
= "setsockopt - IPV6_MULTICAST_LOOP"; goto fail
; }
1917 // And start listening for packets
1918 struct sockaddr_in6 listening_sockaddr6
;
1919 bzero(&listening_sockaddr6
, sizeof(listening_sockaddr6
));
1920 listening_sockaddr6
.sin6_len
= sizeof(listening_sockaddr6
);
1921 listening_sockaddr6
.sin6_family
= AF_INET6
;
1922 listening_sockaddr6
.sin6_port
= port
.NotAnInteger
;
1923 listening_sockaddr6
.sin6_flowinfo
= 0;
1924 // listening_sockaddr6.sin6_addr = IN6ADDR_ANY_INIT; // Want to receive multicasts AND unicasts on this socket
1925 listening_sockaddr6
.sin6_scope_id
= 0;
1926 err
= bind(skt
, (struct sockaddr
*) &listening_sockaddr6
, sizeof(listening_sockaddr6
));
1927 if (err
) { errstr
= "bind"; goto fail
; }
1930 fcntl(skt
, F_SETFL
, fcntl(skt
, F_GETFL
, 0) | O_NONBLOCK
); // set non-blocking
1932 CFSocketContext myCFSocketContext
= { 0, cp
, NULL
, NULL
, NULL
};
1933 *c
= CFSocketCreateWithNative(kCFAllocatorDefault
, *s
, kCFSocketReadCallBack
, myCFSocketCallBack
, &myCFSocketContext
);
1934 *r
= CFSocketCreateRunLoopSource(kCFAllocatorDefault
, *c
, 0);
1935 CFRunLoopAddSource(CFRunLoopGetCurrent(), *r
, kCFRunLoopDefaultMode
);
1940 LogMsg("%s error %ld errno %d (%s)", errstr
, err
, errno
, strerror(errno
));
1941 if (!strcmp(errstr
, "bind") && errno
== EADDRINUSE
)
1942 NotifyOfElusiveBug("Setsockopt SO_REUSEPORT failed", 3814904,
1943 "Alternatively, you can send email to radar-3387020@group.apple.com. "
1944 "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
1949 mDNSlocal mStatus
SetupAddr(mDNSAddr
*ip
, const struct sockaddr
*const sa
)
1951 if (!sa
) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid
); }
1953 if (sa
->sa_family
== AF_INET
)
1955 struct sockaddr_in
*ifa_addr
= (struct sockaddr_in
*)sa
;
1956 ip
->type
= mDNSAddrType_IPv4
;
1957 ip
->ip
.v4
.NotAnInteger
= ifa_addr
->sin_addr
.s_addr
;
1958 return(mStatus_NoError
);
1961 if (sa
->sa_family
== AF_INET6
)
1963 struct sockaddr_in6
*ifa_addr
= (struct sockaddr_in6
*)sa
;
1964 ip
->type
= mDNSAddrType_IPv6
;
1965 if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr
->sin6_addr
)) ifa_addr
->sin6_addr
.__u6_addr
.__u6_addr16
[1] = 0;
1966 ip
->ip
.v6
= *(mDNSv6Addr
*)&ifa_addr
->sin6_addr
;
1967 return(mStatus_NoError
);
1970 LogMsg("SetupAddr invalid sa_family %d", sa
->sa_family
);
1971 return(mStatus_Invalid
);
1974 mDNSlocal mDNSEthAddr
GetBSSID(char *ifa_name
)
1976 mDNSEthAddr eth
= zeroEthAddr
;
1977 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:GetBSSID"), NULL
, NULL
);
1980 CFStringRef entityname
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("State:/Network/Interface/%s/AirPort"), ifa_name
);
1983 CFDictionaryRef dict
= SCDynamicStoreCopyValue(store
, entityname
);
1986 CFRange range
= { 0, 6 }; // Offset, length
1987 CFDataRef data
= CFDictionaryGetValue(dict
, CFSTR("BSSID"));
1988 if (data
&& CFDataGetLength(data
) == 6) CFDataGetBytes(data
, range
, eth
.b
);
1991 CFRelease(entityname
);
1998 mDNSlocal NetworkInterfaceInfoOSX
*AddInterfaceToList(mDNS
*const m
, struct ifaddrs
*ifa
, mDNSs32 utc
)
2000 mDNSu32 scope_id
= if_nametoindex(ifa
->ifa_name
);
2001 mDNSEthAddr bssid
= GetBSSID(ifa
->ifa_name
);
2004 if (SetupAddr(&ip
, ifa
->ifa_addr
) != mStatus_NoError
) return(NULL
);
2005 if (SetupAddr(&mask
, ifa
->ifa_netmask
) != mStatus_NoError
) return(NULL
);
2007 NetworkInterfaceInfoOSX
**p
;
2008 for (p
= &m
->p
->InterfaceList
; *p
; p
= &(*p
)->next
)
2009 if (scope_id
== (*p
)->scope_id
&& mDNSSameAddress(&ip
, &(*p
)->ifinfo
.ip
) && mDNSSameEthAddress(&bssid
, &(*p
)->BSSID
))
2011 debugf("AddInterfaceToList: Found existing interface %lu %.6a with address %#a at %p", scope_id
, &bssid
, &ip
, *p
);
2012 (*p
)->Exists
= mDNStrue
;
2016 NetworkInterfaceInfoOSX
*i
= (NetworkInterfaceInfoOSX
*)mallocL("NetworkInterfaceInfoOSX", sizeof(*i
));
2017 debugf("AddInterfaceToList: Making new interface %lu %.6a with address %#a at %p", scope_id
, &bssid
, &ip
, i
);
2018 if (!i
) return(mDNSNULL
);
2019 bzero(i
, sizeof(NetworkInterfaceInfoOSX
));
2020 i
->ifa_name
= (char *)mallocL("NetworkInterfaceInfoOSX name", strlen(ifa
->ifa_name
) + 1);
2021 if (!i
->ifa_name
) { freeL("NetworkInterfaceInfoOSX", i
); return(mDNSNULL
); }
2022 strcpy(i
->ifa_name
, ifa
->ifa_name
);
2024 i
->ifinfo
.InterfaceID
= mDNSNULL
;
2026 i
->ifinfo
.mask
= mask
;
2027 strncpy(i
->ifinfo
.ifname
, ifa
->ifa_name
, sizeof(i
->ifinfo
.ifname
));
2028 i
->ifinfo
.ifname
[sizeof(i
->ifinfo
.ifname
)-1] = 0;
2029 i
->ifinfo
.Advertise
= m
->AdvertiseLocalAddresses
;
2030 i
->ifinfo
.McastTxRx
= mDNSfalse
; // For now; will be set up later at the end of UpdateInterfaceList
2033 i
->Exists
= mDNStrue
;
2035 i
->scope_id
= scope_id
;
2037 i
->sa_family
= ifa
->ifa_addr
->sa_family
;
2038 i
->Multicast
= (ifa
->ifa_flags
& IFF_MULTICAST
) && !(ifa
->ifa_flags
& IFF_POINTOPOINT
);
2042 i
->ss
.sktv4
= i
->ss
.sktv6
= -1;
2043 i
->ss
.cfsv4
= i
->ss
.cfsv6
= NULL
;
2044 i
->ss
.rlsv4
= i
->ss
.rlsv6
= NULL
;
2050 mDNSlocal NetworkInterfaceInfoOSX
*FindRoutableIPv4(mDNS
*const m
, mDNSu32 scope_id
)
2052 NetworkInterfaceInfoOSX
*i
;
2053 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2054 if (i
->Exists
&& i
->scope_id
== scope_id
&& i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
)
2055 if (!(i
->ifinfo
.ip
.ip
.v4
.b
[0] == 169 && i
->ifinfo
.ip
.ip
.v4
.b
[1] == 254))
2060 mDNSlocal mStatus
UpdateInterfaceList(mDNS
*const m
, mDNSs32 utc
)
2062 mDNSBool foundav4
= mDNSfalse
;
2063 mDNSBool foundav6
= mDNSfalse
;
2064 struct ifaddrs
*ifa
= myGetIfAddrs(1);
2065 struct ifaddrs
*v4Loopback
= NULL
;
2066 struct ifaddrs
*v6Loopback
= NULL
;
2067 mDNSEthAddr PrimaryMAC
= zeroEthAddr
;
2068 char defaultname
[32];
2069 int InfoSocket
= socket(AF_INET6
, SOCK_DGRAM
, 0);
2070 if (InfoSocket
< 3) LogMsg("UpdateInterfaceList: InfoSocket error %d errno %d (%s)", InfoSocket
, errno
, strerror(errno
));
2071 if (m
->SleepState
) ifa
= NULL
;
2075 #if LIST_ALL_INTERFACES
2076 if (ifa
->ifa_addr
->sa_family
== AF_APPLETALK
)
2077 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_APPLETALK",
2078 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2079 else if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
2080 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_LINK",
2081 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2082 else if (ifa
->ifa_addr
->sa_family
!= AF_INET
&& ifa
->ifa_addr
->sa_family
!= AF_INET6
)
2083 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)",
2084 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2085 if (!(ifa
->ifa_flags
& IFF_UP
))
2086 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_UP",
2087 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2088 if (!(ifa
->ifa_flags
& IFF_MULTICAST
))
2089 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_MULTICAST",
2090 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2091 if (ifa
->ifa_flags
& IFF_POINTOPOINT
)
2092 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_POINTOPOINT",
2093 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2094 if (ifa
->ifa_flags
& IFF_LOOPBACK
)
2095 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_LOOPBACK",
2096 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
);
2099 if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
2101 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
2102 if (sdl
->sdl_type
== IFT_ETHER
&& sdl
->sdl_alen
== sizeof(PrimaryMAC
) && mDNSSameEthAddress(&PrimaryMAC
, &zeroEthAddr
))
2103 mDNSPlatformMemCopy(sdl
->sdl_data
+ sdl
->sdl_nlen
, PrimaryMAC
.b
, 6);
2106 if (ifa
->ifa_flags
& IFF_UP
&& ifa
->ifa_addr
)
2107 if (ifa
->ifa_addr
->sa_family
== AF_INET
|| ifa
->ifa_addr
->sa_family
== AF_INET6
)
2109 if (!ifa
->ifa_netmask
)
2112 SetupAddr(&ip
, ifa
->ifa_addr
);
2113 LogMsg("getifaddrs: ifa_netmask is NULL for %5s(%d) Flags %04X Family %2d %#a",
2114 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
, &ip
);
2116 else if (ifa
->ifa_addr
->sa_family
!= ifa
->ifa_netmask
->sa_family
)
2119 SetupAddr(&ip
, ifa
->ifa_addr
);
2120 LogMsg("getifaddrs ifa_netmask for %5s(%d) Flags %04X Family %2d %#a has different family: %d",
2121 ifa
->ifa_name
, if_nametoindex(ifa
->ifa_name
), ifa
->ifa_flags
, ifa
->ifa_addr
->sa_family
, &ip
, ifa
->ifa_netmask
->sa_family
);
2125 int ifru_flags6
= 0;
2126 if (ifa
->ifa_addr
->sa_family
== AF_INET6
&& InfoSocket
>= 0)
2128 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
2129 struct in6_ifreq ifr6
;
2130 bzero((char *)&ifr6
, sizeof(ifr6
));
2131 strncpy(ifr6
.ifr_name
, ifa
->ifa_name
, sizeof(ifr6
.ifr_name
));
2132 ifr6
.ifr_addr
= *sin6
;
2133 if (ioctl(InfoSocket
, SIOCGIFAFLAG_IN6
, &ifr6
) != -1)
2134 ifru_flags6
= ifr6
.ifr_ifru
.ifru_flags6
;
2135 verbosedebugf("%s %.16a %04X %04X", ifa
->ifa_name
, &sin6
->sin6_addr
, ifa
->ifa_flags
, ifru_flags6
);
2137 if (!(ifru_flags6
& (IN6_IFF_NOTREADY
| IN6_IFF_DETACHED
| IN6_IFF_DEPRECATED
| IN6_IFF_TEMPORARY
)))
2139 if (ifa
->ifa_flags
& IFF_LOOPBACK
)
2140 if (ifa
->ifa_addr
->sa_family
== AF_INET
) v4Loopback
= ifa
;
2141 else v6Loopback
= ifa
;
2144 AddInterfaceToList(m
, ifa
, utc
);
2145 if (ifa
->ifa_addr
->sa_family
== AF_INET
) foundav4
= mDNStrue
;
2146 else foundav6
= mDNStrue
;
2151 ifa
= ifa
->ifa_next
;
2154 // For efficiency, we don't register a loopback interface when other interfaces of that family are available
2155 if (!foundav4
&& v4Loopback
) AddInterfaceToList(m
, v4Loopback
, utc
);
2156 if (!foundav6
&& v6Loopback
) AddInterfaceToList(m
, v6Loopback
, utc
);
2158 // Now the list is complete, set the McastTxRx setting for each interface.
2159 // We always send and receive using IPv4.
2160 // To reduce traffic, we send and receive using IPv6 only on interfaces that have no routable IPv4 address.
2161 // Having a routable IPv4 address assigned is a reasonable indicator of being on a large configured network,
2162 // which means there's a good chance that most or all the other devices on that network should also have v4.
2163 // 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.
2164 // At this time, reducing the packet rate is more important than v6-only devices on a large configured network,
2165 // so we are willing to make that sacrifice.
2166 NetworkInterfaceInfoOSX
*i
;
2167 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2170 mDNSBool txrx
= i
->Multicast
&& ((i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
) || !FindRoutableIPv4(m
, i
->scope_id
));
2171 if (i
->ifinfo
.McastTxRx
!= txrx
)
2173 i
->ifinfo
.McastTxRx
= txrx
;
2174 i
->Exists
= 2; // State change; need to deregister and reregister this interface
2177 if (InfoSocket
>= 0) close(InfoSocket
);
2179 mDNS_snprintf(defaultname
, sizeof(defaultname
), "Macintosh-%02X%02X%02X%02X%02X%02X",
2180 PrimaryMAC
.b
[0], PrimaryMAC
.b
[1], PrimaryMAC
.b
[2], PrimaryMAC
.b
[3], PrimaryMAC
.b
[4], PrimaryMAC
.b
[5]);
2182 // Set up the nice label
2183 domainlabel nicelabel
;
2185 GetUserSpecifiedFriendlyComputerName(&nicelabel
);
2186 if (nicelabel
.c
[0] == 0)
2188 LogMsg("Couldn't read user-specified Computer Name; using default “%s” instead", defaultname
);
2189 MakeDomainLabelFromLiteralString(&nicelabel
, defaultname
);
2192 // Set up the RFC 1034-compliant label
2193 domainlabel hostlabel
;
2195 GetUserSpecifiedLocalHostName(&hostlabel
);
2196 if (hostlabel
.c
[0] == 0)
2198 LogMsg("Couldn't read user-specified local hostname; using default “%s.local” instead", defaultname
);
2199 MakeDomainLabelFromLiteralString(&hostlabel
, defaultname
);
2202 if (SameDomainLabel(m
->p
->usernicelabel
.c
, nicelabel
.c
))
2203 debugf("Usernicelabel (%#s) unchanged since last time; not changing m->nicelabel (%#s)", m
->p
->usernicelabel
.c
, m
->nicelabel
.c
);
2206 debugf("Updating m->nicelabel to %#s", nicelabel
.c
);
2207 m
->p
->usernicelabel
= m
->nicelabel
= nicelabel
;
2210 if (SameDomainLabel(m
->p
->userhostlabel
.c
, hostlabel
.c
))
2211 debugf("Userhostlabel (%#s) unchanged since last time; not changing m->hostlabel (%#s)", m
->p
->userhostlabel
.c
, m
->hostlabel
.c
);
2214 debugf("Updating m->hostlabel to %#s", hostlabel
.c
);
2215 m
->p
->userhostlabel
= m
->hostlabel
= hostlabel
;
2219 return(mStatus_NoError
);
2222 mDNSlocal
int CountMaskBits(mDNSAddr
*mask
)
2224 int i
= 0, bits
= 0;
2225 int bytes
= mask
->type
== mDNSAddrType_IPv4
? 4 : mask
->type
== mDNSAddrType_IPv6
? 16 : 0;
2228 mDNSu8 b
= mask
->ip
.v6
.b
[i
++];
2229 while (b
& 0x80) { bits
++; b
<<= 1; }
2232 while (i
< bytes
) if (mask
->ip
.v6
.b
[i
++]) return(-1);
2236 // returns count of non-link local V4 addresses registered
2237 mDNSlocal
int SetupActiveInterfaces(mDNS
*const m
, mDNSs32 utc
)
2239 NetworkInterfaceInfoOSX
*i
;
2241 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2244 NetworkInterfaceInfo
*n
= &i
->ifinfo
;
2245 NetworkInterfaceInfoOSX
*primary
= SearchForInterfaceByName(m
, i
->ifa_name
, i
->sa_family
);
2246 if (!primary
) LogMsg("SetupActiveInterfaces ERROR! SearchForInterfaceByName didn't find %s", i
->ifa_name
);
2248 if (n
->InterfaceID
&& n
->InterfaceID
!= (mDNSInterfaceID
)primary
) // Sanity check
2250 LogMsg("SetupActiveInterfaces ERROR! n->InterfaceID %p != primary %p", n
->InterfaceID
, primary
);
2251 n
->InterfaceID
= mDNSNULL
;
2254 if (!n
->InterfaceID
)
2256 // NOTE: If n->InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
2257 // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
2258 // If n->InterfaceID is NOT set, then we haven't registered it and we should not try to deregister it
2259 n
->InterfaceID
= (mDNSInterfaceID
)primary
;
2260 // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away.
2261 // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds.
2262 // 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.
2263 mDNSBool flapping
= (utc
- i
->LastSeen
> 0 && utc
- i
->LastSeen
< 60);
2264 mDNS_RegisterInterface(m
, n
, flapping
? mDNSPlatformOneSecond
* 5 : 0);
2265 if (i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
&& (i
->ifinfo
.ip
.ip
.v4
.b
[0] != 169 || i
->ifinfo
.ip
.ip
.v4
.b
[1] != 254)) count
++;
2266 LogOperation("SetupActiveInterfaces: Registered %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s",
2267 i
->ifa_name
, i
->scope_id
, &i
->BSSID
, primary
, &n
->ip
, CountMaskBits(&n
->mask
),
2268 flapping
? " (Flapping)" : "", n
->InterfaceActive
? " (Primary)" : "");
2272 debugf("SetupActiveInterfaces: No Tx/Rx on %5s(%lu) %.6a InterfaceID %p %#a", i
->ifa_name
, i
->scope_id
, &i
->BSSID
, primary
, &n
->ip
);
2275 if (i
->sa_family
== AF_INET
&& primary
->ss
.sktv4
== -1)
2277 mStatus err
= SetupSocket(m
, &primary
->ss
, mDNStrue
, &i
->ifinfo
.ip
, AF_INET
);
2278 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
));
2279 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
));
2282 if (i
->sa_family
== AF_INET6
&& primary
->ss
.sktv6
== -1)
2284 mStatus err
= SetupSocket(m
, &primary
->ss
, mDNStrue
, &i
->ifinfo
.ip
, AF_INET6
);
2285 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
));
2286 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
));
2293 mDNSlocal
void MarkAllInterfacesInactive(mDNS
*const m
, mDNSs32 utc
)
2295 NetworkInterfaceInfoOSX
*i
;
2296 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2298 if (i
->Exists
) i
->LastSeen
= utc
;
2299 i
->Exists
= mDNSfalse
;
2303 mDNSlocal
void CloseRunLoopSourceSocket(CFRunLoopSourceRef rls
, CFSocketRef cfs
)
2305 // Note: CFSocketInvalidate also closes the underlying socket for us
2306 // Comments show retain counts (obtained via CFGetRetainCount()) after each call. rls 3 cfs 3
2307 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), rls
, kCFRunLoopDefaultMode
); // rls 2 cfs 3
2308 CFRelease(rls
); // rls ? cfs 3
2309 CFSocketInvalidate(cfs
); // rls ? cfs 1
2310 CFRelease(cfs
); // rls ? cfs ?
2313 mDNSlocal
void CloseSocketSet(CFSocketSet
*ss
)
2315 // Note: MUST NOT close the underlying native BSD sockets.
2316 // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately,
2317 // because it first has to unhook the sockets from its select() call, before it can safely close them.
2318 if (ss
->cfsv4
) CloseRunLoopSourceSocket(ss
->rlsv4
, ss
->cfsv4
);
2319 if (ss
->cfsv6
) CloseRunLoopSourceSocket(ss
->rlsv6
, ss
->cfsv6
);
2320 ss
->sktv4
= ss
->sktv6
= -1;
2321 ss
->cfsv4
= ss
->cfsv6
= NULL
;
2322 ss
->rlsv4
= ss
->rlsv6
= NULL
;
2325 // returns count of non-link local V4 addresses deregistered
2326 mDNSlocal
int ClearInactiveInterfaces(mDNS
*const m
, mDNSs32 utc
)
2329 // If an interface is going away, then deregister this from the mDNSCore.
2330 // We also have to deregister it if the primary interface that it's using for its InterfaceID is going away.
2331 // We have to do this because mDNSCore will use that InterfaceID when sending packets, and if the memory
2332 // it refers to has gone away we'll crash.
2333 // Don't actually close the sockets or free the memory yet: When the last representative of an interface goes away
2334 // mDNSCore may want to send goodbye packets on that interface. (Not yet implemented, but a good idea anyway.)
2335 NetworkInterfaceInfoOSX
*i
;
2337 for (i
= m
->p
->InterfaceList
; i
; i
= i
->next
)
2339 // 1. If this interface is no longer active, or its InterfaceID is changing, deregister it
2340 NetworkInterfaceInfoOSX
*primary
= SearchForInterfaceByName(m
, i
->ifa_name
, i
->sa_family
);
2341 if (i
->ifinfo
.InterfaceID
)
2342 if (i
->Exists
== 0 || i
->Exists
== 2 || i
->ifinfo
.InterfaceID
!= (mDNSInterfaceID
)primary
)
2344 LogOperation("ClearInactiveInterfaces: Deregistering %5s(%lu) %.6a InterfaceID %p %#a/%d%s",
2345 i
->ifa_name
, i
->scope_id
, &i
->BSSID
, i
->ifinfo
.InterfaceID
,
2346 &i
->ifinfo
.ip
, CountMaskBits(&i
->ifinfo
.mask
), i
->ifinfo
.InterfaceActive
? " (Primary)" : "");
2347 mDNS_DeregisterInterface(m
, &i
->ifinfo
);
2348 if (i
->ifinfo
.ip
.type
== mDNSAddrType_IPv4
&& (i
->ifinfo
.ip
.ip
.v4
.b
[0] != 169 || i
->ifinfo
.ip
.ip
.v4
.b
[1] != 254)) count
++;
2349 i
->ifinfo
.InterfaceID
= mDNSNULL
;
2350 // NOTE: If n->InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
2351 // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
2352 // If n->InterfaceID is NOT set, then it's not registered and we should not call mDNS_DeregisterInterface() on it.
2357 // Now that everything that's going to deregister has done so, we can close sockets and free the memory
2358 NetworkInterfaceInfoOSX
**p
= &m
->p
->InterfaceList
;
2362 // 2. Close all our CFSockets. We'll recreate them later as necessary.
2363 // (We may have previously had both v4 and v6, and we may not need both any more.)
2364 CloseSocketSet(&i
->ss
);
2365 // 3. If no longer active, delete interface from list and free memory
2368 if (i
->LastSeen
== utc
) i
->LastSeen
= utc
- 1;
2369 mDNSBool
delete = (NumCacheRecordsForInterfaceID(m
, (mDNSInterfaceID
)i
) == 0) && (utc
- i
->LastSeen
>= 60);
2370 LogOperation("ClearInactiveInterfaces: %-13s %5s(%lu) %.6a InterfaceID %p %#a/%d Age %d%s", delete ? "Deleting" : "Holding",
2371 i
->ifa_name
, i
->scope_id
, &i
->BSSID
, i
->ifinfo
.InterfaceID
,
2372 &i
->ifinfo
.ip
, CountMaskBits(&i
->ifinfo
.mask
), utc
- i
->LastSeen
,
2373 i
->ifinfo
.InterfaceActive
? " (Primary)" : "");
2377 if (i
->ifa_name
) freeL("NetworkInterfaceInfoOSX name", i
->ifa_name
);
2378 freeL("NetworkInterfaceInfoOSX", i
);
2379 continue; // After deleting this object, don't want to do the "p = &i->next;" thing at the end of the loop
2387 mDNSlocal mStatus
GetDNSConfig(void **result
)
2390 static int MessageShown
= 0;
2391 if (!MessageShown
) { MessageShown
= 1; LogMsg("Note: Compiled without Apple-specific Split-DNS support"); }
2393 return mStatus_UnsupportedErr
;
2396 *result
= dns_configuration_copy();
2400 // When running on 10.3 (build 7xxx) and earlier, we don't expect dns_configuration_copy() to succeed
2401 if (mDNSMacOSXSystemBuildNumber(NULL
) < 8) return mStatus_UnsupportedErr
;
2403 // On 10.4, calls to dns_configuration_copy() early in the boot process often fail.
2404 // Apparently this is expected behaviour -- "not a bug".
2405 // Accordingly, we suppress syslog messages for the first three minutes after boot.
2406 // If we are still getting failures after three minutes, then we log them.
2407 if ((mDNSu32
)(mDNSPlatformRawTime()) < (mDNSu32
)(mDNSPlatformOneSecond
* 180)) return mStatus_NoError
;
2409 LogMsg("GetDNSConfig: Error: dns_configuration_copy returned NULL");
2410 return mStatus_UnknownErr
;
2412 return mStatus_NoError
;
2413 #endif // MDNS_NO_DNSINFO
2416 mDNSlocal mStatus
RegisterSplitDNS(mDNS
*m
, int *nAdditions
, int *nDeletions
)
2418 (void)m
; // unused on 10.3 systems
2420 *nAdditions
= *nDeletions
= 0;
2421 mStatus err
= GetDNSConfig(&v
);
2423 #if !MDNS_NO_DNSINFO
2428 dns_config_t
*config
= v
; // use void * to allow compilation on 10.3 systems
2430 p
= m
->uDNS_info
.Servers
;
2431 while (p
) { p
->flag
= -1; p
= p
->next
; } // mark all for deletion
2433 LogOperation("RegisterSplitDNS: Registering %d resolvers", config
->n_resolver
);
2434 for (i
= 0; i
< config
->n_resolver
; i
++)
2438 dns_resolver_t
*r
= config
->resolver
[i
];
2439 if (r
->port
== MulticastDNSPort
.NotAnInteger
) continue; // ignore configurations for .local
2440 if (r
->search_order
== DEFAULT_SEARCH_ORDER
|| !r
->domain
|| !*r
->domain
) d
.c
[0] = 0; // we ignore domain for "default" resolver
2441 else if (!MakeDomainNameFromDNSNameString(&d
, r
->domain
)) { LogMsg("RegisterSplitDNS: bad domain %s", r
->domain
); continue; }
2443 // check if this is the lowest-weighted server for the domain
2444 for (j
= 0; j
< config
->n_resolver
; j
++)
2446 dns_resolver_t
*p
= config
->resolver
[j
];
2447 if (p
->port
== MulticastDNSPort
.NotAnInteger
) continue;
2448 if (p
->search_order
<= r
->search_order
)
2451 if (p
->search_order
== DEFAULT_SEARCH_ORDER
|| !p
->domain
|| !*p
->domain
) tmp
.c
[0] = '\0';
2452 else if (!MakeDomainNameFromDNSNameString(&tmp
, p
->domain
)) { LogMsg("RegisterSplitDNS: bad domain %s", p
->domain
); continue; }
2453 if (SameDomainName(&d
, &tmp
))
2454 if (p
->search_order
< r
->search_order
|| j
< i
) break; // if equal weights, pick first in list, otherwise pick lower-weight (p)
2457 if (j
< config
->n_resolver
) // found a lower-weighted resolver for this domain
2458 { debugf("Rejecting DNS server in slot %d domain %##s (slot %d outranks)", i
, d
.c
, j
); continue; }
2459 // we're using this resolver - find the first IPv4 address
2460 for (n
= 0; n
< r
->n_nameserver
; n
++)
2462 if (r
->nameserver
[n
]->sa_family
== AF_INET
&& !AddrRequiresPPPConnection(r
->nameserver
[n
]))
2465 if (SetupAddr(&saddr
, r
->nameserver
[n
])) { LogMsg("RegisterSplitDNS: bad IP address"); continue; }
2466 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
);
2467 p
= m
->uDNS_info
.Servers
;
2470 if (mDNSSameAddress(&p
->addr
, &saddr
) && SameDomainName(&p
->domain
, &d
)) { p
->flag
= 0; break; }
2475 p
= mallocL("DNSServer", sizeof(*p
));
2476 if (!p
) { LogMsg("Error: malloc"); mDNS_Unlock(m
); return mStatus_UnknownErr
; }
2478 AssignDomainName(&p
->domain
, &d
);
2480 p
->next
= m
->uDNS_info
.Servers
;
2481 m
->uDNS_info
.Servers
= p
;
2484 break; // !!!KRS if we ever support round-robin servers, don't break here
2489 // remove all servers marked for deletion
2490 DNSServer
**s
= &m
->uDNS_info
.Servers
;
2497 freeL("DNSServer", p
);
2500 else s
= &(*s
)->next
;
2503 dns_configuration_free(config
);
2510 mDNSlocal mStatus
RegisterNameServers(mDNS
*const m
, CFDictionaryRef dict
)
2515 mDNSAddr saddr
= { mDNSAddrType_IPv4
, { { { 0 } } } };
2518 mDNS_DeleteDNSServers(m
); // deregister orig list
2519 values
= CFDictionaryGetValue(dict
, kSCPropNetDNSServerAddresses
);
2520 if (!values
) return mStatus_NoError
;
2522 count
= CFArrayGetCount(values
);
2523 for (i
= 0; i
< count
; i
++)
2525 s
= CFArrayGetValueAtIndex(values
, i
);
2526 if (!s
) { LogMsg("ERROR: RegisterNameServers - CFArrayGetValueAtIndex"); break; }
2527 if (!CFStringGetCString(s
, buf
, 256, kCFStringEncodingUTF8
))
2529 LogMsg("ERROR: RegisterNameServers - CFStringGetCString");
2532 if (!inet_aton(buf
, (struct in_addr
*)saddr
.ip
.v4
.b
))
2534 LogMsg("ERROR: RegisterNameServers - invalid address string %s", buf
);
2537 LogOperation("RegisterNameServers: Adding %#a", &saddr
);
2538 mDNS_AddDNSServer(m
, &saddr
, NULL
);
2540 return mStatus_NoError
;
2543 mDNSlocal
void FreeARElemCallback(mDNS
*const m
, AuthRecord
*const rr
, mStatus result
)
2546 ARListElem
*elem
= rr
->RecordContext
;
2547 if (result
== mStatus_MemFree
) freeL("FreeARElemCallback", elem
);
2550 mDNSlocal
void FoundDomain(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
2552 SearchListElem
*slElem
= question
->QuestionContext
;
2553 ARListElem
*arElem
, *ptr
, *prev
;
2560 arElem
= mallocL("FoundDomain - arElem", sizeof(ARListElem
));
2561 if (!arElem
) { LogMsg("ERROR: malloc"); return; }
2562 mDNS_SetupResourceRecord(&arElem
->ar
, mDNSNULL
, mDNSInterface_LocalOnly
, kDNSType_PTR
, 7200, kDNSRecordTypeShared
, FreeARElemCallback
, arElem
);
2563 if (question
== &slElem
->BrowseQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeBrowse
];
2564 else if (question
== &slElem
->DefBrowseQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeBrowseDefault
];
2565 else if (question
== &slElem
->LegacyBrowseQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeBrowseLegacy
];
2566 else if (question
== &slElem
->RegisterQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeRegistration
];
2567 else if (question
== &slElem
->DefRegisterQ
) name
= mDNS_DomainTypeNames
[mDNS_DomainTypeRegistrationDefault
];
2568 else { LogMsg("FoundDomain - unknown question"); return; }
2570 MakeDomainNameFromDNSNameString(arElem
->ar
.resrec
.name
, name
);
2571 AppendDNSNameString (arElem
->ar
.resrec
.name
, "local");
2572 AssignDomainName(&arElem
->ar
.resrec
.rdata
->u
.name
, &answer
->rdata
->u
.name
);
2573 err
= mDNS_Register(m
, &arElem
->ar
);
2576 LogMsg("ERROR: FoundDomain - mDNS_Register returned %d", err
);
2577 freeL("FoundDomain - arElem", arElem
);
2580 arElem
->next
= slElem
->AuthRecs
;
2581 slElem
->AuthRecs
= arElem
;
2585 ptr
= slElem
->AuthRecs
;
2589 if (SameDomainName(&ptr
->ar
.resrec
.rdata
->u
.name
, &answer
->rdata
->u
.name
))
2591 debugf("Deregistering PTR %s -> %s", ptr
->ar
.resrec
.name
->c
, ptr
->ar
.resrec
.rdata
->u
.name
.c
);
2593 if (prev
) prev
->next
= ptr
->next
;
2594 else slElem
->AuthRecs
= ptr
->next
;
2596 err
= mDNS_Deregister(m
, dereg
);
2597 if (err
) LogMsg("ERROR: FoundDomain - mDNS_Deregister returned %d", err
);
2608 mDNSlocal
void MarkSearchListElem(const char *d
)
2610 SearchListElem
*new, *ptr
;
2613 if (!MakeDomainNameFromDNSNameString(&domain
, d
))
2614 { LogMsg("ERROR: MarkSearchListElem - bad domain %##s", d
); return; }
2616 if (SameDomainName(&domain
, &localdomain
) || SameDomainName(&domain
, &LocalReverseMapomain
))
2617 { debugf("MarkSearchListElem - ignoring local domain %##s", domain
.c
); return; }
2619 // if domain is in list, mark as pre-existent (0)
2620 for (ptr
= SearchList
; ptr
; ptr
= ptr
->next
)
2621 if (SameDomainName(&ptr
->domain
, &domain
))
2623 if (ptr
->flag
!= 1) ptr
->flag
= 0; // gracefully handle duplicates - if it is already marked as add, don't bump down to preexistent
2627 // if domain not in list, add to list, mark as add (1)
2630 new = mallocL("MarkSearchListElem - SearchListElem", sizeof(SearchListElem
));
2631 if (!new) { LogMsg("ERROR: MarkSearchListElem - malloc"); return; }
2632 bzero(new, sizeof(SearchListElem
));
2633 AssignDomainName(&new->domain
, &domain
);
2634 new->flag
= 1; // add
2635 new->next
= SearchList
;
2640 // Get the search domains via OS X resolver routines. Returns mStatus_UnsupporterErr if compiled or run on 10.3 systems
2641 mDNSlocal mStatus
GetSearchDomains(void)
2644 mStatus err
= GetDNSConfig(&v
);
2646 #if !MDNS_NO_DNSINFO
2650 dns_config_t
*config
= v
;
2651 if (!config
->n_resolver
) return err
;
2652 dns_resolver_t
*resolv
= config
->resolver
[0]; // use the first slot for search domains
2654 for (i
= 0; i
< resolv
->n_search
; i
++) MarkSearchListElem(resolv
->search
[i
]);
2655 if (resolv
->domain
) MarkSearchListElem(resolv
->domain
);
2656 dns_configuration_free(config
);
2663 // Get search domains from dynamic store - used as a fallback mechanism on 10.3 systems, if GetSearchDomains (above) fails.
2664 mDNSlocal
void GetDSSearchDomains(CFDictionaryRef dict
)
2666 char buf
[MAX_ESCAPED_DOMAIN_NAME
];
2671 // get all the domains from "Search Domains" field of sharing prefs
2674 CFArrayRef searchdomains
= CFDictionaryGetValue(dict
, kSCPropNetDNSSearchDomains
);
2677 count
= CFArrayGetCount(searchdomains
);
2678 for (i
= 0; i
< count
; i
++)
2680 s
= CFArrayGetValueAtIndex(searchdomains
, i
);
2681 if (!s
) { LogMsg("ERROR: GetDSSearchDomains - CFArrayGetValueAtIndex"); break; }
2682 if (!CFStringGetCString(s
, buf
, MAX_ESCAPED_DOMAIN_NAME
, kCFStringEncodingUTF8
))
2684 LogMsg("ERROR: GetDSSearchDomains - CFStringGetCString");
2687 MarkSearchListElem(buf
);
2691 // get DHCP domain field
2692 CFStringRef dname
= CFDictionaryGetValue(dict
, kSCPropNetDNSDomainName
);
2695 if (CFStringGetCString(dname
, buf
, MAX_ESCAPED_DOMAIN_NAME
, kCFStringEncodingUTF8
))
2696 MarkSearchListElem(buf
);
2697 else LogMsg("ERROR: GetDSSearchDomains - CFStringGetCString");
2702 mDNSlocal mStatus
RegisterSearchDomains(mDNS
*const m
, CFDictionaryRef dict
)
2704 struct ifaddrs
*ifa
= NULL
;
2705 SearchListElem
*ptr
, *prev
, *freeSLPtr
;
2709 if (DomainDiscoveryDisabled
) return mStatus_NoError
;
2711 // step 1: mark each elem for removal (-1), unless we aren't passed a dictionary in which case we mark as preexistent
2712 for (ptr
= SearchList
; ptr
; ptr
= ptr
->next
) ptr
->flag
= dict
? -1 : 0;
2714 // Get search domains from resolver library (available in OS X 10.4 and later), reverting to dynamic store on 10.3 systems
2715 if (GetSearchDomains() == mStatus_UnsupportedErr
) GetDSSearchDomains(dict
);
2717 // Construct reverse-map search domains
2718 ifa
= myGetIfAddrs(1);
2722 if (ifa
->ifa_addr
->sa_family
== AF_INET
&& !SetupAddr(&addr
, ifa
->ifa_addr
) && !IsPrivateV4Addr(&addr
) && !(ifa
->ifa_flags
& IFF_LOOPBACK
) && ifa
->ifa_netmask
)
2726 if (!SetupAddr(&netmask
, ifa
->ifa_netmask
))
2728 sprintf(buffer
, "%d.%d.%d.%d.in-addr.arpa.", addr
.ip
.v4
.b
[3] & netmask
.ip
.v4
.b
[3],
2729 addr
.ip
.v4
.b
[2] & netmask
.ip
.v4
.b
[2],
2730 addr
.ip
.v4
.b
[1] & netmask
.ip
.v4
.b
[1],
2731 addr
.ip
.v4
.b
[0] & netmask
.ip
.v4
.b
[0]);
2732 MarkSearchListElem(buffer
);
2735 ifa
= ifa
->ifa_next
;
2738 // delete elems marked for removal, do queries for elems marked add
2743 if (ptr
->flag
== -1) // remove
2745 mDNS_StopQuery(m
, &ptr
->BrowseQ
);
2746 mDNS_StopQuery(m
, &ptr
->RegisterQ
);
2747 mDNS_StopQuery(m
, &ptr
->DefBrowseQ
);
2748 mDNS_StopQuery(m
, &ptr
->DefRegisterQ
);
2749 mDNS_StopQuery(m
, &ptr
->LegacyBrowseQ
);
2751 // deregister records generated from answers to the query
2752 arList
= ptr
->AuthRecs
;
2753 ptr
->AuthRecs
= NULL
;
2756 AuthRecord
*dereg
= &arList
->ar
;
2757 arList
= arList
->next
;
2758 debugf("Deregistering PTR %s -> %s", dereg
->resrec
.name
->c
, dereg
->resrec
.rdata
->u
.name
.c
);
2759 err
= mDNS_Deregister(m
, dereg
);
2760 if (err
) LogMsg("ERROR: RegisterSearchDomains mDNS_Deregister returned %d", err
);
2763 // remove elem from list, delete
2764 if (prev
) prev
->next
= ptr
->next
;
2765 else SearchList
= ptr
->next
;
2768 freeL("RegisterSearchDomains - freeSLPtr", freeSLPtr
);
2772 if (ptr
->flag
== 1) // add
2774 mStatus err1
, err2
, err3
, err4
, err5
;
2775 err1
= mDNS_GetDomains(m
, &ptr
->BrowseQ
, mDNS_DomainTypeBrowse
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2776 err2
= mDNS_GetDomains(m
, &ptr
->DefBrowseQ
, mDNS_DomainTypeBrowseDefault
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2777 err3
= mDNS_GetDomains(m
, &ptr
->RegisterQ
, mDNS_DomainTypeRegistration
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2778 err4
= mDNS_GetDomains(m
, &ptr
->DefRegisterQ
, mDNS_DomainTypeRegistrationDefault
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2779 err5
= mDNS_GetDomains(m
, &ptr
->LegacyBrowseQ
, mDNS_DomainTypeBrowseLegacy
, &ptr
->domain
, mDNSInterface_Any
, FoundDomain
, ptr
);
2780 if (err1
|| err2
|| err3
|| err4
|| err5
)
2781 LogMsg("GetDomains for domain %##s returned error(s):\n"
2782 "%d (mDNS_DomainTypeBrowse)\n"
2783 "%d (mDNS_DomainTypeBrowseDefault)\n"
2784 "%d (mDNS_DomainTypeRegistration)\n"
2785 "%d (mDNS_DomainTypeRegistrationDefault)"
2786 "%d (mDNS_DomainTypeBrowseLegacy)\n",
2787 ptr
->domain
.c
, err1
, err2
, err3
, err4
, err5
);
2791 if (ptr
->flag
) { LogMsg("RegisterSearchDomains - unknown flag %d. Skipping.", ptr
->flag
); }
2797 return mStatus_NoError
;
2800 //!!!KRS here is where we will give success/failure notification to the UI
2801 mDNSlocal
void SCPrefsDynDNSCallback(mDNS
*const m
, AuthRecord
*const rr
, mStatus result
)
2804 debugf("SCPrefsDynDNSCallback: result %d for registration of name %##s", result
, rr
->resrec
.name
->c
);
2805 SetDDNSNameStatus(rr
->resrec
.name
, result
);
2808 mDNSlocal
void SetSecretForDomain(mDNS
*m
, const domainname
*domain
)
2811 char dstring
[MAX_ESCAPED_DOMAIN_NAME
];
2813 void *secret
= NULL
;
2814 domainname
*d
, canon
;
2816 mDNSu32 type
= 'ddns';
2817 mDNSu32 typelen
= sizeof(type
);
2818 char *failedfn
= "(none)";
2819 SecKeychainAttributeList
*attrList
= NULL
;
2820 SecKeychainItemRef itemRef
= NULL
;
2822 err
= SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem
);
2823 if (err
) { failedfn
= "SecKeychainSetPreferenceDomain"; goto cleanup
; }
2825 // canonicalize name by converting to lower case (keychain and some name servers are case sensitive)
2826 ConvertDomainNameToCString(domain
, dstring
);
2827 dlen
= strlen(dstring
);
2828 for (i
= 0; i
< dlen
; i
++) dstring
[i
] = tolower(dstring
[i
]); // canonicalize -> lower case
2829 MakeDomainNameFromDNSNameString(&canon
, dstring
);
2832 // find longest-match key, excluding last label (e.g. excluding ".com")
2833 while (d
->c
[0] && *(d
->c
+ d
->c
[0] + 1))
2835 if (!ConvertDomainNameToCString(d
, dstring
)) { LogMsg("SetSecretForDomain: bad domain %##s", d
->c
); return; }
2836 dlen
= strlen(dstring
);
2837 if (dstring
[dlen
-1] == '.') { dstring
[dlen
-1] = '\0'; dlen
--; } // chop trailing dot
2838 SecKeychainAttribute attrs
[] = { { kSecServiceItemAttr
, strlen(dstring
), dstring
},
2839 { kSecTypeItemAttr
, typelen
, (UInt32
*)&type
} };
2840 SecKeychainAttributeList attributes
= { sizeof(attrs
) / sizeof(attrs
[0]), attrs
};
2841 SecKeychainSearchRef searchRef
;
2843 err
= SecKeychainSearchCreateFromAttributes(NULL
, kSecGenericPasswordItemClass
, &attributes
, &searchRef
);
2844 if (err
) { failedfn
= "SecKeychainSearchCreateFromAttributes"; goto cleanup
; }
2846 err
= SecKeychainSearchCopyNext(searchRef
, &itemRef
);
2850 SecKeychainAttributeInfo attrInfo
;
2852 char keybuf
[MAX_ESCAPED_DOMAIN_NAME
+1];
2855 tags
[0] = kSecAccountItemAttr
;
2857 attrInfo
.tag
= tags
;
2858 attrInfo
.format
= NULL
;
2860 err
= SecKeychainItemCopyAttributesAndData(itemRef
, &attrInfo
, NULL
, &attrList
, &secretlen
, &secret
);
2861 if (err
|| !attrList
) { failedfn
= "SecKeychainItemCopyAttributesAndData"; goto cleanup
; }
2862 if (!secretlen
|| !secret
) { LogMsg("SetSecretForDomain - bad shared secret"); return; }
2863 if (((char *)secret
)[secretlen
-1]) { LogMsg("SetSecretForDomain - Shared secret not NULL-terminated"); goto cleanup
; }
2865 for (i
= 0; i
< attrList
->count
; i
++)
2867 SecKeychainAttribute attr
= attrList
->attr
[i
];
2868 if (attr
.tag
== kSecAccountItemAttr
)
2870 if (!attr
.length
|| attr
.length
> MAX_ESCAPED_DOMAIN_NAME
) { LogMsg("SetSecretForDomain - Bad key length %d", attr
.length
); goto cleanup
; }
2871 strncpy(keybuf
, attr
.data
, attr
.length
);
2872 if (!MakeDomainNameFromDNSNameString(&keyname
, keybuf
)) { LogMsg("SetSecretForDomain - bad key %s", keybuf
); goto cleanup
; }
2873 debugf("Setting shared secret for zone %s with key %##s", dstring
, keyname
.c
);
2874 mDNS_SetSecretForZone(m
, d
, &keyname
, secret
);
2878 if (i
== attrList
->count
) LogMsg("SetSecretForDomain - no key name set");
2881 else if (err
== errSecItemNotFound
) d
= (domainname
*)(d
->c
+ d
->c
[0] + 1);
2882 else { failedfn
= "SecKeychainSearchCopyNext"; goto cleanup
; }
2886 if (err
&& err
!= errSecItemNotFound
) LogMsg("Error: SetSecretForDomain - %s failed with error code %d", failedfn
, err
);
2887 if (attrList
) SecKeychainItemFreeAttributesAndData(attrList
, secret
);
2888 if (itemRef
) CFRelease(itemRef
);
2891 mDNSlocal
void SetSCPrefsBrowseDomainsFromCFArray(mDNS
*m
, CFArrayRef browseDomains
, mDNSBool add
)
2895 CFIndex count
= CFArrayGetCount(browseDomains
);
2896 CFDictionaryRef browseDict
;
2897 char buf
[MAX_ESCAPED_DOMAIN_NAME
];
2900 for (i
= 0; i
< count
; i
++)
2902 browseDict
= (CFDictionaryRef
)CFArrayGetValueAtIndex(browseDomains
, i
);
2903 if (browseDict
&& DDNSSettingEnabled(browseDict
))
2905 CFStringRef name
= CFDictionaryGetValue(browseDict
, CFSTR("Domain"));
2908 domainname BrowseDomain
;
2909 if (!CFStringGetCString(name
, buf
, sizeof(buf
), kCFStringEncodingUTF8
) || !MakeDomainNameFromDNSNameString(&BrowseDomain
, buf
) || !BrowseDomain
.c
[0])
2910 LogMsg("SetSCPrefsBrowseDomainsFromCFArray SCDynamicStore bad DDNS browse domain: %s", buf
[0] ? buf
: "(unknown)");
2911 else SetSCPrefsBrowseDomain(m
, &BrowseDomain
, add
);
2919 mDNSlocal
void DynDNSConfigChanged(mDNS
*const m
)
2921 static mDNSBool LegacyNATInitialized
= mDNSfalse
;
2922 uDNS_GlobalInfo
*u
= &m
->uDNS_info
;
2923 CFDictionaryRef dict
;
2925 domainname RegDomain
, fqdn
;
2926 CFArrayRef NewBrowseDomains
= NULL
;
2927 int nAdditions
= 0, nDeletions
= 0;
2929 // get fqdn, zone from SCPrefs
2930 GetUserSpecifiedDDNSConfig(&fqdn
, &RegDomain
, &NewBrowseDomains
);
2931 ReadDDNSSettingsFromConfFile(m
, CONFIG_FILE
, fqdn
.c
[0] ? NULL
: &fqdn
, RegDomain
.c
[0] ? NULL
: &RegDomain
, &DomainDiscoveryDisabled
);
2933 if (!SameDomainName(&RegDomain
, &DynDNSRegDomain
))
2935 if (DynDNSRegDomain
.c
[0])
2937 RemoveDefRegDomain(&DynDNSRegDomain
);
2938 SetSCPrefsBrowseDomain(m
, &DynDNSRegDomain
, mDNSfalse
); // if we were automatically browsing in our registration domain, stop
2940 AssignDomainName(&DynDNSRegDomain
, &RegDomain
);
2941 if (DynDNSRegDomain
.c
[0])
2943 SetSecretForDomain(m
, &DynDNSRegDomain
);
2944 AddDefRegDomain(&DynDNSRegDomain
);
2945 SetSCPrefsBrowseDomain(m
, &DynDNSRegDomain
, mDNStrue
);
2949 // Add new browse domains to internal list
2950 if (NewBrowseDomains
) SetSCPrefsBrowseDomainsFromCFArray(m
, NewBrowseDomains
, mDNStrue
);
2952 // Remove old browse domains from internal list
2953 if (DynDNSBrowseDomains
)
2955 SetSCPrefsBrowseDomainsFromCFArray(m
, DynDNSBrowseDomains
, mDNSfalse
);
2956 CFRelease(DynDNSBrowseDomains
);
2959 // Replace the old browse domains array with the new array
2960 DynDNSBrowseDomains
= NewBrowseDomains
;
2962 if (!SameDomainName(&fqdn
, &DynDNSHostname
))
2964 if (DynDNSHostname
.c
[0]) mDNS_RemoveDynDNSHostName(m
, &DynDNSHostname
);
2965 AssignDomainName(&DynDNSHostname
, &fqdn
);
2966 if (DynDNSHostname
.c
[0])
2968 SetSecretForDomain(m
, &fqdn
); // no-op if "zone" secret, above, is to be used for hostname
2969 SetDDNSNameStatus(&DynDNSHostname
, 1); // Set status to 1 to indicate "in progress"
2970 mDNS_AddDynDNSHostName(m
, &DynDNSHostname
, SCPrefsDynDNSCallback
, NULL
);
2975 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:DynDNSConfigChanged"), NULL
, NULL
);
2978 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetDNS
);
2979 if (!key
) { LogMsg("ERROR: DNSConfigChanged - SCDynamicStoreKeyCreateNetworkGlobalEntity"); CFRelease(store
); return; }
2980 dict
= SCDynamicStoreCopyValue(store
, key
);
2983 // handle any changes to search domains and DNS server addresses
2984 if (RegisterSplitDNS(m
, &nAdditions
, &nDeletions
) != mStatus_NoError
)
2985 if (dict
) RegisterNameServers(m
, dict
); // fall back to non-split DNS aware configuration on failure
2986 RegisterSearchDomains(m
, dict
); // note that we register name servers *before* search domains
2987 if (dict
) CFRelease(dict
);
2989 // get IPv4 settings
2990 key
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
,kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
2991 if (!key
) { LogMsg("ERROR: RouterChanged - SCDynamicStoreKeyCreateNetworkGlobalEntity"); CFRelease(store
); return; }
2992 dict
= SCDynamicStoreCopyValue(store
, key
);
2995 if (!dict
) // lost v4
2997 mDNS_SetPrimaryInterfaceInfo(m
, NULL
, NULL
);
2998 if (DynDNSHostname
.c
[0]) SetDDNSNameStatus(&DynDNSHostname
, 1); // Set status to 1 to indicate temporary failure
3002 // handle router changes
3005 r
.type
= mDNSAddrType_IPv4
;
3006 r
.ip
.v4
.NotAnInteger
= 0;
3007 CFStringRef router
= CFDictionaryGetValue(dict
, kSCPropNetIPv4Router
);
3010 struct sockaddr_in saddr
;
3012 if (!CFStringGetCString(router
, buf
, 256, kCFStringEncodingUTF8
))
3013 LogMsg("Could not convert router to CString");
3016 saddr
.sin_len
= sizeof(saddr
);
3017 saddr
.sin_family
= AF_INET
;
3019 inet_aton(buf
, &saddr
.sin_addr
);
3020 if (AddrRequiresPPPConnection((struct sockaddr
*)&saddr
)) { debugf("Ignoring router %s (requires PPP connection)", buf
); }
3021 else *(in_addr_t
*)&r
.ip
.v4
= saddr
.sin_addr
.s_addr
;
3025 // handle primary interface changes
3026 // if we gained or lost DNS servers (e.g. logged into VPN) "toggle" primary address so it gets re-registered even if it is unchanged
3027 if (nAdditions
|| nDeletions
) mDNS_SetPrimaryInterfaceInfo(m
, NULL
, NULL
);
3028 CFStringRef primary
= CFDictionaryGetValue(dict
, kSCDynamicStorePropNetPrimaryInterface
);
3031 struct ifaddrs
*ifa
= myGetIfAddrs(1);
3033 if (!CFStringGetCString(primary
, buf
, 256, kCFStringEncodingUTF8
))
3034 { LogMsg("Could not convert router to CString"); goto error
; }
3036 // find primary interface in list
3039 if (ifa
->ifa_addr
->sa_family
== AF_INET
&& !strcmp(buf
, ifa
->ifa_name
))
3042 SetupAddr(&ip
, ifa
->ifa_addr
);
3043 if (ip
.ip
.v4
.b
[0] == 169 && ip
.ip
.v4
.b
[1] == 254)
3044 { mDNS_SetPrimaryInterfaceInfo(m
, NULL
, NULL
); break; } // primary IP is link-local
3045 if (ip
.ip
.v4
.NotAnInteger
!= u
->PrimaryIP
.ip
.v4
.NotAnInteger
||
3046 r
.ip
.v4
.NotAnInteger
!= u
->Router
.ip
.v4
.NotAnInteger
)
3048 if (LegacyNATInitialized
) { LegacyNATDestroy(); LegacyNATInitialized
= mDNSfalse
; }
3049 if (r
.ip
.v4
.NotAnInteger
&& IsPrivateV4Addr(&ip
))
3051 mStatus err
= LegacyNATInit();
3052 if (err
) LogMsg("ERROR: LegacyNATInit");
3053 else LegacyNATInitialized
= mDNStrue
;
3055 mDNS_SetPrimaryInterfaceInfo(m
, &ip
, r
.ip
.v4
.NotAnInteger
? &r
: NULL
);
3059 ifa
= ifa
->ifa_next
;
3067 mDNSexport
void mDNSMacOSXNetworkChanged(mDNS
*const m
)
3069 LogOperation("*** Network Configuration Change ***");
3070 m
->p
->NetworkChanged
= 0; // If we received a network change event and deferred processing, we're now dealing with it
3071 mDNSs32 utc
= mDNSPlatformUTC();
3072 MarkAllInterfacesInactive(m
, utc
);
3073 UpdateInterfaceList(m
, utc
);
3074 int nDeletions
= ClearInactiveInterfaces(m
, utc
);
3075 int nAdditions
= SetupActiveInterfaces(m
, utc
);
3076 DynDNSConfigChanged(m
); // note - call DynDNSConfigChanged *before* mDNS_UpdateLLQs
3077 if (nDeletions
|| nAdditions
) mDNS_UpdateLLQs(m
); // so that LLQs are restarted against the up to date name servers
3079 if (m
->MainCallback
)
3080 m
->MainCallback(m
, mStatus_ConfigChanged
);
3083 mDNSlocal
void NetworkChanged(SCDynamicStoreRef store
, CFArrayRef changedKeys
, void *context
)
3085 (void)store
; // Parameter not used
3086 (void)changedKeys
; // Parameter not used
3087 mDNS
*const m
= (mDNS
*const)context
;
3090 mDNSs32 delay
= mDNSPlatformOneSecond
* 2; // Start off assuming a two-second delay
3092 int c
= CFArrayGetCount(changedKeys
); // Count changes
3093 CFRange range
= { 0, c
};
3094 CFStringRef k1
= SCDynamicStoreKeyCreateComputerName(NULL
);
3095 CFStringRef k2
= SCDynamicStoreKeyCreateHostNames(NULL
);
3098 int c1
= (CFArrayContainsValue(changedKeys
, range
, k1
) != 0); // See if ComputerName changed
3099 int c2
= (CFArrayContainsValue(changedKeys
, range
, k2
) != 0); // See if Local Hostname changed
3100 int c3
= (CFArrayContainsValue(changedKeys
, range
, CFSTR("Setup:/Network/DynamicDNS")) != 0);
3101 if (c
&& c
- c1
- c2
- c3
== 0) delay
= mDNSPlatformOneSecond
/10; // If these were the only changes, shorten delay
3103 if (k1
) CFRelease(k1
);
3104 if (k2
) CFRelease(k2
);
3106 LogOperation("*** NetworkChanged *** %d change%s, delay %d", c
, c
>1?"s":"", delay
);
3108 if (!m
->p
->NetworkChanged
||
3109 m
->p
->NetworkChanged
- NonZeroTime(m
->timenow
+ delay
) < 0)
3110 m
->p
->NetworkChanged
= NonZeroTime(m
->timenow
+ delay
);
3112 if (!m
->SuppressSending
||
3113 m
->SuppressSending
- m
->p
->NetworkChanged
< 0)
3114 m
->SuppressSending
= m
->p
->NetworkChanged
;
3118 mDNSlocal mStatus
WatchForNetworkChanges(mDNS
*const m
)
3121 SCDynamicStoreContext context
= { 0, m
, NULL
, NULL
, NULL
};
3122 SCDynamicStoreRef store
= SCDynamicStoreCreate(NULL
, CFSTR("mDNSResponder:WatchForNetworkChanges"), NetworkChanged
, &context
);
3123 CFStringRef key1
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv4
);
3124 CFStringRef key2
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetIPv6
);
3125 CFStringRef key3
= SCDynamicStoreKeyCreateComputerName(NULL
);
3126 CFStringRef key4
= SCDynamicStoreKeyCreateHostNames(NULL
);
3127 CFStringRef key5
= SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL
, kSCDynamicStoreDomainState
, kSCEntNetDNS
);
3128 CFStringRef pattern1
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv4
);
3129 CFStringRef pattern2
= SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL
, kSCDynamicStoreDomainState
, kSCCompAnyRegex
, kSCEntNetIPv6
);
3131 CFMutableArrayRef keys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3132 CFMutableArrayRef patterns
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3134 if (!store
) { LogMsg("SCDynamicStoreCreate failed: %s", SCErrorString(SCError())); goto error
; }
3135 if (!key1
|| !key2
|| !key3
|| !key4
|| !keys
|| !pattern1
|| !pattern2
|| !patterns
) goto error
;
3137 CFArrayAppendValue(keys
, key1
);
3138 CFArrayAppendValue(keys
, key2
);
3139 CFArrayAppendValue(keys
, key3
);
3140 CFArrayAppendValue(keys
, key4
);
3141 CFArrayAppendValue(keys
, key5
);
3142 CFArrayAppendValue(keys
, CFSTR("Setup:/Network/DynamicDNS"));
3143 CFArrayAppendValue(patterns
, pattern1
);
3144 CFArrayAppendValue(patterns
, pattern2
);
3145 CFArrayAppendValue(patterns
, CFSTR("State:/Network/Interface/[^/]+/AirPort"));
3146 if (!SCDynamicStoreSetNotificationKeys(store
, keys
, patterns
))
3147 { LogMsg("SCDynamicStoreSetNotificationKeys failed: %s", SCErrorString(SCError())); goto error
; }
3149 m
->p
->StoreRLS
= SCDynamicStoreCreateRunLoopSource(NULL
, store
, 0);
3150 if (!m
->p
->StoreRLS
) { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error
; }
3152 CFRunLoopAddSource(CFRunLoopGetCurrent(), m
->p
->StoreRLS
, kCFRunLoopDefaultMode
);
3153 m
->p
->Store
= store
;
3158 if (store
) CFRelease(store
);
3161 if (key1
) CFRelease(key1
);
3162 if (key2
) CFRelease(key2
);
3163 if (key3
) CFRelease(key3
);
3164 if (key4
) CFRelease(key4
);
3165 if (key5
) CFRelease(key5
);
3166 if (pattern1
) CFRelease(pattern1
);
3167 if (pattern2
) CFRelease(pattern2
);
3168 if (keys
) CFRelease(keys
);
3169 if (patterns
) CFRelease(patterns
);
3174 mDNSlocal
void PowerChanged(void *refcon
, io_service_t service
, natural_t messageType
, void *messageArgument
)
3176 mDNS
*const m
= (mDNS
*const)refcon
;
3177 (void)service
; // Parameter not used
3180 case kIOMessageCanSystemPowerOff
: debugf ("PowerChanged kIOMessageCanSystemPowerOff (no action)"); break; // E0000240
3181 case kIOMessageSystemWillPowerOff
: LogOperation("PowerChanged kIOMessageSystemWillPowerOff");
3182 mDNSCoreMachineSleep(m
, true); mDNSMacOSXNetworkChanged(m
); break; // E0000250
3183 case kIOMessageSystemWillNotPowerOff
: debugf ("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; // E0000260
3184 case kIOMessageCanSystemSleep
: debugf ("PowerChanged kIOMessageCanSystemSleep (no action)"); break; // E0000270
3185 case kIOMessageSystemWillSleep
: LogOperation("PowerChanged kIOMessageSystemWillSleep");
3186 mDNSCoreMachineSleep(m
, true); mDNSMacOSXNetworkChanged(m
); break; // E0000280
3187 case kIOMessageSystemWillNotSleep
: debugf ("PowerChanged kIOMessageSystemWillNotSleep (no action)"); break; // E0000290
3188 case kIOMessageSystemHasPoweredOn
: LogOperation("PowerChanged kIOMessageSystemHasPoweredOn");
3189 // If still sleeping (didn't get 'WillPowerOn' message for some reason?) wake now
3190 if (m
->SleepState
) mDNSCoreMachineSleep(m
, false);
3191 // Just to be safe, also make sure our interface list is fully up to date, in case we
3192 // haven't yet received the System Configuration Framework "network changed" event that
3193 // we expect to receive some time shortly after the kIOMessageSystemWillPowerOn message
3194 mDNSMacOSXNetworkChanged(m
); break; // E0000300
3195 case kIOMessageSystemWillRestart
: debugf ("PowerChanged kIOMessageSystemWillRestart (no action)"); break; // E0000310
3196 case kIOMessageSystemWillPowerOn
: LogOperation("PowerChanged kIOMessageSystemWillPowerOn");
3197 // Make sure our interface list is cleared to the empty state, then tell mDNSCore to wake
3198 mDNSMacOSXNetworkChanged(m
); mDNSCoreMachineSleep(m
, false); break; // E0000320
3199 default: LogOperation("PowerChanged unknown message %X", messageType
); break;
3201 IOAllowPowerChange(m
->p
->PowerConnection
, (long)messageArgument
);
3204 mDNSlocal mStatus
WatchForPowerChanges(mDNS
*const m
)
3206 IONotificationPortRef thePortRef
;
3207 m
->p
->PowerConnection
= IORegisterForSystemPower(m
, &thePortRef
, PowerChanged
, &m
->p
->PowerNotifier
);
3208 if (m
->p
->PowerConnection
)
3210 m
->p
->PowerRLS
= IONotificationPortGetRunLoopSource(thePortRef
);
3211 CFRunLoopAddSource(CFRunLoopGetCurrent(), m
->p
->PowerRLS
, kCFRunLoopDefaultMode
);
3212 return(mStatus_NoError
);
3217 CF_EXPORT CFDictionaryRef
_CFCopySystemVersionDictionary(void);
3218 CF_EXPORT
const CFStringRef _kCFSystemVersionProductNameKey
;
3219 CF_EXPORT
const CFStringRef _kCFSystemVersionProductVersionKey
;
3220 CF_EXPORT
const CFStringRef _kCFSystemVersionBuildVersionKey
;
3222 // Major version 6 is 10.2.x (Jaguar)
3223 // Major version 7 is 10.3.x (Panther)
3224 // Major version 8 is 10.4.x (Tiger)
3225 mDNSexport
int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring
)
3227 int major
= 0, minor
= 0;
3228 char letter
= 0, prodname
[256]="Mac OS X", prodvers
[256]="", buildver
[256]="?";
3229 CFDictionaryRef vers
= _CFCopySystemVersionDictionary();
3232 CFStringRef cfprodname
= CFDictionaryGetValue(vers
, _kCFSystemVersionProductNameKey
);
3233 CFStringRef cfprodvers
= CFDictionaryGetValue(vers
, _kCFSystemVersionProductVersionKey
);
3234 CFStringRef cfbuildver
= CFDictionaryGetValue(vers
, _kCFSystemVersionBuildVersionKey
);
3235 if (cfprodname
) CFStringGetCString(cfprodname
, prodname
, sizeof(prodname
), kCFStringEncodingUTF8
);
3236 if (cfprodvers
) CFStringGetCString(cfprodvers
, prodvers
, sizeof(prodvers
), kCFStringEncodingUTF8
);
3237 if (cfbuildver
) CFStringGetCString(cfbuildver
, buildver
, sizeof(buildver
), kCFStringEncodingUTF8
);
3238 sscanf(buildver
, "%d%c%d", &major
, &letter
, &minor
);
3241 if (HINFO_SWstring
) mDNS_snprintf(HINFO_SWstring
, 256, "%s %s (%s), %s", prodname
, prodvers
, buildver
, mDNSResponderVersionString
);
3245 // Test to see if we're the first client running on UDP port 5353, by trying to bind to 5353 without using SO_REUSEPORT.
3246 // If we fail, someone else got here first. That's not a big problem; we can share the port for multicast responses --
3247 // we just need to be aware that we shouldn't expect to successfully receive unicast UDP responses.
3248 mDNSlocal mDNSBool
mDNSPlatformInit_CanReceiveUnicast(void)
3251 int s
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
3253 LogMsg("mDNSPlatformInit_CanReceiveUnicast: socket error %d errno %d (%s)", s
, errno
, strerror(errno
));
3256 struct sockaddr_in s5353
;
3257 s5353
.sin_family
= AF_INET
;
3258 s5353
.sin_port
= MulticastDNSPort
.NotAnInteger
;
3259 s5353
.sin_addr
.s_addr
= 0;
3260 err
= bind(s
, (struct sockaddr
*)&s5353
, sizeof(s5353
));
3264 if (err
) LogMsg("No unicast UDP responses");
3265 else debugf("Unicast UDP responses okay");
3269 // Callback for the _legacy._browse queries - add answer to list of domains to search for empty-string browses
3270 mDNSlocal
void FoundLegacyBrowseDomain(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
3272 DNameListElem
*ptr
, *prev
, *new;
3274 (void)question
; // unused
3276 LogMsg("%s browse domain %##s", AddRecord
? "Adding" : "Removing", answer
->rdata
->u
.name
.c
);
3280 new = mallocL("FoundLegacyBrowseDomain", sizeof(DNameListElem
));
3281 if (!new) { LogMsg("ERROR: malloc"); return; }
3282 AssignDomainName(&new->name
, &answer
->rdata
->u
.name
);
3283 new->next
= DefBrowseList
;
3284 DefBrowseList
= new;
3285 DefaultBrowseDomainChanged(&new->name
, mDNStrue
);
3286 udsserver_default_browse_domain_changed(&new->name
, mDNStrue
);
3291 ptr
= DefBrowseList
;
3295 if (SameDomainName(&ptr
->name
, &answer
->rdata
->u
.name
))
3297 DefaultBrowseDomainChanged(&ptr
->name
, mDNSfalse
);
3298 udsserver_default_browse_domain_changed(&ptr
->name
, mDNSfalse
);
3299 if (prev
) prev
->next
= ptr
->next
;
3300 else DefBrowseList
= ptr
->next
;
3301 freeL("FoundLegacyBrowseDomain", ptr
);
3307 LogMsg("FoundLegacyBrowseDomain: Got remove event for domain %s not in list", answer
->rdata
->u
.name
.c
);
3311 mDNSlocal
void RegisterBrowseDomainPTR(mDNS
*m
, const domainname
*d
, int type
)
3313 // allocate/register legacy and non-legacy _browse PTR record
3314 ARListElem
*browse
= mallocL("ARListElem", sizeof(*browse
));
3315 mDNS_SetupResourceRecord(&browse
->ar
, mDNSNULL
, mDNSInterface_LocalOnly
, kDNSType_PTR
, 7200, kDNSRecordTypeShared
, FreeARElemCallback
, browse
);
3316 MakeDomainNameFromDNSNameString(browse
->ar
.resrec
.name
, mDNS_DomainTypeNames
[type
]);
3317 AppendDNSNameString (browse
->ar
.resrec
.name
, "local");
3318 AssignDomainName(&browse
->ar
.resrec
.rdata
->u
.name
, d
);
3319 mStatus err
= mDNS_Register(m
, &browse
->ar
);
3322 LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err
);
3323 freeL("ARListElem", browse
);
3327 browse
->next
= SCPrefBrowseDomains
;
3328 SCPrefBrowseDomains
= browse
;
3332 mDNSlocal
void DeregisterBrowseDomainPTR(mDNS
*m
, const domainname
*d
, int type
)
3334 ARListElem
*remove
, **ptr
= &SCPrefBrowseDomains
;
3335 domainname lhs
; // left-hand side of PTR, for comparison
3337 MakeDomainNameFromDNSNameString(&lhs
, mDNS_DomainTypeNames
[type
]);
3338 AppendDNSNameString (&lhs
, "local");
3342 if (SameDomainName(&(*ptr
)->ar
.resrec
.rdata
->u
.name
, d
) && SameDomainName((*ptr
)->ar
.resrec
.name
, &lhs
))
3345 *ptr
= (*ptr
)->next
;
3346 mDNS_Deregister(m
, &remove
->ar
);
3349 else ptr
= &(*ptr
)->next
;
3353 // Add or remove a user-specified domain to the list of empty-string browse domains
3354 // Also register a non-legacy _browse PTR record so that the domain appears in enumeration lists
3355 mDNSlocal
void SetSCPrefsBrowseDomain(mDNS
*m
, const domainname
*d
, mDNSBool add
)
3357 debugf("SetSCPrefsBrowseDomain: %s default browse domain %##s", add
? "Adding" : "Removing", d
->c
);
3361 RegisterBrowseDomainPTR(m
, d
, mDNS_DomainTypeBrowse
);
3362 RegisterBrowseDomainPTR(m
, d
, mDNS_DomainTypeBrowseLegacy
);
3366 DeregisterBrowseDomainPTR(m
, d
, mDNS_DomainTypeBrowse
);
3367 DeregisterBrowseDomainPTR(m
, d
, mDNS_DomainTypeBrowseLegacy
);
3371 // Construction of Default Browse domain list (i.e. when clients pass NULL) is as follows:
3372 // 1) query for b._dns-sd._udp.local on LocalOnly interface
3373 // (.local manually generated via explicit callback)
3374 // 2) for each search domain (from prefs pane), query for b._dns-sd._udp.<searchdomain>.
3375 // 3) for each result from (2), register LocalOnly PTR record b._dns-sd._udp.local. -> <result>
3376 // 4) result above should generate a callback from question in (1). result added to global list
3377 // 5) global list delivered to client via GetSearchDomainList()
3378 // 6) client calls to enumerate domains now go over LocalOnly interface
3379 // (!!!KRS may add outgoing interface in addition)
3381 mDNSlocal mStatus
InitDNSConfig(mDNS
*const m
)
3384 static AuthRecord LocalRegPTR
;
3386 // start query for domains to be used in default (empty string domain) browses
3387 err
= mDNS_GetDomains(m
, &LegacyBrowseDomainQ
, mDNS_DomainTypeBrowseLegacy
, NULL
, mDNSInterface_LocalOnly
, FoundLegacyBrowseDomain
, NULL
);
3389 // provide browse domain "local" automatically
3390 SetSCPrefsBrowseDomain(m
, &localdomain
, mDNStrue
);
3392 // register registration domain "local"
3393 mDNS_SetupResourceRecord(&LocalRegPTR
, mDNSNULL
, mDNSInterface_LocalOnly
, kDNSType_PTR
, 7200, kDNSRecordTypeShared
, NULL
, NULL
);
3394 MakeDomainNameFromDNSNameString(LocalRegPTR
.resrec
.name
, mDNS_DomainTypeNames
[mDNS_DomainTypeRegistration
]);
3395 AppendDNSNameString (LocalRegPTR
.resrec
.name
, "local");
3396 AssignDomainName(&LocalRegPTR
.resrec
.rdata
->u
.name
, &localdomain
);
3397 err
= mDNS_Register(m
, &LocalRegPTR
);
3398 if (err
) LogMsg("ERROR: InitDNSConfig - mDNS_Register returned error %d", err
);
3400 return mStatus_NoError
;
3403 mDNSlocal mStatus
mDNSPlatformInit_setup(mDNS
*const m
)
3405 // In 10.4, mDNSResponder is launched very early in the boot process, while other subsystems are still in the process of starting up.
3406 // 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.
3408 for (i
=0; i
<100; i
++)
3410 domainlabel testlabel
;
3412 GetUserSpecifiedLocalHostName(&testlabel
);
3413 if (testlabel
.c
[0]) break;
3419 m
->hostlabel
.c
[0] = 0;
3421 char *HINFO_HWstring
= "Macintosh";
3422 char HINFO_HWstring_buffer
[256];
3423 int get_model
[2] = { CTL_HW
, HW_MODEL
};
3424 size_t len_model
= sizeof(HINFO_HWstring_buffer
);
3425 if (sysctl(get_model
, 2, HINFO_HWstring_buffer
, &len_model
, NULL
, 0) == 0)
3426 HINFO_HWstring
= HINFO_HWstring_buffer
;
3428 char HINFO_SWstring
[256] = "";
3429 if (mDNSMacOSXSystemBuildNumber(HINFO_SWstring
) < 7) m
->KnownBugs
|= mDNS_KnownBug_PhantomInterfaces
;
3430 if (mDNSPlatformInit_CanReceiveUnicast()) m
->CanReceiveUnicastOn5353
= mDNStrue
;
3432 mDNSu32 hlen
= mDNSPlatformStrLen(HINFO_HWstring
);
3433 mDNSu32 slen
= mDNSPlatformStrLen(HINFO_SWstring
);
3434 if (hlen
+ slen
< 254)
3436 m
->HIHardware
.c
[0] = hlen
;
3437 m
->HISoftware
.c
[0] = slen
;
3438 mDNSPlatformMemCopy(HINFO_HWstring
, &m
->HIHardware
.c
[1], hlen
);
3439 mDNSPlatformMemCopy(HINFO_SWstring
, &m
->HISoftware
.c
[1], slen
);
3442 m
->p
->unicastsockets
.m
= m
;
3443 m
->p
->unicastsockets
.info
= NULL
;
3444 m
->p
->unicastsockets
.sktv4
= m
->p
->unicastsockets
.sktv6
= -1;
3445 m
->p
->unicastsockets
.cfsv4
= m
->p
->unicastsockets
.cfsv6
= NULL
;
3446 m
->p
->unicastsockets
.rlsv4
= m
->p
->unicastsockets
.rlsv6
= NULL
;
3448 err
= SetupSocket(m
, &m
->p
->unicastsockets
, mDNSfalse
, &zeroAddr
, AF_INET
);
3449 err
= SetupSocket(m
, &m
->p
->unicastsockets
, mDNSfalse
, &zeroAddr
, AF_INET6
);
3451 struct sockaddr_in s4
;
3452 struct sockaddr_in6 s6
;
3453 int n4
= sizeof(s4
);
3454 int n6
= sizeof(s6
);
3455 if (getsockname(m
->p
->unicastsockets
.sktv4
, (struct sockaddr
*)&s4
, &n4
) < 0) LogMsg("getsockname v4 error %d (%s)", errno
, strerror(errno
));
3456 else m
->UnicastPort4
.NotAnInteger
= s4
.sin_port
;
3457 if (getsockname(m
->p
->unicastsockets
.sktv6
, (struct sockaddr
*)&s6
, &n6
) < 0) LogMsg("getsockname v6 error %d (%s)", errno
, strerror(errno
));
3458 else m
->UnicastPort6
.NotAnInteger
= s6
.sin6_port
;
3460 m
->p
->InterfaceList
= mDNSNULL
;
3461 m
->p
->userhostlabel
.c
[0] = 0;
3462 m
->p
->usernicelabel
.c
[0] = 0;
3463 m
->p
->NotifyUser
= 0;
3464 mDNSs32 utc
= mDNSPlatformUTC();
3465 UpdateInterfaceList(m
, utc
);
3466 SetupActiveInterfaces(m
, utc
);
3468 err
= WatchForNetworkChanges(m
);
3469 if (err
) return(err
);
3471 err
= WatchForPowerChanges(m
);
3472 if (err
) return err
;
3474 DynDNSRegDomain
.c
[0] = '\0';
3475 DynDNSConfigChanged(m
); // Get initial DNS configuration
3481 mDNSexport mStatus
mDNSPlatformInit(mDNS
*const m
)
3483 mStatus result
= mDNSPlatformInit_setup(m
);
3485 // We don't do asynchronous initialization on OS X, so by the time we get here the setup will already
3486 // have succeeded or failed -- so if it succeeded, we should just call mDNSCoreInitComplete() immediately
3487 if (result
== mStatus_NoError
) mDNSCoreInitComplete(m
, mStatus_NoError
);
3491 mDNSexport
void mDNSPlatformClose(mDNS
*const m
)
3493 if (m
->p
->PowerConnection
)
3495 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m
->p
->PowerRLS
, kCFRunLoopDefaultMode
);
3496 CFRunLoopSourceInvalidate(m
->p
->PowerRLS
);
3497 CFRelease(m
->p
->PowerRLS
);
3498 IODeregisterForSystemPower(&m
->p
->PowerNotifier
);
3499 m
->p
->PowerConnection
= 0;
3500 m
->p
->PowerNotifier
= 0;
3501 m
->p
->PowerRLS
= NULL
;
3506 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m
->p
->StoreRLS
, kCFRunLoopDefaultMode
);
3507 CFRunLoopSourceInvalidate(m
->p
->StoreRLS
);
3508 CFRelease(m
->p
->StoreRLS
);
3509 CFRelease(m
->p
->Store
);
3511 m
->p
->StoreRLS
= NULL
;
3514 mDNSs32 utc
= mDNSPlatformUTC();
3515 MarkAllInterfacesInactive(m
, utc
);
3516 ClearInactiveInterfaces(m
, utc
);
3517 CloseSocketSet(&m
->p
->unicastsockets
);
3520 mDNSexport mDNSu32
mDNSPlatformRandomSeed(void)
3522 return(mach_absolute_time());
3525 mDNSexport mDNSs32 mDNSPlatformOneSecond
= 1000;
3527 mDNSexport mStatus
mDNSPlatformTimeInit(void)
3529 // Notes: Typical values for mach_timebase_info:
3530 // tbi.numer = 1000 million
3531 // tbi.denom = 33 million
3532 // These are set such that (mach_absolute_time() * numer/denom) gives us nanoseconds;
3533 // numer / denom = nanoseconds per hardware clock tick (e.g. 30);
3534 // denom / numer = hardware clock ticks per nanosecond (e.g. 0.033)
3535 // (denom*1000000) / numer = hardware clock ticks per millisecond (e.g. 33333)
3536 // So: mach_absolute_time() / ((denom*1000000)/numer) = milliseconds
3538 // Arithmetic notes:
3539 // tbi.denom is at least 1, and not more than 2^32-1.
3540 // Therefore (tbi.denom * 1000000) is at least one million, but cannot overflow a uint64_t.
3541 // tbi.denom is at least 1, and not more than 2^32-1.
3542 // Therefore clockdivisor should end up being a number roughly in the range 10^3 - 10^9.
3543 // If clockdivisor is less than 10^3 then that means that the native clock frequency is less than 1MHz,
3544 // which is unlikely on any current or future Macintosh.
3545 // If clockdivisor is greater than 10^9 then that means the native clock frequency is greater than 1000GHz.
3546 // When we ship Macs with clock frequencies above 1000GHz, we may have to update this code.
3547 struct mach_timebase_info tbi
;
3548 kern_return_t result
= mach_timebase_info(&tbi
);
3549 if (result
== KERN_SUCCESS
) clockdivisor
= ((uint64_t)tbi
.denom
* 1000000) / tbi
.numer
;
3553 mDNSexport mDNSs32
mDNSPlatformRawTime(void)
3555 if (clockdivisor
== 0) { LogMsg("mDNSPlatformRawTime called before mDNSPlatformTimeInit"); return(0); }
3557 static uint64_t last_mach_absolute_time
= 0;
3558 uint64_t this_mach_absolute_time
= mach_absolute_time();
3559 if ((int64_t)this_mach_absolute_time
- (int64_t)last_mach_absolute_time
< 0)
3561 LogMsg("mDNSPlatformRawTime: last_mach_absolute_time %08X%08X", last_mach_absolute_time
);
3562 LogMsg("mDNSPlatformRawTime: this_mach_absolute_time %08X%08X", this_mach_absolute_time
);
3563 // Update last_mach_absolute_time *before* calling NotifyOfElusiveBug()
3564 last_mach_absolute_time
= this_mach_absolute_time
;
3565 // Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xyyy) or later
3566 if (mDNSMacOSXSystemBuildNumber(NULL
) >= 8)
3567 NotifyOfElusiveBug("mach_absolute_time went backwards!", 3438376, "");
3569 last_mach_absolute_time
= this_mach_absolute_time
;
3571 return((mDNSs32
)(this_mach_absolute_time
/ clockdivisor
));
3574 mDNSexport mDNSs32
mDNSPlatformUTC(void)
3579 // Locking is a no-op here, because we're single-threaded with a CFRunLoop, so we can never interrupt ourselves
3580 mDNSexport
void mDNSPlatformLock (const mDNS
*const m
) { (void)m
; }
3581 mDNSexport
void mDNSPlatformUnlock (const mDNS
*const m
) { (void)m
; }
3582 mDNSexport
void mDNSPlatformStrCopy(const void *src
, void *dst
) { strcpy((char *)dst
, (char *)src
); }
3583 mDNSexport mDNSu32
mDNSPlatformStrLen (const void *src
) { return(strlen((char*)src
)); }
3584 mDNSexport
void mDNSPlatformMemCopy(const void *src
, void *dst
, mDNSu32 len
) { memcpy(dst
, src
, len
); }
3585 mDNSexport mDNSBool
mDNSPlatformMemSame(const void *src
, const void *dst
, mDNSu32 len
) { return(memcmp(dst
, src
, len
) == 0); }
3586 mDNSexport
void mDNSPlatformMemZero( void *dst
, mDNSu32 len
) { bzero(dst
, len
); }
3587 mDNSexport
void * mDNSPlatformMemAllocate(mDNSu32 len
) { return(mallocL("mDNSPlatformMemAllocate", len
)); }
3588 mDNSexport
void mDNSPlatformMemFree (void *mem
) { freeL("mDNSPlatformMemFree", mem
); }