Added some debugging messages; removed unused variable 'err' in mDNSPlatformGetPrimar...
[people/sha0/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  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  * 
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  * 
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 // ***************************************************************************
19 // mDNSMacOSX.c:
20 // Supporting routines to run mDNS on a CFRunLoop platform
21 // ***************************************************************************
22
23 // For debugging, set LIST_ALL_INTERFACES to 1 to display all found interfaces,
24 // including ones that mDNSResponder chooses not to use.
25 #define LIST_ALL_INTERFACES 0
26
27 // For enabling AAAA records over IPv4. Setting this to 0 sends only
28 // A records over IPv4 and AAAA over IPv6. Setting this to 1 sends both
29 // AAAA and A records over both IPv4 and IPv6.
30 #define AAAA_OVER_V4 1
31
32 // In Mac OS X 10.4 and earlier, to reduce traffic, we would send and receive using IPv6 only on interfaces that had no routable
33 // IPv4 address. Having a routable IPv4 address assigned is a reasonable indicator of being on a large configured network,
34 // which means there's a good chance that most or all the other devices on that network should also have IPv4.
35 // By doing this we lost the ability to talk to true IPv6-only devices on that link, but we cut the packet rate in half.
36 // At that time, reducing the packet rate was more important than v6-only devices on a large configured network,
37 // so were willing to make that sacrifice.
38 // In Mac OS X 10.5, in 2007, two things have changed:
39 // 1. IPv6-only devices are starting to become more common, so we can't ignore them.
40 // 2. Other efficiency improvements in the code mean that crude hacks like this should no longer be necessary.
41
42 #define USE_V6_ONLY_WHEN_NO_ROUTABLE_V4 0
43
44 #include "mDNSEmbeddedAPI.h"            // Defines the interface provided to the client layer above
45 #include "DNSCommon.h"
46 #include "uDNS.h"
47 #include "mDNSMacOSX.h"                         // Defines the specific types needed to run mDNS on this platform
48 #include "dns_sd.h"                                     // For mDNSInterface_LocalOnly etc.
49 #include "PlatformCommon.h"
50
51 #include <stdio.h>
52 #include <stdarg.h>                 // For va_list support
53 #include <stdlib.h>                 // For arc4random
54 #include <net/if.h>
55 #include <net/if_types.h>                       // For IFT_ETHER
56 #include <net/if_dl.h>
57 #include <net/bpf.h>                            // For BIOCSETIF etc.
58 #include <sys/uio.h>
59 #include <sys/param.h>
60 #include <sys/socket.h>
61 #include <sys/sysctl.h>
62 #include <sys/event.h>
63 #include <fcntl.h>
64 #include <sys/ioctl.h>
65 #include <time.h>                   // platform support for UTC time
66 #include <arpa/inet.h>              // for inet_aton
67 #include <pthread.h>
68
69 #include <netinet/in.h>             // For IP_RECVTTL
70 #ifndef IP_RECVTTL
71 #define IP_RECVTTL 24               // bool; receive reception TTL w/dgram
72 #endif
73
74 #include <netinet/in_systm.h>       // For n_long, required by <netinet/ip.h> below
75 #include <netinet/ip.h>             // For IPTOS_LOWDELAY etc.
76 #include <netinet6/in6_var.h>       // For IN6_IFF_NOTREADY etc.
77 #include <netinet6/nd6.h>           // For ND6_INFINITE_LIFETIME etc.
78
79 #if TARGET_OS_EMBEDDED
80 #define NO_SECURITYFRAMEWORK 1
81 #define NO_CFUSERNOTIFICATION 1
82 #define NO_IOPOWER 1
83 #endif
84
85 #ifndef NO_SECURITYFRAMEWORK
86 #include <Security/SecureTransport.h>
87 #include <Security/Security.h>
88 #endif /* NO_SECURITYFRAMEWORK */
89
90 #include <DebugServices.h>
91 #include "dnsinfo.h"
92
93 // Code contributed by Dave Heller:
94 // Define RUN_ON_PUMA_WITHOUT_IFADDRS to compile code that will
95 // work on Mac OS X 10.1, which does not have the getifaddrs call.
96 #define RUN_ON_PUMA_WITHOUT_IFADDRS 0
97 #if RUN_ON_PUMA_WITHOUT_IFADDRS
98 #include "mDNSMacOSXPuma.c"
99 #else
100 #include <ifaddrs.h>
101 #endif
102
103 #include <IOKit/IOKitLib.h>
104 #include <IOKit/IOMessage.h>
105
106 #if USE_IOPMCOPYACTIVEPMPREFERENCES
107 #include <IOKit/ps/IOPowerSources.h>
108 #include <IOKit/ps/IOPowerSourcesPrivate.h>
109 #endif
110
111 #include <mach/mach_error.h>
112 #include <mach/mach_port.h>
113 #include <mach/mach_time.h>
114 #include "helper.h"
115
116 #include <asl.h>
117
118 #define kInterfaceSpecificOption "interface="
119
120 // ***************************************************************************
121 // Globals
122
123 #if COMPILER_LIKES_PRAGMA_MARK
124 #pragma mark - Globals
125 #endif
126
127 // By default we don't offer sleep proxy service
128 // If OfferSleepProxyService is set non-zero (typically via command-line switch),
129 // then we'll offer sleep proxy service on desktop Macs that are set to never sleep.
130 // We currently do not offer sleep proxy service on laptops, or on machines that are set to go to sleep.
131 mDNSexport int OfferSleepProxyService = 0;
132
133 mDNSexport int OSXVers;
134 mDNSexport int KQueueFD;
135
136 #ifndef NO_SECURITYFRAMEWORK
137 static CFArrayRef ServerCerts;
138 #endif /* NO_SECURITYFRAMEWORK */
139
140 static CFStringRef NetworkChangedKey_IPv4;
141 static CFStringRef NetworkChangedKey_IPv6;
142 static CFStringRef NetworkChangedKey_Hostnames;
143 static CFStringRef NetworkChangedKey_Computername;
144 static CFStringRef NetworkChangedKey_DNS;
145 static CFStringRef NetworkChangedKey_DynamicDNS  = CFSTR("Setup:/Network/DynamicDNS");
146 static CFStringRef NetworkChangedKey_BackToMyMac = CFSTR("Setup:/Network/BackToMyMac");
147
148 static char  HINFO_HWstring_buffer[32];
149 static char *HINFO_HWstring = "Device";
150 static int   HINFO_HWstring_prefixlen = 6;
151
152 mDNSexport int WatchDogReportingThreshold = 250;
153
154 #if APPLE_OSX_mDNSResponder
155 static mDNSu8 SPMetricPortability   = 99;
156 static mDNSu8 SPMetricMarginalPower = 99;
157 static mDNSu8 SPMetricTotalPower    = 99;
158 mDNSexport domainname ActiveDirectoryPrimaryDomain;
159 mDNSexport int        ActiveDirectoryPrimaryDomainLabelCount;
160 mDNSexport mDNSAddr   ActiveDirectoryPrimaryDomainServer;
161 #endif // APPLE_OSX_mDNSResponder
162
163 // ***************************************************************************
164 // Functions
165
166 #if COMPILER_LIKES_PRAGMA_MARK
167 #pragma mark -
168 #pragma mark - Utility Functions
169 #endif
170
171 // We only attempt to send and receive multicast packets on interfaces that are
172 // (a) flagged as multicast-capable
173 // (b) *not* flagged as point-to-point (e.g. modem)
174 // Typically point-to-point interfaces are modems (including mobile-phone pseudo-modems), and we don't want
175 // to run up the user's bill sending multicast traffic over a link where there's only a single device at the
176 // other end, and that device (e.g. a modem bank) is probably not answering Multicast DNS queries anyway.
177 #define MulticastInterface(i) (((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT))
178
179 mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg)  // Both strings are UTF-8 text
180         {
181         static int notifyCount = 0;
182         if (notifyCount) return;
183
184         // If we display our alert early in the boot process, then it vanishes once the desktop appears.
185         // To avoid this, we don't try to display alerts in the first three minutes after boot.
186         if ((mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return;
187
188         // Unless ForceAlerts is defined, we only show these bug report alerts on machines that have a 17.x.x.x address
189         #if !ForceAlerts
190                 {
191                 // Determine if we're at Apple (17.*.*.*)
192                 extern mDNS mDNSStorage;
193                 NetworkInterfaceInfoOSX *i;
194                 for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
195                         if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && i->ifinfo.ip.ip.v4.b[0] == 17)
196                                 break;
197                 if (!i) return; // If not at Apple, don't show the alert
198                 }
199         #endif
200
201         LogMsg("%s", title);
202         LogMsg("%s", msg);
203         // Display a notification to the user
204         notifyCount++;
205
206 #ifndef NO_CFUSERNOTIFICATION
207         mDNSNotify(title, msg);
208 #endif /* NO_CFUSERNOTIFICATION */
209         }
210
211 mDNSlocal struct ifaddrs *myGetIfAddrs(int refresh)
212         {
213         static struct ifaddrs *ifa = NULL;
214
215         if (refresh && ifa)
216                 {
217                 freeifaddrs(ifa);
218                 ifa = NULL;
219                 }
220
221         if (ifa == NULL) getifaddrs(&ifa);
222
223         return ifa;
224         }
225
226 // To match *either* a v4 or v6 instance of this interface name, pass AF_UNSPEC for type
227 mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(mDNS *const m, const char *ifname, int type)
228         {
229         NetworkInterfaceInfoOSX *i;
230         for (i = m->p->InterfaceList; i; i = i->next)
231                 if (i->Exists && !strcmp(i->ifinfo.ifname, ifname) &&
232                         ((type == AF_UNSPEC                                         ) ||
233                          (type == AF_INET  && i->ifinfo.ip.type == mDNSAddrType_IPv4) ||
234                          (type == AF_INET6 && i->ifinfo.ip.type == mDNSAddrType_IPv6))) return(i);
235         return(NULL);
236         }
237
238 mDNSlocal int myIfIndexToName(u_short ifindex, char *name)
239         {
240         struct ifaddrs *ifa;
241         for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next)
242                 if (ifa->ifa_addr->sa_family == AF_LINK)
243                         if (((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index == ifindex)
244                                 { strlcpy(name, ifa->ifa_name, IF_NAMESIZE); return 0; }
245         return -1;
246         }
247
248 mDNSexport NetworkInterfaceInfoOSX *IfindexToInterfaceInfoOSX(const mDNS *const m, mDNSInterfaceID ifindex)
249 {
250         mDNSu32 scope_id = (mDNSu32)(uintptr_t)ifindex;
251         NetworkInterfaceInfoOSX *i;
252
253         // Don't get tricked by inactive interfaces
254         for (i = m->p->InterfaceList; i; i = i->next)
255                 if (i->Registered && i->scope_id == scope_id) return(i);
256
257         return mDNSNULL;
258 }
259
260 mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex)
261         {
262         if (ifindex == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
263         if (ifindex == kDNSServiceInterfaceIndexAny      ) return(mDNSNULL);
264
265         NetworkInterfaceInfoOSX* ifi = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)ifindex);
266         if (!ifi)
267                 {
268                 // Not found. Make sure our interface list is up to date, then try again.
269                 LogInfo("mDNSPlatformInterfaceIDfromInterfaceIndex: InterfaceID for interface index %d not found; Updating interface list", ifindex);
270                 mDNSMacOSXNetworkChanged(m);
271                 ifi = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)ifindex);
272                 }
273
274         if (!ifi) return(mDNSNULL);     
275         
276         return(ifi->ifinfo.InterfaceID);
277         }
278
279
280 mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id)
281         {
282         NetworkInterfaceInfoOSX *i;
283         if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
284         if (id == mDNSInterface_Any      ) return(0);
285
286         mDNSu32 scope_id = (mDNSu32)(uintptr_t)id;
287
288         // Don't use i->Registered here, because we DO want to find inactive interfaces, which have no Registered set
289         for (i = m->p->InterfaceList; i; i = i->next)
290                 if (i->scope_id == scope_id) return(i->scope_id);
291
292         // Not found. Make sure our interface list is up to date, then try again.
293         LogInfo("Interface index for InterfaceID %p not found; Updating interface list", id);
294         mDNSMacOSXNetworkChanged(m);
295         for (i = m->p->InterfaceList; i; i = i->next)
296                 if (i->scope_id == scope_id) return(i->scope_id);
297
298         return(0);
299         }
300
301 #if APPLE_OSX_mDNSResponder
302 mDNSexport void mDNSASLLog(uuid_t *uuid, const char *subdomain, const char *result, const char *signature, const char *fmt, ...)
303         {
304         if (OSXVers < OSXVers_10_6_SnowLeopard)         return;
305
306         static char             buffer[512];
307         aslmsg                  asl_msg = asl_new(ASL_TYPE_MSG);
308
309         if (!asl_msg)   { LogMsg("mDNSASLLog: asl_new failed"); return; }
310         if (uuid)
311                 {
312                 char            uuidStr[37];
313                 uuid_unparse(*uuid, uuidStr);
314                 asl_set         (asl_msg, "com.apple.message.uuid", uuidStr);
315                 }
316
317         static char     domainBase[] = "com.apple.mDNSResponder.%s";
318         mDNS_snprintf   (buffer, sizeof(buffer), domainBase, subdomain);
319         asl_set                 (asl_msg, "com.apple.message.domain", buffer);
320
321         if (result)             asl_set(asl_msg, "com.apple.message.result", result);
322         if (signature)  asl_set(asl_msg, "com.apple.message.signature", signature);
323
324         va_list ptr;
325         va_start(ptr,fmt);
326         mDNS_vsnprintf(buffer, sizeof(buffer), fmt, ptr);
327         va_end(ptr);
328
329         int     old_filter = asl_set_filter(NULL,ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
330         asl_log(NULL, asl_msg, ASL_LEVEL_DEBUG, "%s", buffer);
331         asl_set_filter(NULL, old_filter);
332         asl_free(asl_msg);
333         }
334 #endif // APPLE_OSX_mDNSResponder
335
336 #if COMPILER_LIKES_PRAGMA_MARK
337 #pragma mark -
338 #pragma mark - UDP & TCP send & receive
339 #endif
340
341 mDNSlocal mDNSBool AddrRequiresPPPConnection(const struct sockaddr *addr)
342         {
343         mDNSBool result = mDNSfalse;
344         SCNetworkConnectionFlags flags;
345         SCNetworkReachabilityRef ReachRef = NULL;
346
347         ReachRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, addr);
348         if (!ReachRef) { LogMsg("ERROR: RequiresConnection - SCNetworkReachabilityCreateWithAddress"); goto end; }
349         if (!SCNetworkReachabilityGetFlags(ReachRef, &flags)) { LogMsg("ERROR: AddrRequiresPPPConnection - SCNetworkReachabilityGetFlags"); goto end; }
350         result = flags & kSCNetworkFlagsConnectionRequired;
351
352         end:
353         if (ReachRef) CFRelease(ReachRef);
354         return result;
355         }
356
357 // Note: If InterfaceID is NULL, it means, "send this packet through our anonymous unicast socket"
358 // Note: If InterfaceID is non-NULL it means, "send this packet through our port 5353 socket on the specified interface"
359 // OR send via our primary v4 unicast socket
360 // UPDATE: The UDPSocket *src parameter now allows the caller to specify the source socket
361 mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
362         mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstPort)
363         {
364         NetworkInterfaceInfoOSX *info = mDNSNULL;
365         struct sockaddr_storage to;
366         int s = -1, err;
367         mStatus result = mStatus_NoError;
368
369         if (InterfaceID)
370                 {
371                 info = IfindexToInterfaceInfoOSX(m, InterfaceID);
372                 if (info == NULL)
373                         {
374                         LogMsg("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
375                         return mStatus_BadParamErr;
376                         }
377                 }
378
379         char *ifa_name = InterfaceID ? info->ifinfo.ifname : "unicast";
380
381         if (dst->type == mDNSAddrType_IPv4)
382                 {
383                 struct sockaddr_in *sin_to = (struct sockaddr_in*)&to;
384                 sin_to->sin_len            = sizeof(*sin_to);
385                 sin_to->sin_family         = AF_INET;
386                 sin_to->sin_port           = dstPort.NotAnInteger;
387                 sin_to->sin_addr.s_addr    = dst->ip.v4.NotAnInteger;
388                 s = (src ? src->ss : m->p->permanentsockets).sktv4;
389
390                 if (info)       // Specify outgoing interface
391                         {
392                         if (!mDNSAddrIsDNSMulticast(dst))
393                                 {
394                                 #ifdef IP_BOUND_IF
395                                         if (info->scope_id == 0)
396                                                 LogInfo("IP_BOUND_IF socket option not set -- info %p (%s) scope_id is zero", info, ifa_name);
397                                         else
398                                                 setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
399                                 #else
400                                         {
401                                         static int displayed = 0;
402                                         if (displayed < 1000)
403                                                 {
404                                                 displayed++;
405                                                 LogInfo("IP_BOUND_IF socket option not defined -- cannot specify interface for unicast packets");
406                                                 }
407                                         }
408                                 #endif
409                                 }
410                         else
411                                 {
412                                 err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &info->ifa_v4addr, sizeof(info->ifa_v4addr));
413                                 if (err < 0 && !m->p->NetworkChanged)
414                                         LogMsg("setsockopt - IP_MULTICAST_IF error %.4a %d errno %d (%s)", &info->ifa_v4addr, err, errno, strerror(errno));
415                                 }
416                         }
417                 }
418 #ifndef NO_IPV6
419         else if (dst->type == mDNSAddrType_IPv6)
420                 {
421                 struct sockaddr_in6 *sin6_to = (struct sockaddr_in6*)&to;
422                 sin6_to->sin6_len            = sizeof(*sin6_to);
423                 sin6_to->sin6_family         = AF_INET6;
424                 sin6_to->sin6_port           = dstPort.NotAnInteger;
425                 sin6_to->sin6_flowinfo       = 0;
426                 sin6_to->sin6_addr           = *(struct in6_addr*)&dst->ip.v6;
427                 sin6_to->sin6_scope_id       = info ? info->scope_id : 0;
428                 s = (src ? src->ss : m->p->permanentsockets).sktv6;
429                 if (info && mDNSAddrIsDNSMulticast(dst))        // Specify outgoing interface
430                         {
431                         err = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &info->scope_id, sizeof(info->scope_id));
432                         if (err < 0) LogMsg("setsockopt - IPV6_MULTICAST_IF error %d errno %d (%s)", err, errno, strerror(errno));
433                         }
434                 }
435 #endif
436         else
437                 {
438                 LogMsg("mDNSPlatformSendUDP: dst is not an IPv4 or IPv6 address!");
439 #if ForceAlerts
440                 *(long*)0 = 0;
441 #endif
442                 return mStatus_BadParamErr;
443                 }
444
445         if (s >= 0)
446                 verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %p %5s/%ld to %#a:%d skt %d",
447                         InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s);
448         else
449                 verbosedebugf("mDNSPlatformSendUDP: NOT sending on InterfaceID %p %5s/%ld (socket of this type not available)",
450                         InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort));
451
452         // Note: When sending, mDNSCore may often ask us to send both a v4 multicast packet and then a v6 multicast packet
453         // If we don't have the corresponding type of socket available, then return mStatus_Invalid
454         if (s < 0) return(mStatus_Invalid);
455
456         err = sendto(s, msg, (UInt8*)end - (UInt8*)msg, 0, (struct sockaddr *)&to, to.ss_len);
457         if (err < 0)
458                 {
459                 static int MessageCount = 0;
460                 // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
461                 if (!mDNSAddressIsAllDNSLinkGroup(dst))
462                         if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr);
463                 // Don't report EHOSTUNREACH in the first three minutes after boot
464                 // This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
465                 // but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
466                 if (errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(mStatus_TransientErr);
467                 // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change
468                 if (errno == EADDRNOTAVAIL && m->p->NetworkChanged) return(mStatus_TransientErr);
469                 if (MessageCount < 1000)
470                         {
471                         MessageCount++;
472                         if (errno == EHOSTUNREACH || errno == EADDRNOTAVAIL || errno == ENETDOWN)
473                                 LogInfo("mDNSPlatformSendUDP sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu",
474                                         s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow));
475                         else
476                                 LogMsg("mDNSPlatformSendUDP sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu",
477                                         s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow));
478                         }
479                 result = mStatus_UnknownErr;
480                 }
481
482 #ifdef IP_BOUND_IF
483         if (dst->type == mDNSAddrType_IPv4 && info && !mDNSAddrIsDNSMulticast(dst))
484                 {
485                 static const mDNSu32 ifindex = 0;
486                 setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex));
487                 }
488 #endif
489
490         return(result);
491         }
492
493 mDNSlocal ssize_t myrecvfrom(const int s, void *const buffer, const size_t max,
494         struct sockaddr *const from, size_t *const fromlen, mDNSAddr *dstaddr, char ifname[IF_NAMESIZE], mDNSu8 *ttl)
495         {
496         static unsigned int numLogMessages = 0;
497         struct iovec databuffers = { (char *)buffer, max };
498         struct msghdr   msg;
499         ssize_t         n;
500         struct cmsghdr *cmPtr;
501         char            ancillary[1024];
502
503         *ttl = 255;  // If kernel fails to provide TTL data (e.g. Jaguar doesn't) then assume the TTL was 255 as it should be
504
505         // Set up the message
506         msg.msg_name       = (caddr_t)from;
507         msg.msg_namelen    = *fromlen;
508         msg.msg_iov        = &databuffers;
509         msg.msg_iovlen     = 1;
510         msg.msg_control    = (caddr_t)&ancillary;
511         msg.msg_controllen = sizeof(ancillary);
512         msg.msg_flags      = 0;
513
514         // Receive the data
515         n = recvmsg(s, &msg, 0);
516         if (n<0)
517                 {
518                 if (errno != EWOULDBLOCK && numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned error %d errno %d", s, n, errno);
519                 return(-1);
520                 }
521         if (msg.msg_controllen < (int)sizeof(struct cmsghdr))
522                 {
523                 if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned %d msg.msg_controllen %d < sizeof(struct cmsghdr) %lu",
524                         s, n, msg.msg_controllen, sizeof(struct cmsghdr));
525                 return(-1);
526                 }
527         if (msg.msg_flags & MSG_CTRUNC)
528                 {
529                 if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s);
530                 return(-1);
531                 }
532
533         *fromlen = msg.msg_namelen;
534
535         // Parse each option out of the ancillary data.
536         for (cmPtr = CMSG_FIRSTHDR(&msg); cmPtr; cmPtr = CMSG_NXTHDR(&msg, cmPtr))
537                 {
538                 // debugf("myrecvfrom cmsg_level %d cmsg_type %d", cmPtr->cmsg_level, cmPtr->cmsg_type);
539                 if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVDSTADDR)
540                         {
541                         dstaddr->type = mDNSAddrType_IPv4;
542                         dstaddr->ip.v4 = *(mDNSv4Addr*)CMSG_DATA(cmPtr);
543                         //LogMsg("mDNSMacOSX.c: recvmsg IP_RECVDSTADDR %.4a", &dstaddr->ip.v4);
544                         }
545                 if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVIF)
546                         {
547                         struct sockaddr_dl *sdl = (struct sockaddr_dl *)CMSG_DATA(cmPtr);
548                         if (sdl->sdl_nlen < IF_NAMESIZE)
549                                 {
550                                 mDNSPlatformMemCopy(ifname, sdl->sdl_data, sdl->sdl_nlen);
551                                 ifname[sdl->sdl_nlen] = 0;
552                                 // debugf("IP_RECVIF sdl_index %d, sdl_data %s len %d", sdl->sdl_index, ifname, sdl->sdl_nlen);
553                                 }
554                         }
555                 if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVTTL)
556                         *ttl = *(u_char*)CMSG_DATA(cmPtr);
557                 if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_PKTINFO)
558                         {
559                         struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmPtr);
560                         dstaddr->type = mDNSAddrType_IPv6;
561                         dstaddr->ip.v6 = *(mDNSv6Addr*)&ip6_info->ipi6_addr;
562                         myIfIndexToName(ip6_info->ipi6_ifindex, ifname);
563                         }
564                 if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_HOPLIMIT)
565                         *ttl = *(int*)CMSG_DATA(cmPtr);
566                 }
567
568         return(n);
569         }
570
571 mDNSlocal void myKQSocketCallBack(int s1, short filter, void *context)
572         {
573         KQSocketSet *const ss = (KQSocketSet *)context;
574         mDNS *const m = ss->m;
575         int err = 0, count = 0, closed = 0;
576
577         if (filter != EVFILT_READ)
578                 LogMsg("myKQSocketCallBack: Why is filter %d not EVFILT_READ (%d)?", filter, EVFILT_READ);
579
580         if (s1 != ss->sktv4
581 #ifndef NO_IPV6
582                 && s1 != ss->sktv6
583 #endif
584                 )
585                 {
586                 LogMsg("myKQSocketCallBack: native socket %d", s1);
587                 LogMsg("myKQSocketCallBack: sktv4 %d", ss->sktv4);
588 #ifndef NO_IPV6
589                 LogMsg("myKQSocketCallBack: sktv6 %d", ss->sktv6);
590 #endif
591                 }
592
593         while (!closed)
594                 {
595                 mDNSAddr senderAddr, destAddr;
596                 mDNSIPPort senderPort;
597                 struct sockaddr_storage from;
598                 size_t fromlen = sizeof(from);
599                 char packetifname[IF_NAMESIZE] = "";
600                 mDNSu8 ttl;
601                 err = myrecvfrom(s1, &m->imsg, sizeof(m->imsg), (struct sockaddr *)&from, &fromlen, &destAddr, packetifname, &ttl);
602                 if (err < 0) break;
603
604                 count++;
605                 if (from.ss_family == AF_INET)
606                         {
607                         struct sockaddr_in *s = (struct sockaddr_in*)&from;
608                         senderAddr.type = mDNSAddrType_IPv4;
609                         senderAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr;
610                         senderPort.NotAnInteger = s->sin_port;
611                         //LogInfo("myKQSocketCallBack received IPv4 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
612                         }
613                 else if (from.ss_family == AF_INET6)
614                         {
615                         struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&from;
616                         senderAddr.type = mDNSAddrType_IPv6;
617                         senderAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
618                         senderPort.NotAnInteger = sin6->sin6_port;
619                         //LogInfo("myKQSocketCallBack received IPv6 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
620                         }
621                 else
622                         {
623                         LogMsg("myKQSocketCallBack from is unknown address family %d", from.ss_family);
624                         return;
625                         }
626
627                 // Note: When handling multiple packets in a batch, MUST reset InterfaceID before handling each packet
628                 mDNSInterfaceID InterfaceID = mDNSNULL;
629                 //NetworkInterfaceInfo *intf = m->HostInterfaces;
630                 //while (intf && strcmp(intf->ifname, packetifname)) intf = intf->next;
631
632                 NetworkInterfaceInfoOSX *intf = m->p->InterfaceList;
633                 while (intf && strcmp(intf->ifinfo.ifname, packetifname)) intf = intf->next;
634
635                 // When going to sleep we deregister all our interfaces, but if the machine
636                 // takes a few seconds to sleep we may continue to receive multicasts
637                 // during that time, which would confuse mDNSCoreReceive, because as far
638                 // as it's concerned, we should have no active interfaces any more.
639                 // Hence we ignore multicasts for which we can find no matching InterfaceID.
640                 if (intf) InterfaceID = intf->ifinfo.InterfaceID;
641                 else if (mDNSAddrIsDNSMulticast(&destAddr)) continue;
642
643 //              LogMsg("myKQSocketCallBack got packet from %#a to %#a on interface %#a/%s",
644 //                      &senderAddr, &destAddr, &ss->info->ifinfo.ip, ss->info->ifinfo.ifname);
645
646                 // mDNSCoreReceive may close the socket we're reading from.  We must break out of our
647                 // loop when that happens, or we may try to read from an invalid FD.  We do this by
648                 // setting the closeFlag pointer in the socketset, so CloseSocketSet can inform us
649                 // if it closes the socketset.
650                 ss->closeFlag = &closed;
651
652                 mDNSCoreReceive(m, &m->imsg, (unsigned char*)&m->imsg + err, &senderAddr, senderPort, &destAddr, ss->port, InterfaceID);
653
654                 // if we didn't close, we can safely dereference the socketset, and should to
655                 // reset the closeFlag, since it points to something on the stack
656                 if (!closed) ss->closeFlag = mDNSNULL;
657                 }
658
659         if (err < 0 && (errno != EWOULDBLOCK || count == 0))
660                 {
661                 // Something is busted here.
662                 // kqueue says there is a packet, but myrecvfrom says there is not.
663                 // Try calling select() to get another opinion.
664                 // Find out about other socket parameter that can help understand why select() says the socket is ready for read
665                 // All of this is racy, as data may have arrived after the call to select()
666                 static unsigned int numLogMessages = 0;
667                 int save_errno = errno;
668                 int so_error = -1;
669                 int so_nread = -1;
670                 int fionread = -1;
671                 socklen_t solen = sizeof(int);
672                 fd_set readfds;
673                 struct timeval timeout;
674                 int selectresult;
675                 FD_ZERO(&readfds);
676                 FD_SET(s1, &readfds);
677                 timeout.tv_sec  = 0;
678                 timeout.tv_usec = 0;
679                 selectresult = select(s1+1, &readfds, NULL, NULL, &timeout);
680                 if (getsockopt(s1, SOL_SOCKET, SO_ERROR, &so_error, &solen) == -1)
681                         LogMsg("myKQSocketCallBack getsockopt(SO_ERROR) error %d", errno);
682                 if (getsockopt(s1, SOL_SOCKET, SO_NREAD, &so_nread, &solen) == -1)
683                         LogMsg("myKQSocketCallBack getsockopt(SO_NREAD) error %d", errno);
684                 if (ioctl(s1, FIONREAD, &fionread) == -1)
685                         LogMsg("myKQSocketCallBack ioctl(FIONREAD) error %d", errno);
686                 if (numLogMessages++ < 100)
687                         LogMsg("myKQSocketCallBack recvfrom skt %d error %d errno %d (%s) select %d (%spackets waiting) so_error %d so_nread %d fionread %d count %d",
688                                 s1, err, save_errno, strerror(save_errno), selectresult, FD_ISSET(s1, &readfds) ? "" : "*NO* ", so_error, so_nread, fionread, count);
689                 if (numLogMessages > 5)
690                         NotifyOfElusiveBug("Flaw in Kernel (select/recvfrom mismatch)",
691                                 "Congratulations, you've reproduced an elusive bug.\r"
692                                 "Please contact the current assignee of <rdar://problem/3375328>.\r"
693                                 "Alternatively, you can send email to radar-3387020@group.apple.com. (Note number is different.)\r"
694                                 "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
695
696                 sleep(1);               // After logging this error, rate limit so we don't flood syslog
697                 }
698         }
699
700 // TCP socket support
701
702 typedef enum
703         {
704         handshake_required,
705         handshake_in_progress,
706         handshake_completed,
707         handshake_to_be_closed
708         } handshakeStatus;
709         
710 struct TCPSocket_struct
711         {
712         TCPSocketFlags flags;           // MUST BE FIRST FIELD -- mDNSCore expects every TCPSocket_struct to begin with TCPSocketFlags flags
713         TCPConnectionCallback callback;
714         int fd;
715         KQueueEntry kqEntry;
716 #ifndef NO_SECURITYFRAMEWORK
717         SSLContextRef tlsContext;
718         pthread_t handshake_thread;
719 #endif /* NO_SECURITYFRAMEWORK */
720         void *context;
721         mDNSBool setup;
722         mDNSBool connected;
723         handshakeStatus handshake;
724         mDNS *m; // So we can call KQueueLock from the SSLHandshake thread
725         mStatus err;
726         };
727
728 mDNSlocal void doTcpSocketCallback(TCPSocket *sock)
729         {
730         mDNSBool c = !sock->connected;
731         sock->connected = mDNStrue;
732         sock->callback(sock, sock->context, c, sock->err);
733         // Note: the callback may call CloseConnection here, which frees the context structure!
734         }
735
736 #ifndef NO_SECURITYFRAMEWORK
737
738 mDNSlocal OSStatus tlsWriteSock(SSLConnectionRef connection, const void *data, size_t *dataLength)
739         {
740         int ret = send(((TCPSocket *)connection)->fd, data, *dataLength, 0);
741         if (ret >= 0 && (size_t)ret < *dataLength) { *dataLength = ret; return(errSSLWouldBlock); }
742         if (ret >= 0)                              { *dataLength = ret; return(noErr); }
743         *dataLength = 0;
744         if (errno == EAGAIN                      ) return(errSSLWouldBlock);
745         if (errno == ENOENT                      ) return(errSSLClosedGraceful);
746         if (errno == EPIPE || errno == ECONNRESET) return(errSSLClosedAbort);
747         LogMsg("ERROR: tlsWriteSock: %d error %d (%s)\n", ((TCPSocket *)connection)->fd, errno, strerror(errno));
748         return(errSSLClosedAbort);
749         }
750
751 mDNSlocal OSStatus tlsReadSock(SSLConnectionRef connection, void *data, size_t *dataLength)
752         {
753         int ret = recv(((TCPSocket *)connection)->fd, data, *dataLength, 0);
754         if (ret > 0 && (size_t)ret < *dataLength) { *dataLength = ret; return(errSSLWouldBlock); }
755         if (ret > 0)                              { *dataLength = ret; return(noErr); }
756         *dataLength = 0;
757         if (ret == 0 || errno == ENOENT    ) return(errSSLClosedGraceful);
758         if (            errno == EAGAIN    ) return(errSSLWouldBlock);
759         if (            errno == ECONNRESET) return(errSSLClosedAbort);
760         LogMsg("ERROR: tlsSockRead: error %d (%s)\n", errno, strerror(errno));
761         return(errSSLClosedAbort);
762         }
763
764 mDNSlocal OSStatus tlsSetupSock(TCPSocket *sock, mDNSBool server)
765         {
766         mStatus err = SSLNewContext(server, &sock->tlsContext);
767         if (err) { LogMsg("ERROR: tlsSetupSock: SSLNewContext failed with error code: %d", err); return(err); }
768
769         err = SSLSetIOFuncs(sock->tlsContext, tlsReadSock, tlsWriteSock);
770         if (err) { LogMsg("ERROR: tlsSetupSock: SSLSetIOFuncs failed with error code: %d", err); return(err); }
771
772         err = SSLSetConnection(sock->tlsContext, (SSLConnectionRef) sock);
773         if (err) { LogMsg("ERROR: tlsSetupSock: SSLSetConnection failed with error code: %d", err); return(err); }
774
775         return(err);
776         }
777
778 mDNSlocal void *doSSLHandshake(void *ctx)
779         {
780         // Warning: Touching sock without the kqueue lock!
781         // We're protected because sock->handshake == handshake_in_progress
782         TCPSocket *sock = (TCPSocket*)ctx;
783         mDNS * const m = sock->m; // Get m now, as we may free sock if marked to be closed while we're waiting on SSLHandshake
784         mStatus err = SSLHandshake(sock->tlsContext);
785         
786         KQueueLock(m);
787         LogInfo("doSSLHandshake %p: got lock", sock); // Log *after* we get the lock
788
789         if (sock->handshake == handshake_to_be_closed)
790                 {
791                 LogInfo("SSLHandshake completed after close");
792                 mDNSPlatformTCPCloseConnection(sock);
793                 }
794         else
795                 {
796                 if (sock->fd != -1) KQueueSet(sock->fd, EV_ADD, EVFILT_READ, &sock->kqEntry);
797                 else LogMsg("doSSLHandshake: sock->fd is -1");
798
799                 if (err == errSSLWouldBlock)
800                         sock->handshake = handshake_required;
801                 else
802                         {
803                         if (err)
804                                 {
805                                 LogMsg("SSLHandshake failed: %d%s", err, err == errSSLPeerInternalError ? " (server busy)" : "");
806                                 SSLDisposeContext(sock->tlsContext);
807                                 sock->tlsContext = NULL;
808                                 }
809                         
810                         sock->err = err ? mStatus_ConnFailed : 0;
811                         sock->handshake = handshake_completed;
812                         
813                         LogInfo("doSSLHandshake: %p calling doTcpSocketCallback", sock);
814                         doTcpSocketCallback(sock);
815                         }
816                 }
817         
818         LogInfo("SSLHandshake %p: dropping lock", sock);
819         KQueueUnlock(m, "doSSLHandshake");
820         return NULL;
821         }
822
823 mDNSlocal mStatus spawnSSLHandshake(TCPSocket* sock)
824         {
825         LogInfo("spawnSSLHandshake %p: entry", sock);
826         if (sock->handshake != handshake_required) LogMsg("spawnSSLHandshake: handshake status not required: %d", sock->handshake);
827         sock->handshake = handshake_in_progress;
828         KQueueSet(sock->fd, EV_DELETE, EVFILT_READ, &sock->kqEntry);
829         pthread_attr_t attr;
830         pthread_attr_init(&attr);
831         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
832         mStatus err = pthread_create(&sock->handshake_thread, &attr, doSSLHandshake, sock);
833         pthread_attr_destroy(&attr);
834         if (err)
835                 {
836                 LogMsg("Could not start SSLHandshake thread: (%d) %s", err, strerror(err));
837                 sock->handshake = handshake_completed;
838                 sock->err = err;
839                 KQueueSet(sock->fd, EV_ADD, EVFILT_READ, &sock->kqEntry);
840                 }
841         LogInfo("spawnSSLHandshake %p: done", sock);
842         return err;
843         }
844
845 mDNSlocal mDNSBool IsTunnelModeDomain(const domainname *d)
846         {
847         static const domainname *mmc = (const domainname*) "\x7" "members" "\x3" "mac" "\x3" "com";
848         const domainname *d1 = mDNSNULL;        // TLD
849         const domainname *d2 = mDNSNULL;        // SLD
850         const domainname *d3 = mDNSNULL;
851         while (d->c[0]) { d3 = d2; d2 = d1; d1 = d; d = (const domainname*)(d->c + 1 + d->c[0]); }
852         return(d3 && SameDomainName(d3, mmc));
853         }
854
855 #endif /* NO_SECURITYFRAMEWORK */
856
857 mDNSlocal void tcpKQSocketCallback(__unused int fd, short filter, void *context)
858         {
859         TCPSocket *sock = context;
860         sock->err = mStatus_NoError;
861
862         //if (filter == EVFILT_READ ) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_READ", filter);
863         //if (filter == EVFILT_WRITE) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_WRITE", filter);
864         // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it here with EV_DELETE
865         if (filter == EVFILT_WRITE) KQueueSet(sock->fd, EV_DELETE, EVFILT_WRITE, &sock->kqEntry);
866
867         if (sock->flags & kTCPSocketFlags_UseTLS)
868                 {
869 #ifndef NO_SECURITYFRAMEWORK
870                 if (!sock->setup) { sock->setup = mDNStrue; tlsSetupSock(sock, mDNSfalse); }
871                 
872                 if (sock->handshake == handshake_required) { if (spawnSSLHandshake(sock) == 0) return; }
873                 else if (sock->handshake == handshake_in_progress || sock->handshake == handshake_to_be_closed) return;
874                 else if (sock->handshake != handshake_completed)
875                         {
876                         if (!sock->err) sock->err = mStatus_UnknownErr;
877                         LogMsg("tcpKQSocketCallback called with unexpected SSLHandshake status: %d", sock->handshake);
878                         }
879 #else
880                 sock->err = mStatus_UnsupportedErr;
881 #endif /* NO_SECURITYFRAMEWORK */
882                 }
883         
884         doTcpSocketCallback(sock);
885         }
886
887 mDNSexport int KQueueSet(int fd, u_short flags, short filter, const KQueueEntry *const entryRef)
888         {
889         struct kevent new_event;
890         EV_SET(&new_event, fd, filter, flags, 0, 0, (void*)entryRef);
891         return (kevent(KQueueFD, &new_event, 1, NULL, 0, NULL) < 0) ? errno : 0;
892         }
893
894 mDNSexport void KQueueLock(mDNS *const m)
895         {
896         pthread_mutex_lock(&m->p->BigMutex);
897         m->p->BigMutexStartTime = mDNSPlatformRawTime();
898         }
899
900 mDNSexport void KQueueUnlock(mDNS *const m, const char const *task)
901         {
902         mDNSs32 end = mDNSPlatformRawTime();
903         (void)task;
904         if (end - m->p->BigMutexStartTime >= WatchDogReportingThreshold)
905                 LogInfo("WARNING: %s took %dms to complete", task, end - m->p->BigMutexStartTime);
906
907         pthread_mutex_unlock(&m->p->BigMutex);
908
909         char wake = 1;
910         if (send(m->p->WakeKQueueLoopFD, &wake, sizeof(wake), 0) == -1)
911                 LogMsg("ERROR: KQueueWake: send failed with error code: %d (%s)", errno, strerror(errno));
912         }
913
914 mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags, mDNSIPPort *port)
915         {
916         (void) m;
917
918         TCPSocket *sock = mallocL("TCPSocket/mDNSPlatformTCPSocket", sizeof(TCPSocket));
919         if (!sock) { LogMsg("mDNSPlatformTCPSocket: memory allocation failure"); return(mDNSNULL); }
920
921         mDNSPlatformMemZero(sock, sizeof(TCPSocket));
922         sock->callback          = mDNSNULL;
923         sock->fd                = socket(AF_INET, SOCK_STREAM, 0);
924         sock->kqEntry.KQcallback= tcpKQSocketCallback;
925         sock->kqEntry.KQcontext = sock;
926         sock->kqEntry.KQtask    = "mDNSPlatformTCPSocket";
927         sock->flags             = flags;
928         sock->context           = mDNSNULL;
929         sock->setup             = mDNSfalse;
930         sock->connected         = mDNSfalse;
931         sock->handshake         = handshake_required;
932         sock->m                 = m;
933         sock->err               = mStatus_NoError;
934         
935         if (sock->fd == -1)
936                 {
937                 LogMsg("mDNSPlatformTCPSocket: socket error %d errno %d (%s)", sock->fd, errno, strerror(errno));
938                 freeL("TCPSocket/mDNSPlatformTCPSocket", sock);
939                 return(mDNSNULL);
940                 }
941
942         // Bind it
943         struct sockaddr_in addr;
944         mDNSPlatformMemZero(&addr, sizeof(addr));
945         addr.sin_family = AF_INET;
946         addr.sin_addr.s_addr = htonl(INADDR_ANY);
947         addr.sin_port = port->NotAnInteger;
948         if (bind(sock->fd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
949                 { LogMsg("ERROR: bind %s", strerror(errno)); goto error; }
950
951         // Receive interface identifiers
952         const int on = 1;  // "on" for setsockopt
953         if (setsockopt(sock->fd, IPPROTO_IP, IP_RECVIF, &on, sizeof(on)) < 0)
954                 { LogMsg("setsockopt IP_RECVIF - %s", strerror(errno)); goto error; }
955
956         mDNSPlatformMemZero(&addr, sizeof(addr));
957         socklen_t len = sizeof(addr);
958         if (getsockname(sock->fd, (struct sockaddr*) &addr, &len) < 0)
959                 { LogMsg("getsockname - %s", strerror(errno)); goto error; }
960
961         port->NotAnInteger = addr.sin_port;
962         return sock;
963
964 error:
965         close(sock->fd);
966         freeL("TCPSocket/mDNSPlatformTCPSocket", sock);
967         return(mDNSNULL);
968         }
969
970 mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, mDNSInterfaceID InterfaceID,
971                                           TCPConnectionCallback callback, void *context)
972         {
973         struct sockaddr_in saddr;
974         mStatus err = mStatus_NoError;
975
976         sock->callback          = callback;
977         sock->context           = context;
978         sock->setup             = mDNSfalse;
979         sock->connected         = mDNSfalse;
980         sock->handshake         = handshake_required;
981         sock->err               = mStatus_NoError;
982
983         (void) InterfaceID;     //!!!KRS use this if non-zero!!!
984
985         if (dst->type != mDNSAddrType_IPv4)
986                 {
987                 LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: opperation not supported");
988                 return mStatus_UnknownErr;
989                 }
990
991         mDNSPlatformMemZero(&saddr, sizeof(saddr));
992         saddr.sin_family      = AF_INET;
993         saddr.sin_port        = dstport.NotAnInteger;
994         saddr.sin_len         = sizeof(saddr);
995         saddr.sin_addr.s_addr = dst->ip.v4.NotAnInteger;
996
997         sock->kqEntry.KQcallback = tcpKQSocketCallback;
998         sock->kqEntry.KQcontext  = sock;
999         sock->kqEntry.KQtask     = "Outgoing TCP";
1000
1001         // Watch for connect complete (write is ready)
1002         // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it in tcpKQSocketCallback using EV_DELETE
1003         if (KQueueSet(sock->fd, EV_ADD /* | EV_ONESHOT */, EVFILT_WRITE, &sock->kqEntry))
1004                 {
1005                 LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
1006                 close(sock->fd);
1007                 return errno;
1008                 }
1009
1010         // Watch for incoming data
1011         if (KQueueSet(sock->fd, EV_ADD, EVFILT_READ, &sock->kqEntry))
1012                 {
1013                 LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
1014                 close(sock->fd); // Closing the descriptor removes all filters from the kqueue
1015                 return errno;
1016                 }
1017
1018         if (fcntl(sock->fd, F_SETFL, fcntl(sock->fd, F_GETFL, 0) | O_NONBLOCK) < 0) // set non-blocking
1019                 {
1020                 LogMsg("ERROR: setsockopt O_NONBLOCK - %s", strerror(errno));
1021                 return mStatus_UnknownErr;
1022                 }
1023
1024         // initiate connection wth peer
1025         if (connect(sock->fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
1026                 {
1027                 if (errno == EINPROGRESS) return mStatus_ConnPending;
1028                 if (errno == EHOSTUNREACH || errno == EADDRNOTAVAIL || errno == ENETDOWN)
1029                         LogInfo("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s)", sock->fd, errno, strerror(errno));
1030                 else
1031                         LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s)", sock->fd, errno, strerror(errno));
1032                 close(sock->fd);
1033                 return mStatus_ConnFailed;
1034                 }
1035
1036         LogMsg("NOTE: mDNSPlatformTCPConnect completed synchronously");
1037         // kQueue should notify us, but this LogMsg is to help track down if it doesn't
1038         return err;
1039         }
1040
1041 // Why doesn't mDNSPlatformTCPAccept actually call accept() ?
1042 mDNSexport TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int fd)
1043         {
1044         mStatus err = mStatus_NoError;
1045
1046         TCPSocket *sock = mallocL("TCPSocket/mDNSPlatformTCPAccept", sizeof(TCPSocket));
1047         if (!sock) return(mDNSNULL);
1048
1049         mDNSPlatformMemZero(sock, sizeof(*sock));
1050         sock->fd = fd;
1051         sock->flags = flags;
1052
1053         if (flags & kTCPSocketFlags_UseTLS)
1054                 {
1055 #ifndef NO_SECURITYFRAMEWORK
1056                 if (!ServerCerts) { LogMsg("ERROR: mDNSPlatformTCPAccept: unable to find TLS certificates"); err = mStatus_UnknownErr; goto exit; }
1057
1058                 err = tlsSetupSock(sock, mDNStrue);
1059                 if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: tlsSetupSock failed with error code: %d", err); goto exit; }
1060
1061                 err = SSLSetCertificate(sock->tlsContext, ServerCerts);
1062                 if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: SSLSetCertificate failed with error code: %d", err); goto exit; }
1063 #else
1064                 err = mStatus_UnsupportedErr;
1065 #endif /* NO_SECURITYFRAMEWORK */
1066                 }
1067 #ifndef NO_SECURITYFRAMEWORK
1068 exit:
1069 #endif
1070
1071         if (err) { freeL("TCPSocket/mDNSPlatformTCPAccept", sock); return(mDNSNULL); }
1072         return(sock);
1073         }
1074
1075 mDNSexport void mDNSPlatformTCPCloseConnection(TCPSocket *sock)
1076         {
1077         if (sock)
1078                 {       
1079 #ifndef NO_SECURITYFRAMEWORK
1080                 if (sock->tlsContext)
1081                         {
1082                         if (sock->handshake == handshake_in_progress) // SSLHandshake thread using this sock (esp. tlsContext)
1083                                 {
1084                                 LogInfo("mDNSPlatformTCPCloseConnection: called while handshake in progress");
1085                                 sock->handshake = handshake_to_be_closed;
1086                                 }
1087                         if (sock->handshake == handshake_to_be_closed)
1088                                 return;
1089
1090                         SSLClose(sock->tlsContext);
1091                         SSLDisposeContext(sock->tlsContext);
1092                         sock->tlsContext = NULL;
1093                         }
1094 #endif /* NO_SECURITYFRAMEWORK */
1095                 if (sock->fd != -1)
1096                         {
1097                         shutdown(sock->fd, 2);
1098                         close(sock->fd);
1099                         sock->fd = -1;
1100                         }
1101
1102                 freeL("TCPSocket/mDNSPlatformTCPCloseConnection", sock);
1103                 }
1104         }
1105
1106 mDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed)
1107         {
1108         long nread = 0;
1109         *closed = mDNSfalse;
1110
1111         if (sock->flags & kTCPSocketFlags_UseTLS)
1112                 {
1113 #ifndef NO_SECURITYFRAMEWORK
1114                 if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformReadTCP called while handshake required"); return 0; }
1115                 else if (sock->handshake == handshake_in_progress) return 0;
1116                 else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformReadTCP called with unexpected SSLHandshake status: %d", sock->handshake);
1117
1118                 //LogMsg("Starting SSLRead %d %X", sock->fd, fcntl(sock->fd, F_GETFL, 0));
1119                 mStatus err = SSLRead(sock->tlsContext, buf, buflen, (size_t*)&nread);
1120                 //LogMsg("SSLRead returned %d (%d) nread %d buflen %d", err, errSSLWouldBlock, nread, buflen);
1121                 if (err == errSSLClosedGraceful) { nread = 0; *closed = mDNStrue; }
1122                 else if (err && err != errSSLWouldBlock)
1123                         { LogMsg("ERROR: mDNSPlatformReadTCP - SSLRead: %d", err); nread = -1; *closed = mDNStrue; }
1124 #else
1125                 nread = -1;
1126                 *closed = mDNStrue;
1127 #endif /* NO_SECURITYFRAMEWORK */
1128                 }
1129         else
1130                 {
1131                 static int CLOSEDcount = 0;
1132                 static int EAGAINcount = 0;
1133                 nread = recv(sock->fd, buf, buflen, 0);
1134
1135                 if (nread > 0) { CLOSEDcount = 0; EAGAINcount = 0; } // On success, clear our error counters
1136                 else if (nread == 0)
1137                         {
1138                         *closed = mDNStrue;
1139                         if ((++CLOSEDcount % 1000) == 0) { LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got CLOSED %d times", sock->fd, CLOSEDcount); sleep(1); }
1140                         }
1141                 // else nread is negative -- see what kind of error we got
1142                 else if (errno == ECONNRESET) { nread = 0; *closed = mDNStrue; }
1143                 else if (errno != EAGAIN) { LogMsg("ERROR: mDNSPlatformReadTCP - recv: %d (%s)", errno, strerror(errno)); nread = -1; }
1144                 else // errno is EAGAIN (EWOULDBLOCK) -- no data available
1145                         {
1146                         nread = 0;
1147                         if ((++EAGAINcount % 1000) == 0) { LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got EAGAIN %d times", sock->fd, EAGAINcount); sleep(1); }
1148                         }
1149                 }
1150
1151         return nread;
1152         }
1153
1154 mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len)
1155         {
1156         int nsent;
1157
1158         if (sock->flags & kTCPSocketFlags_UseTLS)
1159                 {
1160 #ifndef NO_SECURITYFRAMEWORK
1161                 size_t  processed;
1162                 if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformWriteTCP called while handshake required"); return 0; }
1163                 if (sock->handshake == handshake_in_progress) return 0;
1164                 else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformWriteTCP called with unexpected SSLHandshake status: %d", sock->handshake);
1165                 
1166                 mStatus err = SSLWrite(sock->tlsContext, msg, len, &processed);
1167
1168                 if (!err) nsent = (int) processed;
1169                 else if (err == errSSLWouldBlock) nsent = 0;
1170                 else { LogMsg("ERROR: mDNSPlatformWriteTCP - SSLWrite returned %d", err); nsent = -1; }
1171 #else
1172                 nsent = -1;
1173 #endif /* NO_SECURITYFRAMEWORK */
1174                 }
1175         else
1176                 {
1177                 nsent = send(sock->fd, msg, len, 0);
1178                 if (nsent < 0)
1179                         {
1180                         if (errno == EAGAIN) nsent = 0;
1181                         else { LogMsg("ERROR: mDNSPlatformWriteTCP - send %s", strerror(errno)); nsent = -1; }
1182                         }
1183                 }
1184
1185         return nsent;
1186         }
1187
1188 mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
1189         {
1190         return sock->fd;
1191         }
1192
1193 // If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
1194 // If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
1195 mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa_family, mDNSIPPort *const outport)
1196         {
1197 #ifndef NO_IPV6
1198         int         *s        = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
1199         KQueueEntry     *k        = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
1200 #else
1201         int         *s        = &cp->sktv4;
1202         KQueueEntry     *k        = &cp->kqsv4;
1203 #endif
1204         const int on = 1;
1205         const int twofivefive = 255;
1206         mStatus err = mStatus_NoError;
1207         char *errstr = mDNSNULL;
1208
1209 #ifdef NO_IPV6
1210         if (sa_family != AF_INET) return -1;
1211 #endif
1212         
1213         cp->closeFlag = mDNSNULL;
1214
1215         int skt = socket(sa_family, SOCK_DGRAM, IPPROTO_UDP);
1216         if (skt < 3) { if (errno != EAFNOSUPPORT) LogMsg("SetupSocket: socket error %d errno %d (%s)", skt, errno, strerror(errno)); return(skt); }
1217
1218         // ... with a shared UDP port, if it's for multicast receiving
1219         if (mDNSSameIPPort(port, MulticastDNSPort) || mDNSSameIPPort(port, NATPMPAnnouncementPort)) err = setsockopt(skt, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
1220         if (err < 0) { errstr = "setsockopt - SO_REUSEPORT"; goto fail; }
1221
1222         if (sa_family == AF_INET)
1223                 {
1224                 // We want to receive destination addresses
1225                 err = setsockopt(skt, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
1226                 if (err < 0) { errstr = "setsockopt - IP_RECVDSTADDR"; goto fail; }
1227
1228                 // We want to receive interface identifiers
1229                 err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
1230                 if (err < 0) { errstr = "setsockopt - IP_RECVIF"; goto fail; }
1231
1232                 // We want to receive packet TTL value so we can check it
1233                 err = setsockopt(skt, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
1234                 // We ignore errors here -- we already know Jaguar doesn't support this, but we can get by without it
1235
1236                 // Send unicast packets with TTL 255
1237                 err = setsockopt(skt, IPPROTO_IP, IP_TTL, &twofivefive, sizeof(twofivefive));
1238                 if (err < 0) { errstr = "setsockopt - IP_TTL"; goto fail; }
1239
1240                 // And multicast packets with TTL 255 too
1241                 err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_TTL, &twofivefive, sizeof(twofivefive));
1242                 if (err < 0) { errstr = "setsockopt - IP_MULTICAST_TTL"; goto fail; }
1243
1244                 // And start listening for packets
1245                 struct sockaddr_in listening_sockaddr;
1246                 listening_sockaddr.sin_family      = AF_INET;
1247                 listening_sockaddr.sin_port        = port.NotAnInteger;         // Pass in opaque ID without any byte swapping
1248                 listening_sockaddr.sin_addr.s_addr = mDNSSameIPPort(port, NATPMPAnnouncementPort) ? AllSystemsMcast.NotAnInteger : 0;
1249                 err = bind(skt, (struct sockaddr *) &listening_sockaddr, sizeof(listening_sockaddr));
1250                 if (err) { errstr = "bind"; goto fail; }
1251                 if (outport) outport->NotAnInteger = listening_sockaddr.sin_port;
1252                 }
1253 #ifndef NO_IPV6
1254         else if (sa_family == AF_INET6)
1255                 {
1256                 // NAT-PMP Announcements make no sense on IPv6, so bail early w/o error
1257                 if (mDNSSameIPPort(port, NATPMPAnnouncementPort)) { if (outport) *outport = zeroIPPort; return mStatus_NoError; }
1258                 
1259                 // We want to receive destination addresses and receive interface identifiers
1260                 err = setsockopt(skt, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on));
1261                 if (err < 0) { errstr = "setsockopt - IPV6_PKTINFO"; goto fail; }
1262
1263                 // We want to receive packet hop count value so we can check it
1264                 err = setsockopt(skt, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));
1265                 if (err < 0) { errstr = "setsockopt - IPV6_HOPLIMIT"; goto fail; }
1266
1267                 // We want to receive only IPv6 packets. Without this option we get IPv4 packets too,
1268                 // with mapped addresses of the form 0:0:0:0:0:FFFF:xxxx:xxxx, where xxxx:xxxx is the IPv4 address
1269                 err = setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
1270                 if (err < 0) { errstr = "setsockopt - IPV6_V6ONLY"; goto fail; }
1271
1272                 // Send unicast packets with TTL 255
1273                 err = setsockopt(skt, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &twofivefive, sizeof(twofivefive));
1274                 if (err < 0) { errstr = "setsockopt - IPV6_UNICAST_HOPS"; goto fail; }
1275
1276                 // And multicast packets with TTL 255 too
1277                 err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &twofivefive, sizeof(twofivefive));
1278                 if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_HOPS"; goto fail; }
1279
1280                 // Want to receive our own packets
1281                 err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &on, sizeof(on));
1282                 if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_LOOP"; goto fail; }
1283
1284                 // And start listening for packets
1285                 struct sockaddr_in6 listening_sockaddr6;
1286                 mDNSPlatformMemZero(&listening_sockaddr6, sizeof(listening_sockaddr6));
1287                 listening_sockaddr6.sin6_len         = sizeof(listening_sockaddr6);
1288                 listening_sockaddr6.sin6_family      = AF_INET6;
1289                 listening_sockaddr6.sin6_port        = port.NotAnInteger;               // Pass in opaque ID without any byte swapping
1290                 listening_sockaddr6.sin6_flowinfo    = 0;
1291                 listening_sockaddr6.sin6_addr        = in6addr_any; // Want to receive multicasts AND unicasts on this socket
1292                 listening_sockaddr6.sin6_scope_id    = 0;
1293                 err = bind(skt, (struct sockaddr *) &listening_sockaddr6, sizeof(listening_sockaddr6));
1294                 if (err) { errstr = "bind"; goto fail; }
1295                 if (outport) outport->NotAnInteger = listening_sockaddr6.sin6_port;
1296                 }
1297 #endif
1298
1299         fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
1300         fcntl(skt, F_SETFD, 1); // set close-on-exec
1301         *s = skt;
1302         k->KQcallback = myKQSocketCallBack;
1303         k->KQcontext  = cp;
1304         k->KQtask     = "UDP packet reception";
1305         KQueueSet(*s, EV_ADD, EVFILT_READ, k);
1306
1307         return(err);
1308
1309         fail:
1310         // For "bind" failures, only write log messages for our shared mDNS port, or for binding to zero
1311         if (strcmp(errstr, "bind") || mDNSSameIPPort(port, MulticastDNSPort) || mDNSIPPortIsZero(port))
1312                 LogMsg("%s skt %d port %d error %d errno %d (%s)", errstr, skt, mDNSVal16(port), err, errno, strerror(errno));
1313
1314         // If we got a "bind" failure of EADDRINUSE, inform the caller as it might need to try another random port
1315         if (!strcmp(errstr, "bind") && errno == EADDRINUSE)
1316                 {
1317                 err = EADDRINUSE;
1318                 if (mDNSSameIPPort(port, MulticastDNSPort))
1319                         NotifyOfElusiveBug("Setsockopt SO_REUSEPORT failed",
1320                                 "Congratulations, you've reproduced an elusive bug.\r"
1321                                 "Please contact the current assignee of <rdar://problem/3814904>.\r"
1322                                 "Alternatively, you can send email to radar-3387020@group.apple.com. (Note number is different.)\r"
1323                                 "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
1324                 }
1325
1326         close(skt);
1327         return(err);
1328         }
1329
1330 mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
1331         {
1332         mStatus err;
1333         mDNSIPPort port = requestedport;
1334         mDNSBool randomizePort = mDNSIPPortIsZero(requestedport);
1335         int i = 10000; // Try at most 10000 times to get a unique random port
1336         UDPSocket *p = mallocL("UDPSocket", sizeof(UDPSocket));
1337         if (!p) { LogMsg("mDNSPlatformUDPSocket: memory exhausted"); return(mDNSNULL); }
1338         mDNSPlatformMemZero(p, sizeof(UDPSocket));
1339         p->ss.port  = zeroIPPort;
1340         p->ss.m     = m;
1341         p->ss.sktv4 = -1;
1342 #ifndef NO_IPV6
1343         p->ss.sktv6 = -1;
1344 #endif
1345
1346         do
1347                 {
1348                 // The kernel doesn't do cryptographically strong random port allocation, so we do it ourselves here
1349                 if (randomizePort) port = mDNSOpaque16fromIntVal(0xC000 + mDNSRandom(0x3FFF));
1350                 err = SetupSocket(&p->ss, port, AF_INET, &p->ss.port);
1351 #ifndef NO_IPV6
1352                 if (!err)
1353                         {
1354                         err = SetupSocket(&p->ss, port, AF_INET6, &p->ss.port);
1355                         if (err) { close(p->ss.sktv4); p->ss.sktv4 = -1; }
1356                         }
1357 #endif
1358                 i--;
1359                 } while (err == EADDRINUSE && randomizePort && i);
1360
1361         if (err)
1362                 {
1363                 // In customer builds we don't want to log failures with port 5351, because this is a known issue
1364                 // of failing to bind to this port when Internet Sharing has already bound to it
1365                 // We also don't want to log about port 5350, due to a known bug when some other
1366                 // process is bound to it.
1367                 if (mDNSSameIPPort(requestedport, NATPMPPort) || mDNSSameIPPort(requestedport, NATPMPAnnouncementPort))
1368                         LogInfo("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
1369                 else LogMsg("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
1370                 freeL("UDPSocket", p);
1371                 return(mDNSNULL);
1372                 }
1373         return(p);
1374         }
1375
1376 mDNSlocal void CloseSocketSet(KQSocketSet *ss)
1377         {
1378         if (ss->sktv4 != -1)
1379                 {
1380                 close(ss->sktv4);
1381                 ss->sktv4 = -1;
1382                 }
1383 #ifndef NO_IPV6
1384         if (ss->sktv6 != -1)
1385                 {
1386                 close(ss->sktv6);
1387                 ss->sktv6 = -1;
1388                 }
1389 #endif
1390         if (ss->closeFlag) *ss->closeFlag = 1;
1391         }
1392
1393 mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock)
1394         {
1395         CloseSocketSet(&sock->ss);
1396         freeL("UDPSocket", sock);
1397         }
1398
1399 #if COMPILER_LIKES_PRAGMA_MARK
1400 #pragma mark -
1401 #pragma mark - BPF Raw packet sending/receiving
1402 #endif
1403
1404 #if APPLE_OSX_mDNSResponder
1405
1406 mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
1407         {
1408         if (!InterfaceID) { LogMsg("mDNSPlatformSendRawPacket: No InterfaceID specified"); return; }
1409         NetworkInterfaceInfoOSX *info;
1410
1411         extern mDNS mDNSStorage;
1412         info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
1413         if (info == NULL)
1414                 {
1415                 LogMsg("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
1416                 return;
1417                 }
1418         if (info->BPF_fd < 0)
1419                 LogMsg("mDNSPlatformSendRawPacket: %s BPF_fd %d not ready", info->ifinfo.ifname, info->BPF_fd);
1420         else
1421                 {
1422                 //LogMsg("mDNSPlatformSendRawPacket %d bytes on %s", end - (mDNSu8 *)msg, info->ifinfo.ifname);
1423                 if (write(info->BPF_fd, msg, end - (mDNSu8 *)msg) < 0)
1424                         LogMsg("mDNSPlatformSendRawPacket: BPF write(%d) failed %d (%s)", info->BPF_fd, errno, strerror(errno));
1425                 }
1426         }
1427
1428 mDNSexport void mDNSPlatformSetLocalARP(const mDNSv4Addr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
1429         {
1430         if (!InterfaceID) { LogMsg("mDNSPlatformSetLocalARP: No InterfaceID specified"); return; }
1431         NetworkInterfaceInfoOSX *info;
1432         extern mDNS mDNSStorage;
1433         info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
1434         if (info == NULL)
1435                 {
1436                 LogMsg("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
1437                 return;
1438                 }
1439         // Manually inject an entry into our local ARP cache.
1440         // (We can't do this by sending an ARP broadcast, because the kernel only pays attention to incoming ARP packets, not outgoing.)
1441         mDNSBool makearp = mDNSv4AddressIsLinkLocal(tpa);
1442         if (!makearp)
1443                 {
1444                 NetworkInterfaceInfoOSX *i;
1445                 for (i = info->m->p->InterfaceList; i; i = i->next)
1446                         if (i->Exists && i->ifinfo.InterfaceID == InterfaceID && i->ifinfo.ip.type == mDNSAddrType_IPv4)
1447                                 if (((i->ifinfo.ip.ip.v4.NotAnInteger ^ tpa->NotAnInteger) & i->ifinfo.mask.ip.v4.NotAnInteger) == 0)
1448                                         makearp = mDNStrue;
1449                 }
1450         if (!makearp)
1451                 LogInfo("Don't need ARP entry for %s %.4a %.6a",            info->ifinfo.ifname, tpa, tha);
1452         else
1453                 {
1454                 int result = mDNSSetARP(info->scope_id, tpa->b, tha->b);
1455                 if (result) LogMsg("Set local ARP entry for %s %.4a %.6a failed: %d", info->ifinfo.ifname, tpa, tha, result);
1456                 else debugf       ("Set local ARP entry for %s %.4a %.6a",            info->ifinfo.ifname, tpa, tha);
1457                 }
1458         }
1459
1460 mDNSlocal void CloseBPF(NetworkInterfaceInfoOSX *const i)
1461         {
1462         LogSPS("%s closing BPF fd %d", i->ifinfo.ifname, i->BPF_fd);
1463
1464         // Note: MUST NOT close() the underlying native BSD sockets.
1465         // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately, because
1466         // it first has to unhook the sockets from its select() call on its other thread, before it can safely close them.
1467         CFRunLoopRemoveSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode);
1468         CFRelease(i->BPF_rls);
1469         CFSocketInvalidate(i->BPF_cfs);
1470         CFRelease(i->BPF_cfs);
1471         i->BPF_fd = -1;
1472         }
1473
1474 mDNSlocal void bpf_callback(const CFSocketRef cfs, const CFSocketCallBackType CallBackType, const CFDataRef address, const void *const data, void *const context)
1475         {
1476         (void)cfs;
1477         (void)CallBackType;
1478         (void)address;
1479         (void)data;
1480
1481         NetworkInterfaceInfoOSX *const info = (NetworkInterfaceInfoOSX *)context;
1482         KQueueLock(info->m);
1483
1484         // Now we've got the lock, make sure the kqueue thread didn't close the fd out from under us (will not be a problem once the OS X
1485         // kernel has a mechanism for dispatching all events to a single thread, but for now we have to guard against this race condition).
1486         if (info->BPF_fd < 0) goto exit;
1487
1488         ssize_t n = read(info->BPF_fd, &info->m->imsg, info->BPF_len);
1489         const mDNSu8 *ptr = (const mDNSu8 *)&info->m->imsg;
1490         const mDNSu8 *end = (const mDNSu8 *)&info->m->imsg + n;
1491         debugf("%3d: bpf_callback got %d bytes on %s", info->BPF_fd, n, info->ifinfo.ifname);
1492
1493         if (n<0)
1494                 {
1495                 LogMsg("Closing %s BPF fd %d due to error %d (%s)", info->ifinfo.ifname, info->BPF_fd, errno, strerror(errno));
1496                 CloseBPF(info);
1497                 goto exit;
1498                 }
1499
1500         while (ptr < end)
1501                 {
1502                 const struct bpf_hdr *bh = (const struct bpf_hdr *)ptr;
1503                 debugf("%3d: bpf_callback bh_caplen %4d bh_datalen %4d remaining %4d", info->BPF_fd, bh->bh_caplen, bh->bh_datalen, end - (ptr + BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen)));
1504                 mDNSCoreReceiveRawPacket(info->m, ptr + bh->bh_hdrlen, ptr + bh->bh_hdrlen + bh->bh_caplen, info->ifinfo.InterfaceID);
1505                 ptr += BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen);
1506                 }
1507 exit:
1508         KQueueUnlock(info->m, "bpf_callback");
1509         }
1510
1511 #define BPF_SetOffset(from, cond, to) (from)->cond = (to) - 1 - (from)
1512
1513 mDNSlocal int CountProxyTargets(mDNS *const m, NetworkInterfaceInfoOSX *x, int *p4, int *p6)
1514         {
1515         int numv4 = 0, numv6 = 0;
1516         AuthRecord *rr;
1517
1518         for (rr = m->ResourceRecords; rr; rr=rr->next)
1519                 if (rr->resrec.InterfaceID == x->ifinfo.InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4)
1520                         {
1521                         if (p4) LogSPS("CountProxyTargets: fd %d %-7s IP%2d %.4a", x->BPF_fd, x->ifinfo.ifname, numv4, &rr->AddressProxy.ip.v4);
1522                         numv4++;
1523                         }
1524
1525         for (rr = m->ResourceRecords; rr; rr=rr->next)
1526                 if (rr->resrec.InterfaceID == x->ifinfo.InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv6)
1527                         {
1528                         if (p6) LogSPS("CountProxyTargets: fd %d %-7s IP%2d %.16a", x->BPF_fd, x->ifinfo.ifname, numv6, &rr->AddressProxy.ip.v6);
1529                         numv6++;
1530                         }
1531
1532         if (p4) *p4 = numv4;
1533         if (p6) *p6 = numv6;
1534         return(numv4 + numv6);
1535         }
1536
1537 mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
1538         {
1539         NetworkInterfaceInfoOSX *x;
1540
1541         //NOTE: We can't use IfIndexToInterfaceInfoOSX because that looks for Registered also.
1542         for (x = m->p->InterfaceList; x; x = x->next) if (x->ifinfo.InterfaceID == InterfaceID) break;
1543
1544         if (!x) { LogMsg("mDNSPlatformUpdateProxyList: ERROR InterfaceID %p not found", InterfaceID); return; }
1545
1546         #define MAX_BPF_ADDRS 250
1547         int numv4 = 0, numv6 = 0;
1548
1549         if (CountProxyTargets(m, x, &numv4, &numv6) > MAX_BPF_ADDRS)
1550                 {
1551                 LogMsg("mDNSPlatformUpdateProxyList: ERROR Too many address proxy records v4 %d v6 %d", numv4, numv6);
1552                 if (numv4 > MAX_BPF_ADDRS) numv4 = MAX_BPF_ADDRS;
1553                 numv6 = MAX_BPF_ADDRS - numv4;
1554                 }
1555
1556         LogSPS("mDNSPlatformUpdateProxyList: fd %d %-7s MAC  %.6a %d v4 %d v6", x->BPF_fd, x->ifinfo.ifname, &x->ifinfo.MAC, numv4, numv6);
1557
1558         // Caution: This is a static structure, so we need to be careful that any modifications we make to it
1559         // are done in such a way that they work correctly when mDNSPlatformUpdateProxyList is called multiple times
1560         static struct bpf_insn filter[17 + MAX_BPF_ADDRS] =
1561                 {
1562                 BPF_STMT(BPF_LD  + BPF_H   + BPF_ABS, 12),                              // 0 Read Ethertype (bytes 12,13)
1563
1564                 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0806, 0, 1),              // 1 If Ethertype == ARP goto next, else 3
1565                 BPF_STMT(BPF_RET + BPF_K,             42),                              // 2 Return 42-byte ARP
1566
1567                 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0800, 4, 0),              // 3 If Ethertype == IPv4 goto 8 (IPv4 address list check) else next
1568
1569                 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x86DD, 0, 9),              // 4 If Ethertype == IPv6 goto next, else exit
1570                 BPF_STMT(BPF_LD  + BPF_H   + BPF_ABS, 20),                              // 5 Read Protocol and Hop Limit (bytes 20,21)
1571                 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x3AFF, 0, 9),              // 6 If (Prot,TTL) == (3A,FF) goto next, else IPv6 address list check
1572                 BPF_STMT(BPF_RET + BPF_K,             78),                              // 7 Return 78-byte ND
1573
1574                 // Is IPv4 packet; check if it's addressed to any IPv4 address we're proxying for
1575                 BPF_STMT(BPF_LD  + BPF_W   + BPF_ABS, 30),                              // 8 Read IPv4 Dst (bytes 30,31,32,33)
1576                 };
1577
1578         struct bpf_insn *pc   = &filter[9];
1579         struct bpf_insn *chk6 = pc   + numv4 + 1;       // numv4 address checks, plus a "return 0"
1580         struct bpf_insn *fail = chk6 + 1 + numv6;       // Get v6 Dst LSW, plus numv6 address checks
1581         struct bpf_insn *ret4 = fail + 1;
1582         struct bpf_insn *ret6 = ret4 + 4;
1583
1584         static const struct bpf_insn rf  = BPF_STMT(BPF_RET + BPF_K, 0);                                // No match: Return nothing
1585
1586         static const struct bpf_insn g6  = BPF_STMT(BPF_LD  + BPF_W   + BPF_ABS, 50);   // Read IPv6 Dst LSW (bytes 50,51,52,53)
1587
1588         static const struct bpf_insn r4a = BPF_STMT(BPF_LDX + BPF_B   + BPF_MSH, 14);   // Get IP Header length (normally 20)
1589         static const struct bpf_insn r4b = BPF_STMT(BPF_LD  + BPF_IMM,           54);   // A = 54 (14-byte Ethernet plus 20-byte TCP + 20 bytes spare)
1590         static const struct bpf_insn r4c = BPF_STMT(BPF_ALU + BPF_ADD + BPF_X,    0);   // A += IP Header length
1591         static const struct bpf_insn r4d = BPF_STMT(BPF_RET + BPF_A, 0);                                // Success: Return Ethernet + IP + TCP + 20 bytes spare (normally 74)
1592
1593         static const struct bpf_insn r6a = BPF_STMT(BPF_RET + BPF_K, 94);                               // Success: Return Eth + IPv6 + TCP + 20 bytes spare
1594
1595         BPF_SetOffset(&filter[4], jf, fail);    // If Ethertype not ARP, IPv4, or IPv6, fail
1596         BPF_SetOffset(&filter[6], jf, chk6);    // If IPv6 but not ICMPv6, go to IPv6 address list check
1597
1598         // BPF Byte-Order Note
1599         // The BPF API designers apparently thought that programmers would not be smart enough to use htons
1600         // and htonl correctly to convert numeric values to network byte order on little-endian machines,
1601         // so instead they chose to make the API implicitly byte-swap *ALL* values, even literal byte strings
1602         // that shouldn't be byte-swapped, like ASCII text, Ethernet addresses, IP addresses, etc.
1603         // As a result, if we put Ethernet addresses and IP addresses in the right byte order, the BPF API
1604         // will byte-swap and make them backwards, and then our filter won't work. So, we have to arrange
1605         // that on little-endian machines we deliberately put addresses in memory with the bytes backwards,
1606         // so that when the BPF API goes through and swaps them all, they end up back as they should be.
1607         // In summary, if we byte-swap all the non-numeric fields that shouldn't be swapped, and we *don't*
1608         // swap any of the numeric values that *should* be byte-swapped, then the filter will work correctly.
1609
1610         // IPSEC capture size notes:
1611         //  8 bytes UDP header
1612         //  4 bytes Non-ESP Marker
1613         // 28 bytes IKE Header
1614         // --
1615         // 40 Total. Capturing TCP Header + 20 gets us enough bytes to receive the IKE Header in a UDP-encapsulated IKE packet.
1616
1617         AuthRecord *rr;
1618         for (rr = m->ResourceRecords; rr; rr=rr->next)
1619                 if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4)
1620                         {
1621                         mDNSv4Addr a = rr->AddressProxy.ip.v4;
1622                         pc->code = BPF_JMP + BPF_JEQ + BPF_K;
1623                         BPF_SetOffset(pc, jt, ret4);
1624                         pc->jf   = 0;
1625                         pc->k    = (bpf_u_int32)a.b[0] << 24 | (bpf_u_int32)a.b[1] << 16 | (bpf_u_int32)a.b[2] << 8 | (bpf_u_int32)a.b[3];
1626                         pc++;
1627                         }
1628         *pc++ = rf;
1629
1630         if (pc != chk6) LogMsg("mDNSPlatformUpdateProxyList: pc %p != chk6 %p", pc, chk6);
1631         *pc++ = g6;     // chk6 points here
1632
1633         for (rr = m->ResourceRecords; rr; rr=rr->next)
1634                 if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv6)
1635                         {
1636                         mDNSv6Addr a = rr->AddressProxy.ip.v6;
1637                         pc->code = BPF_JMP + BPF_JEQ + BPF_K;
1638                         BPF_SetOffset(pc, jt, ret6);
1639                         pc->jf   = 0;
1640                         pc->k    = (bpf_u_int32)a.b[12] << 24 | (bpf_u_int32)a.b[13] << 16 | (bpf_u_int32)a.b[14] << 8 | (bpf_u_int32)a.b[15];
1641                         pc++;
1642                         }
1643
1644         if (pc != fail) LogMsg("mDNSPlatformUpdateProxyList: pc %p != fail %p", pc, fail);
1645         *pc++ = rf;     // fail points here
1646
1647         if (pc != ret4) LogMsg("mDNSPlatformUpdateProxyList: pc %p != ret4 %p", pc, ret4);
1648         *pc++ = r4a;    // ret4 points here
1649         *pc++ = r4b;
1650         *pc++ = r4c;
1651         *pc++ = r4d;
1652
1653         if (pc != ret6) LogMsg("mDNSPlatformUpdateProxyList: pc %p != ret6 %p", pc, ret6);
1654         *pc++ = r6a;    // ret6 points here
1655
1656         struct bpf_program prog = { pc - filter, filter };
1657
1658 #if 0
1659         // For debugging BPF filter program
1660         unsigned int q;
1661         for (q=0; q<prog.bf_len; q++)
1662                 LogSPS("mDNSPlatformUpdateProxyList: %2d { 0x%02x, %d, %d, 0x%08x },", q, prog.bf_insns[q].code, prog.bf_insns[q].jt, prog.bf_insns[q].jf, prog.bf_insns[q].k);
1663 #endif
1664
1665         if (!numv4 && !numv6)
1666                 {
1667                 LogSPS("mDNSPlatformUpdateProxyList: No need for filter");
1668                 if (m->timenow == 0) LogMsg("mDNSPlatformUpdateProxyList: m->timenow == 0");
1669                 // Schedule check to see if we can close this BPF_fd now
1670                 if (!m->p->NetworkChanged) m->p->NetworkChanged = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2);
1671                 // prog.bf_len = 0; This seems to panic the kernel
1672                 }
1673
1674         if (ioctl(x->BPF_fd, BIOCSETF, &prog) < 0) LogMsg("mDNSPlatformUpdateProxyList: BIOCSETF(%d) failed %d (%s)", prog.bf_len, errno, strerror(errno));
1675         else LogSPS("mDNSPlatformUpdateProxyList: BIOCSETF(%d) successful", prog.bf_len);
1676         }
1677
1678 mDNSexport void mDNSPlatformReceiveBPF_fd(mDNS *const m, int fd)
1679         {
1680         mDNS_Lock(m);
1681         
1682         NetworkInterfaceInfoOSX *i;
1683         for (i = m->p->InterfaceList; i; i = i->next) if (i->BPF_fd == -2) break;
1684         if (!i) { LogSPS("mDNSPlatformReceiveBPF_fd: No Interfaces awaiting BPF fd %d; closing", fd); close(fd); }
1685         else
1686                 {
1687                 LogSPS("%s using   BPF fd %d", i->ifinfo.ifname, fd);
1688         
1689                 struct bpf_version v;
1690                 if (ioctl(fd, BIOCVERSION, &v) < 0)
1691                         LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCVERSION failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
1692                 else if (BPF_MAJOR_VERSION != v.bv_major || BPF_MINOR_VERSION != v.bv_minor)
1693                         LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCVERSION header %d.%d kernel %d.%d",
1694                                 fd, i->ifinfo.ifname, BPF_MAJOR_VERSION, BPF_MINOR_VERSION, v.bv_major, v.bv_minor);
1695         
1696                 if (ioctl(fd, BIOCGBLEN, &i->BPF_len) < 0)
1697                         LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCGBLEN failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
1698         
1699                 if (i->BPF_len > sizeof(m->imsg))
1700                         {
1701                         i->BPF_len = sizeof(m->imsg);
1702                         if (ioctl(fd, BIOCSBLEN, &i->BPF_len) < 0)
1703                                 LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCSBLEN failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
1704                         else LogSPS("mDNSPlatformReceiveBPF_fd: %d %s BIOCSBLEN %d", i->BPF_len);
1705                         }
1706         
1707                 static const u_int opt_immediate = 1;
1708                 if (ioctl(fd, BIOCIMMEDIATE, &opt_immediate) < 0)
1709                         LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCIMMEDIATE failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
1710         
1711                 struct ifreq ifr;
1712                 mDNSPlatformMemZero(&ifr, sizeof(ifr));
1713                 strlcpy(ifr.ifr_name, i->ifinfo.ifname, sizeof(ifr.ifr_name));
1714                 if (ioctl(fd, BIOCSETIF, &ifr) < 0)
1715                         { LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCSETIF failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno)); i->BPF_fd = -3; }
1716                 else
1717                         {
1718                         CFSocketContext myCFSocketContext = { 0, i, NULL, NULL, NULL };
1719                         i->BPF_fd  = fd;
1720                         i->BPF_cfs = CFSocketCreateWithNative(kCFAllocatorDefault, fd, kCFSocketReadCallBack, bpf_callback, &myCFSocketContext);
1721                         i->BPF_rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, i->BPF_cfs, 0);
1722                         CFRunLoopAddSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode);
1723                         mDNSPlatformUpdateProxyList(m, i->ifinfo.InterfaceID);
1724                         }
1725                 }
1726
1727         mDNS_Unlock(m);
1728         }
1729
1730 #endif // APPLE_OSX_mDNSResponder
1731
1732 #if COMPILER_LIKES_PRAGMA_MARK
1733 #pragma mark -
1734 #pragma mark - Key Management
1735 #endif
1736
1737 #ifndef NO_SECURITYFRAMEWORK
1738 mDNSlocal CFArrayRef GetCertChain(SecIdentityRef identity)
1739         {
1740         CFMutableArrayRef certChain = NULL;
1741         if (!identity) { LogMsg("getCertChain: identity is NULL"); return(NULL); }
1742         SecCertificateRef cert;
1743         OSStatus err = SecIdentityCopyCertificate(identity, &cert);
1744         if (err || !cert) LogMsg("getCertChain: SecIdentityCopyCertificate() returned %d", (int) err);
1745         else
1746                 {
1747                 SecPolicySearchRef searchRef;
1748                 err = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &searchRef);
1749                 if (err || !searchRef) LogMsg("getCertChain: SecPolicySearchCreate() returned %d", (int) err);
1750                 else
1751                         {
1752                         SecPolicyRef policy;
1753                         err = SecPolicySearchCopyNext(searchRef, &policy);
1754                         if (err || !policy) LogMsg("getCertChain: SecPolicySearchCopyNext() returned %d", (int) err);
1755                         else
1756                                 {
1757                                 CFArrayRef wrappedCert = CFArrayCreate(NULL, (const void**) &cert, 1, &kCFTypeArrayCallBacks);
1758                                 if (!wrappedCert) LogMsg("getCertChain: wrappedCert is NULL");
1759                                 else
1760                                         {
1761                                         SecTrustRef trust;
1762                                         err = SecTrustCreateWithCertificates(wrappedCert, policy, &trust);
1763                                         if (err || !trust) LogMsg("getCertChain: SecTrustCreateWithCertificates() returned %d", (int) err);
1764                                         else
1765                                                 {
1766                                                 err = SecTrustEvaluate(trust, NULL);
1767                                                 if (err) LogMsg("getCertChain: SecTrustEvaluate() returned %d", (int) err);
1768                                                 else
1769                                                         {
1770                                                         CFArrayRef rawCertChain;
1771                                                         CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
1772                                                         err = SecTrustGetResult(trust, NULL, &rawCertChain, &statusChain);
1773                                                         if (err || !rawCertChain || !statusChain) LogMsg("getCertChain: SecTrustGetResult() returned %d", (int) err);
1774                                                         else
1775                                                                 {
1776                                                                 certChain = CFArrayCreateMutableCopy(NULL, 0, rawCertChain);
1777                                                                 if (!certChain) LogMsg("getCertChain: certChain is NULL");
1778                                                                 else
1779                                                                         {
1780                                                                         // Replace the SecCertificateRef at certChain[0] with a SecIdentityRef per documentation for SSLSetCertificate:
1781                                                                         // <http://devworld.apple.com/documentation/Security/Reference/secureTransportRef/index.html>
1782                                                                         CFArraySetValueAtIndex(certChain, 0, identity);
1783                                                                         // Remove root from cert chain, but keep any and all intermediate certificates that have been signed by the root certificate
1784                                                                         if (CFArrayGetCount(certChain) > 1) CFArrayRemoveValueAtIndex(certChain, CFArrayGetCount(certChain) - 1);
1785                                                                         }
1786                                                                 CFRelease(rawCertChain);
1787                                                                 // Do not free statusChain:
1788                                                                 // <http://developer.apple.com/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html> says:
1789                                                                 // certChain: Call the CFRelease function to release this object when you are finished with it.
1790                                                                 // statusChain: Do not attempt to free this pointer; it remains valid until the trust management object is released...
1791                                                                 }
1792                                                         }
1793                                                 CFRelease(trust);
1794                                                 }
1795                                         CFRelease(wrappedCert);
1796                                         }
1797                                 CFRelease(policy);
1798                                 }
1799                         CFRelease(searchRef);
1800                         }
1801                 CFRelease(cert);
1802                 }
1803         return certChain;
1804         }
1805 #endif /* NO_SECURITYFRAMEWORK */
1806
1807 mDNSexport mStatus mDNSPlatformTLSSetupCerts(void)
1808         {
1809 #ifdef NO_SECURITYFRAMEWORK
1810         return mStatus_UnsupportedErr;
1811 #else
1812         SecIdentityRef                  identity = nil;
1813         SecIdentitySearchRef    srchRef = nil;
1814         OSStatus                                err;
1815
1816         // search for "any" identity matching specified key use
1817         // In this app, we expect there to be exactly one
1818         err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_DECRYPT, &srchRef);
1819         if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCreate returned %d", (int) err); return err; }
1820
1821         err = SecIdentitySearchCopyNext(srchRef, &identity);
1822         if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext returned %d", (int) err); return err; }
1823
1824         if (CFGetTypeID(identity) != SecIdentityGetTypeID())
1825                 { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext CFTypeID failure"); return mStatus_UnknownErr; }
1826
1827         // Found one. Call getCertChain to create the correct certificate chain.
1828         ServerCerts = GetCertChain(identity);
1829         if (ServerCerts == nil) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: getCertChain error"); return mStatus_UnknownErr; }
1830
1831         return mStatus_NoError;
1832 #endif /* NO_SECURITYFRAMEWORK */
1833         }
1834
1835 mDNSexport  void  mDNSPlatformTLSTearDownCerts(void)
1836         {
1837 #ifndef NO_SECURITYFRAMEWORK
1838         if (ServerCerts) { CFRelease(ServerCerts); ServerCerts = NULL; }
1839 #endif /* NO_SECURITYFRAMEWORK */
1840         }
1841
1842 // This gets the text of the field currently labelled "Computer Name" in the Sharing Prefs Control Panel
1843 mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel)
1844         {
1845         CFStringEncoding encoding = kCFStringEncodingUTF8;
1846         CFStringRef cfs = SCDynamicStoreCopyComputerName(NULL, &encoding);
1847         if (cfs)
1848                 {
1849                 CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
1850                 CFRelease(cfs);
1851                 }
1852         }
1853
1854 // This gets the text of the field currently labelled "Local Hostname" in the Sharing Prefs Control Panel
1855 mDNSlocal void GetUserSpecifiedLocalHostName(domainlabel *const namelabel)
1856         {
1857         CFStringRef cfs = SCDynamicStoreCopyLocalHostName(NULL);
1858         if (cfs)
1859                 {
1860                 CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
1861                 CFRelease(cfs);
1862                 }
1863         }
1864
1865 mDNSexport mDNSBool DictionaryIsEnabled(CFDictionaryRef dict)
1866         {
1867         mDNSs32 val;
1868         CFNumberRef state = CFDictionaryGetValue(dict, CFSTR("Enabled"));
1869         if (!state) return mDNSfalse;
1870         if (!CFNumberGetValue(state, kCFNumberSInt32Type, &val))
1871                 { LogMsg("ERROR: DictionaryIsEnabled - CFNumberGetValue"); return mDNSfalse; }
1872         return val ? mDNStrue : mDNSfalse;
1873         }
1874
1875 mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
1876         {
1877         if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
1878
1879         if (sa->sa_family == AF_INET)
1880                 {
1881                 struct sockaddr_in *ifa_addr = (struct sockaddr_in *)sa;
1882                 ip->type = mDNSAddrType_IPv4;
1883                 ip->ip.v4.NotAnInteger = ifa_addr->sin_addr.s_addr;
1884                 return(mStatus_NoError);
1885                 }
1886
1887         if (sa->sa_family == AF_INET6)
1888                 {
1889                 struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa;
1890                 // Inside the BSD kernel they use a hack where they stuff the sin6->sin6_scope_id
1891                 // value into the second word of the IPv6 link-local address, so they can just
1892                 // pass around IPv6 address structures instead of full sockaddr_in6 structures.
1893                 // Those hacked IPv6 addresses aren't supposed to escape the kernel in that form, but they do.
1894                 // To work around this we always whack the second word of any IPv6 link-local address back to zero.
1895                 if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
1896                 ip->type = mDNSAddrType_IPv6;
1897                 ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr;
1898                 return(mStatus_NoError);
1899                 }
1900
1901         LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
1902         return(mStatus_Invalid);
1903         }
1904
1905 mDNSlocal mDNSEthAddr GetBSSID(char *ifa_name)
1906         {
1907         mDNSEthAddr eth = zeroEthAddr;
1908         SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetBSSID"), NULL, NULL);
1909         if (!store)
1910                 LogMsg("GetBSSID: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
1911         else
1912                 {
1913                 CFStringRef entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/AirPort"), ifa_name);
1914                 if (entityname)
1915                         {
1916                         CFDictionaryRef dict = SCDynamicStoreCopyValue(store, entityname);
1917                         if (dict)
1918                                 {
1919                                 CFRange range = { 0, 6 };               // Offset, length
1920                                 CFDataRef data = CFDictionaryGetValue(dict, CFSTR("BSSID"));
1921                                 if (data && CFDataGetLength(data) == 6) CFDataGetBytes(data, range, eth.b);
1922                                 CFRelease(dict);
1923                                 }
1924                         CFRelease(entityname);
1925                         }
1926                 CFRelease(store);
1927                 }
1928         return(eth);
1929         }
1930
1931 mDNSlocal int GetMAC(mDNSEthAddr *eth, u_short ifindex)
1932         {
1933         struct ifaddrs *ifa;
1934         for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next)
1935                 if (ifa->ifa_addr->sa_family == AF_LINK)
1936                         {
1937                         const struct sockaddr_dl *const sdl = (const struct sockaddr_dl *)ifa->ifa_addr;
1938                         if (sdl->sdl_index == ifindex)
1939                                 { mDNSPlatformMemCopy(eth->b, sdl->sdl_data + sdl->sdl_nlen, 6); return 0; }
1940                         }
1941         *eth = zeroEthAddr;
1942         return -1;
1943         }
1944
1945 #ifndef SIOCGIFWAKEFLAGS
1946 #define SIOCGIFWAKEFLAGS _IOWR('i', 136, struct ifreq) /* get interface wake property flags */
1947 #endif
1948
1949 #ifndef IF_WAKE_ON_MAGIC_PACKET
1950 #define IF_WAKE_ON_MAGIC_PACKET 0x01
1951 #endif
1952
1953 #ifndef ifr_wake_flags
1954 #define ifr_wake_flags ifr_ifru.ifru_intval
1955 #endif
1956
1957 mDNSlocal mDNSBool NetWakeInterface(NetworkInterfaceInfoOSX *i)
1958         {
1959         if (!MulticastInterface(i)     ) return(mDNSfalse);     // We only use Sleep Proxy Service on multicast-capable interfaces
1960         if (i->ifa_flags & IFF_LOOPBACK) return(mDNSfalse);     // except loopback
1961
1962         int s = socket(AF_INET, SOCK_DGRAM, 0);
1963         if (s < 0) { LogMsg("NetWakeInterface %s socket failed %s errno %d (%s)", i->ifinfo.ifname, errno, strerror(errno)); return(mDNSfalse); }
1964
1965         struct ifreq ifr;
1966         strlcpy(ifr.ifr_name, i->ifinfo.ifname, sizeof(ifr.ifr_name));
1967         if (ioctl(s, SIOCGIFWAKEFLAGS, &ifr) < 0)
1968                 {
1969                 // For some strange reason, in /usr/include/sys/errno.h, EOPNOTSUPP is defined to be
1970                 // 102 when compiling kernel code, and 45 when compiling user-level code. Since this
1971                 // error code is being returned from the kernel, we need to use the kernel version.
1972                 #define KERNEL_EOPNOTSUPP 102
1973                 if (errno != KERNEL_EOPNOTSUPP) // "Operation not supported on socket", the expected result on Leopard and earlier
1974                         LogMsg("NetWakeInterface SIOCGIFWAKEFLAGS %s errno %d (%s)", i->ifinfo.ifname, errno, strerror(errno));
1975                 // If on Leopard or earlier, we get EOPNOTSUPP, so in that case
1976                 // we enable WOL if this interface is not AirPort and "Wake for Network access" is turned on.
1977                 ifr.ifr_wake_flags = (errno == KERNEL_EOPNOTSUPP && !(i)->BSSID.l[0] && i->m->SystemWakeOnLANEnabled) ? IF_WAKE_ON_MAGIC_PACKET : 0;
1978                 }
1979 #if ASSUME_SNOWLEOPARD_INCORRECTLY_REPORTS_AIRPORT_INCAPABLE_OF_WAKE_ON_LAN
1980         else
1981                 {
1982                 // Call succeeded.
1983                 // However, on SnowLeopard, it currently indicates incorrectly that AirPort is incapable of Wake-on-LAN.
1984                 // Therefore, for AirPort interfaces, we just track the system-wide Wake-on-LAN setting.
1985                 if ((i)->BSSID.l[0]) ifr.ifr_wake_flags = i->m->SystemWakeOnLANEnabled ? IF_WAKE_ON_MAGIC_PACKET : 0;
1986                 }
1987 #endif
1988
1989         close(s);
1990
1991         // ifr.ifr_wake_flags = IF_WAKE_ON_MAGIC_PACKET;        // For testing with MacBook Air, using a USB dongle that doesn't actually support Wake-On-LAN
1992
1993         LogSPS("%-6s %#-14a %s WOMP", i->ifinfo.ifname, &i->ifinfo.ip, (ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) ? "supports" : "no");
1994
1995         return((ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) != 0);
1996         }
1997
1998 // Returns pointer to newly created NetworkInterfaceInfoOSX object, or
1999 // pointer to already-existing NetworkInterfaceInfoOSX object found in list, or
2000 // may return NULL if out of memory (unlikely) or parameters are invalid for some reason
2001 // (e.g. sa_family not AF_INET or AF_INET6)
2002 mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifaddrs *ifa, mDNSs32 utc)
2003         {
2004         mDNSu32 scope_id  = if_nametoindex(ifa->ifa_name);
2005         mDNSEthAddr bssid = GetBSSID(ifa->ifa_name);
2006
2007         mDNSAddr ip, mask;
2008         if (SetupAddr(&ip,   ifa->ifa_addr   ) != mStatus_NoError) return(NULL);
2009         if (SetupAddr(&mask, ifa->ifa_netmask) != mStatus_NoError) return(NULL);
2010
2011         NetworkInterfaceInfoOSX **p;
2012         for (p = &m->p->InterfaceList; *p; p = &(*p)->next)
2013                 if (scope_id == (*p)->scope_id &&
2014                         mDNSSameAddress(&ip, &(*p)->ifinfo.ip) &&
2015                         mDNSSameEthAddress(&bssid, &(*p)->BSSID))
2016                         {
2017                         debugf("AddInterfaceToList: Found existing interface %lu %.6a with address %#a at %p", scope_id, &bssid, &ip, *p);
2018                         (*p)->Exists = mDNStrue;
2019                         // If interface was not in getifaddrs list last time we looked, but it is now, update 'AppearanceTime' for this record
2020                         if ((*p)->LastSeen != utc) (*p)->AppearanceTime = utc;
2021
2022                         // If Wake-on-LAN capability of this interface has changed (e.g. because power cable on laptop has been disconnected)
2023                         // we may need to start or stop or sleep proxy browse operation
2024                         const mDNSBool NetWake = NetWakeInterface(*p);
2025                         if ((*p)->ifinfo.NetWake != NetWake)
2026                                 {
2027                                 (*p)->ifinfo.NetWake = NetWake;
2028                                 // If this interface is already registered with mDNSCore, then we need to start or stop its NetWake browse on-the-fly.
2029                                 // If this interface is not already registered (i.e. it's a dormant interface we had in our list
2030                                 // from when we previously saw it) then we mustn't do that, because mDNSCore doesn't know about it yet.
2031                                 // In this case, the mDNS_RegisterInterface() call will take care of starting the NetWake browse if necessary.
2032                                 if ((*p)->Registered)
2033                                         {
2034                                         mDNS_Lock(m);
2035                                         if (NetWake) mDNS_ActivateNetWake_internal  (m, &(*p)->ifinfo);
2036                                         else         mDNS_DeactivateNetWake_internal(m, &(*p)->ifinfo);
2037                                         mDNS_Unlock(m);
2038                                         }
2039                                 }
2040
2041                         return(*p);
2042                         }
2043
2044         NetworkInterfaceInfoOSX *i = (NetworkInterfaceInfoOSX *)mallocL("NetworkInterfaceInfoOSX", sizeof(*i));
2045         debugf("AddInterfaceToList: Making   new   interface %lu %.6a with address %#a at %p", scope_id, &bssid, &ip, i);
2046         if (!i) return(mDNSNULL);
2047         mDNSPlatformMemZero(i, sizeof(NetworkInterfaceInfoOSX));
2048         i->ifinfo.InterfaceID = (mDNSInterfaceID)(uintptr_t)scope_id;
2049         i->ifinfo.ip          = ip;
2050         i->ifinfo.mask        = mask;
2051         strlcpy(i->ifinfo.ifname, ifa->ifa_name, sizeof(i->ifinfo.ifname));
2052         i->ifinfo.ifname[sizeof(i->ifinfo.ifname)-1] = 0;
2053         // We can be configured to disable multicast advertisement, but we want to to support
2054         // local-only services, which need a loopback address record.
2055         i->ifinfo.Advertise   = m->DivertMulticastAdvertisements ? ((ifa->ifa_flags & IFF_LOOPBACK) ? mDNStrue : mDNSfalse) : m->AdvertiseLocalAddresses;
2056         i->ifinfo.McastTxRx   = mDNSfalse; // For now; will be set up later at the end of UpdateInterfaceList
2057
2058         i->next            = mDNSNULL;
2059         i->m               = m;
2060         i->Exists          = mDNStrue;
2061         i->Flashing        = mDNSfalse;
2062         i->Occulting       = mDNSfalse;
2063         i->AppearanceTime  = utc;               // Brand new interface; AppearanceTime is now
2064         i->LastSeen        = utc;
2065         i->ifa_flags       = ifa->ifa_flags;
2066         i->scope_id        = scope_id;
2067         i->BSSID           = bssid;
2068         i->sa_family       = ifa->ifa_addr->sa_family;
2069         i->BPF_fd          = -1;
2070         i->BPF_len         = 0;
2071         i->Registered      = mDNSNULL;
2072
2073         // Do this AFTER i->BSSID has been set up
2074         i->ifinfo.NetWake  = NetWakeInterface(i);
2075         GetMAC(&i->ifinfo.MAC, scope_id);
2076         if (i->ifinfo.NetWake && !i->ifinfo.MAC.l[0])
2077                 LogMsg("AddInterfaceToList: Bad MAC address %.6a for %d %s %#a", &i->ifinfo.MAC, scope_id, i->ifinfo.ifname, &ip);
2078
2079         *p = i;
2080         return(i);
2081         }
2082
2083 #if USE_V6_ONLY_WHEN_NO_ROUTABLE_V4
2084 mDNSlocal NetworkInterfaceInfoOSX *FindRoutableIPv4(mDNS *const m, mDNSu32 scope_id)
2085         {
2086         NetworkInterfaceInfoOSX *i;
2087         for (i = m->p->InterfaceList; i; i = i->next)
2088                 if (i->Exists && i->scope_id == scope_id && i->ifinfo.ip.type == mDNSAddrType_IPv4)
2089                         if (!mDNSv4AddressIsLinkLocal(&i->ifinfo.ip.ip.v4))
2090                                 return(i);
2091         return(mDNSNULL);
2092         }
2093 #endif
2094
2095 #if APPLE_OSX_mDNSResponder
2096
2097 #if COMPILER_LIKES_PRAGMA_MARK
2098 #pragma mark -
2099 #pragma mark - AutoTunnel
2100 #endif
2101
2102 #define kRacoonPort 4500
2103
2104 static DomainAuthInfo* AnonymousRacoonConfig = mDNSNULL;
2105
2106 #ifndef NO_SECURITYFRAMEWORK
2107
2108 static CFMutableDictionaryRef domainStatusDict = NULL;
2109
2110 // MUST be called with lock held
2111 mDNSlocal void RemoveAutoTunnelDomainStatus(const mDNS *const m, const DomainAuthInfo *const info)
2112         {
2113         char buffer[1024];
2114         CFStringRef domain;
2115
2116         LogInfo("RemoveAutoTunnelDomainStatus: %##s", info->domain.c);
2117
2118         if (!domainStatusDict) { LogMsg("RemoveAutoTunnelDomainStatus: No domainStatusDict"); return; }
2119         
2120         buffer[mDNS_snprintf(buffer, sizeof(buffer), "%##s", info->domain.c) - 1] = 0;
2121         domain = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
2122         if (!domain) { LogMsg("RemoveAutoTunnelDomainStatus: Could not create CFString domain"); return; }
2123         
2124         if (CFDictionaryContainsKey(domainStatusDict, domain))
2125                 {
2126                 CFDictionaryRemoveValue(domainStatusDict, domain);
2127                 if (!m->ShutdownTime) mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, mDNSNULL, domainStatusDict);
2128                 }
2129         CFRelease(domain);
2130         }
2131
2132 mDNSlocal mStatus CheckQuestionForStatus(const DNSQuestion *const q)
2133         {
2134         if (q->LongLived)
2135                 {
2136                 if (q->nta || (q->servAddr.type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsOnes(q->servAddr.ip.v4)))
2137                         return mStatus_NoSuchRecord;
2138                 else if (q->state == LLQ_Poll)
2139                         return mStatus_PollingMode;
2140                 else if (q->state != LLQ_Established && !q->DuplicateOf)
2141                         return mStatus_TransientErr;
2142                 }
2143         
2144         return mStatus_NoError;
2145 }
2146
2147 #endif // ndef NO_SECURITYFRAMEWORK
2148
2149 // MUST be called with lock held
2150 mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAuthInfo *const info)
2151         {
2152 #ifdef NO_SECURITYFRAMEWORK
2153         (void)m;
2154         (void)info;
2155 #else
2156         const NATTraversalInfo *const llq = m->LLQNAT.clientContext ? &m->LLQNAT : mDNSNULL;
2157         const NATTraversalInfo *const tun = info->AutoTunnelNAT.clientContext ? &info->AutoTunnelNAT : mDNSNULL;
2158         char buffer[1024];
2159         CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2160         CFStringRef domain = NULL;
2161         CFStringRef tmp = NULL;
2162         CFNumberRef num = NULL;
2163         mStatus status = mStatus_NoError;
2164         
2165         if (!domainStatusDict)
2166                 {
2167                 domainStatusDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2168                 if (!domainStatusDict) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFDictionary domainStatusDict"); return; }
2169                 }
2170         
2171         if (!dict) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFDictionary dict"); return; }
2172
2173         buffer[mDNS_snprintf(buffer, sizeof(buffer), "%##s", info->domain.c) - 1] = 0;
2174         domain = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
2175         if (!domain) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString domain"); return; }
2176
2177         mDNS_snprintf(buffer, sizeof(buffer), "%#a", &m->Router);
2178         tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
2179         if (!tmp)
2180                 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString RouterAddress");
2181         else
2182                 {
2183                 CFDictionarySetValue(dict, CFSTR("RouterAddress"), tmp);
2184                 CFRelease(tmp);
2185                 }
2186         
2187         mDNS_snprintf(buffer, sizeof(buffer), "%.4a", &m->ExternalAddress);
2188         tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
2189         if (!tmp)
2190                 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString ExternalAddress");
2191         else
2192                 {
2193                 CFDictionarySetValue(dict, CFSTR("ExternalAddress"), tmp);
2194                 CFRelease(tmp);
2195                 }
2196         
2197         if (llq)
2198                 {
2199                 mDNSu32 port = mDNSVal16(llq->ExternalPort);
2200                 
2201                 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &port);
2202                 if (!num)
2203                         LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LLQExternalPort");
2204                 else
2205                         {
2206                         CFDictionarySetValue(dict, CFSTR("LLQExternalPort"), num);
2207                         CFRelease(num);
2208                         }
2209
2210                 if (llq->Result)
2211                         {
2212                         num = CFNumberCreate(NULL, kCFNumberSInt32Type, &llq->Result);
2213                         if (!num)
2214                                 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LLQNPMStatus");
2215                         else
2216                                 {
2217                                 CFDictionarySetValue(dict, CFSTR("LLQNPMStatus"), num);
2218                                 CFRelease(num);
2219                                 }
2220                         }
2221                 }
2222         
2223         if (tun)
2224                 {
2225                 mDNSu32 port = mDNSVal16(tun->ExternalPort);
2226                 
2227                 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &port);
2228                 if (!num)
2229                         LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber AutoTunnelExternalPort");
2230                 else
2231                         {
2232                         CFDictionarySetValue(dict, CFSTR("AutoTunnelExternalPort"), num);
2233                         CFRelease(num);
2234                         }
2235
2236                 if (tun->Result)
2237                         {
2238                         num = CFNumberCreate(NULL, kCFNumberSInt32Type, &tun->Result);
2239                         if (!num)
2240                                 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber AutoTunnelNPMStatus");
2241                         else
2242                                 {
2243                                 CFDictionarySetValue(dict, CFSTR("AutoTunnelNPMStatus"), num);
2244                                 CFRelease(num);
2245                                 }
2246                         }
2247                 }
2248         if (tun || llq)
2249                 {
2250                 mDNSu32 code = m->LastNATMapResultCode;
2251                 
2252                 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &code);
2253                 if (!num)
2254                         LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LastNATMapResultCode");
2255                 else
2256                         {
2257                         CFDictionarySetValue(dict, CFSTR("LastNATMapResultCode"), num);
2258                         CFRelease(num);
2259                         }
2260                 }
2261         
2262         if (!llq && !tun)
2263                 {
2264                 status = mStatus_NotInitializedErr;
2265                 mDNS_snprintf(buffer, sizeof(buffer), "Neither LLQ nor AutoTunnel NAT port mapping is currently active");
2266                 }
2267         else if ((llq && llq->Result == mStatus_DoubleNAT) || (tun && tun->Result == mStatus_DoubleNAT))
2268                 {
2269                 status = mStatus_DoubleNAT;
2270                 mDNS_snprintf(buffer, sizeof(buffer), "Double NAT: Router is reporting an external address");
2271                 }
2272         else if ((llq && llq->Result == mStatus_NATPortMappingDisabled) || (tun && tun->Result == mStatus_NATPortMappingDisabled) ||
2273                  (m->LastNATMapResultCode == NATErr_Refused && ((llq && !llq->Result && mDNSIPPortIsZero(llq->ExternalPort)) || (tun && !tun->Result && mDNSIPPortIsZero(tun->ExternalPort)))))
2274                 {
2275                 status = mStatus_NATPortMappingDisabled;
2276                 mDNS_snprintf(buffer, sizeof(buffer), "NAT-PMP is disabled on the router");
2277                 }
2278         else if ((llq && llq->Result) || (tun && tun->Result))
2279                 {
2280                 status = mStatus_NATTraversal;
2281                 mDNS_snprintf(buffer, sizeof(buffer), "Error obtaining NAT port mapping from router");
2282                 }
2283         else if (m->Router.type == mDNSAddrType_None)
2284                 {
2285                 status = mStatus_NoRouter;
2286                 mDNS_snprintf(buffer, sizeof(buffer), "No network connection - none");
2287                 }
2288         else if (m->Router.type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsZero(m->Router.ip.v4))
2289                 {
2290                 status = mStatus_NoRouter;
2291                 mDNS_snprintf(buffer, sizeof(buffer), "No network connection - v4 zero");
2292                 }
2293         else if ((llq && mDNSIPPortIsZero(llq->ExternalPort)) || (tun && mDNSIPPortIsZero(tun->ExternalPort)))
2294                 {
2295                 status = mStatus_NATTraversal;
2296                 mDNS_snprintf(buffer, sizeof(buffer), "Unable to obtain NAT port mapping from router");
2297                 }
2298         else
2299                 {
2300                 DNSQuestion* q, *worst_q = mDNSNULL;
2301                 for (q = m->Questions; q; q=q->next)
2302                         if (q->AuthInfo == info)
2303                                 {
2304                                 mStatus newStatus = CheckQuestionForStatus(q);
2305                                 if              (newStatus == mStatus_NoSuchRecord) { status = newStatus; worst_q = q; break; }
2306                                 else if (newStatus == mStatus_PollingMode)  { status = newStatus; worst_q = q; }
2307                                 else if (newStatus == mStatus_TransientErr && status == mStatus_NoError) { status = newStatus; worst_q = q; }
2308                                 }
2309                 
2310                 if      (status == mStatus_NoError)      mDNS_snprintf(buffer, sizeof(buffer), "Success");
2311                 else if (status == mStatus_NoSuchRecord) mDNS_snprintf(buffer, sizeof(buffer), "GetZoneData %s: %##s", worst_q->nta ? "not yet complete" : "failed", worst_q->qname.c);
2312                 else if (status == mStatus_PollingMode)  mDNS_snprintf(buffer, sizeof(buffer), "Query polling %##s", worst_q->qname.c);
2313                 else if (status == mStatus_TransientErr) mDNS_snprintf(buffer, sizeof(buffer), "Query not yet established %##s", worst_q->qname.c);
2314                 }
2315         
2316         num = CFNumberCreate(NULL, kCFNumberSInt32Type, &status);
2317         if (!num)
2318                 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber StatusCode");
2319         else
2320                 {
2321                 CFDictionarySetValue(dict, CFSTR("StatusCode"), num);
2322                 CFRelease(num);
2323                 }
2324                 
2325         tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
2326         if (!tmp)
2327                 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString StatusMessage");
2328         else
2329                 {
2330                 CFDictionarySetValue(dict, CFSTR("StatusMessage"), tmp);
2331                 CFRelease(tmp);
2332                 }
2333
2334         if (!CFDictionaryContainsKey(domainStatusDict, domain) ||
2335             !CFEqual(dict, (CFMutableDictionaryRef)CFDictionaryGetValue(domainStatusDict, domain)))
2336             {
2337                 CFDictionarySetValue(domainStatusDict, domain, dict);
2338                 if (!m->ShutdownTime) 
2339                         {
2340                         static char statusBuf[16];
2341                         mDNS_snprintf(statusBuf, sizeof(statusBuf), "%d", (int)status);
2342                         mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.domainstatus", status ? "failure" : "success", statusBuf, "");
2343                         mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, mDNSNULL, domainStatusDict);
2344                         }
2345                 }
2346                 
2347         CFRelease(domain);
2348         CFRelease(dict);
2349
2350         debugf("UpdateAutoTunnelDomainStatus: %s", buffer);
2351 #endif // def NO_SECURITYFRAMEWORK
2352         }
2353
2354 // MUST be called with lock held
2355 mDNSexport void UpdateAutoTunnelDomainStatuses(const mDNS *const m)
2356         {
2357 #ifdef NO_SECURITYFRAMEWORK
2358         (void)m;
2359 #else
2360         DomainAuthInfo* info;
2361         for (info = m->AuthInfoList; info; info = info->next)
2362                 if (info->AutoTunnel && !info->deltime)
2363                         UpdateAutoTunnelDomainStatus(m, info);
2364 #endif // def NO_SECURITYFRAMEWORK
2365         }
2366         
2367 // MUST be called with lock held
2368 mDNSlocal mDNSBool TunnelServers(mDNS *const m)
2369         {
2370         ServiceRecordSet *p;
2371         for (p = m->ServiceRegistrations; p; p = p->uDNS_next)
2372                 {
2373                 DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, p->RR_SRV.resrec.name);
2374                 if (AuthInfo && AuthInfo->AutoTunnel && !AuthInfo->deltime) return(mDNStrue);
2375                 }
2376
2377         AuthRecord *r;
2378         for (r = m->ResourceRecords; r; r = r->next)
2379                 if (r->resrec.rrtype == kDNSType_SRV)
2380                         {
2381                         DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, r->resrec.name);
2382                         if (AuthInfo && AuthInfo->AutoTunnel && !AuthInfo->deltime) return(mDNStrue);
2383                         }
2384
2385         return(mDNSfalse);
2386         }
2387
2388 // MUST be called with lock held
2389 mDNSlocal mDNSBool TunnelClients(mDNS *const m)
2390         {
2391         ClientTunnel *p;
2392         for (p = m->TunnelClients; p; p = p->next)
2393                 if (p->q.ThisQInterval < 0)
2394                         return(mDNStrue);
2395         return(mDNSfalse);
2396         }
2397
2398 mDNSlocal void RegisterAutoTunnelRecords(mDNS *m, DomainAuthInfo *info)
2399         {
2400         if (info->AutoTunnelNAT.clientContext && !info->AutoTunnelNAT.Result && !mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort) && AutoTunnelUnregistered(info))
2401                 {
2402                 mStatus err;
2403                 LogInfo("RegisterAutoTunnelRecords %##s (%#s)", info->domain.c, m->hostlabel.c);
2404
2405                 // 1. Set up our address record for the internal tunnel address
2406                 // (User-visible user-friendly host name, used as target in AutoTunnel SRV records)
2407                 info->AutoTunnelHostRecord.namestorage.c[0] = 0;
2408                 AppendDomainLabel(&info->AutoTunnelHostRecord.namestorage, &m->hostlabel);
2409                 AppendDomainName (&info->AutoTunnelHostRecord.namestorage, &info->domain);
2410                 info->AutoTunnelHostRecord.resrec.rdata->u.ipv6 = m->AutoTunnelHostAddr;
2411                 info->AutoTunnelHostRecord.resrec.RecordType = kDNSRecordTypeKnownUnique;
2412                 err = mDNS_Register(m, &info->AutoTunnelHostRecord);
2413                 if (err) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelHostRecord %##s", err, info->AutoTunnelHostRecord.namestorage.c);
2414
2415                 // 2. Set up device info record
2416                 ConstructServiceName(&info->AutoTunnelDeviceInfo.namestorage, &m->nicelabel, &DeviceInfoName, &info->domain);
2417                 mDNSu8 len = m->HIHardware.c[0] < 255 - 6 ? m->HIHardware.c[0] : 255 - 6;
2418                 mDNSPlatformMemCopy(info->AutoTunnelDeviceInfo.resrec.rdata->u.data + 1, "model=", 6);
2419                 mDNSPlatformMemCopy(info->AutoTunnelDeviceInfo.resrec.rdata->u.data + 7, m->HIHardware.c + 1, len);
2420                 info->AutoTunnelDeviceInfo.resrec.rdata->u.data[0] = 6 + len;   // "model=" plus the device string
2421                 info->AutoTunnelDeviceInfo.resrec.rdlength         = 7 + len;   // One extra for the length byte at the start of the string
2422                 info->AutoTunnelDeviceInfo.resrec.RecordType = kDNSRecordTypeKnownUnique;
2423                 err = mDNS_Register(m, &info->AutoTunnelDeviceInfo);
2424                 if (err) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelDeviceInfo %##s", err, info->AutoTunnelDeviceInfo.namestorage.c);
2425
2426                 // 3. Set up our address record for the external tunnel address
2427                 // (Constructed name, not generally user-visible, used as target in IKE tunnel's SRV record)
2428                 info->AutoTunnelTarget.namestorage.c[0] = 0;
2429                 AppendDomainLabel(&info->AutoTunnelTarget.namestorage, &m->AutoTunnelLabel);
2430                 AppendDomainName (&info->AutoTunnelTarget.namestorage, &info->domain);
2431                 info->AutoTunnelTarget.resrec.RecordType = kDNSRecordTypeKnownUnique;
2432
2433                 mDNS_Lock(m);
2434                 mDNS_AddDynDNSHostName(m, &info->AutoTunnelTarget.namestorage, mDNSNULL, info);
2435                 mDNS_Unlock(m);
2436
2437                 // 4. Set up IKE tunnel's SRV record: "AutoTunnelHostRecord SRV 0 0 port AutoTunnelTarget"
2438                 AssignDomainName (&info->AutoTunnelService.namestorage, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
2439                 AppendDomainLabel(&info->AutoTunnelService.namestorage, &m->hostlabel);
2440                 AppendDomainName (&info->AutoTunnelService.namestorage, &info->domain);
2441                 info->AutoTunnelService.resrec.rdata->u.srv.priority = 0;
2442                 info->AutoTunnelService.resrec.rdata->u.srv.weight   = 0;
2443                 info->AutoTunnelService.resrec.rdata->u.srv.port     = info->AutoTunnelNAT.ExternalPort;
2444                 AssignDomainName(&info->AutoTunnelService.resrec.rdata->u.srv.target, &info->AutoTunnelTarget.namestorage);
2445                 info->AutoTunnelService.resrec.RecordType = kDNSRecordTypeKnownUnique;
2446                 err = mDNS_Register(m, &info->AutoTunnelService);
2447                 if (err) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelService %##s", err, info->AutoTunnelService.namestorage.c);
2448
2449                 LogInfo("AutoTunnel server listening for connections on %##s[%.4a]:%d:%##s[%.16a]",
2450                         info->AutoTunnelTarget.namestorage.c,     &m->AdvertisedV4.ip.v4, mDNSVal16(info->AutoTunnelNAT.IntPort),
2451                         info->AutoTunnelHostRecord.namestorage.c, &m->AutoTunnelHostAddr);
2452                 }
2453         }
2454
2455 mDNSlocal void DeregisterAutoTunnelRecords(mDNS *m, DomainAuthInfo *info)
2456         {
2457         LogInfo("DeregisterAutoTunnelRecords %##s", info->domain.c);
2458         if (info->AutoTunnelService.resrec.RecordType > kDNSRecordTypeDeregistering)
2459                 {
2460                 mStatus err = mDNS_Deregister(m, &info->AutoTunnelService);
2461                 if (err)
2462                         {
2463                         info->AutoTunnelService.resrec.RecordType = kDNSRecordTypeUnregistered;
2464                         LogMsg("DeregisterAutoTunnelRecords error %d deregistering AutoTunnelService %##s", err, info->AutoTunnelService.namestorage.c);
2465                         }
2466
2467                 mDNS_Lock(m);
2468                 mDNS_RemoveDynDNSHostName(m, &info->AutoTunnelTarget.namestorage);
2469                 mDNS_Unlock(m);
2470                 }
2471
2472         if (info->AutoTunnelHostRecord.resrec.RecordType > kDNSRecordTypeDeregistering)
2473                 {
2474                 mStatus err = mDNS_Deregister(m, &info->AutoTunnelHostRecord);
2475                 if (err)
2476                         {
2477                         info->AutoTunnelHostRecord.resrec.RecordType = kDNSRecordTypeUnregistered;
2478                         LogMsg("DeregisterAutoTunnelRecords error %d deregistering AutoTunnelHostRecord %##s", err, info->AutoTunnelHostRecord.namestorage.c);
2479                         }
2480                 }
2481
2482         if (info->AutoTunnelDeviceInfo.resrec.RecordType > kDNSRecordTypeDeregistering)
2483                 {
2484                 mStatus err = mDNS_Deregister(m, &info->AutoTunnelDeviceInfo);
2485                 if (err)
2486                         {
2487                         info->AutoTunnelDeviceInfo.resrec.RecordType = kDNSRecordTypeUnregistered;
2488                         LogMsg("DeregisterAutoTunnelRecords error %d deregistering AutoTunnelDeviceInfo %##s", err, info->AutoTunnelDeviceInfo.namestorage.c);
2489                         }
2490                 }
2491         }
2492
2493 mDNSlocal void AutoTunnelRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
2494         {
2495         DomainAuthInfo *info = (DomainAuthInfo *)rr->RecordContext;
2496         if (result == mStatus_MemFree)
2497                 {
2498                 LogInfo("AutoTunnelRecordCallback MemFree %s", ARDisplayString(m, rr));
2499                 // Reset the host record namestorage to force high-level PTR/SRV/TXT to deregister
2500                 if (rr == &info->AutoTunnelHostRecord)
2501                         {
2502                         rr->namestorage.c[0] = 0;
2503                         m->NextSRVUpdate = NonZeroTime(m->timenow);
2504                         LogInfo("AutoTunnelRecordCallback: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
2505                         }
2506                 RegisterAutoTunnelRecords(m,info);
2507                 }
2508         }
2509
2510 mDNSlocal void UpdateAnonymousRacoonConfig(mDNS *m)             // Determine whether we need racoon to accept incoming connections
2511         {
2512         DomainAuthInfo *info;
2513         
2514         for (info = m->AuthInfoList; info; info = info->next)
2515                 if (info->AutoTunnel && !info->deltime && !mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort))
2516                         break;
2517         
2518         if (info != AnonymousRacoonConfig)
2519                 {
2520                 AnonymousRacoonConfig = info;
2521                 // Create or revert configuration file, and start (or SIGHUP) Racoon
2522                 (void)mDNSConfigureServer(AnonymousRacoonConfig ? kmDNSUp : kmDNSDown, AnonymousRacoonConfig ? &AnonymousRacoonConfig->domain : mDNSNULL);
2523                 }
2524         }
2525                 
2526 mDNSlocal void AutoTunnelNATCallback(mDNS *m, NATTraversalInfo *n)
2527         {
2528         DomainAuthInfo *info = (DomainAuthInfo *)n->clientContext;
2529         LogInfo("AutoTunnelNATCallback Result %d %.4a Internal %d External %d %#s.%##s",
2530                 n->Result, &n->ExternalAddress, mDNSVal16(n->IntPort), mDNSVal16(n->ExternalPort), m->hostlabel.c, info->domain.c);
2531
2532         m->NextSRVUpdate = NonZeroTime(m->timenow);
2533         LogInfo("AutoTunnelNATCallback: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
2534
2535         DeregisterAutoTunnelRecords(m,info);
2536         RegisterAutoTunnelRecords(m,info);
2537         
2538         UpdateAnonymousRacoonConfig(m);         // Determine whether we need racoon to accept incoming connections
2539
2540         UpdateAutoTunnelDomainStatus(m, (DomainAuthInfo *)n->clientContext);
2541         }
2542
2543 mDNSlocal void AbortDeregistration(mDNS *const m, AuthRecord *rr)
2544         {
2545         if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
2546                 {
2547                 LogInfo("Aborting deregistration of %s", ARDisplayString(m, rr));
2548                 CompleteDeregistration(m, rr);
2549                 }
2550         else if (rr->resrec.RecordType != kDNSRecordTypeUnregistered)
2551                 LogMsg("AbortDeregistration ERROR RecordType %02X for %s", ARDisplayString(m, rr));
2552         }
2553
2554 // Before SetupLocalAutoTunnelInterface_internal is called,
2555 // m->AutoTunnelHostAddr.b[0] must be non-zero, and there must be at least one TunnelClient or TunnelServer
2556 // Must be called with the lock held
2557 mDNSexport void SetupLocalAutoTunnelInterface_internal(mDNS *const m)
2558         {
2559         LogInfo("SetupLocalAutoTunnelInterface");
2560
2561         // 1. Configure the local IPv6 address
2562         if (!m->AutoTunnelHostAddrActive)
2563                 {
2564                 m->AutoTunnelHostAddrActive = mDNStrue;
2565                 LogInfo("Setting up AutoTunnel address %.16a", &m->AutoTunnelHostAddr);
2566                 (void)mDNSAutoTunnelInterfaceUpDown(kmDNSUp, m->AutoTunnelHostAddr.b);
2567                 }
2568
2569         // 2. If we have at least one server (pending) listening, publish our records
2570         if (TunnelServers(m))
2571                 {
2572                 DomainAuthInfo *info;
2573                 for (info = m->AuthInfoList; info; info = info->next)
2574                         {
2575                         if (info->AutoTunnel && !info->deltime && !info->AutoTunnelNAT.clientContext)
2576                                 {
2577                                 // If we just resurrected a DomainAuthInfo that is still deregistering, we need to abort the deregistration process before re-using the AuthRecord memory
2578                                 AbortDeregistration(m, &info->AutoTunnelHostRecord);
2579                                 AbortDeregistration(m, &info->AutoTunnelDeviceInfo);
2580                                 AbortDeregistration(m, &info->AutoTunnelService);
2581
2582                                 mDNS_SetupResourceRecord(&info->AutoTunnelHostRecord, mDNSNULL, mDNSInterface_Any, kDNSType_AAAA, kHostNameTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
2583                                 mDNS_SetupResourceRecord(&info->AutoTunnelDeviceInfo, mDNSNULL, mDNSInterface_Any, kDNSType_TXT,  kStandardTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
2584                                 mDNS_SetupResourceRecord(&info->AutoTunnelTarget,     mDNSNULL, mDNSInterface_Any, kDNSType_A,    kHostNameTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
2585                                 mDNS_SetupResourceRecord(&info->AutoTunnelService,    mDNSNULL, mDNSInterface_Any, kDNSType_SRV,  kHostNameTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
2586
2587                                 // Try to get a NAT port mapping for the AutoTunnelService
2588                                 info->AutoTunnelNAT.clientCallback   = AutoTunnelNATCallback;
2589                                 info->AutoTunnelNAT.clientContext    = info;
2590                                 info->AutoTunnelNAT.Protocol         = NATOp_MapUDP;
2591                                 info->AutoTunnelNAT.IntPort          = IPSECPort;
2592                                 info->AutoTunnelNAT.RequestedPort    = IPSECPort;
2593                                 info->AutoTunnelNAT.NATLease         = 0;
2594                                 mStatus err = mDNS_StartNATOperation_internal(m, &info->AutoTunnelNAT);
2595                                 if (err) LogMsg("SetupLocalAutoTunnelInterface_internal error %d starting NAT mapping", err);
2596                                 }
2597                         }
2598                 }
2599         }
2600
2601 mDNSlocal mStatus AutoTunnelSetKeys(ClientTunnel *tun, mDNSBool AddNew)
2602         {
2603         return(mDNSAutoTunnelSetKeys(AddNew ? kmDNSAutoTunnelSetKeysReplace : kmDNSAutoTunnelSetKeysDelete, tun->loc_inner.b, tun->loc_outer.b, kRacoonPort, tun->rmt_inner.b, tun->rmt_outer.b, mDNSVal16(tun->rmt_outer_port), SkipLeadingLabels(&tun->dstname, 1)));
2604         }
2605
2606 // If the EUI-64 part of the IPv6 ULA matches, then that means the two addresses point to the same machine
2607 #define mDNSSameClientTunnel(A,B) ((A)->l[2] == (B)->l[2] && (A)->l[3] == (B)->l[3])
2608
2609 mDNSlocal void ReissueBlockedQuestionWithType(mDNS *const m, domainname *d, mDNSBool success, mDNSu16 qtype)
2610         {
2611         DNSQuestion *q = m->Questions;
2612         while (q)
2613                 {
2614                 if (q->NoAnswer == NoAnswer_Suspended && q->qtype == qtype && q->AuthInfo && q->AuthInfo->AutoTunnel && SameDomainName(&q->qname, d))
2615                         {
2616                         LogInfo("Restart %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
2617                         mDNSQuestionCallback *tmp = q->QuestionCallback;
2618                         q->QuestionCallback = AutoTunnelCallback;       // Set QuestionCallback to suppress another call back to AddNewClientTunnel
2619                         mDNS_StopQuery(m, q);
2620                         mDNS_StartQuery(m, q);
2621                         q->QuestionCallback = tmp;                                      // Restore QuestionCallback back to the real value
2622                         if (!success) q->NoAnswer = NoAnswer_Fail;
2623                         // When we call mDNS_StopQuery, it's possible for other subordinate questions like the GetZoneData query to be cancelled too.
2624                         // In general we have to assume that the question list might have changed in arbitrary ways.
2625                         // This code is itself called from a question callback, so the m->CurrentQuestion mechanism is
2626                         // already in use. The safest solution is just to go back to the start of the list and start again.
2627                         // In principle this sounds like an n^2 algorithm, but in practice we almost always activate
2628                         // just one suspended question, so it's really a 2n algorithm.
2629                         q = m->Questions;
2630                         }
2631                 else
2632                         q = q->next;
2633                 }
2634         }
2635
2636 mDNSlocal void ReissueBlockedQuestions(mDNS *const m, domainname *d, mDNSBool success)
2637         {
2638         // 1. We deliberately restart AAAA queries before A queries, because in the common case where a BTTM host has
2639         //    a v6 address but no v4 address, we prefer the caller to get the positive AAAA response before the A NXDOMAIN.
2640         // 2. In the case of AAAA queries, if our tunnel setup failed, then we return a deliberate failure indication to the caller --
2641         //    even if the name does have a valid AAAA record, we don't want clients trying to connect to it without a properly encrypted tunnel.
2642         // 3. For A queries we never fabricate failures -- if a BTTM service is really using raw IPv4, then it doesn't need the IPv6 tunnel.
2643         ReissueBlockedQuestionWithType(m, d, success, kDNSType_AAAA);
2644         ReissueBlockedQuestionWithType(m, d, mDNStrue, kDNSType_A);
2645         }
2646
2647 mDNSlocal void UnlinkAndReissueBlockedQuestions(mDNS *const m, ClientTunnel *tun, mDNSBool success)
2648         {
2649         ClientTunnel **p = &m->TunnelClients;
2650         while (*p != tun && *p) p = &(*p)->next;
2651         if (*p) *p = tun->next;
2652         ReissueBlockedQuestions(m, &tun->dstname, success);
2653         LogInfo("UnlinkAndReissueBlockedQuestions: Disposing ClientTunnel %p", tun);
2654         freeL("ClientTunnel", tun);
2655         }
2656
2657 mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
2658         {
2659         ClientTunnel *tun = (ClientTunnel *)question->QuestionContext;
2660         LogInfo("AutoTunnelCallback tun %p AddRecord %d rdlength %d qtype %d", tun, AddRecord, answer->rdlength, question->qtype);
2661
2662         if (!AddRecord) return;
2663         mDNS_StopQuery(m, question);
2664
2665         if (!answer->rdlength)
2666                 {
2667                 LogInfo("AutoTunnelCallback NXDOMAIN %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
2668                 static char msgbuf[16];
2669                 mDNS_snprintf(msgbuf, sizeof(msgbuf), "%s lookup", DNSTypeName(question->qtype));
2670                 mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.config", "failure", msgbuf, "");
2671                 UnlinkAndReissueBlockedQuestions(m, tun, mDNSfalse);
2672                 return;
2673                 }
2674
2675         if (question->qtype == kDNSType_AAAA)
2676                 {
2677                 if (mDNSSameIPv6Address(answer->rdata->u.ipv6, m->AutoTunnelHostAddr))
2678                         {
2679                         LogInfo("AutoTunnelCallback: suppressing tunnel to self %.16a", &answer->rdata->u.ipv6);
2680                         UnlinkAndReissueBlockedQuestions(m, tun, mDNStrue);
2681                         return;
2682                         }
2683
2684                 tun->rmt_inner = answer->rdata->u.ipv6;
2685                 LogInfo("AutoTunnelCallback: dst host %.16a", &tun->rmt_inner);
2686                 AssignDomainName(&question->qname, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
2687                 AppendDomainName(&question->qname, &tun->dstname);
2688                 question->qtype = kDNSType_SRV;
2689                 mDNS_StartQuery(m, &tun->q);
2690                 }
2691         else if (question->qtype == kDNSType_SRV)
2692                 {
2693                 LogInfo("AutoTunnelCallback: SRV target name %##s", answer->rdata->u.srv.target.c);
2694                 AssignDomainName(&tun->q.qname, &answer->rdata->u.srv.target);
2695                 tun->rmt_outer_port = answer->rdata->u.srv.port;
2696                 question->qtype = kDNSType_A;
2697                 mDNS_StartQuery(m, &tun->q);
2698                 }
2699         else if (question->qtype == kDNSType_A)
2700                 {
2701                 LogInfo("AutoTunnelCallback: SRV target addr %.4a", &answer->rdata->u.ipv4);
2702                 question->ThisQInterval = -1;           // So we know this tunnel setup has completed
2703                 tun->rmt_outer = answer->rdata->u.ipv4;
2704                 tun->loc_inner = m->AutoTunnelHostAddr;
2705                 mDNSAddr tmpDst = { mDNSAddrType_IPv4, {{{0}}} };
2706                 tmpDst.ip.v4 = tun->rmt_outer;
2707                 mDNSAddr tmpSrc = zeroAddr;
2708                 mDNSPlatformSourceAddrForDest(&tmpSrc, &tmpDst);
2709                 if (tmpSrc.type == mDNSAddrType_IPv4) tun->loc_outer = tmpSrc.ip.v4;
2710                 else tun->loc_outer = m->AdvertisedV4.ip.v4;
2711
2712                 ClientTunnel **p = &tun->next;
2713                 mDNSBool needSetKeys = mDNStrue;
2714                 while (*p)
2715                         {
2716                         if (!mDNSSameClientTunnel(&(*p)->rmt_inner, &tun->rmt_inner)) p = &(*p)->next;
2717                         else
2718                                 {
2719                                 ClientTunnel *old = *p;
2720                                 *p = old->next;
2721                                 LogInfo("Found existing AutoTunnel for %##s %.16a", tun->dstname.c, &tun->rmt_inner);
2722                                 if (old->q.ThisQInterval >= 0) mDNS_StopQuery(m, &old->q);
2723                                 else if (!mDNSSameIPv6Address(old->loc_inner, tun->loc_inner) ||
2724                                                  !mDNSSameIPv4Address(old->loc_outer, tun->loc_outer) ||
2725                                                  !mDNSSameIPv6Address(old->rmt_inner, tun->rmt_inner) ||
2726                                                  !mDNSSameIPv4Address(old->rmt_outer, tun->rmt_outer) ||
2727                                                  !mDNSSameIPPort(old->rmt_outer_port, tun->rmt_outer_port))
2728                                         {
2729                                         LogInfo("Deleting existing AutoTunnel for %##s %.16a", tun->dstname.c, &tun->rmt_inner);
2730                                         AutoTunnelSetKeys(old, mDNSfalse);
2731                                         }
2732                                 else needSetKeys = mDNSfalse;
2733
2734                                 LogInfo("AutoTunnelCallback: Disposing ClientTunnel %p", tun);
2735                                 freeL("ClientTunnel", old);
2736                                 }
2737                         }
2738
2739                 if (needSetKeys) LogInfo("New AutoTunnel for %##s %.16a", tun->dstname.c, &tun->rmt_inner);
2740
2741                 if (m->AutoTunnelHostAddr.b[0]) { mDNS_Lock(m); SetupLocalAutoTunnelInterface_internal(m); mDNS_Unlock(m); };
2742
2743                 mStatus result = needSetKeys ? AutoTunnelSetKeys(tun, mDNStrue) : mStatus_NoError;
2744                 static char msgbuf[32];
2745                 mDNS_snprintf(msgbuf, sizeof(msgbuf), "Tunnel setup - %d", result);
2746                 mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.config", result ? "failure" : "success", msgbuf, "");
2747                 // Kick off any questions that were held pending this tunnel setup
2748                 ReissueBlockedQuestions(m, &tun->dstname, (result == mStatus_NoError) ? mDNStrue : mDNSfalse);
2749                 }
2750         else
2751                 LogMsg("AutoTunnelCallback: Unknown question %p", question);
2752         }
2753
2754 // Must be called with the lock held
2755 mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
2756         {
2757         ClientTunnel *p = mallocL("ClientTunnel", sizeof(ClientTunnel));
2758         if (!p) return;
2759         AssignDomainName(&p->dstname, &q->qname);
2760         p->MarkedForDeletion = mDNSfalse;
2761         p->loc_inner      = zerov6Addr;
2762         p->loc_outer      = zerov4Addr;
2763         p->rmt_inner      = zerov6Addr;
2764         p->rmt_outer      = zerov4Addr;
2765         p->rmt_outer_port = zeroIPPort;
2766         p->next = m->TunnelClients;
2767         m->TunnelClients = p;           // We intentionally build list in reverse order
2768
2769         p->q.InterfaceID      = mDNSInterface_Any;
2770         p->q.Target           = zeroAddr;
2771         AssignDomainName(&p->q.qname, &q->qname);
2772         p->q.qtype            = kDNSType_AAAA;
2773         p->q.qclass           = kDNSClass_IN;
2774         p->q.LongLived        = mDNSfalse;
2775         p->q.ExpectUnique     = mDNStrue;
2776         p->q.ForceMCast       = mDNSfalse;
2777         p->q.ReturnIntermed   = mDNStrue;
2778         p->q.QuestionCallback = AutoTunnelCallback;
2779         p->q.QuestionContext  = p;
2780
2781         LogInfo("AddNewClientTunnel start tun %p %##s (%s)%s", p, &q->qname.c, DNSTypeName(q->qtype), q->LongLived ? " LongLived" : "");
2782         mDNS_StartQuery_internal(m, &p->q);
2783         }
2784
2785 #endif // APPLE_OSX_mDNSResponder
2786
2787 #if COMPILER_LIKES_PRAGMA_MARK
2788 #pragma mark -
2789 #pragma mark - Power State & Configuration Change Management
2790 #endif
2791
2792 mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
2793         {
2794         mDNSBool foundav4           = mDNSfalse;
2795         mDNSBool foundav6           = mDNSfalse;
2796         struct ifaddrs *ifa         = myGetIfAddrs(1);
2797         struct ifaddrs *v4Loopback  = NULL;
2798         struct ifaddrs *v6Loopback  = NULL;
2799         char defaultname[64];
2800 #ifndef NO_IPV6
2801         int InfoSocket              = socket(AF_INET6, SOCK_DGRAM, 0);
2802         if (InfoSocket < 3 && errno != EAFNOSUPPORT) LogMsg("UpdateInterfaceList: InfoSocket error %d errno %d (%s)", InfoSocket, errno, strerror(errno));
2803 #endif
2804         if (m->SleepState == SleepState_Sleeping) ifa = NULL;
2805
2806         while (ifa)
2807                 {
2808 #if LIST_ALL_INTERFACES
2809                 if (ifa->ifa_addr->sa_family == AF_APPLETALK)
2810                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_APPLETALK",
2811                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2812                 else if (ifa->ifa_addr->sa_family == AF_LINK)
2813                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_LINK",
2814                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2815                 else if (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6)
2816                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)",
2817                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2818                 if (!(ifa->ifa_flags & IFF_UP))
2819                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_UP",
2820                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2821                 if (!(ifa->ifa_flags & IFF_MULTICAST))
2822                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_MULTICAST",
2823                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2824                 if (ifa->ifa_flags & IFF_POINTOPOINT)
2825                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_POINTOPOINT",
2826                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2827                 if (ifa->ifa_flags & IFF_LOOPBACK)
2828                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_LOOPBACK",
2829                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2830 #endif
2831
2832                 if (ifa->ifa_addr->sa_family == AF_LINK)
2833                         {
2834                         struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr;
2835                         if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == sizeof(m->PrimaryMAC) && mDNSSameEthAddress(&m->PrimaryMAC, &zeroEthAddr))
2836                                 mDNSPlatformMemCopy(m->PrimaryMAC.b, sdl->sdl_data + sdl->sdl_nlen, 6);
2837                         }
2838
2839                 if (ifa->ifa_flags & IFF_UP && ifa->ifa_addr)
2840                         if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6)
2841                                 {
2842                                 if (!ifa->ifa_netmask)
2843                                         {
2844                                         mDNSAddr ip;
2845                                         SetupAddr(&ip, ifa->ifa_addr);
2846                                         LogMsg("getifaddrs: ifa_netmask is NULL for %5s(%d) Flags %04X Family %2d %#a",
2847                                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family, &ip);
2848                                         }
2849                                 // Apparently it's normal for the sa_family of an ifa_netmask to sometimes be zero, so we don't complain about that
2850                                 // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
2851                                 else if (ifa->ifa_netmask->sa_family != ifa->ifa_addr->sa_family && ifa->ifa_netmask->sa_family != 0)
2852                                         {
2853                                         mDNSAddr ip;
2854                                         SetupAddr(&ip, ifa->ifa_addr);
2855                                         LogMsg("getifaddrs ifa_netmask for %5s(%d) Flags %04X Family %2d %#a has different family: %d",
2856                                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family, &ip, ifa->ifa_netmask->sa_family);
2857                                         }
2858                                         // Currently we use a few internal ones like mDNSInterfaceID_LocalOnly etc. that are negative values (0, -1, -2).
2859                                 else if ((int)if_nametoindex(ifa->ifa_name) <= 0)
2860                                         {
2861                                         LogMsg("UpdateInterfaceList: if_nametoindex returned zero/negative value for %5s(%d)", ifa->ifa_name, if_nametoindex(ifa->ifa_name));
2862                                         }
2863                                 else
2864                                         {
2865                                         // Make sure ifa_netmask->sa_family is set correctly
2866                                         // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
2867                                         ifa->ifa_netmask->sa_family = ifa->ifa_addr->sa_family;
2868                                         int ifru_flags6 = 0;
2869 #ifndef NO_IPV6
2870                                         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
2871                                         if (ifa->ifa_addr->sa_family == AF_INET6 && InfoSocket >= 0)
2872                                                 {
2873                                                 struct in6_ifreq ifr6;
2874                                                 mDNSPlatformMemZero((char *)&ifr6, sizeof(ifr6));
2875                                                 strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
2876                                                 ifr6.ifr_addr = *sin6;
2877                                                 if (ioctl(InfoSocket, SIOCGIFAFLAG_IN6, &ifr6) != -1)
2878                                                         ifru_flags6 = ifr6.ifr_ifru.ifru_flags6;
2879                                                 verbosedebugf("%s %.16a %04X %04X", ifa->ifa_name, &sin6->sin6_addr, ifa->ifa_flags, ifru_flags6);
2880                                                 }
2881 #endif
2882                                         if (!(ifru_flags6 & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY)))
2883                                                 {
2884                                                 if (ifa->ifa_flags & IFF_LOOPBACK)
2885                                                         {
2886                                                         if (ifa->ifa_addr->sa_family == AF_INET)     v4Loopback = ifa;
2887 #ifndef NO_IPV6
2888                                                         else if (sin6->sin6_addr.s6_addr[0] != 0xFD) v6Loopback = ifa;
2889 #endif
2890                                                         }
2891                                                 else
2892                                                         {
2893                                                         NetworkInterfaceInfoOSX *i = AddInterfaceToList(m, ifa, utc);
2894                                                         if (i && MulticastInterface(i) && i->ifinfo.Advertise)
2895                                                                 {
2896                                                                 if (ifa->ifa_addr->sa_family == AF_INET) foundav4 = mDNStrue;
2897                                                                 else                                     foundav6 = mDNStrue;
2898                                                                 }
2899                                                         }
2900                                                 }
2901                                         }
2902                                 }
2903                 ifa = ifa->ifa_next;
2904                 }
2905
2906         // For efficiency, we don't register a loopback interface when other interfaces of that family are available and advertising
2907         if (!foundav4 && v4Loopback) AddInterfaceToList(m, v4Loopback, utc);
2908         if (!foundav6 && v6Loopback) AddInterfaceToList(m, v6Loopback, utc);
2909
2910         // Now the list is complete, set the McastTxRx setting for each interface.
2911         NetworkInterfaceInfoOSX *i;
2912         for (i = m->p->InterfaceList; i; i = i->next)
2913                 if (i->Exists)
2914                         {
2915                         mDNSBool txrx = MulticastInterface(i);
2916 #if USE_V6_ONLY_WHEN_NO_ROUTABLE_V4
2917                         txrx = txrx && ((i->ifinfo.ip.type == mDNSAddrType_IPv4) || !FindRoutableIPv4(m, i->scope_id));
2918 #endif
2919                         if (i->ifinfo.McastTxRx != txrx)
2920                                 {
2921                                 i->ifinfo.McastTxRx = txrx;
2922                                 i->Exists = 2; // State change; need to deregister and reregister this interface
2923                                 }
2924                         }
2925
2926 #ifndef NO_IPV6
2927         if (InfoSocket >= 0) close(InfoSocket);
2928 #endif
2929
2930         // If we haven't set up AutoTunnelHostAddr yet, do it now
2931         if (!mDNSSameEthAddress(&m->PrimaryMAC, &zeroEthAddr) && m->AutoTunnelHostAddr.b[0] == 0)
2932                 {
2933                 m->AutoTunnelHostAddr.b[0x0] = 0xFD;            // Required prefix for "locally assigned" ULA (See RFC 4193)
2934                 m->AutoTunnelHostAddr.b[0x1] = mDNSRandom(255);
2935                 m->AutoTunnelHostAddr.b[0x2] = mDNSRandom(255);
2936                 m->AutoTunnelHostAddr.b[0x3] = mDNSRandom(255);
2937                 m->AutoTunnelHostAddr.b[0x4] = mDNSRandom(255);
2938                 m->AutoTunnelHostAddr.b[0x5] = mDNSRandom(255);
2939                 m->AutoTunnelHostAddr.b[0x6] = mDNSRandom(255);
2940                 m->AutoTunnelHostAddr.b[0x7] = mDNSRandom(255);
2941                 m->AutoTunnelHostAddr.b[0x8] = m->PrimaryMAC.b[0] ^ 0x02;       // See RFC 3513, Appendix A for explanation
2942                 m->AutoTunnelHostAddr.b[0x9] = m->PrimaryMAC.b[1];
2943                 m->AutoTunnelHostAddr.b[0xA] = m->PrimaryMAC.b[2];
2944                 m->AutoTunnelHostAddr.b[0xB] = 0xFF;
2945                 m->AutoTunnelHostAddr.b[0xC] = 0xFE;
2946                 m->AutoTunnelHostAddr.b[0xD] = m->PrimaryMAC.b[3];
2947                 m->AutoTunnelHostAddr.b[0xE] = m->PrimaryMAC.b[4];
2948                 m->AutoTunnelHostAddr.b[0xF] = m->PrimaryMAC.b[5];
2949                 m->AutoTunnelLabel.c[0] = mDNS_snprintf((char*)m->AutoTunnelLabel.c+1, 254, "AutoTunnel-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
2950                         m->AutoTunnelHostAddr.b[0x8], m->AutoTunnelHostAddr.b[0x9], m->AutoTunnelHostAddr.b[0xA], m->AutoTunnelHostAddr.b[0xB],
2951                         m->AutoTunnelHostAddr.b[0xC], m->AutoTunnelHostAddr.b[0xD], m->AutoTunnelHostAddr.b[0xE], m->AutoTunnelHostAddr.b[0xF]);
2952                 LogInfo("m->AutoTunnelLabel %#s", m->AutoTunnelLabel.c);
2953                 }
2954         
2955         mDNS_snprintf(defaultname, sizeof(defaultname), "%.*s-%02X%02X%02X%02X%02X%02X", HINFO_HWstring_prefixlen, HINFO_HWstring,
2956                 m->PrimaryMAC.b[0], m->PrimaryMAC.b[1], m->PrimaryMAC.b[2], m->PrimaryMAC.b[3], m->PrimaryMAC.b[4], m->PrimaryMAC.b[5]);
2957
2958         // Set up the nice label
2959         domainlabel nicelabel;
2960         nicelabel.c[0] = 0;
2961         GetUserSpecifiedFriendlyComputerName(&nicelabel);
2962         if (nicelabel.c[0] == 0)
2963                 {
2964                 debugf("Couldn’t read user-specified Computer Name; using default “%s” instead", defaultname);
2965                 MakeDomainLabelFromLiteralString(&nicelabel, defaultname);
2966                 }
2967
2968         // Set up the RFC 1034-compliant label
2969         domainlabel hostlabel;
2970         hostlabel.c[0] = 0;
2971         GetUserSpecifiedLocalHostName(&hostlabel);
2972         if (hostlabel.c[0] == 0)
2973                 {
2974                 debugf("Couldn’t read user-specified Local Hostname; using default “%s.local” instead", defaultname);
2975                 MakeDomainLabelFromLiteralString(&hostlabel, defaultname);
2976                 }
2977
2978         mDNSBool namechange = mDNSfalse;
2979
2980         // We use a case-sensitive comparison here because even though changing the capitalization
2981         // of the name alone is not significant to DNS, it's still a change from the user's point of view
2982         if (SameDomainLabelCS(m->p->usernicelabel.c, nicelabel.c))
2983                 debugf("Usernicelabel (%#s) unchanged since last time; not changing m->nicelabel (%#s)", m->p->usernicelabel.c, m->nicelabel.c);
2984         else
2985                 {
2986                 if (m->p->usernicelabel.c[0])   // Don't show message first time through, when we first read name from prefs on boot
2987                         LogMsg("User updated Computer Name from “%#s” to “%#s”", m->p->usernicelabel.c, nicelabel.c);
2988                 m->p->usernicelabel = m->nicelabel = nicelabel;
2989                 namechange = mDNStrue;
2990                 }
2991
2992         if (SameDomainLabelCS(m->p->userhostlabel.c, hostlabel.c))
2993                 debugf("Userhostlabel (%#s) unchanged since last time; not changing m->hostlabel (%#s)", m->p->userhostlabel.c, m->hostlabel.c);
2994         else
2995                 {
2996                 if (m->p->userhostlabel.c[0])   // Don't show message first time through, when we first read name from prefs on boot
2997                         LogMsg("User updated Local Hostname from “%#s” to “%#s”", m->p->userhostlabel.c, hostlabel.c);
2998                 m->p->userhostlabel = m->hostlabel = hostlabel;
2999                 mDNS_SetFQDN(m);
3000                 namechange = mDNStrue;
3001                 }
3002
3003 #if APPLE_OSX_mDNSResponder
3004         if (namechange)         // If either name has changed, we need to tickle our AutoTunnel state machine to update its registered records
3005                 {
3006                 DomainAuthInfo *info;
3007                 for (info = m->AuthInfoList; info; info = info->next)
3008                         if (info->AutoTunnelNAT.clientContext && !mDNSIPv4AddressIsOnes(info->AutoTunnelNAT.ExternalAddress))
3009                                 AutoTunnelNATCallback(m, &info->AutoTunnelNAT);
3010                 }
3011 #endif // APPLE_OSX_mDNSResponder
3012
3013         return(mStatus_NoError);
3014         }
3015
3016 // Returns number of leading one-bits in mask: 0-32 for IPv4, 0-128 for IPv6
3017 // Returns -1 if all the one-bits are not contiguous
3018 mDNSlocal int CountMaskBits(mDNSAddr *mask)
3019         {
3020         int i = 0, bits = 0;
3021         int bytes = mask->type == mDNSAddrType_IPv4 ? 4 : mask->type == mDNSAddrType_IPv6 ? 16 : 0;
3022         while (i < bytes)
3023                 {
3024                 mDNSu8 b = mask->ip.v6.b[i++];
3025                 while (b & 0x80) { bits++; b <<= 1; }
3026                 if (b) return(-1);
3027                 }
3028         while (i < bytes) if (mask->ip.v6.b[i++]) return(-1);
3029         return(bits);
3030         }
3031
3032 // returns count of non-link local V4 addresses registered
3033 mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
3034         {
3035         NetworkInterfaceInfoOSX *i;
3036         int count = 0;
3037         for (i = m->p->InterfaceList; i; i = i->next)
3038                 if (i->Exists)
3039                         {
3040                         NetworkInterfaceInfo *const n = &i->ifinfo;
3041                         NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifinfo.ifname, AAAA_OVER_V4 ? AF_UNSPEC : i->sa_family);
3042                         if (!primary) LogMsg("SetupActiveInterfaces ERROR! SearchForInterfaceByName didn't find %s", i->ifinfo.ifname);
3043
3044                         if (i->Registered && i->Registered != primary)  // Sanity check
3045                                 {
3046                                 LogMsg("SetupActiveInterfaces ERROR! n->Registered %p != primary %p", i->Registered, primary);
3047                                 i->Registered = mDNSNULL;
3048                                 }
3049
3050                         if (!i->Registered)
3051                                 {
3052                                 // Note: If i->Registered is set, that means we've called mDNS_RegisterInterface() for this interface,
3053                                 // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
3054                                 // If i->Registered is NOT set, then we haven't registered it and we should not try to deregister it
3055                                 //
3056
3057                                 i->Registered = primary;
3058
3059                                 // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away.
3060                                 // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds.
3061                                 // 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.
3062                                 i->Occulting = !(i->ifa_flags & IFF_LOOPBACK) && (utc - i->LastSeen > 0 && utc - i->LastSeen < 60);
3063
3064                                 mDNS_RegisterInterface(m, n, i->Flashing && i->Occulting);
3065
3066                                 if (!mDNSAddressIsLinkLocal(&n->ip)) count++;
3067                                 LogInfo("SetupActiveInterfaces:   Registered    %5s(%lu) %.6a InterfaceID %p(%p), primary %p, %#a/%d%s%s%s",
3068                                         i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, i, primary, &n->ip, CountMaskBits(&n->mask),
3069                                         i->Flashing        ? " (Flashing)"  : "",
3070                                         i->Occulting       ? " (Occulting)" : "",
3071                                         n->InterfaceActive ? " (Primary)"   : "");
3072
3073                                 if (!n->McastTxRx)
3074                                         debugf("SetupActiveInterfaces:   No Tx/Rx on   %5s(%lu) %.6a InterfaceID %p %#a", i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, &n->ip);
3075                                 else
3076                                         {
3077                                         if (i->sa_family == AF_INET)
3078                                                 {
3079                                                 struct ip_mreq imr;
3080                                                 primary->ifa_v4addr.s_addr = n->ip.ip.v4.NotAnInteger;
3081