9b4a364d723b1f8a5a8349d81ecd6911ac26c782
[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 = 11;
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         debugf("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                         debugf("doSSLHandshake: %p calling doTcpSocketCallback", sock);
814                         doTcpSocketCallback(sock);
815                         }
816                 }
817         
818         debugf("SSLHandshake %p: dropping lock", sock);
819         KQueueUnlock(m, "doSSLHandshake");
820         return NULL;
821         }
822
823 mDNSlocal mStatus spawnSSLHandshake(TCPSocket* sock)
824         {
825         debugf("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         debugf("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         if (dst->type != mDNSAddrType_IPv4)
984                 {
985                 LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: opperation not supported");
986                 return mStatus_UnknownErr;
987                 }
988
989         mDNSPlatformMemZero(&saddr, sizeof(saddr));
990         saddr.sin_family      = AF_INET;
991         saddr.sin_port        = dstport.NotAnInteger;
992         saddr.sin_len         = sizeof(saddr);
993         saddr.sin_addr.s_addr = dst->ip.v4.NotAnInteger;
994
995         sock->kqEntry.KQcallback = tcpKQSocketCallback;
996         sock->kqEntry.KQcontext  = sock;
997         sock->kqEntry.KQtask     = "Outgoing TCP";
998
999         // Watch for connect complete (write is ready)
1000         // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it in tcpKQSocketCallback using EV_DELETE
1001         if (KQueueSet(sock->fd, EV_ADD /* | EV_ONESHOT */, EVFILT_WRITE, &sock->kqEntry))
1002                 {
1003                 LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
1004                 close(sock->fd);
1005                 return errno;
1006                 }
1007
1008         // Watch for incoming data
1009         if (KQueueSet(sock->fd, EV_ADD, EVFILT_READ, &sock->kqEntry))
1010                 {
1011                 LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
1012                 close(sock->fd); // Closing the descriptor removes all filters from the kqueue
1013                 return errno;
1014                 }
1015
1016         if (fcntl(sock->fd, F_SETFL, fcntl(sock->fd, F_GETFL, 0) | O_NONBLOCK) < 0) // set non-blocking
1017                 {
1018                 LogMsg("ERROR: setsockopt O_NONBLOCK - %s", strerror(errno));
1019                 return mStatus_UnknownErr;
1020                 }
1021
1022         // We bind to the interface and all subsequent packets including the SYN will be sent out
1023         // on this interface
1024 #ifdef IP_BOUND_IF
1025         if (InterfaceID)
1026                 {
1027                 extern mDNS mDNSStorage;
1028                 NetworkInterfaceInfoOSX *info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
1029                 if (info) setsockopt(sock->fd, IPPROTO_IP, IP_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
1030                 else { LogMsg("mDNSPlatformTCPConnect: Invalid interface index %p", InterfaceID); return mStatus_BadParamErr; }
1031                 }
1032 #else
1033         (void)InterfaceID; // Unused
1034 #endif
1035         // initiate connection wth peer
1036         if (connect(sock->fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
1037                 {
1038                 if (errno == EINPROGRESS) return mStatus_ConnPending;
1039                 if (errno == EHOSTUNREACH || errno == EADDRNOTAVAIL || errno == ENETDOWN)
1040                         LogInfo("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s)", sock->fd, errno, strerror(errno));
1041                 else
1042                         LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s)", sock->fd, errno, strerror(errno));
1043                 close(sock->fd);
1044                 return mStatus_ConnFailed;
1045                 }
1046
1047         LogMsg("NOTE: mDNSPlatformTCPConnect completed synchronously");
1048         // kQueue should notify us, but this LogMsg is to help track down if it doesn't
1049         return err;
1050         }
1051
1052 // Why doesn't mDNSPlatformTCPAccept actually call accept() ?
1053 mDNSexport TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int fd)
1054         {
1055         mStatus err = mStatus_NoError;
1056
1057         TCPSocket *sock = mallocL("TCPSocket/mDNSPlatformTCPAccept", sizeof(TCPSocket));
1058         if (!sock) return(mDNSNULL);
1059
1060         mDNSPlatformMemZero(sock, sizeof(*sock));
1061         sock->fd = fd;
1062         sock->flags = flags;
1063
1064         if (flags & kTCPSocketFlags_UseTLS)
1065                 {
1066 #ifndef NO_SECURITYFRAMEWORK
1067                 if (!ServerCerts) { LogMsg("ERROR: mDNSPlatformTCPAccept: unable to find TLS certificates"); err = mStatus_UnknownErr; goto exit; }
1068
1069                 err = tlsSetupSock(sock, mDNStrue);
1070                 if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: tlsSetupSock failed with error code: %d", err); goto exit; }
1071
1072                 err = SSLSetCertificate(sock->tlsContext, ServerCerts);
1073                 if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: SSLSetCertificate failed with error code: %d", err); goto exit; }
1074 #else
1075                 err = mStatus_UnsupportedErr;
1076 #endif /* NO_SECURITYFRAMEWORK */
1077                 }
1078 #ifndef NO_SECURITYFRAMEWORK
1079 exit:
1080 #endif
1081
1082         if (err) { freeL("TCPSocket/mDNSPlatformTCPAccept", sock); return(mDNSNULL); }
1083         return(sock);
1084         }
1085
1086 mDNSexport void mDNSPlatformTCPCloseConnection(TCPSocket *sock)
1087         {
1088         if (sock)
1089                 {       
1090 #ifndef NO_SECURITYFRAMEWORK
1091                 if (sock->tlsContext)
1092                         {
1093                         if (sock->handshake == handshake_in_progress) // SSLHandshake thread using this sock (esp. tlsContext)
1094                                 {
1095                                 LogInfo("mDNSPlatformTCPCloseConnection: called while handshake in progress");
1096                                 sock->handshake = handshake_to_be_closed;
1097                                 }
1098                         if (sock->handshake == handshake_to_be_closed)
1099                                 return;
1100
1101                         SSLClose(sock->tlsContext);
1102                         SSLDisposeContext(sock->tlsContext);
1103                         sock->tlsContext = NULL;
1104                         }
1105 #endif /* NO_SECURITYFRAMEWORK */
1106                 if (sock->fd != -1)
1107                         {
1108                         shutdown(sock->fd, 2);
1109                         close(sock->fd);
1110                         sock->fd = -1;
1111                         }
1112
1113                 freeL("TCPSocket/mDNSPlatformTCPCloseConnection", sock);
1114                 }
1115         }
1116
1117 mDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed)
1118         {
1119         size_t nread = 0;
1120         *closed = mDNSfalse;
1121
1122         if (sock->flags & kTCPSocketFlags_UseTLS)
1123                 {
1124 #ifndef NO_SECURITYFRAMEWORK
1125                 if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformReadTCP called while handshake required"); return 0; }
1126                 else if (sock->handshake == handshake_in_progress) return 0;
1127                 else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformReadTCP called with unexpected SSLHandshake status: %d", sock->handshake);
1128
1129                 //LogMsg("Starting SSLRead %d %X", sock->fd, fcntl(sock->fd, F_GETFL, 0));
1130                 mStatus err = SSLRead(sock->tlsContext, buf, buflen, &nread);
1131                 //LogMsg("SSLRead returned %d (%d) nread %d buflen %d", err, errSSLWouldBlock, nread, buflen);
1132                 if (err == errSSLClosedGraceful) { nread = 0; *closed = mDNStrue; }
1133                 else if (err && err != errSSLWouldBlock)
1134                         { LogMsg("ERROR: mDNSPlatformReadTCP - SSLRead: %d", err); nread = -1; *closed = mDNStrue; }
1135 #else
1136                 nread = -1;
1137                 *closed = mDNStrue;
1138 #endif /* NO_SECURITYFRAMEWORK */
1139                 }
1140         else
1141                 {
1142                 static int CLOSEDcount = 0;
1143                 static int EAGAINcount = 0;
1144                 nread = recv(sock->fd, buf, buflen, 0);
1145
1146                 if (nread > 0) { CLOSEDcount = 0; EAGAINcount = 0; } // On success, clear our error counters
1147                 else if (nread == 0)
1148                         {
1149                         *closed = mDNStrue;
1150                         if ((++CLOSEDcount % 1000) == 0) { LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got CLOSED %d times", sock->fd, CLOSEDcount); sleep(1); }
1151                         }
1152                 // else nread is negative -- see what kind of error we got
1153                 else if (errno == ECONNRESET) { nread = 0; *closed = mDNStrue; }
1154                 else if (errno != EAGAIN) { LogMsg("ERROR: mDNSPlatformReadTCP - recv: %d (%s)", errno, strerror(errno)); nread = -1; }
1155                 else // errno is EAGAIN (EWOULDBLOCK) -- no data available
1156                         {
1157                         nread = 0;
1158                         if ((++EAGAINcount % 1000) == 0) { LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got EAGAIN %d times", sock->fd, EAGAINcount); sleep(1); }
1159                         }
1160                 }
1161
1162         return nread;
1163         }
1164
1165 mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len)
1166         {
1167         int nsent;
1168
1169         if (sock->flags & kTCPSocketFlags_UseTLS)
1170                 {
1171 #ifndef NO_SECURITYFRAMEWORK
1172                 size_t  processed;
1173                 if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformWriteTCP called while handshake required"); return 0; }
1174                 if (sock->handshake == handshake_in_progress) return 0;
1175                 else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformWriteTCP called with unexpected SSLHandshake status: %d", sock->handshake);
1176                 
1177                 mStatus err = SSLWrite(sock->tlsContext, msg, len, &processed);
1178
1179                 if (!err) nsent = (int) processed;
1180                 else if (err == errSSLWouldBlock) nsent = 0;
1181                 else { LogMsg("ERROR: mDNSPlatformWriteTCP - SSLWrite returned %d", err); nsent = -1; }
1182 #else
1183                 nsent = -1;
1184 #endif /* NO_SECURITYFRAMEWORK */
1185                 }
1186         else
1187                 {
1188                 nsent = send(sock->fd, msg, len, 0);
1189                 if (nsent < 0)
1190                         {
1191                         if (errno == EAGAIN) nsent = 0;
1192                         else { LogMsg("ERROR: mDNSPlatformWriteTCP - send %s", strerror(errno)); nsent = -1; }
1193                         }
1194                 }
1195
1196         return nsent;
1197         }
1198
1199 mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
1200         {
1201         return sock->fd;
1202         }
1203
1204 // If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
1205 // If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
1206 mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa_family, mDNSIPPort *const outport)
1207         {
1208 #ifndef NO_IPV6
1209         int         *s        = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
1210         KQueueEntry     *k        = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
1211 #else
1212         int         *s        = &cp->sktv4;
1213         KQueueEntry     *k        = &cp->kqsv4;
1214 #endif
1215         const int on = 1;
1216         const int twofivefive = 255;
1217         mStatus err = mStatus_NoError;
1218         char *errstr = mDNSNULL;
1219
1220 #ifdef NO_IPV6
1221         if (sa_family != AF_INET) return -1;
1222 #endif
1223         
1224         cp->closeFlag = mDNSNULL;
1225
1226         int skt = socket(sa_family, SOCK_DGRAM, IPPROTO_UDP);
1227         if (skt < 3) { if (errno != EAFNOSUPPORT) LogMsg("SetupSocket: socket error %d errno %d (%s)", skt, errno, strerror(errno)); return(skt); }
1228
1229         // ... with a shared UDP port, if it's for multicast receiving
1230         if (mDNSSameIPPort(port, MulticastDNSPort) || mDNSSameIPPort(port, NATPMPAnnouncementPort)) err = setsockopt(skt, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
1231         if (err < 0) { errstr = "setsockopt - SO_REUSEPORT"; goto fail; }
1232
1233         if (sa_family == AF_INET)
1234                 {
1235                 // We want to receive destination addresses
1236                 err = setsockopt(skt, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
1237                 if (err < 0) { errstr = "setsockopt - IP_RECVDSTADDR"; goto fail; }
1238
1239                 // We want to receive interface identifiers
1240                 err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
1241                 if (err < 0) { errstr = "setsockopt - IP_RECVIF"; goto fail; }
1242
1243                 // We want to receive packet TTL value so we can check it
1244                 err = setsockopt(skt, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
1245                 // We ignore errors here -- we already know Jaguar doesn't support this, but we can get by without it
1246
1247                 // Send unicast packets with TTL 255
1248                 err = setsockopt(skt, IPPROTO_IP, IP_TTL, &twofivefive, sizeof(twofivefive));
1249                 if (err < 0) { errstr = "setsockopt - IP_TTL"; goto fail; }
1250
1251                 // And multicast packets with TTL 255 too
1252                 err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_TTL, &twofivefive, sizeof(twofivefive));
1253                 if (err < 0) { errstr = "setsockopt - IP_MULTICAST_TTL"; goto fail; }
1254
1255                 // And start listening for packets
1256                 struct sockaddr_in listening_sockaddr;
1257                 listening_sockaddr.sin_family      = AF_INET;
1258                 listening_sockaddr.sin_port        = port.NotAnInteger;         // Pass in opaque ID without any byte swapping
1259                 listening_sockaddr.sin_addr.s_addr = mDNSSameIPPort(port, NATPMPAnnouncementPort) ? AllSystemsMcast.NotAnInteger : 0;
1260                 err = bind(skt, (struct sockaddr *) &listening_sockaddr, sizeof(listening_sockaddr));
1261                 if (err) { errstr = "bind"; goto fail; }
1262                 if (outport) outport->NotAnInteger = listening_sockaddr.sin_port;
1263                 }
1264 #ifndef NO_IPV6
1265         else if (sa_family == AF_INET6)
1266                 {
1267                 // NAT-PMP Announcements make no sense on IPv6, so bail early w/o error
1268                 if (mDNSSameIPPort(port, NATPMPAnnouncementPort)) { if (outport) *outport = zeroIPPort; return mStatus_NoError; }
1269                 
1270                 // We want to receive destination addresses and receive interface identifiers
1271                 err = setsockopt(skt, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on));
1272                 if (err < 0) { errstr = "setsockopt - IPV6_PKTINFO"; goto fail; }
1273
1274                 // We want to receive packet hop count value so we can check it
1275                 err = setsockopt(skt, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));
1276                 if (err < 0) { errstr = "setsockopt - IPV6_HOPLIMIT"; goto fail; }
1277
1278                 // We want to receive only IPv6 packets. Without this option we get IPv4 packets too,
1279                 // with mapped addresses of the form 0:0:0:0:0:FFFF:xxxx:xxxx, where xxxx:xxxx is the IPv4 address
1280                 err = setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
1281                 if (err < 0) { errstr = "setsockopt - IPV6_V6ONLY"; goto fail; }
1282
1283                 // Send unicast packets with TTL 255
1284                 err = setsockopt(skt, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &twofivefive, sizeof(twofivefive));
1285                 if (err < 0) { errstr = "setsockopt - IPV6_UNICAST_HOPS"; goto fail; }
1286
1287                 // And multicast packets with TTL 255 too
1288                 err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &twofivefive, sizeof(twofivefive));
1289                 if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_HOPS"; goto fail; }
1290
1291                 // Want to receive our own packets
1292                 err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &on, sizeof(on));
1293                 if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_LOOP"; goto fail; }
1294
1295                 // And start listening for packets
1296                 struct sockaddr_in6 listening_sockaddr6;
1297                 mDNSPlatformMemZero(&listening_sockaddr6, sizeof(listening_sockaddr6));
1298                 listening_sockaddr6.sin6_len         = sizeof(listening_sockaddr6);
1299                 listening_sockaddr6.sin6_family      = AF_INET6;
1300                 listening_sockaddr6.sin6_port        = port.NotAnInteger;               // Pass in opaque ID without any byte swapping
1301                 listening_sockaddr6.sin6_flowinfo    = 0;
1302                 listening_sockaddr6.sin6_addr        = in6addr_any; // Want to receive multicasts AND unicasts on this socket
1303                 listening_sockaddr6.sin6_scope_id    = 0;
1304                 err = bind(skt, (struct sockaddr *) &listening_sockaddr6, sizeof(listening_sockaddr6));
1305                 if (err) { errstr = "bind"; goto fail; }
1306                 if (outport) outport->NotAnInteger = listening_sockaddr6.sin6_port;
1307                 }
1308 #endif
1309
1310         fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
1311         fcntl(skt, F_SETFD, 1); // set close-on-exec
1312         *s = skt;
1313         k->KQcallback = myKQSocketCallBack;
1314         k->KQcontext  = cp;
1315         k->KQtask     = "UDP packet reception";
1316         KQueueSet(*s, EV_ADD, EVFILT_READ, k);
1317
1318         return(err);
1319
1320         fail:
1321         // For "bind" failures, only write log messages for our shared mDNS port, or for binding to zero
1322         if (strcmp(errstr, "bind") || mDNSSameIPPort(port, MulticastDNSPort) || mDNSIPPortIsZero(port))
1323                 LogMsg("%s skt %d port %d error %d errno %d (%s)", errstr, skt, mDNSVal16(port), err, errno, strerror(errno));
1324
1325         // If we got a "bind" failure of EADDRINUSE, inform the caller as it might need to try another random port
1326         if (!strcmp(errstr, "bind") && errno == EADDRINUSE)
1327                 {
1328                 err = EADDRINUSE;
1329                 if (mDNSSameIPPort(port, MulticastDNSPort))
1330                         NotifyOfElusiveBug("Setsockopt SO_REUSEPORT failed",
1331                                 "Congratulations, you've reproduced an elusive bug.\r"
1332                                 "Please contact the current assignee of <rdar://problem/3814904>.\r"
1333                                 "Alternatively, you can send email to radar-3387020@group.apple.com. (Note number is different.)\r"
1334                                 "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
1335                 }
1336
1337         close(skt);
1338         return(err);
1339         }
1340
1341 mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
1342         {
1343         mStatus err;
1344         mDNSIPPort port = requestedport;
1345         mDNSBool randomizePort = mDNSIPPortIsZero(requestedport);
1346         int i = 10000; // Try at most 10000 times to get a unique random port
1347         UDPSocket *p = mallocL("UDPSocket", sizeof(UDPSocket));
1348         if (!p) { LogMsg("mDNSPlatformUDPSocket: memory exhausted"); return(mDNSNULL); }
1349         mDNSPlatformMemZero(p, sizeof(UDPSocket));
1350         p->ss.port  = zeroIPPort;
1351         p->ss.m     = m;
1352         p->ss.sktv4 = -1;
1353 #ifndef NO_IPV6
1354         p->ss.sktv6 = -1;
1355 #endif
1356
1357         do
1358                 {
1359                 // The kernel doesn't do cryptographically strong random port allocation, so we do it ourselves here
1360                 if (randomizePort) port = mDNSOpaque16fromIntVal(0xC000 + mDNSRandom(0x3FFF));
1361                 err = SetupSocket(&p->ss, port, AF_INET, &p->ss.port);
1362 #ifndef NO_IPV6
1363                 if (!err)
1364                         {
1365                         err = SetupSocket(&p->ss, port, AF_INET6, &p->ss.port);
1366                         if (err) { close(p->ss.sktv4); p->ss.sktv4 = -1; }
1367                         }
1368 #endif
1369                 i--;
1370                 } while (err == EADDRINUSE && randomizePort && i);
1371
1372         if (err)
1373                 {
1374                 // In customer builds we don't want to log failures with port 5351, because this is a known issue
1375                 // of failing to bind to this port when Internet Sharing has already bound to it
1376                 // We also don't want to log about port 5350, due to a known bug when some other
1377                 // process is bound to it.
1378                 if (mDNSSameIPPort(requestedport, NATPMPPort) || mDNSSameIPPort(requestedport, NATPMPAnnouncementPort))
1379                         LogInfo("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
1380                 else LogMsg("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
1381                 freeL("UDPSocket", p);
1382                 return(mDNSNULL);
1383                 }
1384         return(p);
1385         }
1386
1387 mDNSlocal void CloseSocketSet(KQSocketSet *ss)
1388         {
1389         if (ss->sktv4 != -1)
1390                 {
1391                 close(ss->sktv4);
1392                 ss->sktv4 = -1;
1393                 }
1394 #ifndef NO_IPV6
1395         if (ss->sktv6 != -1)
1396                 {
1397                 close(ss->sktv6);
1398                 ss->sktv6 = -1;
1399                 }
1400 #endif
1401         if (ss->closeFlag) *ss->closeFlag = 1;
1402         }
1403
1404 mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock)
1405         {
1406         CloseSocketSet(&sock->ss);
1407         freeL("UDPSocket", sock);
1408         }
1409
1410 #if COMPILER_LIKES_PRAGMA_MARK
1411 #pragma mark -
1412 #pragma mark - BPF Raw packet sending/receiving
1413 #endif
1414
1415 #if APPLE_OSX_mDNSResponder
1416
1417 mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
1418         {
1419         if (!InterfaceID) { LogMsg("mDNSPlatformSendRawPacket: No InterfaceID specified"); return; }
1420         NetworkInterfaceInfoOSX *info;
1421
1422         extern mDNS mDNSStorage;
1423         info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
1424         if (info == NULL)
1425                 {
1426                 LogMsg("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
1427                 return;
1428                 }
1429         if (info->BPF_fd < 0)
1430                 LogMsg("mDNSPlatformSendRawPacket: %s BPF_fd %d not ready", info->ifinfo.ifname, info->BPF_fd);
1431         else
1432                 {
1433                 //LogMsg("mDNSPlatformSendRawPacket %d bytes on %s", end - (mDNSu8 *)msg, info->ifinfo.ifname);
1434                 if (write(info->BPF_fd, msg, end - (mDNSu8 *)msg) < 0)
1435                         LogMsg("mDNSPlatformSendRawPacket: BPF write(%d) failed %d (%s)", info->BPF_fd, errno, strerror(errno));
1436                 }
1437         }
1438
1439 mDNSexport void mDNSPlatformSetLocalARP(const mDNSv4Addr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
1440         {
1441         if (!InterfaceID) { LogMsg("mDNSPlatformSetLocalARP: No InterfaceID specified"); return; }
1442         NetworkInterfaceInfoOSX *info;
1443         extern mDNS mDNSStorage;
1444         info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
1445         if (info == NULL)
1446                 {
1447                 LogMsg("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
1448                 return;
1449                 }
1450         // Manually inject an entry into our local ARP cache.
1451         // (We can't do this by sending an ARP broadcast, because the kernel only pays attention to incoming ARP packets, not outgoing.)
1452         mDNSBool makearp = mDNSv4AddressIsLinkLocal(tpa);
1453         if (!makearp)
1454                 {
1455                 NetworkInterfaceInfoOSX *i;
1456                 for (i = info->m->p->InterfaceList; i; i = i->next)
1457                         if (i->Exists && i->ifinfo.InterfaceID == InterfaceID && i->ifinfo.ip.type == mDNSAddrType_IPv4)
1458                                 if (((i->ifinfo.ip.ip.v4.NotAnInteger ^ tpa->NotAnInteger) & i->ifinfo.mask.ip.v4.NotAnInteger) == 0)
1459                                         makearp = mDNStrue;
1460                 }
1461         if (!makearp)
1462                 LogInfo("Don't need ARP entry for %s %.4a %.6a",            info->ifinfo.ifname, tpa, tha);
1463         else
1464                 {
1465                 int result = mDNSSetARP(info->scope_id, tpa->b, tha->b);
1466                 if (result) LogMsg("Set local ARP entry for %s %.4a %.6a failed: %d", info->ifinfo.ifname, tpa, tha, result);
1467                 else debugf       ("Set local ARP entry for %s %.4a %.6a",            info->ifinfo.ifname, tpa, tha);
1468                 }
1469         }
1470
1471 mDNSlocal void CloseBPF(NetworkInterfaceInfoOSX *const i)
1472         {
1473         LogSPS("%s closing BPF fd %d", i->ifinfo.ifname, i->BPF_fd);
1474
1475         // Note: MUST NOT close() the underlying native BSD sockets.
1476         // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately, because
1477         // it first has to unhook the sockets from its select() call on its other thread, before it can safely close them.
1478         CFRunLoopRemoveSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode);
1479         CFRelease(i->BPF_rls);
1480         CFSocketInvalidate(i->BPF_cfs);
1481         CFRelease(i->BPF_cfs);
1482         i->BPF_fd = -1;
1483         }
1484
1485 mDNSlocal void bpf_callback(const CFSocketRef cfs, const CFSocketCallBackType CallBackType, const CFDataRef address, const void *const data, void *const context)
1486         {
1487         (void)cfs;
1488         (void)CallBackType;
1489         (void)address;
1490         (void)data;
1491
1492         NetworkInterfaceInfoOSX *const info = (NetworkInterfaceInfoOSX *)context;
1493         KQueueLock(info->m);
1494
1495         // 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
1496         // kernel has a mechanism for dispatching all events to a single thread, but for now we have to guard against this race condition).
1497         if (info->BPF_fd < 0) goto exit;
1498
1499         ssize_t n = read(info->BPF_fd, &info->m->imsg, info->BPF_len);
1500         const mDNSu8 *ptr = (const mDNSu8 *)&info->m->imsg;
1501         const mDNSu8 *end = (const mDNSu8 *)&info->m->imsg + n;
1502         debugf("%3d: bpf_callback got %d bytes on %s", info->BPF_fd, n, info->ifinfo.ifname);
1503
1504         if (n<0)
1505                 {
1506                 LogMsg("Closing %s BPF fd %d due to error %d (%s)", info->ifinfo.ifname, info->BPF_fd, errno, strerror(errno));
1507                 CloseBPF(info);
1508                 goto exit;
1509                 }
1510
1511         while (ptr < end)
1512                 {
1513                 const struct bpf_hdr *bh = (const struct bpf_hdr *)ptr;
1514                 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)));
1515                 mDNSCoreReceiveRawPacket(info->m, ptr + bh->bh_hdrlen, ptr + bh->bh_hdrlen + bh->bh_caplen, info->ifinfo.InterfaceID);
1516                 ptr += BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen);
1517                 }
1518 exit:
1519         KQueueUnlock(info->m, "bpf_callback");
1520         }
1521
1522 #define BPF_SetOffset(from, cond, to) (from)->cond = (to) - 1 - (from)
1523
1524 mDNSlocal int CountProxyTargets(mDNS *const m, NetworkInterfaceInfoOSX *x, int *p4, int *p6)
1525         {
1526         int numv4 = 0, numv6 = 0;
1527         AuthRecord *rr;
1528
1529         for (rr = m->ResourceRecords; rr; rr=rr->next)
1530                 if (rr->resrec.InterfaceID == x->ifinfo.InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4)
1531                         {
1532                         if (p4) LogSPS("CountProxyTargets: fd %d %-7s IP%2d %.4a", x->BPF_fd, x->ifinfo.ifname, numv4, &rr->AddressProxy.ip.v4);
1533                         numv4++;
1534                         }
1535
1536         for (rr = m->ResourceRecords; rr; rr=rr->next)
1537                 if (rr->resrec.InterfaceID == x->ifinfo.InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv6)
1538                         {
1539                         if (p6) LogSPS("CountProxyTargets: fd %d %-7s IP%2d %.16a", x->BPF_fd, x->ifinfo.ifname, numv6, &rr->AddressProxy.ip.v6);
1540                         numv6++;
1541                         }
1542
1543         if (p4) *p4 = numv4;
1544         if (p6) *p6 = numv6;
1545         return(numv4 + numv6);
1546         }
1547
1548 mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
1549         {
1550         NetworkInterfaceInfoOSX *x;
1551
1552         //NOTE: We can't use IfIndexToInterfaceInfoOSX because that looks for Registered also.
1553         for (x = m->p->InterfaceList; x; x = x->next) if (x->ifinfo.InterfaceID == InterfaceID) break;
1554
1555         if (!x) { LogMsg("mDNSPlatformUpdateProxyList: ERROR InterfaceID %p not found", InterfaceID); return; }
1556
1557         #define MAX_BPF_ADDRS 250
1558         int numv4 = 0, numv6 = 0;
1559
1560         if (CountProxyTargets(m, x, &numv4, &numv6) > MAX_BPF_ADDRS)
1561                 {
1562                 LogMsg("mDNSPlatformUpdateProxyList: ERROR Too many address proxy records v4 %d v6 %d", numv4, numv6);
1563                 if (numv4 > MAX_BPF_ADDRS) numv4 = MAX_BPF_ADDRS;
1564                 numv6 = MAX_BPF_ADDRS - numv4;
1565                 }
1566
1567         LogSPS("mDNSPlatformUpdateProxyList: fd %d %-7s MAC  %.6a %d v4 %d v6", x->BPF_fd, x->ifinfo.ifname, &x->ifinfo.MAC, numv4, numv6);
1568
1569         // Caution: This is a static structure, so we need to be careful that any modifications we make to it
1570         // are done in such a way that they work correctly when mDNSPlatformUpdateProxyList is called multiple times
1571         static struct bpf_insn filter[17 + MAX_BPF_ADDRS] =
1572                 {
1573                 BPF_STMT(BPF_LD  + BPF_H   + BPF_ABS, 12),                              // 0 Read Ethertype (bytes 12,13)
1574
1575                 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0806, 0, 1),              // 1 If Ethertype == ARP goto next, else 3
1576                 BPF_STMT(BPF_RET + BPF_K,             42),                              // 2 Return 42-byte ARP
1577
1578                 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0800, 4, 0),              // 3 If Ethertype == IPv4 goto 8 (IPv4 address list check) else next
1579
1580                 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x86DD, 0, 9),              // 4 If Ethertype == IPv6 goto next, else exit
1581                 BPF_STMT(BPF_LD  + BPF_H   + BPF_ABS, 20),                              // 5 Read Protocol and Hop Limit (bytes 20,21)
1582                 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x3AFF, 0, 9),              // 6 If (Prot,TTL) == (3A,FF) goto next, else IPv6 address list check
1583                 BPF_STMT(BPF_RET + BPF_K,             78),                              // 7 Return 78-byte ND
1584
1585                 // Is IPv4 packet; check if it's addressed to any IPv4 address we're proxying for
1586                 BPF_STMT(BPF_LD  + BPF_W   + BPF_ABS, 30),                              // 8 Read IPv4 Dst (bytes 30,31,32,33)
1587                 };
1588
1589         struct bpf_insn *pc   = &filter[9];
1590         struct bpf_insn *chk6 = pc   + numv4 + 1;       // numv4 address checks, plus a "return 0"
1591         struct bpf_insn *fail = chk6 + 1 + numv6;       // Get v6 Dst LSW, plus numv6 address checks
1592         struct bpf_insn *ret4 = fail + 1;
1593         struct bpf_insn *ret6 = ret4 + 4;
1594
1595         static const struct bpf_insn rf  = BPF_STMT(BPF_RET + BPF_K, 0);                                // No match: Return nothing
1596
1597         static const struct bpf_insn g6  = BPF_STMT(BPF_LD  + BPF_W   + BPF_ABS, 50);   // Read IPv6 Dst LSW (bytes 50,51,52,53)
1598
1599         static const struct bpf_insn r4a = BPF_STMT(BPF_LDX + BPF_B   + BPF_MSH, 14);   // Get IP Header length (normally 20)
1600         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)
1601         static const struct bpf_insn r4c = BPF_STMT(BPF_ALU + BPF_ADD + BPF_X,    0);   // A += IP Header length
1602         static const struct bpf_insn r4d = BPF_STMT(BPF_RET + BPF_A, 0);                                // Success: Return Ethernet + IP + TCP + 20 bytes spare (normally 74)
1603
1604         static const struct bpf_insn r6a = BPF_STMT(BPF_RET + BPF_K, 94);                               // Success: Return Eth + IPv6 + TCP + 20 bytes spare
1605
1606         BPF_SetOffset(&filter[4], jf, fail);    // If Ethertype not ARP, IPv4, or IPv6, fail
1607         BPF_SetOffset(&filter[6], jf, chk6);    // If IPv6 but not ICMPv6, go to IPv6 address list check
1608
1609         // BPF Byte-Order Note
1610         // The BPF API designers apparently thought that programmers would not be smart enough to use htons
1611         // and htonl correctly to convert numeric values to network byte order on little-endian machines,
1612         // so instead they chose to make the API implicitly byte-swap *ALL* values, even literal byte strings
1613         // that shouldn't be byte-swapped, like ASCII text, Ethernet addresses, IP addresses, etc.
1614         // As a result, if we put Ethernet addresses and IP addresses in the right byte order, the BPF API
1615         // will byte-swap and make them backwards, and then our filter won't work. So, we have to arrange
1616         // that on little-endian machines we deliberately put addresses in memory with the bytes backwards,
1617         // so that when the BPF API goes through and swaps them all, they end up back as they should be.
1618         // In summary, if we byte-swap all the non-numeric fields that shouldn't be swapped, and we *don't*
1619         // swap any of the numeric values that *should* be byte-swapped, then the filter will work correctly.
1620
1621         // IPSEC capture size notes:
1622         //  8 bytes UDP header
1623         //  4 bytes Non-ESP Marker
1624         // 28 bytes IKE Header
1625         // --
1626         // 40 Total. Capturing TCP Header + 20 gets us enough bytes to receive the IKE Header in a UDP-encapsulated IKE packet.
1627
1628         AuthRecord *rr;
1629         for (rr = m->ResourceRecords; rr; rr=rr->next)
1630                 if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4)
1631                         {
1632                         mDNSv4Addr a = rr->AddressProxy.ip.v4;
1633                         pc->code = BPF_JMP + BPF_JEQ + BPF_K;
1634                         BPF_SetOffset(pc, jt, ret4);
1635                         pc->jf   = 0;
1636                         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];
1637                         pc++;
1638                         }
1639         *pc++ = rf;
1640
1641         if (pc != chk6) LogMsg("mDNSPlatformUpdateProxyList: pc %p != chk6 %p", pc, chk6);
1642         *pc++ = g6;     // chk6 points here
1643
1644         for (rr = m->ResourceRecords; rr; rr=rr->next)
1645                 if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv6)
1646                         {
1647                         mDNSv6Addr a = rr->AddressProxy.ip.v6;
1648                         pc->code = BPF_JMP + BPF_JEQ + BPF_K;
1649                         BPF_SetOffset(pc, jt, ret6);
1650                         pc->jf   = 0;
1651                         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];
1652                         pc++;
1653                         }
1654
1655         if (pc != fail) LogMsg("mDNSPlatformUpdateProxyList: pc %p != fail %p", pc, fail);
1656         *pc++ = rf;     // fail points here
1657
1658         if (pc != ret4) LogMsg("mDNSPlatformUpdateProxyList: pc %p != ret4 %p", pc, ret4);
1659         *pc++ = r4a;    // ret4 points here
1660         *pc++ = r4b;
1661         *pc++ = r4c;
1662         *pc++ = r4d;
1663
1664         if (pc != ret6) LogMsg("mDNSPlatformUpdateProxyList: pc %p != ret6 %p", pc, ret6);
1665         *pc++ = r6a;    // ret6 points here
1666
1667         struct bpf_program prog = { pc - filter, filter };
1668
1669 #if 0
1670         // For debugging BPF filter program
1671         unsigned int q;
1672         for (q=0; q<prog.bf_len; q++)
1673                 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);
1674 #endif
1675
1676         if (!numv4 && !numv6)
1677                 {
1678                 LogSPS("mDNSPlatformUpdateProxyList: No need for filter");
1679                 if (m->timenow == 0) LogMsg("mDNSPlatformUpdateProxyList: m->timenow == 0");
1680                 // Schedule check to see if we can close this BPF_fd now
1681                 if (!m->p->NetworkChanged) m->p->NetworkChanged = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2);
1682                 // prog.bf_len = 0; This seems to panic the kernel
1683                 if (x->BPF_fd < 0) return;              // If we've already closed our BPF_fd, no need to generate an error message below
1684                 }
1685
1686         if (ioctl(x->BPF_fd, BIOCSETF, &prog) < 0) LogMsg("mDNSPlatformUpdateProxyList: BIOCSETF(%d) failed %d (%s)", prog.bf_len, errno, strerror(errno));
1687         else LogSPS("mDNSPlatformUpdateProxyList: BIOCSETF(%d) successful", prog.bf_len);
1688         }
1689
1690 mDNSexport void mDNSPlatformReceiveBPF_fd(mDNS *const m, int fd)
1691         {
1692         mDNS_Lock(m);
1693         
1694         NetworkInterfaceInfoOSX *i;
1695         for (i = m->p->InterfaceList; i; i = i->next) if (i->BPF_fd == -2) break;
1696         if (!i) { LogSPS("mDNSPlatformReceiveBPF_fd: No Interfaces awaiting BPF fd %d; closing", fd); close(fd); }
1697         else
1698                 {
1699                 LogSPS("%s using   BPF fd %d", i->ifinfo.ifname, fd);
1700         
1701                 struct bpf_version v;
1702                 if (ioctl(fd, BIOCVERSION, &v) < 0)
1703                         LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCVERSION failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
1704                 else if (BPF_MAJOR_VERSION != v.bv_major || BPF_MINOR_VERSION != v.bv_minor)
1705                         LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCVERSION header %d.%d kernel %d.%d",
1706                                 fd, i->ifinfo.ifname, BPF_MAJOR_VERSION, BPF_MINOR_VERSION, v.bv_major, v.bv_minor);
1707         
1708                 if (ioctl(fd, BIOCGBLEN, &i->BPF_len) < 0)
1709                         LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCGBLEN failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
1710         
1711                 if (i->BPF_len > sizeof(m->imsg))
1712                         {
1713                         i->BPF_len = sizeof(m->imsg);
1714                         if (ioctl(fd, BIOCSBLEN, &i->BPF_len) < 0)
1715                                 LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCSBLEN failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
1716                         else LogSPS("mDNSPlatformReceiveBPF_fd: %d %s BIOCSBLEN %d", i->BPF_len);
1717                         }
1718         
1719                 static const u_int opt_immediate = 1;
1720                 if (ioctl(fd, BIOCIMMEDIATE, &opt_immediate) < 0)
1721                         LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCIMMEDIATE failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
1722         
1723                 struct ifreq ifr;
1724                 mDNSPlatformMemZero(&ifr, sizeof(ifr));
1725                 strlcpy(ifr.ifr_name, i->ifinfo.ifname, sizeof(ifr.ifr_name));
1726                 if (ioctl(fd, BIOCSETIF, &ifr) < 0)
1727                         { LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCSETIF failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno)); i->BPF_fd = -3; }
1728                 else
1729                         {
1730                         CFSocketContext myCFSocketContext = { 0, i, NULL, NULL, NULL };
1731                         i->BPF_fd  = fd;
1732                         i->BPF_cfs = CFSocketCreateWithNative(kCFAllocatorDefault, fd, kCFSocketReadCallBack, bpf_callback, &myCFSocketContext);
1733                         i->BPF_rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, i->BPF_cfs, 0);
1734                         CFRunLoopAddSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode);
1735                         mDNSPlatformUpdateProxyList(m, i->ifinfo.InterfaceID);
1736                         }
1737                 }
1738
1739         mDNS_Unlock(m);
1740         }
1741
1742 #endif // APPLE_OSX_mDNSResponder
1743
1744 #if COMPILER_LIKES_PRAGMA_MARK
1745 #pragma mark -
1746 #pragma mark - Key Management
1747 #endif
1748
1749 #ifndef NO_SECURITYFRAMEWORK
1750 mDNSlocal CFArrayRef GetCertChain(SecIdentityRef identity)
1751         {
1752         CFMutableArrayRef certChain = NULL;
1753         if (!identity) { LogMsg("getCertChain: identity is NULL"); return(NULL); }
1754         SecCertificateRef cert;
1755         OSStatus err = SecIdentityCopyCertificate(identity, &cert);
1756         if (err || !cert) LogMsg("getCertChain: SecIdentityCopyCertificate() returned %d", (int) err);
1757         else
1758                 {
1759                 SecPolicySearchRef searchRef;
1760                 err = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &searchRef);
1761                 if (err || !searchRef) LogMsg("getCertChain: SecPolicySearchCreate() returned %d", (int) err);
1762                 else
1763                         {
1764                         SecPolicyRef policy;
1765                         err = SecPolicySearchCopyNext(searchRef, &policy);
1766                         if (err || !policy) LogMsg("getCertChain: SecPolicySearchCopyNext() returned %d", (int) err);
1767                         else
1768                                 {
1769                                 CFArrayRef wrappedCert = CFArrayCreate(NULL, (const void**) &cert, 1, &kCFTypeArrayCallBacks);
1770                                 if (!wrappedCert) LogMsg("getCertChain: wrappedCert is NULL");
1771                                 else
1772                                         {
1773                                         SecTrustRef trust;
1774                                         err = SecTrustCreateWithCertificates(wrappedCert, policy, &trust);
1775                                         if (err || !trust) LogMsg("getCertChain: SecTrustCreateWithCertificates() returned %d", (int) err);
1776                                         else
1777                                                 {
1778                                                 err = SecTrustEvaluate(trust, NULL);
1779                                                 if (err) LogMsg("getCertChain: SecTrustEvaluate() returned %d", (int) err);
1780                                                 else
1781                                                         {
1782                                                         CFArrayRef rawCertChain;
1783                                                         CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
1784                                                         err = SecTrustGetResult(trust, NULL, &rawCertChain, &statusChain);
1785                                                         if (err || !rawCertChain || !statusChain) LogMsg("getCertChain: SecTrustGetResult() returned %d", (int) err);
1786                                                         else
1787                                                                 {
1788                                                                 certChain = CFArrayCreateMutableCopy(NULL, 0, rawCertChain);
1789                                                                 if (!certChain) LogMsg("getCertChain: certChain is NULL");
1790                                                                 else
1791                                                                         {
1792                                                                         // Replace the SecCertificateRef at certChain[0] with a SecIdentityRef per documentation for SSLSetCertificate:
1793                                                                         // <http://devworld.apple.com/documentation/Security/Reference/secureTransportRef/index.html>
1794                                                                         CFArraySetValueAtIndex(certChain, 0, identity);
1795                                                                         // Remove root from cert chain, but keep any and all intermediate certificates that have been signed by the root certificate
1796                                                                         if (CFArrayGetCount(certChain) > 1) CFArrayRemoveValueAtIndex(certChain, CFArrayGetCount(certChain) - 1);
1797                                                                         }
1798                                                                 CFRelease(rawCertChain);
1799                                                                 // Do not free statusChain:
1800                                                                 // <http://developer.apple.com/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html> says:
1801                                                                 // certChain: Call the CFRelease function to release this object when you are finished with it.
1802                                                                 // statusChain: Do not attempt to free this pointer; it remains valid until the trust management object is released...
1803                                                                 }
1804                                                         }
1805                                                 CFRelease(trust);
1806                                                 }
1807                                         CFRelease(wrappedCert);
1808                                         }
1809                                 CFRelease(policy);
1810                                 }
1811                         CFRelease(searchRef);
1812                         }
1813                 CFRelease(cert);
1814                 }
1815         return certChain;
1816         }
1817 #endif /* NO_SECURITYFRAMEWORK */
1818
1819 mDNSexport mStatus mDNSPlatformTLSSetupCerts(void)
1820         {
1821 #ifdef NO_SECURITYFRAMEWORK
1822         return mStatus_UnsupportedErr;
1823 #else
1824         SecIdentityRef                  identity = nil;
1825         SecIdentitySearchRef    srchRef = nil;
1826         OSStatus                                err;
1827
1828         // search for "any" identity matching specified key use
1829         // In this app, we expect there to be exactly one
1830         err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_DECRYPT, &srchRef);
1831         if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCreate returned %d", (int) err); return err; }
1832
1833         err = SecIdentitySearchCopyNext(srchRef, &identity);
1834         if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext returned %d", (int) err); return err; }
1835
1836         if (CFGetTypeID(identity) != SecIdentityGetTypeID())
1837                 { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext CFTypeID failure"); return mStatus_UnknownErr; }
1838
1839         // Found one. Call getCertChain to create the correct certificate chain.
1840         ServerCerts = GetCertChain(identity);
1841         if (ServerCerts == nil) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: getCertChain error"); return mStatus_UnknownErr; }
1842
1843         return mStatus_NoError;
1844 #endif /* NO_SECURITYFRAMEWORK */
1845         }
1846
1847 mDNSexport  void  mDNSPlatformTLSTearDownCerts(void)
1848         {
1849 #ifndef NO_SECURITYFRAMEWORK
1850         if (ServerCerts) { CFRelease(ServerCerts); ServerCerts = NULL; }
1851 #endif /* NO_SECURITYFRAMEWORK */
1852         }
1853
1854 // This gets the text of the field currently labelled "Computer Name" in the Sharing Prefs Control Panel
1855 mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel)
1856         {
1857         CFStringEncoding encoding = kCFStringEncodingUTF8;
1858         CFStringRef cfs = SCDynamicStoreCopyComputerName(NULL, &encoding);
1859         if (cfs)
1860                 {
1861                 CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
1862                 CFRelease(cfs);
1863                 }
1864         }
1865
1866 // This gets the text of the field currently labelled "Local Hostname" in the Sharing Prefs Control Panel
1867 mDNSlocal void GetUserSpecifiedLocalHostName(domainlabel *const namelabel)
1868         {
1869         CFStringRef cfs = SCDynamicStoreCopyLocalHostName(NULL);
1870         if (cfs)
1871                 {
1872                 CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
1873                 CFRelease(cfs);
1874                 }
1875         }
1876
1877 mDNSexport mDNSBool DictionaryIsEnabled(CFDictionaryRef dict)
1878         {
1879         mDNSs32 val;
1880         CFNumberRef state = CFDictionaryGetValue(dict, CFSTR("Enabled"));
1881         if (!state) return mDNSfalse;
1882         if (!CFNumberGetValue(state, kCFNumberSInt32Type, &val))
1883                 { LogMsg("ERROR: DictionaryIsEnabled - CFNumberGetValue"); return mDNSfalse; }
1884         return val ? mDNStrue : mDNSfalse;
1885         }
1886
1887 mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
1888         {
1889         if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
1890
1891         if (sa->sa_family == AF_INET)
1892                 {
1893                 struct sockaddr_in *ifa_addr = (struct sockaddr_in *)sa;
1894                 ip->type = mDNSAddrType_IPv4;
1895                 ip->ip.v4.NotAnInteger = ifa_addr->sin_addr.s_addr;
1896                 return(mStatus_NoError);
1897                 }
1898
1899         if (sa->sa_family == AF_INET6)
1900                 {
1901                 struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa;
1902                 // Inside the BSD kernel they use a hack where they stuff the sin6->sin6_scope_id
1903                 // value into the second word of the IPv6 link-local address, so they can just
1904                 // pass around IPv6 address structures instead of full sockaddr_in6 structures.
1905                 // Those hacked IPv6 addresses aren't supposed to escape the kernel in that form, but they do.
1906                 // To work around this we always whack the second word of any IPv6 link-local address back to zero.
1907                 if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
1908                 ip->type = mDNSAddrType_IPv6;
1909                 ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr;
1910                 return(mStatus_NoError);
1911                 }
1912
1913         LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
1914         return(mStatus_Invalid);
1915         }
1916
1917 mDNSlocal mDNSEthAddr GetBSSID(char *ifa_name)
1918         {
1919         mDNSEthAddr eth = zeroEthAddr;
1920         SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetBSSID"), NULL, NULL);
1921         if (!store)
1922                 LogMsg("GetBSSID: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
1923         else
1924                 {
1925                 CFStringRef entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/AirPort"), ifa_name);
1926                 if (entityname)
1927                         {
1928                         CFDictionaryRef dict = SCDynamicStoreCopyValue(store, entityname);
1929                         if (dict)
1930                                 {
1931                                 CFRange range = { 0, 6 };               // Offset, length
1932                                 CFDataRef data = CFDictionaryGetValue(dict, CFSTR("BSSID"));
1933                                 if (data && CFDataGetLength(data) == 6) CFDataGetBytes(data, range, eth.b);
1934                                 CFRelease(dict);
1935                                 }
1936                         CFRelease(entityname);
1937                         }
1938                 CFRelease(store);
1939                 }
1940         return(eth);
1941         }
1942
1943 mDNSlocal int GetMAC(mDNSEthAddr *eth, u_short ifindex)
1944         {
1945         struct ifaddrs *ifa;
1946         for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next)
1947                 if (ifa->ifa_addr->sa_family == AF_LINK)
1948                         {
1949                         const struct sockaddr_dl *const sdl = (const struct sockaddr_dl *)ifa->ifa_addr;
1950                         if (sdl->sdl_index == ifindex)
1951                                 { mDNSPlatformMemCopy(eth->b, sdl->sdl_data + sdl->sdl_nlen, 6); return 0; }
1952                         }
1953         *eth = zeroEthAddr;
1954         return -1;
1955         }
1956
1957 #ifndef SIOCGIFWAKEFLAGS
1958 #define SIOCGIFWAKEFLAGS _IOWR('i', 136, struct ifreq) /* get interface wake property flags */
1959 #endif
1960
1961 #ifndef IF_WAKE_ON_MAGIC_PACKET
1962 #define IF_WAKE_ON_MAGIC_PACKET 0x01
1963 #endif
1964
1965 #ifndef ifr_wake_flags
1966 #define ifr_wake_flags ifr_ifru.ifru_intval
1967 #endif
1968
1969 mDNSlocal mDNSBool NetWakeInterface(NetworkInterfaceInfoOSX *i)
1970         {
1971         if (!MulticastInterface(i)     ) return(mDNSfalse);     // We only use Sleep Proxy Service on multicast-capable interfaces
1972         if (i->ifa_flags & IFF_LOOPBACK) return(mDNSfalse);     // except loopback
1973
1974         int s = socket(AF_INET, SOCK_DGRAM, 0);
1975         if (s < 0) { LogMsg("NetWakeInterface %s socket failed %s errno %d (%s)", i->ifinfo.ifname, errno, strerror(errno)); return(mDNSfalse); }
1976
1977         struct ifreq ifr;
1978         strlcpy(ifr.ifr_name, i->ifinfo.ifname, sizeof(ifr.ifr_name));
1979         if (ioctl(s, SIOCGIFWAKEFLAGS, &ifr) < 0)
1980                 {
1981                 // For some strange reason, in /usr/include/sys/errno.h, EOPNOTSUPP is defined to be
1982                 // 102 when compiling kernel code, and 45 when compiling user-level code. Since this
1983                 // error code is being returned from the kernel, we need to use the kernel version.
1984                 #define KERNEL_EOPNOTSUPP 102
1985                 if (errno != KERNEL_EOPNOTSUPP) // "Operation not supported on socket", the expected result on Leopard and earlier
1986                         LogMsg("NetWakeInterface SIOCGIFWAKEFLAGS %s errno %d (%s)", i->ifinfo.ifname, errno, strerror(errno));
1987                 // If on Leopard or earlier, we get EOPNOTSUPP, so in that case
1988                 // we enable WOL if this interface is not AirPort and "Wake for Network access" is turned on.
1989                 ifr.ifr_wake_flags = (errno == KERNEL_EOPNOTSUPP && !(i)->BSSID.l[0] && i->m->SystemWakeOnLANEnabled) ? IF_WAKE_ON_MAGIC_PACKET : 0;
1990                 }
1991 #if ASSUME_SNOWLEOPARD_INCORRECTLY_REPORTS_AIRPORT_INCAPABLE_OF_WAKE_ON_LAN
1992         else
1993                 {
1994                 // Call succeeded.
1995                 // However, on SnowLeopard, it currently indicates incorrectly that AirPort is incapable of Wake-on-LAN.
1996                 // Therefore, for AirPort interfaces, we just track the system-wide Wake-on-LAN setting.
1997                 if ((i)->BSSID.l[0]) ifr.ifr_wake_flags = i->m->SystemWakeOnLANEnabled ? IF_WAKE_ON_MAGIC_PACKET : 0;
1998                 }
1999 #endif
2000
2001         close(s);
2002
2003         // 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
2004
2005         LogSPS("%-6s %#-14a %s WOMP", i->ifinfo.ifname, &i->ifinfo.ip, (ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) ? "supports" : "no");
2006
2007         return((ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) != 0);
2008         }
2009
2010 // Returns pointer to newly created NetworkInterfaceInfoOSX object, or
2011 // pointer to already-existing NetworkInterfaceInfoOSX object found in list, or
2012 // may return NULL if out of memory (unlikely) or parameters are invalid for some reason
2013 // (e.g. sa_family not AF_INET or AF_INET6)
2014 mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifaddrs *ifa, mDNSs32 utc)
2015         {
2016         mDNSu32 scope_id  = if_nametoindex(ifa->ifa_name);
2017         mDNSEthAddr bssid = GetBSSID(ifa->ifa_name);
2018
2019         mDNSAddr ip, mask;
2020         if (SetupAddr(&ip,   ifa->ifa_addr   ) != mStatus_NoError) return(NULL);
2021         if (SetupAddr(&mask, ifa->ifa_netmask) != mStatus_NoError) return(NULL);
2022
2023         NetworkInterfaceInfoOSX **p;
2024         for (p = &m->p->InterfaceList; *p; p = &(*p)->next)
2025                 if (scope_id == (*p)->scope_id &&
2026                         mDNSSameAddress(&ip, &(*p)->ifinfo.ip) &&
2027                         mDNSSameEthAddress(&bssid, &(*p)->BSSID))
2028                         {
2029                         debugf("AddInterfaceToList: Found existing interface %lu %.6a with address %#a at %p", scope_id, &bssid, &ip, *p);
2030                         (*p)->Exists = mDNStrue;
2031                         // If interface was not in getifaddrs list last time we looked, but it is now, update 'AppearanceTime' for this record
2032                         if ((*p)->LastSeen != utc) (*p)->AppearanceTime = utc;
2033
2034                         // If Wake-on-LAN capability of this interface has changed (e.g. because power cable on laptop has been disconnected)
2035                         // we may need to start or stop or sleep proxy browse operation
2036                         const mDNSBool NetWake = NetWakeInterface(*p);
2037                         if ((*p)->ifinfo.NetWake != NetWake)
2038                                 {
2039                                 (*p)->ifinfo.NetWake = NetWake;
2040                                 // If this interface is already registered with mDNSCore, then we need to start or stop its NetWake browse on-the-fly.
2041                                 // If this interface is not already registered (i.e. it's a dormant interface we had in our list
2042                                 // from when we previously saw it) then we mustn't do that, because mDNSCore doesn't know about it yet.
2043                                 // In this case, the mDNS_RegisterInterface() call will take care of starting the NetWake browse if necessary.
2044                                 if ((*p)->Registered)
2045                                         {
2046                                         mDNS_Lock(m);
2047                                         if (NetWake) mDNS_ActivateNetWake_internal  (m, &(*p)->ifinfo);
2048                                         else         mDNS_DeactivateNetWake_internal(m, &(*p)->ifinfo);
2049                                         mDNS_Unlock(m);
2050                                         }
2051                                 }
2052
2053                         return(*p);
2054                         }
2055
2056         NetworkInterfaceInfoOSX *i = (NetworkInterfaceInfoOSX *)mallocL("NetworkInterfaceInfoOSX", sizeof(*i));
2057         debugf("AddInterfaceToList: Making   new   interface %lu %.6a with address %#a at %p", scope_id, &bssid, &ip, i);
2058         if (!i) return(mDNSNULL);
2059         mDNSPlatformMemZero(i, sizeof(NetworkInterfaceInfoOSX));
2060         i->ifinfo.InterfaceID = (mDNSInterfaceID)(uintptr_t)scope_id;
2061         i->ifinfo.ip          = ip;
2062         i->ifinfo.mask        = mask;
2063         strlcpy(i->ifinfo.ifname, ifa->ifa_name, sizeof(i->ifinfo.ifname));
2064         i->ifinfo.ifname[sizeof(i->ifinfo.ifname)-1] = 0;
2065         // We can be configured to disable multicast advertisement, but we want to to support
2066         // local-only services, which need a loopback address record.
2067         i->ifinfo.Advertise   = m->DivertMulticastAdvertisements ? ((ifa->ifa_flags & IFF_LOOPBACK) ? mDNStrue : mDNSfalse) : m->AdvertiseLocalAddresses;
2068         i->ifinfo.McastTxRx   = mDNSfalse; // For now; will be set up later at the end of UpdateInterfaceList
2069
2070         i->next            = mDNSNULL;
2071         i->m               = m;
2072         i->Exists          = mDNStrue;
2073         i->Flashing        = mDNSfalse;
2074         i->Occulting       = mDNSfalse;
2075         i->AppearanceTime  = utc;               // Brand new interface; AppearanceTime is now
2076         i->LastSeen        = utc;
2077         i->ifa_flags       = ifa->ifa_flags;
2078         i->scope_id        = scope_id;
2079         i->BSSID           = bssid;
2080         i->sa_family       = ifa->ifa_addr->sa_family;
2081         i->BPF_fd          = -1;
2082         i->BPF_len         = 0;
2083         i->Registered      = mDNSNULL;
2084
2085         // Do this AFTER i->BSSID has been set up
2086         i->ifinfo.NetWake  = NetWakeInterface(i);
2087         GetMAC(&i->ifinfo.MAC, scope_id);
2088         if (i->ifinfo.NetWake && !i->ifinfo.MAC.l[0])
2089                 LogMsg("AddInterfaceToList: Bad MAC address %.6a for %d %s %#a", &i->ifinfo.MAC, scope_id, i->ifinfo.ifname, &ip);
2090
2091         *p = i;
2092         return(i);
2093         }
2094
2095 #if USE_V6_ONLY_WHEN_NO_ROUTABLE_V4
2096 mDNSlocal NetworkInterfaceInfoOSX *FindRoutableIPv4(mDNS *const m, mDNSu32 scope_id)
2097         {
2098         NetworkInterfaceInfoOSX *i;
2099         for (i = m->p->InterfaceList; i; i = i->next)
2100                 if (i->Exists && i->scope_id == scope_id && i->ifinfo.ip.type == mDNSAddrType_IPv4)
2101                         if (!mDNSv4AddressIsLinkLocal(&i->ifinfo.ip.ip.v4))
2102                                 return(i);
2103         return(mDNSNULL);
2104         }
2105 #endif
2106
2107 #if APPLE_OSX_mDNSResponder
2108
2109 #if COMPILER_LIKES_PRAGMA_MARK
2110 #pragma mark -
2111 #pragma mark - AutoTunnel
2112 #endif
2113
2114 #define kRacoonPort 4500
2115
2116 static DomainAuthInfo* AnonymousRacoonConfig = mDNSNULL;
2117
2118 #ifndef NO_SECURITYFRAMEWORK
2119
2120 static CFMutableDictionaryRef domainStatusDict = NULL;
2121
2122 // MUST be called with lock held
2123 mDNSlocal void RemoveAutoTunnelDomainStatus(const mDNS *const m, const DomainAuthInfo *const info)
2124         {
2125         char buffer[1024];
2126         CFStringRef domain;
2127
2128         LogInfo("RemoveAutoTunnelDomainStatus: %##s", info->domain.c);
2129
2130         if (!domainStatusDict) { LogMsg("RemoveAutoTunnelDomainStatus: No domainStatusDict"); return; }
2131         
2132         buffer[mDNS_snprintf(buffer, sizeof(buffer), "%##s", info->domain.c) - 1] = 0;
2133         domain = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
2134         if (!domain) { LogMsg("RemoveAutoTunnelDomainStatus: Could not create CFString domain"); return; }
2135         
2136         if (CFDictionaryContainsKey(domainStatusDict, domain))
2137                 {
2138                 CFDictionaryRemoveValue(domainStatusDict, domain);
2139                 if (!m->ShutdownTime) mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, mDNSNULL, domainStatusDict);
2140                 }
2141         CFRelease(domain);
2142         }
2143
2144 mDNSlocal mStatus CheckQuestionForStatus(const DNSQuestion *const q)
2145         {
2146         if (q->LongLived)
2147                 {
2148                 if (q->nta || (q->servAddr.type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsOnes(q->servAddr.ip.v4)))
2149                         return mStatus_NoSuchRecord;
2150                 else if (q->state == LLQ_Poll)
2151                         return mStatus_PollingMode;
2152                 else if (q->state != LLQ_Established && !q->DuplicateOf)
2153                         return mStatus_TransientErr;
2154                 }
2155         
2156         return mStatus_NoError;
2157 }
2158
2159 #endif // ndef NO_SECURITYFRAMEWORK
2160
2161 // MUST be called with lock held
2162 mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAuthInfo *const info)
2163         {
2164 #ifdef NO_SECURITYFRAMEWORK
2165         (void)m;
2166         (void)info;
2167 #else
2168         const NATTraversalInfo *const llq = m->LLQNAT.clientContext ? &m->LLQNAT : mDNSNULL;
2169         const NATTraversalInfo *const tun = info->AutoTunnelNAT.clientContext ? &info->AutoTunnelNAT : mDNSNULL;
2170         char buffer[1024];
2171         CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2172         CFStringRef domain = NULL;
2173         CFStringRef tmp = NULL;
2174         CFNumberRef num = NULL;
2175         mStatus status = mStatus_NoError;
2176         
2177         if (!domainStatusDict)
2178                 {
2179                 domainStatusDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2180                 if (!domainStatusDict) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFDictionary domainStatusDict"); return; }
2181                 }
2182         
2183         if (!dict) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFDictionary dict"); return; }
2184
2185         buffer[mDNS_snprintf(buffer, sizeof(buffer), "%##s", info->domain.c) - 1] = 0;
2186         domain = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
2187         if (!domain) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString domain"); return; }
2188
2189         mDNS_snprintf(buffer, sizeof(buffer), "%#a", &m->Router);
2190         tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
2191         if (!tmp)
2192                 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString RouterAddress");
2193         else
2194                 {
2195                 CFDictionarySetValue(dict, CFSTR("RouterAddress"), tmp);
2196                 CFRelease(tmp);
2197                 }
2198         
2199         mDNS_snprintf(buffer, sizeof(buffer), "%.4a", &m->ExternalAddress);
2200         tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
2201         if (!tmp)
2202                 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString ExternalAddress");
2203         else
2204                 {
2205                 CFDictionarySetValue(dict, CFSTR("ExternalAddress"), tmp);
2206                 CFRelease(tmp);
2207                 }
2208         
2209         if (llq)
2210                 {
2211                 mDNSu32 port = mDNSVal16(llq->ExternalPort);
2212                 
2213                 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &port);
2214                 if (!num)
2215                         LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LLQExternalPort");
2216                 else
2217                         {
2218                         CFDictionarySetValue(dict, CFSTR("LLQExternalPort"), num);
2219                         CFRelease(num);
2220                         }
2221
2222                 if (llq->Result)
2223                         {
2224                         num = CFNumberCreate(NULL, kCFNumberSInt32Type, &llq->Result);
2225                         if (!num)
2226                                 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LLQNPMStatus");
2227                         else
2228                                 {
2229                                 CFDictionarySetValue(dict, CFSTR("LLQNPMStatus"), num);
2230                                 CFRelease(num);
2231                                 }
2232                         }
2233                 }
2234         
2235         if (tun)
2236                 {
2237                 mDNSu32 port = mDNSVal16(tun->ExternalPort);
2238                 
2239                 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &port);
2240                 if (!num)
2241                         LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber AutoTunnelExternalPort");
2242                 else
2243                         {
2244                         CFDictionarySetValue(dict, CFSTR("AutoTunnelExternalPort"), num);
2245                         CFRelease(num);
2246                         }
2247
2248                 if (tun->Result)
2249                         {
2250                         num = CFNumberCreate(NULL, kCFNumberSInt32Type, &tun->Result);
2251                         if (!num)
2252                                 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber AutoTunnelNPMStatus");
2253                         else
2254                                 {
2255                                 CFDictionarySetValue(dict, CFSTR("AutoTunnelNPMStatus"), num);
2256                                 CFRelease(num);
2257                                 }
2258                         }
2259                 }
2260         if (tun || llq)
2261                 {
2262                 mDNSu32 code = m->LastNATMapResultCode;
2263                 
2264                 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &code);
2265                 if (!num)
2266                         LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LastNATMapResultCode");
2267                 else
2268                         {
2269                         CFDictionarySetValue(dict, CFSTR("LastNATMapResultCode"), num);
2270                         CFRelease(num);
2271                         }
2272                 }
2273         
2274         if (!llq && !tun)
2275                 {
2276                 status = mStatus_NotInitializedErr;
2277                 mDNS_snprintf(buffer, sizeof(buffer), "Neither LLQ nor AutoTunnel NAT port mapping is currently active");
2278                 }
2279         else if ((llq && llq->Result == mStatus_DoubleNAT) || (tun && tun->Result == mStatus_DoubleNAT))
2280                 {
2281                 status = mStatus_DoubleNAT;
2282                 mDNS_snprintf(buffer, sizeof(buffer), "Double NAT: Router is reporting an external address");
2283                 }
2284         else if ((llq && llq->Result == mStatus_NATPortMappingDisabled) || (tun && tun->Result == mStatus_NATPortMappingDisabled) ||
2285                  (m->LastNATMapResultCode == NATErr_Refused && ((llq && !llq->Result && mDNSIPPortIsZero(llq->ExternalPort)) || (tun && !tun->Result && mDNSIPPortIsZero(tun->ExternalPort)))))
2286                 {
2287                 status = mStatus_NATPortMappingDisabled;
2288                 mDNS_snprintf(buffer, sizeof(buffer), "NAT-PMP is disabled on the router");
2289                 }
2290         else if ((llq && llq->Result) || (tun && tun->Result))
2291                 {
2292                 status = mStatus_NATTraversal;
2293                 mDNS_snprintf(buffer, sizeof(buffer), "Error obtaining NAT port mapping from router");
2294                 }
2295         else if (m->Router.type == mDNSAddrType_None)
2296                 {
2297                 status = mStatus_NoRouter;
2298                 mDNS_snprintf(buffer, sizeof(buffer), "No network connection - none");
2299                 }
2300         else if (m->Router.type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsZero(m->Router.ip.v4))
2301                 {
2302                 status = mStatus_NoRouter;
2303                 mDNS_snprintf(buffer, sizeof(buffer), "No network connection - v4 zero");
2304                 }
2305         else if ((llq && mDNSIPPortIsZero(llq->ExternalPort)) || (tun && mDNSIPPortIsZero(tun->ExternalPort)))
2306                 {
2307                 status = mStatus_NATTraversal;
2308                 mDNS_snprintf(buffer, sizeof(buffer), "Unable to obtain NAT port mapping from router");
2309                 }
2310         else
2311                 {
2312                 DNSQuestion* q, *worst_q = mDNSNULL;
2313                 for (q = m->Questions; q; q=q->next)
2314                         if (q->AuthInfo == info)
2315                                 {
2316                                 mStatus newStatus = CheckQuestionForStatus(q);
2317                                 if              (newStatus == mStatus_NoSuchRecord) { status = newStatus; worst_q = q; break; }
2318                                 else if (newStatus == mStatus_PollingMode)  { status = newStatus; worst_q = q; }
2319                                 else if (newStatus == mStatus_TransientErr && status == mStatus_NoError) { status = newStatus; worst_q = q; }
2320                                 }
2321                 
2322                 if      (status == mStatus_NoError)      mDNS_snprintf(buffer, sizeof(buffer), "Success");
2323                 else if (status == mStatus_NoSuchRecord) mDNS_snprintf(buffer, sizeof(buffer), "GetZoneData %s: %##s", worst_q->nta ? "not yet complete" : "failed", worst_q->qname.c);
2324                 else if (status == mStatus_PollingMode)  mDNS_snprintf(buffer, sizeof(buffer), "Query polling %##s", worst_q->qname.c);
2325                 else if (status == mStatus_TransientErr) mDNS_snprintf(buffer, sizeof(buffer), "Query not yet established %##s", worst_q->qname.c);
2326                 }
2327         
2328         num = CFNumberCreate(NULL, kCFNumberSInt32Type, &status);
2329         if (!num)
2330                 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber StatusCode");
2331         else
2332                 {
2333                 CFDictionarySetValue(dict, CFSTR("StatusCode"), num);
2334                 CFRelease(num);
2335                 }
2336                 
2337         tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
2338         if (!tmp)
2339                 LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString StatusMessage");
2340         else
2341                 {
2342                 CFDictionarySetValue(dict, CFSTR("StatusMessage"), tmp);
2343                 CFRelease(tmp);
2344                 }
2345
2346         if (!CFDictionaryContainsKey(domainStatusDict, domain) ||
2347             !CFEqual(dict, (CFMutableDictionaryRef)CFDictionaryGetValue(domainStatusDict, domain)))
2348             {
2349                 CFDictionarySetValue(domainStatusDict, domain, dict);
2350                 if (!m->ShutdownTime) 
2351                         {
2352                         static char statusBuf[16];
2353                         mDNS_snprintf(statusBuf, sizeof(statusBuf), "%d", (int)status);
2354                         mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.domainstatus", status ? "failure" : "success", statusBuf, "");
2355                         mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, mDNSNULL, domainStatusDict);
2356                         }
2357                 }
2358                 
2359         CFRelease(domain);
2360         CFRelease(dict);
2361
2362         debugf("UpdateAutoTunnelDomainStatus: %s", buffer);
2363 #endif // def NO_SECURITYFRAMEWORK
2364         }
2365
2366 // MUST be called with lock held
2367 mDNSexport void UpdateAutoTunnelDomainStatuses(const mDNS *const m)
2368         {
2369 #ifdef NO_SECURITYFRAMEWORK
2370         (void)m;
2371 #else
2372         DomainAuthInfo* info;
2373         for (info = m->AuthInfoList; info; info = info->next)
2374                 if (info->AutoTunnel && !info->deltime)
2375                         UpdateAutoTunnelDomainStatus(m, info);
2376 #endif // def NO_SECURITYFRAMEWORK
2377         }
2378         
2379 // MUST be called with lock held
2380 mDNSlocal mDNSBool TunnelServers(mDNS *const m)
2381         {
2382         ServiceRecordSet *p;
2383         for (p = m->ServiceRegistrations; p; p = p->uDNS_next)
2384                 {
2385                 DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, p->RR_SRV.resrec.name);
2386                 if (AuthInfo && AuthInfo->AutoTunnel && !AuthInfo->deltime) return(mDNStrue);
2387                 }
2388
2389         AuthRecord *r;
2390         for (r = m->ResourceRecords; r; r = r->next)
2391                 if (r->resrec.rrtype == kDNSType_SRV)
2392                         {
2393                         DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, r->resrec.name);
2394                         if (AuthInfo && AuthInfo->AutoTunnel && !AuthInfo->deltime) return(mDNStrue);
2395                         }
2396
2397         return(mDNSfalse);
2398         }
2399
2400 // MUST be called with lock held
2401 mDNSlocal mDNSBool TunnelClients(mDNS *const m)
2402         {
2403         ClientTunnel *p;
2404         for (p = m->TunnelClients; p; p = p->next)
2405                 if (p->q.ThisQInterval < 0)
2406                         return(mDNStrue);
2407         return(mDNSfalse);
2408         }
2409
2410 mDNSlocal void RegisterAutoTunnelRecords(mDNS *m, DomainAuthInfo *info)
2411         {
2412         if (info->AutoTunnelNAT.clientContext && !info->AutoTunnelNAT.Result && !mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort) && AutoTunnelUnregistered(info))
2413                 {
2414                 mStatus err;
2415                 LogInfo("RegisterAutoTunnelRecords %##s (%#s)", info->domain.c, m->hostlabel.c);
2416
2417                 // 1. Set up our address record for the internal tunnel address
2418                 // (User-visible user-friendly host name, used as target in AutoTunnel SRV records)
2419                 info->AutoTunnelHostRecord.namestorage.c[0] = 0;
2420                 AppendDomainLabel(&info->AutoTunnelHostRecord.namestorage, &m->hostlabel);
2421                 AppendDomainName (&info->AutoTunnelHostRecord.namestorage, &info->domain);
2422                 info->AutoTunnelHostRecord.resrec.rdata->u.ipv6 = m->AutoTunnelHostAddr;
2423                 info->AutoTunnelHostRecord.resrec.RecordType = kDNSRecordTypeKnownUnique;
2424                 err = mDNS_Register(m, &info->AutoTunnelHostRecord);
2425                 if (err) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelHostRecord %##s", err, info->AutoTunnelHostRecord.namestorage.c);
2426
2427                 // 2. Set up device info record
2428                 ConstructServiceName(&info->AutoTunnelDeviceInfo.namestorage, &m->nicelabel, &DeviceInfoName, &info->domain);
2429                 mDNSu8 len = m->HIHardware.c[0] < 255 - 6 ? m->HIHardware.c[0] : 255 - 6;
2430                 mDNSPlatformMemCopy(info->AutoTunnelDeviceInfo.resrec.rdata->u.data + 1, "model=", 6);
2431                 mDNSPlatformMemCopy(info->AutoTunnelDeviceInfo.resrec.rdata->u.data + 7, m->HIHardware.c + 1, len);
2432                 info->AutoTunnelDeviceInfo.resrec.rdata->u.data[0] = 6 + len;   // "model=" plus the device string
2433                 info->AutoTunnelDeviceInfo.resrec.rdlength         = 7 + len;   // One extra for the length byte at the start of the string
2434                 info->AutoTunnelDeviceInfo.resrec.RecordType = kDNSRecordTypeKnownUnique;
2435                 err = mDNS_Register(m, &info->AutoTunnelDeviceInfo);
2436                 if (err) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelDeviceInfo %##s", err, info->AutoTunnelDeviceInfo.namestorage.c);
2437
2438                 // 3. Set up our address record for the external tunnel address
2439                 // (Constructed name, not generally user-visible, used as target in IKE tunnel's SRV record)
2440                 info->AutoTunnelTarget.namestorage.c[0] = 0;
2441                 AppendDomainLabel(&info->AutoTunnelTarget.namestorage, &m->AutoTunnelLabel);
2442                 AppendDomainName (&info->AutoTunnelTarget.namestorage, &info->domain);
2443                 info->AutoTunnelTarget.resrec.RecordType = kDNSRecordTypeKnownUnique;
2444
2445                 mDNS_Lock(m);
2446                 mDNS_AddDynDNSHostName(m, &info->AutoTunnelTarget.namestorage, mDNSNULL, info);
2447                 mDNS_Unlock(m);
2448
2449                 // 4. Set up IKE tunnel's SRV record: "AutoTunnelHostRecord SRV 0 0 port AutoTunnelTarget"
2450                 AssignDomainName (&info->AutoTunnelService.namestorage, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
2451                 AppendDomainLabel(&info->AutoTunnelService.namestorage, &m->hostlabel);
2452                 AppendDomainName (&info->AutoTunnelService.namestorage, &info->domain);
2453                 info->AutoTunnelService.resrec.rdata->u.srv.priority = 0;
2454                 info->AutoTunnelService.resrec.rdata->u.srv.weight   = 0;
2455                 info->AutoTunnelService.resrec.rdata->u.srv.port     = info->AutoTunnelNAT.ExternalPort;
2456                 AssignDomainName(&info->AutoTunnelService.resrec.rdata->u.srv.target, &info->AutoTunnelTarget.namestorage);
2457                 info->AutoTunnelService.resrec.RecordType = kDNSRecordTypeKnownUnique;
2458                 err = mDNS_Register(m, &info->AutoTunnelService);
2459                 if (err) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelService %##s", err, info->AutoTunnelService.namestorage.c);
2460
2461                 LogInfo("AutoTunnel server listening for connections on %##s[%.4a]:%d:%##s[%.16a]",
2462                         info->AutoTunnelTarget.namestorage.c,     &m->AdvertisedV4.ip.v4, mDNSVal16(info->AutoTunnelNAT.IntPort),
2463                         info->AutoTunnelHostRecord.namestorage.c, &m->AutoTunnelHostAddr);
2464                 }
2465         }
2466
2467 mDNSlocal void DeregisterAutoTunnelRecords(mDNS *m, DomainAuthInfo *info)
2468         {
2469         LogInfo("DeregisterAutoTunnelRecords %##s", info->domain.c);
2470         if (info->AutoTunnelService.resrec.RecordType > kDNSRecordTypeDeregistering)
2471                 {
2472                 mStatus err = mDNS_Deregister(m, &info->AutoTunnelService);
2473                 if (err)
2474                         {
2475                         info->AutoTunnelService.resrec.RecordType = kDNSRecordTypeUnregistered;
2476                         LogMsg("DeregisterAutoTunnelRecords error %d deregistering AutoTunnelService %##s", err, info->AutoTunnelService.namestorage.c);
2477                         }
2478
2479                 mDNS_Lock(m);
2480                 mDNS_RemoveDynDNSHostName(m, &info->AutoTunnelTarget.namestorage);
2481                 mDNS_Unlock(m);
2482                 }
2483
2484         if (info->AutoTunnelHostRecord.resrec.RecordType > kDNSRecordTypeDeregistering)
2485                 {
2486                 mStatus err = mDNS_Deregister(m, &info->AutoTunnelHostRecord);
2487                 if (err)
2488                         {
2489                         info->AutoTunnelHostRecord.resrec.RecordType = kDNSRecordTypeUnregistered;
2490                         LogMsg("DeregisterAutoTunnelRecords error %d deregistering AutoTunnelHostRecord %##s", err, info->AutoTunnelHostRecord.namestorage.c);
2491                         }
2492                 }
2493
2494         if (info->AutoTunnelDeviceInfo.resrec.RecordType > kDNSRecordTypeDeregistering)
2495                 {
2496                 mStatus err = mDNS_Deregister(m, &info->AutoTunnelDeviceInfo);
2497                 if (err)
2498                         {
2499                         info->AutoTunnelDeviceInfo.resrec.RecordType = kDNSRecordTypeUnregistered;
2500                         LogMsg("DeregisterAutoTunnelRecords error %d deregistering AutoTunnelDeviceInfo %##s", err, info->AutoTunnelDeviceInfo.namestorage.c);
2501                         }
2502                 }
2503         }
2504
2505 mDNSlocal void AutoTunnelRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
2506         {
2507         DomainAuthInfo *info = (DomainAuthInfo *)rr->RecordContext;
2508         if (result == mStatus_MemFree)
2509                 {
2510                 LogInfo("AutoTunnelRecordCallback MemFree %s", ARDisplayString(m, rr));
2511                 // Reset the host record namestorage to force high-level PTR/SRV/TXT to deregister
2512                 if (rr == &info->AutoTunnelHostRecord)
2513                         {
2514                         rr->namestorage.c[0] = 0;
2515                         m->NextSRVUpdate = NonZeroTime(m->timenow);
2516                         LogInfo("AutoTunnelRecordCallback: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
2517                         }
2518                 RegisterAutoTunnelRecords(m,info);
2519                 }
2520         }
2521
2522 mDNSlocal void UpdateAnonymousRacoonConfig(mDNS *m)             // Determine whether we need racoon to accept incoming connections
2523         {
2524         DomainAuthInfo *info;
2525         
2526         for (info = m->AuthInfoList; info; info = info->next)
2527                 if (info->AutoTunnel && !info->deltime && !mDNSIPPortIsZero(info->AutoTunnelNAT.ExternalPort))
2528                         break;
2529         
2530         if (info != AnonymousRacoonConfig)
2531                 {
2532                 AnonymousRacoonConfig = info;
2533                 // Create or revert configuration file, and start (or SIGHUP) Racoon
2534                 (void)mDNSConfigureServer(AnonymousRacoonConfig ? kmDNSUp : kmDNSDown, AnonymousRacoonConfig ? &AnonymousRacoonConfig->domain : mDNSNULL);
2535                 }
2536         }
2537                 
2538 mDNSlocal void AutoTunnelNATCallback(mDNS *m, NATTraversalInfo *n)
2539         {
2540         DomainAuthInfo *info = (DomainAuthInfo *)n->clientContext;
2541         LogInfo("AutoTunnelNATCallback Result %d %.4a Internal %d External %d %#s.%##s",
2542                 n->Result, &n->ExternalAddress, mDNSVal16(n->IntPort), mDNSVal16(n->ExternalPort), m->hostlabel.c, info->domain.c);
2543
2544         m->NextSRVUpdate = NonZeroTime(m->timenow);
2545         LogInfo("AutoTunnelNATCallback: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
2546
2547         DeregisterAutoTunnelRecords(m,info);
2548         RegisterAutoTunnelRecords(m,info);
2549         
2550         UpdateAnonymousRacoonConfig(m);         // Determine whether we need racoon to accept incoming connections
2551
2552         UpdateAutoTunnelDomainStatus(m, (DomainAuthInfo *)n->clientContext);
2553         }
2554
2555 mDNSlocal void AbortDeregistration(mDNS *const m, AuthRecord *rr)
2556         {
2557         if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
2558                 {
2559                 LogInfo("Aborting deregistration of %s", ARDisplayString(m, rr));
2560                 CompleteDeregistration(m, rr);
2561                 }
2562         else if (rr->resrec.RecordType != kDNSRecordTypeUnregistered)
2563                 LogMsg("AbortDeregistration ERROR RecordType %02X for %s", ARDisplayString(m, rr));
2564         }
2565
2566 // Before SetupLocalAutoTunnelInterface_internal is called,
2567 // m->AutoTunnelHostAddr.b[0] must be non-zero, and there must be at least one TunnelClient or TunnelServer
2568 // Must be called with the lock held
2569 mDNSexport void SetupLocalAutoTunnelInterface_internal(mDNS *const m)
2570         {
2571         LogInfo("SetupLocalAutoTunnelInterface");
2572
2573         // 1. Configure the local IPv6 address
2574         if (!m->AutoTunnelHostAddrActive)
2575                 {
2576                 m->AutoTunnelHostAddrActive = mDNStrue;
2577                 LogInfo("Setting up AutoTunnel address %.16a", &m->AutoTunnelHostAddr);
2578                 (void)mDNSAutoTunnelInterfaceUpDown(kmDNSUp, m->AutoTunnelHostAddr.b);
2579                 }
2580
2581         // 2. If we have at least one server (pending) listening, publish our records
2582         if (TunnelServers(m))
2583                 {
2584                 DomainAuthInfo *info;
2585                 for (info = m->AuthInfoList; info; info = info->next)
2586                         {
2587                         if (info->AutoTunnel && !info->deltime && !info->AutoTunnelNAT.clientContext)
2588                                 {
2589                                 // If we just resurrected a DomainAuthInfo that is still deregistering, we need to abort the deregistration process before re-using the AuthRecord memory
2590                                 AbortDeregistration(m, &info->AutoTunnelHostRecord);
2591                                 AbortDeregistration(m, &info->AutoTunnelDeviceInfo);
2592                                 AbortDeregistration(m, &info->AutoTunnelService);
2593
2594                                 mDNS_SetupResourceRecord(&info->AutoTunnelHostRecord, mDNSNULL, mDNSInterface_Any, kDNSType_AAAA, kHostNameTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
2595                                 mDNS_SetupResourceRecord(&info->AutoTunnelDeviceInfo, mDNSNULL, mDNSInterface_Any, kDNSType_TXT,  kStandardTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
2596                                 mDNS_SetupResourceRecord(&info->AutoTunnelTarget,     mDNSNULL, mDNSInterface_Any, kDNSType_A,    kHostNameTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
2597                                 mDNS_SetupResourceRecord(&info->AutoTunnelService,    mDNSNULL, mDNSInterface_Any, kDNSType_SRV,  kHostNameTTL, kDNSRecordTypeUnregistered, AutoTunnelRecordCallback, info);
2598
2599                                 // Try to get a NAT port mapping for the AutoTunnelService
2600                                 info->AutoTunnelNAT.clientCallback   = AutoTunnelNATCallback;
2601                                 info->AutoTunnelNAT.clientContext    = info;
2602                                 info->AutoTunnelNAT.Protocol         = NATOp_MapUDP;
2603                                 info->AutoTunnelNAT.IntPort          = IPSECPort;
2604                                 info->AutoTunnelNAT.RequestedPort    = IPSECPort;
2605                                 info->AutoTunnelNAT.NATLease         = 0;
2606                                 mStatus err = mDNS_StartNATOperation_internal(m, &info->AutoTunnelNAT);
2607                                 if (err) LogMsg("SetupLocalAutoTunnelInterface_internal error %d starting NAT mapping", err);
2608                                 }
2609                         }
2610                 }
2611         }
2612
2613 mDNSlocal mStatus AutoTunnelSetKeys(ClientTunnel *tun, mDNSBool AddNew)
2614         {
2615         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)));
2616         }
2617
2618 // If the EUI-64 part of the IPv6 ULA matches, then that means the two addresses point to the same machine
2619 #define mDNSSameClientTunnel(A,B) ((A)->l[2] == (B)->l[2] && (A)->l[3] == (B)->l[3])
2620
2621 mDNSlocal void ReissueBlockedQuestionWithType(mDNS *const m, domainname *d, mDNSBool success, mDNSu16 qtype)
2622         {
2623         DNSQuestion *q = m->Questions;
2624         while (q)
2625                 {
2626                 if (q->NoAnswer == NoAnswer_Suspended && q->qtype == qtype && q->AuthInfo && q->AuthInfo->AutoTunnel && SameDomainName(&q->qname, d))
2627                         {
2628                         LogInfo("Restart %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
2629                         mDNSQuestionCallback *tmp = q->QuestionCallback;
2630                         q->QuestionCallback = AutoTunnelCallback;       // Set QuestionCallback to suppress another call back to AddNewClientTunnel
2631                         mDNS_StopQuery(m, q);
2632                         mDNS_StartQuery(m, q);
2633                         q->QuestionCallback = tmp;                                      // Restore QuestionCallback back to the real value
2634                         if (!success) q->NoAnswer = NoAnswer_Fail;
2635                         // When we call mDNS_StopQuery, it's possible for other subordinate questions like the GetZoneData query to be cancelled too.
2636                         // In general we have to assume that the question list might have changed in arbitrary ways.
2637                         // This code is itself called from a question callback, so the m->CurrentQuestion mechanism is
2638                         // already in use. The safest solution is just to go back to the start of the list and start again.
2639                         // In principle this sounds like an n^2 algorithm, but in practice we almost always activate
2640                         // just one suspended question, so it's really a 2n algorithm.
2641                         q = m->Questions;
2642                         }
2643                 else
2644                         q = q->next;
2645                 }
2646         }
2647
2648 mDNSlocal void ReissueBlockedQuestions(mDNS *const m, domainname *d, mDNSBool success)
2649         {
2650         // 1. We deliberately restart AAAA queries before A queries, because in the common case where a BTTM host has
2651         //    a v6 address but no v4 address, we prefer the caller to get the positive AAAA response before the A NXDOMAIN.
2652         // 2. In the case of AAAA queries, if our tunnel setup failed, then we return a deliberate failure indication to the caller --
2653         //    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.
2654         // 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.
2655         ReissueBlockedQuestionWithType(m, d, success, kDNSType_AAAA);
2656         ReissueBlockedQuestionWithType(m, d, mDNStrue, kDNSType_A);
2657         }
2658
2659 mDNSlocal void UnlinkAndReissueBlockedQuestions(mDNS *const m, ClientTunnel *tun, mDNSBool success)
2660         {
2661         ClientTunnel **p = &m->TunnelClients;
2662         while (*p != tun && *p) p = &(*p)->next;
2663         if (*p) *p = tun->next;
2664         ReissueBlockedQuestions(m, &tun->dstname, success);
2665         LogInfo("UnlinkAndReissueBlockedQuestions: Disposing ClientTunnel %p", tun);
2666         freeL("ClientTunnel", tun);
2667         }
2668
2669 mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
2670         {
2671         ClientTunnel *tun = (ClientTunnel *)question->QuestionContext;
2672         LogInfo("AutoTunnelCallback tun %p AddRecord %d rdlength %d qtype %d", tun, AddRecord, answer->rdlength, question->qtype);
2673
2674         if (!AddRecord) return;
2675         mDNS_StopQuery(m, question);
2676
2677         if (!answer->rdlength)
2678                 {
2679                 LogInfo("AutoTunnelCallback NXDOMAIN %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
2680                 static char msgbuf[16];
2681                 mDNS_snprintf(msgbuf, sizeof(msgbuf), "%s lookup", DNSTypeName(question->qtype));
2682                 mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.config", "failure", msgbuf, "");
2683                 UnlinkAndReissueBlockedQuestions(m, tun, mDNSfalse);
2684                 return;
2685                 }
2686
2687         if (question->qtype == kDNSType_AAAA)
2688                 {
2689                 if (mDNSSameIPv6Address(answer->rdata->u.ipv6, m->AutoTunnelHostAddr))
2690                         {
2691                         LogInfo("AutoTunnelCallback: suppressing tunnel to self %.16a", &answer->rdata->u.ipv6);
2692                         UnlinkAndReissueBlockedQuestions(m, tun, mDNStrue);
2693                         return;
2694                         }
2695
2696                 tun->rmt_inner = answer->rdata->u.ipv6;
2697                 LogInfo("AutoTunnelCallback: dst host %.16a", &tun->rmt_inner);
2698                 AssignDomainName(&question->qname, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
2699                 AppendDomainName(&question->qname, &tun->dstname);
2700                 question->qtype = kDNSType_SRV;
2701                 mDNS_StartQuery(m, &tun->q);
2702                 }
2703         else if (question->qtype == kDNSType_SRV)
2704                 {
2705                 LogInfo("AutoTunnelCallback: SRV target name %##s", answer->rdata->u.srv.target.c);
2706                 AssignDomainName(&tun->q.qname, &answer->rdata->u.srv.target);
2707                 tun->rmt_outer_port = answer->rdata->u.srv.port;
2708                 question->qtype = kDNSType_A;
2709                 mDNS_StartQuery(m, &tun->q);
2710                 }
2711         else if (question->qtype == kDNSType_A)
2712                 {
2713                 LogInfo("AutoTunnelCallback: SRV target addr %.4a", &answer->rdata->u.ipv4);
2714                 question->ThisQInterval = -1;           // So we know this tunnel setup has completed
2715                 tun->rmt_outer = answer->rdata->u.ipv4;
2716                 tun->loc_inner = m->AutoTunnelHostAddr;
2717                 mDNSAddr tmpDst = { mDNSAddrType_IPv4, {{{0}}} };
2718                 tmpDst.ip.v4 = tun->rmt_outer;
2719                 mDNSAddr tmpSrc = zeroAddr;
2720                 mDNSPlatformSourceAddrForDest(&tmpSrc, &tmpDst);
2721                 if (tmpSrc.type == mDNSAddrType_IPv4) tun->loc_outer = tmpSrc.ip.v4;
2722                 else tun->loc_outer = m->AdvertisedV4.ip.v4;
2723
2724                 ClientTunnel **p = &tun->next;
2725                 mDNSBool needSetKeys = mDNStrue;
2726                 while (*p)
2727                         {
2728                         if (!mDNSSameClientTunnel(&(*p)->rmt_inner, &tun->rmt_inner)) p = &(*p)->next;
2729                         else
2730                                 {
2731                                 ClientTunnel *old = *p;
2732                                 *p = old->next;
2733                                 LogInfo("Found existing AutoTunnel for %##s %.16a", tun->dstname.c, &tun->rmt_inner);
2734                                 if (old->q.ThisQInterval >= 0) mDNS_StopQuery(m, &old->q);
2735                                 else if (!mDNSSameIPv6Address(old->loc_inner, tun->loc_inner) ||
2736                                                  !mDNSSameIPv4Address(old->loc_outer, tun->loc_outer) ||
2737                                                  !mDNSSameIPv6Address(old->rmt_inner, tun->rmt_inner) ||
2738                                                  !mDNSSameIPv4Address(old->rmt_outer, tun->rmt_outer) ||
2739                                                  !mDNSSameIPPort(old->rmt_outer_port, tun->rmt_outer_port))
2740                                         {
2741                                         LogInfo("Deleting existing AutoTunnel for %##s %.16a", tun->dstname.c, &tun->rmt_inner);
2742                                         AutoTunnelSetKeys(old, mDNSfalse);
2743                                         }
2744                                 else needSetKeys = mDNSfalse;
2745
2746                                 LogInfo("AutoTunnelCallback: Disposing ClientTunnel %p", tun);
2747                                 freeL("ClientTunnel", old);
2748                                 }
2749                         }
2750
2751                 if (needSetKeys) LogInfo("New AutoTunnel for %##s %.16a", tun->dstname.c, &tun->rmt_inner);
2752
2753                 if (m->AutoTunnelHostAddr.b[0]) { mDNS_Lock(m); SetupLocalAutoTunnelInterface_internal(m); mDNS_Unlock(m); };
2754
2755                 mStatus result = needSetKeys ? AutoTunnelSetKeys(tun, mDNStrue) : mStatus_NoError;
2756                 static char msgbuf[32];
2757                 mDNS_snprintf(msgbuf, sizeof(msgbuf), "Tunnel setup - %d", result);
2758                 mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.config", result ? "failure" : "success", msgbuf, "");
2759                 // Kick off any questions that were held pending this tunnel setup
2760                 ReissueBlockedQuestions(m, &tun->dstname, (result == mStatus_NoError) ? mDNStrue : mDNSfalse);
2761                 }
2762         else
2763                 LogMsg("AutoTunnelCallback: Unknown question %p", question);
2764         }
2765
2766 // Must be called with the lock held
2767 mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
2768         {
2769         ClientTunnel *p = mallocL("ClientTunnel", sizeof(ClientTunnel));
2770         if (!p) return;
2771         AssignDomainName(&p->dstname, &q->qname);
2772         p->MarkedForDeletion = mDNSfalse;
2773         p->loc_inner      = zerov6Addr;
2774         p->loc_outer      = zerov4Addr;
2775         p->rmt_inner      = zerov6Addr;
2776         p->rmt_outer      = zerov4Addr;
2777         p->rmt_outer_port = zeroIPPort;
2778         p->next = m->TunnelClients;
2779         m->TunnelClients = p;           // We intentionally build list in reverse order
2780
2781         p->q.InterfaceID      = mDNSInterface_Any;
2782         p->q.Target           = zeroAddr;
2783         AssignDomainName(&p->q.qname, &q->qname);
2784         p->q.qtype            = kDNSType_AAAA;
2785         p->q.qclass           = kDNSClass_IN;
2786         p->q.LongLived        = mDNSfalse;
2787         p->q.ExpectUnique     = mDNStrue;
2788         p->q.ForceMCast       = mDNSfalse;
2789         p->q.ReturnIntermed   = mDNStrue;
2790         p->q.QuestionCallback = AutoTunnelCallback;
2791         p->q.QuestionContext  = p;
2792
2793         LogInfo("AddNewClientTunnel start tun %p %##s (%s)%s", p, &q->qname.c, DNSTypeName(q->qtype), q->LongLived ? " LongLived" : "");
2794         mDNS_StartQuery_internal(m, &p->q);
2795         }
2796
2797 #endif // APPLE_OSX_mDNSResponder
2798
2799 #if COMPILER_LIKES_PRAGMA_MARK
2800 #pragma mark -
2801 #pragma mark - Power State & Configuration Change Management
2802 #endif
2803
2804 mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
2805         {
2806         mDNSBool foundav4           = mDNSfalse;
2807         mDNSBool foundav6           = mDNSfalse;
2808         struct ifaddrs *ifa         = myGetIfAddrs(1);
2809         struct ifaddrs *v4Loopback  = NULL;
2810         struct ifaddrs *v6Loopback  = NULL;
2811         char defaultname[64];
2812 #ifndef NO_IPV6
2813         int InfoSocket              = socket(AF_INET6, SOCK_DGRAM, 0);
2814         if (InfoSocket < 3 && errno != EAFNOSUPPORT) LogMsg("UpdateInterfaceList: InfoSocket error %d errno %d (%s)", InfoSocket, errno, strerror(errno));
2815 #endif
2816         if (m->SleepState == SleepState_Sleeping) ifa = NULL;
2817
2818         while (ifa)
2819                 {
2820 #if LIST_ALL_INTERFACES
2821                 if (ifa->ifa_addr->sa_family == AF_APPLETALK)
2822                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_APPLETALK",
2823                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2824                 else if (ifa->ifa_addr->sa_family == AF_LINK)
2825                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_LINK",
2826                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2827                 else if (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6)
2828                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)",
2829                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2830                 if (!(ifa->ifa_flags & IFF_UP))
2831                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_UP",
2832                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2833                 if (!(ifa->ifa_flags & IFF_MULTICAST))
2834                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_MULTICAST",
2835                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2836                 if (ifa->ifa_flags & IFF_POINTOPOINT)
2837                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_POINTOPOINT",
2838                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2839                 if (ifa->ifa_flags & IFF_LOOPBACK)
2840                         LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_LOOPBACK",
2841                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
2842 #endif
2843
2844                 if (ifa->ifa_addr->sa_family == AF_LINK)
2845                         {
2846                         struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr;
2847                         if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == sizeof(m->PrimaryMAC) && mDNSSameEthAddress(&m->PrimaryMAC, &zeroEthAddr))
2848                                 mDNSPlatformMemCopy(m->PrimaryMAC.b, sdl->sdl_data + sdl->sdl_nlen, 6);
2849                         }
2850
2851                 if (ifa->ifa_flags & IFF_UP && ifa->ifa_addr)
2852                         if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6)
2853                                 {
2854                                 if (!ifa->ifa_netmask)
2855                                         {
2856                                         mDNSAddr ip;
2857                                         SetupAddr(&ip, ifa->ifa_addr);
2858                                         LogMsg("getifaddrs: ifa_netmask is NULL for %5s(%d) Flags %04X Family %2d %#a",
2859                                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family, &ip);
2860                                         }
2861                                 // Apparently it's normal for the sa_family of an ifa_netmask to sometimes be zero, so we don't complain about that
2862                                 // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
2863                                 else if (ifa->ifa_netmask->sa_family != ifa->ifa_addr->sa_family && ifa->ifa_netmask->sa_family != 0)
2864                                         {
2865                                         mDNSAddr ip;
2866                                         SetupAddr(&ip, ifa->ifa_addr);
2867                                         LogMsg("getifaddrs ifa_netmask for %5s(%d) Flags %04X Family %2d %#a has different family: %d",
2868                                                 ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family, &ip, ifa->ifa_netmask->sa_family);
2869                                         }
2870                                         // Currently we use a few internal ones like mDNSInterfaceID_LocalOnly etc. that are negative values (0, -1, -2).
2871                                 else if ((int)if_nametoindex(ifa->ifa_name) <= 0)
2872                                         {
2873                                         LogMsg("UpdateInterfaceList: if_nametoindex returned zero/negative value for %5s(%d)", ifa->ifa_name, if_nametoindex(ifa->ifa_name));
2874                                         }
2875                                 else
2876                                         {
2877                                         // Make sure ifa_netmask->sa_family is set correctly
2878                                         // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
2879                                         ifa->ifa_netmask->sa_family = ifa->ifa_addr->sa_family;
2880                                         int ifru_flags6 = 0;
2881 #ifndef NO_IPV6
2882                                         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
2883                                         if (ifa->ifa_addr->sa_family == AF_INET6 && InfoSocket >= 0)
2884                                                 {
2885                                                 struct in6_ifreq ifr6;
2886                                                 mDNSPlatformMemZero((char *)&ifr6, sizeof(ifr6));
2887                                                 strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
2888                                                 ifr6.ifr_addr = *sin6;
2889                                                 if (ioctl(InfoSocket, SIOCGIFAFLAG_IN6, &ifr6) != -1)
2890                                                         ifru_flags6 = ifr6.ifr_ifru.ifru_flags6;
2891                                                 verbosedebugf("%s %.16a %04X %04X", ifa->ifa_name, &sin6->sin6_addr, ifa->ifa_flags, ifru_flags6);
2892                                                 }
2893 #endif
2894                                         if (!(ifru_flags6 & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY)))
2895                                                 {
2896                                                 if (ifa->ifa_flags & IFF_LOOPBACK)
2897                                                         {
2898                                                         if (ifa->ifa_addr->sa_family == AF_INET)     v4Loopback = ifa;
2899 #ifndef NO_IPV6
2900                                                         else if (sin6->sin6_addr.s6_addr[0] != 0xFD) v6Loopback = ifa;
2901 #endif
2902                                                         }
2903                                                 else
2904                                                         {
2905                                                         NetworkInterfaceInfoOSX *i = AddInterfaceToList(m, ifa, utc);
2906                                                         if (i && MulticastInterface(i) && i->ifinfo.Advertise)
2907                                                                 {
2908                                                                 if (ifa->ifa_addr->sa_family == AF_INET) foundav4 = mDNStrue;
2909                                                                 else                                     foundav6 = mDNStrue;
2910                                                                 }
2911                                                         }
2912                                                 }
2913                                         }
2914                                 }
2915                 ifa = ifa->ifa_next;
2916                 }
2917
2918         // For efficiency, we don't register a loopback interface when other interfaces of that family are available and advertising
2919         if (!foundav4 && v4Loopback) AddInterfaceToList(m, v4Loopback, utc);
2920         if (!foundav6 && v6Loopback) AddInterfaceToList(m, v6Loopback, utc);
2921
2922         // Now the list is complete, set the McastTxRx setting for each interface.
2923         NetworkInterfaceInfoOSX *i;
2924         for (i = m->p->InterfaceList; i; i = i->next)
2925                 if (i->Exists)
2926                         {
2927                         mDNSBool txrx = MulticastInterface(i);
2928 #if USE_V6_ONLY_WHEN_NO_ROUTABLE_V4
2929                         txrx = txrx && ((i->ifinfo.ip.type == mDNSAddrType_IPv4) || !FindRoutableIPv4(m, i->scope_id));
2930 #endif
2931                         if (i->ifinfo.McastTxRx != txrx)
2932                                 {
2933                                 i->ifinfo.McastTxRx = txrx;
2934                                 i->Exists = 2; // State change; need to deregister and reregister this interface
2935                                 }
2936                         }
2937
2938 #ifndef NO_IPV6
2939         if (InfoSocket >= 0) close(InfoSocket);
2940 #endif
2941
2942         // If we haven't set up AutoTunnelHostAddr yet, do it now
2943         if (!mDNSSameEthAddress(&m->PrimaryMAC, &zeroEthAddr) && m->AutoTunnelHostAddr.b[0] == 0)
2944                 {
2945                 m->AutoTunnelHostAddr.b[0x0] = 0xFD;            // Required prefix for "locally assigned" ULA (See RFC 4193)
2946                 m->AutoTunnelHostAddr.b[0x1] = mDNSRandom(255);
2947                 m->AutoTunnelHostAddr.b[0x2] = mDNSRandom(255);
2948                 m->AutoTunnelHostAddr.b[0x3] = mDNSRandom(255);
2949                 m->AutoTunnelHostAddr.b[0x4] = mDNSRandom(255);
2950                 m->AutoTunnelHostAddr.b[0x5] = mDNSRandom(255);
2951                 m->AutoTunnelHostAddr.b[0x6] = mDNSRandom(255);
2952                 m->AutoTunnelHostAddr.b[0x7] = mDNSRandom(255);
2953                 m->AutoTunnelHostAddr.b[0x8] = m->PrimaryMAC.b[0] ^ 0x02;       // See RFC 3513, Appendix A for explanation
2954                 m->AutoTunnelHostAddr.b[0x9] = m->PrimaryMAC.b[1];
2955                 m->AutoTunnelHostAddr.b[0xA] = m->PrimaryMAC.b[2];
2956                 m->AutoTunnelHostAddr.b[0xB] = 0xFF;
2957                 m->AutoTunnelHostAddr.b[0xC] = 0xFE;
2958                 m->AutoTunnelHostAddr.b[0xD] = m->PrimaryMAC.b[3];
2959                 m->AutoTunnelHostAddr.b[0xE] = m->PrimaryMAC.b[4];
2960                 m->AutoTunnelHostAddr.b[0xF] = m->PrimaryMAC.b[5];
2961                 m->AutoTunnelLabel.c[0] = mDNS_snprintf((char*)m->AutoTunnelLabel.c+1, 254, "AutoTunnel-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
2962                         m->AutoTunnelHostAddr.b[0x8], m->AutoTunnelHostAddr.b[0x9], m->AutoTunnelHostAddr.b[0xA], m->AutoTunnelHostAddr.b[0xB],
2963                         m->AutoTunnelHostAddr.b[0xC], m->AutoTunnelHostAddr.b[0xD], m->AutoTunnelHostAddr.b[0xE], m->AutoTunnelHostAddr.b[0xF]);
2964                 LogInfo("m->AutoTunnelLabel %#s", m->AutoTunnelLabel.c);
2965                 }
2966         
2967         mDNS_snprintf(defaultname, sizeof(defaultname), "%.*s-%02X%02X%02X%02X%02X%02X", HINFO_HWstring_prefixlen, HINFO_HWstring,
2968                 m->PrimaryMAC.b[0], m->PrimaryMAC.b[1], m->PrimaryMAC.b[2], m->PrimaryMAC.b[3], m->PrimaryMAC.b[4], m->PrimaryMAC.b[5]);
2969
2970         // Set up the nice label
2971         domainlabel nicelabel;
2972         nicelabel.c[0] = 0;
2973         GetUserSpecifiedFriendlyComputerName(&nicelabel);
2974         if (nicelabel.c[0] == 0)
2975                 {
2976                 debugf("Couldn’t read user-specified Computer Name; using default “%s” instead", defaultname);
2977                 MakeDomainLabelFromLiteralString(&nicelabel, defaultname);
2978                 }
2979
2980         // Set up the RFC 1034-compliant label
2981         domainlabel hostlabel;
2982         hostlabel.c[0] = 0;
2983         GetUserSpecifiedLocalHostName(&hostlabel);
2984         if (hostlabel.c[0] == 0)
2985                 {
2986                 debugf("Couldn’t read user-specified Local Hostname; using default “%s.local” instead", defaultname);
2987                 MakeDomainLabelFromLiteralString(&hostlabel, defaultname);
2988                 }
2989
2990         mDNSBool namechange = mDNSfalse;
2991
2992         // We use a case-sensitive comparison here because even though changing the capitalization
2993         // of the name alone is not significant to DNS, it's still a change from the user's point of view
2994         if (SameDomainLabelCS(m->p->usernicelabel.c, nicelabel.c))
2995                 debugf("Usernicelabel (%#s) unchanged since last time; not changing m->nicelabel (%#s)", m->p->usernicelabel.c, m->nicelabel.c);
2996         else
2997                 {
2998                 if (m->p->usernicelabel.c[0])   // Don't show message first time through, when we first read name from prefs on boot
2999                         LogMsg("User updated Computer Name from “%#s” to “%#s”", m->p->usernicelabel.c, nicelabel.c);
3000                 m->p->usernicelabel = m->nicelabel = nicelabel;
3001                 namechange = mDNStrue;
3002                 }
3003
3004         if (SameDomainLabelCS(m->p->userhostlabel.c, hostlabel.c))
3005                 debugf("Userhostlabel (%#s) unchanged since last time; not changing m->hostlabel (%#s)", m->p->userhostlabel.c, m->hostlabel.c);
3006         else
3007                 {
3008                 if (m->p->userhostlabel.c[0])   // Don't show message first time through, when we first read name from prefs on boot
3009                         LogMsg("User updated Local Hostname from “%#s” to “%#s”", m->p->userhostlabel.c, hostlabel.c);
3010                 m->p->userhostlabel = m->hostlabel = hostlabel;
3011                 mDNS_SetFQDN(m);
3012                 namechange = mDNStrue;
3013                 }
3014
3015 #if APPLE_OSX_mDNSResponder
3016         if (namechange)         // If either name has changed, we need to tickle our AutoTunnel state machine to update its registered records
3017                 {
3018                 DomainAuthInfo *info;
3019                 for (info = m->AuthInfoList; info; info = info->next)
3020                         if (info->AutoTunnelNAT.clientContext && !mDNSIPv4AddressIsOnes(info->AutoTunnelNAT.ExternalAddress))
3021                                 AutoTunnelNATCallback(m, &info->AutoTunnelNAT);
3022                 }
3023 #endif // APPLE_OSX_mDNSResponder
3024
3025         return(mStatus_NoError);
3026         }
3027
3028 // Returns number of leading one-bits in mask: 0-32 for IPv4, 0-128 for IPv6
3029 // Returns -1 if all the one-bits are not contiguous
3030 mDNSlocal int CountMaskBits(mDNSAddr *mask)
3031         {
3032         int i = 0, bits = 0;
3033         int bytes = mask->type == mDNSAddrType_IPv4 ? 4 : mask->type == mDNSAddrType_IPv6 ? 16 : 0;
3034         while (i < bytes)
3035                 {
3036                 mDNSu8 b = mask->ip.v6.b[i++];
3037                 while (b & 0x80) { bits++; b <<= 1; }
3038                 if (b) return(-1);
3039                 }
3040         while (i < bytes) if (mask->ip.v6.b[i++]) return(-1);
3041         return(bits);
3042         }
3043
3044 // returns count of non-link local V4 addresses registered
3045 mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
3046         {
3047         NetworkInterfaceInfoOSX *i;
3048         int count = 0;
3049         for (i = m->p->InterfaceList; i; i = i->next)
3050                 if (i->Exists)
3051                         {
3052                         NetworkInterfaceInfo *const n = &i->ifinfo;
3053                         NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifinfo.ifname, AAAA_OVER_V4 ? AF_UNSPEC : i->sa_family);
3054                         if (!primary) LogMsg("SetupActiveInterfaces ERROR! SearchForInterfaceByName didn't find %s", i->ifinfo.ifname);
3055
3056                         if (i->Registered && i->Registered != primary)  // Sanity check
3057                                 {
3058                                 LogMsg("SetupActiveInterfaces ERROR! n->Registered %p != primary %p", i->Registered, primary);
3059                                 i->Registered = mDNSNULL;
3060                                 }
3061
3062                         if (!i->Registered)
3063                                 {
3064                                 // Note: If i->Registered is set, that means we've called mDNS_RegisterInterface() for this interface,
3065                                 // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
3066                                 // If i->Registered is NOT set, then we haven't registered it and we should not try to deregister it
3067                                 //
3068
3069                                 i->Registered = primary;
3070
3071                                 // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away.
3072                                 // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds.
3073                                 // 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.
3074                                 i->Occulting = !(i->ifa_flags & IFF_LOOPBACK) && (utc - i->LastSeen > 0 && utc - i->LastSeen < 60);
3075
3076                                 mDNS_RegisterInterface(m, n, i->Flashing && i->Occulting);
3077
3078                                 if (!mDNSAddressIsLinkLocal(&n->ip)) count++;
3079                                 LogInfo("SetupActiveInterfaces:   Registered    %5s(%lu) %.6a InterfaceID %p(%p), primary %p, %#a/%d%s%s%s",
3080                                         i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, i, primary, &n->ip, CountMaskBits(&n->mask),
3081                                    &n