summaryrefslogtreecommitdiffstats
path: root/mDNSResponder
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-19 08:53:26 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-20 11:23:32 +0200
commitf01edf10244ccd53e098abdc1773c1aa0e4c5f8d (patch)
tree958a1ee323520629c4f027de1d4c56715949aa5c /mDNSResponder
parentmDNSResponder: Update to v625.41.2 (diff)
downloadrtems-libbsd-f01edf10244ccd53e098abdc1773c1aa0e4c5f8d.tar.bz2
mDNSResponder: Update to v765.1.2
The sources can be obtained via: https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-765.1.2.tar.gz Move mDNS_StartResolveService() and mDNS_StopResolveService() to an RTEMS-specific file (rtemsbsd/mdns/mDNSResolveService.c) using the v576.30.4 implementation. Apple removed these functions without explanation. Update #3522.
Diffstat (limited to 'mDNSResponder')
-rw-r--r--mDNSResponder/Clients/ClientCommon.c3
-rw-r--r--mDNSResponder/Clients/Java/nmakefile2
-rw-r--r--mDNSResponder/Clients/dns-sd.c606
-rw-r--r--mDNSResponder/Clients/dnsctl.c227
-rw-r--r--mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/52D711AF-4055-4867-A494-7E31552BB9E1.pngbin0 -> 153759 bytes
-rw-r--r--mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/Screen Shot 2015-09-16 at 3.36.23 PM.pngbin0 -> 6231 bytes
-rw-r--r--mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/Screen Shot 2015-09-16 at 3.46.14 PM.pngbin0 -> 6910 bytes
-rw-r--r--mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/TXT.rtf75
-rw-r--r--mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/unknown.pngbin0 -> 55910 bytes
-rw-r--r--mDNSResponder/Documents/Start mDNSResponder in Xcode.rtfd/A944EB40-AEFD-4CA1-BF10-E8F52835CA8C.pngbin0 -> 90282 bytes
-rw-r--r--mDNSResponder/Documents/Start mDNSResponder in Xcode.rtfd/Screen Shot 2015-09-16 at 4.22.37 PM.pngbin0 -> 8498 bytes
-rw-r--r--mDNSResponder/Documents/Start mDNSResponder in Xcode.rtfd/TXT.rtf57
-rw-r--r--mDNSResponder/Makefile3
-rw-r--r--mDNSResponder/mDNSCore/DNSCommon.c59
-rw-r--r--mDNSResponder/mDNSCore/DNSCommon.h25
-rw-r--r--mDNSResponder/mDNSCore/anonymous.c7
-rw-r--r--mDNSResponder/mDNSCore/dnsproxy.c28
-rw-r--r--mDNSResponder/mDNSCore/dnssec.c7
-rwxr-xr-xmDNSResponder/mDNSCore/mDNS.c1826
-rwxr-xr-xmDNSResponder/mDNSCore/mDNSEmbeddedAPI.h247
-rw-r--r--mDNSResponder/mDNSCore/nsec3.c4
-rwxr-xr-xmDNSResponder/mDNSCore/uDNS.c801
-rwxr-xr-xmDNSResponder/mDNSCore/uDNS.h14
-rw-r--r--mDNSResponder/mDNSMacOSX/BLE.c853
-rw-r--r--mDNSResponder/mDNSMacOSX/BLE.h54
-rw-r--r--mDNSResponder/mDNSMacOSX/DNSProxySupport.c22
-rw-r--r--mDNSResponder/mDNSMacOSX/DNSSECSupport.c8
-rw-r--r--mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c595
-rw-r--r--mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.h180
-rw-r--r--mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryDefines.h2
-rw-r--r--mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryReply.defs60
-rw-r--r--mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryRequest.defs80
-rw-r--r--mDNSResponder/mDNSMacOSX/Metrics.h7
-rw-r--r--mDNSResponder/mDNSMacOSX/Metrics.m1903
-rw-r--r--mDNSResponder/mDNSMacOSX/P2PPacketFilter.c6
-rw-r--r--mDNSResponder/mDNSMacOSX/P2PPacketFilter.h3
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c4
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m4
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.c10
-rw-r--r--mDNSResponder/mDNSMacOSX/Private/com.apple.mDNSResponder.plist19
-rw-r--r--mDNSResponder/mDNSMacOSX/Private/dns_sd_private.h27
-rw-r--r--mDNSResponder/mDNSMacOSX/Private/dns_services.c49
-rw-r--r--mDNSResponder/mDNSMacOSX/Private/dns_services.h3
-rw-r--r--mDNSResponder/mDNSMacOSX/Private/dns_xpc.h30
-rw-r--r--mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c224
-rw-r--r--mDNSResponder/mDNSMacOSX/Private/xpc_services.c13
-rw-r--r--mDNSResponder/mDNSMacOSX/Private/xpc_services.h6
-rw-r--r--mDNSResponder/mDNSMacOSX/SymptomReporter.c59
-rw-r--r--mDNSResponder/mDNSMacOSX/com.apple.dnsextd.plist2
-rw-r--r--mDNSResponder/mDNSMacOSX/com.apple.mDNSResponder.plist10
-rw-r--r--mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist2
-rw-r--r--mDNSResponder/mDNSMacOSX/com.apple.networking.mDNSResponder1
-rw-r--r--mDNSResponder/mDNSMacOSX/coreBLE.h32
-rw-r--r--mDNSResponder/mDNSMacOSX/coreBLE.m371
-rw-r--r--mDNSResponder/mDNSMacOSX/daemon.c1902
-rw-r--r--mDNSResponder/mDNSMacOSX/dnsctl-entitlements.plist2
-rw-r--r--mDNSResponder/mDNSMacOSX/helper-error.h49
-rw-r--r--mDNSResponder/mDNSMacOSX/helper-main.c586
-rw-r--r--mDNSResponder/mDNSMacOSX/helper-server.h3
-rw-r--r--mDNSResponder/mDNSMacOSX/helper-stubs.c823
-rw-r--r--mDNSResponder/mDNSMacOSX/helper.c2678
-rw-r--r--mDNSResponder/mDNSMacOSX/helper.h97
-rw-r--r--mDNSResponder/mDNSMacOSX/helpermsg-types.h2
-rw-r--r--mDNSResponder/mDNSMacOSX/helpermsg.defs143
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSMacOSX.c1346
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSMacOSX.h8
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist8
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSResponder.sb14
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj1042
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/Build All.xcscheme80
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/mDNSResponder.xcscheme101
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSResponderLogging.mobileconfig57
-rw-r--r--mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c10
-rwxr-xr-xmDNSResponder/mDNSPosix/._ReadMe.txtbin171 -> 0 bytes
-rwxr-xr-xmDNSResponder/mDNSPosix/Makefile11
-rwxr-xr-xmDNSResponder/mDNSPosix/ReadMe.txt14
-rwxr-xr-xmDNSResponder/mDNSPosix/mDNSPosix.c72
-rw-r--r--mDNSResponder/mDNSPosix/mdnsd.sh2
-rwxr-xr-xmDNSResponder/mDNSPosix/nss_mdns.c4
-rw-r--r--mDNSResponder/mDNSShared/PlatformCommon.c13
-rw-r--r--mDNSResponder/mDNSShared/dns_sd.h154
-rw-r--r--mDNSResponder/mDNSShared/dnssd_clientshim.c2
-rw-r--r--mDNSResponder/mDNSShared/dnssd_clientstub.c98
-rw-r--r--mDNSResponder/mDNSShared/dnssd_ipc.h2
-rw-r--r--mDNSResponder/mDNSShared/uds_daemon.c683
-rw-r--r--mDNSResponder/mDNSShared/uds_daemon.h19
-rwxr-xr-xmDNSResponder/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp4
-rwxr-xr-xmDNSResponder/mDNSWindows/ControlPanel/ControlPanelExe.cpp9
-rwxr-xr-xmDNSResponder/mDNSWindows/ControlPanel/FourthPage.cpp2
-rwxr-xr-xmDNSResponder/mDNSWindows/DLLStub/DLLStub.cpp4
-rwxr-xr-xmDNSResponder/mDNSWindows/DLLX/DNSSD.cpp2
-rw-r--r--mDNSResponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp12
-rw-r--r--mDNSResponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp2
-rw-r--r--mDNSResponder/mDNSWindows/Java/makefile2
-rw-r--r--mDNSResponder/mDNSWindows/Java/makefile642
-rw-r--r--mDNSResponder/mDNSWindows/NSPTool/NSPTool.c8
-rw-r--r--mDNSResponder/mDNSWindows/SystemService/Service.c2
-rwxr-xr-xmDNSResponder/mDNSWindows/mDNSWin32.c195
-rw-r--r--mDNSResponder/mDNSWindows/mdnsNSP/mdnsNSP.c13
-rw-r--r--mDNSResponder/unittests/DNSMessageTest.c50
-rw-r--r--mDNSResponder/unittests/DNSMessageTest.h8
-rw-r--r--mDNSResponder/unittests/DomainNameTest.c28
-rw-r--r--mDNSResponder/unittests/DomainNameTest.h7
-rw-r--r--mDNSResponder/unittests/InterfaceTest.c19
-rw-r--r--mDNSResponder/unittests/InterfaceTest.h9
-rw-r--r--mDNSResponder/unittests/ResourceRecordTest.c60
-rw-r--r--mDNSResponder/unittests/ResourceRecordTest.h10
-rw-r--r--mDNSResponder/unittests/main.c33
-rw-r--r--mDNSResponder/unittests/unittest.c105
-rw-r--r--mDNSResponder/unittests/unittest.h84
110 files changed, 11487 insertions, 7838 deletions
diff --git a/mDNSResponder/Clients/ClientCommon.c b/mDNSResponder/Clients/ClientCommon.c
index cb59e7b9..f96319ce 100644
--- a/mDNSResponder/Clients/ClientCommon.c
+++ b/mDNSResponder/Clients/ClientCommon.c
@@ -49,8 +49,9 @@ const char *GetNextLabel(const char *cstr, char label[64])
while (*cstr && *cstr != '.') // While we have characters in the label...
{
char c = *cstr++;
- if (c == '\\' && *cstr) // If we have a backslash, and it's not the last character of the string
+ if (c == '\\') // If escape character, check next character
{
+ if (*cstr == '\0') break; // If this is the end of the string, then break
c = *cstr++;
if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1]))
{
diff --git a/mDNSResponder/Clients/Java/nmakefile b/mDNSResponder/Clients/Java/nmakefile
index 89168e0b..1758f7a4 100644
--- a/mDNSResponder/Clients/Java/nmakefile
+++ b/mDNSResponder/Clients/Java/nmakefile
@@ -29,7 +29,7 @@
############################################################################
-JDK = $(JAVA_HOME)
+JDK = "$(JAVA_HOME)"
CP = copy
RM = del /Q
diff --git a/mDNSResponder/Clients/dns-sd.c b/mDNSResponder/Clients/dns-sd.c
index 9469d24d..f36211e5 100644
--- a/mDNSResponder/Clients/dns-sd.c
+++ b/mDNSResponder/Clients/dns-sd.c
@@ -320,18 +320,70 @@ static char *DNSTypeName(unsigned short rr_type)
{
switch (rr_type)
{
- case kDNSServiceType_A: return("Addr");
- case kDNSServiceType_NS: return("NS");
- case kDNSServiceType_MX: return("MX");
- case kDNSServiceType_CNAME: return("CNAME");
- case kDNSServiceType_SOA: return("SOA");
- case kDNSServiceType_PTR: return("PTR");
- case kDNSServiceType_AAAA: return("AAAA");
- case kDNSServiceType_NSEC: return("NSEC");
- case kDNSServiceType_TSIG: return("TSIG");
- case kDNSServiceType_RRSIG: return("RRSIG");
- case kDNSServiceType_DNSKEY: return("DNSKEY");
- case kDNSServiceType_DS: return("DS");
+ case kDNSServiceType_A: return("Addr");
+ case kDNSServiceType_NS: return("NS");
+ case kDNSServiceType_MD: return("MD");
+ case kDNSServiceType_MF: return("MF");
+ case kDNSServiceType_CNAME: return("CNAME");
+ case kDNSServiceType_SOA: return("SOA");
+ case kDNSServiceType_MB: return("MB");
+ case kDNSServiceType_MG: return("MG");
+ case kDNSServiceType_MR: return("MR");
+ case kDNSServiceType_NULL: return("NULL");
+ case kDNSServiceType_WKS: return("WKS");
+ case kDNSServiceType_PTR: return("PTR");
+ case kDNSServiceType_HINFO: return("HINFO");
+ case kDNSServiceType_MINFO: return("MINFO");
+ case kDNSServiceType_MX: return("MX");
+ case kDNSServiceType_TXT: return("TXT");
+ case kDNSServiceType_RP: return("RP");
+ case kDNSServiceType_AFSDB: return("AFSDB");
+ case kDNSServiceType_X25: return("X25");
+ case kDNSServiceType_ISDN: return("ISDN");
+ case kDNSServiceType_RT: return("RT");
+ case kDNSServiceType_NSAP: return("NSAP");
+ case kDNSServiceType_NSAP_PTR: return("NSAP_PTR");
+ case kDNSServiceType_SIG: return("SIG");
+ case kDNSServiceType_KEY: return("KEY");
+ case kDNSServiceType_PX: return("PX");
+ case kDNSServiceType_GPOS: return("GPOS");
+ case kDNSServiceType_AAAA: return("AAAA");
+ case kDNSServiceType_LOC: return("LOC");
+ case kDNSServiceType_NXT: return("NXT");
+ case kDNSServiceType_EID: return("EID");
+ case kDNSServiceType_NIMLOC: return("NIMLOC");
+ case kDNSServiceType_SRV: return("SRV");
+ case kDNSServiceType_ATMA: return("ATMA");
+ case kDNSServiceType_NAPTR: return("NAPTR");
+ case kDNSServiceType_KX: return("KX");
+ case kDNSServiceType_CERT: return("CERT");
+ case kDNSServiceType_A6: return("A6");
+ case kDNSServiceType_DNAME: return("DNAME");
+ case kDNSServiceType_SINK: return("SINK");
+ case kDNSServiceType_OPT: return("OPT");
+ case kDNSServiceType_APL: return("APL");
+ case kDNSServiceType_DS: return("DS");
+ case kDNSServiceType_SSHFP: return("SSHFP");
+ case kDNSServiceType_IPSECKEY: return("IPSECKEY");
+ case kDNSServiceType_RRSIG: return("RRSIG");
+ case kDNSServiceType_NSEC: return("NSEC");
+ case kDNSServiceType_DNSKEY: return("DNSKEY");
+ case kDNSServiceType_DHCID: return("DHCID");
+ case kDNSServiceType_NSEC3: return("NSEC3");
+ case kDNSServiceType_NSEC3PARAM: return("NSEC3PARAM");
+ case kDNSServiceType_HIP: return("HIP");
+ case kDNSServiceType_SPF: return("SPF");
+ case kDNSServiceType_UINFO: return("UINFO");
+ case kDNSServiceType_UID: return("UID");
+ case kDNSServiceType_GID: return("GID");
+ case kDNSServiceType_UNSPEC: return("UNSPEC");
+ case kDNSServiceType_TKEY: return("TKEY");
+ case kDNSServiceType_TSIG: return("TSIG");
+ case kDNSServiceType_IXFR: return("IXFR");
+ case kDNSServiceType_AXFR: return("AXFR");
+ case kDNSServiceType_MAILB: return("MAILB");
+ case kDNSServiceType_MAILA: return("MAILA");
+ case kDNSServiceType_ANY: return("ANY");
default:
{
static char buffer[RR_TYPE_SIZE];
@@ -422,7 +474,9 @@ static DNSServiceProtocol GetProtocol(const char *s)
//*************************************************************************************************************
// Sample callback functions for each of the operation types
-static void printtimestamp(void)
+#define printtimestamp() printtimestamp_F(stdout)
+
+static void printtimestamp_F(FILE *outstream)
{
struct tm tm;
int ms;
@@ -443,10 +497,10 @@ static void printtimestamp(void)
strftime(new_date, sizeof(new_date), "%a %d %b %Y", &tm);
if (strncmp(date, new_date, sizeof(new_date)))
{
- printf("DATE: ---%s---\n", new_date); //display date only if it has changed
+ fprintf(outstream, "DATE: ---%s---\n", new_date); //display date only if it has changed
strncpy(date, new_date, sizeof(date));
}
- printf("%2d:%02d:%02d.%03d ", tm.tm_hour, tm.tm_min, tm.tm_sec, ms);
+ fprintf(outstream, "%2d:%02d:%02d.%03d ", tm.tm_hour, tm.tm_min, tm.tm_sec, ms);
}
// formating time to RFC 4034 format
@@ -467,41 +521,50 @@ static void FormatTime(unsigned long te, unsigned char *buf, int bufsize)
static void print_usage(const char *arg0, int print_all)
{
+ // Print the commonly used command line options. These are listed in "the order they have been in historically".
fprintf(stderr, "%s -E (Enumerate recommended registration domains)\n", arg0);
fprintf(stderr, "%s -F (Enumerate recommended browsing domains)\n", arg0);
fprintf(stderr, "%s -R <Name> <Type> <Domain> <Port> [<TXT>...] (Register a service)\n", arg0);
- fprintf(stderr, "%s -B <Type> <Domain> (Browse for services instances)\n", arg0);
- fprintf(stderr, "%s -L <Name> <Type> <Domain> (Look up a service instance)\n", arg0);
- fprintf(stderr, "%s -P <Name> <Type> <Domain> <Port> <Host> <IP> [<TXT>...] (Proxy)\n", arg0);
- fprintf(stderr, "%s -q <name> <rrtype> <rrclass> (Generic query for any record type)\n", arg0);
- fprintf(stderr, "%s -D <name> <rrtype> <rrclass>(Validate query for any record type with DNSSEC)\n", arg0);
+ fprintf(stderr, "%s -B <Type> <Domain> (Browse for service instances)\n", arg0);
+ fprintf(stderr, "%s -L <Name> <Type> <Domain> (Resolve a service instance)\n", arg0);
+ fprintf(stderr, "%s -Q <name> <rrtype> <rrclass> (Generic query for any record type)\n", arg0);
fprintf(stderr, "%s -Z <Type> <Domain> (Output results in Zone File format)\n", arg0);
fprintf(stderr, "%s -G v4/v6/v4v6 <name> (Get address information for hostname)\n", arg0);
- fprintf(stderr, "%s -g v4/v6/v4v6 <name> (Validate address info for hostname with DNSSEC)\n", arg0);
+ fprintf(stderr, "%s -H (Print usage for complete command list)\n", arg0);
fprintf(stderr, "%s -V (Get version of currently running daemon / system service)\n", arg0);
- if (print_all) //Print all available options for dns-sd tool
+ if (print_all) // Print all available options for dns-sd tool. Keep these in alphabetical order for easier maintenance.
{
- fprintf(stderr, "%s -C <FQDN> <rrtype> <rrclass> (Query; reconfirming each result)\n", arg0);
- fprintf(stderr, "%s -X udp/tcp/udptcp <IntPort> <ExtPort> <TTL> (NAT Port Mapping)\n", arg0);
+ fprintf(stderr, "\n");
fprintf(stderr, "%s -A (Test Adding/Updating/Deleting a record)\n", arg0);
- fprintf(stderr, "%s -U (Test updating a TXT record)\n", arg0);
+ fprintf(stderr, "%s -C <FQDN> <rrtype> <rrclass> (Query; reconfirming each result)\n", arg0);
+ fprintf(stderr, "%s -D <name> <rrtype> <rrclass>(Validate query for any record type with DNSSEC)\n", arg0);
+ fprintf(stderr, "%s -I (Test registering and then immediately updating TXT record)\n", arg0);
fprintf(stderr, "%s -N (Test adding a large NULL record)\n", arg0);
- fprintf(stderr, "%s -T (Test creating a large TXT record)\n", arg0);
fprintf(stderr, "%s -M (Test creating a registration with multiple TXT records)\n", arg0);
- fprintf(stderr, "%s -I (Test registering and then immediately updating TXT record)\n", arg0);
+ fprintf(stderr, "%s -P <Name> <Type> <Domain> <Port> <Host> <IP> [<TXT>...] (Proxy)\n", arg0);
fprintf(stderr, "%s -S (Test multiple operations on a shared socket)\n", arg0);
+ fprintf(stderr, "%s -T (Test creating a large TXT record)\n", arg0);
+ fprintf(stderr, "%s -U (Test updating a TXT record)\n", arg0);
+ fprintf(stderr, "%s -X udp/tcp/udptcp <IntPort> <ExtPort> <TTL> (NAT Port Mapping)\n", arg0);
+ fprintf(stderr, "%s -ble (Use kDNSServiceInterfaceIndexBLE)\n", arg0);
+ fprintf(stderr, "%s -g v4/v6/v4v6 <name> (Validate address info for hostname with DNSSEC)\n", arg0);
fprintf(stderr, "%s -i <Interface> (Run dns-sd cmd on a specific interface (en0/en1)\n", arg0);
- fprintf(stderr, "%s -lo (Run dns-sd cmd using local only interface)\n", arg0);
- fprintf(stderr, "%s -p2p (Use kDNSServiceInterfaceIndexP2P)\n", arg0);
fprintf(stderr, "%s -includep2p (Set kDNSServiceFlagsIncludeP2P flag)\n", arg0);
fprintf(stderr, "%s -includeAWDL (Set kDNSServiceFlagsIncludeAWDL flag)\n", arg0);
+ fprintf(stderr, "%s -intermediates (Set kDNSServiceFlagsReturnIntermediates flag)\n", arg0);
+ fprintf(stderr, "%s -ku (Set kDNSServiceFlagsKnownUnique flag)\n", arg0);
+ fprintf(stderr, "%s -lo (Run dns-sd cmd using local only interface)\n", arg0);
fprintf(stderr, "%s -optional (Set kDNSServiceFlagsValidateOptional flag)\n", arg0);
+ fprintf(stderr, "%s -p2p (Use kDNSServiceInterfaceIndexP2P)\n", arg0);
+ fprintf(stderr, "%s -q <name> <rrtype> <rrclass> (Equivalent to -Q with kDNSServiceFlagsSuppressUnusable set)\n", arg0);
fprintf(stderr, "%s -tc (Set kDNSServiceFlagsBackgroundTrafficClass flag)\n", arg0);
- fprintf(stderr, "%s -unicastResponse (Set kDNSServiceFlagsUnicastResponse flag)\n", arg0);
+ fprintf(stderr, "%s -test (Run basic API input range tests)\n", arg0);
fprintf(stderr, "%s -t1 (Set kDNSServiceFlagsThresholdOne flag)\n", arg0);
fprintf(stderr, "%s -tFinder (Set kDNSServiceFlagsThresholdFinder flag)\n", arg0);
fprintf(stderr, "%s -timeout (Set kDNSServiceFlagsTimeout flag)\n", arg0);
+ fprintf(stderr, "%s -unicastResponse (Set kDNSServiceFlagsUnicastResponse flag)\n", arg0);
+ fprintf(stderr, "%s -autoTrigger (Set kDNSServiceFlagsAutoTrigger flag)\n", arg0);
}
}
@@ -731,17 +794,20 @@ static void DNSSD_API resolve_reply(DNSServiceRef sdref, const DNSServiceFlags f
(void)context; // Unused
EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode);
- if (errorCode)
- printf("Error code %d\n", errorCode);
- else
- {
- printtimestamp();
- printf("%s can be reached at %s:%u (interface %d)", fullname, hosttarget, PortAsNumber, ifIndex);
- if (flags) printf(" Flags: %X", flags);
- // Don't show degenerate TXT records containing nothing but a single empty string
- if (txtLen > 1) { printf("\n"); ShowTXTRecord(txtLen, txtRecord); }
- printf("\n");
- }
+ printtimestamp();
+
+ printf("%s ", fullname);
+
+ if (errorCode == kDNSServiceErr_NoSuchRecord) printf("No Such Record");
+ else if (errorCode) printf("error code %d\n", errorCode);
+ else printf("can be reached at %s:%u (interface %d)", hosttarget, PortAsNumber, ifIndex);
+
+ if (flags) printf(" Flags: %X", flags);
+
+ // Don't show degenerate TXT records containing nothing but a single empty string
+ if (!errorCode && txtLen > 1) { printf("\n"); ShowTXTRecord(txtLen, txtRecord); }
+
+ printf("\n");
if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
}
@@ -776,6 +842,7 @@ static void myTimerCallBack(void)
{
if (updatetest[1] != 'Z') updatetest[1]++;
else updatetest[1] = 'A';
+ // The following line toggles the string length between 1 and 2 characters.
updatetest[0] = 3 - updatetest[0];
updatetest[2] = updatetest[1];
printtimestamp();
@@ -1249,7 +1316,7 @@ static void HandleEvents(void)
DNSServiceErrorType err = kDNSServiceErr_NoError;
if (client && FD_ISSET(dns_sd_fd, &readfds)) err = DNSServiceProcessResult(client );
else if (client_pa && FD_ISSET(dns_sd_fd2, &readfds)) err = DNSServiceProcessResult(client_pa);
- if (err) { fprintf(stderr, "DNSServiceProcessResult returned %d\n", err); stopNow = 1; }
+ if (err) { printtimestamp_F(stderr); fprintf(stderr, "DNSServiceProcessResult returned %d\n", err); stopNow = 1; }
}
else if (result == 0)
myTimerCallBack();
@@ -1306,18 +1373,6 @@ static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordR
default: printf("Error %d\n", errorCode); break;
}
if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
- // DNSServiceRemoveRecord(service, rec, 0); to test record removal
-
-#if 0 // To test updating of individual records registered via DNSServiceRegisterRecord
- if (!errorCode)
- {
- int x = 0x11111111;
- printf("Updating\n");
- DNSServiceUpdateRecord(service, rec, 0, sizeof(x), &x, 0);
- }
-#endif
-
- if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
}
static void getip(const char *const name, struct sockaddr_storage *result)
@@ -1403,6 +1458,215 @@ static char *gettype(char *buffer, char *typ)
return(typ);
}
+// Do some basic tests to verify API handles > 63 byte strings gracefully with
+// a returned error code.
+
+#define STRING_64_BYTES "_123456789012345678901234567890123456789012345678901234567890123"
+
+static int API_string_limit_test()
+{
+ const char * regtype;
+ DNSServiceRef sdRef = NULL;
+ const char * longHost = STRING_64_BYTES ".local";
+ const char * longDomain = "hostname." STRING_64_BYTES;
+
+ printf("Testing for error returns when various strings are > 63 bytes.\n");
+
+ printf("DNSServiceGetAddrInfo(), hostname = %s\n", longHost);
+ if (DNSServiceGetAddrInfo(&sdRef, 0, 0, 0, longHost, addrinfo_reply, 0) == 0)
+ {
+ printf("DNSServiceGetAddrInfo(): expected error return\n");
+ return 1;
+ };
+
+ printf("DNSServiceGetAddrInfo(), hostname = %s\n", longDomain);
+ if (DNSServiceGetAddrInfo(&sdRef, 0, 0, 0, longDomain, addrinfo_reply, 0) == 0)
+ {
+ printf("DNSServiceGetAddrInfo(): expected error return\n");
+ return 1;
+ };
+
+ printf("DNSServiceResolve(), name = %s\n", STRING_64_BYTES);
+ if (DNSServiceResolve(&sdRef, 0, 0, STRING_64_BYTES, "_test._tcp", "local", resolve_reply, NULL) == 0)
+ {
+ printf("DNSServiceResolve(): expected error return\n");
+ return 1;
+ };
+
+ regtype = STRING_64_BYTES "._tcp";
+ printf("DNSServiceResolve(), regtype = %s\n", regtype);
+ if (DNSServiceResolve(&sdRef, 0, 0, "instanceName", regtype, "local", resolve_reply, NULL) == 0)
+ {
+ printf("DNSServiceResolve(): expected error return\n");
+ return 1;
+ };
+
+ printf("DNSServiceResolve(), domain = %s\n", STRING_64_BYTES);
+ if (DNSServiceResolve(&sdRef, 0, 0, "instanceName", "_test._tcp", STRING_64_BYTES, resolve_reply, NULL) == 0)
+ {
+ printf("DNSServiceResolve(): expected error return\n");
+ return 1;
+ };
+
+ printf("Testing for error returns when various strings are > 63 bytes: PASSED\n");
+ return 0;
+}
+
+// local prototypes for routines that don't have prototypes in dns_sd.h
+#if APPLE_OSX_mDNSResponder
+DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain);
+DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid);
+#endif
+
+static int API_NULL_input_test()
+{
+ printf("Running basic API input range tests with all parameters set to 0:\n");
+
+ // Test that API's handle NULL pointers by returning an error when appropriate.
+ printf("DNSServiceRefSockFD()\n");
+ if (DNSServiceRefSockFD(0) != -1)
+ {
+ printf("DNSServiceRefSockFD(): expected dnssd_InvalidSocket return\n");
+ return 1;
+ };
+
+ printf("DNSServiceProcessResult()\n");
+ if (DNSServiceProcessResult(0) == 0)
+ {
+ printf("DNSServiceProcessResult(): expected error return\n");
+ return 1;
+ };
+
+ // no return value, just verify it doesn't crash
+ printf("DNSServiceRefDeallocate()\n");
+ DNSServiceRefDeallocate(0);
+
+ printf("DNSServiceGetProperty()\n");
+ if (DNSServiceGetProperty(0, 0, 0) == 0)
+ {
+ printf("DNSServiceGetProperty(): expected error return\n");
+ return 1;
+ };
+
+ printf("DNSServiceResolve()\n");
+ if (DNSServiceResolve(0, 0, 0, 0, 0, 0, 0, 0) == 0)
+ {
+ printf("DNSServiceResolve(): expected error return\n");
+ return 1;
+ };
+
+ printf("DNSServiceQueryRecord()\n");
+ if (DNSServiceQueryRecord(0, 0, 0, 0, 0, 0, 0, 0) == 0)
+ {
+ printf("DNSServiceQueryRecord(): expected error return\n");
+ return 1;
+ };
+
+ printf("DNSServiceGetAddrInfo()\n");
+ if (DNSServiceGetAddrInfo(0, 0, 0, 0, 0, 0, 0) == 0)
+ {
+ printf("DNSServiceGetAddrInfo(): expected error return\n");
+ return 1;
+ };
+
+ printf("DNSServiceBrowse()\n");
+ if (DNSServiceBrowse(0, 0, 0, 0, 0, 0, 0) == 0)
+ {
+ printf("DNSServiceBrowse(): expected error return\n");
+ return 1;
+ };
+
+#if APPLE_OSX_mDNSResponder
+ printf("DNSServiceSetDefaultDomainForUser()\n");
+ if (DNSServiceSetDefaultDomainForUser(0, 0) == 0)
+ {
+ printf("DNSServiceSetDefaultDomainForUser(): expected error return\n");
+ return 1;
+ };
+#endif
+
+ printf("DNSServiceRegister()\n");
+ if (DNSServiceRegister(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == 0)
+ {
+ printf("DNSServiceRegister(): expected error return\n");
+ return 1;
+ };
+
+ printf("DNSServiceEnumerateDomains()\n");
+ if (DNSServiceEnumerateDomains(0, 0, 0, 0, 0) == 0)
+ {
+ printf("DNSServiceEnumerateDomains(): expected error return\n");
+ return 1;
+ };
+
+ printf("DNSServiceCreateConnection()\n");
+ if (DNSServiceCreateConnection(0) == 0)
+ {
+ printf("DNSServiceCreateConnection(): expected error return\n");
+ return 1;
+ };
+
+#if APPLE_OSX_mDNSResponder
+ printf("DNSServiceCreateDelegateConnection()\n");
+ if (DNSServiceCreateDelegateConnection(0, 0, 0) == 0)
+ {
+ printf("DNSServiceCreateDelegateConnection(): expected error return\n");
+ return 1;
+ };
+#endif
+
+ printf("DNSServiceRegisterRecord()\n");
+ if (DNSServiceRegisterRecord(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == 0)
+ {
+ printf("DNSServiceRegisterRecord(): expected error return\n");
+ return 1;
+ };
+
+ printf("DNSServiceAddRecord()\n");
+ if (DNSServiceAddRecord(0, 0, 0, 0, 0, 0, 0) == 0)
+ {
+ printf("DNSServiceAddRecord(): expected error return\n");
+ return 1;
+ };
+
+ printf("DNSServiceUpdateRecord()\n");
+ if (DNSServiceUpdateRecord(0, 0, 0, 0, 0, 0) == 0)
+ {
+ printf("DNSServiceUpdateRecord(): expected error return\n");
+ return 1;
+ };
+
+ printf("DNSServiceRemoveRecord()\n");
+ if (DNSServiceRemoveRecord(0, 0, 0) == 0)
+ {
+ printf("DNSServiceRemoveRecord(): expected error return\n");
+ return 1;
+ };
+
+ printf("DNSServiceReconfirmRecord()\n");
+ if (DNSServiceReconfirmRecord(0, 0, 0, 0, 0, 0, 0) == 0)
+ {
+ printf("DNSServiceReconfirmRecord(): expected error return\n");
+ return 1;
+ };
+
+
+ printf("Basic API input range tests with all parameters set to 0: PASSED\n");
+ return 0;
+}
+
+static int API_input_range_test()
+{
+
+ if (API_string_limit_test())
+ return 1;
+
+ if (API_NULL_input_test())
+ return 1;
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
DNSServiceErrorType err;
@@ -1432,102 +1696,154 @@ int main(int argc, char **argv)
//TXTRecordSetValue(&txtRecord, "aaa", 1, "b");
//printf("%d\n", TXTRecordContainsKey(TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), "Aaa"));
- if (argc > 1 && !strcmp(argv[1], "-lo"))
- {
- argc--;
- argv++;
- opinterface = kDNSServiceInterfaceIndexLocalOnly;
- printf("Using LocalOnly\n");
- }
-
- if (argc > 1 && (!strcmp(argv[1], "-p2p") || !strcmp(argv[1], "-P2P")))
- {
- argc--;
- argv++;
- opinterface = kDNSServiceInterfaceIndexP2P;
- }
-
- if (argc > 1 && !strcasecmp(argv[1], "-includep2p"))
- {
- argc--;
- argv++;
- flags |= kDNSServiceFlagsIncludeP2P;
- printf("Setting kDNSServiceFlagsIncludeP2P\n");
- }
-
- if (argc > 1 && !strcasecmp(argv[1], "-includeAWDL"))
- {
- argc--;
- argv++;
- flags |= kDNSServiceFlagsIncludeAWDL;
- printf("Setting kDNSServiceFlagsIncludeAWDL\n");
- }
-
- if (argc > 1 && !strcasecmp(argv[1], "-tc"))
+ while (argc > 1)
{
- argc--;
- argv++;
- flags |= kDNSServiceFlagsBackgroundTrafficClass;
- printf("Setting kDNSServiceFlagsBackgroundTrafficClass\n");
- }
-
- if (argc > 1 && !strcasecmp(argv[1], "-t1"))
- {
- argc--;
- argv++;
- flags |= kDNSServiceFlagsThresholdOne;
- printf("Setting kDNSServiceFlagsThresholdOne\n");
- }
-
- if (argc > 1 && !strcasecmp(argv[1], "-tFinder"))
- {
- argc--;
- argv++;
- flags |= kDNSServiceFlagsThresholdFinder;
- printf("Setting kDNSServiceFlagsThresholdFinder\n");
- }
-
- if (argc > 1 && !strcasecmp(argv[1], "-wo"))
- {
- argc--;
- argv++;
- flags |= kDNSServiceFlagsWakeOnlyService;
- printf("Setting kDNSServiceFlagsWakeOnlyService\n");
- }
-
- if (argc > 1 && !strcasecmp(argv[1], "-unicastResponse"))
- {
- argc--;
- argv++;
- flags |= kDNSServiceFlagsUnicastResponse;
- printf("Setting kDNSServiceFlagsUnicastResponse\n");
- }
- if (argc > 1 && !strcasecmp(argv[1], "-timeout"))
- {
- argc--;
- argv++;
- flags |= kDNSServiceFlagsTimeout;
- printf("Setting kDNSServiceFlagsTimeout\n");
- }
- if (argc > 1 && !strcasecmp(argv[1], "-optional"))
- {
- argc--;
- argv++;
- optional = 1;
- printf("Setting DNSSEC optional flag\n");
- }
+ int entryCount;
+
+ // record current argc to see if we process an argument in this pass
+ entryCount = argc;
+
+ if (argc > 1 && !strcmp(argv[1], "-test"))
+ {
+ argc--;
+ argv++;
+ return API_input_range_test();
+ }
+
+ if (argc > 1 && !strcmp(argv[1], "-lo"))
+ {
+ argc--;
+ argv++;
+ opinterface = kDNSServiceInterfaceIndexLocalOnly;
+ printf("Using LocalOnly\n");
+ }
+
+ if (argc > 1 && (!strcasecmp(argv[1], "-p2p")))
+ {
+ argc--;
+ argv++;
+ opinterface = kDNSServiceInterfaceIndexP2P;
+ }
+
+ if (argc > 1 && (!strcasecmp(argv[1], "-ble")))
+ {
+ argc--;
+ argv++;
+ opinterface = kDNSServiceInterfaceIndexBLE;
+ }
+
+ if (argc > 1 && !strcasecmp(argv[1], "-includep2p"))
+ {
+ argc--;
+ argv++;
+ flags |= kDNSServiceFlagsIncludeP2P;
+ printf("Setting kDNSServiceFlagsIncludeP2P\n");
+ }
+
+ if (argc > 1 && !strcasecmp(argv[1], "-includeAWDL"))
+ {
+ argc--;
+ argv++;
+ flags |= kDNSServiceFlagsIncludeAWDL;
+ printf("Setting kDNSServiceFlagsIncludeAWDL\n");
+ }
+
+ if (argc > 1 && !strcasecmp(argv[1], "-intermediates"))
+ {
+ argc--;
+ argv++;
+ flags |= kDNSServiceFlagsReturnIntermediates;
+ printf("Setting kDNSServiceFlagsReturnIntermediates\n");
+ }
- if (argc > 2 && !strcmp(argv[1], "-i"))
- {
- opinterface = if_nametoindex(argv[2]);
- if (!opinterface) opinterface = atoi(argv[2]);
- if (!opinterface) { fprintf(stderr, "Unknown interface %s\n", argv[2]); goto Fail; }
- argc -= 2;
- argv += 2;
+ if (argc > 1 && !strcasecmp(argv[1], "-tc"))
+ {
+ argc--;
+ argv++;
+ flags |= kDNSServiceFlagsBackgroundTrafficClass;
+ printf("Setting kDNSServiceFlagsBackgroundTrafficClass\n");
+ }
+
+ if (argc > 1 && !strcasecmp(argv[1], "-t1"))
+ {
+ argc--;
+ argv++;
+ flags |= kDNSServiceFlagsThresholdOne;
+ printf("Setting kDNSServiceFlagsThresholdOne\n");
+ }
+
+ if (argc > 1 && !strcasecmp(argv[1], "-tFinder"))
+ {
+ argc--;
+ argv++;
+ flags |= kDNSServiceFlagsThresholdFinder;
+ printf("Setting kDNSServiceFlagsThresholdFinder\n");
+ }
+
+ if (argc > 1 && !strcasecmp(argv[1], "-wo"))
+ {
+ argc--;
+ argv++;
+ flags |= kDNSServiceFlagsWakeOnlyService;
+ printf("Setting kDNSServiceFlagsWakeOnlyService\n");
+ }
+
+ if (argc > 1 && !strcasecmp(argv[1], "-ku"))
+ {
+ argc--;
+ argv++;
+ flags |= kDNSServiceFlagsKnownUnique;
+ printf("Setting kDNSServiceFlagsKnownUnique\n");
+ }
+
+ if (argc > 1 && !strcasecmp(argv[1], "-unicastResponse"))
+ {
+ argc--;
+ argv++;
+ flags |= kDNSServiceFlagsUnicastResponse;
+ printf("Setting kDNSServiceFlagsUnicastResponse\n");
+ }
+
+ if (argc > 1 && !strcasecmp(argv[1], "-timeout"))
+ {
+ argc--;
+ argv++;
+ flags |= kDNSServiceFlagsTimeout;
+ printf("Setting kDNSServiceFlagsTimeout\n");
+ }
+
+ if (argc > 1 && !strcasecmp(argv[1], "-autoTrigger"))
+ {
+ argc--;
+ argv++;
+ flags |= kDNSServiceFlagsAutoTrigger;
+ printf("Setting kDNSServiceFlagsAutoTrigger\n");
+ }
+
+ if (argc > 1 && !strcasecmp(argv[1], "-optional"))
+ {
+ argc--;
+ argv++;
+ optional = 1;
+ printf("Setting DNSSEC optional flag\n");
+ }
+
+ if (argc > 2 && !strcmp(argv[1], "-i"))
+ {
+ opinterface = if_nametoindex(argv[2]);
+ if (!opinterface) opinterface = atoi(argv[2]);
+ if (!opinterface) { fprintf(stderr, "Unknown interface %s\n", argv[2]); goto Fail; }
+ argc -= 2;
+ argv += 2;
+ }
+
+ // Exit loop if if we didn't match one of the multi character options.
+ if (argc == entryCount)
+ break;
}
if (argc < 2) goto Fail; // Minimum command line is the command name and one argument
- operation = getfirstoption(argc, argv, "EFBZLlRPQqCAUNTMISVHhD"
+ operation = getfirstoption(argc, argv, "ABCDEFHILMNPQRSTUVZhlq"
"X"
"Gg"
, &opi);
diff --git a/mDNSResponder/Clients/dnsctl.c b/mDNSResponder/Clients/dnsctl.c
index f10f2259..e01c8fec 100644
--- a/mDNSResponder/Clients/dnsctl.c
+++ b/mDNSResponder/Clients/dnsctl.c
@@ -17,16 +17,20 @@
#include <sys/time.h>
#include <net/if.h> // if_nametoindex()
-#include <dispatch/dispatch.h>
#include "dns_services.h"
+#include <xpc/xpc.h>
+#include "dns_xpc.h"
//*************************************************************************************************************
// Globals:
//*************************************************************************************************************
static const char kFilePathSep = '/';
+
static DNSXConnRef ClientRef = NULL;
+static xpc_connection_t dnsctl_conn = NULL;
+
//*************************************************************************************************************
// Utility Funcs:
//*************************************************************************************************************
@@ -56,12 +60,31 @@ static void print_usage(const char *arg0)
fprintf(stderr, "%s USAGE: \n", arg0);
fprintf(stderr, "%s -DP Enable DNS Proxy with Default Parameters \n", arg0);
fprintf(stderr, "%s -DP [-o <output interface>] [-i <input interface(s)>] Enable DNS Proxy \n", arg0);
+ fprintf(stderr, "%s -L [1/2/3/4] Change mDNSResponder Logging Level \n", arg0);
+ fprintf(stderr, "%s -I Print mDNSResponder STATE INFO \n", arg0);
+}
+
+
+static bool DebugEnabled()
+{
+ return true; // keep this true to debug the XPC msgs
+}
+
+static void DebugLog(const char *prefix, xpc_object_t o)
+{
+ if (!DebugEnabled())
+ return;
+
+ char *desc = xpc_copy_description(o);
+ printf("%s: %s \n", prefix, desc);
+ free(desc);
}
//*************************************************************************************************************
// CallBack Funcs:
//*************************************************************************************************************
+
// DNSXEnableProxy Callback from the Daemon
static void dnsproxy_reply(DNSXConnRef connRef, DNSXErrorType errCode)
{
@@ -75,6 +98,8 @@ static void dnsproxy_reply(DNSXConnRef connRef, DNSXErrorType errCode)
DNSXRefDeAlloc(ClientRef); break;
case kDNSX_BadParam : printf(" BAD PARAMETER \n");
DNSXRefDeAlloc(ClientRef); break;
+ case kDNSX_Busy : printf(" BUSY \n");
+ DNSXRefDeAlloc(ClientRef); break;
case kDNSX_UnknownErr :
default : printf(" UNKNOWN ERR \n");
DNSXRefDeAlloc(ClientRef); break;
@@ -84,15 +109,56 @@ static void dnsproxy_reply(DNSXConnRef connRef, DNSXErrorType errCode)
}
//*************************************************************************************************************
+// XPC Funcs:
+//*************************************************************************************************************
-int main(int argc, char **argv)
+static void Init_Connection(const char *servname)
+{
+ dnsctl_conn = xpc_connection_create_mach_service(servname, dispatch_get_main_queue(), XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
+
+ xpc_connection_set_event_handler(dnsctl_conn, ^(xpc_object_t event)
+ {
+ printf("InitConnection: [%s] \n", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
+ });
+
+ xpc_connection_resume(dnsctl_conn);
+}
+
+static void SendDictToServer(xpc_object_t msg)
{
- DNSXErrorType err;
- // Default i/p intf is lo0 and o/p intf is primary interface
- IfIndex Ipintfs[MaxInputIf] = {1, 0, 0, 0, 0};
- IfIndex Opintf = kDNSIfindexAny;
+ DebugLog("SendDictToServer Sending msg to Daemon", msg);
+ xpc_connection_send_message_with_reply(dnsctl_conn, msg, dispatch_get_main_queue(), ^(xpc_object_t recv_msg)
+ {
+ xpc_type_t type = xpc_get_type(recv_msg);
+
+ if (type == XPC_TYPE_DICTIONARY)
+ {
+ DebugLog("SendDictToServer Received reply msg from Daemon", recv_msg);
+ /*
+ // If we ever want to do something based on the reply of the daemon
+ switch (daemon_status)
+ {
+ default:
+ break;
+ }
+ */
+ }
+ else
+ {
+ printf("SendDictToServer Received unexpected reply from daemon [%s]",
+ xpc_dictionary_get_string(recv_msg, XPC_ERROR_KEY_DESCRIPTION));
+ DebugLog("SendDictToServer Unexpected Reply contents", recv_msg);
+ }
+ exit(1);
+ });
+}
+
+//*************************************************************************************************************
+
+int main(int argc, char **argv)
+{
// Extract program name from argv[0], which by convention contains the path to this executable
const char *a0 = strrchr(argv[0], kFilePathSep) + 1;
if (a0 == (const char *)1)
@@ -113,15 +179,20 @@ int main(int argc, char **argv)
if (argc < 2)
goto Usage;
- if ( !strcmp(argv[1], "-DP") || !strcmp(argv[1], "-dp") )
+ printtimestamp();
+ if (!strcasecmp(argv[1], "-DP"))
{
+ DNSXErrorType err;
+ // Default i/p intf is lo0 and o/p intf is primary interface
+ IfIndex Ipintfs[MaxInputIf] = {1, 0, 0, 0, 0};
+ IfIndex Opintf = kDNSIfindexAny;
+
if (argc == 2)
{
- printtimestamp();
- printf("Enabling DNSProxy on mDNSResponder with Default Parameters\n");
dispatch_queue_t my_Q = dispatch_queue_create("com.apple.dnsctl.callback_queue", NULL);
err = DNSXEnableProxy(&ClientRef, kDNSProxyEnable, Ipintfs, Opintf, my_Q, dnsproxy_reply);
- if (err) fprintf(stderr, "DNSXEnableProxy returned %d\n", err);
+ if (err)
+ fprintf(stderr, "DNSXEnableProxy returned %d\n", err);
}
else if (argc > 2)
{
@@ -159,13 +230,96 @@ int main(int argc, char **argv)
argv++;
}
}
- printtimestamp();
printf("Enabling DNSProxy on mDNSResponder \n");
dispatch_queue_t my_Q = dispatch_queue_create("com.apple.dnsctl.callback_queue", NULL);
err = DNSXEnableProxy(&ClientRef, kDNSProxyEnable, Ipintfs, Opintf, my_Q, dnsproxy_reply);
- if (err) fprintf(stderr, "DNSXEnableProxy returned %d\n", err);
+ if (err)
+ fprintf(stderr, "DNSXEnableProxy returned %d\n", err);
+ }
+ }
+ else if (!strcasecmp(argv[1], "-l"))
+ {
+ printf("Changing loglevel of mDNSResponder \n");
+ Init_Connection(kDNSCTLService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+
+ if (argc == 2)
+ {
+ xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level1);
+
+ SendDictToServer(dict);
+ xpc_release(dict);
+ dict = NULL;
+ }
+ else if (argc > 2)
+ {
+ argc--;
+ argv++;
+ switch (atoi(argv[1]))
+ {
+ case log_level1:
+ xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level1);
+ break;
+
+ case log_level2:
+ xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level2);
+ break;
+
+ case log_level3:
+ xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level3);
+ break;
+
+ case log_level4:
+ xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level4);
+ break;
+
+ default:
+ xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level1);
+ break;
+ }
+ SendDictToServer(dict);
+ xpc_release(dict);
+ dict = NULL;
}
}
+ else if(!strcasecmp(argv[1], "-i"))
+ {
+ printf("Get STATE INFO of mDNSResponder \n");
+ Init_Connection(kDNSCTLService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kDNSStateInfo, full_state);
+ SendDictToServer(dict);
+ xpc_release(dict);
+ dict = NULL;
+ }
+ else if(!strcasecmp(argv[1], "-th"))
+ {
+ printf("Sending Test message to mDNSResponder to forward to mDNSResponderHelper\n");
+ Init_Connection(kDNSCTLService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kmDNSResponderTests, test_helper_ipc);
+ SendDictToServer(dict);
+ xpc_release(dict);
+ dict = NULL;
+ }
+ else if(!strcasecmp(argv[1], "-tl"))
+ {
+ printf("Testing mDNSResponder Logging\n");
+ Init_Connection(kDNSCTLService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kmDNSResponderTests, test_mDNS_log);
+ SendDictToServer(dict);
+ xpc_release(dict);
+ dict = NULL;
+ }
else
{
goto Usage;
@@ -178,3 +332,52 @@ Usage:
return 0;
}
+/*
+
+#include <getopt.h>
+
+static int operation;
+
+static int getfirstoption(int argc, char **argv, const char *optstr, int *pOptInd)
+{
+ // Return the recognized option in optstr and the option index of the next arg.
+ int o = getopt(argc, (char *const *)argv, optstr);
+ *pOptInd = optind;
+ return o;
+}
+
+int opindex;
+operation = getfirstoption(argc, argv, "lLDdPp", &opindex);
+if (operation == -1)
+ goto Usage;
+
+
+
+switch (operation)
+{
+ case 'L':
+ case 'l':
+ {
+ printtimestamp();
+ printf("Change Verbosity Level of mDNSResponder\n");
+
+ Init_Connection(kDNSCTLService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ if (dict == NULL)
+ printf("could not create the Msg Dict To Send! \n");
+ xpc_dictionary_set_uint64(dict, kDNSLogLevel, log_level2);
+
+ SendDictToServer(dict);
+
+ xpc_release(dict);
+ dict = NULL;
+ break;
+ }
+ // exit(1);
+
+}
+
+*/
+
diff --git a/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/52D711AF-4055-4867-A494-7E31552BB9E1.png b/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/52D711AF-4055-4867-A494-7E31552BB9E1.png
new file mode 100644
index 00000000..38eef124
--- /dev/null
+++ b/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/52D711AF-4055-4867-A494-7E31552BB9E1.png
Binary files differ
diff --git a/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/Screen Shot 2015-09-16 at 3.36.23 PM.png b/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/Screen Shot 2015-09-16 at 3.36.23 PM.png
new file mode 100644
index 00000000..40426447
--- /dev/null
+++ b/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/Screen Shot 2015-09-16 at 3.36.23 PM.png
Binary files differ
diff --git a/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/Screen Shot 2015-09-16 at 3.46.14 PM.png b/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/Screen Shot 2015-09-16 at 3.46.14 PM.png
new file mode 100644
index 00000000..31cd8070
--- /dev/null
+++ b/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/Screen Shot 2015-09-16 at 3.46.14 PM.png
Binary files differ
diff --git a/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/TXT.rtf b/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/TXT.rtf
new file mode 100644
index 00000000..ddcccfdc
--- /dev/null
+++ b/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/TXT.rtf
@@ -0,0 +1,75 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf120
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 Menlo-Regular;}
+{\colortbl;\red255\green255\blue255;}
+\margl1440\margr1440\vieww25580\viewh24980\viewkind0
+\deftab720
+\pard\pardeftab720\partightenfactor0
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Three steps to attach, and debug in Xcode, a /usr/sbin/mDNSResponder that is already running. One caveat, mDNSResponder has to be built and deployed (using step 1 and 2 below) before it can be attached to Xcode.\
+\
+1.) First you have to build the Xcode project with symbols included and optimizations off.\
+\
+ a.) From Terminal shell, open mDNSResponder Xcode project from top of tree: \'a0\
+\
+ $ open mDNSMacOSX/mDNSResponder.xcodeproj/\
+\
+\pard\pardeftab720\partightenfactor0
+\cf0 You can also just double click on the project from Finder.\
+\
+ b.) Add your diffs to mDNSResponder project.
+\f1\fs22 \
+\pard\pardeftab720\partightenfactor0
+
+\f0\fs24 \cf0 \
+ c.) Set Strip Linked Product to No and compiler Optimization Level to None. Below shows changed settings.\
+\
+\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
+\cf0 \kerning1\expnd0\expndtw0 {{\NeXTGraphic Screen Shot 2015-09-16 at 3.36.23 PM.png \width7680 \height460
+}¬}\
+\
+ {{\NeXTGraphic Screen Shot 2015-09-16 at 3.46.14 PM.png \width8700 \height460
+}¬}\expnd0\expndtw0\kerning0
+\
+\pard\pardeftab720\partightenfactor0
+\cf0 \
+ d. ) Build mDNSResponder by setting the target to mDNSResponder.\
+\
+ {{\NeXTGraphic unknown.png \width4300 \height800 \noorient
+}¬}\
+\
+ Then execute\'a0Command-B to build.\
+\
+\
+2.) Next, deploy newly-created Xcode version.\
+\
+ a.) Go to Terminal shell and type the following: sudo mv \
+\
+ b.) Then drag mDNSResponder from Products list on left side panel (shown below using red arrow) to Terminal shell.\
+\
+\pard\pardeftab720\partightenfactor0
+\cf0 {{\NeXTGraphic 52D711AF-4055-4867-A494-7E31552BB9E1.png \width4420 \height9700
+}¬}\pard\pardeftab720\partightenfactor0
+\cf0 \
+\
+ c.) Execute command.\
+\
+ For example:\
+ \
+ $ sudo mv\'a0/Volumes/iMac\\ HD/Users/llaier/Library/Developer/Xcode/DerivedData/mDNSResponder-fktewmdupxbxrrdlsdljyhmihboz/Build/Products/mDNSResponder\'a0/usr/sbin/mDNSResponder\
+\
+ d.) Restart mDNSResponder by executing the following:\
+\
+ $ sudo killall mDNSResponder\
+\pard\pardeftab720\partightenfactor0
+
+\f1\fs22 \cf0 \
+\
+\pard\pardeftab720\partightenfactor0
+
+\f0\fs24 \cf0 3.) In Xcode, select Debug > Attach to Process > mDNSResponder.
+\f1\fs22 \
+
+\f0\fs24 \
+ Now set a breakpoint and try to trigger it.\
+} \ No newline at end of file
diff --git a/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/unknown.png b/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/unknown.png
new file mode 100644
index 00000000..7e2364e0
--- /dev/null
+++ b/mDNSResponder/Documents/Attach mDNSResponder to Xcode.rtfd/unknown.png
Binary files differ
diff --git a/mDNSResponder/Documents/Start mDNSResponder in Xcode.rtfd/A944EB40-AEFD-4CA1-BF10-E8F52835CA8C.png b/mDNSResponder/Documents/Start mDNSResponder in Xcode.rtfd/A944EB40-AEFD-4CA1-BF10-E8F52835CA8C.png
new file mode 100644
index 00000000..a5410efe
--- /dev/null
+++ b/mDNSResponder/Documents/Start mDNSResponder in Xcode.rtfd/A944EB40-AEFD-4CA1-BF10-E8F52835CA8C.png
Binary files differ
diff --git a/mDNSResponder/Documents/Start mDNSResponder in Xcode.rtfd/Screen Shot 2015-09-16 at 4.22.37 PM.png b/mDNSResponder/Documents/Start mDNSResponder in Xcode.rtfd/Screen Shot 2015-09-16 at 4.22.37 PM.png
new file mode 100644
index 00000000..1341df46
--- /dev/null
+++ b/mDNSResponder/Documents/Start mDNSResponder in Xcode.rtfd/Screen Shot 2015-09-16 at 4.22.37 PM.png
Binary files differ
diff --git a/mDNSResponder/Documents/Start mDNSResponder in Xcode.rtfd/TXT.rtf b/mDNSResponder/Documents/Start mDNSResponder in Xcode.rtfd/TXT.rtf
new file mode 100644
index 00000000..13e14d4a
--- /dev/null
+++ b/mDNSResponder/Documents/Start mDNSResponder in Xcode.rtfd/TXT.rtf
@@ -0,0 +1,57 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf460
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\margl1440\margr1440\vieww51000\viewh25780\viewkind0
+\deftab720
+\pard\pardeftab720\partightenfactor0
+
+\f0\fs24 \cf0 \expnd0\expndtw0\kerning0
+Instructions on how to run a secondary mDNSResponder in the Xcode debugger. (Two known issues, the secondary mDNSResponder will not send unicast mDNS packets and it does not support BTMM.)\
+\
+1.) From Terminal shell, open mDNSResponder Xcode project. \'a0\
+\
+ $ open mDNSMacOSX/mDNSResponder.xcodeproj/\
+\
+You can also just double click on the project from Finder.\
+\
+2.) Configure Xcode Project Scheme by adding the following three arguments, -d -NoSandbox -UseDebugSocket.\
+\
+\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardeftab720\pardirnatural\partightenfactor0
+\cf0 \kerning1\expnd0\expndtw0 {{\NeXTGraphic A944EB40-AEFD-4CA1-BF10-E8F52835CA8C.png \width18360 \height4420
+}¬}\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardeftab720\pardirnatural\partightenfactor0
+\cf0 \expnd0\expndtw0\kerning0
+\
+\pard\pardeftab720\partightenfactor0
+\cf0 \
+3.) Build and run mDNSResponder by setting the target to mDNSResponder.\
+\
+\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardeftab720\pardirnatural\partightenfactor0
+\cf0 \kerning1\expnd0\expndtw0 {{\NeXTGraphic Screen Shot 2015-09-16 at 4.22.37 PM.png \width5980 \height660
+}¬}\expnd0\expndtw0\kerning0
+\
+\pard\pardeftab720\partightenfactor0
+\cf0 \
+ Then execute\'a0Command-R to build and run your code with the active scheme.\
+\
+\pard\pardeftab720\pardirnatural\partightenfactor0
+\cf0 \kerning1\expnd0\expndtw0 \CocoaLigature0 4.) Before using dns-sd with Xcode-version of mDNSResponder, make sure to export the socket UDS path by executing one of the following commands:\
+\
+ From a Borne, bash or zsh, execute this command:\
+\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\pardirnatural\partightenfactor0
+\cf0 export DNSSD_UDS_PATH=/var/tmp/mDNSResponder\
+\
+\pard\tx729\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\pardirnatural\partightenfactor0
+\cf0 From csh or tcsh, execute this command:\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\pardirnatural\partightenfactor0
+\cf0 \
+ \expnd0\expndtw0\kerning0
+\CocoaLigature1 setenv DNSSD_UDS_PATH /var/tmp/mDNSResponder\
+\
+ There may be other variants to setting the environment variable as well for other shells.\kerning1\expnd0\expndtw0 \CocoaLigature0 \
+\
+ Now running dns-sd will interoperate with the secondary Xcode-version of mDNSResponder as long as you run dns-sd from this terminal shell.\
+\
+5.) \expnd0\expndtw0\kerning0
+\CocoaLigature1 Now set a breakpoint in Xcode and try to trigger it using dns-sd.\
+} \ No newline at end of file
diff --git a/mDNSResponder/Makefile b/mDNSResponder/Makefile
index ba79b293..ab610a7c 100644
--- a/mDNSResponder/Makefile
+++ b/mDNSResponder/Makefile
@@ -16,7 +16,7 @@
include $(MAKEFILEPATH)/pb_makefiles/platform.make
-MVERS = "mDNSResponder-625.41.2"
+MVERS = "mDNSResponder-765.1.2"
DDNSWRITECONFIG = "$(DSTROOT)/Library/Application Support/Bonjour/ddnswriteconfig"
VER =
@@ -41,6 +41,7 @@ installsrc:
installhdrs::
cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild installhdrs OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) SDKROOT=$(SDKROOT) -target SystemLibraries $(VER)
+ cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild installhdrs OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) SDKROOT=$(SDKROOT) -target dns_services $(VER)
java:
cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) SDKROOT=$(SDKROOT) -target libjdns_sd.jnilib $(VER)
diff --git a/mDNSResponder/mDNSCore/DNSCommon.c b/mDNSResponder/mDNSCore/DNSCommon.c
index d364ee02..a2b703f7 100644
--- a/mDNSResponder/mDNSCore/DNSCommon.c
+++ b/mDNSResponder/mDNSCore/DNSCommon.c
@@ -43,6 +43,7 @@ mDNSexport const mDNSInterfaceID mDNSInterface_LocalOnly = (mDNSInterfaceID)-2;
mDNSexport const mDNSInterfaceID mDNSInterface_Unicast = (mDNSInterfaceID)-3;
mDNSexport const mDNSInterfaceID mDNSInterface_P2P = (mDNSInterfaceID)-4;
mDNSexport const mDNSInterfaceID uDNSInterfaceMark = (mDNSInterfaceID)-5;
+mDNSexport const mDNSInterfaceID mDNSInterface_BLE = (mDNSInterfaceID)-6;
// Note: Microsoft's proposed "Link Local Multicast Name Resolution Protocol" (LLMNR) is essentially a limited version of
// Multicast DNS, using the same packet formats, naming syntax, and record types as Multicast DNS, but on a different UDP
@@ -107,6 +108,8 @@ mDNSexport const mDNSOpaque16 DNSSecQFlags = { { kDNSFlag0_QR_Query | kDNS
mDNSexport const mDNSOpaque16 ResponseFlags = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery | kDNSFlag0_AA, 0 } };
mDNSexport const mDNSOpaque16 UpdateReqFlags = { { kDNSFlag0_QR_Query | kDNSFlag0_OP_Update, 0 } };
mDNSexport const mDNSOpaque16 UpdateRespFlags = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_Update, 0 } };
+mDNSexport const mDNSOpaque16 SubscribeFlags = { { kDNSFlag0_QR_Query | kDNSFlag0_OP_Subscribe, 0 } };
+mDNSexport const mDNSOpaque16 UnSubscribeFlags= { { kDNSFlag0_QR_Query | kDNSFlag0_OP_UnSubscribe, 0 } };
mDNSexport const mDNSOpaque64 zeroOpaque64 = { { 0 } };
@@ -541,7 +544,7 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RD
}
break;
- default: mDNS_snprintf(buffer+length, RemSpc, "RDLen %d: %s", rr->rdlength, rd->data);
+ default: mDNS_snprintf(buffer+length, RemSpc, "RDLen %d: %.*s", rr->rdlength, rr->rdlength, rd->data);
// Really should scan buffer to check if text is valid UTF-8 and only replace with dots if not
for (ptr = buffer; *ptr; ptr++) if (*ptr < ' ') *ptr = '.';
break;
@@ -803,6 +806,7 @@ mDNSexport mDNSu8 *AppendDNSNameString(domainname *const name, const char *cstri
mDNSu8 c = (mDNSu8)*cstr++; // Read the character
if (c == '\\') // If escape character, check next character
{
+ if (*cstr == '\0') break; // If this is the end of the string, then break
c = (mDNSu8)*cstr++; // Assume we'll just take the next character
if (mDNSIsDigit(cstr[-1]) && mDNSIsDigit(cstr[0]) && mDNSIsDigit(cstr[1]))
{ // If three decimal digits,
@@ -815,7 +819,7 @@ mDNSexport mDNSu8 *AppendDNSNameString(domainname *const name, const char *cstri
}
*ptr++ = c; // Write the character
}
- if (*cstr) cstr++; // Skip over the trailing dot (if present)
+ if (*cstr == '.') cstr++; // Skip over the trailing dot (if present)
if (ptr - lengthbyte - 1 > MAX_DOMAIN_LABEL) // If illegal label, abort
return(mDNSNULL);
*lengthbyte = (mDNSu8)(ptr - lengthbyte - 1); // Fill in the length byte
@@ -1165,7 +1169,8 @@ mDNSexport const mDNSu8 *NSEC3HashName(const domainname *name, rdataNSEC3 *nsec3
const mDNSu8 hash[NSEC3_MAX_HASH_LEN], int *dlen)
{
AlgContext *ctx;
- int i;
+ unsigned int i;
+ unsigned int iterations;
domainname lname;
mDNSu8 *p = (mDNSu8 *)&nsec3->salt;
const mDNSu8 *digest;
@@ -1183,7 +1188,8 @@ mDNSexport const mDNSu8 *NSEC3HashName(const domainname *name, rdataNSEC3 *nsec3
// Note that it is "i <=". The first iteration is for digesting the name and salt.
// The iteration count does not include that.
- for (i = 0; i <= swap16(nsec3->iterations); i++)
+ iterations = swap16(nsec3->iterations);
+ for (i = 0; i <= iterations; i++)
{
ctx = AlgCreate(DIGEST_ALG, nsec3->alg);
if (!ctx)
@@ -1367,17 +1373,14 @@ mDNSexport void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mD
if (InterfaceID == mDNSInterface_LocalOnly && artype != AuthRecordLocalOnly)
{
LogMsg("mDNS_SetupResourceRecord: ERROR!! Mismatch LocalOnly record InterfaceID %p called with artype %d", InterfaceID, artype);
- return;
}
else if (InterfaceID == mDNSInterface_P2P && artype != AuthRecordP2P)
{
LogMsg("mDNS_SetupResourceRecord: ERROR!! Mismatch P2P record InterfaceID %p called with artype %d", InterfaceID, artype);
- return;
}
else if (!InterfaceID && (artype == AuthRecordP2P || artype == AuthRecordLocalOnly))
{
LogMsg("mDNS_SetupResourceRecord: ERROR!! Mismatch InterfaceAny record InterfaceID %p called with artype %d", InterfaceID, artype);
- return;
}
// Don't try to store a TTL bigger than we can represent in platform time units
@@ -1467,8 +1470,6 @@ mDNSexport void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID I
q->ForceMCast = mDNSfalse;
q->ReturnIntermed = mDNSfalse;
q->SuppressUnusable = mDNSfalse;
- q->DenyOnCellInterface = mDNSfalse;
- q->DenyOnExpInterface = mDNSfalse;
q->SearchListIndex = 0;
q->AppendSearchDomains = 0;
q->RetryWithSearchDomains = mDNSfalse;
@@ -1779,7 +1780,7 @@ mDNSexport mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr
// LocalOnly/P2P questions can be answered with AuthRecordAny in this function. LocalOnly/P2P records
// are handled in LocalOnlyRecordAnswersQuestion
- if ((rr->InterfaceID == mDNSInterface_LocalOnly) || (rr->InterfaceID == mDNSInterface_P2P))
+ if (LocalOnlyOrP2PInterface(rr->InterfaceID))
{
LogMsg("SameNameRecordAnswersQuestion: ERROR!! called with LocalOnly ResourceRecord %p, Question %p", rr->InterfaceID, q->InterfaceID);
return mDNSfalse;
@@ -1914,7 +1915,7 @@ mDNSexport mDNSBool AnyTypeRecordAnswersQuestion(const ResourceRecord *const rr,
{
// LocalOnly/P2P questions can be answered with AuthRecordAny in this function. LocalOnly/P2P records
// are handled in LocalOnlyRecordAnswersQuestion
- if ((rr->InterfaceID == mDNSInterface_LocalOnly) || (rr->InterfaceID == mDNSInterface_P2P))
+ if (LocalOnlyOrP2PInterface(rr->InterfaceID))
{
LogMsg("AnyTypeRecordAnswersQuestion: ERROR!! called with LocalOnly ResourceRecord %p, Question %p", rr->InterfaceID, q->InterfaceID);
return mDNSfalse;
@@ -2142,7 +2143,6 @@ mDNSexport const mDNSu8 *FindCompressionPointer(const mDNSu8 *const base, const
return(mDNSNULL);
}
-// Put a string of dot-separated labels as length-prefixed labels
// domainname is a fully-qualified name (i.e. assumed to be ending in a dot, even if it doesn't)
// msg points to the message we're building (pass mDNSNULL if we don't want to use compression pointers)
// end points to the end of the message so far
@@ -2843,7 +2843,7 @@ mDNSlocal mDNSu8 *SanityCheckBitMap(const mDNSu8 *bmap, const mDNSu8 *end, int l
// (domainnames are expanded to 255 bytes) when stored in memory.
//
// This function can also be called with "NULL" msg to parse a single resource record pointed to by ptr.
-// The caller can do this only if the names in the resource records are compressed and validity of the
+// The caller can do this only if the names in the resource records are not compressed and validity of the
// resource record has already been done before. DNSSEC currently uses it this way.
mDNSexport mDNSBool SetRData(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *end,
LargeCacheRecord *const largecr, mDNSu16 rdlength)
@@ -3348,6 +3348,12 @@ mDNSexport mDNSBool SetRData(const DNSMessage *const msg, const mDNSu8 *ptr, con
dlen = DomainNameLength(&name);
rlen = end - ptr;
rr->resrec.rdlength = dlen + rlen;
+ if (rr->resrec.rdlength > MaximumRDSize)
+ {
+ LogInfo("SetRData: Malformed TSIG/TKEY rdlength %d, rr->resrec.rdlength %d, "
+ "bmaplen %d, name %##s", rdlength, rr->resrec.rdlength, name.c);
+ goto fail;
+ }
AssignDomainName((domainname *)rdb->data, &name);
mDNSPlatformMemCopy(rdb->data + dlen, ptr, rlen);
break;
@@ -3626,7 +3632,7 @@ mDNSexport mDNSu32 GetPktLease(mDNS *m, DNSMessage *msg, const mDNSu8 *end)
mDNSlocal const mDNSu8 *DumpRecords(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end, int count, char *label)
{
int i;
- LogMsg("%2d %s", count, label);
+ LogInfo("%2d %s", count, label);
for (i = 0; i < count && ptr; i++)
{
// This puts a LargeCacheRecord on the stack instead of using the shared m->rec storage,
@@ -3634,9 +3640,11 @@ mDNSlocal const mDNSu8 *DumpRecords(mDNS *const m, const DNSMessage *const msg,
// embedded systems) putting a 9kB object on the stack isn't a big problem.
LargeCacheRecord largecr;
ptr = GetLargeResourceRecord(m, msg, ptr, end, mDNSInterface_Any, kDNSRecordTypePacketAns, &largecr);
- if (ptr) LogMsg("%2d TTL%8d %s", i, largecr.r.resrec.rroriginalttl, CRDisplayString(m, &largecr.r));
+ if (ptr)
+ LogInfo("%2d TTL%8d %s", i, largecr.r.resrec.rroriginalttl, CRDisplayString(m, &largecr.r));
}
- if (!ptr) LogMsg("DumpRecords: ERROR: Premature end of packet data");
+ if (!ptr)
+ LogInfo("DumpRecords: ERROR: Premature end of packet data");
return(ptr);
}
@@ -3646,7 +3654,9 @@ mDNSlocal const mDNSu8 *DumpRecords(mDNS *const m, const DNSMessage *const msg,
(X) == kDNSFlag0_OP_Status ? "Status " : \
(X) == kDNSFlag0_OP_Unused3 ? "Unused3 " : \
(X) == kDNSFlag0_OP_Notify ? "Notify " : \
- (X) == kDNSFlag0_OP_Update ? "Update " : "?? " )
+ (X) == kDNSFlag0_OP_Update ? "Update " : \
+ (X) == kDNSFlag0_OP_Subscribe? "Subscribe": \
+ (X) == kDNSFlag0_OP_UnSubscribe? "UnSubscribe" : "?? " )
#define DNS_RC_Name(X) ( \
(X) == kDNSFlag1_RC_NoErr ? "NoErr" : \
@@ -3678,7 +3688,7 @@ mDNSexport void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *t
if (dstaddr || !mDNSIPPortIsZero(dstport))
dbuffer[mDNS_snprintf(dbuffer, sizeof(dbuffer), " to %#a:%d", dstaddr, mDNSVal16(dstport))] = 0;
- LogMsg("-- %s %s DNS %s%s (flags %02X%02X) RCODE: %s (%d) %s%s%s%s%s%sID: %d %d bytes from %s%d%s%s --",
+ LogInfo("-- %s %s DNS %s%s (flags %02X%02X) RCODE: %s (%d) %s%s%s%s%s%sID: %d %d bytes from %s%d%s%s --",
tbuffer, transport,
DNS_OP_Name(msg->h.flags.b[0] & kDNSFlag0_OP_Mask),
msg->h.flags.b[0] & kDNSFlag0_QR_Response ? "Response" : "Query",
@@ -3697,16 +3707,16 @@ mDNSexport void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *t
(msg->h.flags.b[0] & kDNSFlag0_TC) ? " (truncated)" : ""
);
- LogMsg("%2d %s", msg->h.numQuestions, IsUpdate ? "Zone" : "Questions");
+ LogInfo("%2d %s", msg->h.numQuestions, IsUpdate ? "Zone" : "Questions");
for (i = 0; i < msg->h.numQuestions && ptr; i++)
{
ptr = getQuestion(msg, ptr, end, mDNSInterface_Any, &q);
- if (ptr) LogMsg("%2d %##s %s", i, q.qname.c, DNSTypeName(q.qtype));
+ if (ptr) LogInfo("%2d %##s %s", i, q.qname.c, DNSTypeName(q.qtype));
}
ptr = DumpRecords(m, msg, ptr, end, msg->h.numAnswers, IsUpdate ? "Prerequisites" : "Answers");
ptr = DumpRecords(m, msg, ptr, end, msg->h.numAuthorities, IsUpdate ? "Updates" : "Authorities");
DumpRecords(m, msg, ptr, end, msg->h.numAdditionals, "Additionals");
- LogMsg("--------------");
+ LogInfo("--------------");
}
// ***************************************************************************
@@ -3896,6 +3906,10 @@ mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m)
if (e - m->NextScheduledSPS > 0) e = m->NextScheduledSPS;
if (e - m->NextScheduledKA > 0) e = m->NextScheduledKA;
+#if BONJOUR_ON_DEMAND
+ if (m->NextBonjourDisableTime && (e - m->NextBonjourDisableTime > 0)) e = m->NextBonjourDisableTime;
+#endif // BONJOUR_ON_DEMAND
+
// NextScheduledSPRetry only valid when DelaySleep not set
if (!m->DelaySleep && m->SleepLimit && e - m->NextScheduledSPRetry > 0) e = m->NextScheduledSPRetry;
if (m->DelaySleep && e - m->DelaySleep > 0) e = m->DelaySleep;
@@ -3911,6 +3925,9 @@ mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m)
if (e - m->NextScheduledResponse > 0) e = m->NextScheduledResponse;
}
if (e - m->NextScheduledStopTime > 0) e = m->NextScheduledStopTime;
+
+ if (m->NextBLEServiceTime && (e - m->NextBLEServiceTime > 0)) e = m->NextBLEServiceTime;
+
return(e);
}
diff --git a/mDNSResponder/mDNSCore/DNSCommon.h b/mDNSResponder/mDNSCore/DNSCommon.h
index e51b06dd..2da19700 100644
--- a/mDNSResponder/mDNSCore/DNSCommon.h
+++ b/mDNSResponder/mDNSCore/DNSCommon.h
@@ -40,17 +40,19 @@ extern "C" {
typedef enum
{
- kDNSFlag0_QR_Mask = 0x80, // Query or response?
- kDNSFlag0_QR_Query = 0x00,
- kDNSFlag0_QR_Response = 0x80,
-
- kDNSFlag0_OP_Mask = 0x78, // Operation type
- kDNSFlag0_OP_StdQuery = 0x00,
- kDNSFlag0_OP_Iquery = 0x08,
- kDNSFlag0_OP_Status = 0x10,
- kDNSFlag0_OP_Unused3 = 0x18,
- kDNSFlag0_OP_Notify = 0x20,
- kDNSFlag0_OP_Update = 0x28,
+ kDNSFlag0_QR_Mask = 0x80, // Query or response?
+ kDNSFlag0_QR_Query = 0x00,
+ kDNSFlag0_QR_Response = 0x80,
+
+ kDNSFlag0_OP_Mask = 0x78, // Operation type
+ kDNSFlag0_OP_StdQuery = 0x00,
+ kDNSFlag0_OP_Subscribe = 0x06,
+ kDNSFlag0_OP_UnSubscribe = 0x07,
+ kDNSFlag0_OP_Iquery = 0x08,
+ kDNSFlag0_OP_Status = 0x10,
+ kDNSFlag0_OP_Unused3 = 0x18,
+ kDNSFlag0_OP_Notify = 0x20,
+ kDNSFlag0_OP_Update = 0x28,
kDNSFlag0_QROP_Mask = kDNSFlag0_QR_Mask | kDNSFlag0_OP_Mask,
@@ -84,6 +86,7 @@ typedef enum
TSIG_ErrBadTime = 18
} TSIG_ErrorCode;
+
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark -
diff --git a/mDNSResponder/mDNSCore/anonymous.c b/mDNSResponder/mDNSCore/anonymous.c
index 779e4ea6..aaaebc27 100644
--- a/mDNSResponder/mDNSCore/anonymous.c
+++ b/mDNSResponder/mDNSCore/anonymous.c
@@ -71,7 +71,7 @@ mDNSlocal mDNSBool InitializeNSEC3Record(ResourceRecord *rr, const mDNSu8 *AnonD
// Hash the base service name + salt + AnonData
if (!NSEC3HashName(rr->name, nsec3, AnonData, len, hashName, &hlen))
{
- LogMsg("InitializeNSEC3Record: NSEC3HashName failed for ##s", rr->name->c);
+ LogMsg("InitializeNSEC3Record: NSEC3HashName failed for %##s", rr->name->c);
return mDNSfalse;
}
if (hlen != SHA1_HASH_LENGTH)
@@ -280,9 +280,10 @@ mDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNS
int AnonDataLen;
rdataNSEC3 *nsec3;
int hlen;
- const mDNSu8 hashName[NSEC3_MAX_HASH_LEN];
int nxtLength;
mDNSu8 *nxtName;
+ mDNSu8 hashName[NSEC3_MAX_HASH_LEN];
+ mDNSPlatformMemZero(hashName, sizeof(hashName));
debugf("AnonInfoAnswersQuestion: question qname %##s", q->qname.c);
@@ -403,7 +404,7 @@ mDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNS
if (!NSEC3HashName(nsec3RR->name, nsec3, AnonData, AnonDataLen, hashName, &hlen))
{
- LogMsg("AnonInfoAnswersQuestion: NSEC3HashName failed for ##s", nsec3RR->name->c);
+ LogMsg("AnonInfoAnswersQuestion: NSEC3HashName failed for %##s", nsec3RR->name->c);
return mDNSfalse;
}
if (hlen != SHA1_HASH_LENGTH)
diff --git a/mDNSResponder/mDNSCore/dnsproxy.c b/mDNSResponder/mDNSCore/dnsproxy.c
index 5b358864..05b70dd9 100644
--- a/mDNSResponder/mDNSCore/dnsproxy.c
+++ b/mDNSResponder/mDNSCore/dnsproxy.c
@@ -553,14 +553,21 @@ mDNSlocal mDNSBool CheckDNSProxyIpIntf(const mDNS *const m, mDNSInterfaceID Inte
int i;
mDNSu32 ip_ifindex = (mDNSu32)(unsigned long)InterfaceID;
- LogInfo("CheckDNSProxyIpIntf: Stored Input Interface List: [%d] [%d] [%d] [%d] [%d]", m->dp_ipintf[0], m->dp_ipintf[1], m->dp_ipintf[2],
- m->dp_ipintf[3], m->dp_ipintf[4]);
+ LogInfo("CheckDNSProxyIpIntf: Check for ifindex[%d] in stored input interface list: [%d] [%d] [%d] [%d] [%d]",
+ ip_ifindex, m->dp_ipintf[0], m->dp_ipintf[1], m->dp_ipintf[2], m->dp_ipintf[3], m->dp_ipintf[4]);
- for (i = 0; i < MaxIp; i++)
+ if (ip_ifindex > 0)
{
- if (ip_ifindex == m->dp_ipintf[i])
- return mDNStrue;
+ for (i = 0; i < MaxIp; i++)
+ {
+ if (ip_ifindex == m->dp_ipintf[i])
+ return mDNStrue;
+ }
}
+
+ LogMsg("CheckDNSProxyIpIntf: ifindex[%d] not in stored input interface list: [%d] [%d] [%d] [%d] [%d]",
+ ip_ifindex, m->dp_ipintf[0], m->dp_ipintf[1], m->dp_ipintf[2], m->dp_ipintf[3], m->dp_ipintf[4]);
+
return mDNSfalse;
}
@@ -583,7 +590,10 @@ mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, void *const pkt,
debugf("ProxyCallbackCommon: DNS Query coming from InterfaceID %p", InterfaceID);
// Ignore if the DNS Query is not from a Valid Input InterfaceID
if (!CheckDNSProxyIpIntf(m, InterfaceID))
+ {
+ LogMsg("ProxyCallbackCommon: Rejecting DNS Query coming from InterfaceID %p", InterfaceID);
return;
+ }
if ((unsigned)(end - (mDNSu8 *)pkt) < sizeof(DNSMessageHeader))
{
@@ -691,8 +701,7 @@ mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, void *const pkt,
debugf("ProxyCallbackCommon: DNS Query forwarding to interface index %d", m->dp_opintf);
mDNS_SetupQuestion(&pc->q, (mDNSInterfaceID)(unsigned long)m->dp_opintf, &q.qname, q.qtype, ProxyClientCallback, pc);
pc->q.TimeoutQuestion = 1;
- // Even though we don't care about intermediate responses, set ReturnIntermed so that
- // we get the negative responses
+ // Set ReturnIntermed so that we get the negative responses
pc->q.ReturnIntermed = mDNStrue;
pc->q.ProxyQuestion = mDNStrue;
pc->q.ProxyDNSSECOK = pc->DNSSECOK;
@@ -735,9 +744,10 @@ mDNSexport void ProxyTCPCallback(mDNS *const m, void *socket, void *const pkt, c
const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context)
{
LogInfo("ProxyTCPCallback: DNS Message from %#a:%d to %#a:%d length %d", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), end - (mDNSu8 *)pkt);
- // If the connection was closed from the other side, locate the client
+
+ // If the connection was closed from the other side or incoming packet does not match stored input interface list, locate the client
// state and free it.
- if ((end - (mDNSu8 *)pkt) == 0)
+ if (((end - (mDNSu8 *)pkt) == 0) || (!CheckDNSProxyIpIntf(m, InterfaceID)))
{
DNSProxyClient **ppc = &DNSProxyClients;
DNSProxyClient **prevpc;
diff --git a/mDNSResponder/mDNSCore/dnssec.c b/mDNSResponder/mDNSCore/dnssec.c
index bf9acfe8..514a488c 100644
--- a/mDNSResponder/mDNSCore/dnssec.c
+++ b/mDNSResponder/mDNSCore/dnssec.c
@@ -87,6 +87,7 @@ mDNSlocal mDNSBool TrustedKeyPresent(mDNS *const m, DNSSECVerifier *dv);
mDNSlocal mStatus ValidateDS(DNSSECVerifier *dv);
mDNSlocal void DNSSECNegativeValidationCB(mDNS *const m, DNSSECVerifier *dv, CacheGroup *cg, ResourceRecord *answer, DNSSECStatus status);
mDNSlocal RRVerifier* CopyRRVerifier(RRVerifier *from);
+mDNSlocal void FreeDNSSECAuthChainInfo(AuthChain *ac);
// Currently we use this to convert a RRVerifier to resource record so that we can
// use the standard DNS utility functions
@@ -300,6 +301,8 @@ mDNSlocal AuthChain *AuthChainCopy(AuthChain *ae)
if (!ac)
{
LogMsg("AuthChainCopy: AuthChain alloc failure");
+ if (retac)
+ FreeDNSSECAuthChainInfo(retac);
return mDNSfalse;
}
@@ -2523,7 +2526,9 @@ mDNSlocal void FinishDNSSECVerification(mDNS *const m, DNSSECVerifier *dv)
LogDNSSEC("FinishDNSSECVerification: all rdata sets available for sig verification for %##s (%s)",
dv->origName.c, DNSTypeName(dv->origType));
- mDNS_StopQuery(m, &dv->q);
+ // Stop outstanding query if one exists
+ if (dv->q.ThisQInterval != -1)
+ mDNS_StopQuery(m, &dv->q);
if (ValidateSignature(dv, &resultKey, &resultRRSig) == mStatus_NoError)
{
rdataDNSKey *key;
diff --git a/mDNSResponder/mDNSCore/mDNS.c b/mDNSResponder/mDNSCore/mDNS.c
index 6b02be46..d1841a5e 100755
--- a/mDNSResponder/mDNSCore/mDNS.c
+++ b/mDNSResponder/mDNSCore/mDNS.c
@@ -49,6 +49,9 @@
#if APPLE_OSX_mDNSResponder
#include <WebFilterDNS/WebFilterDNS.h>
+// Delay in seconds before disabling multicast after there are no active queries or registrations.
+#define BONJOUR_DISABLE_DELAY 60
+
#if !NO_WCF
WCFConnection *WCFConnectionNew(void) __attribute__((weak_import));
void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import));
@@ -69,7 +72,7 @@ void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import));
// Forward declarations
mDNSlocal void BeginSleepProcessing(mDNS *const m);
mDNSlocal void RetrySPSRegistrations(mDNS *const m);
-mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password);
+mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password, mDNSBool unicastOnly);
mDNSlocal mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q);
mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q);
mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q);
@@ -106,16 +109,39 @@ mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *et
#define NR_AnswerMulticast (mDNSu8*)~0
#define NR_AnswerUnicast (mDNSu8*)~1
-// Defined to set the kDNSQClass_UnicastResponse bit in the first four query packets.
-// else, it's just set it the first query.
-#define mDNS_REQUEST_UNICAST_RESPONSE 0
-
// The code (see SendQueries() and BuildQuestion()) needs to have the
// RequestUnicast value set to a value one greater than the number of times you want the query
// sent with the "request unicast response" (QU) bit set.
#define SET_QU_IN_FIRST_QUERY 2
-#define SET_QU_IN_FIRST_FOUR_QUERIES 5
+#define kDefaultRequestUnicastCount SET_QU_IN_FIRST_QUERY
+
+// The time needed to offload records to a sleep proxy after powerd sends the kIOMessageSystemWillSleep notification
+#define DARK_WAKE_DELAY_SLEEP 5
+#define kDarkWakeDelaySleep (mDNSPlatformOneSecond * DARK_WAKE_DELAY_SLEEP)
+
+// The maximum number of times we delay probing to prevent spurious conflicts due to stale packets
+#define MAX_CONFLICT_PROCESSING_DELAYS 3
+
+// RFC 6762 defines Passive Observation Of Failures (POOF)
+//
+// A host observes the multicast queries issued by the other hosts on
+// the network. One of the major benefits of also sending responses
+// using multicast is that it allows all hosts to see the responses
+// (or lack thereof) to those queries.
+//
+// If a host sees queries, for which a record in its cache would be
+// expected to be given as an answer in a multicast response, but no
+// such answer is seen, then the host may take this as an indication
+// that the record may no longer be valid.
+//
+// After seeing two or more of these queries, and seeing no multicast
+// response containing the expected answer within ten seconds, then even
+// though its TTL may indicate that it is not yet due to expire, that
+// record SHOULD be flushed from the cache.
+//
+// <https://tools.ietf.org/html/rfc6762#section-10.5>
+#define POOF_ENABLED 1
mDNSexport const char *const mDNS_DomainTypeNames[] =
{
@@ -294,13 +320,13 @@ mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const mDNSu32 slot, const Resourc
// Returns the AuthGroup in which the AuthRecord was inserted
mDNSexport AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr)
{
+ (void)m;
AuthGroup *ag;
const mDNSu32 slot = AuthHashSlot(rr->resrec.name);
ag = AuthGroupForRecord(r, slot, &rr->resrec);
if (!ag) ag = GetAuthGroup(r, slot, &rr->resrec); // If we don't have a AuthGroup for this name, make one now
if (ag)
{
- LogInfo("InsertAuthRecord: inserting auth record %s from table", ARDisplayString(m, rr));
*(ag->rrauth_tail) = rr; // Append this record to tail of cache slot list
ag->rrauth_tail = &(rr->next); // Advance tail pointer
}
@@ -310,13 +336,12 @@ mDNSexport AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *r
mDNSexport AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr)
{
AuthGroup *a;
- AuthGroup **ag = &a;
AuthRecord **rp;
const mDNSu32 slot = AuthHashSlot(rr->resrec.name);
a = AuthGroupForRecord(r, slot, &rr->resrec);
if (!a) { LogMsg("RemoveAuthRecord: ERROR!! AuthGroup not found for %s", ARDisplayString(m, rr)); return mDNSNULL; }
- rp = &(*ag)->members;
+ rp = &a->members;
while (*rp)
{
if (*rp != rr)
@@ -330,7 +355,7 @@ mDNSexport AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *r
}
}
// TBD: If there are no more members, release authgroup ?
- (*ag)->rrauth_tail = rp;
+ a->rrauth_tail = rp;
return a;
}
@@ -412,14 +437,15 @@ mDNSexport char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID Interfa
}
// Caller should hold the lock
-mDNSlocal void GenerateNegativeResponse(mDNS *const m, QC_result qc)
+mDNSlocal void GenerateNegativeResponse(mDNS *const m, mDNSInterfaceID InterfaceID, QC_result qc)
{
DNSQuestion *q;
if (!m->CurrentQuestion) { LogMsg("GenerateNegativeResponse: ERROR!! CurrentQuestion not set"); return; }
q = m->CurrentQuestion;
LogInfo("GenerateNegativeResponse: Generating negative response for question %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
- MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any, mDNSNULL);
+ MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, InterfaceID, mDNSNULL);
+
// We need to force the response through in the following cases
//
// a) SuppressUnusable questions that are suppressed
@@ -447,28 +473,10 @@ mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, Re
UDPSocket *sock = q->LocalSocket;
mDNSOpaque16 id = q->TargetQID;
#if TARGET_OS_EMBEDDED
- domainname *originalQName;
+ uDNSMetrics metrics;
#endif
- // if there is a message waiting at the socket, we want to process that instead
- // of throwing it away. If we have a CNAME response that answers
- // both A and AAAA question and while answering it we don't want to throw
- // away the response where the actual addresses are present.
- // This is a stupid hack and we should get rid of it.
- // The chance of there being a second unicast UDP packet already waiting in the kernel before we’ve
- // finished processing the previous one is virtually nil, and will only happen by luck on very rare
- // occasions when running on a machine with a fast network connection and a slow or busy processor.
- // The idea that we’d rely for correctness on this random chance event occurring is ridiculous.
- // -- SC
- if (mDNSPlatformPeekUDP(m, q->LocalSocket))
- {
- LogInfo("AnswerQuestionByFollowingCNAME: Preserving UDP socket for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
- q->LocalSocket = mDNSNULL;
- }
- else
- {
- sock = mDNSNULL;
- }
+ q->LocalSocket = mDNSNULL;
// The SameDomainName check above is to ignore bogus CNAME records that point right back at
// themselves. Without that check we can get into a case where we have two duplicate questions,
@@ -489,29 +497,24 @@ mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, Re
q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, RRDisplayString(m, rr));
#if TARGET_OS_EMBEDDED
- if (q->metrics.originalQName)
- {
- originalQName = q->metrics.originalQName;
- q->metrics.originalQName = mDNSNULL;
- }
- else
+ if ((q->CNAMEReferrals == 0) && !q->metrics.originalQName)
{
- mDNSu16 qNameLen;
+ domainname * qName;
+ mDNSu16 qNameLen;
qNameLen = DomainNameLength(&q->qname);
if ((qNameLen > 0) && (qNameLen <= MAX_DOMAIN_NAME))
{
- originalQName = mDNSPlatformMemAllocate(qNameLen);
- if (originalQName)
+ qName = mDNSPlatformMemAllocate(qNameLen);
+ if (qName)
{
- mDNSPlatformMemCopy(originalQName->c, q->qname.c, qNameLen);
+ mDNSPlatformMemCopy(qName->c, q->qname.c, qNameLen);
+ q->metrics.originalQName = qName;
}
}
- else
- {
- originalQName = mDNSNULL;
- }
}
+ metrics = q->metrics;
+ mDNSPlatformMemZero(&q->metrics, sizeof(q->metrics));
#endif
mDNS_StopQuery_internal(m, q); // Stop old query
AssignDomainName(&q->qname, &rr->rdata->u.name); // Update qname
@@ -530,19 +533,96 @@ mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, Re
// because mDNS_StartQuery_internal re-initializes CNAMEReferrals to zero
q->CNAMEReferrals = c;
#if TARGET_OS_EMBEDDED
- q->metrics.originalQName = originalQName;
+ q->metrics = metrics;
#endif
if (sock)
{
- // We have a message waiting and that should answer this question.
- if (q->LocalSocket)
- mDNSPlatformUDPClose(q->LocalSocket);
- q->LocalSocket = sock;
- q->TargetQID = id;
+ // If our new query is a duplicate, then it can't have a socket of its own, so we have to close the one we saved.
+ if (q->DuplicateOf) mDNSPlatformUDPClose(sock);
+ else
+ {
+ // Transplant the old socket into the new question, and copy the query ID across too.
+ // No need to close the old q->LocalSocket value because it won't have been created yet (they're made lazily on-demand).
+ q->LocalSocket = sock;
+ q->TargetQID = id;
+ }
}
}
}
+#ifdef USE_LIBIDN
+
+#include <unicode/uidna.h>
+
+// #define DEBUG_PUNYCODE 1
+
+mDNSlocal mDNSu8 *PunycodeConvert(const mDNSu8 *const src, mDNSu8 *const dst, const mDNSu8 *const end)
+{
+ UErrorCode errorCode = U_ZERO_ERROR;
+ UIDNAInfo info = UIDNA_INFO_INITIALIZER;
+ UIDNA *uts46 = uidna_openUTS46(UIDNA_USE_STD3_RULES|UIDNA_NONTRANSITIONAL_TO_UNICODE, &errorCode);
+ int32_t len = uidna_nameToASCII_UTF8(uts46, (const char *)src+1, src[0], (char *)dst+1, end-(dst+1), &info, &errorCode);
+ uidna_close(uts46);
+ #if DEBUG_PUNYCODE
+ if (errorCode) LogMsg("uidna_nameToASCII_UTF8(%##s) failed errorCode %d", src, errorCode);
+ if (info.errors) LogMsg("uidna_nameToASCII_UTF8(%##s) failed info.errors 0x%08X", src, info.errors);
+ if (len > MAX_DOMAIN_LABEL) LogMsg("uidna_nameToASCII_UTF8(%##s) result too long %d", src, len);
+ #endif
+ if (errorCode || info.errors || len > MAX_DOMAIN_LABEL) return mDNSNULL;
+ *dst = len;
+ return(dst + 1 + len);
+}
+
+mDNSlocal mDNSBool IsHighASCIILabel(const mDNSu8 *d)
+{
+ int i;
+ for (i=1; i<=d[0]; i++) if (d[i] & 0x80) return mDNStrue;
+ return mDNSfalse;
+}
+
+mDNSlocal const mDNSu8 *FindLastHighASCIILabel(const domainname *const d)
+{
+ const mDNSu8 *ptr = d->c;
+ const mDNSu8 *ans = mDNSNULL;
+ while (ptr[0])
+ {
+ const mDNSu8 *const next = ptr + 1 + ptr[0];
+ if (ptr[0] > MAX_DOMAIN_LABEL || next >= d->c + MAX_DOMAIN_NAME) return mDNSNULL;
+ if (IsHighASCIILabel(ptr)) ans = ptr;
+ ptr = next;
+ }
+ return ans;
+}
+
+mDNSlocal mDNSBool PerformNextPunycodeConversion(const DNSQuestion *const q, domainname *const newname)
+{
+ const mDNSu8 *h = FindLastHighASCIILabel(&q->qname);
+ #if DEBUG_PUNYCODE
+ LogMsg("PerformNextPunycodeConversion: %##s (%s) Last High-ASCII Label %##s", q->qname.c, DNSTypeName(q->qtype), h);
+ #endif
+ if (!h) return mDNSfalse; // There are no high-ascii labels to convert
+
+ mDNSu8 *const dst = PunycodeConvert(h, newname->c + (h - q->qname.c), newname->c + MAX_DOMAIN_NAME);
+ if (!dst)
+ return mDNSfalse; // The label was not convertible to Punycode
+ else
+ {
+ // If Punycode conversion of final eligible label was successful, copy the rest of the domainname
+ const mDNSu8 *const src = h + 1 + h[0];
+ const mDNSu8 remainder = DomainNameLength((domainname*)src);
+ if (dst + remainder > newname->c + MAX_DOMAIN_NAME) return mDNSfalse; // Name too long -- cannot be converted to Punycode
+
+ mDNSPlatformMemCopy(newname->c, q->qname.c, h - q->qname.c); // Fill in the leading part
+ mDNSPlatformMemCopy(dst, src, remainder); // Fill in the trailing part
+ #if DEBUG_PUNYCODE
+ LogMsg("PerformNextPunycodeConversion: %##s converted to %##s", q->qname.c, newname->c);
+ #endif
+ return mDNStrue;
+ }
+}
+
+#endif // USE_LIBIDN
+
// For a single given DNSQuestion pointed to by CurrentQuestion, deliver an add/remove result for the single given AuthRecord
// Note: All the callers should use the m->CurrentQuestion to see if the question is still valid or not
mDNSlocal void AnswerLocalQuestionWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord)
@@ -766,6 +846,8 @@ mDNSlocal mDNSBool PacketRRMatchesSignature(const CacheRecord *const pktrr, cons
pktrr->resrec.InterfaceID != authrr->resrec.InterfaceID) return(mDNSfalse);
if (!(authrr->resrec.RecordType & kDNSRecordTypeUniqueMask) || authrr->WakeUp.HMAC.l[0])
if (pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse);
+ if ((authrr->resrec.InterfaceID == mDNSInterface_Any) &&
+ !mDNSPlatformValidRecordForInterface(authrr, pktrr->resrec.InterfaceID)) return(mDNSfalse);
return (mDNSBool)(
pktrr->resrec.rrclass == authrr->resrec.rrclass &&
pktrr->resrec.namehash == authrr->resrec.namehash &&
@@ -843,11 +925,12 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
if (m->SuppressProbes == 0 || m->SuppressProbes - m->timenow < 0)
{
// To allow us to aggregate probes when a group of services are registered together,
- // the first probe is delayed 1/4 second. This means the common-case behaviour is:
- // 1/4 second wait; probe
+ // the first probe is delayed by a random delay in the range 1/8 to 1/4 second.
+ // This means the common-case behaviour is:
+ // randomized wait; probe
// 1/4 second wait; probe
// 1/4 second wait; probe
- // 1/4 second wait; announce (i.e. service is normally announced exactly one second after being registered)
+ // 1/4 second wait; announce (i.e. service is normally announced 7/8 to 1 second after being registered)
m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2));
// If we already have a *probe* scheduled to go out sooner, then use that time to get better aggregation
@@ -879,7 +962,9 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
}
rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval;
}
- else if (m->SuppressProbes && m->SuppressProbes - m->timenow >= 0)
+ // Skip kDNSRecordTypeKnownUnique records here and set their LastAPTime in the "else" block below so that they get announced immediately,
+ // otherwise, their announcement would be delayed until all other record probes complete.
+ else if ((rr->resrec.RecordType != kDNSRecordTypeKnownUnique) && m->SuppressProbes && m->SuppressProbes - m->timenow >= 0)
rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval + DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2;
else
rr->LastAPTime = m->timenow - rr->ThisAPInterval;
@@ -890,7 +975,7 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
// and we can begin broadcasting our announcements to take over ownership of that IP address.
// If we don't wait for the client to go to sleep, then when the client sees our ARP Announcements there's a risk
// (depending on the OS and networking stack it's using) that it might interpret it as a conflict and change its IP address.
- if (rr->AddressProxy.type)
+ if (rr->AddressProxy.type)
rr->LastAPTime = m->timenow;
// Set LastMCTime to now, to inhibit multicast responses
@@ -1068,26 +1153,25 @@ mDNSexport void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr)
mDNSlocal AuthRecord *CheckAuthIdenticalRecord(AuthHash *r, AuthRecord *rr)
{
- AuthGroup *a;
- AuthGroup **ag = &a;
- AuthRecord **rp;
+ const AuthGroup *a;
+ AuthRecord *rp;
const mDNSu32 slot = AuthHashSlot(rr->resrec.name);
a = AuthGroupForRecord(r, slot, &rr->resrec);
if (!a) return mDNSNULL;
- rp = &(*ag)->members;
- while (*rp)
+ rp = a->members;
+ while (rp)
{
- if (!RecordIsLocalDuplicate(*rp, rr))
- rp=&(*rp)->next;
+ if (!RecordIsLocalDuplicate(rp, rr))
+ rp = rp->next;
else
{
- if ((*rp)->resrec.RecordType == kDNSRecordTypeDeregistering)
+ if (rp->resrec.RecordType == kDNSRecordTypeDeregistering)
{
- (*rp)->AnnounceCount = 0;
- rp=&(*rp)->next;
+ rp->AnnounceCount = 0;
+ rp = rp->next;
}
- else return *rp;
+ else return rp;
}
}
return (mDNSNULL);
@@ -1095,22 +1179,21 @@ mDNSlocal AuthRecord *CheckAuthIdenticalRecord(AuthHash *r, AuthRecord *rr)
mDNSlocal mDNSBool CheckAuthRecordConflict(AuthHash *r, AuthRecord *rr)
{
- AuthGroup *a;
- AuthGroup **ag = &a;
- AuthRecord **rp;
+ const AuthGroup *a;
+ const AuthRecord *rp;
const mDNSu32 slot = AuthHashSlot(rr->resrec.name);
a = AuthGroupForRecord(r, slot, &rr->resrec);
if (!a) return mDNSfalse;
- rp = &(*ag)->members;
- while (*rp)
+ rp = a->members;
+ while (rp)
{
const AuthRecord *s1 = rr->RRSet ? rr->RRSet : rr;
- const AuthRecord *s2 = (*rp)->RRSet ? (*rp)->RRSet : *rp;
- if (s1 != s2 && SameResourceRecordSignature((*rp), rr) && !IdenticalSameNameRecord(&(*rp)->resrec, &rr->resrec))
+ const AuthRecord *s2 = rp->RRSet ? rp->RRSet : rp;
+ if (s1 != s2 && SameResourceRecordSignature(rp, rr) && !IdenticalSameNameRecord(&rp->resrec, &rr->resrec))
return mDNStrue;
else
- rp=&(*rp)->next;
+ rp = rp->next;
}
return (mDNSfalse);
}
@@ -1118,21 +1201,20 @@ mDNSlocal mDNSBool CheckAuthRecordConflict(AuthHash *r, AuthRecord *rr)
// checks to see if "rr" is already present
mDNSlocal AuthRecord *CheckAuthSameRecord(AuthHash *r, AuthRecord *rr)
{
- AuthGroup *a;
- AuthGroup **ag = &a;
- AuthRecord **rp;
+ const AuthGroup *a;
+ AuthRecord *rp;
const mDNSu32 slot = AuthHashSlot(rr->resrec.name);
a = AuthGroupForRecord(r, slot, &rr->resrec);
if (!a) return mDNSNULL;
- rp = &(*ag)->members;
- while (*rp)
+ rp = a->members;
+ while (rp)
{
- if (*rp != rr)
- rp=&(*rp)->next;
+ if (rp != rr)
+ rp = rp->next;
else
{
- return *rp;
+ return rp;
}
}
return (mDNSNULL);
@@ -1158,20 +1240,22 @@ mDNSlocal void DecrementAutoTargetServices(mDNS *const m, AuthRecord *const rr)
LogInfo("DecrementAutoTargetServices: AutoTargetServices %d Record %s", m->AutoTargetServices, ARDisplayString(m, rr));
}
-#if TARGET_OS_WATCH
+#if BONJOUR_ON_DEMAND
if (!AuthRecord_uDNS(rr))
{
if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
- m->NetworkChanged = m->timenow;
+ m->NextBonjourDisableTime = NonZeroTime(m->timenow + (BONJOUR_DISABLE_DELAY * mDNSPlatformOneSecond));
m->NumAllInterfaceRecords--;
LogInfo("DecrementAutoTargetServices: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %s",
m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, ARDisplayString(m, rr));
}
-#endif
+#endif // BONJOUR_ON_DEMAND
}
mDNSlocal void IncrementAutoTargetServices(mDNS *const m, AuthRecord *const rr)
{
+ mDNSBool enablingBonjour = 0;
+
if (RRLocalOnly(rr))
{
// A sanity check, this should be prevented in calling code.
@@ -1179,34 +1263,51 @@ mDNSlocal void IncrementAutoTargetServices(mDNS *const m, AuthRecord *const rr)
return;
}
-#if TARGET_OS_WATCH
+#if BONJOUR_ON_DEMAND
if (!AuthRecord_uDNS(rr))
{
m->NumAllInterfaceRecords++;
LogInfo("IncrementAutoTargetServices: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %s",
m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, ARDisplayString(m, rr));
if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
- m->NetworkChanged = m->timenow;
+ {
+ m->NextBonjourDisableTime = 0;
+ if (m->BonjourEnabled == 0)
+ {
+ // Enable Bonjour immediately by scheduling network changed processing where
+ // we will join the multicast group on each active interface.
+ m->BonjourEnabled = 1;
+ enablingBonjour = 1;
+ m->NetworkChanged = m->timenow;
+ }
+ }
}
-#endif
+#endif // BONJOUR_ON_DEMAND
if (!AuthRecord_uDNS(rr) && rr->resrec.rrtype == kDNSType_SRV && rr->AutoTarget == Target_AutoHost)
{
m->AutoTargetServices++;
LogInfo("IncrementAutoTargetServices: AutoTargetServices %d Record %s", m->AutoTargetServices, ARDisplayString(m, rr));
- // If this is the first advertised service
- if (m->AutoTargetServices == 1)
+
+ // If this is the first advertised service and we did not just enable Bonjour above, then
+ // advertise all the interface records. If we did enable Bonjour above, the interface records will
+ // be advertised during the network changed processing scheduled above, so no need
+ // to do it here.
+ if ((m->AutoTargetServices == 1) && (enablingBonjour == 0))
AdvertiseAllInterfaceRecords(m);
}
}
mDNSlocal void getKeepaliveRaddr(mDNS *const m, AuthRecord *rr, mDNSAddr *raddr)
{
- mDNSAddr laddr;
- mDNSEthAddr eth;
- mDNSIPPort lport, rport;
- mDNSu32 timeout, seq, ack;
- mDNSu16 win;
+ mDNSAddr laddr = zeroAddr;
+ mDNSEthAddr eth = zeroEthAddr;
+ mDNSIPPort lport = zeroIPPort;
+ mDNSIPPort rport = zeroIPPort;
+ mDNSu32 timeout = 0;
+ mDNSu32 seq = 0;
+ mDNSu32 ack = 0;
+ mDNSu16 win = 0;
if (mDNS_KeepaliveRecord(&rr->resrec))
{
@@ -1305,15 +1406,15 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
// Set up by client prior to call
// Field Group 2: Persistent metadata for Authoritative Records
-// rr->Additional1 = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client
-// rr->Additional2 = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client
-// rr->DependentOn = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client
-// rr->RRSet = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client
-// rr->Callback = already set in mDNS_SetupResourceRecord
-// rr->Context = already set in mDNS_SetupResourceRecord
-// rr->RecordType = already set in mDNS_SetupResourceRecord
-// rr->HostTarget = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
-// rr->AllowRemoteQuery = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
+// rr->Additional1 = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client
+// rr->Additional2 = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client
+// rr->DependentOn = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client
+// rr->RRSet = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client
+// rr->Callback = already set in mDNS_SetupResourceRecord
+// rr->Context = already set in mDNS_SetupResourceRecord
+// rr->RecordType = already set in mDNS_SetupResourceRecord
+// rr->HostTarget = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
+// rr->AllowRemoteQuery = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
// Make sure target is not uninitialized data, or we may crash writing debugging log messages
if (rr->AutoTarget && target) target->c[0] = 0;
@@ -1336,9 +1437,9 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
rr->NR_AnswerTo = mDNSNULL;
rr->NR_AdditionalTo = mDNSNULL;
if (!rr->AutoTarget) InitializeLastAPTime(m, rr);
-// rr->LastAPTime = Set for us in InitializeLastAPTime()
-// rr->LastMCTime = Set for us in InitializeLastAPTime()
-// rr->LastMCInterface = Set for us in InitializeLastAPTime()
+// rr->LastAPTime = Set for us in InitializeLastAPTime()
+// rr->LastMCTime = Set for us in InitializeLastAPTime()
+// rr->LastMCInterface = Set for us in InitializeLastAPTime()
rr->NewRData = mDNSNULL;
rr->newrdlength = 0;
rr->UpdateCallback = mDNSNULL;
@@ -1371,12 +1472,12 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
// times with different values if the external NAT port changes during the lifetime of the service registration.
//if (rr->resrec.rrtype == kDNSType_SRV) rr->NATinfo.IntPort = rr->resrec.rdata->u.srv.port;
-// rr->resrec.interface = already set in mDNS_SetupResourceRecord
-// rr->resrec.name->c = MUST be set by client
-// rr->resrec.rrtype = already set in mDNS_SetupResourceRecord
-// rr->resrec.rrclass = already set in mDNS_SetupResourceRecord
-// rr->resrec.rroriginalttl = already set in mDNS_SetupResourceRecord
-// rr->resrec.rdata = MUST be set by client, unless record type is CNAME or PTR and rr->HostTarget is set
+// rr->resrec.interface = already set in mDNS_SetupResourceRecord
+// rr->resrec.name->c = MUST be set by client
+// rr->resrec.rrtype = already set in mDNS_SetupResourceRecord
+// rr->resrec.rrclass = already set in mDNS_SetupResourceRecord
+// rr->resrec.rroriginalttl = already set in mDNS_SetupResourceRecord
+// rr->resrec.rdata = MUST be set by client, unless record type is CNAME or PTR and rr->HostTarget is set
// BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
// since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
@@ -1471,7 +1572,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
if (r)
{
- debugf("mDNS_Register_internal:Adding to duplicate list %s", ARDisplayString(m,rr));
+ LogInfo("mDNS_Register_internal: Adding to duplicate list %s", ARDisplayString(m,rr));
*d = rr;
// If the previous copy of this record is already verified unique,
// then indicate that we should move this record promptly to kDNSRecordTypeUnique state.
@@ -1482,7 +1583,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
}
else
{
- debugf("mDNS_Register_internal: Adding to active record list %s", ARDisplayString(m,rr));
+ LogInfo("mDNS_Register_internal: Adding to active record list %s", ARDisplayString(m,rr));
if (RRLocalOnly(rr))
{
AuthGroup *ag;
@@ -1504,6 +1605,19 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
}
}
+ if (!AuthRecord_uDNS(rr)) // This check is superfluous, given that for unicast records we (currently) bail out above
+ {
+ // We have inserted the record in the list. See if we have to advertise the A/AAAA, HINFO, PTR records.
+ IncrementAutoTargetServices(m, rr);
+
+ // For records that are not going to probe, acknowledge them right away
+ if (rr->resrec.RecordType != kDNSRecordTypeUnique && rr->resrec.RecordType != kDNSRecordTypeDeregistering)
+ AcknowledgeRecord(m, rr);
+
+ // Adding a record may affect whether or not we should sleep
+ mDNS_UpdateAllowSleep(m);
+ }
+
// If this is a non-sleep proxy keepalive record, fetch the MAC address of the remote host.
// This is used by the in-NIC proxy to send the keepalive packets.
if (!rr->WakeUp.HMAC.l[0] && mDNS_KeepaliveRecord(&rr->resrec))
@@ -1519,19 +1633,6 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
mDNSPlatformGetRemoteMacAddr(m, &raddr);
}
- if (!AuthRecord_uDNS(rr)) // This check is superfluous, given that for unicast records we (currently) bail out above
- {
- // We have inserted the record in the list. See if we have to advertise the A/AAAA, HINFO, PTR records.
- IncrementAutoTargetServices(m, rr);
-
- // For records that are not going to probe, acknowledge them right away
- if (rr->resrec.RecordType != kDNSRecordTypeUnique && rr->resrec.RecordType != kDNSRecordTypeDeregistering)
- AcknowledgeRecord(m, rr);
-
- // Adding a record may affect whether or not we should sleep
- mDNS_UpdateAllowSleep(m);
- }
-
return(mStatus_NoError);
}
@@ -1577,13 +1678,12 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr,
if (RRLocalOnly(rr))
{
AuthGroup *a;
- AuthGroup **ag = &a;
AuthRecord **rp;
const mDNSu32 slot = AuthHashSlot(rr->resrec.name);
a = AuthGroupForRecord(&m->rrauth, slot, &rr->resrec);
if (!a) return mDNSfalse;
- rp = &(*ag)->members;
+ rp = &a->members;
while (*rp && *rp != rr) rp=&(*rp)->next;
p = rp;
}
@@ -1793,7 +1893,7 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr,
if (drt != mDNS_Dereg_conflict)
{
mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback
- LogInfo("mDNS_Deregister_internal: mStatus_MemFree for %s", ARDisplayString(m, rr));
+ LogInfo("mDNS_Deregister_internal: callback with mStatus_MemFree for %s", ARDisplayString(m, rr));
if (rr->RecordCallback)
rr->RecordCallback(m, rr, mStatus_MemFree); // MUST NOT touch rr after this
mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again
@@ -1817,6 +1917,10 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr,
}
else
{
+#if APPLE_OSX_mDNSResponder
+ // See if this record was also registered with any D2D plugins.
+ D2D_stop_advertising_record(r2);
+#endif
mDNS_Deregister_internal(m, r2, mDNS_Dereg_conflict);
// As this is a duplicate record, it will be unlinked from the list
// immediately
@@ -1927,9 +2031,8 @@ mDNSlocal void SendDelayedUnicastResponse(mDNS *const m, const mDNSAddr *const d
rr->v6Requester = zerov6Addr;
// Only sent records registered for P2P over P2P interfaces
- if (intf && !mDNSPlatformValidRecordForInterface(rr, intf))
+ if (intf && !mDNSPlatformValidRecordForInterface(rr, intf->InterfaceID))
{
- LogInfo("SendDelayedUnicastResponse: Not sending %s, on %s", ARDisplayString(m, rr), InterfaceNameForID(m, InterfaceID));
continue;
}
@@ -2343,6 +2446,22 @@ mDNSlocal mDNSBool ShouldSendGoodbyesBeforeSleep(mDNS *const m, const NetworkInt
}
}
+mDNSlocal mDNSBool IsInterfaceValidForAuthRecord(const AuthRecord *ar, mDNSInterfaceID InterfaceID)
+{
+ mDNSBool result;
+
+ if (ar->resrec.InterfaceID == mDNSInterface_Any)
+ {
+ result = mDNSPlatformValidRecordForInterface(ar, InterfaceID);
+ }
+ else
+ {
+ result = (ar->resrec.InterfaceID == InterfaceID);
+ }
+
+ return(result);
+}
+
// Note about acceleration of announcements to facilitate automatic coalescing of
// multiple independent threads of announcements into a single synchronized thread:
// The announcements in the packet may be at different stages of maturity;
@@ -2404,8 +2523,10 @@ mDNSlocal void SendResponses(mDNS *const m)
}
else
{
+ mDNSBool unicastOnly;
LogSPS("SendResponses: Sending wakeup %2d for %.6a %s", rr->AnnounceCount-3, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
- SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password);
+ unicastOnly = ((rr->AnnounceCount == WakeupCount) || (rr->AnnounceCount == WakeupCount - 1)) ? mDNStrue : mDNSfalse;
+ SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password, unicastOnly);
for (r2 = rr; r2; r2=r2->next)
if ((r2->resrec.RecordType == kDNSRecordTypeDeregistering) && r2->AnnounceCount && (r2->resrec.InterfaceID == rr->resrec.InterfaceID) &&
mDNSSameEthAddress(&r2->WakeUp.IMAC, &rr->WakeUp.IMAC) && !mDNSSameEthAddress(&zeroEthAddr, &r2->WakeUp.HMAC))
@@ -2506,17 +2627,28 @@ mDNSlocal void SendResponses(mDNS *const m)
if (rr->ImmedAnswer) // If we're sending this as answer, see that its whole RRSet is similarly marked
{
for (r2 = m->ResourceRecords; r2; r2=r2->next)
- if (ResourceRecordIsValidAnswer(r2))
- if (r2->ImmedAnswer != mDNSInterfaceMark &&
- r2->ImmedAnswer != rr->ImmedAnswer && SameResourceRecordSignature(r2, rr))
- r2->ImmedAnswer = !r2->ImmedAnswer ? rr->ImmedAnswer : mDNSInterfaceMark;
+ {
+ if ((r2->resrec.RecordType & kDNSRecordTypeUniqueMask) && ResourceRecordIsValidAnswer(r2) &&
+ (r2->ImmedAnswer != mDNSInterfaceMark) && (r2->ImmedAnswer != rr->ImmedAnswer) &&
+ SameResourceRecordSignature(r2, rr) &&
+ ((rr->ImmedAnswer == mDNSInterfaceMark) || IsInterfaceValidForAuthRecord(r2, rr->ImmedAnswer)))
+ {
+ r2->ImmedAnswer = !r2->ImmedAnswer ? rr->ImmedAnswer : mDNSInterfaceMark;
+ }
+ }
}
else if (rr->ImmedAdditional) // If we're sending this as additional, see that its whole RRSet is similarly marked
{
for (r2 = m->ResourceRecords; r2; r2=r2->next)
- if (ResourceRecordIsValidAnswer(r2))
- if (r2->ImmedAdditional != rr->ImmedAdditional && SameResourceRecordSignature(r2, rr))
- r2->ImmedAdditional = rr->ImmedAdditional;
+ {
+ if ((r2->resrec.RecordType & kDNSRecordTypeUniqueMask) && ResourceRecordIsValidAnswer(r2) &&
+ (r2->ImmedAdditional != rr->ImmedAdditional) &&
+ SameResourceRecordSignature(r2, rr) &&
+ IsInterfaceValidForAuthRecord(r2, rr->ImmedAdditional))
+ {
+ r2->ImmedAdditional = rr->ImmedAdditional;
+ }
+ }
}
}
@@ -2529,6 +2661,7 @@ mDNSlocal void SendResponses(mDNS *const m)
rr->ImmedAdditional = mDNSNULL; // No need to send as additional if sending as answer
rr->LastMCTime = m->timenow;
rr->LastMCInterface = rr->ImmedAnswer;
+ rr->ProbeRestartCount = 0; // Reset the probe restart count
// If we're announcing this record, and it's at least half-way to its ordained time, then consider this announcement done
if (TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2))
{
@@ -2576,9 +2709,8 @@ mDNSlocal void SendResponses(mDNS *const m)
// Skip this interface if the record InterfaceID is *Any and the record is not
// appropriate for the interface type.
if ((rr->SendRNow == intf->InterfaceID) &&
- ((rr->resrec.InterfaceID == mDNSInterface_Any) && !mDNSPlatformValidRecordForInterface(rr, intf)))
+ ((rr->resrec.InterfaceID == mDNSInterface_Any) && !mDNSPlatformValidRecordForInterface(rr, intf->InterfaceID)))
{
- // LogInfo("SendResponses: Not sending %s, on %s", ARDisplayString(m, rr), InterfaceNameForID(m, rr->SendRNow));
rr->SendRNow = GetNextActiveInterfaceID(intf);
}
else if (rr->SendRNow == intf->InterfaceID)
@@ -2651,7 +2783,7 @@ mDNSlocal void SendResponses(mDNS *const m)
// Get the reserved space back
OwnerRecordSpace -= AnoninfoSpace;
- TraceRecordSpace -= AnoninfoSpace;
+ TraceRecordSpace -= AnoninfoSpace;
newptr = responseptr;
for (rr = m->ResourceRecords; rr; rr=rr->next)
{
@@ -2800,10 +2932,9 @@ mDNSlocal void SendResponses(mDNS *const m)
SetupTracerOpt(m, &opt.resrec.rdata->u.opt[0]);
}
newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &opt.resrec);
- if (newptr)
- {
- responseptr = newptr;
- LogInfo("SendResponses put %s %s: %s %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "", intf->ifname, ARDisplayString(m, &opt));
+ if (newptr)
+ {
+ responseptr = newptr;
}
else if (m->omsg.h.numAnswers + m->omsg.h.numAuthorities + m->omsg.h.numAdditionals == 1)
{
@@ -2816,7 +2947,7 @@ mDNSlocal void SendResponses(mDNS *const m)
m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
}
}
-
+
debugf("SendResponses: Sending %d Deregistration%s, %d Announcement%s, %d Answer%s, %d Additional%s on %p",
numDereg, numDereg == 1 ? "" : "s",
numAnnounce, numAnnounce == 1 ? "" : "s",
@@ -3097,11 +3228,11 @@ mDNSlocal const CacheRecord *FindSPSInCache1(mDNS *const m, const DNSQuestion *c
}
return(bestcr);
#else // SPC_DISABLED
- (void) m;
- (void) q;
- (void) c0;
- (void) c1;
- (void) c1;
+ (void) m;
+ (void) q;
+ (void) c0;
+ (void) c1;
+ (void) c1;
return mDNSNULL;
#endif // SPC_DISABLED
}
@@ -3199,7 +3330,7 @@ mDNSlocal void mDNSSendWakeOnResolve(mDNS *const m, DNSQuestion *q)
domainname *d = &q->qname;
// We can't send magic packets without knowing which interface to send it on.
- if (InterfaceID == mDNSInterface_Any || InterfaceID == mDNSInterface_LocalOnly || InterfaceID == mDNSInterface_P2P)
+ if (InterfaceID == mDNSInterface_Any || LocalOnlyOrP2PInterface(InterfaceID))
{
LogMsg("mDNSSendWakeOnResolve: ERROR!! Invalid InterfaceID %p for question %##s", InterfaceID, q->qname.c);
return;
@@ -3415,7 +3546,7 @@ mDNSlocal void SendQueries(mDNS *const m)
// don't send it again until MaxQuestionInterval unless:
// one of its cached answers needs to be refreshed,
// or it's the initial query for a kDNSServiceFlagsThresholdFinder mode browse.
- if (q->BrowseThreshold
+ if (q->BrowseThreshold
&& (q->CurrentAnswers >= q->BrowseThreshold)
&& (q->CachedAnswerNeedsUpdate == mDNSfalse)
&& !((q->flags & kDNSServiceFlagsThresholdFinder) && (q->ThisQInterval == InitialQuestionInterval)))
@@ -3437,7 +3568,7 @@ mDNSlocal void SendQueries(mDNS *const m)
debugf("SendQueries: %##s (%s) next interval %d seconds RequestUnicast = %d",
q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval / InitialQuestionInterval, q->RequestUnicast);
- if (q->ThisQInterval >= QuestionIntervalThreshold)
+ if (q->ThisQInterval > MaxQuestionInterval)
{
q->ThisQInterval = MaxQuestionInterval;
}
@@ -3500,11 +3631,11 @@ mDNSlocal void SendQueries(mDNS *const m)
{
if (ar->AddressProxy.type == mDNSAddrType_IPv4)
{
- // There's a problem here. If a host is waking up, and we probe to see if it responds, then
- // it will see those ARP probes as signalling intent to use the address, so it picks a different one.
- // A more benign way to find out if a host is responding to ARPs might be send a standard ARP *request*
- // (using our sender IP address) instead of an ARP *probe* (using all-zero sender IP address).
- // A similar concern may apply to the NDP Probe too. -- SC
+ // There's a problem here. If a host is waking up, and we probe to see if it responds, then
+ // it will see those ARP probes as signalling intent to use the address, so it picks a different one.
+ // A more benign way to find out if a host is responding to ARPs might be send a standard ARP *request*
+ // (using our sender IP address) instead of an ARP *probe* (using all-zero sender IP address).
+ // A similar concern may apply to the NDP Probe too. -- SC
LogSPS("SendQueries ARP Probe %d %s %s", ar->ProbeCount, InterfaceNameForID(m, ar->resrec.InterfaceID), ARDisplayString(m,ar));
SendARP(m, 1, ar, &zerov4Addr, &zeroEthAddr, &ar->AddressProxy.ip.v4, &ar->WakeUp.IMAC);
}
@@ -3596,7 +3727,6 @@ mDNSlocal void SendQueries(mDNS *const m)
// If interface is P2P type, verify that query should be sent over it.
if (!mDNSPlatformValidQuestionForInterface(q, intf))
{
- LogInfo("SendQueries: Not sending (%s) %##s on %s", DNSTypeName(q->qtype), q->qname.c, InterfaceNameForID(m, intf->InterfaceID));
q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf);
}
// If we're suppressing this question, or we successfully put it, update its SendQNow state
@@ -3636,24 +3766,62 @@ mDNSlocal void SendQueries(mDNS *const m)
// Put probe questions in this packet
for (ar = m->ResourceRecords; ar; ar=ar->next)
- if (ar->SendRNow == intf->InterfaceID)
+ {
+ if (ar->SendRNow != intf->InterfaceID)
+ continue;
+
+ // If interface is a P2P variant, verify that the probe should be sent over it.
+ if (!mDNSPlatformValidRecordForInterface(ar, intf->InterfaceID))
+ {
+ ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
+ ar->IncludeInProbe = mDNSfalse;
+ }
+ else
{
mDNSBool ucast = (ar->ProbeCount >= DefaultProbeCountForTypeUnique-1) && m->CanReceiveUnicastOn5353 && intf->SupportsUnicastMDNSResponse;
mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
const mDNSu8 *const limit = m->omsg.data + (m->omsg.h.numQuestions ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData);
// We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
mDNSu32 forecast = answerforecast + 12 + ar->resrec.rdestimate;
- mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit - forecast, ar->resrec.name, kDNSQType_ANY, (mDNSu16)(ar->resrec.rrclass | ucbit));
- if (newptr)
+ mDNSBool putProbe = mDNStrue;
+ mDNSu16 qclass = ar->resrec.rrclass | ucbit;
+
+ {// Determine if this probe question is already in packet's dns message
+ const mDNSu8 *questionptr = m->omsg.data;
+ DNSQuestion question;
+ mDNSu16 n;
+ for (n = 0; n < m->omsg.h.numQuestions && questionptr; n++)
+ {
+ questionptr = getQuestion(&m->omsg, questionptr, limit, mDNSInterface_Any, &question);
+ if (questionptr && (question.qtype == kDNSQType_ANY) && (question.qclass == qclass) &&
+ (question.qnamehash == ar->resrec.namehash) && SameDomainName(&question.qname, ar->resrec.name))
+ {
+ putProbe = mDNSfalse; // set to false if already in message
+ break;
+ }
+ }
+ }
+
+ if (putProbe)
+ {
+ mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit - forecast, ar->resrec.name, kDNSQType_ANY, qclass);
+ if (newptr)
+ {
+ queryptr = newptr;
+ answerforecast = forecast;
+ ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
+ ar->IncludeInProbe = mDNStrue;
+ verbosedebugf("SendQueries: Put Question %##s (%s) probecount %d InterfaceID= %d %d %d",
+ ar->resrec.name->c, DNSTypeName(ar->resrec.rrtype), ar->ProbeCount, ar->resrec.InterfaceID, ar->resrec.rdestimate, answerforecast);
+ }
+ }
+ else
{
- queryptr = newptr;
- answerforecast = forecast;
ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
ar->IncludeInProbe = mDNStrue;
- verbosedebugf("SendQueries: Put Question %##s (%s) probecount %d",
- ar->resrec.name->c, DNSTypeName(ar->resrec.rrtype), ar->ProbeCount);
}
}
+ }
}
// Put our known answer list (either new one from this question or questions, or remainder of old one from last time)
@@ -3719,7 +3887,7 @@ mDNSlocal void SendQueries(mDNS *const m)
AuthRecord opt;
mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
opt.resrec.rrclass = NormalMaxDNSMessageData;
- opt.resrec.rdlength = sizeof(rdataOPT);
+ opt.resrec.rdlength = sizeof(rdataOPT);
opt.resrec.rdestimate = sizeof(rdataOPT);
if (OwnerRecordSpace && TraceRecordSpace)
{
@@ -3736,19 +3904,18 @@ mDNSlocal void SendQueries(mDNS *const m)
{
SetupTracerOpt(m, &opt.resrec.rdata->u.opt[0]);
}
- LogInfo("SendQueries putting %s %s: %s %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "", intf->ifname, ARDisplayString(m, &opt));
queryptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAdditionals,
&opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData);
if (!queryptr)
- {
+ {
LogMsg("SendQueries: How did we fail to have space for %s %s OPT record (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "",
m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
}
if (queryptr > m->omsg.data + NormalMaxDNSMessageData)
{
if (m->omsg.h.numQuestions != 1 || m->omsg.h.numAnswers != 0 || m->omsg.h.numAuthorities != 1 || m->omsg.h.numAdditionals != 1)
- LogMsg("SendQueries: Why did we generate oversized packet with %s %s OPT record %p %p %p (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "",
- TraceRecordSpace ? "TRACER" : "", m->omsg.data, m->omsg.data + NormalMaxDNSMessageData, queryptr, m->omsg.h.numQuestions, m->omsg.h.numAnswers,
+ LogMsg("SendQueries: Why did we generate oversized packet with %s %s OPT record %p %p %p (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "",
+ TraceRecordSpace ? "TRACER" : "", m->omsg.data, m->omsg.data + NormalMaxDNSMessageData, queryptr, m->omsg.h.numQuestions, m->omsg.h.numAnswers,
m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
}
}
@@ -3817,17 +3984,21 @@ mDNSlocal void SendQueries(mDNS *const m)
{
DNSQuestion *x;
for (x = m->NewQuestions; x; x=x->next) if (x == q) break; // Check if this question is a NewQuestion
- LogInfo("SendQueries: No active interface %d to send %s question: %d %##s (%s)",
- (uint32_t)q->SendQNow, x ? "new" : "old", (uint32_t)q->InterfaceID, q->qname.c, DNSTypeName(q->qtype));
+ // There will not be an active interface for questions applied to mDNSInterface_BLE
+ // so don't log the warning in that case.
+ if (q->InterfaceID != mDNSInterface_BLE)
+ LogInfo("SendQueries: No active interface %d to send %s question: %d %##s (%s)",
+ (uint32_t)q->SendQNow, x ? "new" : "old", (uint32_t)q->InterfaceID, q->qname.c, DNSTypeName(q->qtype));
q->SendQNow = mDNSNULL;
}
q->CachedAnswerNeedsUpdate = mDNSfalse;
}
}
-mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password)
+mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password, mDNSBool unicastOnly)
{
int i, j;
+
mDNSu8 *ptr = m->omsg.data;
NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
if (!intf) { LogMsg("SendARP: No interface with InterfaceID %p found", InterfaceID); return; }
@@ -3853,13 +4024,16 @@ mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAdd
mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID);
- // For Ethernet switches that don't flood-foward packets with unknown unicast destination MAC addresses,
- // broadcast is the only reliable way to get a wakeup packet to the intended target machine.
- // For 802.11 WPA networks, where a sleeping target machine may have missed a broadcast/multicast
- // key rotation, unicast is the only way to get a wakeup packet to the intended target machine.
- // So, we send one of each, unicast first, then broadcast second.
- for (i=0; i<6; i++) m->omsg.data[i] = 0xFF;
- mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID);
+ if (!unicastOnly)
+ {
+ // For Ethernet switches that don't flood-foward packets with unknown unicast destination MAC addresses,
+ // broadcast is the only reliable way to get a wakeup packet to the intended target machine.
+ // For 802.11 WPA networks, where a sleeping target machine may have missed a broadcast/multicast
+ // key rotation, unicast is the only way to get a wakeup packet to the intended target machine.
+ // So, we send one of each, unicast first, then broadcast second.
+ for (i=0; i<6; i++) m->omsg.data[i] = 0xFF;
+ mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID);
+ }
}
// ***************************************************************************
@@ -3891,7 +4065,7 @@ mDNSlocal void ResetQuestionState(mDNS *const m, DNSQuestion *q)
mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord)
{
DNSQuestion *const q = m->CurrentQuestion;
- mDNSBool followcname = FollowCNAME(q, &rr->resrec, AddRecord);
+ const mDNSBool followcname = FollowCNAME(q, &rr->resrec, AddRecord);
verbosedebugf("AnswerCurrentQuestionWithResourceRecord:%4lu %s TTL %d %s",
q->CurrentAnswers, AddRecord ? "Add" : "Rmv", rr->resrec.rroriginalttl, CRDisplayString(m, rr));
@@ -3937,28 +4111,32 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco
}
#if TARGET_OS_EMBEDDED
- if ((AddRecord == QC_add) && Question_uDNS(q) && (!q->metrics.answered || (q->metrics.querySendCount > 0)))
+ if ((AddRecord == QC_add) && Question_uDNS(q) && !followcname)
{
- uDNSMetrics * metrics;
const domainname * queryName;
mDNSu32 responseLatencyMs;
mDNSBool isForCellular;
- metrics = &q->metrics;
- queryName = metrics->originalQName ? metrics->originalQName : &q->qname;
- if (metrics->querySendCount > 0)
+ queryName = q->metrics.originalQName ? q->metrics.originalQName : &q->qname;
+ isForCellular = (q->qDNSServer && q->qDNSServer->cellIntf);
+ if (!q->metrics.answered)
{
- responseLatencyMs = ((m->timenow - metrics->firstQueryTime) * 1000) / mDNSPlatformOneSecond;
+ if (q->metrics.querySendCount > 0)
+ {
+ responseLatencyMs = ((m->timenow - q->metrics.firstQueryTime) * 1000) / mDNSPlatformOneSecond;
+ }
+ else
+ {
+ responseLatencyMs = 0;
+ }
+
+ MetricsUpdateUDNSQueryStats(queryName, q->qtype, &rr->resrec, q->metrics.querySendCount, responseLatencyMs, isForCellular);
+ q->metrics.answered = mDNStrue;
}
- else
+ if (q->metrics.querySendCount > 0)
{
- responseLatencyMs = 0;
+ MetricsUpdateUDNSResolveStats(queryName, &rr->resrec, isForCellular);
}
- isForCellular = (q->qDNSServer && q->qDNSServer->cellIntf);
-
- MetricsUpdateUDNSStats(queryName, mDNStrue, metrics->querySendCount, responseLatencyMs, isForCellular);
- metrics->answered = mDNStrue;
- metrics->querySendCount = 0;
}
#endif
// Note: Use caution here. In the case of records with rr->DelayDelivery set, AnswerCurrentQuestionWithResourceRecord(... mDNStrue)
@@ -3991,6 +4169,30 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco
if (rr->DelayDelivery) return; // We'll come back later when CacheRecordDeferredAdd() calls us
+#ifdef USE_LIBIDN
+ if (rr->resrec.RecordType == kDNSRecordTypePacketNegative) // If negative answer, check if we need to try Punycode conversion
+ {
+ domainname newname;
+ if (PerformNextPunycodeConversion(q, &newname)) // Itertative Punycode conversion succeeded, so reissue question with new name
+ {
+ UDPSocket *const sock = q->LocalSocket; // Save old socket and transaction ID
+ const mDNSOpaque16 id = q->TargetQID;
+ q->LocalSocket = mDNSNULL;
+ mDNS_StopQuery_internal(m, q); // Stop old query
+ AssignDomainName(&q->qname, &newname); // Update qname
+ q->qnamehash = DomainNameHashValue(&q->qname); // and namehash
+ mDNS_StartQuery_internal(m, q); // Start new query
+
+ if (sock) // Transplant saved socket, if appropriate
+ {
+ if (q->DuplicateOf) mDNSPlatformUDPClose(sock);
+ else { q->LocalSocket = sock; q->TargetQID = id; }
+ }
+ return; // All done for now; wait until we get the next answer
+ }
+ }
+#endif // USE_LIBIDN
+
// Only deliver negative answers if client has explicitly requested them except when we are forcing a negative response
// for the purpose of retrying search domains/timeout OR the question is suppressed
if (rr->resrec.RecordType == kDNSRecordTypePacketNegative || (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype)))
@@ -4041,7 +4243,7 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco
// If we get a CNAME back while we are validating the response (i.e., CNAME for DS, DNSKEY, RRSIG),
// don't follow them. If it is a ValidationRequired question, wait for the CNAME to be validated
// first before following it
- if (!ValidatingQuestion(q) && followcname && m->CurrentQuestion == q)
+ if ((m->CurrentQuestion == q) && followcname && !ValidatingQuestion(q))
AnswerQuestionByFollowingCNAME(m, q, &rr->resrec);
}
@@ -4082,7 +4284,7 @@ mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *c
// deliver a RMV (for the current old entry) followed by ADD (for the new entry).
// It needs to schedule the timer for the next cache expiry (ScheduleNextCacheCheckTime),
// so that the cache entry can be purged (purging causes the RMV followed by ADD)
- //
+ //
// 2) A new question is about to be answered and the caller needs to know whether it's
// scheduling should be delayed so that the question is not answered with this record.
// Instead of delivering an ADD (old entry) followed by RMV (old entry) and another ADD
@@ -4317,7 +4519,7 @@ mDNSlocal void ReleaseCacheGroup(mDNS *const m, CacheGroup **cp)
if ((*cp)->rrcache_tail != &(*cp)->members)
LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrcache_tail != &(*cp)->members)");
//if ((*cp)->name != (domainname*)((*cp)->namestorage))
- // LogMsg("ReleaseCacheGroup: %##s, %p %p", (*cp)->name->c, (*cp)->name, (domainname*)((*cp)->namestorage));
+ // LogMsg("ReleaseCacheGroup: %##s, %p %p", (*cp)->name->c, (*cp)->name, (domainname*)((*cp)->namestorage));
if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name);
(*cp)->name = mDNSNULL;
*cp = (*cp)->next; // Cut record from list
@@ -4364,7 +4566,7 @@ mDNSexport void ReleaseCacheRecord(mDNS *const m, CacheRecord *r)
r->resrec.rdata = mDNSNULL;
cg = CacheGroupForRecord(m, slot, &r->resrec);
-
+
if (!cg)
{
// It is okay to have this printed for NSEC/NSEC3s
@@ -4417,7 +4619,7 @@ mDNSlocal void CheckCacheExpiration(mDNS *const m, const mDNSu32 slot, CacheGrou
if (m->timenow - event >= 0) // If expired, delete it
{
*rp = rr->next; // Cut it from the list
-
+
verbosedebugf("CheckCacheExpiration: Deleting%7d %7d %p %s",
m->timenow - rr->TimeRcvd, rr->resrec.rroriginalttl, rr->CRActiveQuestion, CRDisplayString(m, rr));
if (rr->CRActiveQuestion) // If this record has one or more active questions, tell them it's going away
@@ -4509,7 +4711,7 @@ mDNSlocal mDNSBool AnswerQuestionWithLORecord(mDNS *const m, DNSQuestion *q, mDN
// details on how we handle this case. For P2P we just handle "Interface_Any" questions. For LocalOnly
// we handle both mDNSInterface_Any and scoped questions.
- if (rr->ARType == AuthRecordLocalOnly || (rr->ARType == AuthRecordP2P && q->InterfaceID == mDNSInterface_Any))
+ if (rr->ARType == AuthRecordLocalOnly || (rr->ARType == AuthRecordP2P && (q->InterfaceID == mDNSInterface_Any || q->InterfaceID == mDNSInterface_BLE)))
if (LocalOnlyRecordAnswersQuestion(rr, q))
{
if (checkOnly)
@@ -4577,7 +4779,7 @@ mDNSlocal void AnswerSuppressedQuestion(mDNS *const m, DNSQuestion *q)
q->SuppressQuery = mDNSfalse;
q->DisallowPID = mDNSfalse;
- GenerateNegativeResponse(m, QC_suppressed);
+ GenerateNegativeResponse(m, mDNSInterface_Any, QC_suppressed);
q->SuppressQuery = SuppressQuery;
q->DisallowPID = DisallowPID;
@@ -4682,7 +4884,7 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m)
AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add);
if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here
}
- else if (RRTypeIsAddressType(rr->resrec.rrtype) && RRTypeIsAddressType(q->qtype))
+ else if (mDNSOpaque16IsZero(q->TargetQID) && RRTypeIsAddressType(rr->resrec.rrtype) && RRTypeIsAddressType(q->qtype))
ShouldQueryImmediately = mDNSfalse;
}
// We don't use LogInfo for this "Question deleted" message because it happens so routinely that
@@ -4696,7 +4898,7 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m)
if (!QuerySuppressed(q) && !AnsweredFromCache && q->RetryWithSearchDomains)
{
LogInfo("AnswerNewQuestion: Generating response for retrying with search domains %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
- GenerateNegativeResponse(m, QC_forceresponse);
+ GenerateNegativeResponse(m, mDNSInterface_Any, QC_forceresponse);
}
if (m->CurrentQuestion != q) { debugf("AnswerNewQuestion: Question deleted while giving negative answer"); goto exit; }
@@ -4737,6 +4939,7 @@ mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m)
AuthGroup *ag;
DNSQuestion *q = m->NewLocalOnlyQuestions; // Grab the question we're going to answer
m->NewLocalOnlyQuestions = q->next; // Advance NewLocalOnlyQuestions to the next (if any)
+ mDNSBool retEv = mDNSfalse;
debugf("AnswerNewLocalOnlyQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
@@ -4762,6 +4965,7 @@ mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m)
m->CurrentRecord = rr->next;
if (LocalOnlyRecordAnswersQuestion(rr, q))
{
+ retEv = mDNStrue;
AnswerLocalQuestionWithLocalAuthRecord(m, rr, mDNStrue);
if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here
}
@@ -4778,12 +4982,18 @@ mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m)
m->CurrentRecord = rr->next;
if (ResourceRecordAnswersQuestion(&rr->resrec, q))
{
+ retEv = mDNStrue;
AnswerLocalQuestionWithLocalAuthRecord(m, rr, mDNStrue);
if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here
}
}
}
+ // The local host is the authoritative source for LocalOnly questions
+ // so if no records exist and client requested intermediates, then generate a negative response
+ if (!retEv && (m->CurrentQuestion == q) && q->ReturnIntermed)
+ GenerateNegativeResponse(m, mDNSInterface_LocalOnly, QC_forceresponse);
+
m->CurrentQuestion = mDNSNULL;
m->CurrentRecord = mDNSNULL;
}
@@ -4898,7 +5108,7 @@ mDNSlocal CacheGroup *GetCacheGroup(mDNS *const m, const mDNSu32 slot, const Res
cg->namehash = rr->namehash;
cg->members = mDNSNULL;
cg->rrcache_tail = &cg->members;
- if (namelen > sizeof(cg->namestorage))
+ if (namelen > sizeof(cg->namestorage))
cg->name = mDNSPlatformMemAllocate(namelen);
else
cg->name = (domainname*)cg->namestorage;
@@ -5029,7 +5239,7 @@ mDNSlocal void TimeoutQuestions(mDNS *const m)
if (m->timenow - q->StopTime >= 0)
{
LogInfo("TimeoutQuestions: question %p %##s timed out, time %d", q, q->qname.c, m->timenow - q->StopTime);
- GenerateNegativeResponse(m, QC_forceresponse);
+ GenerateNegativeResponse(m, mDNSInterface_Any, QC_forceresponse);
if (m->CurrentQuestion == q) q->StopTime = 0;
}
else
@@ -5135,10 +5345,26 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
mDNS_SendKeepalives(m);
}
+#if BONJOUR_ON_DEMAND
+ if (m->NextBonjourDisableTime && (m->timenow - m->NextBonjourDisableTime >= 0))
+ {
+ // Schedule immediate network change processing to leave the multicast group
+ // since the delay time has expired since the previous active registration or query.
+ m->NetworkChanged = m->timenow;
+ m->NextBonjourDisableTime = 0;
+ m->BonjourEnabled = 0;
+
+ LogInfo("mDNS_Execute: Scheduled network changed processing to leave multicast group.");
+ }
+#endif // BONJOUR_ON_DEMAND
+
// Clear AnnounceOwner if necessary. (Do this *before* SendQueries() and SendResponses().)
if (m->AnnounceOwner && m->timenow - m->AnnounceOwner >= 0)
{
m->AnnounceOwner = 0;
+
+ // This is a good time to reset the delay counter used to prevent spurious conflicts
+ m->DelayConflictProcessing = 0;
}
if (m->DelaySleep && m->timenow - m->DelaySleep >= 0)
@@ -5305,6 +5531,10 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
if (m->timenow - m->NextScheduledNATOp >= 0) CheckNATMappings(m);
if (m->timenow - m->NextuDNSEvent >= 0) uDNS_Tasks(m);
#endif
+#if APPLE_OSX_mDNSResponder
+ extern void serviceBLE();
+ if (m->NextBLEServiceTime && (m->timenow - m->NextBLEServiceTime >= 0)) serviceBLE();
+#endif // APPLE_OSX_mDNSResponder
}
// Note about multi-threaded systems:
@@ -5550,11 +5780,7 @@ mDNSexport void mDNSCoreRestartQuestion(mDNS *const m, DNSQuestion *q)
if (mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q))
{
q->ThisQInterval = InitialQuestionInterval; // MUST be > zero for an active question
-#if mDNS_REQUEST_UNICAST_RESPONSE
- q->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES;
-#else // mDNS_REQUEST_UNICAST_RESPONSE
- q->RequestUnicast = SET_QU_IN_FIRST_QUERY;
-#endif // mDNS_REQUEST_UNICAST_RESPONSE
+ q->RequestUnicast = kDefaultRequestUnicastCount;
q->LastQTime = m->timenow - q->ThisQInterval;
q->RecentAnswerPkts = 0;
ExpireDupSuppressInfo(q->DupSuppress, m->timenow);
@@ -5563,23 +5789,26 @@ mDNSexport void mDNSCoreRestartQuestion(mDNS *const m, DNSQuestion *q)
}
// restart the probe/announce cycle for multicast record
-mDNSexport void mDNSCoreRestartRegistration(mDNS *const m, AuthRecord *rr, int announceCount)
+mDNSexport void mDNSCoreRestartRegistration(mDNS *const m, AuthRecord *rr, int announceCount)
{
if (!AuthRecord_uDNS(rr))
{
if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
rr->ProbeCount = DefaultProbeCountForRecordType(rr->resrec.RecordType);
- // announceCount < 0 indicates default announce count should be used
- if (announceCount < 0)
- announceCount = InitialAnnounceCount;
- if (rr->AnnounceCount < announceCount)
- rr->AnnounceCount = announceCount;
-
if (mDNS_KeepaliveRecord(&rr->resrec))
- rr->AnnounceCount = 0; // Do not announce keepalive records
+ {
+ rr->AnnounceCount = 0; // Do not announce keepalive records
+ }
else
- rr->AnnounceCount = InitialAnnounceCount;
+ {
+ // announceCount < 0 indicates default announce count should be used
+ if (announceCount < 0)
+ announceCount = InitialAnnounceCount;
+ if (rr->AnnounceCount < (mDNSu8)announceCount)
+ rr->AnnounceCount = (mDNSu8)announceCount;
+ }
+
rr->SendNSECNow = mDNSNULL;
InitializeLastAPTime(m, rr);
}
@@ -5672,7 +5901,7 @@ mDNSlocal mDNSBool mDNSUpdateOkToSend(mDNS *const m, AuthRecord *rr, NetworkInte
// If it is not a uDNS record, check to see if the updateid is zero. "updateid" is cleared when we have
// sent the resource record on all the interfaces. If the update id is not zero, check to see if it is time
// to send.
- if (AuthRecord_uDNS(rr) || (rr->AuthFlags & AuthFlagsWakeOnly) || mDNSOpaque16IsZero(rr->updateid) ||
+ if (AuthRecord_uDNS(rr) || (rr->AuthFlags & AuthFlagsWakeOnly) || mDNSOpaque16IsZero(rr->updateid) ||
m->timenow - (rr->LastAPTime + rr->ThisAPInterval) < 0)
{
return mDNSfalse;
@@ -5693,53 +5922,56 @@ mDNSlocal mDNSBool mDNSUpdateOkToSend(mDNS *const m, AuthRecord *rr, NetworkInte
return mDNSfalse;
}
-mDNSexport void UpdateRMACCallback(mDNS *const m, void *context)
-{
- IPAddressMACMapping *addrmap = (IPAddressMACMapping *)context ;
- m->CurrentRecord = m->ResourceRecords;
-
- if (!addrmap)
- {
- LogMsg("UpdateRMACCallback: Address mapping is NULL");
- return;
- }
-
- while (m->CurrentRecord)
- {
- AuthRecord *rr = m->CurrentRecord;
- // If this is a non-sleep proxy keepalive record and the remote IP address matches, update the RData
- if (!rr->WakeUp.HMAC.l[0] && mDNS_KeepaliveRecord(&rr->resrec))
- {
- mDNSAddr raddr;
- getKeepaliveRaddr(m, rr, &raddr);
- if (mDNSSameAddress(&raddr, &addrmap->ipaddr))
- {
- // Update the MAC address only if it is not a zero MAC address
- mDNSEthAddr macAddr;
- mDNSu8 *ptr = GetValueForMACAddr((mDNSu8 *)(addrmap->ethaddr), (mDNSu8 *) (addrmap->ethaddr + sizeof(addrmap->ethaddr)), &macAddr);
- if (ptr != mDNSNULL && !mDNSEthAddressIsZero(macAddr))
- {
- UpdateKeepaliveRData(m, rr, mDNSNULL, mDNStrue, (char *)(addrmap->ethaddr));
- }
- }
- }
- m->CurrentRecord = rr->next;
- }
-
- if (addrmap)
- {
- mDNSPlatformMemFree(addrmap);
- }
+mDNSexport void UpdateRMAC(mDNS *const m, void *context)
+{
+ IPAddressMACMapping *addrmap = (IPAddressMACMapping *)context ;
+ m->CurrentRecord = m->ResourceRecords;
+
+ if (!addrmap)
+ {
+ LogMsg("UpdateRMAC: Address mapping is NULL");
+ return;
+ }
+
+ while (m->CurrentRecord)
+ {
+ AuthRecord *rr = m->CurrentRecord;
+ // If this is a non-sleep proxy keepalive record and the remote IP address matches, update the RData
+ if (!rr->WakeUp.HMAC.l[0] && mDNS_KeepaliveRecord(&rr->resrec))
+ {
+ mDNSAddr raddr;
+ getKeepaliveRaddr(m, rr, &raddr);
+ if (mDNSSameAddress(&raddr, &addrmap->ipaddr))
+ {
+ // Update the MAC address only if it is not a zero MAC address
+ mDNSEthAddr macAddr;
+ mDNSu8 *ptr = GetValueForMACAddr((mDNSu8 *)(addrmap->ethaddr), (mDNSu8 *) (addrmap->ethaddr + sizeof(addrmap->ethaddr)), &macAddr);
+ if (ptr != mDNSNULL && !mDNSEthAddressIsZero(macAddr))
+ {
+ UpdateKeepaliveRData(m, rr, mDNSNULL, mDNStrue, (char *)(addrmap->ethaddr));
+ }
+ }
+ }
+ m->CurrentRecord = rr->next;
+ }
+
+ if (addrmap)
+ mDNSPlatformMemFree(addrmap);
+
}
mDNSexport mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSBool updateMac, char *ethAddr)
{
mDNSu16 newrdlength;
- mDNSAddr laddr, raddr;
- mDNSEthAddr eth;
- mDNSIPPort lport, rport;
- mDNSu32 timeout, seq, ack;
- mDNSu16 win;
+ mDNSAddr laddr = zeroAddr;
+ mDNSAddr raddr = zeroAddr;
+ mDNSEthAddr eth = zeroEthAddr;
+ mDNSIPPort lport = zeroIPPort;
+ mDNSIPPort rport = zeroIPPort;
+ mDNSu32 timeout = 0;
+ mDNSu32 seq = 0;
+ mDNSu32 ack = 0;
+ mDNSu16 win = 0;
UTF8str255 txt;
int rdsize;
RData *newrd;
@@ -5749,8 +5981,7 @@ mDNSexport mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkIn
// Note: If we fail to update the DNS NULL record with additional information in this function, it will be registered
// with the SPS like any other record. SPS will not send keepalives if it does not have additional information.
mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, &raddr, &eth, &seq, &ack, &lport, &rport, &win);
- if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(&raddr) || mDNSIPPortIsZero(lport) ||
- mDNSIPPortIsZero(rport))
+ if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(&raddr) || mDNSIPPortIsZero(lport) || mDNSIPPortIsZero(rport))
{
LogMsg("UpdateKeepaliveRData: not a valid record %s for keepalive %#a:%d %#a:%d", ARDisplayString(m, rr), &laddr, lport.NotAnInteger, &raddr, rport.NotAnInteger);
return mStatus_UnknownErr;
@@ -5813,8 +6044,8 @@ mDNSexport mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkIn
// free that memory here before copying in the new data.
if ( rr->resrec.rdata != &rr->rdatastorage)
{
- mDNSPlatformMemFree(rr->resrec.rdata);
LogSPS("UpdateKeepaliveRData: Freed allocated memory for keep alive packet: %s ", ARDisplayString(m, rr));
+ mDNSPlatformMemFree(rr->resrec.rdata);
}
SetNewRData(&rr->resrec, newrd, newrdlength); // Update our rdata
@@ -5954,7 +6185,7 @@ mDNSlocal void SendSPSRegistrationForOwner(mDNS *const m, NetworkInterfaceInfo *
LogSPS("SendSPSRegistration: Sending Update %s %d (%d) id %5d with %d records %d bytes to %#a:%d", intf->ifname, intf->NextSPSAttempt, sps,
mDNSVal16(m->omsg.h.id), m->omsg.h.mDNS_numUpdates, p - m->omsg.data, &intf->SPSAddr[sps], mDNSVal16(intf->SPSPort[sps]));
- // if (intf->NextSPSAttempt < 5) m->omsg.h.flags = zeroID; // For simulating packet loss
+ // if (intf->NextSPSAttempt < 5) m->omsg.h.flags = zeroID; // For simulating packet loss
err = mDNSSendDNSMessage(m, &m->omsg, p, intf->InterfaceID, mDNSNULL, &intf->SPSAddr[sps], intf->SPSPort[sps], mDNSNULL, mDNSNULL, mDNSfalse);
if (err) LogSPS("SendSPSRegistration: mDNSSendDNSMessage err %d", err);
if (err && intf->SPSAddr[sps].type == mDNSAddrType_IPv4 && intf->NetWakeResolve[sps].ThisQInterval == -1)
@@ -6027,7 +6258,7 @@ mDNSlocal void SPSInitRecordsBeforeUpdate(mDNS *const m, mDNSOpaque64 updateIntI
{
AuthRecord *ar;
LogSPS("SPSInitRecordsBeforeUpdate: UpdateIntID 0x%x 0x%x", updateIntID.l[1], updateIntID.l[0]);
-
+
*WakeOnlyService = mDNSfalse;
// Before we store the A and AAAA records that we are going to register with the sleep proxy,
@@ -6144,7 +6375,7 @@ mDNSlocal void NetWakeResolve(mDNS *const m, DNSQuestion *question, const Resour
if (!AddRecord) return; // Don't care about REMOVE events
if (answer->rrtype != question->qtype) return; // Don't care about CNAMEs
- // if (answer->rrtype == kDNSType_AAAA && sps == 0) return; // To test failing to resolve sleep proxy's address
+ // if (answer->rrtype == kDNSType_AAAA && sps == 0) return; // To test failing to resolve sleep proxy's address
if (answer->rrtype == kDNSType_SRV)
{
@@ -6230,14 +6461,8 @@ mDNSlocal void SendGoodbyesForWakeOnlyService(mDNS *const m, mDNSBool *WakeOnlyS
{
return SendGoodbyesForSelectServices(m, WakeOnlyService, WAKE_ONLY_SERVICE);
}
-#endif // APPLE_OSx_mDNSResponder
+#endif // APPLE_OSX_mDNSResponder
-#ifdef APPLE_OSX_mDNSResponder
-mDNSlocal void SendGoodbyesForACOnlyServices(mDNS *const m, mDNSBool *acOnlyService)
-{
- return SendGoodbyesForSelectServices(m, acOnlyService, AC_ONLY_SERVICE);
-}
-#endif
mDNSlocal void SendSleepGoodbyes(mDNS *const m, mDNSBool AllInterfaces, mDNSBool unicast)
{
@@ -6334,11 +6559,10 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m)
{
mDNSBool SendGoodbyes = mDNStrue;
mDNSBool WakeOnlyService = mDNSfalse;
- mDNSBool ACOnlyService = mDNSfalse;
mDNSBool invokeKACallback = mDNStrue;
const CacheRecord *sps[3] = { mDNSNULL };
mDNSOpaque64 updateIntID = zeroOpaque64;
- mDNSInterfaceID registeredIntfIDS[128];
+ mDNSInterfaceID registeredIntfIDS[128] = { 0 };
mDNSu32 registeredCount = 0;
int skippedRegistrations = 0;
@@ -6351,7 +6575,7 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m)
NetworkInterfaceInfo *intf;
// Clear out the SCDynamic entry that stores the external SPS information
- mDNSPlatformClearSPSMACAddr();
+ mDNSPlatformClearSPSData();
for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
{
@@ -6395,10 +6619,10 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m)
if (ActivateLocalProxy(m, intf, &keepaliveOnly) == mStatus_NoError)
{
SendGoodbyesForWakeOnlyService(m, &WakeOnlyService);
- if (keepaliveOnly)
- SendGoodbyesForACOnlyServices(m, &ACOnlyService);
- SendGoodbyes = mDNSfalse;
- invokeKACallback = mDNSfalse;
+
+ // Send goodbyes for all advertised services if the only record offloaded was the keepalive record.
+ SendGoodbyes = (keepaliveOnly) ? mDNStrue: mDNSfalse;
+ invokeKACallback = mDNSfalse;
LogSPS("BeginSleepProcessing: %-6s using local proxy", intf->ifname);
// This will leave m->SleepState set to SleepState_Transferring,
// which is okay because with no outstanding resolves, or updates in flight,
@@ -6482,7 +6706,7 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m)
//
// - If there are no sleep proxy servers, then send goodbyes on all interfaces
// for both multicast and unicast.
- //
+ //
// - If we skipped registrations on some interfaces, then we have already marked
// them appropriately above. We don't need to send goodbyes for unicast as
// we have registered with at least one sleep proxy.
@@ -6502,10 +6726,10 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m)
LogSPS("BeginSleepProcessing: Not registering with Sleep Proxy Server on all interfaces");
SendSleepGoodbyes(m, mDNSfalse, mDNSfalse);
}
- else if (WakeOnlyService || ACOnlyService)
+ else if (WakeOnlyService)
{
// If we saw WakeOnly service above, send the goodbyes now.
- LogSPS("BeginSleepProcessing: Sending goodbyes for %s", WakeOnlyService? "WakeOnlyService" : "AC Only Service");
+ LogSPS("BeginSleepProcessing: Sending goodbyes for WakeOnlyService");
SendResponses(m);
}
}
@@ -6531,7 +6755,7 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep)
#ifndef SPC_DISABLED
if (oldstate == 1) mDNS_DeregisterService(m, &m->SPSRecords);
#else
- (void)oldstate;
+ (void)oldstate;
#endif
mDNS_ReclaimLockAfterCallback();
}
@@ -6579,7 +6803,11 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep)
{
m->SleepState = SleepState_Awake;
m->SleepSeqNum++;
- m->DelaySleep = 0;
+ // If the machine wakes and then immediately tries to sleep again (e.g. a maintenance wake)
+ // then we enforce a minimum delay of five seconds before we begin sleep processing.
+ // This is to allow time for the Ethernet link to come up, DHCP to get an address, mDNS to issue queries, etc.,
+ // before we make our determination of whether there's a Sleep Proxy out there we should register with.
+ m->DelaySleep = NonZeroTime(m->timenow + kDarkWakeDelaySleep);
}
if (m->SPSState == 3)
@@ -6588,7 +6816,7 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep)
mDNSCoreBeSleepProxyServer_internal(m, m->SPSType, m->SPSPortability, m->SPSMarginalPower, m->SPSTotalPower, m->SPSFeatureFlags);
}
m->mDNSStats.Wakes++;
-
+ m->DelayConflictProcessing = MAX_CONFLICT_PROCESSING_DELAYS;
// ... and the same for NextSPSAttempt
for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) intf->NextSPSAttempt = -1;
@@ -6629,7 +6857,7 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep)
mDNSu32 uTTL = RRUnadjustedTTL(cr->resrec.rroriginalttl);
const mDNSs32 remain = uTTL - (m->timenow - cr->TimeRcvd) / mDNSPlatformOneSecond;
- // -if we have slept longer than the remaining TTL, purge and start fresh.
+ // -if we have slept longer than the remaining TTL, purge and start fresh.
// -if we have been sleeping for a long time, we could reduce TimeRcvd below by
// a sufficiently big value which could cause the value to go into the future
// because of the signed comparison of time. For this to happen, we should have been
@@ -7113,7 +7341,7 @@ mDNSlocal void DeregisterProxyRecord(mDNS *const m, AuthRecord *const rr)
mDNSlocal void ClearKeepaliveProxyRecords(mDNS *const m, const OwnerOptData *const owner, AuthRecord *const thelist, const mDNSInterfaceID InterfaceID)
{
if (m->CurrentRecord)
- LogMsg("ClearIdenticalProxyRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
+ LogMsg("ClearKeepaliveProxyRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
m->CurrentRecord = thelist;
// Normally, the RDATA of the keepalive record will be different each time and hence we always
@@ -7247,9 +7475,9 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
}
- //
+ //
// Look in Authority Section for NSEC3 record
- //
+ //
mDNSParseNSEC3Records(m, query, end, InterfaceID, &McastNSEC3Records);
@@ -7583,7 +7811,6 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
{
SendLegacyResponse = mDNStrue;
}
-
if (SendMulticastResponse || SendUnicastResponse)
{
@@ -7690,15 +7917,17 @@ exit:
// For non-truncated queries, we can definitively say that we should expect
// to be seeing a response for any records still left in the ExpectedAnswers list
if (!(query->h.flags.b[0] & kDNSFlag0_TC))
- if (cr->UnansweredQueries == 0 || m->timenow - cr->LastUnansweredTime >= mDNSPlatformOneSecond)
+ if (cr->UnansweredQueries == 0 || m->timenow - cr->LastUnansweredTime >= mDNSPlatformOneSecond * 3/4)
{
cr->UnansweredQueries++;
cr->LastUnansweredTime = m->timenow;
-#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
if (cr->UnansweredQueries > 1)
- debugf("ProcessQuery: (!TC) UAQ %lu MPQ %lu MPKA %lu %s",
+ #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
+ debugf("ProcessQuery: (!TC) UAQ %lu MPQ %lu MPKA %lu %s",
cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
-#endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING
+ #else
+ debugf("ProcessQuery: UnansweredQueries %lu %s", cr->UnansweredQueries, CRDisplayString(m, cr));
+ #endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING
SetNextCacheCheckTimeForRecord(m, cr);
}
@@ -7706,12 +7935,16 @@ exit:
// then mark it to expire in five seconds if we don't get a response by then.
if (cr->UnansweredQueries >= MaxUnansweredQueries)
{
-#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
// Only show debugging message if this record was not about to expire anyway
- if (RRExpireTime(cr) - m->timenow > 4 * mDNSPlatformOneSecond)
- debugf("ProcessQuery: (Max) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
+ if (RRExpireTime(cr) - m->timenow > (mDNSs32) kDefaultReconfirmTimeForNoAnswer * 4 / 3 + mDNSPlatformOneSecond)
+ #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
+ debugf("ProcessQuery: (Max) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
-#endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING
+ #else
+ LogInfo("ProcessQuery: UnansweredQueries %lu TTL %lu mDNS_Reconfirm() for %s",
+ cr->UnansweredQueries, (RRExpireTime(cr) - m->timenow + mDNSPlatformOneSecond-1) / mDNSPlatformOneSecond, CRDisplayString(m, cr));
+ #endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING
+
m->mDNSStats.PoofCacheDeletions++;
mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
}
@@ -7777,15 +8010,16 @@ mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg,
mDNSBool QueryWasLocalUnicast = srcaddr && dstaddr &&
!mDNSAddrIsDNSMulticast(dstaddr) && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr);
- if (!InterfaceID && dstaddr && mDNSAddrIsDNSMulticast(dstaddr))
+ if (!dstaddr || (!InterfaceID && mDNSAddrIsDNSMulticast(dstaddr)))
{
+ const char *const reason = !dstaddr ? "Received over TCP connection" : "Multicast, but no InterfaceID";
LogMsg("Ignoring Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with "
- "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes (Multicast, but no InterfaceID)",
+ "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes (%s)",
srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), InterfaceID,
msg->h.numQuestions, msg->h.numQuestions == 1 ? ", " : "s,",
msg->h.numAnswers, msg->h.numAnswers == 1 ? ", " : "s,",
msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y, " : "ies,",
- msg->h.numAdditionals, msg->h.numAdditionals == 1 ? " " : "s", end - msg->data);
+ msg->h.numAdditionals, msg->h.numAdditionals == 1 ? " " : "s", end - msg->data, reason);
return;
}
@@ -7875,9 +8109,9 @@ mDNSlocal DNSQuestion *ExpectingUnicastResponseForRecord(mDNS *const m,
}
if (mDNSSameIPPort(srcp, port)) return(q);
- // if (mDNSSameAddress(srcaddr, &q->Target)) return(mDNStrue);
- // if (q->LongLived && mDNSSameAddress(srcaddr, &q->servAddr)) return(mDNStrue); Shouldn't need this now that we have LLQType checking
- // if (TrustedSource(m, srcaddr)) return(mDNStrue);
+ // if (mDNSSameAddress(srcaddr, &q->Target)) return(mDNStrue);
+ // if (q->LongLived && mDNSSameAddress(srcaddr, &q->servAddr)) return(mDNStrue); Shouldn't need this now that we have LLQType checking
+ // if (TrustedSource(m, srcaddr)) return(mDNStrue);
LogInfo("WARNING: Ignoring suspect uDNS response for %##s (%s) [q->Target %#a:%d] from %#a:%d %s",
q->qname.c, DNSTypeName(q->qtype), &q->Target, mDNSVal16(srcp), srcaddr, mDNSVal16(port), CRDisplayString(m, rr));
return(mDNSNULL);
@@ -7915,7 +8149,7 @@ mDNSexport CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, C
if (!m->rec.r.resrec.InterfaceID) debugf("CreateNewCacheEntry %s", CRDisplayString(m, &m->rec.r));
//if (RDLength > InlineCacheRDSize)
- // LogInfo("Rdata len %4d > InlineCacheRDSize %d %s", RDLength, InlineCacheRDSize, CRDisplayString(m, &m->rec.r));
+ // LogInfo("Rdata len %4d > InlineCacheRDSize %d %s", RDLength, InlineCacheRDSize, CRDisplayString(m, &m->rec.r));
if (!cg) cg = GetCacheGroup(m, slot, &m->rec.r.resrec); // If we don't have a CacheGroup for this name, make one now
if (cg) rr = GetCacheRecord(m, cg, RDLength); // Make a cache record, being careful not to recycle cg
@@ -8254,7 +8488,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage *
// the application
if (qptr->ProxyQuestion)
qptr->responseFlags = response->h.flags;
- GenerateNegativeResponse(m, QC_forceresponse);
+ GenerateNegativeResponse(m, mDNSInterface_Any, QC_forceresponse);
m->CurrentQuestion = mDNSNULL;
}
else
@@ -8438,7 +8672,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage *
name = (const domainname *)(name->c + 1 + name->c[0]);
hash = DomainNameHashValue(name);
slot = HashSlot(name);
- // For now, we don't need to update cg here, because we'll do it again immediately, back up at the start of this loop
+ // For now, we don't need to update cg here, because we'll do it again immediately, back up at the start of this loop
//cg = CacheGroupForName(m, slot, hash, name);
}
}
@@ -8614,7 +8848,6 @@ mDNSlocal CacheRecord* mDNSCoreReceiveCacheCheck(mDNS *const m, const DNSMessage
}
else
{
-
// If the packet TTL is zero, that means we're deleting this record.
// To give other hosts on the network a chance to protest, we push the deletion
// out one second into the future. Also, we set UnansweredQueries to MaxUnansweredQueries.
@@ -8685,7 +8918,7 @@ mDNSlocal void mDNSCoreResetRecord(mDNS *const m)
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
if (m->rec.r.resrec.AnonInfo)
{
- FreeAnonInfo(m->rec.r.resrec.AnonInfo);
+ FreeAnonInfo(m->rec.r.resrec.AnonInfo);
m->rec.r.resrec.AnonInfo = mDNSNULL;
}
}
@@ -8722,6 +8955,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
mDNSBool rrsigsCreated = mDNSfalse;
mDNSBool DNSSECQuestion = mDNSfalse;
NetworkInterfaceInfo *llintf = FirstIPv4LLInterfaceForID(m, InterfaceID);
+ mDNSBool recordAcceptedInResponse = mDNSfalse; // Set if a record is accepted from a unicast mDNS response that answers an existing question.
// All records in a DNS response packet are treated as equally valid statements of truth. If we want
// to guard against spoof responses, then the only credible protection against that is cryptographic
@@ -8832,14 +9066,14 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
// and hence retransmit without the EDNS0/DOK option.
if (DNSSECOptionalQuestion(qptr) && qptr->qDNSServer && !qptr->qDNSServer->DNSSECAware)
{
- LogInfo("mDNSCoreReceiveResponse: Server %p responded with code %d to DNSSEC Query %##s (%s), clear DO flag",
+ LogInfo("mDNSCoreReceiveResponse: Server %p responded with code %d to DNSSEC Query %##s (%s), clear DO flag",
qptr->qDNSServer, rcode, q.qname.c, DNSTypeName(q.qtype));
- qptr->qDNSServer->req_DO = mDNSfalse;
+ qptr->qDNSServer->req_DO = mDNSfalse;
}
// For Unicast DNS Queries, penalize the DNSServer
else
{
- LogInfo("mDNSCoreReceiveResponse: Server %p responded with code %d to query %##s (%s)",
+ LogInfo("mDNSCoreReceiveResponse: Server %p responded with code %d to query %##s (%s)",
qptr->qDNSServer, rcode, q.qname.c, DNSTypeName(q.qtype));
PenalizeDNSServer(m, qptr, response->h.flags);
}
@@ -8874,7 +9108,9 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
{
// All responses sent via LL multicast are acceptable for caching
// All responses received over our outbound TCP connections are acceptable for caching
- mDNSBool AcceptableResponse = ResponseMCast || !dstaddr || LLQType;
+ // We accept all records in a unicast response to a multicast query once we find one that
+ // answers an active question.
+ mDNSBool AcceptableResponse = ResponseMCast || !dstaddr || LLQType || recordAcceptedInResponse;
// (Note that just because we are willing to cache something, that doesn't necessarily make it a trustworthy answer
// to any specific question -- any code reading records from the cache needs to make that determination for itself.)
@@ -8961,38 +9197,42 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
// Even though it is AcceptableResponse, we still need a DNSServer pointer for the resource records that
// we create.
- DNSQuestion *q = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, dstport, response->h.id, &m->rec.r, !dstaddr);
-
- // Initialize the DNS server on the resource record which will now filter what questions we answer with
- // this record.
- //
- // We could potentially lookup the DNS server based on the source address, but that may not work always
- // and that's why ExpectingUnicastResponseForRecord does not try to verify whether the response came
- // from the DNS server that queried. We follow the same logic here. If we can find a matching quetion based
- // on the "id" and "source port", then this response answers the question and assume the response
- // came from the same DNS server that we sent the query to.
-
- if (q != mDNSNULL)
- {
- AcceptableResponse = mDNStrue;
- if (!InterfaceID)
- {
- debugf("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype));
- m->rec.r.resrec.rDNSServer = uDNSServer = q->qDNSServer;
- }
- else
- LogInfo("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype));
- }
- else
- {
- // If we can't find a matching question, we need to see whether we have seen records earlier that matched
- // the question. The code below does that. So, make this record unacceptable for now
- if (!InterfaceID)
- {
- debugf("mDNSCoreReceiveResponse: Can't find question for record name %##s", m->rec.r.resrec.name->c);
- AcceptableResponse = mDNSfalse;
- }
- }
+ DNSQuestion *q = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, dstport, response->h.id, &m->rec.r, !dstaddr);
+
+ // Initialize the DNS server on the resource record which will now filter what questions we answer with
+ // this record.
+ //
+ // We could potentially lookup the DNS server based on the source address, but that may not work always
+ // and that's why ExpectingUnicastResponseForRecord does not try to verify whether the response came
+ // from the DNS server that queried. We follow the same logic here. If we can find a matching quetion based
+ // on the "id" and "source port", then this response answers the question and assume the response
+ // came from the same DNS server that we sent the query to.
+
+ if (q != mDNSNULL)
+ {
+ AcceptableResponse = mDNStrue;
+ if (!InterfaceID)
+ {
+ debugf("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype));
+ m->rec.r.resrec.rDNSServer = uDNSServer = q->qDNSServer;
+ }
+ else
+ {
+ // Accept all remaining records in this unicast response to an mDNS query.
+ recordAcceptedInResponse = mDNStrue;
+ LogInfo("mDNSCoreReceiveResponse: Accepting response for query: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+ }
+ }
+ else
+ {
+ // If we can't find a matching question, we need to see whether we have seen records earlier that matched
+ // the question. The code below does that. So, make this record unacceptable for now
+ if (!InterfaceID)
+ {
+ debugf("mDNSCoreReceiveResponse: Can't find question for record name %##s", m->rec.r.resrec.name->c);
+ AcceptableResponse = mDNSfalse;
+ }
+ }
}
}
else if (llintf && llintf->IgnoreIPv4LL && m->rec.r.resrec.rrtype == kDNSType_A)
@@ -9016,7 +9256,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
// This can cause some badly written applications to freeze for a long time if they
// attempt to connect to an IPv4 link-local destination address and then wait for
// that connection attempt to time out before trying other candidate addresses.
-
+
// To mask this client bug, we suppress acceptance of IPv4 link-local address
// records on interfaces where we know the OS will be unwilling even to attempt
// communication with those IPv4 link-local destination addresses.
@@ -9103,13 +9343,36 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
// If we're probing for this record, we just failed
else if (rr->resrec.RecordType == kDNSRecordTypeUnique)
{
+ // At this point in the code, we're probing for uniqueness.
+ // We've sent at least one probe (rr->ProbeCount < DefaultProbeCountForTypeUnique)
+ // but we haven't completed probing yet (rr->resrec.RecordType == kDNSRecordTypeUnique).
// Before we call deregister, check if this is a packet we registered with the sleep proxy.
if (!mDNSCoreRegisteredProxyRecord(m, rr))
{
- LogMsg("mDNSCoreReceiveResponse: ProbeCount %d; will deregister %s", rr->ProbeCount, ARDisplayString(m, rr));
-
- m->mDNSStats.NameConflicts++;
- mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
+ // This may be a conflict due to stale packets on the network. Delay probing by a second.
+ // If there are conflicts after 3 such attempts, then it is a true conflict.
+ if (m->DelayConflictProcessing)
+ {
+ m->DelayConflictProcessing--;
+ LogMsg("Possible spurious conflict for %s. Attempt %d at suppressing probes for one second",
+ ARDisplayString(m, rr), (MAX_CONFLICT_PROCESSING_DELAYS - m->DelayConflictProcessing));
+ rr->ProbeCount = DefaultProbeCountForTypeUnique + 1;
+ rr->AnnounceCount = InitialAnnounceCount;
+ m->SuppressProbes = NonZeroTime(m->timenow + mDNSPlatformOneSecond);
+ InitializeLastAPTime(m, rr);
+ RecordProbeFailure(m, rr); // Repeated late conflicts also cause us to back off to the slower probing rate
+ }
+ else
+ {
+ LogMsg("mDNSCoreReceiveResponse: ProbeCount %d; will deregister %s", rr->ProbeCount, ARDisplayString(m, rr));
+ m->mDNSStats.NameConflicts++;
+#if APPLE_OSX_mDNSResponder
+ // See if this record was also registered with any D2D plugins.
+ D2D_stop_advertising_record(rr);
+#endif
+ mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
+ }
+
}
}
// We assumed this record must be unique, but we were wrong. (e.g. There are two mDNSResponders on the
@@ -9121,6 +9384,9 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
{
LogMsg("mDNSCoreReceiveResponse: Unexpected conflict discarding %s", ARDisplayString(m, rr));
m->mDNSStats.KnownUniqueNameConflicts++;
+#if APPLE_OSX_mDNSResponder
+ D2D_stop_advertising_record(rr);
+#endif
mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
}
else
@@ -9289,7 +9555,7 @@ exit:
continue;
}
}
-
+
// For Unicast (null InterfaceID) the resolver IDs should also match
if ((r1->resrec.InterfaceID == r2->resrec.InterfaceID) &&
(r1->resrec.InterfaceID || (id1 == id2)) &&
@@ -9313,7 +9579,7 @@ exit:
// to give us an aged TTL to correct for how long it has held the record,
// so our received TTLs are expected to vary in that case
- // We also suppress log message in the case of SRV records that are recieved
+ // We also suppress log message in the case of SRV records that are received
// with a TTL of 4500 that are already cached with a TTL of 120 seconds, since
// this behavior was observed for a number of discoveryd based AppleTV's in iOS 8
// GM builds.
@@ -9388,7 +9654,7 @@ exit:
// Note: We need to do this before we call CacheRecordDeferredAdd as this
// might start the verification process which needs these NSEC records
if (!AddNSECSForCacheRecord(m, NSECRecords, NSECCachePtr, rcode))
- {
+ {
LogInfo("mDNSCoreReceiveResponse: AddNSECSForCacheRecord failed to add NSEC for %s", CRDisplayString(m, NSECCachePtr));
FreeNSECRecords(m, NSECRecords);
}
@@ -9408,7 +9674,7 @@ exit:
{
LogInfo("mDNSCoreReceieveResponse: Updating NSEC records in %s", CRDisplayString(m, NSECCachePtr));
if (!AddNSECSForCacheRecord(m, NSECRecords, NSECCachePtr, rcode))
- {
+ {
LogInfo("mDNSCoreReceiveResponse: AddNSECSForCacheRecord failed to add NSEC for %s", CRDisplayString(m, NSECCachePtr));
FreeNSECRecords(m, NSECRecords);
}
@@ -9488,8 +9754,8 @@ mDNSlocal void SPSRecordCallback(mDNS *const m, AuthRecord *const ar, mStatus re
LogMsg("%-7s Conflicting mDNS -- waking %.6a %s", InterfaceNameForID(m, ar->resrec.InterfaceID), &ar->WakeUp.HMAC, ARDisplayString(m, ar));
if (ar->WakeUp.HMAC.l[0])
{
- SendWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.IMAC, &ar->WakeUp.password); // Send one wakeup magic packet
- ScheduleWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.HMAC); // Schedule all other records with the same owner to be woken
+ SendWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.IMAC, &ar->WakeUp.password, mDNSfalse); // Send one wakeup magic packet
+ ScheduleWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.HMAC); // Schedule all other records with the same owner to be woken
}
mDNS_Unlock(m);
}
@@ -9519,7 +9785,7 @@ mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *et
}
else if (*ptr == ':')
{
- if (colons >=5 || val > 255)
+ if (colons >=5)
{
LogMsg("GetValueForMACAddr: Address malformed colons %d val %d", colons, val);
return mDNSNULL;
@@ -9704,32 +9970,33 @@ mDNSlocal mDNSu8 *GetValueForKeepalive(mDNSu8 *ptr, mDNSu8 *limit, mDNSu32 *valu
mDNSexport mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr)
{
- mDNSAddr laddr, raddr;
- mDNSEthAddr eth;
- mDNSIPPort lport, rport;
- mDNSu32 timeout, seq, ack;
- mDNSu16 win;
+ mDNSAddr laddr, raddr;
+ mDNSEthAddr eth;
+ mDNSIPPort lport, rport;
+ mDNSu32 timeout, seq, ack;
+ mDNSu16 win;
- if (!mDNS_KeepaliveRecord(&rr->resrec))
- {
- return mDNSfalse;
- }
+ if (!mDNS_KeepaliveRecord(&rr->resrec))
+ {
+ return mDNSfalse;
+ }
- timeout = seq = ack = 0;
- win = 0;
- laddr = raddr = zeroAddr;
- lport = rport = zeroIPPort;
+ timeout = seq = ack = 0;
+ win = 0;
+ laddr = raddr = zeroAddr;
+ lport = rport = zeroIPPort;
+ eth = zeroEthAddr;
- mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, &raddr, &eth, &seq, &ack, &lport, &rport, &win);
+ mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, &raddr, &eth, &seq, &ack, &lport, &rport, &win);
- if (mDNSAddressIsZero(&laddr) || mDNSIPPortIsZero(lport) ||
- mDNSAddressIsZero(&raddr) || mDNSIPPortIsZero(rport) ||
- mDNSEthAddressIsZero(eth))
- {
- return mDNSfalse;
- }
+ if (mDNSAddressIsZero(&laddr) || mDNSIPPortIsZero(lport) ||
+ mDNSAddressIsZero(&raddr) || mDNSIPPortIsZero(rport) ||
+ mDNSEthAddressIsZero(eth))
+ {
+ return mDNSfalse;
+ }
- return mDNStrue;
+ return mDNStrue;
}
@@ -9760,7 +10027,7 @@ mDNSlocal void mDNS_ExtractKeepaliveInfo(AuthRecord *ar, mDNSu32 *timeout, mDNSA
raddr->type = mDNSAddrType_IPv4;
ptr = GetValueForIPv4Addr(ptr, limit, &raddr->ip.v4);
}
- if (param == 'H')
+ else if (param == 'H')
{
laddr->type = mDNSAddrType_IPv6;
ptr = GetValueForIPv6Addr(ptr, limit, &laddr->ip.v6);
@@ -10106,6 +10373,35 @@ mDNSlocal void mDNSCoreReceiveUpdate(mDNS *const m,
mDNS_SendKeepalives(m);
}
+mDNSlocal mDNSu32 mDNSGenerateOwnerOptForInterface(mDNS *const m, const mDNSInterfaceID InterfaceID, DNSMessage *msg)
+{
+ mDNSu8 *ptr = msg->data;
+ mDNSu8 *end = mDNSNULL;
+ mDNSu32 length = 0;
+ AuthRecord opt;
+
+ mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
+ opt.resrec.rrclass = NormalMaxDNSMessageData;
+ opt.resrec.rdlength = sizeof(rdataOPT);
+ opt.resrec.rdestimate = sizeof(rdataOPT);
+
+ NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
+ SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
+
+ LogSPS("Generated OPT record : %s", ARDisplayString(m, &opt));
+ end = PutResourceRecord(msg, ptr, &msg->h.numAdditionals, &opt.resrec);
+ if (end != mDNSNULL)
+ {
+ // Put all the integer values in IETF byte-order (MSB first, LSB second)
+ SwapDNSHeaderBytes(msg);
+ length = (end - msg->data);
+ }
+ else
+ LogSPS("mDNSGenerateOwnerOptForInterface: Failed to generate owner OPT record");
+
+ return length;
+}
+
mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *end, const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID)
{
if (InterfaceID)
@@ -10166,6 +10462,18 @@ mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg
ifname = InterfaceNameForID(m, InterfaceID);
mDNSPlatformMemCopy(&spsaddr, srcaddr, sizeof (mDNSAddr));
mDNSPlatformStoreSPSMACAddr(&spsaddr, ifname);
+
+ // Store the Owner OPT record for this interface.
+ // Configd may use the OPT record if it detects a conflict with the BSP when the system wakes up
+ DNSMessage optMsg;
+ int length = 0;
+ InitializeDNSMessage(&optMsg.h, zeroID, ResponseFlags);
+ length = mDNSGenerateOwnerOptForInterface(m, InterfaceID, &optMsg);
+ if (length != 0)
+ {
+ length += sizeof(DNSMessageHeader);
+ mDNSPlatformStoreOwnerOptRecord(ifname, &optMsg, length);
+ }
}
// If we were waiting to go to sleep, then this SPS registration or wide-area record deletion
// may have been the thing we were waiting for, so schedule another check to see if we can sleep now.
@@ -10309,17 +10617,21 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co
else if (QR_OP == UpdR) mDNSCoreReceiveUpdateR (m, msg, end, srcaddr, InterfaceID);
else
{
- LogMsg("Unknown DNS packet type %02X%02X from %#-15a:%-5d to %#-15a:%-5d length %d on %p (ignored)",
- msg->h.flags.b[0], msg->h.flags.b[1], srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), end - (mDNSu8 *)pkt, InterfaceID);
if (mDNS_LoggingEnabled)
{
- int i = 0;
- while (i<end - (mDNSu8 *)pkt)
- {
- char buffer[128];
- char *p = buffer + mDNS_snprintf(buffer, sizeof(buffer), "%04X", i);
- do if (i<end - (mDNSu8 *)pkt) p += mDNS_snprintf(p, sizeof(buffer), " %02X", ((mDNSu8 *)pkt)[i]);while (++i & 15);
- LogInfo("%s", buffer);
+ static int msgCount = 0;
+ if (msgCount < 1000) {
+ msgCount++;
+ int i = 0;
+ LogInfo("Unknown DNS packet type %02X%02X from %#-15a:%-5d to %#-15a:%-5d length %d on %p (ignored)",
+ msg->h.flags.b[0], msg->h.flags.b[1], srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), end - (mDNSu8 *)pkt, InterfaceID);
+ while (i<end - (mDNSu8 *)pkt)
+ {
+ char buffer[128];
+ char *p = buffer + mDNS_snprintf(buffer, sizeof(buffer), "%04X", i);
+ do if (i<end - (mDNSu8 *)pkt) p += mDNS_snprintf(p, sizeof(buffer), " %02X", ((mDNSu8 *)pkt)[i]);while (++i & 15);
+ LogInfo("%s", buffer);
+ }
}
}
}
@@ -10435,15 +10747,11 @@ mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const questi
q->triedAllServersOnce = question->triedAllServersOnce;
q->TargetQID = question->TargetQID;
- if (q->LocalSocket)
- {
- mDNSPlatformUDPClose(q->LocalSocket);
- }
-
q->LocalSocket = question->LocalSocket;
+ // No need to close old q->LocalSocket first -- duplicate questions can't have their own sockets
q->state = question->state;
- // q->tcp = question->tcp;
+ // q->tcp = question->tcp;
q->ReqLease = question->ReqLease;
q->expire = question->expire;
q->ntries = question->ntries;
@@ -10451,7 +10759,7 @@ mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const questi
question->LocalSocket = mDNSNULL;
question->nta = mDNSNULL; // If we've got a GetZoneData in progress, transfer it to the newly active question
- // question->tcp = mDNSNULL;
+ // question->tcp = mDNSNULL;
if (q->LocalSocket)
debugf("UpdateQuestionDuplicates transferred LocalSocket pointer for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
@@ -10657,7 +10965,7 @@ mDNSlocal mDNSBool DNSServerMatch(DNSServer *d, mDNSInterfaceID InterfaceID, mDN
//
// 3) Scoped questions (non-zero ServiceID) should consider *only* scoped DNSServers (DNSServer
// with "scoped" set to kScopeServiceID) and their ServiceIDs should match.
- //
+ //
// The first condition in the "if" statement checks to see if both the question and the DNSServer are
// unscoped. The question is unscoped only if InterfaceID is zero and ServiceID is -1.
//
@@ -10715,7 +11023,7 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question)
// match the scoped entries by mistake.
//
// Note: DNS configuration change will help pick the new dns servers but currently it does not affect the timeout
-
+
// Skip DNSServers that are InterfaceID Scoped but have no valid interfaceid set OR DNSServers that are ServiceID Scoped but have no valid serviceid set
if ((curr->scoped == kScopeInterfaceID && curr->interface == mDNSInterface_Any) || (curr->scoped == kScopeServiceID && curr->serviceID <= 0))
{
@@ -10724,7 +11032,8 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question)
}
currcount = CountLabels(&curr->domain);
- if ((!DEQuery || !curr->cellIntf) && DNSServerMatch(curr, question->InterfaceID, question->ServiceID))
+ if ((!curr->cellIntf || (!DEQuery && !(question->flags & kDNSServiceFlagsDenyCellular))) &&
+ DNSServerMatch(curr, question->InterfaceID, question->ServiceID))
{
bettermatch = BetterMatchForName(&question->qname, namecount, &curr->domain, currcount, bestmatchlen);
@@ -10963,7 +11272,7 @@ mDNSlocal mDNSBool ShouldSuppressUnicastQuery(mDNS *const m, DNSQuestion *q, DNS
LogInfo("ShouldSuppressUnicastQuery: Query suppressed for %##s, qtype %s, as the DNS server is NULL", q->qname.c, DNSTypeName(q->qtype));
return mDNStrue;
}
-
+
// Check if the DNS Configuration allows A/AAAA queries to be sent
if ((q->qtype == kDNSType_A) && (d->req_A))
{
@@ -11037,6 +11346,12 @@ mDNSlocal mDNSBool ShouldSuppressDotLocalQuery(mDNS *const m, DNSQuestion *q)
mDNSlocal mDNSBool ShouldSuppressQuery(mDNS *const m, DNSQuestion *q)
{
+ if (q->InterfaceID == mDNSInterface_LocalOnly)
+ {
+ LogInfo("ShouldSuppressQuery: LocalOnly query not suppressed for %##s, qtype %s", q->qname.c, DNSTypeName(q->qtype));
+ return mDNSfalse;
+ }
+
if (q->qtype != kDNSType_A && q->qtype != kDNSType_AAAA)
{
LogInfo("ShouldSuppressQuery: Query not suppressed for %##s, qtype %s, not A/AAAA type", q->qname.c, DNSTypeName(q->qtype));
@@ -11310,7 +11625,7 @@ mDNSlocal void RestartUnicastQuestions(mDNS *const m)
{
if (mDNSOpaque16IsZero(q->TargetQID))
LogMsg("RestartUnicastQuestions: ERROR!! Restart set for multicast question %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-
+
q->Restart = 0;
SuppressStatusChanged(m, q, &restart);
}
@@ -11339,7 +11654,7 @@ mDNSlocal mStatus ValidateParameters(mDNS *const m, DNSQuestion *const question)
}
// If no question->Target specified, clear TargetPort
- if (!question->Target.type)
+ if (!question->Target.type)
question->TargetPort = zeroIPPort;
if (!ValidateDomainName(&question->qname))
@@ -11349,14 +11664,14 @@ mDNSlocal mStatus ValidateParameters(mDNS *const m, DNSQuestion *const question)
}
// If this question is referencing a specific interface, verify it exists
- if (question->InterfaceID && question->InterfaceID != mDNSInterface_LocalOnly && question->InterfaceID != mDNSInterface_Unicast && question->InterfaceID != mDNSInterface_P2P)
+ if (question->InterfaceID && !LocalOnlyOrP2PInterface(question->InterfaceID) && question->InterfaceID != mDNSInterface_Unicast)
{
NetworkInterfaceInfo *intf = FirstInterfaceForID(m, question->InterfaceID);
if (!intf)
LogInfo("ValidateParameters: Note: InterfaceID %d for question %##s (%s) not currently found in active interface list",
(uint32_t)question->InterfaceID, question->qname.c, DNSTypeName(question->qtype));
}
-
+
return(mStatus_NoError);
}
@@ -11367,19 +11682,19 @@ mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question)
// First reset all DNS Configuration
question->qDNSServer = mDNSNULL;
question->validDNSServers = zeroOpaque64;
- question->triedAllServersOnce = 0;
- question->noServerResponse = 0;
+ question->triedAllServersOnce = 0;
+ question->noServerResponse = 0;
question->StopTime = 0;
#if TARGET_OS_EMBEDDED
mDNSPlatformMemZero(&question->metrics, sizeof(question->metrics));
#endif
// Need not initialize the DNS Configuration for Local Only OR P2P Questions
- if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P)
+ if (LocalOnlyOrP2PInterface(question->InterfaceID))
return;
// Proceed to initialize DNS Configuration (some are set in SetValidDNSServers())
if (!mDNSOpaque16IsZero(question->TargetQID))
- {
+ {
mDNSu32 timeout = SetValidDNSServers(m, question);
// We set the timeout whenever mDNS_StartQuery_internal is called. This means if we have
// a networking change/search domain change that calls this function again we keep
@@ -11402,7 +11717,7 @@ mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question)
mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort));
}
else
- {
+ {
if (question->TimeoutQuestion)
question->StopTime = NonZeroTime(m->timenow + GetTimeoutForMcastQuestion(m, question) * mDNSPlatformOneSecond);
}
@@ -11411,7 +11726,7 @@ mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question)
SetNextQueryStopTime(m, question);
// SetNextQueryTime() need not be initialized for LocalOnly OR P2P Questions since those questions
// will never be transmitted on the wire. Hence we call SetNextQueryTime() here.
- SetNextQueryTime(m,question);
+ SetNextQueryTime(m,question);
}
// InitCommonState() is called by mDNS_StartQuery_internal() to initialize the common(uDNS/mDNS) internal
@@ -11420,7 +11735,7 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question)
{
mDNSBool purge;
int i;
- mDNSBool isCellBlocked = mDNSfalse;
+ mDNSBool isBlocked = mDNSfalse;
// Note: In the case where we already have the answer to this question in our cache, that may be all the client
// wanted, and they may immediately cancel their question. In this case, sending an actual query on the wire would
@@ -11468,15 +11783,21 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question)
question->LOAddressAnswers = 0;
question->FlappingInterface1 = mDNSNULL;
question->FlappingInterface2 = mDNSNULL;
-
- // if kDNSServiceFlagsServiceIndex flag is SET by the client, then do NOT call mDNSPlatformGetDNSRoutePolicy()
- // since we would already have the question->ServiceID in that case.
- if (!(question->flags & kDNSServiceFlagsServiceIndex))
- mDNSPlatformGetDNSRoutePolicy(m, question, &isCellBlocked);
- else
- LogInfo("InitCommonState: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] is already set by client", question->qname.c,
+
+ // if kDNSServiceFlagsServiceIndex flag is SET by the client, then do NOT call mDNSPlatformGetDNSRoutePolicy()
+ // since we would already have the question->ServiceID in that case.
+ if (!(question->flags & kDNSServiceFlagsServiceIndex))
+ {
+#if APPLE_OSX_mDNSResponder
+ mDNSPlatformGetDNSRoutePolicy(m, question, &isBlocked);
+#else
+ question->ServiceID = -1;
+#endif
+ }
+ else
+ LogInfo("InitCommonState: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] is already set by client", question->qname.c,
DNSTypeName(question->qtype), question->pid, question->euid, question->ServiceID);
-
+
InitDNSConfig(m, question);
question->AuthInfo = GetAuthInfoForQuestion(m, question);
@@ -11486,7 +11807,7 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question)
// If ServiceID is 0 or the policy disallows making DNS requests,
// set DisallowPID
- question->DisallowPID = (question->ServiceID == 0 || (isCellBlocked && question->qDNSServer && question->qDNSServer->cellIntf));
+ question->DisallowPID = (question->ServiceID == 0 || isBlocked);
if (question->DisallowPID)
LogInfo("InitCommonState: Query suppressed for %##s (%s), PID %d/ServiceID %d not allowed", question->qname.c,
DNSTypeName(question->qtype), question->pid, question->ServiceID);
@@ -11494,47 +11815,27 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question)
question->NextInDQList = mDNSNULL;
question->SendQNow = mDNSNULL;
question->SendOnAll = mDNSfalse;
-
-#if mDNS_REQUEST_UNICAST_RESPONSE
- question->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES;
-#else // mDNS_REQUEST_UNICAST_RESPONSE
- question->RequestUnicast = SET_QU_IN_FIRST_QUERY;
-#endif // mDNS_REQUEST_UNICAST_RESPONSE
+ question->RequestUnicast = kDefaultRequestUnicastCount;
#if APPLE_OSX_mDNSResponder
- // Request unicast response for first 4 queries to increase
- // reliability in an environment with high multicast packet loss.
- // Must set to one more than the number of unicast queries you want, since SendQueries()
- // decrements it before calling BuildQuestion() which acts on it.
- if (question->flags & kDNSServiceFlagsUnicastResponse)
+ // Set the QU bit in the first query for the following options.
+ if ((question->flags & kDNSServiceFlagsUnicastResponse) || (question->flags & kDNSServiceFlagsThresholdFinder))
{
- question->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES;
+ question->RequestUnicast = SET_QU_IN_FIRST_QUERY;
LogInfo("InitCommonState: setting RequestUnicast = %d for %##s (%s)", question->RequestUnicast, question->qname.c,
DNSTypeName(question->qtype));
- }
- else if (question->flags & kDNSServiceFlagsThresholdFinder)
- {
- // always send one request with QU bit set when kDNSServiceFlagsThresholdFinder is set
-#if mDNS_REQUEST_UNICAST_RESPONSE
- question->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES;
-#else // mDNS_REQUEST_UNICAST_RESPONSE
- question->RequestUnicast = SET_QU_IN_FIRST_QUERY;
-#endif // mDNS_REQUEST_UNICAST_RESPONSE
-
- LogInfo("InitCommonState: kDNSServiceFlagsThresholdFinder set, setting RequestUnicast = %d for %##s (%s)",
- question->RequestUnicast, question->qname.c, DNSTypeName(question->qtype));
}
#endif // APPLE_OSX_mDNSResponder
question->LastQTxTime = m->timenow;
- question->CNAMEReferrals = 0;
+ question->CNAMEReferrals = 0;
question->WakeOnResolveCount = 0;
if (question->WakeOnResolve)
- {
+ {
question->WakeOnResolveCount = InitialWakeOnResolveCount;
purge = mDNStrue;
- }
+ }
for (i=0; i<DupSuppressInfoSize; i++)
question->DupSuppress[i].InterfaceID = mDNSNULL;
@@ -11561,7 +11862,7 @@ mDNSlocal void InitWABState(DNSQuestion *const question)
// We won't need one for duplicate questions, or from questions answered immediately out of the cache.
// We also don't need one for LLQs because (when we're using NAT) we want them all to share a single
// NAT mapping for receiving inbound add/remove events.
- question->LocalSocket = mDNSNULL;
+ question->LocalSocket = mDNSNULL;
question->unansweredQueries = 0;
question->nta = mDNSNULL;
question->servAddr = zeroAddr;
@@ -11593,6 +11894,11 @@ mDNSlocal void InitLLQState(DNSQuestion *const question)
question->id = zeroOpaque64;
}
+mDNSlocal void InitDNSPNState(DNSQuestion *const question)
+{
+ question->dnsPushState = DNSPUSH_INIT;
+}
+
// InitDNSSECProxyState() is called by mDNS_StartQuery_internal() to initialize
// DNSSEC & DNS Proxy fields of the DNS Question.
mDNSlocal void InitDNSSECProxyState(mDNS *const m, DNSQuestion *const question)
@@ -11680,19 +11986,30 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
vStatus = ValidateParameters(m, question);
if (vStatus)
return(vStatus);
-
+
+#ifdef USE_LIBIDN
+ // If the TLD includes high-ascii bytes, assume it will need to be converted to Punycode.
+ // (In the future the root name servers may answer UTF-8 queries directly, but for now they do not.)
+ if (IsHighASCIILabel(LastLabel(&question->qname)))
+ {
+ domainname newname;
+ if (PerformNextPunycodeConversion(question, &newname))
+ AssignDomainName(&question->qname, &newname);
+ }
+#endif // USE_LIBIDN
+
question->TargetQID =
#ifndef UNICAST_DISABLED
(question->Target.type || Question_uDNS(question)) ? mDNS_NewMessageID(m) :
#endif // UNICAST_DISABLED
zeroID;
- debugf("mDNS_StartQuery_internal: %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
-
+ debugf("mDNS_StartQuery_internal: %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
+
// Note: It important that new questions are appended at the *end* of the list, not prepended at the start
q = &m->Questions;
- if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P)
+ if (LocalOnlyOrP2PInterface(question->InterfaceID))
q = &m->LocalOnlyQuestions;
- while (*q && *q != question)
+ while (*q && *q != question)
q=&(*q)->next;
if (*q)
@@ -11702,7 +12019,6 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
return(mStatus_AlreadyRegistered);
}
*q = question;
-
// Intialize the question. The only ordering constraint we have today is that
// InitDNSSECProxyState should be called after the DNS server is selected (in
@@ -11712,23 +12028,24 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
purge = InitCommonState(m, question);
InitWABState(question);
InitLLQState(question);
+ InitDNSPNState(question);
InitDNSSECProxyState(m, question);
// FindDuplicateQuestion should be called last after all the intialization
// as the duplicate logic could be potentially based on any field in the
// question.
question->DuplicateOf = FindDuplicateQuestion(m, question);
- if (question->DuplicateOf)
- question->AuthInfo = question->DuplicateOf->AuthInfo;
+ if (question->DuplicateOf)
+ question->AuthInfo = question->DuplicateOf->AuthInfo;
- if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P)
+ if (LocalOnlyOrP2PInterface(question->InterfaceID))
{
- if (!m->NewLocalOnlyQuestions)
+ if (!m->NewLocalOnlyQuestions)
m->NewLocalOnlyQuestions = question;
}
else
{
- if (!m->NewQuestions)
+ if (!m->NewQuestions)
m->NewQuestions = question;
// If the question's id is non-zero, then it's Wide Area
@@ -11743,13 +12060,22 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
}
else
{
-#if TARGET_OS_WATCH
- m->NumAllInterfaceQuestions++;
- LogInfo("mDNS_StartQuery_internal: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %##s (%s)",
- m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, question->qname.c, DNSTypeName(question->qtype));
- if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
- m->NetworkChanged = m->timenow;
-#endif
+#if BONJOUR_ON_DEMAND
+ m->NumAllInterfaceQuestions++;
+ LogInfo("mDNS_StartQuery_internal: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %##s (%s)",
+ m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, question->qname.c, DNSTypeName(question->qtype));
+ if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
+ {
+ m->NextBonjourDisableTime = 0;
+ if (m->BonjourEnabled == 0)
+ {
+ // Enable Bonjour immediately by scheduling network changed processing where
+ // we will join the multicast group on each active interface.
+ m->BonjourEnabled = 1;
+ m->NetworkChanged = m->timenow;
+ }
+ }
+#endif // BONJOUR_ON_DEMAND
if (purge)
{
LogInfo("mDNS_StartQuery_internal: Purging for %##s", question->qname.c);
@@ -11786,7 +12112,8 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que
//LogInfo("mDNS_StopQuery_internal %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
- if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P) qp = &m->LocalOnlyQuestions;
+ if (LocalOnlyOrP2PInterface(question->InterfaceID))
+ qp = &m->LocalOnlyQuestions;
while (*qp && *qp != question) qp=&(*qp)->next;
if (*qp) *qp = (*qp)->next;
else
@@ -11798,29 +12125,36 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que
return(mStatus_BadReferenceErr);
}
-#if TARGET_OS_WATCH
- if (question->InterfaceID != mDNSInterface_LocalOnly && question->InterfaceID != mDNSInterface_P2P && mDNSOpaque16IsZero(question->TargetQID))
+#if BONJOUR_ON_DEMAND
+ if (!LocalOnlyOrP2PInterface(question->InterfaceID) && mDNSOpaque16IsZero(question->TargetQID))
{
- if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
- m->NetworkChanged = m->timenow;
- m->NumAllInterfaceQuestions--;
- LogInfo("mDNS_StopQuery_internal: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %##s (%s)",
- m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, question->qname.c, DNSTypeName(question->qtype));
+ if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
+ m->NextBonjourDisableTime = NonZeroTime(m->timenow + (BONJOUR_DISABLE_DELAY * mDNSPlatformOneSecond));
+ m->NumAllInterfaceQuestions--;
+ LogInfo("mDNS_StopQuery_internal: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %##s (%s)",
+ m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, question->qname.c, DNSTypeName(question->qtype));
}
-#endif
+#endif // BONJOUR_ON_DEMAND
#if TARGET_OS_EMBEDDED
- if (Question_uDNS(question) && !question->metrics.answered)
+ if (Question_uDNS(question) && !question->metrics.answered && (question->metrics.querySendCount > 0))
{
- uDNSMetrics * metrics;
const domainname * queryName;
- mDNSBool isForCellular;
+ mDNSBool isForCell;
+ mDNSu32 durationMs;
- metrics = &question->metrics;
- queryName = metrics->originalQName ? metrics->originalQName : &question->qname;
- isForCellular = (question->qDNSServer && question->qDNSServer->cellIntf);
+ queryName = question->metrics.originalQName ? question->metrics.originalQName : &question->qname;
+ isForCell = (question->qDNSServer && question->qDNSServer->cellIntf);
- MetricsUpdateUDNSStats(queryName, mDNSfalse, metrics->querySendCount, 0, isForCellular);
+ if (question->metrics.querySendCount > 0)
+ {
+ durationMs = ((m->timenow - question->metrics.firstQueryTime) * 1000) / mDNSPlatformOneSecond;
+ }
+ else
+ {
+ durationMs = 0;
+ }
+ MetricsUpdateUDNSQueryStats(queryName, question->qtype, mDNSNULL, question->metrics.querySendCount, durationMs, isForCell);
}
#endif
// Take care to cut question from list *before* calling UpdateQuestionDuplicates
@@ -11835,16 +12169,31 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que
if (rr->CRActiveQuestion == question)
{
DNSQuestion *q;
- // Checking for ActiveQuestion filters questions that are suppressed also
- // as suppressed questions are not active
- for (q = m->Questions; q; q=q->next) // Scan our list of questions
- if (ActiveQuestion(q) && ResourceRecordAnswersQuestion(&rr->resrec, q))
- break;
- if (q)
+ DNSQuestion *replacement = mDNSNULL;
+ // If we find an active question that is answered by this cached record, use it as the cache record's
+ // CRActiveQuestion replacement. If there are no such questions, but there's at least one unsuppressed inactive
+ // question that is answered by this cache record, then use an inactive one to not forgo generating RMV events
+ // via CacheRecordRmv() when the cache record expires.
+ for (q = m->Questions; q && (q != m->NewQuestions); q = q->next)
+ {
+ if (!q->DuplicateOf && !QuerySuppressed(q) && ResourceRecordAnswersQuestion(&rr->resrec, q))
+ {
+ if (q->ThisQInterval > 0)
+ {
+ replacement = q;
+ break;
+ }
+ else if (!replacement)
+ {
+ replacement = q;
+ }
+ }
+ }
+ if (replacement)
debugf("mDNS_StopQuery_internal: Updating CRActiveQuestion to %p for cache record %s, Original question CurrentAnswers %d, new question "
- "CurrentAnswers %d, SuppressQuery %d", q, CRDisplayString(m,rr), question->CurrentAnswers, q->CurrentAnswers, q->SuppressQuery);
- rr->CRActiveQuestion = q; // Question used to be active; new value may or may not be null
- if (!q) m->rrcache_active--; // If no longer active, decrement rrcache_active count
+ "CurrentAnswers %d, SuppressQuery %d", replacement, CRDisplayString(m,rr), question->CurrentAnswers, replacement->CurrentAnswers, replacement->SuppressQuery);
+ rr->CRActiveQuestion = replacement; // Question used to be active; new value may or may not be null
+ if (!replacement) m->rrcache_active--; // If no longer active, decrement rrcache_active count
}
}
@@ -11927,6 +12276,15 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que
question->tcp = mDNSNULL;
}
}
+ else if (question->dnsPushState == DNSPUSH_ESTABLISHED)
+ {
+ if (question->tcp)
+ {
+ UnSubscribeToDNSPushNotificationServer(m, q);
+ question->tcp->question = mDNSNULL;
+ question->tcp = mDNSNULL;
+ }
+ }
#if APPLE_OSX_mDNSResponder
UpdateAutoTunnelDomainStatuses(m);
#endif
@@ -12043,10 +12401,8 @@ mDNSlocal mStatus mDNS_StartBrowse_internal(mDNS *const m, DNSQuestion *const qu
question->LongLived = mDNStrue;
question->ExpectUnique = mDNSfalse;
question->ForceMCast = ForceMCast;
- question->ReturnIntermed = mDNSfalse;
+ question->ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
question->SuppressUnusable = mDNSfalse;
- question->DenyOnCellInterface = mDNSfalse;
- question->DenyOnExpInterface = mDNSfalse;
question->SearchListIndex = 0;
question->AppendSearchDomains = 0;
question->RetryWithSearchDomains = mDNSfalse;
@@ -12087,295 +12443,6 @@ mDNSexport mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
return(status);
}
-mDNSlocal mDNSBool MachineHasActiveIPv6(mDNS *const m)
-{
- NetworkInterfaceInfo *intf;
- for (intf = m->HostInterfaces; intf; intf = intf->next)
- if (intf->ip.type == mDNSAddrType_IPv6) return(mDNStrue);
- return(mDNSfalse);
-}
-
-mDNSlocal void FoundServiceInfoSRV(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
- ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
- mDNSBool PortChanged = !mDNSSameIPPort(query->info->port, answer->rdata->u.srv.port);
- if (!AddRecord) return;
- if (answer->rrtype != kDNSType_SRV) return;
-
- query->info->port = answer->rdata->u.srv.port;
-
- // If this is our first answer, then set the GotSRV flag and start the address query
- if (!query->GotSRV)
- {
- query->GotSRV = mDNStrue;
- query->qAv4.InterfaceID = answer->InterfaceID;
- AssignDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target);
- query->qAv6.InterfaceID = answer->InterfaceID;
- AssignDomainName(&query->qAv6.qname, &answer->rdata->u.srv.target);
- mDNS_StartQuery(m, &query->qAv4);
- // Only do the AAAA query if this machine actually has IPv6 active
- if (MachineHasActiveIPv6(m)) mDNS_StartQuery(m, &query->qAv6);
- }
- // If this is not our first answer, only re-issue the address query if the target host name has changed
- else if ((query->qAv4.InterfaceID != query->qSRV.InterfaceID && query->qAv4.InterfaceID != answer->InterfaceID) ||
- !SameDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target))
- {
- mDNS_StopQuery(m, &query->qAv4);
- if (query->qAv6.ThisQInterval >= 0) mDNS_StopQuery(m, &query->qAv6);
- if (SameDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target) && !PortChanged)
- {
- // If we get here, it means:
- // 1. This is not our first SRV answer
- // 2. The interface ID is different, but the target host and port are the same
- // This implies that we're seeing the exact same SRV record on more than one interface, so we should
- // make our address queries at least as broad as the original SRV query so that we catch all the answers.
- query->qAv4.InterfaceID = query->qSRV.InterfaceID; // Will be mDNSInterface_Any, or a specific interface
- query->qAv6.InterfaceID = query->qSRV.InterfaceID;
- }
- else
- {
- query->qAv4.InterfaceID = answer->InterfaceID;
- AssignDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target);
- query->qAv6.InterfaceID = answer->InterfaceID;
- AssignDomainName(&query->qAv6.qname, &answer->rdata->u.srv.target);
- }
- debugf("FoundServiceInfoSRV: Restarting address queries for %##s (%s)", query->qAv4.qname.c, DNSTypeName(query->qAv4.qtype));
- mDNS_StartQuery(m, &query->qAv4);
- // Only do the AAAA query if this machine actually has IPv6 active
- if (MachineHasActiveIPv6(m)) mDNS_StartQuery(m, &query->qAv6);
- }
- else if (query->ServiceInfoQueryCallback && query->GotADD && query->GotTXT && PortChanged)
- {
- if (++query->Answers >= 100)
- debugf("**** WARNING **** Have given %lu answers for %##s (SRV) %##s %u",
- query->Answers, query->qSRV.qname.c, answer->rdata->u.srv.target.c,
- mDNSVal16(answer->rdata->u.srv.port));
- query->ServiceInfoQueryCallback(m, query);
- }
- // CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's
- // callback function is allowed to do anything, including deleting this query and freeing its memory.
-}
-
-mDNSlocal void FoundServiceInfoTXT(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
- ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
- if (!AddRecord) return;
- if (answer->rrtype != kDNSType_TXT) return;
- if (answer->rdlength > sizeof(query->info->TXTinfo)) return;
-
- query->GotTXT = mDNStrue;
- query->info->TXTlen = answer->rdlength;
- query->info->TXTinfo[0] = 0; // In case answer->rdlength is zero
- mDNSPlatformMemCopy(query->info->TXTinfo, answer->rdata->u.txt.c, answer->rdlength);
-
- verbosedebugf("FoundServiceInfoTXT: %##s GotADD=%d", query->info->name.c, query->GotADD);
-
- // CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's
- // callback function is allowed to do anything, including deleting this query and freeing its memory.
- if (query->ServiceInfoQueryCallback && query->GotADD)
- {
- if (++query->Answers >= 100)
- debugf("**** WARNING **** have given %lu answers for %##s (TXT) %#s...",
- query->Answers, query->qSRV.qname.c, answer->rdata->u.txt.c);
- query->ServiceInfoQueryCallback(m, query);
- }
-}
-
-mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
- ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
- //LogInfo("FoundServiceInfo %d %s", AddRecord, RRDisplayString(m, answer));
- if (!AddRecord) return;
-
- if (answer->rrtype == kDNSType_A)
- {
- query->info->ip.type = mDNSAddrType_IPv4;
- query->info->ip.ip.v4 = answer->rdata->u.ipv4;
- }
- else if (answer->rrtype == kDNSType_AAAA)
- {
- query->info->ip.type = mDNSAddrType_IPv6;
- query->info->ip.ip.v6 = answer->rdata->u.ipv6;
- }
- else
- {
- debugf("FoundServiceInfo: answer %##s type %d (%s) unexpected", answer->name->c, answer->rrtype, DNSTypeName(answer->rrtype));
- return;
- }
-
- query->GotADD = mDNStrue;
- query->info->InterfaceID = answer->InterfaceID;
-
- verbosedebugf("FoundServiceInfo v%ld: %##s GotTXT=%d", query->info->ip.type, query->info->name.c, query->GotTXT);
-
- // CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's
- // callback function is allowed to do anything, including deleting this query and freeing its memory.
- if (query->ServiceInfoQueryCallback && query->GotTXT)
- {
- if (++query->Answers >= 100)
- debugf(answer->rrtype == kDNSType_A ?
- "**** WARNING **** have given %lu answers for %##s (A) %.4a" :
- "**** WARNING **** have given %lu answers for %##s (AAAA) %.16a",
- query->Answers, query->qSRV.qname.c, &answer->rdata->u.data);
- query->ServiceInfoQueryCallback(m, query);
- }
-}
-
-// On entry, the client must have set the name and InterfaceID fields of the ServiceInfo structure
-// If the query is not interface-specific, then InterfaceID may be zero
-// Each time the Callback is invoked, the remainder of the fields will have been filled in
-// In addition, InterfaceID will be updated to give the interface identifier corresponding to that response
-mDNSexport mStatus mDNS_StartResolveService(mDNS *const m,
- ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context)
-{
- mStatus status;
- mDNS_Lock(m);
-
- query->qSRV.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question
- query->qSRV.InterfaceID = info->InterfaceID;
- query->qSRV.flags = 0;
- query->qSRV.Target = zeroAddr;
- AssignDomainName(&query->qSRV.qname, &info->name);
- query->qSRV.qtype = kDNSType_SRV;
- query->qSRV.qclass = kDNSClass_IN;
- query->qSRV.LongLived = mDNSfalse;
- query->qSRV.ExpectUnique = mDNStrue;
- query->qSRV.ForceMCast = mDNSfalse;
- query->qSRV.ReturnIntermed = mDNSfalse;
- query->qSRV.SuppressUnusable = mDNSfalse;
- query->qSRV.DenyOnCellInterface = mDNSfalse;
- query->qSRV.DenyOnExpInterface = mDNSfalse;
- query->qSRV.SearchListIndex = 0;
- query->qSRV.AppendSearchDomains = 0;
- query->qSRV.RetryWithSearchDomains = mDNSfalse;
- query->qSRV.TimeoutQuestion = 0;
- query->qSRV.WakeOnResolve = 0;
- query->qSRV.UseBackgroundTrafficClass = mDNSfalse;
- query->qSRV.ValidationRequired = 0;
- query->qSRV.ValidatingResponse = 0;
- query->qSRV.ProxyQuestion = 0;
- query->qSRV.qnameOrig = mDNSNULL;
- query->qSRV.AnonInfo = mDNSNULL;
- query->qSRV.QuestionCallback = FoundServiceInfoSRV;
- query->qSRV.QuestionContext = query;
-
- query->qTXT.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question
- query->qTXT.InterfaceID = info->InterfaceID;
- query->qTXT.flags = 0;
- query->qTXT.Target = zeroAddr;
- AssignDomainName(&query->qTXT.qname, &info->name);
- query->qTXT.qtype = kDNSType_TXT;
- query->qTXT.qclass = kDNSClass_IN;
- query->qTXT.LongLived = mDNSfalse;
- query->qTXT.ExpectUnique = mDNStrue;
- query->qTXT.ForceMCast = mDNSfalse;
- query->qTXT.ReturnIntermed = mDNSfalse;
- query->qTXT.SuppressUnusable = mDNSfalse;
- query->qTXT.DenyOnCellInterface = mDNSfalse;
- query->qTXT.DenyOnExpInterface = mDNSfalse;
- query->qTXT.SearchListIndex = 0;
- query->qTXT.AppendSearchDomains = 0;
- query->qTXT.RetryWithSearchDomains = mDNSfalse;
- query->qTXT.TimeoutQuestion = 0;
- query->qTXT.WakeOnResolve = 0;
- query->qTXT.UseBackgroundTrafficClass = mDNSfalse;
- query->qTXT.ValidationRequired = 0;
- query->qTXT.ValidatingResponse = 0;
- query->qTXT.ProxyQuestion = 0;
- query->qTXT.qnameOrig = mDNSNULL;
- query->qTXT.AnonInfo = mDNSNULL;
- query->qTXT.QuestionCallback = FoundServiceInfoTXT;
- query->qTXT.QuestionContext = query;
-
- query->qAv4.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question
- query->qAv4.InterfaceID = info->InterfaceID;
- query->qAv4.flags = 0;
- query->qAv4.Target = zeroAddr;
- query->qAv4.qname.c[0] = 0;
- query->qAv4.qtype = kDNSType_A;
- query->qAv4.qclass = kDNSClass_IN;
- query->qAv4.LongLived = mDNSfalse;
- query->qAv4.ExpectUnique = mDNStrue;
- query->qAv4.ForceMCast = mDNSfalse;
- query->qAv4.ReturnIntermed = mDNSfalse;
- query->qAv4.SuppressUnusable = mDNSfalse;
- query->qAv4.DenyOnCellInterface = mDNSfalse;
- query->qAv4.DenyOnExpInterface = mDNSfalse;
- query->qAv4.SearchListIndex = 0;
- query->qAv4.AppendSearchDomains = 0;
- query->qAv4.RetryWithSearchDomains = mDNSfalse;
- query->qAv4.TimeoutQuestion = 0;
- query->qAv4.WakeOnResolve = 0;
- query->qAv4.UseBackgroundTrafficClass = mDNSfalse;
- query->qAv4.ValidationRequired = 0;
- query->qAv4.ValidatingResponse = 0;
- query->qAv4.ProxyQuestion = 0;
- query->qAv4.qnameOrig = mDNSNULL;
- query->qAv4.AnonInfo = mDNSNULL;
- query->qAv4.QuestionCallback = FoundServiceInfo;
- query->qAv4.QuestionContext = query;
-
- query->qAv6.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question
- query->qAv6.InterfaceID = info->InterfaceID;
- query->qAv6.flags = 0;
- query->qAv6.Target = zeroAddr;
- query->qAv6.qname.c[0] = 0;
- query->qAv6.qtype = kDNSType_AAAA;
- query->qAv6.qclass = kDNSClass_IN;
- query->qAv6.LongLived = mDNSfalse;
- query->qAv6.ExpectUnique = mDNStrue;
- query->qAv6.ForceMCast = mDNSfalse;
- query->qAv6.ReturnIntermed = mDNSfalse;
- query->qAv6.SuppressUnusable = mDNSfalse;
- query->qAv6.DenyOnCellInterface = mDNSfalse;
- query->qAv6.DenyOnExpInterface = mDNSfalse;
- query->qAv6.SearchListIndex = 0;
- query->qAv6.AppendSearchDomains = 0;
- query->qAv6.RetryWithSearchDomains = mDNSfalse;
- query->qAv6.TimeoutQuestion = 0;
- query->qAv6.UseBackgroundTrafficClass = mDNSfalse;
- query->qAv6.ValidationRequired = 0;
- query->qAv6.ValidatingResponse = 0;
- query->qAv6.ProxyQuestion = 0;
- query->qAv6.qnameOrig = mDNSNULL;
- query->qAv6.AnonInfo = mDNSNULL;
- query->qAv6.QuestionCallback = FoundServiceInfo;
- query->qAv6.QuestionContext = query;
-
- query->GotSRV = mDNSfalse;
- query->GotTXT = mDNSfalse;
- query->GotADD = mDNSfalse;
- query->Answers = 0;
-
- query->info = info;
- query->ServiceInfoQueryCallback = Callback;
- query->ServiceInfoQueryContext = Context;
-
-// info->name = Must already be set up by client
-// info->interface = Must already be set up by client
- info->ip = zeroAddr;
- info->port = zeroIPPort;
- info->TXTlen = 0;
-
- // We use mDNS_StartQuery_internal here because we're already holding the lock
- status = mDNS_StartQuery_internal(m, &query->qSRV);
- if (status == mStatus_NoError) status = mDNS_StartQuery_internal(m, &query->qTXT);
- if (status != mStatus_NoError) mDNS_StopResolveService(m, query);
-
- mDNS_Unlock(m);
- return(status);
-}
-
-mDNSexport void mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *q)
-{
- mDNS_Lock(m);
- // We use mDNS_StopQuery_internal here because we're already holding the lock
- if (q->qSRV.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qSRV);
- if (q->qTXT.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qTXT);
- if (q->qAv4.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qAv4);
- if (q->qAv6.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qAv6);
- mDNS_Unlock(m);
-}
mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const domainname *dom,
const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context)
@@ -12390,8 +12457,6 @@ mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, m
question->ForceMCast = mDNSfalse;
question->ReturnIntermed = mDNSfalse;
question->SuppressUnusable = mDNSfalse;
- question->DenyOnCellInterface = mDNSfalse;
- question->DenyOnExpInterface = mDNSfalse;
question->SearchListIndex = 0;
question->AppendSearchDomains = 0;
question->RetryWithSearchDomains = mDNSfalse;
@@ -12404,7 +12469,7 @@ mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, m
question->qnameOrig = mDNSNULL;
question->AnonInfo = mDNSNULL;
question->pid = mDNSPlatformGetPID();
- question->euid = 0;
+ question->euid = 0;
question->QuestionCallback = Callback;
question->QuestionContext = Context;
if (DomainType > mDNS_DomainTypeMax) return(mStatus_BadParamErr);
@@ -12615,6 +12680,10 @@ mDNSlocal void DeadvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set)
return;
}
+#if APPLE_OSX_mDNSResponder
+ D2D_stop_advertising_interface(set);
+#endif // APPLE_OSX_mDNSResponder
+
// Unregister these records.
// When doing the mDNS_Exit processing, we first call DeadvertiseInterface for each interface, so by the time the platform
// support layer gets to call mDNS_DeregisterInterface, the address and PTR records have already been deregistered for it.
@@ -12623,11 +12692,6 @@ mDNSlocal void DeadvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set)
if (set->RR_A .resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_A, mDNS_Dereg_normal);
if (set->RR_PTR .resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_PTR, mDNS_Dereg_normal);
if (set->RR_HINFO.resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_HINFO, mDNS_Dereg_normal);
-
-#if APPLE_OSX_mDNSResponder
- D2D_stop_advertising_interface(set);
-#endif // APPLE_OSX_mDNSResponder
-
}
mDNSlocal void AdvertiseAllInterfaceRecords(mDNS *const m)
@@ -12656,6 +12720,23 @@ mDNSlocal void DeadvertiseAllInterfaceRecords(mDNS *const m)
}
}
+// Change target host name for record.
+mDNSlocal void UpdateTargetHostName(mDNS *const m, AuthRecord *const rr)
+{
+#if APPLE_OSX_mDNSResponder
+ // If this record was also registered with any D2D plugins, stop advertising
+ // the version with the old host name.
+ D2D_stop_advertising_record(rr);
+#endif
+
+ SetTargetToHostName(m, rr);
+
+#if APPLE_OSX_mDNSResponder
+ // Advertise the record with the updated host name with the D2D plugins if appropriate.
+ D2D_start_advertising_record(rr);
+#endif
+}
+
mDNSexport void mDNS_SetFQDN(mDNS *const m)
{
domainname newmname;
@@ -12676,8 +12757,8 @@ mDNSexport void mDNS_SetFQDN(mDNS *const m)
}
// 3. Make sure that any AutoTarget SRV records (and the like) get updated
- for (rr = m->ResourceRecords; rr; rr=rr->next) if (rr->AutoTarget) SetTargetToHostName(m, rr);
- for (rr = m->DuplicateRecords; rr; rr=rr->next) if (rr->AutoTarget) SetTargetToHostName(m, rr);
+ for (rr = m->ResourceRecords; rr; rr=rr->next) if (rr->AutoTarget) UpdateTargetHostName(m, rr);
+ for (rr = m->DuplicateRecords; rr; rr=rr->next) if (rr->AutoTarget) UpdateTargetHostName(m, rr);
mDNS_Unlock(m);
}
@@ -12766,7 +12847,7 @@ mDNSlocal void InitializeNetWakeState(mDNS *const m, NetworkInterfaceInfo *set)
// be stopped during interface deregistration. We can't sanity check to see if the
// question has been stopped or not before initializing it to -1 because we need to
// initialize it to -1 the very first time.
-
+
set->NetWakeBrowse.ThisQInterval = -1;
for (i=0; i<3; i++)
{
@@ -12916,6 +12997,7 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
}
LogInfo("mDNS_RegisterInterface: %s (%#a) probedelay %d", set->ifname, &set->ip, probedelay);
+
if (m->SuppressProbes == 0 ||
m->SuppressProbes - NonZeroTime(m->timenow + probedelay) < 0)
m->SuppressProbes = NonZeroTime(m->timenow + probedelay);
@@ -12942,14 +13024,8 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
if (!q->ThisQInterval || q->ThisQInterval > initial)
{
- q->ThisQInterval = initial;
-
-#if mDNS_REQUEST_UNICAST_RESPONSE
- q->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES;
-#else // mDNS_REQUEST_UNICAST_RESPONSE
- q->RequestUnicast = SET_QU_IN_FIRST_QUERY;
-#endif // mDNS_REQUEST_UNICAST_RESPONSE
-
+ q->ThisQInterval = initial;
+ q->RequestUnicast = kDefaultRequestUnicastCount;
}
q->LastQTime = m->timenow - q->ThisQInterval + qdelay;
q->RecentAnswerPkts = 0;
@@ -13235,13 +13311,17 @@ mDNSlocal void NSSCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
}
+// Derive AuthRecType from the coreFlag* values.
+// Note, this is not using the external flags values, kDNSServiceFlags*, defined in dns_sd.h.
+// It should be changed to do so once the use of coreFlag* is completely replaced with
+// the use the kDNSServiceFlags* definitions within mDNSResponder.
mDNSlocal AuthRecType setAuthRecType(mDNSInterfaceID InterfaceID, mDNSu32 flags)
{
AuthRecType artype;
if (InterfaceID == mDNSInterface_LocalOnly)
artype = AuthRecordLocalOnly;
- else if (InterfaceID == mDNSInterface_P2P)
+ else if (InterfaceID == mDNSInterface_P2P || InterfaceID == mDNSInterface_BLE)
artype = AuthRecordP2P;
else if ((InterfaceID == mDNSInterface_Any) && (flags & coreFlagIncludeP2P)
&& (flags & coreFlagIncludeAWDL))
@@ -13256,6 +13336,18 @@ mDNSlocal AuthRecType setAuthRecType(mDNSInterfaceID InterfaceID, mDNSu32 flags)
return artype;
}
+// Used to derive the original D2D specific flags specified by the client in the registration
+// when we don't have access to the original flag (kDNSServiceFlags*) values.
+mDNSexport mDNSu32 deriveD2DFlagsFromAuthRecType(AuthRecType authRecType)
+{
+ mDNSu32 flags = 0;
+ if ((authRecType == AuthRecordAnyIncludeP2P) || (authRecType == AuthRecordAnyIncludeAWDLandP2P))
+ flags |= kDNSServiceFlagsIncludeP2P;
+ else if ((authRecType == AuthRecordAnyIncludeAWDL) || (authRecType == AuthRecordAnyIncludeAWDLandP2P))
+ flags |= kDNSServiceFlagsIncludeAWDL;
+ return flags;
+}
+
// Note:
// Name is first label of domain name (any dots in the name are actual dots, not label separators)
// Type is service type (e.g. "_ipp._tcp.")
@@ -13310,8 +13402,8 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
if (mDNSIPPortIsZero(port))
return(mDNS_RegisterNoSuchService(m, &sr->RR_SRV, name, type, domain, mDNSNULL, InterfaceID, NSSCallback, sr, flags));
- // If the client is registering an oversized TXT record,
- // it is the client's responsibility to alloate a ServiceRecordSet structure that is large enough for it
+ // If the caller is registering an oversized TXT record,
+ // it is the caller's responsibility to allocate a ServiceRecordSet structure that is large enough for it
if (sr->RR_TXT.resrec.rdata->MaxRDLength < txtlen)
sr->RR_TXT.resrec.rdata->MaxRDLength = txtlen;
@@ -13349,7 +13441,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
sr->SubTypes[i].Additional1 = &sr->RR_SRV;
sr->SubTypes[i].Additional2 = &sr->RR_TXT;
}
-
+
SetAnonInfoSRS(sr, NumSubTypes);
// 3. Set up the SRV record rdata.
@@ -13409,6 +13501,7 @@ mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr,
mStatus status;
AuthRecType artype;
mDNSInterfaceID InterfaceID = sr->RR_PTR.resrec.InterfaceID;
+ ResourceRecord *rr;
artype = setAuthRecType(InterfaceID, flags);
@@ -13418,6 +13511,37 @@ mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr,
AssignDomainName(&extra->r.namestorage, sr->RR_SRV.resrec.name);
mDNS_Lock(m);
+ rr = mDNSNULL;
+ if (extra->r.resrec.rrtype == kDNSType_TXT)
+ {
+ if (sr->RR_TXT.resrec.RecordType & kDNSRecordTypeUniqueMask) rr = &sr->RR_TXT.resrec;
+ }
+ else if (extra->r.resrec.rrtype == kDNSType_SRV)
+ {
+ if (sr->RR_SRV.resrec.RecordType & kDNSRecordTypeUniqueMask) rr = &sr->RR_SRV.resrec;
+ }
+
+ if (!rr)
+ {
+ ExtraResourceRecord *srExtra;
+
+ for (srExtra = sr->Extras; srExtra; srExtra = srExtra->next)
+ {
+ if ((srExtra->r.resrec.rrtype == extra->r.resrec.rrtype) && (srExtra->r.resrec.RecordType & kDNSRecordTypeUniqueMask))
+ {
+ rr = &srExtra->r.resrec;
+ break;
+ }
+ }
+ }
+
+ if (rr && (extra->r.resrec.rroriginalttl != rr->rroriginalttl))
+ {
+ LogMsg("mDNS_AddRecordToService: Correcting TTL from %4d to %4d for %s",
+ extra->r.resrec.rroriginalttl, rr->rroriginalttl, RRDisplayString(m, &extra->r.resrec));
+ extra->r.resrec.rroriginalttl = rr->rroriginalttl;
+ }
+
e = &sr->Extras;
while (*e) e = &(*e)->next;
@@ -13593,7 +13717,7 @@ mDNSexport mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr,
if (InterfaceID == mDNSInterface_LocalOnly)
artype = AuthRecordLocalOnly;
- else if (InterfaceID == mDNSInterface_P2P)
+ else if (InterfaceID == mDNSInterface_P2P || InterfaceID == mDNSInterface_BLE)
artype = AuthRecordP2P;
else
artype = AuthRecordAny;
@@ -13820,9 +13944,9 @@ mDNSlocal void mDNSCoreReceiveRawND(mDNS *const m, const mDNSEthAddr *const sha,
}
else if (msg == msg3)
mDNSPlatformSetLocalAddressCacheEntry(m, &rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID);
- else if (msg == msg4)
+ else if (msg == msg4)
SendNDP(m, NDP_Adv, NDP_Solicited, rr, &ndp->target, mDNSNULL, spa, sha);
- else if (msg == msg5)
+ else if (msg == msg5)
SendNDP(m, NDP_Adv, 0, rr, &ndp->target, mDNSNULL, &AllHosts_v6, &AllHosts_v6_Eth);
}
}
@@ -14250,6 +14374,14 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
m->NextScheduledSPS = timenow + 0x78000000;
m->NextScheduledKA = timenow + 0x78000000;
m->NextScheduledStopTime = timenow + 0x78000000;
+ m->NextBLEServiceTime = 0; // zero indicates inactive
+
+#if BONJOUR_ON_DEMAND
+ m->NextBonjourDisableTime = 0; // Timer active when non zero.
+ m->BonjourEnabled = 0; // Set when Bonjour on Demand is enabled and Bonjour is currently enabled.
+#endif // BONJOUR_ON_DEMAND
+
+ m->DelayConflictProcessing = MAX_CONFLICT_PROCESSING_DELAYS;
m->RandomQueryDelay = 0;
m->RandomReconfirmDelay = 0;
m->PktNum = 0;
@@ -14334,19 +14466,11 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
m->WABBrowseQueriesCount = 0;
m->WABLBrowseQueriesCount = 0;
m->WABRegQueriesCount = 0;
-#if TARGET_OS_EMBEDDED || TARGET_OS_WATCH
m->AutoTargetServices = 0;
-#else
- m->AutoTargetServices = 1;
-#endif
-#if TARGET_OS_WATCH
+
+#if BONJOUR_ON_DEMAND
m->NumAllInterfaceRecords = 0;
m->NumAllInterfaceQuestions = 0;
-#else
- // Initialize to 1 for these targets to prevent not joining multicast group for interfaces when
- // both of these values are zero.
- m->NumAllInterfaceRecords = 1;
- m->NumAllInterfaceQuestions = 1;
#endif
// NAT traversal fields
m->LLQNAT.clientCallback = mDNSNULL;
@@ -14386,6 +14510,8 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
m->SPSBrowseCallback = mDNSNULL;
m->ProxyRecords = 0;
+ m->DNSPushServers = mDNSNULL;
+ m->DNSPushZones = mDNSNULL;
#endif
#if APPLE_OSX_mDNSResponder
@@ -14612,6 +14738,23 @@ mDNSlocal void SetConfigState(mDNS *const m, mDNSBool delete)
}
}
+mDNSlocal void SetDynDNSHostNameIfChanged(mDNS *const m, domainname *const fqdn)
+{
+ // Did our FQDN change?
+ if (!SameDomainName(fqdn, &m->FQDN))
+ {
+ if (m->FQDN.c[0]) mDNS_RemoveDynDNSHostName(m, &m->FQDN);
+
+ AssignDomainName(&m->FQDN, fqdn);
+
+ if (m->FQDN.c[0])
+ {
+ mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1);
+ mDNS_AddDynDNSHostName(m, &m->FQDN, DynDNSHostNameCallback, mDNSNULL);
+ }
+ }
+}
+
mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
{
mDNSu32 slot;
@@ -14642,6 +14785,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
SetConfigState(m, mDNStrue);
if (!mDNSPlatformSetDNSConfig(m, mDNStrue, mDNSfalse, &fqdn, mDNSNULL, mDNSNULL, mDNStrue))
{
+ SetDynDNSHostNameIfChanged(m, &fqdn);
SetConfigState(m, mDNSfalse);
mDNS_Unlock(m);
LogInfo("uDNS_SetupDNSConfig: No configuration change");
@@ -14818,6 +14962,14 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
PurgeOrReconfirmCacheRecord(m, cr, ptr, mDNSfalse);
}
}
+
+ // If a cache record's DNSServer pointer is NULL, but its active question got a DNSServer in this DNS configuration
+ // update, then use its DNSServer. This way, the active question and its duplicates don't miss out on RMV events.
+ if (!cr->resrec.rDNSServer && cr->CRActiveQuestion && cr->CRActiveQuestion->qDNSServer)
+ {
+ cr->resrec.rDNSServer = cr->CRActiveQuestion->qDNSServer;
+ LogInfo("uDNS_SetupDNSConfig: Using active question's DNS server %#a for cache record %s", &cr->resrec.rDNSServer->addr, CRDisplayString(m, cr));
+ }
}
while (*p)
@@ -14848,7 +15000,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
if (qptr->qDNSServer == ptr)
{
- LogMsg("uDNS_SetupDNSConfig: ERROR!! Cache Record %s Active question %##s (%s) (scope:%p) poining to DNSServer Address %#a"
+ LogMsg("uDNS_SetupDNSConfig: ERROR!! Cache Record %s Active question %##s (%s) (scope:%p) pointing to DNSServer Address %#a"
" to be freed", CRDisplayString(m, cr), qptr->qname.c, DNSTypeName(qptr->qtype), qptr->InterfaceID, &ptr->addr);
qptr->validDNSServers = zeroOpaque64;
qptr->qDNSServer = mDNSNULL;
@@ -14858,7 +15010,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
{
LogInfo("uDNS_SetupDNSConfig: Cache Record %s, Active question %##s (%s) (scope:%p), pointing to DNSServer %#a (to be deleted),"
" resetting to question's DNSServer Address %#a", CRDisplayString(m, cr), qptr->qname.c, DNSTypeName(qptr->qtype),
- qptr->InterfaceID, &ptr->addr, (qptr->qDNSServer ? &qptr->qDNSServer->addr : mDNSNULL));
+ qptr->InterfaceID, &ptr->addr, (qptr->qDNSServer) ? &qptr->qDNSServer->addr : mDNSNULL);
cr->resrec.rDNSServer = qptr->qDNSServer;
}
}
@@ -14905,19 +15057,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
RestartRecordGetZoneData(m);
}
- // Did our FQDN change?
- if (!SameDomainName(&fqdn, &m->FQDN))
- {
- if (m->FQDN.c[0]) mDNS_RemoveDynDNSHostName(m, &m->FQDN);
-
- AssignDomainName(&m->FQDN, &fqdn);
-
- if (m->FQDN.c[0])
- {
- mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1);
- mDNS_AddDynDNSHostName(m, &m->FQDN, DynDNSHostNameCallback, mDNSNULL);
- }
- }
+ SetDynDNSHostNameIfChanged(m, &fqdn);
mDNS_Unlock(m);
diff --git a/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h b/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h
index 48f8280d..3fd654eb 100755
--- a/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h
+++ b/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h
@@ -96,9 +96,9 @@ extern "C" {
#ifdef LIMITED_RESOURCES_TARGET
// Don't support jumbo frames
// 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total
-#define AbsoluteMaxDNSMessageData 1440
+#define AbsoluteMaxDNSMessageData 1440
// StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes)
-#define MaximumRDSize 264
+#define MaximumRDSize 264
#endif
// ***************************************************************************
@@ -297,20 +297,20 @@ typedef mDNSOpaque48 mDNSEthAddr; // An Ethernet address is a six-byte opa
#define bit_clr_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
#define bit_get_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
-enum
+typedef enum
{
mDNSAddrType_None = 0,
mDNSAddrType_IPv4 = 4,
mDNSAddrType_IPv6 = 6,
mDNSAddrType_Unknown = ~0 // Special marker value used in known answer list recording
-};
+} mDNSAddr_Type;
-enum
+typedef enum
{
mDNSTransport_None = 0,
mDNSTransport_UDP = 1,
mDNSTransport_TCP = 2
-};
+} mDNSTransport_Type;
typedef struct
{
@@ -364,7 +364,8 @@ enum
mStatus_NoRouter = -65566,
mStatus_PollingMode = -65567,
mStatus_Timeout = -65568,
- // -65568 to -65786 currently unused; available for allocation
+ mStatus_HostUnreachErr = -65569,
+ // -65570 to -65786 currently unused; available for allocation
// tcp connection status
mStatus_ConnPending = -65787,
@@ -808,7 +809,7 @@ typedef struct TrustAnchor
struct TrustAnchor *next;
int digestLen;
mDNSu32 validFrom;
- mDNSu32 validUntil;
+ mDNSu32 validUntil;
domainname zone;
rdataDS rds;
} TrustAnchor;
@@ -875,10 +876,10 @@ typedef packedstruct
// For example, SHA-1 hash of 20 bytes will be encoded as 20/5 * 8 = 32 base32
// bytes. For a max domain name size of 255 bytes of base32 encoding : (255/8)*5
// is the max hash length possible.
-#define NSEC3_MAX_HASH_LEN 155
+#define NSEC3_MAX_HASH_LEN 155
// In NSEC3, the names are hashed and stored in the first label and hence cannot exceed label
// size.
-#define NSEC3_MAX_B32_LEN MAX_DOMAIN_LABEL
+#define NSEC3_MAX_B32_LEN MAX_DOMAIN_LABEL
// We define it here instead of dnssec.h so that these values can be used
// in files without bringing in all of dnssec.h unnecessarily.
@@ -1307,14 +1308,6 @@ struct NATTraversalInfo_struct
enum
{
- DNSServer_Untested = 0,
- DNSServer_Passed = 1,
- DNSServer_Failed = 2,
- DNSServer_Disabled = 3
-};
-
-enum
-{
DNSServer_FlagDelete = 0x1,
DNSServer_FlagNew = 0x2,
#if APPLE_OSX_mDNSResponder
@@ -1342,8 +1335,9 @@ enum
{
kScopeNone = 0, // DNS server used by unscoped questions
kScopeInterfaceID = 1, // Scoped DNS server used only by scoped questions
- kScopeServiceID = 2 // Service specific DNS server used only by questions
+ kScopeServiceID = 2, // Service specific DNS server used only by questions
// have a matching serviceID
+ kScopesMaxCount = 3 // Max count for scopes enum
};
// Note: DNSSECAware is set if we are able to get a valid response to
@@ -1360,10 +1354,7 @@ typedef struct DNSServer
mDNSs32 serviceID;
mDNSAddr addr;
mDNSIPPort port;
- mDNSOpaque16 testid;
mDNSu32 flags; // Set when we're planning to delete this from the list
- mDNSu32 teststate; // Have we sent bug-detection query to this server?
- mDNSs32 lasttest; // Time we sent last bug-detection query to this server
domainname domain; // name->server matching for "split dns"
mDNSs32 penaltyTime; // amount of time this server is penalized
mDNSu32 scoped; // See the scoped enum above
@@ -1606,8 +1597,11 @@ struct AuthRecord_struct
#define Question_uDNS(Q) ((Q)->InterfaceID == mDNSInterface_Unicast || (Q)->ProxyQuestion || \
((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname)))
+// AuthRecordLocalOnly records are registered using mDNSInterface_LocalOnly and
+// AuthRecordP2P records are created by D2DServiceFound events. Both record types are kept on the same list.
#define RRLocalOnly(rr) ((rr)->ARType == AuthRecordLocalOnly || (rr)->ARType == AuthRecordP2P)
+// All other auth records, not including those defined as RRLocalOnly().
#define RRAny(rr) ((rr)->ARType == AuthRecordAny || (rr)->ARType == AuthRecordAnyIncludeP2P || (rr)->ARType == AuthRecordAnyIncludeAWDL || (rr)->ARType == AuthRecordAnyIncludeAWDLandP2P)
// Question (A or AAAA) that is suppressed currently because IPv4 or IPv6 address
@@ -1802,6 +1796,25 @@ enum
enum { NoAnswer_Normal = 0, NoAnswer_Suspended = 1, NoAnswer_Fail = 2 };
+// DNS Push Notification
+typedef enum
+{
+ DNSPUSH_NOERROR = 0,
+ DNSPUSH_FORMERR = 1,
+ DNSPUSH_SERVFAIL = 2,
+ DNSPUSH_NOTIMP = 4,
+ DNSPUSH_REFUSED = 5
+} DNSPUSH_ErrorCode;
+
+typedef enum {
+ DNSPUSH_INIT = 1,
+ DNSPUSH_NOSERVER = 2,
+ DNSPUSH_SERVERFOUND = 3,
+ DNSPUSH_ESTABLISHED = 4
+} DNSPush_State;
+
+
+
#define HMAC_LEN 64
#define HMAC_IPAD 0x36
#define HMAC_OPAD 0x5c
@@ -1893,6 +1906,10 @@ typedef struct
mDNSBool answered; // Has this question been answered?
} uDNSMetrics;
+
+extern mDNSu32 curr_num_regservices; // tracks the current number of services registered
+extern mDNSu32 max_num_regservices; // tracks the max number of simultaneous services registered by the device
+
#endif
struct DNSQuestion_struct
@@ -1969,6 +1986,12 @@ struct DNSQuestion_struct
// for TCP: there is some ambiguity in the use of this variable, but in general, it is
// the number of TCP/TLS connection attempts for this LLQ state, or
// the number of packets sent for this TCP/TLS connection
+
+ // DNS Push Notification fields. These fields are only meaningful when LongLived flag is set
+ DNSPush_State dnsPushState; // The state of the DNS push notification negotiation
+ mDNSAddr dnsPushServerAddr; // Address of the system acting as the DNS Push Server
+ mDNSIPPort dnsPushServerPort; // Port on which the DNS Push Server is being advertised.
+
mDNSOpaque64 id;
// DNS Proxy fields
@@ -1976,7 +1999,7 @@ struct DNSQuestion_struct
// till we populate in the cache
mDNSBool DisallowPID; // Is the query allowed for the "PID" that we are sending on behalf of ?
mDNSs32 ServiceID; // Service identifier to match against the DNS server
-
+
// Client API fields: The client must set up these fields *before* calling mDNS_StartQuery()
mDNSInterfaceID InterfaceID; // Non-zero if you want to issue queries only on a single specific IP interface
mDNSu32 flags; // flags from original DNSService*() API request.
@@ -1991,8 +2014,6 @@ struct DNSQuestion_struct
mDNSBool ForceMCast; // Set by client to force mDNS query, even for apparently uDNS names
mDNSBool ReturnIntermed; // Set by client to request callbacks for intermediate CNAME/NXDOMAIN results
mDNSBool SuppressUnusable; // Set by client to suppress unusable queries to be sent on the wire
- mDNSBool DenyOnCellInterface; // Set by client to suppress uDNS queries on cellular interface
- mDNSBool DenyOnExpInterface; // Set by client to suppress uDNS queries on expensive interface
mDNSu8 RetryWithSearchDomains; // Retry with search domains if there is no entry in the cache or AuthRecords
mDNSu8 TimeoutQuestion; // Timeout this question if there is no reply in configured time
mDNSu8 WakeOnResolve; // Send wakeup on resolve
@@ -2014,43 +2035,7 @@ struct DNSQuestion_struct
#endif
};
-typedef struct
-{
- // Client API fields: The client must set up name and InterfaceID *before* calling mDNS_StartResolveService()
- // When the callback is invoked, ip, port, TXTlen and TXTinfo will have been filled in with the results learned from the network.
- domainname name;
- mDNSInterfaceID InterfaceID; // ID of the interface the response was received on
- mDNSAddr ip; // Remote (destination) IP address where this service can be accessed
- mDNSIPPort port; // Port where this service can be accessed
- mDNSu16 TXTlen;
- mDNSu8 TXTinfo[2048]; // Additional demultiplexing information (e.g. LPR queue name)
-} ServiceInfo;
-
-// Note: Within an mDNSServiceInfoQueryCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
-typedef struct ServiceInfoQuery_struct ServiceInfoQuery;
-typedef void mDNSServiceInfoQueryCallback (mDNS *const m, ServiceInfoQuery *query);
-struct ServiceInfoQuery_struct
-{
- // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
- // No fields need to be set up by the client prior to calling mDNS_StartResolveService();
- // all required data is passed as parameters to that function.
- // The ServiceInfoQuery structure memory is working storage for mDNSCore to discover the requested information
- // and place it in the ServiceInfo structure. After the client has called mDNS_StopResolveService(), it may
- // dispose of the ServiceInfoQuery structure while retaining the results in the ServiceInfo structure.
- DNSQuestion qSRV;
- DNSQuestion qTXT;
- DNSQuestion qAv4;
- DNSQuestion qAv6;
- mDNSu8 GotSRV;
- mDNSu8 GotTXT;
- mDNSu8 GotADD;
- mDNSu32 Answers;
- ServiceInfo *info;
- mDNSServiceInfoQueryCallback *ServiceInfoQueryCallback;
- void *ServiceInfoQueryContext;
-};
-
-typedef enum { ZoneServiceUpdate, ZoneServiceQuery, ZoneServiceLLQ } ZoneService;
+typedef enum { ZoneServiceUpdate, ZoneServiceQuery, ZoneServiceLLQ, ZoneServiceDNSPush } ZoneService;
typedef void ZoneDataCallback (mDNS *const m, mStatus err, const ZoneData *result);
@@ -2276,6 +2261,26 @@ typedef struct
extern void LogMDNSStatistics(mDNS *const m);
+typedef struct mDNS_DNSPushNotificationServer DNSPushNotificationServer;
+typedef struct mDNS_DNSPushNotificationZone DNSPushNotificationZone;
+
+struct mDNS_DNSPushNotificationServer
+{
+ mDNSAddr serverAddr; // Server Address
+ tcpInfo_t *connection; // TCP Connection pointer
+ mDNSu32 numberOfQuestions; // Number of questions for this server
+ DNSPushNotificationServer *next;
+} ;
+
+struct mDNS_DNSPushNotificationZone
+{
+ domainname zoneName;
+ DNSPushNotificationServer *servers; // DNS Push Notification Servers for this zone
+ mDNSu32 numberOfQuestions; // Number of questions for this zone
+ DNSPushNotificationZone *next;
+} ;
+
+
struct mDNS_struct
{
// Internal state fields. These hold the main internal state of mDNSCore;
@@ -2320,6 +2325,11 @@ struct mDNS_struct
mDNSs32 NextScheduledNATOp; // Next time to send NAT-traversal packets
mDNSs32 NextScheduledSPS; // Next time to purge expiring Sleep Proxy records
mDNSs32 NextScheduledKA; // Next time to send Keepalive packets (SPS)
+#if BONJOUR_ON_DEMAND
+ mDNSs32 NextBonjourDisableTime; // Next time to leave multicast group if Bonjour on Demand is enabled
+ mDNSu8 BonjourEnabled; // Non zero if Bonjour is currently enabled by the Bonjour on Demand logic
+#endif // BONJOUR_ON_DEMAND
+ mDNSs32 DelayConflictProcessing; // To prevent spurious confilcts due to stale packets on the wire/air.
mDNSs32 RandomQueryDelay; // For de-synchronization of query packets on the wire
mDNSu32 RandomReconfirmDelay; // For de-synchronization of reconfirmation queries on the wire
mDNSs32 PktNum; // Unique sequence number assigned to each received packet
@@ -2348,6 +2358,7 @@ struct mDNS_struct
mDNSs32 NextScheduledStopTime; // Next time to stop a question
+ mDNSs32 NextBLEServiceTime; // Next time to call the BLE discovery management layer. Non zero when active.
// These fields only required for mDNS Searcher...
DNSQuestion *Questions; // List of all registered questions, active and inactive
@@ -2384,7 +2395,7 @@ struct mDNS_struct
mDNSs32 ProbeFailTime;
mDNSu32 NumFailedProbes;
mDNSs32 SuppressProbes;
- Platform_t mDNS_plat; // Why is this here in the “only required for mDNS Responder†section? -- SC
+ Platform_t mDNS_plat; // Why is this here in the “only required for mDNS Responder†section? -- SC
// Unicast-specific data
mDNSs32 NextuDNSEvent; // uDNS next event
@@ -2440,6 +2451,10 @@ struct mDNS_struct
mDNSu8 *UPnPRouterAddressString; // holds both the router's address and port
mDNSu8 *UPnPSOAPAddressString; // holds both address and port for SOAP messages
+ // DNS Push Notification fields
+ DNSPushNotificationServer *DNSPushServers; // DNS Push Notification Servers
+ DNSPushNotificationZone *DNSPushZones;
+
// Sleep Proxy client fields
AuthRecord *SPSRRSet; // To help the client keep track of the records registered with the sleep proxy
@@ -2472,8 +2487,13 @@ struct mDNS_struct
int notifyToken;
int uds_listener_skt; // Listening socket for incoming UDS clients. This should not be here -- it's private to uds_daemon.c and nothing to do with mDNSCore -- SC
mDNSu32 AutoTargetServices; // # of services that have AutoTarget set
- mDNSu32 NumAllInterfaceRecords; // Right now we count *all* multicast records here. Later we may want to change to count interface-specific records separately. (This count includes records on the DuplicateRecords list too.)
- mDNSu32 NumAllInterfaceQuestions; // Right now we count *all* multicast questions here. Later we may want to change to count interface-specific questions separately.
+
+#if BONJOUR_ON_DEMAND
+ // Counters used in Bonjour on Demand logic.
+ mDNSu32 NumAllInterfaceRecords; // Right now we count *all* multicast records here. Later we may want to change to count interface-specific records separately. (This count includes records on the DuplicateRecords list too.)
+ mDNSu32 NumAllInterfaceQuestions; // Right now we count *all* multicast questions here. Later we may want to change to count interface-specific questions separately.
+#endif // BONJOUR_ON_DEMAND
+
DNSSECStatistics DNSSECStats;
mDNSStatistics mDNSStats;
@@ -2501,6 +2521,9 @@ extern const mDNSInterfaceID mDNSInterface_Unicast; // Special value
extern const mDNSInterfaceID mDNSInterfaceMark; // Special value
extern const mDNSInterfaceID mDNSInterface_P2P; // Special value
extern const mDNSInterfaceID uDNSInterfaceMark; // Special value
+extern const mDNSInterfaceID mDNSInterface_BLE; // Special value
+
+#define LocalOnlyOrP2PInterface(INTERFACE) ((INTERFACE == mDNSInterface_LocalOnly) || (INTERFACE == mDNSInterface_P2P) || (INTERFACE == mDNSInterface_BLE))
extern const mDNSIPPort DiscardPort;
extern const mDNSIPPort SSHPort;
@@ -2542,6 +2565,8 @@ extern const mDNSOpaque16 DNSSecQFlags;
extern const mDNSOpaque16 ResponseFlags;
extern const mDNSOpaque16 UpdateReqFlags;
extern const mDNSOpaque16 UpdateRespFlags;
+extern const mDNSOpaque16 SubscribeFlags;
+extern const mDNSOpaque16 UnSubscribeFlags;
extern const mDNSOpaque64 zeroOpaque64;
@@ -2606,7 +2631,7 @@ mDNSinline mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v)
// Every client should call mDNS_Init, passing in storage for the mDNS object and the mDNS_PlatformSupport object.
//
// Clients that are only advertising services should use mDNS_Init_NoCache and mDNS_Init_ZeroCacheSize.
-// Clients that plan to perform queries (mDNS_StartQuery, mDNS_StartBrowse, mDNS_StartResolveService, etc.)
+// Clients that plan to perform queries (mDNS_StartQuery, mDNS_StartBrowse, etc.)
// need to provide storage for the resource record cache, or the query calls will return 'mStatus_NoCache'.
// The rrcachestorage parameter is the address of memory for the resource record cache, and
// the rrcachesize parameter is the number of entries in the CacheRecord array passed in.
@@ -2719,11 +2744,6 @@ typedef enum { mDNS_Dereg_normal, mDNS_Dereg_rapid, mDNS_Dereg_conflict, mDNS_De
// mDNS_RegisterService is a single call to register the set of resource records associated with a given named service.
//
-// mDNS_StartResolveService is single call which is equivalent to multiple calls to mDNS_StartQuery,
-// to find the IP address, port number, and demultiplexing information for a given named service.
-// As with mDNS_StartQuery, it executes asynchronously, and calls the ServiceInfoQueryCallback when the answer is
-// found. After the service is resolved, the client should call mDNS_StopResolveService to complete the transaction.
-// The client can also call mDNS_StopResolveService at any time to abort the transaction.
//
// mDNS_AddRecordToService adds an additional record to a Service Record Set. This record may be deregistered
// via mDNS_RemoveRecordFromService, or by deregistering the service. mDNS_RemoveRecordFromService is passed a
@@ -2753,6 +2773,7 @@ enum
coreFlagWakeOnly = 0x8 // Service won't be registered with sleep proxy
};
+extern mDNSu32 deriveD2DFlagsFromAuthRecType(AuthRecType authRecType);
extern mStatus mDNS_RegisterService (mDNS *const m, ServiceRecordSet *sr,
const domainlabel *const name, const domainname *const type, const domainname *const domain,
const domainname *const host, mDNSIPPort port, const mDNSu8 txtinfo[], mDNSu16 txtlen,
@@ -2780,8 +2801,6 @@ extern mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
mDNSQuestionCallback *Callback, void *Context);
#define mDNS_StopBrowse mDNS_StopQuery
-extern mStatus mDNS_StartResolveService(mDNS *const m, ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context);
-extern void mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *query);
typedef enum
{
@@ -2824,7 +2843,7 @@ extern mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question);
// because that object is defined to be 256 bytes long, but not all domainname objects are truly the full size.
// This macro uses mDNSPlatformMemCopy() to make sure it only touches the actual bytes that are valid.
#define AssignDomainName(DST, SRC) do { mDNSu16 len__ = DomainNameLength((SRC)); \
- if (len__ <= MAX_DOMAIN_NAME) mDNSPlatformMemCopy((DST)->c, (SRC)->c, len__);else (DST)->c[0] = 0;} while(0)
+ if (len__ <= MAX_DOMAIN_NAME) mDNSPlatformMemCopy((DST)->c, (SRC)->c, len__); else (DST)->c[0] = 0; } while(0)
// Comparison functions
#define SameDomainLabelCS(A,B) ((A)[0] == (B)[0] && mDNSPlatformMemSame((A)+1, (B)+1, (A)[0]))
@@ -2906,7 +2925,7 @@ extern mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel
// then the output will be truncated by one character to allow space for the terminating null.
// Unlike standard C vsnprintf/snprintf, they return the number of characters *actually* written,
// not the number of characters that *would* have been printed were buflen unlimited.
-extern mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va_list arg);
+extern mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va_list arg) IS_A_PRINTF_STYLE_FUNCTION(3,0);
extern mDNSu32 mDNS_snprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
extern mDNSu32 NumCacheRecordsForInterfaceID(const mDNS *const m, mDNSInterfaceID id);
extern char *DNSTypeName(mDNSu16 rrtype);
@@ -3095,14 +3114,14 @@ extern mDNSBool DNSDigest_VerifyMessage(DNSMessage *msg, mDNSu8 *end, LargeCache
extern mStatus mDNSPlatformInit (mDNS *const m);
extern void mDNSPlatformClose (mDNS *const m);
extern mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
- mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
+ mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
mDNSIPPort dstport, mDNSBool useBackgroundTrafficClass);
-extern mDNSBool mDNSPlatformPeekUDP (mDNS *const m, UDPSocket *src);
extern void mDNSPlatformLock (const mDNS *const m);
extern void mDNSPlatformUnlock (const mDNS *const m);
extern void mDNSPlatformStrCopy ( void *dst, const void *src);
+extern mDNSu32 mDNSPlatformStrLCopy ( void *dst, const void *src, mDNSu32 len);
extern mDNSu32 mDNSPlatformStrLen ( const void *src);
extern void mDNSPlatformMemCopy ( void *dst, const void *src, mDNSu32 len);
extern mDNSBool mDNSPlatformMemSame (const void *dst, const void *src, mDNSu32 len);
@@ -3199,7 +3218,8 @@ extern void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNS
extern mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti);
extern mStatus mDNSPlatformGetRemoteMacAddr(mDNS *const m, mDNSAddr *raddr);
extern mStatus mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname);
-extern mStatus mDNSPlatformClearSPSMACAddr(void);
+extern mStatus mDNSPlatformClearSPSData(void);
+extern mStatus mDNSPlatformStoreOwnerOptRecord(char *ifname, DNSMessage *msg, int length);
// mDNSPlatformTLSSetupCerts/mDNSPlatformTLSTearDownCerts used by dnsextd
extern mStatus mDNSPlatformTLSSetupCerts(void);
@@ -3220,7 +3240,7 @@ extern void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID In
extern mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID);
extern mDNSBool mDNSPlatformInterfaceIsAWDL(const NetworkInterfaceInfo *intf);
extern mDNSBool mDNSPlatformValidRecordForQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
-extern mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf);
+extern mDNSBool mDNSPlatformValidRecordForInterface(const AuthRecord *rr, mDNSInterfaceID InterfaceID);
extern mDNSBool mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf);
extern void mDNSPlatformFormatTime(unsigned long t, mDNSu8 *buf, int bufsize);
@@ -3315,7 +3335,7 @@ extern void RetrySearchDomainQuestions(mDNS *const m);
extern mDNSBool DomainEnumQuery(const domainname *qname);
extern mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSBool updateMac, char *ethAddr);
extern void UpdateKeepaliveRMACAsync(mDNS *const m, void *context);
-extern void UpdateRMACCallback(mDNS *const m, void *context);
+extern void UpdateRMAC(mDNS *const m, void *context);
// Used only in logging to restrict the number of /etc/hosts entries printed
extern void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result);
@@ -3353,16 +3373,13 @@ extern void mDNSPlatformCloseDNSProxySkts(mDNS *const m);
extern void mDNSPlatformDisposeProxyContext(void *context);
extern mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *start, mDNSu8 *limit);
-// Sleep Assertions are specific to Mac OS X
#if APPLE_OSX_mDNSResponder
-extern void mDNSPlatformSleepAssertion(mDNS *const m, double timeout);
-#endif
-
extern void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isBlocked);
-extern void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q);
+#endif
+extern void mDNSPlatformSetSocktOpt(void *sock, mDNSTransport_Type transType, mDNSAddr_Type addrType, DNSQuestion *q);
extern mDNSs32 mDNSPlatformGetPID(void);
extern mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr);
-
+
// ***************************************************************************
#if 0
#pragma mark -
@@ -3578,18 +3595,17 @@ struct CompileTimeAssertionChecks_mDNS
char sizecheck_AuthRecord [(sizeof(AuthRecord) <= 1208) ? 1 : -1];
char sizecheck_CacheRecord [(sizeof(CacheRecord) <= 232) ? 1 : -1];
char sizecheck_CacheGroup [(sizeof(CacheGroup) <= 232) ? 1 : -1];
- char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 864) ? 1 : -1];
+ char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 894) ? 1 : -1];
- char sizecheck_ZoneData [(sizeof(ZoneData) <= 1700) ? 1 : -1];
+ char sizecheck_ZoneData [(sizeof(ZoneData) <= 1730) ? 1 : -1];
char sizecheck_NATTraversalInfo [(sizeof(NATTraversalInfo) <= 200) ? 1 : -1];
char sizecheck_HostnameInfo [(sizeof(HostnameInfo) <= 3050) ? 1 : -1];
- char sizecheck_DNSServer [(sizeof(DNSServer) <= 340) ? 1 : -1];
- char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 7184) ? 1 : -1];
+ char sizecheck_DNSServer [(sizeof(DNSServer) <= 330) ? 1 : -1];
+ char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 7272) ? 1 : -1];
char sizecheck_ServiceRecordSet [(sizeof(ServiceRecordSet) <= 5540) ? 1 : -1];
char sizecheck_DomainAuthInfo [(sizeof(DomainAuthInfo) <= 7888) ? 1 : -1];
- char sizecheck_ServiceInfoQuery [(sizeof(ServiceInfoQuery) <= 3488) ? 1 : -1];
#if APPLE_OSX_mDNSResponder
- char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1208) ? 1 : -1];
+ char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1230) ? 1 : -1];
#endif
};
@@ -3599,10 +3615,57 @@ mDNSu32 initializeDeviceInfoTXT(mDNS *m, mDNSu8 *ptr);
#if APPLE_OSX_mDNSResponder
extern void D2D_start_advertising_interface(NetworkInterfaceInfo *interface);
extern void D2D_stop_advertising_interface(NetworkInterfaceInfo *interface);
+extern void D2D_start_advertising_record(AuthRecord *ar);
+extern void D2D_stop_advertising_record(AuthRecord *ar);
+#else
+#define D2D_start_advertising_interface(X)
+#define D2D_stop_advertising_interface(X)
+#define D2D_start_advertising_record(X)
+#define D2D_stop_advertising_record(X)
#endif
// ***************************************************************************
+#ifdef __rtems__
+typedef struct
+{
+ // Client API fields: The client must set up name and InterfaceID *before* calling mDNS_StartResolveService()
+ // When the callback is invoked, ip, port, TXTlen and TXTinfo will have been filled in with the results learned from the network.
+ domainname name;
+ mDNSInterfaceID InterfaceID; // ID of the interface the response was received on
+ mDNSAddr ip; // Remote (destination) IP address where this service can be accessed
+ mDNSIPPort port; // Port where this service can be accessed
+ mDNSu16 TXTlen;
+ mDNSu8 TXTinfo[2048]; // Additional demultiplexing information (e.g. LPR queue name)
+} ServiceInfo;
+
+// Note: Within an mDNSServiceInfoQueryCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
+typedef struct ServiceInfoQuery_struct ServiceInfoQuery;
+typedef void mDNSServiceInfoQueryCallback (mDNS *const m, ServiceInfoQuery *query);
+struct ServiceInfoQuery_struct
+{
+ // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
+ // No fields need to be set up by the client prior to calling mDNS_StartResolveService();
+ // all required data is passed as parameters to that function.
+ // The ServiceInfoQuery structure memory is working storage for mDNSCore to discover the requested information
+ // and place it in the ServiceInfo structure. After the client has called mDNS_StopResolveService(), it may
+ // dispose of the ServiceInfoQuery structure while retaining the results in the ServiceInfo structure.
+ DNSQuestion qSRV;
+ DNSQuestion qTXT;
+ DNSQuestion qAv4;
+ DNSQuestion qAv6;
+ mDNSu8 GotSRV;
+ mDNSu8 GotTXT;
+ mDNSu8 GotADD;
+ mDNSu32 Answers;
+ ServiceInfo *info;
+ mDNSServiceInfoQueryCallback *ServiceInfoQueryCallback;
+ void *ServiceInfoQueryContext;
+};
+
+extern mStatus mDNS_StartResolveService(mDNS *const m, ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context);
+extern void mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *query);
+#endif /* __rtems__ */
#ifdef __cplusplus
}
#endif
diff --git a/mDNSResponder/mDNSCore/nsec3.c b/mDNSResponder/mDNSCore/nsec3.c
index c16a42d5..4e9e8c82 100644
--- a/mDNSResponder/mDNSCore/nsec3.c
+++ b/mDNSResponder/mDNSCore/nsec3.c
@@ -238,7 +238,7 @@ mDNSlocal mDNSBool NSEC3Find(mDNS *const m, NSEC3FindValues val, CacheRecord *nc
name = SkipLeadingLabels(origName, i);
if (!NSEC3HashName(name, nsec3, mDNSNULL, 0, hashName, &hlen))
{
- LogMsg("NSEC3Find: NSEC3HashName failed for ##s", name->c);
+ LogMsg("NSEC3Find: NSEC3HashName failed for %##s", name->c);
continue;
}
@@ -708,7 +708,7 @@ mDNSexport CacheRecord *NSEC3RecordIsDelegation(mDNS *const m, domainname *name,
if (!NSEC3HashName(name, nsec3, mDNSNULL, 0, hashName, &hlen))
{
- LogMsg("NSEC3RecordIsDelegation: NSEC3HashName failed for ##s", name->c);
+ LogMsg("NSEC3RecordIsDelegation: NSEC3HashName failed for %##s", name->c);
return mDNSNULL;
}
diff --git a/mDNSResponder/mDNSCore/uDNS.c b/mDNSResponder/mDNSCore/uDNS.c
index 3ba88b5c..694c745c 100755
--- a/mDNSResponder/mDNSCore/uDNS.c
+++ b/mDNSResponder/mDNSCore/uDNS.c
@@ -124,7 +124,7 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons
return mDNSNULL;
}
- if (!d)
+ if (!d)
d = (const domainname *)"";
LogInfo("mDNS_AddDNSServer(%d): Adding %#a for %##s, InterfaceID %p, serviceID %u, scoped %d, resGroupID %d req_A is %s req_AAAA is %s cell %s req_DO is %s",
@@ -135,11 +135,11 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons
while (*p) // Check if we already have this {interface,address,port,domain} tuple registered + reqA/reqAAAA bits
{
- if ((*p)->scoped == scoped && (*p)->interface == interface && (*p)->serviceID == serviceID && (*p)->teststate != DNSServer_Disabled &&
- mDNSSameAddress(&(*p)->addr, addr) && mDNSSameIPPort((*p)->port, port) && SameDomainName(&(*p)->domain, d) &&
+ if ((*p)->scoped == scoped && (*p)->interface == interface && (*p)->serviceID == serviceID &&
+ mDNSSameAddress(&(*p)->addr, addr) && mDNSSameIPPort((*p)->port, port) && SameDomainName(&(*p)->domain, d) &&
(*p)->req_A == reqA && (*p)->req_AAAA == reqAAAA)
{
- if (!((*p)->flags & DNSServer_FlagDelete))
+ if (!((*p)->flags & DNSServer_FlagDelete))
debugf("Note: DNS Server %#a:%d for domain %##s (%p) registered more than once", addr, mDNSVal16(port), d->c, interface);
tmp = *p;
*p = tmp->next;
@@ -192,8 +192,6 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons
(*p)->addr = *addr;
(*p)->port = port;
(*p)->flags = DNSServer_FlagNew;
- (*p)->teststate = /* DNSServer_Untested */ DNSServer_Passed;
- (*p)->lasttest = m->timenow - INIT_UCAST_POLL_INTERVAL;
(*p)->timeout = timeout;
(*p)->cellIntf = cellIntf;
(*p)->req_A = reqA;
@@ -208,11 +206,13 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons
(*p)->next = mDNSNULL;
}
}
- (*p)->penaltyTime = 0;
- // We always update the ID (not just when we allocate a new instance) because we could
- // be adding a new non-scoped resolver with a new ID and we want all the non-scoped
- // resolvers belong to the same group.
- (*p)->resGroupID = resGroupID;
+ if (*p) {
+ (*p)->penaltyTime = 0;
+ // We always update the ID (not just when we allocate a new instance) because we could
+ // be adding a new non-scoped resolver with a new ID and we want all the non-scoped
+ // resolvers belong to the same group.
+ (*p)->resGroupID = resGroupID;
+ }
return(*p);
}
@@ -224,7 +224,7 @@ mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 re
DNSServer *new;
DNSServer *orig = q->qDNSServer;
mDNSu8 rcode = '\0';
-
+
mDNS_CheckLock(m);
LogInfo("PenalizeDNSServer: Penalizing DNS server %#a question for question %p %##s (%s) SuppressUnusable %d",
@@ -234,11 +234,11 @@ mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 re
// return the error, then return the first error.
if (mDNSOpaque16IsZero(q->responseFlags))
q->responseFlags = responseFlags;
-
+
rcode = (mDNSu8)(responseFlags.b[1] & kDNSFlag1_RC_Mask);
// After we reset the qDNSServer to NULL, we could get more SERV_FAILS that might end up
- // peanlizing again.
+ // penalizing again.
if (!q->qDNSServer)
goto end;
@@ -482,7 +482,7 @@ mDNSexport mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
mDNSlocal mStatus uDNS_RequestAddress(mDNS *m)
{
mStatus err = mStatus_NoError;
-
+
if (!m->NATTraversals)
{
m->retryGetAddr = NonZeroTime(m->timenow + 0x78000000);
@@ -497,7 +497,7 @@ mDNSlocal mStatus uDNS_RequestAddress(mDNS *m)
mDNSu8* end = start + sizeof(NATAddrRequest);
err = mDNSPlatformSendUDP(m, start, end, 0, mDNSNULL, &m->Router, NATPMPPort, mDNSfalse);
debugf("uDNS_RequestAddress: Sent NAT-PMP external address request %d", err);
-
+
#ifdef _LEGACY_NAT_TRAVERSAL_
if (mDNSIPPortIsZero(m->UPnPRouterPort) || mDNSIPPortIsZero(m->UPnPSOAPPort))
{
@@ -509,7 +509,7 @@ mDNSlocal mStatus uDNS_RequestAddress(mDNS *m)
mStatus lnterr = LNT_GetExternalAddress(m);
if (lnterr)
LogMsg("uDNS_RequestAddress: LNT_GetExternalAddress returned error %d", lnterr);
-
+
err = err ? err : lnterr; // NAT-PMP error takes precedence
}
#endif // _LEGACY_NAT_TRAVERSAL_
@@ -554,7 +554,7 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool useP
LogMsg("uDNS_SendNATMsg called unexpectedly with NULL info");
return mStatus_BadParamErr;
}
-
+
// send msg if the router's address is private (which means it's non-zero)
if (mDNSv4AddrIsRFC1918(&m->Router.ip.v4))
{
@@ -567,7 +567,7 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool useP
static NATPortMapRequest NATPortReq;
static const mDNSu8* end = (mDNSu8 *)&NATPortReq + sizeof(NATPortMapRequest);
mDNSu8 *p = (mDNSu8 *)&NATPortReq.NATReq_lease;
-
+
NATPortReq.vers = NATMAP_VERS;
NATPortReq.opcode = info->Protocol;
NATPortReq.unused = zeroID;
@@ -577,7 +577,7 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool useP
p[1] = (mDNSu8)((info->NATLease >> 16) & 0xFF);
p[2] = (mDNSu8)((info->NATLease >> 8) & 0xFF);
p[3] = (mDNSu8)( info->NATLease & 0xFF);
-
+
err = mDNSPlatformSendUDP(m, (mDNSu8 *)&NATPortReq, end, 0, mDNSNULL, &m->Router, NATPMPPort, mDNSfalse);
debugf("uDNS_SendNATMsg: Sent NAT-PMP mapping request %d", err);
}
@@ -604,31 +604,31 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool useP
mDNSu8* start = (mDNSu8*)&req;
mDNSu8* end = start + sizeof(req);
mDNSu8* p = (mDNSu8*)&req.lifetime;
-
+
req.version = PCP_VERS;
req.opCode = PCPOp_Map;
req.reserved = zeroID;
-
+
p[0] = (mDNSu8)((info->NATLease >> 24) & 0xFF);
p[1] = (mDNSu8)((info->NATLease >> 16) & 0xFF);
p[2] = (mDNSu8)((info->NATLease >> 8) & 0xFF);
p[3] = (mDNSu8)( info->NATLease & 0xFF);
-
+
mDNSAddrMapIPv4toIPv6(&m->AdvertisedV4.ip.v4, &req.clientAddr);
-
+
req.nonce[0] = m->PCPNonce[0];
req.nonce[1] = m->PCPNonce[1];
req.nonce[2] = m->PCPNonce[2];
-
+
req.protocol = (info->Protocol == NATOp_MapUDP ? PCPProto_UDP : PCPProto_TCP);
-
+
req.reservedMapOp[0] = 0;
req.reservedMapOp[1] = 0;
req.reservedMapOp[2] = 0;
-
+
req.intPort = info->Protocol ? info->IntPort : DiscardPort;
req.extPort = info->RequestedPort;
-
+
// Since we only support IPv4, even if using the all-zeros address, map it, so
// the PCP gateway will give us an IPv4 address & not an IPv6 address.
mDNSAddrMapIPv4toIPv6(&info->NewAddress, &req.extAddress);
@@ -654,7 +654,7 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool useP
mStatus lnterr = LNT_MapPort(m, info);
if (lnterr)
LogMsg("uDNS_SendNATMsg: LNT_MapPort returned error %d", lnterr);
-
+
err = err ? err : lnterr; // PCP error takes precedence
}
#endif // _LEGACY_NAT_TRAVERSAL_
@@ -727,7 +727,7 @@ mDNSexport void natTraversalHandleAddressReply(mDNS *const m, mDNSu16 err, mDNSv
m->NextScheduledNATOp = m->retryGetAddr;
last_err = err;
-
+
for (n = m->NATTraversals; n; n=n->next)
{
// We should change n->NewAddress only when n is one of:
@@ -924,7 +924,7 @@ mDNSexport mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *tra
{
traversal->NATLease = 0;
traversal->retryInterval = 0;
-
+
// In case we most recently sent NAT-PMP, we need to set sentNATPMP to false so
// that we'll send a NAT-PMP request to destroy the mapping. We do this because
// the NATTraversal struct has already been cut from the list, and the client
@@ -940,7 +940,7 @@ mDNSexport mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *tra
// would have requested an IPv4 address.
traversal->RequestedPort = zeroIPPort;
traversal->NewAddress = zerov4Addr;
-
+
uDNS_SendNATMsg(m, traversal, traversal->lastSuccessfulProtocol != NATTProtocolNATPMP);
}
@@ -1573,6 +1573,7 @@ mDNSlocal tcpInfo_t *MakeTCPConn(mDNS *const m, const DNSMessage *const msg, con
}
if (!info->sock) { LogMsg("MakeTCPConn: unable to create TCP socket"); mDNSPlatformMemFree(info); return(mDNSNULL); }
+ mDNSPlatformSetSocktOpt(info->sock, mDNSTransport_TCP, Addr->type, question);
err = mDNSPlatformTCPConnect(info->sock, Addr, Port, hostname, (question ? question->InterfaceID : mDNSNULL), tcpCallback, info);
// Probably suboptimal here.
@@ -1703,6 +1704,7 @@ mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q)
}
}
+
// forward declaration so GetServiceTarget can do reverse lookup if needed
mDNSlocal void GetStaticHostname(mDNS *m);
@@ -1754,11 +1756,13 @@ mDNSlocal const domainname *PUBLIC_LLQ_SERVICE_TYPE = (const domainname*)"\x
mDNSlocal const domainname *PRIVATE_UPDATE_SERVICE_TYPE = (const domainname*)"\x0F_dns-update-tls" "\x04_tcp";
mDNSlocal const domainname *PRIVATE_QUERY_SERVICE_TYPE = (const domainname*)"\x0E_dns-query-tls" "\x04_tcp";
mDNSlocal const domainname *PRIVATE_LLQ_SERVICE_TYPE = (const domainname*)"\x0C_dns-llq-tls" "\x04_tcp";
+mDNSlocal const domainname *DNS_PUSH_NOTIFICATION_SERVICE_TYPE = (const domainname*)"\x0C_dns-push-tls" "\x04_tcp";
#define ZoneDataSRV(X) ( \
- (X)->ZoneService == ZoneServiceUpdate ? ((X)->ZonePrivate ? PRIVATE_UPDATE_SERVICE_TYPE : PUBLIC_UPDATE_SERVICE_TYPE) : \
- (X)->ZoneService == ZoneServiceQuery ? ((X)->ZonePrivate ? PRIVATE_QUERY_SERVICE_TYPE : (const domainname*)"" ) : \
- (X)->ZoneService == ZoneServiceLLQ ? ((X)->ZonePrivate ? PRIVATE_LLQ_SERVICE_TYPE : PUBLIC_LLQ_SERVICE_TYPE ) : (const domainname*)"")
+ (X)->ZoneService == ZoneServiceUpdate ? ((X)->ZonePrivate ? PRIVATE_UPDATE_SERVICE_TYPE : PUBLIC_UPDATE_SERVICE_TYPE) : \
+ (X)->ZoneService == ZoneServiceQuery ? ((X)->ZonePrivate ? PRIVATE_QUERY_SERVICE_TYPE : (const domainname*)"" ) : \
+ (X)->ZoneService == ZoneServiceLLQ ? ((X)->ZonePrivate ? PRIVATE_LLQ_SERVICE_TYPE : PUBLIC_LLQ_SERVICE_TYPE ) : \
+ (X)->ZoneService == ZoneServiceDNSPush ? DNS_PUSH_NOTIFICATION_SERVICE_TYPE : (const domainname*)"")
// Forward reference: GetZoneData_StartQuery references GetZoneData_QuestionCallback, and
// GetZoneData_QuestionCallback calls GetZoneData_StartQuery
@@ -1886,7 +1890,7 @@ mDNSlocal mStatus GetZoneData_StartQuery(mDNS *const m, ZoneData *zd, mDNSu16 qt
zd->question.InterfaceID = mDNSInterface_Any;
zd->question.flags = 0;
zd->question.Target = zeroAddr;
- //zd->question.qname.c[0] = 0; // Already set
+ //zd->question.qname.c[0] = 0; // Already set
zd->question.qtype = qtype;
zd->question.qclass = kDNSClass_IN;
zd->question.LongLived = mDNSfalse;
@@ -1894,8 +1898,6 @@ mDNSlocal mStatus GetZoneData_StartQuery(mDNS *const m, ZoneData *zd, mDNSu16 qt
zd->question.ForceMCast = mDNSfalse;
zd->question.ReturnIntermed = mDNStrue;
zd->question.SuppressUnusable = mDNSfalse;
- zd->question.DenyOnCellInterface = mDNSfalse;
- zd->question.DenyOnExpInterface = mDNSfalse;
zd->question.SearchListIndex = 0;
zd->question.AppendSearchDomains = 0;
zd->question.RetryWithSearchDomains = mDNSfalse;
@@ -2171,7 +2173,7 @@ mDNSlocal void StartRecordNatMap(mDNS *m, AuthRecord *rr)
else { LogMsg("StartRecordNatMap: could not determine transport protocol of service %##s", rr->resrec.name->c); return; }
//LogMsg("StartRecordNatMap: clientContext %p IntPort %d srv.port %d %s",
- // rr->NATinfo.clientContext, mDNSVal16(rr->NATinfo.IntPort), mDNSVal16(rr->resrec.rdata->u.srv.port), ARDisplayString(m, rr));
+ // rr->NATinfo.clientContext, mDNSVal16(rr->NATinfo.IntPort), mDNSVal16(rr->resrec.rdata->u.srv.port), ARDisplayString(m, rr));
if (rr->NATinfo.clientContext) mDNS_StopNATOperation_internal(m, &rr->NATinfo);
rr->NATinfo.Protocol = protocol;
@@ -2584,8 +2586,6 @@ mDNSlocal void GetStaticHostname(mDNS *m)
q->ForceMCast = mDNSfalse;
q->ReturnIntermed = mDNStrue;
q->SuppressUnusable = mDNSfalse;
- q->DenyOnCellInterface = mDNSfalse;
- q->DenyOnExpInterface = mDNSfalse;
q->SearchListIndex = 0;
q->AppendSearchDomains = 0;
q->RetryWithSearchDomains = mDNSfalse;
@@ -2645,12 +2645,30 @@ mDNSexport void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn)
// below could free the memory, and we have to make sure we don't touch hi fields after that.
mDNSBool f4 = hi->arv4.resrec.RecordType != kDNSRecordTypeUnregistered && hi->arv4.state != regState_Unregistered;
mDNSBool f6 = hi->arv6.resrec.RecordType != kDNSRecordTypeUnregistered && hi->arv6.state != regState_Unregistered;
- if (f4) LogInfo("mDNS_RemoveDynDNSHostName removing v4 %##s", fqdn);
- if (f6) LogInfo("mDNS_RemoveDynDNSHostName removing v6 %##s", fqdn);
*ptr = (*ptr)->next; // unlink
- if (f4) mDNS_Deregister_internal(m, &hi->arv4, mDNS_Dereg_normal);
- if (f6) mDNS_Deregister_internal(m, &hi->arv6, mDNS_Dereg_normal);
- // When both deregistrations complete we'll free the memory in the mStatus_MemFree callback
+ if (f4 || f6)
+ {
+ if (f4)
+ {
+ LogInfo("mDNS_RemoveDynDNSHostName removing v4 %##s", fqdn);
+ mDNS_Deregister_internal(m, &hi->arv4, mDNS_Dereg_normal);
+ }
+ if (f6)
+ {
+ LogInfo("mDNS_RemoveDynDNSHostName removing v6 %##s", fqdn);
+ mDNS_Deregister_internal(m, &hi->arv6, mDNS_Dereg_normal);
+ }
+ // When both deregistrations complete we'll free the memory in the mStatus_MemFree callback
+ }
+ else
+ {
+ if (hi->natinfo.clientContext)
+ {
+ mDNS_StopNATOperation_internal(m, &hi->natinfo);
+ hi->natinfo.clientContext = mDNSNULL;
+ }
+ mDNSPlatformMemFree(hi);
+ }
}
mDNS_CheckLock(m);
m->NextSRVUpdate = NonZeroTime(m->timenow);
@@ -3621,13 +3639,13 @@ mDNSlocal void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interface
// Minimum NAT-PMP packet is vers (1) opcode (1) + err (2) = 4 bytes
if (len < 4) { LogMsg("NAT-PMP message too short (%d bytes)", len); return; }
-
+
// Read multi-byte error value (field is identical in a NATPortMapReply)
AddrReply->err = (mDNSu16) ((mDNSu16)pkt[2] << 8 | pkt[3]);
-
+
if (AddrReply->err == NATErr_Vers)
{
- NATTraversalInfo *n;
+ NATTraversalInfo *n;
LogInfo("NAT-PMP version unsupported message received");
for (n = m->NATTraversals; n; n=n->next)
{
@@ -3635,7 +3653,7 @@ mDNSlocal void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interface
// and update the state variables
uDNS_SendNATMsg(m, n, mDNSfalse);
}
-
+
m->NextScheduledNATOp = m->timenow;
return;
@@ -3649,7 +3667,7 @@ mDNSlocal void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interface
LogMsg("NAT-PMP message too short (%d bytes) 0x%X 0x%X", len, AddrReply->opcode, AddrReply->err);
return;
}
-
+
// Read multi-byte upseconds value (field is identical in a NATPortMapReply)
AddrReply->upseconds = (mDNSs32) ((mDNSs32)pkt[4] << 24 | (mDNSs32)pkt[5] << 16 | (mDNSs32)pkt[6] << 8 | pkt[7]);
@@ -3726,16 +3744,16 @@ mDNSlocal void uDNS_ReceivePCPPacket(mDNS *m, const mDNSInterfaceID InterfaceID,
mDNSu8 protocol = 0;
mDNSIPPort intport = zeroIPPort;
mDNSIPPort extport = zeroIPPort;
-
+
// Minimum PCP packet is 24 bytes
if (len < 24)
{
LogMsg("uDNS_ReceivePCPPacket: message too short (%d bytes)", len);
return;
}
-
+
strippedOpCode = reply->opCode & 0x7f;
-
+
if ((reply->opCode & 0x80) == 0x00 || (strippedOpCode != PCPOp_Announce && strippedOpCode != PCPOp_Map))
{
LogMsg("uDNS_ReceivePCPPacket: unhandled opCode %u", reply->opCode);
@@ -3774,11 +3792,11 @@ mDNSlocal void uDNS_ReceivePCPPacket(mDNS *m, const mDNSInterfaceID InterfaceID,
if (strippedOpCode == PCPOp_Announce)
return;
-
+
// We globally keep track of the most recent error code for mappings.
// This seems bad to do with PCP, but best not change it now.
m->LastNATMapResultCode = reply->result;
-
+
if (!reply->result)
{
if (len < sizeof(PCPMapReply))
@@ -3786,7 +3804,7 @@ mDNSlocal void uDNS_ReceivePCPPacket(mDNS *m, const mDNSInterfaceID InterfaceID,
LogMsg("uDNS_ReceivePCPPacket: mapping response too short (%d bytes)", len);
return;
}
-
+
// Check the nonce
if (reply->nonce[0] != m->PCPNonce[0] || reply->nonce[1] != m->PCPNonce[1] || reply->nonce[2] != m->PCPNonce[2])
{
@@ -3825,7 +3843,7 @@ mDNSlocal void uDNS_ReceivePCPPacket(mDNS *m, const mDNSInterfaceID InterfaceID,
{
LogInfo("uDNS_ReceivePCPPacket: error received from server. opcode %X result %X lifetime %X epoch %X",
reply->opCode, reply->result, reply->lifetime, reply->epoch);
-
+
// If the packet is long enough, get the protocol & intport for matching to report
// the error
if (len >= sizeof(PCPMapReply))
@@ -3858,135 +3876,6 @@ mDNSexport void uDNS_ReceiveNATPacket(mDNS *m, const mDNSInterfaceID InterfaceID
LogMsg("uDNS_ReceiveNATPacket: packet with version %u (expected %u or %u)", pkt[0], PCP_VERS, NATMAP_VERS);
}
-// <rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs
-// <rdar://problem/4288449> Add check to avoid crashing NAT gateways that have buggy DNS relay code
-//
-// We know of bugs in home NAT gateways that cause them to crash if they receive certain DNS queries.
-// The DNS queries that make them crash are perfectly legal DNS queries, but even if they weren't,
-// the gateway shouldn't crash -- in today's world of viruses and network attacks, software has to
-// be written assuming that a malicious attacker could send them any packet, properly-formed or not.
-// Still, we don't want to be crashing people's home gateways, so we go out of our way to avoid
-// the queries that crash them.
-//
-// Some examples:
-//
-// 1. Any query where the name ends in ".in-addr.arpa." and the text before this is 32 or more bytes.
-// The query type does not need to be PTR -- the gateway will crash for any query type.
-// e.g. "ping long-name-crashes-the-buggy-router.in-addr.arpa" will crash one of these.
-//
-// 2. Any query that results in a large response with the TC bit set.
-//
-// 3. Any PTR query that doesn't begin with four decimal numbers.
-// These gateways appear to assume that the only possible PTR query is a reverse-mapping query
-// (e.g. "1.0.168.192.in-addr.arpa") and if they ever get a PTR query where the first four
-// labels are not all decimal numbers in the range 0-255, they handle that by crashing.
-// These gateways also ignore the remainder of the name following the four decimal numbers
-// -- whether or not it actually says in-addr.arpa, they just make up an answer anyway.
-//
-// The challenge therefore is to craft a query that will discern whether the DNS server
-// is one of these buggy ones, without crashing it. Furthermore we don't want our test
-// queries making it all the way to the root name servers, putting extra load on those
-// name servers and giving Apple a bad reputation. To this end we send this query:
-// dig -t ptr 1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
-//
-// The text preceding the ".in-addr.arpa." is under 32 bytes, so it won't cause crash (1).
-// It will not yield a large response with the TC bit set, so it won't cause crash (2).
-// It starts with four decimal numbers, so it won't cause crash (3).
-// The name falls within the "1.0.0.127.in-addr.arpa." domain, the reverse-mapping name for the local
-// loopback address, and therefore the query will black-hole at the first properly-configured DNS server
-// it reaches, making it highly unlikely that this query will make it all the way to the root.
-//
-// Finally, the correct response to this query is NXDOMAIN or a similar error, but the
-// gateways that ignore the remainder of the name following the four decimal numbers
-// give themselves away by actually returning a result for this nonsense query.
-
-mDNSlocal const domainname *DNSRelayTestQuestion = (const domainname*)
- "\x1" "1" "\x1" "0" "\x1" "0" "\x3" "127" "\xa" "dnsbugtest"
- "\x1" "1" "\x1" "0" "\x1" "0" "\x3" "127" "\x7" "in-addr" "\x4" "arpa";
-
-// See comments above for DNSRelayTestQuestion
-// If this is the kind of query that has the risk of crashing buggy DNS servers, we do a test question first
-mDNSlocal mDNSBool NoTestQuery(DNSQuestion *q)
-{
- int i;
- mDNSu8 *p = q->qname.c;
- if (q->AuthInfo) return(mDNStrue); // Don't need a test query for private queries sent directly to authoritative server over TLS/TCP
- if (q->qtype != kDNSType_PTR) return(mDNStrue); // Don't need a test query for any non-PTR queries
- for (i=0; i<4; i++) // If qname does not begin with num.num.num.num, can't skip the test query
- {
- if (p[0] < 1 || p[0] > 3) return(mDNSfalse);
- if ( p[1] < '0' || p[1] > '9' ) return(mDNSfalse);
- if (p[0] >= 2 && (p[2] < '0' || p[2] > '9')) return(mDNSfalse);
- if (p[0] >= 3 && (p[3] < '0' || p[3] > '9')) return(mDNSfalse);
- p += 1 + p[0];
- }
- // If remainder of qname is ".in-addr.arpa.", this is a vanilla reverse-mapping query and
- // we can safely do it without needing a test query first, otherwise we need the test query.
- return(SameDomainName((domainname*)p, (const domainname*)"\x7" "in-addr" "\x4" "arpa"));
-}
-
-// Returns mDNStrue if response was handled
-mDNSlocal mDNSBool uDNS_ReceiveTestQuestionResponse(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
- const mDNSAddr *const srcaddr, const mDNSIPPort srcport)
-{
- const mDNSu8 *ptr = msg->data;
- DNSQuestion pktq;
- DNSServer *s;
- mDNSu32 result = 0;
-
- // 1. Find out if this is an answer to one of our test questions
- if (msg->h.numQuestions != 1) return(mDNSfalse);
- ptr = getQuestion(msg, ptr, end, mDNSInterface_Any, &pktq);
- if (!ptr) return(mDNSfalse);
- if (pktq.qtype != kDNSType_PTR || pktq.qclass != kDNSClass_IN) return(mDNSfalse);
- if (!SameDomainName(&pktq.qname, DNSRelayTestQuestion)) return(mDNSfalse);
-
- // 2. If the DNS relay gave us a positive response, then it's got buggy firmware
- // else, if the DNS relay gave us an error or no-answer response, it passed our test
- if ((msg->h.flags.b[1] & kDNSFlag1_RC_Mask) == kDNSFlag1_RC_NoErr && msg->h.numAnswers > 0)
- result = DNSServer_Failed;
- else
- result = DNSServer_Passed;
-
- // 3. Find occurrences of this server in our list, and mark them appropriately
- for (s = m->DNSServers; s; s = s->next)
- {
- mDNSBool matchaddr = (s->teststate != result && mDNSSameAddress(srcaddr, &s->addr) && mDNSSameIPPort(srcport, s->port));
- mDNSBool matchid = (s->teststate == DNSServer_Untested && mDNSSameOpaque16(msg->h.id, s->testid));
- if (matchaddr || matchid)
- {
- DNSQuestion *q;
- s->teststate = result;
- if (result == DNSServer_Passed)
- {
- LogInfo("DNS Server %#a:%d (%#a:%d) %d passed%s",
- &s->addr, mDNSVal16(s->port), srcaddr, mDNSVal16(srcport), mDNSVal16(s->testid),
- matchaddr ? "" : " NOTE: Reply did not come from address to which query was sent");
- }
- else
- {
- LogMsg("NOTE: Wide-Area Service Discovery disabled to avoid crashing defective DNS relay %#a:%d (%#a:%d) %d%s",
- &s->addr, mDNSVal16(s->port), srcaddr, mDNSVal16(srcport), mDNSVal16(s->testid),
- matchaddr ? "" : " NOTE: Reply did not come from address to which query was sent");
- }
-
- // If this server has just changed state from DNSServer_Untested to DNSServer_Passed, then retrigger any waiting questions.
- // We use the NoTestQuery() test so that we only retrigger questions that were actually blocked waiting for this test to complete.
- if (result == DNSServer_Passed) // Unblock any questions that were waiting for this result
- for (q = m->Questions; q; q=q->next)
- if (q->qDNSServer == s && !NoTestQuery(q))
- {
- q->ThisQInterval = INIT_UCAST_POLL_INTERVAL / QuestionIntervalStep;
- q->unansweredQueries = 0;
- q->LastQTime = m->timenow - q->ThisQInterval;
- m->NextScheduledQuery = m->timenow;
- }
- }
- }
-
- return(mDNStrue); // Return mDNStrue to tell uDNS_ReceiveMsg it doesn't need to process this packet further
-}
-
// Called from mDNSCoreReceive with the lock held
mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport)
{
@@ -4015,7 +3904,6 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS
if (QR_OP == StdR)
{
//if (srcaddr && recvLLQResponse(m, msg, end, srcaddr, srcport)) return;
- if (uDNS_ReceiveTestQuestionResponse(m, msg, end, srcaddr, srcport)) return;
for (qptr = m->Questions; qptr; qptr = qptr->next)
if (msg->h.flags.b[0] & kDNSFlag0_TC && mDNSSameOpaque16(qptr->TargetQID, msg->h.id) && m->timenow - qptr->LastQTime < RESPONSE_WINDOW)
{
@@ -4037,7 +3925,7 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS
mDNSs32 expire = m->timenow + (mDNSs32)lease * mDNSPlatformOneSecond;
mDNSu32 random = mDNSRandom((mDNSs32)lease * mDNSPlatformOneSecond/10);
- //rcode = kDNSFlag1_RC_ServFail; // Simulate server failure (rcode 2)
+ //rcode = kDNSFlag1_RC_ServFail; // Simulate server failure (rcode 2)
// Walk through all the records that matches the messageID. There could be multiple
// records if we had sent them in a group
@@ -4200,6 +4088,40 @@ mDNSexport void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneI
mDNS_Unlock(m);
}
+mDNSexport void DNSPushNotificationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo)
+{
+ DNSQuestion *q = (DNSQuestion *)zoneInfo->ZoneDataContext;
+ mDNS_Lock(m);
+
+ // If we get here it means that the GetZoneData operation has completed.
+ // We hold on to the zone data if it is AutoTunnel as we use the hostname
+ // in zoneInfo during the TLS connection setup.
+ q->servAddr = zeroAddr;
+ q->servPort = zeroIPPort;
+ if (!err && zoneInfo && !mDNSIPPortIsZero(zoneInfo->Port) && !mDNSAddressIsZero(&zoneInfo->Addr) && zoneInfo->Host.c[0])
+ {
+ q->dnsPushState = DNSPUSH_SERVERFOUND;
+ q->dnsPushServerAddr = zoneInfo->Addr;
+ q->dnsPushServerPort = zoneInfo->Port;
+ q->ntries = 0;
+ LogInfo("DNSPushNotificationGotZoneData %#a:%d", &q->dnsPushServerAddr, mDNSVal16(q->dnsPushServerPort));
+ SubscribeToDNSPushNotificationServer(m,q);
+ }
+ else
+ {
+ StartLLQPolling(m,q);
+ if (err == mStatus_NoSuchNameErr)
+ {
+ // this actually failed, so mark it by setting address to all ones
+ q->servAddr.type = mDNSAddrType_IPv4;
+ q->servAddr.ip.v4 = onesIPv4Addr;
+ q->dnsPushState = DNSPUSH_NOSERVER;
+ }
+ }
+ mDNS_Unlock(m);
+}
+
+
// Called in normal callback context (i.e. mDNS_busy and mDNS_reentrancy are both 1)
mDNSlocal void PrivateQueryGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo)
{
@@ -4467,7 +4389,7 @@ mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr)
if (!rr->nta) { LogMsg("SendRecordDeregistration:ERROR!! nta is NULL for %s", ARDisplayString(m, rr)); return; }
err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &rr->nta->Addr, rr->nta->Port, mDNSNULL, GetAuthInfoForName_internal(m, rr->resrec.name), mDNSfalse);
if (err) debugf("ERROR: SendRecordDeregistration - mDNSSendDNSMessage - %d", err);
- //if (rr->state == regState_DeregPending) CompleteDeregistration(m, rr); // Don't touch rr after this
+ //if (rr->state == regState_DeregPending) CompleteDeregistration(m, rr); // Don't touch rr after this
}
SetRecordRetry(m, rr, 0);
return;
@@ -4690,17 +4612,35 @@ mDNSlocal void handle_unanswered_query(mDNS *const m)
if (!q->qDNSServer->req_DO)
{
- q->ValidationState = DNSSECValNotRequired;
+ q->ValidationState = DNSSECValNotRequired;
q->ValidationRequired = DNSSEC_VALIDATION_NONE;
-
+
if (q->ProxyQuestion)
q->ProxyDNSSECOK = mDNSfalse;
- LogInfo("handle_unanswered_query: unanswered query for %##s (%s), so turned off validation for %#a",
+ LogInfo("handle_unanswered_query: unanswered query for %##s (%s), so turned off validation for %#a",
q->qname.c, DNSTypeName(q->qtype), &q->qDNSServer->addr);
}
}
}
+mDNSlocal void uDNS_HandleLLQState(mDNS *const m, DNSQuestion *q)
+{
+ // First attempt to use DNS Push Notification.
+ if (q->dnsPushState == DNSPUSH_INIT)
+ DiscoverDNSPushNotificationServer(m, q);
+ switch (q->state)
+ {
+ case LLQ_InitialRequest: startLLQHandshake(m, q); break;
+ case LLQ_SecondaryRequest:
+ // For PrivateQueries, we need to start the handshake again as we don't do the Challenge/Response step
+ if (PrivateQuery(q)) startLLQHandshake(m, q);
+ else sendChallengeResponse(m, q, mDNSNULL);
+ break;
+ case LLQ_Established: sendLLQRefresh(m, q); break;
+ case LLQ_Poll: break; // Do nothing (handled below)
+ }
+}
+
// The question to be checked is not passed in as an explicit parameter;
// instead it is implicit that the question to be checked is m->CurrentQuestion.
mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m)
@@ -4710,22 +4650,10 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m)
if (q->LongLived)
{
- switch (q->state)
- {
- case LLQ_InitialRequest: startLLQHandshake(m, q); break;
- case LLQ_SecondaryRequest:
- // For PrivateQueries, we need to start the handshake again as we don't do the Challenge/Response step
- if (PrivateQuery(q))
- startLLQHandshake(m, q);
- else
- sendChallengeResponse(m, q, mDNSNULL);
- break;
- case LLQ_Established: sendLLQRefresh(m, q); break;
- case LLQ_Poll: break; // Do nothing (handled below)
- }
+ uDNS_HandleLLQState(m,q);
}
- handle_unanswered_query(m);
+ handle_unanswered_query(m);
// We repeat the check above (rather than just making this the "else" case) because startLLQHandshake can change q->state to LLQ_Poll
if (!(q->LongLived && q->state != LLQ_Poll))
{
@@ -4773,36 +4701,25 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m)
for (qptr = q->next ; qptr; qptr = qptr->next)
if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = q->qDNSServer; }
}
- if (q->qDNSServer && q->qDNSServer->teststate != DNSServer_Disabled)
+ if (q->qDNSServer)
{
- mDNSu8 *end = m->omsg.data;
+ mDNSu8 *end;
mStatus err = mStatus_NoError;
mDNSBool private = mDNSfalse;
InitializeDNSMessage(&m->omsg.h, q->TargetQID, (DNSSECQuestion(q) ? DNSSecQFlags : uQueryFlags));
- if (q->qDNSServer->teststate != DNSServer_Untested || NoTestQuery(q))
- {
- end = putQuestion(&m->omsg, m->omsg.data, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
- if (DNSSECQuestion(q) && !q->qDNSServer->cellIntf)
- {
- if (q->ProxyQuestion)
- end = DNSProxySetAttributes(q, &m->omsg.h, &m->omsg, end, m->omsg.data + AbsoluteMaxDNSMessageData);
- else
- end = putDNSSECOption(&m->omsg, end, m->omsg.data + AbsoluteMaxDNSMessageData);
- }
- private = PrivateQuery(q);
- }
- else if (m->timenow - q->qDNSServer->lasttest >= INIT_UCAST_POLL_INTERVAL) // Make sure at least three seconds has elapsed since last test query
+ end = putQuestion(&m->omsg, m->omsg.data, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
+ if (DNSSECQuestion(q) && !q->qDNSServer->cellIntf)
{
- LogInfo("Sending DNS test query to %#a:%d", &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port));
- q->ThisQInterval = INIT_UCAST_POLL_INTERVAL / QuestionIntervalStep;
- q->qDNSServer->lasttest = m->timenow;
- end = putQuestion(&m->omsg, m->omsg.data, m->omsg.data + AbsoluteMaxDNSMessageData, DNSRelayTestQuestion, kDNSType_PTR, kDNSClass_IN);
- q->qDNSServer->testid = m->omsg.h.id;
+ if (q->ProxyQuestion)
+ end = DNSProxySetAttributes(q, &m->omsg.h, &m->omsg, end, m->omsg.data + AbsoluteMaxDNSMessageData);
+ else
+ end = putDNSSECOption(&m->omsg, end, m->omsg.data + AbsoluteMaxDNSMessageData);
}
+ private = PrivateQuery(q);
- if (end > m->omsg.data && (q->qDNSServer->teststate != DNSServer_Failed || NoTestQuery(q)))
+ if (end > m->omsg.data)
{
//LogMsg("uDNS_CheckCurrentQuestion %p %d %p %##s (%s)", q, NextQSendTime(q) - m->timenow, private, q->qname.c, DNSTypeName(q->qtype));
if (private)
@@ -4820,7 +4737,7 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m)
{
q->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort);
if (q->LocalSocket)
- mDNSPlatformSetuDNSSocktOpt(q->LocalSocket, &q->qDNSServer->addr, q);
+ mDNSPlatformSetSocktOpt(q->LocalSocket, mDNSTransport_UDP, q->qDNSServer->addr.type, q);
}
if (!q->LocalSocket) err = mStatus_NoMemoryErr; // If failed to make socket (should be very rare), we'll try again next time
else
@@ -4829,6 +4746,11 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m)
#if TARGET_OS_EMBEDDED
if (!err)
{
+ if (q->metrics.answered)
+ {
+ q->metrics.querySendCount = 0;
+ q->metrics.answered = mDNSfalse;
+ }
if (q->metrics.querySendCount++ == 0)
{
q->metrics.firstQueryTime = m->timenow;
@@ -4839,32 +4761,68 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m)
}
}
- if (err != mStatus_TransientErr) // if it is not a transient error backoff and DO NOT flood queries unnecessarily
+ if (err == mStatus_HostUnreachErr)
{
- q->ThisQInterval = q->ThisQInterval * QuestionIntervalStep; // Only increase interval if send succeeded
- q->unansweredQueries++;
- if (q->ThisQInterval > MAX_UCAST_POLL_INTERVAL)
- q->ThisQInterval = MAX_UCAST_POLL_INTERVAL;
- if (private && q->state != LLQ_Poll)
+ DNSServer *newServer;
+
+ LogInfo("uDNS_CheckCurrentQuestion: host unreachable error for DNS server %#a for question [%p] %##s (%s)",
+ &q->qDNSServer->addr, q, q->qname.c, DNSTypeName(q->qtype));
+
+ if (!StrictUnicastOrdering)
{
- // We don't want to retransmit too soon. Hence, we always schedule our first
- // retransmisson at 3 seconds rather than one second
- if (q->ThisQInterval < (3 * mDNSPlatformOneSecond))
- q->ThisQInterval = q->ThisQInterval * QuestionIntervalStep;
- if (q->ThisQInterval > LLQ_POLL_INTERVAL)
- q->ThisQInterval = LLQ_POLL_INTERVAL;
- LogInfo("uDNS_CheckCurrentQuestion: private non polling question for %##s (%s) will be retried in %d ms", q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval);
+ q->qDNSServer->penaltyTime = NonZeroTime(m->timenow + DNSSERVER_PENALTY_TIME);
}
- if (q->qDNSServer->cellIntf)
+
+ newServer = GetServerForQuestion(m, q);
+ DNSServerChangeForQuestion(m, q, newServer);
+
+ if (q->triedAllServersOnce)
+ {
+ q->LastQTime = m->timenow;
+ }
+ else
{
- // We don't want to retransmit too soon. Schedule our first retransmisson at
- // MIN_UCAST_RETRANS_TIMEOUT seconds.
- if (q->ThisQInterval < MIN_UCAST_RETRANS_TIMEOUT)
- q->ThisQInterval = MIN_UCAST_RETRANS_TIMEOUT;
+ q->ThisQInterval = InitialQuestionInterval;
+ q->LastQTime = m->timenow - q->ThisQInterval;
}
- debugf("uDNS_CheckCurrentQuestion: Increased ThisQInterval to %d for %##s (%s), cell %d", q->ThisQInterval, q->qname.c, DNSTypeName(q->qtype), q->qDNSServer->cellIntf);
+ q->unansweredQueries = 0;
+ q->noServerResponse = 1;
+ }
+ else
+ {
+ if (err != mStatus_TransientErr) // if it is not a transient error backoff and DO NOT flood queries unnecessarily
+ {
+ // If all DNS Servers are not responding, then we back-off using the multiplier UDNSBackOffMultiplier(*2).
+ // Only increase interval if send succeeded
+
+ q->ThisQInterval = q->ThisQInterval * UDNSBackOffMultiplier;
+ if ((q->ThisQInterval > 0) && (q->ThisQInterval < MinQuestionInterval)) // We do not want to retx within 1 sec
+ q->ThisQInterval = MinQuestionInterval;
+
+ q->unansweredQueries++;
+ if (q->ThisQInterval > MAX_UCAST_POLL_INTERVAL)
+ q->ThisQInterval = MAX_UCAST_POLL_INTERVAL;
+ if (private && q->state != LLQ_Poll)
+ {
+ // We don't want to retransmit too soon. Hence, we always schedule our first
+ // retransmisson at 3 seconds rather than one second
+ if (q->ThisQInterval < (3 * mDNSPlatformOneSecond))
+ q->ThisQInterval = q->ThisQInterval * QuestionIntervalStep;
+ if (q->ThisQInterval > LLQ_POLL_INTERVAL)
+ q->ThisQInterval = LLQ_POLL_INTERVAL;
+ LogInfo("uDNS_CheckCurrentQuestion: private non polling question for %##s (%s) will be retried in %d ms", q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval);
+ }
+ if (q->qDNSServer->cellIntf)
+ {
+ // We don't want to retransmit too soon. Schedule our first retransmisson at
+ // MIN_UCAST_RETRANS_TIMEOUT seconds.
+ if (q->ThisQInterval < MIN_UCAST_RETRANS_TIMEOUT)
+ q->ThisQInterval = MIN_UCAST_RETRANS_TIMEOUT;
+ }
+ debugf("uDNS_CheckCurrentQuestion: Increased ThisQInterval to %d for %##s (%s), cell %d", q->ThisQInterval, q->qname.c, DNSTypeName(q->qtype), q->qDNSServer->cellIntf);
+ }
+ q->LastQTime = m->timenow;
}
- q->LastQTime = m->timenow;
SetNextQueryTime(m, q);
}
else
@@ -4927,7 +4885,7 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m)
{
if (SameNameRecordAnswersQuestion(&rr->resrec, q))
{
- LogInfo("uDNS_CheckCurrentQuestion: Purged resourcerecord %s", CRDisplayString(m, rr));
+ LogInfo("uDNS_CheckCurrentQuestion: Purged resourcerecord %s", CRDisplayString(m, rr));
mDNS_PurgeCacheResourceRecord(m, rr);
}
}
@@ -5049,7 +5007,7 @@ mDNSexport void CheckNATMappings(mDNS *m)
const mStatus EffectiveResult = cur->NewResult ? cur->NewResult : mDNSv4AddrIsRFC1918(&EffectiveAddress) ? mStatus_DoubleNAT : mStatus_NoError;
const mDNSIPPort ExternalPort = HaveRoutable ? cur->IntPort :
!mDNSIPv4AddressIsZero(EffectiveAddress) && cur->ExpiryTime ? cur->RequestedPort : zeroIPPort;
-
+
if (!cur->Protocol || HaveRoutable || cur->ExpiryTime || cur->retryInterval > NATMAP_INIT_RETRY * 8)
{
if (!mDNSSameIPv4Address(cur->ExternalAddress, EffectiveAddress) ||
@@ -5337,8 +5295,8 @@ mDNSexport void udns_validatelists(void *const v)
DNSServer *d;
for (d = m->DNSServers; d; d=d->next)
- if (d->next == (DNSServer *)~0 || d->teststate > DNSServer_Disabled)
- LogMemCorruption("m->DNSServers: %p is garbage (%d)", d, d->teststate);
+ if (d->next == (DNSServer *)~0)
+ LogMemCorruption("m->DNSServers: %p is garbage", d);
DomainAuthInfo *info;
for (info = m->AuthInfoList; info; info = info->next)
@@ -5810,101 +5768,327 @@ struct CompileTimeAssertionChecks_uDNS
char sizecheck_SearchListElem[(sizeof(SearchListElem) <= 5000) ? 1 : -1];
};
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark - DNS Push Notification functions
+#endif
+
+mDNSlocal tcpInfo_t * GetTCPConnectionToPushServer(mDNS *m, DNSQuestion *q)
+{
+ // If we already have a question for this zone and if the server is the same, reuse it
+ DNSPushNotificationZone *zone = mDNSNULL;
+ for (zone = m->DNSPushZones; zone != mDNSNULL; zone = zone->next)
+ {
+ if (SameDomainName(&q->nta->ChildName, &zone->zoneName))
+ {
+ DNSPushNotificationServer *zoneServer = mDNSNULL;
+ for (zoneServer = zone->servers; zoneServer != mDNSNULL; zoneServer = zoneServer->next)
+ {
+ if (mDNSSameAddress(&q->dnsPushServerAddr, &zoneServer->serverAddr))
+ {
+ zone->numberOfQuestions++;
+ zoneServer->numberOfQuestions++;
+ return zoneServer->connection;
+ }
+ }
+ }
+ }
+
+ // If we have a connection to this server but it is for a differnt zone, create a new zone entry and reuse the connection
+ DNSPushNotificationServer *server = mDNSNULL;
+ for (server = m->DNSPushServers; server != mDNSNULL; server = server->next)
+ {
+ if (mDNSSameAddress(&q->dnsPushServerAddr, &server->serverAddr))
+ {
+ DNSPushNotificationZone *newZone = mDNSPlatformMemAllocate(sizeof(DNSPushNotificationZone));
+ newZone->numberOfQuestions = 1;
+ newZone->zoneName = q->nta->ChildName;
+ newZone->servers = server;
+
+ // Add the new zone to the begining of the list
+ newZone->next = m->DNSPushZones;
+ m->DNSPushZones = newZone;
+
+ server->numberOfQuestions++;
+ return server->connection;
+ }
+ }
+
+ // If we do not have any existing connections, create a new connection
+ DNSPushNotificationServer *newServer = mDNSPlatformMemAllocate(sizeof(DNSPushNotificationServer));
+ DNSPushNotificationZone *newZone = mDNSPlatformMemAllocate(sizeof(DNSPushNotificationZone));
+
+ newServer->numberOfQuestions = 1;
+ newServer->serverAddr = q->dnsPushServerAddr;
+ newServer->connection = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_UseTLS, &q->dnsPushServerAddr, q->dnsPushServerPort, &q->nta->Host, q, mDNSNULL);
+
+ newZone->numberOfQuestions = 1;
+ newZone->zoneName = q->nta->ChildName;
+ newZone->servers = newServer;
+
+ // Add the new zone to the begining of the list
+ newZone->next = m->DNSPushZones;
+ m->DNSPushZones = newZone;
+
+ newServer->next = m->DNSPushServers;
+ m->DNSPushServers = newServer;
+ return newServer->connection;
+}
+
+mDNSexport void DiscoverDNSPushNotificationServer(mDNS *m, DNSQuestion *q)
+{
+ /* Use the same NAT setup as in the LLQ case */
+ if (m->LLQNAT.clientContext != mDNSNULL) // LLQNAT just started, give it some time
+ {
+ LogInfo("startLLQHandshake: waiting for NAT status for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+ q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10); // Retry in approx 15 minutes
+ q->LastQTime = m->timenow;
+ SetNextQueryTime(m, q);
+ return;
+ }
+
+ // Either we don't have {PCP, NAT-PMP, UPnP/IGD} support (ExternalPort is zero) or behind a Double NAT that may or
+ // may not have {PCP, NAT-PMP, UPnP/IGD} support (NATResult is non-zero)
+ if (mDNSIPPortIsZero(m->LLQNAT.ExternalPort) || m->LLQNAT.Result)
+ {
+ LogInfo("startLLQHandshake: Cannot receive inbound packets; will poll for %##s (%s) External Port %d, NAT Result %d",
+ q->qname.c, DNSTypeName(q->qtype), mDNSVal16(m->LLQNAT.ExternalPort), m->LLQNAT.Result);
+ StartLLQPolling(m, q); // Actually sets up the NAT Auto Tunnel
+ return;
+ }
+
+ if (mDNSIPPortIsZero(q->dnsPushServerPort) && q->dnsPushState == DNSPUSH_INIT)
+ {
+ LogInfo("SubscribeToDNSPushNotificationServer: StartGetZoneData for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+ q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10); // Retry in approx 15 minutes
+ q->LastQTime = m->timenow;
+ SetNextQueryTime(m, q);
+ q->dnsPushServerAddr = zeroAddr;
+ // We know q->dnsPushServerPort is zero because of check above
+ if (q->nta) CancelGetZoneData(m, q->nta);
+ q->nta = StartGetZoneData(m, &q->qname, ZoneServiceDNSPush, DNSPushNotificationGotZoneData, q);
+ return;
+ }
+
+ if (q->tcp)
+ {
+ LogInfo("SubscribeToDNSPushNotificationServer: Disposing existing TCP connection for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+ DisposeTCPConn(q->tcp);
+ q->tcp = mDNSNULL;
+ }
+
+ if (!q->nta)
+ {
+ // Normally we lookup the zone data and then call this function. And we never free the zone data
+ // for "PrivateQuery". But sometimes this can happen due to some race conditions. When we
+ // switch networks, we might end up "Polling" the network e.g., we are behind a Double NAT.
+ // When we poll, we free the zone information as we send the query to the server (See
+ // PrivateQueryGotZoneData). The NAT callback (LLQNATCallback) may happen soon after that. If we
+ // are still behind Double NAT, we would have returned early in this function. But we could
+ // have switched to a network with no NATs and we should get the zone data again.
+ LogInfo("SubscribeToDNSPushNotificationServer: nta is NULL for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+ q->nta = StartGetZoneData(m, &q->qname, ZoneServiceDNSPush, DNSPushNotificationGotZoneData, q);
+ return;
+ }
+ else if (!q->nta->Host.c[0])
+ {
+ // This should not happen. If it happens, we print a log and MakeTCPConn will fail if it can't find a hostname
+ LogMsg("SubscribeToDNSPushNotificationServer: ERROR!!: nta non NULL for %##s (%s) but HostName %d NULL, LongLived %d", q->qname.c, DNSTypeName(q->qtype), q->nta->Host.c[0], q->LongLived);
+ }
+ q->tcp = GetTCPConnectionToPushServer(m,q);
+ // If TCP failed (transient networking glitch) try again in five seconds
+ q->ThisQInterval = (q->tcp != mDNSNULL) ? q->ThisQInterval = 0 : (mDNSPlatformOneSecond * 5);
+ q->LastQTime = m->timenow;
+ SetNextQueryTime(m, q);
+}
+
+
+mDNSexport void SubscribeToDNSPushNotificationServer(mDNS *m, DNSQuestion *q)
+{
+ mDNSu8 *end = mDNSNULL;
+ InitializeDNSMessage(&m->omsg.h, zeroID, SubscribeFlags);
+ end = putQuestion(&m->omsg, end, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
+ if (!end)
+ {
+ LogMsg("ERROR: SubscribeToDNSPushNotificationServer putQuestion failed");
+ return;
+ }
+
+ mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, q->LocalSocket, &q->dnsPushServerAddr, q->dnsPushServerPort, q->tcp->sock, mDNSNULL, mDNSfalse);
+
+ // update question state
+ q->dnsPushState = DNSPUSH_ESTABLISHED;
+ q->ThisQInterval = (kLLQ_INIT_RESEND * mDNSPlatformOneSecond);
+ q->LastQTime = m->timenow;
+ SetNextQueryTime(m, q);
+
+}
+
+mDNSlocal void reconcileDNSPushConnection(mDNS *m, DNSQuestion *q)
+{
+ DNSPushNotificationZone *zone;
+ DNSPushNotificationServer *server;
+ // Update the counts
+ for (zone = m->DNSPushZones; zone != mDNSNULL; zone = zone->next)
+ {
+ if (SameDomainName(&zone->zoneName, &q->nta->ChildName))
+ {
+ zone->numberOfQuestions--;
+ for (server = zone->servers; server != mDNSNULL; server = server->next)
+ {
+ if (mDNSSameAddress(&server->serverAddr, &q->dnsPushServerAddr))
+ server->numberOfQuestions--;
+ }
+ }
+ }
+
+ // Now prune the lists
+ server = m->DNSPushServers;
+ DNSPushNotificationServer *nextServer = mDNSNULL;
+ while(server != mDNSNULL)
+ {
+ nextServer = server->next;
+ if (server->numberOfQuestions <= 0)
+ {
+ DisposeTCPConn(server->connection);
+ if (server == m->DNSPushServers)
+ m->DNSPushServers = nextServer;
+ mDNSPlatformMemFree(server);
+ server = nextServer;
+ }
+ else server = server->next;
+ }
+
+ zone = m->DNSPushZones;
+ DNSPushNotificationZone *nextZone = mDNSNULL;
+ while(zone != mDNSNULL)
+ {
+ nextZone = zone->next;
+ if (zone->numberOfQuestions <= 0)
+ {
+ if (zone == m->DNSPushZones)
+ m->DNSPushZones = nextZone;
+ mDNSPlatformMemFree(zone);
+ zone = nextZone;
+ }
+ else zone = zone->next;
+ }
+
+}
+
+mDNSexport void UnSubscribeToDNSPushNotificationServer(mDNS *m, DNSQuestion *q)
+{
+ mDNSu8 *end = mDNSNULL;
+ InitializeDNSMessage(&m->omsg.h, q->TargetQID, UnSubscribeFlags);
+ end = putQuestion(&m->omsg, end, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
+ if (!end)
+ {
+ LogMsg("ERROR: UnSubscribeToDNSPushNotificationServer - putQuestion failed");
+ return;
+ }
+
+ mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, q->LocalSocket, &q->dnsPushServerAddr, q->dnsPushServerPort, q->tcp->sock, mDNSNULL, mDNSfalse);
+
+ reconcileDNSPushConnection(m, q);
+}
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#endif
#else // !UNICAST_DISABLED
mDNSexport const domainname *GetServiceTarget(mDNS *m, AuthRecord *const rr)
{
- (void) m;
- (void) rr;
+ (void) m;
+ (void) rr;
- return mDNSNULL;
+ return mDNSNULL;
}
mDNSexport DomainAuthInfo *GetAuthInfoForName_internal(mDNS *m, const domainname *const name)
{
- (void) m;
- (void) name;
+ (void) m;
+ (void) name;
- return mDNSNULL;
+ return mDNSNULL;
}
mDNSexport DomainAuthInfo *GetAuthInfoForQuestion(mDNS *m, const DNSQuestion *const q)
{
- (void) m;
- (void) q;
+ (void) m;
+ (void) q;
- return mDNSNULL;
+ return mDNSNULL;
}
mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q)
{
- (void) m;
- (void) q;
+ (void) m;
+ (void) q;
}
mDNSexport void DisposeTCPConn(struct tcpInfo_t *tcp)
{
- (void) tcp;
+ (void) tcp;
}
mDNSexport mStatus mDNS_StartNATOperation_internal(mDNS *m, NATTraversalInfo *traversal)
{
- (void) m;
- (void) traversal;
+ (void) m;
+ (void) traversal;
- return mStatus_UnsupportedErr;
+ return mStatus_UnsupportedErr;
}
mDNSexport mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *traversal)
{
- (void) m;
- (void) traversal;
+ (void) m;
+ (void) traversal;
- return mStatus_UnsupportedErr;
+ return mStatus_UnsupportedErr;
}
mDNSexport void sendLLQRefresh(mDNS *m, DNSQuestion *q)
{
- (void) m;
- (void) q;
+ (void) m;
+ (void) q;
}
mDNSexport ZoneData *StartGetZoneData(mDNS *const m, const domainname *const name, const ZoneService target, ZoneDataCallback callback, void *ZoneDataContext)
{
- (void) m;
- (void) name;
- (void) target;
- (void) callback;
- (void) ZoneDataContext;
+ (void) m;
+ (void) name;
+ (void) target;
+ (void) callback;
+ (void) ZoneDataContext;
- return mDNSNULL;
+ return mDNSNULL;
}
mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData)
{
- (void) m;
- (void) err;
- (void) zoneData;
+ (void) m;
+ (void) err;
+ (void) zoneData;
}
mDNSexport uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
const mDNSAddr *const srcaddr, const mDNSIPPort srcport, DNSQuestion **matchQuestion)
{
- (void) m;
- (void) msg;
- (void) end;
- (void) srcaddr;
- (void) srcport;
- (void) matchQuestion;
+ (void) m;
+ (void) msg;
+ (void) end;
+ (void) srcaddr;
+ (void) srcport;
+ (void) matchQuestion;
- return uDNS_LLQ_Not;
+ return uDNS_LLQ_Not;
}
mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 responseFlags)
{
- (void) m;
- (void) q;
- (void) responseFlags;
+ (void) m;
+ (void) q;
+ (void) responseFlags;
}
mDNSexport void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID)
@@ -5928,7 +6112,7 @@ mDNSexport mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info, const
(void) hostname;
(void) port;
(void) autoTunnel;
-
+
return mStatus_UnsupportedErr;
}
@@ -5938,7 +6122,7 @@ mDNSexport domainname *uDNS_GetNextSearchDomain(mDNS *const m, mDNSInterfaceID
(void) InterfaceID;
(void) searchIndex;
(void) ignoreDotLocal;
-
+
return mDNSNULL;
}
@@ -5946,7 +6130,7 @@ mDNSexport DomainAuthInfo *GetAuthInfoForName(mDNS *m, const domainname *const n
{
(void) m;
(void) name;
-
+
return mDNSNULL;
}
@@ -5954,7 +6138,7 @@ mDNSexport mStatus mDNS_StartNATOperation(mDNS *const m, NATTraversalInfo *trave
{
(void) m;
(void) traversal;
-
+
return mStatus_UnsupportedErr;
}
@@ -5962,7 +6146,7 @@ mDNSexport mStatus mDNS_StopNATOperation(mDNS *const m, NATTraversalInfo *traver
{
(void) m;
(void) traversal;
-
+
return mStatus_UnsupportedErr;
}
@@ -5983,7 +6167,7 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons
(void) reqA;
(void) reqAAAA;
(void) reqDO;
-
+
return mDNSNULL;
}
@@ -6034,8 +6218,27 @@ mDNSexport void RecreateNATMappings(mDNS *const m, const mDNSu32 waitTicks)
mDNSexport mDNSBool IsGetZoneDataQuestion(DNSQuestion *q)
{
(void)q;
-
+
return mDNSfalse;
}
+mDNSexport void SubscribeToDNSPushNotificationServer(mDNS *m, DNSQuestion *q)
+{
+ (void)m;
+ (void)q;
+}
+
+mDNSexport void UnSubscribeToDNSPushNotificationServer(mDNS *m, DNSQuestion *q)
+{
+ (void)m;
+ (void)q;
+}
+
+mDNSexport void DiscoverDNSPushNotificationServer(mDNS *m, DNSQuestion *q)
+{
+ (void)m;
+ (void)q;
+}
+
#endif // !UNICAST_DISABLED
+
diff --git a/mDNSResponder/mDNSCore/uDNS.h b/mDNSResponder/mDNSCore/uDNS.h
index eca8b701..910449f1 100755
--- a/mDNSResponder/mDNSCore/uDNS.h
+++ b/mDNSResponder/mDNSCore/uDNS.h
@@ -47,9 +47,8 @@ extern "C" {
#define QuestionIntervalStep3 (QuestionIntervalStep*QuestionIntervalStep*QuestionIntervalStep)
#define InitialQuestionInterval ((mDNSPlatformOneSecond + QuestionIntervalStep-1) / QuestionIntervalStep)
#define MaxQuestionInterval (3600 * mDNSPlatformOneSecond)
-
-// just move to MaxQuestionInterval once over this threshold
-#define QuestionIntervalThreshold (QuestionIntervalStep3 * mDNSPlatformOneSecond)
+#define UDNSBackOffMultiplier 2
+#define MinQuestionInterval (1 * mDNSPlatformOneSecond)
// For Unicast record registrations, we initialize the interval to 1 second. When we send any query for
// the record registration e.g., GetZoneData, we always back off by QuestionIntervalStep
@@ -82,6 +81,11 @@ extern void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo)
extern void startLLQHandshake(mDNS *m, DNSQuestion *q);
extern void sendLLQRefresh(mDNS *m, DNSQuestion *q);
+extern void DNSPushNotificationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo);
+extern void DiscoverDNSPushNotificationServer(mDNS *m, DNSQuestion *q);
+extern void SubscribeToDNSPushNotificationServer(mDNS *m, DNSQuestion *q);
+extern void UnSubscribeToDNSPushNotificationServer(mDNS *m, DNSQuestion *q);
+
extern void SleepRecordRegistrations(mDNS *m);
// uDNS_UpdateRecord
@@ -144,6 +148,10 @@ extern void uDNS_ReceiveNATPacket(mDNS *m, const mDNSInterfaceID InterfaceID, mD
extern void natTraversalHandleAddressReply(mDNS *const m, mDNSu16 err, mDNSv4Addr ExtAddr);
extern void natTraversalHandlePortMapReply(mDNS *const m, NATTraversalInfo *n, const mDNSInterfaceID InterfaceID, mDNSu16 err, mDNSIPPort extport, mDNSu32 lease, NATTProtocol protocol);
+// DNS Push Notification
+extern void SubscribeToDNSPushNotification(mDNS *m, DNSQuestion *q);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/mDNSResponder/mDNSMacOSX/BLE.c b/mDNSResponder/mDNSMacOSX/BLE.c
new file mode 100644
index 00000000..85fb810c
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BLE.c
@@ -0,0 +1,853 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2015-2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mDNSEmbeddedAPI.h"
+#include "DNSCommon.h"
+#include "mDNSMacOSX.h"
+#include "BLE.h"
+#include <pthread.h>
+
+#pragma mark - Browse and Registration Request Handling
+
+// Disable use of BLE discovery APIs by default.
+mDNSBool EnableBLEBasedDiscovery = mDNSfalse;
+
+typedef struct matchingResponses
+{
+ struct matchingResponses * next;
+ void * response;
+} matchingResponses_t;
+
+// Initially used for both the browse and registration lists.
+typedef struct requestList
+{
+ struct requestList * next;
+ unsigned int refCount;
+ domainname name;
+ mDNSu16 type;
+ DNSServiceFlags flags;
+ mDNSInterfaceID InterfaceID;
+
+// TODO: Possibly restructure the following browse and registration specific
+// members as a union to save a bit of space.
+
+ // The following fields are only used for browse requests currently
+ serviceHash_t browseHash;
+ DNSQuestion * question;
+ mDNSu8 key[MAX_DOMAIN_LABEL];
+ size_t keySize;
+ matchingResponses_t * ourResponses;
+
+ // The following fields are only used for registration requests currently
+ serviceHash_t registeredHash;
+ ServiceRecordSet * serviceRecordSet; // service record set in the original request
+ AuthRecType savedARType;
+ bool triggeredOnAWDL;
+} requestList_t;
+
+// Lists for all DNSServiceBrowse() and DNSServiceRegister() requests using
+// BLE beacon based triggering.
+static requestList_t* BLEBrowseListHead = NULL;
+static requestList_t* BLERegistrationListHead = NULL;
+
+#define isAutoTriggerRequest(ptr) ((ptr->InterfaceID == kDNSServiceInterfaceIndexAny) && (ptr->flags & kDNSServiceFlagsAutoTrigger))
+
+#pragma mark - Manage list of responses that match this request.
+
+mDNSlocal bool inResponseListForRequest(requestList_t *request, void * response)
+{
+ matchingResponses_t * rp;
+
+ for (rp = request->ourResponses; rp; rp = rp->next)
+ if (rp->response == response)
+ break;
+
+ return (rp != 0);
+}
+
+mDNSlocal void addToResponseListForRequest(requestList_t *request, void * response)
+{
+ matchingResponses_t *matchingResponse = calloc(1, sizeof(matchingResponses_t));
+
+ if (matchingResponse == NULL)
+ {
+ LogMsg("addToResponseListForRequest: calloc() failed!");
+ return;
+ }
+ matchingResponse->response = response;
+ matchingResponse->next = request->ourResponses;
+ request->ourResponses = matchingResponse;
+}
+
+// If response is currently in the list of responses, remove it and return true.
+// Othewise, return false.
+mDNSlocal bool removeFromResponseListForRequest(requestList_t *request, void * response)
+{
+ matchingResponses_t ** nextp;
+ bool responseRemoved = false;
+
+ for (nextp = & request->ourResponses; *nextp; nextp = & (*nextp)->next)
+ if ((*nextp)->response == response)
+ break;
+
+ if (*nextp)
+ {
+ LogInfo("removeFromResponseListForRequest: response no longer matches for %##s %s ", request->name.c, DNSTypeName(request->type));
+
+ responseRemoved = true;
+ matchingResponses_t *tmp = *nextp;
+ *nextp = (*nextp)->next;
+ free(tmp);
+ }
+ return responseRemoved;
+}
+
+// Free all current entries on the response list for this request.
+mDNSlocal void freeResponseListEntriesForRequest(requestList_t *request)
+{
+ matchingResponses_t * ptr;
+
+ ptr = request->ourResponses;
+ while (ptr)
+ {
+ matchingResponses_t * tmp;
+
+ tmp = ptr;
+ ptr = ptr->next;
+ free(tmp);
+ }
+}
+
+#pragma mark - Manage request lists
+
+mDNSlocal requestList_t ** findInRequestList(requestList_t ** listHead, const domainname *const name, mDNSu16 type)
+{
+ requestList_t **ptr = listHead;
+
+ for ( ; *ptr; ptr = &(*ptr)->next)
+ if ((*ptr)->type == type && SameDomainName(&(*ptr)->name, name))
+ break;
+
+ return ptr;
+}
+
+mDNSlocal requestList_t * addToRequestList(requestList_t ** listHead, const domainname *const name, mDNSu16 type, DNSServiceFlags flags)
+{
+ requestList_t **ptr = findInRequestList(listHead, name, type);
+
+ if (!*ptr)
+ {
+ *ptr = mDNSPlatformMemAllocate(sizeof(**ptr));
+ mDNSPlatformMemZero(*ptr, sizeof(**ptr));
+ (*ptr)->type = type;
+ (*ptr)->flags = flags;
+ AssignDomainName(&(*ptr)->name, name);
+ }
+ (*ptr)->refCount += 1;
+
+ LogInfo("addToRequestList: %##s %s refcount now %u", (*ptr)->name.c, DNSTypeName((*ptr)->type), (*ptr)->refCount);
+
+ return *ptr;
+}
+
+mDNSlocal void removeFromRequestList(requestList_t ** listHead, const domainname *const name, mDNSu16 type)
+{
+ requestList_t **ptr = findInRequestList(listHead, name, type);
+
+ if (!*ptr) { LogMsg("removeFromRequestList: Didn't find %##s %s in list", name->c, DNSTypeName(type)); return; }
+
+ (*ptr)->refCount -= 1;
+
+ LogInfo("removeFromRequestList: %##s %s refcount now %u", (*ptr)->name.c, DNSTypeName((*ptr)->type), (*ptr)->refCount);
+
+ if (!(*ptr)->refCount)
+ {
+ requestList_t *tmp = *ptr;
+ *ptr = (*ptr)->next;
+ freeResponseListEntriesForRequest(tmp);
+ mDNSPlatformMemFree(tmp);
+ }
+}
+
+#pragma mark - Hashing and beacon state
+
+// Simple string hash based on the Bernstein hash.
+
+#define PRIME 31 // small prime number
+#define MODULO (sizeof(serviceHash_t) * 8)
+#define CONVERT_TO_LOWER_CASE(x) (((x) <= 'Z' && (x) >= 'A') ? ((x) | 0x20) : (x))
+
+mDNSlocal serviceHash_t BLELabelHash(const unsigned char *str, unsigned int length)
+{
+ serviceHash_t hash = 0;
+
+ for (unsigned int i = 0; i < length; i++) {
+ hash = PRIME * hash + CONVERT_TO_LOWER_CASE(*str);
+ str++;
+ }
+
+ hash %= MODULO;
+ LogInfo("BLELabelHash: %d characters hashed to %d", length, hash);
+
+ return ((serviceHash_t)1 << hash);
+}
+
+// Hash just the service type not including the protocol or first "_" character initially.
+mDNSlocal serviceHash_t BLEServiceHash(const domainname *const domain)
+{
+ const unsigned char *p = domain->c;
+ unsigned int length = (unsigned int) *p;
+
+ p++;
+ if (*p != '_')
+ {
+ LogInfo("BLEServiceHash: browse type does not begin with a _");
+ return 0;
+ }
+ p++; // skip the '-"
+ length--;
+
+ if (length > MAX_DOMAIN_LABEL || length == 0)
+ {
+ LogInfo("BLEServiceHash: invalid browse type length: %d characters", length);
+ return 0;
+ }
+
+ return BLELabelHash(p, length);
+}
+
+// Storage for the current Bonjour BLE beacon data;
+typedef struct BLEBeacon
+{
+ serviceHash_t browseHash;
+ serviceHash_t registeredHash;
+} BLEBeacon_t;
+
+BLEBeacon_t BLEBeacon;
+
+mDNSlocal void addServiceToBeacon(serviceHash_t browseHash, serviceHash_t registeredHash)
+{
+ bool beaconUpdated = false;
+
+ if (BLEBeacon.browseHash & browseHash)
+ {
+ LogInfo("addServiceToBeacon: Bit 0x%x already set in browsing services hash", browseHash);
+ }
+ else
+ {
+ BLEBeacon.browseHash |= browseHash;
+ beaconUpdated = true;
+ }
+
+ if (BLEBeacon.registeredHash & registeredHash)
+ {
+ LogInfo("addServiceToBeacon: Bit 0x%x already set in advertising services hash", registeredHash);
+ }
+ else
+ {
+ BLEBeacon.registeredHash |= registeredHash;
+ beaconUpdated = true;
+ }
+
+ if (beaconUpdated)
+ updateBLEBeaconAndScan(BLEBeacon.browseHash, BLEBeacon.registeredHash);
+}
+
+// Go through all the existing browses and registrations to get the
+// current hash values for the corresponding BLE beacon.
+// We must do this when any hash bits are removed do accurately generate
+// the correct combination of all currently set hash bits.
+mDNSlocal void updateBeacon()
+{
+ requestList_t *ptr;
+
+ BLEBeacon.browseHash = 0;
+ BLEBeacon.registeredHash = 0;
+
+ for (ptr = BLEBrowseListHead; ptr; ptr = ptr->next)
+ {
+ BLEBeacon.browseHash |= ptr->browseHash;
+ }
+
+ for (ptr = BLERegistrationListHead; ptr; ptr = ptr->next)
+ {
+ BLEBeacon.registeredHash |= ptr->registeredHash;
+ }
+
+ updateBLEBeaconAndScan(BLEBeacon.browseHash, BLEBeacon.registeredHash);
+}
+
+#pragma mark - Request start/stop
+
+// Forward declarations for mDNSLocal functions that are called before they are defined.
+mDNSlocal void checkForMatchingResponses(requestList_t *bp);
+mDNSlocal void clearResponseLists();
+
+void start_BLE_browse(DNSQuestion * q, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags, mDNSu8 *key, size_t keySize)
+{
+ requestList_t * ptr;
+
+ if (!EnableBLEBasedDiscovery)
+ {
+ LogMsg("start_BLE_browse: EnableBLEBasedDiscovery disabled");
+ return;
+ }
+
+ LogInfo("start_BLE_browse: Starting BLE browse for: %##s %s", domain->c, DNSTypeName(type));
+
+ ptr = addToRequestList(&BLEBrowseListHead, domain, type, flags);
+
+ // If equivalent BLE browse is already running, just return.
+ if (ptr->refCount > 1)
+ {
+ LogInfo("start_BLE_browse: Dup of existing BLE browse.");
+ return;
+ }
+
+ ptr->browseHash = BLEServiceHash(domain);
+ ptr->question = q;
+
+ if (ptr->browseHash == 0)
+ {
+ LogInfo("BLEServiceHash failed!");
+ removeFromRequestList(&BLEBrowseListHead, domain, type);
+ return;
+ }
+
+ // Save these for use in D2D plugin callback logic.
+ memcpy(ptr->key, key, keySize);
+ ptr->keySize = keySize;
+ // Extract the interface ID for easier access in the requestList_t structure
+ ptr->InterfaceID = q->InterfaceID;
+
+ addServiceToBeacon(ptr->browseHash, 0);
+
+ checkForMatchingResponses(ptr);
+}
+
+// Stop the browse.
+// Return true if this is the last reference to the browse, false otherwise.
+bool stop_BLE_browse(const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags)
+{
+ (void) flags; // not used initially
+ requestList_t * ptr;
+ bool lastReference = false;
+
+ if (!EnableBLEBasedDiscovery)
+ {
+ LogMsg("stop_BLE_browse: EnableBLEBasedDiscovery disabled");
+ return lastReference;
+ }
+
+ LogInfo("stop_BLE_browse: Stopping BLE browse for: %##s %s", domain->c, DNSTypeName(type));
+
+ ptr = *(findInRequestList(&BLEBrowseListHead, domain, type));
+ if (ptr == 0)
+ {
+ LogInfo("stop_BLE_browse: No matching browse found.");
+ return lastReference;
+ }
+
+ // If this is the last reference for this browse, update advertising and browsing bits set in
+ // the beacon after removing this browse from the list.
+ if (ptr->refCount == 1)
+ lastReference = true;
+
+ removeFromRequestList(&BLEBrowseListHead, domain, type);
+
+ if (lastReference)
+ updateBeacon();
+
+ // If there are no active browse or registration requests, BLE scanning will be disabled.
+ // Clear the list of responses received to remove any stale response state.
+ if (BLEBrowseListHead == NULL && BLERegistrationListHead == 0)
+ clearResponseLists();
+
+ return lastReference;
+}
+
+extern void internal_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags, DNSQuestion * q);
+extern void internal_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags);
+
+extern void internal_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags);
+extern void internal_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags);
+
+void start_BLE_advertise(ServiceRecordSet * serviceRecordSet, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags)
+{
+ requestList_t * ptr;
+ const domainname * instanceRemoved;
+
+ if (!EnableBLEBasedDiscovery)
+ {
+ LogMsg("start_BLE_advertise: EnableBLEBasedDiscovery disabled");
+ return;
+ }
+
+ // Just process the SRV record for each service registration. The PTR
+ // record already has the service type at the beginning of the domain, but
+ // we want to filter out reverse address PTR records at this point in time, so using
+ // the SRV record instead.
+ if (type != kDNSServiceType_SRV)
+ return;
+
+ if (serviceRecordSet == NULL)
+ {
+ LogInfo("start_BLE_advertise: NULL service record set for: %##s %s, returning", domain->c, DNSTypeName(type));
+ return;
+ }
+ LogInfo("start_BLE_advertise: Starting BLE advertisement for: %##s %s", domain->c, DNSTypeName(type));
+
+ instanceRemoved = SkipLeadingLabels(domain, 1);
+
+ ptr = addToRequestList(&BLERegistrationListHead, instanceRemoved, type, flags);
+
+ // If equivalent BLE registration is already running, just return.
+ if (ptr->refCount > 1)
+ {
+ LogInfo("start_BLE_advertise: Dup of existing BLE advertisement.");
+ return;
+ }
+
+ ptr->registeredHash = BLEServiceHash(instanceRemoved);
+ if (ptr->registeredHash == 0)
+ {
+ LogInfo("BLEServiceHash failed!");
+ removeFromRequestList(&BLERegistrationListHead, instanceRemoved, type);
+ return;
+ }
+ ptr->serviceRecordSet = serviceRecordSet;
+ // Extract the interface ID for easier access in the requestList_t structure
+ ptr->InterfaceID = serviceRecordSet->RR_SRV.resrec.InterfaceID;
+
+ addServiceToBeacon(0, ptr->registeredHash);
+}
+
+void stop_BLE_advertise(const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags)
+{
+ (void) flags; // not used initially
+ requestList_t * ptr;
+ bool lastReference = false;
+ const domainname * instanceRemoved;
+
+ if (!EnableBLEBasedDiscovery)
+ {
+ LogMsg("stop_BLE_advertise: EnableBLEBasedDiscovery disabled");
+ return;
+ }
+
+ // Just process the SRV record for each service registration. The PTR
+ // record already has the service type at the beginning of the domain, but
+ // we want to filter out reverse address PTR records at this point in time, so using
+ // the SRV record instead.
+ if (type != kDNSServiceType_SRV)
+ return;
+
+ LogInfo("stop_BLE_advertise: Stopping BLE advertisement for: %##s %s", domain->c, DNSTypeName(type));
+
+ instanceRemoved = SkipLeadingLabels(domain, 1);
+
+ // Get the request pointer from the indirect pointer returned.
+ ptr = *(findInRequestList(&BLERegistrationListHead, instanceRemoved, type));
+
+ if (ptr == 0)
+ {
+ LogInfo("stop_BLE_advertise: No matching advertisement found.");
+ return;
+ }
+
+ // If this is the last reference for this registration, update advertising and browsing bits set in
+ // the beacon before removing this registration from the request list.
+ if (ptr->refCount == 1)
+ {
+ lastReference = true;
+
+ if (isAutoTriggerRequest(ptr) && ptr->triggeredOnAWDL)
+ {
+ // And remove the corresponding advertisements from the AWDL D2D plugin.
+ // Do it directly here, since we do not set the kDNSServiceFlagsIncludeAWDL bit in the original client request structure
+ // when we trigger the registration over AWDL, we just update the record ARType field, so our caller, external_stop_browsing_for_service()
+ // would not call into the D2D plugin to remove the advertisements in this case.
+ internal_stop_advertising_service(& ptr->serviceRecordSet->RR_PTR.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ internal_stop_advertising_service(& ptr->serviceRecordSet->RR_SRV.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ internal_stop_advertising_service(& ptr->serviceRecordSet->RR_TXT.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ }
+ }
+ removeFromRequestList(&BLERegistrationListHead, instanceRemoved, type);
+
+ if (lastReference)
+ updateBeacon();
+
+ // If there are no active browse or registration requests, BLE scanning will be disabled.
+ // Clear the list of responses received to remove any stale response state.
+ if (BLEBrowseListHead == NULL && BLERegistrationListHead == 0)
+ clearResponseLists();
+}
+
+#pragma mark - Response Handling
+
+// Structure used to track the beacons received from various peers.
+typedef struct responseList
+{
+ struct responseList * next;
+ serviceHash_t browseHash;
+ serviceHash_t registeredHash;
+ mDNSEthAddr senderMAC;
+} responseList_t;
+
+#define RESPONSE_LIST_NUMBER 8
+static responseList_t* BLEResponseListHeads[RESPONSE_LIST_NUMBER];
+
+mDNSlocal responseList_t ** findInResponseList(mDNSEthAddr * ptrToMAC)
+{
+ // Use the least significant byte of the MAC address as our hash index to find the list.
+ responseList_t **ptr = & BLEResponseListHeads[ptrToMAC->b[5] % RESPONSE_LIST_NUMBER];
+
+ for ( ; *ptr; ptr = &(*ptr)->next)
+ {
+ if (memcmp(&(*ptr)->senderMAC, ptrToMAC, sizeof(mDNSEthAddr)) == 0)
+ break;
+ }
+
+ return ptr;
+}
+
+
+mDNSlocal responseList_t ** addToResponseList(serviceHash_t browseHash, serviceHash_t registeredHash, mDNSEthAddr * ptrToMAC)
+{
+ responseList_t **ptr = findInResponseList(ptrToMAC);
+
+ if (!*ptr)
+ {
+ *ptr = mDNSPlatformMemAllocate(sizeof(**ptr));
+ mDNSPlatformMemZero(*ptr, sizeof(**ptr));
+ (*ptr)->browseHash = browseHash;
+ (*ptr)->registeredHash = registeredHash;
+ memcpy(& (*ptr)->senderMAC, ptrToMAC, sizeof(mDNSEthAddr));
+ }
+
+ return ptr;
+}
+
+mDNSlocal void removeFromResponseList(mDNSEthAddr * ptrToMAC)
+{
+ responseList_t **ptr = findInResponseList(ptrToMAC);
+
+ if (!*ptr)
+ {
+ LogMsg("removeFromResponseList: did not find entry for MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ ptrToMAC->b[0], ptrToMAC->b[1], ptrToMAC->b[2], ptrToMAC->b[3], ptrToMAC->b[4], ptrToMAC->b[5]);
+ return;
+ }
+
+ LogInfo("removeFromResponseList: removing entry for MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ ptrToMAC->b[0], ptrToMAC->b[1], ptrToMAC->b[2], ptrToMAC->b[3], ptrToMAC->b[4], ptrToMAC->b[5]);
+
+ responseList_t *tmp = *ptr;
+ *ptr = (*ptr)->next;
+ mDNSPlatformMemFree(tmp);
+}
+
+// Free all current entries on the BLE response lists, removing all pointers
+// to freed structures from the lists.
+mDNSlocal void clearResponseLists()
+{
+ responseList_t **ptr;
+
+ for (unsigned int i = 0; i < RESPONSE_LIST_NUMBER; i++)
+ {
+ ptr = & BLEResponseListHeads[i];
+ while (*ptr)
+ {
+ responseList_t * tmp;
+
+ tmp = *ptr;
+ *ptr = (*ptr)->next;
+ mDNSPlatformMemFree(tmp);
+ }
+ }
+}
+
+// Called from mDNS_Execute() when NextBLEServiceTime is reached
+// to stop the BLE beacon a few seconds after the last request has
+// been stopped. This gives peers a chance to see that this device
+// is no longer browsing for or advertising any services via the
+// BLE beacon.
+void serviceBLE(void)
+{
+ mDNSStorage.NextBLEServiceTime = 0;
+ if (BLEBrowseListHead || BLERegistrationListHead)
+ {
+ // We don't expect to be called if there are active requests.
+ LogInfo("serviceBLE: called with active BLE requests ??");
+ return;
+ }
+ stopBLEBeacon();
+}
+
+// Called from start_BLE_browse() on the mDNSResonder kqueue thread
+mDNSlocal void checkForMatchingResponses(requestList_t *bp)
+{
+ responseList_t *ptr;
+
+ for (unsigned int i = 0; i < RESPONSE_LIST_NUMBER; i++)
+ {
+ for (ptr = BLEResponseListHeads[i]; ptr; ptr = ptr->next)
+ {
+ if ((bp->browseHash & ptr->registeredHash) == bp->browseHash)
+ {
+ // Clear the registered services hash for the response.
+ // The next beacon from this peer will update the hash and our
+ // newly started browse will get an add event if there is a match.
+ ptr->registeredHash = 0;
+ }
+ }
+ }
+}
+
+// Define a fixed name to use for the instance name denoting that one or more instances
+// of a service are being advetised by peers in their BLE beacons.
+// Name format is: length byte + bytes of name string + two byte pointer to the PTR record name.
+// See compression_lhs definition in the D2D plugin code for backgound on 0xc027 DNS name compression pointer value.
+static Byte *BLEinstanceValue = (Byte *) "\x11ThresholdInstance\xc0\x27";
+#define BLEValueSize strlen((const char *)BLEinstanceValue)
+
+void xD2DAddToCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize);
+void xD2DRemoveFromCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize);
+
+// Find each unique browse that matches the registered service hash in the BLE response.
+// Called on the CFRunLoop thread while handling a callback from CoreBluetooth.
+// Caller should hold KQueueLock().
+mDNSlocal void findMatchingBrowse(responseList_t *response)
+{
+ requestList_t *ptr;
+
+ ptr = BLEBrowseListHead;
+ for ( ; ptr; ptr = ptr->next)
+ {
+ if ((ptr->browseHash & response->registeredHash) == ptr->browseHash)
+ {
+
+ LogInfo("findMatchingBrowse: Registration in response matched browse for: %##s", ptr->name.c);
+
+ if (inResponseListForRequest(ptr, response))
+ {
+ LogInfo("findMatchingBrowse: Already on response list for browse: %##s", ptr->name.c);
+
+ continue;
+ }
+ else
+ {
+ LogInfo("findMatchingBrowse: Adding to response list for browse: %##s", ptr->name.c);
+
+ if (ptr->ourResponses == 0)
+ {
+ if (isAutoTriggerRequest(ptr))
+ {
+ LogInfo("findMatchingBrowse: First BLE response, triggering browse for %##s on AWDL", ptr->name.c);
+ ptr->question->flags |= kDNSServiceFlagsIncludeAWDL;
+ mDNSCoreRestartQuestion(& mDNSStorage, ptr->question);
+ // register with the AWDL D2D plugin,
+ internal_start_browsing_for_service(ptr->question->InterfaceID, & ptr->name, ptr->type, ptr->question->flags, ptr->question);
+ }
+
+ // Browse on mDNSInterface_BLE is used to determine if there are one or more instances of the
+ // service type discoveryed over BLE. If this is the first instance, add the psuedo instance defined by BLEinstanceValue.
+ if (ptr->question->InterfaceID == mDNSInterface_BLE)
+ {
+ xD2DAddToCache(& mDNSStorage, kD2DSuccess, 0, D2DBLETransport, ptr->key, ptr->keySize, BLEinstanceValue, BLEValueSize);
+ }
+ }
+ addToResponseListForRequest(ptr, response);
+ }
+ }
+ else
+ {
+ // If a previous response from this peer had matched the browse, remove that response from the
+ // list now. If this is the last matching response, remove the corresponding key from the AWDL D2D plugin
+ if (removeFromResponseListForRequest(ptr, response) && (ptr->ourResponses == 0))
+ {
+ if (ptr->question->InterfaceID == mDNSInterface_BLE)
+ {
+ xD2DRemoveFromCache(& mDNSStorage, kD2DSuccess, 0, D2DBLETransport, ptr->key, ptr->keySize, BLEinstanceValue, BLEValueSize);
+ }
+
+ if (isAutoTriggerRequest(ptr))
+ {
+ LogInfo("findMatchingBrowse: Last BLE response, disabling browse for %##s on AWDL", ptr->name.c);
+ internal_stop_browsing_for_service(ptr->question->InterfaceID, & ptr->name, ptr->type, ptr->question->flags);
+ }
+ }
+ }
+ }
+}
+
+// Find each local registration that matches the service browse hash in the BLE response.
+// Called on the CFRunLoop thread while handling a callback from CoreBluetooth.
+// Caller should hold KQueueLock().
+mDNSlocal void findMatchingRegistration(responseList_t *response)
+{
+ requestList_t *ptr;
+
+ ptr = BLERegistrationListHead;
+ for ( ; ptr; ptr = ptr->next)
+ {
+ if ((ptr->registeredHash & response->browseHash) == ptr->registeredHash)
+ {
+
+ LogInfo("findMatchingRegistration: Incoming browse matched registration for: %##s", ptr->name.c);
+
+ if (inResponseListForRequest(ptr, response))
+ {
+ LogInfo("findMatchingRegistration: Already on response list for registration: %##s", ptr->name.c);
+
+ continue;
+ }
+ else
+ {
+ LogInfo("findMatchingRegistration: Adding to response list for registration: %##s", ptr->name.c);
+
+ // Also pass the registration to the AWDL D2D plugin if this is the first matching peer browse for
+ // an auto triggered local registration.
+ if ((ptr->ourResponses == 0) && isAutoTriggerRequest(ptr))
+ {
+ AuthRecType newARType;
+
+ LogInfo("findMatchingRegistration: First BLE response, triggering registration for %##s on AWDL", ptr->name.c);
+ if (ptr->serviceRecordSet == 0)
+ {
+ LogInfo("findMatchingRegistration: serviceRecordSet pointer is NULL ??");
+ continue;
+ }
+ // Modify the PTR, TXT, and SRV records so that they now apply to AWDL and restart the registration.
+ // RR_ADV is not passed to the D2D plugins froma internal_start_advertising_helper(), so we don't do it here either.
+
+ if (ptr->flags & kDNSServiceFlagsIncludeAWDL)
+ {
+ LogInfo("findMatchingRegistration: registration for %##s already applies to AWDL, skipping", ptr->name.c);
+ continue;
+ }
+
+ // Save the current ARType value to restore when the promotion to use AWDL is stopped.
+ ptr->savedARType = ptr->serviceRecordSet->RR_PTR.ARType;
+
+ // Preserve P2P attribute if original registration was applied to P2P.
+ if (ptr->serviceRecordSet->RR_PTR.ARType == AuthRecordAnyIncludeP2P)
+ newARType = AuthRecordAnyIncludeAWDLandP2P;
+ else
+ newARType = AuthRecordAnyIncludeAWDL;
+
+ ptr->serviceRecordSet->RR_PTR.ARType = newARType;
+ ptr->serviceRecordSet->RR_SRV.ARType = newARType;
+ ptr->serviceRecordSet->RR_TXT.ARType = newARType;
+ mDNSCoreRestartRegistration(& mDNSStorage, & ptr->serviceRecordSet->RR_PTR, -1);
+ mDNSCoreRestartRegistration(& mDNSStorage, & ptr->serviceRecordSet->RR_SRV, -1);
+ mDNSCoreRestartRegistration(& mDNSStorage, & ptr->serviceRecordSet->RR_TXT, -1);
+
+ internal_start_advertising_service(& ptr->serviceRecordSet->RR_PTR.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ internal_start_advertising_service(& ptr->serviceRecordSet->RR_SRV.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ internal_start_advertising_service(& ptr->serviceRecordSet->RR_TXT.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ // indicate the registration has been applied to the AWDL interface
+ ptr->triggeredOnAWDL = true;
+ }
+
+ addToResponseListForRequest(ptr, response);
+ }
+ }
+ else
+ {
+ // If a previous response from this peer had matched the browse, remove that response from the
+ // list now. If this is the last matching response for a local auto triggered registration,
+ // remove the advertised key/value pairs from the AWDL D2D plugin.
+ if (removeFromResponseListForRequest(ptr, response) && (ptr->ourResponses == 0) && isAutoTriggerRequest(ptr))
+ {
+ LogInfo("findMatchingRegistration: Last BLE response, disabling registration for %##s on AWDL", ptr->name.c);
+
+ // Restore the saved ARType and call into the AWDL D2D plugin to stop the corresponding record advertisements over AWDL.
+ ptr->serviceRecordSet->RR_PTR.ARType = ptr->savedARType;
+ ptr->serviceRecordSet->RR_SRV.ARType = ptr->savedARType;
+ ptr->serviceRecordSet->RR_TXT.ARType = ptr->savedARType;
+ internal_stop_advertising_service(& ptr->serviceRecordSet->RR_PTR.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ internal_stop_advertising_service(& ptr->serviceRecordSet->RR_SRV.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ internal_stop_advertising_service(& ptr->serviceRecordSet->RR_TXT.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ }
+ }
+ }
+}
+
+// Called on CFRunLoop thread during CoreBluetooth beacon response processing.
+// Thus, must call KQueueLock() prior to calling any core mDNSResponder routines to register records, etc.
+void responseReceived(serviceHash_t browseHash, serviceHash_t registeredHash, mDNSEthAddr * ptrToMAC)
+{
+ responseList_t ** ptr;
+
+ KQueueLock(& mDNSStorage);
+ ptr = findInResponseList(ptrToMAC);
+ if (*ptr == 0)
+ {
+ // Only add to list if peer is actively browsing or advertising.
+ if (browseHash || registeredHash)
+ {
+ LogInfo("responseReceived: First beacon of this type, adding to list");
+ LogInfo("responseReceived: browseHash = 0x%x, registeredHash = 0x%x",
+ browseHash, registeredHash);
+ LogInfo("responseReceived: sender MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ ptrToMAC->b[0], ptrToMAC->b[1], ptrToMAC->b[2], ptrToMAC->b[3], ptrToMAC->b[4], ptrToMAC->b[5]);
+
+ ptr = addToResponseList(browseHash, registeredHash, ptrToMAC);
+ // See if we are browsing for any of the peers advertised services.
+ findMatchingBrowse(*ptr);
+ // See if we have a registration that matches the peer's browse.
+ findMatchingRegistration(*ptr);
+ }
+ }
+ else // have entry from this MAC in the list
+ {
+ if (((*ptr)->browseHash == browseHash) && ((*ptr)->registeredHash == registeredHash))
+ {
+ // A duplicate of a current entry.
+#if VERBOSE_BLE_DEBUG
+ LogInfo("responseReceived: Duplicate of previous beacon, ignoring");
+ LogInfo("responseReceived: sender MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ ptrToMAC->b[0], ptrToMAC->b[1], ptrToMAC->b[2], ptrToMAC->b[3], ptrToMAC->b[4], ptrToMAC->b[5]);
+#endif // VERBOSE_BLE_DEBUG
+ }
+ else
+ {
+ LogInfo("responseReceived: Update of previous beacon");
+ LogInfo("responseReceived: browseHash = 0x%x, registeredHash = 0x%x",
+ browseHash, registeredHash);
+ LogInfo("responseReceived: sender MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ ptrToMAC->b[0], ptrToMAC->b[1], ptrToMAC->b[2], ptrToMAC->b[3], ptrToMAC->b[4], ptrToMAC->b[5]);
+
+ (*ptr)->browseHash = browseHash;
+ (*ptr)->registeredHash = registeredHash;
+
+ findMatchingBrowse(*ptr);
+ findMatchingRegistration(*ptr);
+ }
+
+ // If peer is no longer browsing or advertising, remove from list.
+ if ((browseHash == 0) && (registeredHash == 0))
+ {
+ LogInfo("responseReceived: Removing peer entry from the list");
+
+ removeFromResponseList(ptrToMAC);
+ }
+ }
+
+ KQueueUnlock(& mDNSStorage, "BLE responseReceived");
+}
diff --git a/mDNSResponder/mDNSMacOSX/BLE.h b/mDNSResponder/mDNSMacOSX/BLE.h
new file mode 100644
index 00000000..970c8faf
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BLE.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2015-2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BLE_H_
+#define _BLE_H_
+
+#include "dns_sd.h"
+#include "dns_sd_private.h"
+
+typedef unsigned int serviceHash_t;
+
+void start_BLE_browse(DNSQuestion * q, const domainname *const typeDomain, DNS_TypeValues type, DNSServiceFlags flags,
+ mDNSu8 *key, size_t keySize);
+bool stop_BLE_browse(const domainname *const typeDomain, DNS_TypeValues type, DNSServiceFlags flags);
+
+void start_BLE_advertise(ServiceRecordSet * serviceRecordSet, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags);
+void stop_BLE_advertise(const domainname *const typeDomain, DNS_TypeValues type, DNSServiceFlags flags);
+
+void responseReceived(serviceHash_t browseHash, serviceHash_t registeredHash, mDNSEthAddr *ptrToMAC);
+
+void serviceBLE(void);
+
+// C interfaces to Objective-C beacon management code.
+void updateBLEBeaconAndScan(serviceHash_t browseHash, serviceHash_t registeredHash);
+void stopBLEBeacon(void);
+
+extern mDNS mDNSStorage;
+extern mDNSBool EnableBLEBasedDiscovery;
+
+// TODO: Add the following to a local D2D.h file
+#include <DeviceToDeviceManager/DeviceToDeviceManager.h>
+
+// Just define as the current max value for now.
+// TODO: Will need to define in DeviceToDeviceManager.framework if we convert this
+// BLE discovery code to a D2D plugin.
+#define D2DBLETransport D2DTransportMax
+
+#define applyToBLE(interface, flags) ((interface == mDNSInterface_BLE) || ((interface == mDNSInterface_Any) && (flags & kDNSServiceFlagsAutoTrigger)))
+
+#endif /* _BLE_H_ */
diff --git a/mDNSResponder/mDNSMacOSX/DNSProxySupport.c b/mDNSResponder/mDNSMacOSX/DNSProxySupport.c
index 34f21a57..7666cbc4 100644
--- a/mDNSResponder/mDNSMacOSX/DNSProxySupport.c
+++ b/mDNSResponder/mDNSMacOSX/DNSProxySupport.c
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <sys/time.h>
#include <sys/event.h>
+#include <netinet/tcp.h>
#define ValidSocket(s) ((s) >= 0)
@@ -101,6 +102,9 @@ mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context)
ProxyTCPInfo_t *ti = (ProxyTCPInfo_t *)context;
TCPSocket *sock = &ti->sock;
KQSocketSet *kq = &sock->ss;
+ struct tcp_info tcp_if;
+ socklen_t size = sizeof(tcp_if);
+ int32_t intf_id = 0;
(void) filter;
@@ -135,6 +139,12 @@ mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context)
mDNSPlatformDisposeProxyContext(ti);
return;
}
+ if (getsockopt(s1, IPPROTO_TCP, TCP_INFO, &tcp_if, &size) != 0)
+ {
+ LogMsg("ProxyTCPReceive: getsockopt for TCP_INFO failed (fd=%d) errno %d", s1, errno);
+ return;
+ }
+ intf_id = tcp_if.tcpi_last_outif;
if (from.ss_family == AF_INET)
{
@@ -148,7 +158,8 @@ mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context)
destAddr.type = mDNSAddrType_IPv4;
destAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr;
- LogInfo("ProxyTCPReceive received IPv4 packet(len %d) from %#-15a to %#-15a on skt %d %s", ti->replyLen, &senderAddr, &destAddr, s1, NULL);
+ LogInfo("ProxyTCPReceive received IPv4 packet(len %d) from %#-15a to %#-15a on skt %d %s ifindex %d",
+ ti->replyLen, &senderAddr, &destAddr, s1, NULL, intf_id);
}
else if (from.ss_family == AF_INET6)
{
@@ -161,7 +172,8 @@ mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context)
destAddr.type = mDNSAddrType_IPv6;
destAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
- LogInfo("ProxyTCPReceive received IPv6 packet(len %d) from %#-15a to %#-15a on skt %d %s", ti->replyLen, &senderAddr, &destAddr, s1, NULL);
+ LogInfo("ProxyTCPReceive received IPv6 packet(len %d) from %#-15a to %#-15a on skt %d %s ifindex %d",
+ ti->replyLen, &senderAddr, &destAddr, s1, NULL, intf_id);
}
else
{
@@ -174,7 +186,7 @@ mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context)
// In the UDP case, there is just a single socket and nothing to free. Hence, the context (last argument)
// would be NULL.
kq->m->p->TCPProxyCallback(kq->m, sock, ti->reply, (mDNSu8 *)ti->reply + ti->replyLen, &senderAddr, senderPort, &destAddr,
- UnicastDNSPort, 0, ti);
+ UnicastDNSPort, (mDNSInterfaceID)(uintptr_t)intf_id, ti);
}
mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context)
@@ -204,6 +216,7 @@ mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context)
return;
}
mDNSPlatformMemZero(ti, sizeof(ProxyTCPInfo_t));
+
TCPSocket *sock = &ti->sock;
kq = &sock->ss;
@@ -222,6 +235,7 @@ mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context)
{
LogMsg("ProxyTCPAccept: IP_RECVIF %d errno %d (%s)", newfd, errno, strerror(errno));
mDNSPlatformDisposeProxyContext(ti);
+ close(newfd);
return;
}
}
@@ -235,6 +249,7 @@ mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context)
{
LogMsg("ProxyTCPAccept: IP_RECVPKTINFO %d errno %d (%s)", newfd, errno, strerror(errno));
mDNSPlatformDisposeProxyContext(ti);
+ close(newfd);
return;
}
}
@@ -244,7 +259,6 @@ mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context)
// Instead of remembering the address family, we remember the right fd.
sock->fd = newfd;
sock->kqEntry = k;
-
k->KQcallback = ProxyTCPSocketCallBack;
k->KQcontext = ti;
k->KQtask = "TCP Proxy packet reception";
diff --git a/mDNSResponder/mDNSMacOSX/DNSSECSupport.c b/mDNSResponder/mDNSMacOSX/DNSSECSupport.c
index 6e5ae108..b87f0d44 100644
--- a/mDNSResponder/mDNSMacOSX/DNSSECSupport.c
+++ b/mDNSResponder/mDNSMacOSX/DNSSECSupport.c
@@ -44,6 +44,8 @@
// When we can't fetch the root TA due to network errors etc., we start off a timer
// to fire at 60 seconds and then keep doubling it till we fetch it
#define InitialTAFetchInterval 60
+#define DNSSECProbePercentage 1
+
#if !TARGET_OS_IPHONE
DNSQuestion DNSSECProbeQuestion;
@@ -165,7 +167,7 @@ mDNSlocal mDNSu8 *ConvertDigest(char *digest, int digestType, int *diglen)
int l, h;
l = HexVal(digest[i]);
h = HexVal(digest[i+1]);
- if (l<0 || h<0) { LogMsg("ConvertDigest: Cannot convert digest"); return NULL;}
+ if (l<0 || h<0) { LogMsg("ConvertDigest: Cannot convert digest"); mDNSPlatformMemFree(dig); return NULL;}
dig[j++] = (mDNSu8)((l << 4) | h);
}
return dig;
@@ -560,8 +562,8 @@ mDNSexport void DNSSECProbe(mDNS *const m)
return;
rand = mDNSRandom(0x3FFFFFFF) % 100;
- // Probe 5% of the time
- if (rand > 5)
+ // Probe 1% of the time
+ if (rand >= DNSSECProbePercentage)
return;
mDNS_DropLockBeforeCallback();
diff --git a/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c b/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c
index efd61b30..dd670ab1 100644
--- a/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c
+++ b/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c
@@ -25,7 +25,6 @@
#include "../mDNSMacOSX/DNSServiceDiscovery.h"
#include "DNSServiceDiscoveryDefines.h"
-#include "DNSServiceDiscoveryReplyServer.h"
#include <stdlib.h>
#include <stdio.h>
@@ -49,25 +48,6 @@ kern_return_t DNSServiceBrowserCreate_rpc
DNSCString domain
);
-extern
-kern_return_t DNSServiceDomainEnumerationCreate_rpc
-(
- mach_port_t server,
- mach_port_t client,
- int registrationDomains
-);
-
-extern
-kern_return_t DNSServiceRegistrationCreate_rpc
-(
- mach_port_t server,
- mach_port_t client,
- DNSCString name,
- DNSCString regtype,
- DNSCString domain,
- IPPort port,
- DNSCString txtRecord
-);
extern
kern_return_t DNSServiceResolverResolve_rpc
@@ -79,36 +59,6 @@ kern_return_t DNSServiceResolverResolve_rpc
DNSCString domain
);
-extern
-kern_return_t DNSServiceRegistrationAddRecord_rpc
-(
- mach_port_t server,
- mach_port_t client,
- int type,
- record_data_t data,
- mach_msg_type_number_t record_dataCnt,
- uint32_t ttl,
- natural_t *reference
-);
-
-extern
-int DNSServiceRegistrationUpdateRecord_rpc
-(
- mach_port_t server,
- mach_port_t client,
- natural_t reference,
- record_data_t data,
- mach_msg_type_number_t record_dataCnt,
- uint32_t ttl
-);
-
-extern
-kern_return_t DNSServiceRegistrationRemoveRecord_rpc
-(
- mach_port_t server,
- mach_port_t client,
- natural_t reference
-);
struct a_requests {
struct a_requests *next;
@@ -122,552 +72,51 @@ struct a_requests {
void *context;
};
-static struct a_requests *a_requests = NULL;
-static pthread_mutex_t a_requests_lock = PTHREAD_MUTEX_INITIALIZER;
-
typedef struct _dns_service_discovery_t {
mach_port_t port;
} dns_service_discovery_t;
-static mach_port_t DNSServiceDiscoveryLookupServer(void)
-{
- static mach_port_t sndPort = MACH_PORT_NULL;
- kern_return_t result;
-
- if (sndPort != MACH_PORT_NULL) {
- return sndPort;
- }
-
- result = bootstrap_look_up(bootstrap_port, DNS_SERVICE_DISCOVERY_SERVER, &sndPort);
- if (result != KERN_SUCCESS) {
- printf("%s(): {%s:%d} bootstrap_look_up() failed: $%x\n", __FUNCTION__, __FILE__, __LINE__, (int) result);
- sndPort = MACH_PORT_NULL;
- }
-
-
- return sndPort;
-}
-
-static void _increaseQueueLengthOnPort(mach_port_t port)
-{
- mach_port_limits_t qlimits;
- kern_return_t result;
-
- qlimits.mpl_qlimit = 16;
- result = mach_port_set_attributes(mach_task_self(), port, MACH_PORT_LIMITS_INFO, (mach_port_info_t)&qlimits, MACH_PORT_LIMITS_INFO_COUNT);
-
- if (result != KERN_SUCCESS) {
- printf("%s(): {%s:%d} mach_port_set_attributes() failed: $%x %s\n", __FUNCTION__, __FILE__, __LINE__, (int) result, mach_error_string(result));
- }
-}
dns_service_discovery_ref DNSServiceBrowserCreate (const char *regtype, const char *domain, DNSServiceBrowserReply callBack,void *context)
{
- mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
- mach_port_t clientPort;
- kern_return_t result;
- dns_service_discovery_ref return_t;
- struct a_requests *request;
-
- if (!serverPort) {
- return NULL;
- }
-
- result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
- if (result != KERN_SUCCESS) {
- printf("Mach port receive creation failed, %s\n", mach_error_string(result));
- return NULL;
- }
- result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
- if (result != KERN_SUCCESS) {
- printf("Mach port send creation failed, %s\n", mach_error_string(result));
- mach_port_destroy(mach_task_self(), clientPort);
- return NULL;
- }
- _increaseQueueLengthOnPort(clientPort);
-
- return_t = malloc(sizeof(dns_service_discovery_t));
- return_t->port = clientPort;
-
- request = malloc(sizeof(struct a_requests));
- request->client_port = clientPort;
- request->context = context;
- request->callout.browserCallback = callBack;
-
- result = DNSServiceBrowserCreate_rpc(serverPort, clientPort, (char *)regtype, (char *)domain);
-
- if (result != KERN_SUCCESS) {
- printf("There was an error creating a browser, %s\n", mach_error_string(result));
- free(request);
- return NULL;
- }
-
- pthread_mutex_lock(&a_requests_lock);
- request->next = a_requests;
- a_requests = request;
- pthread_mutex_unlock(&a_requests_lock);
-
- return return_t;
+
+ (void) regtype; // Unused
+ (void) domain; // Unused
+ (void) callBack; // Unused
+ (void) context; // Unused
+
+ printf("DNSServiceBrowserCreate deprecated since 10.3 \n");
+ return NULL;
+
}
-/* Service Enumeration */
-
-dns_service_discovery_ref DNSServiceDomainEnumerationCreate (int registrationDomains, DNSServiceDomainEnumerationReply callBack, void *context)
-{
- mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
- mach_port_t clientPort;
- kern_return_t result;
- dns_service_discovery_ref return_t;
- struct a_requests *request;
-
- if (!serverPort) {
- return NULL;
- }
-
- result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
- if (result != KERN_SUCCESS) {
- printf("Mach port receive creation failed, %s\n", mach_error_string(result));
- return NULL;
- }
- result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
- if (result != KERN_SUCCESS) {
- printf("Mach port send creation failed, %s\n", mach_error_string(result));
- mach_port_destroy(mach_task_self(), clientPort);
- return NULL;
- }
- _increaseQueueLengthOnPort(clientPort);
-
- return_t = malloc(sizeof(dns_service_discovery_t));
- return_t->port = clientPort;
-
- request = malloc(sizeof(struct a_requests));
- request->client_port = clientPort;
- request->context = context;
- request->callout.enumCallback = callBack;
-
- result = DNSServiceDomainEnumerationCreate_rpc(serverPort, clientPort, registrationDomains);
-
- if (result != KERN_SUCCESS) {
- printf("There was an error creating an enumerator, %s\n", mach_error_string(result));
- free(request);
- return NULL;
- }
-
- pthread_mutex_lock(&a_requests_lock);
- request->next = a_requests;
- a_requests = request;
- pthread_mutex_unlock(&a_requests_lock);
-
- return return_t;
-}
-
-
-/* Service Registration */
-
-dns_service_discovery_ref DNSServiceRegistrationCreate
- (const char *name, const char *regtype, const char *domain, uint16_t port, const char *txtRecord, DNSServiceRegistrationReply callBack, void *context)
-{
- mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
- mach_port_t clientPort;
- kern_return_t result;
- dns_service_discovery_ref return_t;
- struct a_requests *request;
- IPPort IpPort;
- char *portptr = (char *)&port;
-
- if (!serverPort) {
- return NULL;
- }
-
- if (!txtRecord) {
- txtRecord = "";
- }
-
- result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
- if (result != KERN_SUCCESS) {
- printf("Mach port receive creation failed, %s\n", mach_error_string(result));
- return NULL;
- }
- result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
- if (result != KERN_SUCCESS) {
- printf("Mach port send creation failed, %s\n", mach_error_string(result));
- mach_port_destroy(mach_task_self(), clientPort);
- return NULL;
- }
- _increaseQueueLengthOnPort(clientPort);
-
- return_t = malloc(sizeof(dns_service_discovery_t));
- return_t->port = clientPort;
-
- request = malloc(sizeof(struct a_requests));
- request->client_port = clientPort;
- request->context = context;
- request->callout.regCallback = callBack;
-
- // older versions of this code passed the port via mach IPC as an int.
- // we continue to pass it as 4 bytes to maintain binary compatibility,
- // but now ensure that the network byte order is preserved by using a struct
- IpPort.bytes[0] = 0;
- IpPort.bytes[1] = 0;
- IpPort.bytes[2] = portptr[0];
- IpPort.bytes[3] = portptr[1];
-
- result = DNSServiceRegistrationCreate_rpc(serverPort, clientPort, (char *)name, (char *)regtype, (char *)domain, IpPort, (char *)txtRecord);
-
- if (result != KERN_SUCCESS) {
- printf("There was an error creating a resolve, %s\n", mach_error_string(result));
- free(request);
- return NULL;
- }
-
- pthread_mutex_lock(&a_requests_lock);
- request->next = a_requests;
- a_requests = request;
- pthread_mutex_unlock(&a_requests_lock);
-
- return return_t;
-}
-
-/* Resolver requests */
-
dns_service_discovery_ref DNSServiceResolverResolve(const char *name, const char *regtype, const char *domain, DNSServiceResolverReply callBack, void *context)
{
- mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
- mach_port_t clientPort;
- kern_return_t result;
- dns_service_discovery_ref return_t;
- struct a_requests *request;
-
- if (!serverPort) {
- return NULL;
- }
+ (void) name; // Unused
+ (void) regtype; // Unused
+ (void) domain; // Unused
+ (void) callBack; // Unused
+ (void) context; // Unused
+
+ printf("DNSServiceResolverResolve deprecated since 10.3 \n");
+ return NULL;
- result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
- if (result != KERN_SUCCESS) {
- printf("Mach port receive creation failed, %s\n", mach_error_string(result));
- return NULL;
- }
- result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
- if (result != KERN_SUCCESS) {
- printf("Mach port send creation failed, %s\n", mach_error_string(result));
- mach_port_destroy(mach_task_self(), clientPort);
- return NULL;
- }
- _increaseQueueLengthOnPort(clientPort);
-
- return_t = malloc(sizeof(dns_service_discovery_t));
- return_t->port = clientPort;
-
- request = malloc(sizeof(struct a_requests));
- request->client_port = clientPort;
- request->context = context;
- request->callout.resolveCallback = callBack;
-
- DNSServiceResolverResolve_rpc(serverPort, clientPort, (char *)name, (char *)regtype, (char *)domain);
-
- pthread_mutex_lock(&a_requests_lock);
- request->next = a_requests;
- a_requests = request;
- pthread_mutex_unlock(&a_requests_lock);
-
- return return_t;
-}
-
-DNSRecordReference DNSServiceRegistrationAddRecord(dns_service_discovery_ref ref, uint16_t rrtype, uint16_t rdlen, const char *rdata, uint32_t ttl)
-{
- mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
- mach_port_t clientPort;
- natural_t reference = 0;
- kern_return_t result = KERN_SUCCESS;
-
- if (!serverPort) {
- return kDNSServiceDiscoveryUnknownErr;
- }
-
- clientPort = DNSServiceDiscoveryMachPort(ref);
-
- if (!clientPort) {
- return kDNSServiceDiscoveryUnknownErr;
- }
-
- result = DNSServiceRegistrationAddRecord_rpc(serverPort, clientPort, rrtype, (record_data_t)rdata, rdlen, ttl, &reference);
-
- if (result != KERN_SUCCESS) {
- printf("The result of the registration was not successful. Error %d, result %s\n", result, mach_error_string(result));
- }
-
- return reference;
-}
-
-DNSServiceRegistrationReplyErrorType DNSServiceRegistrationUpdateRecord(dns_service_discovery_ref ref, DNSRecordReference reference, uint16_t rdlen, const char *rdata, uint32_t ttl)
-{
- mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
- mach_port_t clientPort;
- kern_return_t result = KERN_SUCCESS;
-
- if (!serverPort) {
- return kDNSServiceDiscoveryUnknownErr;
- }
-
- clientPort = DNSServiceDiscoveryMachPort(ref);
-
- if (!clientPort) {
- return kDNSServiceDiscoveryUnknownErr;
- }
-
- result = DNSServiceRegistrationUpdateRecord_rpc(serverPort, clientPort, (natural_t)reference, (record_data_t)rdata, rdlen, ttl);
- if (result != KERN_SUCCESS) {
- printf("The result of the registration was not successful. Error %d, result %s\n", result, mach_error_string(result));
- return result;
- }
-
- return kDNSServiceDiscoveryNoError;
-}
-
-
-DNSServiceRegistrationReplyErrorType DNSServiceRegistrationRemoveRecord(dns_service_discovery_ref ref, DNSRecordReference reference)
-{
- mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
- mach_port_t clientPort;
- kern_return_t result = KERN_SUCCESS;
-
- if (!serverPort) {
- return kDNSServiceDiscoveryUnknownErr;
- }
-
- clientPort = DNSServiceDiscoveryMachPort(ref);
-
- if (!clientPort) {
- return kDNSServiceDiscoveryUnknownErr;
- }
-
- result = DNSServiceRegistrationRemoveRecord_rpc(serverPort, clientPort, (natural_t)reference);
-
- if (result != KERN_SUCCESS) {
- printf("The result of the registration was not successful. Error %d, result %s\n", result, mach_error_string(result));
- return result;
- }
-
- return kDNSServiceDiscoveryNoError;
}
void DNSServiceDiscovery_handleReply(void *replyMsg)
{
- mach_msg_header_t * msgSendBufPtr;
- mach_msg_header_t * receivedMessage;
- unsigned msgSendBufLength;
-
- msgSendBufLength = internal_DNSServiceDiscoveryReply_subsystem.maxsize;
- msgSendBufPtr = (mach_msg_header_t *) malloc(msgSendBufLength);
-
-
- receivedMessage = ( mach_msg_header_t * ) replyMsg;
-
- // Call DNSServiceDiscoveryReply_server to change mig-generated message into a
- // genuine mach message. It will then cause the callback to get called.
- DNSServiceDiscoveryReply_server ( receivedMessage, msgSendBufPtr );
- ( void ) mach_msg_send ( msgSendBufPtr );
- free(msgSendBufPtr);
+ (void) replyMsg; // Unused
+ printf("DNSServiceDiscovery_handleReply deprecated since 10.3 \n");
}
mach_port_t DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDiscovery)
{
+ printf("DNSServiceDiscoveryMachPort deprecated since 10.3 \n");
return dnsServiceDiscovery->port;
}
void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery)
{
- struct a_requests *request0, *request;
- mach_port_t reply = dnsServiceDiscovery->port;
-
- if (dnsServiceDiscovery->port) {
- pthread_mutex_lock(&a_requests_lock);
- request0 = NULL;
- request = a_requests;
- while (request) {
- if (request->client_port == reply) {
- /* request info found, remove from list */
- if (request0) {
- request0->next = request->next;
- } else {
- a_requests = request->next;
- }
- break;
- } else {
- /* not info for this request, skip to next */
- request0 = request;
- request = request->next;
- }
-
- }
- pthread_mutex_unlock(&a_requests_lock);
-
- free(request);
-
- mach_port_destroy(mach_task_self(), dnsServiceDiscovery->port);
-
- free(dnsServiceDiscovery);
- }
- return;
-}
-
-// reply functions, calls the users setup callbacks with function pointers
-
-kern_return_t internal_DNSServiceDomainEnumerationReply_rpc
-(
- mach_port_t reply,
- int resultType,
- DNSCString replyDomain,
- int flags
-)
-{
- struct a_requests *request;
- void *requestContext = NULL;
- DNSServiceDomainEnumerationReply callback = NULL;
-
- pthread_mutex_lock(&a_requests_lock);
- request = a_requests;
- while (request) {
- if (request->client_port == reply) {
- break;
- }
- request = request->next;
- }
-
- if (request != NULL) {
- callback = (*request->callout.enumCallback);
- requestContext = request->context;
- }
- pthread_mutex_unlock(&a_requests_lock);
-
- if (request != NULL) {
- (callback)(resultType, replyDomain, flags, requestContext);
- }
-
- return KERN_SUCCESS;
-
-}
-
-kern_return_t internal_DNSServiceBrowserReply_rpc
-(
- mach_port_t reply,
- int resultType,
- DNSCString replyName,
- DNSCString replyType,
- DNSCString replyDomain,
- int flags
-)
-{
- struct a_requests *request;
- void *requestContext = NULL;
- DNSServiceBrowserReply callback = NULL;
-
- pthread_mutex_lock(&a_requests_lock);
- request = a_requests;
- while (request) {
- if (request->client_port == reply) {
- break;
- }
- request = request->next;
- }
- if (request != NULL) {
- callback = (*request->callout.browserCallback);
- requestContext = request->context;
- }
-
- pthread_mutex_unlock(&a_requests_lock);
-
- if (request != NULL) {
- (callback)(resultType, replyName, replyType, replyDomain, flags, requestContext);
- }
-
- return KERN_SUCCESS;
-}
-
-
-kern_return_t internal_DNSServiceRegistrationReply_rpc
-(
- mach_port_t reply,
- int resultType
-)
-{
- struct a_requests *request;
- void *requestContext = NULL;
- DNSServiceRegistrationReply callback = NULL;
-
- pthread_mutex_lock(&a_requests_lock);
- request = a_requests;
- while (request) {
- if (request->client_port == reply) {
- break;
- }
- request = request->next;
- }
- if (request != NULL) {
- callback = (*request->callout.regCallback);
- requestContext = request->context;
- }
-
- pthread_mutex_unlock(&a_requests_lock);
- if (request != NULL) {
- (callback)(resultType, requestContext);
- }
- return KERN_SUCCESS;
-}
-
-
-kern_return_t internal_DNSServiceResolverReply_rpc
-(
- mach_port_t reply,
- sockaddr_t interface,
- sockaddr_t address,
- DNSCString txtRecord,
- int flags
-)
-{
- struct sockaddr *interface_storage = NULL;
- struct sockaddr *address_storage = NULL;
- struct a_requests *request;
- void *requestContext = NULL;
- DNSServiceResolverReply callback = NULL;
-
- if (interface) {
- int len = ((struct sockaddr *)interface)->sa_len;
- interface_storage = (struct sockaddr *)malloc(len);
- memcpy(interface_storage, interface, len);
- }
-
- if (address) {
- int len = ((struct sockaddr *)address)->sa_len;
- address_storage = (struct sockaddr *)malloc(len);
- memcpy(address_storage, address, len);
- }
-
- pthread_mutex_lock(&a_requests_lock);
- request = a_requests;
- while (request) {
- if (request->client_port == reply) {
- break;
- }
- request = request->next;
- }
-
- if (request != NULL) {
- callback = (*request->callout.resolveCallback);
- requestContext = request->context;
- }
- pthread_mutex_unlock(&a_requests_lock);
-
- if (request != NULL) {
- (callback)(interface_storage, address_storage, txtRecord, flags, requestContext);
- }
-
- if (interface) {
- free(interface_storage);
- }
- if (address) {
- free(address_storage);
- }
-
- return KERN_SUCCESS;
+ (void) dnsServiceDiscovery; // Unused
+ printf("DNSServiceDiscoveryDeallocate deprecated since 10.3 \n");
}
diff --git a/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.h b/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.h
index a743dd74..004d3259 100644
--- a/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.h
+++ b/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.h
@@ -17,31 +17,7 @@
/*! @header DNS Service Discovery (Deprecated Mach-based API)
*
- * @discussion This section describes the functions, callbacks, and data structures that
- * make up the DNS Service Discovery API.
- *
- * The DNS Service Discovery API is part of Bonjour, Apple's implementation of
- * zero-configuration networking (ZEROCONF).
- *
- * Bonjour allows you to register a network service, such as a
- * printer or file server, so that it can be found by name or browsed
- * for by service type and domain. Using Bonjour, applications can
- * discover what services are available on the network, along with
- * all necessary access information-such as name, IP address, and port
- * number-for a given service.
- *
- * In effect, Bonjour combines the functions of a local DNS server
- * and AppleTalk. Bonjour allows applications to provide user-friendly printer
- * and server browsing, among other things, over standard IP networks.
- * This behavior is a result of combining protocols such as multicast and DNS
- * to add new functionality to the network (such as multicast DNS).
- *
- * Bonjour gives applications easy access to services over local IP
- * networks without requiring the service or the application to support
- * an AppleTalk or a Netbeui stack, and without requiring a DNS server
- * for the local network.
- *
- * Note that this API was deprecated in Mac OS X 10.3, and replaced
+ * @discussion Note that this API was deprecated in Mac OS X 10.3, and replaced
* by the portable cross-platform /usr/include/dns_sd.h API.
*/
@@ -71,29 +47,38 @@ enum {
};
+typedef enum
+{
+ DNSServiceDomainEnumerationReplyAddDomain,
+ DNSServiceDomainEnumerationReplyAddDomainDefault,
+ DNSServiceDomainEnumerationReplyRemoveDomain,
+} DNSServiceDomainEnumerationReplyResultType;
+
+typedef enum
+{
+ DNSServiceDiscoverReplyFlagsFinished,
+ DNSServiceDiscoverReplyFlagsMoreComing,
+} DNSServiceDiscoveryReplyFlags;
+
+typedef void (*DNSServiceDomainEnumerationReply)(
+ DNSServiceDomainEnumerationReplyResultType resultType, // One of DNSServiceDomainEnumerationReplyResultType
+ const char *replyDomain,
+ DNSServiceDiscoveryReplyFlags flags, // DNS Service Discovery reply flags information
+ void *context
+);
+
+
/* possible error code values */
typedef enum
{
- kDNSServiceDiscoveryWaiting = 1,
kDNSServiceDiscoveryNoError = 0,
- // mDNS Error codes are in the range
- // FFFE FF00 (-65792) to FFFE FFFF (-65537)
- kDNSServiceDiscoveryUnknownErr = -65537, // 0xFFFE FFFF
- kDNSServiceDiscoveryNoSuchNameErr = -65538,
- kDNSServiceDiscoveryNoMemoryErr = -65539,
- kDNSServiceDiscoveryBadParamErr = -65540,
- kDNSServiceDiscoveryBadReferenceErr = -65541,
- kDNSServiceDiscoveryBadStateErr = -65542,
- kDNSServiceDiscoveryBadFlagsErr = -65543,
- kDNSServiceDiscoveryUnsupportedErr = -65544,
- kDNSServiceDiscoveryNotInitializedErr = -65545,
- kDNSServiceDiscoveryNoCache = -65546,
- kDNSServiceDiscoveryAlreadyRegistered = -65547,
- kDNSServiceDiscoveryNameConflict = -65548,
- kDNSServiceDiscoveryInvalid = -65549,
- kDNSServiceDiscoveryMemFree = -65792 // 0xFFFE FF00
} DNSServiceRegistrationReplyErrorType;
+typedef void (*DNSServiceRegistrationReply)(
+ DNSServiceRegistrationReplyErrorType errorCode,
+ void *context
+);
+
typedef uint32_t DNSRecordReference;
@@ -107,79 +92,6 @@ typedef uint32_t DNSRecordReference;
*/
void DNSServiceDiscovery_handleReply(void *replyMsg);
-/* Service Registration */
-
-typedef void (*DNSServiceRegistrationReply)(
- DNSServiceRegistrationReplyErrorType errorCode,
- void *context
- );
-
-/*!
- @function DNSServiceRegistrationCreate
- @discussion Register a named service with DNS Service Discovery
- @param name The name of this service instance (e.g. "Steve's Printer")
- @param regtype The service type (e.g. "_printer._tcp." -- see
- RFC 2782 (DNS SRV) and <http://www.iana.org/assignments/port-numbers>)
- @param domain The domain in which to register the service (e.g. "apple.com.")
- @param port The local port on which this service is being offered (in network byte order)
- @param txtRecord Optional protocol-specific additional information
- @param callBack The DNSServiceRegistrationReply function to be called
- @param context A user specified context which will be passed to the callout function.
- @result A dns_registration_t
- */
-dns_service_discovery_ref DNSServiceRegistrationCreate
-(
- const char *name,
- const char *regtype,
- const char *domain,
- uint16_t port,
- const char *txtRecord,
- DNSServiceRegistrationReply callBack,
- void *context
-) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3;
-
-/***************************************************************************/
-/* DNS Domain Enumeration */
-
-typedef enum
-{
- DNSServiceDomainEnumerationReplyAddDomain, // Domain found
- DNSServiceDomainEnumerationReplyAddDomainDefault, // Domain found (and should be selected by default)
- DNSServiceDomainEnumerationReplyRemoveDomain, // Domain has been removed from network
-} DNSServiceDomainEnumerationReplyResultType;
-
-typedef enum
-{
- DNSServiceDiscoverReplyFlagsFinished,
- DNSServiceDiscoverReplyFlagsMoreComing,
-} DNSServiceDiscoveryReplyFlags;
-
-typedef void (*DNSServiceDomainEnumerationReply)(
- DNSServiceDomainEnumerationReplyResultType resultType, // One of DNSServiceDomainEnumerationReplyResultType
- const char *replyDomain,
- DNSServiceDiscoveryReplyFlags flags, // DNS Service Discovery reply flags information
- void *context
- );
-
-/*!
- @function DNSServiceDomainEnumerationCreate
- @discussion Asynchronously create a DNS Domain Enumerator
- @param registrationDomains A boolean indicating whether you are looking
- for recommended registration domains
- (e.g. equivalent to the AppleTalk zone list in the AppleTalk Control Panel)
- or recommended browsing domains
- (e.g. equivalent to the AppleTalk zone list in the Chooser).
- @param callBack The function to be called when domains are found or removed
- @param context A user specified context which will be passed to the callout function.
- @result A dns_registration_t
- */
-dns_service_discovery_ref DNSServiceDomainEnumerationCreate
-(
- int registrationDomains,
- DNSServiceDomainEnumerationReply callBack,
- void *context
-) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3;
-
/***************************************************************************/
/* DNS Service Browser */
@@ -271,44 +183,6 @@ mach_port_t DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDisc
*/
void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3;
-/***************************************************************************/
-/* Registration updating */
-
-
-/*!
- @function DNSServiceRegistrationAddRecord
- @discussion Request that the mDNS Responder add the DNS Record of a specific type
- @param dnsServiceDiscovery A dns_service_discovery_ref as returned from a DNSServiceRegistrationCreate call
- @param rrtype A standard DNS Resource Record Type, from http://www.iana.org/assignments/dns-parameters
- @param rdlen Length of the data
- @param rdata Opaque binary Resource Record data, up to 64 kB.
- @param ttl time to live for the added record.
- @result DNSRecordReference An opaque reference that can be passed to the update and remove record calls. If an error occurs, this value will be zero or negative
- */
-DNSRecordReference DNSServiceRegistrationAddRecord(dns_service_discovery_ref dnsServiceDiscovery, uint16_t rrtype, uint16_t rdlen, const char *rdata, uint32_t ttl) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3;
-
-/*!
- @function DNSServiceRegistrationUpdateRecord
- @discussion Request that the mDNS Responder add the DNS Record of a specific type
- @param dnsServiceDiscovery A dns_service_discovery_ref as returned from a DNSServiceRegistrationCreate call
- @param dnsRecordReference A dnsRecordReference as returned from a DNSServiceRegistrationAddRecord call
- @param rdlen Length of the data
- @param rdata Opaque binary Resource Record data, up to 64 kB.
- @param ttl time to live for the updated record.
- @result DNSServiceRegistrationReplyErrorType If an error occurs, this value will be non zero
- */
-DNSServiceRegistrationReplyErrorType DNSServiceRegistrationUpdateRecord(dns_service_discovery_ref ref, DNSRecordReference reference, uint16_t rdlen, const char *rdata, uint32_t ttl) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3;
-
-/*!
- @function DNSServiceRegistrationRemoveRecord
- @discussion Request that the mDNS Responder remove the DNS Record(s) of a specific type
- @param dnsServiceDiscovery A dns_service_discovery_ref as returned from a DNSServiceRegistrationCreate call
- @param dnsRecordReference A dnsRecordReference as returned from a DNSServiceRegistrationAddRecord call
- @result DNSServiceRegistrationReplyErrorType If an error occurs, this value will be non zero
- */
-DNSServiceRegistrationReplyErrorType DNSServiceRegistrationRemoveRecord(dns_service_discovery_ref ref, DNSRecordReference reference) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3;
-
-
__END_DECLS
#endif /* __DNS_SERVICE_DISCOVERY_H */
diff --git a/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryDefines.h b/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryDefines.h
index 22687b90..01a28cd7 100644
--- a/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryDefines.h
+++ b/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryDefines.h
@@ -20,8 +20,6 @@
#include <mach/mach_types.h>
-#define DNS_SERVICE_DISCOVERY_SERVER "com.apple.mDNSResponder"
-
typedef char DNSCString[1024];
typedef char sockaddr_t[128];
diff --git a/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryReply.defs b/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryReply.defs
deleted file mode 100644
index 993c9553..00000000
--- a/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryReply.defs
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2003, 2006 Apple Computer, Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-subsystem
- DNSServiceDiscoveryReply 7250;
-
-ServerPrefix internal_;
-
-#include <mach/std_types.defs>
-#include <mach/mach_types.defs>
-
-import "DNSServiceDiscoveryDefines.h";
-
-type DNSCString = c_string[*:1024];
-type sockaddr_t = array[128] of char;
-
-simpleroutine DNSServiceDomainEnumerationReply_rpc(
- reply: mach_port_t;
- in resultType: int;
- in replyDomain: DNSCString;
- in flags: int;
- SendTime to: natural_t);
-
-simpleroutine DNSServiceBrowserReply_rpc(
- reply: mach_port_t;
- in resultType: int;
- in replyName: DNSCString;
- in replyType: DNSCString;
- in replyDomain: DNSCString;
- in flags: int;
- SendTime to: natural_t);
-
-
-simpleroutine DNSServiceRegistrationReply_rpc(
- reply: mach_port_t;
- in resultType: int;
- SendTime to: natural_t);
-
-
-simpleroutine DNSServiceResolverReply_rpc(
- reply: mach_port_t;
- in interface: sockaddr_t;
- in address: sockaddr_t;
- in txtRecord: DNSCString;
- in flags: int;
- SendTime to: natural_t);
diff --git a/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryRequest.defs b/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryRequest.defs
deleted file mode 100644
index d3fe292a..00000000
--- a/mDNSResponder/mDNSMacOSX/DNSServiceDiscoveryRequest.defs
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004, 2006 Apple Computer, Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-subsystem
- DNSServiceDiscoveryRequest 7200;
-
-ServerPrefix provide_;
-
-#include <mach/std_types.defs>
-#include <mach/mach_types.defs>
-
-import "DNSServiceDiscoveryDefines.h";
-
-type DNSCString = c_string[*:1024];
-type record_data = ^ array [] of MACH_MSG_TYPE_BYTE
- ctype: record_data_t;
-type IPPort = struct[4] of char ctype:IPPort;
-
-simpleroutine DNSServiceBrowserCreate_rpc(
- server: mach_port_t;
- in client: mach_port_t;
- in regtype: DNSCString;
- in domain: DNSCString);
-
-
-simpleroutine DNSServiceDomainEnumerationCreate_rpc(
- server: mach_port_t;
- in client: mach_port_t;
- in registrationDomains: int);
-
-simpleroutine DNSServiceRegistrationCreate_rpc(
- server: mach_port_t;
- in client: mach_port_t;
- in name: DNSCString;
- in regtype: DNSCString;
- in domain: DNSCString;
- in port: IPPort;
- in txtRecord: DNSCString);
-
-
-simpleroutine DNSServiceResolverResolve_rpc(
- server: mach_port_t;
- in client: mach_port_t;
- in name: DNSCString;
- in regtype: DNSCString;
- in domain: DNSCString);
-
-routine DNSServiceRegistrationAddRecord_rpc(
- server: mach_port_t;
- in client: mach_port_t;
- in record_type: int;
- in record_data: record_data;
- in ttl: uint32_t;
- out record_reference: natural_t);
-
-simpleroutine DNSServiceRegistrationUpdateRecord_rpc(
- server: mach_port_t;
- in client: mach_port_t;
- in record_reference: natural_t;
- in record_data: record_data;
- in ttl: uint32_t);
-
-simpleroutine DNSServiceRegistrationRemoveRecord_rpc(
- server: mach_port_t;
- in client: mach_port_t;
- in record_reference: natural_t);
diff --git a/mDNSResponder/mDNSMacOSX/Metrics.h b/mDNSResponder/mDNSMacOSX/Metrics.h
index a9dea79a..dbe6196a 100644
--- a/mDNSResponder/mDNSMacOSX/Metrics.h
+++ b/mDNSResponder/mDNSMacOSX/Metrics.h
@@ -25,9 +25,10 @@ extern "C" {
#endif
#if TARGET_OS_EMBEDDED
-mStatus MetricsInit(void);
-void MetricsUpdateUDNSStats(const domainname *inQueryName, mDNSBool inAnswered, mDNSu32 inSendCount, mDNSu32 inLatencyMs, mDNSBool inForCellular);
-void LogMetrics(void);
+mStatus MetricsInit(void);
+void MetricsUpdateUDNSQueryStats(const domainname *inQueryName, mDNSu16 inType, const ResourceRecord *inRR, mDNSu32 inSendCount, mDNSu32 inLatencyMs, mDNSBool inForCell);
+void MetricsUpdateUDNSResolveStats(const domainname *inQueryName, const ResourceRecord *inRR, mDNSBool inForCell);
+void LogMetrics(void);
#endif
#ifdef __cplusplus
diff --git a/mDNSResponder/mDNSMacOSX/Metrics.m b/mDNSResponder/mDNSMacOSX/Metrics.m
index 56467dfc..8dae3f5f 100644
--- a/mDNSResponder/mDNSMacOSX/Metrics.m
+++ b/mDNSResponder/mDNSMacOSX/Metrics.m
@@ -17,12 +17,18 @@
#import "Metrics.h"
-#if TARGET_OS_EMBEDDED
+#if (TARGET_OS_EMBEDDED)
#import <CoreUtils/SoftLinking.h>
#import <WirelessDiagnostics/AWDDNSDomainStats.h>
#import <WirelessDiagnostics/AWDMDNSResponderDNSStatistics.h>
+#import <WirelessDiagnostics/AWDMDNSResponderResolveStats.h>
+#import <WirelessDiagnostics/AWDMDNSResponderResolveStatsDNSServer.h>
+#import <WirelessDiagnostics/AWDMDNSResponderResolveStatsDomain.h>
+#import <WirelessDiagnostics/AWDMDNSResponderResolveStatsHostname.h>
+#import <WirelessDiagnostics/AWDMDNSResponderResolveStatsResult.h>
#import <WirelessDiagnostics/AWDMetricIds_MDNSResponder.h>
#import <WirelessDiagnostics/WirelessDiagnostics.h>
+#import <WirelessDiagnostics/AWDMDNSResponderServicesStats.h>
#import "DNSCommon.h"
#import "mDNSMacOSX.h"
@@ -34,44 +40,116 @@
SOFT_LINK_FRAMEWORK(PrivateFrameworks, WirelessDiagnostics)
-SOFT_LINK_CLASS(WirelessDiagnostics, AWDServerConnection)
-#define AWDServerConnectionSoft getAWDServerConnectionClass()
-
-SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderDNSStatistics)
-#define AWDMDNSResponderDNSStatisticsSoft getAWDMDNSResponderDNSStatisticsClass()
-
SOFT_LINK_CLASS(WirelessDiagnostics, AWDDNSDomainStats)
-#define AWDDNSDomainStatsSoft getAWDDNSDomainStatsClass()
+SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderDNSStatistics)
+SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStats)
+SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsDNSServer)
+SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsDomain)
+SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsHostname)
+SOFT_LINK_CLASS(WirelessDiagnostics, AWDMDNSResponderResolveStatsResult)
+SOFT_LINK_CLASS(WirelessDiagnostics, AWDServerConnection)
+SOFT_LINK_CLASS(WirelessDiagnostics, AWDMetricManager)
+
+#define AWDDNSDomainStatsSoft getAWDDNSDomainStatsClass()
+#define AWDMDNSResponderDNSStatisticsSoft getAWDMDNSResponderDNSStatisticsClass()
+#define AWDMDNSResponderResolveStatsSoft getAWDMDNSResponderResolveStatsClass()
+#define AWDMDNSResponderResolveStatsResultSoft getAWDMDNSResponderResolveStatsResultClass()
+#define AWDMDNSResponderResolveStatsDNSServerSoft getAWDMDNSResponderResolveStatsDNSServerClass()
+#define AWDMDNSResponderResolveStatsDomainSoft getAWDMDNSResponderResolveStatsDomainClass()
+#define AWDMDNSResponderResolveStatsHostnameSoft getAWDMDNSResponderResolveStatsHostnameClass()
+#define AWDServerConnectionSoft getAWDServerConnectionClass()
+#define AWDMetricManagerSoft getAWDMetricManagerClass()
//===========================================================================================================================
// Macros
//===========================================================================================================================
-#define countof(X) (sizeof(X) / sizeof(X[0]))
+#define countof(X) (sizeof(X) / sizeof(X[0]))
+#define countof_field(TYPE, FIELD) countof(((TYPE *)0)->FIELD)
+#define increment_saturate(VAR, MAX) do {if ((VAR) < (MAX)) {++(VAR);}} while (0)
+#define ForgetMem(X) do {if(*(X)) {free(*(X)); *(X) = NULL;}} while(0)
//===========================================================================================================================
// Constants
//===========================================================================================================================
-#define kUDNSStatsMaxQuerySendCount 10
+#define kQueryStatsMaxQuerySendCount 10
+#define kQueryStatsSendCountBinCount (kQueryStatsMaxQuerySendCount + 1)
+#define kQueryStatsLatencyBinCount 55
+#define kResolveStatsMaxObjCount 2000
+
+//===========================================================================================================================
+// Data structures
+//===========================================================================================================================
+
+typedef struct
+{
+ const char * cstr; // Name of domain as a c-string.
+ const domainname * name; // Name of domain as length-prefixed labels.
+ int labelCount; // Number of labels in domain name. Used for domain name comparisons.
+
+} Domain;
-// Important: Do not update this list without getting privacy approval. See <rdar://problem/24155761>.
+// Important: Do not add to this list without getting privacy approval beforehand. See <rdar://problem/24155761&26397203>.
+// If you get approval and do add a domain to this list, make sure it passes ValidateDNSStatsDomains() below.
-static const char * const kUDNSStatsDomains[] =
+static const Domain kQueryStatsDomains[] =
{
- ".",
- "apple.com.",
- "icloud.com.",
- "me.com.",
- "google.com.",
- "facebook.com.",
- "youtube.com.",
- "baidu.com.",
- "amazon.com.",
- "yahoo.com.",
- "wikipedia.org."
+ { ".", (domainname *)"", 0 },
+ { "apple.com.", (domainname *)"\x5" "apple" "\x3" "com", 2 },
+ { "icloud.com.", (domainname *)"\x6" "icloud" "\x3" "com", 2 },
+ { "mzstatic.com.", (domainname *)"\x8" "mzstatic" "\x3" "com", 2 },
+ { "me.com.", (domainname *)"\x2" "me" "\x3" "com", 2 },
+ { "google.com.", (domainname *)"\x6" "google" "\x3" "com", 2 },
+ { "youtube.com.", (domainname *)"\x7" "youtube" "\x3" "com", 2 },
+ { "facebook.com.", (domainname *)"\x8" "facebook" "\x3" "com", 2 },
+ { "baidu.com.", (domainname *)"\x5" "baidu" "\x3" "com", 2 },
+ { "yahoo.com.", (domainname *)"\x5" "yahoo" "\x3" "com", 2 },
+ { "qq.com.", (domainname *)"\x2" "qq" "\x3" "com", 2 },
};
+check_compile_time(countof(kQueryStatsDomains) == 11);
+
+// DNSHist contains the per domain per network type histogram data that goes in a DNSDomainStats protobuf message. See
+// <rdar://problem/23980546> MDNSResponder.proto update.
+//
+// answeredQuerySendCountBins
+//
+// An array of 11 histogram bins. The value at index i, for 0 <= i <= 9, is the number of times that an answered DNS query
+// was sent i times. The value at index 10 is the number of times that an answered query was sent 10+ times.
+//
+// unansweredQuerySendCountBins
+//
+// An array of 11 histogram bins. The value at index i, for 0 <= i <= 9, is the number of times that an unanswered DNS query
+// was sent i times. The value at index 10 is the number of times that an unanswered query was sent 10+ times.
+//
+// responseLatencyBins
+//
+// An array of 55 histogram bins. Each array value is the number of DNS queries that were answered in a paricular time
+// interval. The 55 consecutive non-overlapping time intervals have the following non-inclusive upper bounds (all values are
+// in milliseconds): 1, 2, 3, 4, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190,
+// 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, 1000, 1500, 2000, 2500, 3000, 3500, 4000,
+// 4500, 5000, 6000, 7000, 8000, 9000, 10000, ∞.
+
+typedef struct
+{
+ uint16_t unansweredQuerySendCountBins[kQueryStatsSendCountBinCount];
+ uint16_t unansweredQueryDurationBins[kQueryStatsLatencyBinCount];
+ uint16_t answeredQuerySendCountBins[kQueryStatsSendCountBinCount];
+ uint16_t responseLatencyBins[kQueryStatsLatencyBinCount];
+ uint16_t negAnsweredQuerySendCountBins[kQueryStatsSendCountBinCount];
+ uint16_t negResponseLatencyBins[kQueryStatsLatencyBinCount];
+
+} DNSHist;
+
+check_compile_time(sizeof(DNSHist) <= 512);
+check_compile_time(countof_field(DNSHist, unansweredQuerySendCountBins) == (kQueryStatsMaxQuerySendCount + 1));
+check_compile_time(countof_field(DNSHist, answeredQuerySendCountBins) == (kQueryStatsMaxQuerySendCount + 1));
+check_compile_time(countof_field(DNSHist, negAnsweredQuerySendCountBins) == (kQueryStatsMaxQuerySendCount + 1));
+
+// Important: Do not modify kResponseLatencyMsLimits because the code used to generate AWD reports expects the response
+// latency histogram bins to observe these time interval upper bounds.
+
static const mDNSu32 kResponseLatencyMsLimits[] =
{
1, 2, 3, 4, 5,
@@ -83,51 +161,200 @@ static const mDNSu32 kResponseLatencyMsLimits[] =
10000
};
-//===========================================================================================================================
-// Data structures
-//===========================================================================================================================
+check_compile_time(countof(kResponseLatencyMsLimits) == 54);
+check_compile_time(countof_field(DNSHist, unansweredQueryDurationBins) == (countof(kResponseLatencyMsLimits) + 1));
+check_compile_time(countof_field(DNSHist, responseLatencyBins) == (countof(kResponseLatencyMsLimits) + 1));
+check_compile_time(countof_field(DNSHist, negResponseLatencyBins) == (countof(kResponseLatencyMsLimits) + 1));
typedef struct
{
- uint32_t answeredQuerySendCountBins[kUDNSStatsMaxQuerySendCount + 1];
- uint32_t unansweredQuerySendCountBins[kUDNSStatsMaxQuerySendCount + 1];
- uint32_t responseLatencyBins[countof(kResponseLatencyMsLimits) + 1];
+ DNSHist * histAny; // Histogram data for queries of any resource record type.
+ DNSHist * histA; // Histogram data for queries for A resource records.
+ DNSHist * histAAAA; // Histogram data for queries for AAAA resource records.
-} DNSStats;
+} DNSHistSet;
-typedef struct DNSDomainStats * DNSDomainStatsRef;
+typedef struct DNSDomainStats DNSDomainStats;
struct DNSDomainStats
{
- DNSDomainStatsRef next;
- domainname domain;
- int domainLabelCount;
- char * domainStr;
- DNSStats stats;
- DNSStats statsCellular;
+ DNSDomainStats * next; // Pointer to next domain stats in list.
+ const Domain * domain; // Domain for which these stats are collected.
+ DNSHistSet * nonCellular; // Query stats for queries sent over non-cellular interfaces.
+ DNSHistSet * cellular; // Query stats for queries sent over cellular interfaces.
+};
+
+check_compile_time(sizeof(struct DNSDomainStats) <= 32);
+
+static const Domain kResolveStatsDomains[] =
+{
+ { "apple.com.", (domainname *)"\x5" "apple" "\x3" "com", 2 },
+ { "icloud.com.", (domainname *)"\x6" "icloud" "\x3" "com", 2 },
+ { "mzstatic.com.", (domainname *)"\x8" "mzstatic" "\x3" "com", 2 },
+ { "me.com.", (domainname *)"\x2" "me" "\x3" "com", 2 },
+};
+
+check_compile_time(countof(kResolveStatsDomains) == 4);
+
+typedef struct ResolveStatsDomain ResolveStatsDomain;
+typedef struct ResolveStatsHostname ResolveStatsHostname;
+typedef struct ResolveStatsDNSServer ResolveStatsDNSServer;
+typedef struct ResolveStatsIPv4AddrSet ResolveStatsIPv4AddrSet;
+typedef struct ResolveStatsIPv6Addr ResolveStatsIPv6Addr;
+typedef struct ResolveStatsNegAAAASet ResolveStatsNegAAAASet;
+
+struct ResolveStatsDomain
+{
+ ResolveStatsDomain * next; // Next domain object in list.
+ ResolveStatsHostname * hostnameList; // List of hostname objects in this domain.
+ const Domain * domainInfo; // Pointer to domain info.
+};
+
+struct ResolveStatsHostname
+{
+ ResolveStatsHostname * next; // Next hostname object in list.
+ ResolveStatsIPv4AddrSet * addrV4List; // List of IPv4 addresses to which this hostname resolved.
+ ResolveStatsIPv6Addr * addrV6List; // List of IPv6 addresses to which this hostname resolved.
+ ResolveStatsNegAAAASet * negV6List; // List of negative AAAA response objects.
+ uint8_t name[1]; // Variable length storage for hostname as length-prefixed labels.
+};
+
+check_compile_time(sizeof(ResolveStatsHostname) <= 64);
+
+struct ResolveStatsDNSServer
+{
+ ResolveStatsDNSServer * next; // Next DNS server object in list.
+ uint8_t id; // 8-bit ID assigned to this DNS server used by IP address objects.
+ mDNSBool isForCell; // True if this DNS server belongs to a cellular interface.
+ mDNSBool isAddrV6; // True if this DNS server has an IPv6 address instead of IPv4.
+ uint8_t addrBytes[1]; // Variable length storage for DNS server's IP address.
+};
+
+check_compile_time(sizeof(ResolveStatsDNSServer) <= 32);
+
+typedef struct
+{
+ uint16_t count; // Number of times this IPv4 address was provided as a resolution result.
+ uint8_t serverID; // 8-bit ID of the DNS server from which this IPv4 address came.
+ uint8_t isNegative;
+ uint8_t addrBytes[4]; // IPv4 address bytes.
+
+} IPv4AddrCounter;
+
+check_compile_time(sizeof(IPv4AddrCounter) <= 8);
+
+struct ResolveStatsIPv4AddrSet
+{
+ ResolveStatsIPv4AddrSet * next; // Next set of IPv4 address counters in list.
+ IPv4AddrCounter counters[3]; // Array of IPv4 address counters.
+};
+
+check_compile_time(sizeof(ResolveStatsIPv4AddrSet) <= 32);
+
+struct ResolveStatsIPv6Addr
+{
+ ResolveStatsIPv6Addr * next; // Next IPv6 address object in list.
+ uint16_t count; // Number of times this IPv6 address was provided as a resolution result.
+ uint8_t serverID; // 8-bit ID of the DNS server from which this IPv6 address came.
+ uint8_t addrBytes[16]; // IPv6 address bytes.
+};
+
+check_compile_time(sizeof(ResolveStatsIPv6Addr) <= 32);
+
+typedef struct
+{
+ uint16_t count; // Number of times that a negative response was returned by a DNS server.
+ uint8_t serverID; // 8-bit ID of the DNS server that sent the negative responses.
+
+} NegAAAACounter;
+
+check_compile_time(sizeof(NegAAAACounter) <= 4);
+
+struct ResolveStatsNegAAAASet
+{
+ ResolveStatsNegAAAASet * next; // Next set of negative AAAA response counters in list.
+ NegAAAACounter counters[6]; // Array of negative AAAA response counters.
};
+check_compile_time(sizeof(ResolveStatsNegAAAASet) <= 32);
+
+typedef enum
+{
+ kResponseType_IPv4Addr = 1,
+ kResponseType_IPv6Addr = 2,
+ kResponseType_NegA = 3,
+ kResponseType_NegAAAA = 4
+
+} ResponseType;
+
+typedef struct
+{
+ ResponseType type;
+ const uint8_t * data;
+
+} Response;
+
//===========================================================================================================================
// Globals
//===========================================================================================================================
extern mDNS mDNSStorage;
-static DNSDomainStatsRef gDomainStatsList = NULL;
-static AWDServerConnection * gAWDServerConnection = nil;
+static DNSDomainStats * gDomainStatsList = NULL;
+static ResolveStatsDomain * gResolveStatsList = NULL;
+static ResolveStatsDNSServer * gResolveStatsServerList = NULL;
+static unsigned int gResolveStatsNextServerID = 0;
+static int gResolveStatsObjCount = 0;
+static AWDServerConnection * gAWDServerConnection = nil;
//===========================================================================================================================
// Local Prototypes
//===========================================================================================================================
-mDNSlocal mStatus DNSDomainStatsCreate(const char *inDomain, DNSDomainStatsRef *outStats);
-mDNSlocal void DNSDomainStatsFree(DNSDomainStatsRef inStats);
-mDNSlocal void DNSDomainStatsFreeList(DNSDomainStatsRef inList);
-
-mDNSlocal mStatus CreateDomainStatsList(DNSDomainStatsRef *outList);
-mDNSlocal void UpdateDNSStats(DNSStats *inStats, mDNSBool inAnswered, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs);
-mDNSlocal mStatus SubmitAWDMetric(void);
-mDNSlocal mStatus CreateAWDDNSDomainStats(DNSStats *inStats, const char *inDomain, mDNSBool inIsForCellular, AWDDNSDomainStats **outAWDStats);
-mDNSlocal void LogDNSStats(const DNSStats *inStats);
+mDNSlocal mStatus DNSDomainStatsCreate(const Domain *inDomain, DNSDomainStats **outStats);
+mDNSlocal void DNSDomainStatsFree(DNSDomainStats *inStats);
+mDNSlocal void DNSDomainStatsFreeList(DNSDomainStats *inList);
+mDNSlocal mStatus DNSDomainStatsUpdate(DNSDomainStats *inStats, uint16_t inType, const ResourceRecord *inRR, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs, mDNSBool inForCell);
+
+mDNSlocal mStatus ResolveStatsDomainCreate(const Domain *inDomain, ResolveStatsDomain **outDomain);
+mDNSlocal void ResolveStatsDomainFree(ResolveStatsDomain *inDomain);
+mDNSlocal mStatus ResolveStatsDomainUpdate(ResolveStatsDomain *inDomain, const domainname *inHostname, const Response *inResp, const mDNSAddr *inDNSAddr, mDNSBool inForCell);
+mDNSlocal mStatus ResolveStatsDomainCreateAWDVersion(const ResolveStatsDomain *inDomain, AWDMDNSResponderResolveStatsDomain **outDomain);
+
+mDNSlocal mStatus ResolveStatsHostnameCreate(const domainname *inName, ResolveStatsHostname **outHostname);
+mDNSlocal void ResolveStatsHostnameFree(ResolveStatsHostname *inHostname);
+mDNSlocal mStatus ResolveStatsHostnameUpdate(ResolveStatsHostname *inHostname, const Response *inResp, uint8_t inServerID);
+mDNSlocal mStatus ResolveStatsHostnameCreateAWDVersion(const ResolveStatsHostname *inHostname, AWDMDNSResponderResolveStatsHostname **outHostname);
+
+mDNSlocal mStatus ResolveStatsDNSServerCreate(const mDNSAddr *inAddr, mDNSBool inForCell, ResolveStatsDNSServer **outServer);
+mDNSlocal void ResolveStatsDNSServerFree(ResolveStatsDNSServer *inServer);
+mDNSlocal mStatus ResolveStatsDNSServerCreateAWDVersion(const ResolveStatsDNSServer *inServer, AWDMDNSResponderResolveStatsDNSServer **outServer);
+
+mDNSlocal mStatus ResolveStatsIPv4AddrSetCreate(ResolveStatsIPv4AddrSet **outSet);
+mDNSlocal void ResolveStatsIPv4AddrSetFree(ResolveStatsIPv4AddrSet *inSet);
+
+mDNSlocal mStatus ResolveStatsIPv6AddressCreate(uint8_t inServerID, const uint8_t inAddrBytes[16], ResolveStatsIPv6Addr **outAddr);
+mDNSlocal void ResolveStatsIPv6AddressFree(ResolveStatsIPv6Addr *inAddr);
+
+mDNSlocal mStatus ResolveStatsNegAAAASetCreate(ResolveStatsNegAAAASet **outSet);
+mDNSlocal void ResolveStatsNegAAAASetFree(ResolveStatsNegAAAASet *inSet);
+mDNSlocal mStatus ResolveStatsGetServerID(const mDNSAddr *inServerAddr, mDNSBool inForCell, uint8_t *outServerID);
+
+mDNSlocal mStatus CreateDomainStatsList(DNSDomainStats **outList);
+mDNSlocal mStatus CreateResolveStatsList(ResolveStatsDomain **outList);
+mDNSlocal void FreeResolveStatsList(ResolveStatsDomain *inList);
+mDNSlocal void FreeResolveStatsServerList(ResolveStatsDNSServer *inList);
+mDNSlocal mStatus SubmitAWDMetric(UInt32 inMetricID);
+mDNSlocal mStatus SubmitAWDMetricQueryStats(void);
+mDNSlocal mStatus SubmitAWDMetricResolveStats(void);
+mDNSlocal mStatus CreateAWDDNSDomainStats(DNSHist *inHist, const char *inDomain, mDNSBool inForCell, AWDDNSDomainStats_RecordType inType, AWDDNSDomainStats **outStats);
+mDNSlocal mStatus AddAWDDNSDomainStats(AWDMDNSResponderDNSStatistics *inMetric, DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell);
+mDNSlocal void LogDNSHistSet(const DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell);
+mDNSlocal void LogDNSHist(const DNSHist *inHist, const char *inDomain, mDNSBool inForCell, const char *inType);
+mDNSlocal void LogDNSHistSendCounts(const uint16_t inSendCountBins[kQueryStatsSendCountBinCount]);
+mDNSlocal void LogDNSHistLatencies(const uint16_t inLatencyBins[kQueryStatsLatencyBinCount]);
+#if (METRICS_VALIDATE_DNS_STATS_DOMAINS)
+mDNSlocal void ValidateDNSStatsDomains(void);
+#endif
//===========================================================================================================================
// MetricsInit
@@ -137,28 +364,48 @@ mStatus MetricsInit(void)
{
mStatus err;
+#if (METRICS_VALIDATE_DNS_STATS_DOMAINS)
+ ValidateDNSStatsDomains();
+#endif
+
err = CreateDomainStatsList(&gDomainStatsList);
require_noerr_quiet(err, exit);
+ err = CreateResolveStatsList(&gResolveStatsList);
+ require_noerr_quiet(err, exit);
+
@autoreleasepool
{
gAWDServerConnection = [[AWDServerConnectionSoft alloc]
- initWithComponentId: AWDComponentId_MDNSResponder
- andBlockOnConfiguration: NO];
+ initWithComponentId: AWDComponentId_MDNSResponder
+ andBlockOnConfiguration: NO];
if (gAWDServerConnection)
{
[gAWDServerConnection
- registerQueriableMetricCallback: ^(UInt32 metricId)
+ registerQueriableMetricCallback: ^(UInt32 inMetricID)
{
- mStatus localErr;
-
- (void) metricId;
-
- localErr = SubmitAWDMetric();
- if (localErr) LogMsg("SubmitAWDMetric failed with error %d", localErr);
+ SubmitAWDMetric(inMetricID);
}
forIdentifier: (UInt32)AWDMetricId_MDNSResponder_DNSStatistics];
+
+ [gAWDServerConnection
+ registerQueriableMetricCallback: ^(UInt32 inMetricID)
+ {
+ SubmitAWDMetric(inMetricID);
+ }
+ forIdentifier: (UInt32)AWDMetricId_MDNSResponder_ResolveStats];
+
+ [gAWDServerConnection
+ registerQueriableMetricCallback: ^(UInt32 inMetricID)
+ {
+ SubmitAWDMetric(inMetricID);
+ }
+ forIdentifier: (UInt32)AWDMetricId_MDNSResponder_ServicesStats];
+ }
+ else
+ {
+ LogMsg("MetricsInit: failed to create AWD server connection.");
}
}
exit:
@@ -166,67 +413,1022 @@ exit:
}
//===========================================================================================================================
-// MetricsUpdateUDNSStats
+// MetricsUpdateUDNSQueryStats
//===========================================================================================================================
-mDNSexport void MetricsUpdateUDNSStats(const domainname *inQueryName, mDNSBool inAnswered, mDNSu32 inSendCount, mDNSu32 inLatencyMs, mDNSBool inForCellular)
+mDNSexport void MetricsUpdateUDNSQueryStats(const domainname *inQueryName, mDNSu16 inType, const ResourceRecord *inRR, mDNSu32 inSendCount, mDNSu32 inLatencyMs, mDNSBool inForCell)
{
- DNSStats * stats;
- DNSDomainStatsRef domainStats;
+ DNSDomainStats * stats;
int queryLabelCount;
+ const domainname * queryParentDomain;
mDNSBool isQueryInDomain;
+ int skipCount;
+ int skipCountLast = -1;
queryLabelCount = CountLabels(inQueryName);
- for (domainStats = gDomainStatsList; domainStats; domainStats = domainStats->next)
+ for (stats = gDomainStatsList; stats; stats = stats->next)
{
isQueryInDomain = mDNSfalse;
- if (strcmp(domainStats->domainStr, ".") == 0)
+ if (strcmp(stats->domain->cstr, ".") == 0)
{
// All queries are in the root domain.
isQueryInDomain = mDNStrue;
}
else
{
- int skipCount;
- const domainname * queryParentDomain;
-
- skipCount = queryLabelCount - domainStats->domainLabelCount;
+ skipCount = queryLabelCount - stats->domain->labelCount;
if (skipCount >= 0)
{
- queryParentDomain = SkipLeadingLabels(inQueryName, skipCount);
- isQueryInDomain = SameDomainName(queryParentDomain, &domainStats->domain);
+ if (skipCount != skipCountLast)
+ {
+ queryParentDomain = SkipLeadingLabels(inQueryName, skipCount);
+ skipCountLast = skipCount;
+ }
+ isQueryInDomain = SameDomainName(queryParentDomain, stats->domain->name);
}
}
if (isQueryInDomain)
{
- stats = inForCellular ? &domainStats->statsCellular : &domainStats->stats;
- UpdateDNSStats(stats, inAnswered, inSendCount, inLatencyMs);
+ DNSDomainStatsUpdate(stats, inType, inRR, inSendCount, inLatencyMs, inForCell);
+ }
+ }
+
+}
+
+//===========================================================================================================================
+// MetricsUpdateUDNSResolveStats
+//===========================================================================================================================
+
+mDNSexport void MetricsUpdateUDNSResolveStats(const domainname *inQueryName, const ResourceRecord *inRR, mDNSBool inForCell)
+{
+ ResolveStatsDomain * domain;
+ domainname hostname;
+ size_t hostnameLen;
+ mDNSBool isQueryInDomain;
+ int skipCount;
+ int skipCountLast = -1;
+ int queryLabelCount;
+ const domainname * queryParentDomain;
+ Response response;
+
+ require_quiet((inRR->rrtype == kDNSType_A) || (inRR->rrtype == kDNSType_AAAA), exit);
+ require_quiet(inRR->rDNSServer, exit);
+
+ queryLabelCount = CountLabels(inQueryName);
+
+ for (domain = gResolveStatsList; domain; domain = domain->next)
+ {
+ isQueryInDomain = mDNSfalse;
+ skipCount = queryLabelCount - domain->domainInfo->labelCount;
+ if (skipCount >= 0)
+ {
+ if (skipCount != skipCountLast)
+ {
+ queryParentDomain = SkipLeadingLabels(inQueryName, skipCount);
+ skipCountLast = skipCount;
+ }
+ isQueryInDomain = SameDomainName(queryParentDomain, domain->domainInfo->name);
+ }
+ if (!isQueryInDomain) continue;
+
+ hostnameLen = (size_t)(queryParentDomain->c - inQueryName->c);
+ if (hostnameLen >= sizeof(hostname.c)) continue;
+
+ memcpy(hostname.c, inQueryName->c, hostnameLen);
+ hostname.c[hostnameLen] = 0;
+
+ if (inRR->RecordType == kDNSRecordTypePacketNegative)
+ {
+ response.type = (inRR->rrtype == kDNSType_A) ? kResponseType_NegA : kResponseType_NegAAAA;
+ response.data = NULL;
+ }
+ else
+ {
+ response.type = (inRR->rrtype == kDNSType_A) ? kResponseType_IPv4Addr : kResponseType_IPv6Addr;
+ response.data = (inRR->rrtype == kDNSType_A) ? inRR->rdata->u.ipv4.b : inRR->rdata->u.ipv6.b;
+ }
+ ResolveStatsDomainUpdate(domain, &hostname, &response, &inRR->rDNSServer->addr, inForCell);
+ }
+
+exit:
+ return;
+}
+
+//===========================================================================================================================
+// LogMetrics
+//===========================================================================================================================
+
+mDNSexport void LogMetrics(void)
+{
+ DNSDomainStats * stats;
+ const ResolveStatsDomain * domain;
+ const ResolveStatsHostname * hostname;
+ const ResolveStatsDNSServer * server;
+ const ResolveStatsIPv4AddrSet * addrV4;
+ const ResolveStatsIPv6Addr * addrV6;
+ const ResolveStatsNegAAAASet * negV6;
+ int hostnameCount;
+ int i;
+ unsigned int serverID;
+ int serverObjCount = 0;
+ int hostnameObjCount = 0;
+ int addrObjCount = 0;
+
+ LogMsgNoIdent("---- DNS query stats by domain -----");
+
+ for (stats = gDomainStatsList; stats; stats = stats->next)
+ {
+ if (!stats->nonCellular && !stats->cellular)
+ {
+ LogMsgNoIdent("No data for %s", stats->domain->cstr);
+ continue;
+ }
+ if (stats->nonCellular) LogDNSHistSet(stats->nonCellular, stats->domain->cstr, mDNSfalse);
+ if (stats->cellular) LogDNSHistSet(stats->cellular, stats->domain->cstr, mDNStrue);
+ }
+
+ LogMsgNoIdent("---- DNS resolve stats by domain -----");
+
+ LogMsgNoIdent("Servers:");
+ for (server = gResolveStatsServerList; server; server = server->next)
+ {
+ serverObjCount++;
+ LogMsgNoIdent(server->isAddrV6 ? "%2u: %s %.16a" : "%2u: %s %.4a",
+ server->id, server->isForCell ? " C" : "NC", server->addrBytes);
+ }
+
+ for (domain = gResolveStatsList; domain; domain = domain->next)
+ {
+ hostnameCount = 0;
+ for (hostname = domain->hostnameList; hostname; hostname = hostname->next) { hostnameCount++; }
+ hostnameObjCount += hostnameCount;
+
+ LogMsgNoIdent("%##s (%d hostname%s)", domain->domainInfo->name, hostnameCount, (hostnameCount == 1) ? "" : "s");
+
+ for (hostname = domain->hostnameList; hostname; hostname = hostname->next)
+ {
+ LogMsgNoIdent(" %##s", hostname->name);
+ for (serverID = 0; serverID < gResolveStatsNextServerID; ++serverID)
+ {
+ for (addrV4 = hostname->addrV4List; addrV4; addrV4 = addrV4->next)
+ {
+ if (serverID == 0) addrObjCount++;
+ for (i = 0; i < (int)countof(addrV4->counters); ++i)
+ {
+ const IPv4AddrCounter * counter;
+
+ counter = &addrV4->counters[i];
+ if (counter->count == 0) break;
+ if (counter->serverID == serverID)
+ {
+ if (counter->isNegative)
+ {
+ LogMsgNoIdent("%10u: %3u negative A", counter->serverID, counter->count);
+ }
+ else
+ {
+ LogMsgNoIdent("%10u: %3u %.4a", counter->serverID, counter->count, counter->addrBytes);
+ }
+ }
+ }
+ }
+ for (addrV6 = hostname->addrV6List; addrV6; addrV6 = addrV6->next)
+ {
+ if (serverID == 0) addrObjCount++;
+ if (addrV6->serverID == serverID)
+ {
+ LogMsgNoIdent("%10u: %3u %.16a", addrV6->serverID, addrV6->count, addrV6->addrBytes);
+ }
+ }
+ for (negV6 = hostname->negV6List; negV6; negV6 = negV6->next)
+ {
+ if (serverID == 0) addrObjCount++;
+ for (i = 0; i < (int)countof(negV6->counters); ++i)
+ {
+ const NegAAAACounter * counter;
+
+ counter = &negV6->counters[i];
+ if (counter->count == 0) break;
+ if (counter->serverID == serverID)
+ {
+ LogMsgNoIdent("%10u: %3u negative AAAA", counter->serverID, counter->count);
+ }
+ }
+ }
+ }
+ }
+ }
+ LogMsgNoIdent("Total object count: %3d (server %d hostname %d address %d)",
+ serverObjCount + hostnameObjCount + addrObjCount, serverObjCount, hostnameObjCount, addrObjCount);
+
+ LogMsgNoIdent("---- Num of Services Registered -----");
+ LogMsgNoIdent("Current_number_of_services_registered :[%d], Max_number_of_services_registered :[%d]",
+ curr_num_regservices, max_num_regservices);
+}
+
+//===========================================================================================================================
+// DNSDomainStatsCreate
+//===========================================================================================================================
+
+mDNSlocal mStatus DNSDomainStatsCreate(const Domain *inDomain, DNSDomainStats **outStats)
+{
+ mStatus err;
+ DNSDomainStats * obj;
+
+ obj = (DNSDomainStats *)calloc(1, sizeof(*obj));
+ require_action_quiet(obj, exit, err = mStatus_NoMemoryErr);
+
+ obj->domain = inDomain;
+
+ *outStats = obj;
+ err = mStatus_NoError;
+
+exit:
+ return (err);
+}
+
+//===========================================================================================================================
+// DNSDomainStatsFree
+//===========================================================================================================================
+
+mDNSlocal void DNSDomainStatsFree(DNSDomainStats *inStats)
+{
+ if (inStats->nonCellular)
+ {
+ ForgetMem(&inStats->nonCellular->histAny);
+ ForgetMem(&inStats->nonCellular->histA);
+ ForgetMem(&inStats->nonCellular->histAAAA);
+ free(inStats->nonCellular);
+ inStats->nonCellular = NULL;
+ }
+ if (inStats->cellular)
+ {
+ ForgetMem(&inStats->cellular->histAny);
+ ForgetMem(&inStats->cellular->histA);
+ ForgetMem(&inStats->cellular->histAAAA);
+ free(inStats->cellular);
+ inStats->cellular = NULL;
+ }
+ free(inStats);
+}
+
+//===========================================================================================================================
+// DNSDomainStatsFreeList
+//===========================================================================================================================
+
+mDNSlocal void DNSDomainStatsFreeList(DNSDomainStats *inList)
+{
+ DNSDomainStats * stats;
+
+ while ((stats = inList) != NULL)
+ {
+ inList = stats->next;
+ DNSDomainStatsFree(stats);
+ }
+}
+
+//===========================================================================================================================
+// DNSDomainStatsUpdate
+//===========================================================================================================================
+
+mDNSlocal mStatus DNSDomainStatsUpdate(DNSDomainStats *inStats, uint16_t inType, const ResourceRecord *inRR, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs, mDNSBool inForCell)
+{
+ mStatus err;
+ DNSHistSet ** p;
+ DNSHistSet * set;
+ DNSHist * histAny;
+ DNSHist * hist;
+ int i;
+
+ require_action_quiet(inRR || (inQuerySendCount > 0), exit, err = mStatus_NoError);
+
+ p = inForCell ? &inStats->cellular : &inStats->nonCellular;
+ if ((set = *p) == NULL)
+ {
+ set = (DNSHistSet *)calloc(1, sizeof(*set));
+ require_action_quiet(set, exit, err = mStatus_NoMemoryErr);
+ *p = set;
+ }
+ if ((histAny = set->histAny) == NULL)
+ {
+ histAny = (DNSHist *)calloc(1, sizeof(*histAny));
+ require_action_quiet(histAny, exit, err = mStatus_NoMemoryErr);
+ set->histAny = histAny;
+ }
+ if (inType == kDNSType_A)
+ {
+ if ((hist = set->histA) == NULL)
+ {
+ hist = (DNSHist *)calloc(1, sizeof(*hist));
+ require_action_quiet(hist, exit, err = mStatus_NoMemoryErr);
+ set->histA = hist;
+ }
+ }
+ else if (inType == kDNSType_AAAA)
+ {
+ if ((hist = set->histAAAA) == NULL)
+ {
+ hist = (DNSHist *)calloc(1, sizeof(*hist));
+ require_action_quiet(hist, exit, err = mStatus_NoMemoryErr);
+ set->histAAAA = hist;
+ }
+ }
+ else
+ {
+ hist = NULL;
+ }
+
+ if (inRR)
+ {
+ uint16_t * sendCountBins;
+ uint16_t * latencyBins;
+ const mDNSBool isNegative = (inRR->RecordType == kDNSRecordTypePacketNegative);
+
+ i = Min(inQuerySendCount, kQueryStatsMaxQuerySendCount);
+
+ sendCountBins = isNegative ? histAny->negAnsweredQuerySendCountBins : histAny->answeredQuerySendCountBins;
+ increment_saturate(sendCountBins[i], UINT16_MAX);
+ if (hist)
+ {
+ sendCountBins = isNegative ? hist->negAnsweredQuerySendCountBins : hist->answeredQuerySendCountBins;
+ increment_saturate(sendCountBins[i], UINT16_MAX);
+ }
+
+ if (inQuerySendCount > 0)
+ {
+ for (i = 0; (i < (int)countof(kResponseLatencyMsLimits)) && (inLatencyMs >= kResponseLatencyMsLimits[i]); ++i) {}
+ latencyBins = isNegative ? histAny->negResponseLatencyBins : histAny->responseLatencyBins;
+ increment_saturate(latencyBins[i], UINT16_MAX);
+ if (hist)
+ {
+ latencyBins = isNegative ? hist->negResponseLatencyBins : hist->responseLatencyBins;
+ increment_saturate(latencyBins[i], UINT16_MAX);
+ }
}
}
+ else
+ {
+ i = Min(inQuerySendCount, kQueryStatsMaxQuerySendCount);
+ increment_saturate(histAny->unansweredQuerySendCountBins[i], UINT16_MAX);
+ if (hist) increment_saturate(hist->unansweredQuerySendCountBins[i], UINT16_MAX);
+
+ for (i = 0; (i < (int)countof(kResponseLatencyMsLimits)) && (inLatencyMs >= kResponseLatencyMsLimits[i]); ++i) {}
+ increment_saturate(histAny->unansweredQueryDurationBins[i], UINT16_MAX);
+ if (hist) increment_saturate(hist->unansweredQueryDurationBins[i], UINT16_MAX);
+ }
+ err = mStatus_NoError;
+
+exit:
+ return (err);
+}
+
+//===========================================================================================================================
+// ResolveStatsDomainCreate
+//===========================================================================================================================
+
+mDNSlocal mStatus ResolveStatsDomainCreate(const Domain *inDomain, ResolveStatsDomain **outDomain)
+{
+ mStatus err;
+ ResolveStatsDomain * obj;
+
+ obj = (ResolveStatsDomain *)calloc(1, sizeof(*obj));
+ require_action_quiet(obj, exit, err = mStatus_NoMemoryErr);
+
+ obj->domainInfo = inDomain;
+
+ *outDomain = obj;
+ err = mStatus_NoError;
+
+exit:
+ return (err);
+}
+
+//===========================================================================================================================
+// ResolveStatsDomainFree
+//===========================================================================================================================
+
+mDNSlocal void ResolveStatsDomainFree(ResolveStatsDomain *inDomain)
+{
+ ResolveStatsHostname * hostname;
+
+ while ((hostname = inDomain->hostnameList) != NULL)
+ {
+ inDomain->hostnameList = hostname->next;
+ ResolveStatsHostnameFree(hostname);
+ }
+ free(inDomain);
+}
+
+//===========================================================================================================================
+// ResolveStatsDomainUpdate
+//===========================================================================================================================
+
+mDNSlocal mStatus ResolveStatsDomainUpdate(ResolveStatsDomain *inDomain, const domainname *inHostname, const Response *inResp, const mDNSAddr *inDNSAddr, mDNSBool inForCell)
+{
+ mStatus err;
+ ResolveStatsHostname ** p;
+ ResolveStatsHostname * hostname;
+ uint8_t serverID;
+
+ for (p = &inDomain->hostnameList; (hostname = *p) != NULL; p = &hostname->next)
+ {
+ if (SameDomainName((domainname *)hostname->name, inHostname)) break;
+ }
+
+ if (!hostname)
+ {
+ require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused);
+ err = ResolveStatsHostnameCreate(inHostname, &hostname);
+ require_noerr_quiet(err, exit);
+ gResolveStatsObjCount++;
+ *p = hostname;
+ }
+
+ err = ResolveStatsGetServerID(inDNSAddr, inForCell, &serverID);
+ require_noerr_quiet(err, exit);
+
+ err = ResolveStatsHostnameUpdate(hostname, inResp, serverID);
+ require_noerr_quiet(err, exit);
+
+exit:
+ return (err);
+}
+
+//===========================================================================================================================
+// ResolveStatsHostnameCreate
+//===========================================================================================================================
+
+mDNSlocal mStatus ResolveStatsHostnameCreate(const domainname *inName, ResolveStatsHostname **outHostname)
+{
+ mStatus err;
+ ResolveStatsHostname * obj;
+ size_t nameLen;
+
+ nameLen = DomainNameLength(inName);
+ require_action_quiet(nameLen > 0, exit, err = mStatus_Invalid);
+
+ obj = (ResolveStatsHostname *)calloc(1, sizeof(*obj) - 1 + nameLen);
+ require_action_quiet(obj, exit, err = mStatus_NoMemoryErr);
+
+ memcpy(obj->name, inName, nameLen);
+
+ *outHostname = obj;
+ err = mStatus_NoError;
+
+exit:
+ return (err);
+}
+
+//===========================================================================================================================
+// ResolveStatsDomainCreateAWDVersion
+//===========================================================================================================================
+
+mDNSlocal mStatus ResolveStatsDomainCreateAWDVersion(const ResolveStatsDomain *inDomain, AWDMDNSResponderResolveStatsDomain **outDomain)
+{
+ mStatus err;
+ AWDMDNSResponderResolveStatsDomain * domain;
+ ResolveStatsHostname * hostname;
+ AWDMDNSResponderResolveStatsHostname * awdHostname;
+ NSString * name;
+
+ domain = [[AWDMDNSResponderResolveStatsDomainSoft alloc] init];
+ require_action_quiet(domain, exit, err = mStatus_UnknownErr);
+
+ name = [[NSString alloc] initWithUTF8String:inDomain->domainInfo->cstr];
+ require_action_quiet(name, exit, err = mStatus_UnknownErr);
+
+ domain.name = name;
+ [name release];
+ name = nil;
+
+ for (hostname = inDomain->hostnameList; hostname; hostname = hostname->next)
+ {
+ err = ResolveStatsHostnameCreateAWDVersion(hostname, &awdHostname);
+ require_noerr_quiet(err, exit);
+
+ [domain addHostname:awdHostname];
+ [awdHostname release];
+ awdHostname = nil;
+ }
+
+ *outDomain = domain;
+ domain = nil;
+ err = mStatus_NoError;
+
+exit:
+ [domain release];
+ return (err);
+}
+
+//===========================================================================================================================
+// ResolveStatsHostnameFree
+//===========================================================================================================================
+
+mDNSlocal void ResolveStatsHostnameFree(ResolveStatsHostname *inHostname)
+{
+ ResolveStatsIPv4AddrSet * addrV4;
+ ResolveStatsIPv6Addr * addrV6;
+ ResolveStatsNegAAAASet * negV6;
+
+ while ((addrV4 = inHostname->addrV4List) != NULL)
+ {
+ inHostname->addrV4List = addrV4->next;
+ ResolveStatsIPv4AddrSetFree(addrV4);
+ }
+ while ((addrV6 = inHostname->addrV6List) != NULL)
+ {
+ inHostname->addrV6List = addrV6->next;
+ ResolveStatsIPv6AddressFree(addrV6);
+ }
+ while ((negV6 = inHostname->negV6List) != NULL)
+ {
+ inHostname->negV6List = negV6->next;
+ ResolveStatsNegAAAASetFree(negV6);
+ }
+ free(inHostname);
+}
+
+//===========================================================================================================================
+// ResolveStatsHostnameUpdate
+//===========================================================================================================================
+
+mDNSlocal mStatus ResolveStatsHostnameUpdate(ResolveStatsHostname *inHostname, const Response *inResp, uint8_t inServerID)
+{
+ mStatus err;
+
+ if ((inResp->type == kResponseType_IPv4Addr) || (inResp->type == kResponseType_NegA))
+ {
+ ResolveStatsIPv4AddrSet ** p;
+ ResolveStatsIPv4AddrSet * addrV4;
+ int i;
+ IPv4AddrCounter * counter;
+
+ for (p = &inHostname->addrV4List; (addrV4 = *p) != NULL; p = &addrV4->next)
+ {
+ for (i = 0; i < (int)countof(addrV4->counters); ++i)
+ {
+ counter = &addrV4->counters[i];
+ if (counter->count == 0) break;
+ if (counter->serverID != inServerID) continue;
+ if (inResp->type == kResponseType_NegA)
+ {
+ if (counter->isNegative) break;
+ }
+ else
+ {
+ if (memcmp(counter->addrBytes, inResp->data, 4) == 0) break;
+ }
+ }
+ if (i < (int)countof(addrV4->counters)) break;
+ }
+ if (!addrV4)
+ {
+ require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused);
+ err = ResolveStatsIPv4AddrSetCreate(&addrV4);
+ require_noerr_quiet(err, exit);
+ gResolveStatsObjCount++;
+
+ *p = addrV4;
+ counter = &addrV4->counters[0];
+ }
+ if (counter->count == 0)
+ {
+ counter->serverID = inServerID;
+ if (inResp->type == kResponseType_NegA)
+ {
+ counter->isNegative = 1;
+ }
+ else
+ {
+ counter->isNegative = 0;
+ memcpy(counter->addrBytes, inResp->data, 4);
+ }
+ }
+ increment_saturate(counter->count, UINT16_MAX);
+ err = mStatus_NoError;
+ }
+ else if (inResp->type == kResponseType_IPv6Addr)
+ {
+ ResolveStatsIPv6Addr ** p;
+ ResolveStatsIPv6Addr * addrV6;
+
+ for (p = &inHostname->addrV6List; (addrV6 = *p) != NULL; p = &addrV6->next)
+ {
+ if ((addrV6->serverID == inServerID) && (memcmp(addrV6->addrBytes, inResp->data, 16) == 0)) break;
+ }
+ if (!addrV6)
+ {
+ require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused);
+ err = ResolveStatsIPv6AddressCreate(inServerID, inResp->data, &addrV6);
+ require_noerr_quiet(err, exit);
+ gResolveStatsObjCount++;
+
+ *p = addrV6;
+ }
+ increment_saturate(addrV6->count, UINT16_MAX);
+ err = mStatus_NoError;
+ }
+ else if (inResp->type == kResponseType_NegAAAA)
+ {
+ ResolveStatsNegAAAASet ** p;
+ ResolveStatsNegAAAASet * negV6;
+ int i;
+ NegAAAACounter * counter;
+
+ for (p = &inHostname->negV6List; (negV6 = *p) != NULL; p = &negV6->next)
+ {
+ for (i = 0; i < (int)countof(negV6->counters); ++i)
+ {
+ counter = &negV6->counters[i];
+ if ((counter->count == 0) || (counter->serverID == inServerID)) break;
+ }
+ if (i < (int)countof(negV6->counters)) break;
+ }
+ if (!negV6)
+ {
+ require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused);
+ err = ResolveStatsNegAAAASetCreate(&negV6);
+ require_noerr_quiet(err, exit);
+ gResolveStatsObjCount++;
+
+ *p = negV6;
+ counter = &negV6->counters[0];
+ }
+ if (counter->count == 0) counter->serverID = inServerID;
+ increment_saturate(counter->count, UINT16_MAX);
+ err = mStatus_NoError;
+ }
+ else
+ {
+ err = mStatus_Invalid;
+ }
+
+exit:
+ return (err);
+}
+
+//===========================================================================================================================
+// ResolveStatsHostnameCreateAWDVersion
+//===========================================================================================================================
+
+mDNSlocal mStatus ResolveStatsHostnameCreateAWDVersion(const ResolveStatsHostname *inHostname, AWDMDNSResponderResolveStatsHostname **outHostname)
+{
+ mStatus err;
+ AWDMDNSResponderResolveStatsHostname * hostname;
+ NSString * name;
+ char nameBuf[MAX_ESCAPED_DOMAIN_NAME];
+ const char * ptr;
+ ResolveStatsIPv4AddrSet * addrV4;
+ ResolveStatsIPv6Addr * addrV6;
+ ResolveStatsNegAAAASet * negV6;
+ AWDMDNSResponderResolveStatsResult * result = nil;
+ int i;
+
+ hostname = [[AWDMDNSResponderResolveStatsHostnameSoft alloc] init];
+ require_action_quiet(hostname, exit, err = mStatus_UnknownErr);
+
+ ptr = ConvertDomainNameToCString((domainname *)inHostname->name, nameBuf);
+ require_action_quiet(ptr, exit, err = mStatus_UnknownErr);
+
+ name = [[NSString alloc] initWithUTF8String:nameBuf];
+ require_action_quiet(name, exit, err = mStatus_UnknownErr);
+
+ hostname.name = name;
+ [name release];
+ name = nil;
+
+ for (addrV4 = inHostname->addrV4List; addrV4; addrV4 = addrV4->next)
+ {
+ for (i = 0; i < (int)countof(addrV4->counters); ++i)
+ {
+ const IPv4AddrCounter * counter;
+ NSData * addrBytes;
+
+ counter = &addrV4->counters[i];
+ if (counter->count == 0) break;
+
+ result = [[AWDMDNSResponderResolveStatsResultSoft alloc] init];
+ require_action_quiet(result, exit, err = mStatus_UnknownErr);
+
+ if (counter->isNegative)
+ {
+ result.type = AWDMDNSResponderResolveStatsResult_ResultType_NegA;
+ }
+ else
+ {
+ addrBytes = [[NSData alloc] initWithBytes:counter->addrBytes length:4];
+ require_action_quiet(addrBytes, exit, err = mStatus_UnknownErr);
+
+ result.type = AWDMDNSResponderResolveStatsResult_ResultType_IPv4Addr;
+ result.data = addrBytes;
+ [addrBytes release];
+ }
+ result.count = counter->count;
+ result.serverID = counter->serverID;
+
+ [hostname addResult:result];
+ [result release];
+ result = nil;
+ }
+ }
+
+ for (addrV6 = inHostname->addrV6List; addrV6; addrV6 = addrV6->next)
+ {
+ NSData * addrBytes;
+
+ result = [[AWDMDNSResponderResolveStatsResultSoft alloc] init];
+ require_action_quiet(result, exit, err = mStatus_UnknownErr);
+
+ addrBytes = [[NSData alloc] initWithBytes:addrV6->addrBytes length:16];
+ require_action_quiet(addrBytes, exit, err = mStatus_UnknownErr);
+
+ result.type = AWDMDNSResponderResolveStatsResult_ResultType_IPv6Addr;
+ result.count = addrV6->count;
+ result.serverID = addrV6->serverID;
+ result.data = addrBytes;
+
+ [addrBytes release];
+
+ [hostname addResult:result];
+ [result release];
+ result = nil;
+ }
+
+ for (negV6 = inHostname->negV6List; negV6; negV6 = negV6->next)
+ {
+ for (i = 0; i < (int)countof(negV6->counters); ++i)
+ {
+ const NegAAAACounter * counter;
+
+ counter = &negV6->counters[i];
+ if (counter->count == 0) break;
+
+ result = [[AWDMDNSResponderResolveStatsResultSoft alloc] init];
+ require_action_quiet(result, exit, err = mStatus_UnknownErr);
+
+ result.type = AWDMDNSResponderResolveStatsResult_ResultType_NegAAAA;
+ result.count = counter->count;
+ result.serverID = counter->serverID;
+
+ [hostname addResult:result];
+ [result release];
+ result = nil;
+ }
+ }
+
+ *outHostname = hostname;
+ hostname = nil;
+ err = mStatus_NoError;
+
+exit:
+ [result release];
+ [hostname release];
+ return (err);
+}
+
+//===========================================================================================================================
+// ResolveStatsDNSServerCreate
+//===========================================================================================================================
+
+mDNSlocal mStatus ResolveStatsDNSServerCreate(const mDNSAddr *inAddr, mDNSBool inForCell, ResolveStatsDNSServer **outServer)
+{
+ mStatus err;
+ ResolveStatsDNSServer * obj;
+ size_t addrLen;
+
+ require_action_quiet((inAddr->type == mDNSAddrType_IPv4) || (inAddr->type == mDNSAddrType_IPv6), exit, err = mStatus_Invalid);
+
+ addrLen = (inAddr->type == mDNSAddrType_IPv4) ? 4 : 16;
+ obj = (ResolveStatsDNSServer *)calloc(1, sizeof(*obj) - 1 + addrLen);
+ require_action_quiet(obj, exit, err = mStatus_NoMemoryErr);
+
+ obj->isForCell = inForCell;
+ if (inAddr->type == mDNSAddrType_IPv4)
+ {
+ obj->isAddrV6 = mDNSfalse;
+ memcpy(obj->addrBytes, inAddr->ip.v4.b, addrLen);
+ }
+ else
+ {
+ obj->isAddrV6 = mDNStrue;
+ memcpy(obj->addrBytes, inAddr->ip.v6.b, addrLen);
+ }
+
+ *outServer = obj;
+ err = mStatus_NoError;
+
+exit:
+ return (err);
+}
+
+//===========================================================================================================================
+// ResolveStatsDNSServerFree
+//===========================================================================================================================
+
+mDNSlocal void ResolveStatsDNSServerFree(ResolveStatsDNSServer *inServer)
+{
+ free(inServer);
+}
+
+//===========================================================================================================================
+// ResolveStatsDNSServerCreateAWDVersion
+//===========================================================================================================================
+
+mDNSlocal mStatus ResolveStatsDNSServerCreateAWDVersion(const ResolveStatsDNSServer *inServer, AWDMDNSResponderResolveStatsDNSServer **outServer)
+{
+ mStatus err;
+ AWDMDNSResponderResolveStatsDNSServer * server;
+ NSData * addrBytes = nil;
+
+ server = [[AWDMDNSResponderResolveStatsDNSServerSoft alloc] init];
+ require_action_quiet(server, exit, err = mStatus_UnknownErr);
+
+ addrBytes = [[NSData alloc] initWithBytes:inServer->addrBytes length:(inServer->isAddrV6 ? 16 : 4)];
+ require_action_quiet(addrBytes, exit, err = mStatus_UnknownErr);
+
+ server.serverID = inServer->id;
+ server.address = addrBytes;
+ if (inServer->isForCell)
+ {
+ server.networkType = AWDMDNSResponderResolveStatsDNSServer_NetworkType_Cellular;
+ }
+ else
+ {
+ server.networkType = AWDMDNSResponderResolveStatsDNSServer_NetworkType_NonCellular;
+ }
+
+ *outServer = server;
+ server = nil;
+ err = mStatus_NoError;
+
+exit:
+ [addrBytes release];
+ [server release];
+ return (err);
+}
+
+//===========================================================================================================================
+// ResolveStatsIPv4AddrSetCreate
+//===========================================================================================================================
+
+mDNSlocal mStatus ResolveStatsIPv4AddrSetCreate(ResolveStatsIPv4AddrSet **outSet)
+{
+ mStatus err;
+ ResolveStatsIPv4AddrSet * obj;
+
+ obj = (ResolveStatsIPv4AddrSet *)calloc(1, sizeof(*obj));
+ require_action_quiet(obj, exit, err = mStatus_NoMemoryErr);
+
+ *outSet = obj;
+ err = mStatus_NoError;
+
+exit:
+ return (err);
+}
+
+//===========================================================================================================================
+// ResolveStatsIPv4AddrSetFree
+//===========================================================================================================================
+
+mDNSlocal void ResolveStatsIPv4AddrSetFree(ResolveStatsIPv4AddrSet *inSet)
+{
+ free(inSet);
+}
+
+//===========================================================================================================================
+// ResolveStatsIPv6AddressCreate
+//===========================================================================================================================
+
+mDNSlocal mStatus ResolveStatsIPv6AddressCreate(uint8_t inServerID, const uint8_t inAddrBytes[16], ResolveStatsIPv6Addr **outAddr)
+{
+ mStatus err;
+ ResolveStatsIPv6Addr * obj;
+
+ obj = (ResolveStatsIPv6Addr *)calloc(1, sizeof(*obj));
+ require_action_quiet(obj, exit, err = mStatus_NoMemoryErr);
+
+ obj->serverID = inServerID;
+ memcpy(obj->addrBytes, inAddrBytes, 16);
+
+ *outAddr = obj;
+ err = mStatus_NoError;
+
+exit:
+ return (err);
+}
+
+//===========================================================================================================================
+// ResolveStatsIPv6AddressFree
+//===========================================================================================================================
+
+mDNSlocal void ResolveStatsIPv6AddressFree(ResolveStatsIPv6Addr *inAddr)
+{
+ free(inAddr);
+}
+
+//===========================================================================================================================
+// ResolveStatsNegAAAASetCreate
+//===========================================================================================================================
+
+mDNSlocal mStatus ResolveStatsNegAAAASetCreate(ResolveStatsNegAAAASet **outSet)
+{
+ mStatus err;
+ ResolveStatsNegAAAASet * obj;
+
+ obj = (ResolveStatsNegAAAASet *)calloc(1, sizeof(*obj));
+ require_action_quiet(obj, exit, err = mStatus_NoMemoryErr);
+
+ *outSet = obj;
+ err = mStatus_NoError;
+
+exit:
+ return (err);
+}
+
+//===========================================================================================================================
+// ResolveStatsNegAAAASetFree
+//===========================================================================================================================
+
+mDNSlocal void ResolveStatsNegAAAASetFree(ResolveStatsNegAAAASet *inSet)
+{
+ free(inSet);
+}
+
+//===========================================================================================================================
+// ResolveStatsGetServerID
+//===========================================================================================================================
+
+mDNSlocal mStatus ResolveStatsGetServerID(const mDNSAddr *inServerAddr, mDNSBool inForCell, uint8_t *outServerID)
+{
+ mStatus err;
+ ResolveStatsDNSServer ** p;
+ ResolveStatsDNSServer * server;
+
+ require_action_quiet((inServerAddr->type == mDNSAddrType_IPv4) || (inServerAddr->type == mDNSAddrType_IPv6), exit, err = mStatus_Invalid);
+
+ for (p = &gResolveStatsServerList; (server = *p) != NULL; p = &server->next)
+ {
+ if ((inForCell && server->isForCell) || (!inForCell && !server->isForCell))
+ {
+ if (inServerAddr->type == mDNSAddrType_IPv4)
+ {
+ if (!server->isAddrV6 && (memcmp(server->addrBytes, inServerAddr->ip.v4.b, 4) == 0)) break;
+ }
+ else
+ {
+ if (server->isAddrV6 && (memcmp(server->addrBytes, inServerAddr->ip.v6.b, 16) == 0)) break;
+ }
+ }
+ }
+
+ if (!server)
+ {
+ require_action_quiet(gResolveStatsNextServerID <= UINT8_MAX, exit, err = mStatus_Refused);
+ require_action_quiet(gResolveStatsObjCount < kResolveStatsMaxObjCount, exit, err = mStatus_Refused);
+ err = ResolveStatsDNSServerCreate(inServerAddr, inForCell, &server);
+ require_noerr_quiet(err, exit);
+ gResolveStatsObjCount++;
+
+ server->id = gResolveStatsNextServerID++;
+ server->next = gResolveStatsServerList;
+ gResolveStatsServerList = server;
+ }
+ else if (gResolveStatsServerList != server)
+ {
+ *p = server->next;
+ server->next = gResolveStatsServerList;
+ gResolveStatsServerList = server;
+ }
+
+ *outServerID = server->id;
+ err = mStatus_NoError;
+
+exit:
+ return (err);
}
//===========================================================================================================================
// CreateDomainStatsList
//===========================================================================================================================
-mDNSlocal mStatus CreateDomainStatsList(DNSDomainStatsRef *outList)
+mDNSlocal mStatus CreateDomainStatsList(DNSDomainStats **outList)
{
mStatus err;
- size_t i;
- DNSDomainStatsRef domainStats;
- DNSDomainStatsRef * p;
- DNSDomainStatsRef list = NULL;
+ int i;
+ DNSDomainStats * stats;
+ DNSDomainStats ** p;
+ DNSDomainStats * list = NULL;
p = &list;
- for (i = 0; i < countof(kUDNSStatsDomains); ++i)
+ for (i = 0; i < (int)countof(kQueryStatsDomains); ++i)
{
- err = DNSDomainStatsCreate(kUDNSStatsDomains[i], &domainStats);
+ err = DNSDomainStatsCreate(&kQueryStatsDomains[i], &stats);
require_noerr_quiet(err, exit);
- *p = domainStats;
- p = &domainStats->next;
+ *p = stats;
+ p = &stats->next;
}
*outList = list;
@@ -238,28 +1440,62 @@ exit:
}
//===========================================================================================================================
-// UpdateDNSStats
+// CreateResolveStatsList
//===========================================================================================================================
-mDNSlocal void UpdateDNSStats(DNSStats *inStats, mDNSBool inAnswered, mDNSu32 inQuerySendCount, mDNSu32 inLatencyMs)
+mDNSlocal mStatus CreateResolveStatsList(ResolveStatsDomain **outList)
{
- size_t i;
+ mStatus err;
+ int i;
+ ResolveStatsDomain * domain;
+ ResolveStatsDomain ** p;
+ ResolveStatsDomain * list = NULL;
- if (inAnswered)
+ p = &list;
+ for (i = 0; i < (int)countof(kResolveStatsDomains); ++i)
{
- i = (inQuerySendCount <= kUDNSStatsMaxQuerySendCount) ? inQuerySendCount : kUDNSStatsMaxQuerySendCount;
- inStats->answeredQuerySendCountBins[i]++;
+ err = ResolveStatsDomainCreate(&kResolveStatsDomains[i], &domain);
+ require_noerr_quiet(err, exit);
- if (inQuerySendCount > 0)
- {
- for (i = 0; (i < countof(kResponseLatencyMsLimits)) && (inLatencyMs >= kResponseLatencyMsLimits[i]); ++i) {}
- inStats->responseLatencyBins[i]++;
- }
+ *p = domain;
+ p = &domain->next;
}
- else if (inQuerySendCount > 0)
+
+ *outList = list;
+ list = NULL;
+
+exit:
+ FreeResolveStatsList(list);
+ return (err);
+}
+
+//===========================================================================================================================
+// FreeResolveStatsList
+//===========================================================================================================================
+
+mDNSlocal void FreeResolveStatsList(ResolveStatsDomain *inList)
+{
+ ResolveStatsDomain * domain;
+
+ while ((domain = inList) != NULL)
{
- i = (inQuerySendCount <= kUDNSStatsMaxQuerySendCount) ? inQuerySendCount : kUDNSStatsMaxQuerySendCount;
- inStats->unansweredQuerySendCountBins[i]++;
+ inList = domain->next;
+ ResolveStatsDomainFree(domain);
+ }
+}
+
+//===========================================================================================================================
+// FreeResolveStatsServerList
+//===========================================================================================================================
+
+mDNSlocal void FreeResolveStatsServerList(ResolveStatsDNSServer *inList)
+{
+ ResolveStatsDNSServer * server;
+
+ while ((server = inList) != NULL)
+ {
+ inList = server->next;
+ ResolveStatsDNSServerFree(server);
}
}
@@ -267,16 +1503,51 @@ mDNSlocal void UpdateDNSStats(DNSStats *inStats, mDNSBool inAnswered, mDNSu32 in
// SubmitAWDMetric
//===========================================================================================================================
-mDNSlocal mStatus SubmitAWDMetric(void)
+mDNSlocal mStatus SubmitAWDMetric(UInt32 inMetricID)
+{
+ mStatus err = mStatus_NoError;
+
+ switch (inMetricID)
+ {
+ case AWDMetricId_MDNSResponder_DNSStatistics:
+ err = SubmitAWDMetricQueryStats();
+ break;
+
+ case AWDMetricId_MDNSResponder_ResolveStats:
+ err = SubmitAWDMetricResolveStats();
+ break;
+
+ case AWDMetricId_MDNSResponder_ServicesStats:
+ [AWDMetricManagerSoft postMetricWithId:AWDMetricId_MDNSResponder_ServicesStats integerValue:max_num_regservices];
+ KQueueLock(&mDNSStorage);
+ // reset the no of max services since we want to collect the max no of services registered per AWD submission period
+ max_num_regservices = curr_num_regservices;
+ KQueueUnlock(&mDNSStorage, "SubmitAWDSimpleMetricServiceStats");
+ break;
+
+ default:
+ err = mStatus_UnsupportedErr;
+ break;
+ }
+
+ if (err)
+ LogMsg("SubmitAWDMetric for metric ID 0x%08X failed with error %d", inMetricID, err);
+ return (err);
+}
+
+//===========================================================================================================================
+// SubmitAWDMetricQueryStats
+//===========================================================================================================================
+
+mDNSlocal mStatus SubmitAWDMetricQueryStats(void)
{
mStatus err;
BOOL success;
- DNSDomainStatsRef domainStats;
- DNSDomainStatsRef newDomainStatsList;
- DNSDomainStatsRef domainStatsList = NULL;
+ DNSDomainStats * stats;
+ DNSDomainStats * newDomainStatsList;
+ DNSDomainStats * domainStatsList = NULL;
AWDMetricContainer * container = nil;
AWDMDNSResponderDNSStatistics * metric = nil;
- AWDDNSDomainStats * awdDomainStats = nil;
err = CreateDomainStatsList(&newDomainStatsList);
require_noerr_quiet(err, exit);
@@ -285,7 +1556,7 @@ mDNSlocal mStatus SubmitAWDMetric(void)
KQueueLock(&mDNSStorage);
gDomainStatsList = newDomainStatsList;
- KQueueUnlock(&mDNSStorage, "SubmitAWDMetric");
+ KQueueUnlock(&mDNSStorage, "SubmitAWDMetricQueryStats");
container = [gAWDServerConnection newMetricContainerWithIdentifier:AWDMetricId_MDNSResponder_DNSStatistics];
require_action_quiet(container, exit, err = mStatus_UnknownErr);
@@ -293,30 +1564,28 @@ mDNSlocal mStatus SubmitAWDMetric(void)
metric = [[AWDMDNSResponderDNSStatisticsSoft alloc] init];
require_action_quiet(metric, exit, err = mStatus_UnknownErr);
- for (domainStats = domainStatsList; domainStats; domainStats = domainStats->next)
+ while ((stats = domainStatsList) != NULL)
{
- err = CreateAWDDNSDomainStats(&domainStats->stats, domainStats->domainStr, mDNSfalse, &awdDomainStats);
- require_noerr_quiet(err, exit);
-
- [metric addStats:awdDomainStats];
- [awdDomainStats release];
- awdDomainStats = nil;
-
- err = CreateAWDDNSDomainStats(&domainStats->statsCellular, domainStats->domainStr, mDNStrue, &awdDomainStats);
- require_noerr_quiet(err, exit);
-
- [metric addStats:awdDomainStats];
- [awdDomainStats release];
- awdDomainStats = nil;
+ if (stats->nonCellular)
+ {
+ err = AddAWDDNSDomainStats(metric, stats->nonCellular, stats->domain->cstr, mDNSfalse);
+ require_noerr_quiet(err, exit);
+ }
+ if (stats->cellular)
+ {
+ err = AddAWDDNSDomainStats(metric, stats->cellular, stats->domain->cstr, mDNStrue);
+ require_noerr_quiet(err, exit);
+ }
+ domainStatsList = stats->next;
+ DNSDomainStatsFree(stats);
}
container.metric = metric;
success = [gAWDServerConnection submitMetric:container];
- LogMsg("SubmitAWDMetric: metric submission %s.", success ? "succeeded" : "failed" );
+ LogMsg("SubmitAWDMetricQueryStats: metric submission %s.", success ? "succeeded" : "failed" );
err = success ? mStatus_NoError : mStatus_UnknownErr;
exit:
- [awdDomainStats release];
[metric release];
[container release];
DNSDomainStatsFreeList(domainStatsList);
@@ -324,73 +1593,94 @@ exit:
}
//===========================================================================================================================
-// DNSDomainStatsCreate
+// SubmitAWDMetricResolveStats
//===========================================================================================================================
-mDNSlocal mStatus DNSDomainStatsCreate(const char *inDomain, DNSDomainStatsRef *outStats)
+mDNSlocal mStatus SubmitAWDMetricResolveStats(void)
{
- mStatus err;
- DNSDomainStatsRef obj;
- mDNSu8 * ptr;
+ mStatus err;
+ ResolveStatsDomain * newResolveStatsList;
+ ResolveStatsDomain * domainList = NULL;
+ ResolveStatsDNSServer * serverList = NULL;
+ AWDMetricContainer * container = nil;
+ AWDMDNSResponderResolveStats * metric = nil;
+ ResolveStatsDNSServer * server;
+ ResolveStatsDomain * domain;
+ BOOL success;
- obj = (DNSDomainStatsRef) calloc(1, sizeof(*obj));
- require_action_quiet(obj, exit, err = mStatus_NoMemoryErr);
+ err = CreateResolveStatsList(&newResolveStatsList);
+ require_noerr_quiet(err, exit);
- obj->domainStr = strdup(inDomain);
- require_action_quiet(obj, exit, err = mStatus_NoMemoryErr);
+ domainList = gResolveStatsList;
+ serverList = gResolveStatsServerList;
- // Initialize domainname for non-root domains.
+ KQueueLock(&mDNSStorage);
+ gResolveStatsList = newResolveStatsList;
+ gResolveStatsServerList = NULL;
+ gResolveStatsNextServerID = 0;
+ gResolveStatsObjCount = 0;
+ KQueueUnlock(&mDNSStorage, "SubmitAWDMetricResolveStats");
- if (strcmp(obj->domainStr, ".") != 0)
- {
- ptr = MakeDomainNameFromDNSNameString(&obj->domain, obj->domainStr);
- require_action_quiet(ptr, exit, err = mStatus_Invalid);
- obj->domainLabelCount = CountLabels(&obj->domain);
- }
+ container = [gAWDServerConnection newMetricContainerWithIdentifier:AWDMetricId_MDNSResponder_ResolveStats];
+ require_action_quiet(container, exit, err = mStatus_UnknownErr);
- *outStats = obj;
- obj = NULL;
- err = mStatus_NoError;
+ metric = [[AWDMDNSResponderResolveStatsSoft alloc] init];
+ require_action_quiet(metric, exit, err = mStatus_UnknownErr);
-exit:
- if (obj) DNSDomainStatsFree(obj);
- return (err);
-}
+ while ((server = serverList) != NULL)
+ {
+ AWDMDNSResponderResolveStatsDNSServer * awdServer;
-//===========================================================================================================================
-// DNSDomainStatsFree
-//===========================================================================================================================
+ serverList = server->next;
+ err = ResolveStatsDNSServerCreateAWDVersion(server, &awdServer);
+ ResolveStatsDNSServerFree(server);
+ require_noerr_quiet(err, exit);
-mDNSlocal void DNSDomainStatsFree(DNSDomainStatsRef inStats)
-{
- if (inStats->domainStr) free(inStats->domainStr);
- free(inStats);
-}
+ [metric addServer:awdServer];
+ [awdServer release];
+ }
-//===========================================================================================================================
-// DNSDomainStatsFreeList
-//===========================================================================================================================
+ while ((domain = domainList) != NULL)
+ {
+ AWDMDNSResponderResolveStatsDomain * awdDomain;
-mDNSlocal void DNSDomainStatsFreeList(DNSDomainStatsRef inList)
-{
- DNSDomainStatsRef stats;
+ domainList = domain->next;
+ err = ResolveStatsDomainCreateAWDVersion(domain, &awdDomain);
+ ResolveStatsDomainFree(domain);
+ require_noerr_quiet(err, exit);
- while ((stats = inList) != NULL)
- {
- inList = stats->next;
- DNSDomainStatsFree(stats);
+ [metric addDomain:awdDomain];
+ [awdDomain release];
}
+
+ container.metric = metric;
+ success = [gAWDServerConnection submitMetric:container];
+ LogMsg("SubmitAWDMetricResolveStats: metric submission %s.", success ? "succeeded" : "failed" );
+ err = success ? mStatus_NoError : mStatus_UnknownErr;
+
+exit:
+ [metric release];
+ [container release];
+ FreeResolveStatsList(domainList);
+ FreeResolveStatsServerList(serverList);
+ return (err);
}
//===========================================================================================================================
// CreateAWDDNSDomainStats
//===========================================================================================================================
-mDNSlocal mStatus CreateAWDDNSDomainStats(DNSStats *inStats, const char *inDomain, mDNSBool inIsCellType, AWDDNSDomainStats **outAWDStats)
+mDNSlocal mStatus CreateAWDDNSDomainStats(DNSHist *inHist, const char *inDomain, mDNSBool inForCell, AWDDNSDomainStats_RecordType inType, AWDDNSDomainStats **outStats)
{
mStatus err;
AWDDNSDomainStats * awdStats = nil;
NSString * domain = nil;
+ uint32_t sendCountBins[kQueryStatsSendCountBinCount];
+ uint32_t latencyBins[kQueryStatsLatencyBinCount];
+ int i;
+ unsigned int totalAnswered;
+ unsigned int totalNegAnswered;
+ unsigned int totalUnanswered;
awdStats = [[AWDDNSDomainStatsSoft alloc] init];
require_action_quiet(awdStats, exit, err = mStatus_UnknownErr);
@@ -398,22 +1688,62 @@ mDNSlocal mStatus CreateAWDDNSDomainStats(DNSStats *inStats, const char *inDomai
domain = [[NSString alloc] initWithUTF8String:inDomain];
require_action_quiet(domain, exit, err = mStatus_UnknownErr);
- awdStats.domain = domain;
- awdStats.networkType = inIsCellType ? AWDDNSDomainStats_NetworkType_Cellular : AWDDNSDomainStats_NetworkType_NonCellular;
+ awdStats.domain = domain;
+ awdStats.networkType = inForCell ? AWDDNSDomainStats_NetworkType_Cellular : AWDDNSDomainStats_NetworkType_NonCellular;
+ awdStats.recordType = inType;
+
+ totalAnswered = 0;
+ for (i = 0; i < kQueryStatsSendCountBinCount; ++i)
+ {
+ sendCountBins[i] = inHist->answeredQuerySendCountBins[i];
+ totalAnswered += inHist->answeredQuerySendCountBins[i];
+ }
+ [awdStats setAnsweredQuerySendCounts:sendCountBins count:kQueryStatsSendCountBinCount];
- [awdStats
- setAnsweredQuerySendCounts: inStats->answeredQuerySendCountBins
- count: (NSUInteger)countof(inStats->answeredQuerySendCountBins)];
+ totalNegAnswered = 0;
+ for (i = 0; i < kQueryStatsSendCountBinCount; ++i)
+ {
+ sendCountBins[i] = inHist->negAnsweredQuerySendCountBins[i];
+ totalNegAnswered += inHist->negAnsweredQuerySendCountBins[i];
+ }
+ [awdStats setNegAnsweredQuerySendCounts:sendCountBins count:kQueryStatsSendCountBinCount];
- [awdStats
- setUnansweredQuerySendCounts: inStats->unansweredQuerySendCountBins
- count: (NSUInteger)countof(inStats->unansweredQuerySendCountBins)];
+ totalUnanswered = 0;
+ for (i = 0; i < kQueryStatsSendCountBinCount; ++i)
+ {
+ sendCountBins[i] = inHist->unansweredQuerySendCountBins[i];
+ totalUnanswered += inHist->unansweredQuerySendCountBins[i];
+ }
+ [awdStats setUnansweredQuerySendCounts:sendCountBins count:kQueryStatsSendCountBinCount];
- [awdStats
- setResponseLatencyMs: inStats->responseLatencyBins
- count: (NSUInteger)countof(inStats->responseLatencyBins)];
+ if (totalAnswered > inHist->answeredQuerySendCountBins[0])
+ {
+ for (i = 0; i < kQueryStatsLatencyBinCount; ++i)
+ {
+ latencyBins[i] = inHist->responseLatencyBins[i];
+ }
+ [awdStats setResponseLatencyMs:latencyBins count:kQueryStatsLatencyBinCount];
+ }
+
+ if (totalNegAnswered > inHist->negAnsweredQuerySendCountBins[0])
+ {
+ for (i = 0; i < kQueryStatsLatencyBinCount; ++i)
+ {
+ latencyBins[i] = inHist->negResponseLatencyBins[i];
+ }
+ [awdStats setNegResponseLatencyMs:latencyBins count:kQueryStatsLatencyBinCount];
+ }
+
+ if (totalUnanswered > 0)
+ {
+ for (i = 0; i < kQueryStatsLatencyBinCount; ++i)
+ {
+ latencyBins[i] = inHist->unansweredQueryDurationBins[i];
+ }
+ [awdStats setUnansweredQueryDurationMs:latencyBins count:kQueryStatsLatencyBinCount];
+ }
- *outAWDStats = awdStats;
+ *outStats = awdStats;
awdStats = nil;
err = mStatus_NoError;
@@ -424,7 +1754,57 @@ exit:
}
//===========================================================================================================================
-// LogDNSStats
+// AddAWDDNSDomainStats
+//===========================================================================================================================
+
+mDNSlocal mStatus AddAWDDNSDomainStats(AWDMDNSResponderDNSStatistics *inMetric, DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell)
+{
+ mStatus err;
+ AWDDNSDomainStats * awdStats;
+
+ if (inSet->histAny)
+ {
+ err = CreateAWDDNSDomainStats(inSet->histAny, inDomain, inForCell, AWDDNSDomainStats_RecordType_Any, &awdStats);
+ require_noerr_quiet(err, exit);
+
+ [inMetric addStats:awdStats];
+ [awdStats release];
+ }
+ if (inSet->histA)
+ {
+ err = CreateAWDDNSDomainStats(inSet->histA, inDomain, inForCell, AWDDNSDomainStats_RecordType_A, &awdStats);
+ require_noerr_quiet(err, exit);
+
+ [inMetric addStats:awdStats];
+ [awdStats release];
+ }
+ if (inSet->histAAAA)
+ {
+ err = CreateAWDDNSDomainStats(inSet->histAAAA, inDomain, inForCell, AWDDNSDomainStats_RecordType_AAAA, &awdStats);
+ require_noerr_quiet(err, exit);
+
+ [inMetric addStats:awdStats];
+ [awdStats release];
+ }
+ err = mStatus_NoError;
+
+exit:
+ return (err);
+}
+
+//===========================================================================================================================
+// LogDNSHistSet
+//===========================================================================================================================
+
+mDNSlocal void LogDNSHistSet(const DNSHistSet *inSet, const char *inDomain, mDNSBool inForCell)
+{
+ if (inSet->histAny) LogDNSHist(inSet->histAny, inDomain, inForCell, "Any");
+ if (inSet->histA) LogDNSHist(inSet->histA, inDomain, inForCell, "A");
+ if (inSet->histAAAA) LogDNSHist(inSet->histAAAA, inDomain, inForCell, "AAAA");
+}
+
+//===========================================================================================================================
+// LogDNSHist
//===========================================================================================================================
#define Percent(N, D) ((N) * 100) / (D), (((N) * 10000) / (D)) % 100
@@ -432,67 +1812,124 @@ exit:
#define LogStat(LABEL, COUNT, ACCUMULATOR, TOTAL) \
LogMsgNoIdent("%s %5u " PercentFmt " " PercentFmt, (LABEL), (COUNT), Percent(COUNT, TOTAL), Percent(ACCUMULATOR, TOTAL))
-mDNSlocal void LogDNSStats(const DNSStats *inStats)
+mDNSlocal void LogDNSHist(const DNSHist *inHist, const char *inDomain, mDNSBool inForCell, const char *inType)
{
- uint32_t total;
- uint32_t totalUnanswered;
- size_t i;
- char label[16];
+ unsigned int totalAnswered;
+ unsigned int totalNegAnswered;
+ unsigned int totalUnanswered;
+ int i;
+
+ totalAnswered = 0;
+ for (i = 0; i < kQueryStatsSendCountBinCount; ++i)
+ {
+ totalAnswered += inHist->answeredQuerySendCountBins[i];
+ }
+
+ totalNegAnswered = 0;
+ for (i = 0; i < kQueryStatsSendCountBinCount; ++i)
+ {
+ totalNegAnswered += inHist->negAnsweredQuerySendCountBins[i];
+ }
totalUnanswered = 0;
- for (i = 0; i < countof(inStats->unansweredQuerySendCountBins); ++i)
+ for (i = 0; i < kQueryStatsSendCountBinCount; ++i)
+ {
+ totalUnanswered += inHist->unansweredQuerySendCountBins[i];
+ }
+
+ LogMsgNoIdent("Domain: %s (%s, %s)", inDomain, inForCell ? "C" : "NC", inType);
+ LogMsgNoIdent("Answered questions %4u", totalAnswered);
+ LogMsgNoIdent("Negatively answered questions %4u", totalNegAnswered);
+ LogMsgNoIdent("Unanswered questions %4u", totalUnanswered);
+ LogMsgNoIdent("-- Query send counts ---------");
+ LogDNSHistSendCounts(inHist->answeredQuerySendCountBins);
+ LogMsgNoIdent("-- Query send counts (NAQs) --");
+ LogDNSHistSendCounts(inHist->negAnsweredQuerySendCountBins);
+
+ if (totalAnswered > inHist->answeredQuerySendCountBins[0])
+ {
+ LogMsgNoIdent("--- Response times -----------");
+ LogDNSHistLatencies(inHist->responseLatencyBins);
+ }
+
+ if (totalNegAnswered > inHist->negAnsweredQuerySendCountBins[0])
{
- totalUnanswered += inStats->unansweredQuerySendCountBins[i];
+ LogMsgNoIdent("--- Response times (NAQs) ----");
+ LogDNSHistLatencies(inHist->negResponseLatencyBins);
}
+ if (totalUnanswered > 0)
+ {
+ LogMsgNoIdent("--- Unanswered query times ---");
+ LogDNSHistLatencies(inHist->unansweredQueryDurationBins);
+ }
+}
+
+//===========================================================================================================================
+// LogDNSHistSendCounts
+//===========================================================================================================================
+
+mDNSlocal void LogDNSHistSendCounts(const uint16_t inSendCountBins[kQueryStatsSendCountBinCount])
+{
+ uint32_t total;
+ char label[16];
+ int i;
+
total = 0;
- for (i = 0; i <= countof(inStats->answeredQuerySendCountBins); ++i)
+ for (i = 0; i < kQueryStatsSendCountBinCount; ++i)
{
- total += inStats->answeredQuerySendCountBins[i];
+ total += inSendCountBins[i];
}
- LogMsgNoIdent("Answered questions %5u", total);
- LogMsgNoIdent("Unanswered questions %5u", totalUnanswered);
- LogMsgNoIdent("+++ Number of queries sent +++");
if (total > 0)
{
uint32_t accumulator = 0;
- for (i = 0; i < countof(inStats->answeredQuerySendCountBins); ++i)
+ for (i = 0; i < kQueryStatsSendCountBinCount; ++i)
{
- uint32_t count;
- const char * suffix;
-
- count = inStats->answeredQuerySendCountBins[i];
- accumulator += count;
- suffix = (i < (countof(inStats->answeredQuerySendCountBins) - 1)) ? " " : "+";
- snprintf(label, sizeof(label), "%2d%s", (int)i, suffix);
- LogStat(label, count, accumulator, total);
+ accumulator += inSendCountBins[i];
+ if (i < (kQueryStatsSendCountBinCount - 1))
+ {
+ snprintf(label, sizeof(label), "%2d ", i);
+ }
+ else
+ {
+ snprintf(label, sizeof(label), "%2d+", i);
+ }
+ LogStat(label, inSendCountBins[i], accumulator, total);
+ if (accumulator == total) break;
}
}
else
{
LogMsgNoIdent("No data.");
}
+}
+
+//===========================================================================================================================
+// LogDNSHistLatencies
+//===========================================================================================================================
+
+mDNSlocal void LogDNSHistLatencies(const uint16_t inLatencyBins[kQueryStatsLatencyBinCount])
+{
+ uint32_t total;
+ int i;
+ char label[16];
total = 0;
- for (i = 0; i < countof(inStats->responseLatencyBins); ++i)
+ for (i = 0; i < kQueryStatsLatencyBinCount; ++i)
{
- total += inStats->responseLatencyBins[i];
+ total += inLatencyBins[i];
}
- LogMsgNoIdent("+++++++ Response times +++++++");
if (total > 0)
{
uint32_t accumulator = 0;
- for (i = 0; i < countof(inStats->responseLatencyBins); ++i)
+ for (i = 0; i < kQueryStatsLatencyBinCount; ++i)
{
- uint32_t count;
-
- count = inStats->responseLatencyBins[i];
- accumulator += count;
- if (i < countof(kResponseLatencyMsLimits))
+ accumulator += inLatencyBins[i];
+ if (i < (int)countof(kResponseLatencyMsLimits))
{
snprintf(label, sizeof(label), "< %5u ms", kResponseLatencyMsLimits[i]);
}
@@ -500,7 +1937,7 @@ mDNSlocal void LogDNSStats(const DNSStats *inStats)
{
snprintf(label, sizeof(label), "< ∞ ms");
}
- LogStat(label, count, accumulator, total);
+ LogStat(label, inLatencyBins[i], accumulator, total);
if (accumulator == total) break;
}
}
@@ -511,21 +1948,63 @@ mDNSlocal void LogDNSStats(const DNSStats *inStats)
}
//===========================================================================================================================
-// LogMetrics
+// ValidateDNSStatsDomains
//===========================================================================================================================
-mDNSexport void LogMetrics(void)
+#if (METRICS_VALIDATE_DNS_STATS_DOMAINS)
+#warning "Do not include ValidateDNSStatsDomains() in customer release!"
+mDNSlocal void ValidateDNSStatsDomains(void)
{
- DNSDomainStatsRef domainStats;
+ int i;
+ const Domain * domain;
+ mDNSu8 * ptr;
+ domainname domainNameExpected;
+ int labelCountExpected;
+ mDNSBool domainNamesEqual;
+ mDNSBool failed = mDNSfalse;
+
+ for (i = 0; i < countof(kQueryStatsDomains); ++i)
+ {
+ domain = &kQueryStatsDomains[i];
- LogMsgNoIdent("---- DNS stats by domain -----");
+ if (strcmp(domain->cstr, ".") == 0)
+ {
+ domainNameExpected.c[0] = 0;
+ }
+ else
+ {
+ ptr = MakeDomainNameFromDNSNameString(&domainNameExpected, domain->cstr);
+ if (!ptr)
+ {
+ LogMsg("ValidateDNSStatsDomains: Failed to make domain name for \"%s\".", domain->cstr);
+ failed = mDNStrue;
+ goto exit;
+ }
+ }
- for (domainStats = gDomainStatsList; domainStats; domainStats = domainStats->next)
- {
- LogMsgNoIdent("Domain: %s (non-cellular)", domainStats->domainStr);
- LogDNSStats(&domainStats->stats);
- LogMsgNoIdent("Domain: %s (cellular)", domainStats->domainStr);
- LogDNSStats(&domainStats->statsCellular);
+ domainNamesEqual = SameDomainName(domain->name, &domainNameExpected);
+ labelCountExpected = CountLabels(&domainNameExpected);
+ if (domainNamesEqual && (domain->labelCount == labelCountExpected))
+ {
+ LogMsg("ValidateDNSStatsDomains: \"%s\" passed.", domain->cstr);
+ }
+ else
+ {
+ if (!domainNamesEqual)
+ {
+ LogMsg("ValidateDNSStatsDomains: \"%s\" failed: incorrect domain name.", domain->cstr);
+ }
+ if (domain->labelCount != labelCountExpected)
+ {
+ LogMsg("ValidateDNSStatsDomains: \"%s\" failed: incorrect label count. Actual %d, expected %d.",
+ domain->cstr, domain->labelCount, labelCountExpected);
+ }
+ failed = mDNStrue;
+ }
}
+
+exit:
+ if (failed) abort();
}
+#endif
#endif // TARGET_OS_EMBEDDED
diff --git a/mDNSResponder/mDNSMacOSX/P2PPacketFilter.c b/mDNSResponder/mDNSMacOSX/P2PPacketFilter.c
index 0665103f..59a5cf4a 100644
--- a/mDNSResponder/mDNSMacOSX/P2PPacketFilter.c
+++ b/mDNSResponder/mDNSMacOSX/P2PPacketFilter.c
@@ -228,7 +228,9 @@ static void initPortRule( struct pfioc_rule * pr,
int P2PPacketFilterAddBonjourRuleSet(const char * interfaceName, u_int32_t count, pfArray_t portArray, pfArray_t protocolArray )
{
int result;
- u_int32_t i, ticket, poolTicket;
+ u_int32_t i;
+ u_int32_t ticket = 0;
+ u_int32_t poolTicket = 0;
int devFD = -1;
char * anchorPath = MDNS_ANCHOR_PATH;
@@ -278,7 +280,7 @@ int P2PPacketFilterClearBonjourRules()
{
int result;
int pfDev = -1;
- u_int32_t ticket;
+ u_int32_t ticket = 0;
char * anchorPath = MDNS_ANCHOR_PATH;
result = openPFDevice( &pfDev );
diff --git a/mDNSResponder/mDNSMacOSX/P2PPacketFilter.h b/mDNSResponder/mDNSMacOSX/P2PPacketFilter.h
index 904b43ba..23e5410b 100644
--- a/mDNSResponder/mDNSMacOSX/P2PPacketFilter.h
+++ b/mDNSResponder/mDNSMacOSX/P2PPacketFilter.h
@@ -20,7 +20,8 @@
#include "helpermsg-types.h"
-enum {
+enum
+{
PF_SET_RULES,
PF_CLEAR_RULES
};
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c b/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c
index a2ab5464..43da5025 100644
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c
@@ -112,7 +112,7 @@ OSStatus InitConfigAuthority(void)
CFSTR("Describes operation that requires user authorization"));
require_action( rightInfo != NULL, GetStrFailed, err=coreFoundationUnknownErr;);
dict = CreateRightsDict(rightInfo);
- require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr;);
+ require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr; CFRelease(rightInfo));
err = AuthorizationRightSet(gAuthRef, UPDATE_SC_RIGHT, dict, (CFStringRef) NULL,
(CFBundleRef) NULL, (CFStringRef) NULL);
@@ -128,7 +128,7 @@ OSStatus InitConfigAuthority(void)
CFSTR("Describes operation that requires user authorization"));
require_action( rightInfo != NULL, GetStrFailed, err=coreFoundationUnknownErr;);
dict = CreateRightsDict( rightInfo);
- require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr;);
+ require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr; CFRelease(rightInfo));
err = AuthorizationRightSet(gAuthRef, EDIT_SYS_KEYCHAIN_RIGHT, dict, (CFStringRef) NULL,
(CFBundleRef) NULL, (CFStringRef) NULL);
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m b/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m
index 26e3eaf0..ba5f64bf 100644
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m
@@ -333,8 +333,8 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
currentHostName = [[NSString alloc] initWithString:@""];
}
- CFRelease((CFDictionaryRef)origDict);
- CFRelease(store);
+ if (origDict) CFRelease((CFDictionaryRef)origDict);
+ if (store) CFRelease(store);
}
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.c b/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.c
index efb41497..a279c983 100644
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.c
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.c
@@ -75,7 +75,7 @@ OSStatus EnsureToolInstalled(void)
{
CFURLRef bundleURL;
pid_t toolPID;
- int status;
+ int status = 0;
OSStatus err = noErr;
const char *args[] = { kToolPath, "0", "V", NULL };
char toolSourcePath[PATH_MAX] = {};
@@ -98,8 +98,10 @@ OSStatus EnsureToolInstalled(void)
if (bundleURL != NULL)
{
CFURLGetFileSystemRepresentation(bundleURL, false, (UInt8*) toolSourcePath, sizeof toolSourcePath);
- if (strlcat(toolSourcePath, "/Contents/Resources/" kToolName, sizeof toolSourcePath ) >= sizeof toolSourcePath ) return(-1);
CFURLGetFileSystemRepresentation(bundleURL, false, (UInt8*) toolInstallerPath, sizeof toolInstallerPath);
+ CFRelease(bundleURL);
+
+ if (strlcat(toolSourcePath, "/Contents/Resources/" kToolName, sizeof toolSourcePath ) >= sizeof toolSourcePath ) return(-1);
if (strlcat(toolInstallerPath, "/Contents/Resources/" kToolInstaller, sizeof toolInstallerPath) >= sizeof toolInstallerPath) return(-1);
}
else
@@ -164,7 +166,7 @@ static OSStatus ExecWithCmdAndParam(const char *subCmd, CFDataRef paramData)
}
commFD = fileno(tmpfile());
- sprintf(fileNum, "%d", commFD);
+ snprintf(fileNum, sizeof(fileNum), "%d", commFD);
args[1] = fileNum;
args[3] = subCmd;
@@ -185,7 +187,7 @@ static OSStatus ExecWithCmdAndParam(const char *subCmd, CFDataRef paramData)
child = execTool(args);
if (child > 0)
{
- int status;
+ int status = 0;
waitpid(child, &status, 0);
if (WIFEXITED(status))
err = WEXITSTATUS(status);
diff --git a/mDNSResponder/mDNSMacOSX/Private/com.apple.mDNSResponder.plist b/mDNSResponder/mDNSMacOSX/Private/com.apple.mDNSResponder.plist
new file mode 100644
index 00000000..6d403b52
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/Private/com.apple.mDNSResponder.plist
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>DEFAULT-OPTIONS</key>
+ <dict>
+ <key>Default-Privacy-Setting</key>
+ <string>Public</string>
+ <key>Level</key>
+ <dict>
+ <key>Persist</key>
+ <string>Inherit</string>
+ <key>Enable</key>
+ <string>Inherit</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
+
diff --git a/mDNSResponder/mDNSMacOSX/Private/dns_sd_private.h b/mDNSResponder/mDNSMacOSX/Private/dns_sd_private.h
index e0b65cce..f3b480ea 100644
--- a/mDNSResponder/mDNSMacOSX/Private/dns_sd_private.h
+++ b/mDNSResponder/mDNSMacOSX/Private/dns_sd_private.h
@@ -1,5 +1,5 @@
/* -*- Mode: C; tab-width: 4 -*-
- *
+ *
* Copyright (c) 2015 Apple Inc. All rights reserved.
*/
@@ -29,4 +29,29 @@
*/
DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid);
+// Map the source port of the local UDP socket that was opened for sending the DNS query
+// to the process ID of the application that triggered the DNS resolution.
+//
+/* DNSServiceGetPID() Parameters:
+ *
+ * srcport: Source port (in network byte order) of the UDP socket that was created by
+ * the daemon to send the DNS query on the wire.
+ *
+ * pid: Process ID of the application that started the name resolution which triggered
+ * the daemon to send the query on the wire. The value can be -1 if the srcport
+ * cannot be mapped.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success, or kDNSServiceErr_ServiceNotRunning
+ * if the daemon is not running. The value of the pid is undefined if the return
+ * value has error.
+ */
+DNSServiceErrorType DNSSD_API DNSServiceGetPID
+(
+ uint16_t srcport,
+ int32_t *pid
+);
+
+#define kDNSServiceCompPrivateDNS "PrivateDNS"
+#define kDNSServiceCompMulticastDNS "MulticastDNS"
+
#endif
diff --git a/mDNSResponder/mDNSMacOSX/Private/dns_services.c b/mDNSResponder/mDNSMacOSX/Private/dns_services.c
index 794e2526..46e2a23a 100644
--- a/mDNSResponder/mDNSMacOSX/Private/dns_services.c
+++ b/mDNSResponder/mDNSMacOSX/Private/dns_services.c
@@ -10,9 +10,7 @@
#include "dns_xpc.h"
#include <xpc/xpc.h>
#include <Block.h>
-#include <syslog.h>
-
-#define LOG_NOW LOG_INFO
+#include <os/log.h>
//*************************************************************************************************************
// Globals
@@ -41,7 +39,7 @@ static void LogDebug(const char *prefix, xpc_object_t o)
return;
char *desc = xpc_copy_description(o);
- syslog(LOG_NOW, "%s: %s", prefix, desc);
+ os_log_info(OS_LOG_DEFAULT, "%s: %s", prefix, desc);
free(desc);
}
@@ -51,7 +49,7 @@ void DNSXRefDeAlloc(DNSXConnRef connRef)
{
if (connRef == NULL)
{
- syslog(LOG_WARNING, "dns_services DD: DNSXRefDeAlloc called with NULL DNSXConnRef");
+ os_log(OS_LOG_DEFAULT, "dns_services: DNSXRefDeAlloc called with NULL DNSXConnRef");
return;
}
@@ -63,18 +61,18 @@ void DNSXRefDeAlloc(DNSXConnRef connRef)
dispatch_release(connRef->lib_q);
connRef->lib_q = NULL;
connRef->AppCallBack = NULL;
- syslog(LOG_NOW, "dns_services DD: DNSXRefDeAlloc successfully DeAllocated conn_ref & lib_q");
+ os_log_info(OS_LOG_DEFAULT, "dns_services: DNSXRefDeAlloc successfully DeAllocated conn_ref & lib_q");
dispatch_async((connRef)->client_q, ^{
dispatch_release(connRef->client_q);
connRef->client_q = NULL;
free(connRef);
- syslog(LOG_NOW, "dns_services DD: DNSXRefDeAlloc successfully DeAllocated client_q & freed connRef");
+ os_log_info(OS_LOG_DEFAULT, "dns_services: DNSXRefDeAlloc successfully DeAllocated client_q & freed connRef");
});
});
// DO NOT reference connRef after this comment, as it may have been freed
- syslog(LOG_NOW, "dns_services DD: DNSXRefDeAlloc successfully DeAllocated connRef");
+ os_log_info(OS_LOG_DEFAULT, "dns_services: DNSXRefDeAlloc successfully DeAllocated connRef");
}
@@ -83,7 +81,7 @@ static DNSXErrorType SendMsgToServer(DNSXConnRef connRef, xpc_object_t msg)
{
DNSXErrorType errx = kDNSX_NoError;
- LogDebug("dns_services DD: SendMsgToServer Sending msg to Daemon", msg);
+ LogDebug("dns_services: SendMsgToServer Sending msg to Daemon", msg);
xpc_connection_send_message_with_reply((connRef)->conn_ref, msg, (connRef)->lib_q, ^(xpc_object_t recv_msg)
{
@@ -91,13 +89,13 @@ static DNSXErrorType SendMsgToServer(DNSXConnRef connRef, xpc_object_t msg)
if (type == XPC_TYPE_DICTIONARY)
{
- LogDebug("dns_services DD: SendMsgToServer Received reply msg from Daemon", recv_msg);
+ LogDebug("dns_services: SendMsgToServer Received reply msg from Daemon", recv_msg);
uint64_t daemon_status = xpc_dictionary_get_uint64(recv_msg, kDNSDaemonReply);
if (connRef == NULL || connRef->client_q == NULL || connRef->AppCallBack == NULL)
{
// If connRef is bad, do not schedule any callbacks to the client
- syslog(LOG_WARNING, "dns_services DD: SendMsgToServer: connRef is BAD Daemon status code [%llu]", daemon_status);
+ os_log(OS_LOG_DEFAULT, "dns_services: SendMsgToServer: connRef is BAD Daemon status code [%llu]", daemon_status);
}
else
{
@@ -110,14 +108,16 @@ static DNSXErrorType SendMsgToServer(DNSXConnRef connRef, xpc_object_t msg)
});
break;
- case kDNSMsg_BadArg:
+ case kDNSMsg_Busy:
+ os_log(OS_LOG_DEFAULT, "dns_services: SendMsgToServer: DNS Proxy already in use");
dispatch_async((connRef)->client_q, ^{
if (connRef->AppCallBack != NULL)
- ((DNSXEnableProxyReply)connRef->AppCallBack)(connRef, kDNSX_BadParam);
+ ((DNSXEnableProxyReply)connRef->AppCallBack)(connRef, kDNSX_Busy);
});
break;
default:
+ os_log(OS_LOG_DEFAULT, "dns_services: SendMsgToServer: Unknown error");
dispatch_async((connRef)->client_q, ^{
if (connRef->AppCallBack != NULL)
((DNSXEnableProxyReply)connRef->AppCallBack)(connRef, kDNSX_UnknownErr);
@@ -128,9 +128,9 @@ static DNSXErrorType SendMsgToServer(DNSXConnRef connRef, xpc_object_t msg)
}
else
{
- syslog(LOG_WARNING, "dns_services DD: SendMsgToServer Received unexpected reply from daemon [%s]",
+ os_log(OS_LOG_DEFAULT, "dns_services: SendMsgToServer Received unexpected reply from daemon [%s]",
xpc_dictionary_get_string(recv_msg, XPC_ERROR_KEY_DESCRIPTION));
- LogDebug("dns_services DD: SendMsgToServer Unexpected Reply contents", recv_msg);
+ LogDebug("dns_services: SendMsgToServer Unexpected Reply contents", recv_msg);
}
});
@@ -141,13 +141,16 @@ static DNSXErrorType SendMsgToServer(DNSXConnRef connRef, xpc_object_t msg)
static DNSXErrorType InitConnection(DNSXConnRef *connRefOut, const char *servname, dispatch_queue_t clientq, void *AppCallBack)
{
if (connRefOut == NULL)
+ {
+ os_log(OS_LOG_DEFAULT, "dns_services: InitConnection() connRef cannot be NULL");
return kDNSX_BadParam;
+ }
// Use a DNSXConnRef on the stack to be captured in the blocks below, rather than capturing the DNSXConnRef* owned by the client
DNSXConnRef connRef = malloc(sizeof(struct _DNSXConnRef_t));
if (connRef == NULL)
{
- syslog(LOG_WARNING, "dns_services DD: InitConnection() No memory to allocate!");
+ os_log(OS_LOG_DEFAULT, "dns_services: InitConnection() No memory to allocate!");
return kDNSX_NoMem;
}
@@ -160,7 +163,7 @@ static DNSXErrorType InitConnection(DNSXConnRef *connRefOut, const char *servnam
if (connRef->conn_ref == NULL || connRef->lib_q == NULL)
{
- syslog(LOG_WARNING, "dns_services DD: InitConnection() conn_ref/lib_q is NULL");
+ os_log(OS_LOG_DEFAULT, "dns_services: InitConnection() conn_ref/lib_q is NULL");
if (connRef != NULL)
free(connRef);
return kDNSX_NoMem;
@@ -171,12 +174,12 @@ static DNSXErrorType InitConnection(DNSXConnRef *connRefOut, const char *servnam
if (connRef == NULL || connRef->client_q == NULL || connRef->AppCallBack == NULL)
{
// If connRef is bad, do not schedule any callbacks to the client
- syslog(LOG_WARNING, "dns_services DD: InitConnection: connRef is BAD Unexpected Connection Error [%s]",
+ os_log(OS_LOG_DEFAULT, "dns_services: InitConnection: connRef is BAD Unexpected Connection Error [%s]",
xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
}
else
{
- syslog(LOG_WARNING, "dns_services DD: InitConnection: Unexpected Connection Error [%s] Ping the client",
+ os_log(OS_LOG_DEFAULT, "dns_services: InitConnection: Unexpected Connection Error [%s] Ping the client",
xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
dispatch_async(connRef->client_q, ^{
if (connRef->AppCallBack != NULL)
@@ -201,7 +204,7 @@ DNSXErrorType DNSXEnableProxy(DNSXConnRef *connRef, DNSProxyParameters proxypara
// Sanity Checks
if (connRef == NULL || callBack == NULL || clientq == NULL)
{
- syslog(LOG_WARNING, "dns_services DD: DNSXEnableProxy called with NULL DNSXConnRef OR Callback OR ClientQ parameter");
+ os_log(OS_LOG_DEFAULT, "dns_services: DNSXEnableProxy called with NULL DNSXConnRef OR Callback OR ClientQ parameter");
return kDNSX_BadParam;
}
@@ -211,13 +214,13 @@ DNSXErrorType DNSXEnableProxy(DNSXConnRef *connRef, DNSProxyParameters proxypara
errx = InitConnection(connRef, kDNSProxyService, clientq, callBack);
if (errx) // On error InitConnection() leaves *connRef set to NULL
{
- syslog(LOG_WARNING, "dns_services DD: Since InitConnection() returned %d error returning w/o sending msg", errx);
+ os_log(OS_LOG_DEFAULT, "dns_services: Since InitConnection() returned %d error returning w/o sending msg", errx);
return errx;
}
}
else // Client already has a connRef and this is not valid use for this SPI
{
- syslog(LOG_WARNING, "dns_services DD: Client already has a valid connRef! This is incorrect usage from the client");
+ os_log(OS_LOG_DEFAULT, "dns_services: Client already has a valid connRef! This is incorrect usage from the client");
return kDNSX_BadParam;
}
@@ -225,7 +228,7 @@ DNSXErrorType DNSXEnableProxy(DNSXConnRef *connRef, DNSProxyParameters proxypara
xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
if (dict == NULL)
{
- syslog(LOG_WARNING, "dns_services DD: DNSXEnableProxy could not create the Msg Dict To Send!");
+ os_log(OS_LOG_DEFAULT, "dns_services: DNSXEnableProxy could not create the Msg Dict To Send!");
DNSXRefDeAlloc(*connRef);
return kDNSX_NoMem;
}
diff --git a/mDNSResponder/mDNSMacOSX/Private/dns_services.h b/mDNSResponder/mDNSMacOSX/Private/dns_services.h
index 25b911f1..34c68756 100644
--- a/mDNSResponder/mDNSMacOSX/Private/dns_services.h
+++ b/mDNSResponder/mDNSMacOSX/Private/dns_services.h
@@ -22,7 +22,8 @@ typedef enum
kDNSX_NoError = 0,
kDNSX_UnknownErr = -65537, /* 0xFFFE FFFF */
kDNSX_NoMem = -65539, /* No Memory */
- kDNSX_BadParam = -65540, /* Client passes invalid arg/Bad use of SPI */
+ kDNSX_BadParam = -65540, /* Client passed invalid arg */
+ kDNSX_Busy = -65551, /* DNS Proxy already in use: incorrect use of SPI by client */
kDNSX_DaemonNotRunning = -65563 /* Daemon not running */
} DNSXErrorType;
diff --git a/mDNSResponder/mDNSMacOSX/Private/dns_xpc.h b/mDNSResponder/mDNSMacOSX/Private/dns_xpc.h
index 4c961a84..bda2bf92 100644
--- a/mDNSResponder/mDNSMacOSX/Private/dns_xpc.h
+++ b/mDNSResponder/mDNSMacOSX/Private/dns_xpc.h
@@ -11,6 +11,7 @@
#define DNS_XPC_H
#define kDNSProxyService "com.apple.mDNSResponder.dnsproxy"
+#define kDNSCTLService "com.apple.mDNSResponder.dnsctl"
#define kDNSProxyParameters "DNSProxyParameters"
@@ -27,7 +28,34 @@
typedef enum
{
kDNSMsg_NoError = 0,
- kDNSMsg_BadArg
+ kDNSMsg_Busy
} DaemonReplyStatusCodes;
+#define kDNSLogLevel "DNSLoggingVerbosity"
+
+typedef enum
+{
+ log_level1 = 1, // logging off
+ log_level2, // logging USR1
+ log_level3, // logging USR2
+ log_level4, // logging USR1/2
+} DNSLogLevels;
+
+#define kDNSStateInfo "DNSStateInfoLevels"
+
+typedef enum
+{
+ full_state = 1, // full state info of mDNSResponder (INFO)
+} DNSStateInfo;
+
+#define kmDNSResponderTests "mDNSResponderTests"
+
+typedef enum
+{
+ test_helper_ipc = 1, // invokes mDNSResponder to send a test msg to mDNSResponderHelper
+ test_mDNS_log, // invokes mDNSResponder to log using different internal macros
+} mDNSTestModes;
+
+
+
#endif // DNS_XPC_H
diff --git a/mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c b/mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c
new file mode 100644
index 00000000..9b3885e6
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c
@@ -0,0 +1,224 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2015 Apple Inc. All rights reserved.
+ *
+ * dnsctl_server.c
+ * mDNSResponder
+ *
+ * XPC as an IPC mechanism to communicate with dnsctl. Open only to Apple OSX/iOS clients
+ */
+
+#include "xpc_services.h"
+#include "dns_xpc.h"
+
+#include "mDNSMacOSX.h" // KQueueLock/KQueueUnlock
+#include "helper.h" // mDNSResponderHelper tests
+#include <xpc/xpc.h>
+
+// ***************************************************************************
+// Globals
+extern mDNS mDNSStorage;
+static dispatch_queue_t dnsctlserver_queue = NULL;
+// ***************************************************************************
+
+mDNSlocal void handle_logging(mDNSu32 log_level)
+{
+ KQueueLock(&mDNSStorage);
+
+ switch (log_level)
+ {
+ case log_level1:
+ mDNS_LoggingEnabled = mDNS_PacketLoggingEnabled = 0;
+ LogMsg("USR1 Logging:[%s] USR2 Logging:[%s]", mDNS_LoggingEnabled ? "Enabled" : "Disabled", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled");
+ break;
+
+ case log_level2:
+ mDNS_LoggingEnabled = 1;
+ LogMsg("USR1 Logging %s", mDNS_LoggingEnabled ? "Enabled" : "Disabled");
+ break;
+
+ case log_level3:
+ mDNS_PacketLoggingEnabled = 1;
+ LogMsg("USR2 Logging %s", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled");
+ break;
+
+ case log_level4:
+ mDNS_LoggingEnabled = 1 ;
+ mDNS_PacketLoggingEnabled = 1;
+ LogMsg("USR1 Logging:%s USR2 Logging:%s", mDNS_LoggingEnabled ? "Enabled" : "Disabled", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled");
+ break;
+
+ default:
+ mDNS_LoggingEnabled = 0 ;
+ mDNS_PacketLoggingEnabled = 0;
+ break;
+ }
+ UpdateDebugState();
+
+ KQueueUnlock(&mDNSStorage, "LogLevel changed");
+}
+
+mDNSlocal void handle_stateinfo(mDNSu32 state_level)
+{
+ KQueueLock(&mDNSStorage);
+
+ switch (state_level)
+ {
+ case full_state:
+ INFOCallback();
+ break;
+
+ default:
+ INFOCallback();
+ break;
+ }
+
+ KQueueUnlock(&mDNSStorage, "StateInfo dumped");
+}
+
+
+mDNSlocal void handle_test_mode(mDNSu32 test_mode)
+{
+ KQueueLock(&mDNSStorage);
+
+ switch (test_mode)
+ {
+ case test_helper_ipc:
+ mDNSNotify("mDNSResponderHelperTest", "This is just a test message to mDNSResponderHelper. This is NOT an actual alert");
+ break;
+
+ case test_mDNS_log:
+ LogInfo("LogInfo: Should be logged at INFO level");
+ LogOperation("LogOperation: Should be logged at INFO level");
+ LogMsg("LogMsg: Should be logged at DEFAULT level");
+ LogSPS("LogSPS: Should be logged at INFO level");
+ break;
+
+ default:
+ LogMsg("Unidentified Test mode: Please add this test");
+ break;
+ }
+
+ KQueueUnlock(&mDNSStorage, "Test Msg to mDNSResponderHelper");
+}
+
+mDNSlocal void handle_terminate()
+{
+
+ LogInfo("handle_terminate: Client terminated connection.");
+
+}
+
+mDNSlocal void handle_requests(xpc_object_t req)
+{
+ mDNSu32 log_level, state_level, test_mode;
+ xpc_connection_t remote_conn = xpc_dictionary_get_remote_connection(req);
+
+ LogInfo("handle_requests: Handler for dnsctl requests");
+
+ xpc_object_t response = xpc_dictionary_create_reply(req);
+
+ // Return Success Status to the client (essentially ACKing the request)
+ if (response)
+ {
+ xpc_dictionary_set_uint64(response, kDNSDaemonReply, kDNSMsg_NoError);
+ xpc_connection_send_message(remote_conn, response);
+ xpc_release(response);
+ }
+ else
+ {
+ LogMsg("handle_requests: Response Dictionary could not be created");
+ return;
+ }
+
+ // switch here based on dictionary
+ // to handle various different requests like logging, INFO snapshot, etc..
+ if ((xpc_dictionary_get_uint64(req, kDNSLogLevel)))
+ {
+ log_level = (mDNSu32)(xpc_dictionary_get_uint64(req, kDNSLogLevel));
+ handle_logging(log_level);
+ }
+ else if ((xpc_dictionary_get_uint64(req, kDNSStateInfo)))
+ {
+ state_level = (mDNSu32)(xpc_dictionary_get_uint64(req, kDNSStateInfo));
+ handle_stateinfo(state_level);
+ }
+ else if ((xpc_dictionary_get_uint64(req, kmDNSResponderTests)))
+ {
+ test_mode = (mDNSu32)(xpc_dictionary_get_uint64(req, kmDNSResponderTests));
+ handle_test_mode(test_mode);
+ }
+}
+
+mDNSlocal void accept_client(xpc_connection_t conn)
+{
+ uid_t c_euid;
+ int c_pid;
+ c_euid = xpc_connection_get_euid(conn);
+ c_pid = xpc_connection_get_pid(conn);
+
+ if (c_euid != 0 || !IsEntitled(conn, kDNSCTLService))
+ {
+ LogMsg("accept_client: Client PID[%d] is missing Entitlement or is NOT running as root!", c_pid);
+ xpc_connection_cancel(conn);
+ return;
+ }
+
+ xpc_retain(conn);
+ xpc_connection_set_target_queue(conn, dnsctlserver_queue);
+ xpc_connection_set_event_handler(conn, ^(xpc_object_t req_msg)
+ {
+ xpc_type_t type = xpc_get_type(req_msg);
+
+ if (type == XPC_TYPE_DICTIONARY)
+ {
+ handle_requests(req_msg);
+ }
+ else // We hit this case ONLY if Client Terminated Connection OR Crashed
+ {
+ LogInfo("accept_client: Client %p teared down the connection", (void *) conn);
+ handle_terminate();
+ xpc_release(conn);
+ }
+ });
+
+ xpc_connection_resume(conn);
+
+}
+
+mDNSexport void init_dnsctl_service(void)
+{
+
+ xpc_connection_t dnsctl_listener = xpc_connection_create_mach_service(kDNSCTLService, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
+ if (!dnsctl_listener || xpc_get_type(dnsctl_listener) != XPC_TYPE_CONNECTION)
+ {
+ LogMsg("init_dnsctl_service: Error Creating XPC Listener for DNSCTL Server!");
+ return;
+ }
+
+ dnsctlserver_queue = dispatch_queue_create("com.apple.mDNSResponder.dnsctlserver_queue", NULL);
+
+ xpc_connection_set_event_handler(dnsctl_listener, ^(xpc_object_t eventmsg)
+ {
+ xpc_type_t type = xpc_get_type(eventmsg);
+
+ if (type == XPC_TYPE_CONNECTION)
+ {
+ LogInfo("init_dnsctl_service: New DNSCTL Client %p", eventmsg);
+ accept_client(eventmsg);
+ }
+ else if (type == XPC_TYPE_ERROR) // Ideally, we would never hit these cases
+ {
+ LogMsg("init_dnsctl_service: XPCError: %s", xpc_dictionary_get_string(eventmsg, XPC_ERROR_KEY_DESCRIPTION));
+ }
+ else
+ {
+ LogMsg("init_dnsctl_service: Unknown EventMsg type");
+ }
+ });
+
+ xpc_connection_resume(dnsctl_listener);
+}
+
+
+
diff --git a/mDNSResponder/mDNSMacOSX/Private/xpc_services.c b/mDNSResponder/mDNSMacOSX/Private/xpc_services.c
index fb357806..4cad6ba0 100644
--- a/mDNSResponder/mDNSMacOSX/Private/xpc_services.c
+++ b/mDNSResponder/mDNSMacOSX/Private/xpc_services.c
@@ -15,8 +15,7 @@
#include "dnsproxy.h" // DNSProxyInit/ProxyUDPCallback/ProxyTCPCallback
#include "mDNSMacOSX.h" // KQueueLock/KQueueUnlock
-#include <xpc/xpc.h>
-#include <xpc/private.h> // xpc_connection_copy_entitlement_value
+#include <xpc/private.h> // xpc_connection_copy_entitlement_value
// ***************************************************************************
// Globals
@@ -87,10 +86,10 @@ mDNSlocal void handle_dps_request(xpc_object_t req)
{
LogMsg("handle_dps_request: A Client is already using DNS Proxy and your request cannot be handled at this time");
// Return Engaged Status to the client
- xpc_object_t reply = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_object_t reply = xpc_dictionary_create_reply(req);
if (reply)
{
- xpc_dictionary_set_uint64(reply, kDNSDaemonReply, kDNSMsg_BadArg);
+ xpc_dictionary_set_uint64(reply, kDNSDaemonReply, kDNSMsg_Busy);
xpc_connection_send_message(remote_conn, reply);
xpc_release(reply);
}
@@ -138,7 +137,7 @@ mDNSlocal void handle_dps_request(xpc_object_t req)
}
// Verify Client's Entitlement
-mDNSlocal mDNSBool IsEntitled(xpc_connection_t conn, const char *password)
+mDNSexport mDNSBool IsEntitled(xpc_connection_t conn, const char *password)
{
mDNSBool entitled = mDNSfalse;
xpc_object_t ent = xpc_connection_copy_entitlement_value(conn, password);
@@ -157,7 +156,7 @@ mDNSlocal mDNSBool IsEntitled(xpc_connection_t conn, const char *password)
}
if (!entitled)
- LogMsg("IsEntitled: DNSProxyService Client is missing Entitlement!");
+ LogMsg("IsEntitled: Client is missing Entitlement!");
return entitled;
}
@@ -241,8 +240,10 @@ mDNSexport void xpc_server_init()
{
// Add XPC Services here
init_dnsproxy_service();
+ init_dnsctl_service();
}
+
#else // !UNICAST_DISABLED
mDNSexport void xpc_server_init()
diff --git a/mDNSResponder/mDNSMacOSX/Private/xpc_services.h b/mDNSResponder/mDNSMacOSX/Private/xpc_services.h
index 50081bed..8d7c0433 100644
--- a/mDNSResponder/mDNSMacOSX/Private/xpc_services.h
+++ b/mDNSResponder/mDNSMacOSX/Private/xpc_services.h
@@ -14,8 +14,14 @@
#define XPC_SERVICES_H
#include "mDNSEmbeddedAPI.h"
+#include <xpc/xpc.h>
extern void xpc_server_init(void);
extern void xpcserver_info(mDNS *const m);
+extern mDNSBool IsEntitled(xpc_connection_t conn, const char *password);
+extern void init_dnsctl_service(void);
+
+extern void INFOCallback(void);
+
#endif // XPC_SERVICES_H
diff --git a/mDNSResponder/mDNSMacOSX/SymptomReporter.c b/mDNSResponder/mDNSMacOSX/SymptomReporter.c
index 39ce0d41..7dde2f5e 100644
--- a/mDNSResponder/mDNSMacOSX/SymptomReporter.c
+++ b/mDNSResponder/mDNSMacOSX/SymptomReporter.c
@@ -22,7 +22,16 @@
#include <stddef.h>
#include <stdint.h>
#include <sys/socket.h>
+#include <AvailabilityMacros.h>
+#include <TargetConditionals.h>
+
+#define TARGET_OS_MACOSX (TARGET_OS_MAC && !TARGET_OS_IPHONE)
+
+#if (!TARGET_OS_MACOSX || (MAC_OS_X_VERSION_MAX_ALLOWED >= 101200))
+#include <SymptomReporter/SymptomReporter.h>
+#else
#include <Symptoms/SymptomReporter.h>
+#endif
#define SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID 101
#define SYMPTOM_REPORTER_mDNSResponder_TEXT_ID "com.apple.mDNSResponder"
@@ -30,7 +39,7 @@
#define SYMPTOM_DNS_NO_REPLIES 0x00065001
#define SYMPTOM_DNS_RESUMED_RESPONDING 0x00065002
-static symptom_framework_t symptomReporter;
+static symptom_framework_t symptomReporter = mDNSNULL;
static symptom_framework_t (*symptom_framework_init_f)(symptom_ident_t id, const char *originator_string) = mDNSNULL;
static symptom_t (*symptom_new_f)(symptom_framework_t framework, symptom_ident_t id) = mDNSNULL;
static int (*symptom_set_additional_qualifier_f)(symptom_t symptom, uint32_t qualifier_type, size_t qualifier_len, void *qualifier_data) = mDNSNULL;
@@ -39,53 +48,43 @@ static int (*symptom_send_f)(symptom_t symptom) = mDNSNULL;
mDNSlocal mStatus SymptomReporterInitCheck(void)
{
mStatus err;
- static mDNSBool isInitialized = mDNSfalse;
+ static mDNSBool triedInit = mDNSfalse;
static void *symptomReporterLib = mDNSNULL;
+#if (!TARGET_OS_MACOSX || (MAC_OS_X_VERSION_MAX_ALLOWED >= 101200))
+ static const char path[] = "/System/Library/PrivateFrameworks/SymptomReporter.framework/SymptomReporter";
+#else
static const char path[] = "/System/Library/PrivateFrameworks/Symptoms.framework/Frameworks/SymptomReporter.framework/SymptomReporter";
+#endif
- if (!isInitialized)
+ if (!triedInit)
{
+ triedInit = mDNStrue;
+
+ symptomReporterLib = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
if (!symptomReporterLib)
- {
- symptomReporterLib = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
- if (!symptomReporterLib)
- goto exit;
- }
+ goto exit;
+ symptom_framework_init_f = dlsym(symptomReporterLib, "symptom_framework_init");
if (!symptom_framework_init_f)
- {
- symptom_framework_init_f = dlsym(symptomReporterLib, "symptom_framework_init");
- if (!symptom_framework_init_f)
- goto exit;
- }
+ goto exit;
+ symptom_new_f = dlsym(symptomReporterLib, "symptom_new");
if (!symptom_new_f)
- {
- symptom_new_f = dlsym(symptomReporterLib, "symptom_new");
- if (!symptom_new_f)
- goto exit;
- }
+ goto exit;
+ symptom_set_additional_qualifier_f = dlsym(symptomReporterLib, "symptom_set_additional_qualifier");
if (!symptom_set_additional_qualifier_f)
- {
- symptom_set_additional_qualifier_f = dlsym(symptomReporterLib, "symptom_set_additional_qualifier");
- if (!symptom_set_additional_qualifier_f)
- goto exit;
- }
+ goto exit;
+ symptom_send_f = dlsym(symptomReporterLib, "symptom_send");
if (!symptom_send_f)
- {
- symptom_send_f = dlsym(symptomReporterLib, "symptom_send");
- if (!symptom_send_f)
- goto exit;
- }
+ goto exit;
symptomReporter = symptom_framework_init_f(SYMPTOM_REPORTER_mDNSResponder_NUMERIC_ID, SYMPTOM_REPORTER_mDNSResponder_TEXT_ID);
- isInitialized = mDNStrue;
}
exit:
- err = isInitialized ? mStatus_NoError : mStatus_NotInitializedErr;
+ err = symptomReporter ? mStatus_NoError : mStatus_NotInitializedErr;
return err;
}
diff --git a/mDNSResponder/mDNSMacOSX/com.apple.dnsextd.plist b/mDNSResponder/mDNSMacOSX/com.apple.dnsextd.plist
index e31b391f..86d7b777 100644
--- a/mDNSResponder/mDNSMacOSX/com.apple.dnsextd.plist
+++ b/mDNSResponder/mDNSMacOSX/com.apple.dnsextd.plist
@@ -6,8 +6,6 @@
<true/>
<key>Label</key>
<string>com.apple.dnsextd</string>
- <key>OnDemand</key>
- <false/>
<key>ProgramArguments</key>
<array>
<string>/usr/sbin/dnsextd</string>
diff --git a/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponder.plist b/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponder.plist
index 8f5a6408..881f8c9e 100644
--- a/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponder.plist
+++ b/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponder.plist
@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.apple.mDNSResponder.reloaded</string>
- <key>OnDemand</key>
- <false/>
<key>InitGroups</key>
<false/>
<key>UserName</key>
@@ -18,10 +16,10 @@
</array>
<key>MachServices</key>
<dict>
- <key>com.apple.mDNSResponder</key>
+ <key>com.apple.mDNSResponder.dnsproxy</key>
+ <true/>
+ <key>com.apple.mDNSResponder.dnsctl</key>
<true/>
- <key>com.apple.mDNSResponder.dnsproxy</key>
- <true/>
</dict>
<key>Sockets</key>
<dict>
diff --git a/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist b/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist
index f1e3027b..91ed1da3 100644
--- a/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist
+++ b/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist
@@ -12,7 +12,7 @@
</array>
<key>MachServices</key>
<dict>
- <key>com.apple.mDNSResponderHelper</key>
+ <key>com.apple.mDNSResponder_Helper</key>
<true/>
</dict>
<key>POSIXSpawnType</key>
diff --git a/mDNSResponder/mDNSMacOSX/com.apple.networking.mDNSResponder b/mDNSResponder/mDNSMacOSX/com.apple.networking.mDNSResponder
deleted file mode 100644
index d07c99d0..00000000
--- a/mDNSResponder/mDNSMacOSX/com.apple.networking.mDNSResponder
+++ /dev/null
@@ -1 +0,0 @@
-? [= LoggerID com.apple.networking.mDNSResponder] file /Library/Logs/CrashReporter/com.apple.networking.mDNSResponder.log rotate file_max=1M compress
diff --git a/mDNSResponder/mDNSMacOSX/coreBLE.h b/mDNSResponder/mDNSMacOSX/coreBLE.h
new file mode 100644
index 00000000..cc00923a
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/coreBLE.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2015-2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _coreBLE_H_
+#define _coreBLE_H_
+
+#include "BLE.h"
+
+@interface coreBLE : NSObject <CBCentralManagerDelegate, CBPeripheralManagerDelegate, CBPeripheralDelegate>
+
+- (id)init;
+- (void) advertiseBrowses:(serviceHash_t) browseHash andRegistrations:(serviceHash_t) registeredHash;
+- (void) stopBeacon;
+- (void) updateScan:(bool) start;
+
+@end
+
+#endif /* _coreBLE_H_ */
diff --git a/mDNSResponder/mDNSMacOSX/coreBLE.m b/mDNSResponder/mDNSMacOSX/coreBLE.m
new file mode 100644
index 00000000..e764169a
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/coreBLE.m
@@ -0,0 +1,371 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2015-2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mDNSEmbeddedAPI.h"
+#include "DNSCommon.h"
+
+#import <Foundation/Foundation.h>
+#import <CoreBluetooth/CoreBluetooth.h>
+#import <CoreBluetooth/CoreBluetooth_Private.h>
+#import "mDNSMacOSX.h"
+#import "BLE.h"
+#import "coreBLE.h"
+
+static coreBLE * coreBLEptr;
+
+// Call Bluetooth subsystem to start/stop the the Bonjour BLE beacon and
+// beacon scanning based on the current browse and registration hashes.
+void updateBLEBeaconAndScan(serviceHash_t browseHash, serviceHash_t registeredHash)
+{
+ if (coreBLEptr == 0)
+ coreBLEptr = [[coreBLE alloc] init];
+
+ LogInfo("updateBLEBeaconAndScan: browseHash = 0x%x, registeredHash = 0x%x", browseHash, registeredHash);
+
+ [coreBLEptr advertiseBrowses:browseHash andRegistrations: registeredHash];
+ [coreBLEptr updateScan:(browseHash || registeredHash)];
+}
+
+// Stop the current BLE beacon.
+void stopBLEBeacon(void)
+{
+ if (coreBLEptr == 0)
+ {
+ LogInfo("stopBLEBeacon called before BLE scan initialized ??");
+ return;
+ }
+
+ LogInfo("stopBLEBeacon Stopping beacon");
+ [coreBLEptr stopBeacon];
+}
+
+@implementation coreBLE
+{
+ CBCentralManager *_centralManager;
+ CBPeripheralManager *_peripheralManager;
+
+ NSData *_currentlyAdvertisedData;
+
+ // [_centralManager isScanning] is only avilable on iOS and not OSX,
+ // so track scanning state locally.
+ BOOL _isScanning;
+}
+
+- (id)init
+{
+ self = [super init];
+
+ if (self)
+ {
+ _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
+ _peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
+ _currentlyAdvertisedData = nil;
+ _isScanning = NO;
+
+ if (_centralManager == nil || _peripheralManager == nil )
+ {
+ LogMsg("coreBLE initialization failed!");
+ }
+ else
+ {
+ LogInfo("coreBLE initialised");
+ }
+ }
+
+ return self;
+}
+
+#define ADVERTISEMENTDATALENGTH 28 // 31 - 3 (3 bytes for flags)
+
+// TODO:
+// DBDeviceTypeBonjour should eventually be added to the DBDeviceType definitions in WirelessProximity
+// The Bluetooth team recommended using a value < 32 for prototyping, since 32 is the number of
+// beacon types they can track in their duplicate beacon filtering logic.
+#define DBDeviceTypeBonjour 26
+
+// Beacon flags and version byte
+#define BonjourBLEVersion 1
+
+extern mDNS mDNSStorage;
+extern mDNSInterfaceID AWDLInterfaceID;
+
+// Transmit the last beacon indicating we are no longer advertising or browsing any services for two seconds.
+#define LastBeaconTime 2
+
+- (void) advertiseBrowses:(serviceHash_t) browseHash andRegistrations:(serviceHash_t) registeredHash
+{
+ uint8_t advertisingData[ADVERTISEMENTDATALENGTH] = {0, 0xff, 0x4c, 0x00 };
+ uint8_t advertisingLength = 4;
+
+ // TODO: If we have been transmitting a beacon, we probably want to continue transmitting
+ // for a few seconds after both hashes are zero so that that any devices scanning
+ // can see the beacon indicating we have stopped all browses and advertisements.
+
+ // Stop the beacon if there is no data to advertise.
+ if (browseHash == 0 && registeredHash == 0)
+ {
+ LogInfo("advertiseBrowses:andRegistrations Stopping beacon in %d seconds", LastBeaconTime);
+ if (mDNSStorage.NextBLEServiceTime)
+ LogInfo("advertiseBrowses:andRegistrations: NextBLEServiceTime already set ??");
+
+ mDNSStorage.NextBLEServiceTime = NonZeroTime(mDNS_TimeNow_NoLock(& mDNSStorage) + LastBeaconTime * mDNSPlatformOneSecond);
+ }
+ else
+ {
+ mDNSStorage.NextBLEServiceTime = 0;
+ }
+
+ // The beacon type.
+ advertisingData[advertisingLength++] = DBDeviceTypeBonjour;
+
+ // Flags and Version field
+ advertisingData[advertisingLength++] = BonjourBLEVersion;
+
+ memcpy(& advertisingData[advertisingLength], & browseHash, sizeof(serviceHash_t));
+ advertisingLength += sizeof(serviceHash_t);
+ memcpy(& advertisingData[advertisingLength], & registeredHash, sizeof(serviceHash_t));
+ advertisingLength += sizeof(serviceHash_t);
+
+
+ // Add the MAC address of the awdl0 interface. Don't cache it since
+ // it can get updated periodically.
+ if (AWDLInterfaceID)
+ {
+ NetworkInterfaceInfoOSX *intf = IfindexToInterfaceInfoOSX(& mDNSStorage, AWDLInterfaceID);
+ if (intf)
+ memcpy(& advertisingData[advertisingLength], & intf->ifinfo.MAC, sizeof(mDNSEthAddr));
+ else
+ memset( & advertisingData[advertisingLength], 0, sizeof(mDNSEthAddr));
+ }
+ else
+ {
+ // just use zero if not avaiblable
+ memset( & advertisingData[advertisingLength], 0, sizeof(mDNSEthAddr));
+ }
+ advertisingLength += sizeof(mDNSEthAddr);
+
+ // Total length of data advertised, minus this lenght byte.
+ advertisingData[0] = (advertisingLength - 1);
+
+ LogInfo("advertiseBrowses:andRegistrations advertisingLength = %d", advertisingLength);
+
+ NSData* data = [NSData dataWithBytes:advertisingData length:advertisingLength];
+
+ if([_peripheralManager isAdvertising] && [data isEqualToData: _currentlyAdvertisedData])
+ {
+ // No need to restart the advertisement if it is already active with the same data.
+ LogInfo("advertiseBrowses:andRegistrations: No change in advertised data");
+ }
+ else
+ {
+ _currentlyAdvertisedData = data;
+
+ if ([_peripheralManager isAdvertising])
+ {
+ LogInfo("advertiseBrowses:andRegistrations: Stop current advertisement before restarting");
+ [_peripheralManager stopAdvertising];
+ }
+ LogInfo("advertiseBrowses:andRegistrations: Starting beacon");
+
+ [_peripheralManager startAdvertising:@{ CBAdvertisementDataAppleMfgData : _currentlyAdvertisedData, CBCentralManagerScanOptionIsPrivilegedDaemonKey : @YES, @"kCBAdvOptionUseFGInterval" : @YES }];
+ }
+}
+
+- (void) stopBeacon
+{
+ [_peripheralManager stopAdvertising];
+}
+
+- (void) updateScan:(bool) start
+{
+ if (_isScanning)
+ {
+ if (!start)
+ {
+ LogInfo("updateScan: stopping scan");
+ [_centralManager stopScan];
+ _isScanning = NO;
+ }
+ }
+ else
+ {
+ if (start)
+ {
+ LogInfo("updateScan: starting scan");
+
+ _isScanning = YES;
+ [_centralManager scanForPeripheralsWithServices:nil options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @NO }];
+ }
+ }
+}
+
+#pragma mark - CBCentralManagerDelegate protocol
+
+- (void)centralManagerDidUpdateState:(CBCentralManager *)central
+{
+ switch (central.state) {
+ case CBCentralManagerStateUnknown:
+ LogInfo("centralManagerDidUpdateState: CBCentralManagerStateUnknown");
+ break;
+
+ case CBCentralManagerStateResetting:
+ LogInfo("centralManagerDidUpdateState: CBCentralManagerStateResetting");
+ break;
+
+ case CBCentralManagerStateUnsupported:
+ LogInfo("centralManagerDidUpdateState: CBCentralManagerStateUnsupported");
+ break;
+
+ case CBCentralManagerStateUnauthorized:
+ LogInfo("centralManagerDidUpdateState: CBCentralManagerStateUnauthorized");
+ break;
+
+ case CBCentralManagerStatePoweredOff:
+ LogInfo("centralManagerDidUpdateState: CBCentralManagerStatePoweredOff");
+ break;
+
+ case CBCentralManagerStatePoweredOn:
+ LogInfo("centralManagerDidUpdateState: CBCentralManagerStatePoweredOn");
+ break;
+
+ default:
+ LogInfo("centralManagerDidUpdateState: Unknown state ??");
+ break;
+ }
+}
+
+// offset of beacon type in recieved CBAdvertisementDataManufacturerDataKey bytes
+#define beaconTypeByteIndex 2
+
+- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI
+{
+ (void) central;
+ (void) peripheral;
+ (void) RSSI;
+
+ NSData *data = [advertisementData objectForKey:CBAdvertisementDataManufacturerDataKey];
+
+ if (!data) {
+ return;
+ }
+
+ unsigned char *bytes = (unsigned char *)data.bytes;
+
+ // Just parse the DBDeviceTypeBonjour beacons.
+ if (bytes[beaconTypeByteIndex] == DBDeviceTypeBonjour)
+ {
+ serviceHash_t browseHash, registeredHash;
+ mDNSEthAddr senderMAC;
+ unsigned char flagsAndVersion;
+ unsigned char *ptr;
+
+#if VERBOSE_BLE_DEBUG
+ LogInfo("didDiscoverPeripheral: received DBDeviceTypeBonjour beacon, length = %d", [data length]);
+ LogInfo("didDiscoverPeripheral: central = 0x%x, peripheral = 0x%x", central, peripheral);
+#endif // VERBOSE_BLE_DEBUG
+
+ // The DBDeviceTypeBonjour beacon bytes will be:
+ // x4C, 0x0, 0x2A, flags_and_version_byte,, browseHash, advertisingServices_hash_bytes,
+ // 6_bytes_of_sender_AWDL_MAC_address
+
+ ptr = & bytes[beaconTypeByteIndex + 1];
+ flagsAndVersion = *ptr++;
+ memcpy(& browseHash, ptr, sizeof(serviceHash_t));
+ ptr += sizeof(serviceHash_t);
+ memcpy(& registeredHash, ptr, sizeof(serviceHash_t));
+ ptr += sizeof(serviceHash_t);
+ memcpy(& senderMAC, ptr, sizeof(senderMAC));
+
+#if VERBOSE_BLE_DEBUG
+ LogInfo("didDiscoverPeripheral: version = 0x%x, browseHash = 0x%x, registeredHash = 0x%x",
+ flagsAndVersion, browseHash, registeredHash);
+ LogInfo("didDiscoverPeripheral: sender MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ senderMAC.b[0], senderMAC.b[1], senderMAC.b[2], senderMAC.b[3], senderMAC.b[4], senderMAC.b[5]);
+#else
+ (void)flagsAndVersion; // Unused
+#endif // VERBOSE_BLE_DEBUG
+
+ responseReceived(browseHash, registeredHash, & senderMAC);
+
+#if VERBOSE_BLE_DEBUG
+ // Log every 4th package during debug
+ static int pkgsIn = 0;
+
+ if (((pkgsIn++) & 3) == 0)
+ {
+ LogInfo("0x%x 0x%x 0x%x 0x%x 0x%x", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]);
+// LogInfo("0x%x 0x%x 0x%x 0x%x 0x%x", bytes[5], bytes[6], bytes[7], bytes[9], bytes[9]);
+// LogInfo("0x%x 0x%x 0x%x 0x%x 0x%x", bytes[10], bytes[11], bytes[12], bytes[13], bytes[14]);
+// LogInfo("0x%x 0x%x 0x%x 0x%x 0x%x", bytes[15], bytes[16], bytes[17], bytes[18], bytes[19]);
+ }
+#endif // VERBOSE_BLE_DEBUG
+
+ }
+}
+
+#pragma mark - CBPeripheralManagerDelegate protocol
+
+- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
+{
+
+ switch (peripheral.state) {
+ case CBPeripheralManagerStateUnknown:
+ LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStateUnknown");
+ break;
+
+ case CBPeripheralManagerStateResetting:
+ LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStateResetting");
+ break;
+
+ case CBPeripheralManagerStateUnsupported:
+ LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStateUnsupported");
+ break;
+
+ case CBPeripheralManagerStateUnauthorized:
+ LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStateUnauthorized");
+ break;
+
+ case CBPeripheralManagerStatePoweredOff:
+ LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStatePoweredOff");
+ break;
+
+ case CBPeripheralManagerStatePoweredOn:
+ LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStatePoweredOn");
+ break;
+
+ default:
+ LogInfo("peripheralManagerDidUpdateState: Unknown state ??");
+ break;
+ }
+}
+
+- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(nullable NSError *)error
+{
+ (void) peripheral;
+
+ if (error)
+ {
+ const char * errorString = [[error localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding];
+ LogInfo("peripheralManagerDidStartAdvertising: error = %s", errorString ? errorString: "unknown");
+ }
+ else
+ {
+ LogInfo("peripheralManagerDidStartAdvertising:");
+ }
+}
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/daemon.c b/mDNSResponder/mDNSMacOSX/daemon.c
index c1cabb1a..f5478b57 100644
--- a/mDNSResponder/mDNSMacOSX/daemon.c
+++ b/mDNSResponder/mDNSMacOSX/daemon.c
@@ -30,14 +30,8 @@
#include <pthread.h>
#include <sandbox.h>
#include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
-#include <asl.h>
-#include <syslog.h>
#include <err.h>
#include <sysexits.h>
-#include <bootstrap_priv.h> // for bootstrap_check_in()
-
-#include "DNSServiceDiscoveryRequestServer.h"
-#include "DNSServiceDiscoveryReply.h"
#include "uDNS.h"
#include "DNSCommon.h"
@@ -45,35 +39,30 @@
#include "uds_daemon.h" // Interface to the server side implementation of dns_sd.h
#include "xpc_services.h" // Interface to XPC services
-
-#include "../mDNSMacOSX/DNSServiceDiscovery.h"
#include "helper.h"
#if TARGET_OS_EMBEDDED
#include "Metrics.h"
#endif
-static aslclient log_client = NULL;
-static aslmsg log_msg = NULL;
-
-// Used on iOS ONLY for reading mDNSResponder Managed Preferences Profile
-#if TARGET_OS_EMBEDDED
-#define kmDNSEnableLoggingStr CFSTR("EnableLogging")
-#define kmDNSResponderPrefIDStr "com.apple.mDNSResponder.plist"
-#define kmDNSResponderPrefID CFSTR(kmDNSResponderPrefIDStr)
+#if APPLE_OSX_mDNSResponder
+static os_log_t log_general = NULL;
#endif
// Used on OSX(10.11.x onwards) for manipulating mDNSResponder program arguments
-#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
+#if APPLE_OSX_mDNSResponder
// plist file to read the user's preferences
-#define kProgramArguments CFSTR("/Library/Preferences/com.apple.mDNSResponder.plist")
+#define kProgramArguments CFSTR("com.apple.mDNSResponder")
// possible arguments for external customers
-#define kDebugLogging CFSTR("DebugLogging")
-#define kUnicastPacketLogging CFSTR("UnicastPacketLogging")
-#define kAlwaysAppendSearchDomains CFSTR("AlwaysAppendSearchDomains")
-#define kNoMulticastAdvertisements CFSTR("NoMulticastAdvertisements")
-#define kStrictUnicastOrdering CFSTR("StrictUnicastOrdering")
+#define kPreferencesKey_DebugLogging CFSTR("DebugLogging")
+#define kPreferencesKey_UnicastPacketLogging CFSTR("UnicastPacketLogging")
+#define kPreferencesKey_AlwaysAppendSearchDomains CFSTR("AlwaysAppendSearchDomains")
+#define kPreferencesKey_NoMulticastAdvertisements CFSTR("NoMulticastAdvertisements")
+#define kPreferencesKey_StrictUnicastOrdering CFSTR("StrictUnicastOrdering")
+#define kPreferencesKey_OfferSleepProxyService CFSTR("OfferSleepProxyService")
+#define kPreferencesKey_UseInternalSleepProxy CFSTR("UseInternalSleepProxy")
+#define kPreferencesKey_EnableBLEBasedDiscovery CFSTR("EnableBLEBasedDiscovery")
#endif
//*************************************************************************************************************
@@ -91,124 +80,21 @@ static mDNS_PlatformSupport PlatformStorage;
static CacheEntity rrcachestorage[RR_CACHE_SIZE];
struct CompileTimeAssertionChecks_RR_CACHE_SIZE { char a[(RR_CACHE_SIZE >= 141) ? 1 : -1]; };
-static mach_port_t m_port = MACH_PORT_NULL;
#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
mDNSlocal void PrepareForIdle(void *m_param);
#else // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-static mach_port_t client_death_port = MACH_PORT_NULL;
static mach_port_t signal_port = MACH_PORT_NULL;
#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
static dnssd_sock_t *launchd_fds = mDNSNULL;
static size_t launchd_fds_count = 0;
-// mDNS Mach Message Timeout, in milliseconds.
-// We need this to be short enough that we don't deadlock the mDNSResponder if a client
-// fails to service its mach message queue, but long enough to give a well-written
-// client a chance to service its mach message queue without getting cut off.
-// Empirically, 50ms seems to work, so we set the timeout to 250ms to give
-// even extra-slow clients a fair chance before we cut them off.
-#define MDNS_MM_TIMEOUT 250
-
-static mDNSBool advertise = mDNS_Init_AdvertiseLocalAddresses; // By default, advertise addresses (& other records) via multicast
+static mDNSBool NoMulticastAdvertisements = mDNSfalse; // By default, advertise addresses (& other records) via multicast
extern mDNSBool StrictUnicastOrdering;
extern mDNSBool AlwaysAppendSearchDomains;
-
-//*************************************************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Active client list structures
-#endif
-
-typedef struct DNSServiceDomainEnumeration_struct DNSServiceDomainEnumeration;
-struct DNSServiceDomainEnumeration_struct
-{
- DNSServiceDomainEnumeration *next;
- mach_port_t ClientMachPort;
- DNSQuestion dom; // Question asking for domains
- DNSQuestion def; // Question asking for default domain
-};
-
-typedef struct DNSServiceBrowserResult_struct DNSServiceBrowserResult;
-struct DNSServiceBrowserResult_struct
-{
- DNSServiceBrowserResult *next;
- int resultType;
- domainname result;
-};
-
-typedef struct DNSServiceBrowser_struct DNSServiceBrowser;
-
-typedef struct DNSServiceBrowserQuestion
-{
- struct DNSServiceBrowserQuestion *next;
- DNSQuestion q;
- domainname domain;
-} DNSServiceBrowserQuestion;
-
-struct DNSServiceBrowser_struct
-{
- DNSServiceBrowser *next;
- mach_port_t ClientMachPort;
- DNSServiceBrowserQuestion *qlist;
- DNSServiceBrowserResult *results;
- mDNSs32 lastsuccess;
- mDNSBool DefaultDomain; // was the browse started on an explicit domain?
- domainname type; // registration type
-};
-
-typedef struct DNSServiceResolver_struct DNSServiceResolver;
-struct DNSServiceResolver_struct
-{
- DNSServiceResolver *next;
- mach_port_t ClientMachPort;
- ServiceInfoQuery q;
- ServiceInfo i;
- mDNSs32 ReportTime;
-};
-
-// A single registered service: ServiceRecordSet + bookkeeping
-// Note that we duplicate some fields from parent DNSServiceRegistration object
-// to facilitate cleanup, when instances and parent may be deallocated at different times.
-typedef struct ServiceInstance
-{
- struct ServiceInstance *next;
- mach_port_t ClientMachPort;
- mDNSBool autoname; // Set if this name is tied to the Computer Name
- mDNSBool renameonmemfree; // Set if we just got a name conflict and now need to automatically pick a new name
- domainlabel name;
- domainname domain;
- ServiceRecordSet srs;
- // Don't add any fields after ServiceRecordSet.
- // This is where the implicit extra space goes if we allocate an oversized ServiceRecordSet object
-} ServiceInstance;
-
-// A client-created service. May reference several ServiceInstance objects if default
-// settings cause registration in multiple domains.
-typedef struct DNSServiceRegistration
-{
- struct DNSServiceRegistration *next;
- mach_port_t ClientMachPort;
- mDNSBool DefaultDomain;
- mDNSBool autoname;
- size_t rdsize;
- int NumSubTypes;
- char regtype[MAX_ESCAPED_DOMAIN_NAME]; // for use in AllocateSubtypes
- domainlabel name; // used only if autoname is false
- domainname type;
- mDNSIPPort port;
- unsigned char txtinfo[1024];
- size_t txt_len;
- uint32_t NextRef;
- ServiceInstance *regs;
-} DNSServiceRegistration;
-
-static DNSServiceDomainEnumeration *DNSServiceDomainEnumerationList = NULL;
-static DNSServiceBrowser *DNSServiceBrowserList = NULL;
-static DNSServiceResolver *DNSServiceResolverList = NULL;
-static DNSServiceRegistration *DNSServiceRegistrationList = NULL;
+extern mDNSBool EnableBLEBasedDiscovery;
// We keep a list of client-supplied event sources in KQSocketEventSource records
typedef struct KQSocketEventSource
@@ -230,15 +116,12 @@ static KQSocketEventSource *gEventSources;
char _malloc_options[] = "AXZ";
-mDNSlocal void validatelists(mDNS *const m, bool checkCRActiveQuestion)
+mDNSlocal void validatelists(mDNS *const m)
{
-#if TARGET_OS_WATCH
+#if BONJOUR_ON_DEMAND
mDNSu32 NumAllInterfaceRecords = 0;
mDNSu32 NumAllInterfaceQuestions = 0;
-#else
- mDNSu32 NumAllInterfaceRecords = 1;
- mDNSu32 NumAllInterfaceQuestions = 1;
-#endif
+#endif // BONJOUR_ON_DEMAND
// Check local lists
KQSocketEventSource *k;
@@ -246,27 +129,6 @@ mDNSlocal void validatelists(mDNS *const m, bool checkCRActiveQuestion)
if (k->next == (KQSocketEventSource *)~0 || k->fd < 0)
LogMemCorruption("gEventSources: %p is garbage (%d)", k, k->fd);
- // Check Mach client lists
- DNSServiceDomainEnumeration *e;
- for (e = DNSServiceDomainEnumerationList; e; e=e->next)
- if (e->next == (DNSServiceDomainEnumeration *)~0 || e->ClientMachPort == 0 || e->ClientMachPort == (mach_port_t) ~0)
- LogMemCorruption("DNSServiceDomainEnumerationList: %p is garbage (%X)", e, e->ClientMachPort);
-
- DNSServiceBrowser *b;
- for (b = DNSServiceBrowserList; b; b=b->next)
- if (b->next == (DNSServiceBrowser *)~0 || b->ClientMachPort == 0 || b->ClientMachPort == (mach_port_t) ~0)
- LogMemCorruption("DNSServiceBrowserList: %p is garbage (%X)", b, b->ClientMachPort);
-
- DNSServiceResolver *l;
- for (l = DNSServiceResolverList; l; l=l->next)
- if (l->next == (DNSServiceResolver *)~0 || l->ClientMachPort == 0 || l->ClientMachPort == (mach_port_t) ~0)
- LogMemCorruption("DNSServiceResolverList: %p is garbage (%X)", l, l->ClientMachPort);
-
- DNSServiceRegistration *r;
- for (r = DNSServiceRegistrationList; r; r=r->next)
- if (r->next == (DNSServiceRegistration *)~0 || r->ClientMachPort == 0 || r->ClientMachPort == (mach_port_t) ~0)
- LogMemCorruption("DNSServiceRegistrationList: %p is garbage (%X)", r, r->ClientMachPort);
-
// Check Unix Domain Socket client lists (uds_daemon.c)
uds_validatelists();
@@ -279,14 +141,18 @@ mDNSlocal void validatelists(mDNS *const m, bool checkCRActiveQuestion)
if (rr->resrec.name != &rr->namestorage)
LogMemCorruption("ResourceRecords list: %p name %p does not point to namestorage %p %##s",
rr, rr->resrec.name->c, rr->namestorage.c, rr->namestorage.c);
+#if BONJOUR_ON_DEMAND
if (!AuthRecord_uDNS(rr) && !RRLocalOnly(rr)) NumAllInterfaceRecords++;
+#endif // BONJOUR_ON_DEMAND
}
for (rr = m->DuplicateRecords; rr; rr=rr->next)
{
if (rr->next == (AuthRecord *)~0 || rr->resrec.RecordType == 0 || rr->resrec.RecordType == 0xFF)
LogMemCorruption("DuplicateRecords list: %p is garbage (%X)", rr, rr->resrec.RecordType);
+#if BONJOUR_ON_DEMAND
if (!AuthRecord_uDNS(rr) && !RRLocalOnly(rr)) NumAllInterfaceRecords++;
+#endif // BONJOUR_ON_DEMAND
}
rr = m->NewLocalRecords;
@@ -304,23 +170,25 @@ mDNSlocal void validatelists(mDNS *const m, bool checkCRActiveQuestion)
{
if (q->next == (DNSQuestion*)~0 || q->ThisQInterval == (mDNSs32) ~0)
LogMemCorruption("Questions list: %p is garbage (%lX %p)", q, q->ThisQInterval, q->next);
- if (q->InterfaceID != mDNSInterface_LocalOnly && q->InterfaceID != mDNSInterface_P2P && mDNSOpaque16IsZero(q->TargetQID))
+ if (q->DuplicateOf && q->LocalSocket)
+ LogMemCorruption("Questions list: Duplicate Question %p should not have LocalSocket set %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
+#if BONJOUR_ON_DEMAND
+ if (!LocalOnlyOrP2PInterface(q->InterfaceID) && mDNSOpaque16IsZero(q->TargetQID))
NumAllInterfaceQuestions++;
+#endif // BONJOUR_ON_DEMAND
}
- if (checkCRActiveQuestion) {
- CacheGroup *cg;
- CacheRecord *cr;
- mDNSu32 slot;
- FORALL_CACHERECORDS(slot, cg, cr)
+ CacheGroup *cg;
+ CacheRecord *cr;
+ mDNSu32 slot;
+ FORALL_CACHERECORDS(slot, cg, cr)
+ {
+ if (cr->resrec.RecordType == 0 || cr->resrec.RecordType == 0xFF)
+ LogMemCorruption("Cache slot %lu: %p is garbage (%X)", slot, cr, cr->resrec.RecordType);
+ if (cr->CRActiveQuestion)
{
- if (cr->resrec.RecordType == 0 || cr->resrec.RecordType == 0xFF)
- LogMemCorruption("Cache slot %lu: %p is garbage (%X)", slot, cr, cr->resrec.RecordType);
- if (cr->CRActiveQuestion)
- {
- for (q = m->Questions; q; q=q->next) if (q == cr->CRActiveQuestion) break;
- if (!q) LogMemCorruption("Cache slot %lu: CRActiveQuestion %p not in m->Questions list %s", slot, cr->CRActiveQuestion, CRDisplayString(m, cr));
- }
+ for (q = m->Questions; q; q=q->next) if (q == cr->CRActiveQuestion) break;
+ if (!q) LogMemCorruption("Cache slot %lu: CRActiveQuestion %p not in m->Questions list %s", slot, cr->CRActiveQuestion, CRDisplayString(m, cr));
}
}
@@ -338,13 +206,13 @@ mDNSlocal void validatelists(mDNS *const m, bool checkCRActiveQuestion)
if (t->next == (ClientTunnel *)~0 || t->dstname.c[0] > 63)
LogMemCorruption("m->TunnelClients: %p is garbage (%d)", t, t->dstname.c[0]);
-#if TARGET_OS_WATCH
+#if BONJOUR_ON_DEMAND
if (m->NumAllInterfaceRecords != NumAllInterfaceRecords)
LogMemCorruption("NumAllInterfaceRecords is %d should be %d", m->NumAllInterfaceRecords, NumAllInterfaceRecords);
if (m->NumAllInterfaceQuestions != NumAllInterfaceQuestions)
LogMemCorruption("NumAllInterfaceQuestions is %d should be %d", m->NumAllInterfaceQuestions, NumAllInterfaceQuestions);
-#endif
+#endif // BONJOUR_ON_DEMAND
}
mDNSexport void *mallocL(char *msg, unsigned int size)
@@ -361,7 +229,7 @@ mDNSexport void *mallocL(char *msg, unsigned int size)
mem[1] = size;
//mDNSPlatformMemZero(&mem[2], size);
memset(&mem[2], 0xFF, size);
- validatelists(&mDNSStorage, true);
+ validatelists(&mDNSStorage);
return(&mem[2]);
}
}
@@ -379,7 +247,7 @@ mDNSexport void freeL(char *msg, void *x)
else if (MACOSX_MDNS_MALLOC_DEBUGGING >= 2) LogMsg("free( %s : %ld @ %p)", msg, mem[1], &mem[2]);
mem[0] = 0xDEADDEAD;
memset(mem+2, 0xFF, mem[1]);
- validatelists(&mDNSStorage, false);
+ validatelists(&mDNSStorage);
free(mem);
}
}
@@ -387,610 +255,6 @@ mDNSexport void freeL(char *msg, void *x)
#endif
//*************************************************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Mach client request handlers
-#endif
-
-//*************************************************************************************************************
-// Client Death Detection
-
-// This gets called after ALL constituent records of the Service Record Set have been deregistered
-mDNSlocal void FreeServiceInstance(ServiceInstance *x)
-{
- ServiceRecordSet *s = &x->srs;
- ExtraResourceRecord *e = x->srs.Extras, *tmp;
-
- while (e)
- {
- e->r.RecordContext = e;
- tmp = e;
- e = e->next;
- FreeExtraRR(&mDNSStorage, &tmp->r, mStatus_MemFree);
- }
-
- if (s->RR_TXT.resrec.rdata != &s->RR_TXT.rdatastorage)
- freeL("TXT RData", s->RR_TXT.resrec.rdata);
-
- if (s->SubTypes) freeL("ServiceSubTypes", s->SubTypes);
- freeL("ServiceInstance", x);
-}
-
-// AbortClient finds whatever client is identified by the given Mach port,
-// stops whatever operation that client was doing, and frees its memory.
-// In the case of a service registration, the actual freeing may be deferred
-// until we get the mStatus_MemFree message, if necessary
-mDNSlocal void AbortClient(mach_port_t ClientMachPort, void *m)
-{
- DNSServiceDomainEnumeration **e = &DNSServiceDomainEnumerationList;
- DNSServiceBrowser **b = &DNSServiceBrowserList;
- DNSServiceResolver **l = &DNSServiceResolverList;
- DNSServiceRegistration **r = &DNSServiceRegistrationList;
-
- while (*e && (*e)->ClientMachPort != ClientMachPort) e = &(*e)->next;
- if (*e)
- {
- DNSServiceDomainEnumeration *x = *e;
- *e = (*e)->next;
- if (m && m != x)
- LogMsg("%5d: DNSServiceDomainEnumeration(%##s) STOP; WARNING m %p != x %p", ClientMachPort, x->dom.qname.c, m, x);
- else LogOperation("%5d: DNSServiceDomainEnumeration(%##s) STOP", ClientMachPort, x->dom.qname.c);
- mDNS_StopGetDomains(&mDNSStorage, &x->dom);
- mDNS_StopGetDomains(&mDNSStorage, &x->def);
- freeL("DNSServiceDomainEnumeration", x);
- return;
- }
-
- while (*b && (*b)->ClientMachPort != ClientMachPort) b = &(*b)->next;
- if (*b)
- {
- DNSServiceBrowser *x = *b;
- DNSServiceBrowserQuestion *freePtr, *qptr = x->qlist;
- *b = (*b)->next;
- while (qptr)
- {
- if (m && m != x)
- LogMsg("%5d: DNSServiceBrowse(%##s) STOP; WARNING m %p != x %p", ClientMachPort, qptr->q.qname.c, m, x);
- else LogOperation("%5d: DNSServiceBrowse(%##s) STOP", ClientMachPort, qptr->q.qname.c);
- mDNS_StopBrowse(&mDNSStorage, &qptr->q);
- freePtr = qptr;
- qptr = qptr->next;
- freeL("DNSServiceBrowserQuestion", freePtr);
- }
- while (x->results)
- {
- DNSServiceBrowserResult *t = x->results;
- x->results = x->results->next;
- freeL("DNSServiceBrowserResult", t);
- }
- freeL("DNSServiceBrowser", x);
- return;
- }
-
- while (*l && (*l)->ClientMachPort != ClientMachPort) l = &(*l)->next;
- if (*l)
- {
- DNSServiceResolver *x = *l;
- *l = (*l)->next;
- if (m && m != x)
- LogMsg("%5d: DNSServiceResolve(%##s) STOP; WARNING m %p != x %p", ClientMachPort, x->i.name.c, m, x);
- else LogOperation("%5d: DNSServiceResolve(%##s) STOP", ClientMachPort, x->i.name.c);
- mDNS_StopResolveService(&mDNSStorage, &x->q);
- freeL("DNSServiceResolver", x);
- return;
- }
-
- while (*r && (*r)->ClientMachPort != ClientMachPort) r = &(*r)->next;
- if (*r)
- {
- ServiceInstance *si = NULL;
- DNSServiceRegistration *x = *r;
- *r = (*r)->next;
-
- si = x->regs;
- while (si)
- {
- ServiceInstance *instance = si;
- si = si->next;
- instance->renameonmemfree = mDNSfalse;
- if (m && m != x) LogMsg("%5d: DNSServiceRegistration(%##s, %u) STOP; WARNING m %p != x %p", ClientMachPort, instance->srs.RR_SRV.resrec.name->c, SRS_PORT(&instance->srs), m, x);
- else LogOperation("%5d: DNSServiceRegistration(%##s, %u) STOP", ClientMachPort, instance->srs.RR_SRV.resrec.name->c, SRS_PORT(&instance->srs));
-
- // If mDNS_DeregisterService() returns mStatus_NoError, that means that the service was found in the list,
- // is sending its goodbye packet, and we'll get an mStatus_MemFree message when we can free the memory.
- // If mDNS_DeregisterService() returns an error, it means that the service had already been removed from
- // the list, so we should go ahead and free the memory right now
- if (mDNS_DeregisterService(&mDNSStorage, &instance->srs)) FreeServiceInstance(instance); // FreeServiceInstance invalidates pointer
- }
- x->regs = NULL;
- freeL("DNSServiceRegistration", x);
- return;
- }
-
- LogMsg("%5d: died or deallocated, but no record of client can be found!", ClientMachPort);
-}
-
-#define AbortBlockedClient(C,MSG,M) AbortClientWithLogMessage((C), "stopped accepting Mach messages", " (" MSG ")", (M))
-
-mDNSlocal void AbortClientWithLogMessage(mach_port_t c, char *reason, char *msg, void *m)
-{
- DNSServiceDomainEnumeration *e = DNSServiceDomainEnumerationList;
- DNSServiceBrowser *b = DNSServiceBrowserList;
- DNSServiceResolver *l = DNSServiceResolverList;
- DNSServiceRegistration *r = DNSServiceRegistrationList;
- DNSServiceBrowserQuestion *qptr;
-
- while (e && e->ClientMachPort != c) e = e->next;
- while (b && b->ClientMachPort != c) b = b->next;
- while (l && l->ClientMachPort != c) l = l->next;
- while (r && r->ClientMachPort != c) r = r->next;
-
- if (e) LogMsg("%5d: DomainEnumeration(%##s) %s%s", c, e->dom.qname.c, reason, msg);
- else if (b)
- {
- for (qptr = b->qlist; qptr; qptr = qptr->next)
- LogMsg("%5d: Browser(%##s) %s%s", c, qptr->q.qname.c, reason, msg);
- }
- else if (l) LogMsg("%5d: Resolver(%##s) %s%s", c, l->i.name.c, reason, msg);
- else if (r)
- {
- ServiceInstance *si;
- for (si = r->regs; si; si = si->next)
- LogMsg("%5d: Registration(%##s) %s%s", c, si->srs.RR_SRV.resrec.name->c, reason, msg);
- }
- else LogMsg("%5d: (%s) %s, but no record of client can be found!", c, reason, msg);
-
- AbortClient(c, m);
-}
-
-mDNSlocal mDNSBool CheckForExistingClient(mach_port_t c)
-{
- DNSServiceDomainEnumeration *e = DNSServiceDomainEnumerationList;
- DNSServiceBrowser *b = DNSServiceBrowserList;
- DNSServiceResolver *l = DNSServiceResolverList;
- DNSServiceRegistration *r = DNSServiceRegistrationList;
- DNSServiceBrowserQuestion *qptr;
-
- while (e && e->ClientMachPort != c) e = e->next;
- while (b && b->ClientMachPort != c) b = b->next;
- while (l && l->ClientMachPort != c) l = l->next;
- while (r && r->ClientMachPort != c) r = r->next;
- if (e) LogMsg("%5d: DomainEnumeration(%##s) already exists!", c, e->dom.qname.c);
- if (b)
- {
- for (qptr = b->qlist; qptr; qptr = qptr->next)
- LogMsg("%5d: Browser(%##s) already exists!", c, qptr->q.qname.c);
- }
- if (l) LogMsg("%5d: Resolver(%##s) already exists!", c, l->i.name.c);
- if (r) LogMsg("%5d: Registration(%##s) already exists!", c, r->regs ? r->regs->srs.RR_SRV.resrec.name->c : NULL);
- return(e || b || l || r);
-}
-
-#ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-mDNSlocal void ClientDeathCallback(CFMachPortRef unusedport, void *voidmsg, CFIndex size, void *info)
-{
- KQueueLock(&mDNSStorage);
- mach_msg_header_t *msg = (mach_msg_header_t *)voidmsg;
- (void)unusedport; // Unused
- (void)size; // Unused
- (void)info; // Unused
- if (msg->msgh_id == MACH_NOTIFY_DEAD_NAME)
- {
- const mach_dead_name_notification_t *const deathMessage = (mach_dead_name_notification_t *)msg;
- AbortClient(deathMessage->not_port, NULL);
-
- /* Deallocate the send right that came in the dead name notification */
- mach_port_destroy(mach_task_self(), deathMessage->not_port);
- }
- KQueueUnlock(&mDNSStorage, "Mach AbortClient");
-}
-
-#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-mDNSlocal void EnableDeathNotificationForClient(mach_port_t ClientMachPort, void *m)
-{
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
- dispatch_source_t mach_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_SEND, ClientMachPort, 0, dispatch_get_main_queue());
- if (mach_source == mDNSNULL)
- {
- AbortClientWithLogMessage(ClientMachPort, "died/deallocated before we could enable death notification", "", m);
- return;
- }
- dispatch_source_set_event_handler(mach_source, ^{
- mach_port_destroy(mach_task_self(), ClientMachPort);
- });
- dispatch_resume(mach_source);
-#else // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
- mach_port_t prev;
- kern_return_t r = mach_port_request_notification(mach_task_self(), ClientMachPort, MACH_NOTIFY_DEAD_NAME, 0,
- client_death_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &prev);
- // If the port already died while we were thinking about it, then abort the operation right away
- if (r != KERN_SUCCESS)
- AbortClientWithLogMessage(ClientMachPort, "died/deallocated before we could enable death notification", "", m);
-#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-}
-
-//*************************************************************************************************************
-// Domain Enumeration
-
-mDNSlocal void DomainEnumFound(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
- kern_return_t status;
- char buffer[MAX_ESCAPED_DOMAIN_NAME];
- DNSServiceDomainEnumerationReplyResultType rt;
- DNSServiceDomainEnumeration *x = (DNSServiceDomainEnumeration *)question->QuestionContext;
- (void)m; // Unused
-
- debugf("DomainEnumFound: %##s PTR %##s", answer->name->c, answer->rdata->u.name.c);
- if (answer->rrtype != kDNSType_PTR) return;
- if (!x) { debugf("DomainEnumFound: DNSServiceDomainEnumeration is NULL"); return; }
-
- if (AddRecord)
- {
- if (question == &x->dom) rt = DNSServiceDomainEnumerationReplyAddDomain;
- else rt = DNSServiceDomainEnumerationReplyAddDomainDefault;
- }
- else
- {
- if (question == &x->dom) rt = DNSServiceDomainEnumerationReplyRemoveDomain;
- else return;
- }
-
- LogOperation("%5d: DNSServiceDomainEnumeration(%##s) %##s %s",
- x->ClientMachPort, x->dom.qname.c, answer->rdata->u.name.c,
- !AddRecord ? "RemoveDomain" :
- question == &x->dom ? "AddDomain" : "AddDomainDefault");
-
- ConvertDomainNameToCString(&answer->rdata->u.name, buffer);
- status = DNSServiceDomainEnumerationReply_rpc(x->ClientMachPort, rt, buffer, 0, MDNS_MM_TIMEOUT);
- if (status == MACH_SEND_TIMED_OUT)
- AbortBlockedClient(x->ClientMachPort, "enumeration", x);
-}
-
-mDNSexport kern_return_t provide_DNSServiceDomainEnumerationCreate_rpc(mach_port_t unusedserver, mach_port_t client,
- int regDom)
-{
- // Check client parameter
- (void)unusedserver; // Unused
- mStatus err = mStatus_NoError;
- const char *errormsg = "Unknown";
- if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; }
- if (CheckForExistingClient(client)) { err = mStatus_Invalid; errormsg = "Client id already in use"; goto fail; }
-
- mDNS_DomainType dt1 = regDom ? mDNS_DomainTypeRegistration : mDNS_DomainTypeBrowse;
- mDNS_DomainType dt2 = regDom ? mDNS_DomainTypeRegistrationDefault : mDNS_DomainTypeBrowseDefault;
-
- // Allocate memory, and handle failure
- DNSServiceDomainEnumeration *x = mallocL("DNSServiceDomainEnumeration", sizeof(*x));
- if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
-
- // Set up object, and link into list
- x->ClientMachPort = client;
- x->next = DNSServiceDomainEnumerationList;
- DNSServiceDomainEnumerationList = x;
-
- verbosedebugf("%5d: Enumerate %s Domains", client, regDom ? "Registration" : "Browsing");
-
- // Do the operation
- err = mDNS_GetDomains(&mDNSStorage, &x->dom, dt1, NULL, mDNSInterface_LocalOnly, DomainEnumFound, x);
- if (!err) err = mDNS_GetDomains(&mDNSStorage, &x->def, dt2, NULL, mDNSInterface_LocalOnly, DomainEnumFound, x);
- if (err) { AbortClient(client, x); errormsg = "mDNS_GetDomains"; goto fail; }
-
- // Succeeded: Wrap up and return
- LogOperation("%5d: DNSServiceDomainEnumeration(%##s) START", client, x->dom.qname.c);
- EnableDeathNotificationForClient(client, x);
- return(mStatus_NoError);
-
-fail:
- LogMsg("%5d: DNSServiceDomainEnumeration(%d) failed: %s (%d)", client, regDom, errormsg, err);
- return(err);
-}
-
-//*************************************************************************************************************
-// Browse for services
-
-mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
- (void)m; // Unused
-
- if (answer->rrtype != kDNSType_PTR)
- { LogMsg("FoundInstance: Should not be called with rrtype %d (not a PTR record)", answer->rrtype); return; }
-
- domainlabel name;
- domainname type, domain;
- if (!DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain))
- {
- LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
- answer->name->c, answer->rdata->u.name.c);
- return;
- }
-
- DNSServiceBrowserResult *x = mallocL("DNSServiceBrowserResult", sizeof(*x));
- if (!x) { LogMsg("FoundInstance: Failed to allocate memory for result %##s", answer->rdata->u.name.c); return; }
-
- verbosedebugf("FoundInstance: %s %##s", AddRecord ? "Add" : "Rmv", answer->rdata->u.name.c);
- AssignDomainName(&x->result, &answer->rdata->u.name);
- if (AddRecord)
- x->resultType = DNSServiceBrowserReplyAddInstance;
- else x->resultType = DNSServiceBrowserReplyRemoveInstance;
- x->next = NULL;
-
- DNSServiceBrowser *browser = (DNSServiceBrowser *)question->QuestionContext;
- DNSServiceBrowserResult **p = &browser->results;
- while (*p) p = &(*p)->next;
- *p = x;
-
- LogOperation("%5d: DNSServiceBrowse(%##s, %s) RESULT %s %s",
- browser->ClientMachPort, question->qname.c, DNSTypeName(question->qtype), AddRecord ? "Add" : "Rmv", RRDisplayString(m, answer));
-}
-
-mDNSlocal mStatus AddDomainToBrowser(DNSServiceBrowser *browser, const domainname *d)
-{
- mStatus err = mStatus_NoError;
- DNSServiceBrowserQuestion *ptr, *question = NULL;
-
- for (ptr = browser->qlist; ptr; ptr = ptr->next)
- {
- if (SameDomainName(&ptr->q.qname, d))
- { debugf("Domain %##s already contained in browser", d->c); return mStatus_AlreadyRegistered; }
- }
-
- question = mallocL("DNSServiceBrowserQuestion", sizeof(DNSServiceBrowserQuestion));
- if (!question) { LogMsg("Error: malloc"); return mStatus_NoMemoryErr; }
- AssignDomainName(&question->domain, d);
- question->next = browser->qlist;
- LogOperation("%5d: DNSServiceBrowse(%##s%##s) START", browser->ClientMachPort, browser->type.c, d->c);
- err = mDNS_StartBrowse(&mDNSStorage, &question->q, &browser->type, d, mDNSNULL, mDNSInterface_Any, 0, mDNSfalse, mDNSfalse, FoundInstance, browser);
- if (!err)
- browser->qlist = question;
- else
- {
- LogMsg("Error: AddDomainToBrowser: mDNS_StartBrowse %d", err);
- freeL("DNSServiceBrowserQuestion", question);
- }
- return err;
-}
-
-mDNSexport void machserver_automatic_browse_domain_changed(const domainname *d, mDNSBool add)
-{
- DNSServiceBrowser *ptr;
- for (ptr = DNSServiceBrowserList; ptr; ptr = ptr->next)
- {
- if (ptr->DefaultDomain)
- {
- if (add)
- {
- mStatus err = AddDomainToBrowser(ptr, d);
- if (err && err != mStatus_AlreadyRegistered) LogMsg("Default browse in domain %##s for client %5d failed. Continuing", d, ptr->ClientMachPort);
- }
- else
- {
- DNSServiceBrowserQuestion **q = &ptr->qlist;
- while (*q)
- {
- if (SameDomainName(&(*q)->domain, d))
- {
- DNSServiceBrowserQuestion *rem = *q;
- *q = (*q)->next;
- mDNS_StopQueryWithRemoves(&mDNSStorage, &rem->q);
- freeL("DNSServiceBrowserQuestion", rem);
- return;
- }
- q = &(*q)->next;
- }
- LogMsg("Requested removal of default domain %##s not in client %5d's list", d->c, ptr->ClientMachPort);
- }
- }
- }
-}
-
-mDNSexport kern_return_t provide_DNSServiceBrowserCreate_rpc(mach_port_t unusedserver, mach_port_t client,
- DNSCString regtype, DNSCString domain)
-{
- // Check client parameter
- (void)unusedserver; // Unused
- mStatus err = mStatus_NoError;
- const char *errormsg = "Unknown";
-
- if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; }
- if (CheckForExistingClient(client)) { err = mStatus_Invalid; errormsg = "Client id already in use"; goto fail; }
-
- // Check other parameters
- domainname t, d;
- t.c[0] = 0;
- mDNSs32 NumSubTypes = ChopSubTypes(regtype, mDNSNULL); // Note: Modifies regtype string to remove trailing subtypes
- if (NumSubTypes < 0 || NumSubTypes > 1) { errormsg = "Bad Service SubType"; goto badparam; }
- if (NumSubTypes == 1 && !AppendDNSNameString(&t, regtype + strlen(regtype) + 1))
- { errormsg = "Bad Service SubType"; goto badparam; }
- if (!regtype[0] || !AppendDNSNameString(&t, regtype)) { errormsg = "Illegal regtype"; goto badparam; }
- domainname temp;
- if (!MakeDomainNameFromDNSNameString(&temp, regtype)) { errormsg = "Illegal regtype"; goto badparam; }
- if (temp.c[0] > 15 && (!domain || domain[0] == 0)) domain = "local."; // For over-long service types, we only allow domain "local"
-
- // Allocate memory, and handle failure
- DNSServiceBrowser *x = mallocL("DNSServiceBrowser", sizeof(*x));
- if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
-
- // Set up object, and link into list
- AssignDomainName(&x->type, &t);
- x->ClientMachPort = client;
- x->results = NULL;
- x->lastsuccess = 0;
- x->qlist = NULL;
- x->next = DNSServiceBrowserList;
- DNSServiceBrowserList = x;
-
- if (domain[0])
- {
- // Start browser for an explicit domain
- x->DefaultDomain = mDNSfalse;
- if (!MakeDomainNameFromDNSNameString(&d, domain)) { errormsg = "Illegal domain"; goto badparam; }
- err = AddDomainToBrowser(x, &d);
- if (err) { AbortClient(client, x); errormsg = "AddDomainToBrowser"; goto fail; }
- }
- else
- {
- DNameListElem *sdPtr;
- // Start browser on all domains
- x->DefaultDomain = mDNStrue;
- if (!AutoBrowseDomains) { AbortClient(client, x); errormsg = "GetSearchDomainList"; goto fail; }
- for (sdPtr = AutoBrowseDomains; sdPtr; sdPtr = sdPtr->next)
- {
- err = AddDomainToBrowser(x, &sdPtr->name);
- if (err)
- {
- // only terminally bail if .local fails
- if (!SameDomainName(&localdomain, &sdPtr->name))
- LogMsg("Default browse in domain %##s failed. Continuing", sdPtr->name.c);
- else { AbortClient(client, x); errormsg = "AddDomainToBrowser"; goto fail; }
- }
- }
- }
-
- // Succeeded: Wrap up and return
- EnableDeathNotificationForClient(client, x);
- return(mStatus_NoError);
-
-badparam:
- err = mStatus_BadParamErr;
-fail:
- LogMsg("%5d: DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%d)", client, regtype, domain, errormsg, err);
- return(err);
-}
-
-//*************************************************************************************************************
-// Resolve Service Info
-
-mDNSlocal void FoundInstanceInfo(mDNS *const m, ServiceInfoQuery *query)
-{
- kern_return_t status;
- DNSServiceResolver *x = (DNSServiceResolver *)query->ServiceInfoQueryContext;
- NetworkInterfaceInfoOSX *ifx = IfindexToInterfaceInfoOSX(m, query->info->InterfaceID);
- if (query->info->InterfaceID == mDNSInterface_LocalOnly || query->info->InterfaceID == mDNSInterface_P2P) ifx = mDNSNULL;
- struct sockaddr_storage interface;
- struct sockaddr_storage address;
- char cstring[1024];
- int i, pstrlen = query->info->TXTinfo[0];
- (void)m; // Unused
-
- //debugf("FoundInstanceInfo %.4a %.4a %##s", &query->info->InterfaceAddr, &query->info->ip, &query->info->name);
-
- if (query->info->TXTlen > sizeof(cstring)) return;
-
- mDNSPlatformMemZero(&interface, sizeof(interface));
- mDNSPlatformMemZero(&address, sizeof(address));
-
- if (ifx && ifx->ifinfo.ip.type == mDNSAddrType_IPv4)
- {
- struct sockaddr_in *s = (struct sockaddr_in*)&interface;
- s->sin_len = sizeof(*s);
- s->sin_family = AF_INET;
- s->sin_port = 0;
- s->sin_addr.s_addr = ifx->ifinfo.ip.ip.v4.NotAnInteger;
- }
- else if (ifx && ifx->ifinfo.ip.type == mDNSAddrType_IPv6)
- {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&interface;
- sin6->sin6_len = sizeof(*sin6);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_flowinfo = 0;
- sin6->sin6_port = 0;
- sin6->sin6_addr = *(struct in6_addr*)&ifx->ifinfo.ip.ip.v6;
- sin6->sin6_scope_id = ifx->scope_id;
- }
-
- if (query->info->ip.type == mDNSAddrType_IPv4)
- {
- struct sockaddr_in *s = (struct sockaddr_in*)&address;
- s->sin_len = sizeof(*s);
- s->sin_family = AF_INET;
- s->sin_port = query->info->port.NotAnInteger;
- s->sin_addr.s_addr = query->info->ip.ip.v4.NotAnInteger;
- }
- else
- {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&address;
- sin6->sin6_len = sizeof(*sin6);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = query->info->port.NotAnInteger;
- sin6->sin6_flowinfo = 0;
- sin6->sin6_addr = *(struct in6_addr*)&query->info->ip.ip.v6;
- sin6->sin6_scope_id = ifx ? ifx->scope_id : 0;
- }
-
- // The OS X DNSServiceResolverResolve() API is defined using a C-string,
- // but the mDNS_StartResolveService() call actually returns a packed block of P-strings.
- // Hence we have to convert the P-string(s) to a C-string before returning the result to the client.
- // ASCII-1 characters are used in the C-string as boundary markers,
- // to indicate the boundaries between the original constituent P-strings.
- for (i=1; i<query->info->TXTlen; i++)
- {
- if (--pstrlen >= 0)
- cstring[i-1] = query->info->TXTinfo[i];
- else
- {
- cstring[i-1] = 1;
- pstrlen = query->info->TXTinfo[i];
- }
- }
- cstring[i-1] = 0; // Put the terminating NULL on the end
-
- LogOperation("%5d: DNSServiceResolver(%##s) -> %#a:%u", x->ClientMachPort,
- x->i.name.c, &query->info->ip, mDNSVal16(query->info->port));
- status = DNSServiceResolverReply_rpc(x->ClientMachPort,
- (char*)&interface, (char*)&address, cstring, 0, MDNS_MM_TIMEOUT);
- if (status == MACH_SEND_TIMED_OUT)
- AbortBlockedClient(x->ClientMachPort, "resolve", x);
-}
-
-mDNSexport kern_return_t provide_DNSServiceResolverResolve_rpc(mach_port_t unusedserver, mach_port_t client,
- DNSCString name, DNSCString regtype, DNSCString domain)
-{
- // Check client parameter
- (void)unusedserver; // Unused
- mStatus err = mStatus_NoError;
- const char *errormsg = "Unknown";
- if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; }
- if (CheckForExistingClient(client)) { err = mStatus_Invalid; errormsg = "Client id already in use"; goto fail; }
-
- // Check other parameters
- domainlabel n;
- domainname t, d, srv;
- if (!name[0] || !MakeDomainLabelFromLiteralString(&n, name)) { errormsg = "Bad Instance Name"; goto badparam; }
- if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Bad Service Type"; goto badparam; }
- if (!domain[0] || !MakeDomainNameFromDNSNameString(&d, domain)) { errormsg = "Bad Domain"; goto badparam; }
- if (!ConstructServiceName(&srv, &n, &t, &d)) { errormsg = "Bad Name"; goto badparam; }
-
- // Allocate memory, and handle failure
- DNSServiceResolver *x = mallocL("DNSServiceResolver", sizeof(*x));
- if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
-
- // Set up object, and link into list
- x->ClientMachPort = client;
- x->i.InterfaceID = mDNSInterface_Any;
- x->i.name = srv;
- x->ReportTime = NonZeroTime(mDNS_TimeNow(&mDNSStorage) + 130 * mDNSPlatformOneSecond);
- x->next = DNSServiceResolverList;
- DNSServiceResolverList = x;
-
- // Do the operation
- LogOperation("%5d: DNSServiceResolve(%##s) START", client, x->i.name.c);
- err = mDNS_StartResolveService(&mDNSStorage, &x->q, &x->i, FoundInstanceInfo, x);
- if (err) { AbortClient(client, x); errormsg = "mDNS_StartResolveService"; goto fail; }
-
- // Succeeded: Wrap up and return
- EnableDeathNotificationForClient(client, x);
- return(mStatus_NoError);
-
-badparam:
- err = mStatus_BadParamErr;
-fail:
- LogMsg("%5d: DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%d)", client, name, regtype, domain, errormsg, err);
- return(err);
-}
-
-//*************************************************************************************************************
// Registration
mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
@@ -998,274 +262,6 @@ mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
m->p->NotifyUser = NonZeroTime(m->timenow + delay);
}
-mDNSlocal void RegCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus result)
-{
- ServiceInstance *si = (ServiceInstance*)srs->ServiceContext;
-
- if (result == mStatus_NoError)
- {
- kern_return_t status;
- LogOperation("%5d: DNSServiceRegistration(%##s, %u) Name Registered", si->ClientMachPort, srs->RR_SRV.resrec.name->c, SRS_PORT(srs));
- status = DNSServiceRegistrationReply_rpc(si->ClientMachPort, result, MDNS_MM_TIMEOUT);
- if (status == MACH_SEND_TIMED_OUT)
- AbortBlockedClient(si->ClientMachPort, "registration success", si);
- if (si->autoname && CountPeerRegistrations(m, srs) == 0)
- RecordUpdatedNiceLabel(m, 0); // Successfully got new name, tell user immediately
- }
-
- else if (result == mStatus_NameConflict)
- {
- LogOperation("%5d: DNSServiceRegistration(%##s, %u) Name Conflict", si->ClientMachPort, srs->RR_SRV.resrec.name->c, SRS_PORT(srs));
- // Note: By the time we get the mStatus_NameConflict message, the service is already deregistered
- // and the memory is free, so we don't have to wait for an mStatus_MemFree message as well.
- if (si->autoname && CountPeerRegistrations(m, srs) == 0)
- {
- // On conflict for an autoname service, rename and reregister *all* autoname services
- IncrementLabelSuffix(&m->nicelabel, mDNStrue);
- mDNS_ConfigChanged(m);
- }
- else if (si->autoname)
- {
- mDNS_RenameAndReregisterService(m, srs, mDNSNULL);
- return;
- }
- else
- {
- // If we get a name conflict, we tell the client about it, and then they are expected to dispose
- // of their registration in the usual way (which we will catch via client death notification).
- // If the Mach queue is full, we forcibly abort the client immediately.
- kern_return_t status = DNSServiceRegistrationReply_rpc(si->ClientMachPort, result, MDNS_MM_TIMEOUT);
- if (status == MACH_SEND_TIMED_OUT)
- AbortBlockedClient(si->ClientMachPort, "registration conflict", NULL);
- }
- }
-
- else if (result == mStatus_MemFree)
- {
- if (si->renameonmemfree) // We intentionally terminated registration so we could re-register with new name
- {
- debugf("RegCallback renaming %#s to %#s", si->name.c, m->nicelabel.c);
- si->renameonmemfree = mDNSfalse;
- si->name = m->nicelabel;
- mDNS_RenameAndReregisterService(m, srs, &si->name);
- }
- else
- {
- // SANITY CHECK: make sure service instance is no longer in any ServiceRegistration's list
- DNSServiceRegistration *r;
- for (r = DNSServiceRegistrationList; r; r = r->next)
- {
- ServiceInstance **sp = &r->regs;
- while (*sp)
- {
- if (*sp == si) { LogMsg("RegCallback: %##s Still in list; removing", srs->RR_SRV.resrec.name->c); *sp = (*sp)->next; break; }
- sp = &(*sp)->next;
- }
- }
- // END SANITY CHECK
- FreeServiceInstance(si);
- }
- }
-
- else if (result != mStatus_NATTraversal)
- LogMsg("%5d: DNSServiceRegistration(%##s, %u) Unknown Result %d", si->ClientMachPort, srs->RR_SRV.resrec.name->c, SRS_PORT(srs), result);
-}
-
-mDNSlocal mStatus AddServiceInstance(DNSServiceRegistration *x, const domainname *domain)
-{
- mStatus err = 0;
- ServiceInstance *si = NULL;
- AuthRecord *SubTypes = NULL;
-
- for (si = x->regs; si; si = si->next)
- {
- if (SameDomainName(&si->domain, domain))
- { LogMsg("Requested addition of domain %##s already in list", domain->c); return mStatus_AlreadyRegistered; }
- }
-
- SubTypes = AllocateSubTypes(x->NumSubTypes, x->regtype, mDNSNULL);
- if (x->NumSubTypes && !SubTypes) return mStatus_NoMemoryErr;
-
- si = mallocL("ServiceInstance", sizeof(*si) - sizeof(RDataBody) + x->rdsize);
- if (!si) return mStatus_NoMemoryErr;
-
- si->ClientMachPort = x->ClientMachPort;
- si->renameonmemfree = mDNSfalse;
- si->autoname = x->autoname;
- si->name = x->autoname ? mDNSStorage.nicelabel : x->name;
- si->domain = *domain;
- si->srs.AnonData = mDNSNULL;
-
- err = mDNS_RegisterService(&mDNSStorage, &si->srs, &si->name, &x->type, domain, NULL,
- x->port, x->txtinfo, x->txt_len, SubTypes, x->NumSubTypes, mDNSInterface_Any, RegCallback, si, 0);
- if (!err)
- {
- si->next = x->regs;
- x->regs = si;
- }
- else
- {
- LogMsg("Error %d for registration of service in domain %##s", err, domain->c);
- freeL("ServiceInstance", si);
- }
- return err;
-}
-
-mDNSexport void machserver_automatic_registration_domain_changed(const domainname *d, mDNSBool add)
-{
- DNSServiceRegistration *reg;
-
- for (reg = DNSServiceRegistrationList; reg; reg = reg->next)
- {
- if (reg->DefaultDomain)
- {
- if (add)
- AddServiceInstance(reg, d);
- else
- {
- ServiceInstance **si = &reg->regs;
- while (*si)
- {
- if (SameDomainName(&(*si)->domain, d))
- {
- ServiceInstance *s = *si;
- *si = (*si)->next;
- if (mDNS_DeregisterService(&mDNSStorage, &s->srs)) FreeServiceInstance(s); // only free memory synchronously on error
- break;
- }
- si = &(*si)->next;
- }
- if (!si) debugf("Requested removal of default domain %##s not in client %5d's list", d, reg->ClientMachPort); // normal if registration failed
- }
- }
- }
-}
-
-mDNSexport kern_return_t provide_DNSServiceRegistrationCreate_rpc(mach_port_t unusedserver, mach_port_t client,
- DNSCString name, DNSCString regtype, DNSCString domain, IPPort IpPort, DNSCString txtRecord)
-{
- (void)unusedserver; // Unused
- mStatus err = mStatus_NoError;
- const char *errormsg = "Unknown";
-
- // older versions of this code passed the port via mach IPC as an int.
- // we continue to pass it as 4 bytes to maintain binary compatibility,
- // but now ensure that the network byte order is preserved by using a struct
- mDNSIPPort port;
- port.b[0] = IpPort.bytes[2];
- port.b[1] = IpPort.bytes[3];
-
- if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; }
- if (CheckForExistingClient(client)) { err = mStatus_Invalid; errormsg = "Client id already in use"; goto fail; }
-
- // Check for sub-types after the service type
- size_t reglen = strlen(regtype) + 1;
- if (reglen > MAX_ESCAPED_DOMAIN_NAME) { errormsg = "reglen too long"; goto badparam; }
- mDNSs32 NumSubTypes = ChopSubTypes(regtype, mDNSNULL); // Note: Modifies regtype string to remove trailing subtypes
- if (NumSubTypes < 0) { errormsg = "Bad Service SubType"; goto badparam; }
-
- // Check other parameters
- domainlabel n;
- domainname t, d;
- domainname srv;
- if (!name[0]) n = mDNSStorage.nicelabel;
- else if (!MakeDomainLabelFromLiteralString(&n, name)) { errormsg = "Bad Instance Name"; goto badparam; }
- if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Bad Service Type"; goto badparam; }
- if (!MakeDomainNameFromDNSNameString(&d, *domain ? domain : "local.")) { errormsg = "Bad Domain"; goto badparam; }
- if (!ConstructServiceName(&srv, &n, &t, &d)) { errormsg = "Bad Name"; goto badparam; }
-
- unsigned char txtinfo[1024] = "";
- unsigned int data_len = 0;
- unsigned int size = sizeof(RDataBody);
- unsigned char *pstring = &txtinfo[data_len];
- char *ptr = txtRecord;
-
- // The OS X DNSServiceRegistrationCreate() API is defined using a C-string,
- // but the mDNS_RegisterService() call actually requires a packed block of P-strings.
- // Hence we have to convert the C-string to a P-string.
- // ASCII-1 characters are allowed in the C-string as boundary markers,
- // so that a single C-string can be used to represent one or more P-strings.
- while (*ptr)
- {
- if (++data_len >= sizeof(txtinfo)) { errormsg = "TXT record too long"; goto badtxt; }
- if (*ptr == 1) // If this is our boundary marker, start a new P-string
- {
- pstring = &txtinfo[data_len];
- pstring[0] = 0;
- ptr++;
- }
- else
- {
- if (pstring[0] == 255) { errormsg = "TXT record invalid (component longer than 255)"; goto badtxt; }
- pstring[++pstring[0]] = *ptr++;
- }
- }
-
- data_len++;
- if (size < data_len)
- size = data_len;
-
- // Some clients use mDNS for lightweight copy protection, registering a pseudo-service with
- // a port number of zero. When two instances of the protected client are allowed to run on one
- // machine, we don't want to see misleading "Bogus client" messages in syslog and the console.
- if (!mDNSIPPortIsZero(port))
- {
- int count = CountExistingRegistrations(&srv, port);
- if (count)
- LogMsg("%5d: Client application registered %d identical instances of service %##s port %u.",
- client, count+1, srv.c, mDNSVal16(port));
- }
-
- // Allocate memory, and handle failure
- DNSServiceRegistration *x = mallocL("DNSServiceRegistration", sizeof(*x));
- if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
- mDNSPlatformMemZero(x, sizeof(*x));
-
- // Set up object, and link into list
- x->ClientMachPort = client;
- x->DefaultDomain = !domain[0];
- x->autoname = (!name[0]);
- x->rdsize = size;
- x->NumSubTypes = NumSubTypes;
- memcpy(x->regtype, regtype, reglen);
- x->name = n;
- x->type = t;
- x->port = port;
- memcpy(x->txtinfo, txtinfo, 1024);
- x->txt_len = data_len;
- x->NextRef = 0;
- x->regs = NULL;
-
- x->next = DNSServiceRegistrationList;
- DNSServiceRegistrationList = x;
-
- LogOperation("%5d: DNSServiceRegistration(\"%s\", \"%s\", \"%s\", %u) START",
- x->ClientMachPort, name, regtype, domain, mDNSVal16(port));
-
- err = AddServiceInstance(x, &d);
- if (err) { AbortClient(client, x); errormsg = "mDNS_RegisterService"; goto fail; } // bail if .local (or explicit domain) fails
-
- if (x->DefaultDomain)
- {
- DNameListElem *p;
- for (p = AutoRegistrationDomains; p; p = p->next)
- AddServiceInstance(x, &p->name);
- }
-
- // Succeeded: Wrap up and return
- EnableDeathNotificationForClient(client, x);
- return(mStatus_NoError);
-
-badtxt:
- LogMsg("%5d: TXT record: %.100s...", client, txtRecord);
-badparam:
- err = mStatus_BadParamErr;
-fail:
- LogMsg("%5d: DNSServiceRegister(\"%s\", \"%s\", \"%s\", %d) failed: %s (%d)",
- client, name, regtype, domain, mDNSVal16(port), errormsg, err);
- return(err);
-}
-
mDNSlocal void mDNSPreferencesSetNames(mDNS *const m, int key, domainlabel *old, domainlabel *new)
{
domainlabel *prevold, *prevnew;
@@ -1367,234 +363,11 @@ mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
mDNSPreferencesSetNames(m, kmDNSComputerName, &m->p->usernicelabel, &m->nicelabel);
mDNSPreferencesSetNames(m, kmDNSLocalHostName, &m->p->userhostlabel, &m->hostlabel);
- // First we check our list of old Mach-based registered services, to see if any need to be updated to a new name
- DNSServiceRegistration *r;
- for (r = DNSServiceRegistrationList; r; r=r->next)
- if (r->autoname)
- {
- ServiceInstance *si;
- for (si = r->regs; si; si = si->next)
- {
- if (!SameDomainLabelCS(si->name.c, m->nicelabel.c))
- {
- debugf("NetworkChanged renaming %##s to %#s", si->srs.RR_SRV.resrec.name->c, m->nicelabel.c);
- si->renameonmemfree = mDNStrue;
- if (mDNS_DeregisterService_drt(m, &si->srs, mDNS_Dereg_rapid))
- RegCallback(m, &si->srs, mStatus_MemFree); // If service deregistered already, we can re-register immediately
- }
- }
- }
-
// Then we call into the UDS daemon code, to let it do the same
udsserver_handle_configchange(m);
}
}
-//*************************************************************************************************************
-// Add / Update / Remove records from existing Registration
-
-mDNSexport kern_return_t provide_DNSServiceRegistrationAddRecord_rpc(mach_port_t unusedserver, mach_port_t client,
- int type, const char *data, mach_msg_type_number_t data_len, uint32_t ttl, natural_t *reference)
-{
- // Check client parameter
- uint32_t id;
- mStatus err = mStatus_NoError;
- const char *errormsg = "Unknown";
- DNSServiceRegistration *x = DNSServiceRegistrationList;
- if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; }
- ServiceInstance *si;
- size_t size;
- (void)unusedserver; // Unused
- while (x && x->ClientMachPort != client) x = x->next;
- if (!x) { err = mStatus_BadReferenceErr; errormsg = "No such client"; goto fail; }
-
- // Check other parameters
- if (data_len > 8192) { err = mStatus_BadParamErr; errormsg = "data_len > 8K"; goto fail; }
- if (data_len > sizeof(RDataBody)) size = data_len;
- else size = sizeof(RDataBody);
-
- id = x->NextRef++;
- *reference = (natural_t)id;
- for (si = x->regs; si; si = si->next)
- {
- // Allocate memory, and handle failure
- ExtraResourceRecord *extra = mallocL("ExtraResourceRecord", sizeof(*extra) - sizeof(RDataBody) + size);
- if (!extra) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
-
- // Fill in type, length, and data of new record
- extra->r.resrec.rrtype = type;
- extra->r.rdatastorage.MaxRDLength = size;
- extra->r.resrec.rdlength = data_len;
- memcpy(&extra->r.rdatastorage.u.data, data, data_len);
-
- // Do the operation
- LogOperation("%5d: DNSServiceRegistrationAddRecord(%##s, type %d, length %d) REF %p",
- client, si->srs.RR_SRV.resrec.name->c, type, data_len, extra);
- err = mDNS_AddRecordToService(&mDNSStorage, &si->srs, extra, &extra->r.rdatastorage, ttl, 0);
-
- if (err)
- {
- freeL("Extra Resource Record", extra);
- errormsg = "mDNS_AddRecordToService";
- goto fail;
- }
-
- extra->ClientID = id;
- }
-
- return mStatus_NoError;
-
-fail:
- LogMsg("%5d: DNSServiceRegistrationAddRecord(%##s, type %d, length %d) failed: %s (%d)", client, x ? x->name.c : (mDNSu8*)"\x8" "«NULL»", type, data_len, errormsg, err);
- return mStatus_UnknownErr;
-}
-
-mDNSlocal void UpdateCallback(mDNS *const m, AuthRecord *const rr, RData *OldRData, mDNSu16 OldRDLen)
-{
- (void)m; // Unused
- (void)OldRDLen; // Unused
- if (OldRData != &rr->rdatastorage)
- freeL("Old RData", OldRData);
-}
-
-mDNSlocal mStatus UpdateRecord(ServiceRecordSet *srs, mach_port_t client, AuthRecord *rr, const char *data, mach_msg_type_number_t data_len, uint32_t ttl)
-{
- // Check client parameter
- mStatus err = mStatus_NoError;
- const char *errormsg = "Unknown";
- const domainname *name = (const domainname *)"";
-
- name = srs->RR_SRV.resrec.name;
-
- unsigned int size = sizeof(RDataBody);
- if (size < data_len)
- size = data_len;
-
- // Allocate memory, and handle failure
- RData *newrdata = mallocL("RData", sizeof(*newrdata) - sizeof(RDataBody) + size);
- if (!newrdata) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
-
- // Fill in new length, and data
- newrdata->MaxRDLength = size;
- memcpy(&newrdata->u, data, data_len);
-
- // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
- // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
- // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
- if (rr->resrec.rrtype == kDNSType_TXT && data_len == 0) { data_len = 1; newrdata->u.txt.c[0] = 0; }
-
- // Do the operation
- LogOperation("%5d: DNSServiceRegistrationUpdateRecord(%##s, new length %d)",
- client, srs->RR_SRV.resrec.name->c, data_len);
-
- err = mDNS_Update(&mDNSStorage, rr, ttl, data_len, newrdata, UpdateCallback);
- if (err)
- {
- errormsg = "mDNS_Update";
- freeL("RData", newrdata);
- goto fail;
- }
- return(mStatus_NoError);
-
-fail:
- LogMsg("%5d: DNSServiceRegistrationUpdateRecord(%##s, %d) failed: %s (%d)", client, name->c, data_len, errormsg, err);
- return(err);
-}
-
-mDNSexport kern_return_t provide_DNSServiceRegistrationUpdateRecord_rpc(mach_port_t unusedserver, mach_port_t client,
- natural_t reference, const char *data, mach_msg_type_number_t data_len, uint32_t ttl)
-{
- // Check client parameter
- mStatus err = mStatus_NoError;
- const char *errormsg = "Unknown";
- const domainname *name = (const domainname *)"";
- ServiceInstance *si;
-
- (void)unusedserver; // unused
- if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; }
- DNSServiceRegistration *x = DNSServiceRegistrationList;
- while (x && x->ClientMachPort != client) x = x->next;
- if (!x) { err = mStatus_BadReferenceErr; errormsg = "No such client"; goto fail; }
-
- // Check other parameters
- if (data_len > 8192) { err = mStatus_BadParamErr; errormsg = "data_len > 8K"; goto fail; }
-
- for (si = x->regs; si; si = si->next)
- {
- AuthRecord *r = NULL;
-
- // Find the record we're updating. NULL reference means update the primary TXT record
- if (!reference) r = &si->srs.RR_TXT;
- else
- {
- ExtraResourceRecord *ptr;
- for (ptr = si->srs.Extras; ptr; ptr = ptr->next)
- {
- if ((natural_t)ptr->ClientID == reference)
- { r = &ptr->r; break; }
- }
- if (!r) { err = mStatus_BadReferenceErr; errormsg = "No such record"; goto fail; }
- }
- err = UpdateRecord(&si->srs, client, r, data, data_len, ttl);
- if (err) goto fail; //!!!KRS this will cause failures for non-local defaults!
- }
-
- return mStatus_NoError;
-
-fail:
- LogMsg("%5d: DNSServiceRegistrationUpdateRecord(%##s, %X, %d) failed: %s (%d)", client, name->c, reference, data_len, errormsg, err);
- return(err);
-}
-
-mDNSlocal mStatus RemoveRecord(ServiceRecordSet *srs, ExtraResourceRecord *extra, mach_port_t client)
-{
- const domainname *const name = srs->RR_SRV.resrec.name;
- mStatus err = mStatus_NoError;
-
- // Do the operation
- LogOperation("%5d: DNSServiceRegistrationRemoveRecord(%##s)", client, srs->RR_SRV.resrec.name->c);
-
- err = mDNS_RemoveRecordFromService(&mDNSStorage, srs, extra, FreeExtraRR, extra);
- if (err) LogMsg("%5d: DNSServiceRegistrationRemoveRecord (%##s) failed: %d", client, name->c, err);
-
- return err;
-}
-
-mDNSexport kern_return_t provide_DNSServiceRegistrationRemoveRecord_rpc(mach_port_t unusedserver, mach_port_t client,
- natural_t reference)
-{
- // Check client parameter
- (void)unusedserver; // Unused
- mStatus err = mStatus_NoError;
- const char *errormsg = "Unknown";
- if (client == (mach_port_t)-1) { err = mStatus_Invalid; errormsg = "Client id -1 invalid"; goto fail; }
- DNSServiceRegistration *x = DNSServiceRegistrationList;
- ServiceInstance *si;
-
- while (x && x->ClientMachPort != client) x = x->next;
- if (!x) { err = mStatus_BadReferenceErr; errormsg = "No such client"; goto fail; }
-
- for (si = x->regs; si; si = si->next)
- {
- ExtraResourceRecord *e;
- for (e = si->srs.Extras; e; e = e->next)
- {
- if ((natural_t)e->ClientID == reference)
- {
- err = RemoveRecord(&si->srs, e, client);
- if (err) { errormsg = "RemoveRecord failed"; goto fail; }
- break;
- }
- }
- if (!e) { err = mStatus_BadReferenceErr; errormsg = "No such reference"; goto fail; }
- }
-
- return mStatus_NoError;
-
-fail:
- LogMsg("%5d: DNSServiceRegistrationRemoveRecord(%X) failed: %s (%d)", client, reference, errormsg, err);
- return(err);
-}
//*************************************************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
@@ -1607,16 +380,6 @@ mDNSlocal void ExitCallback(int sig)
(void)sig; // Unused
LogMsg("%s stopping", mDNSResponderVersionString);
- debugf("ExitCallback: Aborting MIG clients");
- while (DNSServiceDomainEnumerationList)
- AbortClient(DNSServiceDomainEnumerationList->ClientMachPort, DNSServiceDomainEnumerationList);
- while (DNSServiceBrowserList)
- AbortClient(DNSServiceBrowserList->ClientMachPort, DNSServiceBrowserList);
- while (DNSServiceResolverList)
- AbortClient(DNSServiceResolverList->ClientMachPort, DNSServiceResolverList);
- while (DNSServiceRegistrationList)
- AbortClient(DNSServiceRegistrationList->ClientMachPort, DNSServiceRegistrationList);
-
if (udsserver_exit() < 0)
LogMsg("ExitCallback: udsserver_exit failed");
@@ -1626,99 +389,6 @@ mDNSlocal void ExitCallback(int sig)
#ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-mDNSlocal void DNSserverCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
-{
- mig_reply_error_t *request = msg;
- mig_reply_error_t *reply;
- mach_msg_return_t mr;
- int options;
- (void)port; // Unused
- (void)size; // Unused
- (void)info; // Unused
-
- KQueueLock(&mDNSStorage);
-
- /* allocate a reply buffer */
- reply = CFAllocatorAllocate(NULL, provide_DNSServiceDiscoveryRequest_subsystem.maxsize, 0);
-
- /* call the MiG server routine */
- (void) DNSServiceDiscoveryRequest_server(&request->Head, &reply->Head);
-
- if (!(reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) && (reply->RetCode != KERN_SUCCESS))
- {
- if (reply->RetCode == MIG_NO_REPLY)
- {
- /*
- * This return code is a little tricky -- it appears that the
- * demux routine found an error of some sort, but since that
- * error would not normally get returned either to the local
- * user or the remote one, we pretend it's ok.
- */
- CFAllocatorDeallocate(NULL, reply);
- goto done;
- }
-
- /*
- * destroy any out-of-line data in the request buffer but don't destroy
- * the reply port right (since we need that to send an error message).
- */
- request->Head.msgh_remote_port = MACH_PORT_NULL;
- mach_msg_destroy(&request->Head);
- }
-
- if (reply->Head.msgh_remote_port == MACH_PORT_NULL)
- {
- /* no reply port, so destroy the reply */
- if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)
- mach_msg_destroy(&reply->Head);
- CFAllocatorDeallocate(NULL, reply);
- goto done;
- }
-
- /*
- * send reply.
- *
- * We don't want to block indefinitely because the client
- * isn't receiving messages from the reply port.
- * If we have a send-once right for the reply port, then
- * this isn't a concern because the send won't block.
- * If we have a send right, we need to use MACH_SEND_TIMEOUT.
- * To avoid falling off the kernel's fast RPC path unnecessarily,
- * we only supply MACH_SEND_TIMEOUT when absolutely necessary.
- */
-
- options = MACH_SEND_MSG;
- if (MACH_MSGH_BITS_REMOTE(reply->Head.msgh_bits) == MACH_MSG_TYPE_MOVE_SEND_ONCE)
- options |= MACH_SEND_TIMEOUT;
-
- mr = mach_msg(&reply->Head, /* msg */
- options, /* option */
- reply->Head.msgh_size, /* send_size */
- 0, /* rcv_size */
- MACH_PORT_NULL, /* rcv_name */
- MACH_MSG_TIMEOUT_NONE, /* timeout */
- MACH_PORT_NULL); /* notify */
-
- /* Has a message error occurred? */
- switch (mr)
- {
- case MACH_SEND_INVALID_DEST:
- case MACH_SEND_TIMED_OUT:
- /* the reply can't be delivered, so destroy it */
- mach_msg_destroy(&reply->Head);
- break;
-
- default:
- /* Includes success case. */
- break;
- }
-
- CFAllocatorDeallocate(NULL, reply);
-
-done:
- KQueueUnlock(&mDNSStorage, "Mach client event");
-}
-
// Send a mach_msg to ourselves (since that is signal safe) telling us to cleanup and exit
mDNSlocal void HandleSIG(int sig)
{
@@ -1744,7 +414,7 @@ mDNSlocal void HandleSIG(int sig)
#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-mDNSlocal void INFOCallback(void)
+mDNSexport void INFOCallback(void)
{
mDNSs32 utc = mDNSPlatformUTC();
const mDNSs32 now = mDNS_TimeNow(&mDNSStorage);
@@ -1752,11 +422,6 @@ mDNSlocal void INFOCallback(void)
DNSServer *s;
McastResolver *mr;
- // Create LoggerID(Key)->com.apple.networking.mDNSResponder(Value) pair when SIGINFO is received.
- // This key-value pair is used as a condition by syslogd to Log to com.apple.networking.mDNSResponder.log file
- // present in /etc/asl/com.apple.networking.mDNSResponder.
- asl_set(log_msg, "LoggerID", "com.apple.networking.mDNSResponder");
-
LogMsg("---- BEGIN STATE LOG ---- %s %s %d", mDNSResponderVersionString, OSXVers ? "OSXVers" : "iOSVers", OSXVers ? OSXVers : iOSVers);
udsserver_info(&mDNSStorage);
@@ -1821,14 +486,10 @@ mDNSlocal void INFOCallback(void)
for (s = mDNSStorage.DNSServers; s; s = s->next)
{
NetworkInterfaceInfoOSX *ifx = IfindexToInterfaceInfoOSX(&mDNSStorage, s->interface);
- LogMsgNoIdent("DNS Server %##s %s%s%#a:%d %d %s %d %d %s %s %s %s %s",
+ LogMsgNoIdent("DNS Server %##s %s%s%#a:%d %d %s %d %d %s %s %s %s",
s->domain.c, ifx ? ifx->ifinfo.ifname : "", ifx ? " " : "", &s->addr, mDNSVal16(s->port),
s->penaltyTime ? s->penaltyTime - mDNS_TimeNow(&mDNSStorage) : 0, DNSScopeToString(s->scoped),
s->timeout, s->resGroupID,
- s->teststate == DNSServer_Untested ? "(Untested)" :
- s->teststate == DNSServer_Passed ? "" :
- s->teststate == DNSServer_Failed ? "(Failed)" :
- s->teststate == DNSServer_Disabled ? "(Disabled)" : "(Unknown state)",
s->req_A ? "v4" : "!v4",
s->req_AAAA ? "v6" : "!v6",
s->cellIntf ? "cell" : "!cell",
@@ -1848,75 +509,40 @@ mDNSlocal void INFOCallback(void)
LogMsgNoIdent("Mcast Resolver %##s timeout %u", mr->domain.c, mr->timeout);
}
+ LogMsgNoIdent("------------ Hostnames -------------");
+ if (!mDNSStorage.Hostnames) LogMsgNoIdent("<None>");
+ else
+ {
+ HostnameInfo *hi;
+ for (hi = mDNSStorage.Hostnames; hi; hi = hi->next)
+ {
+ LogMsgNoIdent("%##s v4 %d %s", hi->fqdn.c, hi->arv4.state, ARDisplayString(&mDNSStorage, &hi->arv4));
+ LogMsgNoIdent("%##s v6 %d %s", hi->fqdn.c, hi->arv6.state, ARDisplayString(&mDNSStorage, &hi->arv6));
+ }
+ }
+
+ LogMsgNoIdent("--------------- FQDN ---------------");
+ if (!mDNSStorage.FQDN.c[0]) LogMsgNoIdent("<None>");
+ else
+ {
+ LogMsgNoIdent("%##s", mDNSStorage.FQDN.c);
+ }
+
#if TARGET_OS_EMBEDDED
LogMetrics();
#endif
LogMsgNoIdent("Timenow 0x%08lX (%d)", (mDNSu32)now, now);
LogMsg("---- END STATE LOG ---- %s %s %d", mDNSResponderVersionString, OSXVers ? "OSXVers" : "iOSVers", OSXVers ? OSXVers : iOSVers);
-
- // If logging is disabled, only then clear the key we set at the top of this func
- if (!mDNS_LoggingEnabled)
- asl_unset(log_msg, "LoggerID");
}
-mDNSlocal void DebugSetFilter()
-{
- if (!log_client)
- return;
-
- // When USR1 is turned on, we log only the LOG_WARNING and LOG_NOTICE messages by default.
- // The user has to manually do "syslog -c mDNSResponder -i" to get the LOG_INFO messages
- // also to be logged. Most of the times, we need the INFO level messages for debugging.
- // Hence, we set the filter to INFO level when USR1 logging is turned on to avoid
- // having the user to do this extra step manually.
-
- if (mDNS_LoggingEnabled)
- {
- asl_set_filter(log_client, ASL_FILTER_MASK_UPTO(ASL_LEVEL_INFO));
- asl_set(log_msg, "LoggerID", "com.apple.networking.mDNSResponder");
- // Create LoggerID(Key)->com.apple.networking.mDNSResponder(Value) pair when USR1 Logging is Enabled.
- // This key-value pair is used as a condition by syslogd to Log to com.apple.networking.mDNSResponder.log file
- // present in /etc/asl/com.apple.networking.mDNSResponder.
- }
- else
- {
- asl_set_filter(log_client, ASL_FILTER_MASK_UPTO(ASL_LEVEL_ERR));
- asl_unset(log_msg, "LoggerID");
- // Clear the key-value pair when USR1 Logging is Disabled, as we do not want to log to
- // com.apple.networking.mDNSResponder.log file in this case.
- }
-}
mDNSexport void mDNSPlatformLogToFile(int log_level, const char *buffer)
{
- int asl_level = ASL_LEVEL_ERR;
-
- if (!log_client)
- {
- syslog(log_level, "%s", buffer);
- return;
- }
- switch (log_level)
- {
- case LOG_ERR:
- asl_level = ASL_LEVEL_ERR;
- break;
- case LOG_WARNING:
- asl_level = ASL_LEVEL_WARNING;
- break;
- case LOG_NOTICE:
- asl_level = ASL_LEVEL_NOTICE;
- break;
- case LOG_INFO:
- asl_level = ASL_LEVEL_INFO;
- break;
- case LOG_DEBUG:
- asl_level = ASL_LEVEL_DEBUG;
- break;
- default:
- break;
- }
- asl_log(log_client, log_msg, asl_level, "%s", buffer);
+ if (!log_general)
+ os_log_error(OS_LOG_DEFAULT, "Could NOT create log handle in init_logging()");
+ else
+ os_log_with_type(log_general, log_level, "%s", buffer);
+
}
// Writes the state out to the dynamic store and also affects the ASL filter level
@@ -1970,35 +596,9 @@ mDNSexport void UpdateDebugState()
CFRelease(numZero);
mDNSDynamicStoreSetConfig(kmDNSDebugState, mDNSNULL, dict);
CFRelease(dict);
- // If we turned off USR1 logging, we need to reset the filter
- DebugSetFilter();
-}
-#if TARGET_OS_EMBEDDED
-mDNSlocal void Prefschanged()
-{
- mDNSBool mDNSProf_installed;
- LogMsg("Prefschanged: mDNSResponder Managed Preferences have changed");
- mDNSProf_installed = GetmDNSManagedPref(kmDNSEnableLoggingStr);
- dispatch_async(dispatch_get_main_queue(),
- ^{
- if (mDNSProf_installed)
- {
- mDNS_LoggingEnabled = mDNS_PacketLoggingEnabled = 1;
- }
- else
- {
- LogMsg("Prefschanged: mDNSDebugProfile is uninstalled -> Turning OFF USR1/USR2 Logging with SIGINFO o/p");
- INFOCallback();
- mDNS_LoggingEnabled = mDNS_PacketLoggingEnabled = 0;
- }
- UpdateDebugState();
- // If Logging Enabled: Start Logging to com.apple.networking.mDNSResponder.log (has to be LogInfo)
- LogInfo("Prefschanged: mDNSDebugProfile is installed -> Turned ON USR1/USR2 Logging");
- });
- return;
}
-#endif //TARGET_OS_EMBEDDED
+
#ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
@@ -2031,15 +631,26 @@ mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void
case SIGINT:
case SIGTERM: ExitCallback(msg_header->msgh_id); break;
case SIGINFO: INFOCallback(); break;
- case SIGUSR1: mDNS_LoggingEnabled = mDNS_LoggingEnabled ? 0 : 1;
+ case SIGUSR1:
+#if APPLE_OSX_mDNSResponder
+ mDNS_LoggingEnabled = 1;
+ LogMsg("SIGUSR1: Logging %s on Apple Platforms", mDNS_LoggingEnabled ? "Enabled" : "Disabled");
+#else
+ mDNS_LoggingEnabled = mDNS_LoggingEnabled ? 0 : 1;
LogMsg("SIGUSR1: Logging %s", mDNS_LoggingEnabled ? "Enabled" : "Disabled");
+#endif
WatchDogReportingThreshold = mDNS_LoggingEnabled ? 50 : 250;
UpdateDebugState();
- // If Logging Enabled: Start Logging to com.apple.networking.mDNSResponder.log
- LogInfo("USR1 Logging Enabled: Start Logging to mDNSResponder Log file");
+ LogInfo("USR1 Logging Enabled");
break;
- case SIGUSR2: mDNS_PacketLoggingEnabled = mDNS_PacketLoggingEnabled ? 0 : 1;
+ case SIGUSR2:
+#if APPLE_OSX_mDNSResponder
+ mDNS_PacketLoggingEnabled = 1;
+ LogMsg("SIGUSR2: Packet Logging %s on Apple Platforms", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled");
+#else
+ mDNS_PacketLoggingEnabled = mDNS_PacketLoggingEnabled ? 0 : 1;
LogMsg("SIGUSR2: Packet Logging %s", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled");
+#endif
mDNS_McastTracingEnabled = (mDNS_PacketLoggingEnabled && mDNS_McastLoggingEnabled) ? mDNStrue : mDNSfalse;
LogInfo("SIGUSR2: Multicast Tracing is %s", mDNS_McastTracingEnabled ? "Enabled" : "Disabled");
UpdateDebugState();
@@ -2065,37 +676,24 @@ mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void
mDNSlocal kern_return_t mDNSDaemonInitialize(void)
{
mStatus err;
- CFMachPortRef s_port;
- CFRunLoopSourceRef s_rls;
- CFRunLoopSourceRef d_rls;
-
- s_port = CFMachPortCreateWithPort(NULL, m_port, DNSserverCallback, NULL, NULL);
- CFMachPortRef d_port = CFMachPortCreate(NULL, ClientDeathCallback, NULL, NULL);
err = mDNS_Init(&mDNSStorage, &PlatformStorage,
rrcachestorage, RR_CACHE_SIZE,
- advertise,
+ !NoMulticastAdvertisements,
mDNS_StatusCallback, mDNS_Init_NoInitCallbackContext);
- if (err) { LogMsg("Daemon start: mDNS_Init failed %d", err); return(err); }
-
- client_death_port = CFMachPortGetPort(d_port);
-
- s_rls = CFMachPortCreateRunLoopSource(NULL, s_port, 0);
- CFRunLoopAddSource(PlatformStorage.CFRunLoop, s_rls, kCFRunLoopDefaultMode);
- CFRelease(s_rls);
-
- d_rls = CFMachPortCreateRunLoopSource(NULL, d_port, 0);
- CFRunLoopAddSource(PlatformStorage.CFRunLoop, d_rls, kCFRunLoopDefaultMode);
- CFRelease(d_rls);
+ if (err)
+ {
+ LogMsg("Daemon start: mDNS_Init failed %d", err);
+ return(err);
+ }
CFMachPortRef i_port = CFMachPortCreate(NULL, SignalCallback, NULL, NULL);
CFRunLoopSourceRef i_rls = CFMachPortCreateRunLoopSource(NULL, i_port, 0);
signal_port = CFMachPortGetPort(i_port);
- CFRunLoopAddSource(PlatformStorage.CFRunLoop, i_rls, kCFRunLoopDefaultMode);
+ CFRunLoopAddSource(CFRunLoopGetMain(), i_rls, kCFRunLoopDefaultMode);
CFRelease(i_rls);
-
- if (mDNS_DebugMode) printf("Service registered with Mach Port %d\n", m_port);
+
return(err);
}
@@ -2162,28 +760,21 @@ mDNSlocal void mDNSSetupSignal(dispatch_queue_t queue, int sig)
}
}
-// On 10.2 the MachServerName is DNSServiceDiscoveryServer
-// On 10.3 and later, the MachServerName is com.apple.mDNSResponder
mDNSlocal kern_return_t mDNSDaemonInitialize(void)
{
mStatus err;
- dispatch_source_t mach_source;
dispatch_queue_t queue = dispatch_get_main_queue();
err = mDNS_Init(&mDNSStorage, &PlatformStorage,
rrcachestorage, RR_CACHE_SIZE,
- advertise,
+ !NoMulticastAdvertisements,
mDNS_StatusCallback, mDNS_Init_NoInitCallbackContext);
- if (err) { LogMsg("Daemon start: mDNS_Init failed %d", err); return(err); }
-
- mach_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, m_port, 0, queue);
- if (mach_source == mDNSNULL) {LogMsg("mDNSDaemonInitialize: Error creating source for m_port"); return -1;}
- dispatch_source_set_event_handler(mach_source, ^{
- dispatch_mig_server(mach_source, sizeof(union __RequestUnion__DNSServiceDiscoveryReply_subsystem),
- DNSServiceDiscoveryRequest_server);
- });
- dispatch_resume(mach_source);
+ if (err)
+ {
+ LogMsg("Daemon start: mDNS_Init failed %d", err);
+ return(err);
+ }
mDNSSetupSignal(queue, SIGHUP);
mDNSSetupSignal(queue, SIGINT);
@@ -2215,7 +806,6 @@ mDNSlocal kern_return_t mDNSDaemonInitialize(void)
LogMsg("DaemonIntialize done successfully");
- if (mDNS_DebugMode) printf("Service registered with Mach Port %d\n", m_port);
return(err);
}
@@ -2245,7 +835,11 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m)
// we then systematically lose our own looped-back packets.
if (m->NetworkChanged && now - m->NetworkChanged >= 0) mDNSMacOSXNetworkChanged(m);
- if (m->p->RequestReSleep && now - m->p->RequestReSleep >= 0) { m->p->RequestReSleep = 0; mDNSPowerRequest(0, 0); }
+ if (m->p->RequestReSleep && now - m->p->RequestReSleep >= 0)
+ {
+ m->p->RequestReSleep = 0;
+ mDNSPowerRequest(0, 0);
+ }
// 3. Call mDNS_Execute() to let mDNSCore do what it needs to do
mDNSs32 nextevent = mDNS_Execute(m);
@@ -2262,61 +856,7 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m)
if (nextevent - m->p->RequestReSleep > 0)
nextevent = m->p->RequestReSleep;
- // 4. Deliver any waiting browse messages to clients
- DNSServiceBrowser *b = DNSServiceBrowserList;
-
- while (b)
- {
- // Note: Need to advance b to the next element BEFORE we call DeliverInstance(), because in the
- // event that the client Mach queue overflows, DeliverInstance() will call AbortBlockedClient()
- // and that will cause the DNSServiceBrowser object's memory to be freed before it returns
- DNSServiceBrowser *x = b;
- b = b->next;
- if (x->results) // Try to deliver the list of results
- {
- while (x->results)
- {
- DNSServiceBrowserResult *const r = x->results;
- domainlabel name;
- domainname type, domain;
- DeconstructServiceName(&r->result, &name, &type, &domain); // Don't need to check result; already validated in FoundInstance()
- char cname[MAX_DOMAIN_LABEL+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
- char ctype[MAX_ESCAPED_DOMAIN_NAME];
- char cdom [MAX_ESCAPED_DOMAIN_NAME];
- ConvertDomainLabelToCString_unescaped(&name, cname);
- ConvertDomainNameToCString(&type, ctype);
- ConvertDomainNameToCString(&domain, cdom);
- DNSServiceDiscoveryReplyFlags flags = (r->next) ? DNSServiceDiscoverReplyFlagsMoreComing : 0;
- kern_return_t status = DNSServiceBrowserReply_rpc(x->ClientMachPort, r->resultType, cname, ctype, cdom, flags, 1);
- // If we failed to send the mach message, try again in one second
- if (status == MACH_SEND_TIMED_OUT)
- {
- if (nextevent - now > mDNSPlatformOneSecond)
- nextevent = now + mDNSPlatformOneSecond;
- break;
- }
- else
- {
- x->lastsuccess = now;
- x->results = x->results->next;
- freeL("DNSServiceBrowserResult", r);
- }
- }
- // If this client hasn't read a single message in the last 60 seconds, abort it
- if (now - x->lastsuccess >= 60 * mDNSPlatformOneSecond)
- AbortBlockedClient(x->ClientMachPort, "browse", x);
- }
- }
-
- DNSServiceResolver *l;
- for (l = DNSServiceResolverList; l; l=l->next)
- if (l->ReportTime && now - l->ReportTime >= 0)
- {
- l->ReportTime = 0;
- LogMsgNoIdent("Client application bug: DNSServiceResolver(%##s) active for over two minutes. "
- "This places considerable burden on the network.", l->i.name.c);
- }
-
+
if (m->p->NotifyUser)
{
if (m->p->NotifyUser - now < 0)
@@ -2488,7 +1028,8 @@ mDNSlocal mDNSBool AllowSleepNow(mDNS *const m, mDNSs32 now)
// so we should put it back to sleep. To avoid frustrating the user, we always request at least
// 60 seconds sleep, so if they immediately re-wake the system within seconds of it going to sleep,
// we then shouldn't hit our 30-second window, and we won't attempt to re-sleep the machine.
- if (interval < 60) interval = 60;
+ if (interval < 60)
+ interval = 60;
result = mDNSPowerRequest(1, interval);
@@ -2683,7 +1224,7 @@ mDNSlocal void * KQueueLoop(void *m_param)
LogInfo("WARNING: Idle task took %dms to complete", end - start);
#if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1
- validatelists(m, true);
+ validatelists(m);
#endif
mDNSs32 now = mDNS_TimeNow(m);
@@ -2810,44 +1351,109 @@ mDNSlocal void * KQueueLoop(void *m_param)
#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-mDNSlocal void LaunchdCheckin(void)
+mDNSlocal size_t LaunchdCheckin(void)
{
// Ask launchd for our socket
int result = launch_activate_socket("Listeners", &launchd_fds, &launchd_fds_count);
if (result != 0) { LogMsg("launch_activate_socket() failed errno %d (%s)", errno, strerror(errno)); }
+ return launchd_fds_count;
+}
+
+
+extern int sandbox_init(const char *profile, uint64_t flags, char **errorbuf) __attribute__((weak_import));
+
+#if APPLE_OSX_mDNSResponder
+mDNSlocal mDNSBool PreferencesGetValueBool(CFStringRef key, mDNSBool defaultValue)
+{
+ CFBooleanRef boolean;
+ mDNSBool result = defaultValue;
+
+ boolean = CFPreferencesCopyAppValue(key, kProgramArguments);
+ if (boolean)
+ {
+ if (CFGetTypeID(boolean) == CFBooleanGetTypeID())
+ result = CFBooleanGetValue(boolean) ? mDNStrue : mDNSfalse;
+ CFRelease(boolean);
+ }
+
+ return result;
}
-static mach_port_t RegisterMachService(const char *service_name)
+mDNSlocal int PreferencesGetValueInt(CFStringRef key, int defaultValue)
{
- mach_port_t port = MACH_PORT_NULL;
- kern_return_t kr;
-
- if (KERN_SUCCESS != (kr = bootstrap_check_in(bootstrap_port, (char *)service_name, &port)))
- {
- LogMsg("RegisterMachService: %d %X %s", kr, kr, mach_error_string(kr));
- return MACH_PORT_NULL;
- }
-
- if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND)))
- {
- LogMsg("RegisterMachService: %d %X %s", kr, kr, mach_error_string(kr));
- mach_port_deallocate(mach_task_self(), port);
- return MACH_PORT_NULL;
- }
-
- return port;
+ CFNumberRef number;
+ int numberValue;
+ int result = defaultValue;
+
+ number = CFPreferencesCopyAppValue(key, kProgramArguments);
+ if (number)
+ {
+ if ((CFGetTypeID(number) == CFNumberGetTypeID()) && CFNumberGetValue(number, kCFNumberIntType, &numberValue))
+ result = numberValue;
+ CFRelease(number);
+ }
+
+ return result;
}
+#endif
-extern int sandbox_init(const char *profile, uint64_t flags, char **errorbuf) __attribute__((weak_import));
+mDNSlocal void SandboxProcess(void)
+{
+ // Invoke sandbox profile /usr/share/sandbox/mDNSResponder.sb
+#if MDNS_NO_SANDBOX
+ LogMsg("Note: Compiled without Apple Sandbox support");
+#else // MDNS_NO_SANDBOX
+ if (!sandbox_init)
+ LogMsg("Note: Running without Apple Sandbox support (not available on this OS)");
+ else
+ {
+ char *sandbox_msg;
+ uint64_t sandbox_flags = SANDBOX_NAMED;
+
+ (void)confstr(_CS_DARWIN_USER_CACHE_DIR, NULL, 0);
+
+ int sandbox_err = sandbox_init("mDNSResponder", sandbox_flags, &sandbox_msg);
+ if (sandbox_err)
+ {
+ LogMsg("WARNING: sandbox_init error %s", sandbox_msg);
+ // If we have errors in the sandbox during development, to prevent
+ // exiting, uncomment the following line.
+ //sandbox_free_error(sandbox_msg);
+
+ errx(EX_OSERR, "sandbox_init() failed: %s", sandbox_msg);
+ }
+ else LogInfo("Now running under Apple Sandbox restrictions");
+ }
+#endif // MDNS_NO_SANDBOX
+}
+
+#if APPLE_OSX_mDNSResponder
+mDNSlocal void init_logging(void)
+{
+ log_general = os_log_create("com.apple.mDNSResponder", "AllINFO");
+
+ if (!log_general)
+ {
+ // OS_LOG_DEFAULT is the default logging object, if you are not creating a custom subsystem/category
+ os_log_error(OS_LOG_DEFAULT, "Could NOT create log handle in mDNSResponder");
+ }
+}
+#endif
mDNSexport int main(int argc, char **argv)
{
int i;
kern_return_t status;
- log_client = asl_open(NULL, "mDNSResponder", 0);
- log_msg = asl_new(ASL_TYPE_MSG);
-
+#if DEBUG
+ bool useDebugSocket = mDNSfalse;
+ bool useSandbox = mDNStrue;
+#endif
+
+#if APPLE_OSX_mDNSResponder
+ init_logging();
+#endif
+
mDNSMacOSXSystemBuildNumber(NULL);
LogMsg("%s starting %s %d", mDNSResponderVersionString, OSXVers ? "OSXVers" : "iOSVers", OSXVers ? OSXVers : iOSVers);
@@ -2872,7 +1478,7 @@ mDNSexport int main(int argc, char **argv)
for (i=1; i<argc; i++)
{
if (!strcasecmp(argv[i], "-d" )) mDNS_DebugMode = mDNStrue;
- if (!strcasecmp(argv[i], "-NoMulticastAdvertisements")) advertise = mDNS_Init_DontAdvertiseLocalAddresses;
+ if (!strcasecmp(argv[i], "-NoMulticastAdvertisements")) NoMulticastAdvertisements = mDNStrue;
if (!strcasecmp(argv[i], "-DisableSleepProxyClient" )) DisableSleepProxyClient = mDNStrue;
if (!strcasecmp(argv[i], "-DebugLogging" )) mDNS_LoggingEnabled = mDNStrue;
if (!strcasecmp(argv[i], "-UnicastPacketLogging" )) mDNS_PacketLoggingEnabled = mDNStrue;
@@ -2882,10 +1488,14 @@ mDNSexport int main(int argc, char **argv)
UseInternalSleepProxy = (i+1<argc && mDNSIsDigit(argv[i+1][0]) && argv[i+1][1]==0) ? atoi(argv[++i]) : 1;
if (!strcasecmp(argv[i], "-StrictUnicastOrdering" )) StrictUnicastOrdering = mDNStrue;
if (!strcasecmp(argv[i], "-AlwaysAppendSearchDomains")) AlwaysAppendSearchDomains = mDNStrue;
+#if DEBUG
+ if (!strcasecmp(argv[i], "-UseDebugSocket")) useDebugSocket = mDNStrue;
+ if (!strcasecmp(argv[i], "-NoSandbox")) useSandbox = mDNSfalse;
+#endif
}
-#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
+#if APPLE_OSX_mDNSResponder
/* Reads the external user's program arguments for mDNSResponder starting 10.11.x(El Capitan) on OSX. The options for external user are:
DebugLogging, UnicastPacketLogging, NoMulticastAdvertisements, StrictUnicastOrdering and AlwaysAppendSearchDomains
@@ -2904,51 +1514,27 @@ mDNSexport int main(int argc, char **argv)
1] sudo defaults read /Library/Preferences/com.apple.mDNSResponder.plist
*/
- CFBooleanRef enabled = NULL;
-
- enabled = CFPreferencesCopyValue(kDebugLogging, kProgramArguments, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
- if (enabled != NULL)
- {
- if ((CFGetTypeID(enabled) == CFBooleanGetTypeID()) && CFBooleanGetValue(enabled))
- mDNS_LoggingEnabled = mDNStrue;
- CFRelease(enabled);
- }
-
- enabled = CFPreferencesCopyValue(kUnicastPacketLogging, kProgramArguments, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
- if (enabled != NULL)
- {
- if ((CFGetTypeID(enabled) == CFBooleanGetTypeID()) && CFBooleanGetValue(enabled))
- mDNS_PacketLoggingEnabled = mDNStrue;
- CFRelease(enabled);
- }
-
- enabled = CFPreferencesCopyValue(kNoMulticastAdvertisements, kProgramArguments, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
- if (enabled != NULL)
- {
- if ((CFGetTypeID(enabled) == CFBooleanGetTypeID()) && CFBooleanGetValue(enabled))
- advertise = mDNS_Init_DontAdvertiseLocalAddresses;
- CFRelease(enabled);
- }
-
- enabled = CFPreferencesCopyValue(kStrictUnicastOrdering, kProgramArguments, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
- if (enabled != NULL)
- {
- if ((CFGetTypeID(enabled) == CFBooleanGetTypeID()) && CFBooleanGetValue(enabled))
- StrictUnicastOrdering = mDNStrue;
- CFRelease(enabled);
- }
-
- enabled = CFPreferencesCopyValue(kAlwaysAppendSearchDomains, kProgramArguments, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
- if (enabled != NULL)
- {
- if ((CFGetTypeID(enabled) == CFBooleanGetTypeID()) && CFBooleanGetValue(enabled))
- AlwaysAppendSearchDomains = mDNStrue;
- CFRelease(enabled);
- }
+
+// Currently on Fuji/Whitetail releases we are keeping the logging always enabled.
+// Hence mDNS_LoggingEnabled and mDNS_PacketLoggingEnabled is set to true below by default.
+#if 0
+ mDNS_LoggingEnabled = PreferencesGetValueBool(kPreferencesKey_DebugLogging, mDNS_LoggingEnabled);
+ mDNS_PacketLoggingEnabled = PreferencesGetValueBool(kPreferencesKey_UnicastPacketLogging, mDNS_PacketLoggingEnabled);
+#endif
+
+ mDNS_LoggingEnabled = mDNStrue;
+ mDNS_PacketLoggingEnabled = mDNStrue;
+
+ NoMulticastAdvertisements = PreferencesGetValueBool(kPreferencesKey_NoMulticastAdvertisements, NoMulticastAdvertisements);
+ StrictUnicastOrdering = PreferencesGetValueBool(kPreferencesKey_StrictUnicastOrdering, StrictUnicastOrdering);
+ AlwaysAppendSearchDomains = PreferencesGetValueBool(kPreferencesKey_AlwaysAppendSearchDomains, AlwaysAppendSearchDomains);
+ OfferSleepProxyService = PreferencesGetValueInt(kPreferencesKey_OfferSleepProxyService, OfferSleepProxyService);
+ UseInternalSleepProxy = PreferencesGetValueInt(kPreferencesKey_UseInternalSleepProxy, UseInternalSleepProxy);
+ EnableBLEBasedDiscovery = PreferencesGetValueBool(kPreferencesKey_EnableBLEBasedDiscovery, EnableBLEBasedDiscovery);
#endif
// Note that mDNSPlatformInit will set DivertMulticastAdvertisements in the mDNS structure
- if (!advertise)
+ if (NoMulticastAdvertisements)
LogMsg("-NoMulticastAdvertisements is set: Administratively prohibiting multicast advertisements");
if (AlwaysAppendSearchDomains)
LogMsg("-AlwaysAppendSearchDomains is set");
@@ -2972,7 +1558,16 @@ mDNSexport int main(int argc, char **argv)
mDNSStorage.p = &PlatformStorage; // Make sure mDNSStorage.p is set up, because validatelists uses it
// Need to Start XPC Server Before LaunchdCheckin() (Reason: rdar11023750)
xpc_server_init();
+#if DEBUG
+ if (!useDebugSocket) {
+ if (LaunchdCheckin() == 0)
+ useDebugSocket = mDNStrue;
+ }
+ if (useDebugSocket)
+ SetDebugBoundPath();
+#else
LaunchdCheckin();
+#endif
#ifndef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
@@ -2997,40 +1592,10 @@ mDNSexport int main(int argc, char **argv)
#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
- // Invoke sandbox profile /usr/share/sandbox/mDNSResponder.sb
-#if MDNS_NO_SANDBOX
- LogMsg("Note: Compiled without Apple Sandbox support");
-#else // MDNS_NO_SANDBOX
- if (!sandbox_init)
- LogMsg("Note: Running without Apple Sandbox support (not available on this OS)");
- else
- {
- char *sandbox_msg;
- uint64_t sandbox_flags = SANDBOX_NAMED;
-
- (void)confstr(_CS_DARWIN_USER_CACHE_DIR, NULL, 0);
-
- int sandbox_err = sandbox_init("mDNSResponder", sandbox_flags, &sandbox_msg);
- if (sandbox_err)
- {
- LogMsg("WARNING: sandbox_init error %s", sandbox_msg);
- // If we have errors in the sandbox during development, to prevent
- // exiting, uncomment the following line.
- //sandbox_free_error(sandbox_msg);
-
- errx(EX_OSERR, "sandbox_init() failed: %s", sandbox_msg);
- }
- else LogInfo("Now running under Apple Sandbox restrictions");
- }
-#endif // MDNS_NO_SANDBOX
-
- m_port = RegisterMachService(kmDNSResponderServName);
- // We should ALWAYS receive our Mach port from RegisterMachService() but sanity check before initializing daemon
- if (m_port == MACH_PORT_NULL)
- {
- LogMsg("! MACH PORT IS NULL ! bootstrap_checkin failed to give a mach port");
- return -1;
- }
+#if DEBUG
+ if (useSandbox)
+#endif
+ SandboxProcess();
#if TARGET_OS_EMBEDDED
status = MetricsInit();
@@ -3043,13 +1608,6 @@ mDNSexport int main(int argc, char **argv)
status = udsserver_init(launchd_fds, launchd_fds_count);
if (status) { LogMsg("Daemon start: udsserver_init failed"); goto exit; }
-#if TARGET_OS_EMBEDDED
- _scprefs_observer_watch(scprefs_observer_type_global, kmDNSResponderPrefIDStr, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
- ^{
- Prefschanged();
- });
-#endif
-
mDNSMacOSXNetworkChanged(&mDNSStorage);
UpdateDebugState();
diff --git a/mDNSResponder/mDNSMacOSX/dnsctl-entitlements.plist b/mDNSResponder/mDNSMacOSX/dnsctl-entitlements.plist
index fb9c3a30..d724352a 100644
--- a/mDNSResponder/mDNSMacOSX/dnsctl-entitlements.plist
+++ b/mDNSResponder/mDNSMacOSX/dnsctl-entitlements.plist
@@ -4,5 +4,7 @@
<dict>
<key>com.apple.mDNSResponder.dnsproxy</key>
<true/>
+ <key>com.apple.mDNSResponder.dnsctl</key>
+ <true/>
</dict>
</plist>
diff --git a/mDNSResponder/mDNSMacOSX/helper-error.h b/mDNSResponder/mDNSMacOSX/helper-error.h
deleted file mode 100644
index 6465b734..00000000
--- a/mDNSResponder/mDNSMacOSX/helper-error.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2007-2013 Apple Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-ERROR(kmDNSHelperCommunicationFailed, "Mach communication failed")
-ERROR(kmDNSHelperNotAuthorized, "Not authorized")
-ERROR(kmDNSHelperCreationFailed, "Object creation failed")
-ERROR(kmDNSHelperInvalidPList, "Invalid property list")
-ERROR(kmDNSHelperInvalidNameKey, "Invalid name key")
-ERROR(kmDNSHelperInvalidConfigKey, "Invalid configuration key")
-ERROR(kmDNSHelperTypeError, "Object was not of expected type")
-ERROR(kmDNSHelperPreferencesFailed, "Could not create preferences session")
-ERROR(kmDNSHelperPreferencesLockFailed, "Could not lock preferences")
-ERROR(kmDNSHelperPreferencesSetFailed, "Could not update preferences")
-ERROR(kmDNSHelperKeychainCopyDefaultFailed, "Could not copy keychain default")
-ERROR(kmDNSHelperKeychainSearchCreationFailed, "Could not create keychain search")
-ERROR(kmDNSHelperPListWriteFailed, "Could not write property list to stream")
-ERROR(kmDNSHelperResultTooLarge, "Result too large")
-ERROR(kmDNSHelperInterfaceCreationFailed, "Could not create auto-tunnel interface")
-ERROR(kmDNSHelperInterfaceDeletionFailed, "Could not delete auto-tunnel interface")
-ERROR(kmDNSHelperInvalidInterfaceState, "Invalid interface state requested")
-ERROR(kmDNSHelperInvalidServerState, "Invalid server state requested")
-ERROR(kmDNSHelperRacoonConfigCreationFailed, "Could not create racoon configuration file")
-ERROR(kmDNSHelperRacoonStartFailed, "Could not start racoon")
-ERROR(kmDNSHelperRacoonNotificationFailed, "Could not notify racoon")
-ERROR(kmDNSHelperInvalidTunnelSetKeysOperation, "Invalid tunnel setkey operation requested")
-ERROR(kmDNSHelperInvalidNetworkAddress, "Invalid network address")
-ERROR(kmDNSHelperRouteAdditionFailed, "Could not add route")
-ERROR(kmDNSHelperRouteDeletionFailed, "Could not remove route")
-ERROR(kmDNSHelperRoutingSocketCreationFailed, "Could not create routing socket")
-ERROR(kmDNSHelperDatagramSocketCreationFailed, "Could not create datagram socket")
-ERROR(kmDNSHelperIPsecPolicyCreationFailed, "Could not create IPsec policy")
-ERROR(kmDNSHelperIPsecPolicySetFailed, "Could not set IPsec policy")
-ERROR(kmDNSHelperIPsecRemoveSAFailed, "Could not remove IPsec SA")
-ERROR(kmDNSHelperIPsecPolicySocketCreationFailed, "Could not create IPsec policy socket")
-ERROR(kmDNSHelperIPsecDisabled, "IPSec support was not compiled in to the helper")
diff --git a/mDNSResponder/mDNSMacOSX/helper-main.c b/mDNSResponder/mDNSMacOSX/helper-main.c
index 5e4d9481..9c61e48c 100644
--- a/mDNSResponder/mDNSMacOSX/helper-main.c
+++ b/mDNSResponder/mDNSMacOSX/helper-main.c
@@ -24,7 +24,6 @@
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <servers/bootstrap.h>
-#include <asl.h>
#include <launch.h>
#include <pwd.h>
#include <pthread.h>
@@ -37,8 +36,7 @@
#include <Security/Security.h>
#include "helper.h"
#include "helper-server.h"
-#include "helpermsg.h"
-#include "helpermsgServer.h"
+#include <xpc/private.h>
#if TARGET_OS_EMBEDDED
#define NO_SECURITYFRAMEWORK 1
@@ -50,14 +48,11 @@
#define launch_data_get_machport launch_data_get_fd
#endif
-union max_msg_size
-{
- union __RequestUnion__proxy_helper_subsystem req;
- union __ReplyUnion__proxy_helper_subsystem rep;
-};
-static const mach_msg_size_t MAX_MSG_SIZE = sizeof(union max_msg_size) + MAX_TRAILER_SIZE;
-static aslclient logclient = NULL;
+int mDNSHelperLogEnabled = 0;
+os_log_t log_handle = NULL;
+
+static dispatch_queue_t xpc_queue = NULL;
static int opt_debug;
static pthread_t idletimer_thread;
@@ -67,45 +62,24 @@ unsigned long actualidle = 3600;
CFRunLoopRef gRunLoop = NULL;
CFRunLoopTimerRef gTimer = NULL;
-mach_port_t gPort = MACH_PORT_NULL;
-
-static void helplogv(int level, const char *fmt, va_list ap)
-{
- if (NULL == logclient) { vfprintf(stderr, fmt, ap); fflush(stderr); }
- else asl_vlog(logclient, NULL, level, fmt, ap);
-}
-
-void helplog(int level, const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- helplogv(level, fmt, ap);
- va_end(ap);
-}
-
-// for safe_vproc
-void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *fmt, ...)
-{
- (void)logLevel;
- va_list ap;
- va_start(ap, fmt);
- // safe_vproc only calls LogMsg, so assume logLevel maps to ASL_LEVEL_ERR
- helplog(ASL_LEVEL_ERR, fmt, ap);
- va_end(ap);
-}
static void handle_sigterm(int sig)
{
- // debug("entry sig=%d", sig); Can't use syslog from within a signal handler
+ // os_log_debug(log_handle,"entry sig=%d", sig); Can't use syslog from within a signal handler
assert(sig == SIGTERM);
- (void)proxy_mDNSExit(gPort);
+ helper_exit();
}
static void initialize_logging(void)
{
- logclient = asl_open(NULL, "mDNSResponderHelper", (opt_debug ? ASL_OPT_STDERR : 0));
- if (NULL == logclient) { fprintf(stderr, "Could not initialize ASL logging.\n"); fflush(stderr); return; }
- if (opt_debug) asl_set_filter(logclient, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
+ log_handle = os_log_create("com.apple.mDNSResponderHelper", "INFO");
+
+ if (!log_handle)
+ {
+ // OS_LOG_DEFAULT is the default logging object, if you are not creating a custom subsystem/category
+ os_log_error(OS_LOG_DEFAULT, "Could NOT create log handle in mDNSResponderHelper");
+ }
+
}
static void initialize_id(void)
@@ -116,23 +90,29 @@ static void initialize_id(void)
hardcode.pw_uid = 65;
hardcode.pw_gid = 65;
- if (!pwd) { helplog(ASL_LEVEL_ERR, "Could not find account name `%s'. I will only help root.", login); return; }
+ if (!pwd)
+ {
+ os_log(log_handle, "Could not find account name `%s'. I will only help root.", login);
+ return;
+ }
mDNSResponderUID = pwd->pw_uid;
mDNSResponderGID = pwd->pw_gid;
}
static void diediedie(CFRunLoopTimerRef timer, void *context)
{
- debug("entry %p %p %d", timer, context, actualidle);
+ os_log_info(log_handle, "entry %p %p %lu", timer, context, actualidle);
+
assert(gTimer == timer);
- helplog(ASL_LEVEL_INFO, "mDNSResponder exiting after %d seconds", actualidle);
+ os_log_info(log_handle, "mDNSResponderHelper exiting after [%lu] seconds", actualidle);
+
if (actualidle)
- (void)proxy_mDNSExit(gPort);
+ helper_exit();
}
void pause_idle_timer(void)
{
- debug("entry");
+ os_log_debug(log_handle,"entry");
assert(gTimer);
assert(gRunLoop);
CFRunLoopRemoveTimer(gRunLoop, gTimer, kCFRunLoopDefaultMode);
@@ -140,7 +120,7 @@ void pause_idle_timer(void)
void unpause_idle_timer(void)
{
- debug("entry");
+ os_log_debug(log_handle,"entry");
assert(gRunLoop);
assert(gTimer);
CFRunLoopAddTimer(gRunLoop, gTimer, kCFRunLoopDefaultMode);
@@ -148,21 +128,21 @@ void unpause_idle_timer(void)
void update_idle_timer(void)
{
- debug("entry");
+ os_log_debug(log_handle,"entry");
assert(gTimer);
CFRunLoopTimerSetNextFireDate(gTimer, CFAbsoluteTimeGetCurrent() + actualidle);
}
static void *idletimer(void *context)
{
- debug("entry context=%p", context);
- gRunLoop = CFRunLoopGetCurrent();
+ os_log_debug(log_handle,"entry context=%p", context);
+ gRunLoop = CFRunLoopGetMain();
unpause_idle_timer();
for (;;)
{
- debug("Running CFRunLoop");
+ // os_log_debug(log_handle,"Running CFRunLoop");
CFRunLoopRun();
sleep(1);
}
@@ -174,106 +154,504 @@ static int initialize_timer()
{
gTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + actualidle, actualidle, 0, 0, diediedie, NULL);
int err = 0;
+ os_log_info(log_handle, "mDNSResponderHelper initialize_timer() started");
- debug("entry");
if (0 != (err = pthread_create(&idletimer_thread, NULL, idletimer, NULL)))
- helplog(ASL_LEVEL_ERR, "Could not start idletimer thread: %s", strerror(err));
+ os_log(log_handle, "Could not start idletimer thread: %s", strerror(err));
return err;
}
-static mach_port_t register_service(const char *service_name)
+/*
+ Reads the user's program arguments for mDNSResponderHelper
+ For now we have only one option: mDNSHelperDebugLogging which is used to turn on mDNSResponderHelperLogging
+
+ To turn ON mDNSResponderHelper Verbose Logging,
+ 1] sudo defaults write /Library/Preferences/com.apple.mDNSResponderHelper.plist mDNSHelperDebugLogging -bool YES
+ 2] sudo reboot
+
+ To turn OFF mDNSResponderHelper Logging,
+ 1] sudo defaults delete /Library/Preferences/com.apple.mDNSResponderHelper.plist
+
+ To view the current options set,
+ 1] plutil -p /Library/Preferences/com.apple.mDNSResponderHelper.plist
+ OR
+ 1] sudo defaults read /Library/Preferences/com.apple.mDNSResponderHelper.plist
+*/
+
+static mDNSBool HelperPrefsGetValueBool(CFStringRef key, mDNSBool defaultVal)
+{
+ CFBooleanRef boolean;
+ mDNSBool result = defaultVal;
+
+ boolean = CFPreferencesCopyAppValue(key, kmDNSHelperProgramArgs);
+ if (boolean)
+ {
+ if (CFGetTypeID(boolean) == CFBooleanGetTypeID())
+ result = CFBooleanGetValue(boolean) ? mDNStrue : mDNSfalse;
+ CFRelease(boolean);
+ }
+
+ return result;
+}
+
+
+// Verify Client's Entitlement
+static mDNSBool check_entitlement(xpc_connection_t conn, const char *password)
+{
+ mDNSBool entitled = mDNSfalse;
+ xpc_object_t ent = xpc_connection_copy_entitlement_value(conn, password);
+
+ if (ent)
+ {
+ if (xpc_get_type(ent) == XPC_TYPE_BOOL && xpc_bool_get_value(ent))
+ {
+ entitled = mDNStrue;
+ }
+ xpc_release(ent);
+ }
+ else
+ {
+ os_log(log_handle, "client entitlement is NULL");
+ }
+
+ if (!entitled)
+ os_log(log_handle, "entitlement check failed -> client is missing entitlement!");
+
+ return entitled;
+}
+
+
+static void handle_request(xpc_object_t req)
{
- mach_port_t port = MACH_PORT_NULL;
- kern_return_t kr;
+ mDNSu32 helper_mode = 0;
+ int error_code = 0;
+
+ xpc_connection_t remote_conn = xpc_dictionary_get_remote_connection(req);
+ xpc_object_t response = xpc_dictionary_create_reply(req);
+
+ // switch here based on dictionary to handle different requests from mDNSResponder
+ if ((xpc_dictionary_get_uint64(req, kHelperMode)))
+ {
+ os_log_info(log_handle, "Getting mDNSResponder request mode");
+ helper_mode = (mDNSu32)(xpc_dictionary_get_uint64(req, kHelperMode));
+ }
+
+ switch (helper_mode)
+ {
+ case bpf_request:
+ {
+ os_log_info(log_handle, "Calling new RequestBPF()");
+ RequestBPF();
+ break;
+ }
+
+ case set_name:
+ {
+ const char *old_name;
+ const char *new_name;
+ int pref_key = 0;
+
+ pref_key = (int)(xpc_dictionary_get_uint64(req, kPrefsNameKey));
+ old_name = xpc_dictionary_get_string(req, kPrefsOldName);
+ new_name = xpc_dictionary_get_string(req, kPrefsNewName);
+
+ os_log_info(log_handle, "Calling new SetName() oldname: %s newname: %s key:%d", old_name, new_name, pref_key);
+ PreferencesSetName(pref_key, old_name, new_name);
+ break;
+ }
+
+ case p2p_packetfilter:
+ {
+ pfArray_t pfports;
+ pfArray_t pfprotocols;
+ const char *if_name;
+ uint32_t cmd;
+ uint32_t count;
+
+ cmd = xpc_dictionary_get_uint64(req, "pf_opcode");
+ if_name = xpc_dictionary_get_string(req, "pf_ifname");
+ count = xpc_dictionary_get_uint64(req, "pf_count");
+
+ pfports[0] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_port0");
+ pfports[1] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_port1");
+ pfports[2] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_port2");
+ pfports[3] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_port3");
+
+ pfprotocols[0] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_protocol0");
+ pfprotocols[1] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_protocol1");
+ pfprotocols[2] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_protocol2");
+ pfprotocols[3] = (uint16_t)xpc_dictionary_get_uint64(req, "pf_protocol3");
+
+ os_log_info(log_handle,"Calling new PacketFilterControl()");
+ PacketFilterControl(cmd, if_name, count, pfports, pfprotocols);
+ break;
+ }
+
+ case user_notify:
+ {
+ const char *title;
+ const char *msg;
+ title = xpc_dictionary_get_string(req, "notify_title");
+ msg = xpc_dictionary_get_string(req, "notify_msg");
+
+ os_log_info(log_handle,"Calling new UserNotify() title:%s msg:%s", title, msg);
+ UserNotify(title, msg);
+ break;
+ }
+
+ case power_req:
+ {
+ int key, interval;
+ key = xpc_dictionary_get_uint64(req, "powerreq_key");
+ interval = xpc_dictionary_get_uint64(req, "powerreq_interval");
+
+ os_log_info(log_handle,"Calling new PowerRequest() key[%d] interval[%d]", key, interval);
+ PowerRequest(key, interval, &error_code);
+ break;
+ }
+
+ case send_wakepkt:
+ {
+ const char *ether_addr;
+ const char *ip_addr;
+ int iteration;
+ unsigned int if_id;
+
+ if_id = (unsigned int)xpc_dictionary_get_uint64(req, "interface_index");
+ ether_addr = xpc_dictionary_get_string(req, "ethernet_address");
+ ip_addr = xpc_dictionary_get_string(req, "ip_address");
+ iteration = (int)xpc_dictionary_get_uint64(req, "swp_iteration");
+
+ os_log_info(log_handle, "Calling new SendWakeupPacket() ether_addr[%s] ip_addr[%s] if_id[%d] iteration[%d]",
+ ether_addr, ip_addr, if_id, iteration);
+ SendWakeupPacket(if_id, ether_addr, ip_addr, iteration);
+ break;
+ }
+
+ case set_localaddr_cacheentry:
+ {
+ int if_index, family;
+
+ if_index = xpc_dictionary_get_uint64(req, "slace_ifindex");
+ family = xpc_dictionary_get_uint64(req, "slace_family");
+
+ const uint8_t* ip = xpc_dictionary_get_data(req, "slace_ip", NULL);
+ const uint8_t* eth = xpc_dictionary_get_data(req, "slace_eth", NULL);
+
+ os_log_info(log_handle, "Calling new SetLocalAddressCacheEntry() if_index[%d] family[%d] ", if_index, family);
+
+ SetLocalAddressCacheEntry(if_index, family, ip, eth, &error_code);
+
+ /*
+ static int v6addr_to_string(const v6addr_t addr, char *buf, size_t buflen)
+ {
+ if (NULL == inet_ntop(AF_INET6, addr, buf, buflen))
+ {
+ os_log(log_handle, "inet_ntop failed: %s", strerror(errno));
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ ethaddr_t eth = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x01 } ;
+ const uint8_t* slace_ip = NULL;
+ v6addr_t addr_ipv6;
+ size_t ip_len;
+ slace_ip = xpc_dictionary_get_data(req, "slace_ip", &ip_len);
+ if (slace_ip && (ip_len == sizeof(v6addr_t)))
+ {
+ os_log(log_handle, "mDNSResponderHelper: doing memcpy()");
+ memcpy(&addr_ipv6, slace_ip, ip_len);
+ }
+ char test_ipv6_str[46];
+ v6addr_to_string(addr_ipv6, test_ipv6_str, sizeof(test_ipv6_str));
+ os_log(log_handle, "mDNSResponderHelper: handle_request: set_localaddr_cacheentry: test_ipv6_str is %s", test_ipv6_str);
+ */
+
+ break;
+ }
+
+ case send_keepalive:
+ {
+ uint16_t lport, rport, win;
+ uint32_t seq, ack;
+
+ lport = xpc_dictionary_get_uint64(req, "send_keepalive_lport");
+ rport = xpc_dictionary_get_uint64(req, "send_keepalive_rport");
+ seq = xpc_dictionary_get_uint64(req, "send_keepalive_seq");
+ ack = xpc_dictionary_get_uint64(req, "send_keepalive_ack");
+ win = xpc_dictionary_get_uint64(req, "send_keepalive_win");
+
+ const uint8_t* sadd6 = xpc_dictionary_get_data(req, "send_keepalive_sadd", NULL);
+ const uint8_t* dadd6 = xpc_dictionary_get_data(req, "send_keepalive_dadd", NULL);
+
+ os_log_info(log_handle, "helper-main: handle_request: send_keepalive: lport is[%d] rport is[%d] seq is[%d] ack is[%d] win is[%d]",
+ lport, rport, seq, ack, win);
+
+ SendKeepalive(sadd6, dadd6, lport, rport, seq, ack, win);
+ break;
+ }
+
+ case retreive_tcpinfo:
+ {
+ uint16_t lport, rport;
+ int family;
+ uint32_t seq, ack;
+ uint16_t win;
+ int32_t intfid;
+
+ lport = xpc_dictionary_get_uint64(req, "retreive_tcpinfo_lport");
+ rport = xpc_dictionary_get_uint64(req, "retreive_tcpinfo_rport");
+ family = xpc_dictionary_get_uint64(req, "retreive_tcpinfo_family");
+
+ const uint8_t* laddr = xpc_dictionary_get_data(req, "retreive_tcpinfo_laddr", NULL);
+ const uint8_t* raddr = xpc_dictionary_get_data(req, "retreive_tcpinfo_raddr", NULL);
+
+ os_log_info(log_handle, "helper-main: handle_request: retreive_tcpinfo: lport is[%d] rport is[%d] family is [%d]",
+ lport, rport, family);
+
+ RetrieveTCPInfo(family, laddr, lport, raddr, rport, &seq, &ack, &win, &intfid, &error_code);
+
+ if (response)
+ {
+ xpc_dictionary_set_uint64(response, "retreive_tcpinfo_seq", seq);
+ xpc_dictionary_set_uint64(response, "retreive_tcpinfo_ack", ack);
+ xpc_dictionary_set_uint64(response, "retreive_tcpinfo_win", win);
+ xpc_dictionary_set_uint64(response, "retreive_tcpinfo_ifid", intfid);
+ }
+
+ os_log_info(log_handle, "helper-main: handle_request: retreive_tcpinfo: seq is[%d] ack is[%d] win is [%d] intfid is [%d]",
+ seq, ack, win, intfid);
+
+ break;
+ }
+
+ case autotunnel_setkeys:
+ {
+ uint16_t lport, rport;
+ int replace_del;
+ const char *fqdnstr;
+
+ lport = xpc_dictionary_get_uint64(req, "autotunnelsetkeys_lport");
+ rport = xpc_dictionary_get_uint64(req, "autotunnelsetkeys_rport");
+ replace_del = xpc_dictionary_get_uint64(req, "autotunnelsetkeys_repdel");
+
+ const uint8_t* local_inner = xpc_dictionary_get_data(req, "autotunnelsetkeys_localinner", NULL);
+ const uint8_t* local_outer = xpc_dictionary_get_data(req, "autotunnelsetkeys_localouter", NULL);
+ const uint8_t* remote_inner = xpc_dictionary_get_data(req, "autotunnelsetkeys_remoteinner", NULL);
+ const uint8_t* remote_outer = xpc_dictionary_get_data(req, "autotunnelsetkeys_remoteouter", NULL);
+
+ fqdnstr = xpc_dictionary_get_string(req, "autotunnelsetkeys_fqdnStr");
+
+ os_log_info(log_handle, "helper-main: handle_request: autotunnel_setkeys: lport is[%d] rport is[%d] replace_del is [%d]",
+ lport, rport, replace_del);
+
+
+ HelperAutoTunnelSetKeys(replace_del, local_inner, local_outer, lport, remote_inner, remote_outer, rport, fqdnstr, &error_code);
- if (KERN_SUCCESS != (kr = bootstrap_check_in(bootstrap_port, (char *)service_name, &port)))
+ break;
+ }
+
+
+ case keychain_getsecrets:
+ {
+ unsigned int num_sec = 0;
+ unsigned long secrets = 0;
+ unsigned int sec_cnt = 0;
+
+ os_log_info(log_handle,"Calling new KeyChainGetSecrets()");
+
+ KeychainGetSecrets(&num_sec, &secrets, &sec_cnt, &error_code);
+
+ if (response)
+ {
+ xpc_dictionary_set_uint64(response, "keychain_num_secrets", num_sec);
+ xpc_dictionary_set_data(response, "keychain_secrets", (void *)secrets, sec_cnt);
+ xpc_dictionary_set_uint64(response, "keychain_secrets_count", sec_cnt);
+ }
+
+ os_log_info(log_handle,"helper-main: handle_request: keychain_getsecrets: num_secrets is %d, secrets is %lu, secrets_Cnt is %d",
+ num_sec, secrets, sec_cnt);
+
+ if (secrets)
+ vm_deallocate(mach_task_self(), secrets, sec_cnt);
+
+ break;
+ }
+
+ default:
+ {
+ os_log(log_handle, "handle_request: Unrecognized mode!");
+ error_code = kHelperErr_UndefinedMode;
+ break;
+ }
+ }
+
+ // Return Response Status back to the client (essentially ACKing the request)
+ if (response)
{
- helplog(ASL_LEVEL_ERR, "bootstrap_check_in: %d %X %s", kr, kr, mach_error_string(kr));
- return MACH_PORT_NULL;
+ xpc_dictionary_set_uint64(response, kHelperReplyStatus, kHelperReply_ACK);
+ xpc_dictionary_set_int64(response, kHelperErrCode, error_code);
+ xpc_connection_send_message(remote_conn, response);
+ xpc_release(response);
}
+ else
+ {
+ os_log(log_handle, "handle_requests: Response Dictionary could not be created!");
+ return;
+ }
+
+}
+
+static void accept_client(xpc_connection_t conn)
+{
+ int c_pid = xpc_connection_get_pid(conn);
- if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND)))
+ if (!(check_entitlement(conn, kHelperService)))
{
- helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %d %X %s", kr, kr, mach_error_string(kr));
- mach_port_deallocate(mach_task_self(), port);
- return MACH_PORT_NULL;
+ os_log(log_handle, "accept_client: Helper Client PID[%d] is missing Entitlement. Cancelling connection", c_pid);
+ xpc_connection_cancel(conn);
+ return;
}
+
+ xpc_retain(conn);
+ xpc_connection_set_target_queue(conn, xpc_queue);
+ xpc_connection_set_event_handler(conn, ^(xpc_object_t req_msg)
+ {
+ xpc_type_t type = xpc_get_type(req_msg);
+
+ if (type == XPC_TYPE_DICTIONARY)
+ {
+ os_log_info(log_handle,"accept_client:conn:[%p] client[%d](mDNSResponder) requesting service", (void *) conn, c_pid);
+ handle_request(req_msg);
+ }
+ else // We hit this case ONLY if Client Terminated Connection OR Crashed
+ {
+ os_log(log_handle, "accept_client:conn:[%p] client[%d](mDNSResponder) teared down the connection (OR Crashed)", (void *) conn, c_pid);
+ // handle_termination();
+ xpc_release(conn);
+ }
+ });
+
+ xpc_connection_resume(conn);
+}
+
- return port;
+static void init_helper_service(const char *service_name)
+{
+
+ xpc_connection_t xpc_listener = xpc_connection_create_mach_service(service_name, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
+ if (!xpc_listener || xpc_get_type(xpc_listener) != XPC_TYPE_CONNECTION)
+ {
+ os_log(log_handle, "init_helper_service: Error Creating XPC Listener for mDNSResponderHelperService !!");
+ return;
+ }
+
+ os_log_info(log_handle,"init_helper_service: XPC Listener for mDNSResponderHelperService Listening");
+
+ xpc_queue = dispatch_queue_create("com.apple.mDNSHelper.service_queue", NULL);
+
+ xpc_connection_set_event_handler(xpc_listener, ^(xpc_object_t eventmsg)
+ {
+ xpc_type_t type = xpc_get_type(eventmsg);
+
+ if (type == XPC_TYPE_CONNECTION)
+ {
+ os_log_info(log_handle,"init_helper_service: new mDNSResponderHelper Client %p", eventmsg);
+ accept_client(eventmsg);
+ }
+ else if (type == XPC_TYPE_ERROR) // Ideally, we would never hit these cases below
+ {
+ os_log(log_handle, "init_helper_service: XPCError: %s", xpc_dictionary_get_string(eventmsg, XPC_ERROR_KEY_DESCRIPTION));
+ return;
+ }
+ else
+ {
+ os_log(log_handle, "init_helper_service: Unknown EventMsg type");
+ return;
+ }
+ });
+
+ xpc_connection_resume(xpc_listener);
}
+
int main(int ac, char *av[])
{
char *p = NULL;
- kern_return_t kr = KERN_FAILURE;
long n;
int ch;
- mach_msg_header_t hdr;
while ((ch = getopt(ac, av, "dt:")) != -1)
+ {
switch (ch)
{
- case 'd': opt_debug = 1; break;
- case 't':
- n = strtol(optarg, &p, 0);
- if ('\0' == optarg[0] || '\0' != *p || n > LONG_MAX || n < 0)
- { fprintf(stderr, "Invalid idle timeout: %s\n", optarg); exit(EXIT_FAILURE); }
- maxidle = n;
- break;
- case '?':
- default:
- fprintf(stderr, "Usage: mDNSResponderHelper [-d] [-t maxidle]\n");
- exit(EXIT_FAILURE);
+ case 'd':
+ opt_debug = 1;
+ break;
+ case 't':
+ n = strtol(optarg, &p, 0);
+ if ('\0' == optarg[0] || '\0' != *p || n > LONG_MAX || n < 0)
+ {
+ fprintf(stderr, "Invalid idle timeout: %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ maxidle = n;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Usage: mDNSResponderHelper [-d] [-t maxidle]\n");
+ exit(EXIT_FAILURE);
}
+ }
ac -= optind;
av += optind;
(void)ac; // Unused
(void)av; // Unused
initialize_logging();
- helplog(ASL_LEVEL_INFO, "Starting");
initialize_id();
+ mDNSHelperLogEnabled = HelperPrefsGetValueBool(kPreferencesKey_mDNSHelperLog, mDNSHelperLogEnabled);
+
+// Currently on Fuji/Whitetail releases we are keeping the logging always enabled.
+// Hence mDNSHelperLogEnabled is set to true below by default.
+ mDNSHelperLogEnabled = 1;
+
+ os_log_info(log_handle,"mDNSResponderHelper Starting to run");
+
#ifndef NO_SECURITYFRAMEWORK
// We should normally be running as a system daemon. However, that might not be the case in some scenarios (e.g. debugging).
// Explicitly ensure that our Keychain operations utilize the system domain.
- if (opt_debug) SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
+ if (opt_debug)
+ SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
#endif
- gPort = register_service(kmDNSHelperServiceName);
- if (!gPort)
- exit(EXIT_FAILURE);
- if (maxidle) actualidle = maxidle;
+ if (maxidle)
+ actualidle = maxidle;
signal(SIGTERM, handle_sigterm);
- if (initialize_timer()) exit(EXIT_FAILURE);
- for (n=0; n<100000; n++) if (!gRunLoop) usleep(100);
+ if (initialize_timer())
+ exit(EXIT_FAILURE);
+ for (n=0; n<100000; n++)
+ if (!gRunLoop)
+ usleep(100);
+
if (!gRunLoop)
{
- helplog(ASL_LEVEL_ERR, "gRunLoop not set after waiting");
+ os_log(log_handle, "gRunLoop not set after waiting");
exit(EXIT_FAILURE);
}
- for(;;)
- {
- hdr.msgh_bits = 0;
- hdr.msgh_local_port = gPort;
- hdr.msgh_remote_port = MACH_PORT_NULL;
- hdr.msgh_size = sizeof(hdr);
- hdr.msgh_id = 0;
- kr = mach_msg(&hdr, MACH_RCV_LARGE | MACH_RCV_MSG, 0, hdr.msgh_size, gPort, 0, 0);
- if (MACH_RCV_TOO_LARGE != kr)
- helplog(ASL_LEVEL_ERR, "main MACH_RCV_MSG error: %d %X %s", kr, kr, mach_error_string(kr));
-
- kr = mach_msg_server_once(helper_server, MAX_MSG_SIZE, gPort,
- MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0));
- if (KERN_SUCCESS != kr)
- { helplog(ASL_LEVEL_ERR, "mach_msg_server: %d %X %s", kr, kr, mach_error_string(kr)); exit(EXIT_FAILURE); }
-
- }
- exit(EXIT_SUCCESS);
+ init_helper_service(kHelperService);
+ os_log_info(log_handle,"mDNSResponderHelper is now running");
+ dispatch_main();
+
}
// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
diff --git a/mDNSResponder/mDNSMacOSX/helper-server.h b/mDNSResponder/mDNSMacOSX/helper-server.h
index eb0e6ae1..8a342748 100644
--- a/mDNSResponder/mDNSMacOSX/helper-server.h
+++ b/mDNSResponder/mDNSMacOSX/helper-server.h
@@ -18,14 +18,11 @@
#ifndef H_HELPER_SERVER_H
#define H_HELPER_SERVER_H
-extern void helplog(int, const char *, ...);
extern void pause_idle_timer(void);
extern void unpause_idle_timer(void);
extern void update_idle_timer(void);
extern uid_t mDNSResponderUID;
extern uid_t mDNSResponderGID;
extern CFRunLoopRef gRunLoop;
-#define debug(...) debug_(__func__, __VA_ARGS__)
-extern void debug_(const char *func, const char *fmt, ...);
#endif /* H_HELPER_SERVER_H */
diff --git a/mDNSResponder/mDNSMacOSX/helper-stubs.c b/mDNSResponder/mDNSMacOSX/helper-stubs.c
index e08f5050..a1e804fd 100644
--- a/mDNSResponder/mDNSMacOSX/helper-stubs.c
+++ b/mDNSResponder/mDNSMacOSX/helper-stubs.c
@@ -23,9 +23,10 @@
#include <CoreFoundation/CoreFoundation.h>
#include "mDNSDebug.h"
#include "helper.h"
-#include "helpermsg.h"
#include <dispatch/dispatch.h>
#include <arpa/inet.h>
+#include <xpc/private.h>
+#include <Block.h>
//
// Implementation Notes about the HelperQueue:
@@ -40,67 +41,176 @@
// an argument to the function, the blocks can reference them as they are passed in as pointers. But care should
// be taken to copy them locally as they may cease to exist when the function returns.
//
+
+
+//*************************************************************************************************************
+// Globals
static dispatch_queue_t HelperQueue;
+static xpc_connection_t helper_xpc_conn = NULL;
+
+static int64_t maxwait_secs = 5LL;
+
+#define mDNSHELPER_DEBUG LogOperation
-#define ERROR(x, y) y,
-static const char *errorstring[] =
+//*************************************************************************************************************
+// Utility Functions
+
+static void LogDebug(const char *prefix, xpc_object_t o)
{
- #include "helper-error.h"
- NULL
-};
-#undef ERROR
+ char *desc = xpc_copy_description(o);
+ mDNSHELPER_DEBUG("LogDebug %s: %s", prefix, desc);
+ free(desc);
+}
-mDNSexport mStatus mDNSHelperInit()
+//*************************************************************************************************************
+// XPC Funcs:
+//*************************************************************************************************************
+
+
+mDNSlocal void Init_Connection(const char *servname)
{
- HelperQueue = dispatch_queue_create("com.apple.mDNSResponder.HelperQueue", NULL);
- if (HelperQueue == NULL)
+ helper_xpc_conn = xpc_connection_create_mach_service(servname, HelperQueue, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
+
+ xpc_connection_set_event_handler(helper_xpc_conn, ^(xpc_object_t event)
{
- LogMsg("dispatch_queue_create: Helper queue NULL");
- return mStatus_NoMemoryErr;
- }
- return mStatus_NoError;
+ mDNSHELPER_DEBUG("Init_Connection xpc: [%s] \n", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
+ });
+
+ xpc_connection_resume(helper_xpc_conn);
}
-static mach_port_t getHelperPort(int retry)
+mDNSlocal int SendDict_ToServer(xpc_object_t msg)
{
- static mach_port_t port = MACH_PORT_NULL;
- if (retry) port = MACH_PORT_NULL;
- if (port == MACH_PORT_NULL && BOOTSTRAP_SUCCESS != bootstrap_look_up(bootstrap_port, kmDNSHelperServiceName, &port))
- LogMsg("%s: cannot contact helper", __func__);
- return port;
+ __block int errorcode = kHelperErr_NoResponse;
+
+ LogDebug("SendDict_ToServer Sending msg to Daemon", msg);
+
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0);
+ dispatch_retain(sem); // for the block below
+
+ xpc_connection_send_message_with_reply(helper_xpc_conn, msg, HelperQueue, ^(xpc_object_t recv_msg)
+ {
+ xpc_type_t type = xpc_get_type(recv_msg);
+
+ if (type == XPC_TYPE_DICTIONARY)
+ {
+ LogDebug("SendDict_ToServer Received reply msg from Daemon", recv_msg);
+ uint64_t reply_status = xpc_dictionary_get_uint64(recv_msg, kHelperReplyStatus);
+ errorcode = xpc_dictionary_get_int64(recv_msg, kHelperErrCode);
+
+ switch (reply_status)
+ {
+ case kHelperReply_ACK:
+ mDNSHELPER_DEBUG("NoError: successful reply");
+ break;
+ default:
+ LogMsg("default: Unexpected reply from Helper");
+ break;
+ }
+ }
+ else
+ {
+ LogMsg("SendDict_ToServer Received unexpected reply from daemon [%s]",
+ xpc_dictionary_get_string(recv_msg, XPC_ERROR_KEY_DESCRIPTION));
+ LogDebug("SendDict_ToServer Unexpected Reply contents", recv_msg);
+ }
+
+ dispatch_semaphore_signal(sem);
+ dispatch_release(sem);
+
+ });
+
+ if (dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, (maxwait_secs * NSEC_PER_SEC))) != 0)
+ LogMsg("SendDict_ToServer: UNEXPECTED WAIT_TIME in dispatch_semaphore_wait");
+
+ dispatch_release(sem);
+
+ mDNSHELPER_DEBUG("SendDict_ToServer returning with errorcode[%d]", errorcode);
+
+ return errorcode;
}
-const char *mDNSHelperError(int err)
+mDNSlocal xpc_object_t SendDict_GetReply(xpc_object_t msg)
{
- static const char *p = "<unknown error>";
- if (mDNSHelperErrorBase < err && mDNSHelperErrorEnd > err)
- p = errorstring[err - mDNSHelperErrorBase - 1];
- return p;
+ // Create empty dictionary
+ __block xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ if (!dict) return NULL;
+ xpc_retain(dict);
+
+ LogDebug("SendDict_GetReply Sending msg to Daemon", msg);
+
+ dispatch_semaphore_t sem = dispatch_semaphore_create(0);
+ dispatch_retain(sem); // for the block below
+
+ xpc_connection_send_message_with_reply(helper_xpc_conn, msg, HelperQueue, ^(xpc_object_t recv_msg)
+ {
+ xpc_type_t type = xpc_get_type(recv_msg);
+
+ if (type == XPC_TYPE_DICTIONARY)
+ {
+ LogDebug("SendDict_GetReply Received reply msg from Daemon", recv_msg);
+ uint64_t reply_status = xpc_dictionary_get_uint64(recv_msg, kHelperReplyStatus);
+
+ switch (reply_status)
+ {
+ case kHelperReply_ACK:
+ mDNSHELPER_DEBUG("NoError: successful reply");
+ break;
+ default:
+ LogMsg("default: Unexpected reply from Helper");
+ break;
+ }
+ // Copy result into dict reply
+ xpc_dictionary_apply(recv_msg, ^bool(const char *key, xpc_object_t value)
+ {
+ xpc_dictionary_set_value(dict, key, value);
+ return true;
+ });
+ }
+ else
+ {
+ LogMsg("SendDict_GetReply Received unexpected reply from daemon [%s]",
+ xpc_dictionary_get_string(recv_msg, XPC_ERROR_KEY_DESCRIPTION));
+ LogDebug("SendDict_GetReply Unexpected Reply contents", recv_msg);
+ }
+
+ dispatch_semaphore_signal(sem);
+ dispatch_release(sem);
+ xpc_release(dict);
+
+ });
+
+ if (dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, (maxwait_secs * NSEC_PER_SEC))) != 0)
+ {
+ LogMsg("SendDict_GetReply: UNEXPECTED WAIT_TIME in dispatch_semaphore_wait");
+ xpc_release(dict);
+ dispatch_release(sem);
+
+ return NULL;
+ }
+
+ dispatch_release(sem);
+
+ return dict;
}
-/* Ugly but handy. */
-// We don't bother reporting kIOReturnNotReady because that error code occurs in "normal" operation
-// and doesn't indicate anything unexpected that needs to be investigated
+//**************************************************************************************************************
-#define MACHRETRYLOOP_BEGIN(kr, retry, err, fin) \
- for (;;) \
+mDNSexport mStatus mDNSHelperInit()
+{
+ HelperQueue = dispatch_queue_create("com.apple.mDNSResponder.HelperQueue", NULL);
+ if (HelperQueue == NULL)
{
-#define MACHRETRYLOOP_END(kr, retry, err, fin) \
- if (KERN_SUCCESS == (kr)) break; \
- else if (MACH_SEND_INVALID_DEST == (kr) && 0 == (retry)++) continue; \
- else \
- { \
- (err) = kmDNSHelperCommunicationFailed; \
- LogMsg("%s: Mach communication failed: %d %X %s", __func__, kr, kr, mach_error_string(kr)); \
- goto fin; \
- } \
- } \
- if (0 != (err) && kIOReturnNotReady != (err)) \
- { LogMsg("%s: %d 0x%X (%s)", __func__, (err), (err), mDNSHelperError(err)); goto fin; }
+ LogMsg("dispatch_queue_create: Helper queue NULL");
+ return mStatus_NoMemoryErr;
+ }
+ return mStatus_NoError;
+}
void mDNSPreferencesSetName(int key, domainlabel *old, domainlabel *new)
{
- struct {
+ struct
+ {
char oldname[MAX_DOMAIN_LABEL+1];
char newname[MAX_DOMAIN_LABEL+1];
} names;
@@ -109,250 +219,272 @@ void mDNSPreferencesSetName(int key, domainlabel *old, domainlabel *new)
mDNSPlatformMemZero(names.newname, MAX_DOMAIN_LABEL + 1);
ConvertDomainLabelToCString_unescaped(old, names.oldname);
- if (new) ConvertDomainLabelToCString_unescaped(new, names.newname);
- dispatch_async(HelperQueue, ^{
-
- kern_return_t kr = KERN_FAILURE;
- int retry = 0;
- int err = 0;
-
- LogInfo("%s: oldname %s newname %s", __func__, names.oldname, names.newname);
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSPreferencesSetName(getHelperPort(retry), key, names.oldname, names.newname);
- MACHRETRYLOOP_END(kr, retry, err, fin);
-
-fin:
- (void)err;
- });
+
+ if (new)
+ ConvertDomainLabelToCString_unescaped(new, names.newname);
+
+
+ mDNSHELPER_DEBUG("mDNSPreferencesSetName: XPC IPC Test oldname %s newname %s", names.oldname, names.newname);
+ Init_Connection(kHelperService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kHelperMode, set_name);
+
+ xpc_dictionary_set_uint64(dict, kPrefsNameKey, key);
+ xpc_dictionary_set_string(dict, kPrefsOldName, names.oldname);
+ xpc_dictionary_set_string(dict, kPrefsNewName, names.newname);
+
+ SendDict_ToServer(dict);
+ xpc_release(dict);
+ dict = NULL;
+
}
-void mDNSRequestBPF(void)
+void mDNSRequestBPF()
{
- dispatch_async(HelperQueue, ^{
-
- kern_return_t kr = KERN_FAILURE;
- int retry = 0, err = 0;
- LogInfo("%s: BPF", __func__);
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSRequestBPF(getHelperPort(retry));
- MACHRETRYLOOP_END(kr, retry, err, fin);
-fin:
- (void)err;
- });
+ mDNSHELPER_DEBUG("mDNSRequestBPF: Using XPC IPC");
+ Init_Connection(kHelperService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kHelperMode, bpf_request);
+ SendDict_ToServer(dict);
+ xpc_release(dict);
+ dict = NULL;
+
}
int mDNSPowerRequest(int key, int interval)
{
- kern_return_t kr = KERN_FAILURE;
- int retry = 0, err = 0;
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSPowerRequest(getHelperPort(retry), key, interval, &err);
- MACHRETRYLOOP_END(kr, retry, err, fin);
-fin:
- return err;
+ int err_code = kHelperErr_NotConnected;
+
+ mDNSHELPER_DEBUG("mDNSPowerRequest: Using XPC IPC calling out to Helper key is [%d] interval is [%d]", key, interval);
+ Init_Connection(kHelperService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kHelperMode, power_req);
+ xpc_dictionary_set_uint64(dict, "powerreq_key", key);
+ xpc_dictionary_set_uint64(dict, "powerreq_interval", interval);
+
+ err_code = SendDict_ToServer(dict);
+ xpc_release(dict);
+ dict = NULL;
+
+ mDNSHELPER_DEBUG("mDNSPowerRequest: Using XPC IPC returning error_code %d", err_code);
+ return err_code;
}
int mDNSSetLocalAddressCacheEntry(int ifindex, int family, const v6addr_t ip, const ethaddr_t eth)
{
- kern_return_t kr = KERN_FAILURE;
- int retry = 0, err = 0;
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSSetLocalAddressCacheEntry(getHelperPort(retry), ifindex, family, (uint8_t*)ip, (uint8_t*)eth, &err);
- MACHRETRYLOOP_END(kr, retry, err, fin);
-fin:
- return err;
+ int err_code = kHelperErr_NotConnected;
+
+ mDNSHELPER_DEBUG("mDNSSetLocalAddressCacheEntry: Using XPC IPC calling out to Helper: ifindex is [%d] family is [%d]", ifindex, family);
+
+ Init_Connection(kHelperService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kHelperMode, set_localaddr_cacheentry);
+
+ xpc_dictionary_set_uint64(dict, "slace_ifindex", ifindex);
+ xpc_dictionary_set_uint64(dict, "slace_family", family);
+
+ xpc_dictionary_set_data(dict, "slace_ip", (uint8_t*)ip, sizeof(v6addr_t));
+ xpc_dictionary_set_data(dict, "slace_eth", (uint8_t*)eth, sizeof(ethaddr_t));
+
+ err_code = SendDict_ToServer(dict);
+ xpc_release(dict);
+ dict = NULL;
+
+ mDNSHELPER_DEBUG("mDNSSetLocalAddressCacheEntry: Using XPC IPC returning error_code %d", err_code);
+ return err_code;
}
+
void mDNSNotify(const char *title, const char *msg) // Both strings are UTF-8 text
{
- char *titleCopy = NULL;
- char *msgCopy = NULL;
-
- if (title)
- {
- // Don’t try to call mDNSPlatformMem* routines here, because they call validatelists,
- // which calls back into mDNSNotify, resulting an infinite loop until stack space is exhausted
- int len = strlen(title);
- titleCopy = malloc(len + 1);
- if (!titleCopy)
- {
- LogMsg("mDNSNotify: titleCopy NULL for %s", msg);
- return;
- }
- memcpy(titleCopy, title, len);
- titleCopy[len] = 0;
- }
- if (msg)
- {
- int len = strlen(msg);
- msgCopy = malloc(len + 1);
- if (!msgCopy)
- {
- LogMsg("mDNSNotify: msgCopy NULL for %s", msg);
- return;
- }
- memcpy(msgCopy, msg, len);
- msgCopy[len] = 0;
- }
-
- dispatch_async(HelperQueue, ^{
-
- kern_return_t kr = KERN_FAILURE;
- int retry = 0, err = 0;
-
- LogInfo("%s: title %s, msg %s", __func__, titleCopy, msgCopy);
+ mDNSHELPER_DEBUG("mDNSNotify() calling out to Helper XPC IPC title[%s] msg[%s]", title, msg);
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSNotify(getHelperPort(retry), titleCopy, msgCopy);
- MACHRETRYLOOP_END(kr, retry, err, fin);
-fin:
- // Don’t try to call mDNSPlatformMem* routines here, because they call validatelists,
- // which calls back into mDNSNotify, resulting an infinite loop until stack space is exhausted
- free(titleCopy);
- free(msgCopy);
- (void)err;
- });
+ Init_Connection(kHelperService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kHelperMode, user_notify);
+
+ xpc_dictionary_set_string(dict, "notify_title", title);
+ xpc_dictionary_set_string(dict, "notify_msg", msg);
+
+ SendDict_ToServer(dict);
+ xpc_release(dict);
+ dict = NULL;
+
}
+
int mDNSKeychainGetSecrets(CFArrayRef *result)
{
+
CFPropertyListRef plist = NULL;
CFDataRef bytes = NULL;
- kern_return_t kr = KERN_FAILURE;
unsigned int numsecrets = 0;
- vm_offset_t secrets = 0;
- mach_msg_type_number_t secretsCnt = 0;
- int retry = 0, err = 0;
-
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSKeychainGetSecrets(getHelperPort(retry), &numsecrets, &secrets, &secretsCnt, &err);
- MACHRETRYLOOP_END(kr, retry, err, fin);
+ unsigned int secretsCnt = 0;
+ int error_code = kHelperErr_NotConnected;
+ xpc_object_t reply_dict = NULL;
+ const void *sec = NULL;
+ size_t secrets_size = 0;
+
+ mDNSHELPER_DEBUG("mDNSKeychainGetSecrets: Using XPC IPC calling out to Helper");
+
+ Init_Connection(kHelperService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kHelperMode, keychain_getsecrets);
- if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (void*)secrets, secretsCnt, kCFAllocatorNull)))
+ reply_dict = SendDict_GetReply(dict);
+
+ if (reply_dict != NULL)
{
- err = kmDNSHelperCreationFailed;
- LogMsg("%s: CFDataCreateWithBytesNoCopy failed", __func__);
+ numsecrets = xpc_dictionary_get_uint64(reply_dict, "keychain_num_secrets");
+ sec = xpc_dictionary_get_data(reply_dict, "keychain_secrets", &secrets_size);
+ secretsCnt = xpc_dictionary_get_uint64(reply_dict, "keychain_secrets_count");
+ error_code = xpc_dictionary_get_int64(reply_dict, kHelperErrCode);
+ }
+
+ mDNSHELPER_DEBUG("mDNSKeychainGetSecrets: Using XPC IPC calling out to Helper: numsecrets is %d, secretsCnt is %d error_code is %d secret_size is %d",
+ numsecrets, secretsCnt, error_code, secrets_size);
+
+ if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (void*)sec, secretsCnt, kCFAllocatorNull)))
+ {
+ error_code = kHelperErr_ApiErr;
+ LogMsg("mDNSKeychainGetSecrets: CFDataCreateWithBytesNoCopy failed");
goto fin;
}
+
if (NULL == (plist = CFPropertyListCreateWithData(kCFAllocatorDefault, bytes, kCFPropertyListImmutable, NULL, NULL)))
{
- err = kmDNSHelperInvalidPList;
- LogMsg("%s: CFPropertyListCreateFromXMLData failed", __func__);
+ error_code = kHelperErr_ApiErr;
+ LogMsg("mDNSKeychainGetSecrets: CFPropertyListCreateFromXMLData failed");
goto fin;
}
+
if (CFArrayGetTypeID() != CFGetTypeID(plist))
{
- err = kmDNSHelperTypeError;
- LogMsg("%s: Unexpected result type", __func__);
+ error_code = kHelperErr_ApiErr;
+ LogMsg("mDNSKeychainGetSecrets: Unexpected result type");
CFRelease(plist);
plist = NULL;
goto fin;
}
+
*result = (CFArrayRef)plist;
-
+
+
fin:
- if (bytes) CFRelease(bytes);
- if (secrets) vm_deallocate(mach_task_self(), secrets, secretsCnt);
- return err;
+ if (bytes)
+ CFRelease(bytes);
+ if (dict)
+ xpc_release(dict);
+ if (reply_dict)
+ xpc_release(reply_dict);
+
+ dict = NULL;
+ reply_dict = NULL;
+
+ return error_code;
}
-void mDNSConfigureServer(int updown, const char *const prefix, const domainname *const fqdn)
-{
- struct
- {
- // Assume the prefix is no larger than 10 chars
- char fqdnStr[MAX_ESCAPED_DOMAIN_NAME + 10];
- } name;
-
- mDNSPlatformMemZero(name.fqdnStr, MAX_DOMAIN_LABEL + 10);
-
- if (fqdn)
- {
- mDNSPlatformStrCopy(name.fqdnStr, prefix);
- ConvertDomainNameToCString(fqdn, name.fqdnStr + mDNSPlatformStrLen(prefix));
- }
-
- dispatch_async(HelperQueue, ^{
-
- kern_return_t kr = KERN_SUCCESS;
- int retry = 0, err = 0;
-
- LogInfo("%s: fqdnStr %s", __func__, name.fqdnStr);
-
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSConfigureServer(getHelperPort(retry), updown, name.fqdnStr);
- MACHRETRYLOOP_END(kr, retry, err, fin);
-fin:
- (void)err;
-
- });
-}
int mDNSAutoTunnelSetKeys(int replacedelete, v6addr_t local_inner,
v6addr_t local_outer, short local_port, v6addr_t remote_inner,
v6addr_t remote_outer, short remote_port, const char* const prefix, const domainname *const fqdn)
{
- kern_return_t kr = KERN_SUCCESS;
- int retry = 0, err = 0;
+
+ int err_code = kHelperErr_NotConnected;
+
+ mDNSHELPER_DEBUG("mDNSAutoTunnelSetKeys: Using XPC IPC calling out to Helper. Parameters are repdel[%d], lport[%d], rport[%d], prefix[%s], fqdn[%##s]",
+ replacedelete, local_port, remote_port, prefix, fqdn->c);
+
+
+ char buf1[INET6_ADDRSTRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+ char buf3[INET6_ADDRSTRLEN];
+ char buf4[INET6_ADDRSTRLEN];
+
+ buf1[0] = 0;
+ buf2[0] = 0;
+ buf3[0] = 0;
+ buf4[0] = 0;
+
+ inet_ntop(AF_INET6, local_inner, buf1, sizeof(buf1));
+ inet_ntop(AF_INET6, local_outer, buf2, sizeof(buf2));
+ inet_ntop(AF_INET6, remote_inner, buf3, sizeof(buf3));
+ inet_ntop(AF_INET6, remote_outer, buf4, sizeof(buf4));
+
char fqdnStr[MAX_ESCAPED_DOMAIN_NAME + 10] = { 0 }; // Assume the prefix is no larger than 10 chars
if (fqdn)
{
mDNSPlatformStrCopy(fqdnStr, prefix);
ConvertDomainNameToCString(fqdn, fqdnStr + mDNSPlatformStrLen(prefix));
}
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSAutoTunnelSetKeys(getHelperPort(retry), replacedelete, local_inner, local_outer, local_port, remote_inner, remote_outer, remote_port, fqdnStr, &err);
- MACHRETRYLOOP_END(kr, retry, err, fin);
-fin:
- return err;
-}
+
+ mDNSHELPER_DEBUG("mDNSAutoTunnelSetKeys: Using XPC IPC calling out to Helper: Parameters are local_inner is %s, local_outeris %s, remote_inner is %s, remote_outer is %s",
+ buf1, buf2, buf3, buf4);
+
+ Init_Connection(kHelperService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kHelperMode, autotunnel_setkeys);
+
+ xpc_dictionary_set_data(dict, "autotunnelsetkeys_localinner", (uint8_t*)local_inner, sizeof(v6addr_t));
+ xpc_dictionary_set_data(dict, "autotunnelsetkeys_localouter", (uint8_t*)local_outer, sizeof(v6addr_t));
+ xpc_dictionary_set_data(dict, "autotunnelsetkeys_remoteinner", (uint8_t*)remote_inner, sizeof(v6addr_t));
+ xpc_dictionary_set_data(dict, "autotunnelsetkeys_remoteouter", (uint8_t*)remote_outer, sizeof(v6addr_t));
+
+ xpc_dictionary_set_uint64(dict, "autotunnelsetkeys_lport", local_port);
+ xpc_dictionary_set_uint64(dict, "autotunnelsetkeys_rport", remote_port);
+ xpc_dictionary_set_uint64(dict, "autotunnelsetkeys_repdel", replacedelete);
-void mDNSSendWakeupPacket(unsigned ifid, char *eth_addr, char *ip_addr, int iteration)
-{
- char *ip_addr_copy = NULL;
- char *eth_addr_copy = NULL;
+ // xpc_dictionary_set_string(dict, "autotunnelsetkeys_prefix", prefix);
+ xpc_dictionary_set_string(dict, "autotunnelsetkeys_fqdnStr", fqdnStr);
+
+ err_code = SendDict_ToServer(dict);
+
+ xpc_release(dict);
+ dict = NULL;
- if (eth_addr)
- {
- int len = strlen(eth_addr);
- eth_addr_copy = mDNSPlatformMemAllocate(len + 1);
- if (!eth_addr_copy)
- {
- LogMsg("mDNSSendWakeupPacket: eth_addr_copy NULL for %s", eth_addr);
- return;
- }
- mDNSPlatformMemCopy(eth_addr_copy, eth_addr, len);
- eth_addr_copy[len] = 0;
- }
- if (ip_addr)
- {
- int len = strlen(ip_addr);
- ip_addr_copy = mDNSPlatformMemAllocate(len + 1);
- if (!ip_addr_copy)
- {
- LogMsg("mDNSSendWakeupPacket: ip_addr_copy NULL for %s", ip_addr);
- return;
- }
- mDNSPlatformMemCopy(ip_addr_copy, ip_addr, len);
- ip_addr_copy[len] = 0;
- }
- dispatch_async(HelperQueue, ^{
+ mDNSHELPER_DEBUG("mDNSAutoTunnelSetKeys: Using XPC IPC returning error_code %d", err_code);
+
+ mDNSHELPER_DEBUG("mDNSAutoTunnelSetKeys: this should NOT be done in mDNSResponder/Helper. For future we shall be using <rdar://problem/13792729>");
+ return err_code;
+}
- kern_return_t kr = KERN_SUCCESS;
- int retry = 0, err = 0;
+void mDNSSendWakeupPacket(unsigned int ifid, char *eth_addr, char *ip_addr, int iteration)
+{
+ // (void) ip_addr; // unused
+ // (void) iteration; // unused
- LogInfo("%s: Entered ethernet address %s, ip address %s", __func__, eth_addr_copy, ip_addr_copy);
+ mDNSHELPER_DEBUG("mDNSSendWakeupPacket: Entered ethernet address[%s],ip_address[%s], interface_id[%d], iteration[%d]",
+ eth_addr, ip_addr, ifid, iteration);
+
+ Init_Connection(kHelperService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kHelperMode, send_wakepkt);
+
+ xpc_dictionary_set_uint64(dict, "interface_index", ifid);
+ xpc_dictionary_set_string(dict, "ethernet_address", eth_addr);
+ xpc_dictionary_set_string(dict, "ip_address", ip_addr);
+ xpc_dictionary_set_uint64(dict, "swp_iteration", iteration);
+
+ SendDict_ToServer(dict);
+ xpc_release(dict);
+ dict = NULL;
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSSendWakeupPacket(getHelperPort(retry), ifid, eth_addr_copy, ip_addr_copy, iteration);
- MACHRETRYLOOP_END(kr, retry, err, fin);
-fin:
- if (eth_addr_copy)
- mDNSPlatformMemFree(eth_addr_copy);
- if (ip_addr_copy)
- mDNSPlatformMemFree(ip_addr_copy);
- (void) err;
- });
}
void mDNSPacketFilterControl(uint32_t command, char * ifname, uint32_t count, pfArray_t portArray, pfArray_t protocolArray)
@@ -362,138 +494,127 @@ void mDNSPacketFilterControl(uint32_t command, char * ifname, uint32_t count, pf
pfArray_t portArray;
pfArray_t protocolArray;
} pfa;
- char *ifnameCopy = NULL;
mDNSPlatformMemCopy(pfa.portArray, portArray, sizeof(pfArray_t));
mDNSPlatformMemCopy(pfa.protocolArray, protocolArray, sizeof(pfArray_t));
- if (ifname)
- {
- int len = strlen(ifname);
- ifnameCopy = mDNSPlatformMemAllocate(len + 1);
- if (!ifnameCopy)
- {
- LogMsg("mDNSPacketFilterControl: ifnameCopy NULL");
- return;
- }
- mDNSPlatformMemCopy(ifnameCopy, ifname, len);
- ifnameCopy[len] = 0;
- }
- dispatch_async(HelperQueue, ^{
- kern_return_t kr = KERN_SUCCESS;
- int retry = 0, err = 0;
-
- LogInfo("%s, ifname %s", __func__, ifnameCopy);
+ mDNSHELPER_DEBUG("mDNSPacketFilterControl: XPC IPC, ifname %s", ifname);
+ Init_Connection(kHelperService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kHelperMode, p2p_packetfilter);
+
+ xpc_dictionary_set_uint64(dict, "pf_opcode", command);
+ if (ifname)
+ xpc_dictionary_set_string(dict, "pf_ifname", ifname);
+ xpc_dictionary_set_uint64(dict, "pf_count", count);
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSPacketFilterControl(getHelperPort(retry), command, ifnameCopy, count, (uint16_t *)pfa.portArray, (uint16_t *)pfa.protocolArray);
- MACHRETRYLOOP_END(kr, retry, err, fin);
-fin:
- if (ifnameCopy)
- mDNSPlatformMemFree(ifnameCopy);
- (void) err;
- });
+ xpc_dictionary_set_uint64(dict, "pf_port0", pfa.portArray[0]);
+ xpc_dictionary_set_uint64(dict, "pf_port1", pfa.portArray[1]);
+ xpc_dictionary_set_uint64(dict, "pf_port2", pfa.portArray[2]);
+ xpc_dictionary_set_uint64(dict, "pf_port3", pfa.portArray[3]);
+
+ xpc_dictionary_set_uint64(dict, "pf_protocol0", pfa.protocolArray[0]);
+ xpc_dictionary_set_uint64(dict, "pf_protocol1", pfa.protocolArray[1]);
+ xpc_dictionary_set_uint64(dict, "pf_protocol2", pfa.protocolArray[2]);
+ xpc_dictionary_set_uint64(dict, "pf_protocol3", pfa.protocolArray[3]);
+ SendDict_ToServer(dict);
+ xpc_release(dict);
+ dict = NULL;
+
+ mDNSHELPER_DEBUG("mDNSPacketFilterControl: portArray0[%d] portArray1[%d] portArray2[%d] portArray3[%d] protocolArray0[%d] protocolArray1[%d] protocolArray2[%d] protocolArray3[%d]",
+ pfa.portArray[0], pfa.portArray[1], pfa.portArray[2], pfa.portArray[3], pfa.protocolArray[0], pfa.protocolArray[1], pfa.protocolArray[2], pfa.protocolArray[3]);
+
}
-void mDNSSendKeepalive(v6addr_t sadd, v6addr_t dadd, uint16_t lport, uint16_t rport, unsigned seq, unsigned ack, uint16_t win)
+void mDNSSendKeepalive(const v6addr_t sadd, const v6addr_t dadd, uint16_t lport, uint16_t rport, uint32_t seq, uint32_t ack, uint16_t win)
{
- struct
- {
- v6addr_t sadd;
- v6addr_t dadd;
- } addr;
-
- mDNSPlatformMemCopy(addr.sadd, sadd, sizeof(v6addr_t));
- mDNSPlatformMemCopy(addr.dadd, dadd, sizeof(v6addr_t));
-
- dispatch_async(HelperQueue, ^{
- kern_return_t kr = KERN_FAILURE;
- int retry = 0, err = 0;
- char buf1[INET6_ADDRSTRLEN];
- char buf2[INET6_ADDRSTRLEN];
-
- buf1[0] = 0;
- buf2[0] = 0;
-
- inet_ntop(AF_INET6, addr.sadd, buf1, sizeof(buf1));
- inet_ntop(AF_INET6, addr.dadd, buf2, sizeof(buf2));
- LogInfo("%s: sadd is %s, dadd is %s", __func__, buf1, buf2);
-
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSSendKeepalive(getHelperPort(retry), (uint8_t *)addr.sadd, (uint8_t *)addr.dadd, lport, rport, seq, ack, win);
- MACHRETRYLOOP_END(kr, retry, err, fin);
-fin:
- (void) err;
- });
+ mDNSHELPER_DEBUG("mDNSSendKeepalive: Using XPC IPC calling out to Helper: lport is[%d] rport is[%d] seq is[%d] ack is[%d] win is[%d]",
+ lport, rport, seq, ack, win);
+
+ char buf1[INET6_ADDRSTRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+
+ buf1[0] = 0;
+ buf2[0] = 0;
+
+ inet_ntop(AF_INET6, sadd, buf1, sizeof(buf1));
+ inet_ntop(AF_INET6, dadd, buf2, sizeof(buf2));
+ mDNSHELPER_DEBUG("mDNSSendKeepalive: Using XPC IPC calling out to Helper: sadd is %s, dadd is %s", buf1, buf2);
+
+ Init_Connection(kHelperService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kHelperMode, send_keepalive);
+
+ xpc_dictionary_set_data(dict, "send_keepalive_sadd", (uint8_t*)sadd, sizeof(v6addr_t));
+ xpc_dictionary_set_data(dict, "send_keepalive_dadd", (uint8_t*)dadd, sizeof(v6addr_t));
+
+ xpc_dictionary_set_uint64(dict, "send_keepalive_lport", lport);
+ xpc_dictionary_set_uint64(dict, "send_keepalive_rport", rport);
+ xpc_dictionary_set_uint64(dict, "send_keepalive_seq", seq);
+ xpc_dictionary_set_uint64(dict, "send_keepalive_ack", ack);
+ xpc_dictionary_set_uint64(dict, "send_keepalive_win", win);
+
+ SendDict_ToServer(dict);
+ xpc_release(dict);
+ dict = NULL;
+
}
int mDNSRetrieveTCPInfo(int family, v6addr_t laddr, uint16_t lport, v6addr_t raddr, uint16_t rport, uint32_t *seq, uint32_t *ack, uint16_t *win, int32_t *intfid)
{
- kern_return_t kr = KERN_FAILURE;
- int retry = 0, err = 0;
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSRetrieveTCPInfo(getHelperPort(retry), family, (uint8_t *)laddr, lport, (uint8_t *)raddr, rport, seq, ack, win, intfid);
- MACHRETRYLOOP_END(kr, retry, err, fin);
-fin:
- return err;
-}
-
-void mDNSGetRemoteMAC(mDNS *const m, int family, v6addr_t raddr)
-{
- struct {
- v6addr_t addr;
- } dst;
-
- mDNSPlatformMemCopy(dst.addr, raddr, sizeof(v6addr_t));
- dispatch_async(HelperQueue, ^{
- kern_return_t kr = KERN_FAILURE;
- int retry = 0, err = 0;
- ethaddr_t eth;
- IPAddressMACMapping *addrMapping;
-
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSGetRemoteMAC(getHelperPort(retry), family, (uint8_t *)dst.addr, eth);
- MACHRETRYLOOP_END(kr, retry, err, fin);
- // If the call to get the remote MAC address succeeds, allocate and copy
- // the values and schedule a task to update the MAC address in the TCP Keepalive record.
- if (kr == KERN_SUCCESS)
- {
- addrMapping = mDNSPlatformMemAllocate(sizeof(IPAddressMACMapping));
- snprintf(addrMapping->ethaddr, sizeof(addrMapping->ethaddr), "%02x:%02x:%02x:%02x:%02x:%02x",
- eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
- if (family == AF_INET)
- {
- addrMapping->ipaddr.type = mDNSAddrType_IPv4;
- mDNSPlatformMemCopy(addrMapping->ipaddr.ip.v4.b, dst.addr, sizeof(v6addr_t));
- }
- else
- {
- addrMapping->ipaddr.type = mDNSAddrType_IPv6;
- mDNSPlatformMemCopy(addrMapping->ipaddr.ip.v6.b, dst.addr, sizeof(v6addr_t));
- }
- mDNSPlatformDispatchAsync(m, addrMapping, UpdateRMACCallback);
- }
-fin:
- (void) err;
- });
-
-}
-
-void mDNSStoreSPSMACAddress(int family, v6addr_t spsaddr, char *ifname)
-{
- struct {
- v6addr_t saddr;
- } addr;
- mDNSPlatformMemCopy(addr.saddr, spsaddr, sizeof(v6addr_t));
-
- dispatch_async(HelperQueue, ^{
- kern_return_t kr = KERN_FAILURE;
- int retry = 0, err = 0;
- MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
- kr = proxy_mDNSStoreSPSMACAddress(getHelperPort(retry), family, (uint8_t *)addr.saddr, ifname);
- MACHRETRYLOOP_END(kr, retry, err, fin);
-fin:
- (void)err;
- });
+ int error_code = kHelperErr_NotConnected;
+ xpc_object_t reply_dict = NULL;
+
+ mDNSHELPER_DEBUG("mDNSRetrieveTCPInfo: Using XPC IPC calling out to Helper: lport is[%d] rport is[%d] family is[%d]",
+ lport, rport, family);
+
+ char buf1[INET6_ADDRSTRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+ buf1[0] = 0;
+ buf2[0] = 0;
+
+ inet_ntop(AF_INET6, laddr, buf1, sizeof(buf1));
+ inet_ntop(AF_INET6, raddr, buf2, sizeof(buf2));
+ mDNSHELPER_DEBUG("mDNSRetrieveTCPInfo:: Using XPC IPC calling out to Helper: laddr is %s, raddr is %s", buf1, buf2);
+
+ Init_Connection(kHelperService);
+
+ // Create Dictionary To Send
+ xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_uint64(dict, kHelperMode, retreive_tcpinfo);
+
+ xpc_dictionary_set_data(dict, "retreive_tcpinfo_laddr", (uint8_t*)laddr, sizeof(v6addr_t));
+ xpc_dictionary_set_data(dict, "retreive_tcpinfo_raddr", (uint8_t*)raddr, sizeof(v6addr_t));
+
+ xpc_dictionary_set_uint64(dict, "retreive_tcpinfo_family", family);
+ xpc_dictionary_set_uint64(dict, "retreive_tcpinfo_lport", lport);
+ xpc_dictionary_set_uint64(dict, "retreive_tcpinfo_rport", rport);
+
+ reply_dict = SendDict_GetReply(dict);
+
+ if (reply_dict != NULL)
+ {
+ *seq = xpc_dictionary_get_uint64(reply_dict, "retreive_tcpinfo_seq");
+ *ack = xpc_dictionary_get_uint64(reply_dict, "retreive_tcpinfo_ack");
+ *win = xpc_dictionary_get_uint64(reply_dict, "retreive_tcpinfo_win");
+ *intfid = (int32_t)xpc_dictionary_get_uint64(reply_dict, "retreive_tcpinfo_ifid");
+ error_code = xpc_dictionary_get_int64(reply_dict, kHelperErrCode);
+ }
+
+ mDNSHELPER_DEBUG("mDNSRetrieveTCPInfo: Using XPC IPC calling out to Helper: seq is %d, ack is %d, win is %d, intfid is %d, error is %d",
+ *seq, *ack, *win, *intfid, error_code);
+
+ if (dict)
+ xpc_release(dict);
+ if (reply_dict)
+ xpc_release(reply_dict);
+ dict = NULL;
+ reply_dict = NULL;
+
+ return error_code;
}
diff --git a/mDNSResponder/mDNSMacOSX/helper.c b/mDNSResponder/mDNSMacOSX/helper.c
index 7cf0e523..f5b4f3b2 100644
--- a/mDNSResponder/mDNSMacOSX/helper.c
+++ b/mDNSResponder/mDNSMacOSX/helper.c
@@ -30,7 +30,6 @@
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/socket.h>
-#include <asl.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
@@ -53,9 +52,7 @@
#include "dnssd_ipc.h"
#include "libpfkey.h"
#include "helper.h"
-#include "helpermsgServer.h"
#include "helper-server.h"
-#include "ipsec_options.h"
#include "P2PPacketFilter.h"
#include <netinet/ip.h>
@@ -71,6 +68,7 @@
#ifndef MDNS_NO_IPSEC
#define MDNS_NO_IPSEC 1
#endif
+
#define NO_CFUSERNOTIFICATION 1
#define NO_SECURITYFRAMEWORK 1
#endif
@@ -81,79 +79,51 @@
typedef struct sadb_x_policy *ipsec_policy_t;
-unsigned short InetChecksum(unsigned short *ptr,int nbytes);
-unsigned long in_cksum(unsigned short *ptr,int nbytes);
-void TCPCheckSum(int af, struct tcphdr *t, int tcplen, v6addr_t sadd6, v6addr_t dadd6);
-
uid_t mDNSResponderUID;
gid_t mDNSResponderGID;
-void
-debug_(const char *func, const char *fmt, ...)
-{
- char buf[2048];
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
- helplog(ASL_LEVEL_DEBUG, "%s: %s", func, buf);
-}
-
-static int
-authorized(audit_token_t *token)
+void helper_exit()
{
- int ok = 0;
- pid_t pid = (pid_t)-1;
- uid_t euid = (uid_t)-1;
-
- audit_token_to_au32(*token, NULL, &euid, NULL, NULL, NULL, &pid, NULL,
- NULL);
- ok = (euid == mDNSResponderUID || euid == 0);
- if (!ok)
- helplog(ASL_LEVEL_NOTICE,
- "Unauthorized access by euid=%lu pid=%lu",
- (unsigned long)euid, (unsigned long)pid);
- return ok;
-}
-
-kern_return_t
-do_mDNSExit(__unused mach_port_t port, audit_token_t token)
-{
- debug("entry");
- if (!authorized(&token))
- goto fin;
- helplog(ASL_LEVEL_INFO, "exit");
+ os_log_info(log_handle,"mDNSResponderHelper exiting");
exit(0);
-
-fin:
- debug("fin");
- return KERN_SUCCESS;
}
-kern_return_t do_mDNSRequestBPF(__unused mach_port_t port, audit_token_t token)
+mDNSexport void RequestBPF()
{
- if (!authorized(&token)) return KERN_SUCCESS;
DNSServiceRef ref;
+
DNSServiceErrorType err = ConnectToServer(&ref, 0, send_bpf, NULL, NULL, NULL);
- if (err) { helplog(ASL_LEVEL_ERR, "do_mDNSRequestBPF: ConnectToServer %d", err); return err; }
-
+ if (err)
+ {
+ os_log(log_handle, "RequestBPF: ConnectToServer %d", err);
+ return;
+ }
+
char *ptr;
size_t len = sizeof(DNSServiceFlags);
ipc_msg_hdr *hdr = create_hdr(send_bpf, &len, &ptr, 0, ref);
- if (!hdr) { DNSServiceRefDeallocate(ref); return kDNSServiceErr_NoMemory; }
+ if (!hdr)
+ {
+ os_log(log_handle, "RequestBPF: No mem to allocate");
+ DNSServiceRefDeallocate(ref);
+ return;
+ }
+
put_flags(0, &ptr);
deliver_request(hdr, ref); // Will free hdr for us
DNSServiceRefDeallocate(ref);
update_idle_timer();
- return KERN_SUCCESS;
+
+ os_log_info(log_handle,"RequestBPF: Successful");
}
-kern_return_t do_mDNSPowerRequest(__unused mach_port_t port, int key, int interval, int *err, audit_token_t token)
-{
- *err = -1;
- if (!authorized(&token)) { *err = kmDNSHelperNotAuthorized; goto fin; }
+void PowerRequest(int key, int interval, int *err)
+{
+ *err = kHelperErr_DefaultErr;
+
+ os_log_info(log_handle,"PowerRequest: key %d interval %d, err %d", key, interval, *err);
+
CFArrayRef events = IOPMCopyScheduledPowerEvents();
if (events)
{
@@ -168,19 +138,26 @@ kern_return_t do_mDNSPowerRequest(__unused mach_port_t port, int key, int interv
CFDateRef EventTime = CFDictionaryGetValue(dict, CFSTR(kIOPMPowerEventTimeKey));
CFStringRef EventType = CFDictionaryGetValue(dict, CFSTR(kIOPMPowerEventTypeKey));
IOReturn result = IOPMCancelScheduledPowerEvent(EventTime, id, EventType);
- //helplog(ASL_LEVEL_ERR, "Deleting old event %s");
- if (result) helplog(ASL_LEVEL_ERR, "IOPMCancelScheduledPowerEvent %d failed %d", i, result);
+ //os_log(log_handle, "Deleting old event %s");
+ if (result)
+ os_log(log_handle, "IOPMCancelScheduledPowerEvent %d failed %d", i, result);
}
}
CFRelease(events);
}
-
- if (key < 0) // mDNSPowerRequest(-1,-1) means "clear any stale schedules" (see above)
- *err = 0;
+
+ if (key < 0) // mDNSPowerRequest(-1,-1) means "clear any stale schedules" (see above)
+ {
+ *err = kHelperErr_NoErr;
+ }
else if (key == 0) // mDNSPowerRequest(0, 0) means "sleep now"
{
IOReturn r = IOPMSleepSystem(IOPMFindPowerManagement(MACH_PORT_NULL));
- if (r) { usleep(100000); helplog(ASL_LEVEL_ERR, "IOPMSleepSystem %d", r); }
+ if (r)
+ {
+ usleep(100000);
+ os_log_info(log_handle, "IOPMSleepSystem %d", r);
+ }
*err = r;
}
else if (key > 0)
@@ -189,48 +166,51 @@ kern_return_t do_mDNSPowerRequest(__unused mach_port_t port, int key, int interv
if (wakeTime)
{
CFMutableDictionaryRef scheduleDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
+
CFDictionaryAddValue(scheduleDict, CFSTR(kIOPMPowerEventTimeKey), wakeTime);
CFDictionaryAddValue(scheduleDict, CFSTR(kIOPMPowerEventAppNameKey), CFSTR("mDNSResponderHelper"));
CFDictionaryAddValue(scheduleDict, CFSTR(kIOPMPowerEventTypeKey), key ? CFSTR(kIOPMAutoWake) : CFSTR(kIOPMAutoSleep));
-
+
IOReturn r = IOPMRequestSysWake(scheduleDict);
if (r)
{
usleep(100000);
- helplog(ASL_LEVEL_ERR, "IOPMRequestSysWake(%d) %d %x", interval, r, r);
+ os_log_info(log_handle, "IOPMRequestSysWake(%d) %d %x", interval, r, r);
}
*err = r;
CFRelease(wakeTime);
CFRelease(scheduleDict);
}
}
-fin:
+
update_idle_timer();
- return KERN_SUCCESS;
}
-kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int ifindex, int family, v6addr_t ip, ethaddr_t eth, int *err, audit_token_t token)
+void SetLocalAddressCacheEntry(int ifindex, int family, const v6addr_t ip, const ethaddr_t eth, int *err)
{
- #define IPv6FMTSTRING "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X"
- #define IPv6FMTARGS ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]
- #if 0
+
+#define IPv6FMTSTRING "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X"
+#define IPv6FMTARGS ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]
+
if (family == 4)
- helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry %d IPv%d %d.%d.%d.%d %02X:%02X:%02X:%02X:%02X:%02X",
- ifindex, family, ip[0], ip[1], ip[2], ip[3], eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
+ {
+ os_log_info(log_handle,"SetLocalAddressCacheEntry %d IPv%d %d.%d.%d.%d %02X:%02X:%02X:%02X:%02X:%02X",
+ ifindex, family, ip[0], ip[1], ip[2], ip[3], eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
+ }
else
- helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry %d IPv%d " IPv6FMTSTRING " %02X:%02X:%02X:%02X:%02X:%02X",
- ifindex, family, IPv6FMTARGS, eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
- #endif
-
- *err = -1;
- if (!authorized(&token)) { *err = kmDNSHelperNotAuthorized; goto fin; }
-
+ {
+ os_log_info(log_handle,"SetLocalAddressCacheEntry %d IPv%d " IPv6FMTSTRING " %02X:%02X:%02X:%02X:%02X:%02X",
+ ifindex, family, IPv6FMTARGS, eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
+ }
+
+ *err = kHelperErr_DefaultErr;
+
static int s = -1, seq = 0;
if (s < 0)
{
s = socket(PF_ROUTE, SOCK_RAW, 0);
- if (s < 0) helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: socket(PF_ROUTE, SOCK_RAW, 0) failed %d (%s)", errno, strerror(errno));
+ if (s < 0)
+ os_log(log_handle, "SetLocalAddressCacheEntry: socket(PF_ROUTE, SOCK_RAW, 0) failed %d (%s)", errno, strerror(errno));
}
if (s >= 0)
@@ -241,7 +221,7 @@ kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int if
{
struct { struct rt_msghdr hdr; struct sockaddr_inarp dst; struct sockaddr_dl sdl; } rtmsg;
memset(&rtmsg, 0, sizeof(rtmsg));
-
+
rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
rtmsg.hdr.rtm_version = RTM_VERSION;
rtmsg.hdr.rtm_type = RTM_ADD;
@@ -254,7 +234,7 @@ kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int if
rtmsg.hdr.rtm_use = 0;
rtmsg.hdr.rtm_inits = RTV_EXPIRE;
rtmsg.hdr.rtm_rmx.rmx_expire = tv.tv_sec + 30;
-
+
rtmsg.dst.sin_len = sizeof(rtmsg.dst);
rtmsg.dst.sin_family = AF_INET;
rtmsg.dst.sin_port = 0;
@@ -262,7 +242,7 @@ kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int if
rtmsg.dst.sin_srcaddr.s_addr = 0;
rtmsg.dst.sin_tos = 0;
rtmsg.dst.sin_other = 0;
-
+
rtmsg.sdl.sdl_len = sizeof(rtmsg.sdl);
rtmsg.sdl.sdl_family = AF_LINK;
rtmsg.sdl.sdl_index = ifindex;
@@ -270,26 +250,26 @@ kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int if
rtmsg.sdl.sdl_nlen = 0;
rtmsg.sdl.sdl_alen = ETHER_ADDR_LEN;
rtmsg.sdl.sdl_slen = 0;
-
+
// Target MAC address goes in rtmsg.sdl.sdl_data[0..5]; (See LLADDR() in /usr/include/net/if_dl.h)
memcpy(rtmsg.sdl.sdl_data, eth, sizeof(ethaddr_t));
-
+
int len = write(s, (char *)&rtmsg, sizeof(rtmsg));
if (len < 0)
- helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: write(%d) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s)",
+ os_log(log_handle, "SetLocalAddressCacheEntry: write(%zu) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s)",
sizeof(rtmsg), ifindex, ip[0], ip[1], ip[2], ip[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno));
len = read(s, (char *)&rtmsg, sizeof(rtmsg));
if (len < 0 || rtmsg.hdr.rtm_errno)
- helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: read (%d) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s) %d",
+ os_log(log_handle, "SetLocalAddressCacheEntry: read (%zu) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s) %d",
sizeof(rtmsg), ifindex, ip[0], ip[1], ip[2], ip[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno), rtmsg.hdr.rtm_errno);
-
- *err = 0;
+
+ *err = kHelperErr_NoErr;
}
else
{
struct { struct rt_msghdr hdr; struct sockaddr_in6 dst; struct sockaddr_dl sdl; } rtmsg;
memset(&rtmsg, 0, sizeof(rtmsg));
-
+
rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
rtmsg.hdr.rtm_version = RTM_VERSION;
rtmsg.hdr.rtm_type = RTM_ADD;
@@ -302,14 +282,14 @@ kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int if
rtmsg.hdr.rtm_use = 0;
rtmsg.hdr.rtm_inits = RTV_EXPIRE;
rtmsg.hdr.rtm_rmx.rmx_expire = tv.tv_sec + 30;
-
+
rtmsg.dst.sin6_len = sizeof(rtmsg.dst);
rtmsg.dst.sin6_family = AF_INET6;
rtmsg.dst.sin6_port = 0;
rtmsg.dst.sin6_flowinfo = 0;
rtmsg.dst.sin6_addr = *(struct in6_addr*)ip;
rtmsg.dst.sin6_scope_id = ifindex;
-
+
rtmsg.sdl.sdl_len = sizeof(rtmsg.sdl);
rtmsg.sdl.sdl_family = AF_LINK;
rtmsg.sdl.sdl_index = ifindex;
@@ -317,36 +297,33 @@ kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int if
rtmsg.sdl.sdl_nlen = 0;
rtmsg.sdl.sdl_alen = ETHER_ADDR_LEN;
rtmsg.sdl.sdl_slen = 0;
-
+
// Target MAC address goes in rtmsg.sdl.sdl_data[0..5]; (See LLADDR() in /usr/include/net/if_dl.h)
memcpy(rtmsg.sdl.sdl_data, eth, sizeof(ethaddr_t));
-
+
int len = write(s, (char *)&rtmsg, sizeof(rtmsg));
if (len < 0)
- helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: write(%d) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s)",
+ os_log(log_handle, "SetLocalAddressCacheEntry: write(%zu) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s)",
sizeof(rtmsg), ifindex, IPv6FMTARGS, rtmsg.hdr.rtm_seq, len, errno, strerror(errno));
len = read(s, (char *)&rtmsg, sizeof(rtmsg));
if (len < 0 || rtmsg.hdr.rtm_errno)
- helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: read (%d) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s) %d",
+ os_log(log_handle, "SetLocalAddressCacheEntry: read (%zu) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s) %d",
sizeof(rtmsg), ifindex, IPv6FMTARGS, rtmsg.hdr.rtm_seq, len, errno, strerror(errno), rtmsg.hdr.rtm_errno);
-
- *err = 0;
+
+ *err = kHelperErr_NoErr;
}
-
}
-
-fin:
+
update_idle_timer();
- return KERN_SUCCESS;
}
-kern_return_t do_mDNSNotify(__unused mach_port_t port, const char *title, const char *msg, audit_token_t token)
-{
- if (!authorized(&token)) return KERN_SUCCESS;
+void UserNotify(const char *title, const char *msg)
+{
+
#ifndef NO_CFUSERNOTIFICATION
static const char footer[] = "(Note: This message only appears on machines with 17.x.x.x IP addresses"
- " or on debugging builds with ForceAlerts set — i.e. only at Apple — not on customer machines.)";
+ " or on debugging builds with ForceAlerts set — i.e. only at Apple — not on customer machines.)";
CFStringRef alertHeader = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8);
CFStringRef alertBody = CFStringCreateWithCString(NULL, msg, kCFStringEncodingUTF8);
CFStringRef alertFooter = CFStringCreateWithCString(NULL, footer, kCFStringEncodingUTF8);
@@ -354,18 +331,19 @@ kern_return_t do_mDNSNotify(__unused mach_port_t port, const char *title, const
CFRelease(alertBody);
CFRelease(alertFooter);
int err = CFUserNotificationDisplayNotice(0.0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage, NULL);
- if (err) helplog(ASL_LEVEL_ERR, "CFUserNotificationDisplayNotice returned %d", err);
+ if (err)
+ os_log(log_handle, "CFUserNotificationDisplayNotice returned %d", err);
CFRelease(alertHeader);
CFRelease(alertMessage);
#else
(void)title;
(void)msg;
#endif /* NO_CFUSERNOTIFICATION */
-
+
update_idle_timer();
- return KERN_SUCCESS;
}
+
char usercompname[MAX_DOMAIN_LABEL+1] = {0}; // the last computer name the user saw
char userhostname[MAX_DOMAIN_LABEL+1] = {0}; // the last local host name the user saw
char lastcompname[MAX_DOMAIN_LABEL+1] = {0}; // the last computer name saved to preferences
@@ -386,9 +364,9 @@ static CFRunLoopSourceRef gNotificationRLS = NULL;
static void NotificationCallBackDismissed(CFUserNotificationRef userNotification, CFOptionFlags responseFlags)
{
- debug("entry");
+ os_log_debug(log_handle,"entry");
(void)responseFlags; // Unused
- if (userNotification != gNotification) helplog(ASL_LEVEL_ERR, "NotificationCallBackDismissed: Wrong CFUserNotificationRef");
+ if (userNotification != gNotification) os_log(log_handle, "NotificationCallBackDismissed: Wrong CFUserNotificationRef");
if (gNotificationRLS)
{
// Caution: don't use CFRunLoopGetCurrent() here, because the currently executing thread may not be our "CFRunLoopRun" thread.
@@ -416,7 +394,7 @@ static void ShowNameConflictNotification(CFMutableArrayRef header, CFStringRef s
CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (!dictionary) return;
- debug("entry");
+ os_log_debug(log_handle,"entry");
CFDictionarySetValue(dictionary, kCFUserNotificationAlertHeaderKey, header);
CFDictionarySetValue(dictionary, kCFUserNotificationAlertMessageKey, subtext);
@@ -430,13 +408,13 @@ static void ShowNameConflictNotification(CFMutableArrayRef header, CFStringRef s
{
SInt32 error;
gNotification = CFUserNotificationCreate(NULL, 0, kCFUserNotificationCautionAlertLevel, &error, dictionary);
- if (!gNotification || error) { helplog(ASL_LEVEL_ERR, "ShowNameConflictNotification: CFUserNotificationRef: Error %d", error); return; }
+ if (!gNotification || error) { os_log(log_handle, "ShowNameConflictNotification: CFUserNotificationRef: Error %d", error); return; }
gNotificationRLS = CFUserNotificationCreateRunLoopSource(NULL, gNotification, NotificationCallBackDismissed, 0);
- if (!gNotificationRLS) { helplog(ASL_LEVEL_ERR,"ShowNameConflictNotification: RLS"); CFRelease(gNotification); gNotification = NULL; return; }
+ if (!gNotificationRLS) { os_log(log_handle, "ShowNameConflictNotification: RLS"); CFRelease(gNotification); gNotification = NULL; return; }
// Caution: don't use CFRunLoopGetCurrent() here, because the currently executing thread may not be our "CFRunLoopRun" thread.
// We need to explicitly specify the desired CFRunLoop to which we want to add this event source.
CFRunLoopAddSource(gRunLoop, gNotificationRLS, kCFRunLoopDefaultMode);
- debug("gRunLoop=%p gNotification=%p gNotificationRLS=%p", gRunLoop, gNotification, gNotificationRLS);
+ os_log_debug(log_handle,"gRunLoop=%p gNotification=%p gNotificationRLS=%p", gRunLoop, gNotification, gNotificationRLS);
pause_idle_timer();
}
@@ -454,9 +432,13 @@ static CFMutableArrayRef CreateAlertHeader(const char* oldname, const char* newn
// arbitrary computer name the user may choose, this exact text (with zero-width non-breaking space added)
// can never be one that occurs in the Localizable.strings translation file.
if (!cfoldname)
- helplog(ASL_LEVEL_ERR,"Could not construct CFStrings for old=%s", newname);
+ {
+ os_log(log_handle, "Could not construct CFStrings for old=%s", newname);
+ }
else if (newname && !cfnewname)
- helplog(ASL_LEVEL_ERR,"Could not construct CFStrings for new=%s", newname);
+ {
+ os_log(log_handle, "Could not construct CFStrings for new=%s", newname);
+ }
else
{
const CFStringRef s1 = CFStringCreateWithFormat(NULL, NULL, CFS_Format, cfoldname, suffix);
@@ -465,11 +447,17 @@ static CFMutableArrayRef CreateAlertHeader(const char* oldname, const char* newn
alertHeader = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
if (!s1)
- helplog(ASL_LEVEL_ERR, "Could not construct secondary CFString for old=%s", oldname);
+ {
+ os_log(log_handle, "Could not construct secondary CFString for old=%s", oldname);
+ }
else if (cfnewname && !s2)
- helplog(ASL_LEVEL_ERR, "Could not construct secondary CFString for new=%s", newname);
+ {
+ os_log(log_handle, "Could not construct secondary CFString for new=%s", newname);
+ }
else if (!alertHeader)
- helplog(ASL_LEVEL_ERR, "Could not construct CFArray for notification");
+ {
+ os_log(log_handle, "Could not construct CFArray for notification");
+ }
else
{
// Make sure someone is logged in. We don't want this popping up over the login window
@@ -490,7 +478,9 @@ static CFMutableArrayRef CreateAlertHeader(const char* oldname, const char* newn
CFArrayAppendValue(alertHeader, CFSTR("."));
}
else
+ {
CFArrayAppendValue(alertHeader, CFSTR("All attempts to find an available name by adding a number to the name were also unsuccessful."));
+ }
}
CFRelease(userName);
}
@@ -508,7 +498,7 @@ static CFMutableArrayRef CreateAlertHeader(const char* oldname, const char* newn
static void update_notification(void)
{
#ifndef NO_CFUSERNOTIFICATION
- debug("entry ucn=%s, uhn=%s, lcn=%s, lhn=%s", usercompname, userhostname, lastcompname, lasthostname);
+ os_log_debug(log_handle,"entry ucn=%s, uhn=%s, lcn=%s, lhn=%s", usercompname, userhostname, lastcompname, lasthostname);
if (!CFS_OQ)
{
// Note: The "\xEF\xBB\xBF" byte sequence (U+FEFF) in the CFS_Format string is the UTF-8 encoding of the zero-width non-breaking space character.
@@ -539,7 +529,7 @@ static void update_notification(void)
{
if (gNotificationRLS)
{
- debug("canceling notification %p", gNotification);
+ os_log_debug(log_handle,"canceling notification %p", gNotification);
CFUserNotificationCancel(gNotification);
unpause_idle_timer();
}
@@ -569,8 +559,7 @@ static void update_notification(void)
#endif
}
-kern_return_t
-do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, const char* new, audit_token_t token)
+void PreferencesSetName(int key, const char* old, const char* new)
{
SCPreferencesRef session = NULL;
Boolean ok = FALSE;
@@ -579,37 +568,37 @@ do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, c
char* user = NULL;
char* last = NULL;
Boolean needUpdate = FALSE;
-
- debug("entry %s old=%s new=%s", key==kmDNSComputerName ? "ComputerName" : (key==kmDNSLocalHostName ? "LocalHostName" : "UNKNOWN"), old, new);
- if (!authorized(&token)) goto fin;
-
+
+ os_log_info(log_handle,"PreferencesSetName: entry %s old=%s new=%s",
+ key==kmDNSComputerName ? "ComputerName" : (key==kmDNSLocalHostName ? "LocalHostName" : "UNKNOWN"), old, new);
+
switch ((enum mDNSPreferencesSetNameKey)key)
{
- case kmDNSComputerName:
- user = usercompname;
- last = lastcompname;
- break;
- case kmDNSLocalHostName:
- user = userhostname;
- last = lasthostname;
- break;
- default:
- debug("unrecognized key: %d", key);
- goto fin;
+ case kmDNSComputerName:
+ user = usercompname;
+ last = lastcompname;
+ break;
+ case kmDNSLocalHostName:
+ user = userhostname;
+ last = lasthostname;
+ break;
+ default:
+ os_log(log_handle, "PreferencesSetName: unrecognized key: %d", key);
+ goto fin;
}
-
+
if (!last)
{
- helplog(ASL_LEVEL_ERR, "%s: no last ptr", __func__);
+ os_log(log_handle, "PreferencesSetName: no last ptr");
goto fin;
}
-
+
if (!user)
{
- helplog(ASL_LEVEL_ERR, "%s: no user ptr", __func__);
+ os_log(log_handle, "PreferencesSetName:: no user ptr");
goto fin;
}
-
+
if (0 == strncmp(old, new, MAX_DOMAIN_LABEL+1))
{
// old and new are same means the config changed i.e, the user has set something in the preferences pane.
@@ -634,7 +623,7 @@ do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, c
needUpdate = TRUE;
}
}
-
+
// If we are not showing the dialogue, we need to remember the first "old" value so that
// we maintain the same through the lifetime of the dialogue. Subsequent conflicts don't
// update the "old" value.
@@ -643,57 +632,66 @@ do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, c
strncpy(user, old, MAX_DOMAIN_LABEL);
needUpdate = TRUE;
}
-
+
if (!new[0]) // we've given up trying to construct a name that doesn't conflict
goto fin;
-
+
cfstr = CFStringCreateWithCString(NULL, new, kCFStringEncodingUTF8);
-
- session = SCPreferencesCreate(NULL, CFSTR(kmDNSHelperServiceName), NULL);
-
+
+ session = SCPreferencesCreate(NULL, CFSTR(kHelperService), NULL);
+
if (cfstr == NULL || session == NULL)
{
- debug("SCPreferencesCreate failed");
+ os_log(log_handle, "PreferencesSetName: SCPreferencesCreate failed");
goto fin;
}
if (!SCPreferencesLock(session, 0))
{
- debug("lock failed");
+ os_log(log_handle,"PreferencesSetName: lock failed");
goto fin;
}
locked = TRUE;
-
+
switch ((enum mDNSPreferencesSetNameKey)key)
{
- case kmDNSComputerName:
- {
- // We want to write the new Computer Name to System Preferences, without disturbing the user-selected
- // system-wide default character set used for things like AppleTalk NBP and NETBIOS service advertising.
- // Note that this encoding is not used for the computer name, but since both are set by the same call,
- // we need to take care to set the name without changing the character set.
- CFStringEncoding encoding = kCFStringEncodingUTF8;
- CFStringRef unused = SCDynamicStoreCopyComputerName(NULL, &encoding);
- if (unused) { CFRelease(unused); unused = NULL; }
- else encoding = kCFStringEncodingUTF8;
-
- ok = SCPreferencesSetComputerName(session, cfstr, encoding);
- }
- break;
- case kmDNSLocalHostName:
- ok = SCPreferencesSetLocalHostName(session, cfstr);
- break;
- default:
- break;
- }
-
+ case kmDNSComputerName:
+ {
+ // We want to write the new Computer Name to System Preferences, without disturbing the user-selected
+ // system-wide default character set used for things like AppleTalk NBP and NETBIOS service advertising.
+ // Note that this encoding is not used for the computer name, but since both are set by the same call,
+ // we need to take care to set the name without changing the character set.
+ CFStringEncoding encoding = kCFStringEncodingUTF8;
+ CFStringRef unused = SCDynamicStoreCopyComputerName(NULL, &encoding);
+ if (unused)
+ {
+ CFRelease(unused);
+ unused = NULL;
+ }
+ else
+ {
+ encoding = kCFStringEncodingUTF8;
+ }
+
+ ok = SCPreferencesSetComputerName(session, cfstr, encoding);
+ }
+ break;
+
+ case kmDNSLocalHostName:
+ ok = SCPreferencesSetLocalHostName(session, cfstr);
+ break;
+
+ default:
+ break;
+ }
+
if (!ok || !SCPreferencesCommitChanges(session) ||
!SCPreferencesApplyChanges(session))
{
- debug("SCPreferences update failed");
+ os_log(log_handle, "PreferencesSetName: SCPreferences update failed");
goto fin;
}
- debug("succeeded");
-
+ os_log_info(log_handle,"PreferencesSetName: succeeded");
+
fin:
if (NULL != cfstr)
CFRelease(cfstr);
@@ -704,10 +702,12 @@ fin:
CFRelease(session);
}
update_idle_timer();
- if (needUpdate) update_notification();
- return KERN_SUCCESS;
+ if (needUpdate)
+ update_notification();
+
}
+
enum DNSKeyFormat
{
formatNotDNSKey, formatDdnsTypeItem, formatDnsPrefixedServiceItem, formatBtmmPrefixedServiceItem
@@ -725,8 +725,7 @@ static const char dnsprefix[] = "dns:";
static const char ddns[] = "ddns";
static const char ddnsrev[] = "sndd";
-static enum DNSKeyFormat
-getDNSKeyFormat(SecKeychainItemRef item, SecKeychainAttributeList **attributesp)
+static enum DNSKeyFormat getDNSKeyFormat(SecKeychainItemRef item, SecKeychainAttributeList **attributesp)
{
static UInt32 tags[4] =
{
@@ -741,13 +740,11 @@ getDNSKeyFormat(SecKeychainItemRef item, SecKeychainAttributeList **attributesp)
Boolean malformed = FALSE;
OSStatus status = noErr;
int i = 0;
-
+
*attributesp = NULL;
- if (noErr != (status = SecKeychainItemCopyAttributesAndData(item,
- &attributeInfo, NULL, &attributes, NULL, NULL)))
+ if (noErr != (status = SecKeychainItemCopyAttributesAndData(item, &attributeInfo, NULL, &attributes, NULL, NULL)))
{
- debug("SecKeychainItemCopyAttributesAndData %d - skipping",
- status);
+ os_log_info(log_handle,"getDNSKeyFormat: SecKeychainItemCopyAttributesAndData %d - skipping", status);
goto skip;
}
if (attributeInfo.count != attributes->count)
@@ -757,137 +754,127 @@ getDNSKeyFormat(SecKeychainItemRef item, SecKeychainAttributeList **attributesp)
malformed = TRUE;
if (malformed)
{
- debug(
- "malformed result from SecKeychainItemCopyAttributesAndData - skipping");
+ os_log(log_handle, "getDNSKeyFormat: malformed result from SecKeychainItemCopyAttributesAndData - skipping");
goto skip;
}
+
+ os_log_info(log_handle,"getDNSKeyFormat: entry (\"%.*s\", \"%.*s\", \"%.*s\")",
+ (int)attributes->attr[0].length, attributes->attr[0].data,
+ (int)attributes->attr[1].length, attributes->attr[1].data,
+ (int)attributes->attr[2].length, attributes->attr[2].data);
- debug("entry (\"%.*s\", \"%.*s\", \"%.*s\")",
- (int)attributes->attr[0].length, attributes->attr[0].data,
- (int)attributes->attr[1].length, attributes->attr[1].data,
- (int)attributes->attr[2].length, attributes->attr[2].data);
if (attributes->attr[1].length >= MAX_ESCAPED_DOMAIN_NAME +
sizeof(dnsprefix)-1)
{
- debug("kSecServiceItemAttr too long (%u) - skipping",
+ os_log(log_handle, "getDNSKeyFormat: kSecServiceItemAttr too long (%u) - skipping",
(unsigned int)attributes->attr[1].length);
goto skip;
}
if (attributes->attr[2].length >= MAX_ESCAPED_DOMAIN_NAME)
{
- debug("kSecAccountItemAttr too long (%u) - skipping",
+ os_log(log_handle, "getDNSKeyFormat: kSecAccountItemAttr too long (%u) - skipping",
(unsigned int)attributes->attr[2].length);
goto skip;
}
- if (attributes->attr[1].length >= sizeof(dnsprefix)-1 &&
- 0 == strncasecmp(attributes->attr[1].data, dnsprefix,
- sizeof(dnsprefix)-1))
+ if (attributes->attr[1].length >= sizeof(dnsprefix)-1 && 0 == strncasecmp(attributes->attr[1].data, dnsprefix, sizeof(dnsprefix)-1))
format = formatDnsPrefixedServiceItem;
- else if (attributes->attr[1].length >= sizeof(btmmprefix)-1 &&
- 0 == strncasecmp(attributes->attr[1].data, btmmprefix, sizeof(btmmprefix)-1))
+ else if (attributes->attr[1].length >= sizeof(btmmprefix)-1 && 0 == strncasecmp(attributes->attr[1].data, btmmprefix, sizeof(btmmprefix)-1))
format = formatBtmmPrefixedServiceItem;
- else if (attributes->attr[0].length == sizeof(ddns)-1 &&
- 0 == strncasecmp(attributes->attr[0].data, ddns, sizeof(ddns)-1))
+ else if (attributes->attr[0].length == sizeof(ddns)-1 && 0 == strncasecmp(attributes->attr[0].data, ddns, sizeof(ddns)-1))
format = formatDdnsTypeItem;
- else if (attributes->attr[0].length == sizeof(ddnsrev)-1 &&
- 0 == strncasecmp(attributes->attr[0].data, ddnsrev, sizeof(ddnsrev)-1))
+ else if (attributes->attr[0].length == sizeof(ddnsrev)-1 && 0 == strncasecmp(attributes->attr[0].data, ddnsrev, sizeof(ddnsrev)-1))
format = formatDdnsTypeItem;
else
{
- debug("uninterested in this entry");
+ os_log_info(log_handle,"getDNSKeyFormat: uninterested in this entry");
goto skip;
}
+
*attributesp = attributes;
- debug("accepting this entry");
+ os_log_info(log_handle,"getDNSKeyFormat: accepting this entry");
return format;
-
+
skip:
SecKeychainItemFreeAttributesAndData(attributes, NULL);
return formatNotDNSKey;
}
// Insert the attributes as defined by mDNSKeyChainAttributes
-static CFPropertyListRef
-getKeychainItemInfo(SecKeychainItemRef item,
- SecKeychainAttributeList *attributes, enum DNSKeyFormat format)
+static CFPropertyListRef copyKeychainItemInfo(SecKeychainItemRef item, SecKeychainAttributeList *attributes, enum DNSKeyFormat format)
{
CFMutableArrayRef entry = NULL;
CFDataRef data = NULL;
OSStatus status = noErr;
UInt32 keylen = 0;
void *keyp = 0;
-
- if (NULL == (entry = CFArrayCreateMutable(NULL, 0,
- &kCFTypeArrayCallBacks)))
+
+ if (NULL == (entry = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)))
{
- debug("CFArrayCreateMutable failed");
+ os_log(log_handle, "copyKeychainItemInfo: CFArrayCreateMutable failed");
goto error;
}
-
+
// Insert the Account attribute (kmDNSKcWhere)
switch ((enum DNSKeyFormat)format)
{
- case formatDdnsTypeItem:
- data = CFDataCreate(kCFAllocatorDefault,
- attributes->attr[1].data, attributes->attr[1].length);
- break;
- case formatDnsPrefixedServiceItem:
- case formatBtmmPrefixedServiceItem:
- data = CFDataCreate(kCFAllocatorDefault,
- attributes->attr[1].data, attributes->attr[1].length);
- break;
- default:
- assert("unknown DNSKeyFormat value");
- break;
+ case formatDdnsTypeItem:
+ data = CFDataCreate(kCFAllocatorDefault, attributes->attr[1].data, attributes->attr[1].length);
+ break;
+ case formatDnsPrefixedServiceItem:
+ case formatBtmmPrefixedServiceItem:
+ data = CFDataCreate(kCFAllocatorDefault, attributes->attr[1].data, attributes->attr[1].length);
+ break;
+ default:
+ os_log(log_handle, "copyKeychainItemInfo: unknown DNSKeyFormat value");
+ break;
}
if (NULL == data)
{
- debug("CFDataCreate for attr[1] failed");
+ os_log(log_handle, "copyKeychainItemInfo: CFDataCreate for attr[1] failed");
goto error;
}
CFArrayAppendValue(entry, data);
CFRelease(data);
-
+
// Insert the Where attribute (kmDNSKcAccount)
- if (NULL == (data = CFDataCreate(kCFAllocatorDefault,
- attributes->attr[2].data, attributes->attr[2].length)))
+ if (NULL == (data = CFDataCreate(kCFAllocatorDefault, attributes->attr[2].data, attributes->attr[2].length)))
{
- debug("CFDataCreate for attr[2] failed");
+ os_log(log_handle, "copyKeychainItemInfo: CFDataCreate for attr[2] failed");
goto error;
}
+
CFArrayAppendValue(entry, data);
CFRelease(data);
-
+
// Insert the Key attribute (kmDNSKcKey)
- if (noErr != (status = SecKeychainItemCopyAttributesAndData(item, NULL,
- NULL, NULL, &keylen, &keyp)))
+ if (noErr != (status = SecKeychainItemCopyAttributesAndData(item, NULL, NULL, NULL, &keylen, &keyp)))
{
- debug("could not retrieve key for \"%.*s\": %d",
- (int)attributes->attr[1].length, attributes->attr[1].data,
- status);
+ os_log(log_handle, "copyKeychainItemInfo: could not retrieve key for \"%.*s\": %d",
+ (int)attributes->attr[1].length, attributes->attr[1].data, status);
goto error;
}
+
data = CFDataCreate(kCFAllocatorDefault, keyp, keylen);
SecKeychainItemFreeAttributesAndData(NULL, keyp);
if (NULL == data)
{
- debug("CFDataCreate for keyp failed");
+ os_log(log_handle, "copyKeychainItemInfo: CFDataCreate for keyp failed");
goto error;
}
CFArrayAppendValue(entry, data);
CFRelease(data);
-
+
// Insert the Name attribute (kmDNSKcName)
- if (NULL == (data = CFDataCreate(kCFAllocatorDefault,
- attributes->attr[3].data, attributes->attr[3].length)))
+ if (NULL == (data = CFDataCreate(kCFAllocatorDefault, attributes->attr[3].data, attributes->attr[3].length)))
{
- debug("CFDataCreate for attr[3] failed");
+ os_log(log_handle, "copyKeychainItemInfo: CFDataCreate for attr[3] failed");
goto error;
}
+
CFArrayAppendValue(entry, data);
CFRelease(data);
return entry;
-
+
error:
if (NULL != entry)
CFRelease(entry);
@@ -895,10 +882,7 @@ error:
}
#endif
-kern_return_t
-do_mDNSKeychainGetSecrets(__unused mach_port_t port, __unused unsigned int *numsecrets,
- __unused vm_offset_t *secrets, __unused mach_msg_type_number_t *secretsCnt, __unused int *err,
- __unused audit_token_t token)
+void KeychainGetSecrets(__unused unsigned int *numsecrets,__unused unsigned long *secrets, __unused unsigned int *secretsCnt, __unused int *err)
{
#ifndef NO_SECURITYFRAMEWORK
CFWriteStreamRef stream = NULL;
@@ -911,43 +895,34 @@ do_mDNSKeychainGetSecrets(__unused mach_port_t port, __unused unsigned int *nums
SecKeychainAttributeList *attributes = NULL;
enum DNSKeyFormat format;
OSStatus status = 0;
-
- debug("entry");
- *err = 0;
+
+ os_log_info(log_handle,"KeychainGetSecrets: entry");
+ *err = kHelperErr_NoErr;
*numsecrets = 0;
*secrets = (vm_offset_t)NULL;
- if (!authorized(&token))
- {
- *err = kmDNSHelperNotAuthorized;
- goto fin;
- }
- if (NULL == (keys = CFArrayCreateMutable(NULL, 0,
- &kCFTypeArrayCallBacks)))
+
+ if (NULL == (keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)))
{
- debug("CFArrayCreateMutable failed");
- *err = kmDNSHelperCreationFailed;
+ os_log(log_handle, "KeychainGetSecrets: CFArrayCreateMutable failed");
+ *err = kHelperErr_ApiErr;
goto fin;
}
if (noErr != (status = SecKeychainCopyDefault(&skc)))
{
- *err = kmDNSHelperKeychainCopyDefaultFailed;
+ *err = kHelperErr_ApiErr;
goto fin;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
if (noErr != (status = SecKeychainSearchCreateFromAttributes(skc, kSecGenericPasswordItemClass, NULL, &search)))
{
- *err = kmDNSHelperKeychainSearchCreationFailed;
+ *err = kHelperErr_ApiErr;
goto fin;
}
- for (status = SecKeychainSearchCopyNext(search, &item);
- noErr == status;
- status = SecKeychainSearchCopyNext(search, &item))
+ for (status = SecKeychainSearchCopyNext(search, &item); noErr == status; status = SecKeychainSearchCopyNext(search, &item))
{
- if (formatNotDNSKey != (format = getDNSKeyFormat(item,
- &attributes)) &&
- NULL != (entry = getKeychainItemInfo(item, attributes,
- format)))
+ if (formatNotDNSKey != (format = getDNSKeyFormat(item, &attributes)) &&
+ NULL != (entry = copyKeychainItemInfo(item, attributes, format)))
{
CFArrayAppendValue(keys, entry);
CFRelease(entry);
@@ -957,41 +932,41 @@ do_mDNSKeychainGetSecrets(__unused mach_port_t port, __unused unsigned int *nums
}
#pragma clang diagnostic pop
if (errSecItemNotFound != status)
- helplog(ASL_LEVEL_ERR, "%s: SecKeychainSearchCopyNext failed: %d",
- __func__, status);
- if (NULL == (stream =
- CFWriteStreamCreateWithAllocatedBuffers(kCFAllocatorDefault,
- kCFAllocatorDefault)))
- {
- *err = kmDNSHelperCreationFailed;
- debug("CFWriteStreamCreateWithAllocatedBuffers failed");
+ os_log(log_handle, "KeychainGetSecrets: SecKeychainSearchCopyNext failed: %d", status);
+
+ if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(kCFAllocatorDefault, kCFAllocatorDefault)))
+ {
+ *err = kHelperErr_ApiErr;
+ os_log(log_handle, "KeychainGetSecrets:CFWriteStreamCreateWithAllocatedBuffers failed");
goto fin;
}
+
CFWriteStreamOpen(stream);
- if (0 == CFPropertyListWrite(keys, stream,
- kCFPropertyListBinaryFormat_v1_0, 0, NULL))
+ if (0 == CFPropertyListWrite(keys, stream, kCFPropertyListBinaryFormat_v1_0, 0, NULL))
{
- *err = kmDNSHelperPListWriteFailed;
- debug("CFPropertyListWriteToStream failed");
+ *err = kHelperErr_ApiErr;
+ os_log(log_handle, "KeychainGetSecrets:CFPropertyListWriteToStream failed");
goto fin;
}
- result = CFWriteStreamCopyProperty(stream,
- kCFStreamPropertyDataWritten);
- if (KERN_SUCCESS != vm_allocate(mach_task_self(), secrets,
- CFDataGetLength(result), VM_FLAGS_ANYWHERE))
+ result = CFWriteStreamCopyProperty(stream, kCFStreamPropertyDataWritten);
+
+ if (KERN_SUCCESS != vm_allocate(mach_task_self(), secrets, CFDataGetLength(result), VM_FLAGS_ANYWHERE))
{
- *err = kmDNSHelperCreationFailed;
- debug("vm_allocate failed");
+ *err = kHelperErr_ApiErr;
+ os_log(log_handle, "KeychainGetSecrets: vm_allocate failed");
goto fin;
}
- CFDataGetBytes(result, CFRangeMake(0, CFDataGetLength(result)),
- (void *)*secrets);
+
+ CFDataGetBytes(result, CFRangeMake(0, CFDataGetLength(result)), (void *)*secrets);
*secretsCnt = CFDataGetLength(result);
*numsecrets = CFArrayGetCount(keys);
- debug("succeeded");
-
+
+ os_log_info(log_handle,"KeychainGetSecrets: succeeded");
+
fin:
- debug("returning %u secrets", *numsecrets);
+ os_log_info(log_handle,"KeychainGetSecrets: returning numsecrets[%u] secrets[%lu] secrets addr[%p] secretscount[%u]",
+ *numsecrets, *secrets, secrets, *secretsCnt);
+
if (NULL != stream)
{
CFWriteStreamClose(stream);
@@ -1006,395 +981,610 @@ fin:
if (NULL != skc)
CFRelease(skc);
update_idle_timer();
- return KERN_SUCCESS;
+
+ *err = KERN_SUCCESS;
+
#else
- return KERN_FAILURE;
+
+ *err = KERN_FAILURE;
+
#endif
+
}
-#ifndef MDNS_NO_IPSEC
-typedef enum _mDNSTunnelPolicyWhich
-{
- kmDNSTunnelPolicySetup,
- kmDNSTunnelPolicyTeardown,
- kmDNSTunnelPolicyGenerate
-} mDNSTunnelPolicyWhich;
-
-// For kmDNSTunnelPolicySetup, you can setup IPv6-in-IPv6 tunnel or IPv6-in-IPv4 tunnel
-// kmDNSNoTunnel is used for other Policy types
-typedef enum _mDNSTunnelType
-{
- kmDNSNoTunnel,
- kmDNSIPv6IPv4Tunnel,
- kmDNSIPv6IPv6Tunnel
-} mDNSTunnelType;
-
-static const uint8_t kWholeV6Mask = 128;
-
-#endif /* ifndef MDNS_NO_IPSEC */
-
-#ifndef MDNS_NO_IPSEC
-
-static const char g_racoon_config_dir[] = "/var/run/racoon/";
-static const char g_racoon_config_dir_old[] = "/etc/racoon/remote/";
CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey;
-// Major version 6 is 10.2.x (Jaguar)
-// Major version 7 is 10.3.x (Panther)
-// Major version 8 is 10.4.x (Tiger)
-// Major version 9 is 10.5.x (Leopard)
-// Major version 10 is 10.6.x (SnowLeopard)
-// Major version 11 is 10.7.x (Lion)
-// Major version 12 is 10.8.x (MountainLion)
-// Major version 13 is 10.9.x (Mavericks)
-// Major version 14 is 10.10.x (Yosemite)
-// Major version 15 is 10.11.x (ElCapitan)
-static int MacOSXSystemBuildNumber(char* letter_out, int* minor_out)
+
+void SendWakeupPacket(unsigned int ifid, const char *eth_addr, const char *ip_addr, int iteration)
{
- int major = 0, minor = 0;
- char letter = 0, buildver[256]="<Unknown>";
- CFDictionaryRef vers = _CFCopySystemVersionDictionary();
- if (vers)
+ int bpf_fd, i, j;
+ struct ifreq ifr;
+ char ifname[IFNAMSIZ];
+ char packet[512];
+ char *ptr = packet;
+ char bpf_device[12];
+ struct ether_addr *ea;
+ // (void) ip_addr; // unused
+ // (void) iteration; // unused
+
+ os_log_info(log_handle,"SendWakeupPacket() ether_addr[%s] ip_addr[%s] if_id[%d] iteration[%d]",
+ eth_addr, ip_addr, ifid, iteration);
+
+ if (if_indextoname(ifid, ifname) == NULL)
{
- CFStringRef cfbuildver = CFDictionaryGetValue(vers, _kCFSystemVersionBuildVersionKey);
- if (cfbuildver) CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8);
- sscanf(buildver, "%d%c%d", &major, &letter, &minor);
- CFRelease(vers);
+ os_log(log_handle, "SendWakeupPacket: invalid interface index %u", ifid);
+ return;
}
- else
- helplog(ASL_LEVEL_NOTICE, "_CFCopySystemVersionDictionary failed");
+
+ ea = ether_aton(eth_addr);
+ if (ea == NULL)
+ {
+ os_log(log_handle, "SendWakeupPacket: invalid ethernet address %s", eth_addr);
+ return;
+ }
+
+ for (i = 0; i < 100; i++)
+ {
+ snprintf(bpf_device, sizeof(bpf_device), "/dev/bpf%d", i);
+ bpf_fd = open(bpf_device, O_RDWR, 0);
+
+ if (bpf_fd == -1)
+ continue;
+ else
+ break;
+ }
+
+ if (bpf_fd == -1)
+ {
+ os_log(log_handle, "SendWakeupPacket: cannot find a bpf device");
+ return;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+ if (ioctl(bpf_fd, BIOCSETIF, (char *)&ifr) < 0)
+ {
+ os_log(log_handle, "SendWakeupPacket: BIOCSETIF failed %s", strerror(errno));
+ return;
+ }
+
+ // 0x00 Destination address
+ for (i=0; i<6; i++)
+ *ptr++ = ea->octet[i];
+
+ // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option,
+ // BPF will fill in the real interface address for us)
+ for (i=0; i<6; i++)
+ *ptr++ = 0;
+
+ // 0x0C Ethertype (0x0842)
+ *ptr++ = 0x08;
+ *ptr++ = 0x42;
+
+ // 0x0E Wakeup sync sequence
+ for (i=0; i<6; i++)
+ *ptr++ = 0xFF;
+
+ // 0x14 Wakeup data
+ for (j=0; j<16; j++)
+ for (i=0; i<6; i++)
+ *ptr++ = ea->octet[i];
+
+ // 0x74 Password
+ for (i=0; i<6; i++)
+ *ptr++ = 0;
+
+ if (write(bpf_fd, packet, ptr - packet) < 0)
+ {
+ os_log(log_handle, "SendWakeupPacket: write failed %s", strerror(errno));
+ return;
+ }
+ os_log(log_handle, "SendWakeupPacket: sent unicast eth_addr %s, ip_addr %s", eth_addr, ip_addr);
+
+ // Send a broadcast one to handle ethernet switches that don't flood forward packets with
+ // unknown mac addresses.
+ for (i=0; i<6; i++)
+ packet[i] = 0xFF;
+
+ if (write(bpf_fd, packet, ptr - packet) < 0)
+ {
+ os_log(log_handle, "SendWakeupPacket: write failed %s", strerror(errno));
+ return;
+ }
+ os_log(log_handle, "SendWakeupPacket: sent broadcast eth_addr %s, ip_addr %s", eth_addr, ip_addr);
+
+ close(bpf_fd);
- if (!major) { major=10; letter = 'A'; minor = 190; helplog(ASL_LEVEL_NOTICE, "Note: No Major Build Version number found; assuming 10A190"); }
- if (letter_out) *letter_out = letter;
- if (minor_out) *minor_out = minor;
- return(major);
}
-static int UseOldRacoon()
-{
- static int g_oldRacoon = -1;
- if (g_oldRacoon == -1)
+// Open the specified port for protocol in the P2P firewall.
+void PacketFilterControl(uint32_t command, const char * ifname, uint32_t count, pfArray_t portArray, pfArray_t protocolArray)
+{
+ int error;
+
+ os_log_info(log_handle,"PacketFilterControl: command %d ifname %s, count %d",
+ command, ifname, count);
+ os_log_info(log_handle,"PacketFilterControl: portArray0[%d] portArray1[%d] portArray2[%d] portArray3[%d] protocolArray0[%d] protocolArray1[%d] protocolArray2[%d] protocolArray3[%d]", portArray[0], portArray[1], portArray[2], portArray[3], protocolArray[0], protocolArray[1], protocolArray[2], protocolArray[3]);
+
+ switch (command)
{
- char letter = 0;
- int minor = 0;
- g_oldRacoon = (MacOSXSystemBuildNumber(&letter, &minor) < 10);
- debug("%s", g_oldRacoon ? "old" : "new");
+ case PF_SET_RULES:
+ error = P2PPacketFilterAddBonjourRuleSet(ifname, count, portArray, protocolArray);
+ if (error)
+ os_log(log_handle, "P2PPacketFilterAddBonjourRuleSet failed %s", strerror(error));
+ break;
+
+ case PF_CLEAR_RULES:
+ error = P2PPacketFilterClearBonjourRules();
+ if (error)
+ os_log(log_handle, "P2PPacketFilterClearBonjourRules failed %s", strerror(error));
+ break;
+
+ default:
+ os_log(log_handle, "PacketFilterControl: invalid command %d", command);
+ break;
}
- return g_oldRacoon;
-}
-
-static int RacoonSignal()
-{
- return UseOldRacoon() ? SIGHUP : SIGUSR1;
}
-static const char* GetRacoonConfigDir()
+static unsigned long in_cksum(unsigned short *ptr, int nbytes)
{
- return UseOldRacoon() ? g_racoon_config_dir_old : g_racoon_config_dir;
+ unsigned long sum;
+ u_short oddbyte;
+
+ /*
+ * Our algorithm is simple, using a 32-bit accumulator (sum),
+ * we add sequential 16-bit words to it, and at the end, fold back
+ * all the carry bits from the top 16 bits into the lower 16 bits.
+ */
+ sum = 0;
+ while (nbytes > 1)
+ {
+ sum += *ptr++;
+ nbytes -= 2;
+ }
+
+ /* mop up an odd byte, if necessary */
+ if (nbytes == 1)
+ {
+ /* make sure top half is zero */
+ oddbyte = 0;
+
+ /* one byte only */
+ *((u_char *)&oddbyte) = *(u_char *)ptr;
+ sum += oddbyte;
+ }
+ /* Add back carry outs from top 16 bits to low 16 bits. */
+ sum = (sum >> 16) + (sum & 0xffff);
+
+ /* add carry */
+ sum += (sum >> 16);
+
+ return sum;
}
-static const char* GetOldRacoonConfigDir()
+static unsigned short InetChecksum(unsigned short *ptr, int nbytes)
{
- return UseOldRacoon() ? NULL : g_racoon_config_dir_old;
+ unsigned long sum;
+
+ sum = in_cksum(ptr, nbytes);
+ return (unsigned short)~sum;
}
-static const char racoon_config_file[] = "anonymous.conf";
-static const char racoon_config_file_orig[] = "anonymous.conf.orig";
-
-static const char configHeader[] = "# BackToMyMac\n";
-
-static int IsFamiliarRacoonConfiguration(const char* racoon_config_path)
+static void TCPCheckSum(int af, struct tcphdr *t, int tcplen, const v6addr_t sadd6, const v6addr_t dadd6)
{
- int fd = open(racoon_config_path, O_RDONLY);
- debug("entry %s", racoon_config_path);
- if (0 > fd)
+ unsigned long sum = 0;
+ unsigned short *ptr;
+
+ /* TCP header checksum */
+ sum = in_cksum((unsigned short *)t, tcplen);
+
+ if (af == AF_INET)
{
- helplog(ASL_LEVEL_NOTICE, "open \"%s\" failed: %s", racoon_config_path, strerror(errno));
- return 0;
+ /* Pseudo header */
+ ptr = (unsigned short *)sadd6;
+ sum += *ptr++;
+ sum += *ptr++;
+ ptr = (unsigned short *)dadd6;
+ sum += *ptr++;
+ sum += *ptr++;
}
- else
+ else if (af == AF_INET6)
{
- char header[sizeof(configHeader)] = {0};
- ssize_t bytesRead = read(fd, header, sizeof(header)-1);
- close(fd);
- if (bytesRead != sizeof(header)-1) return 0;
- return (0 == memcmp(header, configHeader, sizeof(header)-1));
+ /* Pseudo header */
+ ptr = (unsigned short *)sadd6;
+ sum += *ptr++;
+ sum += *ptr++;
+ sum += *ptr++;
+ sum += *ptr++;
+ sum += *ptr++;
+ sum += *ptr++;
+ sum += *ptr++;
+ sum += *ptr++;
+ ptr = (unsigned short *)dadd6;
+ sum += *ptr++;
+ sum += *ptr++;
+ sum += *ptr++;
+ sum += *ptr++;
+ sum += *ptr++;
+ sum += *ptr++;
+ sum += *ptr++;
+ sum += *ptr++;
}
+
+ sum += htons(tcplen);
+ sum += htons(IPPROTO_TCP);
+
+ while (sum >> 16)
+ sum = (sum >> 16) + (sum & 0xFFFF);
+
+ t->th_sum = ~sum;
+
}
-static void
-revertAnonymousRacoonConfiguration(const char* dir)
+void SendKeepalive(const v6addr_t sadd6, const v6addr_t dadd6, uint16_t lport, uint16_t rport, uint32_t seq, uint32_t ack, uint16_t win)
{
- if (!dir) return;
-
- debug("entry %s", dir);
-
- char racoon_config_path[64];
- strlcpy(racoon_config_path, dir, sizeof(racoon_config_path));
- strlcat(racoon_config_path, racoon_config_file, sizeof(racoon_config_path));
+
+#define IPv6FMTSTRING "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X"
+#define IPv6FMTSARGS sadd6[0], sadd6[1], sadd6[2], sadd6[3], sadd6[4], sadd6[5], sadd6[6], sadd6[7], sadd6[8], sadd6[9], sadd6[10], sadd6[11], sadd6[12], sadd6[13], sadd6[14], sadd6[15]
+#define IPv6FMTDARGS dadd6[0], dadd6[1], dadd6[2], dadd6[3], dadd6[4], dadd6[5], dadd6[6], dadd6[7], dadd6[8], dadd6[9], dadd6[10], dadd6[11], dadd6[12], dadd6[13], dadd6[14], dadd6[15]
- struct stat s;
- int ret = stat(racoon_config_path, &s);
- debug("stat(%s): %d errno=%d", racoon_config_path, ret, errno);
- if (ret == 0)
+ os_log_info(log_handle, "SendKeepalive: "IPv6FMTSTRING" :space: "IPv6FMTSTRING"",
+ IPv6FMTSARGS, IPv6FMTDARGS);
+
+ struct packet4
{
- if (IsFamiliarRacoonConfiguration(racoon_config_path))
- {
- helplog(ASL_LEVEL_INFO, "\"%s\" looks familiar, unlinking", racoon_config_path);
- unlink(racoon_config_path);
- }
- else
+ struct ip ip;
+ struct tcphdr tcp;
+ } packet4;
+ struct packet6
+ {
+ struct tcphdr tcp;
+ } packet6;
+ int sock, on;
+ struct tcphdr *t;
+ int af;
+ struct sockaddr_storage ss_to;
+ struct sockaddr_in *sin_to = (struct sockaddr_in *)&ss_to;
+ struct sockaddr_in6 *sin6_to = (struct sockaddr_in6 *)&ss_to;
+ void *packet;
+ ssize_t packetlen;
+ char ctlbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
+ struct msghdr msghdr;
+ struct iovec iov;
+ ssize_t len;
+
+ os_log_info(log_handle,"SendKeepalive invoked: lport is[%d] rport is[%d] seq is[%d] ack is[%d] win is[%d]",
+ lport, rport, seq, ack, win);
+
+ char buf1[INET6_ADDRSTRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+
+ buf1[0] = 0;
+ buf2[0] = 0;
+
+ inet_ntop(AF_INET6, sadd6, buf1, sizeof(buf1));
+ inet_ntop(AF_INET6, dadd6, buf2, sizeof(buf2));
+
+ os_log_info(log_handle,"SendKeepalive invoked: sadd6 is %s, dadd6 is %s", buf1, buf2);
+
+ // all the incoming arguments are in network order
+ if ((*(unsigned *)(sadd6 +4) == 0) && (*(unsigned *)(sadd6 + 8) == 0) && (*(unsigned *)(sadd6 + 12) == 0))
+ {
+ af = AF_INET;
+ memset(&packet4, 0, sizeof (packet4));
+
+ /* Fill in all the IP header information - should be in host order*/
+ packet4.ip.ip_v = 4; /* 4-bit Version */
+ packet4.ip.ip_hl = 5; /* 4-bit Header Length */
+ packet4.ip.ip_tos = 0; /* 8-bit Type of service */
+ packet4.ip.ip_len = 40; /* 16-bit Total length */
+ packet4.ip.ip_id = 9864; /* 16-bit ID field */
+ packet4.ip.ip_off = 0; /* 13-bit Fragment offset */
+ packet4.ip.ip_ttl = 63; /* 8-bit Time To Live */
+ packet4.ip.ip_p = IPPROTO_TCP; /* 8-bit Protocol */
+ packet4.ip.ip_sum = 0; /* 16-bit Header checksum (below) */
+ memcpy(&packet4.ip.ip_src.s_addr, sadd6, 4);
+ memcpy(&packet4.ip.ip_dst.s_addr, dadd6, 4);
+
+ /* IP header checksum */
+ packet4.ip.ip_sum = InetChecksum((unsigned short *)&packet4.ip, 20);
+ t = &packet4.tcp;
+ packet = &packet4;
+ packetlen = 40; // sum of IPv4 header len(20) and TCP header len(20)
+ }
+ else
+ {
+ af = AF_INET6;
+ memset(&packet6, 0, sizeof (packet6));
+ t = &packet6.tcp;
+ packet = &packet6;
+ // We don't send IPv6 header, hence just the TCP header len (20)
+ packetlen = 20;
+ }
+
+ /* Fill in all the TCP header information */
+ t->th_sport = lport; /* 16-bit Source port number */
+ t->th_dport = rport; /* 16-bit Destination port */
+ t->th_seq = seq; /* 32-bit Sequence Number */
+ t->th_ack = ack; /* 32-bit Acknowledgement Number */
+ t->th_off = 5; /* Data offset */
+ t->th_flags = TH_ACK;
+ t->th_win = win;
+ t->th_sum = 0; /* 16-bit checksum (below) */
+ t->th_urp = 0; /* 16-bit urgent offset */
+
+ TCPCheckSum(af, t, 20, sadd6, dadd6);
+
+ /* Open up a RAW socket */
+ if ((sock = socket(af, SOCK_RAW, IPPROTO_TCP)) < 0)
+ {
+ os_log(log_handle, "SendKeepalive: socket %s", strerror(errno));
+ return;
+ }
+
+ if (af == AF_INET)
+ {
+ on = 1;
+ if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)))
{
- helplog(ASL_LEVEL_NOTICE, "\"%s\" does not look familiar, leaving in place", racoon_config_path);
+ close(sock);
+ os_log(log_handle, "SendKeepalive: setsockopt %s", strerror(errno));
return;
}
+
+ memset(sin_to, 0, sizeof(struct sockaddr_in));
+ sin_to->sin_len = sizeof(struct sockaddr_in);
+ sin_to->sin_family = AF_INET;
+ memcpy(&sin_to->sin_addr, sadd6, sizeof(struct in_addr));
+ sin_to->sin_port = rport;
+
+ msghdr.msg_control = NULL;
+ msghdr.msg_controllen = 0;
+
}
- else if (errno != ENOENT)
+ else
{
- helplog(ASL_LEVEL_NOTICE, "stat failed for \"%s\", leaving in place: %s", racoon_config_path, strerror(errno));
- return;
+ struct cmsghdr *ctl;
+
+ memset(sin6_to, 0, sizeof(struct sockaddr_in6));
+ sin6_to->sin6_len = sizeof(struct sockaddr_in6);
+ sin6_to->sin6_family = AF_INET6;
+ memcpy(&sin6_to->sin6_addr, dadd6, sizeof(struct in6_addr));
+
+ sin6_to->sin6_port = rport;
+ sin6_to->sin6_flowinfo = 0;
+
+
+ msghdr.msg_control = ctlbuf;
+ msghdr.msg_controllen = sizeof(ctlbuf);
+ ctl = CMSG_FIRSTHDR(&msghdr);
+ ctl->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+ ctl->cmsg_level = IPPROTO_IPV6;
+ ctl->cmsg_type = IPV6_PKTINFO;
+ struct in6_pktinfo *pktinfo = (struct in6_pktinfo *) CMSG_DATA(ctl);
+ memcpy(&pktinfo->ipi6_addr, sadd6, sizeof(struct in6_addr));
+ pktinfo->ipi6_ifindex = 0;
}
-
- char racoon_config_path_orig[64];
- strlcpy(racoon_config_path_orig, dir, sizeof(racoon_config_path_orig));
- strlcat(racoon_config_path_orig, racoon_config_file_orig, sizeof(racoon_config_path_orig));
-
- ret = stat(racoon_config_path_orig, &s);
- debug("stat(%s): %d errno=%d", racoon_config_path_orig, ret, errno);
- if (ret == 0)
+
+ msghdr.msg_name = (struct sockaddr *)&ss_to;
+ msghdr.msg_namelen = ss_to.ss_len;
+ iov.iov_base = packet;
+ iov.iov_len = packetlen;
+ msghdr.msg_iov = &iov;
+ msghdr.msg_iovlen = 1;
+ msghdr.msg_flags = 0;
+
+again:
+ len = sendmsg(sock, &msghdr, 0);
+ if (len == -1)
{
- if (0 > rename(racoon_config_path_orig, racoon_config_path))
- helplog(ASL_LEVEL_NOTICE, "rename \"%s\" \"%s\" failed: %s", racoon_config_path_orig, racoon_config_path, strerror(errno));
- else
- debug("reverted \"%s\" to \"%s\"", racoon_config_path_orig, racoon_config_path);
+ if (errno == EINTR)
+ goto again;
}
- else if (errno != ENOENT)
+
+ if (len != packetlen)
{
- helplog(ASL_LEVEL_NOTICE, "stat failed for \"%s\", leaving in place: %s", racoon_config_path_orig, strerror(errno));
- return;
+ os_log(log_handle, "SendKeepalive: sendmsg failed %s", strerror(errno));
}
-}
+ else
+ {
+ char source[INET6_ADDRSTRLEN], dest[INET6_ADDRSTRLEN];
+
+ inet_ntop(af, (void *)sadd6, source, sizeof(source));
+ inet_ntop(af, (void *)dadd6, dest, sizeof(dest));
+
+ os_log(log_handle, "SendKeepalive: Success Source %s:%d, Dest %s:%d, %u, %u, %u",
+ source, ntohs(lport), dest, ntohs(rport), ntohl(seq), ntohl(ack), ntohs(win));
+
+ }
+ close(sock);
-static void
-moveAsideAnonymousRacoonConfiguration(const char* dir)
-{
- if (!dir) return;
+}
- debug("entry %s", dir);
- char racoon_config_path[64];
- strlcpy(racoon_config_path, dir, sizeof(racoon_config_path));
- strlcat(racoon_config_path, racoon_config_file, sizeof(racoon_config_path));
+void RetrieveTCPInfo(int family, const v6addr_t laddr, uint16_t lport, const v6addr_t raddr, uint16_t rport, uint32_t *seq, uint32_t *ack, uint16_t *win, int32_t *intfid, int *err)
+{
+
+ struct tcp_info ti;
+ struct info_tuple itpl;
+ int mib[4];
+ unsigned int miblen;
+ size_t len;
+ size_t sz;
+
+ memset(&itpl, 0, sizeof(struct info_tuple));
+ memset(&ti, 0, sizeof(struct tcp_info));
+
+ char buf1[INET6_ADDRSTRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+
+ buf1[0] = 0;
+ buf2[0] = 0;
+
+ inet_ntop(AF_INET6, laddr, buf1, sizeof(buf1));
+ inet_ntop(AF_INET6, raddr, buf2, sizeof(buf2));
+
+ os_log_info(log_handle, "RetrieveTCPInfo invoked: laddr is %s, raddr is %s", buf1, buf2);
+
+ os_log_info(log_handle,"RetrieveTCPInfo invoked: lport is[%d] rport is[%d] family is [%d]",
+ lport, rport, family);
- struct stat s;
- int ret = stat(racoon_config_path, &s);
- if (ret == 0)
+ if (family == AF_INET)
{
- if (IsFamiliarRacoonConfiguration(racoon_config_path))
- {
- helplog(ASL_LEVEL_INFO, "\"%s\" looks familiar, unlinking", racoon_config_path);
- unlink(racoon_config_path);
- }
- else
- {
- char racoon_config_path_orig[64];
- strlcpy(racoon_config_path_orig, dir, sizeof(racoon_config_path_orig));
- strlcat(racoon_config_path_orig, racoon_config_file_orig, sizeof(racoon_config_path_orig));
- if (0 > rename(racoon_config_path, racoon_config_path_orig)) // If we didn't write it, move it to the side so it can be reverted later
- helplog(ASL_LEVEL_NOTICE, "rename \"%s\" to \"%s\" failed: %s", racoon_config_path, racoon_config_path_orig, strerror(errno));
- else
- debug("successfully renamed \"%s\" to \"%s\"", racoon_config_path, racoon_config_path_orig);
- }
+ memcpy(&itpl.itpl_local_sin.sin_addr, laddr, sizeof(struct in_addr));
+ memcpy(&itpl.itpl_remote_sin.sin_addr, raddr, sizeof(struct in_addr));
+ itpl.itpl_local_sin.sin_port = lport;
+ itpl.itpl_remote_sin.sin_port = rport;
+ itpl.itpl_local_sin.sin_family = AF_INET;
+ itpl.itpl_remote_sin.sin_family = AF_INET;
}
- else if (errno != ENOENT)
+ else
{
- helplog(ASL_LEVEL_NOTICE, "stat failed for \"%s\", leaving in place: %s", racoon_config_path, strerror(errno));
- return;
+ memcpy(&itpl.itpl_local_sin6.sin6_addr, laddr, sizeof(struct in6_addr));
+ memcpy(&itpl.itpl_remote_sin6.sin6_addr, raddr, sizeof(struct in6_addr));
+ itpl.itpl_local_sin6.sin6_port = lport;
+ itpl.itpl_remote_sin6.sin6_port = rport;
+ itpl.itpl_local_sin6.sin6_family = AF_INET6;
+ itpl.itpl_remote_sin6.sin6_family = AF_INET6;
}
-}
-
-static int
-ensureExistenceOfRacoonConfigDir(const char* const racoon_config_dir)
-{
- struct stat s;
- int ret = stat(racoon_config_dir, &s);
- if (ret != 0)
+ itpl.itpl_proto = IPPROTO_TCP;
+ sz = sizeof(mib)/sizeof(mib[0]);
+ if (sysctlnametomib("net.inet.tcp.info", mib, &sz) == -1)
{
- if (errno != ENOENT)
- {
- helplog(ASL_LEVEL_ERR, "stat of \"%s\" failed (%d): %s",
- racoon_config_dir, ret, strerror(errno));
- return -1;
- }
- else
- {
- ret = mkdir(racoon_config_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
- if (ret != 0)
- {
- helplog(ASL_LEVEL_ERR, "mkdir \"%s\" failed: %s",
- racoon_config_dir, strerror(errno));
- return -1;
- }
- else
- helplog(ASL_LEVEL_INFO, "created directory \"%s\"", racoon_config_dir);
- }
+ os_log(log_handle, "RetrieveTCPInfo: sysctlnametomib failed %d, %s", errno, strerror(errno));
+ *err = errno;
}
- else if (!(s.st_mode & S_IFDIR))
+ miblen = (unsigned int)sz;
+ len = sizeof(struct tcp_info);
+ if (sysctl(mib, miblen, &ti, &len, &itpl, sizeof(struct info_tuple)) == -1)
{
- helplog(ASL_LEVEL_ERR, "\"%s\" is not a directory!",
- racoon_config_dir);
- return -1;
+ os_log(log_handle, "RetrieveTCPInfo: sysctl failed %d, %s", errno, strerror(errno));
+ *err = errno;
}
-
- return 0;
+
+ *seq = ti.tcpi_snd_nxt - 1;
+ *ack = ti.tcpi_rcv_nxt;
+ *win = ti.tcpi_rcv_space >> ti.tcpi_rcv_wscale;
+ *intfid = ti.tcpi_last_outif;
+ *err = KERN_SUCCESS;
+
}
-static int
-createAnonymousRacoonConfiguration(const char *fqdn)
-{
- static const char config1[] =
- "remote anonymous {\n"
- " exchange_mode aggressive;\n"
- " doi ipsec_doi;\n"
- " situation identity_only;\n"
- " verify_identifier off;\n"
- " generate_policy on;\n"
- " shared_secret keychain_by_id \"";
- static const char config2[] =
- "\";\n"
- " nonce_size 16;\n"
- " lifetime time 15 min;\n"
- " initial_contact on;\n"
- " support_proxy on;\n"
- " nat_traversal force;\n"
- " proposal_check claim;\n"
- " proposal {\n"
- " encryption_algorithm aes;\n"
- " hash_algorithm sha256;\n"
- " authentication_method pre_shared_key;\n"
- " dh_group 2;\n"
- " lifetime time 15 min;\n"
- " }\n"
- " proposal {\n"
- " encryption_algorithm aes;\n"
- " hash_algorithm sha1;\n"
- " authentication_method pre_shared_key;\n"
- " dh_group 2;\n"
- " lifetime time 15 min;\n"
- " }\n"
- "}\n\n"
- "sainfo anonymous { \n"
- " pfs_group 2;\n"
- " lifetime time 10 min;\n"
- " encryption_algorithm aes;\n"
- " authentication_algorithm hmac_sha256,hmac_sha1;\n"
- " compression_algorithm deflate;\n"
- "}\n";
- char tmp_config_path[64];
- char racoon_config_path[64];
- const char* const racoon_config_dir = GetRacoonConfigDir();
- const char* const racoon_config_dir_old = GetOldRacoonConfigDir();
- int fd = -1;
-
- debug("entry");
-
- if (0 > ensureExistenceOfRacoonConfigDir(racoon_config_dir))
- return -1;
-
- strlcpy(tmp_config_path, racoon_config_dir, sizeof(tmp_config_path));
- strlcat(tmp_config_path, "tmp.XXXXXX", sizeof(tmp_config_path));
+#ifndef MDNS_NO_IPSEC
- fd = mkstemp(tmp_config_path);
+static const char configHeader[] = "# BackToMyMac\n";
+static const char g_racoon_config_dir[] = "/var/run/racoon/";
+static const char g_racoon_config_dir_old[] = "/etc/racoon/remote/";
- if (0 > fd)
+static int MacOSXSystemBuildNumber(char* letter_out, int* minor_out)
+{
+ int major = 0, minor = 0;
+ char letter = 0, buildver[256]="<Unknown>";
+ CFDictionaryRef vers = _CFCopySystemVersionDictionary();
+ if (vers)
{
- helplog(ASL_LEVEL_ERR, "mkstemp \"%s\" failed: %s",
- tmp_config_path, strerror(errno));
- return -1;
+ CFStringRef cfbuildver = CFDictionaryGetValue(vers, _kCFSystemVersionBuildVersionKey);
+ if (cfbuildver) CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8);
+ sscanf(buildver, "%d%c%d", &major, &letter, &minor);
+ CFRelease(vers);
}
- write(fd, configHeader, sizeof(configHeader)-1);
- write(fd, config1, sizeof(config1)-1);
- write(fd, fqdn, strlen(fqdn));
- write(fd, config2, sizeof(config2)-1);
- close(fd);
-
- strlcpy(racoon_config_path, racoon_config_dir, sizeof(racoon_config_path));
- strlcat(racoon_config_path, racoon_config_file, sizeof(racoon_config_path));
-
- moveAsideAnonymousRacoonConfiguration(racoon_config_dir_old);
- moveAsideAnonymousRacoonConfiguration(racoon_config_dir);
+ else
+ os_log_info(log_handle, "_CFCopySystemVersionDictionary failed");
+
+ if (!major) { major=16; letter = 'A'; minor = 300; os_log_info(log_handle, "Note: No Major Build Version number found; assuming 16A300"); }
+ if (letter_out) *letter_out = letter;
+ if (minor_out) *minor_out = minor;
+ return(major);
+}
- if (0 > rename(tmp_config_path, racoon_config_path))
+static int UseOldRacoon()
+{
+ static int g_oldRacoon = -1;
+
+ if (g_oldRacoon == -1)
{
- unlink(tmp_config_path);
- helplog(ASL_LEVEL_ERR, "rename \"%s\" \"%s\" failed: %s",
- tmp_config_path, racoon_config_path, strerror(errno));
- revertAnonymousRacoonConfiguration(racoon_config_dir_old);
- revertAnonymousRacoonConfiguration(racoon_config_dir);
- return -1;
+ char letter = 0;
+ int minor = 0;
+ g_oldRacoon = (MacOSXSystemBuildNumber(&letter, &minor) < 10);
+ os_log_debug(log_handle, "%s", g_oldRacoon ? "old" : "new");
}
+
+ return g_oldRacoon;
+}
- debug("successfully renamed \"%s\" \"%s\"", tmp_config_path, racoon_config_path);
- return 0;
+static int RacoonSignal()
+{
+ return UseOldRacoon() ? SIGHUP : SIGUSR1;
}
-static int
-notifyRacoon(void)
+static int notifyRacoon(void)
{
- debug("entry");
+ os_log_debug(log_handle,"entry");
static const char racoon_pid_path[] = "/var/run/racoon.pid";
char buf[] = "18446744073709551615"; /* largest 64-bit integer */
char *p = NULL;
ssize_t n = 0;
unsigned long m = 0;
int fd = open(racoon_pid_path, O_RDONLY);
-
+
if (0 > fd)
{
- debug("open \"%s\" failed, and that's OK: %s", racoon_pid_path,
+ os_log_debug(log_handle,"open \"%s\" failed, and that's OK: %s", racoon_pid_path,
strerror(errno));
- return kmDNSHelperRacoonNotificationFailed;
+ return kHelperErr_RacoonNotificationFailed;
}
n = read(fd, buf, sizeof(buf)-1);
close(fd);
if (1 > n)
{
- debug("read of \"%s\" failed: %s", racoon_pid_path,
+ os_log_debug(log_handle,"read of \"%s\" failed: %s", racoon_pid_path,
n == 0 ? "empty file" : strerror(errno));
- return kmDNSHelperRacoonNotificationFailed;
+ return kHelperErr_RacoonNotificationFailed;
}
buf[n] = '\0';
m = strtoul(buf, &p, 10);
if (*p != '\0' && !isspace(*p))
{
- debug("invalid PID \"%s\" (around '%c')", buf, *p);
- return kmDNSHelperRacoonNotificationFailed;
+ os_log_debug(log_handle,"invalid PID \"%s\" (around '%c')", buf, *p);
+ return kHelperErr_RacoonNotificationFailed;
}
if (2 > m)
{
- debug("refusing to kill PID %lu", m);
- return kmDNSHelperRacoonNotificationFailed;
+ os_log_debug(log_handle,"refusing to kill PID %lu", m);
+ return kHelperErr_RacoonNotificationFailed;
}
if (0 != kill(m, RacoonSignal()))
{
- debug("Could not signal racoon (%lu): %s", m, strerror(errno));
- return kmDNSHelperRacoonNotificationFailed;
+ os_log_debug(log_handle,"Could not signal racoon (%lu): %s", m, strerror(errno));
+ return kHelperErr_RacoonNotificationFailed;
}
- debug("Sent racoon (%lu) signal %d", m, RacoonSignal());
+
+ os_log_debug(log_handle, "Sent racoon (%lu) signal %d", m, RacoonSignal());
return 0;
}
-static void
-closefds(int from)
+static const char* GetRacoonConfigDir()
+{
+ return UseOldRacoon() ? g_racoon_config_dir_old : g_racoon_config_dir;
+}
+/*
+static const char* GetOldRacoonConfigDir()
+{
+ return UseOldRacoon() ? NULL : g_racoon_config_dir_old;
+}
+*/
+
+static void closefds(int from)
{
int fd = 0;
struct dirent entry, *entryp = NULL;
DIR *dirp = opendir("/dev/fd");
-
+
if (dirp == NULL)
{
/* fall back to the erroneous getdtablesize method */
@@ -1411,60 +1601,59 @@ closefds(int from)
closedir(dirp);
}
-static int
-startRacoonOld(void)
+
+static int startRacoonOld(void)
{
- debug("entry");
+ os_log_debug(log_handle,"entry");
char * const racoon_args[] = { "/usr/sbin/racoon", "-e", NULL };
ssize_t n = 0;
pid_t pid = 0;
int status = 0;
-
+
if (0 == (pid = fork()))
{
closefds(0);
execve(racoon_args[0], racoon_args, NULL);
- helplog(ASL_LEVEL_ERR, "execve of \"%s\" failed: %s",
+ os_log_info(log_handle, "execve of \"%s\" failed: %s",
racoon_args[0], strerror(errno));
exit(2);
}
- helplog(ASL_LEVEL_NOTICE, "racoon (pid=%lu) started",
+ os_log_info(log_handle,"racoon (pid=%lu) started",
(unsigned long)pid);
n = waitpid(pid, &status, 0);
if (-1 == n)
{
- helplog(ASL_LEVEL_ERR, "Unexpected waitpid failure: %s",
+ os_log(log_handle, "Unexpected waitpid failure: %s",
strerror(errno));
- return kmDNSHelperRacoonStartFailed;
+ return kHelperErr_RacoonStartFailed;
}
else if (pid != n)
{
- helplog(ASL_LEVEL_ERR, "Unexpected waitpid return value %d",
- (int)n);
- return kmDNSHelperRacoonStartFailed;
+ os_log(log_handle, "Unexpected waitpid return value %d", (int)n);
+ return kHelperErr_RacoonStartFailed;
}
else if (WIFSIGNALED(status))
{
- helplog(ASL_LEVEL_ERR,
+ os_log(log_handle,
"racoon (pid=%lu) terminated due to signal %d",
(unsigned long)pid, WTERMSIG(status));
- return kmDNSHelperRacoonStartFailed;
+ return kHelperErr_RacoonStartFailed;
}
else if (WIFSTOPPED(status))
{
- helplog(ASL_LEVEL_ERR,
+ os_log(log_handle,
"racoon (pid=%lu) has stopped due to signal %d",
(unsigned long)pid, WSTOPSIG(status));
- return kmDNSHelperRacoonStartFailed;
+ return kHelperErr_RacoonStartFailed;
}
else if (0 != WEXITSTATUS(status))
{
- helplog(ASL_LEVEL_ERR,
+ os_log(log_handle,
"racoon (pid=%lu) exited with status %d",
(unsigned long)pid, WEXITSTATUS(status));
- return kmDNSHelperRacoonStartFailed;
+ return kHelperErr_RacoonStartFailed;
}
- debug("racoon (pid=%lu) daemonized normally", (unsigned long)pid);
+ os_log_debug(log_handle, "racoon (pid=%lu) daemonized normally", (unsigned long)pid);
return 0;
}
@@ -1480,18 +1669,17 @@ typedef struct vpnctl_hdr_struct
u_int16_t len;
} vpnctl_hdr;
-static int
-startRacoon(void)
+static int startRacoon(void)
{
- debug("entry");
+ os_log_debug(log_handle,"entry");
int fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (0 > fd)
{
- helplog(ASL_LEVEL_ERR, "Could not create endpoint for racoon control socket: %d %s",
+ os_log(log_handle,"Could not create endpoint for racoon control socket: %d %s",
errno, strerror(errno));
- return kmDNSHelperRacoonStartFailed;
+ return kHelperErr_RacoonStartFailed;
}
-
+
struct sockaddr_un saddr;
memset(&saddr, 0, sizeof(saddr));
saddr.sun_family = AF_UNIX;
@@ -1501,52 +1689,50 @@ startRacoon(void)
int result = connect(fd, (struct sockaddr*) &saddr, saddr.sun_len);
if (0 > result)
{
- helplog(ASL_LEVEL_ERR, "Could not connect racoon control socket %s: %d %s",
+ os_log(log_handle, "Could not connect racoon control socket %s: %d %s",
racoon_control_sock_path, errno, strerror(errno));
- return kmDNSHelperRacoonStartFailed;
+ return kHelperErr_RacoonStartFailed;
}
-
+
u_int32_t btmm_cookie = 0x4d4d5442;
vpnctl_hdr h = { htons(VPNCTL_CMD_PING), 0, btmm_cookie, 0, 0, 0 };
size_t bytes = 0;
ssize_t ret = 0;
-
+
while (bytes < sizeof(vpnctl_hdr))
{
ret = write(fd, ((unsigned char*)&h)+bytes, sizeof(vpnctl_hdr) - bytes);
if (ret == -1)
{
- helplog(ASL_LEVEL_ERR, "Could not write to racoon control socket: %d %s",
- errno, strerror(errno));
- return kmDNSHelperRacoonStartFailed;
+ os_log(log_handle, "Could not write to racoon control socket: %d %s", errno, strerror(errno));
+ return kHelperErr_RacoonStartFailed;
}
bytes += ret;
}
-
+
int nfds = fd + 1;
fd_set fds;
int counter = 0;
struct timeval tv;
bytes = 0;
h.cookie = 0;
-
+
for (counter = 0; counter < 100; counter++)
{
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv = (struct timeval){ 0, 10000 }; // 10 milliseconds * 100 iterations = 1 second max wait time
-
+
result = select(nfds, &fds, (fd_set*)NULL, (fd_set*)NULL, &tv);
if (result > 0)
{
if (FD_ISSET(fd, &fds))
{
ret = read(fd, ((unsigned char*)&h)+bytes, sizeof(vpnctl_hdr) - bytes);
-
+
if (ret == -1)
{
- helplog(ASL_LEVEL_ERR, "Could not read from racoon control socket: %d %s",
- strerror(errno));
+ os_log(log_handle,"Could not read from racoon control socket: %d %s", errno, strerror(errno));
break;
}
bytes += ret;
@@ -1554,72 +1740,53 @@ startRacoon(void)
}
else
{
- debug("select returned but fd_isset not on expected fd\n");
+ os_log_debug(log_handle, "select returned but fd_isset not on expected fd");
}
}
else if (result < 0)
{
- debug("select returned %d errno %d %s\n", result, errno, strerror(errno));
+ os_log_debug(log_handle, "select returned %d errno %d %s", result, errno, strerror(errno));
if (errno != EINTR) break;
}
}
-
+
close(fd);
-
- if (bytes < sizeof(vpnctl_hdr) || h.cookie != btmm_cookie) return kmDNSHelperRacoonStartFailed;
-
- debug("racoon started");
+
+ if (bytes < sizeof(vpnctl_hdr) || h.cookie != btmm_cookie)
+ return kHelperErr_RacoonStartFailed;
+
+ os_log_debug(log_handle, "racoon started");
return 0;
}
-static int
-kickRacoon(void)
+static int kickRacoon(void)
{
if ( 0 == notifyRacoon() )
return 0;
return UseOldRacoon() ? startRacoonOld() : startRacoon();
}
-#endif /* ndef MDNS_NO_IPSEC */
-
-int
-do_mDNSConfigureServer(__unused mach_port_t port, int updown, const char *fqdn, audit_token_t token)
+typedef enum _mDNSTunnelPolicyWhich
{
-#ifndef MDNS_NO_IPSEC
- debug("entry");
- if (!authorized(&token)) goto fin;
-
- switch ((enum mDNSUpDown)updown)
- {
- case kmDNSUp:
- if (0 != createAnonymousRacoonConfiguration(fqdn)) goto fin;
- break;
- case kmDNSDown:
- revertAnonymousRacoonConfiguration(GetOldRacoonConfigDir());
- revertAnonymousRacoonConfiguration(GetRacoonConfigDir());
- break;
- default:
- goto fin;
- }
-
- if (0 != kickRacoon())
- goto fin;
- debug("succeeded");
+ kmDNSTunnelPolicySetup,
+ kmDNSTunnelPolicyTeardown,
+ kmDNSTunnelPolicyGenerate
+} mDNSTunnelPolicyWhich;
-fin:
-#else
- (void)port; (void)updown; (void)fqdn; (void)token;
-#endif
- update_idle_timer();
- return KERN_SUCCESS;
-}
+// For kmDNSTunnelPolicySetup, you can setup IPv6-in-IPv6 tunnel or IPv6-in-IPv4 tunnel
+// kmDNSNoTunnel is used for other Policy types
+typedef enum _mDNSTunnelType
+{
+ kmDNSNoTunnel,
+ kmDNSIPv6IPv4Tunnel,
+ kmDNSIPv6IPv6Tunnel
+} mDNSTunnelType;
-#ifndef MDNS_NO_IPSEC
+static const uint8_t kWholeV6Mask = 128;
static unsigned int routeSeq = 1;
-static int
-setupTunnelRoute(v6addr_t local, v6addr_t remote)
+static int setupTunnelRoute(const v6addr_t local, const v6addr_t remote)
{
struct
{
@@ -1629,14 +1796,15 @@ setupTunnelRoute(v6addr_t local, v6addr_t remote)
} msg;
int err = 0;
int s = -1;
-
+
if (0 > (s = socket(PF_ROUTE, SOCK_RAW, AF_INET)))
{
- helplog(ASL_LEVEL_ERR, "socket(PF_ROUTE, ...) failed: %s",
- strerror(errno));
- err = kmDNSHelperRoutingSocketCreationFailed;
+ os_log(log_handle,"socket(PF_ROUTE, ...) failed: %s", strerror(errno));
+
+ err = kHelperErr_RoutingSocketCreationFailed;
goto fin;
}
+
memset(&msg, 0, sizeof(msg));
msg.hdr.rtm_msglen = sizeof(msg);
msg.hdr.rtm_type = RTM_ADD;
@@ -1647,36 +1815,35 @@ setupTunnelRoute(v6addr_t local, v6addr_t remote)
msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
msg.hdr.rtm_inits = RTV_MTU;
msg.hdr.rtm_rmx.rmx_mtu = 1280;
-
+
msg.dst.sin6_len = sizeof(msg.dst);
msg.dst.sin6_family = AF_INET6;
memcpy(&msg.dst.sin6_addr, remote, sizeof(msg.dst.sin6_addr));
-
+
msg.gtwy.sin6_len = sizeof(msg.gtwy);
msg.gtwy.sin6_family = AF_INET6;
memcpy(&msg.gtwy.sin6_addr, local, sizeof(msg.gtwy.sin6_addr));
-
+
/* send message, ignore error when route already exists */
if (0 > write(s, &msg, msg.hdr.rtm_msglen))
{
int errno_ = errno;
-
- debug("write to routing socket failed: %s", strerror(errno_));
+
+ os_log_info(log_handle,"write to routing socket failed: %s", strerror(errno_));
if (EEXIST != errno_)
{
- err = kmDNSHelperRouteAdditionFailed;
+ err = kHelperErr_RouteAdditionFailed;
goto fin;
}
}
-
+
fin:
if (0 <= s)
close(s);
return err;
}
-static int
-teardownTunnelRoute(v6addr_t remote)
+static int teardownTunnelRoute(const v6addr_t remote)
{
struct
{
@@ -1685,75 +1852,113 @@ teardownTunnelRoute(v6addr_t remote)
} msg;
int err = 0;
int s = -1;
-
+
if (0 > (s = socket(PF_ROUTE, SOCK_RAW, AF_INET)))
{
- helplog(ASL_LEVEL_ERR, "socket(PF_ROUTE, ...) failed: %s",
- strerror(errno));
- err = kmDNSHelperRoutingSocketCreationFailed;
+ os_log(log_handle, "socket(PF_ROUTE, ...) failed: %s", strerror(errno));
+ err = kHelperErr_RoutingSocketCreationFailed;
goto fin;
}
memset(&msg, 0, sizeof(msg));
-
+
msg.hdr.rtm_msglen = sizeof(msg);
msg.hdr.rtm_type = RTM_DELETE;
msg.hdr.rtm_version = RTM_VERSION;
msg.hdr.rtm_seq = routeSeq++;
msg.hdr.rtm_addrs = RTA_DST;
-
+
msg.dst.sin6_len = sizeof(msg.dst);
msg.dst.sin6_family = AF_INET6;
memcpy(&msg.dst.sin6_addr, remote, sizeof(msg.dst.sin6_addr));
if (0 > write(s, &msg, msg.hdr.rtm_msglen))
{
int errno_ = errno;
-
- debug("write to routing socket failed: %s", strerror(errno_));
+
+ os_log_debug(log_handle,"write to routing socket failed: %s", strerror(errno_));
+
if (ESRCH != errno_)
{
- err = kmDNSHelperRouteDeletionFailed;
+ err = kHelperErr_RouteDeletionFailed;
goto fin;
}
}
-
+
fin:
if (0 <= s)
close(s);
return err;
}
-static int
-v4addr_to_string(v4addr_t addr, char *buf, size_t buflen)
+static int v4addr_to_string(v4addr_t addr, char *buf, size_t buflen)
{
if (NULL == inet_ntop(AF_INET, addr, buf, buflen))
{
- helplog(ASL_LEVEL_ERR, "inet_ntop failed: %s",
- strerror(errno));
- return kmDNSHelperInvalidNetworkAddress;
+ os_log(log_handle, "v4addr_to_string() inet_ntop failed: %s", strerror(errno));
+ return kHelperErr_InvalidNetworkAddress;
}
else
+ {
return 0;
+ }
}
-static int
-v6addr_to_string(v6addr_t addr, char *buf, size_t buflen)
+static int v6addr_to_string(const v6addr_t addr, char *buf, size_t buflen)
{
if (NULL == inet_ntop(AF_INET6, addr, buf, buflen))
{
- helplog(ASL_LEVEL_ERR, "inet_ntop failed: %s",
- strerror(errno));
- return kmDNSHelperInvalidNetworkAddress;
+ os_log(log_handle, "v6addr_to_string inet_ntop failed: %s", strerror(errno));
+ return kHelperErr_InvalidNetworkAddress;
}
else
+ {
return 0;
+ }
+}
+
+static int ensureExistenceOfRacoonConfigDir(const char* const racoon_config_dir)
+{
+ struct stat s;
+ int ret = stat(racoon_config_dir, &s);
+ if (ret != 0)
+ {
+ if (errno != ENOENT)
+ {
+ os_log(log_handle, "stat of \"%s\" failed (%d): %s",
+ racoon_config_dir, ret, strerror(errno));
+ return -1;
+ }
+ else
+ {
+ ret = mkdir(racoon_config_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+ if (ret != 0)
+ {
+ os_log(log_handle, "mkdir \"%s\" failed: %s",
+ racoon_config_dir, strerror(errno));
+ return -1;
+ }
+ else
+ {
+ os_log_info(log_handle, "created directory \"%s\"", racoon_config_dir);
+ }
+ }
+ }
+ else if (!(s.st_mode & S_IFDIR))
+ {
+ os_log(log_handle, "\"%s\" is not a directory!",
+ racoon_config_dir);
+ return -1;
+ }
+
+ return 0;
}
+
+
/* Caller owns object returned in `policy' */
-static int
-generateTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, int in,
+static int generateTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, int in,
v4addr_t src, uint16_t src_port,
v4addr_t dst, uint16_t dst_port,
- v6addr_t src6, v6addr_t dst6,
+ const v6addr_t src6, const v6addr_t dst6,
ipsec_policy_t *policy, size_t *len)
{
char srcs[INET_ADDRSTRLEN], dsts[INET_ADDRSTRLEN];
@@ -1762,132 +1967,134 @@ generateTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, int in,
char *inOut = in ? "in" : "out";
ssize_t n = 0;
int err = 0;
-
+
*policy = NULL;
*len = 0;
-
+
switch (which)
{
- case kmDNSTunnelPolicySetup:
- if (type == kmDNSIPv6IPv4Tunnel)
- {
- if (0 != (err = v4addr_to_string(src, srcs, sizeof(srcs))))
- goto fin;
- if (0 != (err = v4addr_to_string(dst, dsts, sizeof(dsts))))
- goto fin;
- n = snprintf(buf, sizeof(buf),
- "%s ipsec esp/tunnel/%s[%u]-%s[%u]/require",
- inOut, srcs, src_port, dsts, dst_port);
- }
- else if (type == kmDNSIPv6IPv6Tunnel)
- {
- if (0 != (err = v6addr_to_string(src6, srcs6, sizeof(srcs6))))
- goto fin;
- if (0 != (err = v6addr_to_string(dst6, dsts6, sizeof(dsts6))))
- goto fin;
- n = snprintf(buf, sizeof(buf),
- "%s ipsec esp/tunnel/%s-%s/require",
- inOut, srcs6, dsts6);
- }
- break;
- case kmDNSTunnelPolicyTeardown:
- n = strlcpy(buf, inOut, sizeof(buf));
- break;
- case kmDNSTunnelPolicyGenerate:
- n = snprintf(buf, sizeof(buf), "%s generate", inOut);
- break;
- default:
- err = kmDNSHelperIPsecPolicyCreationFailed;
- goto fin;
+ case kmDNSTunnelPolicySetup:
+ if (type == kmDNSIPv6IPv4Tunnel)
+ {
+ if (0 != (err = v4addr_to_string(src, srcs, sizeof(srcs))))
+ goto fin;
+ if (0 != (err = v4addr_to_string(dst, dsts, sizeof(dsts))))
+ goto fin;
+ n = snprintf(buf, sizeof(buf),
+ "%s ipsec esp/tunnel/%s[%u]-%s[%u]/require",
+ inOut, srcs, src_port, dsts, dst_port);
+ }
+ else if (type == kmDNSIPv6IPv6Tunnel)
+ {
+ if (0 != (err = v6addr_to_string(src6, srcs6, sizeof(srcs6))))
+ goto fin;
+ if (0 != (err = v6addr_to_string(dst6, dsts6, sizeof(dsts6))))
+ goto fin;
+ n = snprintf(buf, sizeof(buf),
+ "%s ipsec esp/tunnel/%s-%s/require",
+ inOut, srcs6, dsts6);
+ }
+ break;
+ case kmDNSTunnelPolicyTeardown:
+ n = strlcpy(buf, inOut, sizeof(buf));
+ break;
+ case kmDNSTunnelPolicyGenerate:
+ n = snprintf(buf, sizeof(buf), "%s generate", inOut);
+ break;
+ default:
+ err = kHelperErr_IPsecPolicyCreationFailed;
+ goto fin;
}
-
+
if (n >= (int)sizeof(buf))
{
- err = kmDNSHelperResultTooLarge;
+ err = kHelperErr_ResultTooLarge;
goto fin;
}
-
- debug("policy=\"%s\"", buf);
+
+ os_log_info(log_handle, "policy=\"%s\"", buf);
+
if (NULL == (*policy = (ipsec_policy_t)ipsec_set_policy(buf, n)))
{
- helplog(ASL_LEVEL_ERR,
- "Could not create IPsec policy from \"%s\"", buf);
- err = kmDNSHelperIPsecPolicyCreationFailed;
+ os_log_info(log_handle, "Could not create IPsec policy from \"%s\"", buf);
+ err = kHelperErr_IPsecPolicyCreationFailed;
goto fin;
}
*len = ((ipsec_policy_t)(*policy))->sadb_x_policy_len * 8;
-
+
fin:
return err;
}
-static int
-sendPolicy(int s, int setup,
+static int sendPolicy(int s, int setup,
struct sockaddr *src, uint8_t src_bits,
struct sockaddr *dst, uint8_t dst_bits,
ipsec_policy_t policy, size_t len)
{
static unsigned int policySeq = 0;
int err = 0;
-
- debug("entry, setup=%d", setup);
+
+ os_log_debug(log_handle, "entry, setup=%d", setup);
+
if (setup)
err = pfkey_send_spdadd(s, src, src_bits, dst, dst_bits, -1,
(char *)policy, len, policySeq++);
else
err = pfkey_send_spddelete(s, src, src_bits, dst, dst_bits, -1,
(char *)policy, len, policySeq++);
+
if (0 > err)
{
- helplog(ASL_LEVEL_ERR, "Could not set IPsec policy: %s",
- ipsec_strerror());
- err = kmDNSHelperIPsecPolicySetFailed;
+ os_log(log_handle, "Could not set IPsec policy: %s", ipsec_strerror());
+ err = kHelperErr_IPsecPolicySetFailed;
goto fin;
}
else
+ {
err = 0;
- debug("succeeded");
-
+ }
+
+ os_log_debug(log_handle, "succeeded");
+
fin:
return err;
}
-static int
-removeSA(int s, struct sockaddr *src, struct sockaddr *dst)
+static int removeSA(int s, struct sockaddr *src, struct sockaddr *dst)
{
int err = 0;
-
- debug("entry");
+
+ os_log_debug(log_handle, "entry");
+
err = pfkey_send_delete_all(s, SADB_SATYPE_ESP, IPSEC_MODE_ANY, src, dst);
if (0 > err)
{
- helplog(ASL_LEVEL_ERR, "Could not remove IPsec SA: %s", ipsec_strerror());
- err = kmDNSHelperIPsecRemoveSAFailed;
+ os_log(log_handle, "Could not remove IPsec SA: %s", ipsec_strerror());
+ err = kHelperErr_IPsecRemoveSAFailed;
goto fin;
}
err = pfkey_send_delete_all(s, SADB_SATYPE_ESP, IPSEC_MODE_ANY, dst, src);
if (0 > err)
{
- helplog(ASL_LEVEL_ERR, "Could not remove IPsec SA: %s", ipsec_strerror());
- err = kmDNSHelperIPsecRemoveSAFailed;
+ os_log(log_handle, "Could not remove IPsec SA: %s", ipsec_strerror());
+ err = kHelperErr_IPsecRemoveSAFailed;
goto fin;
}
else
err = 0;
-
- debug("succeeded");
-
+
+ os_log_debug(log_handle, "succeeded");
+
fin:
return err;
}
-static int
-doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type,
- v6addr_t loc_inner, uint8_t loc_bits,
+static int doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type,
+ const v6addr_t loc_inner, uint8_t loc_bits,
v4addr_t loc_outer, uint16_t loc_port,
- v6addr_t rmt_inner, uint8_t rmt_bits,
+ const v6addr_t rmt_inner, uint8_t rmt_bits,
v4addr_t rmt_outer, uint16_t rmt_port,
- v6addr_t loc_outer6, v6addr_t rmt_outer6)
+ const v6addr_t loc_outer6, const v6addr_t rmt_outer6)
{
struct sockaddr_in6 sin6_loc;
struct sockaddr_in6 sin6_rmt;
@@ -1895,47 +2102,48 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type,
size_t len = 0;
int s = -1;
int err = 0;
-
- debug("entry");
+
+ os_log_debug(log_handle,"entry");
if (0 > (s = pfkey_open()))
{
- helplog(ASL_LEVEL_ERR,
- "Could not create IPsec policy socket: %s",
- ipsec_strerror());
- err = kmDNSHelperIPsecPolicySocketCreationFailed;
+ os_log(log_handle, "Could not create IPsec policy socket: %s", ipsec_strerror());
+ err = kHelperErr_IPsecPolicySocketCreationFailed;
goto fin;
}
-
+
memset(&sin6_loc, 0, sizeof(sin6_loc));
sin6_loc.sin6_len = sizeof(sin6_loc);
sin6_loc.sin6_family = AF_INET6;
sin6_loc.sin6_port = htons(0);
memcpy(&sin6_loc.sin6_addr, loc_inner, sizeof(sin6_loc.sin6_addr));
-
+
memset(&sin6_rmt, 0, sizeof(sin6_rmt));
sin6_rmt.sin6_len = sizeof(sin6_rmt);
sin6_rmt.sin6_family = AF_INET6;
sin6_rmt.sin6_port = htons(0);
memcpy(&sin6_rmt.sin6_addr, rmt_inner, sizeof(sin6_rmt.sin6_addr));
-
+
int setup = which != kmDNSTunnelPolicyTeardown;
-
+
if (0 != (err = generateTunnelPolicy(which, type, 1,
rmt_outer, rmt_port,
loc_outer, loc_port,
rmt_outer6, loc_outer6,
&policy, &len)))
goto fin;
+
if (0 != (err = sendPolicy(s, setup,
(struct sockaddr *)&sin6_rmt, rmt_bits,
(struct sockaddr *)&sin6_loc, loc_bits,
policy, len)))
goto fin;
+
if (NULL != policy)
{
free(policy);
policy = NULL;
}
+
if (0 != (err = generateTunnelPolicy(which, type, 0,
loc_outer, loc_port,
rmt_outer, rmt_port,
@@ -1947,7 +2155,7 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type,
(struct sockaddr *)&sin6_rmt, rmt_bits,
policy, len)))
goto fin;
-
+
if (which == kmDNSTunnelPolicyTeardown)
{
if (rmt_port) // Outer tunnel is IPv4
@@ -1960,7 +2168,7 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type,
sin_loc.sin_len = sizeof(sin_loc);
sin_loc.sin_family = AF_INET;
memcpy(&sin_loc.sin_addr, loc_outer, sizeof(sin_loc.sin_addr));
-
+
memset(&sin_rmt, 0, sizeof(sin_rmt));
sin_rmt.sin_len = sizeof(sin_rmt);
sin_rmt.sin_family = AF_INET;
@@ -1975,12 +2183,12 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type,
{
struct sockaddr_in6 sin6_lo;
struct sockaddr_in6 sin6_rm;
-
+
memset(&sin6_lo, 0, sizeof(sin6_lo));
sin6_lo.sin6_len = sizeof(sin6_lo);
sin6_lo.sin6_family = AF_INET6;
memcpy(&sin6_lo.sin6_addr, loc_outer6, sizeof(sin6_lo.sin6_addr));
-
+
memset(&sin6_rm, 0, sizeof(sin6_rm));
sin6_rm.sin6_len = sizeof(sin6_rm);
sin6_rm.sin6_family = AF_INET6;
@@ -1990,10 +2198,9 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type,
}
}
}
-
-
- debug("succeeded");
-
+
+ os_log_debug(log_handle,"succeeded");
+
fin:
if (s >= 0)
pfkey_close(s);
@@ -2004,104 +2211,117 @@ fin:
#endif /* ndef MDNS_NO_IPSEC */
-int
-do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete,
- v6addr_t loc_inner, v6addr_t loc_outer6, uint16_t loc_port,
- v6addr_t rmt_inner, v6addr_t rmt_outer6, uint16_t rmt_port,
- const char *id, int *err, audit_token_t token)
+int HelperAutoTunnelSetKeys(int replacedelete, const v6addr_t loc_inner, const v6addr_t loc_outer6, uint16_t loc_port, const v6addr_t rmt_inner,
+ const v6addr_t rmt_outer6, uint16_t rmt_port, const char *id, int *err)
{
#ifndef MDNS_NO_IPSEC
static const char config[] =
- "%s"
- "remote %s [%u] {\n"
- " disconnect_on_idle idle_timeout 600 idle_direction idle_outbound;\n"
- " exchange_mode aggressive;\n"
- " doi ipsec_doi;\n"
- " situation identity_only;\n"
- " verify_identifier off;\n"
- " generate_policy on;\n"
- " my_identifier user_fqdn \"%s\";\n"
- " shared_secret keychain \"%s\";\n"
- " nonce_size 16;\n"
- " lifetime time 15 min;\n"
- " initial_contact on;\n"
- " support_proxy on;\n"
- " nat_traversal force;\n"
- " proposal_check claim;\n"
- " proposal {\n"
- " encryption_algorithm aes;\n"
- " hash_algorithm sha256;\n"
- " authentication_method pre_shared_key;\n"
- " dh_group 2;\n"
- " lifetime time 15 min;\n"
- " }\n"
- " proposal {\n"
- " encryption_algorithm aes;\n"
- " hash_algorithm sha1;\n"
- " authentication_method pre_shared_key;\n"
- " dh_group 2;\n"
- " lifetime time 15 min;\n"
- " }\n"
- "}\n\n"
- "sainfo address %s any address %s any {\n"
- " pfs_group 2;\n"
- " lifetime time 10 min;\n"
- " encryption_algorithm aes;\n"
- " authentication_algorithm hmac_sha256,hmac_sha1;\n"
- " compression_algorithm deflate;\n"
- "}\n\n"
- "sainfo address %s any address %s any {\n"
- " pfs_group 2;\n"
- " lifetime time 10 min;\n"
- " encryption_algorithm aes;\n"
- " authentication_algorithm hmac_sha256,hmac_sha1;\n"
- " compression_algorithm deflate;\n"
- "}\n";
+ "%s"
+ "remote %s [%u] {\n"
+ " disconnect_on_idle idle_timeout 600 idle_direction idle_outbound;\n"
+ " exchange_mode aggressive;\n"
+ " doi ipsec_doi;\n"
+ " situation identity_only;\n"
+ " verify_identifier off;\n"
+ " generate_policy on;\n"
+ " my_identifier user_fqdn \"%s\";\n"
+ " shared_secret keychain \"%s\";\n"
+ " nonce_size 16;\n"
+ " lifetime time 15 min;\n"
+ " initial_contact on;\n"
+ " support_proxy on;\n"
+ " nat_traversal force;\n"
+ " proposal_check claim;\n"
+ " proposal {\n"
+ " encryption_algorithm aes;\n"
+ " hash_algorithm sha256;\n"
+ " authentication_method pre_shared_key;\n"
+ " dh_group 2;\n"
+ " lifetime time 15 min;\n"
+ " }\n"
+ " proposal {\n"
+ " encryption_algorithm aes;\n"
+ " hash_algorithm sha1;\n"
+ " authentication_method pre_shared_key;\n"
+ " dh_group 2;\n"
+ " lifetime time 15 min;\n"
+ " }\n"
+ "}\n\n"
+ "sainfo address %s any address %s any {\n"
+ " pfs_group 2;\n"
+ " lifetime time 10 min;\n"
+ " encryption_algorithm aes;\n"
+ " authentication_algorithm hmac_sha256,hmac_sha1;\n"
+ " compression_algorithm deflate;\n"
+ "}\n\n"
+ "sainfo address %s any address %s any {\n"
+ " pfs_group 2;\n"
+ " lifetime time 10 min;\n"
+ " encryption_algorithm aes;\n"
+ " authentication_algorithm hmac_sha256,hmac_sha1;\n"
+ " compression_algorithm deflate;\n"
+ "}\n";
char path[PATH_MAX] = "";
char li[INET6_ADDRSTRLEN], lo[INET_ADDRSTRLEN], lo6[INET6_ADDRSTRLEN],
- ri[INET6_ADDRSTRLEN], ro[INET_ADDRSTRLEN], ro6[INET6_ADDRSTRLEN];
+ ri[INET6_ADDRSTRLEN], ro[INET_ADDRSTRLEN], ro6[INET6_ADDRSTRLEN];
FILE *fp = NULL;
int fd = -1;
char tmp_path[PATH_MAX] = "";
v4addr_t loc_outer, rmt_outer;
-
- debug("entry");
- *err = 0;
- if (!authorized(&token))
- {
- *err = kmDNSHelperNotAuthorized;
- goto fin;
- }
+
+ os_log_debug(log_handle,"HelperAutoTunnelSetKeys: entry");
+ *err = kHelperErr_NoErr;
+
+ char buf1[INET6_ADDRSTRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+ char buf3[INET6_ADDRSTRLEN];
+ char buf4[INET6_ADDRSTRLEN];
+
+ buf1[0] = 0;
+ buf2[0] = 0;
+ buf3[0] = 0;
+ buf4[0] = 0;
+
+ inet_ntop(AF_INET6, loc_inner, buf1, sizeof(buf1));
+ inet_ntop(AF_INET6, loc_outer6, buf2, sizeof(buf2));
+ inet_ntop(AF_INET6, rmt_inner, buf3, sizeof(buf3));
+ inet_ntop(AF_INET6, rmt_outer6, buf4, sizeof(buf4));
+
+ os_log_info(log_handle, "HelperAutoTunnelSetKeys: Parameters are local_inner is %s, local_outer is %s, remote_inner is %s, remote_outer is %s id is %s",
+ buf1, buf2, buf3, buf4, id);
+
switch ((enum mDNSAutoTunnelSetKeysReplaceDelete)replacedelete)
{
- case kmDNSAutoTunnelSetKeysReplace:
- case kmDNSAutoTunnelSetKeysDelete:
- break;
- default:
- *err = kmDNSHelperInvalidTunnelSetKeysOperation;
- goto fin;
+ case kmDNSAutoTunnelSetKeysReplace:
+ case kmDNSAutoTunnelSetKeysDelete:
+ break;
+ default:
+ *err = kHelperErr_InvalidTunnelSetKeysOperation;
+ goto fin;
}
-
+
if (0 != (*err = v6addr_to_string(loc_inner, li, sizeof(li))))
goto fin;
if (0 != (*err = v6addr_to_string(rmt_inner, ri, sizeof(ri))))
goto fin;
-
- debug("loc_inner=%s rmt_inner=%s", li, ri);
+
+ os_log_debug(log_handle, "loc_inner=%s rmt_inner=%s", li, ri);
+
if (!rmt_port)
{
loc_outer[0] = loc_outer[1] = loc_outer[2] = loc_outer[3] = 0;
rmt_outer[0] = rmt_outer[1] = rmt_outer[2] = rmt_outer[3] = 0;
-
+
if (0 != (*err = v6addr_to_string(loc_outer6, lo6, sizeof(lo6))))
goto fin;
if (0 != (*err = v6addr_to_string(rmt_outer6, ro6, sizeof(ro6))))
goto fin;
- debug("IPv6 outer tunnel: loc_outer6=%s rmt_outer6=%s", lo6, ro6);
- if ((int)sizeof(path) <= snprintf(path, sizeof(path),
- "%s%s.conf", GetRacoonConfigDir(), ro6))
+
+ os_log_debug(log_handle, "IPv6 outer tunnel: loc_outer6=%s rmt_outer6=%s", lo6, ro6);
+
+ if ((int)sizeof(path) <= snprintf(path, sizeof(path), "%s%s.conf", GetRacoonConfigDir(), ro6))
{
- *err = kmDNSHelperResultTooLarge;
+ *err = kHelperErr_ResultTooLarge;
goto fin;
}
}
@@ -2111,77 +2331,71 @@ do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete,
loc_outer[1] = loc_outer6[1];
loc_outer[2] = loc_outer6[2];
loc_outer[3] = loc_outer6[3];
-
+
rmt_outer[0] = rmt_outer6[0];
rmt_outer[1] = rmt_outer6[1];
rmt_outer[2] = rmt_outer6[2];
rmt_outer[3] = rmt_outer6[3];
-
+
if (0 != (*err = v4addr_to_string(loc_outer, lo, sizeof(lo))))
goto fin;
if (0 != (*err = v4addr_to_string(rmt_outer, ro, sizeof(ro))))
goto fin;
- debug("IPv4 outer tunnel: loc_outer=%s loc_port=%u rmt_outer=%s rmt_port=%u",
- lo, loc_port, ro, rmt_port);
-
- if ((int)sizeof(path) <= snprintf(path, sizeof(path),
- "%s%s.%u.conf", GetRacoonConfigDir(), ro,
- rmt_port))
+
+ os_log_debug(log_handle, "IPv4 outer tunnel: loc_outer=%s loc_port=%u rmt_outer=%s rmt_port=%u",
+ lo, loc_port, ro, rmt_port);
+
+ if ((int)sizeof(path) <= snprintf(path, sizeof(path), "%s%s.%u.conf", GetRacoonConfigDir(), ro, rmt_port))
{
- *err = kmDNSHelperResultTooLarge;
+ *err = kHelperErr_ResultTooLarge;
goto fin;
}
}
-
-
-
+
if (kmDNSAutoTunnelSetKeysReplace == replacedelete)
{
if (0 > ensureExistenceOfRacoonConfigDir(GetRacoonConfigDir()))
{
- *err = kmDNSHelperRacoonConfigCreationFailed;
+ *err = kHelperErr_RacoonConfigCreationFailed;
goto fin;
}
if ((int)sizeof(tmp_path) <=
snprintf(tmp_path, sizeof(tmp_path), "%s.XXXXXX", path))
{
- *err = kmDNSHelperResultTooLarge;
+ *err = kHelperErr_ResultTooLarge;
goto fin;
}
if (0 > (fd = mkstemp(tmp_path)))
{
- helplog(ASL_LEVEL_ERR, "mkstemp \"%s\" failed: %s",
- tmp_path, strerror(errno));
- *err = kmDNSHelperRacoonConfigCreationFailed;
+ os_log(log_handle, "mkstemp \"%s\" failed: %s", tmp_path, strerror(errno));
+ *err = kHelperErr_RacoonConfigCreationFailed;
goto fin;
}
if (NULL == (fp = fdopen(fd, "w")))
{
- helplog(ASL_LEVEL_ERR, "fdopen: %s",
- strerror(errno));
- *err = kmDNSHelperRacoonConfigCreationFailed;
+ os_log(log_handle, "fdopen: %s", strerror(errno));
+ *err = kHelperErr_RacoonConfigCreationFailed;
goto fin;
}
+
fd = -1;
fprintf(fp, config, configHeader, (!rmt_port ? ro6 : ro), rmt_port, id, id, ri, li, li, ri);
fclose(fp);
fp = NULL;
+
if (0 > rename(tmp_path, path))
{
- helplog(ASL_LEVEL_ERR,
- "rename \"%s\" \"%s\" failed: %s",
- tmp_path, path, strerror(errno));
- *err = kmDNSHelperRacoonConfigCreationFailed;
+ os_log(log_handle, "rename \"%s\" \"%s\" failed: %s", tmp_path, path, strerror(errno));
+ *err = kHelperErr_RacoonConfigCreationFailed;
goto fin;
}
}
else
{
if (0 != unlink(path))
- debug("unlink \"%s\" failed: %s", path,
- strerror(errno));
+ os_log_debug(log_handle, "unlink \"%s\" failed: %s", path, strerror(errno));
}
-
+
if (0 != (*err = doTunnelPolicy(kmDNSTunnelPolicyTeardown, kmDNSNoTunnel,
loc_inner, kWholeV6Mask, loc_outer, loc_port,
rmt_inner, kWholeV6Mask, rmt_outer, rmt_port, loc_outer6, rmt_outer6)))
@@ -2191,19 +2405,20 @@ do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete,
loc_inner, kWholeV6Mask, loc_outer, loc_port,
rmt_inner, kWholeV6Mask, rmt_outer, rmt_port, loc_outer6, rmt_outer6)))
goto fin;
-
+
if (0 != (*err = teardownTunnelRoute(rmt_inner)))
goto fin;
+
if (kmDNSAutoTunnelSetKeysReplace == replacedelete &&
0 != (*err = setupTunnelRoute(loc_inner, rmt_inner)))
goto fin;
-
+
if (kmDNSAutoTunnelSetKeysReplace == replacedelete &&
0 != (*err = kickRacoon()))
goto fin;
-
- debug("succeeded");
-
+
+ os_log_debug(log_handle, "succeeded");
+
fin:
if (NULL != fp)
fclose(fp);
@@ -2212,709 +2427,14 @@ fin:
unlink(tmp_path);
#else
(void)replacedelete; (void)loc_inner; (void)loc_outer6; (void)loc_port; (void)rmt_inner;
- (void)rmt_outer6; (void)rmt_port; (void)id; (void)token;
-
- *err = kmDNSHelperIPsecDisabled;
+ (void)rmt_outer6; (void)rmt_port; (void)id;
+
+ *err = kHelperErr_IPsecDisabled;
#endif /* MDNS_NO_IPSEC */
update_idle_timer();
return KERN_SUCCESS;
}
-kern_return_t
-do_mDNSSendWakeupPacket(__unused mach_port_t port, unsigned ifid, const char *eth_addr, const char *ip_addr, int iteration, audit_token_t token)
-{
- int bpf_fd, i, j;
- struct ifreq ifr;
- char ifname[IFNAMSIZ];
- char packet[512];
- char *ptr = packet;
- char bpf_device[12];
- struct ether_addr *ea;
- (void) ip_addr; // unused
- (void) iteration; // unused
- (void) token; // unused
-
- if (if_indextoname(ifid, ifname) == NULL)
- {
- helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket invalid interface index %u", ifid);
- return errno;
- }
-
- ea = ether_aton(eth_addr);
- if (ea == NULL)
- {
- helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket invalid ethernet address %s", eth_addr);
- return errno;
- }
-
- for (i = 0; i < 100; i++)
- {
- snprintf(bpf_device, sizeof(bpf_device), "/dev/bpf%d", i);
- bpf_fd = open(bpf_device, O_RDWR, 0);
- if (bpf_fd == -1)
- continue;
- else break;
- }
-
- if (bpf_fd == -1)
- {
- helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket cannot find a bpf device");
- return ENXIO;
- }
-
- memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-
- if (ioctl(bpf_fd, BIOCSETIF, (char *)&ifr) < 0)
- {
- helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket BIOCSETIF failed %s", strerror(errno));
- return errno;
- }
-
- // 0x00 Destination address
- for (i=0; i<6; i++) *ptr++ = ea->octet[i];
-
- // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us)
- for (i=0; i<6; i++) *ptr++ = 0;
-
- // 0x0C Ethertype (0x0842)
- *ptr++ = 0x08;
- *ptr++ = 0x42;
-
- // 0x0E Wakeup sync sequence
- for (i=0; i<6; i++) *ptr++ = 0xFF;
-
- // 0x14 Wakeup data
- for (j=0; j<16; j++) for (i=0; i<6; i++) *ptr++ = ea->octet[i];
-
- // 0x74 Password
- for (i=0; i<6; i++) *ptr++ = 0;
-
- if (write(bpf_fd, packet, ptr - packet) < 0)
- {
- helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket write failed %s", strerror(errno));
- return errno;
- }
- helplog(ASL_LEVEL_INFO, "do_mDNSSendWakeupPacket sent unicast eth_addr %s, ip_addr %s", eth_addr, ip_addr);
- // Send a broadcast one to handle ethernet switches that don't flood forward packets with
- // unknown mac addresses.
- for (i=0; i<6; i++) packet[i] = 0xFF;
- if (write(bpf_fd, packet, ptr - packet) < 0)
- {
- helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket write failed %s", strerror(errno));
- return errno;
- }
- helplog(ASL_LEVEL_INFO, "do_mDNSSendWakeupPacket sent broadcast eth_addr %s, ip_addr %s", eth_addr, ip_addr);
- close(bpf_fd);
- return KERN_SUCCESS;
-}
-
-// Open the specified port for protocol in the P2P firewall.
-kern_return_t
-do_mDNSPacketFilterControl(__unused mach_port_t port, uint32_t command, const char * ifname, uint32_t count, pfArray_t portArray, pfArray_t protocolArray, audit_token_t token)
-{
- (void) token; // unused
- int error;
- kern_return_t result = KERN_SUCCESS;
-
- helplog(ASL_LEVEL_INFO, "do_mDNSPacketFilterControl: command %d ifname %s, count %d",
- command, ifname, count);
-
- switch (command)
- {
- case PF_SET_RULES:
- error = P2PPacketFilterAddBonjourRuleSet(ifname, count, portArray, protocolArray);
- if (error)
- {
- helplog(ASL_LEVEL_ERR, "P2PPacketFilterAddBonjourRuleSet failed %s", strerror(error));
- result = KERN_FAILURE;
- }
- break;
-
- case PF_CLEAR_RULES:
- error = P2PPacketFilterClearBonjourRules();
- if (error)
- {
- helplog(ASL_LEVEL_ERR, "P2PPacketFilterClearBonjourRules failed %s", strerror(error));
- result = KERN_FAILURE;
- }
- break;
-
- default:
- helplog(ASL_LEVEL_ERR, "do_mDNSPacketFilterControl: invalid command %d", command);
- result = KERN_INVALID_ARGUMENT;
- break;
- }
-
- return result;
-}
-
-unsigned long
-in_cksum(unsigned short *ptr,int nbytes)
-{
- unsigned long sum;
- u_short oddbyte;
-
- /*
- * Our algorithm is simple, using a 32-bit accumulator (sum),
- * we add sequential 16-bit words to it, and at the end, fold back
- * all the carry bits from the top 16 bits into the lower 16 bits.
- */
- sum = 0;
- while (nbytes > 1)
- {
- sum += *ptr++;
- nbytes -= 2;
- }
-
- /* mop up an odd byte, if necessary */
- if (nbytes == 1)
- {
- /* make sure top half is zero */
- oddbyte = 0;
-
- /* one byte only */
- *((u_char *)&oddbyte) = *(u_char *)ptr;
- sum += oddbyte;
- }
- /* Add back carry outs from top 16 bits to low 16 bits. */
- sum = (sum >> 16) + (sum & 0xffff);
-
- /* add carry */
- sum += (sum >> 16);
-
- return sum;
-}
-
-unsigned short
-InetChecksum(unsigned short *ptr,int nbytes)
-{
- unsigned long sum;
-
- sum = in_cksum(ptr, nbytes);
- return (unsigned short)~sum;
-}
-
-void TCPCheckSum(int af, struct tcphdr *t, int tcplen, v6addr_t sadd6, v6addr_t dadd6)
-{
- unsigned long sum = 0;
- unsigned short *ptr;
-
- /* TCP header checksum */
- sum = in_cksum((unsigned short *)t, tcplen);
-
- if (af == AF_INET)
- {
- /* Pseudo header */
- ptr = (unsigned short *)sadd6;
- sum += *ptr++;
- sum += *ptr++;
- ptr = (unsigned short *)dadd6;
- sum += *ptr++;
- sum += *ptr++;
- }
- else if (af == AF_INET6)
- {
- /* Pseudo header */
- ptr = (unsigned short *)sadd6;
- sum += *ptr++;
- sum += *ptr++;
- sum += *ptr++;
- sum += *ptr++;
- sum += *ptr++;
- sum += *ptr++;
- sum += *ptr++;
- sum += *ptr++;
- ptr = (unsigned short *)dadd6;
- sum += *ptr++;
- sum += *ptr++;
- sum += *ptr++;
- sum += *ptr++;
- sum += *ptr++;
- sum += *ptr++;
- sum += *ptr++;
- sum += *ptr++;
- }
-
- sum += htons(tcplen);
- sum += htons(IPPROTO_TCP);
-
- while (sum >> 16)
- sum = (sum >> 16) + (sum & 0xFFFF);
-
- t->th_sum = ~sum;
-
-}
-
-kern_return_t do_mDNSSendKeepalive(__unused mach_port_t port, v6addr_t sadd6, v6addr_t dadd6, uint16_t lport, uint16_t rport, unsigned seq, unsigned ack, uint16_t win, audit_token_t token)
-{
- struct packet4 {
- struct ip ip;
- struct tcphdr tcp;
- } packet4;
- struct packet6 {
- struct tcphdr tcp;
- } packet6;
- int sock, on;
- struct tcphdr *t;
- int af;
- struct sockaddr_storage ss_to;
- struct sockaddr_in *sin_to = (struct sockaddr_in *)&ss_to;
- struct sockaddr_in6 *sin6_to = (struct sockaddr_in6 *)&ss_to;
- void *packet;
- ssize_t packetlen;
- char ctlbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
- struct msghdr msghdr;
- struct iovec iov;
- ssize_t len;
-
- if (!authorized(&token))
- {
- helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: Not authorized");
- return kmDNSHelperNotAuthorized;
- }
-
- helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: called");
-
- // all the incoming arguments are in network order
- if ((*(unsigned *)(sadd6 +4) == 0) && (*(unsigned *)(sadd6 + 8) == 0) && (*(unsigned *)(sadd6 + 12) == 0))
- {
- af = AF_INET;
- memset(&packet4, 0, sizeof (packet4));
-
- /* Fill in all the IP header information - should be in host order*/
- packet4.ip.ip_v = 4; /* 4-bit Version */
- packet4.ip.ip_hl = 5; /* 4-bit Header Length */
- packet4.ip.ip_tos = 0; /* 8-bit Type of service */
- packet4.ip.ip_len = 40; /* 16-bit Total length */
- packet4.ip.ip_id = 9864; /* 16-bit ID field */
- packet4.ip.ip_off = 0; /* 13-bit Fragment offset */
- packet4.ip.ip_ttl = 63; /* 8-bit Time To Live */
- packet4.ip.ip_p = IPPROTO_TCP; /* 8-bit Protocol */
- packet4.ip.ip_sum = 0; /* 16-bit Header checksum (below) */
- memcpy(&packet4.ip.ip_src.s_addr, sadd6, 4);
- memcpy(&packet4.ip.ip_dst.s_addr, dadd6, 4);
-
- /* IP header checksum */
- packet4.ip.ip_sum = InetChecksum((unsigned short *)&packet4.ip, 20);
- t = &packet4.tcp;
- packet = &packet4;
- packetlen = 40; // sum of IPv4 header len(20) and TCP header len(20)
- }
- else
- {
- af = AF_INET6;
- memset(&packet6, 0, sizeof (packet6));
- t = &packet6.tcp;
- packet = &packet6;
- // We don't send IPv6 header, hence just the TCP header len (20)
- packetlen = 20;
- }
-
- /* Fill in all the TCP header information */
- t->th_sport = lport; /* 16-bit Source port number */
- t->th_dport = rport; /* 16-bit Destination port */
- t->th_seq = seq; /* 32-bit Sequence Number */
- t->th_ack = ack; /* 32-bit Acknowledgement Number */
- t->th_off = 5; /* Data offset */
- t->th_flags = TH_ACK;
- t->th_win = win;
- t->th_sum = 0; /* 16-bit checksum (below) */
- t->th_urp = 0; /* 16-bit urgent offset */
-
- TCPCheckSum(af, t, 20, sadd6, dadd6);
-
- /* Open up a RAW socket */
- if ((sock = socket(af, SOCK_RAW, IPPROTO_TCP)) < 0)
- {
- helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: socket %s", strerror(errno));
- return errno;
- }
-
-
- if (af == AF_INET)
- {
- on = 1;
- if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)))
- {
- close(sock);
- helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: setsockopt %s", strerror(errno));
- return errno;
- }
-
- memset(sin_to, 0, sizeof(struct sockaddr_in));
- sin_to->sin_len = sizeof(struct sockaddr_in);
- sin_to->sin_family = AF_INET;
- memcpy(&sin_to->sin_addr, sadd6, sizeof(struct in_addr));
- sin_to->sin_port = rport;
-
- msghdr.msg_control = NULL;
- msghdr.msg_controllen = 0;
-
- }
- else
- {
- struct cmsghdr *ctl;
-
- memset(sin6_to, 0, sizeof(struct sockaddr_in6));
- sin6_to->sin6_len = sizeof(struct sockaddr_in6);
- sin6_to->sin6_family = AF_INET6;
- memcpy(&sin6_to->sin6_addr, dadd6, sizeof(struct in6_addr));
-
- sin6_to->sin6_port = rport;
- sin6_to->sin6_flowinfo = 0;
-
-
- msghdr.msg_control = ctlbuf;
- msghdr.msg_controllen = sizeof(ctlbuf);
- ctl = CMSG_FIRSTHDR(&msghdr);
- ctl->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
- ctl->cmsg_level = IPPROTO_IPV6;
- ctl->cmsg_type = IPV6_PKTINFO;
- struct in6_pktinfo *pktinfo = (struct in6_pktinfo *) CMSG_DATA(ctl);
- memcpy(&pktinfo->ipi6_addr, sadd6, sizeof(struct in6_addr));
- pktinfo->ipi6_ifindex = 0;
- }
-
- msghdr.msg_name = (struct sockaddr *)&ss_to;
- msghdr.msg_namelen = ss_to.ss_len;
- iov.iov_base = packet;
- iov.iov_len = packetlen;
- msghdr.msg_iov = &iov;
- msghdr.msg_iovlen = 1;
- msghdr.msg_flags = 0;
-again:
- len = sendmsg(sock, &msghdr, 0);
- if (len == -1)
- {
- if (errno == EINTR)
- goto again;
- }
-
- if (len != packetlen)
- {
- helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: sendmsg failed %s", strerror(errno));
- }
- else
- {
- char source[INET6_ADDRSTRLEN], dest[INET6_ADDRSTRLEN];
-
- inet_ntop(af, (void *)sadd6, source, sizeof(source));
- inet_ntop(af, (void *)dadd6, dest, sizeof(dest));
-
- helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: Success Source %s:%d, Dest %s:%d, %u, %u, %u", source, ntohs(lport), dest, ntohs(rport), ntohl(seq), ntohl(ack), ntohs(win));
-
- }
- close(sock);
- return KERN_SUCCESS;
-}
-
-kern_return_t do_mDNSRetrieveTCPInfo(__unused mach_port_t port, int family, v6addr_t laddr, uint16_t lport, v6addr_t raddr, uint16_t rport,
- uint32_t *seq, uint32_t *ack, uint16_t *win, int32_t *intfid, audit_token_t token)
-{
- struct tcp_info ti;
- struct info_tuple itpl;
- int mib[4];
- unsigned int miblen;
- size_t len;
- size_t sz;
-
- memset(&itpl, 0, sizeof(struct info_tuple));
- memset(&ti, 0, sizeof(struct tcp_info));
-
- if (!authorized(&token))
- {
- helplog(ASL_LEVEL_ERR, "mDNSRetrieveTCPInfo: Not authorized");
- return kmDNSHelperNotAuthorized;
- }
-
- if (family == AF_INET)
- {
- memcpy(&itpl.itpl_local_sin.sin_addr, laddr, sizeof(struct in_addr));
- memcpy(&itpl.itpl_remote_sin.sin_addr, raddr, sizeof(struct in_addr));
- itpl.itpl_local_sin.sin_port = lport;
- itpl.itpl_remote_sin.sin_port = rport;
- itpl.itpl_local_sin.sin_family = AF_INET;
- itpl.itpl_remote_sin.sin_family = AF_INET;
- }
- else
- {
- memcpy(&itpl.itpl_local_sin6.sin6_addr, laddr, sizeof(struct in6_addr));
- memcpy(&itpl.itpl_remote_sin6.sin6_addr, raddr, sizeof(struct in6_addr));
- itpl.itpl_local_sin6.sin6_port = lport;
- itpl.itpl_remote_sin6.sin6_port = rport;
- itpl.itpl_local_sin6.sin6_family = AF_INET6;
- itpl.itpl_remote_sin6.sin6_family = AF_INET6;
- }
- itpl.itpl_proto = IPPROTO_TCP;
- sz = sizeof(mib)/sizeof(mib[0]);
- if (sysctlnametomib("net.inet.tcp.info", mib, &sz) == -1)
- {
- helplog(ASL_LEVEL_ERR, "do_RetrieveTCPInfo: sysctlnametomib failed %d, %s", errno, strerror(errno));
- return errno;
- }
- miblen = (unsigned int)sz;
- len = sizeof(struct tcp_info);
- if (sysctl(mib, miblen, &ti, &len, &itpl, sizeof(struct info_tuple)) == -1)
- {
- helplog(ASL_LEVEL_ERR, "do_RetrieveTCPInfo: sysctl failed %d, %s", errno, strerror(errno));
- return errno;
- }
-
- *seq = ti.tcpi_snd_nxt - 1;
- *ack = ti.tcpi_rcv_nxt;
- *win = ti.tcpi_rcv_space >> ti.tcpi_rcv_wscale;
- *intfid = ti.tcpi_last_outif;
- return KERN_SUCCESS;
-}
-
-static int getMACAddress(int family, v6addr_t raddr, v6addr_t gaddr, int *gfamily, ethaddr_t eth)
-{
- struct
- {
- struct rt_msghdr m_rtm;
- char m_space[512];
- } m_rtmsg;
-
- struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
- char *cp = m_rtmsg.m_space;
- int seq = 6367, sock, rlen, i;
- struct sockaddr_in *sin = NULL;
- struct sockaddr_in6 *sin6 = NULL;
- struct sockaddr_dl *sdl = NULL;
- struct sockaddr_storage sins;
- struct sockaddr_dl sdl_m;
-
-#define NEXTADDR(w, s, len) \
- if (rtm->rtm_addrs & (w)) \
- { \
- bcopy((char *)s, cp, len); \
- cp += len; \
- }
-
- bzero(&sins, sizeof(struct sockaddr_storage));
- bzero(&sdl_m, sizeof(struct sockaddr_dl));
- bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
-
- sock = socket(PF_ROUTE, SOCK_RAW, 0);
- if (sock < 0)
- {
- helplog(ASL_LEVEL_ERR, "mDNSGetRemoteMAC: Can not open the socket - %s", strerror(errno));
- return errno;
- }
-
- rtm->rtm_addrs |= RTA_DST | RTA_GATEWAY;
- rtm->rtm_type = RTM_GET;
- rtm->rtm_flags = 0;
- rtm->rtm_version = RTM_VERSION;
- rtm->rtm_seq = ++seq;
-
- sdl_m.sdl_len = sizeof(sdl_m);
- sdl_m.sdl_family = AF_LINK;
- if (family == AF_INET)
- {
- sin = (struct sockaddr_in*)&sins;
- sin->sin_family = AF_INET;
- sin->sin_len = sizeof(struct sockaddr_in);
- memcpy(&sin->sin_addr, raddr, sizeof(struct in_addr));
- NEXTADDR(RTA_DST, sin, sin->sin_len);
- }
- else if (family == AF_INET6)
- {
- sin6 = (struct sockaddr_in6 *)&sins;
- sin6->sin6_len = sizeof(struct sockaddr_in6);
- sin6->sin6_family = AF_INET6;
- memcpy(&sin6->sin6_addr, raddr, sizeof(struct in6_addr));
- NEXTADDR(RTA_DST, sin6, sin6->sin6_len);
- }
- NEXTADDR(RTA_GATEWAY, &sdl_m, sdl_m.sdl_len);
- rtm->rtm_msglen = rlen = cp - (char *)&m_rtmsg;
-
- if (write(sock, (char *)&m_rtmsg, rlen) < 0)
- {
- helplog(ASL_LEVEL_INFO, "do_mDNSGetRemoteMAC: writing to routing socket: %s", strerror(errno));
- close(sock);
- return errno;
- }
-
- do
- {
- rlen = read(sock, (char *)&m_rtmsg, sizeof(m_rtmsg));
- }
- while (rlen > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != getpid()));
-
- if (rlen < 0)
- helplog(ASL_LEVEL_ERR, "do_mDNSGetRemoteMAC: Read from routing socket failed");
-
- if (family == AF_INET)
- {
- sin = (struct sockaddr_in *) (rtm + 1);
- sdl = (struct sockaddr_dl *) (sin->sin_len + (char *) sin);
- }
- else if (family == AF_INET6)
- {
- sin6 = (struct sockaddr_in6 *) (rtm +1);
- sdl = (struct sockaddr_dl *) (sin6->sin6_len + (char *) sin6);
- }
- if (!sdl)
- {
- helplog(ASL_LEVEL_ERR, "do_mDNSGetRemoteMAC: sdl is NULL for family %d", family);
- close(sock);
- return -1;
- }
- // If the address is not on the local net, we get the IP address of the gateway.
- // We would have to repeat the process to get the MAC address of the gateway
- *gfamily = sdl->sdl_family;
- if (sdl->sdl_family == AF_INET)
- {
- if (sin)
- {
- struct sockaddr_in *new_sin = (struct sockaddr_in *)(sin->sin_len +(char*) sin);
- memcpy(gaddr, &new_sin->sin_addr, sizeof(struct in_addr));
- }
- else
- {
- helplog(ASL_LEVEL_ERR, "do_mDNSGetRemoteMAC: sin is NULL");
- }
- close(sock);
- return -1;
- }
- else if (sdl->sdl_family == AF_INET6)
- {
- if (sin6)
- {
- struct sockaddr_in6 *new_sin6 = (struct sockaddr_in6 *)(sin6->sin6_len +(char*) sin6);
- memcpy(gaddr, &new_sin6->sin6_addr, sizeof(struct in6_addr));
- }
- else
- {
- helplog(ASL_LEVEL_ERR, "do_mDNSGetRemoteMAC: sin6 is NULL");
- }
- close(sock);
- return -1;
- }
-
- unsigned char *ptr = (unsigned char *)LLADDR(sdl);
- for (i = 0; i < ETHER_ADDR_LEN; i++)
- (eth)[i] = *(ptr +i);
-
- close(sock);
- return KERN_SUCCESS;
-}
-
-kern_return_t do_mDNSGetRemoteMAC(__unused mach_port_t port, int family, v6addr_t raddr, ethaddr_t eth, audit_token_t token)
-{
- int ret = 0;
- v6addr_t gateway;
- int gfamily;
- int count = 0;
-
- if (!authorized(&token))
- {
- helplog(ASL_LEVEL_ERR, "mDNSGetRemoteMAC: Not authorized");
- return kmDNSHelperNotAuthorized;
- }
-
- do
- {
- ret = getMACAddress(family, raddr, gateway, &gfamily, eth);
- if (ret == -1)
- {
- memcpy(raddr, gateway, sizeof(family));
- family = gfamily;
- count++;
- }
- }
- while ((ret == -1) && (count < 5));
- return ret;
-}
-
-
-kern_return_t do_mDNSStoreSPSMACAddress(__unused mach_port_t port, int family, v6addr_t spsaddr, const char *ifname, audit_token_t token)
-{
- ethaddr_t eth;
- char spsip[INET6_ADDRSTRLEN];
- int ret = 0;
- CFStringRef sckey = NULL;
- SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:StoreSPSMACAddress"), NULL, NULL);
- SCDynamicStoreRef ipstore = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetIPv6Addresses"), NULL, NULL);
- CFMutableDictionaryRef dict = NULL;
- CFStringRef entityname = NULL;
- CFDictionaryRef ipdict = NULL;
- CFArrayRef addrs = NULL;
-
- if (!authorized(&token))
- {
- helplog(ASL_LEVEL_ERR, "mDNSStoreSPSMAC: Not authorized");
- return kmDNSHelperNotAuthorized;
- }
-
- if ((store == NULL) || (ipstore == NULL))
- {
- helplog(ASL_LEVEL_ERR, "Unable to access SC Dynamic Store");
- return KERN_FAILURE;
- }
-
- // Get the MAC address of the Sleep Proxy Server
- memset(eth, 0, sizeof(eth));
- ret = do_mDNSGetRemoteMAC(port, family, spsaddr, eth, token);
- if (ret != KERN_SUCCESS)
- {
- helplog(ASL_LEVEL_ERR, "mDNSStoreSPSMAC: Failed to determine the MAC address");
- goto fin;
- }
-
- // Create/Update the dynamic store entry for the specified interface
- sckey = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", ifname, "/BonjourSleepProxyAddress");
- dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- if (!dict)
- {
- helplog(ASL_LEVEL_ERR, "SPSCreateDict: Could not create CFDictionary dict");
- ret = KERN_FAILURE;
- goto fin;
- }
-
- CFStringRef macaddr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"), eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
- CFDictionarySetValue(dict, CFSTR("MACAddress"), macaddr);
- if (NULL != macaddr) CFRelease(macaddr);
-
- if( NULL == inet_ntop(family, (void *)spsaddr, spsip, sizeof(spsip)))
- {
- helplog(ASL_LEVEL_ERR, "inet_ntop failed: %s", strerror(errno));
- ret = kmDNSHelperInvalidNetworkAddress;
- goto fin;
- }
-
- CFStringRef ipaddr = CFStringCreateWithCString(NULL, spsip, kCFStringEncodingUTF8);
- CFDictionarySetValue(dict, CFSTR("IPAddress"), ipaddr);
- if (NULL != ipaddr) CFRelease(ipaddr);
-
- // Get the current IPv6 addresses on this interface and store them so NAs can be sent on wakeup
- if ((entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/IPv6"), ifname)) != NULL)
- {
- if ((ipdict = SCDynamicStoreCopyValue(ipstore, entityname)) != NULL)
- {
- if((addrs = CFDictionaryGetValue(ipdict, CFSTR("Addresses"))) != NULL)
- {
- addrs = CFRetain(addrs);
- CFDictionarySetValue(dict, CFSTR("RegisteredAddresses"), addrs);
- }
- }
- }
- SCDynamicStoreSetValue(store, sckey, dict);
-
-fin:
- if (store) CFRelease(store);
- if (ipstore) CFRelease(ipstore);
- if (sckey) CFRelease(sckey);
- if (dict) CFRelease(dict);
- if (ipdict) CFRelease(ipdict);
- if (entityname) CFRelease(entityname);
- if (addrs) CFRelease(addrs);
-
- update_idle_timer();
- return ret;
-}
diff --git a/mDNSResponder/mDNSMacOSX/helper.h b/mDNSResponder/mDNSMacOSX/helper.h
index 04332eff..eedf7380 100644
--- a/mDNSResponder/mDNSMacOSX/helper.h
+++ b/mDNSResponder/mDNSMacOSX/helper.h
@@ -18,7 +18,71 @@
#ifndef H_HELPER_H
#define H_HELPER_H
-#define kmDNSHelperServiceName "com.apple.mDNSResponderHelper"
+#include <os/log.h>
+
+#define kHelperService "com.apple.mDNSResponder_Helper"
+
+#define kmDNSHelperProgramArgs CFSTR("com.apple.mDNSResponderHelper")
+#define kPreferencesKey_mDNSHelperLog CFSTR("mDNSHelperDebugLogging")
+
+#define kHelperMode "HelperMode"
+#define kHelperReplyStatus "HelperReplyStatusToClient"
+#define kHelperErrCode "HelperErrorCodefromCall"
+
+#define kPrefsNameKey "PreferencesNameKey"
+#define kPrefsOldName "PreferencesOldName"
+#define kPrefsNewName "PreferencesNewName"
+
+extern int mDNSHelperLogEnabled;
+
+extern os_log_t log_handle;
+
+typedef enum
+{
+ bpf_request = 1,
+ set_name = 2,
+ p2p_packetfilter = 3,
+ user_notify = 4,
+ power_req = 5,
+ send_wakepkt = 6,
+ set_localaddr_cacheentry = 7,
+ send_keepalive = 8,
+ retreive_tcpinfo = 9,
+ keychain_getsecrets = 10,
+ autotunnel_setkeys = 11,
+ request_other,
+} HelperModes;
+
+typedef enum
+{
+ kHelperReply_ACK = 0,
+} HelperReplyStatusCodes;
+
+
+typedef enum
+{
+ kHelperErr_NoErr = 0,
+ kHelperErr_DefaultErr = -1,
+ kHelperErr_NotConnected = -2,
+ kHelperErr_NoResponse = -3,
+ kHelperErr_UndefinedMode = -4,
+ kHelperErr_ApiErr = -5,
+ kHelperErr_InvalidTunnelSetKeysOperation = -6,
+ kHelperErr_InvalidNetworkAddress = -7,
+ kHelperErr_ResultTooLarge = -8,
+ kHelperErr_RacoonConfigCreationFailed = -9,
+ kHelperErr_IPsecPolicySocketCreationFailed = -10,
+ kHelperErr_IPsecPolicyCreationFailed = -11,
+ kHelperErr_IPsecPolicySetFailed = -12,
+ kHelperErr_IPsecRemoveSAFailed = -13,
+ kHelperErr_IPsecDisabled = -14,
+ kHelperErr_RoutingSocketCreationFailed = -15,
+ kHelperErr_RouteDeletionFailed = -16,
+ kHelperErr_RouteAdditionFailed = -17,
+ kHelperErr_RacoonStartFailed = -18,
+ kHelperErr_RacoonNotificationFailed = -19,
+} HelperErrorCodes;
+
enum mDNSPreferencesSetNameKey
{
@@ -38,6 +102,7 @@ enum mDNSAutoTunnelSetKeysReplaceDelete
kmDNSAutoTunnelSetKeysDelete
};
+
// helper parses the system keychain and returns the information to mDNSResponder.
// It returns four attributes. Attributes are defined after how they show up in
// keychain access utility (the actual attribute name to retrieve these are different).
@@ -49,36 +114,40 @@ enum mDNSKeyChainAttributes
kmDNSKcName // Name
};
-#define ERROR(x, y) x,
-enum mDNSHelperErrors
-{
- mDNSHelperErrorBase = 2300,
- #include "helper-error.h"
- mDNSHelperErrorEnd
-};
-#undef ERROR
-
#include "mDNSEmbeddedAPI.h"
#include "helpermsg-types.h"
extern const char *mDNSHelperError(int errornum);
extern mStatus mDNSHelperInit(void);
+
+
extern void mDNSRequestBPF(void);
extern int mDNSPowerRequest(int key, int interval);
extern int mDNSSetLocalAddressCacheEntry(int ifindex, int family, const v6addr_t ip, const ethaddr_t eth);
extern void mDNSNotify(const char *title, const char *msg); // Both strings are UTF-8 text
extern void mDNSPreferencesSetName(int key, domainlabel *old, domainlabel *new);
extern int mDNSKeychainGetSecrets(CFArrayRef *secrets);
-extern void mDNSConfigureServer(int updown, const char *const prefix, const domainname *const fqdn);
extern int mDNSAutoTunnelSetKeys(int replacedelete, v6addr_t local_inner,
v6addr_t local_outer, short local_port, v6addr_t remote_inner,
v6addr_t remote_outer, short remote_port, const char *const prefix, const domainname *const fqdn);
extern void mDNSSendWakeupPacket(unsigned ifid, char *eth_addr, char *ip_addr, int iteration);
extern void mDNSPacketFilterControl(uint32_t command, char * ifname, uint32_t count, pfArray_t portArray, pfArray_t protocolArray);
-extern void mDNSSendKeepalive(v6addr_t sadd, v6addr_t dadd, uint16_t lport, uint16_t rport, unsigned seq, unsigned ack, uint16_t win);
+extern void mDNSSendKeepalive(const v6addr_t sadd, const v6addr_t dadd, uint16_t lport, uint16_t rport, unsigned seq, unsigned ack, uint16_t win);
extern int mDNSRetrieveTCPInfo(int family, v6addr_t laddr, uint16_t lport, v6addr_t raddr, uint16_t rport, uint32_t *seq, uint32_t *ack, uint16_t *win, int32_t *intfid);
-extern void mDNSGetRemoteMAC(mDNS *const m, int family, v6addr_t raddr);
-extern void mDNSStoreSPSMACAddress(int family, v6addr_t spsaddr, char *ifname);
+
+extern void RequestBPF(void);
+extern void PreferencesSetName(int key, const char* old, const char* new);
+extern void PacketFilterControl(uint32_t command, const char * ifname, uint32_t count, pfArray_t portArray, pfArray_t protocolArray);
+extern void UserNotify(const char *title, const char *msg); // Both strings are UTF-8 text
+extern void PowerRequest(int key, int interval, int *error);
+extern void SendWakeupPacket(unsigned int ifid, const char *eth_addr, const char *ip_addr, int iteration);
+extern void SetLocalAddressCacheEntry(int ifindex, int family, const v6addr_t ip, const ethaddr_t eth, int *err);
+extern void SendKeepalive(const v6addr_t sadd6, const v6addr_t dadd6, uint16_t lport, uint16_t rport, uint32_t seq, uint32_t ack, uint16_t win);
+extern void RetrieveTCPInfo(int family, const v6addr_t laddr, uint16_t lport, const v6addr_t raddr, uint16_t rport, uint32_t *seq, uint32_t *ack, uint16_t *win, int32_t *intfid, int *err);
+extern void KeychainGetSecrets(__unused unsigned int *numsecrets,__unused unsigned long *secrets, __unused unsigned int *secretsCnt, __unused int *err);
+extern int HelperAutoTunnelSetKeys(int replacedelete, const v6addr_t loc_inner, const v6addr_t loc_outer6, uint16_t loc_port, const v6addr_t rmt_inner,
+ const v6addr_t rmt_outer6, uint16_t rmt_port, const char *id, int *err);
+extern void helper_exit(void);
#endif /* H_HELPER_H */
diff --git a/mDNSResponder/mDNSMacOSX/helpermsg-types.h b/mDNSResponder/mDNSMacOSX/helpermsg-types.h
index 88411800..689b249e 100644
--- a/mDNSResponder/mDNSMacOSX/helpermsg-types.h
+++ b/mDNSResponder/mDNSMacOSX/helpermsg-types.h
@@ -24,7 +24,7 @@ typedef uint8_t ethaddr_t[ 6];
typedef uint8_t v6addr_t [16];
typedef const char *string_t;
-#define PFPortArraySize 16
+#define PFPortArraySize 4
typedef uint16_t pfArray_t [PFPortArraySize];
#endif /* H_HELPERMSG_TYPES_H */
diff --git a/mDNSResponder/mDNSMacOSX/helpermsg.defs b/mDNSResponder/mDNSMacOSX/helpermsg.defs
deleted file mode 100644
index 35239967..00000000
--- a/mDNSResponder/mDNSMacOSX/helpermsg.defs
+++ /dev/null
@@ -1,143 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2007-2013 Apple Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <mach/std_types.defs>
-#include <mach/mach_types.defs>
-
-import "helpermsg-types.h";
-
-type v4addr_t = array [ 4] of uint8_t;
-type ethaddr_t = array [ 6] of uint8_t;
-type v6addr_t = array [16] of uint8_t;
-type string_t = c_string[*:1024];
-
-// Mig doesn't generate the output file if I use the constant PFPortArraySize below
-type pfArray_t = array [16] of uint16_t;
-
-subsystem helper 1833193043;
-serverprefix do_;
-userprefix proxy_;
-
-simpleroutine mDNSExit( port : mach_port_t;
- ServerAuditToken token : audit_token_t);
-
-simpleroutine mDNSRequestBPF( port : mach_port_t;
- ServerAuditToken token : audit_token_t);
-
-routine mDNSPowerRequest( port : mach_port_t;
- key : int;
- interval : int;
- out err : int;
- ServerAuditToken token : audit_token_t);
-
-routine mDNSSetLocalAddressCacheEntry(
- port : mach_port_t;
- ifindex : int;
- family : int;
- ip : v6addr_t;
- eth : ethaddr_t;
- out err : int;
- ServerAuditToken token : audit_token_t);
-
-simpleroutine mDNSNotify( port : mach_port_t;
- title : string_t;
- msg : string_t;
- ServerAuditToken token : audit_token_t);
-
-simpleroutine mDNSPreferencesSetName(
- port : mach_port_t;
- key : int;
- old : string_t;
- new : string_t;
- ServerAuditToken token : audit_token_t);
-
-routine mDNSKeychainGetSecrets( port : mach_port_t;
- out numsecrets : unsigned;
- out secrets : pointer_t;
- out err : int;
- ServerAuditToken token : audit_token_t);
-
-simpleroutine mDNSConfigureServer(
- port : mach_port_t;
- updown : int;
- id : string_t;
- ServerAuditToken token : audit_token_t);
-
-routine mDNSAutoTunnelSetKeys( port : mach_port_t;
- replacedelete : int;
- local_inner : v6addr_t;
- local_outer : v6addr_t;
- local_port : uint16_t; /* Port expressed as a numeric integer value */
- remote_inner : v6addr_t;
- remote_outer : v6addr_t;
- remote_port : uint16_t; /* Port expressed as a numeric integer value */
- id : string_t;
- out err : int;
- ServerAuditToken token : audit_token_t);
-
-simpleroutine mDNSSendWakeupPacket(
- port : mach_port_t;
- ifid : unsigned;
- eth_addr : string_t;
- ip_addr : string_t;
- iteration : int;
- ServerAuditToken token : audit_token_t);
-
-simpleroutine mDNSPacketFilterControl(
- port : mach_port_t;
- command : uint32_t;
- ifname : string_t;
- arraySize : uint32_t;
- portArray : pfArray_t;
- protocolArray : pfArray_t;
- ServerAuditToken token : audit_token_t);
-
-
-simpleroutine mDNSSendKeepalive( port : mach_port_t;
- sadd : v6addr_t;
- dadd : v6addr_t;
- lport : uint16_t;
- rport : uint16_t;
- seq : unsigned;
- ack : unsigned;
- win : uint16_t;
- ServerAuditToken token : audit_token_t);
-
-routine mDNSRetrieveTCPInfo(
- port : mach_port_t;
- family : int;
- laddr : v6addr_t;
- lport : uint16_t;
- raddr : v6addr_t;
- rport : uint16_t;
- out seq : uint32_t;
- out ack : uint32_t;
- out win : uint16_t;
- out intfid : int32_t;
- ServerAuditToken token : audit_token_t);
-
-routine mDNSGetRemoteMAC( port : mach_port_t;
- family : int;
- raddr : v6addr_t;
- out eth : ethaddr_t;
- ServerAuditToken token : audit_token_t);
-
-simpleroutine mDNSStoreSPSMACAddress( port : mach_port_t;
- family : int;
- spsaddr : v6addr_t;
- ifname : string_t;
- ServerAuditToken token : audit_token_t);
diff --git a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c
index deae0d1a..c57eddda 100644
--- a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c
+++ b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
- * Copyright (c) 2002-2015 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2016 Apple Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
#include "uDNS.h"
#include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform
#include "dns_sd.h" // For mDNSInterface_LocalOnly etc.
+#include "dns_sd_private.h"
#include "PlatformCommon.h"
#include "uds_daemon.h"
#include "CryptoSupport.h"
@@ -60,7 +61,7 @@
#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.
+#include <netinet6/in6_var.h> // For IN6_IFF_TENTATIVE etc.
#include <netinet/tcp.h>
@@ -100,6 +101,8 @@
#include <AWACS.h>
#include <ne_session.h> // for ne_session_set_socket_attributes()
#if !NO_D2D
+#include "BLE.h"
+
D2DStatus D2DInitialize(CFRunLoopRef runLoop, D2DServiceCallback serviceCallback, void* userData) __attribute__((weak_import));
D2DStatus D2DRetain(D2DServiceInstance instanceHandle, D2DTransportType transportType) __attribute__((weak_import));
D2DStatus D2DStopAdvertisingPairOnTransport(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize, D2DTransportType transport) __attribute__((weak_import));
@@ -111,6 +114,9 @@ void D2DStartResolvingPairOnTransport(const Byte *key, const size_t keySize, con
void D2DStopResolvingPairOnTransport(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize, D2DTransportType transport) __attribute__((weak_import));
D2DStatus D2DTerminate() __attribute__((weak_import));
+void xD2DAddToCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize);
+void xD2DRemoveFromCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize);
+
#endif // ! NO_D2D
#else
@@ -132,7 +138,7 @@ D2DStatus D2DTerminate() __attribute__((weak_import));
#define DARK_WAKE_TIME 16 // Time we hold an idle sleep assertion for maintenance after a wake notification
// cache the InterfaceID of the AWDL interface
-static mDNSInterfaceID AWDLInterfaceID;
+mDNSInterfaceID AWDLInterfaceID;
// ***************************************************************************
// Globals
@@ -176,9 +182,6 @@ mDNSexport int WatchDogReportingThreshold = 250;
dispatch_queue_t SSLqueue;
-//To prevent blocking the main queue, all writes to DynamicStore happen on the DynamicStoreQueue
-static dispatch_queue_t DynamicStoreQueue;
-
#if TARGET_OS_EMBEDDED
#define kmDNSResponderManagedPrefsID CFSTR("/Library/Managed Preferences/mobile/com.apple.mDNSResponder.plist")
#endif
@@ -243,6 +246,26 @@ mDNSexport void D2D_stop_advertising_interface(NetworkInterfaceInfo *interface)
}
}
+// If record would have been advertised to the D2D plugin layer, stop that advertisement.
+mDNSexport void D2D_stop_advertising_record(AuthRecord *ar)
+{
+ DNSServiceFlags flags = deriveD2DFlagsFromAuthRecType(ar->ARType);
+ if (callExternalHelpers(ar->resrec.InterfaceID, ar->resrec.name, flags))
+ {
+ external_stop_advertising_service(&ar->resrec, flags);
+ }
+}
+
+// If record should be advertised to the D2D plugin layer, start that advertisement.
+mDNSexport void D2D_start_advertising_record(AuthRecord *ar)
+{
+ DNSServiceFlags flags = deriveD2DFlagsFromAuthRecType(ar->ARType);
+ if (callExternalHelpers(ar->resrec.InterfaceID, ar->resrec.name, flags))
+ {
+ external_start_advertising_service(&ar->resrec, flags);
+ }
+}
+
// Name compression items for fake packet version number 1
static const mDNSu8 compression_packet_v1 = 0x01;
@@ -304,65 +327,6 @@ mDNSlocal void DomainnameToLower(const domainname * const in, domainname * const
out->c[ptr-start] = *ptr;
}
-mDNSlocal mStatus DNSNameCompressionParseBytes(mDNS *const m, const mDNSu8 *const lhs, const mDNSu16 lhs_len, const mDNSu8 *const rhs, const mDNSu16 rhs_len, AuthRecord *rr)
-{
- if (mDNS_LoggingEnabled)
- {
- LogInfo("%s", __func__);
- LogInfo(" Static Bytes: (%d bytes)", compression_lhs - (mDNSu8*)&compression_base_msg);
- PrintHex((mDNSu8*)&compression_base_msg, compression_lhs - (mDNSu8*)&compression_base_msg);
- }
-
- mDNSu8 *ptr = compression_lhs; // pointer to the end of our fake packet
-
- // Check to make sure we're not going to go past the end of the DNSMessage data
- // 7 = 2 for CLASS (-1 for our version) + 4 for TTL + 2 for RDLENGTH
- if (ptr + lhs_len - 7 + rhs_len >= compression_limit) return mStatus_NoMemoryErr;
-
- // Copy the LHS onto our fake wire packet
- mDNSPlatformMemCopy(ptr, lhs, lhs_len);
- ptr += lhs_len - 1;
-
- // Check the 'fake packet' version number, to ensure that we know how to decompress this data
- if (*ptr != compression_packet_v1) return mStatus_Incompatible;
-
- // two bytes of CLASS
- ptr = putVal16(ptr, kDNSClass_IN | kDNSClass_UniqueRRSet);
-
- // four bytes of TTL
- ptr = putVal32(ptr, 120);
-
- // Copy the RHS length into the RDLENGTH of our fake wire packet
- ptr = putVal16(ptr, rhs_len);
-
- // Copy the RHS onto our fake wire packet
- mDNSPlatformMemCopy(ptr, rhs, rhs_len);
- ptr += rhs_len;
-
- if (mDNS_LoggingEnabled)
- {
- LogInfo(" Our Bytes (%d bytes): ", ptr - compression_lhs);
- PrintHex(compression_lhs, ptr - compression_lhs);
- }
-
- ptr = (mDNSu8 *) GetLargeResourceRecord(m, &compression_base_msg, compression_lhs, ptr, mDNSInterface_Any, kDNSRecordTypePacketAns, &m->rec);
- if (!ptr || m->rec.r.resrec.RecordType == kDNSRecordTypePacketNegative)
- { LogMsg("DNSNameCompressionParseBytes: failed to get large RR"); m->rec.r.resrec.RecordType = 0; return mStatus_UnknownErr; }
- else LogInfo("DNSNameCompressionParseBytes: got rr: %s", CRDisplayString(m, &m->rec.r));
-
- mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSInterface_P2P, m->rec.r.resrec.rrtype, 7200, kDNSRecordTypeShared, AuthRecordP2P, FreeD2DARElemCallback, NULL);
- AssignDomainName(&rr->namestorage, &m->rec.namestorage);
- rr->resrec.rdlength = m->rec.r.resrec.rdlength;
- rr->resrec.rdata->MaxRDLength = m->rec.r.resrec.rdlength;
- mDNSPlatformMemCopy(rr->resrec.rdata->u.data, m->rec.r.resrec.rdata->u.data, m->rec.r.resrec.rdlength);
- rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
- SetNewRData(&rr->resrec, mDNSNULL, 0); // Sets rr->rdatahash for us
-
- m->rec.r.resrec.RecordType = 0; // Mark m->rec as no longer in use
-
- return mStatus_NoError;
-}
-
mDNSlocal mDNSu8 * DNSNameCompressionBuildLHS(const domainname* typeDomain, DNS_TypeValues qtype)
{
mDNSu8 *ptr = putDomainNameAsLabels(&compression_base_msg, compression_lhs, compression_limit, typeDomain);
@@ -459,8 +423,8 @@ mDNSlocal void xD2DClearCache(const domainname *regType, DNS_TypeValues qtype)
{
if ((ptr->ar.resrec.rrtype == qtype) && SameDomainName(&ptr->ar.namestorage, regType))
{
- mDNS_Deregister(&mDNSStorage, &ptr->ar);
LogInfo("xD2DClearCache: Clearing cache record and deregistering %s", ARDisplayString(&mDNSStorage, &ptr->ar));
+ mDNS_Deregister(&mDNSStorage, &ptr->ar);
}
}
}
@@ -498,11 +462,12 @@ mDNSlocal void D2DBrowseListRetain(const domainname *const name, mDNSu16 type)
LogInfo("D2DBrowseListRetain: %##s %s refcount now %u", (*ptr)->name.c, DNSTypeName((*ptr)->type), (*ptr)->refCount);
}
-mDNSlocal void D2DBrowseListRelease(const domainname *const name, mDNSu16 type)
+// Returns true if found in list, false otherwise
+mDNSlocal bool D2DBrowseListRelease(const domainname *const name, mDNSu16 type)
{
D2DBrowseListElem **ptr = D2DFindInBrowseList(name, type);
- if (!*ptr) { LogMsg("D2DBrowseListRelease: Didn't find %##s %s in list", name->c, DNSTypeName(type)); return; }
+ if (!*ptr) { LogMsg("D2DBrowseListRelease: Didn't find %##s %s in list", name->c, DNSTypeName(type)); return false; }
(*ptr)->refCount -= 1;
@@ -514,35 +479,125 @@ mDNSlocal void D2DBrowseListRelease(const domainname *const name, mDNSu16 type)
*ptr = (*ptr)->next;
mDNSPlatformMemFree(tmp);
}
+ return true;
}
-mDNSlocal mStatus xD2DParse(mDNS *const m, const mDNSu8 * const lhs, const mDNSu16 lhs_len, const mDNSu8 * const rhs, const mDNSu16 rhs_len, AuthRecord *rr)
+mDNSlocal mStatus xD2DParse(mDNS *const m, const mDNSu8 * const lhs, const mDNSu16 lhs_len, const mDNSu8 * const rhs, const mDNSu16 rhs_len, D2DRecordListElem **D2DListp)
{
- if (*(lhs + (lhs_len - 1)) == compression_packet_v1)
- return DNSNameCompressionParseBytes(m, lhs, lhs_len, rhs, rhs_len, rr);
- else
+ // Sanity check that key array (lhs) has one domain name, followed by the record type and single byte D2D
+ // plugin protocol version number.
+ // Note, we don't have a DNSMessage pointer at this point, so just pass in the lhs value as the lower bound
+ // of the input bytes we are processing. skipDomainName() does not try to follow name compression pointers,
+ // so it is safe to pass it the key byte array since it will stop parsing the DNS name and return a pointer
+ // to the byte after the first name compression pointer it encounters.
+ const mDNSu8 *keyp = skipDomainName((const DNSMessage *const) lhs, lhs, lhs + lhs_len);
+
+ // There should be 3 bytes remaining in a valid key,
+ // two for the DNS record type, and one for the D2D protocol version number.
+ if (keyp == NULL || (keyp + 3 != (lhs + lhs_len)))
+ {
+ LogInfo("xD2DParse: Could not parse DNS name in key");
return mStatus_Incompatible;
+ }
+ keyp += 2; // point to D2D compression packet format version byte
+ if (*keyp != compression_packet_v1)
+ {
+ LogInfo("xD2DParse: Invalid D2D packet version: %d", *keyp);
+ return mStatus_Incompatible;
+ }
+
+ if (mDNS_LoggingEnabled)
+ {
+ LogInfo("%s", __func__);
+ LogInfo(" Static Bytes: (%d bytes)", compression_lhs - (mDNSu8*)&compression_base_msg);
+ PrintHex((mDNSu8*)&compression_base_msg, compression_lhs - (mDNSu8*)&compression_base_msg);
+ }
+
+ mDNSu8 *ptr = compression_lhs; // pointer to the end of our fake packet
+
+ // Check to make sure we're not going to go past the end of the DNSMessage data
+ // 7 = 2 for CLASS (-1 for our version) + 4 for TTL + 2 for RDLENGTH
+ if (ptr + lhs_len - 7 + rhs_len >= compression_limit) return mStatus_NoMemoryErr;
+
+ // Copy the LHS onto our fake wire packet
+ mDNSPlatformMemCopy(ptr, lhs, lhs_len);
+ ptr += lhs_len - 1;
+
+ // Check the 'fake packet' version number, to ensure that we know how to decompress this data
+ if (*ptr != compression_packet_v1) return mStatus_Incompatible;
+
+ // two bytes of CLASS
+ ptr = putVal16(ptr, kDNSClass_IN | kDNSClass_UniqueRRSet);
+
+ // four bytes of TTL
+ ptr = putVal32(ptr, 120);
+
+ // Copy the RHS length into the RDLENGTH of our fake wire packet
+ ptr = putVal16(ptr, rhs_len);
+
+ // Copy the RHS onto our fake wire packet
+ mDNSPlatformMemCopy(ptr, rhs, rhs_len);
+ ptr += rhs_len;
+
+ if (mDNS_LoggingEnabled)
+ {
+ LogInfo(" Our Bytes (%d bytes): ", ptr - compression_lhs);
+ PrintHex(compression_lhs, ptr - compression_lhs);
+ }
+
+ ptr = (mDNSu8 *) GetLargeResourceRecord(m, &compression_base_msg, compression_lhs, ptr, mDNSInterface_Any, kDNSRecordTypePacketAns, &m->rec);
+ if (!ptr || m->rec.r.resrec.RecordType == kDNSRecordTypePacketNegative)
+ {
+ LogMsg("xD2DParse: failed to get large RR");
+ m->rec.r.resrec.RecordType = 0;
+ return mStatus_UnknownErr;
+ }
+ else
+ {
+ LogInfo("xD2DParse: got rr: %s", CRDisplayString(m, &m->rec.r));
+ }
+
+ *D2DListp = mDNSPlatformMemAllocate(sizeof(D2DRecordListElem) + (m->rec.r.resrec.rdlength <= sizeof(RDataBody) ? 0 : m->rec.r.resrec.rdlength - sizeof(RDataBody)));
+ if (!*D2DListp) return mStatus_NoMemoryErr;
+
+ AuthRecord *rr = &(*D2DListp)->ar;
+ mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSInterface_P2P, m->rec.r.resrec.rrtype, 7200, kDNSRecordTypeShared, AuthRecordP2P, FreeD2DARElemCallback, NULL);
+ AssignDomainName(&rr->namestorage, &m->rec.namestorage);
+ rr->resrec.rdlength = m->rec.r.resrec.rdlength;
+ rr->resrec.rdata->MaxRDLength = m->rec.r.resrec.rdlength;
+ mDNSPlatformMemCopy(rr->resrec.rdata->u.data, m->rec.r.resrec.rdata->u.data, m->rec.r.resrec.rdlength);
+ rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
+ SetNewRData(&rr->resrec, mDNSNULL, 0); // Sets rr->rdatahash for us
+
+ m->rec.r.resrec.RecordType = 0; // Mark m->rec as no longer in use
+
+ return mStatus_NoError;
}
-mDNSlocal void xD2DAddToCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
+mDNSexport void xD2DAddToCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
{
if (result == kD2DSuccess)
{
if ( key == NULL || value == NULL || keySize == 0 || valueSize == 0) { LogMsg("xD2DAddToCache: NULL Byte * passed in or length == 0"); return; }
mStatus err;
- D2DRecordListElem *ptr = mDNSPlatformMemAllocate(sizeof(D2DRecordListElem) + (valueSize < sizeof(RData) ? 0 : valueSize - sizeof(RData)));
-
- if (ptr == NULL) { LogMsg("xD2DAddToCache: memory allocation failure"); return; }
+ D2DRecordListElem *ptr = NULL;
- err = xD2DParse(m, (const mDNSu8 * const)key, (const mDNSu16)keySize, (const mDNSu8 * const)value, (const mDNSu16)valueSize, &ptr->ar);
+ err = xD2DParse(m, (const mDNSu8 * const)key, (const mDNSu16)keySize, (const mDNSu8 * const)value, (const mDNSu16)valueSize, &ptr);
if (err)
{
LogMsg("xD2DAddToCache: xD2DParse returned error: %d", err);
PrintHelper(__func__, (mDNSu8 *)key, (mDNSu16)keySize, (mDNSu8 *)value, (mDNSu16)valueSize);
- mDNSPlatformMemFree(ptr);
+ if (ptr)
+ mDNSPlatformMemFree(ptr);
return;
}
+
+ // If the record was created based on a BLE beacon, update the interface index to indicate
+ // this and thus match BLE specific queries.
+ if (transportType == D2DBLETransport)
+ ptr->ar.resrec.InterfaceID = mDNSInterface_BLE;
+
err = mDNS_Register(m, &ptr->ar);
if (err)
{
@@ -564,17 +619,17 @@ mDNSlocal void xD2DAddToCache(mDNS *const m, D2DStatus result, D2DServiceInstanc
mDNSlocal D2DRecordListElem * xD2DFindInList(mDNS *const m, const Byte *const key, const size_t keySize, const Byte *const value, const size_t valueSize)
{
D2DRecordListElem *ptr = D2DRecords;
- D2DRecordListElem *arptr;
+ D2DRecordListElem *arptr = NULL;
if ( key == NULL || value == NULL || keySize == 0 || valueSize == 0) { LogMsg("xD2DFindInList: NULL Byte * passed in or length == 0"); return NULL; }
- arptr = mDNSPlatformMemAllocate(sizeof(D2DRecordListElem) + (valueSize < sizeof(RData) ? 0 : valueSize - sizeof(RData)));
- if (arptr == NULL) { LogMsg("xD2DFindInList: memory allocation failure"); return NULL; }
-
- if (xD2DParse(m, (const mDNSu8 *const)key, (const mDNSu16)keySize, (const mDNSu8 *const)value, (const mDNSu16)valueSize, &arptr->ar) != mStatus_NoError)
+ mStatus err = xD2DParse(m, (const mDNSu8 *const)key, (const mDNSu16)keySize, (const mDNSu8 *const)value, (const mDNSu16)valueSize, &arptr);
+ if (err)
{
- LogMsg("xD2DFindInList: xD2DParse failed for key: %p (%u) value: %p (%u)", key, keySize, value, valueSize);
- mDNSPlatformMemFree(arptr);
+ LogMsg("xD2DFindInList: xD2DParse returned error: %d", err);
+ PrintHelper(__func__, (mDNSu8 *)key, (mDNSu16)keySize, (mDNSu8 *)value, (mDNSu16)valueSize);
+ if (arptr)
+ mDNSPlatformMemFree(arptr);
return NULL;
}
@@ -589,7 +644,7 @@ mDNSlocal D2DRecordListElem * xD2DFindInList(mDNS *const m, const Byte *const ke
return ptr;
}
-mDNSlocal void xD2DRemoveFromCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
+mDNSexport void xD2DRemoveFromCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
{
(void)transportType; // We don't care about this, yet.
(void)instanceHandle; // We don't care about this, yet.
@@ -777,23 +832,45 @@ mDNSlocal D2DTransportType xD2DInterfaceToTransportType(mDNSInterfaceID Interfac
return D2DTransportMax;
}
-mDNSexport void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags)
+// Similar to callExternalHelpers(), but without the checks for the BLE specific interface or flags.
+// It's assumed that the domain was already verified to be .local once we are at this level.
+mDNSlocal mDNSBool callInternalHelpers(mDNSInterfaceID InterfaceID, DNSServiceFlags flags)
{
- domainname lower;
+ if ( ((InterfaceID == mDNSInterface_Any) && (flags & (kDNSServiceFlagsIncludeP2P | kDNSServiceFlagsIncludeAWDL)))
+ || mDNSPlatformInterfaceIsD2D(InterfaceID))
+ return mDNStrue;
+ else
+ return mDNSfalse;
+}
- if (qtype == kDNSServiceType_A || qtype == kDNSServiceType_AAAA)
+mDNSexport void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags, DNSQuestion * q)
+{
+ // BLE support currently not handled by a D2D plugin
+ if (applyToBLE(InterfaceID, flags))
{
- LogInfo("external_start_browsing_for_service: ignoring address record");
- return;
+ domainname lower;
+
+ DomainnameToLower(typeDomain, &lower);
+ // pass in the key and keySize
+ mDNSu8 *end = DNSNameCompressionBuildLHS(&lower, qtype);
+ start_BLE_browse(q, &lower, qtype, flags, compression_lhs, end - compression_lhs);
}
+ if (callInternalHelpers(InterfaceID, flags))
+ internal_start_browsing_for_service(InterfaceID, typeDomain, qtype, flags);
+}
+
+mDNSexport void internal_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags)
+{
+ domainname lower;
+
DomainnameToLower(typeDomain, &lower);
if (!D2DBrowseListRefCount(&lower, qtype))
{
D2DTransportType transportType, excludedTransport;
- LogInfo("external_start_browsing_for_service: Starting browse for: %##s %s", lower.c, DNSTypeName(qtype));
+ LogInfo("%s: Starting browse for: %##s %s", __func__, lower.c, DNSTypeName(qtype));
mDNSu8 *end = DNSNameCompressionBuildLHS(&lower, qtype);
PrintHelper(__func__, compression_lhs, end - compression_lhs, mDNSNULL, 0);
@@ -817,22 +894,34 @@ mDNSexport void external_start_browsing_for_service(mDNSInterfaceID InterfaceID,
mDNSexport void external_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags)
{
- domainname lower;
-
- if (qtype == kDNSServiceType_A || qtype == kDNSServiceType_AAAA)
+ // BLE support currently not handled by a D2D plugin
+ if (applyToBLE(InterfaceID, flags))
{
- LogInfo("external_stop_browsing_for_service: ignoring address record");
- return;
+ domainname lower;
+
+ // If this is the last instance of this browse, clear any cached records recieved for it.
+ // We are not guaranteed to get a D2DServiceLost event for all key, value pairs cached over BLE.
+ DomainnameToLower(typeDomain, &lower);
+ if (stop_BLE_browse(&lower, qtype, flags))
+ xD2DClearCache(&lower, qtype);
}
+ if (callInternalHelpers(InterfaceID, flags))
+ internal_stop_browsing_for_service(InterfaceID, typeDomain, qtype, flags);
+}
+
+mDNSexport void internal_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags)
+{
+ domainname lower;
+
DomainnameToLower(typeDomain, &lower);
- D2DBrowseListRelease(&lower, qtype);
- if (!D2DBrowseListRefCount(&lower, qtype))
+ // If found in list and this is the last reference to this browse, remove the key from the D2D plugins.
+ if (D2DBrowseListRelease(&lower, qtype) && !D2DBrowseListRefCount(&lower, qtype))
{
D2DTransportType transportType, excludedTransport;
- LogInfo("external_stop_browsing_for_service: Stopping browse for: %##s %s", lower.c, DNSTypeName(qtype));
+ LogInfo("%s: Stopping browse for: %##s %s", __func__, lower.c, DNSTypeName(qtype));
mDNSu8 *end = DNSNameCompressionBuildLHS(&lower, qtype);
PrintHelper(__func__, compression_lhs, end - compression_lhs, mDNSNULL, 0);
@@ -860,13 +949,24 @@ mDNSexport void external_stop_browsing_for_service(mDNSInterfaceID InterfaceID,
mDNSexport void external_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags)
{
+ // Note, start_BLE_advertise() is currently called directly from external_start_advertising_helper() since
+ // it needs to pass the ServiceRecordSet so that we can promote the record advertisements to AWDL
+ // when we see the corresponding browse indication over BLE.
+
+ if (callInternalHelpers(resourceRecord->InterfaceID, flags))
+ internal_start_advertising_service(resourceRecord, flags);
+}
+
+mDNSexport void internal_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags)
+{
domainname lower;
mDNSu8 *rhs = NULL;
mDNSu8 *end = NULL;
D2DTransportType transportType, excludedTransport;
DomainnameToLower(resourceRecord->name, &lower);
- LogInfo("external_start_advertising_service: %s", RRDisplayString(&mDNSStorage, resourceRecord));
+ LogInfo("%s: %s", __func__, RRDisplayString(&mDNSStorage, resourceRecord));
+
// For SRV records, update packet filter if p2p interface already exists, otherwise,
// if will be updated when we get the KEV_DL_IF_ATTACHED event for the interface.
if (resourceRecord->rrtype == kDNSType_SRV)
@@ -894,14 +994,30 @@ mDNSexport void external_start_advertising_service(const ResourceRecord *const r
mDNSexport void external_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags)
{
+ // BLE support currently not handled by a D2D plugin
+ if (applyToBLE(resourceRecord->InterfaceID, flags))
+ {
+ domainname lower;
+
+ DomainnameToLower(resourceRecord->name, &lower);
+ stop_BLE_advertise(&lower, resourceRecord->rrtype, flags);
+ }
+
+ if (callInternalHelpers(resourceRecord->InterfaceID, flags))
+ internal_stop_advertising_service(resourceRecord, flags);
+}
+
+mDNSexport void internal_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags)
+{
domainname lower;
mDNSu8 *rhs = NULL;
mDNSu8 *end = NULL;
D2DTransportType transportType, excludedTransport;
DomainnameToLower(resourceRecord->name, &lower);
- LogInfo("external_stop_advertising_service: %s", RRDisplayString(&mDNSStorage, resourceRecord));
+ LogInfo("%s: %s", __func__, RRDisplayString(&mDNSStorage, resourceRecord));
+ // For SRV records, update packet filter if p2p interface already exists, otherwise,
// For SRV records, update packet filter to to remove this port from list
if (resourceRecord->rrtype == kDNSType_SRV)
mDNSUpdatePacketFilter(resourceRecord);
@@ -969,8 +1085,8 @@ mDNSexport void external_start_resolving_service(mDNSInterfaceID InterfaceID, co
if (AWDL_used && AWDLInterfaceID)
{
LogInfo("external_start_resolving_service: browse for TXT and SRV over AWDL");
- external_start_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_TXT, 0);
- external_start_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_SRV, 0);
+ external_start_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_TXT, 0, 0);
+ external_start_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_SRV, 0, 0);
}
}
@@ -1022,7 +1138,12 @@ mDNSexport void external_stop_resolving_service(mDNSInterfaceID InterfaceID, con
#elif APPLE_OSX_mDNSResponder
-mDNSexport void external_start_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags;}
+mDNSexport void internal_start_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags }
+mDNSexport void internal_stop_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags;}
+mDNSexport void internal_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { (void)resourceRecord; (void)flags;}
+mDNSexport void internal_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { (void)resourceRecord; (void)flags;}
+
+mDNSexport void external_start_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags; (void)q }
mDNSexport void external_stop_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags;}
mDNSexport void external_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { (void)resourceRecord; (void)flags;}
mDNSexport void external_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { (void)resourceRecord; (void)flags;}
@@ -1046,14 +1167,12 @@ mDNSexport void external_stop_resolving_service(const domainname *const fqdn, DN
// to run up the user's bill sending multicast traffic over a link where there's only a single device at the
// other end, and that device (e.g. a modem bank) is probably not answering Multicast DNS queries anyway.
-// We also don't want to use multicast on *any* physical interface on very constrained devices.
-#if 0
-#define MulticastInterface(i) ((i)->ifa_flags & IFF_LOOPBACK)
-#elif TARGET_OS_WATCH
-#define MulticastInterface(i) ((i)->m->NumAllInterfaceRecords + (i)->m->NumAllInterfaceQuestions > 0 && ((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT))
+#if BONJOUR_ON_DEMAND
+#define MulticastInterface(i) ((i)->m->BonjourEnabled && ((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT))
#else
#define MulticastInterface(i) (((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT))
#endif
+#define SPSInterface(i) ((i)->ifinfo.McastTxRx && !((i)->ifa_flags & IFF_LOOPBACK) && !(i)->D2DInterface)
mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg) // Both strings are UTF-8 text
{
@@ -1065,7 +1184,8 @@ mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg) // Both
for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && i->ifinfo.ip.ip.v4.b[0] == 17)
break;
- if (!i) return; // If not at Apple, don't show the alert
+ if (!i)
+ return; // If not at Apple, don't show the alert
}
#endif
@@ -1075,12 +1195,20 @@ mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg) // Both
// If we display our alert early in the boot process, then it vanishes once the desktop appears.
// To avoid this, we don't try to display alerts in the first three minutes after boot.
if ((mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180))
- { LogMsg("Suppressing notification early in boot: %d", mDNSPlatformRawTime()); return; }
+ {
+ LogMsg("Suppressing notification early in boot: %d", mDNSPlatformRawTime());
+ return;
+ }
#ifndef NO_CFUSERNOTIFICATION
static int notifyCount = 0; // To guard against excessive display of warning notifications
- if (notifyCount < 5) { notifyCount++; mDNSNotify(title, msg); }
+ if (notifyCount < 5)
+ {
+ notifyCount++;
+ mDNSNotify(title, msg);
+ }
#endif /* NO_CFUSERNOTIFICATION */
+
}
// Write a syslog message and display an alert, then if ForceAlerts is set, generate a stack trace
@@ -1249,10 +1377,11 @@ mDNSexport void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropert
subkeyCopy[len] = 0;
}
- dispatch_async(DynamicStoreQueue, ^{
+ dispatch_async(dispatch_get_main_queue(), ^{
CFWriteStreamRef stream = NULL;
CFDataRef bytes = NULL;
CFIndex ret;
+ KQueueLock(&mDNSStorage);
if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(NULL, NULL)))
{
@@ -1274,7 +1403,6 @@ mDNSexport void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropert
CFWriteStreamClose(stream);
CFRelease(stream);
stream = NULL;
- LogInfo("mDNSDynamicStoreSetConfig: key %d subkey %s", key, subkeyCopy);
DynamicStoreWrite(key, subkeyCopy ? subkeyCopy : "", (uintptr_t)CFDataGetBytePtr(bytes), CFDataGetLength(bytes));
END:
@@ -1288,6 +1416,8 @@ mDNSexport void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropert
CFRelease(bytes);
if (subkeyCopy)
mDNSPlatformMemFree(subkeyCopy);
+
+ KQueueUnlock(&mDNSStorage, "mDNSDynamicStoreSetConfig");
});
}
@@ -1303,50 +1433,6 @@ mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(mDNS *const m, const
return(NULL);
}
-#if TARGET_OS_EMBEDDED
-mDNSlocal SCPreferencesRef mDNSManagedPrefsGet(void)
-{
- SCPreferencesRef smDNSManagedPrefs = NULL;
- smDNSManagedPrefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("mDNSManagedPrefs"), kmDNSResponderManagedPrefsID);
-
- return (smDNSManagedPrefs);
-}
-
-mDNSlocal mDNSBool GetmDNSManagedPrefKeyVal(SCPreferencesRef prefs, CFStringRef key)
-{
- mDNSBool val = mDNSfalse;
- CFBooleanRef val_cf = NULL;
-
- if (prefs != NULL)
- {
- val_cf = SCPreferencesGetValue(prefs, key);
- if (isA_CFBoolean(val_cf) != NULL)
- val = CFBooleanGetValue(val_cf); //When mDNSResponder-Debug-profile is Installed
- else
- val = mDNSfalse; //When mDNSResponder-Debug-profile is Uninstalled
- }
- else
- {
- LogMsg("GetmDNSManagedPrefKeyVal: mDNSManagedPrefs are NULL!");
- val = mDNSfalse;
- }
- return (val);
-}
-
-mDNSexport mDNSBool GetmDNSManagedPref(CFStringRef key)
-{
- SCPreferencesRef managed = NULL;
- mDNSBool ret_value;
-
- managed = mDNSManagedPrefsGet();
- ret_value = GetmDNSManagedPrefKeyVal(managed, key);
-
- if (managed)
- CFRelease(managed);
- return (ret_value);
-}
-#endif //TARGET_OS_EMBEDDED
-
mDNSlocal int myIfIndexToName(u_short ifindex, char *name)
{
struct ifaddrs *ifa;
@@ -1373,6 +1459,7 @@ mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const
{
if (ifindex == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
if (ifindex == kDNSServiceInterfaceIndexP2P ) return(mDNSInterface_P2P);
+ if (ifindex == kDNSServiceInterfaceIndexBLE ) return(mDNSInterface_BLE);
if (ifindex == kDNSServiceInterfaceIndexAny ) return(mDNSNULL);
NetworkInterfaceInfoOSX* ifi = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)ifindex);
@@ -1393,9 +1480,11 @@ mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const
mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange)
{
NetworkInterfaceInfoOSX *i;
+ if (id == mDNSInterface_Any ) return(0);
if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
+ if (id == mDNSInterface_Unicast ) return(0);
if (id == mDNSInterface_P2P ) return(kDNSServiceInterfaceIndexP2P);
- if (id == mDNSInterface_Any ) return(0);
+ if (id == mDNSInterface_BLE ) return(kDNSServiceInterfaceIndexBLE);
mDNSu32 scope_id = (mDNSu32)(uintptr_t)id;
@@ -1727,62 +1816,74 @@ mDNSlocal void setTrafficClass(int socketfd, mDNSBool useBackgroundTrafficClass)
(void) setsockopt(socketfd, SOL_SOCKET, SO_TRAFFIC_CLASS, (void *)&traffic_class, sizeof(traffic_class));
}
-mDNSexport void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q)
+mDNSlocal int mDNSPlatformGetSocktFd(void *sockCxt, mDNSTransport_Type transType, mDNSAddr_Type addrType)
{
- if (src)
+ if (transType == mDNSTransport_UDP)
+ {
+ UDPSocket* sock = (UDPSocket*) sockCxt;
+ return (addrType == mDNSAddrType_IPv4) ? sock->ss.sktv4 : sock->ss.sktv6;
+ }
+ else if (transType == mDNSTransport_TCP)
{
- int s;
- char unenc_name[MAX_ESCAPED_DOMAIN_NAME];
- ConvertDomainNameToCString(&q->qname, unenc_name);
+ TCPSocket* sock = (TCPSocket*) sockCxt;
+ return (addrType == mDNSAddrType_IPv4) ? sock->ss.sktv4 : sock->ss.sktv6;
+ }
+ else
+ {
+ LogInfo("mDNSPlatformGetSocktFd: invalid transport %d", transType);
+ return kInvalidSocketRef;
+ }
+}
- if (dst->type == mDNSAddrType_IPv4)
- s = src->ss.sktv4;
- else
- s = src->ss.sktv6;
+mDNSexport void mDNSPlatformSetSocktOpt(void *sockCxt, mDNSTransport_Type transType, mDNSAddr_Type addrType, DNSQuestion *q)
+{
+ int sockfd;
+ char unenc_name[MAX_ESCAPED_DOMAIN_NAME];
- if (q->pid)
- {
- if (setsockopt(s, SOL_SOCKET, SO_DELEGATED, &q->pid, sizeof(q->pid)) == -1)
- LogInfo("mDNSPlatformSetuDNSSocktOpt: Delegate PID failed %s for PID %d", strerror(errno), q->pid);
- }
- else
- {
- if (setsockopt(s, SOL_SOCKET, SO_DELEGATED_UUID, &q->uuid, sizeof(q->uuid)) == -1)
- LogInfo("mDNSPlatformSetuDNSSocktOpt: Delegate UUID failed %s", strerror(errno));
- }
-
- // set the domain on the UDP socket
- if (!(ne_session_set_socket_attributes(s, unenc_name, NULL)))
- LogInfo("mDNSPlatformSetuDNSSocktOpt: ne_session_set_socket_attributes()-> setting domain failed for %s", unenc_name);
+ // verify passed-in arguments exist and that sockfd is valid
+ if (q == mDNSNULL || sockCxt == mDNSNULL || (sockfd = mDNSPlatformGetSocktFd(sockCxt, transType, addrType)) < 0)
+ return;
-#if defined(SO_NOWAKEFROMSLEEP)
- int nowake = 1;
- if (setsockopt(s, SOL_SOCKET, SO_NOWAKEFROMSLEEP, &nowake, sizeof(nowake)) == -1)
- LogInfo("mDNSPlatformSetuDNSSocktOpt: SO_NOWAKEFROMSLEEP failed %s", strerror(errno));
-#endif
-
- if (q->DenyOnCellInterface || q->DenyOnExpInterface)
- {
+ if (q->pid)
+ {
+ if (setsockopt(sockfd, SOL_SOCKET, SO_DELEGATED, &q->pid, sizeof(q->pid)) == -1)
+ LogMsg("mDNSPlatformSetSocktOpt: Delegate PID failed %s for PID %d", strerror(errno), q->pid);
+ }
+ else
+ {
+ if (setsockopt(sockfd, SOL_SOCKET, SO_DELEGATED_UUID, &q->uuid, sizeof(q->uuid)) == -1)
+ LogMsg("mDNSPlatformSetSocktOpt: Delegate UUID failed %s", strerror(errno));
+ }
+
+ // set the domain on the socket
+ ConvertDomainNameToCString(&q->qname, unenc_name);
+ if (!(ne_session_set_socket_attributes(sockfd, unenc_name, NULL)))
+ LogInfo("mDNSPlatformSetSocktOpt: ne_session_set_socket_attributes()-> setting domain failed for %s", unenc_name);
+
+ int nowake = 1;
+ if (setsockopt(sockfd, SOL_SOCKET, SO_NOWAKEFROMSLEEP, &nowake, sizeof(nowake)) == -1)
+ LogInfo("mDNSPlatformSetSocktOpt: SO_NOWAKEFROMSLEEP failed %s", strerror(errno));
+
+ if ((q->flags & kDNSServiceFlagsDenyCellular) || (q->flags & kDNSServiceFlagsDenyExpensive))
+ {
#if defined(SO_RESTRICT_DENY_CELLULAR)
- if (q->DenyOnCellInterface)
- {
- int restrictions = 0;
- restrictions = SO_RESTRICT_DENY_CELLULAR;
- if (setsockopt(s, SOL_SOCKET, SO_RESTRICTIONS, &restrictions, sizeof(restrictions)) == -1)
- LogInfo("mDNSPlatformSetuDNSSocktOpt: SO_RESTRICT_DENY_CELLULAR failed %s", strerror(errno));
- }
+ if (q->flags & kDNSServiceFlagsDenyCellular)
+ {
+ int restrictions = 0;
+ restrictions = SO_RESTRICT_DENY_CELLULAR;
+ if (setsockopt(sockfd, SOL_SOCKET, SO_RESTRICTIONS, &restrictions, sizeof(restrictions)) == -1)
+ LogMsg("mDNSPlatformSetSocktOpt: SO_RESTRICT_DENY_CELLULAR failed %s", strerror(errno));
+ }
#endif
#if defined(SO_RESTRICT_DENY_EXPENSIVE)
- if (q->DenyOnExpInterface)
- {
- int restrictions = 0;
- restrictions = SO_RESTRICT_DENY_EXPENSIVE;
- if (setsockopt(s, SOL_SOCKET, SO_RESTRICTIONS, &restrictions, sizeof(restrictions)) == -1)
- LogInfo("mDNSPlatformSetuDNSSocktOpt: SO_RESTRICT_DENY_EXPENSIVE failed %s", strerror(errno));
- }
+ if (q->flags & kDNSServiceFlagsDenyExpensive)
+ {
+ int restrictions = 0;
+ restrictions = SO_RESTRICT_DENY_EXPENSIVE;
+ if (setsockopt(sockfd, SOL_SOCKET, SO_RESTRICTIONS, &restrictions, sizeof(restrictions)) == -1)
+ LogMsg("mDNSPlatformSetSocktOpt: SO_RESTRICT_DENY_EXPENSIVE failed %s", strerror(errno));
+ }
#endif
- }
-
}
}
@@ -1938,7 +2039,10 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
LogInfo("mDNSPlatformSendUDP -> sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu",
s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow));
if (!mDNSAddressIsAllDNSLinkGroup(dst))
- if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr);
+ {
+ if (errno == EHOSTUNREACH) return(mStatus_HostUnreachErr);
+ if (errno == EHOSTDOWN || errno == ENETDOWN || errno == ENETUNREACH) return(mStatus_TransientErr);
+ }
// Don't report EHOSTUNREACH in the first three minutes after boot
// This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
// but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
@@ -1962,14 +2066,6 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
result = mStatus_UnknownErr;
}
-#ifdef IP_BOUND_IF
- if (dst->type == mDNSAddrType_IPv4 && info && !mDNSAddrIsDNSMulticast(dst))
- {
- static const mDNSu32 ifindex = 0;
- setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex));
- }
-#endif
-
return(result);
}
@@ -2089,33 +2185,6 @@ mDNSlocal mDNSInterfaceID FindMyInterface(mDNS *const m, const mDNSAddr *addr)
return(mDNSInterface_Any);
}
-// This is a stupid hack and we should get rid of it.
-// The chance of there being a second unicast UDP packet already waiting in the kernel before we’ve
-// finished processing the previous one is virtually nil, and will only happen by luck on very rare
-// occasions when running on a machine with a fast network connection and a slow or busy processor.
-// The idea that we’d rely for correctness on this random chance event occurring is ridiculous.
-// -- SC
-mDNSexport mDNSBool mDNSPlatformPeekUDP(mDNS *const m, UDPSocket *src)
-{
- // We should have a DNSMessage header followed by the question and an answer
- // which also includes a CNAME (that's when this function is called). To keep it
- // simple, we expect at least the size of DNSMessage header(12) and size of "A"
- // record (14 bytes).
- char buffer[26];
- int ret;
-
- (void) m;
-
- if (!src)
- return mDNSfalse;
-
- ret = recv(src->ss.sktv4, buffer, sizeof(buffer), MSG_PEEK);
- if (ret > 0)
- return mDNStrue;
- else
- return mDNSfalse;
-}
-
mDNSexport void myKQSocketCallBack(int s1, short filter, void *context)
{
KQSocketSet *const ss = (KQSocketSet *)context;
@@ -2133,7 +2202,7 @@ mDNSexport void myKQSocketCallBack(int s1, short filter, void *context)
while (!closed)
{
- mDNSAddr senderAddr, destAddr;
+ mDNSAddr senderAddr, destAddr = zeroAddr;
mDNSIPPort senderPort;
struct sockaddr_storage from;
size_t fromlen = sizeof(from);
@@ -2680,16 +2749,16 @@ mDNSlocal mStatus SetupTCPSocket(TCPSocket *sock, u_short sa_family, mDNSIPPort
addr.sin_family = AF_INET;
addr.sin_port = port->NotAnInteger;
err = bind(skt, (struct sockaddr*) &addr, sizeof(addr));
- if (err < 0) { LogMsg("ERROR: bind %s", strerror(errno)); return err; }
+ if (err < 0) { LogMsg("ERROR: bind %s", strerror(errno)); close(skt); return err; }
// Receive interface identifiers
err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
- if (err < 0) { LogMsg("setsockopt IP_RECVIF - %s", strerror(errno)); return err; }
+ if (err < 0) { LogMsg("setsockopt IP_RECVIF - %s", strerror(errno)); close(skt); return err; }
mDNSPlatformMemZero(&addr, sizeof(addr));
socklen_t len = sizeof(addr);
err = getsockname(skt, (struct sockaddr*) &addr, &len);
- if (err < 0) { LogMsg("getsockname - %s", strerror(errno)); return err; }
+ if (err < 0) { LogMsg("getsockname - %s", strerror(errno)); close(skt); return err; }
port->NotAnInteger = addr.sin_port;
}
@@ -2701,16 +2770,16 @@ mDNSlocal mStatus SetupTCPSocket(TCPSocket *sock, u_short sa_family, mDNSIPPort
addr6.sin6_family = AF_INET6;
addr6.sin6_port = port->NotAnInteger;
err = bind(skt, (struct sockaddr*) &addr6, sizeof(addr6));
- if (err < 0) { LogMsg("ERROR: bind6 %s", strerror(errno)); return err; }
+ if (err < 0) { LogMsg("ERROR: bind6 %s", strerror(errno)); close(skt); return err; }
// We want to receive destination addresses and receive interface identifiers
err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
- if (err < 0) { LogMsg("ERROR: setsockopt IPV6_RECVPKTINFO %s", strerror(errno)); return err; }
+ if (err < 0) { LogMsg("ERROR: setsockopt IPV6_RECVPKTINFO %s", strerror(errno)); close(skt); return err; }
mDNSPlatformMemZero(&addr6, sizeof(addr6));
socklen_t len = sizeof(addr6);
err = getsockname(skt, (struct sockaddr *) &addr6, &len);
- if (err < 0) { LogMsg("getsockname6 - %s", strerror(errno)); return err; }
+ if (err < 0) { LogMsg("getsockname6 - %s", strerror(errno)); close(skt); return err; }
port->NotAnInteger = addr6.sin6_port;
@@ -3106,6 +3175,14 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa
if (err < 0) { errstr = "setsockopt - SO_REUSEPORT"; goto fail; }
}
+ // Don't want to wake from sleep for inbound packets on the mDNS sockets
+ if (mDNSSameIPPort(port, MulticastDNSPort))
+ {
+ int nowake = 1;
+ if (setsockopt(skt, SOL_SOCKET, SO_NOWAKEFROMSLEEP, &nowake, sizeof(nowake)) == -1)
+ LogInfo("SetupSocket: SO_NOWAKEFROMSLEEP failed %s", strerror(errno));
+ }
+
if (sa_family == AF_INET)
{
// We want to receive destination addresses
@@ -3140,7 +3217,7 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa
else if (sa_family == AF_INET6)
{
// NAT-PMP Announcements make no sense on IPv6, and we don't support IPv6 for PCP, so bail early w/o error
- if (mDNSSameIPPort(port, NATPMPAnnouncementPort)) { if (outport) *outport = zeroIPPort;return mStatus_NoError; }
+ if (mDNSSameIPPort(port, NATPMPAnnouncementPort)) { if (outport) *outport = zeroIPPort; close(skt); return mStatus_NoError; }
// We want to receive destination addresses and receive interface identifiers
err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
@@ -3329,7 +3406,7 @@ mDNSlocal void CloseBPF(NetworkInterfaceInfoOSX *const i)
// Note: MUST NOT close() the underlying native BSD sockets.
// CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately, because
// it first has to unhook the sockets from its select() call on its other thread, before it can safely close them.
- CFRunLoopRemoveSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode);
+ CFRunLoopRemoveSource(CFRunLoopGetMain(), i->BPF_rls, kCFRunLoopDefaultMode);
CFRelease(i->BPF_rls);
CFSocketInvalidate(i->BPF_cfs);
CFRelease(i->BPF_cfs);
@@ -3407,34 +3484,374 @@ mDNSexport void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIP
mDNSSendKeepalive(sadd->ip.v6.b, dadd->ip.v6.b, lport->NotAnInteger, rport->NotAnInteger, seq, ack, win);
}
-mDNSexport mStatus mDNSPlatformClearSPSMACAddr(void)
+mDNSexport mStatus mDNSPlatformClearSPSData(void)
{
- CFStringRef entityname = NULL;
+ CFStringRef spsAddress = NULL;
+ CFStringRef ownerOPTRec = NULL;
- if ((entityname = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", "[^/]", "/BonjourSleepProxyAddress")))
+ if ((spsAddress = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", "[^/]", "/BonjourSleepProxyAddress")))
{
- if (SCDynamicStoreRemoveValue(NULL, entityname) == false)
- LogSPS("mDNSPlatformClearSPSMACAddr: Unable to remove key");
+ if (SCDynamicStoreRemoveValue(NULL, spsAddress) == false)
+ LogSPS("mDNSPlatformClearSPSData: Unable to remove sleep proxy address key");
}
- if (entityname)
- CFRelease(entityname);
+ if((ownerOPTRec = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", "[^/]", "/BonjourSleepProxyOPTRecord")))
+ {
+ if (SCDynamicStoreRemoveValue(NULL, ownerOPTRec) == false)
+ LogSPS("mDNSPlatformClearSPSData: Unable to remove sleep proxy owner option record key");
+ }
+
+ if (spsAddress) CFRelease(spsAddress);
+ if (ownerOPTRec) CFRelease(ownerOPTRec);
return KERN_SUCCESS;
}
+mDNSlocal int getMACAddress(int family, v6addr_t raddr, v6addr_t gaddr, int *gfamily, ethaddr_t eth)
+{
+ struct
+ {
+ struct rt_msghdr m_rtm;
+ char m_space[512];
+ } m_rtmsg;
+
+ struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
+ char *cp = m_rtmsg.m_space;
+ int seq = 6367, sock, rlen, i;
+ struct sockaddr_in *sin = NULL;
+ struct sockaddr_in6 *sin6 = NULL;
+ struct sockaddr_dl *sdl = NULL;
+ struct sockaddr_storage sins;
+ struct sockaddr_dl sdl_m;
+
+#define NEXTADDR(w, s, len) \
+if (rtm->rtm_addrs & (w)) \
+{ \
+bcopy((char *)s, cp, len); \
+cp += len; \
+}
+
+ bzero(&sins, sizeof(struct sockaddr_storage));
+ bzero(&sdl_m, sizeof(struct sockaddr_dl));
+ bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
+
+ sock = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (sock < 0)
+ {
+ LogMsg("getMACAddress: Can not open the socket - %s", strerror(errno));
+ return errno;
+ }
+
+ rtm->rtm_addrs |= RTA_DST | RTA_GATEWAY;
+ rtm->rtm_type = RTM_GET;
+ rtm->rtm_flags = 0;
+ rtm->rtm_version = RTM_VERSION;
+ rtm->rtm_seq = ++seq;
+
+ sdl_m.sdl_len = sizeof(sdl_m);
+ sdl_m.sdl_family = AF_LINK;
+ if (family == AF_INET)
+ {
+ sin = (struct sockaddr_in*)&sins;
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(struct sockaddr_in);
+ memcpy(&sin->sin_addr, raddr, sizeof(struct in_addr));
+ NEXTADDR(RTA_DST, sin, sin->sin_len);
+ }
+ else if (family == AF_INET6)
+ {
+ sin6 = (struct sockaddr_in6 *)&sins;
+ sin6->sin6_len = sizeof(struct sockaddr_in6);
+ sin6->sin6_family = AF_INET6;
+ memcpy(&sin6->sin6_addr, raddr, sizeof(struct in6_addr));
+ NEXTADDR(RTA_DST, sin6, sin6->sin6_len);
+ }
+ NEXTADDR(RTA_GATEWAY, &sdl_m, sdl_m.sdl_len);
+ rtm->rtm_msglen = rlen = cp - (char *)&m_rtmsg;
+
+ if (write(sock, (char *)&m_rtmsg, rlen) < 0)
+ {
+ LogMsg("getMACAddress: writing to routing socket: %s", strerror(errno));
+ close(sock);
+ return errno;
+ }
+
+ do
+ {
+ rlen = read(sock, (char *)&m_rtmsg, sizeof(m_rtmsg));
+ }
+ while (rlen > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != getpid()));
+
+ if (rlen < 0)
+ LogMsg("getMACAddress: Read from routing socket failed");
+
+ if (family == AF_INET)
+ {
+ sin = (struct sockaddr_in *) (rtm + 1);
+ sdl = (struct sockaddr_dl *) (sin->sin_len + (char *) sin);
+ }
+ else if (family == AF_INET6)
+ {
+ sin6 = (struct sockaddr_in6 *) (rtm +1);
+ sdl = (struct sockaddr_dl *) (sin6->sin6_len + (char *) sin6);
+ }
+
+ if (!sdl)
+ {
+ LogMsg("getMACAddress: sdl is NULL for family %d", family);
+ close(sock);
+ return -1;
+ }
+
+ // If the address is not on the local net, we get the IP address of the gateway.
+ // We would have to repeat the process to get the MAC address of the gateway
+ *gfamily = sdl->sdl_family;
+ if (sdl->sdl_family == AF_INET)
+ {
+ if (sin)
+ {
+ struct sockaddr_in *new_sin = (struct sockaddr_in *)(sin->sin_len +(char*) sin);
+ memcpy(gaddr, &new_sin->sin_addr, sizeof(struct in_addr));
+ }
+ else
+ {
+ LogMsg("getMACAddress: sin is NULL");
+ }
+ close(sock);
+ return -1;
+ }
+ else if (sdl->sdl_family == AF_INET6)
+ {
+ if (sin6)
+ {
+ struct sockaddr_in6 *new_sin6 = (struct sockaddr_in6 *)(sin6->sin6_len +(char*) sin6);
+ memcpy(gaddr, &new_sin6->sin6_addr, sizeof(struct in6_addr));
+ }
+ else
+ {
+ LogMsg("getMACAddress: sin6 is NULL");
+ }
+ close(sock);
+ return -1;
+ }
+
+ unsigned char *ptr = (unsigned char *)LLADDR(sdl);
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ (eth)[i] = *(ptr +i);
+
+ close(sock);
+
+ return KERN_SUCCESS;
+}
+
+mDNSlocal int GetRemoteMacinternal(int family, v6addr_t raddr, ethaddr_t eth)
+{
+ int ret = 0;
+ v6addr_t gateway;
+ int gfamily = 0;
+ int count = 0;
+
+ do
+ {
+ ret = getMACAddress(family, raddr, gateway, &gfamily, eth);
+ if (ret == -1)
+ {
+ memcpy(raddr, gateway, sizeof(family));
+ family = gfamily;
+ count++;
+ }
+ }
+ while ((ret == -1) && (count < 5));
+ return ret;
+}
+
+mDNSlocal int StoreSPSMACAddressinternal(int family, v6addr_t spsaddr, const char *ifname)
+{
+ ethaddr_t eth;
+ char spsip[INET6_ADDRSTRLEN];
+ int ret = 0;
+ CFStringRef sckey = NULL;
+ SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:StoreSPSMACAddress"), NULL, NULL);
+ SCDynamicStoreRef ipstore = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetIPv6Addresses"), NULL, NULL);
+ CFMutableDictionaryRef dict = NULL;
+ CFStringRef entityname = NULL;
+ CFDictionaryRef ipdict = NULL;
+ CFArrayRef addrs = NULL;
+
+ if ((store == NULL) || (ipstore == NULL))
+ {
+ LogMsg("StoreSPSMACAddressinternal: Unable to accesss SC Dynamic Store");
+ ret = -1;
+ goto fin;
+ }
+
+ // Get the MAC address of the Sleep Proxy Server
+ memset(eth, 0, sizeof(eth));
+ ret = GetRemoteMacinternal(family, spsaddr, eth);
+ if (ret != 0)
+ {
+ LogMsg("StoreSPSMACAddressinternal: Failed to determine the MAC address");
+ goto fin;
+ }
+
+ // Create/Update the dynamic store entry for the specified interface
+ sckey = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", ifname, "/BonjourSleepProxyAddress");
+ dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (!dict)
+ {
+ LogMsg("StoreSPSMACAddressinternal: SPSCreateDict() Could not create CFDictionary dict");
+ ret = -1;
+ goto fin;
+ }
+
+ CFStringRef macaddr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"), eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
+ CFDictionarySetValue(dict, CFSTR("MACAddress"), macaddr);
+ if (NULL != macaddr)
+ CFRelease(macaddr);
+
+ if( NULL == inet_ntop(family, (void *)spsaddr, spsip, sizeof(spsip)))
+ {
+ LogMsg("StoreSPSMACAddressinternal: inet_ntop failed: %s", strerror(errno));
+ ret = -1;
+ goto fin;
+ }
+
+ CFStringRef ipaddr = CFStringCreateWithCString(NULL, spsip, kCFStringEncodingUTF8);
+ CFDictionarySetValue(dict, CFSTR("IPAddress"), ipaddr);
+ if (NULL != ipaddr)
+ CFRelease(ipaddr);
+
+ // Get the current IPv6 addresses on this interface and store them so NAs can be sent on wakeup
+ if ((entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/IPv6"), ifname)) != NULL)
+ {
+ if ((ipdict = SCDynamicStoreCopyValue(ipstore, entityname)) != NULL)
+ {
+ if((addrs = CFDictionaryGetValue(ipdict, CFSTR("Addresses"))) != NULL)
+ {
+ addrs = CFRetain(addrs);
+ CFDictionarySetValue(dict, CFSTR("RegisteredAddresses"), addrs);
+ }
+ }
+ }
+ SCDynamicStoreSetValue(store, sckey, dict);
+
+fin:
+ if (store) CFRelease(store);
+ if (ipstore) CFRelease(ipstore);
+ if (sckey) CFRelease(sckey);
+ if (dict) CFRelease(dict);
+ if (ipdict) CFRelease(ipdict);
+ if (entityname) CFRelease(entityname);
+ if (addrs) CFRelease(addrs);
+
+ return ret;
+}
+
+mDNSlocal void mDNSStoreSPSMACAddress(int family, v6addr_t spsaddr, char *ifname)
+{
+ struct
+ {
+ v6addr_t saddr;
+ } addr;
+ int err = 0;
+
+ mDNSPlatformMemCopy(addr.saddr, spsaddr, sizeof(v6addr_t));
+
+ err = StoreSPSMACAddressinternal(family, (uint8_t *)addr.saddr, ifname);
+ if (err != 0)
+ LogMsg("mDNSStoreSPSMACAddress : failed");
+}
+
mDNSexport mStatus mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname)
{
int family = (spsaddr->type == mDNSAddrType_IPv4) ? AF_INET : AF_INET6;
- LogSPS("mDNSPlatformStoreSPSMACAddr : Storing %#a on interface %s", spsaddr, ifname);
+
+ LogInfo("mDNSPlatformStoreSPSMACAddr : Storing %#a on interface %s", spsaddr, ifname);
mDNSStoreSPSMACAddress(family, spsaddr->ip.v6.b, ifname);
+
return KERN_SUCCESS;
}
+
+mDNSexport mStatus mDNSPlatformStoreOwnerOptRecord(char *ifname, DNSMessage* msg, int length)
+{
+ int ret = 0;
+ CFStringRef sckey = NULL;
+ SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:StoreOwnerOPTRecord"), NULL, NULL);
+ CFMutableDictionaryRef dict = NULL;
+
+ if (store == NULL)
+ {
+ LogMsg("mDNSPlatformStoreOwnerOptRecord: Unable to accesss SC Dynamic Store");
+ ret = -1;
+ goto fin;
+ }
+
+ // Create/Update the dynamic store entry for the specified interface
+ sckey = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", ifname, "/BonjourSleepProxyOPTRecord");
+ dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (!dict)
+ {
+ LogMsg("mDNSPlatformStoreOwnerOptRecord: Could not create CFDictionary dictionary to store OPT Record");
+ ret =-1;
+ goto fin;
+ }
+
+ CFDataRef optRec = NULL;
+ optRec = CFDataCreate(NULL, (const uint8_t *)msg, (CFIndex)length);
+ CFDictionarySetValue(dict, CFSTR("OwnerOPTRecord"), optRec);
+ if (NULL != optRec) CFRelease(optRec);
+
+ SCDynamicStoreSetValue(store, sckey, dict);
+
+fin:
+ if (NULL != store) CFRelease(store);
+ if (NULL != sckey) CFRelease(sckey);
+ if (NULL != dict) CFRelease(dict);
+ return ret;
+}
+
+mDNSlocal void mDNSGet_RemoteMAC(mDNS *const m, int family, v6addr_t raddr)
+{
+ ethaddr_t eth;
+ IPAddressMACMapping *addrMapping;
+ int kr = KERN_FAILURE;
+ struct
+ {
+ v6addr_t addr;
+ } dst;
+
+ mDNSPlatformMemCopy(dst.addr, raddr, sizeof(v6addr_t));
+
+ kr = GetRemoteMacinternal(family, (uint8_t *)dst.addr, eth);
+
+ // If the call to get the remote MAC address succeeds, allocate and copy
+ // the values and schedule a task to update the MAC address in the TCP Keepalive record.
+ if (kr == 0)
+ {
+ addrMapping = mDNSPlatformMemAllocate(sizeof(IPAddressMACMapping));
+ snprintf(addrMapping->ethaddr, sizeof(addrMapping->ethaddr), "%02x:%02x:%02x:%02x:%02x:%02x",
+ eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
+ if (family == AF_INET)
+ {
+ addrMapping->ipaddr.type = mDNSAddrType_IPv4;
+ mDNSPlatformMemCopy(addrMapping->ipaddr.ip.v4.b, raddr, sizeof(v6addr_t));
+ }
+ else
+ {
+ addrMapping->ipaddr.type = mDNSAddrType_IPv6;
+ mDNSPlatformMemCopy(addrMapping->ipaddr.ip.v6.b, raddr, sizeof(v6addr_t));
+ }
+ UpdateRMAC(m, addrMapping);
+ }
+}
+
mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNS *const m, mDNSAddr *raddr)
{
int family = (raddr->type == mDNSAddrType_IPv4) ? AF_INET : AF_INET6;
-
- mDNSGetRemoteMAC(m, family, raddr->ip.v6.b);
+
+ LogInfo("mDNSPlatformGetRemoteMacAddr calling mDNSGet_RemoteMAC");
+ mDNSGet_RemoteMAC(m, family, raddr->ip.v6.b);
+
return KERN_SUCCESS;
}
@@ -3485,7 +3902,7 @@ mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID
NetworkInterfaceInfoOSX *x;
// Note: We can't use IfIndexToInterfaceInfoOSX because that looks for Registered also.
- for (x = m->p->InterfaceList; x; x = x->next) if (x->ifinfo.InterfaceID == InterfaceID) break;
+ for (x = m->p->InterfaceList; x; x = x->next) if ((x->ifinfo.InterfaceID == InterfaceID) && (x->BPF_fd >= 0)) break;
if (!x) { LogMsg("mDNSPlatformUpdateProxyList: ERROR InterfaceID %p not found", InterfaceID); return; }
@@ -3711,7 +4128,7 @@ mDNSexport void mDNSPlatformReceiveBPF_fd(mDNS *const m, int fd)
i->BPF_fd = fd;
i->BPF_cfs = CFSocketCreateWithNative(kCFAllocatorDefault, fd, kCFSocketReadCallBack, bpf_callback, &myCFSocketContext);
i->BPF_rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, i->BPF_cfs, 0);
- CFRunLoopAddSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode);
+ CFRunLoopAddSource(CFRunLoopGetMain(), i->BPF_rls, kCFRunLoopDefaultMode);
#endif
mDNSPlatformUpdateProxyList(m, i->ifinfo.InterfaceID);
}
@@ -3999,8 +4416,8 @@ mDNSlocal mDNSBool InterfaceSupportsKeepAlive(NetworkInterfaceInfo *const intf)
mDNSlocal mDNSBool NetWakeInterface(NetworkInterfaceInfoOSX *i)
{
- if (!MulticastInterface(i) ) return(mDNSfalse); // We only use Sleep Proxy Service on multicast-capable interfaces
- if (i->ifa_flags & IFF_LOOPBACK) return(mDNSfalse); // except loopback
+ // We only use Sleep Proxy Service on multicast-capable interfaces, except loopback and D2D.
+ if (!SPSInterface(i)) return(mDNSfalse);
// If the interface supports TCPKeepalive, it is capable of waking up for a magic packet
// This check is needed since the SIOCGIFWAKEFLAGS ioctl returns wrong values for WOMP capability
@@ -4140,6 +4557,7 @@ exit:
// Return true if the interface is associate to a CarPlay hosted SSID.
mDNSlocal mDNSBool IsCarPlaySSID(char *ifa_name)
{
+ static WiFiManagerClientRef manager = NULL;
mDNSBool rvalue = mDNSfalse;
if (!MobileWiFiLibLoad())
@@ -4148,10 +4566,15 @@ mDNSlocal mDNSBool IsCarPlaySSID(char *ifa_name)
// If we have associated with a CarPlay hosted SSID, then use the same
// optimizations that are used if an interface has the IFEF_DIRECTLINK flag set.
- WiFiManagerClientRef manager;
+ // Get one WiFiManagerClientRef to use for all calls.
+ if (manager == NULL)
+ manager = WiFiManagerClientCreate_p(NULL, kWiFiClientTypeNormal);
- manager = WiFiManagerClientCreate_p(NULL, kWiFiClientTypeNormal);
- if (manager != NULL)
+ if (manager == NULL)
+ {
+ LogInfo("IsCarPlaySSID: WiFiManagerClientCreate() failed!");
+ }
+ else
{
CFArrayRef devices;
@@ -4174,7 +4597,6 @@ mDNSlocal mDNSBool IsCarPlaySSID(char *ifa_name)
}
CFRelease(devices);
}
- CFRelease(manager);
}
return rvalue;
@@ -4263,6 +4685,8 @@ mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifad
i->ifinfo.Loopback = ((ifa->ifa_flags & IFF_LOOPBACK) != 0) ? mDNStrue : mDNSfalse;
i->ifinfo.IgnoreIPv4LL = ((eflags & IFEF_ARPLL) != 0) ? mDNSfalse : mDNStrue;
+ // Setting DirectLink indicates we can do the optimization of skipping the probe phase
+ // for the interface address records since they should be unique.
if (eflags & IFEF_DIRECTLINK)
i->ifinfo.DirectLink = mDNStrue;
else
@@ -4281,6 +4705,7 @@ mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifad
// Bonjour requests over the AWDL interface.
i->ifinfo.SupportsUnicastMDNSResponse = mDNSfalse;
AWDLInterfaceID = i->ifinfo.InterfaceID;
+ i->ifinfo.DirectLink = mDNStrue;
LogInfo("AddInterfaceToList: AWDLInterfaceID = %d", (int) AWDLInterfaceID);
}
else
@@ -4555,7 +4980,7 @@ mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAut
else if (llqStatus == mStatus_NoSuchRecord)
{
status = llqStatus;
- mDNS_snprintf(buffer, sizeof(buffer), llqBuffer);
+ mDNS_snprintf(buffer, sizeof(buffer), "%s", llqBuffer);
}
else if ((llq && llq->Result == mStatus_DoubleNAT) || (tun && tun->Result == mStatus_DoubleNAT))
{
@@ -4582,7 +5007,7 @@ mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAut
else
{
status = llqStatus;
- mDNS_snprintf(buffer, sizeof(buffer), llqBuffer);
+ mDNS_snprintf(buffer, sizeof(buffer), "%s", llqBuffer);
LogInfo("UpdateAutoTunnelDomainStatus: LLQ Status %d, %s", status, buffer);
}
@@ -4649,8 +5074,7 @@ mDNSlocal void UpdateAnonymousRacoonConfig(mDNS *m) // Determine whether we
if (info != AnonymousRacoonConfig)
{
AnonymousRacoonConfig = info;
- // Create or revert configuration file, and start (or SIGHUP) Racoon
- (void)mDNSConfigureServer(AnonymousRacoonConfig ? kmDNSUp : kmDNSDown, AnonymousRacoonConfig ? btmmprefix : mDNSNULL, AnonymousRacoonConfig ? &AnonymousRacoonConfig->domain : mDNSNULL);
+ LogInfo("UpdateAnonymousRacoonConfig need not be done in mDNSResponder");
}
}
@@ -5388,8 +5812,6 @@ mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
p->q.ForceMCast = mDNSfalse;
p->q.ReturnIntermed = mDNStrue;
p->q.SuppressUnusable = mDNSfalse;
- p->q.DenyOnCellInterface = mDNSfalse;
- p->q.DenyOnExpInterface = mDNSfalse;
p->q.SearchListIndex = 0;
p->q.AppendSearchDomains = 0;
p->q.RetryWithSearchDomains = mDNSfalse;
@@ -5507,7 +5929,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
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 (!(ifru_flags6 & (IN6_IFF_TENTATIVE | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY)))
{
if (ifa->ifa_flags & IFF_LOOPBACK)
{
@@ -5634,6 +6056,9 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
{
NetworkInterfaceInfoOSX *i;
int count = 0;
+
+ // Recalculate SuppressProbes time based on the current set of active interfaces.
+ m->SuppressProbes = 0;
for (i = m->p->InterfaceList; i; i = i->next)
if (i->Exists)
{
@@ -5687,8 +6112,8 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
if (!n->McastTxRx)
{
debugf("SetupActiveInterfaces: No Tx/Rx on %5s(%lu) %.6a InterfaceID %p %#a", i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, &n->ip);
-#if TARGET_OS_WATCH
- // We join the Bonjour multicast group on the watch only when a client request is active,
+#if TARGET_OS_EMBEDDED
+ // We join the Bonjour multicast group on Apple embedded platforms ONLY when a client request is active,
// so we leave the multicast group here to clear any residual group membership.
if (i->sa_family == AF_INET)
{
@@ -5719,7 +6144,7 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
LogMsg("setsockopt - IPV6_LEAVE_GROUP error %d errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
}
}
-#endif // TARGET_OS_WATCH
+#endif // TARGET_OS_EMBEDDED
}
else
{
@@ -5963,21 +6388,38 @@ mDNSexport const char *DNSScopeToString(mDNSu32 scope)
}
}
-mDNSlocal void ConfigSearchDomains(mDNS *const m, dns_resolver_t *resolver, mDNSInterfaceID interface, mDNSu32 scope, MD5_CTX *sdc)
+mDNSlocal void ConfigSearchDomains(mDNS *const m, dns_resolver_t *resolver, mDNSInterfaceID interfaceId, mDNSu32 scope, MD5_CTX *sdc, uint64_t generation)
{
const char *scopeString = DNSScopeToString(scope);
int j;
+ domainname d;
+
+ if (scope == kScopeNone)
+ interfaceId = mDNSInterface_Any;
- if (scope != kScopeNone)
+ if (scope == kScopeNone || scope == kScopeInterfaceID)
{
- LogInfo("ConfigSearchDomains: (%s) Ignoring search domain for Interface %p", scopeString, interface);
- return;
+ for (j = 0; j < resolver->n_search; j++)
+ {
+ if (MakeDomainNameFromDNSNameString(&d, resolver->search[j]) != NULL)
+ {
+ static char interface_buf[32];
+ mDNS_snprintf(interface_buf, sizeof(interface_buf), "for interface %s", InterfaceNameForID(m, interfaceId));
+ LogInfo("ConfigSearchDomains: (%s) configuring search domain %s %s (generation= %llu)", scopeString,
+ resolver->search[j], (interfaceId == mDNSInterface_Any) ? "" : interface_buf, generation);
+ UpdateSearchDomainHash(m, sdc, resolver->search[j], interfaceId);
+ mDNS_AddSearchDomain_CString(resolver->search[j], interfaceId);
+ }
+ else
+ {
+ LogInfo("ConfigSearchDomains: An invalid search domain was detected for %s domain %s n_nameserver %d, (generation= %llu)",
+ DNSScopeToString(scope), resolver->domain, resolver->n_nameserver, generation);
+ }
+ }
}
- for (j = 0; j < resolver->n_search; j++)
+ else
{
- LogInfo("ConfigSearchDomains: (%s) configuring search list %s", scopeString, resolver->search[j]);
- UpdateSearchDomainHash(m, sdc, resolver->search[j], NULL);
- mDNS_AddSearchDomain_CString(resolver->search[j], NULL);
+ LogInfo("ConfigSearchDomains: (%s) Ignoring search domain for interface %s", scopeString, InterfaceNameForID(m,interfaceId));
}
}
@@ -6140,7 +6582,8 @@ mDNSlocal void ConfigResolvers(mDNS *const m, dns_config_t *config, mDNSu32 scop
if (setsearch)
{
- ConfigSearchDomains(m, resolver[i], interface, scope, sdc);
+ ConfigSearchDomains(m, resolver[i], interface, scope, sdc, config->generation);
+
// Parse other scoped resolvers for search lists
if (!setservers)
continue;
@@ -6522,9 +6965,8 @@ mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers,
}
else
{
- LogInfo("mDNSPlatformSetDNSConfig: config->n_resolver = %d, generation %llu", config->n_resolver, config->generation);
- // SameDomainName check below is to fix <rdar://problem/18059009> Dynamic DNS hostname changes not noticed
- if (m->p->LastConfigGeneration == config->generation && (!fqdn || (SameDomainName(fqdn, &m->FQDN))))
+ LogInfo("mDNSPlatformSetDNSConfig: config->n_resolver = %d, generation %llu, last %llu", config->n_resolver, config->generation, m->p->LastConfigGeneration);
+ if (m->p->LastConfigGeneration == config->generation)
{
LogInfo("mDNSPlatformSetDNSConfig: generation number %llu same, not processing", config->generation);
dns_configuration_free(config);
@@ -6855,7 +7297,7 @@ mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m)
else LogInfo("UpdateBTMMRelayConnection: Not calling AWS_Disconnect");
}
}
-#else
+#elif !TARGET_OS_EMBEDDED
mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m)
{
(void) m; // Unused
@@ -6863,12 +7305,14 @@ mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m)
}
#endif // ! NO_AWACS
+#if !TARGET_OS_EMBEDDED
mDNSlocal void ProcessConndConfigChanges(mDNS *const m);
+#endif
#endif // APPLE_OSX_mDNSResponder
// MUST be called holding the lock
-mDNSexport void SetDomainSecrets(mDNS *m)
+mDNSlocal void SetDomainSecrets_internal(mDNS *m)
{
#ifdef NO_SECURITYFRAMEWORK
(void) m;
@@ -7134,6 +7578,15 @@ mDNSexport void SetDomainSecrets(mDNS *m)
#endif /* NO_SECURITYFRAMEWORK */
}
+mDNSexport void SetDomainSecrets(mDNS *m)
+{
+#if DEBUG
+ // Don't get secrets for BTMM if running in debug mode
+ if (!IsDebugSocketInUse())
+#endif
+ SetDomainSecrets_internal(m);
+}
+
mDNSlocal void SetLocalDomains(void)
{
CFMutableArrayRef sa = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
@@ -7303,6 +7756,7 @@ mDNSlocal void UpdateSPSStatus(mDNS *const m, DNSQuestion *question, const Resou
CFRelease(ifname);
}
+#if !TARGET_OS_EMBEDDED
mDNSlocal mDNSs32 GetSystemSleepTimerSetting(void)
{
mDNSs32 val = -1;
@@ -7365,6 +7819,7 @@ mDNSlocal void SetSPS(mDNS *const m)
mDNSCoreBeSleepProxyServer(m, sps, SPMetricPortability, SPMetricMarginalPower, SPMetricTotalPower, SPMetricFeatures);
}
+#endif // !TARGET_OS_EMBEDDED
// The definitions below should eventually come from some externally-supplied header file.
// However, since these definitions can't really be changed without breaking binary compatibility,
@@ -7396,14 +7851,28 @@ typedef struct
mDNSlocal mDNSu16 GetPortArray(mDNS *const m, int trans, mDNSIPPort *portarray)
{
const domainlabel *const tp = (trans == mDNSTransport_UDP) ? (const domainlabel *)"\x4_udp" : (const domainlabel *)"\x4_tcp";
- int count = 0;
+ int count = 0;
+
AuthRecord *rr;
for (rr = m->ResourceRecords; rr; rr=rr->next)
+ {
if (rr->resrec.rrtype == kDNSType_SRV && SameDomainLabel(ThirdLabel(rr->resrec.name)->c, tp->c))
{
- if (portarray) portarray[count] = rr->resrec.rdata->u.srv.port;
- count++;
+ if (!portarray)
+ count++;
+ else
+ {
+ int i;
+ for (i = 0; i < count; i++)
+ if (mDNSSameIPPort(portarray[i], rr->resrec.rdata->u.srv.port))
+ break;
+
+ // Add it into the port list only if it not already present in the list
+ if (i >= count)
+ portarray[count++] = rr->resrec.rdata->u.srv.port;
+ }
}
+ }
// If Back to My Mac is on, also wake for packets to the IPSEC UDP port (4500)
if (trans == mDNSTransport_UDP && m->AutoTunnelNAT.clientContext)
@@ -7546,7 +8015,7 @@ mDNSexport mDNSBool SupportsInNICProxy(NetworkInterfaceInfo *const intf)
{
if(!UseInternalSleepProxy)
{
- LogSPS("SupportsInNICProxy: Internal Sleep Proxy is disabled");
+ LogMsg("SupportsInNICProxy: Internal Sleep Proxy is disabled");
return mDNSfalse;
}
return CheckInterfaceSupport(intf, mDNS_IOREG_KEY);
@@ -7607,10 +8076,10 @@ mDNSexport mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const
cmd.numRRRecords = CountProxyRecords(m, &cmd.rrBufferSize, intf, TCPKAOnly, supportsTCPKA);
cmd.compression = sizeof(DNSMessageHeader);
- DNSMessage *msg = (DNSMessage *)mallocL("mDNSOffloadCmd msg", sizeof(DNSMessageHeader) + cmd.rrBufferSize);
- cmd.rrRecords.ptr = mallocL("mDNSOffloadCmd rrRecords", cmd.numRRRecords * sizeof(FatPtr));
- cmd.udpPorts.ptr = mallocL("mDNSOffloadCmd udpPorts", cmd.numUDPPorts * sizeof(mDNSIPPort));
- cmd.tcpPorts.ptr = mallocL("mDNSOffloadCmd tcpPorts", cmd.numTCPPorts * sizeof(mDNSIPPort));
+ DNSMessage *msg = (DNSMessage *)mallocL("mDNSOffloadCmd msg", sizeof(DNSMessageHeader) + cmd.rrBufferSize);
+ cmd.rrRecords.ptr = cmd.numRRRecords ? mallocL("mDNSOffloadCmd rrRecords", cmd.numRRRecords * sizeof(FatPtr)) : NULL;
+ cmd.udpPorts.ptr = cmd.numUDPPorts ? mallocL("mDNSOffloadCmd udpPorts" , cmd.numUDPPorts * sizeof(mDNSIPPort)) : NULL;
+ cmd.tcpPorts.ptr = cmd.numTCPPorts ? mallocL("mDNSOffloadCmd tcpPorts" , cmd.numTCPPorts * sizeof(mDNSIPPort)) : NULL;
LogSPS("ActivateLocalProxy: msg %p %d RR %p %d, UDP %p %d, TCP %p %d",
msg, cmd.rrBufferSize,
@@ -7618,23 +8087,15 @@ mDNSexport mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const
cmd.udpPorts.ptr, cmd.numUDPPorts,
cmd.tcpPorts.ptr, cmd.numTCPPorts);
- if (!msg || !cmd.rrRecords.ptr || !cmd.udpPorts.ptr || !cmd.tcpPorts.ptr)
- LogMsg("ActivateLocalProxy: Failed to allocate memory: msg %p %d RR %p %d, UDP %p %d, TCP %p %d",
- msg, cmd.rrBufferSize,
- cmd.rrRecords.ptr, cmd.numRRRecords,
- cmd.udpPorts.ptr, cmd.numUDPPorts,
- cmd.tcpPorts.ptr, cmd.numTCPPorts);
- else
- {
- GetProxyRecords(m, msg, &cmd.rrBufferSize, cmd.rrRecords.ptr, TCPKAOnly, supportsTCPKA);
- GetPortArray(m, mDNSTransport_UDP, cmd.udpPorts.ptr);
- GetPortArray(m, mDNSTransport_TCP, cmd.tcpPorts.ptr);
- char outputData[2];
- size_t outputDataSize = sizeof(outputData);
- kr = IOConnectCallStructMethod(conObj, 0, &cmd, sizeof(cmd), outputData, &outputDataSize);
- LogSPS("ActivateLocalProxy: IOConnectCallStructMethod for %s/%s/%s %d", intf->ifname, n1, n2, kr);
- if (kr == KERN_SUCCESS) result = mStatus_NoError;
- }
+ if (msg && cmd.rrRecords.ptr) GetProxyRecords(m, msg, &cmd.rrBufferSize, cmd.rrRecords.ptr, TCPKAOnly, supportsTCPKA);
+ if (cmd.udpPorts.ptr) cmd.numUDPPorts = GetPortArray(m, mDNSTransport_UDP, cmd.udpPorts.ptr);
+ if (cmd.tcpPorts.ptr) cmd.numTCPPorts = GetPortArray(m, mDNSTransport_TCP, cmd.tcpPorts.ptr);
+
+ char outputData[2];
+ size_t outputDataSize = sizeof(outputData);
+ kr = IOConnectCallStructMethod(conObj, 0, &cmd, sizeof(cmd), outputData, &outputDataSize);
+ LogSPS("ActivateLocalProxy: IOConnectCallStructMethod for %s/%s/%s %d", intf->ifname, n1, n2, kr);
+ if (kr == KERN_SUCCESS) result = mStatus_NoError;
if (cmd.tcpPorts.ptr) freeL("mDNSOffloadCmd udpPorts", cmd.tcpPorts.ptr);
if (cmd.udpPorts.ptr) freeL("mDNSOffloadCmd tcpPorts", cmd.udpPorts.ptr);
@@ -7683,10 +8144,15 @@ mDNSlocal mDNSu8 SystemWakeForNetworkAccess(void)
mDNSlocal mDNSBool SystemSleepOnlyIfWakeOnLAN(void)
{
mDNSs32 val = 0;
- GetCurrentPMSetting(CFSTR("PrioritizeNetworkReachabilityOverSleep"), &val);
+ // PrioritizeNetworkReachabilityOverSleep has been deprecated.
+ // GetCurrentPMSetting(CFSTR("PrioritizeNetworkReachabilityOverSleep"), &val);
+ // Statically set the PrioritizeNetworkReachabilityOverSleep value to 1 for AppleTV
+ if (IsAppleTV())
+ val = 1;
return val != 0 ? mDNStrue : mDNSfalse;
}
+
#if APPLE_OSX_mDNSResponder
// When sleeping, we always ensure that the _autotunnel6 record (if connected to RR relay)
// gets deregistered, so that older peers are forced to connect over direct UDP instead of
@@ -7744,6 +8210,7 @@ mDNSexport void RemoveAutoTunnel6Record(mDNS *const m)
UpdateAutoTunnel6Record(m, info);
}
+#if !TARGET_OS_EMBEDDED
mDNSlocal mDNSBool IPv6AddressIsOnInterface(mDNSv6Addr ipv6Addr, char *ifname)
{
struct ifaddrs *ifa;
@@ -7978,6 +8445,7 @@ mDNSlocal void ProcessConndConfigChanges(mDNS *const m)
// If awacsd crashes or exits for some reason, restart it
UpdateBTMMRelayConnection(m);
}
+#endif // !TARGET_OS_EMBEDDED
#endif /* APPLE_OSX_mDNSResponder */
mDNSlocal mDNSBool IsAppleNetwork(mDNS *const m)
@@ -8027,11 +8495,11 @@ mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
m->NetworkChanged ? "" : " (no scheduled configuration change)");
m->NetworkChanged = 0; // If we received a network change event and deferred processing, we're now dealing with it
- // If we have any NOTREADY IPv6 addresses, wait until they've finished configuring
+ // If we have *any* TENTATIVE IPv6 addresses, wait until they've finished configuring
int InfoSocket = socket(AF_INET6, SOCK_DGRAM, 0);
if (InfoSocket > 0)
{
- mDNSBool notready = mDNSfalse;
+ mDNSBool tentative = mDNSfalse;
struct ifaddrs *ifa = myGetIfAddrs(1);
while (ifa)
{
@@ -8046,25 +8514,29 @@ mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
// We can expect that an IN6_IFF_TENTATIVE address will shortly become ready,
// but an IN6_IFF_DUPLICATED address may not.
if (ioctl(InfoSocket, SIOCGIFAFLAG_IN6, &ifr6) != -1)
+ {
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
{
LogInfo("*** Network Configuration Change *** IPv6 address %.16a TENTATIVE, will retry", &ifr6.ifr_addr.sin6_addr);
- notready = mDNStrue;
+ tentative = mDNStrue;
+ // no need to check other interfaces if we already found out that one interface is TENTATIVE
+ break;
}
+ }
}
ifa = ifa->ifa_next;
}
close(InfoSocket);
- if (notready)
+ if (tentative)
{
mDNS_Lock(m);
SetNetworkChanged(m, mDNSPlatformOneSecond / 2);
mDNS_Unlock(m);
return;
}
- LogInfo("*** Network Configuration Change *** No IPv6 address NOTREADY, will continue");
+ LogInfo("*** Network Configuration Change *** No IPv6 address TENTATIVE, will continue");
}
-
+
mDNSs32 utc = mDNSPlatformUTC();
m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
m->SystemSleepOnlyIfWakeOnLAN = SystemSleepOnlyIfWakeOnLAN();
@@ -8073,7 +8545,7 @@ mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
ClearInactiveInterfaces(m, utc);
SetupActiveInterfaces(m, utc);
-#if APPLE_OSX_mDNSResponder
+#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
mDNS_Lock(m);
ProcessConndConfigChanges(m);
@@ -8129,14 +8601,19 @@ mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
NetworkInterfaceInfoOSX *i;
for (i = m->p->InterfaceList; i; i = i->next)
{
- if (!m->SPSSocket) // Not being Sleep Proxy Server; close any open BPF fds
+ if (!m->SPSSocket) // Not being Sleep Proxy Server; close any open BPF fds
{
- if (i->BPF_fd >= 0 && CountProxyTargets(m, i, mDNSNULL, mDNSNULL) == 0) CloseBPF(i);
+ if (i->BPF_fd >= 0 && CountProxyTargets(m, i, mDNSNULL, mDNSNULL) == 0)
+ CloseBPF(i);
}
- else // else, we're Sleep Proxy Server; open BPF fds
+ else // else, we're Sleep Proxy Server; open BPF fds
{
- if (i->Exists && i->Registered == i && i->ifinfo.McastTxRx && !(i->ifa_flags & IFF_LOOPBACK) && i->BPF_fd == -1)
- { LogSPS("%s requesting BPF", i->ifinfo.ifname); i->BPF_fd = -2; mDNSRequestBPF(); }
+ if (i->Exists && (i->Registered == i) && SPSInterface(i) && i->BPF_fd == -1)
+ {
+ LogMsg("%s mDNSMacOSXNetworkChanged: requesting BPF", i->ifinfo.ifname);
+ i->BPF_fd = -2;
+ mDNSRequestBPF();
+ }
}
}
@@ -8411,6 +8888,8 @@ mDNSlocal void DynamicStoreReconnected(SCDynamicStoreRef store, void *info)
mDNS *const m = (mDNS *const)info;
(void)store;
+ KQueueLock(m); // serialize with KQueueLoop()
+
LogInfo("DynamicStoreReconnected: Reconnected");
// State:/Network/MulticastDNS
@@ -8429,15 +8908,14 @@ mDNSlocal void DynamicStoreReconnected(SCDynamicStoreRef store, void *info)
mDNSDynamicStoreSetConfig(kmDNSPrivateConfig, mDNSNULL, privateDnsArray);
#if APPLE_OSX_mDNSResponder
- mDNS_Lock(m);
// State:/Network/BackToMyMac
UpdateAutoTunnelDomainStatuses(m);
- mDNS_Unlock(m);
// State:/Network/Interface/en0/SleepProxyServers
if (spsStatusDict)
CFDictionaryApplyFunction(spsStatusDict, RefreshSPSStatus, NULL);
#endif
+ KQueueUnlock(m, "DynamicStoreReconnected");
}
mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m)
@@ -8474,7 +8952,7 @@ mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m)
#else
m->p->StoreRLS = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
if (!m->p->StoreRLS) { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error; }
- CFRunLoopAddSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode);
+ CFRunLoopAddSource(CFRunLoopGetMain(), m->p->StoreRLS, kCFRunLoopDefaultMode);
#endif
SCDynamicStoreSetDisconnectCallBack(store, DynamicStoreReconnected);
m->p->Store = store;
@@ -8521,7 +8999,7 @@ mDNSlocal void mDNSSetPacketFilterRules(mDNS *const m, char * ifname, const Reso
continue;
}
- LogInfo("mDNSSetPacketFilterRules: found %s", ARDisplayString(m, rr));
+ LogMsg("mDNSSetPacketFilterRules: found %s", ARDisplayString(m, rr));
portArray[count] = rr->resrec.rdata->u.srv.port.NotAnInteger;
@@ -8529,13 +9007,21 @@ mDNSlocal void mDNSSetPacketFilterRules(mDNS *const m, char * ifname, const Reso
p = rr->resrec.name->c;
// Skip to App Protocol
- if (p[0]) p += 1 + p[0];
+ if (p[0])
+ p += 1 + p[0];
// Skip to Transport Protocol
- if (p[0]) p += 1 + p[0];
+ if (p[0])
+ p += 1 + p[0];
- if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_tcp")) protocolArray[count] = IPPROTO_TCP;
- else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp")) protocolArray[count] = IPPROTO_UDP;
+ if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_tcp"))
+ {
+ protocolArray[count] = IPPROTO_TCP;
+ }
+ else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp"))
+ {
+ protocolArray[count] = IPPROTO_UDP;
+ }
else
{
LogMsg("mDNSSetPacketFilterRules: could not determine transport protocol of service");
@@ -8651,12 +9137,8 @@ mDNSlocal mDNSBool allZeroSSTH(struct opaque_presence_indication *op)
return mDNStrue;
}
-// mDNS_Reconfirm_internal() adds 33% to this interval, so the records should
-// be removed in 4 seconds.
-#define kAWDLReconfirmTime ((mDNSu32)mDNSPlatformOneSecond * 3)
-
// Mark records from this peer for deletion from the cache.
-mDNSlocal void removeCachedPeerRecords(mDNS *const m, mDNSu32 ifindex, mDNSAddr *ap)
+mDNSlocal void removeCachedPeerRecords(mDNS *const m, mDNSu32 ifindex, mDNSAddr *ap, bool purgeNow)
{
mDNSu32 slot;
CacheGroup *cg;
@@ -8680,7 +9162,11 @@ mDNSlocal void removeCachedPeerRecords(mDNS *const m, mDNSu32 ifindex, mDNSAddr
{
LogInfo("removeCachedPeerRecords: %s %##s marking for deletion",
DNSTypeName(cr->resrec.rrtype), cr->resrec.name->c);
- mDNS_Reconfirm_internal(m, cr, kAWDLReconfirmTime);
+
+ if (purgeNow)
+ mDNS_PurgeCacheResourceRecord(m, cr);
+ else
+ mDNS_Reconfirm_internal(m, cr, 0); // use default minimum reconfirm time
}
}
}
@@ -8705,8 +9191,8 @@ mDNSlocal void nodePresence(mDNS *const m, struct kev_dl_node_presence * p)
peerAddr.type = mDNSAddrType_IPv6;
peerAddr.ip.v6 = *(mDNSv6Addr*)&p->sin6_node_address.sin6_addr;
- LogInfo("nodePresence: ssth is all zeroes, delete cached records from this peer");
- removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr);
+ LogInfo("nodePresence: ssth is all zeroes, reconfirm cached records for this peer");
+ removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr, false);
}
}
@@ -8724,8 +9210,8 @@ mDNSlocal void nodeAbsence(mDNS *const m, struct kev_dl_node_absence * p)
peerAddr.type = mDNSAddrType_IPv6;
peerAddr.ip.v6 = *(mDNSv6Addr*)&p->sin6_node_address.sin6_addr;
- LogInfo("nodeAbsence: delete cached records from this peer");
- removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr);
+ LogInfo("nodeAbsence: immediately purge cached records from this peer");
+ removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr, true);
}
mDNSlocal void SysEventCallBack(int s1, short __unused filter, void *context)
@@ -8922,25 +9408,20 @@ mDNSlocal void PowerOn(mDNS *const m)
{
mDNSCoreMachineSleep(m, false); // Will set m->SleepState = SleepState_Awake;
- // Hold on to a sleep assertion to allow mDNSResponder to perform its maintenance activities.
- // This allows for the network link to come up, DHCP to get an address, mDNS to issue queries etc.
- // We will clear this assertion as soon as we think the mainenance activities are done.
- mDNSPlatformPreventSleep(m, DARK_WAKE_TIME, "mDNSResponder:maintenance");
-
if (m->p->WakeAtUTC)
{
long utc = mDNSPlatformUTC();
mDNSPowerRequest(-1,-1); // Need to explicitly clear any previous power requests -- they're not cleared automatically on wake
if (m->p->WakeAtUTC - utc > 30)
- {
+ {
LogSPS("PowerChanged PowerOn %d seconds early, assuming not maintenance wake", m->p->WakeAtUTC - utc);
}
- else if (utc - m->p->WakeAtUTC > 30)
+ else if (utc - m->p->WakeAtUTC > 30)
{
LogSPS("PowerChanged PowerOn %d seconds late, assuming not maintenance wake", utc - m->p->WakeAtUTC);
}
else if (IsAppleTV())
- {
+ {
LogSPS("PowerChanged PowerOn %d seconds late, device is an AppleTV running iOS so not re-sleeping", utc - m->p->WakeAtUTC);
}
else
@@ -8949,6 +9430,12 @@ mDNSlocal void PowerOn(mDNS *const m)
m->p->RequestReSleep = mDNS_TimeNow(m) + 20 * mDNSPlatformOneSecond;
}
}
+
+ // Hold on to a sleep assertion to allow mDNSResponder to perform its maintenance activities.
+ // This allows for the network link to come up, DHCP to get an address, mDNS to issue queries etc.
+ // We will clear this assertion as soon as we think the mainenance activities are done.
+ mDNSPlatformPreventSleep(m, DARK_WAKE_TIME, "mDNSResponder:maintenance");
+
}
mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messageType, void *messageArgument)
@@ -8969,7 +9456,7 @@ mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messag
if (m->SleepState == SleepState_Sleeping) mDNSMacOSXNetworkChanged(m);
break;
case kIOMessageSystemWillNotPowerOff: LogSPS("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; // E0000260
- case kIOMessageCanSystemSleep: LogSPS("PowerChanged kIOMessageCanSystemSleep (no action)"); break; // E0000270
+ case kIOMessageCanSystemSleep: LogSPS("PowerChanged kIOMessageCanSystemSleep"); break; // E0000270
case kIOMessageSystemWillSleep: LogSPS("PowerChanged kIOMessageSystemWillSleep"); // E0000280
mDNSCoreMachineSleep(m, true);
break;
@@ -9004,8 +9491,11 @@ mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messag
default: LogSPS("PowerChanged unknown message %X", messageType); break;
}
- if (messageType == kIOMessageSystemWillSleep) m->p->SleepCookie = (long)messageArgument;
- else IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument);
+ if ((messageType == kIOMessageSystemWillSleep) || (messageType== kIOMessageCanSystemSleep))
+ {
+ m->p->SleepCookie = (long)messageArgument;
+ IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument);
+ }
KQueueUnlock(m, "PowerChanged Sleep/Wake");
}
@@ -9329,93 +9819,77 @@ mDNSlocal void mDNSMacOSXParseEtcHostsLine(mDNS *const m, char *buffer, ssize_t
// We might have some extra white spaces at the end for the common case of "1.2.3.4 somehost".
// When we parse again below, EtchHostsParseOneName would return -1 and we will end up
// doing the right thing.
+
if (!MakeDomainNameFromDNSNameString(&first, name1))
{
LogMsg("mDNSMacOSXParseEtcHostsLine: ERROR!! cannot convert to domain name %s", name1);
freeaddrinfo(gairesults);
return;
}
+ mDNSMacOSXCreateEtcHostsEntry(m, &first, gairesults->ai_addr, mDNSNULL, ifname, auth);
+
+ // /etc/hosts alias discussion:
+ //
// If the /etc/hosts has an entry like this
//
- // 1.2.3.4 sun star bright
+ // ip_address cname [aliases...]
+ // 1.2.3.4 sun star bright
//
// star and bright are aliases (gethostbyname h_alias should point to these) and sun is the canonical
// name (getaddrinfo ai_cannonname and gethostbyname h_name points to "sun")
//
// To achieve this, we need to add the entry like this:
//
- // star CNAME bright
- // bright CNAME sun
// sun A 1.2.3.4
+ // star CNAME sun
+ // bright CNAME sun
//
- // We store the first name we parsed in "first". Then we parse additional names adding CNAME records
- // till we reach the end. When we reach the end, we wrap around and add one final CNAME with the last
- // entry and the first entry. Finally, we add the Address (A/AAAA) record.
+ // We store the first name we parsed in "first" and add the address (A/AAAA) record.
+ // Then we parse additional names adding CNAME records till we reach the end.
+
aliasIndex = 0;
- while (i <= length)
+ while (i < length)
{
- // Parse a name. If there are no names, we need to know whether we
- // parsed CNAMEs before or not. If we parsed CNAMEs before, then we
- // add a CNAME with the last name and the first name. Otherwise, this
- // is same as the common case above where the line has just one name
- // but with trailing white spaces.
+ // Continue to parse additional aliases until we reach end of the line and
+ // for each "alias" parsed, add a CNAME record where "alias" points to the first "name".
+ // See also /etc/hosts alias discussion above
+
i = EtcHostsParseOneName(i + 1, length, buffer, &name2);
+
if (name2)
{
+ if ((aliasIndex) && (*buffer == *name2))
+ break; // break out of the loop if we wrap around
+
if (!MakeDomainNameFromDNSNameString(&name2d, name2))
{
LogMsg("mDNSMacOSXParseEtcHostsLine: ERROR!! cannot convert to domain name %s", name2);
freeaddrinfo(gairesults);
return;
}
- aliasIndex++;
- }
- else if (!aliasIndex)
- {
- // We have never parsed any aliases. This case happens if there
- // is just one name and some extra white spaces at the end.
- LogInfo("mDNSMacOSXParseEtcHostsLine: White space at the end of %##s", first.c);
- break;
- }
- else
- {
- // We have parsed at least one alias before and we reached the end of the line.
- // Setup a CNAME for the last name with "first" name as its RDATA
- name2d.c[0] = 0;
- AssignDomainName(&name2d, &first);
- }
-
- // Don't add a CNAME for the first alias we parse (see the example above).
- // As we parse more, we might discover that there are no more aliases, in
- // which case we would have set "name2d" to "first" above. We need to add
- // the CNAME in that case.
-
- if (aliasIndex > 1 || SameDomainName(&name2d, &first))
- {
// Ignore if it points to itself
- if (!SameDomainName(&name1d, &name2d))
+ if (!SameDomainName(&first, &name2d))
{
- if (!mDNSMacOSXCreateEtcHostsEntry(m, &name1d, mDNSNULL, &name2d, ifname, auth))
+ if (!mDNSMacOSXCreateEtcHostsEntry(m, &name2d, mDNSNULL, &first, ifname, auth))
{
freeaddrinfo(gairesults);
return;
}
}
else
- LogMsg("mDNSMacOSXParseEtcHostsLine: Ignoring entry with same names name1 %##s, name2 %##s", name1d.c, name2d.c);
+ {
+ LogInfo("mDNSMacOSXParseEtcHostsLine: Ignoring entry with same names first %##s, name2 %##s", first.c, name2d.c);
+ }
+ aliasIndex++;
+ }
+ else if (!aliasIndex)
+ {
+ // We have never parsed any aliases. This case happens if there
+ // is just one name and some extra white spaces at the end.
+ LogInfo("mDNSMacOSXParseEtcHostsLine: White space at the end of %##s", first.c);
+ break;
}
-
- // If we have already wrapped around, we just need to add the A/AAAA record alone
- // which is done below
- if (SameDomainName(&name2d, &first)) break;
-
- // Remember the current name so that we can set the CNAME record if we parse one
- // more name
- name1d.c[0] = 0;
- AssignDomainName(&name1d, &name2d);
}
- // Added all the CNAMEs if any, add the "A/AAAA" record
- mDNSMacOSXCreateEtcHostsEntry(m, &first, gairesults->ai_addr, mDNSNULL, ifname, auth);
}
freeaddrinfo(gairesults);
}
@@ -9813,9 +10287,9 @@ mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m)
if (!EtcHostsDeleteOldEntries(m, &newhosts, mDNStrue))
{
LogInfo("mDNSMacOSXUpdateEtcHosts: No work");
+ FreeNewHosts(&newhosts);
mDNS_Unlock(m);
KQueueUnlock(m, "/etc/hosts changed");
- FreeNewHosts(&newhosts);
return;
}
}
@@ -9838,10 +10312,9 @@ mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m)
// is called back where we do the Registration of the record. This results in RMV followed by ADD which
// looks normal.
mDNSCoreRestartAddressQueries(m, mDNSfalse, FlushAllCacheRecords, UpdateEtcHosts, &newhosts);
+ FreeNewHosts(&newhosts);
mDNS_Unlock(m);
-
KQueueUnlock(m, "/etc/hosts changed");
- FreeNewHosts(&newhosts);
}
#if COMPILER_LIKES_PRAGMA_MARK
@@ -9988,7 +10461,6 @@ mDNSlocal void SetupLocalHostRecords(mDNS *const m)
mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
{
mStatus err;
- m->p->CFRunLoop = CFRunLoopGetCurrent();
char HINFO_SWstring[256] = "";
mDNSMacOSXSystemBuildNumber(HINFO_SWstring);
@@ -9997,13 +10469,6 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
if (err)
return err;
- DynamicStoreQueue = dispatch_queue_create("com.apple.mDNSResponder.DynamicStoreQueue", NULL);
- if (DynamicStoreQueue == NULL)
- {
- LogMsg("dispatch_queue_create: DynamicStoreQueue NULL!");
- return mStatus_NoMemoryErr;
- }
-
// Store mDNSResponder Platform
if (OSXVers)
{
@@ -10170,7 +10635,7 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
IOPMConnectionSetDispatchQueue(c, dispatch_get_main_queue());
LogInfo("IOPMConnectionSetDispatchQueue is now running");
#else
- iopmerr = IOPMConnectionScheduleWithRunLoop(c, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+ iopmerr = IOPMConnectionScheduleWithRunLoop(c, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
if (iopmerr) LogMsg("IOPMConnectionScheduleWithRunLoop failed %d", iopmerr);
LogInfo("IOPMConnectionScheduleWithRunLoop is now running");
#endif /* MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM */
@@ -10187,7 +10652,7 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
IONotificationPortSetDispatchQueue(m->p->PowerPortRef, dispatch_get_main_queue());
#else
- CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
+ CFRunLoopAddSource(CFRunLoopGetMain(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
#endif /* MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM */
}
}
@@ -10252,7 +10717,7 @@ mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
// We only initialize if mDNSCore successfully initialized.
if (D2DInitialize)
{
- D2DStatus ds = D2DInitialize(m->p->CFRunLoop, xD2DServiceCallback, m) ;
+ D2DStatus ds = D2DInitialize(CFRunLoopGetMain(), xD2DServiceCallback, m) ;
if (ds != kD2DSuccess)
LogMsg("D2DInitialiize failed: %d", ds);
else
@@ -10272,7 +10737,7 @@ mDNSexport void mDNSPlatformClose(mDNS *const m)
#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
IONotificationPortSetDispatchQueue(m->p->PowerPortRef, NULL);
#else
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
+ CFRunLoopRemoveSource(CFRunLoopGetMain(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
#endif
// According to <http://developer.apple.com/qa/qa2004/qa1340.html>, a single call
// to IORegisterForSystemPower creates *three* objects that need to be disposed individually:
@@ -10288,7 +10753,7 @@ mDNSexport void mDNSPlatformClose(mDNS *const m)
if (!SCDynamicStoreSetDispatchQueue(m->p->Store, NULL))
LogMsg("mDNSPlatformClose: SCDynamicStoreSetDispatchQueue failed");
#else
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode);
+ CFRunLoopRemoveSource(CFRunLoopGetMain(), m->p->StoreRLS, kCFRunLoopDefaultMode);
CFRunLoopSourceInvalidate(m->p->StoreRLS);
CFRelease(m->p->StoreRLS);
m->p->StoreRLS = NULL;
@@ -10299,7 +10764,7 @@ mDNSexport void mDNSPlatformClose(mDNS *const m)
if (m->p->PMRLS)
{
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->PMRLS, kCFRunLoopDefaultMode);
+ CFRunLoopRemoveSource(CFRunLoopGetMain(), m->p->PMRLS, kCFRunLoopDefaultMode);
CFRunLoopSourceInvalidate(m->p->PMRLS);
CFRelease(m->p->PMRLS);
m->p->PMRLS = NULL;
@@ -10338,8 +10803,7 @@ mDNSexport void mDNSPlatformClose(mDNS *const m)
if (AnonymousRacoonConfig)
{
AnonymousRacoonConfig = mDNSNULL;
- LogInfo("mDNSPlatformClose: Deconfiguring autotunnel");
- (void)mDNSConfigureServer(kmDNSDown, mDNSNULL, mDNSNULL);
+ LogInfo("mDNSPlatformClose: Deconfiguring autotunnel need not be done in mDNSResponder");
}
#endif // APPLE_OSX_mDNSResponder
}
@@ -10416,8 +10880,9 @@ mDNSexport mDNSs32 mDNSPlatformUTC(void)
// Locking is a no-op here, because we're single-threaded with a CFRunLoop, so we can never interrupt ourselves
mDNSexport void mDNSPlatformLock (const mDNS *const m) { (void)m; }
mDNSexport void mDNSPlatformUnlock (const mDNS *const m) { (void)m; }
-mDNSexport void mDNSPlatformStrCopy( void *dst, const void *src) { strcpy((char *)dst, (char *)src); }
-mDNSexport mDNSu32 mDNSPlatformStrLen ( const void *src) { return(strlen((char*)src)); }
+mDNSexport void mDNSPlatformStrCopy( void *dst, const void *src) { strcpy((char *)dst, (const char *)src); }
+mDNSexport mDNSu32 mDNSPlatformStrLCopy( void *dst, const void *src, mDNSu32 dstlen) { return (strlcpy((char *)dst, (const char *)src, dstlen)); }
+mDNSexport mDNSu32 mDNSPlatformStrLen ( const void *src) { return(strlen((const char*)src)); }
mDNSexport void mDNSPlatformMemCopy( void *dst, const void *src, mDNSu32 len) { memcpy(dst, src, len); }
mDNSexport mDNSBool mDNSPlatformMemSame(const void *dst, const void *src, mDNSu32 len) { return(memcmp(dst, src, len) == 0); }
mDNSexport int mDNSPlatformMemCmp(const void *dst, const void *src, mDNSu32 len) { return(memcmp(dst, src, len)); }
@@ -10513,6 +10978,11 @@ mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
if (InterfaceID == mDNSInterface_P2P)
return mDNStrue;
+ // mDNSInterface_BLE not considered a D2D interface for the purpose of this
+ // routine, since it's not implemented via a D2D plugin.
+ if (InterfaceID == mDNSInterface_BLE)
+ return mDNSfalse;
+
if ( (InterfaceID == mDNSInterface_Any)
|| (InterfaceID == mDNSInterfaceMark)
|| (InterfaceID == mDNSInterface_LocalOnly)
@@ -10536,18 +11006,18 @@ mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
// Filter records send over P2P (D2D) type interfaces
// Note that the terms P2P and D2D are used synonymously in the current code and comments.
-mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf)
+mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(const AuthRecord *rr, mDNSInterfaceID InterfaceID)
{
// For an explicit match to a valid interface ID, return true.
- if (rr->resrec.InterfaceID == intf->InterfaceID)
+ if (rr->resrec.InterfaceID == InterfaceID)
return mDNStrue;
// Only filtering records for D2D type interfaces, return true for all other interface types.
- if (!mDNSPlatformInterfaceIsD2D(intf->InterfaceID))
+ if (!mDNSPlatformInterfaceIsD2D(InterfaceID))
return mDNStrue;
// If it's an AWDL interface the record must be explicitly marked to include AWDL.
- if (intf->InterfaceID == AWDLInterfaceID)
+ if (InterfaceID == AWDLInterfaceID)
{
if (rr->ARType == AuthRecordAnyIncludeAWDL || rr->ARType == AuthRecordAnyIncludeAWDLandP2P)
return mDNStrue;
@@ -10600,11 +11070,7 @@ mDNSexport mDNSBool mDNSPlatformValidRecordForQuestion(const ResourceRecord *c
return mDNStrue;
if ((rr->InterfaceID == AWDLInterfaceID) && !(q->flags & kDNSServiceFlagsIncludeAWDL))
- {
- LogInfo("mDNSPlatformValidRecordForQuestion: Record recieved over AWDL not returned for %s %##s query",
- DNSTypeName(q->qtype), q->qname.c);
return mDNSfalse;
- }
return mDNStrue;
}
diff --git a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.h b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.h
index 56c0902a..20f7a321 100644
--- a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.h
+++ b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.h
@@ -31,6 +31,7 @@ extern "C" {
#include "mDNSEmbeddedAPI.h" // for domain name structure
#include <net/if.h>
+#include <os/log.h>
//#define MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
@@ -41,9 +42,7 @@ extern "C" {
#if TARGET_OS_EMBEDDED
#define NO_SECURITYFRAMEWORK 1
#define NO_CFUSERNOTIFICATION 1
-#include <MobileGestalt.h> // for IsAppleTV()
-#include <SystemConfiguration/scprefs_observer.h> // for _scprefs_observer_watch()
-extern mDNSBool GetmDNSManagedPref(CFStringRef key);
+#include <MobileGestalt.h> // for IsAppleTV()
#endif
#ifndef NO_SECURITYFRAMEWORK
@@ -51,8 +50,6 @@ extern mDNSBool GetmDNSManagedPref(CFStringRef key);
#include <Security/Security.h>
#endif /* NO_SECURITYFRAMEWORK */
-#define kmDNSResponderServName "com.apple.mDNSResponder"
-
enum mDNSDynamicStoreSetConfigKey
{
kmDNSMulticastConfig = 1,
@@ -177,7 +174,6 @@ struct mDNS_PlatformSupport_struct
mDNSs32 HostNameConflict; // Time we experienced conflict on our link-local host name
mDNSs32 KeyChainTimer;
- CFRunLoopRef CFRunLoop;
SCDynamicStoreRef Store;
CFRunLoopSourceRef StoreRLS;
CFRunLoopSourceRef PMRLS;
diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist b/mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist
index 8f7f77d9..ef23e4b6 100644
--- a/mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist
+++ b/mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist
@@ -10,6 +10,8 @@
<true/>
<key>com.apple.private.SCNetworkConnection-proxy-user</key>
<true/>
+ <key>com.apple.mDNSResponder_Helper</key>
+ <true/>
<key>com.apple.private.network.reserved-port</key>
<true/>
<key>com.apple.SystemConfiguration.SCDynamicStore-write-access</key>
@@ -24,5 +26,11 @@
<true/>
<key>com.apple.private.network.awdl.restricted</key>
<true/>
+ <key>com.apple.BTServer.allowRestrictedServices</key>
+ <true/>
+ <key>com.apple.BTServer.appleMfgDataAdvertising</key>
+ <true/>
+ <key>com.apple.BTServer.appleMfgDataScanner</key>
+ <true/>
</dict>
</plist>
diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder.sb b/mDNSResponder/mDNSMacOSX/mDNSResponder.sb
index 5c8eedd7..30747491 100644
--- a/mDNSResponder/mDNSMacOSX/mDNSResponder.sb
+++ b/mDNSResponder/mDNSMacOSX/mDNSResponder.sb
@@ -50,10 +50,12 @@
(global-name "com.apple.CoreServices.coreservicesd")
(global-name "com.apple.coreservices.quarantine-resolver")
(global-name "com.apple.distributed_notifications.2")
+ (global-name "com.apple.distributed_notifications@1v3")
(global-name "com.apple.lsd.mapdb")
(global-name "com.apple.ocspd")
(global-name "com.apple.PowerManagement.control")
(global-name "com.apple.mDNSResponderHelper")
+ (global-name "com.apple.mDNSResponder_Helper")
(global-name "com.apple.SecurityServer")
(global-name "com.apple.SystemConfiguration.configd")
(global-name "com.apple.SystemConfiguration.SCNetworkReachability")
@@ -110,7 +112,11 @@
(literal "/Library/Security/Trust Settings/Admin.plist")
(regex #"^/Library/Preferences/com\.apple\.security\.")
(literal "/Library/Preferences/SystemConfiguration/com.apple.PowerManagement.plist")
- (literal "/private/var/preferences/SystemConfiguration/preferences.plist"))
+ (literal "/private/var/preferences/SystemConfiguration/preferences.plist")
+ (subpath "/System/Library/Preferences/Logging")
+ (subpath "/AppleInternal/Library/Preferences/Logging")
+ (subpath "/Library/Preferences/Logging"))
+
; For MAC Address
(allow system-info (info-type "net.link.addr"))
@@ -122,12 +128,6 @@
(deny file-read-data (regex #"^/Library/Keychains/") (with no-log))
(allow file-read-data (literal "/Library/Keychains/System.keychain"))
-; Access to mDNSResponder Managed Preferences profile
-; instead of using (mobile-preferences-read "com.apple.mDNSResponder") we use the lines below for OSX compatibility
-(allow file-read* (literal "/private/var/Managed Preferences/mobile"))
-(allow file-read* (literal "/private/var/Library/Preferences/"))
-(allow file-read* (literal "/Library/Managed Preferences"))
-(allow file-read* (literal "/private/var/Managed Preferences/mobile/com.apple.mDNSResponder.plist"))
; Our Module Directory Services cache
(allow file-read-data
diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
index ef2fecbd..3e6c3fd7 100644
--- a/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
+++ b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
@@ -103,21 +103,12 @@
215FFAEE124000F900470DE1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
215FFAEF124000F900470DE1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
215FFAF0124000F900470DE1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
- 215FFAF1124000F900470DE1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
- 215FFAF2124000F900470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
- 215FFAF3124000F900470DE1 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
215FFAF41240011800470DE1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
215FFAF51240011800470DE1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
215FFAF61240011800470DE1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
- 215FFAF71240011800470DE1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
- 215FFAF81240011800470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
- 215FFAF91240011800470DE1 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
215FFAFA1240013400470DE1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
215FFAFB1240013400470DE1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
215FFAFC1240013400470DE1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
- 215FFAFD1240013400470DE1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
- 215FFAFE1240013400470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
- 215FFAFF1240013400470DE1 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
216D9ACE1720C9F5008066E1 /* uDNSPathEvalulation.c in Sources */ = {isa = PBXBuildFile; fileRef = 216D9ACD1720C9F5008066E1 /* uDNSPathEvalulation.c */; };
218E8E51156D8C0300720DA0 /* dnsproxy.c in Sources */ = {isa = PBXBuildFile; fileRef = 218E8E4F156D8C0300720DA0 /* dnsproxy.c */; };
218E8E53156D8C0300720DA0 /* dnsproxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 218E8E50156D8C0300720DA0 /* dnsproxy.h */; };
@@ -133,15 +124,22 @@
21F51DC11B3541940070B05C /* com.apple.mDNSResponder.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 21F51DBF1B35412D0070B05C /* com.apple.mDNSResponder.plist */; };
21F51DC31B3541F50070B05C /* com.apple.mDNSResponderHelper.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 21F51DBE1B3541030070B05C /* com.apple.mDNSResponderHelper.plist */; };
21F51DC51B3542210070B05C /* com.apple.dnsextd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 21F51DBD1B3540DB0070B05C /* com.apple.dnsextd.plist */; };
+ 222A3C5B1C1B75F2003A6FFD /* DNSServiceDiscoveryDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 222A3C581C1B743B003A6FFD /* DNSServiceDiscoveryDefines.h */; };
+ 222A3C6A1C1B7777003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; };
+ 222A3C6B1C1B7778003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; };
+ 222A3C6C1C1B7779003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; };
+ 222A3C6D1C1B777A003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; };
+ 222A3C6E1C1B777B003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; };
+ 222A3C6F1C1B777C003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; };
+ 2243AE391C90AECF0079023E /* CoreBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2243AE381C90AECF0079023E /* CoreBluetooth.framework */; };
+ 22448EA31C90A7BE004F25CC /* BLE.c in Sources */ = {isa = PBXBuildFile; fileRef = 22448EA11C90A7B5004F25CC /* BLE.c */; };
+ 22448EA41C90A7CB004F25CC /* BLE.h in Headers */ = {isa = PBXBuildFile; fileRef = 22448EA21C90A7B5004F25CC /* BLE.h */; };
+ 22448EA71C90A837004F25CC /* coreBLE.h in Headers */ = {isa = PBXBuildFile; fileRef = 22448EA51C90A82D004F25CC /* coreBLE.h */; };
+ 227687F31C90AD580019382D /* coreBLE.m in Sources */ = {isa = PBXBuildFile; fileRef = 22448EA61C90A82D004F25CC /* coreBLE.m */; };
2E0405F50C3195F700F13B59 /* helper.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405F40C3195F700F13B59 /* helper.c */; };
- 2E0405F60C31961100F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; settings = {ATTRIBUTES = (Client, Server, ); COMPILER_FLAGS = "-Wno-error"; }; };
2E0406150C3197CB00F13B59 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E0406140C3197CB00F13B59 /* libbsm.dylib */; };
- 2E04061F0C3198B700F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; };
2E04070A0C31EEEC00F13B59 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
2E04070B0C31EEEC00F13B59 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; };
- 2E3552900C3A95C100CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; };
- 2E3552920C3A95C100CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; };
- 2E35529D0C3A9E7600CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; };
2E35529E0C3A9E7600CA1CB7 /* helper-stubs.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */; };
2E35529F0C3A9E7600CA1CB7 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
2E4D9B050C38C19500480551 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
@@ -152,35 +150,39 @@
2E96A51D0C39BDAC0087C4D2 /* helper-main.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0406CA0C31E9AD00F13B59 /* helper-main.c */; };
2E96A5260C39BE480087C4D2 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
2E96A5320C39C1A50087C4D2 /* helper-stubs.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */; };
- 2EAE955A0C31F4D30021F738 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; };
2EC8F8EC0C39CCAC003C9C48 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
2ECC11A60C4FEC3800CB1885 /* helpermsg-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */; };
2ECC11A80C4FEC3800CB1885 /* helpermsg-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */; };
2EDC5E730C39EA640092701B /* helper-server.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EDC5E720C39EA640092701B /* helper-server.h */; };
2EDC5E750C39EA640092701B /* helper-server.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EDC5E720C39EA640092701B /* helper-server.h */; };
+ 371D0FBC1BF545FA00E5DB26 /* InterfaceTest.c in Sources */ = {isa = PBXBuildFile; fileRef = 371D0FBA1BF545FA00E5DB26 /* InterfaceTest.c */; };
+ 371D0FBF1BF666EB00E5DB26 /* ResourceRecordTest.c in Sources */ = {isa = PBXBuildFile; fileRef = 371D0FBD1BF666EB00E5DB26 /* ResourceRecordTest.c */; };
+ 373202101BAB4444007DE806 /* DNSMessageTest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3732020F1BAB4349007DE806 /* DNSMessageTest.c */; };
+ 3771F67D1BA387DD0072355E /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 37DDE9351BA386E70092AC61 /* main.c */; };
+ 37DDE9331BA383D30092AC61 /* unittest.c in Sources */ = {isa = PBXBuildFile; fileRef = 37DDE9271BA3825C0092AC61 /* unittest.c */; };
+ 37FEBD581BC789AA00638EA4 /* DNSCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F60587CEF6001880B3 /* DNSCommon.c */; };
4A7B9E8014FDA25000B84CC1 /* mDNSResponder.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A7B9E7E14FDA1BB00B84CC1 /* mDNSResponder.plist */; };
4A7B9E8214FDA26C00B84CC1 /* mDNSResponder.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A7B9E7C14FDA19F00B84CC1 /* mDNSResponder.txt */; };
4AAE0C9A0C68EA81003882A5 /* mDNSResponderHelper.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */; };
4BD2B63A134FE09F002B96D5 /* P2PPacketFilter.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BD2B638134FE09F002B96D5 /* P2PPacketFilter.c */; };
4BD2B63B134FE09F002B96D5 /* P2PPacketFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BD2B639134FE09F002B96D5 /* P2PPacketFilter.h */; };
+ 729DF4601CD40630005ECF70 /* com.apple.mDNSResponder.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 729DF45F1CD40630005ECF70 /* com.apple.mDNSResponder.plist */; };
72FB5467166D5FCA0090B2D9 /* dnsctl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72FB545A166D5F960090B2D9 /* dnsctl.c */; };
8415A6571897109000BDBA26 /* libdns_services.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8415A6561897109000BDBA26 /* libdns_services.dylib */; };
- 8418673E15AB8C2D00BB7F70 /* com.apple.networking.mDNSResponder in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8418673A15AB8B6900BB7F70 /* com.apple.networking.mDNSResponder */; };
+ 8417375C1B967D37000CD5C2 /* dnsctl_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 8417375A1B967CBE000CD5C2 /* dnsctl_server.c */; };
848DA5C7165477E000D2E8B4 /* xpc_services.c in Sources */ = {isa = PBXBuildFile; fileRef = 848DA5C6165477E000D2E8B4 /* xpc_services.c */; };
848DA5CA165477EB00D2E8B4 /* xpc_services.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DA5C9165477EB00D2E8B4 /* xpc_services.h */; };
848DA5D616547F7200D2E8B4 /* dns_xpc.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DA5D516547F7200D2E8B4 /* dns_xpc.h */; };
84C5B33C166553F100C324A8 /* dns_services.c in Sources */ = {isa = PBXBuildFile; fileRef = 84C5B339166553AF00C324A8 /* dns_services.c */; };
84F4C090188F050200D1E1DE /* dns_services.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F4C08F188F04CF00D1E1DE /* dns_services.h */; settings = {ATTRIBUTES = (Private, ); }; };
BD03E88D1AD31278005E8A81 /* SymptomReporter.c in Sources */ = {isa = PBXBuildFile; fileRef = BD03E88C1AD31278005E8A81 /* SymptomReporter.c */; };
- BD2806081C40775600455151 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BD2806071C40775600455151 /* Foundation.framework */; };
- BD64FE9C1C40762F0040EAB3 /* Metrics.h in Headers */ = {isa = PBXBuildFile; fileRef = BD64FE9A1C40762F0040EAB3 /* Metrics.h */; };
- BD64FE9D1C40762F0040EAB3 /* Metrics.m in Sources */ = {isa = PBXBuildFile; fileRef = BD64FE9B1C40762F0040EAB3 /* Metrics.m */; };
+ BDA3F08A1C48DB920054FB4B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDA3F0891C48DB910054FB4B /* Foundation.framework */; };
+ BDA3F08D1C48DBEA0054FB4B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDA3F0891C48DB910054FB4B /* Foundation.framework */; };
+ BDA3F08E1C48DCA50054FB4B /* Metrics.h in Headers */ = {isa = PBXBuildFile; fileRef = BDA3F0871C48DB6D0054FB4B /* Metrics.h */; };
+ BDA3F08F1C48DCA50054FB4B /* Metrics.m in Sources */ = {isa = PBXBuildFile; fileRef = BDA3F0881C48DB6D0054FB4B /* Metrics.m */; };
BDA9A7881B3A924C00523835 /* dns_sd_private.h in Headers */ = {isa = PBXBuildFile; fileRef = BDA9A7871B3A923600523835 /* dns_sd_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
BDA9A7891B3A92A500523835 /* dns_sd_private.h in Headers */ = {isa = PBXBuildFile; fileRef = BDA9A7871B3A923600523835 /* dns_sd_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
- D284BE530ADD80740027CCDF /* DNSServiceDiscoveryDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */; };
D284BE540ADD80740027CCDF /* dnssd_ipc.h in Headers */ = {isa = PBXBuildFile; fileRef = F5E11B5B04A28126019798ED /* dnssd_ipc.h */; };
- D284BE560ADD80740027CCDF /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Client, ); }; };
- D284BE570ADD80740027CCDF /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; settings = {ATTRIBUTES = (Server, ); }; };
D284BE580ADD80740027CCDF /* mDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBE9022EAF5A00000109 /* mDNS.c */; };
D284BE590ADD80740027CCDF /* uDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F70587CEF6001880B3 /* uDNS.c */; };
D284BE5A0ADD80740027CCDF /* DNSCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F60587CEF6001880B3 /* DNSCommon.c */; };
@@ -216,7 +218,6 @@
D284BED20ADD80A20027CCDF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
D284BED50ADD80A20027CCDF /* dnsextd.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FFF4F63A06CFE4DD00459EFD /* dnsextd.8 */; };
D284BEDE0ADD80A70027CCDF /* ddnswriteconfig.m in Sources */ = {isa = PBXBuildFile; fileRef = FFFB0DAF07B43CBA00B88D48 /* ddnswriteconfig.m */; };
- D284BEE00ADD80A70027CCDF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FFFB0DB407B43D2700B88D48 /* Foundation.framework */; };
D284BEE10ADD80A70027CCDF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
D284BEE20ADD80A70027CCDF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; };
D284BEE30ADD80A70027CCDF /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
@@ -241,23 +242,15 @@
D284BF040ADD80B00027CCDF /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF2609FA07B4433800CE10E5 /* Cocoa.framework */; };
D284BF050ADD80B00027CCDF /* PreferencePanes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF260A1F07B4436900CE10E5 /* PreferencePanes.framework */; };
D284BF060ADD80B00027CCDF /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
+ FF3C72AA1CE3E62200CDF81E /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FF3C72A91CE3E62200CDF81E /* libicucore.dylib */; };
FFA572330AF18F1C0055A0F1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
FFA572340AF18F1C0055A0F1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
FFA572350AF18F1C0055A0F1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
FFA5723F0AF18F450055A0F1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
FFA572400AF18F450055A0F1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
FFA572410AF18F450055A0F1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
- FFA572490AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
- FFA5724A0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
- FFA5724B0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
FFAE66F0105F0CD900162116 /* ddnswriteconfig in Resources */ = {isa = PBXBuildFile; fileRef = D284BEE80ADD80A70027CCDF /* ddnswriteconfig */; };
FFB437150EB165BD00E17C68 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CA213D02786FC30CCA2C71 /* IOKit.framework */; };
- FFC22AA20B00F42A00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
- FFC22AA30B00F42B00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
- FFC22AA40B00F42C00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
- FFC22AA50B00F43000BAB070 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
- FFC22AA60B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
- FFC22AA70B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
FFD52A9E1AF858DD00CAD3EC /* CryptoAlg.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F4B145B2AE100939099 /* CryptoAlg.h */; };
FFF589B70E37F66800EF515C /* ClientCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FF5852100DD27BD300862BDF /* ClientCommon.c */; };
FFF589C10E37F67E00EF515C /* ClientCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FF5852100DD27BD300862BDF /* ClientCommon.c */; };
@@ -528,10 +521,10 @@
8418673D15AB8BFF00BB7F70 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
- dstPath = /private/etc/asl/;
+ dstPath = /System/Library/Preferences/Logging/Subsystems;
dstSubfolderSpec = 0;
files = (
- 8418673E15AB8C2D00BB7F70 /* com.apple.networking.mDNSResponder in CopyFiles */,
+ 729DF4601CD40630005ECF70 /* com.apple.mDNSResponder.plist in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
@@ -610,17 +603,35 @@
21F51DBD1B3540DB0070B05C /* com.apple.dnsextd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.dnsextd.plist; sourceTree = "<group>"; };
21F51DBE1B3541030070B05C /* com.apple.mDNSResponderHelper.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.mDNSResponderHelper.plist; sourceTree = "<group>"; };
21F51DBF1B35412D0070B05C /* com.apple.mDNSResponder.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.mDNSResponder.plist; sourceTree = "<group>"; };
- 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.mig; path = helpermsg.defs; sourceTree = "<group>"; };
+ 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DNSServiceDiscovery.c; sourceTree = "<group>"; };
+ 222A3C571C1B743B003A6FFD /* DNSServiceDiscovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscovery.h; sourceTree = "<group>"; };
+ 222A3C581C1B743B003A6FFD /* DNSServiceDiscoveryDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscoveryDefines.h; sourceTree = "<group>"; };
+ 2243AE381C90AECF0079023E /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = System/Library/Frameworks/CoreBluetooth.framework; sourceTree = SDKROOT; };
+ 22448EA11C90A7B5004F25CC /* BLE.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BLE.c; sourceTree = "<group>"; };
+ 22448EA21C90A7B5004F25CC /* BLE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BLE.h; sourceTree = "<group>"; };
+ 22448EA51C90A82D004F25CC /* coreBLE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coreBLE.h; sourceTree = "<group>"; };
+ 22448EA61C90A82D004F25CC /* coreBLE.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = coreBLE.m; sourceTree = "<group>"; };
2E0405F00C31955500F13B59 /* mDNSResponderHelper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mDNSResponderHelper; sourceTree = BUILT_PRODUCTS_DIR; };
2E0405F40C3195F700F13B59 /* helper.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = helper.c; sourceTree = "<group>"; };
2E0406140C3197CB00F13B59 /* libbsm.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbsm.dylib; path = /usr/lib/libbsm.dylib; sourceTree = "<absolute>"; };
2E0406CA0C31E9AD00F13B59 /* helper-main.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "helper-main.c"; sourceTree = "<group>"; };
- 2E35528F0C3A95C100CA1CB7 /* helper-error.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "helper-error.h"; sourceTree = "<group>"; };
2E8165F60C59835F00485EB2 /* libipsec.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libipsec.dylib; path = /usr/lib/libipsec.dylib; sourceTree = "<absolute>"; };
2E96A5250C39BE480087C4D2 /* helper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = helper.h; sourceTree = "<group>"; };
2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "helper-stubs.c"; sourceTree = "<group>"; };
2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "helpermsg-types.h"; sourceTree = "<group>"; };
2EDC5E720C39EA640092701B /* helper-server.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "helper-server.h"; sourceTree = "<group>"; };
+ 371D0FBA1BF545FA00E5DB26 /* InterfaceTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = InterfaceTest.c; path = ../unittests/InterfaceTest.c; sourceTree = "<group>"; };
+ 371D0FBB1BF545FA00E5DB26 /* InterfaceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InterfaceTest.h; path = ../unittests/InterfaceTest.h; sourceTree = "<group>"; };
+ 371D0FBD1BF666EB00E5DB26 /* ResourceRecordTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ResourceRecordTest.c; path = ../unittests/ResourceRecordTest.c; sourceTree = "<group>"; };
+ 371D0FBE1BF666EB00E5DB26 /* ResourceRecordTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResourceRecordTest.h; path = ../unittests/ResourceRecordTest.h; sourceTree = "<group>"; };
+ 3732020F1BAB4349007DE806 /* DNSMessageTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = DNSMessageTest.c; path = ../unittests/DNSMessageTest.c; sourceTree = "<group>"; };
+ 373202111BAB63E8007DE806 /* DNSMessageTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DNSMessageTest.h; path = ../unittests/DNSMessageTest.h; sourceTree = "<group>"; };
+ 37AF802A1BF699AF00D657F6 /* DomainNameTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = DomainNameTest.c; path = ../unittests/DomainNameTest.c; sourceTree = "<group>"; };
+ 37AF802B1BF699AF00D657F6 /* DomainNameTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DomainNameTest.h; path = ../unittests/DomainNameTest.h; sourceTree = "<group>"; };
+ 37DDE9271BA3825C0092AC61 /* unittest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = unittest.c; path = ../unittests/unittest.c; sourceTree = "<group>"; };
+ 37DDE9281BA382670092AC61 /* unittest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = unittest.h; path = ../unittests/unittest.h; sourceTree = "<group>"; };
+ 37DDE92D1BA383610092AC61 /* unittests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = unittests; sourceTree = BUILT_PRODUCTS_DIR; };
+ 37DDE9351BA386E70092AC61 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = ../unittests/main.c; sourceTree = "<group>"; };
4A2E69DD0F5475A3004A87B0 /* uds_daemon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = uds_daemon.h; path = ../mDNSShared/uds_daemon.h; sourceTree = SOURCE_ROOT; };
4A3600DF0F34F8CD00453EFB /* DeviceToDeviceManager.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DeviceToDeviceManager.framework; path = /System/Library/PrivateFrameworks/DeviceToDeviceManager.framework; sourceTree = "<absolute>"; };
4A7B9E7C14FDA19F00B84CC1 /* mDNSResponder.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = mDNSResponder.txt; sourceTree = "<group>"; };
@@ -635,12 +646,10 @@
654BE64F02B63B93000001D1 /* mDNSEmbeddedAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mDNSEmbeddedAPI.h; path = ../mDNSCore/mDNSEmbeddedAPI.h; sourceTree = "<group>"; };
654BE65002B63B93000001D1 /* mDNSDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mDNSDebug.h; path = ../mDNSCore/mDNSDebug.h; sourceTree = "<group>"; };
65713D46025A293200000109 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = /System/Library/Frameworks/SystemConfiguration.framework; sourceTree = "<absolute>"; };
- 6575FBE9022EAF5A00000109 /* mDNS.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; name = mDNS.c; path = ../mDNSCore/mDNS.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
- 6575FBEB022EAF7200000109 /* mDNSMacOSX.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = mDNSMacOSX.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
- 6575FBEC022EAF7200000109 /* daemon.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = daemon.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
- 6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscoveryDefines.h; sourceTree = "<group>"; };
- 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = DNSServiceDiscoveryReply.defs; sourceTree = "<group>"; };
- 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = DNSServiceDiscoveryRequest.defs; sourceTree = "<group>"; };
+ 6575FBE9022EAF5A00000109 /* mDNS.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; name = mDNS.c; path = ../mDNSCore/mDNS.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+ 6575FBEB022EAF7200000109 /* mDNSMacOSX.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = mDNSMacOSX.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+ 6575FBEC022EAF7200000109 /* daemon.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = daemon.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
+ 729DF45F1CD40630005ECF70 /* com.apple.mDNSResponder.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = com.apple.mDNSResponder.plist; path = Private/com.apple.mDNSResponder.plist; sourceTree = "<group>"; };
72FB545A166D5F960090B2D9 /* dnsctl.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = dnsctl.c; path = ../Clients/dnsctl.c; sourceTree = "<group>"; };
72FB545F166D5FB00090B2D9 /* dnsctl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dnsctl; sourceTree = BUILT_PRODUCTS_DIR; };
7F18A9F60587CEF6001880B3 /* DNSCommon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = DNSCommon.c; path = ../mDNSCore/DNSCommon.c; sourceTree = SOURCE_ROOT; };
@@ -649,8 +658,7 @@
7F869685066EE02400D2A2DC /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = "<absolute>"; };
7FC8F9D406D14E66007E879D /* LegacyNATTraversal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = LegacyNATTraversal.c; sourceTree = SOURCE_ROOT; };
8415A6561897109000BDBA26 /* libdns_services.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libdns_services.dylib; path = /usr/lib/libdns_services.dylib; sourceTree = "<absolute>"; };
- 8418673A15AB8B6900BB7F70 /* com.apple.networking.mDNSResponder */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.networking.mDNSResponder; sourceTree = "<group>"; };
- 8418673C15AB8B8000BB7F70 /* mDNSResponderLogging.mobileconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = mDNSResponderLogging.mobileconfig; sourceTree = "<group>"; };
+ 8417375A1B967CBE000CD5C2 /* dnsctl_server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnsctl_server.c; path = Private/dnsctl_server.c; sourceTree = "<group>"; };
848DA5C6165477E000D2E8B4 /* xpc_services.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xpc_services.c; path = Private/xpc_services.c; sourceTree = "<group>"; };
848DA5C9165477EB00D2E8B4 /* xpc_services.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xpc_services.h; path = Private/xpc_services.h; sourceTree = "<group>"; };
848DA5D516547F7200D2E8B4 /* dns_xpc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_xpc.h; path = Private/dns_xpc.h; sourceTree = "<group>"; };
@@ -658,10 +666,9 @@
84C5B339166553AF00C324A8 /* dns_services.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = dns_services.c; path = Private/dns_services.c; sourceTree = "<group>"; };
84F4C08F188F04CF00D1E1DE /* dns_services.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_services.h; path = Private/dns_services.h; sourceTree = "<group>"; };
BD03E88C1AD31278005E8A81 /* SymptomReporter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SymptomReporter.c; sourceTree = "<group>"; };
- BD2806071C40775600455151 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
- BD64FE9A1C40762F0040EAB3 /* Metrics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Metrics.h; sourceTree = "<group>"; };
- BD64FE9B1C40762F0040EAB3 /* Metrics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Metrics.m; sourceTree = "<group>"; };
- BD64FE9E1C4076B40040EAB3 /* WirelessDiagnostics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WirelessDiagnostics.framework; path = System/Library/PrivateFrameworks/WirelessDiagnostics.framework; sourceTree = SDKROOT; };
+ BDA3F0871C48DB6D0054FB4B /* Metrics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Metrics.h; sourceTree = "<group>"; };
+ BDA3F0881C48DB6D0054FB4B /* Metrics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Metrics.m; sourceTree = "<group>"; };
+ BDA3F0891C48DB910054FB4B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
BDA9A7871B3A923600523835 /* dns_sd_private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dns_sd_private.h; path = Private/dns_sd_private.h; sourceTree = "<group>"; };
D284BE730ADD80740027CCDF /* mDNSResponder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mDNSResponder; sourceTree = BUILT_PRODUCTS_DIR; };
D284BEB00ADD80920027CCDF /* dns-sd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "dns-sd"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -685,14 +692,14 @@
DB2CC4680662DFF500335AB3 /* JavaVM.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaVM.framework; path = /System/Library/Frameworks/JavaVM.framework; sourceTree = "<absolute>"; };
DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mDNSDebug.c; path = ../mDNSShared/mDNSDebug.c; sourceTree = SOURCE_ROOT; };
DBAAFE2C057E8F660085CAD0 /* GenLinkedList.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GenLinkedList.c; path = ../mDNSShared/GenLinkedList.c; sourceTree = SOURCE_ROOT; };
- F525E72804AA167501F1CF4D /* uds_daemon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = uds_daemon.c; path = ../mDNSShared/uds_daemon.c; sourceTree = SOURCE_ROOT; };
+ F525E72804AA167501F1CF4D /* uds_daemon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = uds_daemon.c; path = ../mDNSShared/uds_daemon.c; sourceTree = SOURCE_ROOT; usesTabs = 0; };
F5E11B5A04A28126019798ED /* dnssd_ipc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnssd_ipc.c; path = ../mDNSShared/dnssd_ipc.c; sourceTree = SOURCE_ROOT; };
F5E11B5B04A28126019798ED /* dnssd_ipc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dnssd_ipc.h; path = ../mDNSShared/dnssd_ipc.h; sourceTree = SOURCE_ROOT; };
FF08480607CEB8E800AE6769 /* inprogress.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = inprogress.tiff; path = PreferencePane/Artwork/inprogress.tiff; sourceTree = SOURCE_ROOT; };
FF13FFEA0A5DA44A00897C81 /* dnsextd_lexer.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; name = dnsextd_lexer.l; path = ../mDNSShared/dnsextd_lexer.l; sourceTree = SOURCE_ROOT; };
FF13FFEC0A5DA45500897C81 /* dnsextd_parser.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; name = dnsextd_parser.y; path = ../mDNSShared/dnsextd_parser.y; sourceTree = SOURCE_ROOT; };
FF1C919D07021D77001048AB /* dns-sd.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = "dns-sd.1"; path = "../mDNSShared/dns-sd.1"; sourceTree = SOURCE_ROOT; };
- FF1C919F07021E3F001048AB /* dns-sd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "dns-sd.c"; path = "../Clients/dns-sd.c"; sourceTree = SOURCE_ROOT; };
+ FF1C919F07021E3F001048AB /* dns-sd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "dns-sd.c"; path = "../Clients/dns-sd.c"; sourceTree = SOURCE_ROOT; usesTabs = 0; };
FF25794606C9A8BF00376F7B /* dnsextd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnsextd.c; path = ../mDNSShared/dnsextd.c; sourceTree = SOURCE_ROOT; };
FF2609FA07B4433800CE10E5 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
FF260A1F07B4436900CE10E5 /* PreferencePanes.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PreferencePanes.framework; path = /System/Library/Frameworks/PreferencePanes.framework; sourceTree = "<absolute>"; };
@@ -710,14 +717,13 @@
FF2C5FB00A48B8680066DA11 /* DNSSDRecordRegistrar.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSSDRecordRegistrar.java; path = ../mDNSShared/Java/DNSSDRecordRegistrar.java; sourceTree = SOURCE_ROOT; };
FF2C5FB20A48B86E0066DA11 /* RegisterRecordListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = RegisterRecordListener.java; path = ../mDNSShared/Java/RegisterRecordListener.java; sourceTree = SOURCE_ROOT; };
FF354EB108516C63007C00E1 /* installtool */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; name = installtool; path = PreferencePane/installtool; sourceTree = SOURCE_ROOT; };
+ FF3C72A91CE3E62200CDF81E /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.Internal.sdk/usr/lib/libicucore.dylib; sourceTree = DEVELOPER_DIR; };
FF485D5105632E0000130380 /* mDNSResponder.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = mDNSResponder.8; path = ../mDNSShared/mDNSResponder.8; sourceTree = SOURCE_ROOT; };
FF5852100DD27BD300862BDF /* ClientCommon.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ClientCommon.c; path = ../Clients/ClientCommon.c; sourceTree = SOURCE_ROOT; };
FF85880B0BD599F40080D89F /* mDNSResponder.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mDNSResponder.sb; sourceTree = SOURCE_ROOT; };
FFA572390AF18F1C0055A0F1 /* libsystem_dnssd_debug.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_dnssd_debug.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
FFA572450AF18F450055A0F1 /* libsystem_dnssd_profile.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_dnssd_profile.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
- FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DNSServiceDiscovery.c; sourceTree = "<group>"; };
- FFA572600AF1908D0055A0F1 /* DNSServiceDiscovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscovery.h; sourceTree = "<group>"; };
- FFA572630AF190C20055A0F1 /* dns_sd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_sd.h; path = ../mDNSShared/dns_sd.h; sourceTree = SOURCE_ROOT; };
+ FFA572630AF190C20055A0F1 /* dns_sd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_sd.h; path = ../mDNSShared/dns_sd.h; sourceTree = SOURCE_ROOT; usesTabs = 0; };
FFB765840AEED9C700583A2C /* libsystem_dnssd.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_dnssd.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
FFCB6D73075D539900B8AF62 /* PlatformCommon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = PlatformCommon.c; path = ../mDNSShared/PlatformCommon.c; sourceTree = SOURCE_ROOT; };
FFE6935007C2CA7F00283007 /* ConfigurationAuthority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConfigurationAuthority.h; path = PreferencePane/ConfigurationAuthority.h; sourceTree = SOURCE_ROOT; };
@@ -730,7 +736,6 @@
FFFB0DAD07B43CBA00B88D48 /* PrivilegedOperations.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = PrivilegedOperations.c; sourceTree = "<group>"; };
FFFB0DAE07B43CBA00B88D48 /* ConfigurationAuthority.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ConfigurationAuthority.c; sourceTree = "<group>"; };
FFFB0DAF07B43CBA00B88D48 /* ddnswriteconfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ddnswriteconfig.m; sourceTree = "<group>"; };
- FFFB0DB407B43D2700B88D48 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
FFFF8F800C3307AC00722979 /* dnsextd.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dnsextd.conf; path = ../mDNSShared/dnsextd.conf; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
@@ -776,6 +781,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 37DDE92A1BA383610092AC61 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
72FB545C166D5FB00090B2D9 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -795,8 +807,10 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 2243AE391C90AECF0079023E /* CoreBluetooth.framework in Frameworks */,
D284BE650ADD80740027CCDF /* CoreFoundation.framework in Frameworks */,
- BD2806081C40775600455151 /* Foundation.framework in Frameworks */,
+ FF3C72AA1CE3E62200CDF81E /* libicucore.dylib in Frameworks */,
+ BDA3F08A1C48DB920054FB4B /* Foundation.framework in Frameworks */,
D284BE670ADD80740027CCDF /* IOKit.framework in Frameworks */,
D284BE680ADD80740027CCDF /* Security.framework in Frameworks */,
D284BE660ADD80740027CCDF /* SystemConfiguration.framework in Frameworks */,
@@ -835,7 +849,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- D284BEE00ADD80A70027CCDF /* Foundation.framework in Frameworks */,
+ BDA3F08D1C48DBEA0054FB4B /* Foundation.framework in Frameworks */,
D284BEE10ADD80A70027CCDF /* Security.framework in Frameworks */,
D284BEE20ADD80A70027CCDF /* SystemConfiguration.framework in Frameworks */,
D284BEE30ADD80A70027CCDF /* CoreFoundation.framework in Frameworks */,
@@ -881,14 +895,16 @@
08FB7794FE84155DC02AAC07 /* mDNSResponder */ = {
isa = PBXGroup;
children = (
+ 2243AE381C90AECF0079023E /* CoreBluetooth.framework */,
+ 729DF45F1CD40630005ECF70 /* com.apple.mDNSResponder.plist */,
08FB7795FE84155DC02AAC07 /* mDNS Server Sources */,
6575FC1F022EB78C00000109 /* Command-Line Clients */,
213FB20912028902002B3A08 /* Bonjour Events Plugin */,
- 6575FBFE022EAFA800000109 /* MIG files */,
DB2CC4420662DCE500335AB3 /* Java Support */,
FFFB0DA407B43BED00B88D48 /* PreferencePane */,
08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
19C28FBDFE9D53C911CA2CBB /* Products */,
+ 37DDE9241BA382280092AC61 /* Unit Tests */,
);
name = mDNSResponder;
sourceTree = "<group>";
@@ -896,12 +912,18 @@
08FB7795FE84155DC02AAC07 /* mDNS Server Sources */ = {
isa = PBXGroup;
children = (
+ 22448EA51C90A82D004F25CC /* coreBLE.h */,
+ 22448EA61C90A82D004F25CC /* coreBLE.m */,
+ 22448EA11C90A7B5004F25CC /* BLE.c */,
+ 22448EA21C90A7B5004F25CC /* BLE.h */,
+ 222A3C571C1B743B003A6FFD /* DNSServiceDiscovery.h */,
+ 222A3C581C1B743B003A6FFD /* DNSServiceDiscoveryDefines.h */,
+ 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */,
21DD8FBD161E9A250033C8F8 /* anonymous.c */,
21DD8FBE161E9A250033C8F8 /* anonymous.h */,
21F51DBD1B3540DB0070B05C /* com.apple.dnsextd.plist */,
21F51DBF1B35412D0070B05C /* com.apple.mDNSResponder.plist */,
21F51DBE1B3541030070B05C /* com.apple.mDNSResponderHelper.plist */,
- 8418673A15AB8B6900BB7F70 /* com.apple.networking.mDNSResponder */,
21A57F4A145B2AE100939099 /* CryptoAlg.c */,
21A57F4B145B2AE100939099 /* CryptoAlg.h */,
21A57F51145B2B1400939099 /* CryptoSupport.c */,
@@ -930,11 +952,8 @@
2124FA2F1471E9B50021D7BB /* dnssec.h */,
21070E5D16486B9000A69507 /* DNSSECSupport.c */,
21070E5E16486B9000A69507 /* DNSSECSupport.h */,
- FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */,
- FFA572600AF1908D0055A0F1 /* DNSServiceDiscovery.h */,
DBAAFE2C057E8F660085CAD0 /* GenLinkedList.c */,
4ADB5F230F6AB9F400B95BF3 /* helper-entitlements.plist */,
- 2E35528F0C3A95C100CA1CB7 /* helper-error.h */,
2E0406CA0C31E9AD00F13B59 /* helper-main.c */,
2EDC5E720C39EA640092701B /* helper-server.h */,
2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */,
@@ -955,9 +974,8 @@
FF85880B0BD599F40080D89F /* mDNSResponder.sb */,
4A7B9E7C14FDA19F00B84CC1 /* mDNSResponder.txt */,
4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */,
- 8418673C15AB8B8000BB7F70 /* mDNSResponderLogging.mobileconfig */,
- BD64FE9A1C40762F0040EAB3 /* Metrics.h */,
- BD64FE9B1C40762F0040EAB3 /* Metrics.m */,
+ BDA3F0871C48DB6D0054FB4B /* Metrics.h */,
+ BDA3F0881C48DB6D0054FB4B /* Metrics.m */,
2124FA321471E9DE0021D7BB /* nsec.c */,
2124FA2B1471E98C0021D7BB /* nsec.h */,
2127A47515C3C7B900A857FC /* nsec3.c */,
@@ -971,6 +989,7 @@
216D9ACD1720C9F5008066E1 /* uDNSPathEvalulation.c */,
F525E72804AA167501F1CF4D /* uds_daemon.c */,
4A2E69DD0F5475A3004A87B0 /* uds_daemon.h */,
+ 8417375A1B967CBE000CD5C2 /* dnsctl_server.c */,
848DA5C6165477E000D2E8B4 /* xpc_services.c */,
848DA5C9165477EB00D2E8B4 /* xpc_services.h */,
);
@@ -983,19 +1002,18 @@
FF2609FA07B4433800CE10E5 /* Cocoa.framework */,
09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */,
4A3600DF0F34F8CD00453EFB /* DeviceToDeviceManager.framework */,
- FFFB0DB407B43D2700B88D48 /* Foundation.framework */,
- BD2806071C40775600455151 /* Foundation.framework */,
+ BDA3F0891C48DB910054FB4B /* Foundation.framework */,
00CA213D02786FC30CCA2C71 /* IOKit.framework */,
DB2CC4680662DFF500335AB3 /* JavaVM.framework */,
2E0406140C3197CB00F13B59 /* libbsm.dylib */,
8415A6561897109000BDBA26 /* libdns_services.dylib */,
2E8165F60C59835F00485EB2 /* libipsec.dylib */,
219D5541149ED645004464AE /* libxml2.dylib */,
+ FF3C72A91CE3E62200CDF81E /* libicucore.dylib */,
FF260A1F07B4436900CE10E5 /* PreferencePanes.framework */,
7F869685066EE02400D2A2DC /* Security.framework */,
65713D46025A293200000109 /* SystemConfiguration.framework */,
21F432971134AA6800581B69 /* WebFilterDNS.framework */,
- BD64FE9E1C4076B40040EAB3 /* WirelessDiagnostics.framework */,
);
name = "External Frameworks and Libraries";
sourceTree = "<group>";
@@ -1019,6 +1037,7 @@
FFA572450AF18F450055A0F1 /* libsystem_dnssd_profile.dylib */,
D284BE730ADD80740027CCDF /* mDNSResponder */,
2E0405F00C31955500F13B59 /* mDNSResponderHelper */,
+ 37DDE92D1BA383610092AC61 /* unittests */,
);
name = Products;
sourceTree = "<group>";
@@ -1032,15 +1051,22 @@
name = "Bonjour Events Plugin";
sourceTree = "<group>";
};
- 6575FBFE022EAFA800000109 /* MIG files */ = {
+ 37DDE9241BA382280092AC61 /* Unit Tests */ = {
isa = PBXGroup;
children = (
- 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */,
- 6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */,
- 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */,
- 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */,
- );
- name = "MIG files";
+ 37AF802A1BF699AF00D657F6 /* DomainNameTest.c */,
+ 37AF802B1BF699AF00D657F6 /* DomainNameTest.h */,
+ 371D0FBD1BF666EB00E5DB26 /* ResourceRecordTest.c */,
+ 371D0FBE1BF666EB00E5DB26 /* ResourceRecordTest.h */,
+ 373202111BAB63E8007DE806 /* DNSMessageTest.h */,
+ 3732020F1BAB4349007DE806 /* DNSMessageTest.c */,
+ 37DDE9351BA386E70092AC61 /* main.c */,
+ 37DDE9271BA3825C0092AC61 /* unittest.c */,
+ 37DDE9281BA382670092AC61 /* unittest.h */,
+ 371D0FBA1BF545FA00E5DB26 /* InterfaceTest.c */,
+ 371D0FBB1BF545FA00E5DB26 /* InterfaceTest.h */,
+ );
+ name = "Unit Tests";
sourceTree = "<group>";
};
6575FC1F022EB78C00000109 /* Command-Line Clients */ = {
@@ -1142,7 +1168,6 @@
files = (
2EC8F8EC0C39CCAC003C9C48 /* helper.h in Headers */,
2EDC5E730C39EA640092701B /* helper-server.h in Headers */,
- 2E3552920C3A95C100CA1CB7 /* helper-error.h in Headers */,
2ECC11A80C4FEC3800CB1885 /* helpermsg-types.h in Headers */,
2E8165E80C5980E300485EB2 /* libpfkey.h in Headers */,
2E8165EA0C5980F700485EB2 /* ipsec_strerror.h in Headers */,
@@ -1162,12 +1187,9 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
- BD64FE9C1C40762F0040EAB3 /* Metrics.h in Headers */,
- D284BE530ADD80740027CCDF /* DNSServiceDiscoveryDefines.h in Headers */,
D284BE540ADD80740027CCDF /* dnssd_ipc.h in Headers */,
2E96A5260C39BE480087C4D2 /* helper.h in Headers */,
2EDC5E750C39EA640092701B /* helper-server.h in Headers */,
- 2E3552900C3A95C100CA1CB7 /* helper-error.h in Headers */,
2ECC11A60C4FEC3800CB1885 /* helpermsg-types.h in Headers */,
21A57F4E145B2AE100939099 /* CryptoAlg.h in Headers */,
21A57F55145B2B1400939099 /* CryptoSupport.h in Headers */,
@@ -1175,9 +1197,13 @@
2124FA301471E9B50021D7BB /* dnssec.h in Headers */,
218E8E53156D8C0300720DA0 /* dnsproxy.h in Headers */,
2127A47915C3C7B900A857FC /* nsec3.h in Headers */,
+ 222A3C5B1C1B75F2003A6FFD /* DNSServiceDiscoveryDefines.h in Headers */,
21DD8FC1161E9A250033C8F8 /* anonymous.h in Headers */,
21070E6116486B9000A69507 /* DNSSECSupport.h in Headers */,
848DA5CA165477EB00D2E8B4 /* xpc_services.h in Headers */,
+ BDA3F08E1C48DCA50054FB4B /* Metrics.h in Headers */,
+ 22448EA71C90A837004F25CC /* coreBLE.h in Headers */,
+ 22448EA41C90A7CB004F25CC /* BLE.h in Headers */,
848DA5D616547F7200D2E8B4 /* dns_xpc.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1200,7 +1226,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
- 2E35529D0C3A9E7600CA1CB7 /* helper-error.h in Headers */,
2E35529F0C3A9E7600CA1CB7 /* helper.h in Headers */,
FFD52A9E1AF858DD00CAD3EC /* CryptoAlg.h in Headers */,
);
@@ -1352,6 +1377,23 @@
productReference = 2E0405F00C31955500F13B59 /* mDNSResponderHelper */;
productType = "com.apple.product-type.tool";
};
+ 37DDE92C1BA383610092AC61 /* unittests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 37DDE9311BA383610092AC61 /* Build configuration list for PBXNativeTarget "unittests" */;
+ buildPhases = (
+ 37DDE9291BA383610092AC61 /* Sources */,
+ 37DDE92A1BA383610092AC61 /* Frameworks */,
+ 37DDE9341BA384000092AC61 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = unittests;
+ productName = unittests;
+ productReference = 37DDE92D1BA383610092AC61 /* unittests */;
+ productType = "com.apple.product-type.tool";
+ };
72FB545E166D5FB00090B2D9 /* dnsctl */ = {
isa = PBXNativeTarget;
buildConfigurationList = 72FB5465166D5FB00090B2D9 /* Build configuration list for PBXNativeTarget "dnsctl" */;
@@ -1572,6 +1614,11 @@
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0700;
+ TargetAttributes = {
+ 37DDE92C1BA383610092AC61 = {
+ CreatedOnToolsVersion = 7.0;
+ };
+ };
};
buildConfigurationList = D284BE2B0ADD78180027CCDF /* Build configuration list for PBXProject "mDNSResponder" */;
compatibilityVersion = "Xcode 3.2";
@@ -1610,6 +1657,7 @@
84C5B3341665529800C324A8 /* dns_services */,
D284BEB20ADD809A0027CCDF /* libjdns_sd.jnilib */,
4AE471670EAFF81900A6C5AD /* dns_sd.jar */,
+ 37DDE92C1BA383610092AC61 /* unittests */,
);
};
/* End PBXProject section */
@@ -1683,7 +1731,22 @@
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/bin/bash -e -x";
- shellScript = "DSTROOT=${DSTROOT}\nmkdir -p \"$DSTROOT/usr/include\"\nsed 's/\\(^#define _DNS_SD_LIBDISPATCH \\)0$/\\1 1/' \"$SRCROOT/../mDNSShared/dns_sd.h\" > \"$DSTROOT/usr/include/dns_sd.h\"\n\nif [[ \"${ACTION}\" == \"installhdrs\" ]]; then\n DSTROOT=${DSTROOT}\n mkdir -p \"$DSTROOT/usr/local/include\"\n sed 's/\\(^#define _DNS_SD_LIBDISPATCH \\)0$/\\1 1/' \"$SRCROOT/../mDNSMacOSX/Private/dns_services.h\" > \"$DSTROOT/usr/local/include/dns_services.h\"\n exit 0\nfi\n\nif [[ \"${PLATFORM_NAME}\" =~ \"simulator\" ]]; then\n ln -s libsystem_dnssd.dylib ${DSTROOT}${INSTALL_PATH}/libsystem_sim_dnssd.dylib\nfi\n";
+ shellScript = "DSTROOT=${DSTROOT}\nmkdir -p \"$DSTROOT/usr/include\"\nsed 's/\\(^#define _DNS_SD_LIBDISPATCH \\)0$/\\1 1/' \"$SRCROOT/../mDNSShared/dns_sd.h\" > \"$DSTROOT/usr/include/dns_sd.h\"\n\nif [[ \"${ACTION}\" == \"installhdrs\" ]]; then\n exit 0\nfi\n\nif [[ \"${PLATFORM_NAME}\" =~ \"simulator\" ]]; then\n ln -s libsystem_dnssd.dylib ${DSTROOT}${INSTALL_PATH}/libsystem_sim_dnssd.dylib\nfi\n";
+ };
+ 37DDE9341BA384000092AC61 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(TARGET_BUILD_DIR)/$(TARGET_NAME)",
+ );
+ outputPaths = (
+ "$(TARGET_BUILD_DIR)/unittest_success",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "cd \"$TARGET_BUILD_DIR\"\n./\"$TARGET_NAME\"\n# touch unittest_success\nif [ ! -f unittest_success ] ; then exit -1; fi";
};
4A4EE3A413CB8E82005C624B /* Build yacc file into derived source files */ = {
isa = PBXShellScriptBuildPhase;
@@ -1738,10 +1801,8 @@
files = (
215FFAEE124000F900470DE1 /* dnssd_ipc.c in Sources */,
215FFAEF124000F900470DE1 /* dnssd_clientlib.c in Sources */,
+ 222A3C6A1C1B7777003A6FFD /* DNSServiceDiscovery.c in Sources */,
215FFAF0124000F900470DE1 /* dnssd_clientstub.c in Sources */,
- 215FFAF1124000F900470DE1 /* DNSServiceDiscovery.c in Sources */,
- 215FFAF2124000F900470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */,
- 215FFAF3124000F900470DE1 /* DNSServiceDiscoveryReply.defs in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1751,10 +1812,8 @@
files = (
215FFAF41240011800470DE1 /* dnssd_ipc.c in Sources */,
215FFAF51240011800470DE1 /* dnssd_clientlib.c in Sources */,
+ 222A3C6B1C1B7778003A6FFD /* DNSServiceDiscovery.c in Sources */,
215FFAF61240011800470DE1 /* dnssd_clientstub.c in Sources */,
- 215FFAF71240011800470DE1 /* DNSServiceDiscovery.c in Sources */,
- 215FFAF81240011800470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */,
- 215FFAF91240011800470DE1 /* DNSServiceDiscoveryReply.defs in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1764,10 +1823,8 @@
files = (
215FFAFA1240013400470DE1 /* dnssd_ipc.c in Sources */,
215FFAFB1240013400470DE1 /* dnssd_clientlib.c in Sources */,
+ 222A3C6C1C1B7779003A6FFD /* DNSServiceDiscovery.c in Sources */,
215FFAFC1240013400470DE1 /* dnssd_clientstub.c in Sources */,
- 215FFAFD1240013400470DE1 /* DNSServiceDiscovery.c in Sources */,
- 215FFAFE1240013400470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */,
- 215FFAFF1240013400470DE1 /* DNSServiceDiscoveryReply.defs in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1776,13 +1833,25 @@
buildActionMask = 2147483647;
files = (
2E0405F50C3195F700F13B59 /* helper.c in Sources */,
- 2E0405F60C31961100F13B59 /* helpermsg.defs in Sources */,
2E96A51D0C39BDAC0087C4D2 /* helper-main.c in Sources */,
2E8165E90C5980EE00485EB2 /* pfkey.c in Sources */,
4BD2B63A134FE09F002B96D5 /* P2PPacketFilter.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 37DDE9291BA383610092AC61 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 371D0FBF1BF666EB00E5DB26 /* ResourceRecordTest.c in Sources */,
+ 37FEBD581BC789AA00638EA4 /* DNSCommon.c in Sources */,
+ 371D0FBC1BF545FA00E5DB26 /* InterfaceTest.c in Sources */,
+ 373202101BAB4444007DE806 /* DNSMessageTest.c in Sources */,
+ 3771F67D1BA387DD0072355E /* main.c in Sources */,
+ 37DDE9331BA383D30092AC61 /* unittest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
72FB545B166D5FB00090B2D9 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1803,26 +1872,25 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- D284BE560ADD80740027CCDF /* DNSServiceDiscoveryReply.defs in Sources */,
- D284BE570ADD80740027CCDF /* DNSServiceDiscoveryRequest.defs in Sources */,
+ 227687F31C90AD580019382D /* coreBLE.m in Sources */,
D284BE580ADD80740027CCDF /* mDNS.c in Sources */,
D284BE590ADD80740027CCDF /* uDNS.c in Sources */,
D284BE5A0ADD80740027CCDF /* DNSCommon.c in Sources */,
D284BE5B0ADD80740027CCDF /* DNSDigest.c in Sources */,
D284BE5D0ADD80740027CCDF /* mDNSDebug.c in Sources */,
D284BE5E0ADD80740027CCDF /* uds_daemon.c in Sources */,
+ 22448EA31C90A7BE004F25CC /* BLE.c in Sources */,
D284BE5F0ADD80740027CCDF /* dnssd_ipc.c in Sources */,
D284BE600ADD80740027CCDF /* PlatformCommon.c in Sources */,
D284BE610ADD80740027CCDF /* mDNSMacOSX.c in Sources */,
+ BDA3F08F1C48DCA50054FB4B /* Metrics.m in Sources */,
D284BE620ADD80740027CCDF /* LegacyNATTraversal.c in Sources */,
D284BE630ADD80740027CCDF /* daemon.c in Sources */,
- 2E04061F0C3198B700F13B59 /* helpermsg.defs in Sources */,
2E96A5320C39C1A50087C4D2 /* helper-stubs.c in Sources */,
21A57F4C145B2AE100939099 /* CryptoAlg.c in Sources */,
21A57F53145B2B1400939099 /* CryptoSupport.c in Sources */,
2124FA331471E9DE0021D7BB /* nsec.c in Sources */,
213BDC6D147319F400000896 /* dnssec.c in Sources */,
- BD64FE9D1C40762F0040EAB3 /* Metrics.m in Sources */,
218E8E51156D8C0300720DA0 /* dnsproxy.c in Sources */,
21DED43515702C0F0060B6B9 /* DNSProxySupport.c in Sources */,
216D9ACE1720C9F5008066E1 /* uDNSPathEvalulation.c in Sources */,
@@ -1831,6 +1899,7 @@
21DD8FBF161E9A250033C8F8 /* anonymous.c in Sources */,
21070E5F16486B9000A69507 /* DNSSECSupport.c in Sources */,
848DA5C7165477E000D2E8B4 /* xpc_services.c in Sources */,
+ 8417375C1B967D37000CD5C2 /* dnsctl_server.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1865,7 +1934,6 @@
D284BECC0ADD80A20027CCDF /* dnsextd_parser.y in Sources */,
D284BECB0ADD80A20027CCDF /* dnsextd_lexer.l in Sources */,
D284BECD0ADD80A20027CCDF /* PlatformCommon.c in Sources */,
- 2EAE955A0C31F4D30021F738 /* helpermsg.defs in Sources */,
2E35529E0C3A9E7600CA1CB7 /* helper-stubs.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1895,10 +1963,8 @@
files = (
FFA572330AF18F1C0055A0F1 /* dnssd_ipc.c in Sources */,
FFA572340AF18F1C0055A0F1 /* dnssd_clientlib.c in Sources */,
+ 222A3C6E1C1B777B003A6FFD /* DNSServiceDiscovery.c in Sources */,
FFA572350AF18F1C0055A0F1 /* dnssd_clientstub.c in Sources */,
- FFA5724A0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */,
- FFC22AA40B00F42C00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */,
- FFC22AA60B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1908,10 +1974,8 @@
files = (
FFA5723F0AF18F450055A0F1 /* dnssd_ipc.c in Sources */,
FFA572400AF18F450055A0F1 /* dnssd_clientlib.c in Sources */,
+ 222A3C6F1C1B777C003A6FFD /* DNSServiceDiscovery.c in Sources */,
FFA572410AF18F450055A0F1 /* dnssd_clientstub.c in Sources */,
- FFA5724B0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */,
- FFC22AA30B00F42B00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */,
- FFC22AA70B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1921,10 +1985,8 @@
files = (
FFFA38660AEEDB2B0065B80A /* dnssd_ipc.c in Sources */,
FFFA38630AEEDB090065B80A /* dnssd_clientlib.c in Sources */,
+ 222A3C6D1C1B777A003A6FFD /* DNSServiceDiscovery.c in Sources */,
FFFA38650AEEDB130065B80A /* dnssd_clientstub.c in Sources */,
- FFA572490AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */,
- FFC22AA20B00F42A00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */,
- FFC22AA50B00F43000BAB070 /* DNSServiceDiscoveryReply.defs in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2070,15 +2132,238 @@
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
- 03067D740C83A3CB0022BE1F /* Development */ = {
+ 03067D740C83A3CB0022BE1F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- GCC_OPTIMIZATION_LEVEL = s;
PRODUCT_NAME = "Build Some";
};
- name = Development;
+ name = Release;
+ };
+ 0C419F121BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/Debug";
+ CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)/Debug";
+ COPY_PHASE_STRIP = NO;
+ DEAD_CODE_STRIPPING = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__APPLE_USE_RFC_3542=1",
+ "_DNS_SD_LIBDISPATCH=1",
+ "APPLE_OSX_mDNSResponder=1",
+ "__MigTypeCheck=1",
+ "mDNSResponderVersion=${MVERS}",
+ _LEGACY_NAT_TRAVERSAL_,
+ "_BUILDING_XCODE_PROJECT_=1",
+ "DEBUG=1",
+ "BONJOUR_ON_DEMAND=1",
+ "USE_LIBIDN=1",
+ );
+ GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+ MVERS = "\"(Engineering Build)\"";
+ OTHER_CFLAGS = (
+ "-DUSE_SYSTEMCONFIGURATION_PRIVATE_HEADERS",
+ "-fwrapv",
+ );
+ SDKROOT = macosx.internal;
+ STRIP_INSTALLED_PRODUCT = NO;
+ STRIP_STYLE = debugging;
+ SUPPORTED_PLATFORMS = "macosx iphoneos";
+ WARNING_CFLAGS = (
+ "-W",
+ "-Wall",
+ "-Wmissing-prototypes",
+ "-Wno-four-char-constants",
+ "-Wno-unknown-pragmas",
+ "-Wshadow",
+ "-Wno-format",
+ "-Wformat-security",
+ );
+ YACC_GENERATED_FILE_STEM = Standard;
+ };
+ name = Debug;
+ };
+ 0C419F131BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "Build All";
+ };
+ name = Debug;
+ };
+ 0C419F141BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "Build Some";
+ };
+ name = Debug;
+ };
+ 0C419F151BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "Build All";
+ };
+ name = Debug;
+ };
+ 0C419F161BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ "APPLY_RULES_IN_COPY_FILES[sdk=appletvos*]" = YES;
+ "APPLY_RULES_IN_COPY_FILES[sdk=iphoneos*]" = YES;
+ "APPLY_RULES_IN_COPY_FILES[sdk=watchos*]" = YES;
+ CODE_SIGN_ENTITLEMENTS = "mDNSResponder-entitlements.plist";
+ CODE_SIGN_IDENTITY = "-";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ );
+ GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+ HEADER_SEARCH_PATHS = (
+ "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/PrivateHeaders",
+ ../mDNSShared,
+ "${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders",
+ "${APPLE_INTERNAL_DEVELOPER_DIR}/Headers",
+ "${CONFIGURATION_TEMP_DIR}",
+ "$(SDKROOT)/usr/include/libxml2",
+ "$(SDKROOT)/usr/local/include/",
+ );
+ INSTALL_PATH = /usr/sbin;
+ LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
+ MACOSX_DEPLOYMENT_TARGET = 10.10;
+ ORDER_FILE = "${SRCROOT}/mDNSResponder.order";
+ OTHER_LDFLAGS = "";
+ "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = (
+ "-weak_framework",
+ DeviceToDeviceManager,
+ "-lMobileGestalt",
+ );
+ "OTHER_LDFLAGS[sdk=macosx*][arch=*]" = (
+ "-lAWACS",
+ "-weak_framework",
+ WebFilterDNS,
+ "-weak_framework",
+ DeviceToDeviceManager,
+ );
+ "PLIST_FILE_OUTPUT_FORMAT[sdk=appletvos*]" = binary;
+ "PLIST_FILE_OUTPUT_FORMAT[sdk=iphoneos*]" = binary;
+ "PLIST_FILE_OUTPUT_FORMAT[sdk=watchos*]" = binary;
+ PRODUCT_NAME = mDNSResponder;
+ PROVISIONING_PROFILE = "";
+ };
+ name = Debug;
+ };
+ 0C419F171BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ "APPLY_RULES_IN_COPY_FILES[sdk=appletvos*]" = YES;
+ "APPLY_RULES_IN_COPY_FILES[sdk=iphoneos*]" = YES;
+ "APPLY_RULES_IN_COPY_FILES[sdk=watchos*]" = YES;
+ CODE_SIGN_ENTITLEMENTS = "helper-entitlements.plist";
+ CODE_SIGN_IDENTITY = "-";
+ HEADER_SEARCH_PATHS = (
+ "${CONFIGURATION_TEMP_DIR}",
+ "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
+ "$(SDKROOT)/usr/local/include",
+ );
+ INSTALL_PATH = /usr/sbin;
+ LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
+ MACOSX_DEPLOYMENT_TARGET = 10.10;
+ OTHER_LDFLAGS = "-lipsec";
+ "PLIST_FILE_OUTPUT_FORMAT[sdk=appletvos*]" = binary;
+ "PLIST_FILE_OUTPUT_FORMAT[sdk=iphoneos*]" = binary;
+ "PLIST_FILE_OUTPUT_FORMAT[sdk=watchos*]" = binary;
+ PRODUCT_NAME = mDNSResponderHelper;
+ PROVISIONING_PROFILE = "";
+ };
+ name = Debug;
+ };
+ 0C419F181BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ ../mDNSShared,
+ "${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders",
+ );
+ INSTALL_PATH = /usr/bin;
+ PRODUCT_NAME = "dns-sd";
+ };
+ name = Debug;
};
- 213FB21A12028A7B002B3A08 /* Development */ = {
+ 0C419F191BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_ENTITLEMENTS = "dnsctl-entitlements.plist";
+ CODE_SIGN_IDENTITY = "-";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_STRICT_ALIASING = YES;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INSTALL_PATH = /usr/local/bin;
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE = "";
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ 0C419F1A1BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ "${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders",
+ "${APPLE_INTERNAL_DEVELOPER_DIR}/Headers",
+ "${CONFIGURATION_TEMP_DIR}",
+ /System/Library/Frameworks/System.Framework/PrivateHeaders,
+ );
+ INSTALL_PATH = /usr/sbin;
+ LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
+ MACOSX_DEPLOYMENT_TARGET = 10.10;
+ OTHER_CFLAGS = "-UAPPLE_OSX_mDNSResponder";
+ PRODUCT_NAME = dnsextd;
+ };
+ name = Debug;
+ };
+ 0C419F1B1BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = "/Library/Application Support/Bonjour";
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ OTHER_LDFLAGS = "-Wl,-pie";
+ PRODUCT_NAME = ddnswriteconfig;
+ };
+ name = Debug;
+ };
+ 0C419F1C1BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_ENABLE_OBJC_GC = supported;
+ INFOPLIST_FILE = "PreferencePane/Info-PreferencePane.plist";
+ INSTALL_PATH = /AppleInternal/Library/PreferencePanes;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ PRODUCT_NAME = Bonjour;
+ WRAPPER_EXTENSION = prefPane;
+ };
+ name = Debug;
+ };
+ 0C419F1D1BA20DF600A70FF7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
@@ -2090,25 +2375,30 @@
PROVISIONING_PROFILE = "";
WRAPPER_EXTENSION = plugin;
};
- name = Development;
+ name = Debug;
};
- 2141DCF9123FFB5D0086D23E /* Development */ = {
+ 0C419F1E1BA20DF600A70FF7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- GCC_OPTIMIZATION_LEVEL = 0;
PRODUCT_NAME = SystemLibraries;
};
- name = Development;
+ name = Debug;
};
- 2141DD0C123FFC7F0086D23E /* Development */ = {
+ 0C419F1F1BA20DF600A70FF7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- GCC_OPTIMIZATION_LEVEL = s;
PRODUCT_NAME = SystemLibrariesStatic;
};
- name = Development;
+ name = Debug;
+ };
+ 0C419F201BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = SystemLibrariesDynamic;
+ };
+ name = Debug;
};
- 2141DD1E123FFCDB0086D23E /* Development */ = {
+ 0C419F211BA20DF600A70FF7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_PREPROCESSOR_DEFINITIONS = (
@@ -2122,9 +2412,9 @@
PRODUCT_NAME = dns_sd;
"SKIP_INSTALL[sdk=iphonesimulator*]" = YES;
};
- name = Development;
+ name = Debug;
};
- 2141DD25123FFD100086D23E /* Development */ = {
+ 0C419F221BA20DF600A70FF7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_PREPROCESSOR_DEFINITIONS = (
@@ -2136,9 +2426,9 @@
PRODUCT_NAME = dns_sd_debug;
"SKIP_INSTALL[sdk=iphonesimulator*]" = YES;
};
- name = Development;
+ name = Debug;
};
- 2141DD2B123FFD2C0086D23E /* Development */ = {
+ 0C419F231BA20DF600A70FF7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
@@ -2152,15 +2442,247 @@
PRODUCT_NAME = dns_sd_profile;
"SKIP_INSTALL[sdk=iphonesimulator*]" = YES;
};
- name = Development;
+ name = Debug;
};
- 2E0405F20C31955500F13B59 /* Development */ = {
+ 0C419F241BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
+ EXECUTABLE_EXTENSION = dylib;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "__DARWIN_NON_CANCELABLE=1",
+ );
+ HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
+ INSTALLHDRS_COPY_PHASE = YES;
+ INSTALLHDRS_SCRIPT_PHASE = YES;
+ INSTALL_PATH = /usr/lib/system;
+ INTERPOSITION_SIM_SUFFIX = "";
+ "INTERPOSITION_SIM_SUFFIX[sdk=iphonesimulator*]" = _sim;
+ LINK_WITH_STANDARD_LIBRARIES = NO;
+ OTHER_LDFLAGS = (
+ "-Wl,-umbrella,System",
+ "-L/usr/lib/system",
+ "-ldyld",
+ "-lcompiler_rt",
+ "-lsystem$(INTERPOSITION_SIM_SUFFIX)_kernel",
+ "-lsystem$(INTERPOSITION_SIM_SUFFIX)_platform",
+ "-lsystem$(INTERPOSITION_SIM_SUFFIX)_pthread",
+ "-lsystem_malloc",
+ "-lsystem_c",
+ "-lsystem_blocks",
+ "-ldispatch",
+ "-llaunch",
+ "-lsystem_asl",
+ );
+ PRODUCT_NAME = libsystem_dnssd;
+ };
+ name = Debug;
+ };
+ 0C419F251BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
+ EXECUTABLE_EXTENSION = dylib;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "__DARWIN_NON_CANCELABLE=1",
+ );
+ HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
+ INSTALL_PATH = /usr/lib/system;
+ INTERPOSITION_SIM_SUFFIX = "";
+ "INTERPOSITION_SIM_SUFFIX[sdk=iphonesimulator*]" = _sim;
+ LINK_WITH_STANDARD_LIBRARIES = NO;
+ OTHER_LDFLAGS = (
+ "-Wl,-umbrella,System",
+ "-L/usr/lib/system",
+ "-ldyld",
+ "-lcompiler_rt",
+ "-lsystem$(INTERPOSITION_SIM_SUFFIX)_kernel",
+ "-lsystem$(INTERPOSITION_SIM_SUFFIX)_platform",
+ "-lsystem$(INTERPOSITION_SIM_SUFFIX)_pthread",
+ "-lsystem_malloc",
+ "-lsystem_c",
+ "-lsystem_blocks",
+ "-ldispatch",
+ "-llaunch",
+ "-lsystem_asl",
+ );
+ PRODUCT_NAME = libsystem_dnssd_debug;
+ };
+ name = Debug;
+ };
+ 0C419F261BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
+ EXECUTABLE_EXTENSION = dylib;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "__DARWIN_NON_CANCELABLE=1",
+ );
+ GENERATE_PROFILING_CODE = YES;
+ HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
+ INSTALL_PATH = /usr/lib/system;
+ INTERPOSITION_SIM_SUFFIX = "";
+ "INTERPOSITION_SIM_SUFFIX[sdk=iphonesimulator*]" = _sim;
+ LINK_WITH_STANDARD_LIBRARIES = NO;
+ OTHER_LDFLAGS = (
+ "-Wl,-umbrella,System",
+ "-L/usr/lib/system",
+ "-ldyld",
+ "-lcompiler_rt",
+ "-lsystem$(INTERPOSITION_SIM_SUFFIX)_kernel",
+ "-lsystem$(INTERPOSITION_SIM_SUFFIX)_platform",
+ "-lsystem$(INTERPOSITION_SIM_SUFFIX)_pthread",
+ "-lsystem_malloc",
+ "-lsystem_c",
+ "-lsystem_blocks",
+ "-ldispatch",
+ "-llaunch",
+ "-lsystem_asl",
+ );
+ PRODUCT_NAME = libsystem_dnssd_profile;
+ };
+ name = Debug;
+ };
+ 0C419F271BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ EXECUTABLE_PREFIX = lib;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INSTALL_PATH = /usr/lib;
+ MACOSX_DEPLOYMENT_TARGET = 10.8;
+ ONLY_ACTIVE_ARCH = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ 0C419F281BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ EXECUTABLE_EXTENSION = jnilib;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ HEADER_SEARCH_PATHS = (
+ ../mDNSShared,
+ "${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/A/Headers",
+ "${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/1.3.1/Headers",
+ "${PROJECT_DERIVED_FILE_DIR}",
+ );
+ INSTALL_PATH = /usr/lib/java;
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ PRODUCT_NAME = libjdns_sd;
+ };
+ name = Debug;
+ };
+ 0C419F291BA20DF600A70FF7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = dns_sd.jar;
+ };
+ name = Debug;
+ };
+ 213FB21A12028A7B002B3A08 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ BUNDLE_LOADER = /usr/libexec/UserEventAgent;
+ CODE_SIGN_IDENTITY = "-";
+ INFOPLIST_FILE = "BonjourEvents-Info.plist";
+ INSTALL_PATH = /System/Library/UserEventPlugins/;
+ PRODUCT_NAME = BonjourEvents;
+ PROVISIONING_PROFILE = "";
+ WRAPPER_EXTENSION = plugin;
+ };
+ name = Release;
+ };
+ 2141DCF9123FFB5D0086D23E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = SystemLibraries;
+ };
+ name = Release;
+ };
+ 2141DD0C123FFC7F0086D23E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = SystemLibrariesStatic;
+ };
+ name = Release;
+ };
+ 2141DD1E123FFCDB0086D23E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "__DARWIN_NON_CANCELABLE=1",
+ );
+ HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
+ INSTALLHDRS_COPY_PHASE = YES;
+ INSTALLHDRS_SCRIPT_PHASE = YES;
+ INSTALL_PATH = /usr/local/lib/system;
+ PRODUCT_NAME = dns_sd;
+ "SKIP_INSTALL[sdk=iphonesimulator*]" = YES;
+ };
+ name = Release;
+ };
+ 2141DD25123FFD100086D23E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "__DARWIN_NON_CANCELABLE=1",
+ );
+ HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
+ INSTALL_PATH = /usr/local/lib/system;
+ PRODUCT_NAME = dns_sd_debug;
+ "SKIP_INSTALL[sdk=iphonesimulator*]" = YES;
+ };
+ name = Release;
+ };
+ 2141DD2B123FFD2C0086D23E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "__DARWIN_NON_CANCELABLE=1",
+ );
+ GENERATE_PROFILING_CODE = YES;
+ HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
+ INSTALL_PATH = /usr/local/lib/system;
+ PRODUCT_NAME = dns_sd_profile;
+ "SKIP_INSTALL[sdk=iphonesimulator*]" = YES;
+ };
+ name = Release;
+ };
+ 2E0405F20C31955500F13B59 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
"APPLY_RULES_IN_COPY_FILES[sdk=appletvos*]" = YES;
"APPLY_RULES_IN_COPY_FILES[sdk=iphoneos*]" = YES;
"APPLY_RULES_IN_COPY_FILES[sdk=watchos*]" = YES;
- "CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "helper-entitlements.plist";
+ CODE_SIGN_ENTITLEMENTS = "helper-entitlements.plist";
CODE_SIGN_IDENTITY = "-";
HEADER_SEARCH_PATHS = (
"${CONFIGURATION_TEMP_DIR}",
@@ -2177,17 +2699,81 @@
PRODUCT_NAME = mDNSResponderHelper;
PROVISIONING_PROFILE = "";
};
- name = Development;
+ name = Release;
};
- 4AE471680EAFF81900A6C5AD /* Development */ = {
+ 37AF80271BF6997A00D657F6 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- GCC_OPTIMIZATION_LEVEL = 0;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
PRODUCT_NAME = dns_sd.jar;
};
+ name = Release;
+ };
+ 37AF80281BF6997A00D657F6 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ PRODUCT_NAME = unittests;
+ };
+ name = Release;
+ };
+ 37AF80291BF6997A00D657F6 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ PRODUCT_NAME = unittests;
+ };
+ name = Debug;
+ };
+ 37DDE9321BA383610092AC61 /* Development */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)";
+ CLANG_WARN_CONSTANT_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)";
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = NO;
+ CLANG_WARN_ENUM_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)";
+ CLANG_WARN_INT_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)";
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = NO;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = NO;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = NO;
+ GCC_WARN_UNUSED_FUNCTION = NO;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ STRIP_INSTALLED_PRODUCT = NO;
+ };
name = Development;
};
- 72FB5466166D5FB00090B2D9 /* Development */ = {
+ 72FB5466166D5FB00090B2D9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
@@ -2203,7 +2789,6 @@
CODE_SIGN_IDENTITY = "-";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
- GCC_OPTIMIZATION_LEVEL = s;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
@@ -2220,9 +2805,9 @@
PROVISIONING_PROFILE = "";
SDKROOT = macosx;
};
- name = Development;
+ name = Release;
};
- 84C5B3371665529800C324A8 /* Development */ = {
+ 84C5B3371665529800C324A8 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
@@ -2233,7 +2818,6 @@
EXECUTABLE_PREFIX = lib;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
- GCC_OPTIMIZATION_LEVEL = s;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
@@ -2249,20 +2833,20 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
};
- name = Development;
+ name = Release;
};
- D284BE290ADD78180027CCDF /* Development */ = {
+ D284BE290ADD78180027CCDF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "Build All";
};
- name = Development;
+ name = Release;
};
- D284BE2C0ADD78180027CCDF /* Development */ = {
+ D284BE2C0ADD78180027CCDF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)";
- CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)";
+ CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/Release";
+ CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)/Release";
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
@@ -2273,6 +2857,8 @@
"mDNSResponderVersion=${MVERS}",
_LEGACY_NAT_TRAVERSAL_,
"_BUILDING_XCODE_PROJECT_=1",
+ "BONJOUR_ON_DEMAND=1",
+ "USE_LIBIDN=1",
);
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
@@ -2290,12 +2876,14 @@
"-Wno-four-char-constants",
"-Wno-unknown-pragmas",
"-Wshadow",
+ "-Wno-format",
+ "-Wformat-security",
);
YACC_GENERATED_FILE_STEM = Standard;
};
- name = Development;
+ name = Release;
};
- D284BE6E0ADD80740027CCDF /* Development */ = {
+ D284BE6E0ADD80740027CCDF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
"APPLY_RULES_IN_COPY_FILES[sdk=appletvos*]" = YES;
@@ -2340,11 +2928,10 @@
"PLIST_FILE_OUTPUT_FORMAT[sdk=watchos*]" = binary;
PRODUCT_NAME = mDNSResponder;
PROVISIONING_PROFILE = "";
- SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
};
- name = Development;
+ name = Release;
};
- D284BEAE0ADD80920027CCDF /* Development */ = {
+ D284BEAE0ADD80920027CCDF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
HEADER_SEARCH_PATHS = (
@@ -2354,9 +2941,9 @@
INSTALL_PATH = /usr/bin;
PRODUCT_NAME = "dns-sd";
};
- name = Development;
+ name = Release;
};
- D284BEBC0ADD809A0027CCDF /* Development */ = {
+ D284BEBC0ADD809A0027CCDF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2372,14 +2959,11 @@
INSTALL_PATH = /usr/lib/java;
LIBRARY_STYLE = DYNAMIC;
MACH_O_TYPE = mh_dylib;
- OTHER_CFLAGS = "";
- OTHER_LIBTOOL_FLAGS = "";
PRODUCT_NAME = libjdns_sd;
- SECTORDER_FLAGS = "";
};
- name = Development;
+ name = Release;
};
- D284BED70ADD80A20027CCDF /* Development */ = {
+ D284BED70ADD80A20027CCDF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
HEADER_SEARCH_PATHS = (
@@ -2394,9 +2978,9 @@
OTHER_CFLAGS = "-UAPPLE_OSX_mDNSResponder";
PRODUCT_NAME = dnsextd;
};
- name = Development;
+ name = Release;
};
- D284BEE60ADD80A70027CCDF /* Development */ = {
+ D284BEE60ADD80A70027CCDF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
INSTALL_PATH = "/Library/Application Support/Bonjour";
@@ -2404,23 +2988,21 @@
OTHER_LDFLAGS = "-Wl,-pie";
PRODUCT_NAME = ddnswriteconfig;
};
- name = Development;
+ name = Release;
};
- D284BF090ADD80B00027CCDF /* Development */ = {
+ D284BF090ADD80B00027CCDF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_ENABLE_OBJC_GC = supported;
- GCC_SYMBOLS_PRIVATE_EXTERN = NO;
INFOPLIST_FILE = "PreferencePane/Info-PreferencePane.plist";
INSTALL_PATH = /AppleInternal/Library/PreferencePanes;
MACOSX_DEPLOYMENT_TARGET = 10.6;
- OTHER_LDFLAGS = "-twolevel_namespace";
PRODUCT_NAME = Bonjour;
WRAPPER_EXTENSION = prefPane;
};
- name = Development;
+ name = Release;
};
- FFA572380AF18F1C0055A0F1 /* Development */ = {
+ FFA572380AF18F1C0055A0F1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
@@ -2451,9 +3033,9 @@
);
PRODUCT_NAME = libsystem_dnssd_debug;
};
- name = Development;
+ name = Release;
};
- FFA572440AF18F450055A0F1 /* Development */ = {
+ FFA572440AF18F450055A0F1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
@@ -2486,23 +3068,23 @@
);
PRODUCT_NAME = libsystem_dnssd_profile;
};
- name = Development;
+ name = Release;
};
- FFA5726F0AF191200055A0F1 /* Development */ = {
+ FFA5726F0AF191200055A0F1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = SystemLibrariesDynamic;
};
- name = Development;
+ name = Release;
};
- FFB7657F0AEED99D00583A2C /* Development */ = {
+ FFB7657F0AEED99D00583A2C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "Build All";
};
- name = Development;
+ name = Release;
};
- FFB7658A0AEED9FB00583A2C /* Development */ = {
+ FFB7658A0AEED9FB00583A2C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
@@ -2535,7 +3117,7 @@
);
PRODUCT_NAME = libsystem_dnssd;
};
- name = Development;
+ name = Release;
};
/* End XCBuildConfiguration section */
@@ -2543,63 +3125,81 @@
03067D730C83A3CB0022BE1F /* Build configuration list for PBXAggregateTarget "Build Some" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 03067D740C83A3CB0022BE1F /* Development */,
+ 03067D740C83A3CB0022BE1F /* Release */,
+ 0C419F141BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
213FB21B12028A7C002B3A08 /* Build configuration list for PBXNativeTarget "BonjourEvents" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 213FB21A12028A7B002B3A08 /* Development */,
+ 213FB21A12028A7B002B3A08 /* Release */,
+ 0C419F1D1BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
2141DD08123FFB830086D23E /* Build configuration list for PBXAggregateTarget "SystemLibraries" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 2141DCF9123FFB5D0086D23E /* Development */,
+ 2141DCF9123FFB5D0086D23E /* Release */,
+ 0C419F1E1BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
2141DD18123FFC990086D23E /* Build configuration list for PBXAggregateTarget "SystemLibrariesStatic" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 2141DD0C123FFC7F0086D23E /* Development */,
+ 2141DD0C123FFC7F0086D23E /* Release */,
+ 0C419F1F1BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
2141DD1F123FFCF90086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_static" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 2141DD1E123FFCDB0086D23E /* Development */,
+ 2141DD1E123FFCDB0086D23E /* Release */,
+ 0C419F211BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
2141DD35123FFD3B0086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_debug_static" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 2141DD25123FFD100086D23E /* Development */,
+ 2141DD25123FFD100086D23E /* Release */,
+ 0C419F221BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
2141DD36123FFD3B0086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_profile_static" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 2141DD2B123FFD2C0086D23E /* Development */,
+ 2141DD2B123FFD2C0086D23E /* Release */,
+ 0C419F231BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
2E0405F30C31956600F13B59 /* Build configuration list for PBXNativeTarget "mDNSResponderHelper" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 2E0405F20C31955500F13B59 /* Development */,
+ 2E0405F20C31955500F13B59 /* Release */,
+ 0C419F171BA20DF600A70FF7 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 37DDE9311BA383610092AC61 /* Build configuration list for PBXNativeTarget "unittests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 37DDE9321BA383610092AC61 /* Development */,
+ 37AF80281BF6997A00D657F6 /* Release */,
+ 37AF80291BF6997A00D657F6 /* Debug */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Development;
@@ -2607,130 +3207,146 @@
4AE471770EAFF84000A6C5AD /* Build configuration list for PBXLegacyTarget "dns_sd.jar" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 4AE471680EAFF81900A6C5AD /* Development */,
+ 0C419F291BA20DF600A70FF7 /* Debug */,
+ 37AF80271BF6997A00D657F6 /* Release */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
72FB5465166D5FB00090B2D9 /* Build configuration list for PBXNativeTarget "dnsctl" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 72FB5466166D5FB00090B2D9 /* Development */,
+ 72FB5466166D5FB00090B2D9 /* Release */,
+ 0C419F191BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
84C5B3361665529800C324A8 /* Build configuration list for PBXNativeTarget "dns_services" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 84C5B3371665529800C324A8 /* Development */,
+ 84C5B3371665529800C324A8 /* Release */,
+ 0C419F271BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
D284BE280ADD78180027CCDF /* Build configuration list for PBXAggregateTarget "Build More" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- D284BE290ADD78180027CCDF /* Development */,
+ D284BE290ADD78180027CCDF /* Release */,
+ 0C419F131BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
D284BE2B0ADD78180027CCDF /* Build configuration list for PBXProject "mDNSResponder" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- D284BE2C0ADD78180027CCDF /* Development */,
+ D284BE2C0ADD78180027CCDF /* Release */,
+ 0C419F121BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
D284BE6D0ADD80740027CCDF /* Build configuration list for PBXNativeTarget "mDNSResponder" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- D284BE6E0ADD80740027CCDF /* Development */,
+ D284BE6E0ADD80740027CCDF /* Release */,
+ 0C419F161BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
D284BEAD0ADD80920027CCDF /* Build configuration list for PBXNativeTarget "dns-sd tool" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- D284BEAE0ADD80920027CCDF /* Development */,
+ D284BEAE0ADD80920027CCDF /* Release */,
+ 0C419F181BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
D284BEBB0ADD809A0027CCDF /* Build configuration list for PBXNativeTarget "libjdns_sd.jnilib" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- D284BEBC0ADD809A0027CCDF /* Development */,
+ D284BEBC0ADD809A0027CCDF /* Release */,
+ 0C419F281BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
D284BED60ADD80A20027CCDF /* Build configuration list for PBXNativeTarget "dnsextd" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- D284BED70ADD80A20027CCDF /* Development */,
+ D284BED70ADD80A20027CCDF /* Release */,
+ 0C419F1A1BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
D284BEE50ADD80A70027CCDF /* Build configuration list for PBXNativeTarget "ddnswriteconfig" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- D284BEE60ADD80A70027CCDF /* Development */,
+ D284BEE60ADD80A70027CCDF /* Release */,
+ 0C419F1B1BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
D284BF080ADD80B00027CCDF /* Build configuration list for PBXNativeTarget "PreferencePane" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- D284BF090ADD80B00027CCDF /* Development */,
+ D284BF090ADD80B00027CCDF /* Release */,
+ 0C419F1C1BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
FFA572370AF18F1C0055A0F1 /* Build configuration list for PBXNativeTarget "libdns_sd_debug_dynamic" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- FFA572380AF18F1C0055A0F1 /* Development */,
+ FFA572380AF18F1C0055A0F1 /* Release */,
+ 0C419F251BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
FFA572430AF18F450055A0F1 /* Build configuration list for PBXNativeTarget "libdns_sd_profile_dynamic" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- FFA572440AF18F450055A0F1 /* Development */,
+ FFA572440AF18F450055A0F1 /* Release */,
+ 0C419F261BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
FFA5726E0AF191200055A0F1 /* Build configuration list for PBXAggregateTarget "SystemLibrariesDynamic" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- FFA5726F0AF191200055A0F1 /* Development */,
+ FFA5726F0AF191200055A0F1 /* Release */,
+ 0C419F201BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
FFB7657E0AEED99D00583A2C /* Build configuration list for PBXAggregateTarget "Build All" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- FFB7657F0AEED99D00583A2C /* Development */,
+ FFB7657F0AEED99D00583A2C /* Release */,
+ 0C419F151BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
FFB765890AEED9FB00583A2C /* Build configuration list for PBXNativeTarget "libdns_sd_dynamic" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- FFB7658A0AEED9FB00583A2C /* Development */,
+ FFB7658A0AEED9FB00583A2C /* Release */,
+ 0C419F241BA20DF600A70FF7 /* Debug */,
);
defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Development;
+ defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/Build All.xcscheme b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/Build All.xcscheme
new file mode 100644
index 00000000..6bc511e5
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/Build All.xcscheme
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0710"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "FFB7657B0AEED96B00583A2C"
+ BuildableName = "Build All"
+ BlueprintName = "Build All"
+ ReferencedContainer = "container:mDNSResponder.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ </Testables>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Development"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "FFB7657B0AEED96B00583A2C"
+ BuildableName = "Build All"
+ BlueprintName = "Build All"
+ ReferencedContainer = "container:mDNSResponder.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Development"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "FFB7657B0AEED96B00583A2C"
+ BuildableName = "Build All"
+ BlueprintName = "Build All"
+ ReferencedContainer = "container:mDNSResponder.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Development"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/mDNSResponder.xcscheme b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/mDNSResponder.xcscheme
new file mode 100644
index 00000000..7ba2fe06
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/xcshareddata/xcschemes/mDNSResponder.xcscheme
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0710"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "D284BE500ADD80740027CCDF"
+ BuildableName = "mDNSResponder"
+ BlueprintName = "mDNSResponder"
+ ReferencedContainer = "container:mDNSResponder.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "D284BE500ADD80740027CCDF"
+ BuildableName = "mDNSResponder"
+ BlueprintName = "mDNSResponder"
+ ReferencedContainer = "container:mDNSResponder.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "D284BE500ADD80740027CCDF"
+ BuildableName = "mDNSResponder"
+ BlueprintName = "mDNSResponder"
+ ReferencedContainer = "container:mDNSResponder.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <CommandLineArguments>
+ <CommandLineArgument
+ argument = "-d -NoSandbox -UseDebugSocket"
+ isEnabled = "YES">
+ </CommandLineArgument>
+ <CommandLineArgument
+ argument = "-DebugLogging"
+ isEnabled = "YES">
+ </CommandLineArgument>
+ </CommandLineArguments>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Development"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "D284BE500ADD80740027CCDF"
+ BuildableName = "mDNSResponder"
+ BlueprintName = "mDNSResponder"
+ ReferencedContainer = "container:mDNSResponder.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Development"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponderLogging.mobileconfig b/mDNSResponder/mDNSMacOSX/mDNSResponderLogging.mobileconfig
deleted file mode 100644
index 34ec0d9a..00000000
--- a/mDNSResponder/mDNSMacOSX/mDNSResponderLogging.mobileconfig
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>PayloadIdentifier</key>
- <string>com.apple.mDNSResponder</string>
- <key>PayloadUUID</key>
- <string>6D0962E1-558A-44FB-8FE0-1F4F0BD157F4</string>
- <key>PayloadDescription</key>
- <string>Turns on mDNSResponder Debug Logging</string>
- <key>PayloadDisplayName</key>
- <string>mDNSResponder Debug Logging</string>
- <key>PayloadOrganization</key>
- <string>Apple, Inc</string>
- <key>PayloadType</key>
- <string>Configuration</string>
- <key>PayloadVersion</key>
- <integer>2</integer>
-
- <key>ConsentText</key>
- <dict>
- <key>en</key>
- <string>English consent text</string>
- <key>jp</key>
- <string>Japanese consent text</string>
- <key>default</key>
- <string>Default consent text - used if none of the other languages match</string>
- </dict>
-
- <key>PayloadContent</key>
- <array>
- <dict>
- <key>PayloadUUID</key>
- <string>6D0962E1-558A-44FB-8FE0-1F4F0BD157F4</string>
- <key>PayloadIdentifier</key>
- <string>com.apple.defaults.1</string>
- <key>PayloadType</key>
- <string>com.apple.defaults.managed</string>
- <key>PayloadVersion</key>
- <integer>1</integer>
- <key>PayloadContent</key>
- <array>
- <dict>
- <key>DefaultsDomainName</key>
- <string>com.apple.mDNSResponder</string>
- <key>DefaultsData</key>
- <dict>
- <key>EnableLogging</key>
- <true/>
- </dict>
- </dict>
- </array>
- </dict>
- </array>
-</dict>
-</plist>
-
diff --git a/mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c b/mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c
index 1314584d..cc0d0bae 100644
--- a/mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c
+++ b/mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c
@@ -20,7 +20,7 @@
#include <network/private.h>
//Gets the DNSPolicy from NW PATH EVALUATOR
-mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isCellBlocked)
+mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isBlocked)
{
(void) m;
q->ServiceID = -1; // initialize the ServiceID to default value of -1
@@ -28,7 +28,7 @@ mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDN
// Return for non-unicast DNS queries, invalid pid, if NWPathEvaluation is already done by the client, or NWPathEvaluation not available on this OS
if (mDNSOpaque16IsZero(q->TargetQID) || (q->pid < 0) || (q->flags & kDNSServiceFlagsPathEvaluationDone) || !nw_endpoint_create_host)
{
- *isCellBlocked = mDNSfalse;
+ *isBlocked = mDNSfalse;
return;
}
@@ -142,10 +142,10 @@ mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDN
}
}
- if (isUUIDSet && TARGET_OS_IPHONE && nw_path_get_status(path) == nw_path_status_unsatisfied && nw_path_get_reason(path) == nw_path_reason_policy_drop)
- *isCellBlocked = mDNStrue;
+ if (isUUIDSet && (nw_path_get_status(path) == nw_path_status_unsatisfied) && (nw_path_get_reason(path) == nw_path_reason_policy_drop))
+ *isBlocked = mDNStrue;
else
- *isCellBlocked = mDNSfalse;
+ *isBlocked = mDNSfalse;
if (path != NULL)
network_release(path);
diff --git a/mDNSResponder/mDNSPosix/._ReadMe.txt b/mDNSResponder/mDNSPosix/._ReadMe.txt
deleted file mode 100755
index cd621b2a..00000000
--- a/mDNSResponder/mDNSPosix/._ReadMe.txt
+++ /dev/null
Binary files differ
diff --git a/mDNSResponder/mDNSPosix/Makefile b/mDNSResponder/mDNSPosix/Makefile
index de8bd00c..4f98e90f 100755
--- a/mDNSResponder/mDNSPosix/Makefile
+++ b/mDNSResponder/mDNSPosix/Makefile
@@ -146,6 +146,7 @@ ifeq ($(os),x)
# we get build failures: ‘daemon’ is deprecated (declared at /usr/include/stdlib.h:283)
CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -Werror -Wdeclaration-after-statement \
-D__MAC_OS_X_VERSION_MIN_REQUIRED=__MAC_OS_X_VERSION_10_4 \
+ -DHAVE_STRLCPY=1 \
-D__APPLE_USE_RFC_2292 #-Wunreachable-code
CC = gcc
LD = $(CC) -dynamiclib
@@ -218,7 +219,7 @@ CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_OS) $(CFLAGS_DEBUG)
all: setup Daemon libdns_sd Clients SAClient SAResponder SAProxyResponder Identify NetMonitor $(OPTIONALTARG)
-install: setup InstalledDaemon InstalledStartup InstalledLib InstalledManPages InstalledClients $(OPTINSTALL)
+install: setup InstalledStartup InstalledDaemon InstalledLib InstalledManPages InstalledClients $(OPTINSTALL)
# 'setup' sets up the build directory structure the way we want
setup:
@@ -297,9 +298,10 @@ InstalledNSS: $(NSSINSTPATH)/$(NSSLINKNAME) /etc/nss_mdns.conf $(MANPATH)/man5/n
@echo $+ " installed"
# Note: If daemon already installed, we make sure it's stopped before overwriting it
-$(INSTBASE)/sbin/mdnsd: $(BUILDDIR)/mdnsd
+$(INSTBASE)/sbin/mdnsd: $(BUILDDIR)/mdnsd $(STARTUPSCRIPTDIR)/$(STARTUPSCRIPTNAME)
@if test -x $@; then $(STARTUPSCRIPTDIR)/$(STARTUPSCRIPTNAME) stop; fi
$(CP) $< $@
+ @$(STARTUPSCRIPTDIR)/$(STARTUPSCRIPTNAME) start
$(INSTBASE)/lib/libdns_sd.$(LDSUFFIX).$(LIBVERS): $(BUILDDIR)/libdns_sd.$(LDSUFFIX)
$(CP) $< $@
@@ -312,12 +314,9 @@ endif
$(INSTBASE)/include/dns_sd.h: $(SHAREDDIR)/dns_sd.h
$(CP) $< $@
-# We make this target dependent on $(INSTBASE)/sbin/mdnsd because we need to ensure
-# that the daemon is installed *before* we try to execute the command to start it.
-$(STARTUPSCRIPTDIR)/$(STARTUPSCRIPTNAME): mdnsd.sh $(STARTUPSCRIPTDIR) $(INSTBASE)/sbin/mdnsd
+$(STARTUPSCRIPTDIR)/$(STARTUPSCRIPTNAME): mdnsd.sh $(STARTUPSCRIPTDIR)
$(CP) $< $@
chmod ugo+x $@
- $@ start
ifdef RUNLEVELSCRIPTSDIR
ifeq ($(wildcard $(RUNLEVELSCRIPTSDIR)/runlevels/default), $(RUNLEVELSCRIPTSDIR)/runlevels/default)
$(LN) $@ $(RUNLEVELSCRIPTSDIR)/runlevels/default/mdns
diff --git a/mDNSResponder/mDNSPosix/ReadMe.txt b/mDNSResponder/mDNSPosix/ReadMe.txt
index a374ddf0..c2f56412 100755
--- a/mDNSResponder/mDNSPosix/ReadMe.txt
+++ b/mDNSResponder/mDNSPosix/ReadMe.txt
@@ -308,20 +308,6 @@ CVE-ID
CVE-2011-0220 : JaeSeung Song of the Department of Computing at Imperial
College London
-Impact:  A local application may be able to cause a denial of service
-Description:  A denial of service issue was addressed through
-improved memory handling.
-CVE-ID
-CVE-2015-7988 : Alexandre Helie
-
-Impact:  A remote attacker may be able to cause unexpected
-application termination or arbitrary code execution
-Description:  Multiple memory corruption issues existed in DNS
-data parsing. These issues were addressed through improved bounds
-checking.
-CVE-ID
-CVE-2015-7987 : Alexandre Helie
-
To Do List
----------
• port to a System V that's not Solaris
diff --git a/mDNSResponder/mDNSPosix/mDNSPosix.c b/mDNSResponder/mDNSPosix/mDNSPosix.c
index 77b57149..07633703 100755
--- a/mDNSResponder/mDNSPosix/mDNSPosix.c
+++ b/mDNSResponder/mDNSPosix/mDNSPosix.c
@@ -147,7 +147,7 @@ mDNSlocal void SockAddrTomDNSAddr(const struct sockaddr *const sa, mDNSAddr *ipA
// mDNS core calls this routine when it needs to send a packet.
mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
- mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
+ mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
mDNSIPPort dstPort, mDNSBool useBackgroundTrafficClass)
{
int err = 0;
@@ -320,13 +320,6 @@ mDNSlocal void SocketDataReady(mDNS *const m, PosixNetworkInterface *intf, int s
&senderAddr, senderPort, &destAddr, MulticastDNSPort, InterfaceID);
}
-mDNSexport mDNSBool mDNSPlatformPeekUDP(mDNS *const m, UDPSocket *src)
-{
- (void)m; // unused
- (void)src; // unused
- return mDNSfalse;
-}
-
mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS * const m, TCPSocketFlags flags, mDNSIPPort * port, mDNSBool useBackgroundTrafficClass)
{
(void)m; // Unused
@@ -929,8 +922,8 @@ mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct
// and skip the probe phase of the probe/announce packet sequence.
intf->coreIntf.DirectLink = mDNSfalse;
#ifdef DIRECTLINK_INTERFACE_NAME
- if (strcmp(intfName, STRINGIFY(DIRECTLINK_INTERFACE_NAME)) == 0)
- intf->coreIntf.DirectLink = mDNStrue;
+ if (strcmp(intfName, STRINGIFY(DIRECTLINK_INTERFACE_NAME)) == 0)
+ intf->coreIntf.DirectLink = mDNStrue;
#endif
intf->coreIntf.SupportsUnicastMDNSResponse = mDNStrue;
@@ -1419,14 +1412,36 @@ mDNSexport void mDNSPlatformUnlock (const mDNS *const m)
// On the Posix platform this maps directly to the ANSI C strcpy.
mDNSexport void mDNSPlatformStrCopy(void *dst, const void *src)
{
- strcpy((char *)dst, (char *)src);
+ strcpy((char *)dst, (const char *)src);
+}
+
+mDNSexport mDNSu32 mDNSPlatformStrLCopy(void *dst, const void *src, mDNSu32 len)
+{
+#if HAVE_STRLCPY
+ return ((mDNSu32)strlcpy((char *)dst, (const char *)src, len));
+#else
+ size_t srcLen;
+
+ srcLen = strlen((const char *)src);
+ if (srcLen < len)
+ {
+ memcpy(dst, src, srcLen + 1);
+ }
+ else if (len > 0)
+ {
+ memcpy(dst, src, len - 1);
+ ((char *)dst)[len - 1] = '\0';
+ }
+
+ return ((mDNSu32)srcLen);
+#endif
}
// mDNS core calls this routine to get the length of a C string.
// On the Posix platform this maps directly to the ANSI C strlen.
mDNSexport mDNSu32 mDNSPlatformStrLen (const void *src)
{
- return strlen((char*)src);
+ return strlen((const char*)src);
}
// mDNS core calls this routine to copy memory.
@@ -1558,10 +1573,10 @@ mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID Inte
(void) iteration;
}
-mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf)
+mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(const AuthRecord *rr, mDNSInterfaceID InterfaceID)
{
(void) rr;
- (void) intf;
+ (void) InterfaceID;
return 1;
}
@@ -1620,37 +1635,38 @@ mDNSexport mStatus mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifnam
return mStatus_NoError;
}
-mDNSexport mStatus mDNSPlatformClearSPSMACAddr(void)
+mDNSexport mStatus mDNSPlatformClearSPSData(void)
{
return mStatus_NoError;
}
+mDNSexport mStatus mDNSPlatformStoreOwnerOptRecord(char *ifname, DNSMessage *msg, int length)
+{
+ (void) ifname; // Unused
+ (void) msg; // Unused
+ (void) length; // Unused
+ return mStatus_UnsupportedErr;
+}
+
mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
{
(void) sock; // unused
-
+
return (mDNSu16)-1;
}
mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
{
(void) InterfaceID; // unused
-
- return mDNSfalse;
-}
-
-mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isCellBlocked)
-{
- (void) m;
- q->ServiceID = -1;
- *isCellBlocked = mDNSfalse;
+ return mDNSfalse;
}
-mDNSexport void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q)
+mDNSexport void mDNSPlatformSetSocktOpt(void *sock, mDNSTransport_Type transType, mDNSAddr_Type addrType, DNSQuestion *q)
{
- (void) src;
- (void) dst;
+ (void) sock;
+ (void) transType;
+ (void) addrType;
(void) q;
}
diff --git a/mDNSResponder/mDNSPosix/mdnsd.sh b/mDNSResponder/mDNSPosix/mdnsd.sh
index c43d9fcb..6e65612b 100644
--- a/mDNSResponder/mDNSPosix/mdnsd.sh
+++ b/mDNSResponder/mDNSPosix/mdnsd.sh
@@ -40,6 +40,7 @@ if [ -r /sbin/start-stop-daemon ]; then
else
killmdnsd() {
kill -TERM `cat /var/run/mdnsd.pid`
+ sleep 1
}
START=
STOP=killmdnsd
@@ -60,7 +61,6 @@ case "$1" in
reload|restart|force-reload)
echo -n "Restarting Apple Darwin Multicast DNS / DNS Service Discovery daemon:"
$STOP $DAEMON
- sleep 1
$START $DAEMON
echo -n " mdnsd"
;;
diff --git a/mDNSResponder/mDNSPosix/nss_mdns.c b/mDNSResponder/mDNSPosix/nss_mdns.c
index ade4d4d2..afadb3c6 100755
--- a/mDNSResponder/mDNSPosix/nss_mdns.c
+++ b/mDNSResponder/mDNSPosix/nss_mdns.c
@@ -1088,6 +1088,7 @@ mdns_lookup_callback
ns_type_t expected_rr_type =
af_to_rr (result->hostent->h_addrtype);
+ // Idiot check class
if (rrclass != C_IN)
{
syslog (LOG_WARNING,
@@ -1269,6 +1270,7 @@ add_address_to_buffer (result_map_t * result, const void * data, int len)
return NULL;
}
+ // Idiot check
if (len != result->hostent->h_length)
{
syslog (LOG_WARNING,
@@ -1309,6 +1311,7 @@ contains_address (result_map_t * result, const void * data, int len)
{
int i;
+ // Idiot check
if (len != result->hostent->h_length)
{
syslog (LOG_WARNING,
@@ -2470,6 +2473,7 @@ cmp_dns_suffix (const char * name, const char * domain)
const char * nametail;
const char * domaintail;
+ // Idiot checks
if (*name == 0 || *name == k_dns_separator)
{
// Name can't be empty or start with separator
diff --git a/mDNSResponder/mDNSShared/PlatformCommon.c b/mDNSResponder/mDNSShared/PlatformCommon.c
index 4f844560..49c8fd19 100644
--- a/mDNSResponder/mDNSShared/PlatformCommon.c
+++ b/mDNSResponder/mDNSShared/PlatformCommon.c
@@ -23,6 +23,10 @@
#include <netinet/in.h> // Needed for sockaddr_in
#include <syslog.h>
+#if APPLE_OSX_mDNSResponder
+#include <os/log.h>
+#endif
+
#include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
#include "DNSCommon.h"
#include "PlatformCommon.h"
@@ -174,6 +178,14 @@ mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, m
int syslog_level = LOG_ERR;
switch (loglevel)
{
+#if APPLE_OSX_mDNSResponder
+ case MDNS_LOG_MSG: syslog_level = OS_LOG_TYPE_DEFAULT; break;
+ case MDNS_LOG_OPERATION: syslog_level = OS_LOG_TYPE_INFO; break;
+ case MDNS_LOG_SPS: syslog_level = OS_LOG_TYPE_INFO; break;
+ case MDNS_LOG_INFO: syslog_level = OS_LOG_TYPE_INFO; break;
+ case MDNS_LOG_DEBUG: syslog_level = OS_LOG_TYPE_DEBUG; break;
+ default: syslog_level = OS_LOG_TYPE_DEFAULT; break;
+#else
case MDNS_LOG_MSG: syslog_level = LOG_ERR; break;
case MDNS_LOG_OPERATION: syslog_level = LOG_WARNING; break;
case MDNS_LOG_SPS: syslog_level = LOG_NOTICE; break;
@@ -182,6 +194,7 @@ mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, m
default:
fprintf(stderr, "Unknown loglevel %d, assuming LOG_ERR\n", loglevel);
fflush(stderr);
+#endif
}
if (!log_inited) { openlog(ident, LOG_CONS, LOG_DAEMON); log_inited++; }
diff --git a/mDNSResponder/mDNSShared/dns_sd.h b/mDNSResponder/mDNSShared/dns_sd.h
index cf32ea1e..33ecfef2 100644
--- a/mDNSResponder/mDNSShared/dns_sd.h
+++ b/mDNSResponder/mDNSShared/dns_sd.h
@@ -66,7 +66,7 @@
*/
#ifndef _DNS_SD_H
-#define _DNS_SD_H 6254102
+#define _DNS_SD_H 7650102
#ifdef __cplusplus
extern "C" {
@@ -88,6 +88,13 @@ extern "C" {
#define DNSSD_API
#endif
+#if defined(_WIN32)
+#include <winsock2.h>
+typedef SOCKET dnssd_sock_t;
+#else
+typedef int dnssd_sock_t;
+#endif
+
/* stdint.h does not exist on FreeBSD 4.x; its types are defined in sys/types.h instead */
#if defined(__FreeBSD__) && (__FreeBSD__ < 5)
#include <sys/types.h>
@@ -180,6 +187,15 @@ enum
* in the future they will be delivered as usual.
*/
+ kDNSServiceFlagsAutoTrigger = 0x1,
+ /* Valid for browses using kDNSServiceInterfaceIndexAny.
+ * Will auto trigger the browse over AWDL as well once the service is discoveryed
+ * over BLE.
+ * This flag is an input value to DNSServiceBrowse(), which is why we can
+ * use the same value as kDNSServiceFlagsMoreComing, which is an output flag
+ * for various client callbacks.
+ */
+
kDNSServiceFlagsAdd = 0x2,
kDNSServiceFlagsDefault = 0x4,
/* Flags for domain enumeration and browse/query reply callbacks.
@@ -330,10 +346,21 @@ enum
*
* 5. Thread Safety
* The dns_sd.h API does not presuppose any particular threading model, and consequently
- * does no locking of its own (which would require linking some specific threading library).
- * If client code calls API routines on the same DNSServiceRef concurrently
- * from multiple threads, it is the client's responsibility to use a mutext
- * lock or take similar appropriate precautions to serialize those calls.
+ * does no locking internally (which would require linking with a specific threading library).
+ * If the client concurrently, from multiple threads (or contexts), calls API routines using
+ * the same DNSServiceRef, it is the client's responsibility to provide mutual exclusion for
+ * that DNSServiceRef.
+
+ * For example, use of DNSServiceRefDeallocate requires caution. A common mistake is as follows:
+ * Thread B calls DNSServiceRefDeallocate to deallocate sdRef while Thread A is processing events
+ * using sdRef. Doing this will lead to intermittent crashes on thread A if the sdRef is used after
+ * it was deallocated.
+
+ * A telltale sign of this crash type is to see DNSServiceProcessResult on the stack preceding the
+ * actual crash location.
+
+ * To state this more explicitly, mDNSResponder does not queue DNSServiceRefDeallocate so
+ * that it occurs discretely before or after an event is handled.
*/
kDNSServiceFlagsSuppressUnusable = 0x8000,
@@ -405,7 +432,7 @@ enum
kDNSServiceFlagsSecure = 0x200010,
/*
- * The response has been validated by verifying all the signaures in the response and was able to
+ * The response has been validated by verifying all the signatures in the response and was able to
* build a successful authentication chain starting from a known trust anchor.
*/
@@ -673,24 +700,49 @@ enum
* -- or --
* "Why is kDNSServiceMaxDomainName 1009, when the maximum legal domain name is 256 bytes?"
*
- * All strings used in the DNS-SD APIs are UTF-8 strings. Apart from the exceptions noted below,
- * the APIs expect the strings to be properly escaped, using the conventional DNS escaping rules:
+ * All strings used in the DNS-SD APIs are UTF-8 strings.
+ * Apart from the exceptions noted below, the APIs expect the strings to be properly escaped, using the
+ * conventional DNS escaping rules, as used by the traditional DNS res_query() API, as described below:
*
- * '\\' represents a single literal '\' in the name
- * '\.' represents a single literal '.' in the name
+ * Generally all UTF-8 characters (which includes all US ASCII characters) represent themselves,
+ * with two exceptions, the dot ('.') character, which is the label separator,
+ * and the backslash ('\') character, which is the escape character.
+ * The escape character ('\') is interpreted as described below:
+ *
* '\ddd', where ddd is a three-digit decimal value from 000 to 255,
- * represents a single literal byte with that value.
- * A bare unescaped '.' is a label separator, marking a boundary between domain and subdomain.
+ * represents a single literal byte with that value. Any byte value may be
+ * represented in '\ddd' format, even characters that don't strictly need to be escaped.
+ * For example, the ASCII code for 'w' is 119, and therefore '\119' is equivalent to 'w'.
+ * Thus the command "ping '\119\119\119.apple.com'" is the equivalent to the command "ping 'www.apple.com'".
+ * Nonprinting ASCII characters in the range 0-31 are often represented this way.
+ * In particular, the ASCII NUL character (0) cannot appear in a C string because C uses it as the
+ * string terminator character, so ASCII NUL in a domain name has to be represented in a C string as '\000'.
+ * Other characters like space (ASCII code 32) are sometimes represented as '\032'
+ * in contexts where having an actual space character in a C string would be inconvenient.
+ *
+ * Otherwise, for all cases where a '\' is followed by anything other than a three-digit decimal value
+ * from 000 to 255, the character sequence '\x' represents a single literal occurrence of character 'x'.
+ * This is legal for any character, so, for example, '\w' is equivalent to 'w'.
+ * Thus the command "ping '\w\w\w.apple.com'" is the equivalent to the command "ping 'www.apple.com'".
+ * However, this encoding is most useful when representing the characters '.' and '\',
+ * which otherwise would have special meaning in DNS name strings.
+ * This means that the following encodings are particularly common:
+ * '\\' represents a single literal '\' in the name
+ * '\.' represents a single literal '.' in the name
+ *
+ * A lone escape character ('\') appearing at the end of a string is not allowed, since it is
+ * followed by neither a three-digit decimal value from 000 to 255 nor a single character.
+ * If a lone escape character ('\') does appear as the last character of a string, it is silently ignored.
*
* The exceptions, that do not use escaping, are the routines where the full
* DNS name of a resource is broken, for convenience, into servicename/regtype/domain.
* In these routines, the "servicename" is NOT escaped. It does not need to be, since
* it is, by definition, just a single literal string. Any characters in that string
* represent exactly what they are. The "regtype" portion is, technically speaking,
- * escaped, but since legal regtypes are only allowed to contain letters, digits,
- * and hyphens, there is nothing to escape, so the issue is moot. The "domain"
- * portion is also escaped, though most domains in use on the public Internet
- * today, like regtypes, don't contain any characters that need to be escaped.
+ * escaped, but since legal regtypes are only allowed to contain US ASCII letters,
+ * digits, and hyphens, there is nothing to escape, so the issue is moot.
+ * The "domain" portion is also escaped, though most domains in use on the public
+ * Internet today, like regtypes, don't contain any characters that need to be escaped.
* As DNS-SD becomes more popular, rich-text domains for service discovery will
* become common, so software should be written to cope with domains with escaping.
*
@@ -742,12 +794,23 @@ enum
* in a way such that it does not inadvertently appear in service lists on
* all the other machines on the network.
*
- * If the client passes kDNSServiceInterfaceIndexLocalOnly when browsing
- * then it will find *all* records registered on that same local machine.
- * Clients explicitly wishing to discover *only* LocalOnly services can
- * accomplish this by inspecting the interfaceIndex of each service reported
- * to their DNSServiceBrowseReply() callback function, and discarding those
- * where the interface index is not kDNSServiceInterfaceIndexLocalOnly.
+ * If the client passes kDNSServiceInterfaceIndexLocalOnly when querying or
+ * browsing, then the LocalOnly authoritative records and /etc/hosts caches
+ * are searched and will find *all* records registered or configured on that
+ * same local machine.
+ *
+ * If interested in getting negative answers to local questions while querying
+ * or browsing, then set both the kDNSServiceInterfaceIndexLocalOnly and the
+ * kDNSServiceFlagsReturnIntermediates flags. If no local answers exist at this
+ * moment in time, then the reply will return an immediate negative answer. If
+ * local records are subsequently created that answer the question, then those
+ * answers will be delivered, for as long as the question is still active.
+ *
+ * Clients explicitly wishing to discover *only* LocalOnly services during a
+ * browse may do this, without flags, by inspecting the interfaceIndex of each
+ * service reported to a DNSServiceBrowseReply() callback function, and
+ * discarding those answers where the interface index is not set to
+ * kDNSServiceInterfaceIndexLocalOnly.
*
* kDNSServiceInterfaceIndexP2P is meaningful only in Browse, QueryRecord, Register,
* and Resolve operations. It should not be used in other DNSService APIs.
@@ -776,6 +839,7 @@ enum
#define kDNSServiceInterfaceIndexLocalOnly ((uint32_t)-1)
#define kDNSServiceInterfaceIndexUnicast ((uint32_t)-2)
#define kDNSServiceInterfaceIndexP2P ((uint32_t)-3)
+#define kDNSServiceInterfaceIndexBLE ((uint32_t)-4)
typedef uint32_t DNSServiceFlags;
typedef uint32_t DNSServiceProtocol;
@@ -833,29 +897,6 @@ DNSServiceErrorType DNSSD_API DNSServiceGetProperty
#define kDNSServiceProperty_DaemonVersion "DaemonVersion"
-
-// Map the source port of the local UDP socket that was opened for sending the DNS query
-// to the process ID of the application that triggered the DNS resolution.
-//
-/* DNSServiceGetPID() Parameters:
- *
- * srcport: Source port (in network byte order) of the UDP socket that was created by
- * the daemon to send the DNS query on the wire.
- *
- * pid: Process ID of the application that started the name resolution which triggered
- * the daemon to send the query on the wire. The value can be -1 if the srcport
- * cannot be mapped.
- *
- * return value: Returns kDNSServiceErr_NoError on success, or kDNSServiceErr_ServiceNotRunning
- * if the daemon is not running. The value of the pid is undefined if the return
- * value has error.
- */
-DNSServiceErrorType DNSSD_API DNSServiceGetPID
-(
- uint16_t srcport,
- int32_t *pid
-);
-
/*********************************************************************************************
*
* Unix Domain Socket access, DNSServiceRef deallocation, and data processing functions
@@ -876,8 +917,8 @@ DNSServiceErrorType DNSSD_API DNSServiceGetPID
* a client can choose to fork a thread and have it loop calling "DNSServiceProcessResult(ref);"
* If DNSServiceProcessResult() is called when no data is available for reading on the socket, it
* will block until data does become available, and then process the data and return to the caller.
- * The application is reponsible for checking the return value of DNSServiceProcessResult() to determine
- * if the socket is valid and if it should continue to process data on the socket.
+ * The application is responsible for checking the return value of DNSServiceProcessResult()
+ * to determine if the socket is valid and if it should continue to process data on the socket.
* When data arrives on the socket, the client is responsible for calling DNSServiceProcessResult(ref)
* in a timely fashion -- if the client allows a large backlog of data to build up the daemon
* may terminate the connection.
@@ -888,7 +929,7 @@ DNSServiceErrorType DNSSD_API DNSServiceGetPID
* error.
*/
-int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef);
+dnssd_sock_t DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef);
/* DNSServiceProcessResult()
@@ -1237,7 +1278,7 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister
* Note that the DNSServiceAddRecord/UpdateRecord/RemoveRecord are *NOT* thread-safe
* with respect to a single DNSServiceRef. If you plan to have multiple threads
* in your program simultaneously add, update, or remove records from the same
- * DNSServiceRef, then it's the caller's responsibility to use a mutext lock
+ * DNSServiceRef, then it's the caller's responsibility to use a mutex lock
* or take similar appropriate precautions to serialize those calls.
*
* Parameters;
@@ -2247,8 +2288,8 @@ typedef union _TXTRecordRef_t { char PrivateData[16]; char *ForceNaturalAlignmen
* For most applications, DNS-SD TXT records are generally
* less than 100 bytes, so in most cases a simple fixed-sized
* 256-byte buffer will be more than sufficient.
- * Recommended size limits for DNS-SD TXT Records are discussed in
- * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
+ * Recommended size limits for DNS-SD TXT Records are discussed in RFC 6763
+ * <https://tools.ietf.org/html/rfc6763#section-6.2>
*
* Note: When passing parameters to and from these TXT record APIs,
* the key name does not include the '=' character. The '=' character
@@ -2298,8 +2339,8 @@ void DNSSD_API TXTRecordDeallocate
* - Present with no value ("key" appears alone)
* - Present with empty value ("key=" appears in TXT record)
* - Present with non-empty value ("key=value" appears in TXT record)
- * For more details refer to "Data Syntax for DNS-SD TXT Records" in
- * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
+ * For more details refer to "Data Syntax for DNS-SD TXT Records" in RFC 6763
+ * <https://tools.ietf.org/html/rfc6763#section-6>
*
* txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate().
*
@@ -2611,13 +2652,6 @@ DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive
);
#endif
-#ifdef __APPLE_API_PRIVATE
-
-#define kDNSServiceCompPrivateDNS "PrivateDNS"
-#define kDNSServiceCompMulticastDNS "MulticastDNS"
-
-#endif //__APPLE_API_PRIVATE
-
/* Some C compiler cleverness. We can make the compiler check certain things for us,
* and report errors at compile-time if anything is wrong. The usual way to do this would
* be to use a run-time "if" statement or the conventional run-time "assert" mechanism, but
diff --git a/mDNSResponder/mDNSShared/dnssd_clientshim.c b/mDNSResponder/mDNSShared/dnssd_clientshim.c
index f6997295..b4824b4d 100644
--- a/mDNSResponder/mDNSShared/dnssd_clientshim.c
+++ b/mDNSResponder/mDNSShared/dnssd_clientshim.c
@@ -97,7 +97,7 @@ typedef struct
DNSQuestion q;
} mDNS_DirectOP_QueryRecord;
-int DNSServiceRefSockFD(DNSServiceRef sdRef)
+dnssd_sock_t DNSServiceRefSockFD(DNSServiceRef sdRef)
{
(void)sdRef; // Unused
return(0);
diff --git a/mDNSResponder/mDNSShared/dnssd_clientstub.c b/mDNSResponder/mDNSShared/dnssd_clientstub.c
index 5e151d08..5e12e0b1 100644
--- a/mDNSResponder/mDNSShared/dnssd_clientstub.c
+++ b/mDNSResponder/mDNSShared/dnssd_clientstub.c
@@ -172,6 +172,19 @@ struct _DNSRecordRef_t
DNSServiceOp *sdr;
};
+#if !defined(USE_TCP_LOOPBACK)
+static void SetUDSPath(struct sockaddr_un *saddr, const char *path)
+{
+ size_t pathLen;
+
+ pathLen = strlen(path);
+ if (pathLen < sizeof(saddr->sun_path))
+ memcpy(saddr->sun_path, path, pathLen + 1);
+ else
+ saddr->sun_path[0] = '\0';
+}
+#endif
+
// Write len bytes. Return 0 on success, -1 on error
static int write_all(dnssd_sock_t sd, char *buf, size_t len)
{
@@ -185,7 +198,7 @@ static int write_all(dnssd_sock_t sd, char *buf, size_t len)
// Should never happen. If it does, it indicates some OS bug,
// or that the mDNSResponder daemon crashed (which should never happen).
#if !defined(__ppc__) && defined(SO_ISDEFUNCT)
- int defunct;
+ int defunct = 0;
socklen_t dlen = sizeof (defunct);
if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0)
syslog(LOG_WARNING, "dnssd_clientstub write_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
@@ -272,6 +285,12 @@ static int more_bytes(dnssd_sock_t sd)
fd_set *fs;
int ret;
+#if defined(_WIN32)
+ fs = &readfds;
+ FD_ZERO(fs);
+ FD_SET(sd, fs);
+ ret = select((int)sd+1, fs, (fd_set*)NULL, (fd_set*)NULL, &tv);
+#else
if (sd < FD_SETSIZE)
{
fs = &readfds;
@@ -296,6 +315,7 @@ static int more_bytes(dnssd_sock_t sd)
ret = select((int)sd+1, fs, (fd_set*)NULL, (fd_set*)NULL, &tv);
if (fs != &readfds)
free(fs);
+#endif
return (ret > 0);
}
@@ -561,7 +581,7 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f
saddr.sin_port = htons(MDNS_TCP_SERVERPORT);
#else
saddr.sun_family = AF_LOCAL;
- strcpy(saddr.sun_path, uds_serverpath);
+ SetUDSPath(&saddr, uds_serverpath);
#if !defined(__ppc__) && defined(SO_DEFUNCTOK)
{
int defunct = 1;
@@ -671,7 +691,7 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
#ifndef NOT_HAVE_SA_LEN
caddr.sun_len = sizeof(struct sockaddr_un);
#endif
- strcpy(caddr.sun_path, data);
+ SetUDSPath(&caddr, data);
mask = umask(0);
bindresult = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr));
umask(mask);
@@ -852,7 +872,7 @@ cleanup:
return err;
}
-int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef)
+dnssd_sock_t DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef)
{
if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with NULL DNSServiceRef"); return dnssd_InvalidSocket; }
@@ -869,7 +889,7 @@ int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef)
return dnssd_InvalidSocket;
}
- return (int) sdRef->sockfd;
+ return sdRef->sockfd;
}
#if _DNS_SD_LIBDISPATCH
@@ -1154,13 +1174,18 @@ void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef)
DNSServiceErrorType DNSSD_API DNSServiceGetProperty(const char *property, void *result, uint32_t *size)
{
+ DNSServiceErrorType err;
char *ptr;
- size_t len = strlen(property) + 1;
+ size_t len;
ipc_msg_hdr *hdr;
DNSServiceOp *tmp;
uint32_t actualsize;
- DNSServiceErrorType err = ConnectToServer(&tmp, 0, getproperty_request, NULL, NULL, NULL);
+ if (!property || !result || !size)
+ return kDNSServiceErr_BadParam;
+
+ len = strlen(property) + 1;
+ err = ConnectToServer(&tmp, 0, getproperty_request, NULL, NULL, NULL);
if (err) return err;
hdr = create_hdr(getproperty_request, &len, &ptr, 0, tmp);
@@ -1280,7 +1305,7 @@ DNSServiceErrorType DNSSD_API DNSServiceResolve
ipc_msg_hdr *hdr;
DNSServiceErrorType err;
- if (!name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam;
+ if (!sdRef || !name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam;
// Need a real InterfaceID for WakeOnResolve
if ((flags & kDNSServiceFlagsWakeOnResolve) != 0 &&
@@ -1355,6 +1380,9 @@ DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
ipc_msg_hdr *hdr;
DNSServiceErrorType err;
+ // NULL name handled below.
+ if (!sdRef || !callBack) return kDNSServiceErr_BadParam;
+
if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny())
flags |= kDNSServiceFlagsIncludeP2P;
@@ -1464,7 +1492,7 @@ DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo
ipc_msg_hdr *hdr;
DNSServiceErrorType err;
- if (!hostname) return kDNSServiceErr_BadParam;
+ if (!sdRef || !hostname || !callBack) return kDNSServiceErr_BadParam;
err = ConnectToServer(sdRef, flags, addrinfo_request, handle_addrinfo_response, callBack, context);
if (err)
@@ -1518,6 +1546,9 @@ DNSServiceErrorType DNSSD_API DNSServiceBrowse
ipc_msg_hdr *hdr;
DNSServiceErrorType err;
+ // NULL domain handled below
+ if (!sdRef || !regtype || !callBack) return kDNSServiceErr_BadParam;
+
if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny())
flags |= kDNSServiceFlagsIncludeP2P;
@@ -1546,11 +1577,16 @@ DNSServiceErrorType DNSSD_API DNSServiceBrowse
DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain);
DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain)
{
+ DNSServiceErrorType err;
DNSServiceOp *tmp;
char *ptr;
- size_t len = sizeof(flags) + strlen(domain) + 1;
+ size_t len;
ipc_msg_hdr *hdr;
- DNSServiceErrorType err = ConnectToServer(&tmp, 0, setdomain_request, NULL, NULL, NULL);
+
+ if (!domain) return kDNSServiceErr_BadParam;
+ len = sizeof(flags) + strlen(domain) + 1;
+
+ err = ConnectToServer(&tmp, 0, setdomain_request, NULL, NULL, NULL);
if (err) return err;
hdr = create_hdr(setdomain_request, &len, &ptr, 0, tmp);
@@ -1596,8 +1632,8 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister
DNSServiceErrorType err;
union { uint16_t s; u_char b[2]; } port = { PortInNetworkByteOrder };
+ if (!sdRef || !regtype) return kDNSServiceErr_BadParam;
if (!name) name = "";
- if (!regtype) return kDNSServiceErr_BadParam;
if (!domain) domain = "";
if (!host) host = "";
if (!txtRecord) txtRecord = (void*)"";
@@ -1659,9 +1695,13 @@ DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
size_t len;
ipc_msg_hdr *hdr;
DNSServiceErrorType err;
+ int f1;
+ int f2;
+
+ if (!sdRef || !callBack) return kDNSServiceErr_BadParam;
- int f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0;
- int f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0;
+ f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0;
+ f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0;
if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
err = ConnectToServer(sdRef, flags, enumeration_request, handle_enumeration_response, callBack, context);
@@ -1736,10 +1776,13 @@ static void ConnectionResponse(DNSServiceOp *const sdr, const CallbackHeader *co
DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef)
{
+ DNSServiceErrorType err;
char *ptr;
size_t len = 0;
ipc_msg_hdr *hdr;
- DNSServiceErrorType err = ConnectToServer(sdRef, 0, connection_request, ConnectionResponse, NULL, NULL);
+
+ if (!sdRef) return kDNSServiceErr_BadParam;
+ err = ConnectToServer(sdRef, 0, connection_request, ConnectionResponse, NULL, NULL);
if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL
hdr = create_hdr(connection_request, &len, &ptr, 0, *sdRef);
@@ -1757,6 +1800,7 @@ DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *
size_t len = 0;
ipc_msg_hdr *hdr;
+ if (!sdRef) return kDNSServiceErr_BadParam;
DNSServiceErrorType err = ConnectToServer(sdRef, 0, connection_delegate_request, ConnectionResponse, NULL, NULL);
if (err)
{
@@ -1846,7 +1890,11 @@ DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny())
flags |= kDNSServiceFlagsIncludeP2P;
- if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
+ if (!sdRef || !RecordRef || !fullname || !rdata || !callBack)
+ {
+ syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with NULL parameter");
+ return kDNSServiceErr_BadParam;
+ }
if (!DNSServiceRefValid(sdRef))
{
@@ -1927,8 +1975,11 @@ DNSServiceErrorType DNSSD_API DNSServiceAddRecord
DNSRecordRef rref;
DNSRecord **p;
- if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
- if (!RecordRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSRecordRef pointer"); return kDNSServiceErr_BadParam; }
+ if (!sdRef || !RecordRef || !rdata)
+ {
+ syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL parameter");
+ return kDNSServiceErr_BadParam;
+ }
if (sdRef->op != reg_service_request)
{
syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with non-DNSServiceRegister DNSServiceRef %p %d", sdRef, sdRef->op);
@@ -1988,7 +2039,11 @@ DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
size_t len = 0;
char *ptr;
- if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
+ if (!sdRef || !rdata)
+ {
+ syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with NULL parameter");
+ return kDNSServiceErr_BadParam;
+ }
if (!DNSServiceRefValid(sdRef))
{
@@ -2064,12 +2119,15 @@ DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
const void *rdata
)
{
+ DNSServiceErrorType err;
char *ptr;
size_t len;
ipc_msg_hdr *hdr;
DNSServiceOp *tmp;
- DNSServiceErrorType err = ConnectToServer(&tmp, flags, reconfirm_record_request, NULL, NULL, NULL);
+ if (!fullname || !rdata) return kDNSServiceErr_BadParam;
+
+ err = ConnectToServer(&tmp, flags, reconfirm_record_request, NULL, NULL, NULL);
if (err) return err;
len = sizeof(DNSServiceFlags);
diff --git a/mDNSResponder/mDNSShared/dnssd_ipc.h b/mDNSResponder/mDNSShared/dnssd_ipc.h
index 7dc64c5f..96466a94 100644
--- a/mDNSResponder/mDNSShared/dnssd_ipc.h
+++ b/mDNSResponder/mDNSShared/dnssd_ipc.h
@@ -41,7 +41,6 @@
# define dnssd_EWOULDBLOCK WSAEWOULDBLOCK
# define dnssd_EINTR WSAEINTR
# define dnssd_ECONNRESET WSAECONNRESET
-# define dnssd_sock_t SOCKET
# define dnssd_socklen_t int
# define dnssd_close(sock) closesocket(sock)
# define dnssd_errno WSAGetLastError()
@@ -67,7 +66,6 @@ extern char *win32_strerror(int inErrorCode);
# define dnssd_EINTR EINTR
# define dnssd_ECONNRESET ECONNRESET
# define dnssd_EPIPE EPIPE
-# define dnssd_sock_t int
# define dnssd_socklen_t unsigned int
# define dnssd_close(sock) close(sock)
# define dnssd_errno errno
diff --git a/mDNSResponder/mDNSShared/uds_daemon.c b/mDNSResponder/mDNSShared/uds_daemon.c
index be89f319..0102453f 100644
--- a/mDNSResponder/mDNSShared/uds_daemon.c
+++ b/mDNSResponder/mDNSShared/uds_daemon.c
@@ -48,17 +48,18 @@ mDNSBool AlwaysAppendSearchDomains = mDNSfalse;
#endif
#endif
-#ifdef LOCAL_PEERPID
-#include <sys/un.h> // for LOCAL_PEERPID
+#ifdef LOCAL_PEEREPID
+#include <sys/un.h> // for LOCAL_PEEREPID
#include <sys/socket.h> // for getsockopt
#include <sys/proc_info.h> // for struct proc_bsdshortinfo
#include <libproc.h> // for proc_pidinfo()
-#endif //LOCAL_PEERPID
+#endif //LOCAL_PEEREPID
//upto 16 characters of process name (defined in <sys/proc.h> but we do not want to include that file)
#define MAXCOMLEN 16
#if APPLE_OSX_mDNSResponder
#include <WebFilterDNS/WebFilterDNS.h>
+#include "BLE.h"
#if !NO_WCF
@@ -225,7 +226,8 @@ struct request_state
DNSServiceFlags flags;
DNSQuestion q_all;
DNSQuestion q_default;
- } enumeration;
+ DNSQuestion q_autoall;
+ } enumeration;
struct
{
DNSQuestion q;
@@ -271,11 +273,19 @@ typedef struct reply_state
mDNSexport mDNS mDNSStorage;
mDNSexport const char ProgramName[] = "mDNSResponder";
+#if defined(USE_TCP_LOOPBACK)
+static char* boundPath = NULL;
+#else
+static char* boundPath = MDNS_UDS_SERVERPATH;
+#endif
+#if DEBUG
+#define MDNS_UDS_SERVERPATH_DEBUG "/var/tmp/mDNSResponder"
+#endif
static dnssd_sock_t listenfd = dnssd_InvalidSocket;
static request_state *all_requests = NULL;
-#ifdef LOCAL_PEERPID
+#ifdef LOCAL_PEEREPID
struct proc_bsdshortinfo proc;
-#endif //LOCAL_PEERPID
+#endif //LOCAL_PEEREPID
mDNSlocal void set_peer_pid(request_state *request);
mDNSlocal void LogMcastClientInfo(request_state *req);
mDNSlocal void GetMcastClients(request_state *req);
@@ -284,6 +294,13 @@ static mDNSu32 i_mcount; // sets mcount when McastLogging is enabled(PROF sign
static mDNSu32 n_mrecords; // tracks the current active mcast records for McastLogging
static mDNSu32 n_mquests; // tracks the current active mcast questions for McastLogging
+
+#if TARGET_OS_EMBEDDED
+mDNSu32 curr_num_regservices = 0;
+mDNSu32 max_num_regservices = 0;
+#endif
+
+
// Note asymmetry here between registration and browsing.
// For service registrations we only automatically register in domains that explicitly appear in local configuration data
// (so AutoRegistrationDomains could equally well be called SCPrefRegDomains)
@@ -340,9 +357,9 @@ mDNSlocal void my_perror(char *errmsg)
mDNSlocal void my_throttled_perror(char *err_msg)
{
static int uds_throttle_count = 0;
- if ((uds_throttle_count++ % 250) == 0)
+ if ((uds_throttle_count++ % 250) == 0)
my_perror(err_msg);
-}
+}
// LogMcastQuestion/LogMcastQ should be called after the DNSQuestion struct is initialized(especially for q->TargetQID)
// Hence all calls are made after mDNS_StartQuery()/mDNS_StopQuery()/mDNS_StopBrowse() is called.
@@ -360,9 +377,11 @@ mDNSlocal void LogMcastQuestion(mDNS *const m, const DNSQuestion *const q, reque
{
mcount--;
}
- LogMcast("%s: %##s (%s) (%s) Client(%d)[%s]", status ? "+Question" : "-Question", q->qname.c, DNSTypeName(q->qtype),
- q->InterfaceID == mDNSInterface_LocalOnly ? "lo" : q->InterfaceID == mDNSInterface_P2P ? "p2p" :
- q->InterfaceID == mDNSInterface_Any ? "any" : InterfaceNameForID(m, q->InterfaceID),
+ LogMcast("%s: %##s (%s) (%s) Client(%d)[%s]", status ? "+Question" : "-Question", q->qname.c, DNSTypeName(q->qtype),
+ q->InterfaceID == mDNSInterface_LocalOnly ? "lo" :
+ q->InterfaceID == mDNSInterface_P2P ? "p2p" :
+ q->InterfaceID == mDNSInterface_BLE ? "BLE" :
+ q->InterfaceID == mDNSInterface_Any ? "any" : InterfaceNameForID(m, q->InterfaceID),
req->process_id, req->pid_name);
LogMcastStateInfo(m, mflag, mDNSfalse, mDNSfalse);
}
@@ -386,8 +405,10 @@ mDNSlocal void LogMcastService(mDNS *const m, const AuthRecord *const ar, reques
mcount--;
}
LogMcast("%s: %##s (%s) (%s) Client(%d)[%s]", status ? "+Service" : "-Service", ar->resrec.name->c, DNSTypeName(ar->resrec.rrtype),
- ar->resrec.InterfaceID == mDNSInterface_LocalOnly ? "lo" : ar->resrec.InterfaceID == mDNSInterface_P2P ? "p2p" :
- ar->resrec.InterfaceID == mDNSInterface_Any ? "all" : InterfaceNameForID(m, ar->resrec.InterfaceID),
+ ar->resrec.InterfaceID == mDNSInterface_LocalOnly ? "lo" :
+ ar->resrec.InterfaceID == mDNSInterface_P2P ? "p2p" :
+ ar->resrec.InterfaceID == mDNSInterface_BLE ? "BLE" :
+ ar->resrec.InterfaceID == mDNSInterface_Any ? "all" : InterfaceNameForID(m, ar->resrec.InterfaceID),
req->process_id, req->pid_name);
LogMcastStateInfo(m, mflag, mDNSfalse, mDNSfalse);
}
@@ -407,13 +428,13 @@ mDNSexport void LogMcastStateInfo(mDNS *const m, mDNSBool mflag, mDNSBool start,
{
request_state *req, *r;
for (req = all_requests; req; req=req->next)
- {
+ {
if (req->primary) // If this is a subbordinate operation, check that the parent is in the list
- {
- for (r = all_requests; r && r != req; r=r->next)
- if (r == req->primary)
+ {
+ for (r = all_requests; r && r != req; r=r->next)
+ if (r == req->primary)
goto foundpar;
- }
+ }
// For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
GetMcastClients(req);
foundpar:;
@@ -432,28 +453,28 @@ mDNSexport void LogMcastStateInfo(mDNS *const m, mDNSBool mflag, mDNSBool start,
// wrong value if MulticastLogging is disabled and then re-enabled
LogMcastNoIdent("--- START MCAST STATE LOG ---");
if (!all_requests)
- {
+ {
mcount = 0;
LogMcastNoIdent("<None>");
- }
- else
- {
+ }
+ else
+ {
request_state *req, *r;
for (req = all_requests; req; req=req->next)
- {
+ {
if (req->primary) // If this is a subbordinate operation, check that the parent is in the list
- {
- for (r = all_requests; r && r != req; r=r->next)
- if (r == req->primary)
+ {
+ for (r = all_requests; r && r != req; r=r->next)
+ if (r == req->primary)
goto foundparent;
LogMcastNoIdent("%3d: Orphan operation; parent not found in request list", req->sd);
- }
+ }
// For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info
LogMcastClientInfo(req);
foundparent:;
}
if(!mcount) // To initially set mcount
- mcount = i_mcount;
+ mcount = i_mcount;
}
if (mcount == 0)
{
@@ -461,7 +482,7 @@ mDNSexport void LogMcastStateInfo(mDNS *const m, mDNSBool mflag, mDNSBool start,
LogMcastNoIdent("--- MCOUNT[%d]: IMPKTNUM[%d] ---", mcount, i_mpktnum);
}
if (mflag)
- LogMcastNoIdent("--- MCOUNT[%d]: CMPKTNUM[%d] - IMPKTNUM[%d] = [%d]PKTS ---", mcount, m->MPktNum, i_mpktnum, (m->MPktNum - i_mpktnum));
+ LogMcastNoIdent("--- MCOUNT[%d]: CMPKTNUM[%d] - IMPKTNUM[%d] = [%d]PKTS ---", mcount, m->MPktNum, i_mpktnum, (m->MPktNum - i_mpktnum));
LogMcastNoIdent("--- END MCAST STATE LOG ---");
}
}
@@ -507,6 +528,24 @@ mDNSlocal void abort_request(request_state *req)
req->terminate = (req_termination_fn) ~0;
}
+#if DEBUG
+mDNSexport void SetDebugBoundPath(void)
+{
+#if !defined(USE_TCP_LOOPBACK)
+ boundPath = MDNS_UDS_SERVERPATH_DEBUG;
+#endif
+}
+
+mDNSexport int IsDebugSocketInUse(void)
+{
+#if !defined(USE_TCP_LOOPBACK)
+ return !strcmp(boundPath, MDNS_UDS_SERVERPATH_DEBUG);
+#else
+ return mDNSfalse;
+#endif
+}
+#endif
+
mDNSlocal void AbortUnlinkAndFree(request_state *req)
{
request_state **p = &all_requests;
@@ -611,9 +650,7 @@ mDNSlocal mStatus GenerateNTDResponse(const domainname *const servicename, const
}
}
-// Special support to enable the DNSServiceBrowse call made by Bonjour Browser
-// Remove after Bonjour Browser is updated to use DNSServiceQueryRecord instead of DNSServiceBrowse
-mDNSlocal void GenerateBonjourBrowserResponse(const domainname *const servicename, const mDNSInterfaceID id,
+mDNSlocal void GenerateBrowseReply(const domainname *const servicename, const mDNSInterfaceID id,
request_state *const request, reply_state **const rep, reply_op_t op, DNSServiceFlags flags, mStatus err)
{
char namestr[MAX_DOMAIN_LABEL+1];
@@ -665,7 +702,7 @@ mDNSlocal AuthRecord *read_rr_from_ipc_msg(request_state *request, int GetTTL, i
mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend);
const char *rdata = get_rdata (&request->msgptr, request->msgend, rdlen);
mDNSu32 ttl = GetTTL ? get_uint32(&request->msgptr, request->msgend) : 0;
- int storage_size = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody);
+ size_t storage_size = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody);
AuthRecord *rr;
mDNSInterfaceID InterfaceID;
AuthRecType artype;
@@ -691,7 +728,7 @@ mDNSlocal AuthRecord *read_rr_from_ipc_msg(request_state *request, int GetTTL, i
InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
if (InterfaceID == mDNSInterface_LocalOnly)
artype = AuthRecordLocalOnly;
- else if (InterfaceID == mDNSInterface_P2P)
+ else if (InterfaceID == mDNSInterface_P2P || InterfaceID == mDNSInterface_BLE)
artype = AuthRecordP2P;
else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P)
&& (flags & kDNSServiceFlagsIncludeAWDL))
@@ -782,12 +819,14 @@ mDNSlocal mDNSBool AuthorizedDomain(const request_state * const request, const d
#pragma mark - external helpers
#endif
-mDNSlocal mDNSBool callExternalHelpers(mDNSInterfaceID InterfaceID, const domainname *const domain, DNSServiceFlags flags)
+mDNSexport mDNSBool callExternalHelpers(mDNSInterfaceID InterfaceID, const domainname *const domain, DNSServiceFlags flags)
{
#if APPLE_OSX_mDNSResponder
- if ( ((InterfaceID == mDNSInterface_Any) && (flags & (kDNSServiceFlagsIncludeP2P | kDNSServiceFlagsIncludeAWDL)) && IsLocalDomain(domain))
- || mDNSPlatformInterfaceIsD2D(InterfaceID))
+ // Only call D2D layer routines if request applies to a D2D interface and the domain is "local".
+ if ( (((InterfaceID == mDNSInterface_Any) && (flags & (kDNSServiceFlagsIncludeP2P | kDNSServiceFlagsIncludeAWDL | kDNSServiceFlagsAutoTrigger)))
+ || mDNSPlatformInterfaceIsD2D(InterfaceID) || (InterfaceID == mDNSInterface_BLE))
+ && IsLocalDomain(domain))
{
return mDNStrue;
}
@@ -822,6 +861,14 @@ mDNSlocal void external_start_advertising_helper(service_instance *const instanc
external_start_advertising_service(&instance->srs.RR_PTR.resrec, instance->request->flags);
external_start_advertising_service(&instance->srs.RR_SRV.resrec, instance->request->flags);
+
+#if APPLE_OSX_mDNSResponder
+ if (applyToBLE(instance->srs.RR_SRV.resrec.InterfaceID, instance->request->flags))
+ {
+ start_BLE_advertise(& instance->srs, instance->srs.RR_SRV.resrec.name , instance->srs.RR_SRV.resrec.rrtype, instance->request->flags);
+ }
+#endif // APPLE_OSX_mDNSResponder
+
external_start_advertising_service(&instance->srs.RR_TXT.resrec, instance->request->flags);
for (e = instance->srs.Extras; e; e = e->next)
@@ -1014,6 +1061,9 @@ mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, m
}
else if (result == mStatus_MemFree)
{
+#if TARGET_OS_EMBEDDED
+ curr_num_regservices--;
+#endif
if (instance->request && instance->renameonmemfree)
{
external_stop_advertising_helper(instance);
@@ -1148,24 +1198,24 @@ mDNSlocal void set_peer_pid(request_state *request)
socklen_t len = sizeof(p);
request->pid_name[0] = '\0';
request->process_id = -1;
-#ifdef LOCAL_PEERPID
- if (request->sd < 0)
+#ifdef LOCAL_PEEREPID
+ if (request->sd < 0)
return;
- // to extract the pid value
- if (getsockopt(request->sd, SOL_LOCAL, LOCAL_PEERPID, &p, &len) != 0)
+ // to extract the effective pid value
+ if (getsockopt(request->sd, SOL_LOCAL, LOCAL_PEEREPID, &p, &len) != 0)
return;
// to extract the process name from the pid value
if (proc_pidinfo(p, PROC_PIDT_SHORTBSDINFO, 1, &proc, PROC_PIDT_SHORTBSDINFO_SIZE) == 0)
return;
- mDNSPlatformStrCopy(request->pid_name, proc.pbsi_comm);
+ mDNSPlatformStrLCopy(request->pid_name, proc.pbsi_comm, sizeof(request->pid_name));
request->process_id = p;
- debugf("set_peer_pid: Client PEERPID is %d %s", p, request->pid_name);
-#else // !LOCAL_PEERPID
+ debugf("set_peer_pid: Client PEEREPID is %d %s", p, request->pid_name);
+#else // !LOCAL_PEEREPID
len = 0;
LogInfo("set_peer_pid: Not Supported on this version of OS");
if (request->sd < 0)
return;
-#endif // LOCAL_PEERPID
+#endif // LOCAL_PEEREPID
}
mDNSlocal void connection_termination(request_state *request)
@@ -1196,7 +1246,7 @@ mDNSlocal void connection_termination(request_state *request)
{
registered_record_entry *ptr = request->u.reg_recs;
LogOperation("%3d: DNSServiceRegisterRecord(%u %s) STOP PID[%d](%s)", request->sd, ptr->key, RRDisplayString(&mDNSStorage, &ptr->rr->resrec), request->process_id, request->pid_name);
- request->u.reg_recs = request->u.reg_recs->next;
+ request->u.reg_recs = request->u.reg_recs->next;
ptr->rr->RecordContext = NULL;
if (ptr->external_advertise)
{
@@ -1248,7 +1298,7 @@ mDNSlocal mStatus handle_regrecord_request(request_state *request)
}
// allocate registration entry, link into list
re = mallocL("registered_record_entry", sizeof(registered_record_entry));
- if (!re)
+ if (!re)
FatalError("ERROR: malloc");
re->key = request->hdr.reg_index;
re->rr = rr;
@@ -1259,7 +1309,7 @@ mDNSlocal mStatus handle_regrecord_request(request_state *request)
rr->RecordCallback = regrecord_callback;
re->origInterfaceID = rr->resrec.InterfaceID;
- if (rr->resrec.InterfaceID == mDNSInterface_P2P)
+ if (rr->resrec.InterfaceID == mDNSInterface_P2P)
rr->resrec.InterfaceID = mDNSInterface_Any;
#if 0
if (!AuthorizedDomain(request, rr->resrec.name, AutoRegistrationDomains)) return (mStatus_NoError);
@@ -1267,7 +1317,7 @@ mDNSlocal mStatus handle_regrecord_request(request_state *request)
if (rr->resrec.rroriginalttl == 0)
rr->resrec.rroriginalttl = DefaultTTLforRRType(rr->resrec.rrtype);
- LogOperation("%3d: DNSServiceRegisterRecord(%u %s) START PID[%d](%s)", request->sd, re->key, RRDisplayString(&mDNSStorage, &rr->resrec),
+ LogOperation("%3d: DNSServiceRegisterRecord(%u %s) START PID[%d](%s)", request->sd, re->key, RRDisplayString(&mDNSStorage, &rr->resrec),
request->process_id, request->pid_name);
err = mDNS_Register(&mDNSStorage, rr);
@@ -1279,7 +1329,7 @@ mDNSlocal mStatus handle_regrecord_request(request_state *request)
}
else
{
- LogMcastS(&mDNSStorage, rr, request, reg_start);
+ LogMcastS(&mDNSStorage, rr, request, reg_start);
re->next = request->u.reg_recs;
request->u.reg_recs = re;
}
@@ -1291,17 +1341,17 @@ mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m);
mDNSlocal void regservice_termination_callback(request_state *request)
{
- if (!request)
- {
- LogMsg("regservice_termination_callback context is NULL");
- return;
+ if (!request)
+ {
+ LogMsg("regservice_termination_callback context is NULL");
+ return;
}
while (request->u.servicereg.instances)
{
service_instance *p = request->u.servicereg.instances;
request->u.servicereg.instances = request->u.servicereg.instances->next;
// only safe to free memory if registration is not valid, i.e. deregister fails (which invalidates p)
- LogOperation("%3d: DNSServiceRegister(%##s, %u) STOP PID[%d](%s)", request->sd, p->srs.RR_SRV.resrec.name->c,
+ LogOperation("%3d: DNSServiceRegister(%##s, %u) STOP PID[%d](%s)", request->sd, p->srs.RR_SRV.resrec.name->c,
mDNSVal16(p->srs.RR_SRV.resrec.rdata->u.srv.port), request->process_id, request->pid_name);
external_stop_advertising_helper(p);
@@ -1320,9 +1370,9 @@ mDNSlocal void regservice_termination_callback(request_state *request)
}
}
if (request->u.servicereg.txtdata)
- {
- freeL("service_info txtdata", request->u.servicereg.txtdata);
- request->u.servicereg.txtdata = NULL;
+ {
+ freeL("service_info txtdata", request->u.servicereg.txtdata);
+ request->u.servicereg.txtdata = NULL;
}
if (request->u.servicereg.autoname)
{
@@ -1347,7 +1397,7 @@ mDNSlocal mStatus add_record_to_service(request_state *request, service_instance
ServiceRecordSet *srs = &instance->srs;
mStatus result;
mDNSu32 coreFlags = 0; // translate to corresponding mDNSCore flag definitions
- int size = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody);
+ size_t size = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody);
ExtraResourceRecord *extra = mallocL("ExtraResourceRecord", sizeof(*extra) - sizeof(RDataBody) + size);
if (!extra) { my_perror("ERROR: malloc"); return mStatus_NoMemoryErr; }
@@ -1363,15 +1413,15 @@ mDNSlocal mStatus add_record_to_service(request_state *request, service_instance
coreFlags |= coreFlagIncludeP2P;
if (request->flags & kDNSServiceFlagsIncludeAWDL)
coreFlags |= coreFlagIncludeAWDL;
-
+
result = mDNS_AddRecordToService(&mDNSStorage, srs, extra, &extra->r.rdatastorage, ttl, coreFlags);
- if (result)
- {
- freeL("ExtraResourceRecord/add_record_to_service", extra);
- return result;
+ if (result)
+ {
+ freeL("ExtraResourceRecord/add_record_to_service", extra);
+ return result;
}
LogMcastS(&mDNSStorage, &srs->RR_PTR, request, reg_start);
-
+
extra->ClientID = request->hdr.reg_index;
if ( instance->external_advertise
&& callExternalHelpers(request->u.servicereg.InterfaceID, &instance->domain, request->flags))
@@ -1437,14 +1487,7 @@ mDNSlocal void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd
if (external_advertise)
{
ResourceRecord ext = rr->resrec;
- DNSServiceFlags flags = 0;
-
- // Since we don't have a copy of the flags value used when the record was registered,
- // we'll have to derive it from the ARType field.
- if (rr->ARType == AuthRecordAnyIncludeP2P)
- flags |= kDNSServiceFlagsIncludeP2P;
- else if (rr->ARType == AuthRecordAnyIncludeAWDL)
- flags |= kDNSServiceFlagsIncludeAWDL;
+ DNSServiceFlags flags = deriveD2DFlagsFromAuthRecType(rr->ARType);
if (ext.rdlength == oldrdlen && mDNSPlatformMemSame(&ext.rdata->u, &oldrd->u, oldrdlen)) goto exit;
SetNewRData(&ext, oldrd, oldrdlen);
@@ -1459,7 +1502,7 @@ exit:
mDNSlocal mStatus update_record(AuthRecord *rr, mDNSu16 rdlen, const char *rdata, mDNSu32 ttl, const mDNSBool *const external_advertise)
{
mStatus result;
- const int rdsize = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody);
+ const size_t rdsize = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody);
RData *newrd = mallocL("RData/update_record", sizeof(RData) - sizeof(RDataBody) + rdsize);
if (!newrd) FatalError("ERROR: malloc");
newrd->MaxRDLength = (mDNSu16) rdsize;
@@ -1709,7 +1752,7 @@ mDNSexport mDNSs32 ChopSubTypes(char *regtype, char **AnonData)
mDNSexport AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p, char **AnonData)
{
AuthRecord *st = mDNSNULL;
- //
+ //
// "p" is pointing at the regtype e.g., _http._tcp followed by ":<AnonData>" indicated
// by AnonData being non-NULL which is in turn follwed by ",<SubTypes>" indicated by
// NumSubTypes being non-zero. We need to skip the initial regtype to get to the actual
@@ -1757,7 +1800,7 @@ mDNSexport AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p, char **Ano
if (!MakeDomainNameFromDNSNameString(&st[i].namestorage, p))
{
freeL("ServiceSubTypes", st);
- if (*AnonData)
+ if (AnonData && *AnonData)
freeL("AnonymousData", *AnonData);
return(mDNSNULL);
}
@@ -1771,7 +1814,7 @@ mDNSexport AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p, char **Ano
mDNSlocal mStatus register_service_instance(request_state *request, const domainname *domain)
{
service_instance **ptr, *instance;
- const int extra_size = (request->u.servicereg.txtlen > sizeof(RDataBody)) ? (request->u.servicereg.txtlen - sizeof(RDataBody)) : 0;
+ size_t extra_size = (request->u.servicereg.txtlen > sizeof(RDataBody)) ? (request->u.servicereg.txtlen - sizeof(RDataBody)) : 0;
const mDNSBool DomainIsLocal = SameDomainName(domain, &localdomain);
mStatus result;
mDNSInterfaceID interfaceID = request->u.servicereg.InterfaceID;
@@ -1828,14 +1871,14 @@ mDNSlocal mStatus register_service_instance(request_state *request, const domain
char *AnonData = mDNSNULL;
instance->subtypes = AllocateSubTypes(request->u.servicereg.num_subtypes, request->u.servicereg.type_as_string, &AnonData);
if (AnonData)
- instance->srs.AnonData = (const mDNSu8 *)AnonData;
+ instance->srs.AnonData = (const mDNSu8 *)AnonData;
}
if (request->u.servicereg.num_subtypes && !instance->subtypes)
- {
- unlink_and_free_service_instance(instance);
- instance = NULL;
- FatalError("ERROR: malloc");
+ {
+ unlink_and_free_service_instance(instance);
+ instance = NULL;
+ FatalError("ERROR: malloc");
}
result = mDNS_RegisterService(&mDNSStorage, &instance->srs,
@@ -1849,7 +1892,7 @@ mDNSlocal mStatus register_service_instance(request_state *request, const domain
if (!result)
{
*ptr = instance; // Append this to the end of our request->u.servicereg.instances list
- LogOperation("%3d: DNSServiceRegister(%##s, %u) ADDED", instance->request->sd,
+ LogOperation("%3d: DNSServiceRegister(%##s, %u) ADDED", instance->request->sd,
instance->srs.RR_SRV.resrec.name->c, mDNSVal16(request->u.servicereg.port));
LogMcastS(&mDNSStorage, &instance->srs.RR_SRV, request, reg_start);
}
@@ -1867,10 +1910,6 @@ mDNSlocal void udsserver_default_reg_domain_changed(const DNameListElem *const d
{
request_state *request;
-#if APPLE_OSX_mDNSResponder
- machserver_automatic_registration_domain_changed(&d->name, add);
-#endif // APPLE_OSX_mDNSResponder
-
LogMsg("%s registration domain %##s", add ? "Adding" : "Removing", d->name.c);
for (request = all_requests; request; request = request->next)
{
@@ -2045,7 +2084,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request)
request->u.servicereg.instances = NULL;
request->u.servicereg.txtlen = 0;
request->u.servicereg.txtdata = NULL;
- mDNSPlatformStrCopy(request->u.servicereg.type_as_string, type_as_string);
+ mDNSPlatformStrLCopy(request->u.servicereg.type_as_string, type_as_string, sizeof(request->u.servicereg.type_as_string));
if (request->msgptr + 2 > request->msgend) request->msgptr = NULL;
else
@@ -2148,7 +2187,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request)
}
LogOperation("%3d: DNSServiceRegister(%X, %d, \"%s\", \"%s\", \"%s\", \"%s\", %u) START PID[%d](%s)",
- request->sd, flags, interfaceIndex, name, request->u.servicereg.type_as_string, domain, host,
+ request->sd, flags, interfaceIndex, name, request->u.servicereg.type_as_string, domain, host,
mDNSVal16(request->u.servicereg.port), request->process_id, request->pid_name);
// We need to unconditionally set request->terminate, because even if we didn't successfully
@@ -2160,6 +2199,12 @@ mDNSlocal mStatus handle_regservice_request(request_state *request)
request->terminate = regservice_termination_callback;
err = register_service_instance(request, &d);
+
+#if TARGET_OS_EMBEDDED
+ ++curr_num_regservices;
+ if (curr_num_regservices > max_num_regservices)
+ max_num_regservices = curr_num_regservices;
+#endif
#if 0
err = AuthorizedDomain(request, &d, AutoRegistrationDomains) ? register_service_instance(request, &d) : mStatus_NoError;
@@ -2179,7 +2224,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request)
}
return(err);
-
+
bad_param:
freeL("handle_regservice_request (txtdata)", request->u.servicereg.txtdata);
request->u.servicereg.txtdata = NULL;
@@ -2207,14 +2252,21 @@ mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const Resourc
flags |= kDNSServiceFlagsThresholdReached;
}
+ // if returning a negative answer, then use question's name in reply
+ if (answer->RecordType == kDNSRecordTypePacketNegative)
+ {
+ GenerateBrowseReply(&question->qname, answer->InterfaceID, req, &rep, browse_reply_op, flags, kDNSServiceErr_NoSuchRecord);
+ goto validReply;
+ }
+
if (GenerateNTDResponse(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError) != mStatus_NoError)
{
if (SameDomainName(&req->u.browser.regtype, (const domainname*)"\x09_services\x07_dns-sd\x04_udp"))
{
// Special support to enable the DNSServiceBrowse call made by Bonjour Browser
// Remove after Bonjour Browser is updated to use DNSServiceQueryRecord instead of DNSServiceBrowse
- GenerateBonjourBrowserResponse(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError);
- goto bonjourbrowserhack;
+ GenerateBrowseReply(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError);
+ goto validReply;
}
LogMsg("%3d: FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
@@ -2222,7 +2274,7 @@ mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const Resourc
return;
}
-bonjourbrowserhack:
+validReply:
LogOperation("%3d: DNSServiceBrowse(%##s, %s) RESULT %s %d: %s",
req->sd, question->qname.c, DNSTypeName(question->qtype), AddRecord ? "Add" : "Rmv",
@@ -2231,6 +2283,36 @@ bonjourbrowserhack:
append_reply(req, rep);
}
+mDNSlocal void SetQuestionPolicy(DNSQuestion *q, request_state *req)
+{
+ int i;
+ q->euid = req->uid;
+ // The policy is either based on pid or UUID. Pass a zero pid
+ // to the "core" if the UUID is valid. If we always pass the pid,
+ // then the "core" needs to determine whether the uuid is valid
+ // by examining all the 16 bytes at the time of the policy
+ // check and also when setting the delegate socket option. Also, it
+ // requires that we zero out the uuid wherever the question is
+ // initialized to make sure that it is not interpreted as valid.
+ // To prevent these intrusive changes, just pass a zero pid to indicate
+ // that pid is not valid when uuid is valid. In future if we need the
+ // pid in the question, we will reevaluate this strategy.
+ if (req->validUUID)
+ {
+ for (i = 0; i < UUID_SIZE; i++)
+ {
+ q->uuid[i] = req->uuid[i];
+ }
+ q->pid = 0;
+ }
+ else
+ {
+ q->pid = req->process_id;
+ }
+
+ //debugf("SetQuestionPolicy: q->euid[%d] q->pid[%d] uuid is valid : %s", q->euid, q->pid, req->validUUID ? "true" : "false");
+}
+
mDNSlocal mStatus add_domain_to_browser(request_state *info, const domainname *d)
{
browser_t *b, *p;
@@ -2244,8 +2326,10 @@ mDNSlocal mStatus add_domain_to_browser(request_state *info, const domainname *d
b = mallocL("browser_t", sizeof(*b));
if (!b) return mStatus_NoMemoryErr;
+ mDNSPlatformMemZero(b, sizeof(*b));
AssignDomainName(&b->domain, d);
- err = mDNS_StartBrowse(&mDNSStorage, &b->q, &info->u.browser.regtype, d, info->u.browser.AnonData, info->u.browser.interface_id, info->flags,
+ SetQuestionPolicy(&b->q, info);
+ err = mDNS_StartBrowse(&mDNSStorage, &b->q, &info->u.browser.regtype, d, info->u.browser.AnonData, info->u.browser.interface_id, info->flags,
info->u.browser.ForceMCast, (info->flags & kDNSServiceFlagsBackgroundTrafficClass) != 0, FoundInstance, info);
if (err)
{
@@ -2256,7 +2340,7 @@ mDNSlocal mStatus add_domain_to_browser(request_state *info, const domainname *d
{
b->next = info->u.browser.browsers;
info->u.browser.browsers = b;
- LogOperation("%3d: DNSServiceBrowse(%##s) START PID[%d](%s)", info->sd, b->q.qname.c, info->process_id,
+ LogOperation("%3d: DNSServiceBrowse(%##s) START PID[%d](%s)", info->sd, b->q.qname.c, info->process_id,
info->pid_name);
LogMcastQ(&mDNSStorage, &b->q, info, q_start);
if (callExternalHelpers(info->u.browser.interface_id, &b->domain, info->flags))
@@ -2264,7 +2348,7 @@ mDNSlocal mStatus add_domain_to_browser(request_state *info, const domainname *d
domainname tmp;
ConstructServiceName(&tmp, NULL, &info->u.browser.regtype, &b->domain);
LogInfo("add_domain_to_browser: calling external_start_browsing_for_service()");
- external_start_browsing_for_service(info->u.browser.interface_id, &tmp, kDNSType_PTR, info->flags);
+ external_start_browsing_for_service(info->u.browser.interface_id, &tmp, kDNSType_PTR, info->flags, &b->q);
}
}
return err;
@@ -2284,18 +2368,18 @@ mDNSlocal void browse_termination_callback(request_state *info)
{
browser_t *ptr = info->u.browser.browsers;
- if (callExternalHelpers(info->u.browser.interface_id, &ptr->domain, info->flags))
+ if (callExternalHelpers(ptr->q.InterfaceID, &ptr->domain, ptr->q.flags))
{
domainname tmp;
ConstructServiceName(&tmp, NULL, &info->u.browser.regtype, &ptr->domain);
LogInfo("browse_termination_callback: calling external_stop_browsing_for_service()");
- external_stop_browsing_for_service(info->u.browser.interface_id, &tmp, kDNSType_PTR, info->flags);
+ external_stop_browsing_for_service(ptr->q.InterfaceID, &tmp, kDNSType_PTR, ptr->q.flags);
}
info->u.browser.browsers = ptr->next;
LogOperation("%3d: DNSServiceBrowse(%##s) STOP PID[%d](%s)", info->sd, ptr->q.qname.c, info->process_id, info->pid_name);
mDNS_StopBrowse(&mDNSStorage, &ptr->q); // no need to error-check result
- LogMcastQ(&mDNSStorage, &ptr->q, info, q_stop);
+ LogMcastQ(&mDNSStorage, &ptr->q, info, q_stop);
freeL("browser_t/browse_termination_callback", ptr);
}
}
@@ -2305,10 +2389,6 @@ mDNSlocal void udsserver_automatic_browse_domain_changed(const DNameListElem *co
request_state *request;
debugf("udsserver_automatic_browse_domain_changed: %s default browse domain %##s", add ? "Adding" : "Removing", d->name.c);
-#if APPLE_OSX_mDNSResponder
- machserver_automatic_browse_domain_changed(&d->name, add);
-#endif // APPLE_OSX_mDNSResponder
-
for (request = all_requests; request; request = request->next)
{
if (request->terminate != browse_termination_callback) continue; // Not a browse operation
@@ -2665,7 +2745,7 @@ mDNSlocal mStatus handle_browse_request(request_state *request)
if (!MakeDomainNameFromDNSNameString(&temp, regtype)) return(mStatus_BadParamErr);
// For over-long service types, we only allow domain "local"
- if (temp.c[0] > 15 && domain[0] == 0) mDNSPlatformStrCopy(domain, "local.");
+ if (temp.c[0] > 15 && domain[0] == 0) mDNSPlatformStrLCopy(domain, "local.", sizeof(domain));
// Set up browser info
request->u.browser.ForceMCast = (flags & kDNSServiceFlagsForceMulticast) != 0;
@@ -2674,7 +2754,7 @@ mDNSlocal mStatus handle_browse_request(request_state *request)
request->u.browser.default_domain = !domain[0];
request->u.browser.browsers = NULL;
- LogOperation("%3d: DNSServiceBrowse(%X, %d, \"%##s\", \"%s\") START PID[%d](%s)",
+ LogOperation("%3d: DNSServiceBrowse(%X, %d, \"%##s\", \"%s\") START PID[%d](%s)",
request->sd, request->flags, interfaceIndex, request->u.browser.regtype.c, domain, request->process_id, request->pid_name);
if (request->u.browser.default_domain)
@@ -2730,10 +2810,12 @@ mDNSlocal mStatus handle_browse_request(request_state *request)
mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
{
size_t len = 0;
- char fullname[MAX_ESCAPED_DOMAIN_NAME], target[MAX_ESCAPED_DOMAIN_NAME];
+ char fullname[MAX_ESCAPED_DOMAIN_NAME], target[MAX_ESCAPED_DOMAIN_NAME] = "0";
char *data;
reply_state *rep;
request_state *req = question->QuestionContext;
+ const DNSServiceErrorType error =
+ (answer->RecordType == kDNSRecordTypePacketNegative) ? kDNSServiceErr_NoSuchRecord : kDNSServiceErr_NoError;
(void)m; // Unused
LogOperation("%3d: DNSServiceResolve(%##s) %s %s", req->sd, question->qname.c, AddRecord ? "ADD" : "RMV", RRDisplayString(m, answer));
@@ -2751,7 +2833,9 @@ mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, con
if (!req->u.resolve.txt || !req->u.resolve.srv) return; // only deliver result to client if we have both answers
ConvertDomainNameToCString(answer->name, fullname);
- ConvertDomainNameToCString(&req->u.resolve.srv->rdata->u.srv.target, target);
+
+ if (answer->RecordType != kDNSRecordTypePacketNegative)
+ ConvertDomainNameToCString(&req->u.resolve.srv->rdata->u.srv.target, target);
// calculate reply length
len += sizeof(DNSServiceFlags);
@@ -2766,7 +2850,7 @@ mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, con
rep = create_reply(resolve_reply_op, len, req);
rep->rhdr->flags = dnssd_htonl(0);
rep->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse));
- rep->rhdr->error = dnssd_htonl(kDNSServiceErr_NoError);
+ rep->rhdr->error = dnssd_htonl(error);
data = (char *)&rep->rhdr[1];
@@ -2788,7 +2872,7 @@ mDNSlocal void resolve_termination_callback(request_state *request)
mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qtxt);
mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qsrv);
LogMcastQ(&mDNSStorage, &request->u.resolve.qsrv, request, q_stop);
- if (request->u.resolve.external_advertise)
+ if (request->u.resolve.external_advertise)
external_stop_resolving_service(request->u.resolve.qsrv.InterfaceID, &request->u.resolve.qsrv.qname, request->flags);
}
@@ -2858,8 +2942,6 @@ mDNSlocal mStatus handle_resolve_request(request_state *request)
request->u.resolve.qsrv.ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0;
request->u.resolve.qsrv.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
request->u.resolve.qsrv.SuppressUnusable = mDNSfalse;
- request->u.resolve.qsrv.DenyOnCellInterface = mDNSfalse;
- request->u.resolve.qsrv.DenyOnExpInterface = mDNSfalse;
request->u.resolve.qsrv.SearchListIndex = 0;
request->u.resolve.qsrv.AppendSearchDomains = 0;
request->u.resolve.qsrv.RetryWithSearchDomains = mDNSfalse;
@@ -2887,8 +2969,6 @@ mDNSlocal mStatus handle_resolve_request(request_state *request)
request->u.resolve.qtxt.ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0;
request->u.resolve.qtxt.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
request->u.resolve.qtxt.SuppressUnusable = mDNSfalse;
- request->u.resolve.qtxt.DenyOnCellInterface = mDNSfalse;
- request->u.resolve.qtxt.DenyOnExpInterface = mDNSfalse;
request->u.resolve.qtxt.SearchListIndex = 0;
request->u.resolve.qtxt.AppendSearchDomains = 0;
request->u.resolve.qtxt.RetryWithSearchDomains = mDNSfalse;
@@ -2914,15 +2994,15 @@ mDNSlocal mStatus handle_resolve_request(request_state *request)
#endif
// ask the questions
- LogOperation("%3d: DNSServiceResolve(%X %d %##s) START PID[%d](%s)", request->sd, flags, interfaceIndex,
- request->u.resolve.qsrv.qname.c, request->process_id, request->pid_name);
+ LogOperation("%3d: DNSServiceResolve(%X %d %##s) START PID[%d](%s)", request->sd, flags, interfaceIndex,
+ request->u.resolve.qsrv.qname.c, request->process_id, request->pid_name);
err = mDNS_StartQuery(&mDNSStorage, &request->u.resolve.qsrv);
-
+
if (!err)
{
err = mDNS_StartQuery(&mDNSStorage, &request->u.resolve.qtxt);
if (err)
- {
+ {
mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qsrv);
}
else
@@ -3198,7 +3278,7 @@ mDNSlocal mStatus SendAdditionalQuery(DNSQuestion *q, request_state *request, mS
(void) q;
(void) request;
(void) err;
-
+
return mStatus_NoError;
#endif // !UNICAST_DISABLED
}
@@ -3279,7 +3359,7 @@ mDNSlocal void queryrecord_result_reply(mDNS *const m, request_state *req, DNSQu
rep = create_reply(req->hdr.op == query_request ? query_reply_op : addrinfo_reply_op, len, req);
if (AddRecord)
- flags |= kDNSServiceFlagsAdd;
+ flags |= kDNSServiceFlagsAdd;
if (question->ValidationStatus != 0)
{
error = kDNSServiceErr_NoError;
@@ -3304,7 +3384,7 @@ mDNSlocal void queryrecord_result_reply(mDNS *const m, request_state *req, DNSQu
}
}
}
-
+
rep->rhdr->flags = dnssd_htonl(flags);
// Call mDNSPlatformInterfaceIndexfromInterfaceID, but suppressNetworkChange (last argument). Otherwise, if the
// InterfaceID is not valid, then it simulates a "NetworkChanged" which in turn makes questions
@@ -3622,7 +3702,7 @@ mDNSlocal void queryrecord_result_callback(mDNS *const m, DNSQuestion *question,
mDNSlocal void queryrecord_termination_callback(request_state *request)
{
LogOperation("%3d: DNSServiceQueryRecord(%##s, %s) STOP PID[%d](%s)",
- request->sd, request->u.queryrecord.q.qname.c, DNSTypeName(request->u.queryrecord.q.qtype), request->process_id, request->pid_name);
+ request->sd, request->u.queryrecord.q.qname.c, DNSTypeName(request->u.queryrecord.q.qtype), request->process_id, request->pid_name);
if (request->u.queryrecord.q.QuestionContext)
{
mDNS_StopQuery(&mDNSStorage, &request->u.queryrecord.q); // no need to error check
@@ -3686,40 +3766,11 @@ mDNSlocal void queryrecord_termination_callback(request_state *request)
#endif // APPLE_OSX_mDNSResponder
}
-mDNSlocal void SetQuestionPolicy(DNSQuestion *q, request_state *req)
-{
- int i;
- q->euid = req->uid;
- // The policy is either based on pid or UUID. Pass a zero pid
- // to the "core" if the UUID is valid. If we always pass the pid,
- // then the "core" needs to determine whether the uuid is valid
- // by examining all the 16 bytes at the time of the policy
- // check and also when setting the delegate socket option. Also, it
- // requires that we zero out the uuid wherever the question is
- // initialized to make sure that it is not interpreted as valid.
- // To prevent these intrusive changes, just pass a zero pid to indicate
- // that pid is not valid when uuid is valid. In future if we need the
- // pid in the question, we will reevaluate this strategy.
- if (req->validUUID)
- {
- for (i = 0; i < UUID_SIZE; i++)
- {
- q->uuid[i] = req->uuid[i];
- }
- q->pid = 0;
- }
- else
- {
- q->pid = req->process_id;
- }
-
- //debugf("SetQuestionPolicy: q->euid[%d] q->pid[%d] uuid is valid : %s", q->euid, q->pid, req->validUUID ? "true" : "false");
-}
-
mDNSlocal mStatus handle_queryrecord_request(request_state *request)
{
DNSQuestion *const q = &request->u.queryrecord.q;
char name[256];
+ size_t nameLen;
mDNSu16 rrtype, rrclass;
mStatus err;
@@ -3731,6 +3782,9 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request)
// interface is not currently in our list.
if (interfaceIndex && !InterfaceID)
{
+ if (interfaceIndex > 1)
+ LogMsg("handle_queryrecord_request: interfaceIndex %d is currently inactive requested by client[%d][%s]",
+ interfaceIndex, request->process_id, request->pid_name);
// If it's one of the specially defined inteface index values, just return an error.
// Also, caller should return an error immediately if lo0 (index 1) is not configured
// into the current active interfaces. See background in Radar 21967160.
@@ -3774,8 +3828,6 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request)
q->TimeoutQuestion = (flags & kDNSServiceFlagsTimeout ) != 0;
q->WakeOnResolve = 0;
q->UseBackgroundTrafficClass = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
- q->DenyOnCellInterface = (flags & kDNSServiceFlagsDenyCellular) != 0;
- q->DenyOnExpInterface = (flags & kDNSServiceFlagsDenyExpensive) != 0;
if ((flags & kDNSServiceFlagsValidate) != 0)
q->ValidationRequired = DNSSEC_VALIDATION_SECURE;
else if ((flags & kDNSServiceFlagsValidateOptional) != 0)
@@ -3793,7 +3845,7 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request)
//Turn off dnssec validation for local domains and Question Types: RRSIG/ANY(ANY Type is not supported yet)
if ((IsLocalDomain(&q->qname)) || (q->qtype == kDNSServiceType_RRSIG) || (q->qtype == kDNSServiceType_ANY))
q->ValidationRequired = 0;
-
+
// Don't append search domains for fully qualified domain names including queries
// such as e.g., "abc." that has only one label. We convert all names to FQDNs as internally
// we only deal with FQDNs. Hence, we cannot look at qname to figure out whether we should
@@ -3803,9 +3855,10 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request)
// argument "AlwaysAppendSearchDomains", then we do it for any query which is not fully qualified.
// For DNSSEC questions, append search domains only if kDNSServiceFlagsValidateOptional is set.
- if ((!(q->ValidationRequired == DNSSEC_VALIDATION_SECURE)) && (!(q->ValidationRequired == DNSSEC_VALIDATION_INSECURE))
- && (rrtype == kDNSType_A || rrtype == kDNSType_AAAA) && name[strlen(name) - 1] != '.' &&
- (AlwaysAppendSearchDomains || CountLabels(&q->qname) == 1))
+ nameLen = strlen(name);
+ if ((!(q->ValidationRequired == DNSSEC_VALIDATION_SECURE)) && (!(q->ValidationRequired == DNSSEC_VALIDATION_INSECURE))
+ && (rrtype == kDNSType_A || rrtype == kDNSType_AAAA) && ((nameLen == 0) || (name[nameLen - 1] != '.')) &&
+ (AlwaysAppendSearchDomains || CountLabels(&q->qname) == 1))
{
q->AppendSearchDomains = 1;
q->AppendLocalSearchDomains = 1;
@@ -3825,13 +3878,13 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request)
SetQuestionPolicy(q, request);
LogOperation("%3d: DNSServiceQueryRecord(%X, %d, %##s, %s) START PID[%d](%s)",
- request->sd, flags, interfaceIndex, q->qname.c, DNSTypeName(q->qtype), request->process_id, request->pid_name);
+ request->sd, flags, interfaceIndex, q->qname.c, DNSTypeName(q->qtype), request->process_id, request->pid_name);
err = mDNS_StartQuery(&mDNSStorage, q);
-
+
if (err)
- {
+ {
LogMsg("%3d: ERROR: DNSServiceQueryRecord %##s %s mDNS_StartQuery: %d", request->sd, q->qname.c, DNSTypeName(q->qtype), (int)err);
- }
+ }
else
{
request->terminate = queryrecord_termination_callback;
@@ -3839,7 +3892,7 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request)
if (callExternalHelpers(q->InterfaceID, &q->qname, flags))
{
LogInfo("handle_queryrecord_request: calling external_start_browsing_for_service()");
- external_start_browsing_for_service(q->InterfaceID, &q->qname, q->qtype, flags);
+ external_start_browsing_for_service(q->InterfaceID, &q->qname, q->qtype, flags, q);
}
}
@@ -3888,7 +3941,8 @@ mDNSlocal void enum_termination_callback(request_state *request)
else
{
LogInfo("%3d: DNSServiceEnumeration Cancel WAB Browse PID[%d](%s)", request->sd, request->process_id, request->pid_name);
- uDNS_StopWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY);
+ uDNS_StopWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY | UDNS_WAB_LBROWSE_QUERY);
+ mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_autoall);
}
mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all);
mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_default);
@@ -3955,6 +4009,7 @@ mDNSlocal mStatus handle_enum_request(request_state *request)
// necessary context can be reached from the callbacks
request->u.enumeration.q_all.QuestionContext = request;
request->u.enumeration.q_default.QuestionContext = request;
+ if (!reg) request->u.enumeration.q_autoall.QuestionContext = request;
// if the caller hasn't specified an explicit interface, we use local-only to get the system-wide list.
if (!InterfaceID) InterfaceID = mDNSInterface_LocalOnly;
@@ -3968,7 +4023,16 @@ mDNSlocal mStatus handle_enum_request(request_state *request)
{
err = mDNS_GetDomains(&mDNSStorage, &request->u.enumeration.q_default, t_default, NULL, InterfaceID, enum_result_callback, request);
if (err) mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all);
- else request->terminate = enum_termination_callback;
+ else if (!reg)
+ {
+ err = mDNS_GetDomains(&mDNSStorage, &request->u.enumeration.q_autoall, mDNS_DomainTypeBrowseAutomatic, NULL, InterfaceID, enum_result_callback, request);
+ if (err)
+ {
+ mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all);
+ mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_default);
+ }
+ }
+ if (!err) request->terminate = enum_termination_callback;
}
if (!err)
{
@@ -3978,10 +4042,10 @@ mDNSlocal mStatus handle_enum_request(request_state *request)
LogInfo("%3d: DNSServiceEnumerateDomains Start WAB Registration PID[%d](%s)", request->sd, request->process_id, request->pid_name);
uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_REG_QUERY);
}
- else
+ else
{
LogInfo("%3d: DNSServiceEnumerateDomains Start WAB Browse PID[%d](%s)", request->sd, request->process_id, request->pid_name);
- uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY);
+ uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY | UDNS_WAB_LBROWSE_QUERY);
}
}
@@ -4045,7 +4109,7 @@ mDNSlocal mStatus handle_release_request(request_state *request)
LogOperation("%3d: PeerConnectionRelease(%X %##s) START PID[%d](%s)",
request->sd, flags, instance.c, request->process_id, request->pid_name);
-
+
external_connection_release(&instance);
return(err);
}
@@ -4054,7 +4118,7 @@ mDNSlocal mStatus handle_release_request(request_state *request)
mDNSlocal mStatus handle_release_request(request_state *request)
{
- (void) request;
+ (void) request;
return mStatus_UnsupportedErr;
}
@@ -4116,11 +4180,14 @@ mDNSlocal void handle_connection_delegate_request(request_state *request)
{
len = sizeof(pid);
if (getsockopt(request->sd, SOL_LOCAL, LOCAL_PEEREPID, &request->process_id, &len) != 0)
+ {
+ LogMsg("handle_connection_delegate_request: getsockopt for LOCAL_PEEREPID failed errno:%d / %s", errno, strerror(errno));
return;
+ }
// to extract the process name from the pid value
if (proc_pidinfo(request->process_id, PROC_PIDT_SHORTBSDINFO, 1, &proc, PROC_PIDT_SHORTBSDINFO_SIZE) == 0)
return;
- mDNSPlatformStrCopy(request->pid_name, proc.pbsi_comm);
+ mDNSPlatformStrLCopy(request->pid_name, proc.pbsi_comm, sizeof(request->pid_name));
debugf("handle_connection_delegate_request: process id %d, name %s", request->process_id, request->pid_name);
}
#endif
@@ -4129,7 +4196,10 @@ mDNSlocal void handle_connection_delegate_request(request_state *request)
{
len = UUID_SIZE;
if (getsockopt(request->sd, SOL_LOCAL, LOCAL_PEEREUUID, request->uuid, &len) != 0)
+ {
+ LogMsg("handle_connection_delegate_request: getsockopt for LOCAL_PEEREUUID failed errno:%d / %s", errno, strerror(errno));
return;
+ }
request->validUUID = mDNStrue;
}
#endif
@@ -4197,7 +4267,7 @@ mDNSlocal void handle_getpid_request(request_state *request)
}
}
}
-
+
pi.err = 0;
pi.pid = pid;
send_all(request->sd, (const char *)&pi, sizeof(PIDInfo));
@@ -4216,8 +4286,8 @@ mDNSlocal void port_mapping_termination_callback(request_state *request)
{
LogOperation("%3d: DNSServiceNATPortMappingCreate(%X, %u, %u, %d) STOP PID[%d](%s)", request->sd,
DNSServiceProtocol(request->u.pm.NATinfo.Protocol),
- mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease,
- request->process_id, request->pid_name);
+ mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease,
+ request->process_id, request->pid_name);
mDNS_StopNATOperation(&mDNSStorage, &request->u.pm.NATinfo);
}
@@ -4309,8 +4379,8 @@ mDNSlocal mStatus handle_port_mapping_request(request_state *request)
request->u.pm.NATinfo.clientContext = request;
LogOperation("%3d: DNSServiceNATPortMappingCreate(%X, %u, %u, %d) START PID[%d](%s)", request->sd,
- protocol, mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease,
- request->process_id, request->pid_name);
+ protocol, mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease,
+ request->process_id, request->pid_name);
err = mDNS_StartNATOperation(&mDNSStorage, &request->u.pm.NATinfo);
if (err) LogMsg("ERROR: mDNS_StartNATOperation: %d", (int)err);
else request->terminate = port_mapping_termination_callback;
@@ -4327,13 +4397,19 @@ mDNSlocal mStatus handle_port_mapping_request(request_state *request)
mDNSlocal void addrinfo_termination_callback(request_state *request)
{
LogOperation("%3d: DNSServiceGetAddrInfo(%##s) STOP PID[%d](%s)", request->sd, request->u.addrinfo.q4.qname.c,
- request->process_id, request->pid_name);
+ request->process_id, request->pid_name);
if (request->u.addrinfo.q4.QuestionContext)
{
mDNS_StopQuery(&mDNSStorage, &request->u.addrinfo.q4);
LogMcastQ(&mDNSStorage, &request->u.addrinfo.q4, request, q_stop);
request->u.addrinfo.q4.QuestionContext = mDNSNULL;
+
+ if (callExternalHelpers(request->u.addrinfo.interface_id, &request->u.addrinfo.q4.qname, request->flags))
+ {
+ LogInfo("addrinfo_termination_callback: calling external_stop_browsing_for_service() for kDNSServiceType_A record");
+ external_stop_browsing_for_service(request->u.addrinfo.interface_id, &request->u.addrinfo.q4.qname, kDNSServiceType_A, request->flags);
+ }
}
if (request->u.addrinfo.q4.qnameOrig)
{
@@ -4363,6 +4439,12 @@ mDNSlocal void addrinfo_termination_callback(request_state *request)
mDNS_StopQuery(&mDNSStorage, &request->u.addrinfo.q6);
LogMcastQ(&mDNSStorage, &request->u.addrinfo.q6, request, q_stop);
request->u.addrinfo.q6.QuestionContext = mDNSNULL;
+
+ if (callExternalHelpers(request->u.addrinfo.interface_id, &request->u.addrinfo.q6.qname, request->flags))
+ {
+ LogInfo("addrinfo_termination_callback: calling external_stop_browsing_for_service() for kDNSServiceType_AAAA record");
+ external_stop_browsing_for_service(request->u.addrinfo.interface_id, &request->u.addrinfo.q6.qname, kDNSServiceType_AAAA, request->flags);
+ }
}
if (request->u.addrinfo.q6.qnameOrig)
{
@@ -4421,13 +4503,14 @@ mDNSlocal void addrinfo_termination_callback(request_state *request)
mDNSlocal mStatus handle_addrinfo_request(request_state *request)
{
char hostname[256];
+ size_t hostnameLen;
domainname d;
mStatus err = 0;
mDNSs32 serviceIndex = -1; // default unscoped value for ServiceID is -1
mDNSInterfaceID InterfaceID;
-
+
DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend);
-
+
mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend);
if (flags & kDNSServiceFlagsServiceIndex)
@@ -4439,7 +4522,7 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
serviceIndex = interfaceIndex;
interfaceIndex = 0;
}
-
+
mDNSPlatformMemZero(&request->u.addrinfo, sizeof(request->u.addrinfo));
InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex);
@@ -4448,6 +4531,9 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
// interface is not currently in our list.
if (interfaceIndex && !InterfaceID)
{
+ if (interfaceIndex > 1)
+ LogMsg("handle_addrinfo_request: interfaceIndex %d is currently inactive requested by client[%d][%s]",
+ interfaceIndex, request->process_id, request->pid_name);
// If it's one of the specially defined inteface index values, just return an error.
if (PreDefinedInterfaceIndex(interfaceIndex))
{
@@ -4455,7 +4541,7 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
return(mStatus_BadParamErr);
}
- // Otherwise, use the specified interface index value and the registration will
+ // Otherwise, use the specified interface index value and the request will
// be applied to that interface when it comes up.
InterfaceID = (mDNSInterfaceID)(uintptr_t)interfaceIndex;
LogInfo("handle_addrinfo_request: query pending for interface index %d", interfaceIndex);
@@ -4500,8 +4586,6 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
request->u.addrinfo.q4.TimeoutQuestion = request->u.addrinfo.q6.TimeoutQuestion = (flags & kDNSServiceFlagsTimeout ) != 0;
request->u.addrinfo.q4.WakeOnResolve = request->u.addrinfo.q6.WakeOnResolve = 0;
request->u.addrinfo.q4.UseBackgroundTrafficClass = request->u.addrinfo.q6.UseBackgroundTrafficClass = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
- request->u.addrinfo.q4.DenyOnCellInterface = request->u.addrinfo.q6.DenyOnCellInterface = (flags & kDNSServiceFlagsDenyCellular) != 0;
- request->u.addrinfo.q4.DenyOnExpInterface = request->u.addrinfo.q6.DenyOnExpInterface = (flags & kDNSServiceFlagsDenyExpensive) != 0;
if ((flags & kDNSServiceFlagsValidate) != 0)
request->u.addrinfo.q4.ValidationRequired = request->u.addrinfo.q6.ValidationRequired = DNSSEC_VALIDATION_SECURE;
else if ((flags & kDNSServiceFlagsValidateOptional) != 0)
@@ -4521,13 +4605,18 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
if (IsLocalDomain(&d))
request->u.addrinfo.q4.ValidationRequired = request->u.addrinfo.q6.ValidationRequired = 0;
+ hostnameLen = strlen(hostname);
+
+ LogOperation("%3d: DNSServiceGetAddrInfo(%X, %d, %d, %##s) START PID[%d](%s)",
+ request->sd, flags, interfaceIndex, request->u.addrinfo.protocol, d.c, request->process_id, request->pid_name);
+
if (request->u.addrinfo.protocol & kDNSServiceProtocol_IPv6)
{
request->u.addrinfo.q6.qtype = kDNSServiceType_AAAA;
request->u.addrinfo.q6.SearchListIndex = 0;
// For DNSSEC questions, append search domains only if kDNSServiceFlagsValidateOptional is set
- if ((!(request->u.addrinfo.q6.ValidationRequired == DNSSEC_VALIDATION_SECURE)) && (!(request->u.addrinfo.q6.ValidationRequired == DNSSEC_VALIDATION_INSECURE))
- && hostname[strlen(hostname) - 1] != '.' && (AlwaysAppendSearchDomains || CountLabels(&d) == 1))
+ if ((!(request->u.addrinfo.q6.ValidationRequired == DNSSEC_VALIDATION_SECURE)) && (!(request->u.addrinfo.q6.ValidationRequired == DNSSEC_VALIDATION_INSECURE))
+ && ((hostnameLen == 0) || (hostname[hostnameLen - 1] != '.')) && (AlwaysAppendSearchDomains || CountLabels(&d) == 1))
{
request->u.addrinfo.q6.AppendSearchDomains = 1;
request->u.addrinfo.q6.AppendLocalSearchDomains = 1;
@@ -4550,9 +4639,14 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
err = SendAdditionalQuery(&request->u.addrinfo.q6, request, err);
#endif // APPLE_OSX_mDNSResponder
if (!err)
- {
+ {
request->terminate = addrinfo_termination_callback;
LogMcastQ(&mDNSStorage, &request->u.addrinfo.q6, request, q_start);
+ if (callExternalHelpers(InterfaceID, &d, flags))
+ {
+ LogInfo("handle_addrinfo_request: calling external_start_browsing_for_service() for kDNSServiceType_AAAA record");
+ external_start_browsing_for_service(InterfaceID, &d, kDNSServiceType_AAAA, flags, &request->u.addrinfo.q6);
+ }
}
}
@@ -4565,8 +4659,8 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
// "AlwaysAppendSearchDomains", then we do it for any query which is not fully qualified.
// For DNSSEC questions, append search domains only if kDNSServiceFlagsValidateOptional is set.
- if ((!(request->u.addrinfo.q4.ValidationRequired == DNSSEC_VALIDATION_SECURE)) && (!(request->u.addrinfo.q4.ValidationRequired == DNSSEC_VALIDATION_INSECURE))
- && hostname[strlen(hostname) - 1] != '.' && (AlwaysAppendSearchDomains || CountLabels(&d) == 1))
+ if ((!(request->u.addrinfo.q4.ValidationRequired == DNSSEC_VALIDATION_SECURE)) && (!(request->u.addrinfo.q4.ValidationRequired == DNSSEC_VALIDATION_INSECURE))
+ && ((hostnameLen == 0) || (hostname[hostnameLen - 1] != '.')) && (AlwaysAppendSearchDomains || CountLabels(&d) == 1))
{
request->u.addrinfo.q4.AppendSearchDomains = 1;
request->u.addrinfo.q4.AppendLocalSearchDomains = 1;
@@ -4585,11 +4679,17 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
LogMsg("ERROR: mDNS_StartQuery: %d", (int)err);
request->u.addrinfo.q4.QuestionContext = mDNSNULL;
if (request->u.addrinfo.protocol & kDNSServiceProtocol_IPv6)
- {
- // If we started a query for IPv6, we need to cancel it
+ {
+ // If we started a query for IPv6, we need to cancel it
mDNS_StopQuery(&mDNSStorage, &request->u.addrinfo.q6);
request->u.addrinfo.q6.QuestionContext = mDNSNULL;
- }
+
+ if (callExternalHelpers(InterfaceID, &d, flags))
+ {
+ LogInfo("addrinfo_termination_callback: calling external_stop_browsing_for_service() for kDNSServiceType_AAAA record");
+ external_stop_browsing_for_service(InterfaceID, &d, kDNSServiceType_AAAA, flags);
+ }
+ }
}
#if APPLE_OSX_mDNSResponder
err = SendAdditionalQuery(&request->u.addrinfo.q4, request, err);
@@ -4598,10 +4698,14 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
{
request->terminate = addrinfo_termination_callback;
LogMcastQ(&mDNSStorage, &request->u.addrinfo.q4, request, q_start);
- }
+ if (callExternalHelpers(InterfaceID, &d, flags))
+ {
+ LogInfo("handle_addrinfo_request: calling external_start_browsing_for_service() for kDNSServiceType_A record");
+ external_start_browsing_for_service(InterfaceID, &d, kDNSServiceType_A, flags, &request->u.addrinfo.q4);
+ }
+ }
}
- LogOperation("%3d: DNSServiceGetAddrInfo(%X, %d, %d, %##s) START PID[%d](%s)", request->sd, flags, interfaceIndex, request->u.addrinfo.protocol, d.c, request->process_id, request->pid_name);
return(err);
}
@@ -4614,10 +4718,10 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
mDNSlocal request_state *NewRequest(void)
{
request_state **p = &all_requests;
- while (*p)
+ while (*p)
p=&(*p)->next;
*p = mallocL("request_state", sizeof(request_state));
- if (!*p)
+ if (!*p)
FatalError("ERROR: malloc");
mDNSPlatformMemZero(*p, sizeof(request_state));
return(*p);
@@ -4758,7 +4862,7 @@ mDNSlocal void read_msg(request_state *req)
get_string(&req->msgptr, req->msgend, ctrl_path, MAX_CTLPATH); // path is first element in message buffer
mDNSPlatformMemZero(&cliaddr, sizeof(cliaddr));
cliaddr.sun_family = AF_LOCAL;
- mDNSPlatformStrCopy(cliaddr.sun_path, ctrl_path);
+ mDNSPlatformStrLCopy(cliaddr.sun_path, ctrl_path, sizeof(cliaddr.sun_path));
// If the error return path UDS name is empty string, that tells us
// that this is a new version of the library that's going to pass us
// the error return path socket via sendmsg/recvmsg
@@ -4771,8 +4875,8 @@ mDNSlocal void read_msg(request_state *req)
#endif
req->errsd = socket(AF_DNSSD, SOCK_STREAM, 0);
- if (!dnssd_SocketValid(req->errsd))
- {
+ if (!dnssd_SocketValid(req->errsd))
+ {
my_throttled_perror("ERROR: socket");
req->ts = t_error;
return;
@@ -4838,22 +4942,22 @@ mDNSlocal void request_callback(int fd, short filter, void *info)
for (;;)
{
read_msg(req);
- if (req->ts == t_morecoming)
+ if (req->ts == t_morecoming)
+ return;
+ if (req->ts == t_terminated || req->ts == t_error)
+ {
+ AbortUnlinkAndFree(req);
return;
- if (req->ts == t_terminated || req->ts == t_error)
- {
- AbortUnlinkAndFree(req);
- return;
}
- if (req->ts != t_complete)
- {
- LogMsg("request_callback: req->ts %d != t_complete PID[%d][%s]", req->ts, req->process_id, req->pid_name);
- AbortUnlinkAndFree(req);
- return;
+ if (req->ts != t_complete)
+ {
+ LogMsg("request_callback: req->ts %d != t_complete PID[%d][%s]", req->ts, req->process_id, req->pid_name);
+ AbortUnlinkAndFree(req);
+ return;
}
if (req->hdr.version != VERSION)
{
- LogMsg("request_callback: ERROR: client IPC version %d incompatible with daemon IPC version %d PID[%d][%s]",
+ LogMsg("request_callback: ERROR: client IPC version %d incompatible with daemon IPC version %d PID[%d][%s]",
req->hdr.version, VERSION, req->process_id, req->pid_name);
AbortUnlinkAndFree(req);
return;
@@ -4881,24 +4985,24 @@ mDNSlocal void request_callback(int fd, short filter, void *info)
case send_bpf: // Same as cancel_request below
case cancel_request: min_size = 0; break;
case release_request: min_size += sizeof(mDNSu32) + 3 /* type, type, domain */; break;
- default: LogMsg("request_callback: ERROR: validate_message - unsupported req type: %d PID[%d][%s]",
- req->hdr.op, req->process_id, req->pid_name);
+ default: LogMsg("request_callback: ERROR: validate_message - unsupported req type: %d PID[%d][%s]",
+ req->hdr.op, req->process_id, req->pid_name);
min_size = -1; break;
}
if ((mDNSs32)req->data_bytes < min_size)
- {
- LogMsg("request_callback: Invalid message %d bytes; min for %d is %d PID[%d][%s]",
- req->data_bytes, req->hdr.op, min_size, req->process_id, req->pid_name);
- AbortUnlinkAndFree(req);
- return;
+ {
+ LogMsg("request_callback: Invalid message %d bytes; min for %d is %d PID[%d][%s]",
+ req->data_bytes, req->hdr.op, min_size, req->process_id, req->pid_name);
+ AbortUnlinkAndFree(req);
+ return;
}
if (LightweightOp(req->hdr.op) && !req->terminate)
- {
- LogMsg("request_callback: Reg/Add/Update/Remove %d require existing connection PID[%d][%s]",
- req->hdr.op, req->process_id, req->pid_name);
- AbortUnlinkAndFree(req);
- return;
+ {
+ LogMsg("request_callback: Reg/Add/Update/Remove %d require existing connection PID[%d][%s]",
+ req->hdr.op, req->process_id, req->pid_name);
+ AbortUnlinkAndFree(req);
+ return;
}
// If req->terminate is already set, this means this operation is sharing an existing connection
@@ -4929,6 +5033,7 @@ mDNSlocal void request_callback(int fd, short filter, void *info)
if (req->process_id)
{
newreq->process_id = req->process_id;
+ mDNSPlatformStrLCopy(newreq->pid_name, req->pid_name, (mDNSu32)sizeof(newreq->pid_name));
}
else
{
@@ -4948,7 +5053,7 @@ mDNSlocal void request_callback(int fd, short filter, void *info)
err = mStatus_ServiceNotRunning;
}
else
- {
+ {
switch(req->hdr.op)
{
// These are all operations that have their own first-class request_state object
@@ -4983,7 +5088,7 @@ mDNSlocal void request_callback(int fd, short filter, void *info)
case remove_record_request: err = handle_removerecord_request(req); break;
case cancel_request: handle_cancel_request (req); break;
case release_request: err = handle_release_request (req); break;
- default: LogMsg("request_callback: %3d:ERROR: Unsupported UDS req:%d PID[%d][%s]",
+ default: LogMsg("request_callback: %3d:ERROR: Unsupported UDS req:%d PID[%d][%s]",
req->sd, req->hdr.op, req->process_id, req->pid_name); break;
}
}
@@ -5032,7 +5137,7 @@ mDNSlocal void connect_callback(int fd, short filter, void *info)
if (!dnssd_SocketValid(sd))
{
- if (dnssd_errno != dnssd_EWOULDBLOCK)
+ if (dnssd_errno != dnssd_EWOULDBLOCK)
my_throttled_perror("ERROR: accept");
return;
}
@@ -5063,9 +5168,9 @@ mDNSlocal void connect_callback(int fd, short filter, void *info)
#if APPLE_OSX_mDNSResponder
struct xucred x;
socklen_t xucredlen = sizeof(x);
- if (getsockopt(sd, 0, LOCAL_PEERCRED, &x, &xucredlen) >= 0 && x.cr_version == XUCRED_VERSION)
+ if (getsockopt(sd, 0, LOCAL_PEERCRED, &x, &xucredlen) >= 0 && x.cr_version == XUCRED_VERSION)
request->uid = x.cr_uid; // save the effective userid of the client
- else
+ else
my_perror("ERROR: getsockopt, LOCAL_PEERCRED");
debugf("LOCAL_PEERCRED %d %u %u %d", xucredlen, x.cr_version, x.cr_uid, x.cr_ngroups);
@@ -5110,7 +5215,7 @@ mDNSlocal mDNSBool uds_socket_setup(dnssd_sock_t skt)
return mDNSfalse;
}
else
- {
+ {
LogOperation("%3d: Listening for incoming Unix Domain Socket client requests", skt);
mDNSStorage.uds_listener_skt = skt;
}
@@ -5168,19 +5273,19 @@ mDNSexport int udsserver_init(dnssd_sock_t skts[], mDNSu32 count)
#else
{
mode_t mask = umask(0);
- unlink(MDNS_UDS_SERVERPATH); // OK if this fails
+ unlink(boundPath); // OK if this fails
laddr.sun_family = AF_LOCAL;
#ifndef NOT_HAVE_SA_LEN
// According to Stevens (section 3.2), there is no portable way to
// determine whether sa_len is defined on a particular platform.
laddr.sun_len = sizeof(struct sockaddr_un);
#endif
- if (strlen(MDNS_UDS_SERVERPATH) >= sizeof(laddr.sun_path))
+ if (strlen(boundPath) >= sizeof(laddr.sun_path))
{
LogMsg("ERROR: MDNS_UDS_SERVERPATH must be < %d characters", (int)sizeof(laddr.sun_path));
goto error;
}
- mDNSPlatformStrCopy(laddr.sun_path, MDNS_UDS_SERVERPATH);
+ mDNSPlatformStrLCopy(laddr.sun_path, boundPath, sizeof(laddr.sun_path));
ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr));
umask(mask);
if (ret < 0)
@@ -5260,7 +5365,7 @@ mDNSexport int udsserver_exit(void)
// Currently, we're unable to remove /var/run/mdnsd because we've changed to userid "nobody"
// to give up unnecessary privilege, but we need to be root to remove this Unix Domain Socket.
// It would be nice if we could find a solution to this problem
- if (unlink(MDNS_UDS_SERVERPATH))
+ if (unlink(boundPath))
debugf("Unable to remove %s", MDNS_UDS_SERVERPATH);
#endif
}
@@ -5273,9 +5378,9 @@ mDNSexport int udsserver_exit(void)
mDNSlocal void LogClientInfo(mDNS *const m, request_state *req)
{
char prefix[16];
- if (req->primary)
+ if (req->primary)
mDNS_snprintf(prefix, sizeof(prefix), " -> ");
- else
+ else
mDNS_snprintf(prefix, sizeof(prefix), "%3d:", req->sd);
if (!req->terminate)
@@ -5287,8 +5392,8 @@ mDNSlocal void LogClientInfo(mDNS *const m, request_state *req)
request_state *r;
for (p = req->u.reg_recs; p; p=p->next) num_records++;
for (r = req->next; r; r=r->next) if (r->primary == req) num_ops++;
- LogMsgNoIdent("%s DNSServiceCreateConnection: %d registered record%s, %d kDNSServiceFlagsShareConnection operation%s PID[%d](%s)",
- prefix, num_records, num_records != 1 ? "s" : "", num_ops, num_ops != 1 ? "s" : "",
+ LogMsgNoIdent("%s DNSServiceCreateConnection: %d registered record%s, %d kDNSServiceFlagsShareConnection operation%s PID[%d](%s)",
+ prefix, num_records, num_records != 1 ? "s" : "", num_ops, num_ops != 1 ? "s" : "",
req->process_id, req->pid_name);
for (p = req->u.reg_recs; p; p=p->next)
LogMsgNoIdent(" -> DNSServiceRegisterRecord 0x%08X %2d %3d %s PID[%d](%s)",
@@ -5336,7 +5441,7 @@ mDNSlocal void LogClientInfo(mDNS *const m, request_state *req)
mDNSVal16(req->u.pm.NATinfo.ExternalPort),
req->u.pm.NATinfo.NATLease,
req->u.pm.NATinfo.Lifetime,
- req->process_id, req->pid_name);
+ req->process_id, req->pid_name);
else if (req->terminate == addrinfo_termination_callback)
LogMsgNoIdent("%s DNSServiceGetAddrInfo 0x%08X %2d %s%s %##s PID[%d](%s)",
prefix, req->flags, req->interfaceIndex,
@@ -5354,18 +5459,18 @@ mDNSlocal void GetMcastClients(request_state *req)
int num_records = 0, num_ops = 0;
const registered_record_entry *p;
request_state *r;
- for (p = req->u.reg_recs; p; p=p->next)
+ for (p = req->u.reg_recs; p; p=p->next)
num_records++;
- for (r = req->next; r; r=r->next)
- if (r->primary == req)
+ for (r = req->next; r; r=r->next)
+ if (r->primary == req)
num_ops++;
for (p = req->u.reg_recs; p; p=p->next)
{
if (!AuthRecord_uDNS(p->rr))
n_mrecords++;
}
- for (r = req->next; r; r=r->next)
- if (r->primary == req)
+ for (r = req->next; r; r=r->next)
+ if (r->primary == req)
GetMcastClients(r);
}
else if (req->terminate == regservice_termination_callback)
@@ -5374,7 +5479,7 @@ mDNSlocal void GetMcastClients(request_state *req)
for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
{
if (!AuthRecord_uDNS(&ptr->srs.RR_SRV))
- n_mrecords++;
+ n_mrecords++;
}
}
else if (req->terminate == browse_termination_callback)
@@ -5417,19 +5522,19 @@ mDNSlocal void LogMcastClientInfo(request_state *req)
int num_records = 0, num_ops = 0;
const registered_record_entry *p;
request_state *r;
- for (p = req->u.reg_recs; p; p=p->next)
+ for (p = req->u.reg_recs; p; p=p->next)
num_records++;
- for (r = req->next; r; r=r->next)
- if (r->primary == req)
+ for (r = req->next; r; r=r->next)
+ if (r->primary == req)
num_ops++;
for (p = req->u.reg_recs; p; p=p->next)
{
if (!AuthRecord_uDNS(p->rr))
- LogMcastNoIdent("R: -> DNSServiceRegisterRecord: %##s %s PID[%d](%s)", p->rr->resrec.name->c,
+ LogMcastNoIdent("R: -> DNSServiceRegisterRecord: %##s %s PID[%d](%s)", p->rr->resrec.name->c,
DNSTypeName(p->rr->resrec.rrtype), req->process_id, req->pid_name, i_mcount++);
}
- for (r = req->next; r; r=r->next)
- if (r->primary == req)
+ for (r = req->next; r; r=r->next)
+ if (r->primary == req)
LogMcastClientInfo(r);
}
else if (req->terminate == regservice_termination_callback)
@@ -5437,8 +5542,8 @@ mDNSlocal void LogMcastClientInfo(request_state *req)
service_instance *ptr;
for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next)
{
- if (!AuthRecord_uDNS(&ptr->srs.RR_SRV))
- LogMcastNoIdent("R: DNSServiceRegister: %##s %u/%u PID[%d](%s)", ptr->srs.RR_SRV.resrec.name->c, mDNSVal16(req->u.servicereg.port),
+ if (!AuthRecord_uDNS(&ptr->srs.RR_SRV))
+ LogMcastNoIdent("R: DNSServiceRegister: %##s %u/%u PID[%d](%s)", ptr->srs.RR_SRV.resrec.name->c, mDNSVal16(req->u.servicereg.port),
SRS_PORT(&ptr->srs), req->process_id, req->pid_name, i_mcount++);
}
}
@@ -5461,7 +5566,7 @@ mDNSlocal void LogMcastClientInfo(request_state *req)
else if (req->terminate == queryrecord_termination_callback)
{
if ((mDNSOpaque16IsZero(req->u.queryrecord.q.TargetQID)) && (req->u.queryrecord.q.ThisQInterval > 0))
- LogMcastNoIdent("Q: DNSServiceQueryRecord %##s %s PID[%d](%s)", req->u.queryrecord.q.qname.c, DNSTypeName(req->u.queryrecord.q.qtype),
+ LogMcastNoIdent("Q: DNSServiceQueryRecord %##s %s PID[%d](%s)", req->u.queryrecord.q.qname.c, DNSTypeName(req->u.queryrecord.q.qtype),
req->process_id, req->pid_name, i_mcount++);
}
else if (req->terminate == addrinfo_termination_callback)
@@ -5476,7 +5581,7 @@ mDNSlocal void LogMcastClientInfo(request_state *req)
{
return;
}
-
+
}
mDNSlocal char *RecordTypeName(mDNSu8 rtype)
@@ -5549,9 +5654,14 @@ mDNSlocal void LogLocalOnlyAuthRecords(mDNS *const m)
// Print a maximum of 400 records
if (ar->ARType == AuthRecordLocalOnly)
- LogMsgNoIdent(" %s LO %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
+ LogMsgNoIdent(" %s LO %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
else if (ar->ARType == AuthRecordP2P)
- LogMsgNoIdent(" %s PP %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
+ {
+ if (ar->resrec.InterfaceID == mDNSInterface_BLE)
+ LogMsgNoIdent(" %s BLE %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
+ else
+ LogMsgNoIdent(" %s PP %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar));
+ }
}
}
@@ -5573,21 +5683,23 @@ mDNSlocal void LogOneAuthRecord(mDNS *const m, const AuthRecord *ar, mDNSs32 now
char anstr[256];
if (AuthRecord_uDNS(ar))
{
- LogMsgNoIdent("%7d %7d %7d %7d %s %s",
+ LogMsgNoIdent("%7d %7d %7d %-7s %4d %s %s",
ar->ThisAPInterval / mDNSPlatformOneSecond,
(ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond,
ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0,
+ "-U-",
ar->state,
ar->AllowRemoteQuery ? "☠" : " ",
ARDisplayString(m, ar));
}
else
{
- LogMsgNoIdent("%7d %7d %7d %7s %s %s%s",
+ LogMsgNoIdent("%7d %7d %7d %-7s 0x%02X %s %s%s",
ar->ThisAPInterval / mDNSPlatformOneSecond,
ar->AnnounceCount ? (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond : 0,
ar->TimeExpire ? (ar->TimeExpire - now) / mDNSPlatformOneSecond : 0,
ifname ? ifname : "ALL",
+ ar->resrec.RecordType,
ar->AllowRemoteQuery ? "☠" : " ",
ARDisplayString(m, ar), AnonInfoToString(ar->resrec.AnonInfo, anstr, sizeof(anstr)));
}
@@ -5603,7 +5715,7 @@ mDNSlocal void LogAuthRecords(mDNS *const m, const mDNSs32 now, AuthRecord *Reso
const char *const ifname = InterfaceNameForID(m, ar->resrec.InterfaceID);
if ((ar->WakeUp.HMAC.l[0] != 0) == (proxy != mDNSNULL))
{
- if (showheader) { showheader = mDNSfalse; LogMsgNoIdent(" Int Next Expire State"); }
+ if (showheader) { showheader = mDNSfalse; LogMsgNoIdent(" Int Next Expire if State"); }
if (proxy) (*proxy)++;
if (!mDNSPlatformMemSame(&owner, &ar->WakeUp, sizeof(owner)))
{
@@ -5625,7 +5737,10 @@ mDNSlocal void LogAuthRecords(mDNS *const m, const mDNSs32 now, AuthRecord *Reso
}
else if (ar->ARType == AuthRecordP2P)
{
- LogMsgNoIdent(" PP %s", ARDisplayString(m, ar));
+ if (ar->resrec.InterfaceID == mDNSInterface_BLE)
+ LogMsgNoIdent(" BLE %s", ARDisplayString(m, ar));
+ else
+ LogMsgNoIdent(" PP %s", ARDisplayString(m, ar));
}
else
{
@@ -5731,7 +5846,7 @@ mDNSlocal char *AnonDataToString(const mDNSu8 *ad, int adlen, char *adstr, int a
mDNSexport void LogMDNSStatistics(mDNS *const m)
{
LogMsgNoIdent("--- MDNS Statistics ---");
-
+
LogMsgNoIdent("Name Conflicts %u", m->mDNSStats.NameConflicts);
LogMsgNoIdent("KnownUnique Name Conflicts %u", m->mDNSStats.KnownUniqueNameConflicts);
LogMsgNoIdent("Duplicate Query Suppressions %u", m->mDNSStats.DupQuerySuppressions);
@@ -5849,10 +5964,11 @@ mDNSexport void udsserver_info(mDNS *const m)
LogMsgNoIdent("%lu question%s; %lu active", CacheUsed, CacheUsed > 1 ? "s" : "", CacheActive);
}
- LogMsgNoIdent("----- Local-Only Questions -----");
+ LogMsgNoIdent("----- LocalOnly, P2P Questions -----");
if (!m->LocalOnlyQuestions) LogMsgNoIdent("<None>");
else for (q = m->LocalOnlyQuestions; q; q=q->next)
- LogMsgNoIdent(" %5d %-6s%##s%s",
+ LogMsgNoIdent(" %3s %5d %-6s%##s%s",
+ q->InterfaceID == mDNSInterface_LocalOnly ? "LO ": q->InterfaceID == mDNSInterface_BLE ? "BLE": "P2P",
q->CurrentAnswers, DNSTypeName(q->qtype), q->qname.c, q->DuplicateOf ? " (dup)" : "");
LogMsgNoIdent("---- Active UDS Client Requests ----");
@@ -5872,7 +5988,7 @@ mDNSexport void udsserver_info(mDNS *const m)
foundparent:;
}
}
-
+
LogMsgNoIdent("-------- NAT Traversals --------");
LogMsgNoIdent("ExtAddress %.4a Retry %d Interval %d",
&m->ExtAddress,
@@ -5965,7 +6081,7 @@ foundparent:;
}
}
LogInfo("--- Trust Anchors ---");
- if (!m->TrustAnchors)
+ if (!m->TrustAnchors)
{
LogInfo("<None>");
}
@@ -6017,6 +6133,14 @@ foundparent:;
LogMsgNoIdent("---- Task Scheduling Timers ----");
+#if BONJOUR_ON_DEMAND
+ LogMsgNoIdent("BonjourEnabled %d", m->BonjourEnabled);
+#endif // BONJOUR_ON_DEMAND
+
+#if APPLE_OSX_mDNSResponder
+ LogMsgNoIdent("EnableBLEBasedDiscovery %d", EnableBLEBasedDiscovery);
+#endif // APPLE_OSX_mDNSResponder
+
if (!m->NewQuestions)
LogMsgNoIdent("NewQuestion <NONE>");
else
@@ -6058,6 +6182,11 @@ foundparent:;
LogTimer("m->NextCacheCheck ", m->NextCacheCheck);
LogTimer("m->NextScheduledSPS ", m->NextScheduledSPS);
LogTimer("m->NextScheduledKA ", m->NextScheduledKA);
+
+#if BONJOUR_ON_DEMAND
+ LogTimer("m->NextBonjourDisableTime ", m->NextBonjourDisableTime);
+#endif // BONJOUR_ON_DEMAND
+
LogTimer("m->NextScheduledSPRetry ", m->NextScheduledSPRetry);
LogTimer("m->DelaySleep ", m->DelaySleep);
@@ -6186,15 +6315,16 @@ mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent)
if (r->u.resolve.ReportTime && now - r->u.resolve.ReportTime >= 0)
{
r->u.resolve.ReportTime = 0;
- LogMsgNoIdent("Client application bug PID[%d](%s) : DNSServiceResolve(%##s) active for over two minutes. "
- "This places considerable burden on the network.", r->process_id, r->pid_name, r->u.resolve.qsrv.qname.c);
+ // if client received results and resolve still active
+ if (r->u.resolve.txt && r->u.resolve.srv)
+ LogMsgNoIdent("Client application PID[%d](%s) has received results for DNSServiceResolve(%##s) yet remains active over two minutes.", r->process_id, r->pid_name, r->u.resolve.qsrv.qname.c);
}
// Note: Only primary req's have reply lists, not subordinate req's.
while (r->replies) // Send queued replies
{
transfer_state result;
- if (r->replies->next)
+ if (r->replies->next)
r->replies->rhdr->flags |= dnssd_htonl(kDNSServiceFlagsMoreComing);
result = send_msg(r); // Returns t_morecoming if buffer full because client is not reading
if (result == t_complete)
@@ -6206,7 +6336,12 @@ mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent)
r->unresponsiveness_reports = 0;
continue;
}
- else if (result == t_terminated || result == t_error)
+ else if (result == t_terminated)
+ {
+ LogInfo("%3d: Could not write data to client PID[%d](%s) because connection is terminated by the client", r->sd, r->process_id, r->pid_name);
+ abort_request(r);
+ }
+ else if (result == t_error)
{
LogMsg("%3d: Could not write data to client PID[%d](%s) because of error - aborting connection", r->sd, r->process_id, r->pid_name);
LogClientInfo(&mDNSStorage, r);
@@ -6217,21 +6352,21 @@ mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent)
if (r->replies) // If we failed to send everything, check our time_blocked timer
{
- if (nextevent - now > mDNSPlatformOneSecond)
+ if (nextevent - now > mDNSPlatformOneSecond)
nextevent = now + mDNSPlatformOneSecond;
- if (mDNSStorage.SleepState != SleepState_Awake)
+ if (mDNSStorage.SleepState != SleepState_Awake)
r->time_blocked = 0;
- else if (!r->time_blocked)
+ else if (!r->time_blocked)
r->time_blocked = NonZeroTime(now);
else if (now - r->time_blocked >= 10 * mDNSPlatformOneSecond * (r->unresponsiveness_reports+1))
{
int num = 0;
struct reply_state *x = r->replies;
- while (x)
- {
- num++;
- x=x->next;
+ while (x)
+ {
+ num++;
+ x=x->next;
}
LogMsg("%3d: Could not write data to client PID[%d](%s) after %ld seconds, %d repl%s waiting",
r->sd, r->process_id, r->pid_name, (now - r->time_blocked) / mDNSPlatformOneSecond, num, num == 1 ? "y" : "ies");
@@ -6261,10 +6396,10 @@ struct CompileTimeAssertionChecks_uds_daemon
// Check our structures are reasonable sizes. Including overly-large buffers, or embedding
// other overly-large structures instead of having a pointer to them, can inadvertently
// cause structure sizes (and therefore memory usage) to balloon unreasonably.
- char sizecheck_request_state [(sizeof(request_state) <= 2000) ? 1 : -1];
+ char sizecheck_request_state [(sizeof(request_state) <= 2954) ? 1 : -1];
char sizecheck_registered_record_entry[(sizeof(registered_record_entry) <= 60) ? 1 : -1];
char sizecheck_service_instance [(sizeof(service_instance) <= 6552) ? 1 : -1];
- char sizecheck_browser_t [(sizeof(browser_t) <= 1128) ? 1 : -1];
+ char sizecheck_browser_t [(sizeof(browser_t) <= 1150) ? 1 : -1];
char sizecheck_reply_hdr [(sizeof(reply_hdr) <= 12) ? 1 : -1];
char sizecheck_reply_state [(sizeof(reply_state) <= 64) ? 1 : -1];
};
diff --git a/mDNSResponder/mDNSShared/uds_daemon.h b/mDNSResponder/mDNSShared/uds_daemon.h
index 6cc9197d..ef98450b 100644
--- a/mDNSResponder/mDNSShared/uds_daemon.h
+++ b/mDNSResponder/mDNSShared/uds_daemon.h
@@ -53,15 +53,14 @@ extern DNameListElem *AutoBrowseDomains;
extern mDNSs32 ChopSubTypes(char *regtype, char **AnonData);
extern AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p, char **AnonData);
extern int CountExistingRegistrations(domainname *srv, mDNSIPPort port);
+extern mDNSBool callExternalHelpers(mDNSInterfaceID InterfaceID, const domainname *const domain, DNSServiceFlags flags);
extern void FreeExtraRR(mDNS *const m, AuthRecord *const rr, mStatus result);
extern int CountPeerRegistrations(mDNS *const m, ServiceRecordSet *const srs);
#if APPLE_OSX_mDNSResponder
-extern void machserver_automatic_browse_domain_changed(const domainname *d, mDNSBool add);
-extern void machserver_automatic_registration_domain_changed(const domainname *d, mDNSBool add);
// D2D interface support
-extern void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags);
+extern void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags, DNSQuestion * q);
extern void external_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags);
extern void external_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags);
extern void external_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags);
@@ -69,12 +68,17 @@ extern void external_start_resolving_service(mDNSInterfaceID InterfaceID, const
extern void external_stop_resolving_service(mDNSInterfaceID InterfaceID, const domainname *const fqdn, DNSServiceFlags flags);
extern void external_connection_release(const domainname *instance);
+extern void internal_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags);
+extern void internal_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags);
+extern void internal_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags);
+extern void internal_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags);
+
#else // APPLE_OSX_mDNSResponder
-#define external_start_browsing_for_service(A,B,C,D) (void)(A)
+#define external_start_browsing_for_service(A,B,C,D,E) (void)(A)
#define external_stop_browsing_for_service(A,B,C,D) (void)(A)
#define external_start_advertising_service(A,B) (void)(A)
-#define external_stop_advertising_service(A,B) (void)(A)
+#define external_stop_advertising_service(A,B) do { (void)(A); (void)(B); } while (0)
#define external_start_resolving_service(A,B,C) (void)(A)
#define external_stop_resolving_service(A,B,C) (void)(A)
#define external_connection_release(A) (void)(A)
@@ -83,3 +87,8 @@ extern void external_connection_release(const domainname *instance);
extern const char mDNSResponderVersionString_SCCS[];
#define mDNSResponderVersionString (mDNSResponderVersionString_SCCS+5)
+
+#if DEBUG
+extern void SetDebugBoundPath(void);
+extern int IsDebugSocketInUse(void);
+#endif
diff --git a/mDNSResponder/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp b/mDNSResponder/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp
index 5fae9555..34c418e3 100755
--- a/mDNSResponder/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp
+++ b/mDNSResponder/mDNSWindows/ControlPanel/ConfigPropertySheet.cpp
@@ -227,8 +227,8 @@ CConfigPropertySheet::DecodeDomainName( const char * raw, CString & decoded )
for (i = 0; i < labels; i++)
{
buffer = (char *)GetNextLabel(buffer, nextLabel);
- strcat(decodedDomainString, nextLabel);
- strcat(decodedDomainString, ".");
+ strcat_s(decodedDomainString, sizeof(decodedDomainString), nextLabel);
+ strcat_s(decodedDomainString, sizeof(decodedDomainString), ".");
}
// Remove trailing dot from domain name.
diff --git a/mDNSResponder/mDNSWindows/ControlPanel/ControlPanelExe.cpp b/mDNSResponder/mDNSWindows/ControlPanel/ControlPanelExe.cpp
index 36447d11..94de794b 100755
--- a/mDNSResponder/mDNSWindows/ControlPanel/ControlPanelExe.cpp
+++ b/mDNSResponder/mDNSWindows/ControlPanel/ControlPanelExe.cpp
@@ -23,6 +23,7 @@
#include <DebugServices.h>
#include "loclibrary.h"
+#include <strsafe.h>
#ifdef _DEBUG
@@ -205,7 +206,7 @@ CCPApp::Register( LPCTSTR inClsidString, LPCTSTR inName, LPCTSTR inCanonicalName
n = sizeof_array( entries );
for( i = 0; i < n; ++i )
{
- wsprintf( keyName, entries[ i ].subKey, inClsidString );
+ StringCbPrintf( keyName, sizeof( keyName ), entries[ i ].subKey, inClsidString );
err = RegCreateKeyEx( entries[ i ].rootKey, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL );
require_noerr( err, exit );
@@ -232,10 +233,10 @@ CCPApp::Unregister( LPCTSTR clsidString )
{
TCHAR keyName[ MAX_PATH * 2 ];
- wsprintf( keyName, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace\\%s", clsidString );
+ StringCbPrintf( keyName, sizeof( keyName ), L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace\\%s", clsidString );
MyRegDeleteKey( HKEY_LOCAL_MACHINE, keyName );
- wsprintf( keyName, L"CLSID\\%s", clsidString );
+ StringCbPrintf( keyName, sizeof( keyName ), L"CLSID\\%s", clsidString );
MyRegDeleteKey( HKEY_CLASSES_ROOT, keyName );
}
@@ -313,7 +314,7 @@ CCPApp::InitInstance()
require_noerr( err, exit );
- wsprintf( iconPath, L"%s,-%d", exePath, IDR_APPLET );
+ StringCbPrintf( iconPath, sizeof( iconPath ), L"%s,-%d", exePath, IDR_APPLET );
localizedName.LoadString( IDS_APPLET_NAME );
toolTip.LoadString( IDS_APPLET_TOOLTIP );
diff --git a/mDNSResponder/mDNSWindows/ControlPanel/FourthPage.cpp b/mDNSResponder/mDNSWindows/ControlPanel/FourthPage.cpp
index b6c8d15d..7ded08fc 100755
--- a/mDNSResponder/mDNSWindows/ControlPanel/FourthPage.cpp
+++ b/mDNSResponder/mDNSWindows/ControlPanel/FourthPage.cpp
@@ -183,7 +183,7 @@ void CFourthPage::OnBnClickedPowerManagement()
- sprintf( buf, "check box: %d", m_checkBox.GetCheck() );
+ snprintf( buf, sizeof( buf ), "check box: %d", m_checkBox.GetCheck() );
OutputDebugStringA( buf );
diff --git a/mDNSResponder/mDNSWindows/DLLStub/DLLStub.cpp b/mDNSResponder/mDNSWindows/DLLStub/DLLStub.cpp
index 503465f2..38fd5e0a 100755
--- a/mDNSResponder/mDNSWindows/DLLStub/DLLStub.cpp
+++ b/mDNSResponder/mDNSWindows/DLLStub/DLLStub.cpp
@@ -80,12 +80,12 @@ DLLStub::GetProcAddress( FARPROC * func, LPCSTR lpProcName )
}
-int DNSSD_API
+dnssd_sock_t DNSSD_API
DNSServiceRefSockFD(DNSServiceRef sdRef)
{
typedef int (DNSSD_API * Func)(DNSServiceRef sdRef);
static Func func = NULL;
- int ret = -1;
+ int ret = INVALID_SOCKET;
if ( DLLStub::GetProcAddress( ( FARPROC* ) &func, __FUNCTION__ ) )
{
diff --git a/mDNSResponder/mDNSWindows/DLLX/DNSSD.cpp b/mDNSResponder/mDNSWindows/DLLX/DNSSD.cpp
index 8813d2df..f011dd14 100755
--- a/mDNSResponder/mDNSWindows/DLLX/DNSSD.cpp
+++ b/mDNSResponder/mDNSWindows/DLLX/DNSSD.cpp
@@ -643,7 +643,7 @@ CDNSSD::ResolveReply
record->AddRef();
char buf[ 64 ];
- sprintf( buf, "txtLen = %d", txtLen );
+ snprintf( buf, sizeof( buf ), "txtLen = %d", txtLen );
OutputDebugStringA( buf );
if ( txtLen > 0 )
diff --git a/mDNSResponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp b/mDNSResponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp
index 9e4db65b..fe46be08 100644
--- a/mDNSResponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp
+++ b/mDNSResponder/mDNSWindows/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp
@@ -269,7 +269,7 @@ static void
DNSStatus inStatusCode,
const DNSBrowserEvent * inEvent );
-static char * DNSNetworkAddressToString( const DNSNetworkAddress *inAddr, char *outString );
+static char * DNSNetworkAddressToString( const DNSNetworkAddress *inAddr, size_t inLen, char *outString );
static DWORD UTF8StringToStringObject( const char *inUTF8, CString &inObject );
static DWORD StringObjectToUTF8String( CString &inObject, std::string &outUTF8 );
@@ -1273,8 +1273,8 @@ static void
serviceInstance->name = inEvent->data.resolved->name;
serviceInstance->type = inEvent->data.resolved->type;
serviceInstance->domain = inEvent->data.resolved->domain;
- serviceInstance->ip = DNSNetworkAddressToString( &inEvent->data.resolved->address, s );
- serviceInstance->ifIP = DNSNetworkAddressToString( &inEvent->data.resolved->interfaceIP, s );
+ serviceInstance->ip = DNSNetworkAddressToString( &inEvent->data.resolved->address, sizeof( s ), s );
+ serviceInstance->ifIP = DNSNetworkAddressToString( &inEvent->data.resolved->interfaceIP, sizeof( s ), s );
serviceInstance->text = inEvent->data.resolved->textRecord;
serviceInstance->hostName = inEvent->data.resolved->hostName;
@@ -1303,7 +1303,7 @@ static void
// Note: Currently only supports IPv4 network addresses.
//===========================================================================================================================
-static char * DNSNetworkAddressToString( const DNSNetworkAddress *inAddr, char *outString )
+static char * DNSNetworkAddressToString( const DNSNetworkAddress *inAddr, size_t inLen, char *outString )
{
const DNSUInt8 * p;
DNSUInt16 port;
@@ -1312,11 +1312,11 @@ static char * DNSNetworkAddressToString( const DNSNetworkAddress *inAddr, char *
port = ntohs( inAddr->u.ipv4.port.v16 );
if( port != kDNSPortInvalid )
{
- sprintf( outString, "%u.%u.%u.%u:%u", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ], port );
+ snprintf( outString, inLen, "%u.%u.%u.%u:%u", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ], port );
}
else
{
- sprintf( outString, "%u.%u.%u.%u", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
+ snprintf( outString, inLen, "%u.%u.%u.%u", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
}
return( outString );
}
diff --git a/mDNSResponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp b/mDNSResponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp
index 92cdeb30..67b9cb85 100644
--- a/mDNSResponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp
+++ b/mDNSResponder/mDNSWindows/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp
@@ -204,7 +204,7 @@ void
{
char ip[ 64 ];
- sprintf( ip, "%u.%u.%u.%u:%u",
+ snprintf( ip, sizeof( ip ), "%u.%u.%u.%u:%u",
inEvent->data.resolved->address.u.ipv4.addr.v8[ 0 ],
inEvent->data.resolved->address.u.ipv4.addr.v8[ 1 ],
inEvent->data.resolved->address.u.ipv4.addr.v8[ 2 ],
diff --git a/mDNSResponder/mDNSWindows/Java/makefile b/mDNSResponder/mDNSWindows/Java/makefile
index 2e4b6bd0..da237976 100644
--- a/mDNSResponder/mDNSWindows/Java/makefile
+++ b/mDNSResponder/mDNSWindows/Java/makefile
@@ -34,7 +34,7 @@
COREDIR = ..\..\mDNSCore
SHAREDDIR = ..\..\mDNSShared
-JDK = $(JAVA_HOME)
+JDK = "$(JAVA_HOME)"
CC = cl
RC = rc
diff --git a/mDNSResponder/mDNSWindows/Java/makefile64 b/mDNSResponder/mDNSWindows/Java/makefile64
index fb0ff9ce..5845ab5e 100644
--- a/mDNSResponder/mDNSWindows/Java/makefile64
+++ b/mDNSResponder/mDNSWindows/Java/makefile64
@@ -34,7 +34,7 @@
COREDIR = ..\..\mDNSCore
SHAREDDIR = ..\..\mDNSShared
-JDK = $(JAVA_HOME)
+JDK = "$(JAVA_HOME)"
CC = cl
RC = rc
diff --git a/mDNSResponder/mDNSWindows/NSPTool/NSPTool.c b/mDNSResponder/mDNSWindows/NSPTool/NSPTool.c
index f3052d16..0be174df 100644
--- a/mDNSResponder/mDNSWindows/NSPTool/NSPTool.c
+++ b/mDNSResponder/mDNSWindows/NSPTool/NSPTool.c
@@ -38,7 +38,7 @@ DEBUG_LOCAL OSStatus ListNameSpaces( void );
DEBUG_LOCAL OSStatus ReorderNameSpaces( void );
DEBUG_LOCAL WCHAR * CharToWCharString( const char *inCharString, WCHAR *outWCharString );
-DEBUG_LOCAL char * GUIDtoString( const GUID *inGUID, char *outString );
+DEBUG_LOCAL char * GUIDtoString( const GUID *inGUID, size_t inLen, char *outString );
DEBUG_LOCAL OSStatus StringToGUID( const char *inCharString, GUID *outGUID );
DEBUG_LOCAL BOOL gToolQuietMode = FALSE;
@@ -390,7 +390,7 @@ DEBUG_LOCAL OSStatus ListNameSpaces( void )
for( i = 0; i < n; ++i )
{
fprintf( stdout, "Name Space %d\n", i + 1 );
- fprintf( stdout, " NSProviderId: %s\n", GUIDtoString( &array[ i ].NSProviderId, s ) );
+ fprintf( stdout, " NSProviderId: %s\n", GUIDtoString( &array[ i ].NSProviderId, sizeof( s ), s ) );
fprintf( stdout, " dwNameSpace: %d\n", array[ i ].dwNameSpace );
fprintf( stdout, " fActive: %s\n", array[ i ].fActive ? "YES" : "NO" );
fprintf( stdout, " dwVersion: %d\n", array[ i ].dwVersion );
@@ -536,12 +536,12 @@ DEBUG_LOCAL WCHAR * CharToWCharString( const char *inCharString, WCHAR *outWChar
// GUIDtoString
//===========================================================================================================================
-DEBUG_LOCAL char * GUIDtoString( const GUID *inGUID, char *outString )
+DEBUG_LOCAL char * GUIDtoString( const GUID *inGUID, size_t inLen, char *outString )
{
check( inGUID );
check( outString );
- sprintf( outString, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ _snprintf( outString, inLen, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
inGUID->Data1, inGUID->Data2, inGUID->Data3,
inGUID->Data4[ 0 ], inGUID->Data4[ 1 ], inGUID->Data4[ 2 ], inGUID->Data4[ 3 ],
inGUID->Data4[ 4 ], inGUID->Data4[ 5 ], inGUID->Data4[ 6 ], inGUID->Data4[ 7 ] );
diff --git a/mDNSResponder/mDNSWindows/SystemService/Service.c b/mDNSResponder/mDNSWindows/SystemService/Service.c
index d175326f..1dea5c79 100644
--- a/mDNSResponder/mDNSWindows/SystemService/Service.c
+++ b/mDNSResponder/mDNSWindows/SystemService/Service.c
@@ -786,7 +786,7 @@ static void ReportStatus( int inType, const char *inFormat, ... )
BOOL ok;
const char * array[ 1 ];
- vsprintf( s, inFormat, args );
+ vsnprintf( s, sizeof( s ), inFormat, args );
array[ 0 ] = s;
ok = ReportEventA( gServiceEventSource, (WORD) inType, 0, MDNSRESPONDER_LOG, NULL, 1, 0, array, NULL );
check_translated_errno( ok, GetLastError(), kUnknownErr );
diff --git a/mDNSResponder/mDNSWindows/mDNSWin32.c b/mDNSResponder/mDNSWindows/mDNSWin32.c
index 0789cf4d..011125b9 100755
--- a/mDNSResponder/mDNSWindows/mDNSWin32.c
+++ b/mDNSResponder/mDNSWindows/mDNSWin32.c
@@ -106,7 +106,6 @@ mDNSlocal int getifaddrs( struct ifaddrs **outAddrs );
mDNSlocal void freeifaddrs( struct ifaddrs *inAddrs );
-
// Platform Accessors
#ifdef __cplusplus
@@ -127,8 +126,6 @@ mDNSexport mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInter
// Wakeup Structs
-#define kUnicastWakeupNumTries ( 1 )
-#define kUnicastWakeupSleepBetweenTries ( 0 )
#define kMulticastWakeupNumTries ( 18 )
#define kMulticastWakeupSleepBetweenTries ( 100 )
@@ -152,7 +149,6 @@ typedef struct MulticastWakeupStruct
mDNSlocal int getifaddrs_ipv4( struct ifaddrs **outAddrs );
-
mDNSlocal DWORD GetPrimaryInterface();
mDNSlocal mStatus AddressToIndexAndMask( struct sockaddr * address, uint32_t * index, struct sockaddr * mask );
mDNSlocal mDNSBool CanReceiveUnicast( void );
@@ -216,12 +212,10 @@ mDNSlocal BOOL gEnableIPv6 = TRUE;
#endif
-
#ifndef HCRYPTPROV
typedef ULONG_PTR HCRYPTPROV; // WinCrypt.h, line 249
#endif
-
#ifndef CRYPT_MACHINE_KEYSET
# define CRYPT_MACHINE_KEYSET 0x00000020
#endif
@@ -277,7 +271,6 @@ mDNSlocal HANDLE gSMBThreadQuitEvent = NULL;
#define kSMBRegisterEvent ( WAIT_OBJECT_0 + 1 )
#define kSMBDeregisterEvent ( WAIT_OBJECT_0 + 2 )
-
#if 0
#pragma mark -
#pragma mark == Platform Support ==
@@ -570,7 +563,6 @@ mDNSexport void mDNSPlatformClose( mDNS * const inMDNS )
dlog( kDebugLevelTrace, DEBUG_NAME "platform close done\n" );
}
-
//===========================================================================================================================
// mDNSPlatformLock
//===========================================================================================================================
@@ -602,6 +594,39 @@ mDNSexport void mDNSPlatformStrCopy( void *inDst, const void *inSrc )
}
//===========================================================================================================================
+// mDNSPlatformStrLCopy
+//===========================================================================================================================
+
+mDNSexport mDNSu32 mDNSPlatformStrLCopy( void *inDst, const void *inSrc, mDNSu32 inSize )
+{
+ const char * src = (const char *) inSrc;
+
+ if( inSize > 0 )
+ {
+ size_t n;
+ char * dst = (char *) inDst;
+
+ for( n = inSize - 1; n > 0; --n )
+ {
+ if( ( *dst++ = *src++ ) == '\0' )
+ {
+ // Null terminator encountered, so exit.
+ goto exit;
+ }
+ }
+ *dst = '\0';
+ }
+
+ while( *src++ != '\0' )
+ {
+ // Stop at null terminator.
+ }
+
+exit:
+ return( (mDNSu32)( src - (const char *) inSrc ) - 1 );
+}
+
+//===========================================================================================================================
// mDNSPlatformStrLen
//===========================================================================================================================
@@ -940,7 +965,6 @@ mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID( mDNS * const inMDN
return( index );
}
-
//===========================================================================================================================
// mDNSPlatformTCPSocket
//===========================================================================================================================
@@ -1077,12 +1101,10 @@ exit:
return err;
}
-
//===========================================================================================================================
// mDNSPlatformTCPAccept
//===========================================================================================================================
-mDNSexport
mDNSexport TCPSocket *mDNSPlatformTCPAccept( TCPSocketFlags flags, int fd )
{
TCPSocket * sock = NULL;
@@ -1109,7 +1131,6 @@ exit:
return sock;
}
-
//===========================================================================================================================
// mDNSPlatformTCPCloseConnection
//===========================================================================================================================
@@ -1133,7 +1154,6 @@ mDNSexport void mDNSPlatformTCPCloseConnection( TCPSocket *sock )
}
}
-
//===========================================================================================================================
// mDNSPlatformReadTCP
//===========================================================================================================================
@@ -1173,7 +1193,6 @@ mDNSexport long mDNSPlatformReadTCP( TCPSocket *sock, void *inBuffer, unsigned l
return nread;
}
-
//===========================================================================================================================
// mDNSPlatformWriteTCP
//===========================================================================================================================
@@ -1207,8 +1226,6 @@ mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock )
return ( int ) sock->fd;
}
-
-
//===========================================================================================================================
// TCPSocketNotification
//===========================================================================================================================
@@ -1248,8 +1265,6 @@ exit:
return;
}
-
-
//===========================================================================================================================
// mDNSPlatformUDPSocket
//===========================================================================================================================
@@ -1362,7 +1377,6 @@ mDNSexport void mDNSPlatformUDPClose( UDPSocket *sock )
}
}
-
//===========================================================================================================================
// mDNSPlatformSendUDP
//===========================================================================================================================
@@ -1450,21 +1464,12 @@ exit:
return( err );
}
-
-mDNSexport mDNSBool mDNSPlatformPeekUDP(mDNS *const m, UDPSocket *src)
-{
- DEBUG_UNUSED( m );
- DEBUG_UNUSED( src );
- return mDNSfalse;
-}
-
mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
{
DEBUG_UNUSED( m );
DEBUG_UNUSED( InterfaceID );
}
-
mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason)
{
DEBUG_UNUSED( m );
@@ -1482,14 +1487,13 @@ mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID Inte
unsigned char buf[ 102 ];
char hex[ 3 ] = { 0 };
unsigned char *bufPtr = buf;
- struct sockaddr_storage saddr;
- INT len = sizeof( saddr );
- mDNSBool unicast = mDNSfalse;
MulticastWakeupStruct *info;
int i;
mStatus err;
- (void) InterfaceID;
+ (void) InterfaceID; // unused
+ (void) ipaddr; // unused
+ (void) iteration; // unused
require_action( ethaddr, exit, err = mStatus_BadParamErr );
@@ -1512,44 +1516,6 @@ mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID Inte
bufPtr += sizeof( mac );
}
- if ( ipaddr )
- {
- if ( WSAStringToAddressA( ipaddr, AF_INET, NULL, ( LPSOCKADDR ) &saddr, &len ) == 0 )
- {
- struct sockaddr_in * saddr4 = ( struct sockaddr_in* ) &saddr;
- saddr4->sin_port = htons( 9 );
- len = sizeof( *saddr4 );
-
- if ( saddr4->sin_addr.s_addr != htonl( INADDR_ANY ) )
- {
- unicast = mDNStrue;
- }
- }
- else if ( WSAStringToAddressA( ipaddr, AF_INET6, NULL, ( LPSOCKADDR ) &saddr, &len ) == 0 )
- {
- mDNSInterfaceData *ifd = ( mDNSInterfaceData* ) InterfaceID;
- struct sockaddr_in6 * saddr6 = ( struct sockaddr_in6* ) &saddr;
- saddr6->sin6_port = htons( 9 );
-
- if ( ifd != NULL )
- {
- saddr6->sin6_scope_id = ifd->scopeID;
- }
-
- len = sizeof( *saddr6 );
-
- if ( memcmp( &saddr6->sin6_addr, &in6addr_any, sizeof( IN6_ADDR ) ) != 0 )
- {
- unicast = mDNStrue;
- }
- }
- }
-
- if ( ( iteration < 2 ) && ( unicast ) )
- {
- SendWakeupPacket( m, ( LPSOCKADDR ) &saddr, len, ( const char* ) buf, sizeof( buf ), kUnicastWakeupNumTries, kUnicastWakeupSleepBetweenTries );
- }
-
info = ( MulticastWakeupStruct* ) malloc( sizeof( MulticastWakeupStruct ) );
require_action( info, exit, err = mStatus_NoMemoryErr );
info->inMDNS = m;
@@ -1570,11 +1536,10 @@ exit:
return;
}
-
-mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf)
+mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(const AuthRecord *rr, mDNSInterfaceID InterfaceID)
{
DEBUG_UNUSED( rr );
- DEBUG_UNUSED( intf );
+ DEBUG_UNUSED( InterfaceID );
return mDNStrue;
}
@@ -1601,7 +1566,6 @@ mDNSexport void mDNSPlatformFormatTime(unsigned long te, mDNSu8 *buf, int bufsiz
if (bufsize) buf[0] = 0;
}
-
mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
{
DEBUG_UNUSED( m );
@@ -1610,7 +1574,6 @@ mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSA
DEBUG_UNUSED( InterfaceID );
}
-
mDNSexport void mDNSPlatformReceiveRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
{
DEBUG_UNUSED( msg );
@@ -1711,7 +1674,6 @@ mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers,
return mDNStrue;
}
-
//===========================================================================================================================
// mDNSPlatformDynDNSHostNameStatusChanged
//===========================================================================================================================
@@ -1756,7 +1718,6 @@ exit:
return;
}
-
//===========================================================================================================================
// SetDomainSecrets
//===========================================================================================================================
@@ -1798,7 +1759,6 @@ SetDomainSecrets( mDNS * const m )
}
}
-
//===========================================================================================================================
// SetSearchDomainList
//===========================================================================================================================
@@ -1849,7 +1809,6 @@ exit:
SetReverseMapSearchDomainList();
}
-
//===========================================================================================================================
// SetReverseMapSearchDomainList
//===========================================================================================================================
@@ -1871,10 +1830,10 @@ SetReverseMapSearchDomainList( void )
if (!SetupAddr(&netmask, ifa->ifa_netmask))
{
- sprintf(buffer, "%d.%d.%d.%d.in-addr.arpa.", addr.ip.v4.b[3] & netmask.ip.v4.b[3],
- addr.ip.v4.b[2] & netmask.ip.v4.b[2],
- addr.ip.v4.b[1] & netmask.ip.v4.b[1],
- addr.ip.v4.b[0] & netmask.ip.v4.b[0]);
+ _snprintf(buffer, sizeof( buffer ), "%d.%d.%d.%d.in-addr.arpa.", addr.ip.v4.b[3] & netmask.ip.v4.b[3],
+ addr.ip.v4.b[2] & netmask.ip.v4.b[2],
+ addr.ip.v4.b[1] & netmask.ip.v4.b[1],
+ addr.ip.v4.b[0] & netmask.ip.v4.b[0]);
mDNS_AddSearchDomain_CString(buffer, mDNSNULL);
}
}
@@ -1885,7 +1844,6 @@ SetReverseMapSearchDomainList( void )
return;
}
-
//===========================================================================================================================
// SetDNSServers
//===========================================================================================================================
@@ -1978,7 +1936,6 @@ exit:
}
}
-
//===========================================================================================================================
// SetDomainFromDHCP
//===========================================================================================================================
@@ -2071,7 +2028,6 @@ exit:
}
}
-
//===========================================================================================================================
// mDNSPlatformGetPrimaryInterface
//===========================================================================================================================
@@ -2171,8 +2127,16 @@ mDNSexport mStatus mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifna
return mStatus_UnsupportedErr;
}
-mDNSexport mStatus mDNSPlatformClearSPSMACAddr(void)
+mDNSexport mStatus mDNSPlatformClearSPSData(void)
+{
+ return mStatus_UnsupportedErr;
+}
+
+mDNSexport mStatus mDNSPlatformStoreOwnerOptRecord(char *ifname, DNSMessage *msg, int length)
{
+ (void) ifname; // Unused
+ (void) msg; // Unused
+ (void) length; // Unused
return mStatus_UnsupportedErr;
}
@@ -2188,18 +2152,11 @@ mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, m
return mStatus_UnsupportedErr;
}
-mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isCellBlocked)
-{
- (void) m;
-
- q->ServiceID = -1;
- *isCellBlocked = mDNSfalse;
-}
-
-mDNSexport void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q)
+mDNSexport void mDNSPlatformSetSocktOpt(void *sock, mDNSTransport_Type transType, mDNSAddr_Type addrType, DNSQuestion *q)
{
- (void) src;
- (void) dst;
+ (void) sock;
+ (void) transType;
+ (void) addrType;
(void) q;
}
@@ -2263,13 +2220,11 @@ mDNSexport void verbosedebugf_( const char *inFormat, ... )
}
#endif
-
#if 0
#pragma mark -
#pragma mark == Platform Internals ==
#endif
-
//===========================================================================================================================
// SetupNiceName
//===========================================================================================================================
@@ -2341,7 +2296,7 @@ mStatus SetupNiceName( mDNS * const inMDNS )
{
// Invalidate name so fall back to a default name.
- strcpy( utf8, kMDNSDefaultName );
+ strcpy_s( utf8, sizeof( utf8 ), kMDNSDefaultName );
}
utf8[ sizeof( utf8 ) - 1 ] = '\0';
@@ -2411,7 +2366,7 @@ mDNSlocal mStatus SetupHostName( mDNS * const inMDNS )
{
// Invalidate name so fall back to a default name.
- strcpy( tempString, kMDNSDefaultName );
+ strcpy_s( tempString, sizeof( tempString ), kMDNSDefaultName );
}
tempString[ sizeof( tempString ) - 1 ] = '\0';
@@ -2456,7 +2411,6 @@ mDNSlocal mStatus SetupName( mDNS * const inMDNS )
return err;
}
-
//===========================================================================================================================
// SetupInterfaceList
//===========================================================================================================================
@@ -3209,7 +3163,6 @@ mDNSlocal mStatus SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAd
return( err );
}
-
#if 0
#pragma mark -
#endif
@@ -3404,7 +3357,6 @@ exit:
return;
}
-
//===========================================================================================================================
// InterfaceListDidChange
//===========================================================================================================================
@@ -3435,7 +3387,6 @@ void InterfaceListDidChange( mDNS * const inMDNS )
mDNSCoreMachineSleep( inMDNS, mDNSfalse ); // What is this for? Mac OS X does not do this
}
-
//===========================================================================================================================
// ComputerDescriptionDidChange
//===========================================================================================================================
@@ -3448,7 +3399,6 @@ void ComputerDescriptionDidChange( mDNS * const inMDNS )
SetupNiceName( inMDNS );
}
-
//===========================================================================================================================
// TCPIPConfigDidChange
//===========================================================================================================================
@@ -3463,7 +3413,6 @@ void TCPIPConfigDidChange( mDNS * const inMDNS )
check_noerr( err );
}
-
//===========================================================================================================================
// DynDNSConfigDidChange
//===========================================================================================================================
@@ -3480,7 +3429,6 @@ void DynDNSConfigDidChange( mDNS * const inMDNS )
check_noerr( err );
}
-
//===========================================================================================================================
// FileSharingDidChange
//===========================================================================================================================
@@ -3492,7 +3440,6 @@ void FileSharingDidChange( mDNS * const inMDNS )
CheckFileShares( inMDNS );
}
-
//===========================================================================================================================
// FilewallDidChange
//===========================================================================================================================
@@ -3504,7 +3451,6 @@ void FirewallDidChange( mDNS * const inMDNS )
CheckFileShares( inMDNS );
}
-
#if 0
#pragma mark -
#pragma mark == Utilities ==
@@ -3982,7 +3928,7 @@ mDNSlocal int getifaddrs_ipv4( struct ifaddrs **outAddrs )
ifa->ifa_name = (char *) malloc( 16 );
require_action( ifa->ifa_name, exit, err = WSAENOBUFS );
- sprintf( ifa->ifa_name, "%d", i + 1 );
+ _snprintf( ifa->ifa_name, 16, "%d", i + 1 );
// Get interface flags.
@@ -4092,7 +4038,6 @@ mDNSlocal void freeifaddrs( struct ifaddrs *inIFAs )
}
}
-
//===========================================================================================================================
// GetPrimaryInterface
//===========================================================================================================================
@@ -4123,7 +4068,6 @@ GetPrimaryInterface()
err = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
require_noerr( err, exit );
-
// Search for the row in the table we want.
for ( i = 0; i < pIpForwardTable->dwNumEntries; i++)
@@ -4152,7 +4096,6 @@ exit:
return index;
}
-
//===========================================================================================================================
// AddressToIndexAndMask
//===========================================================================================================================
@@ -4213,7 +4156,6 @@ exit:
return err;
}
-
//===========================================================================================================================
// CanReceiveUnicast
//===========================================================================================================================
@@ -4244,7 +4186,6 @@ mDNSlocal mDNSBool CanReceiveUnicast( void )
return( ok );
}
-
//===========================================================================================================================
// IsPointToPoint
//===========================================================================================================================
@@ -4286,7 +4227,6 @@ exit:
return ret;
}
-
//===========================================================================================================================
// GetWindowsVersionString
//===========================================================================================================================
@@ -4387,7 +4327,6 @@ exit:
return( err );
}
-
//===========================================================================================================================
// RegQueryString
//===========================================================================================================================
@@ -4436,7 +4375,6 @@ exit:
return err;
}
-
//===========================================================================================================================
// StringToAddress
//===========================================================================================================================
@@ -4476,7 +4414,6 @@ exit:
return err;
}
-
//===========================================================================================================================
// myGetIfAddrs
//===========================================================================================================================
@@ -4500,7 +4437,6 @@ myGetIfAddrs(int refresh)
return ifa;
}
-
//===========================================================================================================================
// TCHARtoUTF8
//===========================================================================================================================
@@ -4523,7 +4459,6 @@ exit:
#endif
}
-
//===========================================================================================================================
// WindowsLatin1toUTF8
//===========================================================================================================================
@@ -4561,7 +4496,6 @@ exit:
return( err );
}
-
//===========================================================================================================================
// TCPCloseSocket
//===========================================================================================================================
@@ -4578,7 +4512,6 @@ TCPCloseSocket( TCPSocket * sock )
}
}
-
//===========================================================================================================================
// UDPCloseSocket
//===========================================================================================================================
@@ -4596,7 +4529,6 @@ UDPCloseSocket( UDPSocket * sock )
}
}
-
//===========================================================================================================================
// SetupAddr
//===========================================================================================================================
@@ -4626,7 +4558,6 @@ mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
return(mStatus_Invalid);
}
-
mDNSlocal void GetDDNSFQDN( domainname *const fqdn )
{
LPSTR name = NULL;
@@ -4670,7 +4601,6 @@ exit:
}
}
-
#ifdef UNICODE
mDNSlocal void GetDDNSDomains( DNameListElem ** domains, LPCWSTR lpSubKey )
#else
@@ -4754,7 +4684,6 @@ exit:
}
}
-
mDNSlocal void SetDomainSecret( mDNS * const m, const domainname * inDomain )
{
char domainUTF8[ 256 ];
@@ -4801,7 +4730,6 @@ exit:
return;
}
-
mDNSlocal VOID CALLBACK
CheckFileSharesProc( LPVOID arg, DWORD dwTimerLowValue, DWORD dwTimerHighValue )
{
@@ -4813,7 +4741,6 @@ CheckFileSharesProc( LPVOID arg, DWORD dwTimerLowValue, DWORD dwTimerHighValue )
CheckFileShares( m );
}
-
mDNSlocal unsigned __stdcall
SMBRegistrationThread( void * arg )
{
@@ -4902,7 +4829,6 @@ exit:
return 0;
}
-
mDNSlocal void
CheckFileShares( mDNS * const m )
{
@@ -5056,7 +4982,6 @@ exit:
}
}
-
BOOL
IsWOMPEnabled( mDNS * const m )
{
@@ -5078,7 +5003,6 @@ IsWOMPEnabled( mDNS * const m )
return enabled;
}
-
mDNSlocal mDNSu8
IsWOMPEnabledForAdapter( const char * adapterName )
{
@@ -5128,7 +5052,6 @@ exit:
return ( mDNSu8 ) ok;
}
-
mDNSlocal void
SendWakeupPacket( mDNS * const inMDNS, LPSOCKADDR addr, INT addrlen, const char * buf, INT buflen, INT numTries, INT msecSleep )
{
@@ -5175,7 +5098,6 @@ exit:
}
}
-
mDNSlocal void _cdecl
SendMulticastWakeupPacket( void *arg )
{
@@ -5190,7 +5112,6 @@ SendMulticastWakeupPacket( void *arg )
_endthread();
}
-
mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result)
{
DEBUG_UNUSED( m );
diff --git a/mDNSResponder/mDNSWindows/mdnsNSP/mdnsNSP.c b/mDNSResponder/mDNSWindows/mdnsNSP/mdnsNSP.c
index 2cd01eff..21baa866 100644
--- a/mDNSResponder/mDNSWindows/mdnsNSP/mdnsNSP.c
+++ b/mDNSResponder/mDNSWindows/mdnsNSP/mdnsNSP.c
@@ -1847,7 +1847,7 @@ InHostsTable( const char * name )
HostsFile * hFile;
GetSystemDirectory( systemDirectory, sizeof( systemDirectory ) );
- sprintf( hFileName, "%s\\drivers\\etc\\hosts", systemDirectory );
+ snprintf( hFileName, sizeof( hFileName ), "%s\\drivers\\etc\\hosts", systemDirectory );
err = HostsFileOpen( &hFile, hFileName );
require_noerr( err, exit );
@@ -2072,6 +2072,7 @@ HostsFileNext( HostsFile * self, HostsFileInfo ** hInfo )
int idx;
int i;
short family;
+ size_t len;
OSStatus err = kNoErr;
check( self );
@@ -2146,9 +2147,10 @@ HostsFileNext( HostsFile * self, HostsFileInfo ** hInfo )
// Now we have the name
- (*hInfo)->m_host.h_name = (char*) malloc( strlen( tok ) + 1 );
+ len = strlen( tok ) + 1;
+ (*hInfo)->m_host.h_name = (char*) malloc( len );
require_action( (*hInfo)->m_host.h_name, exit, err = kNoMemoryErr );
- strcpy( (*hInfo)->m_host.h_name, tok );
+ strcpy_s( (*hInfo)->m_host.h_name, len, tok );
// Now create the address (IPv6/IPv4)
@@ -2220,10 +2222,11 @@ HostsFileNext( HostsFile * self, HostsFileInfo ** hInfo )
require_action( (*hInfo)->m_host.h_aliases, exit, err = kNoMemoryErr );
}
- (*hInfo)->m_host.h_aliases[i] = (char*) malloc( strlen( tok ) + 1 );
+ len = strlen( tok ) + 1;
+ (*hInfo)->m_host.h_aliases[i] = (char*) malloc( len );
require_action( (*hInfo)->m_host.h_aliases[i], exit, err = kNoMemoryErr );
- strcpy( (*hInfo)->m_host.h_aliases[i], tok );
+ strcpy_s( (*hInfo)->m_host.h_aliases[i], len, tok );
if (( tok = strpbrk( tok, " \t")) != NULL )
{
diff --git a/mDNSResponder/unittests/DNSMessageTest.c b/mDNSResponder/unittests/DNSMessageTest.c
new file mode 100644
index 00000000..fedfed3b
--- /dev/null
+++ b/mDNSResponder/unittests/DNSMessageTest.c
@@ -0,0 +1,50 @@
+#include "mDNSEmbeddedAPI.h"
+#include "DNSMessageTest.h"
+#include "../mDNSCore/DNSCommon.h"
+
+int SizeTest(void);
+int InitializeTest(void);
+int PutDomainNameAsLabels(void);
+int PutRData(void);
+int Finalize(void);
+
+
+DNSMessage *msg;
+
+
+UNITTEST_HEADER(DNSMessageTest)
+ UNITTEST_TEST(SizeTest)
+ UNITTEST_TEST(InitializeTest)
+ UNITTEST_TEST(Finalize)
+UNITTEST_FOOTER
+
+
+UNITTEST_HEADER(SizeTest)
+ msg = (DNSMessage *)malloc (sizeof(DNSMessage));
+ UNITTEST_ASSERT_RETURN(msg != NULL);
+
+ // message header should be 12 bytes
+ UNITTEST_ASSERT(sizeof(msg->h) == 12);
+UNITTEST_FOOTER
+
+
+UNITTEST_HEADER(InitializeTest)
+ // Initialize the message
+ InitializeDNSMessage(&msg->h, onesID, QueryFlags);
+
+ // Check that the message is initialized properly
+ UNITTEST_ASSERT(msg->h.numAdditionals == 0);
+ UNITTEST_ASSERT(msg->h.numAnswers == 0);
+ UNITTEST_ASSERT(msg->h.numQuestions == 0);
+ UNITTEST_ASSERT(msg->h.numAuthorities == 0);
+UNITTEST_FOOTER
+
+
+UNITTEST_HEADER(PutDomainNameAsLabels)
+
+UNITTEST_FOOTER
+
+UNITTEST_HEADER(Finalize)
+ UNITTEST_ASSERT_RETURN(msg != NULL)
+ free(msg);
+UNITTEST_FOOTER \ No newline at end of file
diff --git a/mDNSResponder/unittests/DNSMessageTest.h b/mDNSResponder/unittests/DNSMessageTest.h
new file mode 100644
index 00000000..147175f7
--- /dev/null
+++ b/mDNSResponder/unittests/DNSMessageTest.h
@@ -0,0 +1,8 @@
+#ifndef DNSMessageTest_h
+#define DNSMessageTest_h
+
+#include "unittest.h"
+
+int DNSMessageTest(void);
+
+#endif /* DNSMessageTest_h */ \ No newline at end of file
diff --git a/mDNSResponder/unittests/DomainNameTest.c b/mDNSResponder/unittests/DomainNameTest.c
new file mode 100644
index 00000000..571725a5
--- /dev/null
+++ b/mDNSResponder/unittests/DomainNameTest.c
@@ -0,0 +1,28 @@
+#include "DomainNameTest.h"
+#include "mDNSEmbeddedAPI.h"
+#include "../mDNSCore/DNSCommon.h"
+
+int SameDomainNameTest(void);
+int SameDomainLabelTest(void);
+int LocalDomainTest(void);
+
+
+UNITTEST_HEADER(DomainNameTest)
+ UNITTEST_TEST(SameDomainLabelTest)
+ UNITTEST_TEST(SameDomainNameTest)
+ UNITTEST_TEST(LocalDomainTest)
+UNITTEST_FOOTER
+
+
+
+
+UNITTEST_HEADER(SameDomainLabelTest)
+UNITTEST_FOOTER
+
+
+UNITTEST_HEADER(SameDomainNameTest)
+UNITTEST_FOOTER
+
+
+UNITTEST_HEADER(LocalDomainTest)
+UNITTEST_FOOTER \ No newline at end of file
diff --git a/mDNSResponder/unittests/DomainNameTest.h b/mDNSResponder/unittests/DomainNameTest.h
new file mode 100644
index 00000000..1c429c20
--- /dev/null
+++ b/mDNSResponder/unittests/DomainNameTest.h
@@ -0,0 +1,7 @@
+#ifndef DomainNameTest_h
+#define DomainNameTest_h
+
+#include "unittest.h"
+int DomainNameTest(void);
+
+#endif /* DomainNameTest_h */
diff --git a/mDNSResponder/unittests/InterfaceTest.c b/mDNSResponder/unittests/InterfaceTest.c
new file mode 100644
index 00000000..a9738141
--- /dev/null
+++ b/mDNSResponder/unittests/InterfaceTest.c
@@ -0,0 +1,19 @@
+#include "InterfaceTest.h"
+#include "mDNSEmbeddedAPI.h"
+
+
+NetworkInterfaceInfo *intf;
+mDNS *m;
+
+int LocalSubnetTest(void);
+
+UNITTEST_HEADER(InterfaceTest)
+ UNITTEST_TEST(LocalSubnetTest)
+UNITTEST_FOOTER
+
+UNITTEST_HEADER(LocalSubnetTest)
+ // need a way to initialize m before we call into the class of APIs that use a ptr to mDNS
+ // should that pointer be common to all tests?
+ // mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr)
+ // TEST_ASSERT_RETURN (for IPv4/IPv6 local subnet)
+UNITTEST_FOOTER
diff --git a/mDNSResponder/unittests/InterfaceTest.h b/mDNSResponder/unittests/InterfaceTest.h
new file mode 100644
index 00000000..f94b3da1
--- /dev/null
+++ b/mDNSResponder/unittests/InterfaceTest.h
@@ -0,0 +1,9 @@
+
+#ifndef InterfaceTest_h
+#define InterfaceTest_h
+
+#include "unittest.h"
+
+int InterfaceTest(void);
+
+#endif /* InterfaceTest_h */
diff --git a/mDNSResponder/unittests/ResourceRecordTest.c b/mDNSResponder/unittests/ResourceRecordTest.c
new file mode 100644
index 00000000..d0530086
--- /dev/null
+++ b/mDNSResponder/unittests/ResourceRecordTest.c
@@ -0,0 +1,60 @@
+#include "mDNSEmbeddedAPI.h"
+#include "../mDNSCore/DNSCommon.h"
+#include "ResourceRecordTest.h"
+
+int TXTSetupTest(void);
+int ASetupTest(void);
+int OPTSetupTest(void);
+
+
+UNITTEST_HEADER(ResourceRecordTest)
+ UNITTEST_TEST(TXTSetupTest)
+ UNITTEST_TEST(ASetupTest)
+ UNITTEST_TEST(OPTSetupTest)
+UNITTEST_FOOTER
+
+
+UNITTEST_HEADER(TXTSetupTest)
+
+ AuthRecord authRec;
+ mDNS_SetupResourceRecord(&authRec, mDNSNULL, mDNSInterface_Any, kDNSType_TXT, kStandardTTL, kDNSRecordTypeShared, AuthRecordAny,mDNSNULL, mDNSNULL);
+ UNITTEST_ASSERT_RETURN(authRec.resrec.RecordType == kDNSType_TXT);
+ UNITTEST_ASSERT_RETURN(authRec.resrec.rdata->MaxRDLength == sizeof(RDataBody));
+
+ // Retest with a RDataStorage set to a a buffer
+UNITTEST_FOOTER
+
+
+UNITTEST_HEADER(ASetupTest)
+ AuthRecord authRec;
+ mDNS_SetupResourceRecord(&authRec, mDNSNULL, mDNSInterface_Any, kDNSType_A, kHostNameTTL, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
+ UNITTEST_ASSERT_RETURN(authRec.resrec.RecordType == kDNSType_A);
+ // Add more verifications
+
+UNITTEST_FOOTER
+
+
+UNITTEST_HEADER(OPTSetupTest)
+ AuthRecord opt;
+ mDNSu32 updatelease = 7200;
+/* mDNSu8 data[AbsoluteMaxDNSMessageData];
+ mDNSu8 *p = data;
+ mDNSu16 numAdditionals;
+*/
+ // Setup the OPT Record
+ mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
+
+ // Verify the basic initialization is all ok
+
+ opt.resrec.rrclass = NormalMaxDNSMessageData;
+ opt.resrec.rdlength = sizeof(rdataOPT); // One option in this OPT record
+ opt.resrec.rdestimate = sizeof(rdataOPT);
+ opt.resrec.rdata->u.opt[0].opt = kDNSOpt_Lease;
+ opt.resrec.rdata->u.opt[0].u.updatelease = updatelease;
+
+ // Put the resource record in and verify everything is fine
+ // p = PutResourceRecordTTLWithLimit(&data, p, &numAdditionals, &opt.resrec, opt.resrec.rroriginalttl, data + AbsoluteMaxDNSMessageData);
+
+
+ // Repeat with bad data to make sure it bails out cleanly
+UNITTEST_FOOTER \ No newline at end of file
diff --git a/mDNSResponder/unittests/ResourceRecordTest.h b/mDNSResponder/unittests/ResourceRecordTest.h
new file mode 100644
index 00000000..d762d016
--- /dev/null
+++ b/mDNSResponder/unittests/ResourceRecordTest.h
@@ -0,0 +1,10 @@
+
+
+#ifndef ResourceRecordTest_h
+#define ResourceRecordTest_h
+
+#include "unittest.h"
+
+int ResourceRecordTest(void);
+
+#endif /* ResourceRecordTest_h */
diff --git a/mDNSResponder/unittests/main.c b/mDNSResponder/unittests/main.c
new file mode 100644
index 00000000..752fffb7
--- /dev/null
+++ b/mDNSResponder/unittests/main.c
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2015 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "unittest.h"
+#include "DNSMessageTest.h"
+
+const char *HWVersionString = "unittestMac1,1";
+const char *OSVersionString = "unittest 1.1.1 (1A111)";
+const char *BinaryNameString = "unittest";
+const char *VersionString = "unittest mDNSResponer-00 (Jan 1 1970 00:00:00)";
+
+int run_tests(void);
+
+UNITTEST_HEADER(run_tests)
+UNITTEST_GROUP(DNSMessageTest)
+UNITTEST_FOOTER
+
+UNITTEST_MAIN
diff --git a/mDNSResponder/unittests/unittest.c b/mDNSResponder/unittests/unittest.c
new file mode 100644
index 00000000..1ad4b030
--- /dev/null
+++ b/mDNSResponder/unittests/unittest.c
@@ -0,0 +1,105 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2015 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdlib.h>
+#include "unittest.h"
+
+int _unittest_assert_i(const int condition, const int i, const char * const conditionStr,
+ const char * const filename, const unsigned int linenum,
+ const char * const functionname, __test_item ** __i, int * const __success)
+{
+ if (!condition)
+ {
+ __test_item* tba = malloc(sizeof(__test_item));
+ tba->next = *__i;
+ tba->file = filename;
+ tba->line = linenum;
+ tba->func = functionname;
+ tba->s = conditionStr;
+ tba->iter_count = i;
+ *__i = tba;
+ *__success = 0;
+ printf("F");
+ }
+ else
+ {
+ printf(".");
+ }
+
+ fflush(NULL);
+ return condition;
+}
+
+void _unittest_print_list(__test_item* __i)
+{
+ __test_item* __tmp = NULL;
+ while (__i)
+ {
+ __test_item* __o = __i->next;
+ __i->next = __tmp;
+ __tmp = __i;
+ __i = __o;
+ }
+ __i = __tmp;
+
+ while(__i)
+ {
+ printf("%s: In function `%s':\n%s:%d: error: failed UNITTEST_ASSERT", __i->file, __i->func, __i->file, __i->line);
+ if (__i->iter_count != -1) printf(" at iteration %d", __i->iter_count);
+ printf(": %s\n", __i->s);
+ __test_item* tbd = __i;
+ __i = __i->next;
+ free(tbd);
+ }
+}
+
+// test by building like:
+// gcc -g -Wall -Werror -DTEST_UNITTEST_SCAFFOLD unittest.c
+// #define TEST_UNITTEST_SCAFFOLD 1
+#if TEST_UNITTEST_SCAFFOLD
+
+// modify this test as necessary to test the scaffold
+UNITTEST_HEADER(test1)
+ int i = 0;
+ int j = 1;
+ int k = 2;
+
+ UNITTEST_ASSERT(i==j);
+ UNITTEST_ASSERTI(j==i, k);
+ UNITTEST_ASSERT(i==i);
+ UNITTEST_ASSERTI(j==j, k);
+ UNITTEST_ASSERT_RETURN(j==j);
+ UNITTEST_ASSERTI_RETURN(j==j, k);
+UNITTEST_FOOTER
+
+UNITTEST_HEADER(test2)
+ UNITTEST_ASSERT(1);
+ UNITTEST_ASSERT(0);
+ UNITTEST_ASSERT(1);
+UNITTEST_FOOTER
+
+UNITTEST_HEADER(unittest_tests)
+UNITTEST_TEST(test1)
+UNITTEST_TEST(test2)
+UNITTEST_FOOTER
+
+UNITTEST_HEADER(run_tests)
+UNITTEST_GROUP(unittest_tests)
+UNITTEST_FOOTER
+
+UNITTEST_MAIN
+
+#endif // TEST_UNITTEST_SCAFFOLD
diff --git a/mDNSResponder/unittests/unittest.h b/mDNSResponder/unittests/unittest.h
new file mode 100644
index 00000000..a219aa86
--- /dev/null
+++ b/mDNSResponder/unittests/unittest.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2015 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <signal.h>
+
+#ifndef _UNITTEST_H_
+#define _UNITTEST_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct __test_item_
+{
+ struct __test_item_* next;
+ const char* file;
+ unsigned int line;
+ const char* func;
+ const char* s;
+ int iter_count;
+} __test_item;
+
+
+#define UNITTEST_HEADER(X) int X() { int __success = 1; __test_item* __i = NULL;
+
+#define UNITTEST_GROUP(X) { printf("== %s ==\n", #X); __success = X() && __success; }
+#define UNITTEST_TEST(X) { printf("%s: ", #X); fflush(NULL); __success = X() && __success; }
+
+int _unittest_assert_i(const int condition, const int i, const char * const conditionStr,
+ const char * const filename, const unsigned int linenum,
+ const char * const functionname, __test_item ** __i, int * const __success);
+#define UNITTEST_ASSERTI(X,I) (_unittest_assert_i((X)!=0, (I), #X, __FILE__, __LINE__, __func__, &__i, &__success))
+#define UNITTEST_ASSERT(X) UNITTEST_ASSERTI(X, -1)
+#define UNITTEST_ASSERTI_RETURN(X,I) { if (!UNITTEST_ASSERTI(X,I)) goto __unittest_footer__; }
+#define UNITTEST_ASSERT_RETURN(X) UNITTEST_ASSERTI_RETURN(X, -1)
+
+void _unittest_print_list(__test_item* __i);
+#define UNITTEST_FOOTER goto __unittest_footer__; __unittest_footer__: printf("\n"); fflush(NULL); _unittest_print_list(__i); return __success; }
+
+#define UNITTEST_MAIN int main (int argc, char** argv) \
+ { \
+ (void)(argv); \
+ signal(SIGPIPE, SIG_IGN); \
+ FILE* fp; \
+ unlink("unittest_success"); \
+ if (!run_tests()) return -1; \
+ fp = fopen("unittest_success", "w"); \
+ if (!fp) return -2; \
+ fclose(fp); \
+ printf("unit test SUCCESS\n"); \
+ if (argc != 1) \
+ { \
+ char c; \
+ printf("run leaks now\n"); \
+ read(STDIN_FILENO, &c, 1); \
+ } \
+ return 0; \
+ }
+
+#define UNITTEST_FAIL_ASSERT { assert(((void*)__func__) == 0); }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ndef _UNITTEST_H_