]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/mDNSMacOSX.c
mDNSResponder-107.4.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / mDNSMacOSX.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
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
12 * file.
13 *
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.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23
24 Change History (most recent first):
25
26 $Log: mDNSMacOSX.c,v $
27 Revision 1.318 2005/10/20 00:10:34 cheshire
28 <rdar://problem/4290265> Add check to avoid crashing NAT gateways that have buggy DNS relay code
29
30 Revision 1.317 2005/09/24 01:10:26 cheshire
31 Fix comment typos
32
33 Revision 1.316 2005/07/29 18:04:22 ksekar
34 <rdar://problem/4137930> Hostname registration should register IPv6 AAAA record with DNS Update
35
36 Revision 1.315 2005/07/22 21:50:55 ksekar
37 Fix GCC 4.0/Intel compiler warnings
38
39 Revision 1.314 2005/07/11 02:12:09 cheshire
40 <rdar://problem/4147774> Be defensive against invalid UTF-8 in dynamic host names
41 Fix copy-and-paste error: "CFRelease(StatusVals[0]);" should be "CFRelease(StateVals[0]);"
42
43 Revision 1.313 2005/07/04 23:52:25 cheshire
44 <rdar://problem/3923098> Things are showing up with a bogus interface index
45
46 Revision 1.312 2005/07/04 22:24:36 cheshire
47 Export NotifyOfElusiveBug() so other files can call it
48
49 Revision 1.311 2005/06/15 13:20:43 cheshire
50 <rdar://problem/4147774> Be defensive against invalid UTF-8 in dynamic host names
51
52 Revision 1.310 2005/04/07 00:49:58 cheshire
53 <rdar://problem/4080074> PPP connection disables Bonjour ".local" lookups
54
55 Revision 1.309 2005/03/23 05:53:29 cheshire
56 Fix %s where it should have been %##s in debugf & LogMsg calls
57
58 Revision 1.308 2005/03/09 00:48:44 cheshire
59 <rdar://problem/4015157> QU packets getting sent too early on wake from sleep
60 Move "m->p->NetworkChanged = 0;" line from caller to callee
61
62 Revision 1.307 2005/03/03 03:12:02 cheshire
63 Add comment about mDNSMacOSXSystemBuildNumber()
64
65 Revision 1.306 2005/03/02 22:18:00 cheshire
66 <rdar://problem/3930171> mDNSResponder requires AppleInternal packages to build on Tiger
67
68 Revision 1.305 2005/02/26 05:08:28 cheshire
69 <rdar://problem/3930171> mDNSResponder requires AppleInternal packages to build on Tiger
70 Added dnsinfo.h to project directory
71
72 Revision 1.304 2005/02/25 23:51:22 cheshire
73 <rdar://problem/4021868> SendServiceRegistration fails on wake from sleep
74 Return mStatus_UnknownErr instead of -1
75
76 Revision 1.303 2005/02/25 17:47:45 ksekar
77 <rdar://problem/4021868> SendServiceRegistration fails on wake from sleep
78
79 Revision 1.302 2005/02/25 02:34:14 cheshire
80 <rdar://problem/4017292> Should not indicate successful dynamic update if no network connection
81 Show status as 1 (in progress) while we're trying
82
83 Revision 1.301 2005/02/24 21:55:57 ksekar
84 <rdar://problem/4017292> Should not indicate successful dynamic update if no network connection
85
86 Revision 1.300 2005/02/15 20:03:13 ksekar
87 <rdar://problem/4005868> Crash when SCPreferences contains empty array
88
89 Revision 1.299 2005/02/15 02:46:53 cheshire
90 <rdar://problem/3967876> Don't log ENETUNREACH errors for unicast destinations
91
92 Revision 1.298 2005/02/10 00:41:59 cheshire
93 Fix compiler warning
94
95 Revision 1.297 2005/02/09 23:38:51 ksekar
96 <rdar://problem/3993508> Reregister hostname when DNS server changes but IP address does not
97
98 Revision 1.296 2005/02/01 21:06:52 ksekar
99 Avoid spurious log message
100
101 Revision 1.295 2005/02/01 19:33:30 ksekar
102 <rdar://problem/3985239> Keychain format too restrictive
103
104 Revision 1.294 2005/01/27 21:30:23 cheshire
105 <rdar://problem/3952067> "Can't assign requested address" message after AirPort turned off
106 Don't write syslog messages for EADDRNOTAVAIL if we know network configuration changes are happening
107
108 Revision 1.293 2005/01/27 19:15:41 cheshire
109 Remove extraneous LogMsg() call
110
111 Revision 1.292 2005/01/27 17:48:38 cheshire
112 Added comment about CFSocketInvalidate closing the underlying socket
113
114 Revision 1.291 2005/01/27 00:10:58 cheshire
115 <rdar://problem/3967867> Name change log messages every time machine boots
116
117 Revision 1.290 2005/01/25 23:18:30 ksekar
118 fix for <rdar://problem/3971467> requires that local-only ".local" registration record be created
119
120 Revision 1.289 2005/01/25 18:08:31 ksekar
121 Removed redundant debug output
122
123 Revision 1.288 2005/01/25 17:42:26 ksekar
124 Renamed FoundDefBrowseDomain -> FoundLegacyBrowseDomain,
125 cleaned up duplicate log messages when adding/removing browse domains
126
127 Revision 1.287 2005/01/25 16:59:23 ksekar
128 <rdar://problem/3971138> sa_len not set checking reachability for TCP connections
129
130 Revision 1.286 2005/01/25 02:02:37 cheshire
131 <rdar://problem/3970673> mDNSResponder leaks
132 GetSearchDomains() was not calling dns_configuration_free().
133
134 Revision 1.285 2005/01/22 00:07:54 ksekar
135 <rdar://problem/3960546> mDNSResponder should look at all browse domains in SCPreferences
136
137 Revision 1.284 2005/01/21 23:07:17 ksekar
138 <rdar://problem/3960795> mDNSResponder causes Dial on Demand
139
140 Revision 1.283 2005/01/19 21:16:16 cheshire
141 Make sure when we set NetworkChanged that we don't set it to zero
142
143 Revision 1.282 2005/01/19 19:19:21 ksekar
144 <rdar://problem/3960191> Need a way to turn off domain discovery
145
146 Revision 1.281 2005/01/18 18:10:55 ksekar
147 <rdar://problem/3954575> Use 10.4 resolver API to get search domains
148
149 Revision 1.280 2005/01/17 22:48:52 ksekar
150 No longer need to call MarkSearchListElem for registration domain
151
152 Revision 1.279 2005/01/17 20:40:34 ksekar
153 SCPreferences changes should remove exactly one browse and one legacy browse domain for each remove event
154
155 Revision 1.278 2005/01/17 19:53:34 ksekar
156 Refinement to previous fix - register _legacy._browse records for SCPreference domains to achieve correct reference counting
157
158 Revision 1.277 2005/01/12 00:17:50 ksekar
159 <rdar://problem/3933573> Update LLQs *after* setting DNS
160
161 Revision 1.276 2005/01/10 17:39:10 ksekar
162 Refinement to 1.272 - avoid spurious warnings when registration and browse domains are set to same value and toggled on/off
163
164 Revision 1.275 2005/01/10 04:02:22 ksekar
165 Refinement to <rdar://problem/3891628> - strip trailing dot before writing hostname status to dynamic store
166
167 Revision 1.274 2005/01/10 03:41:36 ksekar
168 Correction to checkin 1.272 - check that registration domain is set
169 before trying to remove it as an implicit browse domain
170
171 Revision 1.273 2005/01/08 00:42:18 ksekar
172 <rdar://problem/3922758> Clean up syslog messages
173
174 Revision 1.272 2005/01/07 23:21:42 ksekar
175 <rdar://problem/3891628> Clean up SCPreferences format
176
177 Revision 1.271 2004/12/20 23:18:12 cheshire
178 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
179 One more refinement: When an interface with a v6LL address gets a v4 address too, that's not a flap
180
181 Revision 1.270 2004/12/20 21:28:14 cheshire
182 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
183 Additional refinements to handle sleep/wake better
184
185 Revision 1.269 2004/12/20 20:48:11 cheshire
186 Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xxx) or later
187
188 Revision 1.268 2004/12/18 03:19:04 cheshire
189 Show netmask in error log
190
191 Revision 1.267 2004/12/18 00:51:52 cheshire
192 Use symbolic constant kDNSServiceInterfaceIndexLocalOnly instead of (mDNSu32) ~0
193
194 Revision 1.266 2004/12/17 23:49:38 cheshire
195 <rdar://problem/3922754> Computer Name change is slow
196 Also treat changes to "Setup:/Network/DynamicDNS" the same way
197
198 Revision 1.265 2004/12/17 23:37:47 cheshire
199 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
200 (and other repetitive configuration changes)
201
202 Revision 1.264 2004/12/17 19:03:05 cheshire
203 Update debugging messages to show netmask a simple CIDR-style numeric value (0-128)
204
205 Revision 1.263 2004/12/17 05:25:46 cheshire
206 <rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs
207
208 Revision 1.262 2004/12/17 04:48:32 cheshire
209 <rdar://problem/3922754> Computer Name change is slow
210
211 Revision 1.261 2004/12/17 02:40:08 cheshire
212 Undo last change -- it was too strict
213
214 Revision 1.260 2004/12/16 22:17:16 cheshire
215 Only accept multicast packets on interfaces that have McastTxRx set
216
217 Revision 1.259 2004/12/16 20:13:01 cheshire
218 <rdar://problem/3324626> Cache memory management improvements
219
220 Revision 1.258 2004/12/14 00:18:05 cheshire
221 Don't log dns_configuration_copy() failures in the first three minutes after boot
222
223 Revision 1.257 2004/12/10 19:45:46 cheshire
224 <rdar://problem/3915074> Reduce egregious stack space usage
225 Reduced myCFSocketCallBack() stack frame from 9K to 512 bytes
226
227 Revision 1.256 2004/12/10 04:35:43 cheshire
228 <rdar://problem/3907233> Show "Note: Compiled without Apple-specific split DNS support" only once
229
230 Revision 1.255 2004/12/10 04:12:54 ksekar
231 <rdar://problem/3890764> Need new DefaultBrowseDomain key
232
233 Revision 1.254 2004/12/10 01:55:31 ksekar
234 <rdar://problem/3899067> Keychain lookups should be in lower case.
235
236 Revision 1.253 2004/12/09 03:15:41 ksekar
237 <rdar://problem/3806610> use _legacy instead of _default to find "empty string" browse domains
238
239 Revision 1.252 2004/12/07 01:32:42 cheshire
240 Don't log dns_configuration_copy() failure when running on 10.3
241
242 Revision 1.251 2004/12/06 22:30:31 cheshire
243 Added debugging log message
244
245 Revision 1.250 2004/12/06 06:59:08 ksekar
246 RegisterSplitDNS should return Unsupported error when compiled on Panther
247
248 Revision 1.249 2004/12/04 00:29:46 cheshire
249 Add "#ifdef MAC_OS_X_VERSION_10_4" around split-DNS code that can't be compiled on 10.3 systems
250 (When compiled on 10.3, code will not include split-DNS support.)
251
252 Revision 1.248 2004/12/01 20:57:20 ksekar
253 <rdar://problem/3873921> Wide Area Service Discovery must be split-DNS aware
254
255 Revision 1.247 2004/12/01 03:26:58 cheshire
256 Remove unused variables
257
258 Revision 1.246 2004/12/01 01:51:34 cheshire
259 Move ReadDDNSSettingsFromConfFile() from mDNSMacOSX.c to PlatformCommon.c
260
261 Revision 1.245 2004/11/30 03:24:04 cheshire
262 <rdar://problem/3854544> Defer processing network configuration changes until configuration has stabilized
263
264 Revision 1.244 2004/11/30 02:59:35 cheshire
265 For debugging diagnostics, added identifying strings in SCDynamicStoreCreate() calls
266
267 Revision 1.243 2004/11/29 19:17:29 ksekar
268 <rdar://problem/3878195> Unnecessary GetUserSpecifiedDDNSConfig log messages
269
270 Revision 1.242 2004/11/29 18:37:38 ksekar
271 <rdar://problem/3889341> Buffer overflow in GetConfigOption
272
273 Revision 1.241 2004/11/25 01:37:04 ksekar
274 <rdar://problem/3894854> Config file and SCPreferences don't play well together
275
276 Revision 1.240 2004/11/25 01:29:42 ksekar
277 Remove unnecessary log messages
278
279 Revision 1.239 2004/11/25 01:27:19 ksekar
280 <rdar://problem/3885859> Don't try to advertise link-local IP addresses via dynamic update
281
282 Revision 1.238 2004/11/24 22:00:59 cheshire
283 Move definition of mDNSAddressIsAllDNSLinkGroup() from mDNSMacOSX.c to mDNSEmbeddedAPI.h
284
285 Revision 1.237 2004/11/24 21:54:44 cheshire
286 <rdar://problem/3894475> mDNSCore not receiving unicast responses properly
287
288 Revision 1.236 2004/11/23 03:39:46 cheshire
289 Let interface name/index mapping capability live directly in JNISupport.c,
290 instead of having to call through to the daemon via IPC to get this information.
291
292 Revision 1.235 2004/11/17 01:45:35 cheshire
293 <rdar://problem/3847435> mDNS buddy list frequently becomes empty if you let the machine sleep
294 Refresh our interface list on receiving kIOMessageSystemHasPoweredOn,
295 in case we get no System Configuration Framework "network changed" event.
296
297 Revision 1.234 2004/11/17 00:32:56 ksekar
298 <rdar://problem/3880773> mDNSResponder will not discover zones contained both in Search Domains and DHCP Domain option
299
300 Revision 1.233 2004/11/12 03:16:45 rpantos
301 rdar://problem/3809541 Add mDNSPlatformGetInterfaceByName, mDNSPlatformGetInterfaceName
302
303 Revision 1.232 2004/11/10 20:40:54 ksekar
304 <rdar://problem/3868216> LLQ mobility fragile on non-primary interface
305
306 Revision 1.231 2004/11/06 00:59:33 ksekar
307 Don't log ENETDOWN errors for unicast destinations (pollutes log on
308 wake from sleep)
309
310 Revision 1.230 2004/11/05 01:04:10 ksekar
311 <rdar://problem/3774577> LegacyNATDestroy() called too enthusiastically
312
313 Revision 1.229 2004/11/03 03:45:16 cheshire
314 <rdar://problem/3863627> mDNSResponder does not inform user of Computer Name collisions
315
316 Revision 1.228 2004/11/02 23:47:32 cheshire
317 <rdar://problem/3863214> Default hostname and Computer Name should be unique
318
319 Revision 1.227 2004/11/02 04:23:03 cheshire
320 Change to more informative name "GetUserSpecifiedLocalHostName()"
321
322 Revision 1.226 2004/11/01 20:36:19 ksekar
323 <rdar://problem/3802395> mDNSResponder should not receive Keychain Notifications
324
325 Revision 1.225 2004/10/28 19:03:04 cheshire
326 Remove \n from LogMsg() calls
327
328 Revision 1.224 2004/10/28 17:47:34 cheshire
329 Oops. Forgot the %d in the log message.
330
331 Revision 1.223 2004/10/28 17:24:28 cheshire
332 Updated "bad ifa_netmask" log message to give more information
333
334 Revision 1.222 2004/10/28 03:36:34 cheshire
335 <rdar://problem/3856535> Share the same port for both multicast and unicast receiving
336
337 Revision 1.221 2004/10/28 03:24:41 cheshire
338 Rename m->CanReceiveUnicastOn as m->CanReceiveUnicastOn5353
339
340 Revision 1.220 2004/10/28 00:53:57 cheshire
341 Export mDNSMacOSXNetworkChanged() so it's callable from outside this mDNSMacOSX.c;
342 Add LogOperation() call to record when we get network change events
343
344 Revision 1.219 2004/10/27 20:42:20 cheshire
345 Clean up debugging messages
346
347 Revision 1.218 2004/10/27 02:03:59 cheshire
348 Update debugging messages
349
350 Revision 1.217 2004/10/26 20:48:21 cheshire
351 Improve logging messages
352
353 Revision 1.216 2004/10/26 01:02:37 cheshire
354 Update comment
355
356 Revision 1.215 2004/10/25 20:09:00 ksekar
357 Cleaned up config file parsing.
358
359 Revision 1.214 2004/10/25 19:30:53 ksekar
360 <rdar://problem/3827956> Simplify dynamic host name structures
361
362 Revision 1.213 2004/10/23 01:16:01 cheshire
363 <rdar://problem/3851677> uDNS operations not always reliable on multi-homed hosts
364
365 Revision 1.212 2004/10/22 20:52:08 ksekar
366 <rdar://problem/3799260> Create NAT port mappings for Long Lived Queries
367
368 Revision 1.211 2004/10/22 01:07:11 cheshire
369 <rdar://problem/3375328> select() says data is waiting; recvfrom() says there is no data
370 Log error message if socket() ever returns file descriptors 0, 1 or 2 (stdin/stdout/stderr).
371 These are all supposed to be remapped to /dev/null
372
373 Revision 1.210 2004/10/20 02:19:54 cheshire
374 Eliminate "SetupAddr invalid sa_family" warning from RegisterSearchDomains()
375
376 Revision 1.209 2004/10/16 00:17:00 cheshire
377 <rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
378
379 Revision 1.208 2004/10/15 23:00:18 ksekar
380 <rdar://problem/3799242> Need to update LLQs on location changes
381
382 Revision 1.207 2004/10/13 22:45:23 cheshire
383 <rdar://problem/3438392> Ten-second delay before kIOMessageSystemHasPoweredOn message
384
385 Revision 1.206 2004/10/13 22:11:46 cheshire
386 Update debugging messages
387
388 Revision 1.205 2004/10/12 21:10:11 cheshire
389 <rdar://problem/3438376> mach_absolute_time() not monotonically increasing
390 Do a NotifyOfElusiveBug() if we see mach_absolute_time() go backwards
391
392 Revision 1.204 2004/10/12 03:20:52 ksekar
393 <rdar://problem/3835614> Incorrect LogMsg produces garbage on errors
394
395 Revision 1.203 2004/10/08 04:29:25 ksekar
396 <rdar://problem/3831842> Allow default search domains to be set via hint from DHCP
397
398 Revision 1.202 2004/10/04 05:56:04 cheshire
399 <rdar://problem/3824730> mDNSResponder doesn't respond to certain AirPort changes
400
401 Revision 1.201 2004/09/30 00:24:59 ksekar
402 <rdar://problem/3695802> Dynamically update default registration domains on config change
403
404 Revision 1.200 2004/09/26 23:20:35 ksekar
405 <rdar://problem/3813108> Allow default registrations in multiple wide-area domains
406
407 Revision 1.199 2004/09/24 23:54:55 cheshire
408 <rdar://problem/3787102> Don't use kCFSocketCloseOnInvalidate
409
410 Revision 1.198 2004/09/24 23:47:49 cheshire
411 Correct comment and error message
412
413 Revision 1.197 2004/09/24 23:39:27 cheshire
414 <rdar://problem/3733705> Only IPv6 loopback address advertised on laptop w/no networking
415
416 Revision 1.196 2004/09/24 20:53:04 cheshire
417 Revise error message to say "Setsockopt SO_REUSEPORT failed" instead of "Flaw in Kernel"
418
419 Revision 1.195 2004/09/24 19:21:45 cheshire
420 <rdar://problem/3671626> Report "Address already in use" errors
421
422 Revision 1.194 2004/09/24 19:16:54 cheshire
423 Remove "mDNS *const m" parameter from NotifyOfElusiveBug();
424 Refine error message to say "Flaw in Kernel (select/recvfrom mismatch)"
425
426 Revision 1.193 2004/09/22 00:41:59 cheshire
427 Move tcp connection status codes into the legal range allocated for mDNS use
428
429 Revision 1.192 2004/09/21 21:02:55 cheshire
430 Set up ifname before calling mDNS_RegisterInterface()
431
432 Revision 1.191 2004/09/21 19:19:36 cheshire
433 <rdar://problem/3760923> Combine WatchForDynDNSChanges() into WatchForNetworkChanges()
434
435 Revision 1.190 2004/09/21 19:04:45 cheshire
436 Strip trailing white space from the ends of lines
437
438 Revision 1.189 2004/09/21 00:13:28 cheshire
439 Fix build failure (io_connect_t and io_object_t are integers, not pointers)
440
441 Revision 1.188 2004/09/20 23:52:02 cheshire
442 CFSocket{Puma}.c renamed to mDNSMacOSX{Puma}.c
443
444 Revision 1.187 2004/09/18 01:37:01 cheshire
445 Update comment
446
447 Revision 1.186 2004/09/18 01:11:57 ksekar
448 <rdar://problem/3806734> Add a user's default domain to empty-string browse list
449
450 Revision 1.185 2004/09/17 01:08:52 cheshire
451 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
452 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
453 declared in that file are ONLY appropriate to single-address-space embedded applications.
454 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
455
456 Revision 1.184 2004/09/17 00:19:10 cheshire
457 For consistency with AllDNSLinkGroupv6, rename AllDNSLinkGroup to AllDNSLinkGroupv4
458
459 Revision 1.183 2004/09/17 00:15:56 cheshire
460 Rename mDNSPlatformInit_ReceiveUnicast to mDNSPlatformInit_CanReceiveUnicast
461
462 Revision 1.182 2004/09/16 21:36:36 cheshire
463 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
464 Changes to add necessary locking calls around unicast DNS operations
465
466 Revision 1.181 2004/09/16 02:03:42 cheshire
467 <rdar://problem/3802944> Change address to notify user of kernel flaw
468
469 Revision 1.180 2004/09/16 01:58:22 cheshire
470 Fix compiler warnings
471
472 Revision 1.179 2004/09/16 00:24:49 cheshire
473 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
474
475 Revision 1.178 2004/09/15 21:51:34 cheshire
476 <rdar://problem/3387020> mDNSResponder should notify user of kernel flaw
477 Calling CFUserNotificationDisplayNotice too early in the boot process seems to kill
478 the machine, so make sure we don't do this until at least three minutes after boot.
479
480 Revision 1.177 2004/09/15 01:16:29 cheshire
481 <rdar://problem/3387020> mDNSResponder should notify user of kernel flaw
482
483 Revision 1.176 2004/09/14 23:42:36 cheshire
484 <rdar://problem/3801296> Need to seed random number generator from platform-layer data
485
486 Revision 1.175 2004/09/14 21:35:46 cheshire
487 Minor code tidying, and added comments about CFRetainCounts
488
489 Revision 1.174 2004/09/14 19:14:57 ksekar
490 <rdar://problem/3192531> DynDNS: Discovery of DynDNS Zones via Reverse-Map PTR
491
492 Revision 1.173 2004/08/25 23:35:22 ksekar
493 <rdar://problem/3770615>: Error converting shared secret from base-64 to binary
494
495 Revision 1.172 2004/08/25 02:01:45 cheshire
496 <rdar://problem/3774777> Need to be able to get status of Dynamic DNS Host Name Update
497
498 Revision 1.171 2004/08/25 01:04:42 cheshire
499 Don't need to CFRelease name and array
500
501 Revision 1.170 2004/08/25 00:37:28 ksekar
502 <rdar://problem/3774635>: Cleanup DynDNS hostname registration code
503
504 Revision 1.169 2004/08/18 17:35:41 ksekar
505 <rdar://problem/3651443>: Feature #9586: Need support for Legacy NAT gateways
506
507 Revision 1.168 2004/08/17 03:16:24 ksekar
508 Fixed checkin 1.166 - enumeration type changed for wrong invocation of mDNS_GetDomains
509
510 Revision 1.167 2004/08/17 00:52:43 ksekar
511 Fix config file parse error, make semantics match SCPreferences
512 configuration input.
513
514 Revision 1.166 2004/08/16 19:55:07 ksekar
515 Change enumeration type to BrowseDefault to construct empty-string
516 browse list as result of checking 1.161.
517
518 Revision 1.165 2004/08/16 19:52:40 ksekar
519 Pass computer name + zone for FQDN after keychain notification,
520 setting global default service registration domain to the zone.
521
522 Revision 1.164 2004/08/16 16:52:37 ksekar
523 Pass in zone read from keychain to mDNS_SetFQDNs.
524
525 Revision 1.163 2004/08/14 03:22:42 cheshire
526 <rdar://problem/3762579> Dynamic DNS UI <-> mDNSResponder glue
527 Add GetUserSpecifiedDDNSName() routine
528 Convert ServiceRegDomain to domainname instead of C string
529 Replace mDNS_GenerateFQDN/mDNS_GenerateGlobalFQDN with mDNS_SetFQDNs
530
531 Revision 1.162 2004/08/12 22:34:00 cheshire
532 All strings should be read as kCFStringEncodingUTF8, not kCFStringEncodingASCII
533
534 Revision 1.161 2004/08/11 00:17:46 ksekar
535 <rdar://problem/3757662>: 8A227: Need Lighthouse configred machines to
536 set default bit for their domains
537
538 Revision 1.160 2004/07/29 19:27:16 ksekar
539 NATPMP Support - minor fixes and cleanup
540
541 Revision 1.159 2004/07/26 22:49:31 ksekar
542 <rdar://problem/3651409>: Feature #9516: Need support for NATPMP in client
543
544 Revision 1.158 2004/07/13 21:24:24 rpantos
545 Fix for <rdar://problem/3701120>.
546
547 Revision 1.157 2004/06/08 18:54:48 ksekar
548 <rdar://problem/3681378>: mDNSResponder leaks after exploring in Printer Setup Utility
549
550 Revision 1.156 2004/06/05 00:04:26 cheshire
551 <rdar://problem/3668639>: wide-area domains should be returned in reg. domain enumeration
552
553 Revision 1.155 2004/06/04 08:58:30 ksekar
554 <rdar://problem/3668624>: Keychain integration for secure dynamic update
555
556 Revision 1.154 2004/05/31 22:22:28 ksekar
557 <rdar://problem/3668639>: wide-area domains should be returned in
558 reg. domain enumeration
559
560 Revision 1.153 2004/05/26 17:06:33 cheshire
561 <rdar://problem/3668515>: Don't rely on CFSocketInvalidate() to remove RunLoopSource
562
563 Revision 1.152 2004/05/18 23:51:26 cheshire
564 Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
565
566 Revision 1.151 2004/05/17 21:46:34 cheshire
567 <rdar://problem/3616426>: When interface is turned off, browse "remove" events are delivered with interface index zero
568 Take care to correctly update InterfaceIDs when a dormant interface comes back to life
569
570 Revision 1.150 2004/05/13 04:54:20 ksekar
571 Unified list copy/free code. Added symetric list for
572
573 Revision 1.149 2004/05/13 03:55:14 ksekar
574 Fixed list traversal bug in FoundDefSearchDomain.
575
576 Revision 1.148 2004/05/12 22:03:08 ksekar
577 Made GetSearchDomainList a true platform-layer call (declaration moved
578 from mDNSMacOSX.h to mDNSEmbeddedAPI.h), impelemted to return "local"
579 only on non-OSX platforms. Changed call to return a copy of the list
580 to avoid shared memory issues. Added a routine to free the list.
581
582 Revision 1.147 2004/05/12 02:03:25 ksekar
583 Non-local domains will only be browsed by default, and show up in
584 _browse domain enumeration, if they contain an _browse._dns-sd ptr record.
585
586 Revision 1.146 2004/04/27 02:49:15 cheshire
587 <rdar://problem/3634655>: mDNSResponder leaks sockets on bind() error
588
589 Revision 1.145 2004/04/21 03:08:03 cheshire
590 Rename 'alias' to more descriptive name 'primary'
591
592 Revision 1.144 2004/04/21 03:04:35 cheshire
593 Minor cleanup for clarity
594
595 Revision 1.143 2004/04/21 03:03:30 cheshire
596 Preparation work: AddInterfaceToList() should return pointer to structure it creates
597
598 Revision 1.142 2004/04/21 02:49:11 cheshire
599 To reduce future confusion, renamed 'TxAndRx' to 'McastTxRx'
600
601 Revision 1.141 2004/04/21 02:20:47 cheshire
602 Rename interface field 'CurrentlyActive' to more descriptive 'Exists'
603
604 Revision 1.140 2004/04/14 23:09:29 ksekar
605 Support for TSIG signed dynamic updates.
606
607 Revision 1.139 2004/04/09 17:40:26 cheshire
608 Remove unnecessary "Multicast" field -- it duplicates the semantics of the existing McastTxRx field
609
610 Revision 1.138 2004/04/09 16:37:16 cheshire
611 Suggestion from Bob Bradley:
612 Move NumCacheRecordsForInterfaceID() to DNSCommon.c so it's available to all platform layers
613
614 Revision 1.137 2004/04/08 00:59:55 cheshire
615 <rdar://problem/3609972> When interface turned off, browse "remove" events delivered with interface index zero
616 Unify use of the InterfaceID field, and make code that walks the list respect the 'Exists' flag
617
618 Revision 1.136 2004/04/07 01:08:57 cheshire
619 <rdar://problem/3609972> When interface turned off, browse "remove" events delivered with interface index zero
620
621 Revision 1.135 2004/03/19 01:01:03 ksekar
622 Fixed config file parsing to chop newline
623
624 Revision 1.134 2004/03/13 01:57:34 ksekar
625 <rdar://problem/3192546>: DynDNS: Dynamic update of service records
626
627 Revision 1.133 2004/02/02 22:46:56 cheshire
628 Move "CFRelease(dict);" inside the "if (dict)" check
629
630 Revision 1.132 2004/01/28 02:30:08 ksekar
631 Added default Search Domains to unicast browsing, controlled via
632 Networking sharing prefs pane. Stopped sending unicast messages on
633 every interface. Fixed unicast resolving via mach-port API.
634
635 Revision 1.131 2004/01/27 22:57:48 cheshire
636 <rdar://problem/3534352>: Need separate socket for issuing unicast queries
637
638 Revision 1.130 2004/01/27 22:28:40 cheshire
639 <rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
640 Additional lingering port 53 code deleted
641
642 Revision 1.129 2004/01/27 20:15:23 cheshire
643 <rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
644
645 Revision 1.128 2004/01/24 23:58:17 cheshire
646 Change to use mDNSVal16() instead of shifting and ORing
647
648 Revision 1.127 2004/01/24 04:59:16 cheshire
649 Fixes so that Posix/Linux, OS9, Windows, and VxWorks targets build again
650
651 Revision 1.126 2004/01/23 23:23:15 ksekar
652 Added TCP support for truncated unicast messages.
653
654 Revision 1.125 2004/01/22 03:43:09 cheshire
655 Export constants like mDNSInterface_LocalOnly so that the client layers can use them
656
657 Revision 1.124 2004/01/21 21:53:19 cheshire
658 <rdar://problem/3448144>: Don't try to receive unicast responses if we're not the first to bind to the UDP port
659
660 Revision 1.123 2004/01/20 03:18:25 cheshire
661 Removed "LogMsg("Hey There!");" that evidently got checked in my mistake
662
663 Revision 1.122 2003/12/17 20:43:59 cheshire
664 <rdar://problem/3496728>: Syslog messages saying "sendto failed"
665
666 Revision 1.121 2003/12/13 03:05:28 ksekar
667 <rdar://problem/3192548>: DynDNS: Unicast query of service records
668
669 Revision 1.120 2003/12/08 21:00:46 rpantos
670 Changes to support mDNSResponder on Linux.
671
672 Revision 1.119 2003/12/03 02:35:15 cheshire
673 Also report value of m->timenow when logging sendto() failure
674
675 Revision 1.118 2003/11/14 20:59:09 cheshire
676 Clients can't use AssignDomainName macro because mDNSPlatformMemCopy is defined in mDNSPlatformFunctions.h.
677 Best solution is just to combine mDNSEmbeddedAPI.h and mDNSPlatformFunctions.h into a single file.
678
679 Revision 1.117 2003/11/08 22:18:29 cheshire
680 <rdar://problem/3477870>: Don't need to show process ID in *every* mDNSResponder syslog message
681
682 Revision 1.116 2003/09/23 16:39:49 cheshire
683 When LogAllOperations is set, also report registration and deregistration of interfaces
684
685 Revision 1.115 2003/09/10 00:45:55 cheshire
686 <rdar://problem/3412328> Don't log "sendto failed" errors during the first two minutes of startup
687
688 Revision 1.114 2003/08/27 02:55:13 cheshire
689 <rdar://problem/3387910>: Bug: Don't report mDNSPlatformSendUDP sendto errno 64 (Host is down)
690
691 Revision 1.113 2003/08/19 22:20:00 cheshire
692 <rdar://problem/3376721> Don't use IPv6 on interfaces that have a routable IPv4 address configured
693 More minor refinements
694
695 Revision 1.112 2003/08/19 03:04:43 cheshire
696 <rdar://problem/3376721> Don't use IPv6 on interfaces that have a routable IPv4 address configured
697
698 Revision 1.111 2003/08/18 22:53:37 cheshire
699 <rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformRawTime()
700
701 Revision 1.110 2003/08/16 03:39:00 cheshire
702 <rdar://problem/3338440> InterfaceID -1 indicates "local only"
703
704 Revision 1.109 2003/08/15 02:19:49 cheshire
705 <rdar://problem/3375225> syslog messages: myCFSocketCallBack recvfrom skt 6 error -1 errno 35
706 Also limit number of messages to at most 100
707
708 Revision 1.108 2003/08/12 22:24:52 cheshire
709 <rdar://problem/3375225> syslog messages: myCFSocketCallBack recvfrom skt 6 error -1 errno 35
710 This message indicates a kernel bug, but still we don't want to flood syslog.
711 Do a sleep(1) after writing this log message, to limit the rate.
712
713 Revision 1.107 2003/08/12 19:56:25 cheshire
714 Update to APSL 2.0
715
716 Revision 1.106 2003/08/12 13:48:32 cheshire
717 Add comment explaining clockdivisor calculation
718
719 Revision 1.105 2003/08/12 13:44:14 cheshire
720 <rdar://problem/3370229> mDNSResponder *VERY* unhappy if time goes backwards
721 Use mach_absolute_time() (which is guaranteed to always go forwards, resetting only on reboot)
722 instead of gettimeofday() (which can jump back if the user manually changes their time/date)
723
724 Revision 1.104 2003/08/12 13:12:07 cheshire
725 Textual search/replace: Indicate local functions using "mDNSlocal" instead of "static"
726
727 Revision 1.103 2003/08/08 18:36:04 cheshire
728 <rdar://problem/3344154> Only need to revalidate on interface removal on platforms that have the PhantomInterfaces bug
729
730 Revision 1.102 2003/08/06 00:14:52 cheshire
731 <rdar://problem/3330324> Need to check IP TTL on responses
732 Also add corresponding checks in the IPv6 code path
733
734 Revision 1.101 2003/08/05 22:20:16 cheshire
735 <rdar://problem/3330324> Need to check IP TTL on responses
736
737 Revision 1.100 2003/08/05 21:18:50 cheshire
738 <rdar://problem/3363185> mDNSResponder should ignore 6to4
739 Only use interfaces that are marked as multicast-capable (IFF_MULTICAST)
740
741 Revision 1.99 2003/08/05 20:13:52 cheshire
742 <rdar://problem/3294080> mDNSResponder using IPv6 interfaces before they are ready
743 Ignore interfaces with the IN6_IFF_NOTREADY flag set
744
745 Revision 1.98 2003/07/20 03:38:51 ksekar
746 <rdar://problem/3320722>
747 Completed support for Unix-domain socket based API.
748
749 Revision 1.97 2003/07/19 03:15:16 cheshire
750 Add generic MemAllocate/MemFree prototypes to mDNSPlatformFunctions.h,
751 and add the obvious trivial implementations to each platform support layer
752
753 Revision 1.96 2003/07/18 00:30:00 cheshire
754 <rdar://problem/3268878> Remove mDNSResponder version from packet header and use HINFO record instead
755
756 Revision 1.95 2003/07/12 03:15:20 cheshire
757 <rdar://problem/3324848> After SCDynamicStore notification, mDNSResponder updates
758 m->hostlabel even if user hasn't actually actually changed their dot-local hostname
759
760 Revision 1.94 2003/07/03 00:51:54 cheshire
761 <rdar://problem/3287213> When select() and recvmgs() disagree, get more info from kernel about the socket state
762
763 Revision 1.93 2003/07/03 00:09:14 cheshire
764 <rdar://problem/3286004> New APIs require a mDNSPlatformInterfaceIDfromInterfaceIndex() call
765 Additional refinement suggested by Josh: Use info->scope_id instead of if_nametoindex(info->ifa_name);
766
767 Revision 1.92 2003/07/02 21:19:51 cheshire
768 <rdar://problem/3313413> Update copyright notices, etc., in source code comments
769
770 Revision 1.91 2003/06/24 01:53:51 cheshire
771 Minor update to comments
772
773 Revision 1.90 2003/06/24 01:51:47 cheshire
774 <rdar://problem/3303118> Oops: Double-dispose of sockets
775 Don't need to close sockets: CFSocketInvalidate() does that for us
776
777 Revision 1.89 2003/06/21 18:12:47 cheshire
778 <rdar://problem/3296061> mDNSResponder cannot handle interfaces whose total name is >3 chars
779 One-line change: should say "IF_NAMESIZE", not sizeof(ifname)
780
781 Revision 1.88 2003/06/12 23:38:37 cheshire
782 <rdar://problem/3291162> mDNSResponder doesn't detect some configuration changes
783 Also check that scope_id matches before concluding that two interfaces are the same
784
785 Revision 1.87 2003/06/10 01:14:11 cheshire
786 <rdar://problem/3286004> New APIs require a mDNSPlatformInterfaceIDfromInterfaceIndex() call
787
788 Revision 1.86 2003/05/28 02:41:52 cheshire
789 <rdar://problem/3034346> Time to remove Mac OS 9 UDP Port 53 legacy support
790
791 Revision 1.85 2003/05/28 02:39:47 cheshire
792 Minor change to debugging messages
793
794 Revision 1.84 2003/05/27 22:29:40 cheshire
795 Remove out-dated comment
796
797 Revision 1.83 2003/05/26 03:21:29 cheshire
798 Tidy up address structure naming:
799 mDNSIPAddr => mDNSv4Addr (for consistency with mDNSv6Addr)
800 mDNSAddr.addr.ipv4 => mDNSAddr.ip.v4
801 mDNSAddr.addr.ipv6 => mDNSAddr.ip.v6
802
803 Revision 1.82 2003/05/26 03:01:27 cheshire
804 <rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
805
806 Revision 1.81 2003/05/24 02:06:42 cheshire
807 <rdar://problem/3268480> IPv6 Multicast Loopback doesn't work
808 Tried setting IPV6_MULTICAST_LOOP; it doesn't help.
809 However, it is probably wise to have the code explicitly set this socket
810 option anyway, in case the default changes in later versions of Unix.
811
812 Revision 1.80 2003/05/24 02:02:24 cheshire
813 <rdar://problem/3221880> if_indextoname consumes a lot of CPU
814 Fix error in myIfIndexToName; was returning prematurely
815
816 Revision 1.79 2003/05/23 23:07:44 cheshire
817 <rdar://problem/3268199> Must not write to stderr when running as daemon
818
819 Revision 1.78 2003/05/23 01:19:04 cheshire
820 <rdar://problem/3267085> mDNSResponder needs to signal type of service to AirPort
821 Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
822
823 Revision 1.77 2003/05/23 01:12:05 cheshire
824 Minor code tidying
825
826 Revision 1.76 2003/05/22 01:26:01 cheshire
827 Tidy up log messages
828
829 Revision 1.75 2003/05/22 00:07:09 cheshire
830 <rdar://problem/3264366> myCFSocketCallBack recvfrom(5) error 1, errno 35
831 Extra logging to determine whether there is a bug in CFSocket
832
833 Revision 1.74 2003/05/21 20:20:12 cheshire
834 Fix warnings (mainly printf format string warnings, like using "%d" where
835 it should say "%lu", etc.) and improve error logging (use strerror()
836 to include textual error message as well as numeric error in log messages).
837
838 Revision 1.73 2003/05/21 17:56:29 ksekar
839 <rdar://problem/3191277>: mDNSResponder doesn't watch for IPv6 address changes
840
841 Revision 1.72 2003/05/14 18:48:41 cheshire
842 <rdar://problem/3159272> mDNSResponder should be smarter about reconfigurations
843 More minor refinements:
844 mDNSMacOSX.c needs to do *all* its mDNS_DeregisterInterface calls before freeing memory
845 mDNS_DeregisterInterface revalidates cache record when *any* representative of an interface goes away
846
847 Revision 1.71 2003/05/14 07:08:37 cheshire
848 <rdar://problem/3159272> mDNSResponder should be smarter about reconfigurations
849 Previously, when there was any network configuration change, mDNSResponder
850 would tear down the entire list of active interfaces and start again.
851 That was very disruptive, and caused the entire cache to be flushed,
852 and caused lots of extra network traffic. Now it only removes interfaces
853 that have really gone, and only adds new ones that weren't there before.
854
855 Revision 1.70 2003/05/07 18:30:24 cheshire
856 Fix signed/unsigned comparison warning
857
858 Revision 1.69 2003/05/06 20:14:44 cheshire
859 Change "tp" to "tv"
860
861 Revision 1.68 2003/05/06 00:00:49 cheshire
862 <rdar://problem/3248914> Rationalize naming of domainname manipulation functions
863
864 Revision 1.67 2003/04/29 00:43:44 cheshire
865 Fix compiler warnings
866
867 Revision 1.66 2003/04/26 02:41:58 cheshire
868 <rdar://problem/3241281> Change timenow from a local variable to a structure member
869
870 Revision 1.65 2003/04/26 02:34:01 cheshire
871 Add missing mDNSexport
872
873 Revision 1.64 2003/04/15 16:48:06 jgraessl
874 <rdar://problem/3228833>
875 Modified code in CFSocket notifier function to read all packets on the socket
876 instead of reading only one packet every time the notifier was called.
877
878 Revision 1.63 2003/04/15 16:33:50 jgraessl
879 <rdar://problem/3221880>
880 Switched to our own copy of if_indextoname to improve performance.
881
882 Revision 1.62 2003/03/28 01:55:44 cheshire
883 Minor improvements to debugging messages
884
885 Revision 1.61 2003/03/27 03:30:56 cheshire
886 <rdar://problem/3210018> Name conflicts not handled properly, resulting in memory corruption, and eventual crash
887 Problem was that HostNameCallback() was calling mDNS_DeregisterInterface(), which is not safe in a callback
888 Fixes:
889 1. Make mDNS_DeregisterInterface() safe to call from a callback
890 2. Make HostNameCallback() use mDNS_DeadvertiseInterface() instead
891 (it never really needed to deregister the interface at all)
892
893 Revision 1.60 2003/03/15 04:40:38 cheshire
894 Change type called "mDNSOpaqueID" to the more descriptive name "mDNSInterfaceID"
895
896 Revision 1.59 2003/03/11 01:23:26 cheshire
897 <rdar://problem/3194246> mDNSResponder socket problems
898
899 Revision 1.58 2003/03/06 01:43:04 cheshire
900 <rdar://problem/3189097> Additional debugging code in mDNSResponder
901 Improve "LIST_ALL_INTERFACES" output
902
903 Revision 1.57 2003/03/05 22:36:27 cheshire
904 <rdar://problem/3186338> Loopback doesn't work with mDNSResponder-27
905 Temporary workaround: Skip loopback interface *only* if we found at least one v4 interface to use
906
907 Revision 1.56 2003/03/05 01:50:38 cheshire
908 <rdar://problem/3189097> Additional debugging code in mDNSResponder
909
910 Revision 1.55 2003/02/21 01:54:09 cheshire
911 <rdar://problem/3099194> mDNSResponder needs performance improvements
912 Switched to using new "mDNS_Execute" model (see "Implementer Notes.txt")
913
914 Revision 1.54 2003/02/20 06:48:35 cheshire
915 <rdar://problem/3169535> Xserve RAID needs to do interface-specific registrations
916 Reviewed by: Josh Graessley, Bob Bradley
917
918 Revision 1.53 2003/01/29 02:21:23 cheshire
919 Return mStatus_Invalid if can't send packet because socket not available
920
921 Revision 1.52 2003/01/28 19:39:43 jgraessl
922 Enabling AAAA over IPv4 support.
923
924 Revision 1.51 2003/01/28 05:11:23 cheshire
925 Fixed backwards comparison in SearchForInterfaceByName
926
927 Revision 1.50 2003/01/13 23:49:44 jgraessl
928 Merged changes for the following fixes in to top of tree:
929 <rdar://problem/3086540> computer name changes not handled properly
930 <rdar://problem/3124348> service name changes are not properly handled
931 <rdar://problem/3124352> announcements sent in pairs, failing chattiness test
932
933 Revision 1.49 2002/12/23 22:13:30 jgraessl
934 Reviewed by: Stuart Cheshire
935 Initial IPv6 support for mDNSResponder.
936
937 Revision 1.48 2002/11/22 01:37:52 cheshire
938 <rdar://problem/3108426> mDNSResponder is monitoring ServiceEntities instead of InterfaceEntities
939
940 Revision 1.47 2002/09/21 20:44:51 zarzycki
941 Added APSL info
942
943 Revision 1.46 2002/09/19 21:25:35 cheshire
944 mDNS_snprintf() doesn't need to be in a separate file
945
946 Revision 1.45 2002/09/17 01:45:13 cheshire
947 Add LIST_ALL_INTERFACES symbol for debugging
948
949 Revision 1.44 2002/09/17 01:36:23 cheshire
950 Move Puma support to mDNSMacOSXPuma.c
951
952 Revision 1.43 2002/09/17 01:05:28 cheshire
953 Change mDNS_AdvertiseLocalAddresses to be an Init parameter instead of a global
954
955 Revision 1.42 2002/09/16 23:13:50 cheshire
956 Minor code tidying
957
958 */
959
960 // ***************************************************************************
961 // mDNSMacOSX.c:
962 // Supporting routines to run mDNS on a CFRunLoop platform
963 // ***************************************************************************
964
965 // For debugging, set LIST_ALL_INTERFACES to 1 to display all found interfaces,
966 // including ones that mDNSResponder chooses not to use.
967 #define LIST_ALL_INTERFACES 0
968
969 // For enabling AAAA records over IPv4. Setting this to 0 sends only
970 // A records over IPv4 and AAAA over IPv6. Setting this to 1 sends both
971 // AAAA and A records over both IPv4 and IPv6.
972 #define AAAA_OVER_V4 1
973
974 #include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
975 #include "DNSCommon.h"
976 #include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform
977 #include "../mDNSShared/uds_daemon.h" // Defines communication interface from platform layer up to UDS daemon
978 #include "PlatformCommon.h"
979
980 #include <stdio.h>
981 #include <stdarg.h> // For va_list support
982 #include <net/if.h>
983 #include <net/if_types.h> // For IFT_ETHER
984 #include <net/if_dl.h>
985 #include <sys/uio.h>
986 #include <sys/param.h>
987 #include <sys/socket.h>
988 #include <sys/sysctl.h>
989 #include <fcntl.h>
990 #include <sys/ioctl.h>
991 #include <time.h> // platform support for UTC time
992 #include <arpa/inet.h> // for inet_aton
993
994 #include <netinet/in.h> // For IP_RECVTTL
995 #ifndef IP_RECVTTL
996 #define IP_RECVTTL 24 // bool; receive reception TTL w/dgram
997 #endif
998
999 #include <netinet/in_systm.h> // For n_long, required by <netinet/ip.h> below
1000 #include <netinet/ip.h> // For IPTOS_LOWDELAY etc.
1001 #include <netinet6/in6_var.h> // For IN6_IFF_NOTREADY etc.
1002
1003 #include <Security/Security.h>
1004
1005 #include "dnsinfo.h"
1006
1007 // Code contributed by Dave Heller:
1008 // Define RUN_ON_PUMA_WITHOUT_IFADDRS to compile code that will
1009 // work on Mac OS X 10.1, which does not have the getifaddrs call.
1010 #define RUN_ON_PUMA_WITHOUT_IFADDRS 0
1011 #if RUN_ON_PUMA_WITHOUT_IFADDRS
1012 #include "mDNSMacOSXPuma.c"
1013 #else
1014 #include <ifaddrs.h>
1015 #endif
1016
1017 #include <IOKit/IOKitLib.h>
1018 #include <IOKit/IOMessage.h>
1019 #include <mach/mach_time.h>
1020
1021 typedef struct SearchListElem
1022 {
1023 struct SearchListElem *next;
1024 domainname domain;
1025 int flag;
1026 DNSQuestion BrowseQ;
1027 DNSQuestion DefBrowseQ;
1028 DNSQuestion LegacyBrowseQ;
1029 DNSQuestion RegisterQ;
1030 DNSQuestion DefRegisterQ;
1031 ARListElem *AuthRecs;
1032 } SearchListElem;
1033
1034
1035 // ***************************************************************************
1036 // Globals
1037
1038 static mDNSu32 clockdivisor = 0;
1039
1040 // for domain enumeration and default browsing/registration
1041 static SearchListElem *SearchList = NULL; // where we search for _browse domains
1042 static DNSQuestion LegacyBrowseDomainQ; // our local enumeration query for _legacy._browse domains
1043 static DNameListElem *DefBrowseList = NULL; // cache of answers to above query (where we search for empty string browses)
1044 static DNameListElem *DefRegList = NULL; // manually generated list of domains where we register for empty string registrations
1045 static ARListElem *SCPrefBrowseDomains = NULL; // manually generated local-only PTR records for browse domains we get from SCPreferences
1046
1047 static domainname DynDNSRegDomain; // Default wide-area zone for service registration
1048 static CFArrayRef DynDNSBrowseDomains = NULL; // Default wide-area zones for legacy ("empty string") browses
1049 static domainname DynDNSHostname;
1050
1051 static mDNSBool DomainDiscoveryDisabled = mDNSfalse;
1052
1053 #define CONFIG_FILE "/etc/mDNSResponder.conf"
1054 #define DYNDNS_KEYCHAIN_SERVICE "DynDNS Shared Secret"
1055 #define SYS_KEYCHAIN_PATH "/Library/Keychains/System.keychain"
1056
1057 // Function Prototypes
1058 mDNSlocal void SetSCPrefsBrowseDomain(mDNS *m, const domainname *d, mDNSBool add);
1059
1060 // ***************************************************************************
1061 // Functions
1062
1063 // routines to allow access to default domain lists from daemon layer
1064
1065 mDNSexport DNameListElem *mDNSPlatformGetSearchDomainList(void)
1066 {
1067 return mDNS_CopyDNameList(DefBrowseList);
1068 }
1069
1070 mDNSexport DNameListElem *mDNSPlatformGetRegDomainList(void)
1071 {
1072 return mDNS_CopyDNameList(DefRegList);
1073 }
1074
1075 // utility routines to manage registration domain lists
1076
1077 mDNSlocal void AddDefRegDomain(domainname *d)
1078 {
1079 DNameListElem *newelem = NULL, *ptr;
1080
1081 // make sure name not already in list
1082 for (ptr = DefRegList; ptr; ptr = ptr->next)
1083 {
1084 if (SameDomainName(&ptr->name, d))
1085 { debugf("duplicate addition of default reg domain %##s", d->c); return; }
1086 }
1087
1088 newelem = mallocL("DNameListElem", sizeof(*newelem));
1089 if (!newelem) { LogMsg("Error - malloc"); return; }
1090 AssignDomainName(&newelem->name, d);
1091 newelem->next = DefRegList;
1092 DefRegList = newelem;
1093
1094 DefaultRegDomainChanged(d, mDNStrue);
1095 udsserver_default_reg_domain_changed(d, mDNStrue);
1096 }
1097
1098 mDNSlocal void RemoveDefRegDomain(domainname *d)
1099 {
1100 DNameListElem *ptr = DefRegList, *prev = NULL;
1101
1102 while (ptr)
1103 {
1104 if (SameDomainName(&ptr->name, d))
1105 {
1106 if (prev) prev->next = ptr->next;
1107 else DefRegList = ptr->next;
1108 freeL("DNameListElem", ptr);
1109 DefaultRegDomainChanged(d, mDNSfalse);
1110 udsserver_default_reg_domain_changed(d, mDNSfalse);
1111 return;
1112 }
1113 prev = ptr;
1114 ptr = ptr->next;
1115 }
1116 debugf("Requested removal of default registration domain %##s not in contained in list", d->c);
1117 }
1118
1119 mDNSexport void NotifyOfElusiveBug(const char *title, mDNSu32 radarid, const char *msg)
1120 {
1121 static int notifyCount = 0;
1122 if (notifyCount) return;
1123
1124 // If we display our alert early in the boot process, then it vanishes once the desktop appears.
1125 // To avoid this, we don't try to display alerts in the first three minutes after boot.
1126 if ((mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return;
1127
1128 // Unless ForceAlerts is defined, we only show these bug report alerts on machines that have a 17.x.x.x address
1129 #if !ForceAlerts
1130 {
1131 // Determine if we're at Apple (17.*.*.*)
1132 extern mDNS mDNSStorage;
1133 NetworkInterfaceInfoOSX *i;
1134 for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
1135 if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && i->ifinfo.ip.ip.v4.b[0] == 17)
1136 break;
1137 if (!i) return; // If not at Apple, don't show the alert
1138 }
1139 #endif
1140
1141 // Send a notification to the user to contact coreos-networking
1142 notifyCount++;
1143 CFStringRef alertHeader = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8);
1144 CFStringRef alertFormat = CFSTR("Congratulations, you've reproduced an elusive bug. Please contact the owner of <rdar://problem/%d>. %s");
1145 CFStringRef alertMessage = CFStringCreateWithFormat(NULL, NULL, alertFormat, radarid, msg);
1146 CFUserNotificationDisplayNotice(0.0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage, NULL);
1147 }
1148
1149 mDNSlocal struct ifaddrs* myGetIfAddrs(int refresh)
1150 {
1151 static struct ifaddrs *ifa = NULL;
1152
1153 if (refresh && ifa)
1154 {
1155 freeifaddrs(ifa);
1156 ifa = NULL;
1157 }
1158
1159 if (ifa == NULL) getifaddrs(&ifa);
1160
1161 return ifa;
1162 }
1163
1164 mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(mDNS *const m, const char *ifname, int type)
1165 {
1166 NetworkInterfaceInfoOSX *i;
1167 for (i = m->p->InterfaceList; i; i = i->next)
1168 if (i->Exists && !strcmp(i->ifa_name, ifname) &&
1169 ((AAAA_OVER_V4 ) ||
1170 (type == AF_INET && i->ifinfo.ip.type == mDNSAddrType_IPv4) ||
1171 (type == AF_INET6 && i->ifinfo.ip.type == mDNSAddrType_IPv6) )) return(i);
1172 return(NULL);
1173 }
1174
1175 mDNSlocal int myIfIndexToName(u_short index, char* name)
1176 {
1177 struct ifaddrs *ifa;
1178 for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next)
1179 if (ifa->ifa_addr->sa_family == AF_LINK)
1180 if (((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index == index)
1181 { strncpy(name, ifa->ifa_name, IF_NAMESIZE); return 0; }
1182 return -1;
1183 }
1184
1185 mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS *const m, mDNSu32 index)
1186 {
1187 NetworkInterfaceInfoOSX *i;
1188 if (index == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
1189 if (index)
1190 for (i = m->p->InterfaceList; i; i = i->next)
1191 // Don't get tricked by inactive interfaces with no InterfaceID set
1192 if (i->ifinfo.InterfaceID && i->scope_id == index) return(i->ifinfo.InterfaceID);
1193 return(mDNSNULL);
1194 }
1195
1196 mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(const mDNS *const m, mDNSInterfaceID id)
1197 {
1198 NetworkInterfaceInfoOSX *i;
1199 if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
1200 if (id)
1201 for (i = m->p->InterfaceList; i; i = i->next)
1202 // Don't use i->ifinfo.InterfaceID here, because we DO want to find inactive interfaces, which have no InterfaceID set
1203 if ((mDNSInterfaceID)i == id) return(i->scope_id);
1204 return 0;
1205 }
1206
1207 mDNSlocal mDNSBool AddrRequiresPPPConnection(const struct sockaddr *addr)
1208 {
1209 mDNSBool result = mDNSfalse;
1210 SCNetworkConnectionFlags flags;
1211 SCNetworkReachabilityRef ReachRef = NULL;
1212
1213 ReachRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, addr);
1214 if (!ReachRef) { LogMsg("ERROR: RequiresConnection - SCNetworkReachabilityCreateWithAddress"); goto end; }
1215 if (!SCNetworkReachabilityGetFlags(ReachRef, &flags)) { LogMsg("ERROR: AddrRequiresPPPConnection - SCNetworkReachabilityGetFlags"); goto end; }
1216 result = flags & kSCNetworkFlagsConnectionRequired;
1217
1218 end:
1219 if (ReachRef) CFRelease(ReachRef);
1220 return result;
1221 }
1222
1223 // NOTE: If InterfaceID is NULL, it means, "send this packet through our anonymous unicast socket"
1224 // NOTE: If InterfaceID is non-NULL it means, "send this packet through our port 5353 socket on the specified interface"
1225 // OR send via our primary v4 unicast socket
1226 mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
1227 mDNSInterfaceID InterfaceID, const mDNSAddr *dst, mDNSIPPort dstPort)
1228 {
1229 #pragma unused(m)
1230
1231 // Note: For this platform we've adopted the convention that InterfaceIDs are secretly pointers
1232 // to the NetworkInterfaceInfoOSX structure that holds the active sockets. The mDNSCore code
1233 // doesn't know that and doesn't need to know that -- it just treats InterfaceIDs as opaque identifiers.
1234 NetworkInterfaceInfoOSX *info = (NetworkInterfaceInfoOSX *)InterfaceID;
1235 char *ifa_name = info ? info->ifa_name : "unicast";
1236 struct sockaddr_storage to;
1237 int s = -1, err;
1238
1239 // Sanity check: Make sure that if we're sending a query via unicast, we're sending it using our
1240 // anonymous socket created for this purpose, so that we'll receive the response.
1241 // If we use one of the many multicast sockets bound to port 5353 then we may not receive responses reliably.
1242 if (info && !mDNSAddrIsDNSMulticast(dst))
1243 {
1244 const DNSMessage *const m = (DNSMessage *)msg;
1245 if ((m->h.flags.b[0] & kDNSFlag0_QR_Mask) == kDNSFlag0_QR_Query)
1246 LogMsg("mDNSPlatformSendUDP: ERROR: Sending query OP from mDNS port to non-mDNS destination %#a:%d", dst, mDNSVal16(dstPort));
1247 }
1248
1249 if (dst->type == mDNSAddrType_IPv4)
1250 {
1251 struct sockaddr_in *sin_to = (struct sockaddr_in*)&to;
1252 sin_to->sin_len = sizeof(*sin_to);
1253 sin_to->sin_family = AF_INET;
1254 sin_to->sin_port = dstPort.NotAnInteger;
1255 sin_to->sin_addr.s_addr = dst->ip.v4.NotAnInteger;
1256 s = info ? info->ss.sktv4 : m->p->unicastsockets.sktv4;
1257 }
1258 else if (dst->type == mDNSAddrType_IPv6)
1259 {
1260 struct sockaddr_in6 *sin6_to = (struct sockaddr_in6*)&to;
1261 sin6_to->sin6_len = sizeof(*sin6_to);
1262 sin6_to->sin6_family = AF_INET6;
1263 sin6_to->sin6_port = dstPort.NotAnInteger;
1264 sin6_to->sin6_flowinfo = 0;
1265 sin6_to->sin6_addr = *(struct in6_addr*)&dst->ip.v6;
1266 sin6_to->sin6_scope_id = info ? info->scope_id : 0;
1267 s = info ? info->ss.sktv6 : m->p->unicastsockets.sktv6;
1268 }
1269 else
1270 {
1271 LogMsg("mDNSPlatformSendUDP: dst is not an IPv4 or IPv6 address!");
1272 return mStatus_BadParamErr;
1273 }
1274
1275 // Don't send if it would cause dial on demand connection initiation. As an optimization,
1276 // don't bother consulting reachability API / routing table when sending Multicast DNS
1277 // since we ignore PPP interfaces for mDNS traffic
1278 if (!mDNSAddrIsDNSMulticast(dst) && AddrRequiresPPPConnection((struct sockaddr *)&to))
1279 {
1280 debugf("mDNSPlatformSendUDP: Surpressing sending to avoid dial-on-demand connection");
1281 return mStatus_NoError;
1282 }
1283
1284 if (s >= 0)
1285 verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %p %5s/%ld to %#a:%d skt %d",
1286 InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s);
1287 else
1288 verbosedebugf("mDNSPlatformSendUDP: NOT sending on InterfaceID %p %5s/%ld (socket of this type not available)",
1289 InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort));
1290
1291 // Note: When sending, mDNSCore may often ask us to send both a v4 multicast packet and then a v6 multicast packet
1292 // If we don't have the corresponding type of socket available, then return mStatus_Invalid
1293 if (s < 0) return(mStatus_Invalid);
1294
1295 err = sendto(s, msg, (UInt8*)end - (UInt8*)msg, 0, (struct sockaddr *)&to, to.ss_len);
1296 if (err < 0)
1297 {
1298 // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
1299 if (!mDNSAddressIsAllDNSLinkGroup(dst))
1300 if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr);
1301 // Don't report EHOSTUNREACH in the first three minutes after boot
1302 // This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
1303 // but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
1304 if (errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(mStatus_TransientErr);
1305 // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change
1306 if (errno == EADDRNOTAVAIL && m->p->NetworkChanged) return(mStatus_TransientErr);
1307 LogMsg("mDNSPlatformSendUDP sendto failed to send packet on InterfaceID %p %5s/%ld to %#a:%d skt %d error %d errno %d (%s) %lu",
1308 InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow));
1309 return(mStatus_UnknownErr);
1310 }
1311
1312 return(mStatus_NoError);
1313 }
1314
1315 mDNSlocal ssize_t myrecvfrom(const int s, void *const buffer, const size_t max,
1316 struct sockaddr *const from, size_t *const fromlen, mDNSAddr *dstaddr, char ifname[IF_NAMESIZE], mDNSu8 *ttl)
1317 {
1318 static unsigned int numLogMessages = 0;
1319 struct iovec databuffers = { (char *)buffer, max };
1320 struct msghdr msg;
1321 ssize_t n;
1322 struct cmsghdr *cmPtr;
1323 char ancillary[1024];
1324
1325 *ttl = 255; // If kernel fails to provide TTL data (e.g. Jaguar doesn't) then assume the TTL was 255 as it should be
1326
1327 // Set up the message
1328 msg.msg_name = (caddr_t)from;
1329 msg.msg_namelen = *fromlen;
1330 msg.msg_iov = &databuffers;
1331 msg.msg_iovlen = 1;
1332 msg.msg_control = (caddr_t)&ancillary;
1333 msg.msg_controllen = sizeof(ancillary);
1334 msg.msg_flags = 0;
1335
1336 // Receive the data
1337 n = recvmsg(s, &msg, 0);
1338 if (n<0)
1339 {
1340 if (errno != EWOULDBLOCK && numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned error %d errno %d", s, n, errno);
1341 return(-1);
1342 }
1343 if (msg.msg_controllen < (int)sizeof(struct cmsghdr))
1344 {
1345 if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_controllen %d < sizeof(struct cmsghdr) %lu",
1346 s, msg.msg_controllen, sizeof(struct cmsghdr));
1347 return(-1);
1348 }
1349 if (msg.msg_flags & MSG_CTRUNC)
1350 {
1351 if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s);
1352 return(-1);
1353 }
1354
1355 *fromlen = msg.msg_namelen;
1356
1357 // Parse each option out of the ancillary data.
1358 for (cmPtr = CMSG_FIRSTHDR(&msg); cmPtr; cmPtr = CMSG_NXTHDR(&msg, cmPtr))
1359 {
1360 // debugf("myrecvfrom cmsg_level %d cmsg_type %d", cmPtr->cmsg_level, cmPtr->cmsg_type);
1361 if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVDSTADDR)
1362 {
1363 dstaddr->type = mDNSAddrType_IPv4;
1364 dstaddr->ip.v4.NotAnInteger = *(u_int32_t*)CMSG_DATA(cmPtr);
1365 }
1366 if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVIF)
1367 {
1368 struct sockaddr_dl *sdl = (struct sockaddr_dl *)CMSG_DATA(cmPtr);
1369 if (sdl->sdl_nlen < IF_NAMESIZE)
1370 {
1371 mDNSPlatformMemCopy(sdl->sdl_data, ifname, sdl->sdl_nlen);
1372 ifname[sdl->sdl_nlen] = 0;
1373 // debugf("IP_RECVIF sdl_index %d, sdl_data %s len %d", sdl->sdl_index, ifname, sdl->sdl_nlen);
1374 }
1375 }
1376 if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVTTL)
1377 {
1378 *ttl = *(u_char*)CMSG_DATA(cmPtr);
1379 }
1380 if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_PKTINFO)
1381 {
1382 struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmPtr);
1383 dstaddr->type = mDNSAddrType_IPv6;
1384 dstaddr->ip.v6 = *(mDNSv6Addr*)&ip6_info->ipi6_addr;
1385 myIfIndexToName(ip6_info->ipi6_ifindex, ifname);
1386 }
1387 if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_HOPLIMIT)
1388 {
1389 *ttl = *(int*)CMSG_DATA(cmPtr);
1390 }
1391 }
1392
1393 return(n);
1394 }
1395
1396 // On entry, context points to our CFSocketSet
1397 // If ss->info is NULL, we received this packet on our anonymous unicast socket
1398 // If ss->info is non-NULL, we received this packet on port 5353 on the indicated interface
1399 mDNSlocal void myCFSocketCallBack(const CFSocketRef cfs, const CFSocketCallBackType CallBackType, const CFDataRef address, const void *const data, void *const context)
1400 {
1401 const CFSocketSet *const ss = (const CFSocketSet *)context;
1402 mDNS *const m = ss->m;
1403 const int skt = CFSocketGetNative(cfs);
1404 const int s1 = (cfs == ss->cfsv4) ? ss->sktv4 : (cfs == ss->cfsv6) ? ss->sktv6 : -1;
1405 int err, count = 0;
1406
1407 (void)address; // Parameter not used
1408 (void)data; // Parameter not used
1409
1410 if (CallBackType != kCFSocketReadCallBack)
1411 LogMsg("myCFSocketCallBack: Why is CallBackType %d not kCFSocketReadCallBack?", CallBackType);
1412
1413 if (s1 < 0 || s1 != skt)
1414 {
1415 LogMsg("myCFSocketCallBack: s1 %d native socket %d, cfs %p", s1, skt, cfs);
1416 LogMsg("myCFSocketCallBack: cfsv4 %p, sktv4 %d", ss->cfsv4, ss->sktv4);
1417 LogMsg("myCFSocketCallBack: cfsv6 %p, sktv6 %d", ss->cfsv6, ss->sktv6);
1418 }
1419
1420 while (1)
1421 {
1422 // NOTE: When handling multiple packets in a batch, MUST reset InterfaceID before handling each packet
1423 mDNSInterfaceID InterfaceID = ss->info ? ss->info->ifinfo.InterfaceID : mDNSNULL;
1424 mDNSAddr senderAddr, destAddr;
1425 mDNSIPPort senderPort, destPort = MulticastDNSPort;
1426 struct sockaddr_storage from;
1427 size_t fromlen = sizeof(from);
1428 char packetifname[IF_NAMESIZE] = "";
1429 mDNSu8 ttl;
1430 err = myrecvfrom(s1, &m->imsg, sizeof(m->imsg), (struct sockaddr *)&from, &fromlen, &destAddr, packetifname, &ttl);
1431 if (err < 0) break;
1432
1433 count++;
1434 if (from.ss_family == AF_INET)
1435 {
1436 struct sockaddr_in *sin = (struct sockaddr_in*)&from;
1437 senderAddr.type = mDNSAddrType_IPv4;
1438 senderAddr.ip.v4.NotAnInteger = sin->sin_addr.s_addr;
1439 senderPort.NotAnInteger = sin->sin_port;
1440 }
1441 else if (from.ss_family == AF_INET6)
1442 {
1443 struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&from;
1444 senderAddr.type = mDNSAddrType_IPv6;
1445 senderAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
1446 senderPort.NotAnInteger = sin6->sin6_port;
1447 }
1448 else
1449 {
1450 LogMsg("myCFSocketCallBack from is unknown address family %d", from.ss_family);
1451 return;
1452 }
1453
1454 if (mDNSAddrIsDNSMulticast(&destAddr))
1455 {
1456 // Even though we indicated a specific interface in the IP_ADD_MEMBERSHIP call, a weirdness of the
1457 // sockets API means that even though this socket has only officially joined the multicast group
1458 // on one specific interface, the kernel will still deliver multicast packets to it no matter which
1459 // interface they arrive on. According to the official Unix Powers That Be, this is Not A Bug.
1460 // To work around this weirdness, we use the IP_RECVIF option to find the name of the interface
1461 // on which the packet arrived, and ignore the packet if it really arrived on some other interface.
1462 if (!ss->info || !ss->info->Exists)
1463 {
1464 verbosedebugf("myCFSocketCallBack got multicast packet from %#a to %#a on unicast socket (Ignored)", &senderAddr, &destAddr);
1465 return;
1466 }
1467 else if (strcmp(ss->info->ifa_name, packetifname))
1468 {
1469 verbosedebugf("myCFSocketCallBack got multicast packet from %#a to %#a on interface %#a/%s (Ignored -- really arrived on interface %s)",
1470 &senderAddr, &destAddr, &ss->info->ifinfo.ip, ss->info->ifa_name, packetifname);
1471 return;
1472 }
1473 else
1474 verbosedebugf("myCFSocketCallBack got multicast packet from %#a to %#a on interface %#a/%s",
1475 &senderAddr, &destAddr, &ss->info->ifinfo.ip, ss->info->ifa_name);
1476 }
1477 else
1478 {
1479 // Note: Unicast packets are delivered to *one* of our listening sockets,
1480 // not necessarily the one bound to the physical interface where the packet arrived.
1481 // To sort this out we search our interface list and update InterfaceID to reference
1482 // the mDNSCore interface object for the interface where the packet was actually received.
1483 NetworkInterfaceInfo *intf = m->HostInterfaces;
1484 while (intf && strcmp(intf->ifname, packetifname)) intf = intf->next;
1485 if (intf) InterfaceID = intf->InterfaceID;
1486 }
1487
1488 mDNSCoreReceive(m, &m->imsg, (unsigned char*)&m->imsg + err, &senderAddr, senderPort, &destAddr, destPort, InterfaceID);
1489 }
1490
1491 if (err < 0 && (errno != EWOULDBLOCK || count == 0))
1492 {
1493 // Something is busted here.
1494 // CFSocket says there is a packet, but myrecvfrom says there is not.
1495 // Try calling select() to get another opinion.
1496 // Find out about other socket parameter that can help understand why select() says the socket is ready for read
1497 // All of this is racy, as data may have arrived after the call to select()
1498 int save_errno = errno;
1499 int so_error = -1;
1500 int so_nread = -1;
1501 int fionread = -1;
1502 socklen_t solen = sizeof(int);
1503 fd_set readfds;
1504 FD_ZERO(&readfds);
1505 FD_SET(s1, &readfds);
1506 struct timeval timeout;
1507 timeout.tv_sec = 0;
1508 timeout.tv_usec = 0;
1509 int selectresult = select(s1+1, &readfds, NULL, NULL, &timeout);
1510 if (getsockopt(s1, SOL_SOCKET, SO_ERROR, &so_error, &solen) == -1)
1511 LogMsg("myCFSocketCallBack getsockopt(SO_ERROR) error %d", errno);
1512 if (getsockopt(s1, SOL_SOCKET, SO_NREAD, &so_nread, &solen) == -1)
1513 LogMsg("myCFSocketCallBack getsockopt(SO_NREAD) error %d", errno);
1514 if (ioctl(s1, FIONREAD, &fionread) == -1)
1515 LogMsg("myCFSocketCallBack ioctl(FIONREAD) error %d", errno);
1516 static unsigned int numLogMessages = 0;
1517 if (numLogMessages++ < 100)
1518 LogMsg("myCFSocketCallBack recvfrom skt %d error %d errno %d (%s) select %d (%spackets waiting) so_error %d so_nread %d fionread %d count %d",
1519 s1, err, save_errno, strerror(save_errno), selectresult, FD_ISSET(s1, &readfds) ? "" : "*NO* ", so_error, so_nread, fionread, count);
1520 if (numLogMessages > 5)
1521 NotifyOfElusiveBug("Flaw in Kernel (select/recvfrom mismatch)", 3375328,
1522 "Alternatively, you can send email to radar-3387020@group.apple.com. "
1523 "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
1524
1525 sleep(1); // After logging this error, rate limit so we don't flood syslog
1526 }
1527 }
1528
1529 // TCP socket support for unicast DNS and Dynamic DNS Update
1530
1531 typedef struct
1532 {
1533 TCPConnectionCallback callback;
1534 void *context;
1535 int connected;
1536 } tcpInfo_t;
1537
1538 mDNSlocal void tcpCFSocketCallback(CFSocketRef cfs, CFSocketCallBackType CallbackType, CFDataRef address,
1539 const void *data, void *context)
1540 {
1541 #pragma unused(CallbackType, address, data)
1542 mDNSBool connect = mDNSfalse;
1543
1544 tcpInfo_t *info = context;
1545 if (!info->connected)
1546 {
1547 connect = mDNStrue;
1548 info->connected = mDNStrue; // prevent connected flag from being set in future callbacks
1549 }
1550 info->callback(CFSocketGetNative(cfs), info->context, connect);
1551 // NOTE: the callback may call CloseConnection here, which frees the context structure!
1552 }
1553
1554 mDNSexport mStatus mDNSPlatformTCPConnect(const mDNSAddr *dst, mDNSOpaque16 dstport, mDNSInterfaceID InterfaceID,
1555 TCPConnectionCallback callback, void *context, int *descriptor)
1556 {
1557 int sd, on = 1; // "on" for setsockopt
1558 struct sockaddr_in saddr;
1559 CFSocketContext cfContext = { 0, NULL, 0, 0, 0 };
1560 tcpInfo_t *info;
1561 CFSocketRef sr;
1562 CFRunLoopSourceRef rls;
1563
1564 (void)InterfaceID; //!!!KRS use this if non-zero!!!
1565
1566 *descriptor = 0;
1567 if (dst->type != mDNSAddrType_IPv4)
1568 {
1569 LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: opperation not supported");
1570 return mStatus_UnknownErr;
1571 }
1572
1573 bzero(&saddr, sizeof(saddr));
1574 saddr.sin_family = AF_INET;
1575 saddr.sin_port = dstport.NotAnInteger;
1576 saddr.sin_len = sizeof(saddr);
1577 memcpy(&saddr.sin_addr, &dst->ip.v4.NotAnInteger, sizeof(saddr.sin_addr));
1578
1579 // Don't send if it would cause dial on demand connection initiation.
1580 if (AddrRequiresPPPConnection((struct sockaddr *)&saddr))
1581 {
1582 debugf("mDNSPlatformTCPConnect: Surpressing sending to avoid dial-on-demand connection");
1583 return mStatus_UnknownErr;
1584 }
1585
1586 sd = socket(AF_INET, SOCK_STREAM, 0);
1587 if (sd < 3) { LogMsg("mDNSPlatformTCPConnect: socket error %d errno %d (%s)", sd, errno, strerror(errno)); return mStatus_UnknownErr; }
1588
1589 // set non-blocking
1590 if (fcntl(sd, F_SETFL, O_NONBLOCK) < 0)
1591 {
1592 LogMsg("ERROR: setsockopt O_NONBLOCK - %s", strerror(errno));
1593 return mStatus_UnknownErr;
1594 }
1595
1596 // receive interface identifiers
1597 if (setsockopt(sd, IPPROTO_IP, IP_RECVIF, &on, sizeof(on)) < 0)
1598 {
1599 LogMsg("setsockopt IP_RECVIF - %s", strerror(errno));
1600 return mStatus_UnknownErr;
1601 }
1602 // set up CF wrapper, add to Run Loop
1603 info = mallocL("mDNSPlatformTCPConnect", sizeof(tcpInfo_t));
1604 info->callback = callback;
1605 info->context = context;
1606 cfContext.info = info;
1607 sr = CFSocketCreateWithNative(kCFAllocatorDefault, sd, kCFSocketReadCallBack | kCFSocketConnectCallBack,
1608 tcpCFSocketCallback, &cfContext);
1609 if (!sr)
1610 {
1611 LogMsg("ERROR: mDNSPlatformTCPConnect - CFSocketRefCreateWithNative failed");
1612 freeL("mDNSPlatformTCPConnect", info);
1613 return mStatus_UnknownErr;
1614 }
1615
1616 rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, sr, 0);
1617 if (!rls)
1618 {
1619 LogMsg("ERROR: mDNSPlatformTCPConnect - CFSocketCreateRunLoopSource failed");
1620 freeL("mDNSPlatformTCPConnect", info);
1621 return mStatus_UnknownErr;
1622 }
1623
1624 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
1625 CFRelease(rls);
1626
1627 // initiate connection wth peer
1628 if (connect(sd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
1629 {
1630 if (errno == EINPROGRESS)
1631 {
1632 info->connected = 0;
1633 *descriptor= sd;
1634 return mStatus_ConnPending;
1635 }
1636 LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: %s", strerror(errno));
1637 freeL("mDNSPlatformTCPConnect", info);
1638 CFSocketInvalidate(sr); // Note: Also closes the underlying socket
1639 return mStatus_ConnFailed;
1640 }
1641 info->connected = 1;
1642 *descriptor = sd;
1643 return mStatus_ConnEstablished;
1644 }
1645
1646 mDNSexport void mDNSPlatformTCPCloseConnection(int sd)
1647 {
1648 CFSocketContext cfContext;
1649 tcpInfo_t *info;
1650 CFSocketRef sr;
1651
1652 if (sd < 3) LogMsg("mDNSPlatformTCPCloseConnection: ERROR sd %d < 3", sd);
1653
1654 // Get the CFSocket for the descriptor
1655 sr = CFSocketCreateWithNative(kCFAllocatorDefault, sd, kCFSocketNoCallBack, NULL, NULL);
1656 if (!sr) { LogMsg("ERROR: mDNSPlatformTCPCloseConnection - CFSocketCreateWithNative returned NULL"); return; }
1657
1658 CFSocketGetContext(sr, &cfContext);
1659 if (!cfContext.info)
1660 {
1661 LogMsg("ERROR: mDNSPlatformTCPCloseConnection - could not retreive tcpInfo from socket context");
1662 CFRelease(sr);
1663 return;
1664 }
1665 CFRelease(sr); // this only releases the copy we allocated with CreateWithNative above
1666
1667 info = cfContext.info;
1668
1669 // Note: MUST NOT close the underlying native BSD socket.
1670 // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately,
1671 // because it first has to unhook the sockets from its select() call, before it can safely close them.
1672 CFSocketInvalidate(sr);
1673 CFRelease(sr);
1674 freeL("mDNSPlatformTCPCloseConnection", info);
1675 }
1676
1677 mDNSexport int mDNSPlatformReadTCP(int sd, void *buf, int buflen)
1678 {
1679 int nread = recv(sd, buf, buflen, 0);
1680 if (nread < 0)
1681 {
1682 if (errno == EAGAIN) return 0; // no data available (call would block)
1683 LogMsg("ERROR: mDNSPlatformReadTCP - recv: %s", strerror(errno));
1684 return -1;
1685 }
1686 return nread;
1687 }
1688
1689 mDNSexport int mDNSPlatformWriteTCP(int sd, const char *msg, int len)
1690 {
1691 int nsent = send(sd, msg, len, 0);
1692
1693 if (nsent < 0)
1694 {
1695 if (errno == EAGAIN) return 0; // blocked
1696 LogMsg("ERROR: mDNSPlatformWriteTCP - sendL %s", strerror(errno));
1697 return -1;
1698 }
1699 return nsent;
1700 }
1701
1702 // This gets the text of the field currently labelled "Computer Name" in the Sharing Prefs Control Panel
1703 mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel)
1704 {
1705 CFStringEncoding encoding = kCFStringEncodingUTF8;
1706 CFStringRef cfs = SCDynamicStoreCopyComputerName(NULL, &encoding);
1707 if (cfs)
1708 {
1709 CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
1710 CFRelease(cfs);
1711 }
1712 }
1713
1714 // This gets the text of the field currently labelled "Local Hostname" in the Sharing Prefs Control Panel
1715 mDNSlocal void GetUserSpecifiedLocalHostName(domainlabel *const namelabel)
1716 {
1717 CFStringRef cfs = SCDynamicStoreCopyLocalHostName(NULL);
1718 if (cfs)
1719 {
1720 CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
1721 CFRelease(cfs);
1722 }
1723 }
1724
1725 mDNSlocal mDNSBool DDNSSettingEnabled(CFDictionaryRef dict)
1726 {
1727 mDNSs32 val;
1728 CFNumberRef state = CFDictionaryGetValue(dict, CFSTR("Enabled"));
1729 if (!state) return mDNSfalse;
1730 if (!CFNumberGetValue(state, kCFNumberSInt32Type, &val)) { LogMsg("ERROR: DDNSSettingEnabled - CFNumberGetValue"); return mDNSfalse; }
1731 return val ? mDNStrue : mDNSfalse;
1732 }
1733
1734 mDNSlocal void GetUserSpecifiedDDNSConfig(domainname *const fqdn, domainname *const regDomain, CFArrayRef *const browseDomains)
1735 {
1736 char buf[MAX_ESCAPED_DOMAIN_NAME];
1737
1738 fqdn->c[0] = 0;
1739 regDomain->c[0] = 0;
1740 buf[0] = 0;
1741 *browseDomains = NULL;
1742
1743 SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetUserSpecifiedDDNSConfig"), NULL, NULL);
1744 if (store)
1745 {
1746 CFDictionaryRef dict = SCDynamicStoreCopyValue(store, CFSTR("Setup:/Network/DynamicDNS"));
1747 if (dict)
1748 {
1749 CFArrayRef fqdnArray = CFDictionaryGetValue(dict, CFSTR("HostNames"));
1750 if (fqdnArray && CFArrayGetCount(fqdnArray) > 0)
1751 {
1752 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
1753 if (fqdnDict && DDNSSettingEnabled(fqdnDict))
1754 {
1755 CFStringRef name = CFDictionaryGetValue(fqdnDict, CFSTR("Domain"));
1756 if (name)
1757 {
1758 if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
1759 !MakeDomainNameFromDNSNameString(fqdn, buf) || !fqdn->c[0])
1760 LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS host name: %s", buf[0] ? buf : "(unknown)");
1761 else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS host name: %s", buf);
1762 }
1763 }
1764 }
1765
1766 CFArrayRef regArray = CFDictionaryGetValue(dict, CFSTR("RegistrationDomains"));
1767 if (regArray && CFArrayGetCount(regArray) > 0)
1768 {
1769 CFDictionaryRef regDict = CFArrayGetValueAtIndex(regArray, 0);
1770 if (regDict && DDNSSettingEnabled(regDict))
1771 {
1772 CFStringRef name = CFDictionaryGetValue(regDict, CFSTR("Domain"));
1773 if (name)
1774 {
1775 if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
1776 !MakeDomainNameFromDNSNameString(regDomain, buf) || !regDomain->c[0])
1777 LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS registration domain: %s", buf[0] ? buf : "(unknown)");
1778 else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS registration zone: %s", buf);
1779 }
1780 }
1781 }
1782 CFArrayRef browseArray = CFDictionaryGetValue(dict, CFSTR("BrowseDomains"));
1783 if (browseArray && CFArrayGetCount(browseArray) > 0)
1784 {
1785 CFRetain(browseArray);
1786 *browseDomains = browseArray;
1787 }
1788 CFRelease(dict);
1789 }
1790 CFRelease(store);
1791 }
1792 }
1793
1794 mDNSlocal void SetDDNSNameStatus(domainname *const dname, mStatus status)
1795 {
1796 SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:SetDDNSNameStatus"), NULL, NULL);
1797 if (store)
1798 {
1799 char uname[MAX_ESCAPED_DOMAIN_NAME];
1800 ConvertDomainNameToCString(dname, uname);
1801 char *p = uname;
1802
1803 while (*p)
1804 {
1805 *p = tolower(*p);
1806 if (!(*(p+1)) && *p == '.') *p = 0; // if last character, strip trailing dot
1807 p++;
1808 }
1809
1810 // We need to make a CFDictionary called "State:/Network/DynamicDNS" containing (at present) a single entity.
1811 // That single entity is a CFDictionary with name "HostNames".
1812 // The "HostNames" CFDictionary contains a set of name/value pairs, where the each name is the FQDN
1813 // in question, and the corresponding value is a CFDictionary giving the state for that FQDN.
1814 // (At present we only support a single FQDN, so this dictionary holds just a single name/value pair.)
1815 // The CFDictionary for each FQDN holds (at present) a single name/value pair,
1816 // where the name is "Status" and the value is a CFNumber giving an errror code (with zero meaning success).
1817
1818 const CFStringRef StateKeys [1] = { CFSTR("HostNames") };
1819 const CFStringRef HostKeys [1] = { CFStringCreateWithCString(NULL, uname, kCFStringEncodingUTF8) };
1820 const CFStringRef StatusKeys[1] = { CFSTR("Status") };
1821 if (!HostKeys[0]) LogMsg("SetDDNSNameStatus: CFStringCreateWithCString(%s) failed", uname);
1822 else
1823 {
1824 const CFNumberRef StatusVals[1] = { CFNumberCreate(NULL, kCFNumberSInt32Type, &status) };
1825 if (!StatusVals[0]) LogMsg("SetDDNSNameStatus: CFNumberCreate(%ld) failed", status);
1826 else
1827 {
1828 const CFDictionaryRef HostVals[1] = { CFDictionaryCreate(NULL, (void*)StatusKeys, (void*)StatusVals, 1, NULL, NULL) };
1829 if (HostVals[0])
1830 {
1831 const CFDictionaryRef StateVals[1] = { CFDictionaryCreate(NULL, (void*)HostKeys, (void*)HostVals, 1, NULL, NULL) };
1832 if (StateVals[0])
1833 {
1834 CFDictionaryRef StateDict = CFDictionaryCreate(NULL, (void*)StateKeys, (void*)StateVals, 1, NULL, NULL);
1835 if (StateDict)
1836 {
1837 SCDynamicStoreSetValue(store, CFSTR("State:/Network/DynamicDNS"), StateDict);
1838 CFRelease(StateDict);
1839 }
1840 CFRelease(StateVals[0]);
1841 }
1842 CFRelease(HostVals[0]);
1843 }
1844 CFRelease(StatusVals[0]);
1845 }
1846 CFRelease(HostKeys[0]);
1847 }
1848 CFRelease(store);
1849 }
1850 }
1851
1852 // If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
1853 // If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
1854 mDNSlocal mStatus SetupSocket(mDNS *const m, CFSocketSet *cp, mDNSBool mcast, const mDNSAddr *ifaddr, u_short sa_family)
1855 {
1856 int *s = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
1857 CFSocketRef *c = (sa_family == AF_INET) ? &cp->cfsv4 : &cp->cfsv6;
1858 CFRunLoopSourceRef *r = (sa_family == AF_INET) ? &cp->rlsv4 : &cp->rlsv6;
1859 const int on = 1;
1860 const int twofivefive = 255;
1861 mStatus err = mStatus_NoError;
1862 char *errstr = mDNSNULL;
1863
1864 mDNSIPPort port = (mcast | m->CanReceiveUnicastOn5353) ? MulticastDNSPort : zeroIPPort;
1865
1866 if (*s >= 0) { LogMsg("SetupSocket ERROR: socket %d is already set", *s); return(-1); }
1867 if (*c) { LogMsg("SetupSocket ERROR: CFSocketRef %p is already set", *c); return(-1); }
1868
1869 // Open the socket...
1870 int skt = socket(sa_family, SOCK_DGRAM, IPPROTO_UDP);
1871 if (skt < 3) { LogMsg("SetupSocket: socket error %d errno %d (%s)", skt, errno, strerror(errno)); return(skt); }
1872
1873 // ... with a shared UDP port, if it's for multicast receiving
1874 if (port.NotAnInteger) err = setsockopt(skt, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
1875 if (err < 0) { errstr = "setsockopt - SO_REUSEPORT"; goto fail; }
1876
1877 if (sa_family == AF_INET)
1878 {
1879 // We want to receive destination addresses
1880 err = setsockopt(skt, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
1881 if (err < 0) { errstr = "setsockopt - IP_RECVDSTADDR"; goto fail; }
1882
1883 // We want to receive interface identifiers
1884 err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
1885 if (err < 0) { errstr = "setsockopt - IP_RECVIF"; goto fail; }
1886
1887 // We want to receive packet TTL value so we can check it
1888 err = setsockopt(skt, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
1889 // We ignore errors here -- we already know Jaguar doesn't support this, but we can get by without it
1890
1891 // Add multicast group membership on this interface, if it's for multicast receiving
1892 if (mcast)
1893 {
1894 struct in_addr addr = { ifaddr->ip.v4.NotAnInteger };
1895 struct ip_mreq imr;
1896 imr.imr_multiaddr.s_addr = AllDNSLinkGroupv4.NotAnInteger;
1897 imr.imr_interface = addr;
1898 err = setsockopt(skt, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr));
1899 if (err < 0) { errstr = "setsockopt - IP_ADD_MEMBERSHIP"; goto fail; }
1900
1901 // Specify outgoing interface too
1902 err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr));
1903 if (err < 0) { errstr = "setsockopt - IP_MULTICAST_IF"; goto fail; }
1904 }
1905
1906 // Send unicast packets with TTL 255
1907 err = setsockopt(skt, IPPROTO_IP, IP_TTL, &twofivefive, sizeof(twofivefive));
1908 if (err < 0) { errstr = "setsockopt - IP_TTL"; goto fail; }
1909
1910 // And multicast packets with TTL 255 too
1911 err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_TTL, &twofivefive, sizeof(twofivefive));
1912 if (err < 0) { errstr = "setsockopt - IP_MULTICAST_TTL"; goto fail; }
1913
1914 // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
1915 const int ip_tosbits = IPTOS_LOWDELAY | IPTOS_THROUGHPUT;
1916 err = setsockopt(skt, IPPROTO_IP, IP_TOS, &ip_tosbits, sizeof(ip_tosbits));
1917 if (err < 0) { errstr = "setsockopt - IP_TOS"; goto fail; }
1918
1919 // And start listening for packets
1920 struct sockaddr_in listening_sockaddr;
1921 listening_sockaddr.sin_family = AF_INET;
1922 listening_sockaddr.sin_port = port.NotAnInteger;
1923 listening_sockaddr.sin_addr.s_addr = 0; // Want to receive multicasts AND unicasts on this socket
1924 err = bind(skt, (struct sockaddr *) &listening_sockaddr, sizeof(listening_sockaddr));
1925 if (err) { errstr = "bind"; goto fail; }
1926 }
1927 else if (sa_family == AF_INET6)
1928 {
1929 // We want to receive destination addresses and receive interface identifiers
1930 err = setsockopt(skt, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on));
1931 if (err < 0) { errstr = "setsockopt - IPV6_PKTINFO"; goto fail; }
1932
1933 // We want to receive packet hop count value so we can check it
1934 err = setsockopt(skt, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));
1935 if (err < 0) { errstr = "setsockopt - IPV6_HOPLIMIT"; goto fail; }
1936
1937 // We want to receive only IPv6 packets, without this option, we may
1938 // get IPv4 addresses as mapped addresses.
1939 err = setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
1940 if (err < 0) { errstr = "setsockopt - IPV6_V6ONLY"; goto fail; }
1941
1942 if (mcast)
1943 {
1944 // Add multicast group membership on this interface, if it's for multicast receiving
1945 int interface_id = if_nametoindex(cp->info->ifa_name);
1946 struct ipv6_mreq i6mr;
1947 i6mr.ipv6mr_interface = interface_id;
1948 i6mr.ipv6mr_multiaddr = *(struct in6_addr*)&AllDNSLinkGroupv6;
1949 err = setsockopt(skt, IPPROTO_IPV6, IPV6_JOIN_GROUP, &i6mr, sizeof(i6mr));
1950 if (err < 0) { errstr = "setsockopt - IPV6_JOIN_GROUP"; goto fail; }
1951
1952 // Specify outgoing interface too
1953 err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_IF, &interface_id, sizeof(interface_id));
1954 if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_IF"; goto fail; }
1955 }
1956
1957 // Send unicast packets with TTL 255
1958 err = setsockopt(skt, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &twofivefive, sizeof(twofivefive));
1959 if (err < 0) { errstr = "setsockopt - IPV6_UNICAST_HOPS"; goto fail; }
1960
1961 // And multicast packets with TTL 255 too
1962 err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &twofivefive, sizeof(twofivefive));
1963 if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_HOPS"; goto fail; }
1964
1965 // Note: IPV6_TCLASS appears not to be implemented on OS X right now (or indeed on ANY version of Unix?)
1966 #ifdef IPV6_TCLASS
1967 // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate
1968 int tclass = IPTOS_LOWDELAY | IPTOS_THROUGHPUT; // This may not be right (since tclass is not implemented on OS X, I can't test it)
1969 err = setsockopt(skt, IPPROTO_IPV6, IPV6_TCLASS, &tclass, sizeof(tclass));
1970 if (err < 0) { errstr = "setsockopt - IPV6_TCLASS"; goto fail; }
1971 #endif
1972
1973 // Want to receive our own packets
1974 err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &on, sizeof(on));
1975 if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_LOOP"; goto fail; }
1976
1977 // And start listening for packets
1978 struct sockaddr_in6 listening_sockaddr6;
1979 bzero(&listening_sockaddr6, sizeof(listening_sockaddr6));
1980 listening_sockaddr6.sin6_len = sizeof(listening_sockaddr6);
1981 listening_sockaddr6.sin6_family = AF_INET6;
1982 listening_sockaddr6.sin6_port = port.NotAnInteger;
1983 listening_sockaddr6.sin6_flowinfo = 0;
1984 // listening_sockaddr6.sin6_addr = IN6ADDR_ANY_INIT; // Want to receive multicasts AND unicasts on this socket
1985 listening_sockaddr6.sin6_scope_id = 0;
1986 err = bind(skt, (struct sockaddr *) &listening_sockaddr6, sizeof(listening_sockaddr6));
1987 if (err) { errstr = "bind"; goto fail; }
1988 }
1989
1990 fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
1991 *s = skt;
1992 CFSocketContext myCFSocketContext = { 0, cp, NULL, NULL, NULL };
1993 *c = CFSocketCreateWithNative(kCFAllocatorDefault, *s, kCFSocketReadCallBack, myCFSocketCallBack, &myCFSocketContext);
1994 *r = CFSocketCreateRunLoopSource(kCFAllocatorDefault, *c, 0);
1995 CFRunLoopAddSource(CFRunLoopGetCurrent(), *r, kCFRunLoopDefaultMode);
1996
1997 return(err);
1998
1999 fail:
2000 LogMsg("%s error %ld errno %d (%s)", errstr, err, errno, strerror(errno));
2001 if (!strcmp(errstr, "bind") && errno == EADDRINUSE)
2002 NotifyOfElusiveBug("Setsockopt SO_REUSEPORT failed", 3814904,
2003 "Alternatively, you can send email to radar-3387020@group.apple.com. "
2004 "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
2005 close(skt);
2006 return(err);
2007 }
2008
2009 mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
2010 {
2011 if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
2012
2013 if (sa->sa_family == AF_INET)
2014 {
2015 struct sockaddr_in *ifa_addr = (struct sockaddr_in *)sa;
2016 ip->type = mDNSAddrType_IPv4;
2017 ip->ip.v4.NotAnInteger = ifa_addr->sin_addr.s_addr;
2018 return(mStatus_NoError);
2019 }
2020
2021 if (sa->sa_family == AF_INET6)
2022 {
2023 struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa;
2024 ip->type = mDNSAddrType_IPv6;
2025 if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
2026 ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr;
2027 return(mStatus_NoError);
2028 }
2029
2030 LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
2031 return(mStatus_Invalid);
2032 }
2033
2034 mDNSlocal mDNSEthAddr GetBSSID(char *ifa_name)
2035 {
2036 mDNSEthAddr eth = zeroEthAddr;
2037 SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetBSSID"), NULL, NULL);
2038 if (store)
2039 {
2040 CFStringRef entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/AirPort"), ifa_name);
2041 if (entityname)
2042 {
2043 CFDictionaryRef dict = SCDynamicStoreCopyValue(store, entityname);
2044 if (dict)
2045 {
2046 CFRange range = { 0, 6 }; // Offset, length
2047 CFDataRef data = CFDictionaryGetValue(dict, CFSTR("BSSID"));
2048 if (data && CFDataGetLength(data) == 6) CFDataGetBytes(data, range, eth.b);
2049 CFRelease(dict);
2050 }
2051 CFRelease(entityname);
2052 }
2053 CFRelease(store);
2054 }
2055 return(eth);
2056 }
2057
2058 mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifaddrs *ifa, mDNSs32 utc)
2059 {
2060 mDNSu32 scope_id = if_nametoindex(ifa->ifa_name);
2061 mDNSEthAddr bssid = GetBSSID(ifa->ifa_name);
2062
2063 mDNSAddr ip, mask;
2064 if (SetupAddr(&ip, ifa->ifa_addr ) != mStatus_NoError) return(NULL);
2065 if (SetupAddr(&mask, ifa->ifa_netmask) != mStatus_NoError) return(NULL);
2066
2067 NetworkInterfaceInfoOSX **p;
2068 for (p = &m->p->InterfaceList; *p; p = &(*p)->next)
2069 if (scope_id == (*p)->scope_id && mDNSSameAddress(&ip, &(*p)->ifinfo.ip) && mDNSSameEthAddress(&bssid, &(*p)->BSSID))
2070 {
2071 debugf("AddInterfaceToList: Found existing interface %lu %.6a with address %#a at %p", scope_id, &bssid, &ip, *p);
2072 (*p)->Exists = mDNStrue;
2073 return(*p);
2074 }
2075
2076 NetworkInterfaceInfoOSX *i = (NetworkInterfaceInfoOSX *)mallocL("NetworkInterfaceInfoOSX", sizeof(*i));
2077 debugf("AddInterfaceToList: Making new interface %lu %.6a with address %#a at %p", scope_id, &bssid, &ip, i);
2078 if (!i) return(mDNSNULL);
2079 bzero(i, sizeof(NetworkInterfaceInfoOSX));
2080 i->ifa_name = (char *)mallocL("NetworkInterfaceInfoOSX name", strlen(ifa->ifa_name) + 1);
2081 if (!i->ifa_name) { freeL("NetworkInterfaceInfoOSX", i); return(mDNSNULL); }
2082 strcpy(i->ifa_name, ifa->ifa_name);
2083
2084 i->ifinfo.InterfaceID = mDNSNULL;
2085 i->ifinfo.ip = ip;
2086 i->ifinfo.mask = mask;
2087 strncpy(i->ifinfo.ifname, ifa->ifa_name, sizeof(i->ifinfo.ifname));
2088 i->ifinfo.ifname[sizeof(i->ifinfo.ifname)-1] = 0;
2089 i->ifinfo.Advertise = m->AdvertiseLocalAddresses;
2090 i->ifinfo.McastTxRx = mDNSfalse; // For now; will be set up later at the end of UpdateInterfaceList
2091
2092 i->next = mDNSNULL;
2093 i->Exists = mDNStrue;
2094 i->LastSeen = utc;
2095 i->scope_id = scope_id;
2096 i->BSSID = bssid;
2097 i->sa_family = ifa->ifa_addr->sa_family;
2098 i->Multicast = (ifa->ifa_flags & IFF_MULTICAST) && !(ifa->ifa_flags & IFF_POINTOPOINT);
2099
2100 i->ss.m = m;
2101 i->ss.info = i;
2102 i->ss.sktv4 = i->ss.sktv6 = -1;
2103 i->ss.cfsv4 = i->ss.cfsv6 = NULL;
2104 i->ss.rlsv4 = i->ss.rlsv6 = NULL;
2105
2106 *p = i;
2107 return(i);
2108 }
2109
2110 mDNSlocal NetworkInterfaceInfoOSX *FindRoutableIPv4(mDNS *const m, mDNSu32 scope_id)
2111 {
2112 NetworkInterfaceInfoOSX *i;
2113 for (i = m->p->InterfaceList; i; i = i->next)
2114 if (i->Exists && i->scope_id == scope_id && i->ifinfo.ip.type == mDNSAddrType_IPv4)
2115 if (!(i->ifinfo.ip.ip.v4.b[0] == 169 && i->ifinfo.ip.ip.v4.b[1] == 254))
2116 return(i);
2117 return(mDNSNULL);
2118 }
2119
2120 mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
2121 {
2122 mDNSBool foundav4 = mDNSfalse;
2123 mDNSBool foundav6 = mDNSfalse;
2124 struct ifaddrs *ifa = myGetIfAddrs(1);
2125 struct ifaddrs *v4Loopback = NULL;
2126 struct ifaddrs *v6Loopback = NULL;
2127 mDNSEthAddr PrimaryMAC = zeroEthAddr;
2128 char defaultname[32];
2129 int InfoSocket = socket(AF_INET6, SOCK_DGRAM, 0);
2130 if (InfoSocket < 3) LogMsg("UpdateInterfaceList: InfoSocket error %d errno %d (%s)", InfoSocket, errno, strerror(errno));
2131 if (m->SleepState) ifa = NULL;
2132
2133 while (ifa)
2134 {
2135 #if LIST_ALL_INTERFACES
2136 if (ifa->ifa_addr->sa_family == AF_APPLETALK)
2137 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_APPLETALK",
2138 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2139 else if (ifa->ifa_addr->sa_family == AF_LINK)
2140 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_LINK",
2141 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2142 else if (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6)
2143 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)",
2144 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2145 if (!(ifa->ifa_flags & IFF_UP))
2146 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_UP",
2147 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2148 if (!(ifa->ifa_flags & IFF_MULTICAST))
2149 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_MULTICAST",
2150 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2151 if (ifa->ifa_flags & IFF_POINTOPOINT)
2152 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_POINTOPOINT",
2153 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2154 if (ifa->ifa_flags & IFF_LOOPBACK)
2155 LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_LOOPBACK",
2156 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2157 #endif
2158
2159 if (ifa->ifa_addr->sa_family == AF_LINK)
2160 {
2161 struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr;
2162 if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == sizeof(PrimaryMAC) && mDNSSameEthAddress(&PrimaryMAC, &zeroEthAddr))
2163 mDNSPlatformMemCopy(sdl->sdl_data + sdl->sdl_nlen, PrimaryMAC.b, 6);
2164 }
2165
2166 if (ifa->ifa_flags & IFF_UP && ifa->ifa_addr)
2167 if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6)
2168 {
2169 if (!ifa->ifa_netmask)
2170 {
2171 mDNSAddr ip;
2172 SetupAddr(&ip, ifa->ifa_addr);
2173 LogMsg("getifaddrs: ifa_netmask is NULL for %5s(%d) Flags %04X Family %2d %#a",
2174 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family, &ip);
2175 }
2176 else if (ifa->ifa_addr->sa_family != ifa->ifa_netmask->sa_family)
2177 {
2178 mDNSAddr ip;
2179 SetupAddr(&ip, ifa->ifa_addr);
2180 LogMsg("getifaddrs ifa_netmask for %5s(%d) Flags %04X Family %2d %#a has different family: %d",
2181 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family, &ip, ifa->ifa_netmask->sa_family);
2182 }
2183 else
2184 {
2185 int ifru_flags6 = 0;
2186 if (ifa->ifa_addr->sa_family == AF_INET6 && InfoSocket >= 0)
2187 {
2188 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
2189 struct in6_ifreq ifr6;
2190 bzero((char *)&ifr6, sizeof(ifr6));
2191 strncpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
2192 ifr6.ifr_addr = *sin6;
2193 if (ioctl(InfoSocket, SIOCGIFAFLAG_IN6, &ifr6) != -1)
2194 ifru_flags6 = ifr6.ifr_ifru.ifru_flags6;
2195 verbosedebugf("%s %.16a %04X %04X", ifa->ifa_name, &sin6->sin6_addr, ifa->ifa_flags, ifru_flags6);
2196 }
2197 if (!(ifru_flags6 & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY)))
2198 {
2199 if (ifa->ifa_flags & IFF_LOOPBACK)
2200 if (ifa->ifa_addr->sa_family == AF_INET) v4Loopback = ifa;
2201 else v6Loopback = ifa;
2202 else
2203 {
2204 NetworkInterfaceInfoOSX *i = AddInterfaceToList(m, ifa, utc);
2205 if (i && i->Multicast)
2206 {
2207 if (ifa->ifa_addr->sa_family == AF_INET) foundav4 = mDNStrue;
2208 else foundav6 = mDNStrue;
2209 }
2210 }
2211 }
2212 }
2213 }
2214 ifa = ifa->ifa_next;
2215 }
2216
2217 // For efficiency, we don't register a loopback interface when other interfaces of that family are available
2218 if (!foundav4 && v4Loopback) AddInterfaceToList(m, v4Loopback, utc);
2219 if (!foundav6 && v6Loopback) AddInterfaceToList(m, v6Loopback, utc);
2220
2221 // Now the list is complete, set the McastTxRx setting for each interface.
2222 // We always send and receive using IPv4.
2223 // To reduce traffic, we send and receive using IPv6 only on interfaces that have no routable IPv4 address.
2224 // Having a routable IPv4 address assigned is a reasonable indicator of being on a large configured network,
2225 // which means there's a good chance that most or all the other devices on that network should also have v4.
2226 // 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.
2227 // At this time, reducing the packet rate is more important than v6-only devices on a large configured network,
2228 // so we are willing to make that sacrifice.
2229 NetworkInterfaceInfoOSX *i;
2230 for (i = m->p->InterfaceList; i; i = i->next)
2231 if (i->Exists)
2232 {
2233 mDNSBool txrx = i->Multicast && ((i->ifinfo.ip.type == mDNSAddrType_IPv4) || !FindRoutableIPv4(m, i->scope_id));
2234 if (i->ifinfo.McastTxRx != txrx)
2235 {
2236 i->ifinfo.McastTxRx = txrx;
2237 i->Exists = 2; // State change; need to deregister and reregister this interface
2238 }
2239 }
2240 if (InfoSocket >= 0) close(InfoSocket);
2241
2242 mDNS_snprintf(defaultname, sizeof(defaultname), "Macintosh-%02X%02X%02X%02X%02X%02X",
2243 PrimaryMAC.b[0], PrimaryMAC.b[1], PrimaryMAC.b[2], PrimaryMAC.b[3], PrimaryMAC.b[4], PrimaryMAC.b[5]);
2244
2245 // Set up the nice label
2246 domainlabel nicelabel;
2247 nicelabel.c[0] = 0;
2248 GetUserSpecifiedFriendlyComputerName(&nicelabel);
2249 if (nicelabel.c[0] == 0)
2250 {
2251 LogMsg("Couldn't read user-specified Computer Name; using default “%s” instead", defaultname);
2252 MakeDomainLabelFromLiteralString(&nicelabel, defaultname);
2253 }
2254
2255 // Set up the RFC 1034-compliant label
2256 domainlabel hostlabel;
2257 hostlabel.c[0] = 0;
2258 GetUserSpecifiedLocalHostName(&hostlabel);
2259 if (hostlabel.c[0] == 0)
2260 {
2261 LogMsg("Couldn't read user-specified local hostname; using default “%s.local” instead", defaultname);
2262 MakeDomainLabelFromLiteralString(&hostlabel, defaultname);
2263 }
2264
2265 if (SameDomainLabel(m->p->usernicelabel.c, nicelabel.c))
2266 debugf("Usernicelabel (%#s) unchanged since last time; not changing m->nicelabel (%#s)", m->p->usernicelabel.c, m->nicelabel.c);
2267 else
2268 {
2269 debugf("Updating m->nicelabel to %#s", nicelabel.c);
2270 m->p->usernicelabel = m->nicelabel = nicelabel;
2271 }
2272
2273 if (SameDomainLabel(m->p->userhostlabel.c, hostlabel.c))
2274 debugf("Userhostlabel (%#s) unchanged since last time; not changing m->hostlabel (%#s)", m->p->userhostlabel.c, m->hostlabel.c);
2275 else
2276 {
2277 debugf("Updating m->hostlabel to %#s", hostlabel.c);
2278 m->p->userhostlabel = m->hostlabel = hostlabel;
2279 mDNS_SetFQDN(m);
2280 }
2281
2282 return(mStatus_NoError);
2283 }
2284
2285 mDNSlocal int CountMaskBits(mDNSAddr *mask)
2286 {
2287 int i = 0, bits = 0;
2288 int bytes = mask->type == mDNSAddrType_IPv4 ? 4 : mask->type == mDNSAddrType_IPv6 ? 16 : 0;
2289 while (i < bytes)
2290 {
2291 mDNSu8 b = mask->ip.v6.b[i++];
2292 while (b & 0x80) { bits++; b <<= 1; }
2293 if (b) return(-1);
2294 }
2295 while (i < bytes) if (mask->ip.v6.b[i++]) return(-1);
2296 return(bits);
2297 }
2298
2299 // returns count of non-link local V4 addresses registered
2300 mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
2301 {
2302 NetworkInterfaceInfoOSX *i;
2303 int count = 0;
2304 for (i = m->p->InterfaceList; i; i = i->next)
2305 if (i->Exists)
2306 {
2307 NetworkInterfaceInfo *n = &i->ifinfo;
2308 NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifa_name, i->sa_family);
2309 if (!primary) LogMsg("SetupActiveInterfaces ERROR! SearchForInterfaceByName didn't find %s", i->ifa_name);
2310
2311 if (n->InterfaceID && n->InterfaceID != (mDNSInterfaceID)primary) // Sanity check
2312 {
2313 LogMsg("SetupActiveInterfaces ERROR! n->InterfaceID %p != primary %p", n->InterfaceID, primary);
2314 n->InterfaceID = mDNSNULL;
2315 }
2316
2317 if (!n->InterfaceID)
2318 {
2319 // NOTE: If n->InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
2320 // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
2321 // If n->InterfaceID is NOT set, then we haven't registered it and we should not try to deregister it
2322 n->InterfaceID = (mDNSInterfaceID)primary;
2323 // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away.
2324 // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds.
2325 // 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.
2326 mDNSBool flapping = (utc - i->LastSeen > 0 && utc - i->LastSeen < 60);
2327 mDNS_RegisterInterface(m, n, flapping ? mDNSPlatformOneSecond * 5 : 0);
2328 if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && (i->ifinfo.ip.ip.v4.b[0] != 169 || i->ifinfo.ip.ip.v4.b[1] != 254)) count++;
2329 LogOperation("SetupActiveInterfaces: Registered %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s",
2330 i->ifa_name, i->scope_id, &i->BSSID, primary, &n->ip, CountMaskBits(&n->mask),
2331 flapping ? " (Flapping)" : "", n->InterfaceActive ? " (Primary)" : "");
2332 }
2333
2334 if (!n->McastTxRx)
2335 debugf("SetupActiveInterfaces: No Tx/Rx on %5s(%lu) %.6a InterfaceID %p %#a", i->ifa_name, i->scope_id, &i->BSSID, primary, &n->ip);
2336 else
2337 {
2338 if (i->sa_family == AF_INET && primary->ss.sktv4 == -1)
2339 {
2340 mStatus err = SetupSocket(m, &primary->ss, mDNStrue, &i->ifinfo.ip, AF_INET);
2341 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));
2342 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));
2343 }
2344
2345 if (i->sa_family == AF_INET6 && primary->ss.sktv6 == -1)
2346 {
2347 mStatus err = SetupSocket(m, &primary->ss, mDNStrue, &i->ifinfo.ip, AF_INET6);
2348 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));
2349 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));
2350 }
2351 }
2352 }
2353 return count;
2354 }
2355
2356 mDNSlocal void MarkAllInterfacesInactive(mDNS *const m, mDNSs32 utc)
2357 {
2358 NetworkInterfaceInfoOSX *i;
2359 for (i = m->p->InterfaceList; i; i = i->next)
2360 {
2361 if (i->Exists) i->LastSeen = utc;
2362 i->Exists = mDNSfalse;
2363 }
2364 }
2365
2366 mDNSlocal void CloseRunLoopSourceSocket(CFRunLoopSourceRef rls, CFSocketRef cfs)
2367 {
2368 // Note: CFSocketInvalidate also closes the underlying socket for us
2369 // Comments show retain counts (obtained via CFGetRetainCount()) after each call. rls 3 cfs 3
2370 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); // rls 2 cfs 3
2371 CFRelease(rls); // rls ? cfs 3
2372 CFSocketInvalidate(cfs); // rls ? cfs 1
2373 CFRelease(cfs); // rls ? cfs ?
2374 }
2375
2376 mDNSlocal void CloseSocketSet(CFSocketSet *ss)
2377 {
2378 // Note: MUST NOT close the underlying native BSD sockets.
2379 // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately,
2380 // because it first has to unhook the sockets from its select() call, before it can safely close them.
2381 if (ss->cfsv4) CloseRunLoopSourceSocket(ss->rlsv4, ss->cfsv4);
2382 if (ss->cfsv6) CloseRunLoopSourceSocket(ss->rlsv6, ss->cfsv6);
2383 ss->sktv4 = ss->sktv6 = -1;
2384 ss->cfsv4 = ss->cfsv6 = NULL;
2385 ss->rlsv4 = ss->rlsv6 = NULL;
2386 }
2387
2388 // returns count of non-link local V4 addresses deregistered
2389 mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc)
2390 {
2391 // First pass:
2392 // If an interface is going away, then deregister this from the mDNSCore.
2393 // We also have to deregister it if the primary interface that it's using for its InterfaceID is going away.
2394 // We have to do this because mDNSCore will use that InterfaceID when sending packets, and if the memory
2395 // it refers to has gone away we'll crash.
2396 // Don't actually close the sockets or free the memory yet: When the last representative of an interface goes away
2397 // mDNSCore may want to send goodbye packets on that interface. (Not yet implemented, but a good idea anyway.)
2398 NetworkInterfaceInfoOSX *i;
2399 int count = 0;
2400 for (i = m->p->InterfaceList; i; i = i->next)
2401 {
2402 // 1. If this interface is no longer active, or its InterfaceID is changing, deregister it
2403 NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifa_name, i->sa_family);
2404 if (i->ifinfo.InterfaceID)
2405 if (i->Exists == 0 || i->Exists == 2 || i->ifinfo.InterfaceID != (mDNSInterfaceID)primary)
2406 {
2407 LogOperation("ClearInactiveInterfaces: Deregistering %5s(%lu) %.6a InterfaceID %p %#a/%d%s",
2408 i->ifa_name, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID,
2409 &i->ifinfo.ip, CountMaskBits(&i->ifinfo.mask), i->ifinfo.InterfaceActive ? " (Primary)" : "");
2410 mDNS_DeregisterInterface(m, &i->ifinfo);
2411 if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && (i->ifinfo.ip.ip.v4.b[0] != 169 || i->ifinfo.ip.ip.v4.b[1] != 254)) count++;
2412 i->ifinfo.InterfaceID = mDNSNULL;
2413 // NOTE: If n->InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
2414 // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
2415 // If n->InterfaceID is NOT set, then it's not registered and we should not call mDNS_DeregisterInterface() on it.
2416 }
2417 }
2418
2419 // Second pass:
2420 // Now that everything that's going to deregister has done so, we can close sockets and free the memory
2421 NetworkInterfaceInfoOSX **p = &m->p->InterfaceList;
2422 while (*p)
2423 {
2424 i = *p;
2425 // 2. Close all our CFSockets. We'll recreate them later as necessary.
2426 // (We may have previously had both v4 and v6, and we may not need both any more.)
2427 CloseSocketSet(&i->ss);
2428 // 3. If no longer active, delete interface from list and free memory
2429 if (!i->Exists)
2430 {
2431 if (i->LastSeen == utc) i->LastSeen = utc - 1;
2432 mDNSBool delete = (NumCacheRecordsForInterfaceID(m, (mDNSInterfaceID)i) == 0) && (utc - i->LastSeen >= 60);
2433 LogOperation("ClearInactiveInterfaces: %-13s %5s(%lu) %.6a InterfaceID %p %#a/%d Age %d%s", delete ? "Deleting" : "Holding",
2434 i->ifa_name, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID,
2435 &i->ifinfo.ip, CountMaskBits(&i->ifinfo.mask), utc - i->LastSeen,
2436 i->ifinfo.InterfaceActive ? " (Primary)" : "");
2437 if (delete)
2438 {
2439 *p = i->next;
2440 if (i->ifa_name) freeL("NetworkInterfaceInfoOSX name", i->ifa_name);
2441 freeL("NetworkInterfaceInfoOSX", i);
2442 continue; // After deleting this object, don't want to do the "p = &i->next;" thing at the end of the loop
2443 }
2444 }
2445 p = &i->next;
2446 }
2447 return count;
2448 }
2449
2450 mDNSlocal mStatus GetDNSConfig(void **result)
2451 {
2452 #if MDNS_NO_DNSINFO
2453 static int MessageShown = 0;
2454 if (!MessageShown) { MessageShown = 1; LogMsg("Note: Compiled without Apple-specific Split-DNS support"); }
2455 *result = NULL;
2456 return mStatus_UnsupportedErr;
2457 #else
2458
2459 *result = dns_configuration_copy();
2460
2461 if (!*result)
2462 {
2463 // When running on 10.3 (build 7xxx) and earlier, we don't expect dns_configuration_copy() to succeed
2464 if (mDNSMacOSXSystemBuildNumber(NULL) < 8) return mStatus_UnsupportedErr;
2465
2466 // On 10.4, calls to dns_configuration_copy() early in the boot process often fail.
2467 // Apparently this is expected behaviour -- "not a bug".
2468 // Accordingly, we suppress syslog messages for the first three minutes after boot.
2469 // If we are still getting failures after three minutes, then we log them.
2470 if ((mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return mStatus_NoError;
2471
2472 LogMsg("GetDNSConfig: Error: dns_configuration_copy returned NULL");
2473 return mStatus_UnknownErr;
2474 }
2475 return mStatus_NoError;
2476 #endif // MDNS_NO_DNSINFO
2477 }
2478
2479 mDNSlocal mStatus RegisterSplitDNS(mDNS *m, int *nAdditions, int *nDeletions)
2480 {
2481 (void)m; // unused on 10.3 systems
2482 void *v;
2483 *nAdditions = *nDeletions = 0;
2484 mStatus err = GetDNSConfig(&v);
2485
2486 #if !MDNS_NO_DNSINFO
2487 if (!err && v)
2488 {
2489 int i;
2490 DNSServer *p;
2491 dns_config_t *config = v; // use void * to allow compilation on 10.3 systems
2492 mDNS_Lock(m);
2493 p = m->uDNS_info.Servers;
2494 while (p) { p->del = mDNStrue; p = p->next; } // mark all for deletion
2495
2496 LogOperation("RegisterSplitDNS: Registering %d resolvers", config->n_resolver);
2497 for (i = 0; i < config->n_resolver; i++)
2498 {
2499 int j, n;
2500 domainname d;
2501 dns_resolver_t *r = config->resolver[i];
2502 if (r->port == MulticastDNSPort.NotAnInteger) continue; // ignore configurations for .local
2503 if (r->search_order == DEFAULT_SEARCH_ORDER || !r->domain || !*r->domain) d.c[0] = 0; // we ignore domain for "default" resolver
2504 else if (!MakeDomainNameFromDNSNameString(&d, r->domain)) { LogMsg("RegisterSplitDNS: bad domain %s", r->domain); continue; }
2505
2506 // check if this is the lowest-weighted server for the domain
2507 for (j = 0; j < config->n_resolver; j++)
2508 {
2509 dns_resolver_t *p = config->resolver[j];
2510 if (p->port == MulticastDNSPort.NotAnInteger) continue;
2511 if (p->search_order <= r->search_order)
2512 {
2513 domainname tmp;
2514 if (p->search_order == DEFAULT_SEARCH_ORDER || !p->domain || !*p->domain) tmp.c[0] = '\0';
2515 else if (!MakeDomainNameFromDNSNameString(&tmp, p->domain)) { LogMsg("RegisterSplitDNS: bad domain %s", p->domain); continue; }
2516 if (SameDomainName(&d, &tmp))
2517 if (p->search_order < r->search_order || j < i) break; // if equal weights, pick first in list, otherwise pick lower-weight (p)
2518 }
2519 }
2520 if (j < config->n_resolver) // found a lower-weighted resolver for this domain
2521 { debugf("Rejecting DNS server in slot %d domain %##s (slot %d outranks)", i, d.c, j); continue; }
2522 // we're using this resolver - find the first IPv4 address
2523 for (n = 0; n < r->n_nameserver; n++)
2524 {
2525 if (r->nameserver[n]->sa_family == AF_INET && !AddrRequiresPPPConnection(r->nameserver[n]))
2526 {
2527 // %%% This should use mDNS_AddDNSServer() instead of duplicating functionality here
2528 mDNSAddr saddr;
2529 if (SetupAddr(&saddr, r->nameserver[n])) { LogMsg("RegisterSplitDNS: bad IP address"); continue; }
2530 // mDNSAddr saddr = { mDNSAddrType_IPv4, { { { 192, 168, 1, 1 } } } }; // for testing
2531 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);
2532 p = m->uDNS_info.Servers;
2533 while (p)
2534 {
2535 if (mDNSSameAddress(&p->addr, &saddr) && SameDomainName(&p->domain, &d)) { p->del = mDNSfalse; break; }
2536 else p = p->next;
2537 }
2538 if (!p)
2539 {
2540 p = mallocL("DNSServer", sizeof(*p));
2541 if (!p) { LogMsg("Error: malloc"); mDNS_Unlock(m); return mStatus_UnknownErr; }
2542 p->addr = saddr;
2543 p->del = mDNSfalse;
2544 p->teststate = DNSServer_Untested;
2545 AssignDomainName(&p->domain, &d);
2546 p->next = m->uDNS_info.Servers;
2547 m->uDNS_info.Servers = p;
2548 (*nAdditions)++;
2549 }
2550 break; // !!!KRS if we ever support round-robin servers, don't break here
2551 }
2552 }
2553 }
2554
2555 // remove all servers marked for deletion
2556 DNSServer **s = &m->uDNS_info.Servers;
2557 while (*s)
2558 {
2559 if ((*s)->del)
2560 {
2561 p = *s;
2562 *s = (*s)->next;
2563 freeL("DNSServer", p);
2564 (*nDeletions)--;
2565 }
2566 else s = &(*s)->next;
2567 }
2568 mDNS_Unlock(m);
2569 dns_configuration_free(config);
2570 }
2571 #endif
2572
2573 return err;
2574 }
2575
2576 mDNSlocal mStatus RegisterNameServers(mDNS *const m, CFDictionaryRef dict)
2577 {
2578 int i, count;
2579 CFArrayRef values;
2580 char buf[256];
2581 mDNSAddr saddr = { mDNSAddrType_IPv4, { { { 0 } } } };
2582 CFStringRef s;
2583
2584 mDNS_DeleteDNSServers(m); // deregister orig list
2585 values = CFDictionaryGetValue(dict, kSCPropNetDNSServerAddresses);
2586 if (!values) return mStatus_NoError;
2587
2588 count = CFArrayGetCount(values);
2589 for (i = 0; i < count; i++)
2590 {
2591 s = CFArrayGetValueAtIndex(values, i);
2592 if (!s) { LogMsg("ERROR: RegisterNameServers - CFArrayGetValueAtIndex"); break; }
2593 if (!CFStringGetCString(s, buf, 256, kCFStringEncodingUTF8))
2594 {
2595 LogMsg("ERROR: RegisterNameServers - CFStringGetCString");
2596 continue;
2597 }
2598 if (!inet_aton(buf, (struct in_addr *)saddr.ip.v4.b))
2599 {
2600 LogMsg("ERROR: RegisterNameServers - invalid address string %s", buf);
2601 continue;
2602 }
2603 LogOperation("RegisterNameServers: Adding %#a", &saddr);
2604 mDNS_AddDNSServer(m, &saddr, NULL);
2605 }
2606 return mStatus_NoError;
2607 }
2608
2609 mDNSlocal void FreeARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
2610 {
2611 (void)m; // unused
2612 ARListElem *elem = rr->RecordContext;
2613 if (result == mStatus_MemFree) freeL("FreeARElemCallback", elem);
2614 }
2615
2616 mDNSlocal void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
2617 {
2618 SearchListElem *slElem = question->QuestionContext;
2619 ARListElem *arElem, *ptr, *prev;
2620 AuthRecord *dereg;
2621 const char *name;
2622 mStatus err;
2623
2624 if (AddRecord)
2625 {
2626 arElem = mallocL("FoundDomain - arElem", sizeof(ARListElem));
2627 if (!arElem) { LogMsg("ERROR: malloc"); return; }
2628 mDNS_SetupResourceRecord(&arElem->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, FreeARElemCallback, arElem);
2629 if (question == &slElem->BrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowse];
2630 else if (question == &slElem->DefBrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseDefault];
2631 else if (question == &slElem->LegacyBrowseQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeBrowseLegacy];
2632 else if (question == &slElem->RegisterQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistration];
2633 else if (question == &slElem->DefRegisterQ) name = mDNS_DomainTypeNames[mDNS_DomainTypeRegistrationDefault];
2634 else { LogMsg("FoundDomain - unknown question"); return; }
2635
2636 MakeDomainNameFromDNSNameString(arElem->ar.resrec.name, name);
2637 AppendDNSNameString (arElem->ar.resrec.name, "local");
2638 AssignDomainName(&arElem->ar.resrec.rdata->u.name, &answer->rdata->u.name);
2639 err = mDNS_Register(m, &arElem->ar);
2640 if (err)
2641 {
2642 LogMsg("ERROR: FoundDomain - mDNS_Register returned %d", err);
2643 freeL("FoundDomain - arElem", arElem);
2644 return;
2645 }
2646 arElem->next = slElem->AuthRecs;
2647 slElem->AuthRecs = arElem;
2648 }
2649 else
2650 {
2651 ptr = slElem->AuthRecs;
2652 prev = NULL;
2653 while (ptr)
2654 {
2655 if (SameDomainName(&ptr->ar.resrec.rdata->u.name, &answer->rdata->u.name))
2656 {
2657 debugf("Deregistering PTR %##s -> %##s", ptr->ar.resrec.name->c, ptr->ar.resrec.rdata->u.name.c);
2658 dereg = &ptr->ar;
2659 if (prev) prev->next = ptr->next;
2660 else slElem->AuthRecs = ptr->next;
2661 ptr = ptr->next;
2662 err = mDNS_Deregister(m, dereg);
2663 if (err) LogMsg("ERROR: FoundDomain - mDNS_Deregister returned %d", err);
2664 }
2665 else
2666 {
2667 prev = ptr;
2668 ptr = ptr->next;
2669 }
2670 }
2671 }
2672 }
2673
2674 mDNSlocal void MarkSearchListElem(const char *d)
2675 {
2676 SearchListElem *new, *ptr;
2677 domainname domain;
2678
2679 if (!MakeDomainNameFromDNSNameString(&domain, d))
2680 { LogMsg("ERROR: MarkSearchListElem - bad domain %##s", d); return; }
2681
2682 if (SameDomainName(&domain, &localdomain) || SameDomainName(&domain, &LocalReverseMapomain))
2683 { debugf("MarkSearchListElem - ignoring local domain %##s", domain.c); return; }
2684
2685 // if domain is in list, mark as pre-existent (0)
2686 for (ptr = SearchList; ptr; ptr = ptr->next)
2687 if (SameDomainName(&ptr->domain, &domain))
2688 {
2689 if (ptr->flag != 1) ptr->flag = 0; // gracefully handle duplicates - if it is already marked as add, don't bump down to preexistent
2690 break;
2691 }
2692
2693 // if domain not in list, add to list, mark as add (1)
2694 if (!ptr)
2695 {
2696 new = mallocL("MarkSearchListElem - SearchListElem", sizeof(SearchListElem));
2697 if (!new) { LogMsg("ERROR: MarkSearchListElem - malloc"); return; }
2698 bzero(new, sizeof(SearchListElem));
2699 AssignDomainName(&new->domain, &domain);
2700 new->flag = 1; // add
2701 new->next = SearchList;
2702 SearchList = new;
2703 }
2704 }
2705
2706 // Get the search domains via OS X resolver routines. Returns mStatus_UnsupporterErr if compiled or run on 10.3 systems
2707 mDNSlocal mStatus GetSearchDomains(void)
2708 {
2709 void *v;
2710 mStatus err = GetDNSConfig(&v);
2711
2712 #if !MDNS_NO_DNSINFO
2713 if (!err && v)
2714 {
2715 int i;
2716 dns_config_t *config = v;
2717 if (!config->n_resolver) return err;
2718 dns_resolver_t *resolv = config->resolver[0]; // use the first slot for search domains
2719
2720 for (i = 0; i < resolv->n_search; i++) MarkSearchListElem(resolv->search[i]);
2721 if (resolv->domain) MarkSearchListElem(resolv->domain);
2722 dns_configuration_free(config);
2723 }
2724 #endif
2725
2726 return err;
2727 }
2728
2729 // Get search domains from dynamic store - used as a fallback mechanism on 10.3 systems, if GetSearchDomains (above) fails.
2730 mDNSlocal void GetDSSearchDomains(CFDictionaryRef dict)
2731 {
2732 char buf[MAX_ESCAPED_DOMAIN_NAME];
2733 int i, count;
2734
2735 CFStringRef s;
2736
2737 // get all the domains from "Search Domains" field of sharing prefs
2738 if (dict)
2739 {
2740 CFArrayRef searchdomains = CFDictionaryGetValue(dict, kSCPropNetDNSSearchDomains);
2741 if (searchdomains)
2742 {
2743 count = CFArrayGetCount(searchdomains);
2744 for (i = 0; i < count; i++)
2745 {
2746 s = CFArrayGetValueAtIndex(searchdomains, i);
2747 if (!s) { LogMsg("ERROR: GetDSSearchDomains - CFArrayGetValueAtIndex"); break; }
2748 if (!CFStringGetCString(s, buf, MAX_ESCAPED_DOMAIN_NAME, kCFStringEncodingUTF8))
2749 {
2750 LogMsg("ERROR: GetDSSearchDomains - CFStringGetCString");
2751 continue;
2752 }
2753 MarkSearchListElem(buf);
2754 }
2755 }
2756
2757 // get DHCP domain field
2758 CFStringRef dname = CFDictionaryGetValue(dict, kSCPropNetDNSDomainName);
2759 if (dname)
2760 {
2761 if (CFStringGetCString(dname, buf, MAX_ESCAPED_DOMAIN_NAME, kCFStringEncodingUTF8))
2762 MarkSearchListElem(buf);
2763 else LogMsg("ERROR: GetDSSearchDomains - CFStringGetCString");
2764 }
2765 }
2766 }
2767
2768 mDNSlocal mStatus RegisterSearchDomains(mDNS *const m, CFDictionaryRef dict)
2769 {
2770 struct ifaddrs *ifa = NULL;
2771 SearchListElem *ptr, *prev, *freeSLPtr;
2772 ARListElem *arList;
2773 mStatus err;
2774
2775 if (DomainDiscoveryDisabled) return mStatus_NoError;
2776
2777 // step 1: mark each elem for removal (-1), unless we aren't passed a dictionary in which case we mark as preexistent
2778 for (ptr = SearchList; ptr; ptr = ptr->next) ptr->flag = dict ? -1 : 0;
2779
2780 // Get search domains from resolver library (available in OS X 10.4 and later), reverting to dynamic store on 10.3 systems
2781 if (GetSearchDomains() == mStatus_UnsupportedErr) GetDSSearchDomains(dict);
2782
2783 // Construct reverse-map search domains
2784 ifa = myGetIfAddrs(1);
2785 while (ifa)
2786 {
2787 mDNSAddr addr;
2788 if (ifa->ifa_addr->sa_family == AF_INET && !SetupAddr(&addr, ifa->ifa_addr) && !IsPrivateV4Addr(&addr) && !(ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_netmask)
2789 {
2790 mDNSAddr netmask;
2791 char buffer[256];
2792 if (!SetupAddr(&netmask, ifa->ifa_netmask))
2793 {
2794 sprintf(buffer, "%d.%d.%d.%d.in-addr.arpa.", addr.ip.v4.b[3] & netmask.ip.v4.b[3],
2795 addr.ip.v4.b[2] & netmask.ip.v4.b[2],
2796 addr.ip.v4.b[1] & netmask.ip.v4.b[1],
2797 addr.ip.v4.b[0] & netmask.ip.v4.b[0]);
2798 MarkSearchListElem(buffer);
2799 }
2800 }
2801 ifa = ifa->ifa_next;
2802 }
2803
2804 // delete elems marked for removal, do queries for elems marked add
2805 prev = NULL;
2806 ptr = SearchList;
2807 while (ptr)
2808 {
2809 if (ptr->flag == -1) // remove
2810 {
2811 mDNS_StopQuery(m, &ptr->BrowseQ);
2812 mDNS_StopQuery(m, &ptr->RegisterQ);
2813 mDNS_StopQuery(m, &ptr->DefBrowseQ);
2814 mDNS_StopQuery(m, &ptr->DefRegisterQ);
2815 mDNS_StopQuery(m, &ptr->LegacyBrowseQ);
2816
2817 // deregister records generated from answers to the query
2818 arList = ptr->AuthRecs;
2819 ptr->AuthRecs = NULL;
2820 while (arList)
2821 {
2822 AuthRecord *dereg = &arList->ar;
2823 arList = arList->next;
2824 debugf("Deregistering PTR %##s -> %##s", dereg->resrec.name->c, dereg->resrec.rdata->u.name.c);
2825 err = mDNS_Deregister(m, dereg);
2826 if (err) LogMsg("ERROR: RegisterSearchDomains mDNS_Deregister returned %d", err);
2827 }
2828
2829 // remove elem from list, delete
2830 if (prev) prev->next = ptr->next;
2831 else SearchList = ptr->next;
2832 freeSLPtr = ptr;
2833 ptr = ptr->next;
2834 freeL("RegisterSearchDomains - freeSLPtr", freeSLPtr);
2835 continue;
2836 }
2837
2838 if (ptr->flag == 1) // add
2839 {
2840 mStatus err1, err2, err3, err4, err5;
2841 err1 = mDNS_GetDomains(m, &ptr->BrowseQ, mDNS_DomainTypeBrowse, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
2842 err2 = mDNS_GetDomains(m, &ptr->DefBrowseQ, mDNS_DomainTypeBrowseDefault, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
2843 err3 = mDNS_GetDomains(m, &ptr->RegisterQ, mDNS_DomainTypeRegistration, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
2844 err4 = mDNS_GetDomains(m, &ptr->DefRegisterQ, mDNS_DomainTypeRegistrationDefault, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
2845 err5 = mDNS_GetDomains(m, &ptr->LegacyBrowseQ, mDNS_DomainTypeBrowseLegacy, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
2846 if (err1 || err2 || err3 || err4 || err5)
2847 LogMsg("GetDomains for domain %##s returned error(s):\n"
2848 "%d (mDNS_DomainTypeBrowse)\n"
2849 "%d (mDNS_DomainTypeBrowseDefault)\n"
2850 "%d (mDNS_DomainTypeRegistration)\n"
2851 "%d (mDNS_DomainTypeRegistrationDefault)"
2852 "%d (mDNS_DomainTypeBrowseLegacy)\n",
2853 ptr->domain.c, err1, err2, err3, err4, err5);
2854 ptr->flag = 0;
2855 }
2856
2857 if (ptr->flag) { LogMsg("RegisterSearchDomains - unknown flag %d. Skipping.", ptr->flag); }
2858
2859 prev = ptr;
2860 ptr = ptr->next;
2861 }
2862
2863 return mStatus_NoError;
2864 }
2865
2866 //!!!KRS here is where we will give success/failure notification to the UI
2867 mDNSlocal void SCPrefsDynDNSCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
2868 {
2869 (void)m; // unused
2870 debugf("SCPrefsDynDNSCallback: result %d for registration of name %##s", result, rr->resrec.name->c);
2871 SetDDNSNameStatus(rr->resrec.name, result);
2872 }
2873
2874 mDNSlocal void SetSecretForDomain(mDNS *m, const domainname *domain)
2875 {
2876 OSStatus err = 0;
2877 char dstring[MAX_ESCAPED_DOMAIN_NAME];
2878 mDNSu32 secretlen;
2879 void *secret = NULL;
2880 domainname *d, canon;
2881 int i, dlen;
2882 mDNSu32 type = 'ddns';
2883 mDNSu32 typelen = sizeof(type);
2884 char *failedfn = "(none)";
2885 SecKeychainAttributeList *attrList = NULL;
2886 SecKeychainItemRef itemRef = NULL;
2887
2888 err = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
2889 if (err) { failedfn = "SecKeychainSetPreferenceDomain"; goto cleanup; }
2890
2891 // canonicalize name by converting to lower case (keychain and some name servers are case sensitive)
2892 ConvertDomainNameToCString(domain, dstring);
2893 dlen = strlen(dstring);
2894 for (i = 0; i < dlen; i++) dstring[i] = tolower(dstring[i]); // canonicalize -> lower case
2895 MakeDomainNameFromDNSNameString(&canon, dstring);
2896 d = &canon;
2897
2898 // find longest-match key, excluding last label (e.g. excluding ".com")
2899 while (d->c[0] && *(d->c + d->c[0] + 1))
2900 {
2901 if (!ConvertDomainNameToCString(d, dstring)) { LogMsg("SetSecretForDomain: bad domain %##s", d->c); return; }
2902 dlen = strlen(dstring);
2903 if (dstring[dlen-1] == '.') { dstring[dlen-1] = '\0'; dlen--; } // chop trailing dot
2904 SecKeychainAttribute attrs[] = { { kSecServiceItemAttr, strlen(dstring), dstring },
2905 { kSecTypeItemAttr, typelen, (UInt32 *)&type } };
2906 SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
2907 SecKeychainSearchRef searchRef;
2908
2909 err = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributes, &searchRef);
2910 if (err) { failedfn = "SecKeychainSearchCreateFromAttributes"; goto cleanup; }
2911
2912 err = SecKeychainSearchCopyNext(searchRef, &itemRef);
2913 if (!err)
2914 {
2915 mDNSu32 tags[1];
2916 SecKeychainAttributeInfo attrInfo;
2917 mDNSu32 i;
2918 char keybuf[MAX_ESCAPED_DOMAIN_NAME+1];
2919 domainname keyname;
2920
2921 tags[0] = kSecAccountItemAttr;
2922 attrInfo.count = 1;
2923 attrInfo.tag = tags;
2924 attrInfo.format = NULL;
2925
2926 err = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL, &attrList, &secretlen, &secret);
2927 if (err || !attrList) { failedfn = "SecKeychainItemCopyAttributesAndData"; goto cleanup; }
2928 if (!secretlen || !secret) { LogMsg("SetSecretForDomain - bad shared secret"); return; }
2929 if (((char *)secret)[secretlen-1]) { LogMsg("SetSecretForDomain - Shared secret not NULL-terminated"); goto cleanup; }
2930
2931 for (i = 0; i < attrList->count; i++)
2932 {
2933 SecKeychainAttribute attr = attrList->attr[i];
2934 if (attr.tag == kSecAccountItemAttr)
2935 {
2936 if (!attr.length || attr.length > MAX_ESCAPED_DOMAIN_NAME) { LogMsg("SetSecretForDomain - Bad key length %d", attr.length); goto cleanup; }
2937 strncpy(keybuf, attr.data, attr.length);
2938 if (!MakeDomainNameFromDNSNameString(&keyname, keybuf)) { LogMsg("SetSecretForDomain - bad key %s", keybuf); goto cleanup; }
2939 debugf("Setting shared secret for zone %s with key %##s", dstring, keyname.c);
2940 mDNS_SetSecretForZone(m, d, &keyname, secret);
2941 break;
2942 }
2943 }
2944 if (i == attrList->count) LogMsg("SetSecretForDomain - no key name set");
2945 goto cleanup;
2946 }
2947 else if (err == errSecItemNotFound) d = (domainname *)(d->c + d->c[0] + 1);
2948 else { failedfn = "SecKeychainSearchCopyNext"; goto cleanup; }
2949 }
2950
2951 cleanup:
2952 if (err && err != errSecItemNotFound) LogMsg("Error: SetSecretForDomain - %s failed with error code %d", failedfn, err);
2953 if (attrList) SecKeychainItemFreeAttributesAndData(attrList, secret);
2954 if (itemRef) CFRelease(itemRef);
2955 }
2956
2957 mDNSlocal void SetSCPrefsBrowseDomainsFromCFArray(mDNS *m, CFArrayRef browseDomains, mDNSBool add)
2958 {
2959 if (browseDomains)
2960 {
2961 CFIndex count = CFArrayGetCount(browseDomains);
2962 CFDictionaryRef browseDict;
2963 char buf[MAX_ESCAPED_DOMAIN_NAME];
2964 int i;
2965
2966 for (i = 0; i < count; i++)
2967 {
2968 browseDict = (CFDictionaryRef)CFArrayGetValueAtIndex(browseDomains, i);
2969 if (browseDict && DDNSSettingEnabled(browseDict))
2970 {
2971 CFStringRef name = CFDictionaryGetValue(browseDict, CFSTR("Domain"));
2972 if (name)
2973 {
2974 domainname BrowseDomain;
2975 if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) || !MakeDomainNameFromDNSNameString(&BrowseDomain, buf) || !BrowseDomain.c[0])
2976 LogMsg("SetSCPrefsBrowseDomainsFromCFArray SCDynamicStore bad DDNS browse domain: %s", buf[0] ? buf : "(unknown)");
2977 else SetSCPrefsBrowseDomain(m, &BrowseDomain, add);
2978 }
2979 }
2980 }
2981 }
2982 }
2983
2984
2985 mDNSlocal void DynDNSConfigChanged(mDNS *const m)
2986 {
2987 static mDNSBool LegacyNATInitialized = mDNSfalse;
2988 uDNS_GlobalInfo *u = &m->uDNS_info;
2989 CFDictionaryRef dict;
2990 CFStringRef key;
2991 domainname RegDomain, fqdn;
2992 CFArrayRef NewBrowseDomains = NULL;
2993 int nAdditions = 0, nDeletions = 0;
2994
2995 // get fqdn, zone from SCPrefs
2996 GetUserSpecifiedDDNSConfig(&fqdn, &RegDomain, &NewBrowseDomains);
2997 ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, fqdn.c[0] ? NULL : &fqdn, RegDomain.c[0] ? NULL : &RegDomain, &DomainDiscoveryDisabled);
2998
2999 if (!SameDomainName(&RegDomain, &DynDNSRegDomain))
3000 {
3001 if (DynDNSRegDomain.c[0])
3002 {
3003 RemoveDefRegDomain(&DynDNSRegDomain);
3004 SetSCPrefsBrowseDomain(m, &DynDNSRegDomain, mDNSfalse); // if we were automatically browsing in our registration domain, stop
3005 }
3006 AssignDomainName(&DynDNSRegDomain, &RegDomain);
3007 if (DynDNSRegDomain.c[0])
3008 {
3009 SetSecretForDomain(m, &DynDNSRegDomain);
3010 AddDefRegDomain(&DynDNSRegDomain);
3011 SetSCPrefsBrowseDomain(m, &DynDNSRegDomain, mDNStrue);
3012 }
3013 }
3014
3015 // Add new browse domains to internal list
3016 if (NewBrowseDomains) SetSCPrefsBrowseDomainsFromCFArray(m, NewBrowseDomains, mDNStrue);
3017
3018 // Remove old browse domains from internal list
3019 if (DynDNSBrowseDomains)
3020 {
3021 SetSCPrefsBrowseDomainsFromCFArray(m, DynDNSBrowseDomains, mDNSfalse);
3022 CFRelease(DynDNSBrowseDomains);
3023 }
3024
3025 // Replace the old browse domains array with the new array
3026 DynDNSBrowseDomains = NewBrowseDomains;
3027
3028 if (!SameDomainName(&fqdn, &DynDNSHostname))
3029 {
3030 if (DynDNSHostname.c[0]) mDNS_RemoveDynDNSHostName(m, &DynDNSHostname);
3031 AssignDomainName(&DynDNSHostname, &fqdn);
3032 if (DynDNSHostname.c[0])
3033 {
3034 SetSecretForDomain(m, &fqdn); // no-op if "zone" secret, above, is to be used for hostname
3035 SetDDNSNameStatus(&DynDNSHostname, 1); // Set status to 1 to indicate "in progress"
3036 mDNS_AddDynDNSHostName(m, &DynDNSHostname, SCPrefsDynDNSCallback, NULL);
3037 }
3038 }
3039
3040 // get DNS settings
3041 SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:DynDNSConfigChanged"), NULL, NULL);
3042 if (!store) return;
3043
3044 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetDNS);
3045 if (!key) { LogMsg("ERROR: DNSConfigChanged - SCDynamicStoreKeyCreateNetworkGlobalEntity"); CFRelease(store); return; }
3046 dict = SCDynamicStoreCopyValue(store, key);
3047 CFRelease(key);
3048
3049 // handle any changes to search domains and DNS server addresses
3050 if (RegisterSplitDNS(m, &nAdditions, &nDeletions) != mStatus_NoError)
3051 if (dict) RegisterNameServers(m, dict); // fall back to non-split DNS aware configuration on failure
3052 RegisterSearchDomains(m, dict); // note that we register name servers *before* search domains
3053 if (dict) CFRelease(dict);
3054
3055 // get IPv4 settings
3056 key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,kSCDynamicStoreDomainState, kSCEntNetIPv4);
3057 if (!key) { LogMsg("ERROR: RouterChanged - SCDynamicStoreKeyCreateNetworkGlobalEntity"); CFRelease(store); return; }
3058 dict = SCDynamicStoreCopyValue(store, key);
3059 CFRelease(key);
3060 CFRelease(store);
3061 if (!dict) // lost v4
3062 {
3063 mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL, NULL);
3064 if (DynDNSHostname.c[0]) SetDDNSNameStatus(&DynDNSHostname, 1); // Set status to 1 to indicate temporary failure
3065 return;
3066 }
3067
3068 // handle router changes
3069 mDNSAddr r;
3070 char buf[256];
3071 r.type = mDNSAddrType_IPv4;
3072 r.ip.v4.NotAnInteger = 0;
3073 CFStringRef router = CFDictionaryGetValue(dict, kSCPropNetIPv4Router);
3074 if (router)
3075 {
3076 struct sockaddr_in saddr;
3077
3078 if (!CFStringGetCString(router, buf, 256, kCFStringEncodingUTF8))
3079 LogMsg("Could not convert router to CString");
3080 else
3081 {
3082 saddr.sin_len = sizeof(saddr);
3083 saddr.sin_family = AF_INET;
3084 saddr.sin_port = 0;
3085 inet_aton(buf, &saddr.sin_addr);
3086 if (AddrRequiresPPPConnection((struct sockaddr *)&saddr)) { debugf("Ignoring router %s (requires PPP connection)", buf); }
3087 else *(in_addr_t *)&r.ip.v4 = saddr.sin_addr.s_addr;
3088 }
3089 }
3090
3091 // handle primary interface changes
3092 // 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
3093 if (nAdditions || nDeletions) mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL, NULL);
3094 CFStringRef primary = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface);
3095 if (primary)
3096 {
3097 mDNSAddr v4 = zeroAddr, v6 = zeroAddr;
3098 mDNSBool HavePrimaryGlobalv6 = mDNSfalse; // does the primary interface have a global v6 address?
3099 struct ifaddrs *ifa = myGetIfAddrs(1);
3100
3101 if (!CFStringGetCString(primary, buf, 256, kCFStringEncodingUTF8))
3102 { LogMsg("Could not convert router to CString"); goto error; }
3103
3104 // find primary interface in list
3105 while (ifa && (!v4.ip.v4.NotAnInteger || !HavePrimaryGlobalv6))
3106 {
3107 mDNSAddr tmp6 = zeroAddr;
3108 if (!strcmp(buf, ifa->ifa_name))
3109 {
3110 if (ifa->ifa_addr->sa_family == AF_INET) SetupAddr(&v4, ifa->ifa_addr);
3111 else if (ifa->ifa_addr->sa_family == AF_INET6)
3112 {
3113 SetupAddr(&tmp6, ifa->ifa_addr);
3114 if (tmp6.ip.v6.b[0] >> 5 == 1) // global prefix: 001
3115 { HavePrimaryGlobalv6 = mDNStrue; v6 = tmp6; }
3116 }
3117 }
3118 else
3119 {
3120 // We'll take a V6 address from the non-primary interface if the primary interface doesn't have a global V6 address
3121 if (!HavePrimaryGlobalv6 && ifa->ifa_addr->sa_family == AF_INET6 && !v6.ip.v6.b[0])
3122 {
3123 SetupAddr(&tmp6, ifa->ifa_addr);
3124 if (tmp6.ip.v6.b[0] >> 5 == 1) v6 = tmp6;
3125 }
3126 }
3127 ifa = ifa->ifa_next;
3128 }
3129
3130 // Note that while we advertise v6, we still require v4 (possibly NAT'd, but not link-local) because we must use
3131 // V4 to communicate w/ our DNS server
3132
3133 if (v4.ip.v4.b[0] == 169 && v4.ip.v4.b[1] == 254) mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL, NULL); // primary IP is link-local
3134 else
3135 {
3136 if (v4.ip.v4.NotAnInteger != u->AdvertisedV4.ip.v4.NotAnInteger ||
3137 memcmp(v6.ip.v6.b, u->AdvertisedV6.ip.v6.b, 16) ||
3138 r.ip.v4.NotAnInteger != u->Router.ip.v4.NotAnInteger)
3139 {
3140 if (LegacyNATInitialized) { LegacyNATDestroy(); LegacyNATInitialized = mDNSfalse; }
3141 if (r.ip.v4.NotAnInteger && IsPrivateV4Addr(&v4))
3142 {
3143 mStatus err = LegacyNATInit();
3144 if (err) LogMsg("ERROR: LegacyNATInit");
3145 else LegacyNATInitialized = mDNStrue;
3146 }
3147 mDNS_SetPrimaryInterfaceInfo(m, &v4, v6.ip.v6.b[0] ? &v6 : NULL, r.ip.v4.NotAnInteger ? &r : NULL);
3148 }
3149 }
3150 }
3151 error:
3152 CFRelease(dict);
3153 }
3154
3155 mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
3156 {
3157 LogOperation("*** Network Configuration Change ***");
3158 m->p->NetworkChanged = 0; // If we received a network change event and deferred processing, we're now dealing with it
3159 mDNSs32 utc = mDNSPlatformUTC();
3160 MarkAllInterfacesInactive(m, utc);
3161 UpdateInterfaceList(m, utc);
3162 int nDeletions = ClearInactiveInterfaces(m, utc);
3163 int nAdditions = SetupActiveInterfaces(m, utc);
3164 DynDNSConfigChanged(m); // note - call DynDNSConfigChanged *before* mDNS_UpdateLLQs
3165 if (nDeletions || nAdditions) mDNS_UpdateLLQs(m); // so that LLQs are restarted against the up to date name servers
3166
3167 if (m->MainCallback)
3168 m->MainCallback(m, mStatus_ConfigChanged);
3169 }
3170
3171 mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context)
3172 {
3173 (void)store; // Parameter not used
3174 (void)changedKeys; // Parameter not used
3175 mDNS *const m = (mDNS *const)context;
3176 mDNS_Lock(m);
3177
3178 mDNSs32 delay = mDNSPlatformOneSecond * 2; // Start off assuming a two-second delay
3179
3180 int c = CFArrayGetCount(changedKeys); // Count changes
3181 CFRange range = { 0, c };
3182 CFStringRef k1 = SCDynamicStoreKeyCreateComputerName(NULL);
3183 CFStringRef k2 = SCDynamicStoreKeyCreateHostNames(NULL);
3184 if (k1 && k2)
3185 {
3186 int c1 = (CFArrayContainsValue(changedKeys, range, k1) != 0); // See if ComputerName changed
3187 int c2 = (CFArrayContainsValue(changedKeys, range, k2) != 0); // See if Local Hostname changed
3188 int c3 = (CFArrayContainsValue(changedKeys, range, CFSTR("Setup:/Network/DynamicDNS")) != 0);
3189 if (c && c - c1 - c2 - c3 == 0) delay = mDNSPlatformOneSecond/10; // If these were the only changes, shorten delay
3190 }
3191 if (k1) CFRelease(k1);
3192 if (k2) CFRelease(k2);
3193
3194 LogOperation("*** NetworkChanged *** %d change%s, delay %d", c, c>1?"s":"", delay);
3195
3196 if (!m->p->NetworkChanged ||
3197 m->p->NetworkChanged - NonZeroTime(m->timenow + delay) < 0)
3198 m->p->NetworkChanged = NonZeroTime(m->timenow + delay);
3199
3200 if (!m->SuppressSending ||
3201 m->SuppressSending - m->p->NetworkChanged < 0)
3202 m->SuppressSending = m->p->NetworkChanged;
3203 mDNS_Unlock(m);
3204 }
3205
3206 mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m)
3207 {
3208 mStatus err = -1;
3209 SCDynamicStoreContext context = { 0, m, NULL, NULL, NULL };
3210 SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:WatchForNetworkChanges"), NetworkChanged, &context);
3211 CFStringRef key1 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
3212 CFStringRef key2 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6);
3213 CFStringRef key3 = SCDynamicStoreKeyCreateComputerName(NULL);
3214 CFStringRef key4 = SCDynamicStoreKeyCreateHostNames(NULL);
3215 CFStringRef key5 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetDNS);
3216 CFStringRef pattern1 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4);
3217 CFStringRef pattern2 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6);
3218
3219 CFMutableArrayRef keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
3220 CFMutableArrayRef patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
3221
3222 if (!store) { LogMsg("SCDynamicStoreCreate failed: %s", SCErrorString(SCError())); goto error; }
3223 if (!key1 || !key2 || !key3 || !key4 || !keys || !pattern1 || !pattern2 || !patterns) goto error;
3224
3225 CFArrayAppendValue(keys, key1);
3226 CFArrayAppendValue(keys, key2);
3227 CFArrayAppendValue(keys, key3);
3228 CFArrayAppendValue(keys, key4);
3229 CFArrayAppendValue(keys, key5);
3230 CFArrayAppendValue(keys, CFSTR("Setup:/Network/DynamicDNS"));
3231 CFArrayAppendValue(patterns, pattern1);
3232 CFArrayAppendValue(patterns, pattern2);
3233 CFArrayAppendValue(patterns, CFSTR("State:/Network/Interface/[^/]+/AirPort"));
3234 if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns))
3235 { LogMsg("SCDynamicStoreSetNotificationKeys failed: %s", SCErrorString(SCError())); goto error; }
3236
3237 m->p->StoreRLS = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
3238 if (!m->p->StoreRLS) { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error; }
3239
3240 CFRunLoopAddSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode);
3241 m->p->Store = store;
3242 err = 0;
3243 goto exit;
3244
3245 error:
3246 if (store) CFRelease(store);
3247
3248 exit:
3249 if (key1) CFRelease(key1);
3250 if (key2) CFRelease(key2);
3251 if (key3) CFRelease(key3);
3252 if (key4) CFRelease(key4);
3253 if (key5) CFRelease(key5);
3254 if (pattern1) CFRelease(pattern1);
3255 if (pattern2) CFRelease(pattern2);
3256 if (keys) CFRelease(keys);
3257 if (patterns) CFRelease(patterns);
3258
3259 return(err);
3260 }
3261
3262 mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messageType, void *messageArgument)
3263 {
3264 mDNS *const m = (mDNS *const)refcon;
3265 (void)service; // Parameter not used
3266 switch(messageType)
3267 {
3268 case kIOMessageCanSystemPowerOff: debugf ("PowerChanged kIOMessageCanSystemPowerOff (no action)"); break; // E0000240
3269 case kIOMessageSystemWillPowerOff: LogOperation("PowerChanged kIOMessageSystemWillPowerOff");
3270 mDNSCoreMachineSleep(m, true); mDNSMacOSXNetworkChanged(m); break; // E0000250
3271 case kIOMessageSystemWillNotPowerOff: debugf ("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; // E0000260
3272 case kIOMessageCanSystemSleep: debugf ("PowerChanged kIOMessageCanSystemSleep (no action)"); break; // E0000270
3273 case kIOMessageSystemWillSleep: LogOperation("PowerChanged kIOMessageSystemWillSleep");
3274 mDNSCoreMachineSleep(m, true); mDNSMacOSXNetworkChanged(m); break; // E0000280
3275 case kIOMessageSystemWillNotSleep: debugf ("PowerChanged kIOMessageSystemWillNotSleep (no action)"); break; // E0000290
3276 case kIOMessageSystemHasPoweredOn: LogOperation("PowerChanged kIOMessageSystemHasPoweredOn");
3277 // If still sleeping (didn't get 'WillPowerOn' message for some reason?) wake now
3278 if (m->SleepState) mDNSCoreMachineSleep(m, false);
3279 // Just to be safe, also make sure our interface list is fully up to date, in case we
3280 // haven't yet received the System Configuration Framework "network changed" event that
3281 // we expect to receive some time shortly after the kIOMessageSystemWillPowerOn message
3282 mDNSMacOSXNetworkChanged(m); break; // E0000300
3283 case kIOMessageSystemWillRestart: debugf ("PowerChanged kIOMessageSystemWillRestart (no action)"); break; // E0000310
3284 case kIOMessageSystemWillPowerOn: LogOperation("PowerChanged kIOMessageSystemWillPowerOn");
3285 // Make sure our interface list is cleared to the empty state, then tell mDNSCore to wake
3286 mDNSMacOSXNetworkChanged(m); mDNSCoreMachineSleep(m, false); break; // E0000320
3287 default: LogOperation("PowerChanged unknown message %X", messageType); break;
3288 }
3289 IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument);
3290 }
3291
3292 mDNSlocal mStatus WatchForPowerChanges(mDNS *const m)
3293 {
3294 IONotificationPortRef thePortRef;
3295 m->p->PowerConnection = IORegisterForSystemPower(m, &thePortRef, PowerChanged, &m->p->PowerNotifier);
3296 if (m->p->PowerConnection)
3297 {
3298 m->p->PowerRLS = IONotificationPortGetRunLoopSource(thePortRef);
3299 CFRunLoopAddSource(CFRunLoopGetCurrent(), m->p->PowerRLS, kCFRunLoopDefaultMode);
3300 return(mStatus_NoError);
3301 }
3302 return(-1);
3303 }
3304
3305 CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
3306 CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey;
3307 CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey;
3308 CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey;
3309
3310 // Major version 6 is 10.2.x (Jaguar)
3311 // Major version 7 is 10.3.x (Panther)
3312 // Major version 8 is 10.4.x (Tiger)
3313 mDNSexport int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring)
3314 {
3315 int major = 0, minor = 0;
3316 char letter = 0, prodname[256]="Mac OS X", prodvers[256]="", buildver[256]="?";
3317 CFDictionaryRef vers = _CFCopySystemVersionDictionary();
3318 if (vers)
3319 {
3320 CFStringRef cfprodname = CFDictionaryGetValue(vers, _kCFSystemVersionProductNameKey);
3321 CFStringRef cfprodvers = CFDictionaryGetValue(vers, _kCFSystemVersionProductVersionKey);
3322 CFStringRef cfbuildver = CFDictionaryGetValue(vers, _kCFSystemVersionBuildVersionKey);
3323 if (cfprodname) CFStringGetCString(cfprodname, prodname, sizeof(prodname), kCFStringEncodingUTF8);
3324 if (cfprodvers) CFStringGetCString(cfprodvers, prodvers, sizeof(prodvers), kCFStringEncodingUTF8);
3325 if (cfbuildver) CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8);
3326 sscanf(buildver, "%d%c%d", &major, &letter, &minor);
3327 CFRelease(vers);
3328 }
3329 if (HINFO_SWstring) mDNS_snprintf(HINFO_SWstring, 256, "%s %s (%s), %s", prodname, prodvers, buildver, mDNSResponderVersionString);
3330 return(major);
3331 }
3332
3333 // Test to see if we're the first client running on UDP port 5353, by trying to bind to 5353 without using SO_REUSEPORT.
3334 // If we fail, someone else got here first. That's not a big problem; we can share the port for multicast responses --
3335 // we just need to be aware that we shouldn't expect to successfully receive unicast UDP responses.
3336 mDNSlocal mDNSBool mDNSPlatformInit_CanReceiveUnicast(void)
3337 {
3338 int err = -1;
3339 int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
3340 if (s < 3)
3341 LogMsg("mDNSPlatformInit_CanReceiveUnicast: socket error %d errno %d (%s)", s, errno, strerror(errno));
3342 else
3343 {
3344 struct sockaddr_in s5353;
3345 s5353.sin_family = AF_INET;
3346 s5353.sin_port = MulticastDNSPort.NotAnInteger;
3347 s5353.sin_addr.s_addr = 0;
3348 err = bind(s, (struct sockaddr *)&s5353, sizeof(s5353));
3349 close(s);
3350 }
3351
3352 if (err) LogMsg("No unicast UDP responses");
3353 else debugf("Unicast UDP responses okay");
3354 return(err == 0);
3355 }
3356
3357 // Callback for the _legacy._browse queries - add answer to list of domains to search for empty-string browses
3358 mDNSlocal void FoundLegacyBrowseDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
3359 {
3360 DNameListElem *ptr, *prev, *new;
3361 (void)m; // unused;
3362 (void)question; // unused
3363
3364 LogMsg("%s browse domain %##s", AddRecord ? "Adding" : "Removing", answer->rdata->u.name.c);
3365
3366 if (AddRecord)
3367 {
3368 new = mallocL("FoundLegacyBrowseDomain", sizeof(DNameListElem));
3369 if (!new) { LogMsg("ERROR: malloc"); return; }
3370 AssignDomainName(&new->name, &answer->rdata->u.name);
3371 new->next = DefBrowseList;
3372 DefBrowseList = new;
3373 DefaultBrowseDomainChanged(&new->name, mDNStrue);
3374 udsserver_default_browse_domain_changed(&new->name, mDNStrue);
3375 return;
3376 }
3377 else
3378 {
3379 ptr = DefBrowseList;
3380 prev = NULL;
3381 while (ptr)
3382 {
3383 if (SameDomainName(&ptr->name, &answer->rdata->u.name))
3384 {
3385 DefaultBrowseDomainChanged(&ptr->name, mDNSfalse);
3386 udsserver_default_browse_domain_changed(&ptr->name, mDNSfalse);
3387 if (prev) prev->next = ptr->next;
3388 else DefBrowseList = ptr->next;
3389 freeL("FoundLegacyBrowseDomain", ptr);
3390 return;
3391 }
3392 prev = ptr;
3393 ptr = ptr->next;
3394 }
3395 LogMsg("FoundLegacyBrowseDomain: Got remove event for domain %##s not in list", answer->rdata->u.name.c);
3396 }
3397 }
3398
3399 mDNSlocal void RegisterBrowseDomainPTR(mDNS *m, const domainname *d, int type)
3400 {
3401 // allocate/register legacy and non-legacy _browse PTR record
3402 ARListElem *browse = mallocL("ARListElem", sizeof(*browse));
3403 mDNS_SetupResourceRecord(&browse->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, FreeARElemCallback, browse);
3404 MakeDomainNameFromDNSNameString(browse->ar.resrec.name, mDNS_DomainTypeNames[type]);
3405 AppendDNSNameString (browse->ar.resrec.name, "local");
3406 AssignDomainName(&browse->ar.resrec.rdata->u.name, d);
3407 mStatus err = mDNS_Register(m, &browse->ar);
3408 if (err)
3409 {
3410 LogMsg("SetSCPrefsBrowseDomain: mDNS_Register returned error %d", err);
3411 freeL("ARListElem", browse);
3412 }
3413 else
3414 {
3415 browse->next = SCPrefBrowseDomains;
3416 SCPrefBrowseDomains = browse;
3417 }
3418 }
3419
3420 mDNSlocal void DeregisterBrowseDomainPTR(mDNS *m, const domainname *d, int type)
3421 {
3422 ARListElem *remove, **ptr = &SCPrefBrowseDomains;
3423 domainname lhs; // left-hand side of PTR, for comparison
3424
3425 MakeDomainNameFromDNSNameString(&lhs, mDNS_DomainTypeNames[type]);
3426 AppendDNSNameString (&lhs, "local");
3427
3428 while (*ptr)
3429 {
3430 if (SameDomainName(&(*ptr)->ar.resrec.rdata->u.name, d) && SameDomainName((*ptr)->ar.resrec.name, &lhs))
3431 {
3432 remove = *ptr;
3433 *ptr = (*ptr)->next;
3434 mDNS_Deregister(m, &remove->ar);
3435 return;
3436 }
3437 else ptr = &(*ptr)->next;
3438 }
3439 }
3440
3441 // Add or remove a user-specified domain to the list of empty-string browse domains
3442 // Also register a non-legacy _browse PTR record so that the domain appears in enumeration lists
3443 mDNSlocal void SetSCPrefsBrowseDomain(mDNS *m, const domainname *d, mDNSBool add)
3444 {
3445 debugf("SetSCPrefsBrowseDomain: %s default browse domain %##s", add ? "Adding" : "Removing", d->c);
3446
3447 if (add)
3448 {
3449 RegisterBrowseDomainPTR(m, d, mDNS_DomainTypeBrowse);
3450 RegisterBrowseDomainPTR(m, d, mDNS_DomainTypeBrowseLegacy);
3451 }
3452 else
3453 {
3454 DeregisterBrowseDomainPTR(m, d, mDNS_DomainTypeBrowse);
3455 DeregisterBrowseDomainPTR(m, d, mDNS_DomainTypeBrowseLegacy);
3456 }
3457 }
3458
3459 // Construction of Default Browse domain list (i.e. when clients pass NULL) is as follows:
3460 // 1) query for b._dns-sd._udp.local on LocalOnly interface
3461 // (.local manually generated via explicit callback)
3462 // 2) for each search domain (from prefs pane), query for b._dns-sd._udp.<searchdomain>.
3463 // 3) for each result from (2), register LocalOnly PTR record b._dns-sd._udp.local. -> <result>
3464 // 4) result above should generate a callback from question in (1). result added to global list
3465 // 5) global list delivered to client via GetSearchDomainList()
3466 // 6) client calls to enumerate domains now go over LocalOnly interface
3467 // (!!!KRS may add outgoing interface in addition)
3468
3469 mDNSlocal mStatus InitDNSConfig(mDNS *const m)
3470 {
3471 mStatus err;
3472 static AuthRecord LocalRegPTR;
3473
3474 // start query for domains to be used in default (empty string domain) browses
3475 err = mDNS_GetDomains(m, &LegacyBrowseDomainQ, mDNS_DomainTypeBrowseLegacy, NULL, mDNSInterface_LocalOnly, FoundLegacyBrowseDomain, NULL);
3476
3477 // provide browse domain "local" automatically
3478 SetSCPrefsBrowseDomain(m, &localdomain, mDNStrue);
3479
3480 // register registration domain "local"
3481 mDNS_SetupResourceRecord(&LocalRegPTR, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, NULL, NULL);
3482 MakeDomainNameFromDNSNameString(LocalRegPTR.resrec.name, mDNS_DomainTypeNames[mDNS_DomainTypeRegistration]);
3483 AppendDNSNameString (LocalRegPTR.resrec.name, "local");
3484 AssignDomainName(&LocalRegPTR.resrec.rdata->u.name, &localdomain);
3485 err = mDNS_Register(m, &LocalRegPTR);
3486 if (err) LogMsg("ERROR: InitDNSConfig - mDNS_Register returned error %d", err);
3487
3488 return mStatus_NoError;
3489 }
3490
3491 mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
3492 {
3493 // In 10.4, mDNSResponder is launched very early in the boot process, while other subsystems are still in the process of starting up.
3494 // 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.
3495 int i;
3496 for (i=0; i<100; i++)
3497 {
3498 domainlabel testlabel;
3499 testlabel.c[0] = 0;
3500 GetUserSpecifiedLocalHostName(&testlabel);
3501 if (testlabel.c[0]) break;
3502 usleep(50000);
3503 }
3504
3505 mStatus err;
3506
3507 m->hostlabel.c[0] = 0;
3508
3509 char *HINFO_HWstring = "Macintosh";
3510 char HINFO_HWstring_buffer[256];
3511 int get_model[2] = { CTL_HW, HW_MODEL };
3512 size_t len_model = sizeof(HINFO_HWstring_buffer);
3513 if (sysctl(get_model, 2, HINFO_HWstring_buffer, &len_model, NULL, 0) == 0)
3514 HINFO_HWstring = HINFO_HWstring_buffer;
3515
3516 char HINFO_SWstring[256] = "";
3517 if (mDNSMacOSXSystemBuildNumber(HINFO_SWstring) < 7) m->KnownBugs |= mDNS_KnownBug_PhantomInterfaces;
3518 if (mDNSPlatformInit_CanReceiveUnicast()) m->CanReceiveUnicastOn5353 = mDNStrue;
3519
3520 mDNSu32 hlen = mDNSPlatformStrLen(HINFO_HWstring);
3521 mDNSu32 slen = mDNSPlatformStrLen(HINFO_SWstring);
3522 if (hlen + slen < 254)
3523 {
3524 m->HIHardware.c[0] = hlen;
3525 m->HISoftware.c[0] = slen;
3526 mDNSPlatformMemCopy(HINFO_HWstring, &m->HIHardware.c[1], hlen);
3527 mDNSPlatformMemCopy(HINFO_SWstring, &m->HISoftware.c[1], slen);
3528 }
3529
3530 m->p->unicastsockets.m = m;
3531 m->p->unicastsockets.info = NULL;
3532 m->p->unicastsockets.sktv4 = m->p->unicastsockets.sktv6 = -1;
3533 m->p->unicastsockets.cfsv4 = m->p->unicastsockets.cfsv6 = NULL;
3534 m->p->unicastsockets.rlsv4 = m->p->unicastsockets.rlsv6 = NULL;
3535
3536 err = SetupSocket(m, &m->p->unicastsockets, mDNSfalse, &zeroAddr, AF_INET);
3537 err = SetupSocket(m, &m->p->unicastsockets, mDNSfalse, &zeroAddr, AF_INET6);
3538
3539 struct sockaddr_in s4;
3540 struct sockaddr_in6 s6;
3541 socklen_t n4 = sizeof(s4);
3542 socklen_t n6 = sizeof(s6);
3543 if (getsockname(m->p->unicastsockets.sktv4, (struct sockaddr *)&s4, &n4) < 0) LogMsg("getsockname v4 error %d (%s)", errno, strerror(errno));
3544 else m->UnicastPort4.NotAnInteger = s4.sin_port;
3545 if (getsockname(m->p->unicastsockets.sktv6, (struct sockaddr *)&s6, &n6) < 0) LogMsg("getsockname v6 error %d (%s)", errno, strerror(errno));
3546 else m->UnicastPort6.NotAnInteger = s6.sin6_port;
3547
3548 m->p->InterfaceList = mDNSNULL;
3549 m->p->userhostlabel.c[0] = 0;
3550 m->p->usernicelabel.c[0] = 0;
3551 m->p->NotifyUser = 0;
3552 mDNSs32 utc = mDNSPlatformUTC();
3553 UpdateInterfaceList(m, utc);
3554 SetupActiveInterfaces(m, utc);
3555
3556 err = WatchForNetworkChanges(m);
3557 if (err) return(err);
3558
3559 err = WatchForPowerChanges(m);
3560 if (err) return err;
3561
3562 DynDNSRegDomain.c[0] = '\0';
3563 DynDNSConfigChanged(m); // Get initial DNS configuration
3564
3565 InitDNSConfig(m);
3566 return(err);
3567 }
3568
3569 mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
3570 {
3571 mStatus result = mDNSPlatformInit_setup(m);
3572
3573 // We don't do asynchronous initialization on OS X, so by the time we get here the setup will already
3574 // have succeeded or failed -- so if it succeeded, we should just call mDNSCoreInitComplete() immediately
3575 if (result == mStatus_NoError) mDNSCoreInitComplete(m, mStatus_NoError);
3576 return(result);
3577 }
3578
3579 mDNSexport void mDNSPlatformClose(mDNS *const m)
3580 {
3581 if (m->p->PowerConnection)
3582 {
3583 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->PowerRLS, kCFRunLoopDefaultMode);
3584 CFRunLoopSourceInvalidate(m->p->PowerRLS);
3585 CFRelease(m->p->PowerRLS);
3586 IODeregisterForSystemPower(&m->p->PowerNotifier);
3587 m->p->PowerConnection = 0;
3588 m->p->PowerNotifier = 0;
3589 m->p->PowerRLS = NULL;
3590 }
3591
3592 if (m->p->Store)
3593 {
3594 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode);
3595 CFRunLoopSourceInvalidate(m->p->StoreRLS);
3596 CFRelease(m->p->StoreRLS);
3597 CFRelease(m->p->Store);
3598 m->p->Store = NULL;
3599 m->p->StoreRLS = NULL;
3600 }
3601
3602 mDNSs32 utc = mDNSPlatformUTC();
3603 MarkAllInterfacesInactive(m, utc);
3604 ClearInactiveInterfaces(m, utc);
3605 CloseSocketSet(&m->p->unicastsockets);
3606 }
3607
3608 mDNSexport mDNSu32 mDNSPlatformRandomSeed(void)
3609 {
3610 return(mach_absolute_time());
3611 }
3612
3613 mDNSexport mDNSs32 mDNSPlatformOneSecond = 1000;
3614
3615 mDNSexport mStatus mDNSPlatformTimeInit(void)
3616 {
3617 // Notes: Typical values for mach_timebase_info:
3618 // tbi.numer = 1000 million
3619 // tbi.denom = 33 million
3620 // These are set such that (mach_absolute_time() * numer/denom) gives us nanoseconds;
3621 // numer / denom = nanoseconds per hardware clock tick (e.g. 30);
3622 // denom / numer = hardware clock ticks per nanosecond (e.g. 0.033)
3623 // (denom*1000000) / numer = hardware clock ticks per millisecond (e.g. 33333)
3624 // So: mach_absolute_time() / ((denom*1000000)/numer) = milliseconds
3625 //
3626 // Arithmetic notes:
3627 // tbi.denom is at least 1, and not more than 2^32-1.
3628 // Therefore (tbi.denom * 1000000) is at least one million, but cannot overflow a uint64_t.
3629 // tbi.denom is at least 1, and not more than 2^32-1.
3630 // Therefore clockdivisor should end up being a number roughly in the range 10^3 - 10^9.
3631 // If clockdivisor is less than 10^3 then that means that the native clock frequency is less than 1MHz,
3632 // which is unlikely on any current or future Macintosh.
3633 // If clockdivisor is greater than 10^9 then that means the native clock frequency is greater than 1000GHz.
3634 // When we ship Macs with clock frequencies above 1000GHz, we may have to update this code.
3635 struct mach_timebase_info tbi;
3636 kern_return_t result = mach_timebase_info(&tbi);
3637 if (result == KERN_SUCCESS) clockdivisor = ((uint64_t)tbi.denom * 1000000) / tbi.numer;
3638 return(result);
3639 }
3640
3641 mDNSexport mDNSs32 mDNSPlatformRawTime(void)
3642 {
3643 if (clockdivisor == 0) { LogMsg("mDNSPlatformRawTime called before mDNSPlatformTimeInit"); return(0); }
3644
3645 static uint64_t last_mach_absolute_time = 0;
3646 uint64_t this_mach_absolute_time = mach_absolute_time();
3647 if ((int64_t)this_mach_absolute_time - (int64_t)last_mach_absolute_time < 0)
3648 {
3649 LogMsg("mDNSPlatformRawTime: last_mach_absolute_time %08X%08X", last_mach_absolute_time);
3650 LogMsg("mDNSPlatformRawTime: this_mach_absolute_time %08X%08X", this_mach_absolute_time);
3651 // Update last_mach_absolute_time *before* calling NotifyOfElusiveBug()
3652 last_mach_absolute_time = this_mach_absolute_time;
3653 // Only show "mach_absolute_time went backwards" notice on 10.4 (build 8xyyy) or later
3654 if (mDNSMacOSXSystemBuildNumber(NULL) >= 8)
3655 NotifyOfElusiveBug("mach_absolute_time went backwards!", 3438376, "");
3656 }
3657 last_mach_absolute_time = this_mach_absolute_time;
3658
3659 return((mDNSs32)(this_mach_absolute_time / clockdivisor));
3660 }
3661
3662 mDNSexport mDNSs32 mDNSPlatformUTC(void)
3663 {
3664 return time(NULL);
3665 }
3666
3667 // Locking is a no-op here, because we're single-threaded with a CFRunLoop, so we can never interrupt ourselves
3668 mDNSexport void mDNSPlatformLock (const mDNS *const m) { (void)m; }
3669 mDNSexport void mDNSPlatformUnlock (const mDNS *const m) { (void)m; }
3670 mDNSexport void mDNSPlatformStrCopy(const void *src, void *dst) { strcpy((char *)dst, (char *)src); }
3671 mDNSexport mDNSu32 mDNSPlatformStrLen (const void *src) { return(strlen((char*)src)); }
3672 mDNSexport void mDNSPlatformMemCopy(const void *src, void *dst, mDNSu32 len) { memcpy(dst, src, len); }
3673 mDNSexport mDNSBool mDNSPlatformMemSame(const void *src, const void *dst, mDNSu32 len) { return(memcmp(dst, src, len) == 0); }
3674 mDNSexport void mDNSPlatformMemZero( void *dst, mDNSu32 len) { bzero(dst, len); }
3675 mDNSexport void * mDNSPlatformMemAllocate(mDNSu32 len) { return(mallocL("mDNSPlatformMemAllocate", len)); }
3676 mDNSexport void mDNSPlatformMemFree (void *mem) { freeL("mDNSPlatformMemFree", mem); }