#define mDNS_AllowPort53 0
#define LIST_ALL_INTERFACES 0
#define AAAA_OVER_V4 1
#include "mDNSClientAPI.h" // Defines the interface provided to the client layer above
#include "mDNSPlatformFunctions.h" // Defines the interface to the supporting layer below
#include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform
#include <stdio.h>
#include <unistd.h> // For select() and close()
#include <stdarg.h> // For va_list support
#include <net/if.h>
#include <net/if_dl.h>
#include <sys/uio.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <netinet/in.h> // For IP_RECVTTL
#ifndef IP_RECVTTL
#define IP_RECVTTL 24
#endif
#include <netinet/in_systm.h> // For n_long, required by <netinet/ip.h> below
#include <netinet/ip.h> // For IPTOS_LOWDELAY etc.
#include <netinet6/in6_var.h> // For IN6_IFF_NOTREADY etc.
#define RUN_ON_PUMA_WITHOUT_IFADDRS 0
#if RUN_ON_PUMA_WITHOUT_IFADDRS
#include "CFSocketPuma.c"
#else
#include <ifaddrs.h>
#endif
#include <IOKit/IOKitLib.h>
#include <IOKit/IOMessage.h>
#include <mach/mach_time.h>
static mDNSu32 clockdivisor = 0;
#define mDNSSameIPv4Address(A,B) ((A).NotAnInteger == (B).NotAnInteger)
#define mDNSSameIPv6Address(A,B) ((A).l[0] == (B).l[0] && (A).l[1] == (B).l[1] && (A).l[2] == (B).l[2] && (A).l[3] == (B).l[3])
#define mDNSAddressIsAllDNSLinkGroup(X) ( \
((X)->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address((X)->ip.v4, AllDNSLinkGroup )) || \
((X)->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address((X)->ip.v6, AllDNSLinkGroupv6)) )
#if MDNS_DEBUGMSGS
mDNSexport void debugf_(const char *format, ...)
{
unsigned char buffer[512];
va_list ptr;
va_start(ptr,format);
buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
va_end(ptr);
fprintf(stderr,"%s\n", buffer);
fflush(stderr);
}
#endif
#if MDNS_DEBUGMSGS > 1
mDNSexport void verbosedebugf_(const char *format, ...)
{
unsigned char buffer[512];
va_list ptr;
va_start(ptr,format);
buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
va_end(ptr);
fprintf(stderr,"%s\n", buffer);
fflush(stderr);
}
#endif
mDNSexport void LogMsg(const char *format, ...)
{
unsigned char buffer[512];
va_list ptr;
va_start(ptr,format);
buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
va_end(ptr);
extern int debug_mode;
if (debug_mode) {
fprintf(stderr,"%s\n", buffer);
fflush(stderr);
}
else {
openlog("mDNSResponder", LOG_CONS | LOG_PERROR | LOG_PID, LOG_DAEMON);
syslog(LOG_ERR, "%s", buffer);
closelog();
}
}
mDNSlocal struct ifaddrs* myGetIfAddrs(int refresh)
{
static struct ifaddrs *ifa = NULL;
if (refresh && ifa)
{
freeifaddrs(ifa);
ifa = NULL;
}
if (ifa == NULL) getifaddrs(&ifa);
return ifa;
}
mDNSlocal int myIfIndexToName(u_short index, char* name)
{
struct ifaddrs *ifa;
for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next)
if (ifa->ifa_addr->sa_family == AF_LINK)
if (((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index == index)
{ strncpy(name, ifa->ifa_name, IF_NAMESIZE); return 0; }
return -1;
}
mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS *const m, mDNSu32 index)
{
NetworkInterfaceInfoOSX *i;
if (index == (uint32_t)~0) return((mDNSInterfaceID)~0);
if (index)
for (i = m->p->InterfaceList; i; i = i->next)
if (i->scope_id == index)
return(i->ifinfo.InterfaceID);
return(mDNSNULL);
}
mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(const mDNS *const m, mDNSInterfaceID id)
{
NetworkInterfaceInfoOSX *i;
if (id == (mDNSInterfaceID)~0) return((mDNSu32)~0);
if (id)
for (i = m->p->InterfaceList; i; i = i->next)
if (i->ifinfo.InterfaceID == id)
return i->scope_id;
return 0;
}
mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
mDNSInterfaceID InterfaceID, mDNSIPPort srcPort, const mDNSAddr *dst, mDNSIPPort dstPort)
{
#pragma unused(m)
NetworkInterfaceInfoOSX *info = (NetworkInterfaceInfoOSX *)InterfaceID;
struct sockaddr_storage to;
int s, err;
if (!InterfaceID) { LogMsg("mDNSPlatformSendUDP ERROR! Cannot send from zero InterfaceID"); return mStatus_BadParamErr; }
if (dst->type == mDNSAddrType_IPv4)
{
struct sockaddr_in* sin_to = (struct sockaddr_in*)&to;
sin_to->sin_len = sizeof(*sin_to);
sin_to->sin_family = AF_INET;
sin_to->sin_port = dstPort.NotAnInteger;
sin_to->sin_addr.s_addr = dst->ip.v4.NotAnInteger;
}
else if (dst->type == mDNSAddrType_IPv6)
{
struct sockaddr_in6* sin6_to = (struct sockaddr_in6*)&to;
sin6_to->sin6_len = sizeof(*sin6_to);
sin6_to->sin6_family = AF_INET6;
sin6_to->sin6_port = dstPort.NotAnInteger;
sin6_to->sin6_flowinfo = 0;
sin6_to->sin6_addr = *(struct in6_addr*)&dst->ip.v6;
sin6_to->sin6_scope_id = info->scope_id;
}
else
{
LogMsg("mDNSPlatformSendUDP: dst is not an IPv4 or IPv6 address!\n");
return mStatus_BadParamErr;
}
if (srcPort.NotAnInteger == MulticastDNSPort.NotAnInteger)
{
if (dst->type == mDNSAddrType_IPv4) s = info->sktv4;
else if (dst->type == mDNSAddrType_IPv6) s = info->sktv6;
else s = -1;
}
#if mDNS_AllowPort53
else if (srcPort.NotAnInteger == UnicastDNSPort.NotAnInteger && dst->type == mDNSAddrType_IPv4)
s = info->skt53;
#endif
else { LogMsg("Source port %d not allowed", (mDNSu16)srcPort.b[0]<<8 | srcPort.b[1]); return(-1); }
if (s >= 0)
verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %X %s/%d to %#a:%d skt %d",
InterfaceID, info->ifa_name, dst->type, dst, (mDNSu16)dstPort.b[0]<<8 | dstPort.b[1], s);
else
verbosedebugf("mDNSPlatformSendUDP: NOT sending on InterfaceID %X %s/%d (socket of this type not available)",
InterfaceID, info->ifa_name, dst->type, dst, (mDNSu16)dstPort.b[0]<<8 | dstPort.b[1]);
if (s < 0) return(mStatus_Invalid);
err = sendto(s, msg, (UInt8*)end - (UInt8*)msg, 0, (struct sockaddr *)&to, to.ss_len);
if (err < 0)
{
if (errno == EHOSTDOWN && !mDNSAddressIsAllDNSLinkGroup(dst)) return(err);
if (errno == EHOSTUNREACH && (mDNSu32)(m->timenow) < (mDNSu32)(mDNSPlatformOneSecond * 120)) return(err);
LogMsg("mDNSPlatformSendUDP sendto failed to send packet on InterfaceID %p %s/%ld to %#a:%d skt %d error %d errno %d (%s)",
InterfaceID, info->ifa_name, dst->type, dst, (mDNSu16)dstPort.b[0]<<8 | dstPort.b[1], s, err, errno, strerror(errno));
return(err);
}
return(mStatus_NoError);
}
mDNSlocal ssize_t myrecvfrom(const int s, void *const buffer, const size_t max,
struct sockaddr *const from, size_t *const fromlen, mDNSAddr *dstaddr, char ifname[IF_NAMESIZE], mDNSu8 *ttl)
{
static unsigned int numLogMessages = 0;
struct iovec databuffers = { (char *)buffer, max };
struct msghdr msg;
ssize_t n;
struct cmsghdr *cmPtr;
char ancillary[1024];
*ttl = 255;
msg.msg_name = (caddr_t)from;
msg.msg_namelen = *fromlen;
msg.msg_iov = &databuffers;
msg.msg_iovlen = 1;
msg.msg_control = (caddr_t)&ancillary;
msg.msg_controllen = sizeof(ancillary);
msg.msg_flags = 0;
n = recvmsg(s, &msg, 0);
if (n<0)
{
if (errno != EWOULDBLOCK && numLogMessages++ < 100) LogMsg("CFSocket.c: recvmsg(%d) returned error %d errno %d", s, n, errno);
return(-1);
}
if (msg.msg_controllen < (int)sizeof(struct cmsghdr))
{
if (numLogMessages++ < 100) LogMsg("CFSocket.c: recvmsg(%d) msg.msg_controllen %d < sizeof(struct cmsghdr) %lu",
s, msg.msg_controllen, sizeof(struct cmsghdr));
return(-1);
}
if (msg.msg_flags & MSG_CTRUNC)
{
if (numLogMessages++ < 100) LogMsg("CFSocket.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s);
return(-1);
}
*fromlen = msg.msg_namelen;
for (cmPtr = CMSG_FIRSTHDR(&msg); cmPtr; cmPtr = CMSG_NXTHDR(&msg, cmPtr))
{
if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVDSTADDR)
{
dstaddr->type = mDNSAddrType_IPv4;
dstaddr->ip.v4.NotAnInteger = *(u_int32_t*)CMSG_DATA(cmPtr);
}
if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVIF)
{
struct sockaddr_dl *sdl = (struct sockaddr_dl *)CMSG_DATA(cmPtr);
if (sdl->sdl_nlen < IF_NAMESIZE)
{
mDNSPlatformMemCopy(sdl->sdl_data, ifname, sdl->sdl_nlen);
ifname[sdl->sdl_nlen] = 0;
}
}
if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVTTL)
{
*ttl = *(u_char*)CMSG_DATA(cmPtr);
}
if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_PKTINFO)
{
struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmPtr);
dstaddr->type = mDNSAddrType_IPv6;
dstaddr->ip.v6 = *(mDNSv6Addr*)&ip6_info->ipi6_addr;
myIfIndexToName(ip6_info->ipi6_ifindex, ifname);
}
if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_HOPLIMIT)
{
*ttl = *(int*)CMSG_DATA(cmPtr);
}
}
return(n);
}
mDNSlocal void myCFSocketCallBack(CFSocketRef cfs, CFSocketCallBackType CallBackType, CFDataRef address, const void *data, void *context)
{
mDNSAddr senderAddr, destAddr;
mDNSIPPort senderPort, destPort = MulticastDNSPort;
NetworkInterfaceInfoOSX *info = (NetworkInterfaceInfoOSX *)context;
mDNS *const m = info->m;
DNSMessage packet;
struct sockaddr_storage from;
size_t fromlen = sizeof(from);
char packetifname[IF_NAMESIZE] = "";
int err, s1 = -1, skt = CFSocketGetNative(cfs);
int count = 0;
(void)address; (void)data;
if (CallBackType != kCFSocketReadCallBack) LogMsg("myCFSocketCallBack: Why is CallBackType %d not kCFSocketReadCallBack?", CallBackType);
#if mDNS_AllowPort53
if (cfs == info->cfs53) { s1 = info->skt53; destPort = UnicastDNSPort; }
else
#endif
if (cfs == info->cfsv4) s1 = info->sktv4;
else if (cfs == info->cfsv6) s1 = info->sktv6;
if (s1 < 0 || s1 != skt)
{
LogMsg("myCFSocketCallBack: s1 %d native socket %d, cfs %p", s1, skt, cfs);
#if mDNS_AllowPort53
LogMsg("myCFSocketCallBack: cfs53 %p, skt53 %d", info->cfs53, info->skt53);
#endif
LogMsg("myCFSocketCallBack: cfsv4 %p, sktv4 %d", info->cfsv4, info->sktv4);
LogMsg("myCFSocketCallBack: cfsv6 %p, sktv6 %d", info->cfsv6, info->sktv6);
}
mDNSu8 ttl;
while ((err = myrecvfrom(s1, &packet, sizeof(packet), (struct sockaddr *)&from, &fromlen, &destAddr, packetifname, &ttl)) >= 0)
{
count++;
if (from.ss_family == AF_INET)
{
struct sockaddr_in *sin = (struct sockaddr_in*)&from;
senderAddr.type = mDNSAddrType_IPv4;
senderAddr.ip.v4.NotAnInteger = sin->sin_addr.s_addr;
senderPort.NotAnInteger = sin->sin_port;
}
else if (from.ss_family == AF_INET6)
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&from;
senderAddr.type = mDNSAddrType_IPv6;
senderAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
senderPort.NotAnInteger = sin6->sin6_port;
}
else
{
LogMsg("myCFSocketCallBack from is unknown address family %d", from.ss_family);
return;
}
if (strcmp(info->ifa_name, packetifname))
{
verbosedebugf("myCFSocketCallBack got a packet from %#a to %#a on interface %#a/%s (Ignored -- really arrived on interface %s)",
&senderAddr, &destAddr, &info->ifinfo.ip, info->ifa_name, packetifname);
return;
}
else
verbosedebugf("myCFSocketCallBack got a packet from %#a to %#a on interface %#a/%s",
&senderAddr, &destAddr, &info->ifinfo.ip, info->ifa_name);
if (err < (int)sizeof(DNSMessageHeader)) { debugf("myCFSocketCallBack packet length (%d) too short", err); return; }
mDNSCoreReceive(m, &packet, (unsigned char*)&packet + err, &senderAddr, senderPort, &destAddr, destPort, info->ifinfo.InterfaceID, ttl);
}
if (err < 0 && (errno != EWOULDBLOCK || count == 0))
{
int save_errno = errno;
int so_error = -1;
int so_nread = -1;
int fionread = -1;
int solen = sizeof(int);
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(s1, &readfds);
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
int selectresult = select(s1+1, &readfds, NULL, NULL, &timeout);
if (getsockopt(s1, SOL_SOCKET, SO_ERROR, &so_error, &solen) == -1)
LogMsg("myCFSocketCallBack getsockopt(SO_ERROR) error %d", errno);
if (getsockopt(s1, SOL_SOCKET, SO_NREAD, &so_nread, &solen) == -1)
LogMsg("myCFSocketCallBack getsockopt(SO_NREAD) error %d", errno);
if (ioctl(s1, FIONREAD, &fionread) == -1)
LogMsg("myCFSocketCallBack ioctl(FIONREAD) error %d", errno);
static unsigned int numLogMessages = 0;
if (numLogMessages++ < 100)
LogMsg("myCFSocketCallBack recvfrom skt %d error %d errno %d (%s) select %d (%spackets waiting) so_error %d so_nread %d fionread %d count %d",
s1, err, save_errno, strerror(save_errno), selectresult, FD_ISSET(s1, &readfds) ? "" : "*NO* ", so_error, so_nread, fionread, count);
sleep(1); }
}
mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel)
{
CFStringEncoding encoding = kCFStringEncodingUTF8;
CFStringRef cfs = SCDynamicStoreCopyComputerName(NULL, &encoding);
if (cfs)
{
CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
CFRelease(cfs);
}
}
mDNSlocal void GetUserSpecifiedRFC1034ComputerName(domainlabel *const namelabel)
{
CFStringRef cfs = SCDynamicStoreCopyLocalHostName(NULL);
if (cfs)
{
CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
CFRelease(cfs);
}
}
mDNSlocal mStatus SetupSocket(NetworkInterfaceInfoOSX *i, mDNSIPPort port, int *s, CFSocketRef *c)
{
const int on = 1;
const int twofivefive = 255;
if (*s >= 0) { LogMsg("SetupSocket ERROR: socket %d is already set", *s); return(-1); }
if (*c) { LogMsg("SetupSocket ERROR: CFSocketRef %p is already set", *c); return(-1); }
int skt = socket(i->sa_family, SOCK_DGRAM, IPPROTO_UDP);
if (skt < 0) { LogMsg("socket error %d errno %d (%s)", skt, errno, strerror(errno)); return(skt); }
mStatus err = setsockopt(skt, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
if (err < 0) { LogMsg("setsockopt - SO_REUSEPORT error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
if (i->sa_family == AF_INET)
{
err = setsockopt(skt, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
if (err < 0) { LogMsg("setsockopt - IP_RECVDSTADDR error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
if (err < 0) { LogMsg("setsockopt - IP_RECVIF error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
err = setsockopt(skt, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
struct in_addr addr = { i->ifinfo.ip.ip.v4.NotAnInteger };
struct ip_mreq imr;
imr.imr_multiaddr.s_addr = AllDNSLinkGroup.NotAnInteger;
imr.imr_interface = addr;
err = setsockopt(skt, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr));
if (err < 0) { LogMsg("setsockopt - IP_ADD_MEMBERSHIP error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr));
if (err < 0) { LogMsg("setsockopt - IP_MULTICAST_IF error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
err = setsockopt(skt, IPPROTO_IP, IP_TTL, &twofivefive, sizeof(twofivefive));
if (err < 0) { LogMsg("setsockopt - IP_TTL error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_TTL, &twofivefive, sizeof(twofivefive));
if (err < 0) { LogMsg("setsockopt - IP_MULTICAST_TTL error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
const int ip_tosbits = IPTOS_LOWDELAY | IPTOS_THROUGHPUT;
err = setsockopt(skt, IPPROTO_IP, IP_TOS, &ip_tosbits, sizeof(ip_tosbits));
if (err < 0) { LogMsg("setsockopt - IP_TOS error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
struct sockaddr_in listening_sockaddr;
listening_sockaddr.sin_family = AF_INET;
listening_sockaddr.sin_port = port.NotAnInteger;
listening_sockaddr.sin_addr.s_addr = 0; err = bind(skt, (struct sockaddr *) &listening_sockaddr, sizeof(listening_sockaddr));
if (err)
{
if (port.NotAnInteger == UnicastDNSPort.NotAnInteger) { close(skt); err = 0; }
else LogMsg("bind error %ld errno %d (%s)", err, errno, strerror(errno));
return(err);
}
}
else if (i->sa_family == AF_INET6)
{
err = setsockopt(skt, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on));
if (err < 0) { LogMsg("setsockopt - IPV6_PKTINFO error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
err = setsockopt(skt, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));
if (err < 0) { LogMsg("setsockopt - IPV6_HOPLIMIT error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
err = setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
if (err < 0) { LogMsg("setsockopt - IPV6_V6ONLY error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
int interface_id = if_nametoindex(i->ifa_name);
struct ipv6_mreq i6mr;
i6mr.ipv6mr_interface = interface_id;
i6mr.ipv6mr_multiaddr = *(struct in6_addr*)&AllDNSLinkGroupv6;
err = setsockopt(skt, IPPROTO_IPV6, IPV6_JOIN_GROUP, &i6mr, sizeof(i6mr));
if (err < 0) { LogMsg("setsockopt - IPV6_JOIN_GROUP error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_IF, &interface_id, sizeof(interface_id));
if (err < 0) { LogMsg("setsockopt - IPV6_MULTICAST_IF error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
err = setsockopt(skt, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &twofivefive, sizeof(twofivefive));
if (err < 0) { LogMsg("setsockopt - IPV6_UNICAST_HOPS error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &twofivefive, sizeof(twofivefive));
if (err < 0) { LogMsg("setsockopt - IPV6_MULTICAST_HOPS error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
#ifdef IPV6_TCLASS
int tclass = IPTOS_LOWDELAY | IPTOS_THROUGHPUT; err = setsockopt(skt, IPPROTO_IPV6, IPV6_TCLASS, &tclass, sizeof(tclass));
if (err < 0) { LogMsg("setsockopt - IPV6_TCLASS error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
#endif
err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &on, sizeof(on));
if (err < 0) { LogMsg("setsockopt - IPV6_MULTICAST_LOOP error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
struct sockaddr_in6 listening_sockaddr6;
bzero(&listening_sockaddr6, sizeof(listening_sockaddr6));
listening_sockaddr6.sin6_len = sizeof(listening_sockaddr6);
listening_sockaddr6.sin6_family = AF_INET6;
listening_sockaddr6.sin6_port = port.NotAnInteger;
listening_sockaddr6.sin6_flowinfo = 0;
listening_sockaddr6.sin6_scope_id = 0;
err = bind(skt, (struct sockaddr *) &listening_sockaddr6, sizeof(listening_sockaddr6));
if (err) { LogMsg("bind error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); }
}
fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); *s = skt;
CFSocketContext myCFSocketContext = { 0, i->ifinfo.InterfaceID, NULL, NULL, NULL };
*c = CFSocketCreateWithNative(kCFAllocatorDefault, *s, kCFSocketReadCallBack, myCFSocketCallBack, &myCFSocketContext);
CFRunLoopSourceRef rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, *c, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
CFRelease(rls);
return(err);
}
mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
{
if (sa->sa_family == AF_INET)
{
struct sockaddr_in *ifa_addr = (struct sockaddr_in *)sa;
ip->type = mDNSAddrType_IPv4;
ip->ip.v4.NotAnInteger = ifa_addr->sin_addr.s_addr;
return(0);
}
else if (sa->sa_family == AF_INET6)
{
struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa;
ip->type = mDNSAddrType_IPv6;
if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr;
return(0);
}
else
{
LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
return(-1);
}
}
mDNSlocal mStatus AddInterfaceToList(mDNS *const m, struct ifaddrs *ifa)
{
mDNSu32 scope_id = if_nametoindex(ifa->ifa_name);
mDNSAddr ip;
SetupAddr(&ip, ifa->ifa_addr);
NetworkInterfaceInfoOSX **p;
for (p = &m->p->InterfaceList; *p; p = &(*p)->next)
if (scope_id == (*p)->scope_id && mDNSSameAddress(&ip, &(*p)->ifinfo.ip))
{
debugf("AddInterfaceToList: Found existing interface %u with address %#a", scope_id, &ip);
(*p)->CurrentlyActive = mDNStrue;
return(0);
}
debugf("AddInterfaceToList: Making new interface %u with address %#a", scope_id, &ip);
NetworkInterfaceInfoOSX *i = (NetworkInterfaceInfoOSX *)mallocL("NetworkInterfaceInfoOSX", sizeof(*i));
if (!i) return(-1);
i->ifa_name = (char *)mallocL("NetworkInterfaceInfoOSX name", strlen(ifa->ifa_name) + 1);
if (!i->ifa_name) { freeL("NetworkInterfaceInfoOSX", i); return(-1); }
strcpy(i->ifa_name, ifa->ifa_name);
i->ifinfo.InterfaceID = mDNSNULL;
i->ifinfo.ip = ip;
i->ifinfo.Advertise = m->AdvertiseLocalAddresses;
i->ifinfo.TxAndRx = mDNSfalse;
i->next = mDNSNULL;
i->m = m;
i->scope_id = scope_id;
i->CurrentlyActive = mDNStrue;
i->sa_family = ifa->ifa_addr->sa_family;
#if mDNS_AllowPort53
i->skt53 = -1;
i->cfs53 = NULL;
#endif
i->sktv4 = -1;
i->cfsv4 = NULL;
i->sktv6 = -1;
i->cfsv6 = NULL;
if (!i->ifa_name) return(-1);
*p = i;
return(0);
}
mDNSlocal NetworkInterfaceInfoOSX *FindRoutableIPv4(mDNS *const m, mDNSu32 scope_id)
{
NetworkInterfaceInfoOSX *i;
for (i = m->p->InterfaceList; i; i = i->next)
if (i->CurrentlyActive && i->scope_id == scope_id && i->ifinfo.ip.type == mDNSAddrType_IPv4)
if (!(i->ifinfo.ip.ip.v4.b[0] == 169 && i->ifinfo.ip.ip.v4.b[1] == 254))
return(i);
return(mDNSNULL);
}
mDNSlocal mStatus UpdateInterfaceList(mDNS *const m)
{
mDNSBool foundav4 = mDNSfalse;
struct ifaddrs *ifa = myGetIfAddrs(1);
struct ifaddrs *theLoopback = NULL;
int err = (ifa != NULL) ? 0 : (errno != 0 ? errno : -1);
int InfoSocket = err ? -1 : socket(AF_INET6, SOCK_DGRAM, 0);
if (err) return(err);
m->nicelabel.c[0] = 0;
GetUserSpecifiedFriendlyComputerName(&m->nicelabel);
if (m->nicelabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->nicelabel, "Macintosh");
domainlabel hostlabel;
hostlabel.c[0] = 0;
GetUserSpecifiedRFC1034ComputerName(&hostlabel);
if (hostlabel.c[0] == 0) MakeDomainLabelFromLiteralString(&hostlabel, "Macintosh");
if (SameDomainLabel(m->p->userhostlabel.c, hostlabel.c))
debugf("Userhostlabel (%#s) unchanged since last time; not changing m->hostlabel (%#s)", m->p->userhostlabel.c, m->hostlabel.c);
else
{
debugf("Updating m->hostlabel to %#s", hostlabel.c);
m->p->userhostlabel = m->hostlabel = hostlabel;
mDNS_GenerateFQDN(m);
}
while (ifa)
{
#if LIST_ALL_INTERFACES
if (ifa->ifa_addr->sa_family == AF_APPLETALK)
debugf("UpdateInterfaceList: %4s(%d) Flags %04X Family %2d is AF_APPLETALK",
ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
else if (ifa->ifa_addr->sa_family == AF_LINK)
debugf("UpdateInterfaceList: %4s(%d) Flags %04X Family %2d is AF_LINK",
ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
else if (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6)
debugf("UpdateInterfaceList: %4s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)",
ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
if (!(ifa->ifa_flags & IFF_UP))
debugf("UpdateInterfaceList: %4s(%d) Flags %04X Family %2d Interface not IFF_UP",
ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
if (ifa->ifa_flags & IFF_POINTOPOINT)
debugf("UpdateInterfaceList: %4s(%d) Flags %04X Family %2d Interface IFF_POINTOPOINT",
ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
if (ifa->ifa_flags & IFF_LOOPBACK)
debugf("UpdateInterfaceList: %4s(%d) Flags %04X Family %2d Interface IFF_LOOPBACK",
ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
#endif
if ((ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) &&
(ifa->ifa_flags & IFF_MULTICAST) &&
(ifa->ifa_flags & IFF_UP) && !(ifa->ifa_flags & IFF_POINTOPOINT))
{
int ifru_flags6 = 0;
if (ifa->ifa_addr->sa_family == AF_INET6 && InfoSocket >= 0)
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
struct in6_ifreq ifr6;
bzero((char *)&ifr6, sizeof(ifr6));
strncpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr = *sin6;
if (ioctl(InfoSocket, SIOCGIFAFLAG_IN6, &ifr6) != -1)
ifru_flags6 = ifr6.ifr_ifru.ifru_flags6;
verbosedebugf("%s %.16a %04X %04X", ifa->ifa_name, &sin6->sin6_addr, ifa->ifa_flags, ifru_flags6);
}
if (!(ifru_flags6 & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY)))
{
if (ifa->ifa_flags & IFF_LOOPBACK)
theLoopback = ifa;
else
{
AddInterfaceToList(m, ifa);
if (ifa->ifa_addr->sa_family == AF_INET)
foundav4 = mDNStrue;
}
}
}
ifa = ifa->ifa_next;
}
if (!foundav4 && theLoopback)
AddInterfaceToList(m, theLoopback);
NetworkInterfaceInfoOSX *i;
for (i = m->p->InterfaceList; i; i = i->next)
if (i->CurrentlyActive)
{
mDNSBool txrx = ((i->ifinfo.ip.type == mDNSAddrType_IPv4) || !FindRoutableIPv4(m, i->scope_id));
if (i->ifinfo.TxAndRx != txrx)
{
i->ifinfo.TxAndRx = txrx;
i->CurrentlyActive = 2; }
}
if (InfoSocket >= 0) close(InfoSocket);
return(err);
}
mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(mDNS *const m, char *ifname, int type)
{
NetworkInterfaceInfoOSX *i;
for (i = m->p->InterfaceList; i; i = i->next)
if (!strcmp(i->ifa_name, ifname) &&
((AAAA_OVER_V4 ) ||
(type == AF_INET && i->ifinfo.ip.type == mDNSAddrType_IPv4) ||
(type == AF_INET6 && i->ifinfo.ip.type == mDNSAddrType_IPv6) )) return(i);
return(NULL);
}
mDNSlocal void SetupActiveInterfaces(mDNS *const m)
{
NetworkInterfaceInfoOSX *i;
for (i = m->p->InterfaceList; i; i = i->next)
{
mStatus err = 0;
NetworkInterfaceInfo *n = &i->ifinfo;
NetworkInterfaceInfoOSX *alias = SearchForInterfaceByName(m, i->ifa_name, i->sa_family);
if (!alias) alias = i;
if (n->InterfaceID && n->InterfaceID != (mDNSInterfaceID)alias)
{
LogMsg("SetupActiveInterfaces ERROR! n->InterfaceID %p != alias %p", n->InterfaceID, alias);
n->InterfaceID = mDNSNULL;
}
if (!n->InterfaceID)
{
n->InterfaceID = (mDNSInterfaceID)alias;
mDNS_RegisterInterface(m, n);
debugf("SetupActiveInterfaces: Registered %s(%lu) InterfaceID %p %#a%s",
i->ifa_name, i->scope_id, alias, &n->ip, n->InterfaceActive ? " (Primary)" : "");
}
if (!n->TxAndRx)
debugf("SetupActiveInterfaces: No TX/Rx on %s(%lu) InterfaceID %p %#a", i->ifa_name, i->scope_id, alias, &n->ip);
else
{
if (i->sa_family == AF_INET && alias->sktv4 == -1)
{
#if mDNS_AllowPort53
err = SetupSocket(i, UnicastDNSPort, &alias->skt53, &alias->cfs53);
#endif
if (!err) err = SetupSocket(i, MulticastDNSPort, &alias->sktv4, &alias->cfsv4);
if (err == 0) debugf("SetupActiveInterfaces: v4 socket%2d %s(%lu) InterfaceID %p %#a", alias->sktv4, i->ifa_name, i->scope_id, n->InterfaceID, &n->ip);
else LogMsg("SetupActiveInterfaces: v4 socket%2d %s(%lu) InterfaceID %p %#a FAILED", alias->sktv4, i->ifa_name, i->scope_id, n->InterfaceID, &n->ip);
}
if (i->sa_family == AF_INET6 && alias->sktv6 == -1)
{
err = SetupSocket(i, MulticastDNSPort, &alias->sktv6, &alias->cfsv6);
if (err == 0) debugf("SetupActiveInterfaces: v6 socket%2d %s(%lu) InterfaceID %p %#a", alias->sktv6, i->ifa_name, i->scope_id, n->InterfaceID, &n->ip);
else LogMsg("SetupActiveInterfaces: v6 socket%2d %s(%lu) InterfaceID %p %#a FAILED", alias->sktv6, i->ifa_name, i->scope_id, n->InterfaceID, &n->ip);
}
}
}
}
mDNSlocal void MarkAllInterfacesInactive(mDNS *const m)
{
NetworkInterfaceInfoOSX *i;
for (i = m->p->InterfaceList; i; i = i->next)
i->CurrentlyActive = mDNSfalse;
}
mDNSlocal void ClearInactiveInterfaces(mDNS *const m)
{
NetworkInterfaceInfoOSX *i;
for (i = m->p->InterfaceList; i; i = i->next)
{
NetworkInterfaceInfoOSX *alias = (NetworkInterfaceInfoOSX *)(i->ifinfo.InterfaceID);
if (i->ifinfo.InterfaceID && (!i->CurrentlyActive || (alias && !alias->CurrentlyActive) || i->CurrentlyActive == 2))
{
debugf("ClearInactiveInterfaces: Deregistering %#a", &i->ifinfo.ip);
mDNS_DeregisterInterface(m, &i->ifinfo);
i->ifinfo.InterfaceID = mDNSNULL;
}
}
NetworkInterfaceInfoOSX **p = &m->p->InterfaceList;
while (*p)
{
i = *p;
#if mDNS_AllowPort53
if (i->cfs53) { CFSocketInvalidate(i->cfs53); CFRelease(i->cfs53); }
i->skt53 = -1;
i->cfs53 = NULL;
#endif
if (i->cfsv4) { CFSocketInvalidate(i->cfsv4); CFRelease(i->cfsv4); }
if (i->cfsv6) { CFSocketInvalidate(i->cfsv6); CFRelease(i->cfsv6); }
i->sktv4 = i->sktv6 = -1;
i->cfsv4 = i->cfsv6 = NULL;
if (!i->CurrentlyActive)
{
debugf("ClearInactiveInterfaces: Deleting %#a", &i->ifinfo.ip);
*p = i->next;
if (i->ifa_name) freeL("NetworkInterfaceInfoOSX name", i->ifa_name);
freeL("NetworkInterfaceInfoOSX", i);
}
else
p = &i->next;
}
}
mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context)
{
(void)store; (void)changedKeys; debugf("*** Network Configuration Change ***");
mDNS *const m = (mDNS *const)context;
MarkAllInterfacesInactive(m);
UpdateInterfaceList(m);
ClearInactiveInterfaces(m);
SetupActiveInterfaces(m);
if (m->MainCallback)
m->MainCallback(m, mStatus_ConfigChanged);
}
mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m)
{
mStatus err = -1;
SCDynamicStoreContext context = { 0, m, NULL, NULL, NULL };
SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder"), NetworkChanged, &context);
CFStringRef key1 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
CFStringRef key2 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6);
CFStringRef key3 = SCDynamicStoreKeyCreateComputerName(NULL);
CFStringRef key4 = SCDynamicStoreKeyCreateHostNames(NULL);
CFStringRef pattern1 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4);
CFStringRef pattern2 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6);
CFMutableArrayRef keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
CFMutableArrayRef patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
if (!store) { LogMsg("SCDynamicStoreCreate failed: %s\n", SCErrorString(SCError())); goto error; }
if (!key1 || !key2 || !key3 || !key4 || !keys || !pattern1 || !pattern2 || !patterns) goto error;
CFArrayAppendValue(keys, key1);
CFArrayAppendValue(keys, key2);
CFArrayAppendValue(keys, key3);
CFArrayAppendValue(keys, key4);
CFArrayAppendValue(patterns, pattern1);
CFArrayAppendValue(patterns, pattern2);
if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns))
{ LogMsg("SCDynamicStoreSetNotificationKeys failed: %s\n", SCErrorString(SCError())); goto error; }
m->p->StoreRLS = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
if (!m->p->StoreRLS) { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s\n", SCErrorString(SCError())); goto error; }
CFRunLoopAddSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode);
m->p->Store = store;
err = 0;
goto exit;
error:
if (store) CFRelease(store);
exit:
if (key1) CFRelease(key1);
if (key2) CFRelease(key2);
if (key3) CFRelease(key3);
if (key4) CFRelease(key4);
if (pattern1) CFRelease(pattern1);
if (pattern2) CFRelease(pattern2);
if (keys) CFRelease(keys);
if (patterns) CFRelease(patterns);
return(err);
}
mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messageType, void *messageArgument)
{
mDNS *const m = (mDNS *const)refcon;
(void)service; switch(messageType)
{
case kIOMessageCanSystemPowerOff: debugf("PowerChanged kIOMessageCanSystemPowerOff (no action)"); break; case kIOMessageSystemWillPowerOff: debugf("PowerChanged kIOMessageSystemWillPowerOff"); mDNSCoreMachineSleep(m, true); break; case kIOMessageSystemWillNotPowerOff: debugf("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; case kIOMessageCanSystemSleep: debugf("PowerChanged kIOMessageCanSystemSleep (no action)"); break; case kIOMessageSystemWillSleep: debugf("PowerChanged kIOMessageSystemWillSleep"); mDNSCoreMachineSleep(m, true); break; case kIOMessageSystemWillNotSleep: debugf("PowerChanged kIOMessageSystemWillNotSleep (no action)"); break; case kIOMessageSystemHasPoweredOn: debugf("PowerChanged kIOMessageSystemHasPoweredOn"); mDNSCoreMachineSleep(m, false); break; default: debugf("PowerChanged unknown message %X", messageType); break;
}
IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument);
}
mDNSlocal mStatus WatchForPowerChanges(mDNS *const m)
{
IONotificationPortRef thePortRef;
m->p->PowerConnection = IORegisterForSystemPower(m, &thePortRef, PowerChanged, &m->p->PowerNotifier);
if (m->p->PowerConnection)
{
m->p->PowerRLS = IONotificationPortGetRunLoopSource(thePortRef);
CFRunLoopAddSource(CFRunLoopGetCurrent(), m->p->PowerRLS, kCFRunLoopDefaultMode);
return(mStatus_NoError);
}
return(-1);
}
CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey;
CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey;
CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey;
mDNSexport mDNSBool mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring)
{
int major = 0, minor = 0;
char letter = 0, prodname[256]="Mac OS X", prodvers[256]="", buildver[256]="?";
CFDictionaryRef vers = _CFCopySystemVersionDictionary();
if (vers)
{
CFStringRef cfprodname = CFDictionaryGetValue(vers, _kCFSystemVersionProductNameKey);
CFStringRef cfprodvers = CFDictionaryGetValue(vers, _kCFSystemVersionProductVersionKey);
CFStringRef cfbuildver = CFDictionaryGetValue(vers, _kCFSystemVersionBuildVersionKey);
if (cfprodname) CFStringGetCString(cfprodname, prodname, sizeof(prodname), kCFStringEncodingUTF8);
if (cfprodvers) CFStringGetCString(cfprodvers, prodvers, sizeof(prodvers), kCFStringEncodingUTF8);
if (cfbuildver) CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8);
sscanf(buildver, "%d%c%d", &major, &letter, &minor);
CFRelease(vers);
}
if (HINFO_SWstring) mDNS_snprintf(HINFO_SWstring, 256, "%s %s (%s), %s", prodname, prodvers, buildver, mDNSResponderVersionString);
return(major);
}
mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
{
mStatus err;
m->hostlabel.c[0] = 0;
char *HINFO_HWstring = "Macintosh";
char HINFO_HWstring_buffer[256];
int get_model[2] = { CTL_HW, HW_MODEL };
size_t len_model = sizeof(HINFO_HWstring_buffer);
if (sysctl(get_model, 2, HINFO_HWstring_buffer, &len_model, NULL, 0) == 0)
HINFO_HWstring = HINFO_HWstring_buffer;
char HINFO_SWstring[256] = "";
if (mDNSMacOSXSystemBuildNumber(HINFO_SWstring) < 7) m->KnownBugs = mDNS_KnownBug_PhantomInterfaces;
mDNSu32 hlen = mDNSPlatformStrLen(HINFO_HWstring);
mDNSu32 slen = mDNSPlatformStrLen(HINFO_SWstring);
if (hlen + slen < 254)
{
m->HIHardware.c[0] = hlen;
m->HISoftware.c[0] = slen;
mDNSPlatformMemCopy(HINFO_HWstring, &m->HIHardware.c[1], hlen);
mDNSPlatformMemCopy(HINFO_SWstring, &m->HISoftware.c[1], slen);
}
m->p->InterfaceList = mDNSNULL;
m->p->userhostlabel.c[0] = 0;
UpdateInterfaceList(m);
SetupActiveInterfaces(m);
err = WatchForNetworkChanges(m);
if (err) return(err);
err = WatchForPowerChanges(m);
return(err);
}
mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
{
mStatus result = mDNSPlatformInit_setup(m);
if (result == mStatus_NoError) mDNSCoreInitComplete(m, mStatus_NoError);
return(result);
}
mDNSexport void mDNSPlatformClose(mDNS *const m)
{
if (m->p->PowerConnection)
{
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->PowerRLS, kCFRunLoopDefaultMode);
CFRunLoopSourceInvalidate(m->p->PowerRLS);
CFRelease(m->p->PowerRLS);
IODeregisterForSystemPower(&m->p->PowerNotifier);
m->p->PowerConnection = NULL;
m->p->PowerNotifier = NULL;
m->p->PowerRLS = NULL;
}
if (m->p->Store)
{
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode);
CFRunLoopSourceInvalidate(m->p->StoreRLS);
CFRelease(m->p->StoreRLS);
CFRelease(m->p->Store);
m->p->Store = NULL;
m->p->StoreRLS = NULL;
}
MarkAllInterfacesInactive(m);
ClearInactiveInterfaces(m);
}
mDNSexport mDNSs32 mDNSPlatformOneSecond = 1000;
mDNSexport mStatus mDNSPlatformTimeInit(mDNSs32 *timenow)
{
struct mach_timebase_info tbi;
kern_return_t result = mach_timebase_info(&tbi);
if (result != KERN_SUCCESS) return(result);
clockdivisor = ((uint64_t)tbi.denom * 1000000) / tbi.numer;
*timenow = mDNSPlatformTimeNow();
return(mStatus_NoError);
}
mDNSexport mDNSs32 mDNSPlatformTimeNow(void)
{
if (clockdivisor == 0) { LogMsg("mDNSPlatformTimeNow called before mDNSPlatformTimeInit"); return(0); }
return((mDNSs32)(mach_absolute_time() / clockdivisor));
}
mDNSexport void mDNSPlatformLock (const mDNS *const m) { (void)m; }
mDNSexport void mDNSPlatformUnlock (const mDNS *const m) { (void)m; }
mDNSexport void mDNSPlatformStrCopy(const void *src, void *dst) { strcpy((char *)dst, (char *)src); }
mDNSexport mDNSu32 mDNSPlatformStrLen (const void *src) { return(strlen((char*)src)); }
mDNSexport void mDNSPlatformMemCopy(const void *src, void *dst, mDNSu32 len) { memcpy(dst, src, len); }
mDNSexport mDNSBool mDNSPlatformMemSame(const void *src, const void *dst, mDNSu32 len) { return(memcmp(dst, src, len) == 0); }
mDNSexport void mDNSPlatformMemZero( void *dst, mDNSu32 len) { bzero(dst, len); }
mDNSexport void * mDNSPlatformMemAllocate(mDNSu32 len) { return(mallocL("mDNSPlatformMemAllocate", len)); }
mDNSexport void mDNSPlatformMemFree (void *mem) { freeL("mDNSPlatformMemFree", mem); }