import latest version

This commit is contained in:
christos 2018-01-14 19:40:50 +00:00
parent d3be8271c6
commit ebf96090b3
67 changed files with 15032 additions and 3557 deletions

View File

@ -1,8 +1,8 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2008 Apple Inc. All rights reserved.
* Copyright (c) 2008-2011 Apple Inc. All rights reserved.
*
* Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
* Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
* ("Apple") in consideration of your agreement to the following terms, and your
* use, installation, modification or redistribution of this Apple software
* constitutes acceptance of these terms. If you do not agree with these terms,
@ -16,7 +16,7 @@
* the Apple Software in its entirety and without modifications, you must retain
* this notice and the following text and disclaimers in all such redistributions of
* the Apple Software. Neither the name, trademarks, service marks or logos of
* Apple Computer, Inc. may be used to endorse or promote products derived from the
* Apple Inc. may be used to endorse or promote products derived from the
* Apple Software without specific prior written permission from Apple. Except as
* expressly stated in this notice, no other rights or licenses, express or implied,
* are granted by Apple herein, including but not limited to any patent rights that
@ -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]))
{

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2012 Apple Inc. All rights reserved.
* Copyright (c) 2012-2015 Apple Inc. All rights reserved.
*
* dnsctl.c
* Command-line tool using libdns_services.dylib
@ -17,38 +17,42 @@
#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:
//*************************************************************************************************************
static void printtimestamp(void)
static void printtimestamp(void)
{
struct tm tm;
int ms;
struct tm tm;
int ms;
static char date[16];
static char new_date[16];
struct timeval tv;
struct timeval tv;
gettimeofday(&tv, NULL);
localtime_r((time_t*)&tv.tv_sec, &tm);
ms = tv.tv_usec/1000;
strftime(new_date, sizeof(new_date), "%a %d %b %Y", &tm);
//display date only if it has changed
if (strncmp(date, new_date, sizeof(new_date)))
{
{
printf("DATE: ---%s---\n", new_date);
strncpy(date, new_date, sizeof(date));
}
printf("%2d:%02d:%02d.%03d ", tm.tm_hour, tm.tm_min, tm.tm_sec, ms);
strlcpy(date, new_date, sizeof(date));
}
printf("%2d:%02d:%02d.%03d ", tm.tm_hour, tm.tm_min, tm.tm_sec, ms);
}
static void print_usage(const char *arg0)
@ -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)
{
@ -69,59 +92,108 @@ static void dnsproxy_reply(DNSXConnRef connRef, DNSXErrorType errCode)
printtimestamp();
switch (errCode)
{
case kDNSX_NoError : printf(" SUCCESS \n"); break;
case kDNSX_DictError : printf(" DICT ERROR \n"); break;
case kDNSX_NoError : printf(" SUCCESS \n");
break;
case kDNSX_DaemonNotRunning : printf(" NO DAEMON \n");
DNSXRefDeAlloc(ClientRef); break;
case kDNSX_Engaged : printf(" ENGAGED \n");
DNSXRefDeAlloc(ClientRef); break;
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;
default : printf(" UNKNOWN ERR \n");
DNSXRefDeAlloc(ClientRef); break;
}
fflush(NULL);
}
//*************************************************************************************************************
// XPC Funcs:
//*************************************************************************************************************
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)
{
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)
{
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;
// Extract program name from argv[0], which by convention contains the path to this executable
const char *a0 = strrchr(argv[0], kFilePathSep) + 1;
const char *a0 = strrchr(argv[0], kFilePathSep) + 1;
if (a0 == (const char *)1)
a0 = argv[0];
// Must run as root
if (0 != geteuid())
{
fprintf(stderr, "%s MUST run as root!!\n", a0);
exit(-1);
if (0 != geteuid())
{
fprintf(stderr, "%s MUST run as root!!\n", a0);
exit(-1);
}
if ((sizeof(argv) == 8))
printf("dnsctl running in 64-bit mode\n");
else if ((sizeof(argv) == 4))
printf("dnsctl running in 32-bit mode\n");
// expects atleast one argument
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("Proceeding to Enable 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);
}
else if (argc > 2)
{
argc--;
@ -129,17 +201,17 @@ int main(int argc, char **argv)
if (!strcmp(argv[1], "-o"))
{
Opintf = if_nametoindex(argv[2]);
if (!Opintf)
if (!Opintf)
Opintf = atoi(argv[2]);
if (!Opintf)
{
fprintf(stderr, "Could not parse o/p interface [%s]: Passing default primary \n", argv[2]);
if (!Opintf)
{
fprintf(stderr, "Could not parse o/p interface [%s]: Passing default primary \n", argv[2]);
Opintf = kDNSIfindexAny;
}
argc -= 2;
argv += 2;
}
if (argc > 2 && !strcmp(argv[1], "-i"))
if (argc > 2 && !strcmp(argv[1], "-i"))
{
int i;
argc--;
@ -148,31 +220,164 @@ int main(int argc, char **argv)
{
Ipintfs[i] = if_nametoindex(argv[1]);
if (!Ipintfs[i])
Ipintfs[i] = atoi(argv[1]);
Ipintfs[i] = atoi(argv[1]);
if (!Ipintfs[i])
{
fprintf(stderr, "Could not parse i/p interface [%s]: Passing default lo0 \n", argv[2]);
fprintf(stderr, "Could not parse i/p interface [%s]: Passing default lo0 \n", argv[2]);
Ipintfs[i] = 1;
}
argc--;
argv++;
}
}
printtimestamp();
printf("Proceeding to Enable DNSProxy on mDNSResponder \n");
}
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);
err = DNSXEnableProxy(&ClientRef, kDNSProxyEnable, Ipintfs, Opintf, my_Q, dnsproxy_reply);
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;
}
dispatch_main();
dispatch_main();
Usage:
print_usage(a0);
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);
}
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2011-2012 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.

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2011-2012 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.
@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CRYPTO_ALG_H
#define __CRYPTO_ALG_H

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2002-2013 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2002-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.
@ -21,6 +21,10 @@
#include "CryptoAlg.h"
#include "anonymous.h"
#ifdef UNIT_TEST
#include "unittest.h"
#endif
// Disable certain benign warnings with Microsoft compilers
#if (defined(_MSC_VER))
// Disable "conditional expression is constant" warning for debug macros.
@ -43,6 +47,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,8 +112,11 @@ 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 } };
mDNSexport const mDNSOpaque64 zeroOpaque64 = { { 0 } };
mDNSexport const mDNSOpaque128 zeroOpaque128 = { { 0 } };
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
@ -510,10 +518,10 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RD
length += mDNS_snprintf(buffer+length, RemSpc, "\t%s %s %d %d %s %s %d %##s ",
DNSTypeName(swap16(rrsig->typeCovered)), DNSSECAlgName(rrsig->alg), rrsig->labels, swap32(rrsig->origTTL),
expTimeBuf, inceptTimeBuf, swap16(rrsig->keyTag), ((domainname *)(&rrsig->signerName))->c);
expTimeBuf, inceptTimeBuf, swap16(rrsig->keyTag), rrsig->signerName);
len = DomainNameLength((domainname *)&rrsig->signerName);
length += baseEncode(buffer + length, RemSpc, (const mDNSu8 *)(rd->data + len + RRSIG_FIXED_SIZE),
baseEncode(buffer + length, RemSpc, (const mDNSu8 *)(rd->data + len + RRSIG_FIXED_SIZE),
rr->rdlength - (len + RRSIG_FIXED_SIZE), ENC_BASE64);
}
break;
@ -521,7 +529,7 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RD
rdataDNSKey *rrkey = (rdataDNSKey *)rd->data;
length += mDNS_snprintf(buffer+length, RemSpc, "\t%d %d %s %u ", swap16(rrkey->flags), rrkey->proto,
DNSSECAlgName(rrkey->alg), (unsigned int)keytag((mDNSu8 *)rrkey, rr->rdlength));
length += baseEncode(buffer + length, RemSpc, (const mDNSu8 *)(rd->data + DNSKEY_FIXED_SIZE),
baseEncode(buffer + length, RemSpc, (const mDNSu8 *)(rd->data + DNSKEY_FIXED_SIZE),
rr->rdlength - DNSKEY_FIXED_SIZE, ENC_BASE64);
}
break;
@ -541,7 +549,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;
@ -619,6 +627,8 @@ mDNSexport mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip)
#pragma mark - Domain Name Utility Functions
#endif
#if !APPLE_OSX_mDNSResponder
mDNSexport mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b)
{
int i;
@ -639,6 +649,8 @@ mDNSexport mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b)
return(mDNStrue);
}
#endif // !APPLE_OSX_mDNSResponder
mDNSexport mDNSBool SameDomainName(const domainname *const d1, const domainname *const d2)
{
const mDNSu8 * a = d1->c;
@ -803,6 +815,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 +828,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
@ -967,10 +980,6 @@ mDNSexport void ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], do
hostlabel->c[0] = (mDNSu8)(ptr - &hostlabel->c[1]);
}
#define ValidTransportProtocol(X) ( (X)[0] == 4 && (X)[1] == '_' && \
((((X)[2] | 0x20) == 'u' && ((X)[3] | 0x20) == 'd') || (((X)[2] | 0x20) == 't' && ((X)[3] | 0x20) == 'c')) && \
((X)[4] | 0x20) == 'p')
mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn,
const domainlabel *name, const domainname *type, const domainname *const domain)
{
@ -1029,10 +1038,6 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn,
{
LogMsg("Bad service type in %#s.%##s%##s Application protocol name must be underscore plus 1-15 characters. "
"See <http://www.dns-sd.org/ServiceTypes.html>", name->c, type->c, domain->c);
#if APPLE_OSX_mDNSResponder
ConvertDomainNameToCString(type, typeBuf);
mDNSASLLog(mDNSNULL, "serviceType.nameTooLong", "noop", typeBuf, "");
#endif
}
if (len < 2 || len >= 0x40 || (len > 16 && !SameDomainName(domain, &localdomain))) return(mDNSNULL);
if (src[1] != '_') { errormsg = "Application protocol name must begin with underscore"; goto fail; }
@ -1049,19 +1054,13 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn,
if (src[i] == '_' && loggedUnderscore == mDNSfalse)
{
ConvertDomainNameToCString(type, typeBuf);
mDNSASLLog(mDNSNULL, "serviceType.nameWithUnderscore", "noop", typeBuf, "");
LogInfo("ConstructServiceName: Service type with non-leading underscore %s", typeBuf);
loggedUnderscore = mDNStrue;
}
#endif
continue;
}
errormsg = "Application protocol name must contain only letters, digits, and hyphens";
#if APPLE_OSX_mDNSResponder
{
ConvertDomainNameToCString(type, typeBuf);
mDNSASLLog(mDNSNULL, "serviceType.nameWithIllegalCharacters", "noop", typeBuf, "");
}
#endif
goto fail;
}
for (i=0; i<=len; i++) *dst++ = *src++;
@ -1165,7 +1164,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 +1183,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 +1368,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 +1465,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;
@ -1481,6 +1477,7 @@ mDNSexport void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID I
q->qnameOrig = mDNSNULL;
q->AnonInfo = mDNSNULL;
q->pid = mDNSPlatformGetPID();
q->euid = 0;
q->DisallowPID = mDNSfalse;
q->ServiceID = -1;
q->QuestionCallback = callback;
@ -1778,7 +1775,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;
@ -1913,7 +1910,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;
@ -2141,7 +2138,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
@ -2357,13 +2353,9 @@ mDNSexport mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNS
case kDNSType_NSEC: {
// For NSEC records, rdlength represents the exact number of bytes
// of in memory storage.
int len = rr->rdlength;
mDNSu8 *nsec = (mDNSu8 *)rdb->data;
domainname *name = (domainname *)nsec;
int dlen;
dlen = DomainNameLength(name);
len -= dlen;
const int dlen = DomainNameLength(name);
nsec += dlen;
// This function is called when we are sending a NSEC record as part of mDNS,
// or to copy the data to any other buffer needed which could be a mDNS or uDNS
@ -2376,7 +2368,6 @@ mDNSexport mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNS
int i, j, wlen;
wlen = *(nsec + 1);
nsec += 2; // Skip the window number and len
len -= 2;
// For our simplified use of NSEC synthetic records:
//
@ -2406,6 +2397,7 @@ mDNSexport mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNS
else
{
int win, wlen;
int len = rr->rdlength - dlen;
// Sanity check whether the bitmap is good
while (len)
@ -2607,7 +2599,7 @@ mDNSexport mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domain
}
// for dynamic updates
mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease)
mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease)
{
AuthRecord rr;
mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
@ -2616,13 +2608,13 @@ mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease)
rr.resrec.rdestimate = sizeof(rdataOPT);
rr.resrec.rdata->u.opt[0].opt = kDNSOpt_Lease;
rr.resrec.rdata->u.opt[0].u.updatelease = lease;
end = PutResourceRecordTTLJumbo(msg, end, &msg->h.numAdditionals, &rr.resrec, 0);
if (!end) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTL"); return mDNSNULL; }
return end;
ptr = PutResourceRecordTTLJumbo(msg, ptr, &msg->h.numAdditionals, &rr.resrec, 0);
if (!ptr) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTL"); return mDNSNULL; }
return ptr;
}
// for dynamic updates
mDNSexport mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease, mDNSu8 *limit)
mDNSexport mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease, mDNSu8 *limit)
{
AuthRecord rr;
mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
@ -2631,9 +2623,9 @@ mDNSexport mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *end, mDNSu32
rr.resrec.rdestimate = sizeof(rdataOPT);
rr.resrec.rdata->u.opt[0].opt = kDNSOpt_Lease;
rr.resrec.rdata->u.opt[0].u.updatelease = lease;
end = PutResourceRecordTTLWithLimit(msg, end, &msg->h.numAdditionals, &rr.resrec, 0, limit);
if (!end) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTLWithLimit"); return mDNSNULL; }
return end;
ptr = PutResourceRecordTTLWithLimit(msg, ptr, &msg->h.numAdditionals, &rr.resrec, 0, limit);
if (!ptr) { LogMsg("ERROR: putUpdateLeaseWithLimit - PutResourceRecordTTLWithLimit"); return mDNSNULL; }
return ptr;
}
mDNSexport mDNSu8 *putDNSSECOption(DNSMessage *msg, mDNSu8 *end, mDNSu8 *limit)
@ -2650,7 +2642,7 @@ mDNSexport mDNSu8 *putDNSSECOption(DNSMessage *msg, mDNSu8 *end, mDNSu8 *limit)
// set the DO bit
ttl |= 0x8000;
end = PutResourceRecordTTLWithLimit(msg, end, &msg->h.numAdditionals, &rr.resrec, ttl, limit);
if (!end) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTLWithLimit"); return mDNSNULL; }
if (!end) { LogMsg("ERROR: putDNSSECOption - PutResourceRecordTTLWithLimit"); return mDNSNULL; }
return end;
}
@ -2757,12 +2749,12 @@ mDNSexport const mDNSu8 *getDomainName(const DNSMessage *const msg, const mDNSu8
while (1) // Read sequence of labels
{
int i;
mDNSu16 offset;
const mDNSu8 len = *ptr++; // Read length of this label
if (len == 0) break; // If length is zero, that means this name is complete
switch (len & 0xC0)
{
int i;
mDNSu16 offset;
case 0x00: if (ptr + len >= end) // Remember: expect at least one more byte for the root label
{ debugf("getDomainName: Malformed domain name (overruns packet end)"); return(mDNSNULL); }
@ -2846,7 +2838,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)
@ -3351,6 +3343,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;
@ -3441,12 +3439,7 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage
mDNSu16 pktrdlength;
if (largecr == &m->rec && m->rec.r.resrec.RecordType)
{
LogMsg("GetLargeResourceRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r));
#if ForceAlerts
*(long*)0 = 0;
#endif
}
LogFatalError("GetLargeResourceRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r));
rr->next = mDNSNULL;
rr->resrec.name = &largecr->namestorage;
@ -3459,12 +3452,6 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage
rr->CRActiveQuestion = mDNSNULL;
rr->UnansweredQueries = 0;
rr->LastUnansweredTime= 0;
#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
rr->MPUnansweredQ = 0;
rr->MPLastUnansweredQT= 0;
rr->MPUnansweredKA = 0;
rr->MPExpectingKA = mDNSfalse;
#endif
rr->NextInCFList = mDNSNULL;
rr->resrec.InterfaceID = InterfaceID;
@ -3619,22 +3606,33 @@ mDNSexport const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const
}
// Get the lease life of records in a dynamic update
// returns 0 on error or if no lease present
mDNSexport mDNSu32 GetPktLease(mDNS *m, DNSMessage *msg, const mDNSu8 *end)
mDNSexport mDNSBool GetPktLease(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, mDNSu32 *const lease)
{
mDNSu32 result = 0;
const mDNSu8 *ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space);
if (ptr) ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
if (ptr && m->rec.r.resrec.rdlength >= DNSOpt_LeaseData_Space && m->rec.r.resrec.rdata->u.opt[0].opt == kDNSOpt_Lease)
result = m->rec.r.resrec.rdata->u.opt[0].u.updatelease;
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
return(result);
if (ptr)
{
ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_OPT)
{
const rdataOPT *o;
const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength];
for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++)
if (o->opt == kDNSOpt_Lease)
{
*lease = o->u.updatelease;
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
return mDNStrue;
}
}
m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
}
return mDNSfalse;
}
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,
@ -3642,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);
}
@ -3654,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" : \
@ -3686,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",
@ -3705,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");
ptr = DumpRecords(m, msg, ptr, end, msg->h.numAdditionals, "Additionals");
LogMsg("--------------");
DumpRecords(m, msg, ptr, end, msg->h.numAdditionals, "Additionals");
LogInfo("--------------");
}
// ***************************************************************************
@ -3723,13 +3725,14 @@ mDNSexport void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *t
#pragma mark - Packet Sending Functions
#endif
#ifdef UNIT_TEST
// Run the unit test of mDNSSendDNSMessage
UNITTEST_SENDDNSMESSAGE
#else
// Stub definition of TCPSocket_struct so we can access flags field. (Rest of TCPSocket_struct is platform-dependent.)
struct TCPSocket_struct { TCPSocketFlags flags; /* ... */ };
struct UDPSocket_struct
{
mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
};
// Stub definition of UDPSocket_struct so we can access port field. (Rest of UDPSocket_struct is platform-dependent.)
struct UDPSocket_struct { mDNSIPPort port; /* ... */ };
// Note: When we sign a DNS message using DNSDigest_SignMessage(), the current real-time clock value is used, which
// is why we generally defer signing until we send the message, to ensure the signature is as fresh as possible.
@ -3827,6 +3830,7 @@ mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNS
return(status);
}
#endif // UNIT_TEST
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
@ -3844,12 +3848,7 @@ mDNSexport void mDNS_Lock_(mDNS *const m, const char * const functionname)
// If that client callback does mDNS API calls, mDNS_reentrancy and mDNS_busy will both be one
// If mDNS_busy != mDNS_reentrancy that's a bad sign
if (m->mDNS_busy != m->mDNS_reentrancy)
{
LogMsg("%s: mDNS_Lock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy);
#if ForceAlerts
*(long*)0 = 0;
#endif
}
LogFatalError("%s: mDNS_Lock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy);
// If this is an initial entry into the mDNSCore code, set m->timenow
// else, if this is a re-entrant entry into the mDNSCore code, m->timenow should already be set
@ -3889,7 +3888,7 @@ mDNSlocal AuthRecord *AnyLocalRecordReady(const mDNS *const m)
mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m)
{
mDNSs32 e = m->timenow + 0x78000000;
mDNSs32 e = m->timenow + FutureTime;
if (m->mDNSPlatformStatus != mStatus_NoError) return(e);
if (m->NewQuestions)
{
@ -3912,6 +3911,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;
@ -3927,85 +3930,95 @@ 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);
}
#define LogTSE TSE++,LogMsg
mDNSexport void ShowTaskSchedulingError(mDNS *const m)
{
int TSE = 0;
AuthRecord *rr;
mDNS_Lock(m);
LogMsg("Task Scheduling Error: Continuously busy for more than a second");
LogMsg("Task Scheduling Error: *** Continuously busy for more than a second");
// Note: To accurately diagnose *why* we're busy, the debugging code here needs to mirror the logic in GetNextScheduledEvent above
if (m->NewQuestions && (!m->NewQuestions->DelayAnswering || m->timenow - m->NewQuestions->DelayAnswering >= 0))
LogMsg("Task Scheduling Error: NewQuestion %##s (%s)",
LogTSE("Task Scheduling Error: NewQuestion %##s (%s)",
m->NewQuestions->qname.c, DNSTypeName(m->NewQuestions->qtype));
if (m->NewLocalOnlyQuestions)
LogMsg("Task Scheduling Error: NewLocalOnlyQuestions %##s (%s)",
LogTSE("Task Scheduling Error: NewLocalOnlyQuestions %##s (%s)",
m->NewLocalOnlyQuestions->qname.c, DNSTypeName(m->NewLocalOnlyQuestions->qtype));
if (m->NewLocalRecords)
{
rr = AnyLocalRecordReady(m);
if (rr) LogMsg("Task Scheduling Error: NewLocalRecords %s", ARDisplayString(m, rr));
if (rr) LogTSE("Task Scheduling Error: NewLocalRecords %s", ARDisplayString(m, rr));
}
if (m->NewLocalOnlyRecords) LogMsg("Task Scheduling Error: NewLocalOnlyRecords");
if (m->NewLocalOnlyRecords) LogTSE("Task Scheduling Error: NewLocalOnlyRecords");
if (m->SPSProxyListChanged) LogMsg("Task Scheduling Error: SPSProxyListChanged");
if (m->LocalRemoveEvents) LogMsg("Task Scheduling Error: LocalRemoveEvents");
if (m->SPSProxyListChanged) LogTSE("Task Scheduling Error: SPSProxyListChanged");
if (m->timenow - m->NextScheduledEvent >= 0)
LogMsg("Task Scheduling Error: m->NextScheduledEvent %d", m->timenow - m->NextScheduledEvent);
if (m->LocalRemoveEvents) LogTSE("Task Scheduling Error: LocalRemoveEvents");
#ifndef UNICAST_DISABLED
if (m->timenow - m->NextuDNSEvent >= 0)
LogMsg("Task Scheduling Error: m->NextuDNSEvent %d", m->timenow - m->NextuDNSEvent);
LogTSE("Task Scheduling Error: m->NextuDNSEvent %d", m->timenow - m->NextuDNSEvent);
if (m->timenow - m->NextScheduledNATOp >= 0)
LogMsg("Task Scheduling Error: m->NextScheduledNATOp %d", m->timenow - m->NextScheduledNATOp);
LogTSE("Task Scheduling Error: m->NextScheduledNATOp %d", m->timenow - m->NextScheduledNATOp);
if (m->NextSRVUpdate && m->timenow - m->NextSRVUpdate >= 0)
LogMsg("Task Scheduling Error: m->NextSRVUpdate %d", m->timenow - m->NextSRVUpdate);
LogTSE("Task Scheduling Error: m->NextSRVUpdate %d", m->timenow - m->NextSRVUpdate);
#endif
if (m->timenow - m->NextCacheCheck >= 0)
LogMsg("Task Scheduling Error: m->NextCacheCheck %d", m->timenow - m->NextCacheCheck);
LogTSE("Task Scheduling Error: m->NextCacheCheck %d", m->timenow - m->NextCacheCheck);
if (m->timenow - m->NextScheduledSPS >= 0)
LogMsg("Task Scheduling Error: m->NextScheduledSPS %d", m->timenow - m->NextScheduledSPS);
LogTSE("Task Scheduling Error: m->NextScheduledSPS %d", m->timenow - m->NextScheduledSPS);
if (m->timenow - m->NextScheduledKA >= 0)
LogMsg("Task Scheduling Error: m->NextScheduledKA %d", m->timenow - m->NextScheduledKA);
LogTSE("Task Scheduling Error: m->NextScheduledKA %d", m->timenow - m->NextScheduledKA);
if (!m->DelaySleep && m->SleepLimit && m->timenow - m->NextScheduledSPRetry >= 0)
LogMsg("Task Scheduling Error: m->NextScheduledSPRetry %d", m->timenow - m->NextScheduledSPRetry);
LogTSE("Task Scheduling Error: m->NextScheduledSPRetry %d", m->timenow - m->NextScheduledSPRetry);
if (m->DelaySleep && m->timenow - m->DelaySleep >= 0)
LogMsg("Task Scheduling Error: m->DelaySleep %d", m->timenow - m->DelaySleep);
LogTSE("Task Scheduling Error: m->DelaySleep %d", m->timenow - m->DelaySleep);
if (m->SuppressSending && m->timenow - m->SuppressSending >= 0)
LogMsg("Task Scheduling Error: m->SuppressSending %d", m->timenow - m->SuppressSending);
LogTSE("Task Scheduling Error: m->SuppressSending %d", m->timenow - m->SuppressSending);
if (m->timenow - m->NextScheduledQuery >= 0)
LogMsg("Task Scheduling Error: m->NextScheduledQuery %d", m->timenow - m->NextScheduledQuery);
LogTSE("Task Scheduling Error: m->NextScheduledQuery %d", m->timenow - m->NextScheduledQuery);
if (m->timenow - m->NextScheduledProbe >= 0)
LogMsg("Task Scheduling Error: m->NextScheduledProbe %d", m->timenow - m->NextScheduledProbe);
LogTSE("Task Scheduling Error: m->NextScheduledProbe %d", m->timenow - m->NextScheduledProbe);
if (m->timenow - m->NextScheduledResponse >= 0)
LogMsg("Task Scheduling Error: m->NextScheduledResponse %d", m->timenow - m->NextScheduledResponse);
LogTSE("Task Scheduling Error: m->NextScheduledResponse %d", m->timenow - m->NextScheduledResponse);
if (m->timenow - m->NextScheduledStopTime >= 0)
LogTSE("Task Scheduling Error: m->NextScheduledStopTime %d", m->timenow - m->NextScheduledStopTime);
if (m->timenow - m->NextScheduledEvent >= 0)
LogTSE("Task Scheduling Error: m->NextScheduledEvent %d", m->timenow - m->NextScheduledEvent);
if (m->NetworkChanged && m->timenow - m->NetworkChanged >= 0)
LogTSE("Task Scheduling Error: NetworkChanged %d", m->timenow - m->NetworkChanged);
if (!TSE) LogMsg("Task Scheduling Error: *** No likely causes identified");
else LogMsg("Task Scheduling Error: *** %d potential cause%s identified (significant only if the same cause consistently appears)", TSE, TSE > 1 ? "s" : "");
mDNS_Unlock(m);
}
mDNSexport void mDNS_Unlock_(mDNS *const m, const char * const functionname)
mDNSexport void mDNS_Unlock_(mDNS *const m, const char *const functionname)
{
// Decrement mDNS_busy
m->mDNS_busy--;
// Check for locking failures
if (m->mDNS_busy != m->mDNS_reentrancy)
{
LogMsg("%s: mDNS_Unlock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy);
#if ForceAlerts
*(long*)0 = 0;
#endif
}
LogFatalError("%s: mDNS_Unlock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy);
// If this is a final exit from the mDNSCore code, set m->NextScheduledEvent and clear m->timenow
if (m->mDNS_busy == 0)
@ -4049,7 +4062,8 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt
for (c = *fmt; c != 0; c = *++fmt)
{
if (c != '%')
unsigned long n;
if (c != '%')
{
*sbuffer++ = (char)c;
if (++nwritten >= buflen) goto exit;
@ -4105,7 +4119,6 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt
conv:
switch (c) // perform appropriate conversion
{
unsigned long n;
case 'h': F.hSize = 1; c = *++fmt; goto conv;
case 'l': // fall through
case 'L': F.lSize = 1; c = *++fmt; goto conv;

View File

@ -40,17 +40,19 @@ extern "C" {
typedef enum
{
kDNSFlag0_QR_Mask = 0x80, // Query or response?
kDNSFlag0_QR_Query = 0x00,
kDNSFlag0_QR_Response = 0x80,
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_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 -
@ -220,7 +223,7 @@ extern mDNSu8 *putDeletionRecord(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *r
extern mDNSu8 *putDeletionRecordWithLimit(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr, mDNSu8 *limit);
extern mDNSu8 *putDeleteRRSetWithLimit(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype, mDNSu8 *limit);
extern mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name);
extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease);
extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease);
extern mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease, mDNSu8 *limit);
extern mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *ptr, DomainAuthInfo *authInfo, mDNSu8 *limit);
@ -237,8 +240,7 @@ extern const mDNSu8 *NSEC3HashName(const domainname *name, rdataNSEC3 *nsec3, co
#pragma mark - DNS Message Parsing Functions
#endif
#define AuthHashSlot(X) (DomainNameHashValue(X) % AUTH_HASH_SLOTS)
#define HashSlot(X) (DomainNameHashValue(X) % CACHE_HASH_SLOTS)
#define HashSlotFromNameHash(X) ((X) % CACHE_HASH_SLOTS)
extern mDNSu32 DomainNameHashValue(const domainname *const name);
extern void SetNewRData(ResourceRecord *const rr, RData *NewRData, mDNSu16 rdlength);
extern const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end);
@ -257,7 +259,7 @@ extern const mDNSu8 *LocateAuthorities(const DNSMessage *const msg, const mDNSu8
extern const mDNSu8 *LocateAdditionals(const DNSMessage *const msg, const mDNSu8 *const end);
extern const mDNSu8 *LocateOptRR(const DNSMessage *const msg, const mDNSu8 *const end, int minsize);
extern const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end);
extern mDNSu32 GetPktLease(mDNS *m, DNSMessage *msg, const mDNSu8 *end);
extern mDNSBool GetPktLease(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, mDNSu32 *const lease);
extern void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *transport,
const mDNSAddr *srcaddr, mDNSIPPort srcport,
const mDNSAddr *dstaddr, mDNSIPPort dstport, const DNSMessage *const msg, const mDNSu8 *const end);
@ -297,16 +299,16 @@ extern void mDNS_Unlock_(mDNS *const m, const char * const functionname);
#define mDNS_Unlock(X) mDNS_Unlock_((X), __func__)
#define mDNS_CheckLock(X) { if ((X)->mDNS_busy != (X)->mDNS_reentrancy+1) \
LogMsg("%s: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", __func__, (X)->mDNS_busy, (X)->mDNS_reentrancy); }
#define mDNS_CheckLock(X) \
if ((X)->mDNS_busy != (X)->mDNS_reentrancy+1) LogMsg("%s: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", __func__, (X)->mDNS_busy, (X)->mDNS_reentrancy)
#define mDNS_DropLockBeforeCallback() do { m->mDNS_reentrancy++; \
if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Locking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \
} while (0)
if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Locking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \
} while (0)
#define mDNS_ReclaimLockAfterCallback() do { \
if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Unlocking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \
m->mDNS_reentrancy--; } while (0)
if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Unlocking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \
m->mDNS_reentrancy--; } while (0)
#ifdef __cplusplus
}

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2002-2011 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2002-2011 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.
@ -15,7 +15,6 @@
* limitations under the License.
*/
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2012 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2012-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.
@ -27,6 +27,14 @@
#define ANON_NSEC3_ITERATIONS 1
struct AnonInfoResourceRecord_struct
{
ResourceRecord resrec;
RData rdatastorage;
};
typedef struct AnonInfoResourceRecord_struct AnonInfoResourceRecord;
mDNSlocal mDNSBool InitializeNSEC3Record(ResourceRecord *rr, const mDNSu8 *AnonData, int len, mDNSu32 salt)
{
const mDNSu8 *ptr;
@ -63,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)
@ -118,9 +126,10 @@ mDNSlocal ResourceRecord *ConstructNSEC3Record(const domainname *service, const
mDNSlocal ResourceRecord *CopyNSEC3ResourceRecord(AnonymousInfo *si, const ResourceRecord *rr)
{
int len;
AnonInfoResourceRecord *anonRR;
domainname *name;
ResourceRecord *nsec3rr;
mDNSu32 neededLen;
mDNSu32 extraLen;
if (rr->rdlength < MCAST_NSEC3_RDLENGTH)
{
@ -128,22 +137,26 @@ mDNSlocal ResourceRecord *CopyNSEC3ResourceRecord(AnonymousInfo *si, const Resou
return mDNSNULL;
}
// Allocate space for the name and the rdata along with the ResourceRecord
len = DomainNameLength(rr->name);
nsec3rr = mDNSPlatformMemAllocate(sizeof(ResourceRecord) + len + sizeof(RData));
if (!nsec3rr)
neededLen = rr->rdlength + DomainNameLength(rr->name);
extraLen = (neededLen > sizeof(RDataBody)) ? (neededLen - sizeof(RDataBody)) : 0;
anonRR = (AnonInfoResourceRecord *)mDNSPlatformMemAllocate(sizeof(AnonInfoResourceRecord) + extraLen);
if (!anonRR)
return mDNSNULL;
*nsec3rr = *rr;
name = (domainname *)((mDNSu8 *)nsec3rr + sizeof(ResourceRecord));
nsec3rr->name = (const domainname *)name;
anonRR->resrec = *rr;
anonRR->rdatastorage.MaxRDLength = rr->rdlength;
mDNSPlatformMemCopy(anonRR->rdatastorage.u.data, rr->rdata->u.data, rr->rdlength);
name = (domainname *)(anonRR->rdatastorage.u.data + rr->rdlength);
AssignDomainName(name, rr->name);
nsec3rr->rdata = (RData *)((mDNSu8 *)nsec3rr->name + len);
mDNSPlatformMemCopy(nsec3rr->rdata->u.data, rr->rdata->u.data, rr->rdlength);
anonRR->resrec.name = name;
anonRR->resrec.rdata = &anonRR->rdatastorage;
si->nsec3RR = nsec3rr;
si->nsec3RR = (ResourceRecord *)anonRR;
return nsec3rr;
return si->nsec3RR;
}
// When a service is started or a browse is started with the Anonymous data, we allocate a new random
@ -227,6 +240,12 @@ mDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQues
debugf("SetAnonData: question %##s(%p), rr %##s(%p)", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo);
if (ForQuestion)
{
if (q->AnonInfo->AnonDataLen < rr->AnonInfo->AnonDataLen)
{
mDNSPlatformMemFree(q->AnonInfo->AnonData);
q->AnonInfo->AnonData = mDNSNULL;
}
if (!q->AnonInfo->AnonData)
{
q->AnonInfo->AnonData = mDNSPlatformMemAllocate(rr->AnonInfo->AnonDataLen);
@ -238,6 +257,12 @@ mDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQues
}
else
{
if (rr->AnonInfo->AnonDataLen < q->AnonInfo->AnonDataLen)
{
mDNSPlatformMemFree(rr->AnonInfo->AnonData);
rr->AnonInfo->AnonData = mDNSNULL;
}
if (!rr->AnonInfo->AnonData)
{
rr->AnonInfo->AnonData = mDNSPlatformMemAllocate(q->AnonInfo->AnonDataLen);
@ -262,9 +287,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);
@ -385,7 +411,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)

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2012 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2012 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.

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2011-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.
@ -19,6 +19,8 @@
#ifndef UNICAST_DISABLED
mDNSexport mDNS mDNSStorage;
// Implementation Notes
//
// DNS Proxy listens on port 53 (UDPv4v6 & TCPv4v6) for DNS queries. It handles only
@ -72,7 +74,7 @@ struct DNSProxyClient_struct {
};
#define MIN_DNS_MESSAGE_SIZE 512
DNSProxyClient *DNSProxyClients;
static DNSProxyClient *DNSProxyClients;
mDNSlocal void FreeDNSProxyClient(DNSProxyClient *pc)
{
@ -83,10 +85,6 @@ mDNSlocal void FreeDNSProxyClient(DNSProxyClient *pc)
mDNSlocal mDNSBool ParseEDNS0(DNSProxyClient *pc, const mDNSu8 *ptr, int length, const mDNSu8 *limit)
{
mDNSu16 rrtype, rrclass;
mDNSu8 rcode, version;
mDNSu16 flag;
if (ptr + length > limit)
{
LogInfo("ParseEDNS0: Not enough space in the packet");
@ -94,18 +92,19 @@ mDNSlocal mDNSBool ParseEDNS0(DNSProxyClient *pc, const mDNSu8 *ptr, int length,
}
// Skip the root label
ptr++;
rrtype = (mDNSu16) ((mDNSu16)ptr[0] << 8 | ptr[1]);
mDNSu16 rrtype = (mDNSu16) ((mDNSu16)ptr[0] << 8 | ptr[1]);
if (rrtype != kDNSType_OPT)
{
LogInfo("ParseEDNS0: Not the right type %d", rrtype);
return mDNSfalse;
}
rrclass = (mDNSu16) ((mDNSu16)ptr[2] << 8 | ptr[3]);
rcode = ptr[4];
version = ptr[5];
flag = (mDNSu16) ((mDNSu16)ptr[6] << 8 | ptr[7]);
mDNSu16 rrclass = (mDNSu16) ((mDNSu16)ptr[2] << 8 | ptr[3]);
#if MDNS_DEBUGMSGS
mDNSu8 rcode = ptr[4];
mDNSu8 version = ptr[5];
mDNSu16 flag = (mDNSu16) ((mDNSu16)ptr[6] << 8 | ptr[7]);
debugf("rrtype is %s, length is %d, rcode %d, version %d, flag 0x%x", DNSTypeName(rrtype), rrclass, rcode, version, flag);
#endif
pc->rcvBufSize = rrclass;
pc->DNSSECOK = ptr[6] & 0x80;
@ -133,7 +132,7 @@ mDNSexport mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DN
return ptr;
}
mDNSlocal mDNSu8 *AddEDNS0Option(mDNS *const m, mDNSu8 *ptr, mDNSu8 *limit)
mDNSlocal mDNSu8 *AddEDNS0Option(mDNSu8 *ptr, mDNSu8 *limit)
{
int len = 4096;
@ -142,7 +141,7 @@ mDNSlocal mDNSu8 *AddEDNS0Option(mDNS *const m, mDNSu8 *ptr, mDNSu8 *limit)
LogInfo("AddEDNS0Option: not enough space");
return mDNSNULL;
}
m->omsg.h.numAdditionals++;
mDNSStorage.omsg.h.numAdditionals++;
ptr[0] = 0;
ptr[1] = (mDNSu8) (kDNSType_OPT >> 8);
ptr[2] = (mDNSu8) (kDNSType_OPT & 0xFF);
@ -183,9 +182,9 @@ mDNSlocal mDNSOpaque16 SetResponseFlags(DNSProxyClient *pc, const mDNSOpaque16 r
return rFlags;
}
mDNSlocal mDNSu8 *AddResourceRecords(mDNS *const m, DNSProxyClient *pc, mDNSu8 **prevptr, mStatus *error)
mDNSlocal mDNSu8 *AddResourceRecords(DNSProxyClient *pc, mDNSu8 **prevptr, mStatus *error)
{
mDNSu32 slot;
mDNS *const m = &mDNSStorage;
CacheGroup *cg;
CacheRecord *cr;
int len = sizeof(DNSMessageHeader);
@ -198,6 +197,8 @@ mDNSlocal mDNSu8 *AddResourceRecords(mDNS *const m, DNSProxyClient *pc, mDNSu8 *
CacheRecord *soa = mDNSNULL;
CacheRecord *cname = mDNSNULL;
mDNSu8 *limit;
domainname tempQName;
mDNSu32 tempQNameHash;
*error = mStatus_NoError;
*prevptr = mDNSNULL;
@ -225,20 +226,16 @@ mDNSlocal mDNSu8 *AddResourceRecords(mDNS *const m, DNSProxyClient *pc, mDNSu8 *
}
LogInfo("AddResourceRecords: Limit is %d", limit - m->omsg.data);
if (!SameDomainName(&pc->qname, &pc->q.qname))
{
AssignDomainName(&pc->q.qname, &pc->qname);
pc->q.qnamehash = DomainNameHashValue(&pc->q.qname);
}
AssignDomainName(&tempQName, &pc->qname);
tempQNameHash = DomainNameHashValue(&tempQName);
again:
nsec = soa = cname = mDNSNULL;
slot = HashSlot(&pc->q.qname);
cg = CacheGroupForName(m, slot, pc->q.qnamehash, &pc->q.qname);
cg = CacheGroupForName(m, tempQNameHash, &tempQName);
if (!cg)
{
LogInfo("AddResourceRecords: CacheGroup not found");
LogInfo("AddResourceRecords: CacheGroup not found for %##s", tempQName.c);
*error = mStatus_NoSuchRecord;
return mDNSNULL;
}
@ -347,8 +344,8 @@ again:
}
if (cname)
{
AssignDomainName(&pc->q.qname, &cname->resrec.rdata->u.name);
pc->q.qnamehash = DomainNameHashValue(&pc->q.qname);
AssignDomainName(&tempQName, &cname->resrec.rdata->u.name);
tempQNameHash = DomainNameHashValue(&tempQName);
goto again;
}
if (!ptr)
@ -359,14 +356,14 @@ again:
}
if (pc->rcvBufSize)
{
ptr = AddEDNS0Option(m, ptr, limit);
ptr = AddEDNS0Option(ptr, limit);
if (!ptr)
{
*prevptr = orig;
return mDNSNULL;
}
len += (ptr - orig);
orig = ptr;
// orig = ptr; Commented out to avoid value never read error message
}
LogInfo("AddResourceRecord: Added %d bytes to the packet", len);
return ptr;
@ -412,7 +409,7 @@ mDNSlocal void ProxyClientCallback(mDNS *const m, DNSQuestion *question, const R
return;
}
}
ptr = AddResourceRecords(m, pc, &prevptr, &error);
ptr = AddResourceRecords(pc, &prevptr, &error);
if (!ptr)
{
LogInfo("ProxyClientCallback: AddResourceRecords NULL for %##s (%s)", &pc->qname.c, DNSTypeName(pc->q.qtype));
@ -471,14 +468,16 @@ mDNSlocal void ProxyClientCallback(mDNS *const m, DNSQuestion *question, const R
}
}
}
debugf("ProxyClientCallback: InterfaceID is %p for response to client", pc->interfaceID);
if (!pc->tcp)
{
mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, (UDPSocket *)pc->socket, &pc->addr, pc->port, mDNSNULL, mDNSNULL, mDNSfalse);
mDNSSendDNSMessage(m, &m->omsg, ptr, pc->interfaceID, (UDPSocket *)pc->socket, &pc->addr, pc->port, mDNSNULL, mDNSNULL, mDNSfalse);
}
else
{
mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &pc->addr, pc->port, (TCPSocket *)pc->socket, mDNSNULL, mDNSfalse);
mDNSSendDNSMessage(m, &m->omsg, ptr, pc->interfaceID, mDNSNULL, &pc->addr, pc->port, (TCPSocket *)pc->socket, mDNSNULL, mDNSfalse);
}
done:
@ -496,13 +495,11 @@ done:
FreeDNSProxyClient(pc);
}
mDNSlocal void SendError(mDNS *const m, void *socket, void *const pkt, const mDNSu8 *const end, const mDNSAddr *dstaddr,
mDNSlocal void SendError(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *dstaddr,
const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, mDNSBool tcp, void *context, mDNSu8 rcode)
{
int pktlen = (int)(end - (mDNSu8 *)pkt);
DNSMessage *msg = (DNSMessage *)pkt;
(void) InterfaceID;
mDNS *const m = &mDNSStorage;
int pktlen = (int)(end - (mDNSu8 *)msg);
// RFC 1035 requires that we copy the question back and RFC 2136 is okay with sending nothing
// in the body or send back whatever we get for updates. It is easy to return whatever we get
@ -514,28 +511,27 @@ mDNSlocal void SendError(mDNS *const m, void *socket, void *const pkt, const mDN
mDNSPlatformMemCopy(&m->omsg.h, &msg->h, sizeof(DNSMessageHeader));
m->omsg.h.flags.b[0] |= kDNSFlag0_QR_Response;
m->omsg.h.flags.b[1] = rcode;
mDNSPlatformMemCopy(m->omsg.data, (mDNSu8 *)&msg->h.numQuestions, pktlen);
mDNSPlatformMemCopy(m->omsg.data, (mDNSu8 *)&msg->data, (pktlen - sizeof(DNSMessageHeader)));
if (!tcp)
{
mDNSSendDNSMessage(m, &m->omsg, (mDNSu8 *)&m->omsg + pktlen, mDNSInterface_Any, socket, dstaddr, dstport, mDNSNULL, mDNSNULL,
mDNSSendDNSMessage(m, &m->omsg, (mDNSu8 *)&m->omsg + pktlen, InterfaceID, socket, dstaddr, dstport, mDNSNULL, mDNSNULL,
mDNSfalse);
}
else
{
mDNSSendDNSMessage(m, &m->omsg, (mDNSu8 *)&m->omsg + pktlen, mDNSInterface_Any, mDNSNULL, dstaddr, dstport, (TCPSocket *)socket,
mDNSSendDNSMessage(m, &m->omsg, (mDNSu8 *)&m->omsg + pktlen, InterfaceID, mDNSNULL, dstaddr, dstport, (TCPSocket *)socket,
mDNSNULL, mDNSfalse);
}
mDNSPlatformDisposeProxyContext(context);
}
mDNSlocal DNSQuestion *IsDuplicateClient(const mDNS *const m, const mDNSAddr *const addr, const mDNSIPPort port, const mDNSOpaque16 id,
mDNSlocal DNSQuestion *IsDuplicateClient(const mDNSAddr *const addr, const mDNSIPPort port, const mDNSOpaque16 id,
const DNSQuestion *const question)
{
DNSProxyClient *pc;
(void) m; // unused
for (pc = DNSProxyClients; pc; pc = pc->next)
for (pc = DNSProxyClients; pc; pc = pc->next)
{
if (mDNSSameAddress(&pc->addr, addr) &&
mDNSSameIPPort(pc->port, port) &&
@ -551,32 +547,40 @@ mDNSlocal DNSQuestion *IsDuplicateClient(const mDNS *const m, const mDNSAddr *co
return(mDNSNULL);
}
mDNSlocal mDNSBool CheckDNSProxyIpIntf(const mDNS *const m, mDNSInterfaceID InterfaceID)
mDNSlocal mDNSBool CheckDNSProxyIpIntf(mDNSInterfaceID InterfaceID)
{
mDNS *const m = &mDNSStorage;
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;
}
mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, void *const pkt, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
mDNSlocal void ProxyCallbackCommon(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, mDNSBool tcp, void *context)
{
DNSMessage *msg = (DNSMessage *)pkt;
mDNS *const m = &mDNSStorage;
mDNSu8 QR_OP;
const mDNSu8 *ptr;
DNSQuestion q, *qptr;
DNSProxyClient *pc;
const mDNSu8 *optRR;
const mDNSu8 *optRR = mDNSNULL;
int optLen = 0;
DNSProxyClient **ppc = &DNSProxyClients;
@ -585,20 +589,15 @@ 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))
return;
if ((unsigned)(end - (mDNSu8 *)pkt) < sizeof(DNSMessageHeader))
if (!CheckDNSProxyIpIntf(InterfaceID))
{
debugf("ProxyCallbackCommon: DNS Message from %#a:%d to %#a:%d length %d too short", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), end - (mDNSu8 *)pkt);
LogMsg("ProxyCallbackCommon: Rejecting DNS Query coming from InterfaceID %p", InterfaceID);
return;
}
QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask);
if (QR_OP != kDNSFlag0_QR_Query)
if ((unsigned)(end - (mDNSu8 *)msg) < sizeof(DNSMessageHeader))
{
LogInfo("ProxyCallbackCommon: Not a query(%d) for pkt from %#a:%d", QR_OP, srcaddr, mDNSVal16(srcport));
SendError(m, socket, pkt, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_NotImpl);
debugf("ProxyCallbackCommon: DNS Message from %#a:%d to %#a:%d length %d too short", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - (mDNSu8 *)msg));
return;
}
@ -609,11 +608,19 @@ mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, void *const pkt,
msg->h.numAuthorities = (mDNSu16)((mDNSu16)ptr[4] << 8 | ptr[5]);
msg->h.numAdditionals = (mDNSu16)((mDNSu16)ptr[6] << 8 | ptr[7]);
QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask);
if (QR_OP != kDNSFlag0_QR_Query)
{
LogInfo("ProxyCallbackCommon: Not a query(%d) for pkt from %#a:%d", QR_OP, srcaddr, mDNSVal16(srcport));
SendError(socket, msg, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_NotImpl);
return;
}
if (msg->h.numQuestions != 1 || msg->h.numAnswers || msg->h.numAuthorities)
{
LogInfo("ProxyCallbackCommon: Malformed pkt from %#a:%d, Q:%d, An:%d, Au:%d", srcaddr, mDNSVal16(srcport),
msg->h.numQuestions, msg->h.numAnswers, msg->h.numAuthorities);
SendError(m, socket, pkt, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_FormErr);
SendError(socket, msg, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_FormErr);
return;
}
ptr = msg->data;
@ -621,7 +628,7 @@ mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, void *const pkt,
if (!ptr)
{
LogInfo("ProxyCallbackCommon: Question cannot be parsed for pkt from %#a:%d", srcaddr, mDNSVal16(srcport));
SendError(m, socket, pkt, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_FormErr);
SendError(socket, msg, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_FormErr);
return;
}
else
@ -649,7 +656,7 @@ mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, void *const pkt,
LogInfo("ProxyCallbackCommon: EDNS0 opt not present in Question %##s (%s), ptr %p", q.qname.c, DNSTypeName(q.qtype), ptr);
}
qptr = IsDuplicateClient(m, srcaddr, srcport, msg->h.id, &q);
qptr = IsDuplicateClient(srcaddr, srcport, msg->h.id, &q);
if (qptr)
{
LogInfo("ProxyCallbackCommon: Found a duplicate for pkt from %#a:%d, ignoring this", srcaddr, mDNSVal16(srcport));
@ -694,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;
@ -727,20 +733,21 @@ mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, void *const pkt,
mDNS_StartQuery(m, &pc->q);
}
mDNSexport void ProxyUDPCallback(mDNS *const m, void *socket, void *const pkt, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
mDNSexport void ProxyUDPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context)
{
LogInfo("ProxyUDPCallback: DNS Message from %#a:%d to %#a:%d length %d", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), end - (mDNSu8 *)pkt);
ProxyCallbackCommon(m, socket, pkt, end, srcaddr, srcport, dstaddr, dstport, InterfaceID, mDNSfalse, context);
LogInfo("ProxyUDPCallback: DNS Message from %#a:%d to %#a:%d length %d", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - (mDNSu8 *)msg));
ProxyCallbackCommon(socket, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID, mDNSfalse, context);
}
mDNSexport void ProxyTCPCallback(mDNS *const m, void *socket, void *const pkt, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
mDNSexport void ProxyTCPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
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
LogInfo("ProxyTCPCallback: DNS Message from %#a:%d to %#a:%d length %d", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - (mDNSu8 *)msg));
// 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 *)msg) == 0) || (!CheckDNSProxyIpIntf(InterfaceID)))
{
DNSProxyClient **ppc = &DNSProxyClients;
DNSProxyClient **prevpc;
@ -763,11 +770,12 @@ mDNSexport void ProxyTCPCallback(mDNS *const m, void *socket, void *const pkt, c
FreeDNSProxyClient(*ppc);
return;
}
ProxyCallbackCommon(m, socket, pkt, end, srcaddr, srcport, dstaddr, dstport, InterfaceID, mDNStrue, context);
ProxyCallbackCommon(socket, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID, mDNStrue, context);
}
mDNSexport void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf)
mDNSexport void DNSProxyInit(mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf)
{
mDNS *const m = &mDNSStorage;
int i;
// Store DNSProxy Interface fields in mDNS struct
@ -779,8 +787,9 @@ mDNSexport void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf
m->dp_ipintf[1], m->dp_ipintf[2], m->dp_ipintf[3], m->dp_ipintf[4], m->dp_opintf);
}
mDNSexport void DNSProxyTerminate(mDNS *const m)
mDNSexport void DNSProxyTerminate(void)
{
mDNS *const m = &mDNSStorage;
int i;
// Clear DNSProxy Interface fields from mDNS struct
@ -793,11 +802,10 @@ mDNSexport void DNSProxyTerminate(mDNS *const m)
}
#else // UNICAST_DISABLED
mDNSexport void ProxyUDPCallback(mDNS *const m, void *socket, void *const pkt, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context)
mDNSexport void ProxyUDPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context)
{
(void) m;
(void) socket;
(void) pkt;
(void) msg;
(void) end;
(void) srcaddr;
(void) srcport;
@ -807,11 +815,10 @@ mDNSexport void ProxyUDPCallback(mDNS *const m, void *socket, void *const pkt, c
(void) context;
}
mDNSexport void ProxyTCPCallback(mDNS *const m, void *socket, void *const pkt, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context)
mDNSexport void ProxyTCPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context)
{
(void) m;
(void) socket;
(void) pkt;
(void) msg;
(void) end;
(void) srcaddr;
(void) srcport;
@ -821,15 +828,13 @@ mDNSexport void ProxyTCPCallback(mDNS *const m, void *socket, void *const pkt, c
(void) context;
}
mDNSexport void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf)
mDNSexport void DNSProxyInit(mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf)
{
(void) m;
(void) IpIfArr;
(void) OpIf;
}
extern void DNSProxyTerminate(mDNS *const m)
extern void DNSProxyTerminate(void)
{
(void) m;
}

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2011-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.
@ -14,17 +14,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __DNS_PROXY_H
#define __DNS_PROXY_H
#include "mDNSEmbeddedAPI.h"
#include "DNSCommon.h"
extern void ProxyUDPCallback(mDNS *const m, void *socket, void *const pkt, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
extern void ProxyUDPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context);
extern void ProxyTCPCallback(mDNS *const m, void *socket, void *const pkt, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
extern void ProxyTCPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context);
extern void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf);
extern void DNSProxyTerminate(mDNS *const m);
extern void DNSProxyInit(mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf);
extern void DNSProxyTerminate(void);
#endif // __DNS_PROXY_H

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2011-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.
@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mDNSEmbeddedAPI.h"
#include "DNSSECSupport.h"
#include "DNSCommon.h"
@ -86,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
@ -299,6 +301,8 @@ mDNSlocal AuthChain *AuthChainCopy(AuthChain *ae)
if (!ac)
{
LogMsg("AuthChainCopy: AuthChain alloc failure");
if (retac)
FreeDNSSECAuthChainInfo(retac);
return mDNSfalse;
}
@ -309,7 +313,7 @@ mDNSlocal AuthChain *AuthChainCopy(AuthChain *ae)
rvfrom = ae->rrset;
rvto = &ac->rrset;
while (rvfrom)
while (rvfrom && rvto)
{
*rvto = CopyRRVerifier(rvfrom);
rvfrom = rvfrom->next;
@ -318,7 +322,7 @@ mDNSlocal AuthChain *AuthChainCopy(AuthChain *ae)
rvfrom = ae->rrsig;
rvto = &ac->rrsig;
while (rvfrom)
while (rvfrom && rvto)
{
*rvto = CopyRRVerifier(rvfrom);
rvfrom = rvfrom->next;
@ -327,7 +331,7 @@ mDNSlocal AuthChain *AuthChainCopy(AuthChain *ae)
rvfrom = ae->key;
rvto = &ac->key;
while (rvfrom)
while (rvfrom && rvto)
{
*rvto = CopyRRVerifier(rvfrom);
rvfrom = rvfrom->next;
@ -703,7 +707,6 @@ mDNSexport void ValidateRRSIG(DNSSECVerifier *dv, RRVerifierSet type, const Reso
mDNSlocal mStatus CheckRRSIGForRRSet(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr)
{
mDNSu32 slot;
CacheGroup *cg;
CacheRecord *cr;
RRVerifier *rv;
@ -718,8 +721,7 @@ mDNSlocal mStatus CheckRRSIGForRRSet(mDNS *const m, DNSSECVerifier *dv, CacheRec
}
rv = dv->rrset;
slot = HashSlot(&rv->name);
cg = CacheGroupForName(m, slot, rv->namehash, &rv->name);
cg = CacheGroupForName(m, rv->namehash, &rv->name);
if (!cg)
{
debugdnssec("CheckRRSIGForRRSet: cg null");
@ -803,7 +805,6 @@ mDNSlocal void CheckOneKeyForRRSIG(DNSSECVerifier *dv, const ResourceRecord *con
mDNSlocal mStatus CheckKeyForRRSIG(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr)
{
mDNSu32 slot;
mDNSu32 namehash;
CacheGroup *cg;
CacheRecord *cr;
@ -821,9 +822,8 @@ mDNSlocal mStatus CheckKeyForRRSIG(mDNS *const m, DNSSECVerifier *dv, CacheRecor
rrsig = (rdataRRSig *)dv->rrsig->rdata;
name = (domainname *)&rrsig->signerName;
slot = HashSlot(name);
namehash = DomainNameHashValue(name);
cg = CacheGroupForName(m, slot, namehash, name);
cg = CacheGroupForName(m, namehash, name);
if (!cg)
{
debugdnssec("CheckKeyForRRSIG: cg null for %##s", name->c);
@ -883,7 +883,6 @@ mDNSlocal void CheckOneRRSIGForKey(DNSSECVerifier *dv, const ResourceRecord *con
mDNSlocal mStatus CheckRRSIGForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr)
{
mDNSu32 slot;
mDNSu32 namehash;
CacheGroup *cg;
CacheRecord *cr;
@ -905,9 +904,8 @@ mDNSlocal mStatus CheckRRSIGForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecor
rrsig = (rdataRRSig *)dv->rrsig->rdata;
name = (domainname *)&rrsig->signerName;
slot = HashSlot(name);
namehash = DomainNameHashValue(name);
cg = CacheGroupForName(m, slot, namehash, name);
cg = CacheGroupForName(m, namehash, name);
if (!cg)
{
debugdnssec("CheckRRSIGForKey: cg null %##s", name->c);
@ -1006,7 +1004,6 @@ mDNSlocal void CheckOneDSForKey(DNSSECVerifier *dv, const ResourceRecord *const
mDNSlocal mStatus CheckDSForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr)
{
mDNSu32 slot;
mDNSu32 namehash;
CacheGroup *cg;
CacheRecord *cr;
@ -1026,9 +1023,8 @@ mDNSlocal mStatus CheckDSForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecord *
}
rrsig = (rdataRRSig *)dv->rrsig->rdata;
name = (domainname *)&rrsig->signerName;
slot = HashSlot(name);
namehash = DomainNameHashValue(name);
cg = CacheGroupForName(m, slot, namehash, name);
cg = CacheGroupForName(m, namehash, name);
if (!cg)
{
debugdnssec("CheckDSForKey: cg null for %s", name->c);
@ -1065,7 +1061,6 @@ mDNSlocal mStatus CheckDSForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecord *
return mStatus_NoError;
else
return mStatus_NoSuchRecord;
return (dv->ds ? mStatus_NoError : mStatus_NoSuchRecord);
}
// It returns mDNStrue if we have all the rrsets for verification and mDNSfalse otherwise.
@ -2333,10 +2328,7 @@ mDNSlocal void SetTTLRRSet(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus statu
CacheRecord *rr;
RRVerifier *rrsigv;
rdataRRSig *rrsig;
mDNSu32 slot;
CacheGroup *cg;
int sigNameLen, len;
mDNSu8 *ptr;
mDNSu32 rrTTL, rrsigTTL, rrsigOrigTTL, rrsigTimeTTL;
domainname *qname;
mDNSu16 qtype;
@ -2367,8 +2359,7 @@ mDNSlocal void SetTTLRRSet(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus statu
question.ThisQInterval = -1;
InitializeQuestion(m, &question, dv->InterfaceID, qname, qtype, mDNSNULL, mDNSNULL);
slot = HashSlot(&question.qname);
cg = CacheGroupForName(m, slot, question.qnamehash, &question.qname);
cg = CacheGroupForName(m, question.qnamehash, &question.qname);
if (!cg)
{
@ -2400,17 +2391,11 @@ mDNSlocal void SetTTLRRSet(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus statu
{
rrsigv = dv->ac->rrsig;
rrsig = (rdataRRSig *)rrsigv->rdata;
sigNameLen = DomainNameLength((domainname *)&rrsig->signerName);
// pointer to signature and the length
ptr = (mDNSu8 *)(rrsigv->rdata + sigNameLen + RRSIG_FIXED_SIZE);
len = rrsigv->rdlength - RRSIG_FIXED_SIZE - sigNameLen;
}
else
{
rrsigv = mDNSNULL;
rrsig = mDNSNULL;
ptr = mDNSNULL;
sigNameLen = len = 0;
}
rrsigRR = mDNSNULL;
@ -2531,7 +2516,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;
@ -2694,7 +2681,7 @@ mDNSlocal void DNSSECNoResponse(mDNS *const m, DNSSECVerifier *dv)
{
CacheGroup *cg;
CacheRecord *cr;
mDNSu32 slot, namehash;
mDNSu32 namehash;
ResourceRecord *answer = mDNSNULL;
LogDNSSEC("DNSSECNoResponse: called");
@ -2707,10 +2694,9 @@ mDNSlocal void DNSSECNoResponse(mDNS *const m, DNSSECVerifier *dv)
BumpDNSSECStats(m, kStatsActionSet, kStatsTypeStatus, DNSSEC_NoResponse);
slot = HashSlot(&dv->origName);
namehash = DomainNameHashValue(&dv->origName);
cg = CacheGroupForName(m, (const mDNSu32)slot, namehash, &dv->origName);
cg = CacheGroupForName(m, namehash, &dv->origName);
if (!cg)
{
LogDNSSEC("DNSSECNoResponse: cg NULL for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
@ -3036,7 +3022,7 @@ done:
mDNSlocal void DNSSECValidationCB(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus status)
{
mDNSu32 slot, namehash;
mDNSu32 namehash;
CacheGroup *cg;
CacheRecord *cr;
@ -3056,10 +3042,9 @@ mDNSlocal void DNSSECValidationCB(mDNS *const m, DNSSECVerifier *dv, DNSSECStatu
ProveInsecure(m, dv, mDNSNULL, mDNSNULL);
return;
}
slot = HashSlot(&dv->origName);
namehash = DomainNameHashValue(&dv->origName);
cg = CacheGroupForName(m, (const mDNSu32)slot, namehash, &dv->origName);
cg = CacheGroupForName(m, namehash, &dv->origName);
if (!cg)
{
LogDNSSEC("DNSSECValidationCB: cg NULL for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType));
@ -3085,8 +3070,7 @@ mDNSlocal void DNSSECValidationCB(mDNS *const m, DNSSECVerifier *dv, DNSSECStatu
mDNSexport void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion *q)
{
mDNSu32 slot = HashSlot(&q->qname);
CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
CacheRecord *rr;
mDNSBool first = mDNSfalse;
static mDNSBool TrustAnchorsUpdated = mDNSfalse;
@ -3187,14 +3171,11 @@ mDNSexport void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion *
mDNSlocal mDNSBool TrustedKeyPresent(mDNS *const m, DNSSECVerifier *dv)
{
rdataRRSig *rrsig;
rdataDS *ds;
rdataDNSKey *key;
TrustAnchor *ta;
RRVerifier *keyv;
rrsig = (rdataRRSig *)dv->rrsig->rdata;
// Walk all our trusted DS Records to see if we have a matching DNS KEY record that verifies
// the hash. If we find one, verify that this key was used to sign the KEY rrsets in
// this zone. Loop till we find one.
@ -3325,14 +3306,12 @@ mDNSlocal mStatus TrustedKey(mDNS *const m, DNSSECVerifier *dv)
mDNSlocal CacheRecord* NegativeCacheRecordForRR(mDNS *const m, const ResourceRecord *const rr)
{
mDNSu32 slot;
mDNSu32 namehash;
CacheGroup *cg;
CacheRecord *cr;
slot = HashSlot(rr->name);
namehash = DomainNameHashValue(rr->name);
cg = CacheGroupForName(m, slot, namehash, rr->name);
cg = CacheGroupForName(m, namehash, rr->name);
if (!cg)
{
LogMsg("NegativeCacheRecordForRR: cg null %##s", rr->name->c);

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2011-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.
@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __DNSSEC_H
#define __DNSSEC_H

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2002-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.
@ -148,12 +148,18 @@ extern void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *format, ...) IS
// (or completely overhauled to use the new "log to a separate file" facility)
#define LogMsgNoIdent LogMsg
#if APPLE_OSX_mDNSResponder
extern void LogFatalError(const char *format, ...);
#else
#define LogFatalError LogMsg
#endif
#if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1
extern void *mallocL(char *msg, unsigned int size);
extern void freeL(char *msg, void *x);
extern void LogMemCorruption(const char *format, ...);
extern void uds_validatelists(void);
extern void udns_validatelists(void *const v);
extern void LogMemCorruption(const char *format, ...);
#else
#define mallocL(X,Y) malloc(Y)
#define freeL(X,Y) free(Y)

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2002-2013 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2002-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.
@ -70,6 +70,7 @@
#include "mDNSDebug.h"
#if APPLE_OSX_mDNSResponder
#include <uuid/uuid.h>
#include <TargetConditionals.h>
#endif
#ifdef __cplusplus
@ -90,20 +91,14 @@ extern "C" {
// In order to disable the above features pass the option to your compiler, e.g. -D UNICAST_DISABLED
// Additionally, the LIMITED_RESOURCES_TARGET compile option will eliminate caching and
// and reduce the maximum DNS message sizes.
// Additionally, the LIMITED_RESOURCES_TARGET compile option will reduce the maximum DNS message sizes.
#ifdef LIMITED_RESOURCES_TARGET
// Don't support jumbo frames
#define AbsoluteMaxDNSMessageData 1500
// By the time you add IPv6 header (40 bytes) UDP header (8 bytes) and DNS message header (12 bytes)
// this makes 1560 which is 60 bytes over the standard Ethernet MTU. D'oh!
// 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total
#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
// Don't cache anything
#define AUTH_HASH_SLOTS 1
#define CACHE_HASH_SLOTS 1
#define MaximumRDSize 264
#endif
// ***************************************************************************
@ -301,21 +296,26 @@ typedef mDNSOpaque48 mDNSEthAddr; // An Ethernet address is a six-byte opa
#define bit_set_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
#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))))
// Bit operations for opaque 128 bit quantity. Uses the 32 bit quantity(l[4]) to set and clear bits
#define bit_set_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
#define bit_clr_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
#define bit_get_opaque128(op128, index) (op128.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
{
@ -369,7 +369,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,
@ -486,7 +487,7 @@ typedef struct UDPSocket_struct UDPSocket;
#define mDNS_numPrereqs numAnswers
#define mDNS_numUpdates numAuthorities
typedef packedstruct
typedef struct
{
mDNSOpaque16 id;
mDNSOpaque16 flags;
@ -503,7 +504,7 @@ typedef packedstruct
#define AbsoluteMaxDNSMessageData 8940
#endif
#define NormalMaxDNSMessageData 1440
typedef packedstruct
typedef struct
{
DNSMessageHeader h; // Note: Size 12 bytes
mDNSu8 data[AbsoluteMaxDNSMessageData]; // 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000
@ -556,7 +557,7 @@ typedef packedstruct
{
mDNSu8 vlen;
mDNSu8 tos;
mDNSu16 totlen;
mDNSOpaque16 totlen;
mDNSOpaque16 id;
mDNSOpaque16 flagsfrags;
mDNSu8 ttl;
@ -621,7 +622,7 @@ typedef packedstruct
mDNSu16 checksum;
} UDPHeader; // 8 bytes; IP protocol type 0x11
typedef packedstruct
typedef struct
{
mDNSu8 type; // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement
mDNSu8 code;
@ -726,7 +727,7 @@ typedef packedstruct
// Bit 6 (value 0x40) is set for answer records; clear for authority/additional records
// Bit 5 (value 0x20) is set for records received with the kDNSClass_UniqueRRSet
enum
typedef enum
{
kDNSRecordTypeUnregistered = 0x00, // Not currently in any list
kDNSRecordTypeDeregistering = 0x01, // Shared record about to announce its departure and leave the list
@ -754,7 +755,7 @@ enum
kDNSRecordTypePacketNegative = 0xF0, // Pseudo-RR generated to cache non-existence results like NXDomain
kDNSRecordTypePacketUniqueMask = 0x10 // True for PacketAddUnique, PacketAnsUnique, PacketAuthUnique, kDNSRecordTypePacketNegative
};
} kDNSRecordTypes;
typedef packedstruct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target; } rdataSRV;
typedef packedstruct { mDNSu16 preference; domainname exchange; } rdataMX;
@ -813,14 +814,14 @@ typedef struct TrustAnchor
struct TrustAnchor *next;
int digestLen;
mDNSu32 validFrom;
mDNSu32 validUntil;
mDNSu32 validUntil;
domainname zone;
rdataDS rds;
} TrustAnchor;
//size of rdataRRSIG excluding signerName and signature (which are variable fields)
#define RRSIG_FIXED_SIZE 18
typedef packedstruct
typedef struct
{
mDNSu16 typeCovered;
mDNSu8 alg;
@ -829,7 +830,7 @@ typedef packedstruct
mDNSu32 sigExpireTime;
mDNSu32 sigInceptTime;
mDNSu16 keyTag;
mDNSu8 *signerName;
mDNSu8 signerName[1]; // signerName is a dynamically-sized array
// mDNSu8 *signature
} rdataRRSig;
@ -880,10 +881,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.
@ -942,7 +943,7 @@ typedef struct
} TracerOptData;
// Note: rdataOPT format may be repeated an arbitrary number of times in a single resource record
typedef packedstruct
typedef struct
{
mDNSu16 opt;
mDNSu16 optlen;
@ -1186,7 +1187,7 @@ typedef enum
PCPResult_ExcesRemotePeer = 13
} PCPResult_t;
typedef packedstruct
typedef struct
{
mDNSu8 version;
mDNSu8 opCode;
@ -1201,7 +1202,7 @@ typedef packedstruct
mDNSv6Addr extAddress;
} PCPMapRequest;
typedef packedstruct
typedef struct
{
mDNSu8 version;
mDNSu8 opCode;
@ -1312,16 +1313,11 @@ struct NATTraversalInfo_struct
enum
{
DNSServer_Untested = 0,
DNSServer_Passed = 1,
DNSServer_Failed = 2,
DNSServer_Disabled = 3
};
enum
{
DNSServer_FlagDelete = 1,
DNSServer_FlagNew = 2
DNSServer_FlagDelete = 0x1,
DNSServer_FlagNew = 0x2,
#if APPLE_OSX_mDNSResponder
DNSServer_FlagUnreachable = 0x4,
#endif
};
enum
@ -1344,8 +1340,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
@ -1362,22 +1359,19 @@ 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
mDNSu32 timeout; // timeout value for questions
mDNSBool cellIntf; // Resolver from Cellular Interface ?
mDNSu16 resGroupID; // ID of the resolver group that contains this DNSServer
mDNSu8 retransDO; // Total Retransmissions for queries sent with DO option
mDNSBool cellIntf; // Resolver from Cellular Interface?
mDNSBool req_A; // If set, send v4 query (DNSConfig allows A queries)
mDNSBool req_AAAA; // If set, send v6 query (DNSConfig allows AAAA queries)
mDNSBool req_DO; // If set, okay to send DNSSEC queries (EDNS DO bit is supported)
mDNSBool retransDO; // Total Retransmissions for queries sent with DO option
mDNSBool DNSSECAware; // set if we are able to receive a response to a request
// sent with DO option.
mDNSBool DNSSECAware; // Set if we are able to receive a response to a request sent with DO option.
mDNSBool isExpensive; // True if the interface to this server is expensive.
} DNSServer;
typedef struct
@ -1391,9 +1385,9 @@ typedef struct
struct ResourceRecord_struct
{
mDNSu8 RecordType; // See enum above
mDNSu16 rrtype;
mDNSu16 rrclass;
mDNSu8 RecordType; // See kDNSRecordTypes enum.
mDNSu16 rrtype; // See DNS_TypeValues enum.
mDNSu16 rrclass; // See DNS_ClassValues enum.
mDNSu32 rroriginalttl; // In seconds
mDNSu16 rdlength; // Size of the raw rdata, in bytes, in the on-the-wire format
// (In-memory storage may be larger, for structures containing 'holes', like SOA)
@ -1413,7 +1407,7 @@ struct ResourceRecord_struct
// that are interface-specific (e.g. address records, especially linklocal addresses)
const domainname *name;
RData *rdata; // Pointer to storage for this rdata
DNSServer *rDNSServer; // Unicast DNS server authoritative for this entry;null for multicast
DNSServer *rDNSServer; // Unicast DNS server authoritative for this entry; null for multicast
AnonymousInfo *AnonInfo; // Anonymous Information
};
@ -1502,7 +1496,7 @@ struct AuthRecord_struct
AuthRecord *next; // Next in list; first element of structure for efficiency reasons
// Field Group 1: Common ResourceRecord fields
ResourceRecord resrec; // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit
ResourceRecord resrec; // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit (now 44/64)
// Field Group 2: Persistent metadata for Authoritative Records
AuthRecord *Additional1; // Recommended additional record to include in response (e.g. SRV for PTR record)
@ -1606,10 +1600,13 @@ struct AuthRecord_struct
// Everywhere else in the code, the determination of whether a question is unicast is made by checking to see if TargetQID is nonzero.
#define AuthRecord_uDNS(R) ((R)->resrec.InterfaceID == mDNSInterface_Any && !(R)->ForceMCast && !IsLocalDomain((R)->resrec.name))
#define Question_uDNS(Q) ((Q)->InterfaceID == mDNSInterface_Unicast || (Q)->ProxyQuestion || \
((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname)))
((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && (Q)->InterfaceID != mDNSInterface_BLE && !(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
@ -1634,7 +1631,7 @@ typedef struct ARListElem
struct CacheRecord_struct
{
CacheRecord *next; // Next in list; first element of structure for efficiency reasons
ResourceRecord resrec; // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit
ResourceRecord resrec; // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit (now 44/64)
// Transient state for Cache Records
CacheRecord *NextInKAList; // Link to the next element in the chain of known answers to send
@ -1647,24 +1644,17 @@ struct CacheRecord_struct
mDNSu8 UnansweredQueries; // Number of times we've issued a query for this record without getting an answer
mDNSu8 CRDNSSECQuestion; // Set to 1 if this was created in response to a DNSSEC question
mDNSOpaque16 responseFlags; // Second 16 bit in the DNS response
#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
mDNSu32 MPUnansweredQ; // Multi-packet query handling: Number of times we've seen a query for this record
mDNSs32 MPLastUnansweredQT; // Multi-packet query handling: Last time we incremented MPUnansweredQ
mDNSu32 MPUnansweredKA; // Multi-packet query handling: Number of times we've seen this record in a KA list
mDNSBool MPExpectingKA; // Multi-packet query handling: Set when we increment MPUnansweredQ; allows one KA
#endif
CacheRecord *NextInCFList; // Set if this is in the list of records we just received with the cache flush bit set
CacheRecord *nsec; // NSEC records needed for non-existence proofs
CacheRecord *soa; // SOA record to return for proxy questions
mDNSAddr sourceAddress; // node from which we received this record
// Size to here is 76 bytes when compiling 32-bit; 104 bytes when compiling 64-bit
// Size to here is 76 bytes when compiling 32-bit; 104 bytes when compiling 64-bit (now 160 bytes for 64-bit)
RData_small smallrdatastorage; // Storage for small records is right here (4 bytes header + 68 bytes data = 72 bytes)
};
// Should match the CacheGroup_struct members, except namestorage[]. Only used to calculate
// the size of the namestorage array in CacheGroup_struct so that
// sizeof(CacheGroup) == sizeof(CacheRecord)
// the size of the namestorage array in CacheGroup_struct so that sizeof(CacheGroup) == sizeof(CacheRecord)
struct CacheGroup_base
{
CacheGroup *next;
@ -1805,6 +1795,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
@ -1887,6 +1896,31 @@ typedef enum { DNSSECValNotRequired = 0, DNSSECValRequired, DNSSECValInProgress,
// RFC 4122 defines it to be 16 bytes
#define UUID_SIZE 16
#define AWD_METRICS (USE_AWD && TARGET_OS_EMBEDDED)
#if AWD_METRICS
typedef struct
{
domainname * originalQName; // Name of original A/AAAA record if this question is for a CNAME record.
mDNSu32 querySendCount; // Number of queries that have been sent to DNS servers so far.
mDNSs32 firstQueryTime; // The time when the first query was sent to a DNS server.
mDNSBool answered; // Has this question been answered?
} uDNSMetrics;
#endif
// DNS64 code is only for iOS, which is currently the only Apple OS that supports DNS proxy network extensions.
#define USE_DNS64 (HAVE_DNS64 && TARGET_OS_IOS)
#if USE_DNS64
#include "DNS64State.h"
#endif
#if TARGET_OS_EMBEDDED
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
{
// Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
@ -1939,7 +1973,7 @@ struct DNSQuestion_struct
// |-> DNS Configuration related fields used in uDNS (Subset of Wide Area/Unicast fields)
DNSServer *qDNSServer; // Caching server for this query (in the absence of an SRV saying otherwise)
mDNSOpaque64 validDNSServers; // Valid DNSServers for this question
mDNSOpaque128 validDNSServers; // Valid DNSServers for this question
mDNSu16 noServerResponse; // At least one server did not respond.
mDNSu16 triedAllServersOnce; // Tried all DNS servers once
mDNSu8 unansweredQueries; // The number of unanswered queries to this server
@ -1961,6 +1995,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
@ -1968,7 +2008,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.
@ -1983,8 +2023,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
@ -1997,48 +2035,19 @@ struct DNSQuestion_struct
mDNSu8 ProxyDNSSECOK; // Proxy Question with EDNS0 DNSSEC OK bit set
mDNSs32 pid; // Process ID of the client that is requesting the question
mDNSu8 uuid[UUID_SIZE]; // Unique ID of the client that is requesting the question (valid only if pid is zero)
mDNSu32 euid; // Effective User Id of the client that is requesting the question
domainname *qnameOrig; // Copy of the original question name if it is not fully qualified
mDNSQuestionCallback *QuestionCallback;
void *QuestionContext;
#if TARGET_OS_EMBEDDED
uDNSMetrics metrics; // Data used for collecting unicast DNS query metrics.
#endif
#if USE_DNS64
DNS64 dns64; // DNS64 state for performing IPv6 address synthesis on networks with NAT64.
#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);
@ -2145,6 +2154,8 @@ struct NetworkInterfaceInfo_struct
mDNSu8 SendGoodbyes; // Send goodbyes on this interface while sleeping
mDNSBool DirectLink; // a direct link, indicating we can skip the probe for
// address records
mDNSBool SupportsUnicastMDNSResponse; // Indicates that the interface supports unicast responses
// to Bonjour queries. Generally true for an interface.
};
#define SLE_DELETE 0x00000001
@ -2259,8 +2270,33 @@ typedef struct
mDNSu32 CacheRefreshed; // Number of times the cache was refreshed due to a response
mDNSu32 WakeOnResolves; // Number of times we did a wake on resolve
} mDNSStatistics;
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;
} ;
// Time constant (~= 260 hours ~= 10 days and 21 hours) used to set
// various time values to a point well into the future.
#define FutureTime 0x38000000
struct mDNS_struct
{
// Internal state fields. These hold the main internal state of mDNSCore;
@ -2269,6 +2305,7 @@ struct mDNS_struct
// all required data is passed as parameters to that function.
mDNS_PlatformSupport *p; // Pointer to platform-specific data of indeterminite size
mDNSs32 NetworkChanged;
mDNSBool CanReceiveUnicastOn5353;
mDNSBool AdvertiseLocalAddresses;
mDNSBool DivertMulticastAdvertisements; // from interfaces that do not advertise local addresses to local-only
@ -2304,6 +2341,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
@ -2320,9 +2362,6 @@ struct mDNS_struct
// during which underying platform layer should inhibit system sleep
mDNSs32 TimeSlept; // Time we went to sleep.
mDNSs32 StatStartTime; // Time we started gathering statistics during this interval.
mDNSs32 NextStatLogTime; // Next time to log statistics.
mDNSs32 ActiveStatTime; // Total time awake/gathering statistics for this log period.
mDNSs32 UnicastPacketsSent; // Number of unicast packets sent.
mDNSs32 MulticastPacketsSent; // Number of multicast packets sent.
mDNSs32 RemoteSubnet; // Multicast packets received from outside our subnet.
@ -2332,6 +2371,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
@ -2368,7 +2408,7 @@ struct mDNS_struct
mDNSs32 ProbeFailTime;
mDNSu32 NumFailedProbes;
mDNSs32 SuppressProbes;
Platform_t mDNS_plat;
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
@ -2418,11 +2458,15 @@ struct mDNS_struct
mDNSBool SSDPWANPPPConnection; // whether we should send the SSDP query for WANIPConnection or WANPPPConnection
mDNSIPPort UPnPRouterPort; // port we send discovery messages to
mDNSIPPort UPnPSOAPPort; // port we send SOAP messages to
mDNSu8 *UPnPRouterURL; // router's URL string
char *UPnPRouterURL; // router's URL string
mDNSBool UPnPWANPPPConnection; // whether we're using WANIPConnection or WANPPPConnection
mDNSu8 *UPnPSOAPURL; // router's SOAP control URL string
mDNSu8 *UPnPRouterAddressString; // holds both the router's address and port
mDNSu8 *UPnPSOAPAddressString; // holds both address and port for SOAP messages
char *UPnPSOAPURL; // router's SOAP control URL string
char *UPnPRouterAddressString; // holds both the router's address and port
char *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
@ -2445,7 +2489,6 @@ struct mDNS_struct
#if APPLE_OSX_mDNSResponder
ClientTunnel *TunnelClients;
uuid_t asl_uuid; // uuid for ASL logging
void *WCF;
#endif
// DNS Proxy fields
@ -2454,9 +2497,15 @@ struct mDNS_struct
TrustAnchor *TrustAnchors;
int notifyToken;
int uds_listener_skt; // Listening socket for incoming UDS clients
mDNSBool mDNSOppCaching; // Opportunistic Caching
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
#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;
@ -2468,8 +2517,8 @@ struct mDNS_struct
};
#define FORALL_CACHERECORDS(SLOT,CG,CR) \
for ((SLOT) = 0; (SLOT) < CACHE_HASH_SLOTS; (SLOT)++) \
for ((CG)=m->rrcache_hash[(SLOT)]; (CG); (CG)=(CG)->next) \
for ((SLOT) = 0; (SLOT) < CACHE_HASH_SLOTS; (SLOT)++) \
for ((CG)=m->rrcache_hash[(SLOT)]; (CG); (CG)=(CG)->next) \
for ((CR) = (CG)->members; (CR); (CR)=(CR)->next)
// ***************************************************************************
@ -2484,6 +2533,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;
@ -2525,11 +2577,17 @@ 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;
extern const mDNSOpaque128 zeroOpaque128;
extern mDNSBool StrictUnicastOrdering;
extern mDNSu8 NumUnicastDNSServers;
#if APPLE_OSX_mDNSResponder
extern mDNSu8 NumUnreachableDNSServers;
#endif
#define localdomain (*(const domainname *)"\x5" "local")
#define DeviceInfoName (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp")
@ -2586,7 +2644,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.
@ -2648,7 +2706,6 @@ extern mStatus mDNS_Init (mDNS *const m, mDNS_PlatformSupport *const p,
extern void mDNS_ConfigChanged(mDNS *const m);
extern void mDNS_GrowCache (mDNS *const m, CacheEntity *storage, mDNSu32 numrecords);
extern void mDNS_GrowAuth (mDNS *const m, AuthEntity *storage, mDNSu32 numrecords);
extern void mDNS_StartExit (mDNS *const m);
extern void mDNS_FinalExit (mDNS *const m);
#define mDNS_Close(m) do { mDNS_StartExit(m); mDNS_FinalExit(m); } while(0)
@ -2700,11 +2757,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
@ -2723,17 +2775,7 @@ typedef enum { mDNS_Dereg_normal, mDNS_Dereg_rapid, mDNS_Dereg_conflict, mDNS_De
extern void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID,
mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, AuthRecType artype, mDNSRecordCallback Callback, void *Context);
// mDNS_RegisterService() flags parameter bit definitions.
// Note these are only defined to transfer the corresponding DNSServiceFlags settings into mDNSCore routines,
// since code in mDNSCore does not include the DNSServiceFlags definitions in dns_sd.h.
enum
{
coreFlagIncludeP2P = 0x1, // include P2P interfaces when using mDNSInterface_Any
coreFlagIncludeAWDL = 0x2, // include AWDL interface when using mDNSInterface_Any
coreFlagKnownUnique = 0x4, // client guarantees that SRV and TXT record names are unique
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,
@ -2761,8 +2803,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
{
@ -2784,7 +2824,7 @@ extern mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, mDNS_DomainT
#define mDNS_StopAdvertiseDomains mDNS_Deregister
extern mDNSOpaque16 mDNS_NewMessageID(mDNS *const m);
extern mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr, mDNSBool *myself);
extern mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr);
extern DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question);
extern mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question);
@ -2805,7 +2845,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]))
@ -2862,6 +2902,10 @@ extern char *ConvertDomainNameToCString_withescape(const domainname *const na
extern void ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], domainlabel *const hostlabel);
#define ValidTransportProtocol(X) ( (X)[0] == 4 && (X)[1] == '_' && \
((((X)[2] | 0x20) == 'u' && ((X)[3] | 0x20) == 'd') || (((X)[2] | 0x20) == 't' && ((X)[3] | 0x20) == 'c')) && \
((X)[4] | 0x20) == 'p')
extern mDNSu8 *ConstructServiceName(domainname *const fqdn, const domainlabel *name, const domainname *type, const domainname *const domain);
extern mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel *const name, domainname *const type, domainname *const domain);
@ -2887,7 +2931,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);
@ -2917,6 +2961,7 @@ extern mDNSBool mDNSAddrIPv4FromMappedIPv6(mDNSv6Addr *in, mDNSv4Addr *out);
#define mDNSIPPortIsZero(A) ((A).NotAnInteger == 0)
#define mDNSOpaque16IsZero(A) ((A).NotAnInteger == 0)
#define mDNSOpaque64IsZero(A) (((A)->l[0] | (A)->l[1] ) == 0)
#define mDNSOpaque128IsZero(A) (((A)->l[0] | (A)->l[1] | (A)->l[2] | (A)->l[3]) == 0)
#define mDNSIPv4AddressIsZero(A) ((A).NotAnInteger == 0)
#define mDNSIPv6AddressIsZero(A) (((A).l[0] | (A).l[1] | (A).l[2] | (A).l[3]) == 0)
#define mDNSEthAddressIsZero(A) (((A).w[0] | (A).w[1] | (A).w[2] ) == 0)
@ -2951,12 +2996,6 @@ extern mDNSBool mDNSAddrIPv4FromMappedIPv6(mDNSv6Addr *in, mDNSv4Addr *out);
((X)->type == mDNSAddrType_IPv4) ? mDNSv4AddressIsLinkLocal(&(X)->ip.v4) : \
((X)->type == mDNSAddrType_IPv6) ? mDNSv6AddressIsLinkLocal(&(X)->ip.v6) : mDNSfalse)
#define mDNSv4AddressIsLoopback(X) ((X)->b[0] == 127 && (X)->b[1] == 0 && (X)->b[2] == 0 && (X)->b[3] == 1)
#define mDNSv6AddressIsLoopback(X) ((((X)->l[0] | (X)->l[1] | (X)->l[2]) == 0) && ((X)->b[12] == 0 && (X)->b[13] == 0 && (X)->b[14] == 0 && (X)->b[15] == 1))
#define mDNSAddressIsLoopback(X) ( \
((X)->type == mDNSAddrType_IPv4) ? mDNSv4AddressIsLoopback(&(X)->ip.v4) : \
((X)->type == mDNSAddrType_IPv6) ? mDNSv6AddressIsLoopback(&(X)->ip.v6) : mDNSfalse)
// ***************************************************************************
#if 0
@ -3000,8 +3039,8 @@ extern void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCa
extern void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn);
extern void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, const mDNSAddr *v6addr, const mDNSAddr *router);
extern DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSs32 serviceID, const mDNSAddr *addr,
const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSu16 resGroupID, mDNSBool reqA,
mDNSBool reqAAAA, mDNSBool reqDO);
const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSBool isExpensive, mDNSu16 resGroupID,
mDNSBool reqA, mDNSBool reqAAAA, mDNSBool reqDO);
extern void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 responseFlags);
extern void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID);
@ -3076,14 +3115,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);
@ -3119,17 +3158,6 @@ extern void mDNSPlatformWriteDebugMsg(const char *msg);
#endif
extern void mDNSPlatformWriteLogMsg(const char *ident, const char *msg, mDNSLogLevel_t loglevel);
#if APPLE_OSX_mDNSResponder
// Utility function for ASL logging
mDNSexport void mDNSASLLog(uuid_t *uuid, const char *subdomain, const char *result, const char *signature, const char *fmt, ...);
// Log unicast and multicast traffic statistics once a day. Also used for DNSSEC statistics.
#define kDefaultNextStatsticsLogTime (24 * 60 * 60)
extern void mDNSLogStatistics(mDNS *const m);
#endif // APPLE_OSX_mDNSResponder
// Platform support modules should provide the following functions to map between opaque interface IDs
// and interface indexes in order to support the DNS-SD API. If your target platform does not support
// multiple interfaces and/or does not support the DNS-SD API, these functions can be empty.
@ -3160,7 +3188,7 @@ typedef enum
} TCPSocketFlags;
typedef void (*TCPConnectionCallback)(TCPSocket *sock, void *context, mDNSBool ConnectionEstablished, mStatus err);
extern TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags, mDNSIPPort *port, mDNSBool useBackgroundTrafficClass); // creates a TCP socket
extern TCPSocket *mDNSPlatformTCPSocket(TCPSocketFlags flags, mDNSIPPort *port, mDNSBool useBackgroundTrafficClass); // creates a TCP socket
extern TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd);
extern int mDNSPlatformTCPGetFD(TCPSocket *sock);
extern mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, domainname *hostname,
@ -3168,19 +3196,21 @@ extern mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, m
extern void mDNSPlatformTCPCloseConnection(TCPSocket *sock);
extern long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed);
extern long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len);
extern UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport);
extern UDPSocket *mDNSPlatformUDPSocket(const mDNSIPPort requestedport);
extern mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock);
extern void mDNSPlatformUDPClose(UDPSocket *sock);
extern void mDNSPlatformReceiveBPF_fd(mDNS *const m, int fd);
extern void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID);
extern mDNSBool mDNSPlatformUDPSocketEncounteredEOF(const UDPSocket *sock);
extern void mDNSPlatformReceiveBPF_fd(int fd);
extern void mDNSPlatformUpdateProxyList(const mDNSInterfaceID InterfaceID);
extern void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID);
extern void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID);
extern void mDNSPlatformSetLocalAddressCacheEntry(const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID);
extern void mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst);
extern void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win);
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 mDNSPlatformRetrieveTCPInfo(mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti);
extern mStatus mDNSPlatformGetRemoteMacAddr(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);
@ -3189,18 +3219,19 @@ extern void mDNSPlatformTLSTearDownCerts(void);
// Platforms that support unicast browsing and dynamic update registration for clients who do not specify a domain
// in browse/registration calls must implement these routines to get the "default" browse/registration list.
extern mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains,
extern mDNSBool mDNSPlatformSetDNSConfig(mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains,
DNameListElem **BrowseDomains, mDNSBool ackConfig);
extern mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *router);
extern mStatus mDNSPlatformGetPrimaryInterface(mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *router);
extern void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status);
extern void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason);
extern void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration);
extern void mDNSPlatformSetAllowSleep(mDNSBool allowSleep, const char *reason);
extern void mDNSPlatformPreventSleep(mDNSu32 timeout, const char *reason);
extern void mDNSPlatformSendWakeupPacket(mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration);
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);
@ -3253,10 +3284,19 @@ extern void LNT_ClearState(mDNS *const m);
extern void mDNS_SetFQDN(mDNS *const m);
extern void mDNS_ActivateNetWake_internal (mDNS *const m, NetworkInterfaceInfo *set);
extern void mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set);
extern mStatus mDNS_RegisterInterface (mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping);
extern void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping);
// Attributes that controls the Bonjour operation initiation and response speed for an interface.
typedef enum
{
FastActivation, // For p2p* and DirectLink type interfaces
NormalActivation, // For standard interface timing
SlowActivation // For flapping interfaces
} InterfaceActivationSpeed;
extern mStatus mDNS_RegisterInterface (mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed probeDelay);
extern void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed probeDelay);
extern void mDNSCoreInitComplete(mDNS *const m, mStatus result);
extern void mDNSCoreReceive(mDNS *const m, void *const msg, const mDNSu8 *const end,
extern void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
const mDNSAddr *const srcaddr, const mDNSIPPort srcport,
const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID);
extern void mDNSCoreRestartQueries(mDNS *const m);
@ -3276,7 +3316,7 @@ extern void mDNSCoreReceiveRawPacket (mDNS *const m, const mDNSu8 *const p,
extern mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip);
extern CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg, mDNSs32 delay, mDNSBool Add, const mDNSAddr *sourceAddress);
extern CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name);
extern CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 namehash, const domainname *const name);
extern void ReleaseCacheRecord(mDNS *const m, CacheRecord *r);
extern void ScheduleNextCacheCheckTime(mDNS *const m, const mDNSu32 slot, const mDNSs32 event);
extern void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const rr);
@ -3295,13 +3335,13 @@ 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);
// exported for using the hash for /etc/hosts AuthRecords
extern AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name);
extern AuthGroup *AuthGroupForRecord(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr);
extern AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 namehash, const domainname *const name);
extern AuthGroup *AuthGroupForRecord(AuthHash *r, const ResourceRecord *const rr);
extern AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
extern AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
extern mDNSBool mDNS_CheckForCacheRecord(mDNS *const m, DNSQuestion *q, mDNSu16 qtype);
@ -3310,36 +3350,36 @@ extern mDNSBool mDNS_CheckForCacheRecord(mDNS *const m, DNSQuestion *q, mDNSu16
// In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer
#if APPLE_OSX_mDNSResponder
extern void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
extern void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q);
extern void StartServerTunnel(mDNS *const m, DomainAuthInfo *const info);
extern void AddNewClientTunnel(DNSQuestion *const q);
extern void StartServerTunnel(DomainAuthInfo *const info);
extern void UpdateAutoTunnelDomainStatuses(const mDNS *const m);
extern void RemoveAutoTunnel6Record(mDNS *const m);
extern mDNSBool RecordReadyForSleep(mDNS *const m, AuthRecord *rr);
extern mDNSBool RecordReadyForSleep(AuthRecord *rr);
// For now this LocalSleepProxy stuff is specific to Mac OS X.
// In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer
extern mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const intf);
extern void mDNSPlatformUpdateDNSStatus(mDNS *const m, DNSQuestion *q);
extern void mDNSPlatformTriggerDNSRetry(mDNS *const m, DNSQuestion *v4q, DNSQuestion *v6q);
extern mStatus ActivateLocalProxy(NetworkInterfaceInfo *const intf, mDNSBool *keepaliveOnly);
extern void mDNSPlatformUpdateDNSStatus(DNSQuestion *q);
extern void mDNSPlatformTriggerDNSRetry(DNSQuestion *v4q, DNSQuestion *v6q);
extern void mDNSPlatformLogToFile(int log_level, const char *buffer);
extern mDNSBool SupportsInNICProxy(NetworkInterfaceInfo *const intf);
extern mStatus SymptomReporterDNSServerReachable(mDNS *const m, const mDNSAddr *addr);
extern mStatus SymptomReporterDNSServerUnreachable(DNSServer *s);
#endif
typedef void ProxyCallback (mDNS *const m, void *socket, void *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
typedef void ProxyCallback (void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context);
extern void mDNSPlatformInitDNSProxySkts(mDNS *const m, ProxyCallback *UDPCallback, ProxyCallback *TCPCallback);
extern void mDNSPlatformInitDNSProxySkts(ProxyCallback *UDPCallback, ProxyCallback *TCPCallback);
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);
extern void mDNSPlatformGetDNSRoutePolicy(DNSQuestion *q, mDNSBool *isBlocked);
#endif
extern mDNSBool mDNSPlatformAllowPID(mDNS *const m, DNSQuestion *q);
extern mDNSs32 mDNSPlatformGetServiceID(mDNS *const m, DNSQuestion *q);
extern void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q);
extern void mDNSPlatformSetSocktOpt(void *sock, mDNSTransport_Type transType, mDNSAddr_Type addrType, const DNSQuestion *q);
extern mDNSs32 mDNSPlatformGetPID(void);
extern mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr);
extern mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q);
// ***************************************************************************
#if 0
@ -3547,6 +3587,11 @@ struct CompileTimeAssertionChecks_mDNS
char assertK[(sizeof(UDPHeader ) == 8 ) ? 1 : -1];
char assertL[(sizeof(IKEHeader ) == 28 ) ? 1 : -1];
char assertM[(sizeof(TCPHeader ) == 20 ) ? 1 : -1];
char assertN[(sizeof(rdataOPT) == 24 ) ? 1 : -1];
char assertO[(sizeof(rdataRRSig) == 20 ) ? 1 : -1];
char assertP[(sizeof(PCPMapRequest) == 60 ) ? 1 : -1];
char assertQ[(sizeof(PCPMapReply) == 60 ) ? 1 : -1];
// 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
@ -3556,21 +3601,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) <= 832) ? 1 : -1];
char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 912) ? 1 : -1];
// Checks commented out when sizeof(DNSQuestion) change cascaded into having to change yet another
// set of hardcoded size values because these structures contain one or more DNSQuestion
// instances.
// char sizecheck_ZoneData [(sizeof(ZoneData) <= 1648) ? 1 : -1];
char sizecheck_ZoneData [(sizeof(ZoneData) <= 1744) ? 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) <= 6988) ? 1 : -1];
char sizecheck_DNSServer [(sizeof(DNSServer) <= 330) ? 1 : -1];
char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 7376) ? 1 : -1];
char sizecheck_ServiceRecordSet [(sizeof(ServiceRecordSet) <= 5540) ? 1 : -1];
char sizecheck_DomainAuthInfo [(sizeof(DomainAuthInfo) <= 7888) ? 1 : -1];
// char sizecheck_ServiceInfoQuery [(sizeof(ServiceInfoQuery) <= 3302) ? 1 : -1];
#if APPLE_OSX_mDNSResponder
// char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1160) ? 1 : -1];
char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1256) ? 1 : -1];
#endif
};
@ -3580,6 +3621,13 @@ 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
// ***************************************************************************

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2011-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.
@ -56,12 +56,10 @@ mDNSlocal CacheRecord *NSECParentForQuestion(mDNS *const m, DNSQuestion *q)
{
CacheGroup *cg;
CacheRecord *cr;
mDNSu32 slot;
mDNSu32 namehash;
slot = HashSlot(&q->qname);
namehash = DomainNameHashValue(&q->qname);
cg = CacheGroupForName(m, slot, namehash, &q->qname);
cg = CacheGroupForName(m, namehash, &q->qname);
if (!cg)
{
LogDNSSEC("NSECParentForQuestion: Cannot find cg for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
@ -611,7 +609,7 @@ mDNSlocal mDNSBool NSECNoDataError(mDNS *const m, ResourceRecord *rr, domainname
{
const domainname *oname = rr->name; // owner name
if (wildcard) *wildcard = mDNSNULL;
*wildcard = mDNSNULL;
// RFC 4035
//
// section 3.1.3.1 : Name matches. Prove that the type does not exist and also CNAME is
@ -676,10 +674,10 @@ mDNSlocal mDNSBool NSECNoDataError(mDNS *const m, ResourceRecord *rr, domainname
// a subdomain e.g., y.x.example or z.y.x.example and so on.
if (oname->c[0] == 1 && oname->c[1] == '*')
{
int r, s;
int s;
const domainname *ce = SkipLeadingLabels(oname, 1);
r = DNSSECCanonicalOrder(name, ce, &s);
DNSSECCanonicalOrder(name, ce, &s);
if (s)
{
if (RRAssertsExistence(rr, qtype) || RRAssertsExistence(rr, kDNSType_CNAME))
@ -912,18 +910,18 @@ mDNSlocal void NoDataProof(mDNS *const m, DNSSECVerifier *dv, CacheRecord *ncr)
// First verify wildcard NSEC and then when we are done, we
// will verify the noname nsec
dv->pendingNSEC = r;
LogDNSSEC("NoDataProof: Verifying wild and noname %s", RRDisplayString(m, nsec_wild));
LogDNSSEC("NoDataProof: Verifying wild and noname %s", nsec_wild ? RRDisplayString(m, nsec_wild) : "NULL");
VerifyNSEC(m, nsec_wild, mDNSNULL, dv, ncr, NoDataNSECCallback);
}
else if ((dv->flags & WILDCARD_PROVES_NONAME_EXISTS) ||
(dv->flags & NSEC_PROVES_NOTYPE_EXISTS))
{
LogDNSSEC("NoDataProof: Verifying wild %s", RRDisplayString(m, nsec_wild));
LogDNSSEC("NoDataProof: Verifying wild %s", nsec_wild ? RRDisplayString(m, nsec_wild) : "NULL");
VerifyNSEC(m, nsec_wild, mDNSNULL, dv, ncr, mDNSNULL);
}
else if (dv->flags & NSEC_PROVES_NONAME_EXISTS)
{
LogDNSSEC("NoDataProof: Verifying noname %s", RRDisplayString(m, nsec_noname));
LogDNSSEC("NoDataProof: Verifying noname %s", nsec_noname ? RRDisplayString(m, nsec_noname) : "NULL");
VerifyNSEC(m, nsec_noname, mDNSNULL, dv, ncr, mDNSNULL);
}
return;
@ -1050,12 +1048,11 @@ mDNSexport CacheRecord *NSECRecordIsDelegation(mDNS *const m, domainname *name,
{
CacheGroup *cg;
CacheRecord *cr;
mDNSu32 slot, namehash;
mDNSu32 namehash;
slot = HashSlot(name);
namehash = DomainNameHashValue(name);
cg = CacheGroupForName(m, (const mDNSu32)slot, namehash, name);
cg = CacheGroupForName(m, namehash, name);
if (!cg)
{
LogDNSSEC("NSECRecordForName: cg NULL for %##s", name);

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2011-2012 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.
@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __NSEC_H
#define __NSEC_H

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2011-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.
@ -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;
}
@ -332,7 +332,7 @@ mDNSlocal mDNSBool NSEC3Find(mDNS *const m, NSEC3FindValues val, CacheRecord *nc
}
}
if ((val == NSEC3Covers || val == NSEC3CEProof) && !(*closerEncloser))
if ((val == NSEC3Covers || val == NSEC3CEProof) && (!closerEncloser || !(*closerEncloser)))
{
if (NSEC3CoversName(m, cr, hashName, hlen, b32Name, b32len))
{
@ -349,23 +349,22 @@ mDNSlocal mDNSBool NSEC3Find(mDNS *const m, NSEC3FindValues val, CacheRecord *nc
// 2.3) If there is a matching NSEC3 RR in the response and the flag
// was set, then the proof is complete, and SNAME is the closest
// encloser.
if (val == NSEC3CEProof)
if (val == NSEC3CEProof && closestEncloser && *closestEncloser)
{
if (*closestEncloser && *closerEncloser)
if (closerEncloser && *closerEncloser)
{
LogDNSSEC("NSEC3Find: Found closest and closer encloser");
return mDNStrue;
}
// 2.4) If there is a matching NSEC3 RR in the response, but the flag
// is not set, then the response is bogus.
//
// Note: We don't have to wait till we finish trying all the names. If the matchName
// happens, we found the closest encloser which means we should have found the closer
// encloser before.
if (*closestEncloser && !(*closerEncloser))
else
{
// 2.4) If there is a matching NSEC3 RR in the response, but the flag
// is not set, then the response is bogus.
//
// Note: We don't have to wait till we finish trying all the names. If the matchName
// happens, we found the closest encloser which means we should have found the closer
// encloser before.
LogDNSSEC("NSEC3Find: Found closest, but not closer encloser");
return mDNSfalse;
}
@ -388,8 +387,7 @@ mDNSlocal mDNSBool NSEC3ClosestEncloserProof(mDNS *const m, CacheRecord *ncr, do
// Note: It is possible that closestEncloser and closerEncloser are the same.
if (!closestEncloser || !closerEncloser || !ce)
{
LogMsg("NSEC3ClosestEncloserProof: ClosestEncloser %p or CloserEncloser %p ce %p, something is NULL", *closestEncloser,
*closerEncloser, *ce);
LogMsg("NSEC3ClosestEncloserProof: ClosestEncloser %p or CloserEncloser %p ce %p, something is NULL", closestEncloser, closerEncloser, ce);
return mDNSfalse;
}
@ -677,12 +675,11 @@ mDNSexport CacheRecord *NSEC3RecordIsDelegation(mDNS *const m, domainname *name,
CacheGroup *cg;
CacheRecord *cr;
CacheRecord *ncr;
mDNSu32 slot, namehash;
mDNSu32 namehash;
slot = HashSlot(name);
namehash = DomainNameHashValue(name);
cg = CacheGroupForName(m, (const mDNSu32)slot, namehash, name);
cg = CacheGroupForName(m, namehash, name);
if (!cg)
{
LogDNSSEC("NSEC3RecordForName: cg NULL for %##s", name);
@ -710,7 +707,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;
}

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2011-2012 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.

File diff suppressed because it is too large Load Diff

View File

@ -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
@ -124,7 +128,7 @@ extern mStatus uDNS_SetupDNSConfig(mDNS *const m);
extern void uDNS_SetupWABQueries(mDNS *const m);
extern void uDNS_StartWABQueries(mDNS *const m, int queryType);
extern void uDNS_StopWABQueries(mDNS *const m, int queryType);
extern domainname *uDNS_GetNextSearchDomain(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal);
extern domainname *uDNS_GetNextSearchDomain(mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal);
typedef enum
{
@ -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

View File

@ -118,11 +118,11 @@ mDNSlocal void ParseCmdLinArgs(int argc, char **argv)
}
}
mDNSlocal void DumpStateLog(mDNS *const m)
mDNSlocal void DumpStateLog()
// Dump a little log of what we've been up to.
{
LogMsg("---- BEGIN STATE LOG ----");
udsserver_info(m);
LogMsg("---- BEGIN STATE LOG ----");
udsserver_info();
LogMsg("---- END STATE LOG ----");
}
@ -160,7 +160,7 @@ mDNSlocal mStatus MainLoop(mDNS *m) // Loop until we quit.
(void) mDNSPosixRunEventLoopOnce(m, &timeout, &signals, &gotData);
if (sigismember(&signals, SIGHUP )) Reconfigure(m);
if (sigismember(&signals, SIGUSR1)) DumpStateLog(m);
if (sigismember(&signals, SIGUSR1)) DumpStateLog();
// SIGPIPE happens when we try to write to a dead client; death should be detected soon in request_callback() and cleaned up.
if (sigismember(&signals, SIGPIPE)) LogMsg("Received SIGPIPE - ignoring");
if (sigismember(&signals, SIGINT) || sigismember(&signals, SIGTERM)) break;
@ -235,9 +235,8 @@ mStatus udsSupportRemoveFDFromEventLoop(int fd, void *platform_data) // N
return err;
}
mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
mDNSexport void RecordUpdatedNiceLabel(mDNSs32 delay)
{
(void)m;
(void)delay;
// No-op, for now
}

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2002-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.
@ -52,6 +52,7 @@
#include "mDNSUNP.h"
#include "GenLinkedList.h"
#include "dnsproxy.h"
// ***************************************************************************
// Structures
@ -138,7 +139,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;
@ -311,16 +312,8 @@ mDNSlocal void SocketDataReady(mDNS *const m, PosixNetworkInterface *intf, int s
&senderAddr, senderPort, &destAddr, MulticastDNSPort, InterfaceID);
}
mDNSexport mDNSBool mDNSPlatformPeekUDP(mDNS *const m, UDPSocket *src)
mDNSexport TCPSocket *mDNSPlatformTCPSocket(TCPSocketFlags flags, mDNSIPPort * port, mDNSBool useBackgroundTrafficClass)
{
(void)m; // unused
(void)src; // unused
return mDNSfalse;
}
mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS * const m, TCPSocketFlags flags, mDNSIPPort * port, mDNSBool useBackgroundTrafficClass)
{
(void)m; // Unused
(void)flags; // Unused
(void)port; // Unused
(void)useBackgroundTrafficClass; // Unused
@ -375,9 +368,8 @@ mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned
return 0;
}
mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS * const m, mDNSIPPort port)
mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNSIPPort port)
{
(void)m; // Unused
(void)port; // Unused
return NULL;
}
@ -387,9 +379,8 @@ mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock)
(void)sock; // Unused
}
mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
mDNSexport void mDNSPlatformUpdateProxyList(const mDNSInterfaceID InterfaceID)
{
(void)m; // Unused
(void)InterfaceID; // Unused
}
@ -400,9 +391,8 @@ mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *c
(void)InterfaceID; // Unused
}
mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
{
(void)m; // Unused
(void)tpa; // Unused
(void)tha; // Unused
(void)InterfaceID; // Unused
@ -417,9 +407,8 @@ mDNSexport void mDNSPlatformTLSTearDownCerts(void)
{
}
mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason)
mDNSexport void mDNSPlatformSetAllowSleep(mDNSBool allowSleep, const char *reason)
{
(void) m;
(void) allowSleep;
(void) reason;
}
@ -441,10 +430,9 @@ mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result
#pragma mark ***** DDNS Config Platform Functions
#endif
mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains,
mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains,
DNameListElem **BrowseDomains, mDNSBool ackConfig)
{
(void) m;
(void) setservers;
(void) fqdn;
(void) setsearch;
@ -455,9 +443,8 @@ mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers,
return mDNStrue;
}
mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS * const m, mDNSAddr * v4, mDNSAddr * v6, mDNSAddr * router)
mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNSAddr * v4, mDNSAddr * v6, mDNSAddr * router)
{
(void) m;
(void) v4;
(void) v6;
(void) router;
@ -512,10 +499,11 @@ mDNSexport int ParseDNSServers(mDNS *m, const char *filePath)
mDNSAddr DNSAddr;
DNSAddr.type = mDNSAddrType_IPv4;
DNSAddr.ip.v4.NotAnInteger = ina.s_addr;
mDNS_AddDNSServer(m, NULL, mDNSInterface_Any, 0, &DNSAddr, UnicastDNSPort, kScopeNone, 0, mDNSfalse, 0, mDNStrue, mDNStrue, mDNSfalse);
mDNS_AddDNSServer(m, NULL, mDNSInterface_Any, 0, &DNSAddr, UnicastDNSPort, kScopeNone, 0, mDNSfalse, mDNSfalse, 0, mDNStrue, mDNStrue, mDNSfalse);
numOfServers++;
}
}
fclose(fp);
return (numOfServers > 0) ? 0 : -1;
}
@ -581,11 +569,20 @@ mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNS
// interface must have already been deregistered with the mDNS core.
mDNSlocal void FreePosixNetworkInterface(PosixNetworkInterface *intf)
{
int rv;
assert(intf != NULL);
if (intf->intfName != NULL) free((void *)intf->intfName);
if (intf->multicastSocket4 != -1) assert(close(intf->multicastSocket4) == 0);
if (intf->multicastSocket4 != -1)
{
rv = close(intf->multicastSocket4);
assert(rv == 0);
}
#if HAVE_IPV6
if (intf->multicastSocket6 != -1) assert(close(intf->multicastSocket6) == 0);
if (intf->multicastSocket6 != -1)
{
rv = close(intf->multicastSocket6);
assert(rv == 0);
}
#endif
// Move interface to the RecentInterfaces list for a minute
@ -602,7 +599,7 @@ mDNSlocal void ClearInterfaceList(mDNS *const m)
while (m->HostInterfaces)
{
PosixNetworkInterface *intf = (PosixNetworkInterface*)(m->HostInterfaces);
mDNS_DeregisterInterface(m, &intf->coreIntf, mDNSfalse);
mDNS_DeregisterInterface(m, &intf->coreIntf, NormalActivation);
if (gMDNSPlatformPosixVerboseLevel > 0) fprintf(stderr, "Deregistered interface %s\n", intf->intfName);
FreePosixNetworkInterface(intf);
}
@ -639,10 +636,22 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
// ... with a shared UDP port, if it's for multicast receiving
if (err == 0 && port.NotAnInteger)
{
#if defined(SO_REUSEPORT)
err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEPORT, &kOn, sizeof(kOn));
#elif defined(SO_REUSEADDR)
// <rdar://problem/20946253>
// We test for SO_REUSEADDR first, as suggested by Jonny Törnbom from Axis Communications
// Linux kernel versions 3.9 introduces support for socket option
// SO_REUSEPORT, however this is not implemented the same as on *BSD
// systems. Linux version implements a "port hijacking" prevention
// mechanism, limiting processes wanting to bind to an already existing
// addr:port to have the same effective UID as the first who bound it. What
// this meant for us was that the daemon ran as one user and when for
// instance mDNSClientPosix was executed by another user, it wasn't allowed
// to bind to the socket. Our suggestion was to switch the order in which
// SO_REUSEPORT and SO_REUSEADDR was tested so that SO_REUSEADDR stays on
// top and SO_REUSEPORT to be used only if SO_REUSEADDR doesn't exist.
#if defined(SO_REUSEADDR) && !defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
#elif defined(SO_REUSEPORT)
err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEPORT, &kOn, sizeof(kOn));
#else
#error This platform has no way to avoid address busy errors on multicast.
#endif
@ -836,7 +845,13 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
}
// Clean up
if (err != 0 && *sktPtr != -1) { assert(close(*sktPtr) == 0); *sktPtr = -1; }
if (err != 0 && *sktPtr != -1)
{
int rv;
rv = close(*sktPtr);
assert(rv == 0);
*sktPtr = -1;
}
assert((err == 0) == (*sktPtr != -1));
return err;
}
@ -855,7 +870,7 @@ mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct
assert(intfMask != NULL);
// Allocate the interface structure itself.
intf = (PosixNetworkInterface*)malloc(sizeof(*intf));
intf = (PosixNetworkInterface*)calloc(1, sizeof(*intf));
if (intf == NULL) { assert(0); err = ENOMEM; }
// And make a copy of the intfName.
@ -907,13 +922,14 @@ 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;
// The interface is all ready to go, let's register it with the mDNS core.
if (err == 0)
err = mDNS_RegisterInterface(m, &intf->coreIntf, mDNSfalse);
err = mDNS_RegisterInterface(m, &intf->coreIntf, NormalActivation);
// Clean up.
if (err == 0)
@ -1315,11 +1331,20 @@ mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
// In our case all we need to do is to tear down every network interface.
mDNSexport void mDNSPlatformClose(mDNS *const m)
{
int rv;
assert(m != NULL);
ClearInterfaceList(m);
if (m->p->unicastSocket4 != -1) assert(close(m->p->unicastSocket4) == 0);
if (m->p->unicastSocket4 != -1)
{
rv = close(m->p->unicastSocket4);
assert(rv == 0);
}
#if HAVE_IPV6
if (m->p->unicastSocket6 != -1) assert(close(m->p->unicastSocket6) == 0);
if (m->p->unicastSocket6 != -1)
{
rv = close(m->p->unicastSocket6);
assert(rv == 0);
}
#endif
}
@ -1366,14 +1391,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.
@ -1439,16 +1486,14 @@ mDNSexport mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DN
return ptr;
}
mDNSexport void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[], mDNSu32 OpIf)
mDNSexport void DNSProxyInit(mDNSu32 IpIfArr[], mDNSu32 OpIf)
{
(void) m;
(void) IpIfArr;
(void) OpIf;
}
mDNSexport void DNSProxyTerminate(mDNS *const m)
mDNSexport void DNSProxyTerminate(void)
{
(void) m;
}
// mDNS core calls this routine to clear blocks of memory.
@ -1461,12 +1506,19 @@ mDNSexport void mDNSPlatformMemZero(void *dst, mDNSu32 len)
mDNSexport void * mDNSPlatformMemAllocate(mDNSu32 len) { return(malloc(len)); }
mDNSexport void mDNSPlatformMemFree (void *mem) { free(mem); }
#if _PLATFORM_HAS_STRONG_PRNG_
mDNSexport mDNSu32 mDNSPlatformRandomNumber(void)
{
return(arc4random());
}
#else
mDNSexport mDNSu32 mDNSPlatformRandomSeed(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return(tv.tv_usec);
}
#endif
mDNSexport mDNSs32 mDNSPlatformOneSecond = 1024;
@ -1496,19 +1548,18 @@ mDNSexport mDNSs32 mDNSPlatformUTC(void)
return time(NULL);
}
mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
mDNSexport void mDNSPlatformSendWakeupPacket(mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
{
(void) m;
(void) InterfaceID;
(void) EthAddr;
(void) IPAddr;
(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;
}
@ -1539,9 +1590,8 @@ mDNSexport void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIP
(void) win; // Unused
}
mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti)
mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti)
{
(void) m; // Unused
(void) laddr; // Unused
(void) raddr; // Unused
(void) lport; // Unused
@ -1551,10 +1601,9 @@ mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, m
return mStatus_NoError;
}
mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNS *const m, mDNSAddr *raddr)
mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNSAddr *raddr)
{
(void) raddr; // Unused
(void) m; // Unused
return mStatus_NoError;
}
@ -1567,43 +1616,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 mDNSBool mDNSPlatformAllowPID(mDNS *const m, DNSQuestion *q)
mDNSexport void mDNSPlatformSetSocktOpt(void *sock, mDNSTransport_Type transType, mDNSAddr_Type addrType, const DNSQuestion *q)
{
(void) m;
(void) q;
return mDNStrue;
}
mDNSexport mDNSs32 mDNSPlatformGetServiceID(mDNS *const m, DNSQuestion *q)
{
(void) m;
(void) q;
return -1;
}
mDNSexport void mDNSPlatformSetDelegatePID(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q)
{
(void) src;
(void) dst;
(void) sock;
(void) transType;
(void) addrType;
(void) q;
}

View File

@ -65,7 +65,7 @@ extern mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m);
// Call mDNSPosixGetFDSet before calling select(), to update the parameters
// as may be necessary to meet the needs of the mDNSCore code.
// The timeout pointer MUST NOT be NULL.
// Set timeout->tv_sec to 0x3FFFFFFF if you want to have effectively no timeout
// Set timeout->tv_sec to FutureTime if you want to have effectively no timeout
// After calling mDNSPosixGetFDSet(), call select(nfds, &readfds, NULL, NULL, &timeout); as usual
// After select() returns, call mDNSPosixProcessFDSet() to let mDNSCore do its work
extern void mDNSPosixGetFDSet(mDNS *m, int *nfds, fd_set *readfds, struct timeval *timeout);

View File

@ -83,14 +83,12 @@ void plen_to_mask(int plen, char *addr) {
struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
{
struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
FILE *fp;
FILE *fp = NULL;
char addr[8][5];
int flags, myflags, index, plen, scope;
char ifname[9], lastname[IFNAMSIZ];
char addr6[32+7+1]; /* don't forget the seven ':' */
struct addrinfo hints, *res0;
struct sockaddr_in6 *sin6;
struct in6_addr *addrptr;
int err;
int sockfd = -1;
struct ifreq ifr;
@ -150,18 +148,13 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
char ipv6addr[INET6_ADDRSTRLEN];
plen_to_mask(plen, ipv6addr);
ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
if (ifi->ifi_addr == NULL) {
if (ifi->ifi_netmask == NULL) {
goto gotError;
}
sin6=calloc(1, sizeof(struct sockaddr_in6));
addrptr=calloc(1, sizeof(struct in6_addr));
inet_pton(family, ipv6addr, addrptr);
sin6->sin6_family=family;
sin6->sin6_addr=*addrptr;
sin6->sin6_scope_id=scope;
memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6));
free(sin6);
((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_family=family;
((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_scope_id=scope;
inet_pton(family, ipv6addr, &((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_addr);
/* Add interface name */
memcpy(ifi->ifi_name, ifname, IFI_NAME);
@ -179,6 +172,7 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
* EADDRNOTAVAIL for the main interface
*/
free(ifi->ifi_addr);
free(ifi->ifi_netmask);
free(ifi);
ifipnext = ifiptr;
*ifipnext = ifipold;
@ -205,7 +199,12 @@ gotError:
}
done:
if (sockfd != -1) {
assert(close(sockfd) == 0);
int rv;
rv = close(sockfd);
assert(rv == 0);
}
if (fp != NULL) {
fclose(fp);
}
return(ifihead); /* pointer to first structure in linked list */
}

View File

@ -834,6 +834,12 @@ typedef unsigned long int uintptr_t;
#endif
#endif
// Limits
#if( !defined( UINT32_MAX ) )
#define UINT32_MAX UINT32_C( 4294967295 )
#endif
#if 0
#pragma mark == bool ==
#endif

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2003-2011 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.
@ -13,13 +13,6 @@
* 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.
File: GenLinkedList.c
Contains: implementation of generic linked lists.
Version: 1.0
Tabs: 4 spaces
*/
#include "GenLinkedList.h"

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2004-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.
@ -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++; }
@ -190,10 +203,13 @@ mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, m
if (ident && ident[0] && mDNSPlatformClockDivisor)
syslog(syslog_level, "%8d.%03d: %s", (int)(t/1000), ms, buffer);
else
#elif APPLE_OSX_mDNSResponder
mDNSPlatformLogToFile(syslog_level, buffer);
#else
syslog(syslog_level, "%s", buffer);
#endif
{
#if APPLE_OSX_mDNSResponder
mDNSPlatformLogToFile(syslog_level, buffer);
#else
syslog(syslog_level, "%s", buffer);
#endif
}
}
}

View File

@ -1,6 +1,6 @@
.\" -*- tab-width: 4 -*-
.\"
.\" Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
.\" Copyright (c) 2004-2012 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.

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2003-2013 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2003-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
* 3. Neither the name of Apple Inc. ("Apple") nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
@ -66,7 +66,7 @@
*/
#ifndef _DNS_SD_H
#define _DNS_SD_H 5763004
#define _DNS_SD_H 8780101
#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.
*/
@ -484,23 +511,24 @@ enum
* is only set in the callbacks and kDNSServiceFlagsThresholdOne is only set on
* input to a DNSServiceBrowse call.
*/
kDNSServiceFlagsDenyCellular = 0x8000000,
kDNSServiceFlagsPrivateOne = 0x8000000,
/*
* This flag is meaningful only for Unicast DNS queries. When set, the kernel will restrict
* DNS resolutions on the cellular interface for that request.
* This flag is private and should not be used.
*/
kDNSServiceFlagsServiceIndex = 0x10000000,
kDNSServiceFlagsPrivateTwo = 0x10000000,
/*
* This flag is meaningful only for DNSServiceGetAddrInfo() for Unicast DNS queries.
* When set, DNSServiceGetAddrInfo() will interpret the "interfaceIndex" argument of the call
* as the "serviceIndex".
* This flag is private and should not be used.
*/
kDNSServiceFlagsDenyExpensive = 0x20000000
kDNSServiceFlagsPrivateThree = 0x20000000,
/*
* This flag is meaningful only for Unicast DNS queries. When set, the kernel will restrict
* DNS resolutions on interfaces defined as expensive for that request.
* This flag is private and should not be used.
*/
kDNSServiceFlagsPrivateFour = 0x40000000
/*
* This flag is private and should not be used.
*/
};
@ -667,24 +695,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.
*
@ -704,7 +757,7 @@ enum
* full DNS name, the helper function DNSServiceConstructFullName() is provided.
*
* The following (highly contrived) example illustrates the escaping process.
* Suppose you have an service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp"
* Suppose you have a service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp"
* in subdomain "4th. Floor" of subdomain "Building 2" of domain "apple.com."
* The full (escaped) DNS name of this service's SRV record would be:
* Dr\.\032Smith\\Dr\.\032Johnson._ftp._tcp.4th\.\032Floor.Building\0322.apple.com.
@ -724,9 +777,8 @@ enum
* DNS server." Normally, most clients will use 0 for interface index to
* automatically get the default sensible behaviour.
*
* If the client passes a positive interface index, then for multicast names that
* indicates to do the operation only on that one interface. For unicast names the
* interface index is ignored unless kDNSServiceFlagsForceMulticast is also set.
* If the client passes a positive interface index, then that indicates to do the
* operation only on that one specified interface.
*
* If the client passes kDNSServiceInterfaceIndexLocalOnly when registering
* a service, then that service will be found *only* by other local clients
@ -737,12 +789,29 @@ 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.
*
* If the kDNSServiceFlagsTimeout and kDNSServiceInterfaceIndexLocalOnly flags
* are set simultaneously when either DNSServiceQueryRecord or DNSServiceGetAddrInfo
* is called then both flags take effect. However, if DNSServiceQueryRecord is called
* with both the kDNSServiceFlagsSuppressUnusable and kDNSServiceInterfaceIndexLocalOnly
* flags set, then the kDNSServiceFlagsSuppressUnusable flag is ignored.
*
* 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.
@ -771,6 +840,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;
@ -828,29 +898,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
@ -871,8 +918,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.
@ -883,7 +930,7 @@ DNSServiceErrorType DNSSD_API DNSServiceGetPID
* error.
*/
int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef);
dnssd_sock_t DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef);
/* DNSServiceProcessResult()
@ -1085,14 +1132,14 @@ typedef void (DNSSD_API *DNSServiceRegisterReply)
* and the registration will remain active indefinitely until the client
* terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
*
* flags: Indicates the renaming behavior on name conflict (most applications
* will pass 0). See flag definitions above for details.
*
* interfaceIndex: If non-zero, specifies the interface on which to register the service
* (the index for a given interface is determined via the if_nametoindex()
* family of calls.) Most applications will pass 0 to register on all
* available interfaces. See "Constants for specifying an interface index" for more details.
*
* flags: Indicates the renaming behavior on name conflict (most applications
* will pass 0). See flag definitions above for details.
*
* name: If non-NULL, specifies the service name to be registered.
* Most applications will not specify a name, in which case the computer
* name is used (this name is communicated to the client via the callback).
@ -1232,7 +1279,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;
@ -1315,7 +1362,7 @@ DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
/* DNSServiceRemoveRecord
*
* Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister
* an record registered individually via DNSServiceRegisterRecord().
* a record registered individually via DNSServiceRegisterRecord().
*
* Parameters:
*
@ -1623,7 +1670,9 @@ DNSServiceErrorType DNSSD_API DNSServiceResolve
* only applies to clients that cancel the asynchronous operation when
* they get a result. Clients that leave the asynchronous operation
* running can safely assume that the data remains valid until they
* get another callback telling them otherwise.
* get another callback telling them otherwise. The ttl value is not
* updated when the daemon answers from the cache, hence relying on
* the accuracy of the ttl value is not recommended.
*
* context: The context pointer that was passed to the callout.
*
@ -1729,7 +1778,9 @@ DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
* only applies to clients that cancel the asynchronous operation when
* they get a result. Clients that leave the asynchronous operation
* running can safely assume that the data remains valid until they
* get another callback telling them otherwise.
* get another callback telling them otherwise. The ttl value is not
* updated when the daemon answers from the cache, hence relying on
* the accuracy of the ttl value is not recommended.
*
* context: The context pointer that was passed to the callout.
*
@ -2242,8 +2293,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
@ -2293,8 +2344,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().
*
@ -2606,41 +2657,6 @@ DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive
);
#endif
#ifdef APPLE_OSX_mDNSResponder
/* DNSServiceCreateDelegateConnection()
*
* Create a delegate connection to the daemon allowing efficient registration of
* multiple individual records.
*
* Parameters:
*
* sdRef: A pointer to an uninitialized DNSServiceRef. Deallocating
* the reference (via DNSServiceRefDeallocate()) severs the
* connection and deregisters all records registered on this connection.
*
* pid : Process ID of the delegate
*
* uuid: UUID of the delegate
*
* Note that only one of the two arguments (pid or uuid) can be specified. If pid
* is zero, uuid will be assumed to be a valid value; otherwise pid will be used.
*
* return value: Returns kDNSServiceErr_NoError on success, otherwise returns
* an error code indicating the specific failure that occurred (in which
* case the DNSServiceRef is not initialized). kDNSServiceErr_NotAuth is
* returned to indicate that the calling process does not have entitlements
* to use this API.
*/
DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid);
#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

View File

@ -0,0 +1,15 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2016 Apple Inc. All rights reserved.
*/
#ifndef _DNS_SD_INTERNAL_H
#define _DNS_SD_INTERNAL_H
#if !APPLE_OSX_mDNSResponder
#define DNSSD_NO_CREATE_DELEGATE_CONNECTION 1
#endif
#include "dns_sd_private.h"
#endif

View File

@ -0,0 +1,89 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2015 Apple Inc. All rights reserved.
*/
#ifndef _DNS_SD_PRIVATE_H
#define _DNS_SD_PRIVATE_H
// Private flags (kDNSServiceFlagsPrivateOne, kDNSServiceFlagsPrivateTwo, kDNSServiceFlagsPrivateThree, kDNSServiceFlagsPrivateFour) from dns_sd.h
enum
{
kDNSServiceFlagsDenyCellular = 0x8000000,
/*
* This flag is meaningful only for Unicast DNS queries. When set, the daemon will restrict
* DNS resolutions on the cellular interface for that request.
*/
kDNSServiceFlagsServiceIndex = 0x10000000,
/*
* This flag is meaningful only for DNSServiceGetAddrInfo() for Unicast DNS queries.
* When set, DNSServiceGetAddrInfo() will interpret the "interfaceIndex" argument of the call
* as the "serviceIndex".
*/
kDNSServiceFlagsDenyExpensive = 0x20000000,
/*
* This flag is meaningful only for Unicast DNS queries. When set, the daemon will restrict
* DNS resolutions on interfaces defined as expensive for that request.
*/
kDNSServiceFlagsPathEvaluationDone = 0x40000000
/*
* This flag is meaningful for only Unicast DNS queries.
* When set, it indicates that Network PathEvaluation has already been performed.
*/
};
#if !DNSSD_NO_CREATE_DELEGATE_CONNECTION
/* DNSServiceCreateDelegateConnection()
*
* Parameters:
*
* sdRef: A pointer to an uninitialized DNSServiceRef. Deallocating
* the reference (via DNSServiceRefDeallocate()) severs the
* connection and deregisters all records registered on this connection.
*
* pid : Process ID of the delegate
*
* uuid: UUID of the delegate
*
* Note that only one of the two arguments (pid or uuid) can be specified. If pid
* is zero, uuid will be assumed to be a valid value; otherwise pid will be used.
*
* return value: Returns kDNSServiceErr_NoError on success, otherwise returns
* an error code indicating the specific failure that occurred (in which
* case the DNSServiceRef is not initialized). kDNSServiceErr_NotAuth is
* returned to indicate that the calling process does not have entitlements
* to use this API.
*/
DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid);
#endif
// 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

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2006-2010 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.
@ -76,6 +76,7 @@ typedef struct ZoneSpec
static StringListElem * g_stringList = NULL;
static StringListElem * g_addrList = NULL;
static KeySpec * g_keys;
static ZoneSpec * g_zones;
static ZoneSpec g_zoneSpec;
@ -173,6 +174,22 @@ optionsstatement:
|
LISTEN_ON PORT NUMBER addresscontent
{
mDNSIPPort listen_port = mDNSOpaque16fromIntVal( $3 );
DaemonInfo* d = ( DaemonInfo* ) context;
d->addr.sin_port = ( listen_port.NotAnInteger) ? listen_port.NotAnInteger : UnicastDNSPort.NotAnInteger;
StringListElem* addr = g_addrList;
while (addr != NULL)
{
StringListElem* next;
// The first ipv4 address in {,} is used; the rest are ignored.
if (inet_pton( AF_INET, addr->string, &d->addr.sin_addr ) == 0) {
inet_pton( AF_INET, "127.0.0.1", &d->ns_addr.sin_addr );
LogMsg("LISTEN_ON: An invalid ipv4 address, %s, detected.", addr->string);
}
next = addr->next;
free(addr);
addr = next;
}
}
|
NAMESERVER ADDRESS networkaddress
@ -308,6 +325,20 @@ addressstatements:
addressstatement:
DOTTED_DECIMAL_ADDRESS
{
StringListElem * elem;
elem = ( StringListElem* ) malloc( sizeof( StringListElem ) );
if ( !elem )
{
LogMsg("ERROR: memory allocation failure");
YYABORT;
}
elem->string = $1;
elem->next = g_addrList;
g_addrList = elem;
}
;

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
* Copyright (c) 2004-2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
* 3. Neither the name of Apple Inc. ("Apple") nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
* Copyright (c) 2003-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
* 3. Neither the name of Apple Inc. ("Apple") nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
@ -29,14 +29,15 @@
#include <errno.h>
#include <stdlib.h>
#include "dnssd_ipc.h"
#if APPLE_OSX_mDNSResponder
#include <mach-o/dyld.h>
#include <uuid/uuid.h>
#include <TargetConditionals.h>
#include "dns_sd_internal.h"
#endif
#include "dnssd_ipc.h"
#if defined(_WIN32)
#define _SSIZE_T
@ -74,7 +75,7 @@ static void syslog( int priority, const char * message, ...)
va_start( args, message );
len = _vscprintf( message, args ) + 1;
buffer = malloc( len * sizeof(char) );
if ( buffer ) { vsprintf( buffer, message, args ); OutputDebugString( buffer ); free( buffer ); }
if ( buffer ) { vsnprintf( buffer, len, message, args ); OutputDebugString( buffer ); free( buffer ); }
WSASetLastError( err );
}
#else
@ -171,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)
{
@ -181,10 +195,11 @@ static int write_all(dnssd_sock_t sd, char *buf, size_t len)
ssize_t num_written = send(sd, buf, (long)len, 0);
if (num_written < 0 || (size_t)num_written > len)
{
// Should never happen. If it does, it indicates some OS bug,
// Check whether socket has gone defunct,
// otherwise, an error here indicates some OS bug
// or that the mDNSResponder daemon crashed (which should never happen).
#if !defined(__ppc__) && defined(SO_ISDEFUNCT)
int defunct;
#if !defined(__ppc__) && defined(SO_ISDEFUNCT)
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));
@ -195,12 +210,12 @@ static int write_all(dnssd_sock_t sd, char *buf, size_t len)
(num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
else
syslog(LOG_INFO, "dnssd_clientstub write_all(%d) DEFUNCT", sd);
#else
#else
syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd,
(long)num_written, (long)len,
(num_written < 0) ? dnssd_errno : 0,
(num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
#endif
#endif
return -1;
}
buf += num_written;
@ -231,7 +246,9 @@ static int read_all(dnssd_sock_t sd, char *buf, int len)
{
int printWarn = 0;
int defunct = 0;
// Should never happen. If it does, it indicates some OS bug,
// Check whether socket has gone defunct,
// otherwise, an error here indicates some OS bug
// or that the mDNSResponder daemon crashed (which should never happen).
#if defined(WIN32)
// <rdar://problem/7481776> Suppress logs for "A non-blocking socket operation
@ -271,6 +288,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;
@ -284,7 +307,7 @@ static int more_bytes(dnssd_sock_t sd)
// two ints and not just one.
int nfdbits = sizeof (int) * 8;
int nints = (sd/nfdbits) + 1;
fs = (fd_set *)calloc(nints, sizeof(int));
fs = (fd_set *)calloc(nints, (size_t)sizeof(int));
if (fs == NULL)
{
syslog(LOG_WARNING, "dnssd_clientstub more_bytes: malloc failed");
@ -295,6 +318,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);
}
@ -355,7 +379,7 @@ static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int
struct timeval tv;
if (gettimeofday(&tv, NULL) < 0)
{ syslog(LOG_WARNING, "dnssd_clientstub create_hdr: gettimeofday failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); return NULL; }
sprintf(ctrl_path, "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(),
snprintf(ctrl_path, sizeof(ctrl_path), "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(),
(unsigned long)(tv.tv_sec & 0xFFF), (unsigned long)(tv.tv_usec));
*len += strlen(ctrl_path) + 1;
#else
@ -405,7 +429,11 @@ static void FreeDNSServiceOp(DNSServiceOp *x)
// We don't use our DNSServiceRefValid macro here because if we're cleaning up after a socket() call failed
// then sockfd could legitimately contain a failing value (e.g. dnssd_InvalidSocket)
if ((x->sockfd ^ x->validator) != ValidatorBits)
{
static DNSServiceOp *op_were_not_going_to_free_but_we_need_to_fool_the_analyzer;
syslog(LOG_WARNING, "dnssd_clientstub attempt to dispose invalid DNSServiceRef %p %08X %08X", x, x->sockfd, x->validator);
op_were_not_going_to_free_but_we_need_to_fool_the_analyzer = x;
}
else
{
x->next = NULL;
@ -425,8 +453,8 @@ static void FreeDNSServiceOp(DNSServiceOp *x)
x->disp_queue = NULL;
#endif
// DNSRecords may have been added to subordinate sdRef e.g., DNSServiceRegister/DNSServiceAddRecord
// or on the main sdRef e.g., DNSServiceCreateConnection/DNSServiveRegisterRecord. DNSRecords may have
// been freed if the application called DNSRemoveRecord
// or on the main sdRef e.g., DNSServiceCreateConnection/DNSServiceRegisterRecord.
// DNSRecords may have been freed if the application called DNSRemoveRecord.
FreeDNSRecords(x);
if (x->kacontext)
{
@ -530,6 +558,11 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f
char* uds_serverpath = getenv(MDNS_UDS_SERVERPATH_ENVVAR);
if (uds_serverpath == NULL)
uds_serverpath = MDNS_UDS_SERVERPATH;
else if (strlen(uds_serverpath) >= MAX_CTLPATH)
{
uds_serverpath = MDNS_UDS_SERVERPATH;
syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: using default path since env len is invalid");
}
#endif
*ref = NULL;
sdr->sockfd = socket(AF_DNSSD, SOCK_STREAM, 0);
@ -551,7 +584,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;
@ -578,8 +611,10 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f
}
else
{
#if !defined(USE_TCP_LOOPBACK)
syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect() failed path:%s Socket:%d Err:%d Errno:%d %s",
uds_serverpath, sdr->sockfd, err, dnssd_errno, dnssd_strerror(dnssd_errno));
#endif
dnssd_close(sdr->sockfd);
FreeDNSServiceOp(sdr);
return kDNSServiceErr_ServiceNotRunning;
@ -597,21 +632,31 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f
static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
{
uint32_t datalen = hdr->datalen; // We take a copy here because we're going to convert hdr->datalen to network byte order
#if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
char *const data = (char *)hdr + sizeof(ipc_msg_hdr);
#endif
uint32_t datalen;
dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
DNSServiceErrorType err = kDNSServiceErr_Unknown; // Default for the "goto cleanup" cases
int MakeSeparateReturnSocket = 0;
int MakeSeparateReturnSocket;
#if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
char *data;
#endif
if (!hdr)
{
syslog(LOG_WARNING, "dnssd_clientstub deliver_request: !hdr");
return kDNSServiceErr_Unknown;
}
datalen = hdr->datalen; // We take a copy here because we're going to convert hdr->datalen to network byte order
#if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
data = (char *)hdr + sizeof(ipc_msg_hdr);
#endif
// Note: need to check hdr->op, not sdr->op.
// hdr->op contains the code for the specific operation we're currently doing, whereas sdr->op
// contains the original parent DNSServiceOp (e.g. for an add_record_request, hdr->op will be
// add_record_request but the parent sdr->op will be connection_request or reg_service_request)
if (sdr->primary ||
hdr->op == reg_record_request || hdr->op == add_record_request || hdr->op == update_record_request || hdr->op == remove_record_request)
MakeSeparateReturnSocket = 1;
MakeSeparateReturnSocket = (sdr->primary ||
hdr->op == reg_record_request || hdr->op == add_record_request || hdr->op == update_record_request || hdr->op == remove_record_request);
if (!DNSServiceRefValid(sdr))
{
@ -621,12 +666,6 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
return kDNSServiceErr_BadReference;
}
if (!hdr)
{
syslog(LOG_WARNING, "dnssd_clientstub deliver_request: !hdr");
return kDNSServiceErr_Unknown;
}
if (MakeSeparateReturnSocket)
{
#if defined(USE_TCP_LOOPBACK)
@ -661,7 +700,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);
@ -842,7 +881,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; }
@ -859,7 +898,7 @@ int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef)
return dnssd_InvalidSocket;
}
return (int) sdRef->sockfd;
return sdRef->sockfd;
}
#if _DNS_SD_LIBDISPATCH
@ -1144,13 +1183,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);
@ -1158,6 +1202,8 @@ DNSServiceErrorType DNSSD_API DNSServiceGetProperty(const char *property, void *
put_string(property, &ptr);
err = deliver_request(hdr, tmp); // Will free hdr for us
if (err) { DNSServiceRefDeallocate(tmp); return err; }
if (read_all(tmp->sockfd, (char*)&actualsize, (int)sizeof(actualsize)) < 0)
{ DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; }
@ -1178,28 +1224,21 @@ DNSServiceErrorType DNSSD_API DNSServiceGetPID(const uint16_t srcport, int32_t *
{
char *ptr;
ipc_msg_hdr *hdr;
DNSServiceOp *tmp;
DNSServiceOp *tmp = NULL;
size_t len = sizeof(int32_t);
DNSServiceErrorType err = ConnectToServer(&tmp, 0, getpid_request, NULL, NULL, NULL);
if (err)
return err;
if (err) return err;
hdr = create_hdr(getpid_request, &len, &ptr, 0, tmp);
if (!hdr)
{
DNSServiceRefDeallocate(tmp);
return kDNSServiceErr_NoMemory;
}
if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
put_uint16(srcport, &ptr);
err = deliver_request(hdr, tmp); // Will free hdr for us
if (err) { DNSServiceRefDeallocate(tmp); return err; }
if (read_all(tmp->sockfd, (char*)pid, sizeof(int32_t)) < 0)
{
DNSServiceRefDeallocate(tmp);
return kDNSServiceErr_ServiceNotRunning;
}
{ DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; }
DNSServiceRefDeallocate(tmp);
return kDNSServiceErr_NoError;
@ -1275,14 +1314,15 @@ 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 &&
((interfaceIndex == kDNSServiceInterfaceIndexAny) ||
(interfaceIndex == kDNSServiceInterfaceIndexLocalOnly) ||
(interfaceIndex == kDNSServiceInterfaceIndexUnicast) ||
(interfaceIndex == kDNSServiceInterfaceIndexP2P)))
(interfaceIndex == kDNSServiceInterfaceIndexP2P) ||
(interfaceIndex == kDNSServiceInterfaceIndexBLE)))
{
return kDNSServiceErr_BadParam;
}
@ -1350,6 +1390,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;
@ -1391,6 +1434,7 @@ static void handle_addrinfo_response(DNSServiceOp *const sdr, const CallbackHead
rdlen = get_uint16(&data, end);
rdata = get_rdata (&data, end, rdlen);
ttl = get_uint32(&data, end);
(void)rrclass; // Unused
// We only generate client callbacks for A and AAAA results (including NXDOMAIN results for
// those types, if the client has requested those with the kDNSServiceFlagsReturnIntermediates).
@ -1458,7 +1502,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)
@ -1512,6 +1556,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;
@ -1540,11 +1587,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);
@ -1590,8 +1642,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*)"";
@ -1613,13 +1665,7 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister
hdr = create_hdr(reg_service_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
// If it is going over a shared connection, then don't set the IPC_FLAGS_NOREPLY
// as it affects all the operations over the shared connection. This is not
// a normal case and hence receiving the response back from the daemon and
// discarding it in ConnectionResponse is okay.
if (!(flags & kDNSServiceFlagsShareConnection) && !callBack) hdr->ipc_flags |= IPC_FLAGS_NOREPLY;
if (!callBack) hdr->ipc_flags |= IPC_FLAGS_NOREPLY;
put_flags(flags, &ptr);
put_uint32(interfaceIndex, &ptr);
@ -1659,9 +1705,13 @@ DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
size_t len;
ipc_msg_hdr *hdr;
DNSServiceErrorType err;
int f1;
int f2;
int f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0;
int f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0;
if (!sdRef || !callBack) return kDNSServiceErr_BadParam;
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 +1786,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 +1810,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 +1900,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 && rdlen) || !callBack)
{
syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with NULL parameter");
return kDNSServiceErr_BadParam;
}
if (!DNSServiceRefValid(sdRef))
{
@ -1927,8 +1985,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 && rdlen))
{
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 +2049,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 && rdlen))
{
syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with NULL parameter");
return kDNSServiceErr_BadParam;
}
if (!DNSServiceRefValid(sdRef))
{
@ -2064,12 +2129,15 @@ DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
const void *rdata
)
{
DNSServiceErrorType err;
char *ptr;
size_t len;
ipc_msg_hdr *hdr;
DNSServiceOp *tmp;
DNSServiceOp *tmp = NULL;
DNSServiceErrorType err = ConnectToServer(&tmp, flags, reconfirm_record_request, NULL, NULL, NULL);
if (!fullname || (!rdata && rdlen)) return kDNSServiceErr_BadParam;
err = ConnectToServer(&tmp, flags, reconfirm_record_request, NULL, NULL, NULL);
if (err) return err;
len = sizeof(DNSServiceFlags);

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
* Copyright (c) 2003-2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
* 3. Neither the name of Apple Inc. ("Apple") nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
* Copyright (c) 2003-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
* 3. Neither the name of Apple Inc. ("Apple") nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
@ -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
@ -88,7 +86,7 @@ extern char *win32_strerror(int inErrorCode);
# define MDNS_UDS_SERVERPATH_ENVVAR "DNSSD_UDS_PATH"
# define LISTENQ 100
// longest legal control path length
# define MAX_CTLPATH 256
# define MAX_CTLPATH (sizeof(((struct sockaddr_un*)0)->sun_path))
# define dnssd_sockaddr_t struct sockaddr_un
#endif

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2003-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.
@ -13,13 +13,6 @@
* 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.
File: mDNSDebug.c
Contains: Implementation of debugging utilities. Requires a POSIX environment.
Version: 1.0
*/
#include "mDNSDebug.h"

View File

@ -1,6 +1,6 @@
.\" -*- tab-width: 4 -*-
.\"
.\" Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved.
.\" Copyright (c) 2003-2012 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.
@ -80,9 +80,28 @@ A SIGINFO signal will dump a snapshot summary of the internal state to
.Pa /var/log/system.log Ns :
.Pp
.Dl % sudo killall -INFO mDNSResponder
.Sh OPTIONAL ARGUMENTS
.Nm
accepts the following optional arguments:
.Bl -tag -width "AlwaysAppendSearchDomains"
.It Fl AlwaysAppendSearchDomains
Append search domains for multi-labeled Partially Qualified Domain Name as well as single-labeled Partially Qualified Domain Name.
This argument is not recommended because of the extra DNS traffic it generates and its adverse effect on battery life.
.It Fl NoMulticastAdvertisements
Prevent the system from advertising Bonjour services via Multicast DNS.
.El
.Pp
To cause
.Nm
to run with these optional arguments when it launches on OS X 10.11 (El Capitan) and later, set the
.Sy AlwaysAppendSearchDomains
or
.Sy NoMulticastAdvertisements
boolean keys to true in /Library/Preferences/com.apple.mDNSResponder.plist and reboot.
.Pp
.Sh FILES
.Pa /usr/sbin/mDNSResponder \" Pathname
.\"
.Pa /usr/sbin/mDNSResponder
.Pa /Library/Preferences/com.apple.mDNSResponder.plist
.Pp
.Sh INFO
.Pp
@ -112,5 +131,5 @@ daemon first appeared in Mac OS X 10.2 (Jaguar).
Also available from the Darwin open source repository
(though not officially supported by Apple) are
.Nm
daemons for other platforms, including Mac OS 9, Microsoft Windows,
daemons for other platforms, including Microsoft Windows,
Linux, FreeBSD, NetBSD, Solaris, and other POSIX systems.

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
* Copyright (c) 2002-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.
@ -13,28 +13,214 @@
* 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.
File: uds_daemon.h
Contains: Interfaces necessary to talk to uds_daemon.c.
Version: 1.0
*/
#ifndef UDS_DAEMON_H
#define UDS_DAEMON_H
#include "mDNSEmbeddedAPI.h"
#include "dnssd_ipc.h"
/* Client request: */
// ***************************************************************************
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark -
#pragma mark - Types and Data Structures
#endif
typedef enum
{
t_uninitialized,
t_morecoming,
t_complete,
t_error,
t_terminated
} transfer_state;
typedef struct request_state request_state;
typedef void (*req_termination_fn)(request_state *request);
typedef struct registered_record_entry
{
struct registered_record_entry *next;
mDNSu32 key;
client_context_t regrec_client_context;
request_state *request;
mDNSBool external_advertise;
mDNSInterfaceID origInterfaceID;
AuthRecord *rr; // Pointer to variable-sized AuthRecord (Why a pointer? Why not just embed it here?)
} registered_record_entry;
// A single registered service: ServiceRecordSet + bookkeeping
// Note that we duplicate some fields from parent service_info object
// to facilitate cleanup, when instances and parent may be deallocated at different times.
typedef struct service_instance
{
struct service_instance *next;
request_state *request;
AuthRecord *subtypes;
mDNSBool renameonmemfree; // Set on config change when we deregister original name
mDNSBool clientnotified; // Has client been notified of successful registration yet?
mDNSBool default_local; // is this the "local." from an empty-string registration?
mDNSBool external_advertise; // is this is being advertised externally?
domainname domain;
ServiceRecordSet srs; // note -- variable-sized object -- must be last field in struct
} service_instance;
// for multi-domain default browsing
typedef struct browser_t
{
struct browser_t *next;
domainname domain;
DNSQuestion q;
} browser_t;
#ifdef _WIN32
typedef unsigned int pid_t;
typedef unsigned int socklen_t;
#endif
#if (!defined(MAXCOMLEN))
#define MAXCOMLEN 16
#endif
struct request_state
{
request_state *next;
request_state *primary; // If this operation is on a shared socket, pointer to primary
// request_state for the original DNSServiceCreateConnection() operation
dnssd_sock_t sd;
pid_t process_id; // Client's PID value
char pid_name[MAXCOMLEN]; // Client's process name
mDNSu8 uuid[UUID_SIZE];
mDNSBool validUUID;
dnssd_sock_t errsd;
mDNSu32 uid;
void * platform_data;
// Note: On a shared connection these fields in the primary structure, including hdr, are re-used
// for each new request. This is because, until we've read the ipc_msg_hdr to find out what the
// operation is, we don't know if we're going to need to allocate a new request_state or not.
transfer_state ts;
mDNSu32 hdr_bytes; // bytes of header already read
ipc_msg_hdr hdr;
mDNSu32 data_bytes; // bytes of message data already read
char *msgbuf; // pointer to data storage to pass to free()
const char *msgptr; // pointer to data to be read from (may be modified)
char *msgend; // pointer to byte after last byte of message
// reply, termination, error, and client context info
int no_reply; // don't send asynchronous replies to client
mDNSs32 time_blocked; // record time of a blocked client
int unresponsiveness_reports;
struct reply_state *replies; // corresponding (active) reply list
req_termination_fn terminate;
DNSServiceFlags flags;
mDNSu32 interfaceIndex;
union
{
registered_record_entry *reg_recs; // list of registrations for a connection-oriented request
struct
{
mDNSInterfaceID interface_id;
mDNSBool default_domain;
mDNSBool ForceMCast;
domainname regtype;
browser_t *browsers;
const mDNSu8 *AnonData;
} browser;
struct
{
mDNSInterfaceID InterfaceID;
mDNSu16 txtlen;
void *txtdata;
mDNSIPPort port;
domainlabel name;
char type_as_string[MAX_ESCAPED_DOMAIN_NAME];
domainname type;
mDNSBool default_domain;
domainname host;
mDNSBool autoname; // Set if this name is tied to the Computer Name
mDNSBool autorename; // Set if this client wants us to automatically rename on conflict
mDNSBool allowremotequery; // Respond to unicast queries from outside the local link?
int num_subtypes;
mDNSBool AnonData;
service_instance *instances;
} servicereg;
struct
{
mDNSInterfaceID interface_id;
mDNSu32 flags;
mDNSu32 protocol;
DNSQuestion q4;
DNSQuestion *q42;
DNSQuestion q6;
DNSQuestion *q62;
mDNSu8 v4ans;
mDNSu8 v6ans;
} addrinfo;
struct
{
mDNSIPPort ReqExt; // External port we originally requested, for logging purposes
NATTraversalInfo NATinfo;
} pm;
struct
{
DNSServiceFlags flags;
DNSQuestion q_all;
DNSQuestion q_default;
DNSQuestion q_autoall;
} enumeration;
struct
{
DNSQuestion q;
DNSQuestion *q2;
mDNSu8 ans;
} queryrecord;
struct
{
DNSQuestion qtxt;
DNSQuestion qsrv;
const ResourceRecord *txt;
const ResourceRecord *srv;
mDNSs32 ReportTime;
mDNSBool external_advertise;
} resolve;
} u;
};
// struct physically sits between ipc message header and call-specific fields in the message buffer
typedef struct
{
DNSServiceFlags flags; // Note: This field is in NETWORK byte order
mDNSu32 ifi; // Note: This field is in NETWORK byte order
DNSServiceErrorType error; // Note: This field is in NETWORK byte order
} reply_hdr;
typedef struct reply_state
{
struct reply_state *next; // If there are multiple unsent replies
mDNSu32 totallen;
mDNSu32 nwriten;
ipc_msg_hdr mhdr[1];
reply_hdr rhdr[1];
} reply_state;
/* Client interface: */
#define SRS_PORT(S) mDNSVal16((S)->RR_SRV.resrec.rdata->u.srv.port)
#define LogTimer(MSG,T) LogMsgNoIdent( MSG " %08X %11d %08X %11d", (T), (T), (T)-now, (T)-now)
extern int udsserver_init(dnssd_sock_t skts[], mDNSu32 count);
extern mDNSs32 udsserver_idle(mDNSs32 nextevent);
extern void udsserver_info(mDNS *const m); // print out info about current state
extern void udsserver_info(void); // print out info about current state
extern void udsserver_handle_configchange(mDNS *const m);
extern int udsserver_exit(void); // should be called prior to app exit
extern void LogMcastStateInfo(mDNS *const m, mDNSBool mflag, mDNSBool start, mDNSBool mstatelog);
extern void LogMcastStateInfo(mDNSBool mflag, mDNSBool start, mDNSBool mstatelog);
#define LogMcastQ (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMcastQuestion
#define LogMcastS (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMcastService
#define LogMcast (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMsg
@ -47,7 +233,7 @@ extern mStatus udsSupportAddFDToEventLoop(dnssd_sock_t fd, udsEventCallback call
extern int udsSupportReadFD(dnssd_sock_t fd, char* buf, int len, int flags, void *platform_data);
extern mStatus udsSupportRemoveFDFromEventLoop(dnssd_sock_t fd, void *platform_data); // Note: This also CLOSES the file descriptor as well
extern void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay);
extern void RecordUpdatedNiceLabel(mDNSs32 delay);
// Globals and functions defined in uds_daemon.c and also shared with the old "daemon.c" on OS X
@ -58,13 +244,12 @@ 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);
extern int CountPeerRegistrations(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_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags);
@ -79,7 +264,7 @@ extern void external_connection_release(const domainname *instance);
#define external_start_browsing_for_service(A,B,C,D) (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)
@ -88,3 +273,10 @@ 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
#endif /* UDS_DAEMON_H */

View File

@ -0,0 +1,400 @@
#include "CNameRecordTests.h"
#include "unittest_common.h"
mDNSlocal int InitThisUnitTest(void);
mDNSlocal int StartClientQueryRequest(void);
mDNSlocal int PopulateCacheWithClientResponseRecords(void);
mDNSlocal int SimulateNetworkChangeAndVerifyTest(void);
mDNSlocal int FinalizeUnitTest(void);
mDNSlocal mStatus AddDNSServer(void);
// This unit test's variables
static UDPSocket* local_socket;
static request_state* client_request_message;
struct UDPSocket_struct
{
mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
};
typedef struct UDPSocket_struct UDPSocket;
// This client request was generated using the following command: "dns-sd -Q 123server.dotbennu.com. A".
uint8_t query_client_msgbuf[35] = {
0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x32, 0x33, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x2e, 0x64, 0x6f, 0x74, 0x62, 0x65, 0x6e, 0x6e, 0x75, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00,
0x01, 0x00, 0x01
};
// This uDNS message is a canned response that was originally captured by wireshark.
uint8_t query_response_msgbuf[108] = {
0x69, 0x41, // transaction id
0x85, 0x80, // flags
0x00, 0x01, // 1 question for 123server.dotbennu.com. Addr
0x00, 0x02, // 2 anwsers: 123server.dotbennu.com. CNAME test212.dotbennu.com., test212.dotbennu.com. Addr 10.100.0.1,
0x00, 0x01, // 1 authorities anwser: dotbennu.com. NS cardinal2.apple.com.
0x00, 0x00, 0x09, 0x31, 0x32, 0x33,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x08, 0x64, 0x6f, 0x74, 0x62, 0x65, 0x6e, 0x6e, 0x75, 0x03,
0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00,
0x02, 0x56, 0x00, 0x0a, 0x07, 0x74, 0x65, 0x73, 0x74, 0x32, 0x31, 0x32, 0xc0, 0x16, 0xc0, 0x34,
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x04, 0x0a, 0x64, 0x00, 0x01, 0xc0, 0x16,
0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x51, 0x80, 0x00, 0x12, 0x09, 0x63, 0x61, 0x72, 0x64, 0x69,
0x6e, 0x61, 0x6c, 0x32, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x65, 0xc0, 0x1f
};
// Variables associated with contents of the above uDNS message
#define uDNS_TargetQID 16745
char udns_original_domainname_cstr[] = "123server.dotbennu.com.";
char udns_cname_domainname_cstr[] = "test212.dotbennu.com.";
static const mDNSv4Addr dns_response_ipv4 = {{ 10, 100, 0, 1 }};
UNITTEST_HEADER(CNameRecordTests)
UNITTEST_TEST(InitThisUnitTest)
UNITTEST_TEST(StartClientQueryRequest)
UNITTEST_TEST(PopulateCacheWithClientResponseRecords)
UNITTEST_TEST(SimulateNetworkChangeAndVerifyTest)
UNITTEST_TEST(FinalizeUnitTest)
UNITTEST_FOOTER
// The InitThisUnitTest() initializes the mDNSResponder environment as well as
// a DNSServer. It also allocates memory for a local_socket and client request.
// Note: This unit test does not send packets on the wire and it does not open sockets.
UNITTEST_HEADER(InitThisUnitTest)
// Init unit test environment and verify no error occurred.
mStatus result = init_mdns_environment(mDNStrue);
UNITTEST_ASSERT(result == mStatus_NoError);
// Add one DNS server and verify it was added.
AddDNSServer();
UNITTEST_ASSERT(NumUnicastDNSServers == 1);
// Create memory for a socket that is never used or opened.
local_socket = mDNSPlatformMemAllocate(sizeof(UDPSocket));
mDNSPlatformMemZero(local_socket, sizeof(UDPSocket));
// Create memory for a request that is used to make this unit test's client request.
client_request_message = calloc(1, sizeof(request_state));
UNITTEST_FOOTER
// This test simulates a uds client request by setting up a client request and then
// calling mDNSResponder's handle_client_request. The handle_client_request function
// processes the request and starts a query. This unit test verifies
// the client request and query were setup as expected. This unit test also calls
// mDNS_execute which determines the cache does not contain the new question's
// answer.
UNITTEST_HEADER(StartClientQueryRequest)
mDNS *const m = &mDNSStorage;
request_state* req = client_request_message;
char *msgptr = (char *)query_client_msgbuf;
size_t msgsz = sizeof(query_client_msgbuf);
mDNSs32 min_size = sizeof(DNSServiceFlags) + sizeof(mDNSu32) + 4;
DNSQuestion *q;
mStatus err = mStatus_NoError;
char qname_cstr[MAX_ESCAPED_DOMAIN_NAME];
// Process the unit test's client request
start_client_request(req, msgptr, msgsz, query_request, local_socket);
UNITTEST_ASSERT(err == mStatus_NoError);
// Verify the request fields were set as expected
UNITTEST_ASSERT(req->next == mDNSNULL);
UNITTEST_ASSERT(req->primary == mDNSNULL);
UNITTEST_ASSERT(req->sd == client_req_sd);
UNITTEST_ASSERT(req->process_id == client_req_process_id);
UNITTEST_ASSERT(!strcmp(req->pid_name, client_req_pid_name));
UNITTEST_ASSERT(req->validUUID == mDNSfalse);
UNITTEST_ASSERT(req->errsd == 0);
UNITTEST_ASSERT(req->uid == client_req_uid);
UNITTEST_ASSERT(req->ts == t_complete);
UNITTEST_ASSERT((mDNSs32)req->data_bytes > min_size);
UNITTEST_ASSERT(req->msgend == msgptr+msgsz);
UNITTEST_ASSERT(req->msgbuf == mDNSNULL);
UNITTEST_ASSERT(req->hdr.version == VERSION);
UNITTEST_ASSERT(req->replies == mDNSNULL);
UNITTEST_ASSERT(req->terminate != mDNSNULL);
UNITTEST_ASSERT(req->flags == kDNSServiceFlagsReturnIntermediates);
UNITTEST_ASSERT(req->interfaceIndex == kDNSServiceInterfaceIndexAny);
// Verify the query fields were set as expected
q = &req->u.queryrecord.q;
UNITTEST_ASSERT(q != mDNSNULL);
UNITTEST_ASSERT(q == m->Questions);
UNITTEST_ASSERT(q == m->NewQuestions);
UNITTEST_ASSERT(q->SuppressUnusable == mDNSfalse);
UNITTEST_ASSERT(q->ReturnIntermed == mDNStrue);
UNITTEST_ASSERT(q->SuppressQuery == mDNSfalse);
UNITTEST_ASSERT(q->qnameOrig == mDNSNULL);
ConvertDomainNameToCString(&q->qname, qname_cstr);
UNITTEST_ASSERT(!strcmp(qname_cstr, udns_original_domainname_cstr));
UNITTEST_ASSERT(q->qnamehash == DomainNameHashValue(&q->qname));
UNITTEST_ASSERT(q->InterfaceID == mDNSInterface_Any);
UNITTEST_ASSERT(q->flags == req->flags);
UNITTEST_ASSERT(q->qtype == 1);
UNITTEST_ASSERT(q->qclass == 1);
UNITTEST_ASSERT(q->LongLived == 0);
UNITTEST_ASSERT(q->ExpectUnique == mDNSfalse);
UNITTEST_ASSERT(q->ForceMCast == 0);
UNITTEST_ASSERT(q->TimeoutQuestion == 0);
UNITTEST_ASSERT(q->WakeOnResolve == 0);
UNITTEST_ASSERT(q->UseBackgroundTrafficClass == 0);
UNITTEST_ASSERT(q->ValidationRequired == 0);
UNITTEST_ASSERT(q->ValidatingResponse == 0);
UNITTEST_ASSERT(q->ProxyQuestion == 0);
UNITTEST_ASSERT(q->AnonInfo == mDNSNULL);
UNITTEST_ASSERT(q->QuestionCallback != mDNSNULL);
UNITTEST_ASSERT(q->QuestionContext == req);
UNITTEST_ASSERT(q->SearchListIndex == 0);
UNITTEST_ASSERT(q->DNSSECAuthInfo == mDNSNULL);
UNITTEST_ASSERT(q->DAIFreeCallback == mDNSNULL);
UNITTEST_ASSERT(q->RetryWithSearchDomains == 0);
UNITTEST_ASSERT(q->AppendSearchDomains == 0);
UNITTEST_ASSERT(q->AppendLocalSearchDomains == 0);
UNITTEST_ASSERT(q->DuplicateOf == mDNSNULL);
// Call mDNS_Execute to see if the new question, q, has an answer in the cache.
// It won't be yet because the cache is empty.
m->NextScheduledEvent = mDNS_TimeNow_NoLock(m);
mDNS_Execute(m);
// Verify mDNS_Execute processed the new question.
UNITTEST_ASSERT(m->NewQuestions == mDNSNULL);
// Verify the cache is empty and the request got no reply.
UNITTEST_ASSERT(m->rrcache_totalused == 0);
UNITTEST_ASSERT(req->replies == mDNSNULL);
UNITTEST_FOOTER
// This unit test receives a canned uDNS response message by calling the mDNSCoreReceive() function.
// It then verifies cache entries were added for the CNAME and A records that were contained in the
// answers of the canned response, query_response_msgbuf. This unit test also verifies that
// 2 add events were generated for the client.
UNITTEST_HEADER(PopulateCacheWithClientResponseRecords)
mDNS *const m = &mDNSStorage;
DNSMessage *msgptr = (DNSMessage *)query_response_msgbuf;
size_t msgsz = sizeof(query_response_msgbuf);
struct reply_state *reply;
request_state* req = client_request_message;
DNSQuestion *q = &req->u.queryrecord.q;
const char *data;
const char *end;
char name[kDNSServiceMaxDomainName];
uint16_t rrtype, rrclass, rdlen;
const char *rdata;
size_t len;
char domainname_cstr[MAX_ESCAPED_DOMAIN_NAME];
// Receive and populate the cache with canned response
receive_response(req, msgptr, msgsz);
// Verify 2 cache entries for CName and A record are present
mDNSu32 CacheUsed =0, notUsed =0;
LogCacheRecords_ut(mDNS_TimeNow(m), &CacheUsed, &notUsed);
UNITTEST_ASSERT(CacheUsed == m->rrcache_totalused);
UNITTEST_ASSERT(CacheUsed == 4); // 2 for the CacheGroup object plus 2 for the A and CNAME records
UNITTEST_ASSERT(m->PktNum == 1); // one packet was received
// Verify question's qname is now set with the A record's domainname
UNITTEST_ASSERT(q->qnameOrig == mDNSNULL);
ConvertDomainNameToCString(&q->qname, domainname_cstr);
UNITTEST_ASSERT(q->qnamehash == DomainNameHashValue(&q->qname));
UNITTEST_ASSERT(!strcmp(domainname_cstr, udns_cname_domainname_cstr));
// Verify client's add event for CNAME is properly formed
reply = req->replies;
UNITTEST_ASSERT(reply != mDNSNULL);
UNITTEST_ASSERT(reply->next == mDNSNULL);
data = (char *)&reply->rhdr[1];
end = data+reply->totallen;
get_string(&data, data+reply->totallen, name, kDNSServiceMaxDomainName);
rrtype = get_uint16(&data, end);
rrclass = get_uint16(&data, end);
rdlen = get_uint16(&data, end);
rdata = get_rdata(&data, end, rdlen);
len = get_reply_len(name, rdlen);
UNITTEST_ASSERT(reply->totallen == len + sizeof(ipc_msg_hdr));
UNITTEST_ASSERT(reply->mhdr->version == VERSION);
UNITTEST_ASSERT(reply->mhdr->datalen == len);
UNITTEST_ASSERT(reply->mhdr->ipc_flags == 0);
UNITTEST_ASSERT(reply->mhdr->op == query_reply_op);
UNITTEST_ASSERT(reply->rhdr->flags == htonl(kDNSServiceFlagsAdd));
UNITTEST_ASSERT(reply->rhdr->ifi == kDNSServiceInterfaceIndexAny);
UNITTEST_ASSERT(reply->rhdr->error == kDNSServiceErr_NoError);
UNITTEST_ASSERT(rrtype == kDNSType_CNAME);
UNITTEST_ASSERT(rrclass == kDNSClass_IN);
ConvertDomainNameToCString((const domainname *const)rdata, domainname_cstr);
UNITTEST_ASSERT(!strcmp(domainname_cstr, "test212.dotbennu.com."));
// The mDNS_Execute call generates an add event for the A record
m->NextScheduledEvent = mDNS_TimeNow_NoLock(m);
mDNS_Execute(m);
// Verify the client's reply contains a properly formed add event for the A record.
reply = req->replies;
UNITTEST_ASSERT(reply != mDNSNULL);
UNITTEST_ASSERT(reply->next != mDNSNULL);
reply = reply->next;
data = (char *)&reply->rhdr[1];
end = data+reply->totallen;
get_string(&data, data+reply->totallen, name, kDNSServiceMaxDomainName);
rrtype = get_uint16(&data, end);
rrclass = get_uint16(&data, end);
rdlen = get_uint16(&data, end);
rdata = get_rdata(&data, end, rdlen);
len = get_reply_len(name, rdlen);
UNITTEST_ASSERT(reply->totallen == len + sizeof(ipc_msg_hdr));
UNITTEST_ASSERT(reply->mhdr->version == VERSION);
UNITTEST_ASSERT(reply->mhdr->datalen == len);
UNITTEST_ASSERT(reply->mhdr->ipc_flags == 0);
UNITTEST_ASSERT(reply->mhdr->op == query_reply_op);
UNITTEST_ASSERT(reply->rhdr->flags == htonl(kDNSServiceFlagsAdd));
UNITTEST_ASSERT(reply->rhdr->ifi == kDNSServiceInterfaceIndexAny);
UNITTEST_ASSERT(reply->rhdr->error == kDNSServiceErr_NoError);
UNITTEST_ASSERT(rrtype == kDNSType_A);
UNITTEST_ASSERT(rrclass == kDNSClass_IN);
UNITTEST_ASSERT(rdata[0] == dns_response_ipv4.b[0]);
UNITTEST_ASSERT(rdata[1] == dns_response_ipv4.b[1]);
UNITTEST_ASSERT(rdata[2] == dns_response_ipv4.b[2]);
UNITTEST_ASSERT(rdata[3] == dns_response_ipv4.b[3]);
UNITTEST_FOOTER
// This function verifies the cache and event handling occurred as expected when a network change happened.
// The uDNS_SetupDNSConfig is called to simulate a network change and two outcomes occur. First the A record
// query is restarted and sent to a new DNS server. Second the cache records are purged. Then mDNS_Execute
// is called and it removes the purged cache records and generates a remove event for the A record.
// The following are verified:
// 1.) The restart of query for A record.
// 2.) The cache is empty after mDNS_Execute removes the cache entres.
// 3.) The remove event is verified by examining the request's reply data.
UNITTEST_HEADER(SimulateNetworkChangeAndVerifyTest)
mDNS *const m = &mDNSStorage;
request_state* req = client_request_message;
DNSQuestion* q = &req->u.queryrecord.q;
mDNSu32 CacheUsed =0, notUsed =0;
const char *data; const char *end;
char name[kDNSServiceMaxDomainName];
uint16_t rrtype, rrclass, rdlen;
const char *rdata;
size_t len;
// The uDNS_SetupDNSConfig reconfigures the resolvers so the A record query is restarted and
// both the CNAME and A record are purged.
uDNS_SetupDNSConfig(m);
// Verify the A record query was restarted. This is done indirectly by noticing the transaction id and interval have changed.
UNITTEST_ASSERT(q->ThisQInterval == InitialQuestionInterval);
UNITTEST_ASSERT(q->TargetQID.NotAnInteger != uDNS_TargetQID);
// Then mDNS_Execute removes both records from the cache and calls the client back with a remove event for A record.
m->NextScheduledEvent = mDNS_TimeNow_NoLock(m);
mDNS_Execute(m);
// Verify the cache entries are removed
LogCacheRecords_ut(mDNS_TimeNow(m), &CacheUsed, &notUsed);
UNITTEST_ASSERT(CacheUsed == m->rrcache_totalused);
UNITTEST_ASSERT(CacheUsed == 0);
// Verify the A record's remove event is setup as expected in the reply data
struct reply_state *reply;
reply = req->replies;
UNITTEST_ASSERT(reply != mDNSNULL);
UNITTEST_ASSERT(reply != mDNSNULL);
UNITTEST_ASSERT(reply->next != mDNSNULL);
UNITTEST_ASSERT(reply->next->next != mDNSNULL);
reply = reply->next->next; // Get to last event to verify remove event
data = (char *)&reply->rhdr[1];
end = data+reply->totallen;
get_string(&data, data+reply->totallen, name, kDNSServiceMaxDomainName);
rrtype = get_uint16(&data, end);
rrclass = get_uint16(&data, end);
rdlen = get_uint16(&data, end);
rdata = get_rdata(&data, end, rdlen);
len = get_reply_len(name, rdlen);
UNITTEST_ASSERT(reply->totallen == reply->mhdr->datalen + sizeof(ipc_msg_hdr));
UNITTEST_ASSERT(reply->mhdr->version == VERSION);
UNITTEST_ASSERT(reply->mhdr->datalen == len);
UNITTEST_ASSERT(reply->mhdr->ipc_flags == 0);
UNITTEST_ASSERT(reply->mhdr->op == query_reply_op);
UNITTEST_ASSERT(reply->rhdr->flags != htonl(kDNSServiceFlagsAdd));
UNITTEST_ASSERT(reply->rhdr->ifi == kDNSServiceInterfaceIndexAny);
UNITTEST_ASSERT(reply->rhdr->error == kDNSServiceErr_NoError);
UNITTEST_ASSERT(rrtype == kDNSType_A);
UNITTEST_ASSERT(rrclass == kDNSClass_IN);
UNITTEST_ASSERT(rdata[0] == dns_response_ipv4.b[0]);
UNITTEST_ASSERT(rdata[1] == dns_response_ipv4.b[1]);
UNITTEST_ASSERT(rdata[2] == dns_response_ipv4.b[2]);
UNITTEST_ASSERT(rdata[3] == dns_response_ipv4.b[3]);
UNITTEST_FOOTER
// This function does memory cleanup and no verification.
UNITTEST_HEADER(FinalizeUnitTest)
mDNS *m = &mDNSStorage;
request_state* req = client_request_message;
DNSServer *ptr, **p = &m->DNSServers;
while (req->replies)
{
reply_state *reply = req->replies;
req->replies = req->replies->next;
mDNSPlatformMemFree(reply);
}
mDNSPlatformMemFree(req);
mDNSPlatformMemFree(local_socket);
while (*p)
{
ptr = *p;
*p = (*p)->next;
LogInfo("FinalizeUnitTest: Deleting server %p %#a:%d (%##s)", ptr, &ptr->addr, mDNSVal16(ptr->port), ptr->domain.c);
mDNSPlatformMemFree(ptr);
}
UNITTEST_FOOTER
// The mDNS_AddDNSServer function adds a dns server to mDNSResponder's list.
mDNSlocal mStatus AddDNSServer(void)
{
mDNS *m = &mDNSStorage;
m->timenow = 0;
mDNS_Lock(m);
domainname d;
mDNSAddr addr;
mDNSIPPort port;
mDNSs32 serviceID = 0;
mDNSu32 scoped = 0;
mDNSu32 timeout = dns_server_timeout;
mDNSBool cellIntf = 0;
mDNSBool isExpensive = 0;
mDNSu16 resGroupID = dns_server_resGroupID;
mDNSBool reqA = mDNStrue;
mDNSBool reqAAAA = mDNStrue;
mDNSBool reqDO = mDNSfalse;
d.c[0] = 0;
addr.type = mDNSAddrType_IPv4;
addr.ip.v4.NotAnInteger = dns_server_ipv4.NotAnInteger;
port.NotAnInteger = client_resp_src_port;
mDNS_AddDNSServer(m, &d, primary_interfaceID, serviceID, &addr, port, scoped, timeout,
cellIntf, isExpensive, resGroupID,
reqA, reqAAAA, reqDO);
mDNS_Unlock(m);
return mStatus_NoError;
}

View File

@ -0,0 +1,9 @@
#ifndef ReconfirmRecordTests_h
#define ReconfirmRecordTests_h
#include "unittest.h"
int CNameRecordTests(void);
#endif /* ReconfirmRecordTests_h */

View File

@ -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

View File

@ -0,0 +1,8 @@
#ifndef DNSMessageTest_h
#define DNSMessageTest_h
#include "unittest.h"
int DNSMessageTest(void);
#endif /* DNSMessageTest_h */

View File

@ -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

View File

@ -0,0 +1,7 @@
#ifndef DomainNameTest_h
#define DomainNameTest_h
#include "unittest.h"
int DomainNameTest(void);
#endif /* DomainNameTest_h */

View File

@ -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

View File

@ -0,0 +1,9 @@
#ifndef InterfaceTest_h
#define InterfaceTest_h
#include "unittest.h"
int InterfaceTest(void);
#endif /* InterfaceTest_h */

View File

@ -0,0 +1,378 @@
#include "LocalOnlyTimeoutTests.h"
#include "unittest_common.h"
mDNSlocal int InitUnitTest(void);
mDNSlocal int StartLocalOnlyClientQueryRequest(void);
mDNSlocal int PopulateCacheWithClientLOResponseRecords(void);
mDNSlocal int RestartLocalOnlyClientQueryRequest(void);
mDNSlocal int FinalizeUnitTest(void);
mDNSlocal mStatus InitEtcHostsRecords();
// This unit test's variables
static request_state* client_request_message;
static UDPSocket* local_socket;
static char domainname_cstr[MAX_ESCAPED_DOMAIN_NAME];
// This query request message was generated from the following command: "dns-sd -lo -timeout -Q cardinal2.apple.com. A"
char query_req_msgbuf[33]= {
0x00, 0x01, 0x90, 0x00,
// DNSServiceFlags.L = (kDNSServiceFlagsReturnIntermediates |kDNSServiceFlagsSuppressUnusable | kDNSServiceFlagsTimeout)
0xff, 0xff, 0xff, 0xff,
// interfaceIndex = mDNSInterface_LocalOnly
0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c,
0x32, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x00, 0x00, 0x01, 0x00,
0x01
};
UNITTEST_HEADER(LocalOnlyTimeoutTests)
UNITTEST_TEST(InitUnitTest)
UNITTEST_TEST(StartLocalOnlyClientQueryRequest)
UNITTEST_TEST(PopulateCacheWithClientLOResponseRecords)
UNITTEST_TEST(RestartLocalOnlyClientQueryRequest)
UNITTEST_TEST(FinalizeUnitTest)
UNITTEST_FOOTER
// The InitUnitTest() initializes a minimal mDNSResponder environment as
// well as allocates memory for a local_socket and client request.
// It also sets the domainname_cstr specified in the client's query request.
// Note: This unit test does not send packets on the wire and it does not open sockets.
UNITTEST_HEADER(InitUnitTest)
// Init mDNSStorage
mStatus result = init_mdns_storage();
if (result != mStatus_NoError)
return result;
// Allocate a client request
local_socket = calloc(1, sizeof(request_state));
// Allocate memory for a request that is used to make client requests.
client_request_message = calloc(1, sizeof(request_state));
// Init domainname that is used by unit tests
strlcpy(domainname_cstr, "cardinal2.apple.com.", sizeof(domainname_cstr));
UNITTEST_FOOTER
// This unit test starts a local only request for "cardinal2.apple.com.". It first
// calls start_client_request to start a query, it then verifies the
// req and query data structures are set as expected. Next, the cache is verified to
// be empty by AnswerNewLocalOnlyQuestion() and so results in GenerateNegativeResponse()
// getting called which sets up a reply with a negative answer in it for the client.
// On return from mDNS_Execute, the client's reply structure is verified to be set as
// expected. Lastly the timeout is simulated and mDNS_Execute is called. This results
// in a call to TimeoutQuestions(). And again, the GenerateNegativeResponse() is called
// which returns a negative response to the client. This time the client reply is verified
// to be setup with a timeout result.
UNITTEST_HEADER(StartLocalOnlyClientQueryRequest)
mDNS *const m = &mDNSStorage;
request_state* req = client_request_message;
char *msgptr = (char *)query_req_msgbuf;
size_t msgsz = sizeof(query_req_msgbuf);
DNSQuestion *q;
mDNSs32 min_size = sizeof(DNSServiceFlags) + sizeof(mDNSu32) + 4;
mStatus err = mStatus_NoError;
char qname_cstr[MAX_ESCAPED_DOMAIN_NAME];
struct reply_state *reply;
size_t len;
// Process the unit test's client request
start_client_request(req, msgptr, msgsz, query_request, local_socket);
UNITTEST_ASSERT(err == mStatus_NoError);
// Verify the query initialized and request fields were set as expected
UNITTEST_ASSERT(err == mStatus_NoError);
UNITTEST_ASSERT(req->hdr.version == VERSION);
UNITTEST_ASSERT((mDNSs32)req->data_bytes > min_size);
UNITTEST_ASSERT(req->flags == (kDNSServiceFlagsSuppressUnusable | kDNSServiceFlagsReturnIntermediates | kDNSServiceFlagsTimeout));
UNITTEST_ASSERT(req->interfaceIndex == kDNSServiceInterfaceIndexLocalOnly);
UNITTEST_ASSERT(req->terminate != mDNSNULL);
q = &req->u.queryrecord.q;
UNITTEST_ASSERT(q == m->NewLocalOnlyQuestions);
UNITTEST_ASSERT(m->Questions == NULL);
UNITTEST_ASSERT(m->NewQuestions == NULL);
UNITTEST_ASSERT(q->SuppressUnusable == 1);
UNITTEST_ASSERT(q->ReturnIntermed == 1);
UNITTEST_ASSERT(q->SuppressQuery == 0); // Regress <rdar://problem/27571734>
UNITTEST_ASSERT(q->qnameOrig == mDNSNULL);
ConvertDomainNameToCString(&q->qname, qname_cstr);
UNITTEST_ASSERT(!strcmp(qname_cstr, domainname_cstr));
UNITTEST_ASSERT(q->qnamehash == DomainNameHashValue(&q->qname));
UNITTEST_ASSERT(q->InterfaceID == mDNSInterface_LocalOnly);
UNITTEST_ASSERT(q->flags == req->flags);
UNITTEST_ASSERT(q->qtype == 1);
UNITTEST_ASSERT(q->qclass == 1);
UNITTEST_ASSERT(q->LongLived == 0);
UNITTEST_ASSERT(q->ExpectUnique == mDNSfalse);
UNITTEST_ASSERT(q->ForceMCast == 0);
UNITTEST_ASSERT(q->TimeoutQuestion == 1);
UNITTEST_ASSERT(q->WakeOnResolve == 0);
UNITTEST_ASSERT(q->UseBackgroundTrafficClass == 0);
UNITTEST_ASSERT(q->ValidationRequired == 0);
UNITTEST_ASSERT(q->ValidatingResponse == 0);
UNITTEST_ASSERT(q->ProxyQuestion == 0);
UNITTEST_ASSERT(q->AnonInfo == mDNSNULL);
UNITTEST_ASSERT(q->QuestionCallback != mDNSNULL);
UNITTEST_ASSERT(q->QuestionContext == req);
UNITTEST_ASSERT(q->SearchListIndex == 0);
UNITTEST_ASSERT(q->DNSSECAuthInfo == mDNSNULL);
UNITTEST_ASSERT(q->DAIFreeCallback == mDNSNULL);
UNITTEST_ASSERT(q->RetryWithSearchDomains == 0);
UNITTEST_ASSERT(q->StopTime != 0);
UNITTEST_ASSERT(q->AppendSearchDomains == 0);
UNITTEST_ASSERT(q->AppendLocalSearchDomains == 0);
UNITTEST_ASSERT(q->DuplicateOf == mDNSNULL);
// At this point the the cache is empty. Calling mDNS_Execute will answer the local-only
// question with a negative response.
m->NextScheduledEvent = mDNS_TimeNow_NoLock(m);
mDNS_Execute(m); // Regress <rdar://problem/28721294>
// Verify reply is a negative response and error code is set to kDNSServiceErr_NoSuchRecord error.
reply = req->replies;
UNITTEST_ASSERT(reply != mDNSNULL);
UNITTEST_ASSERT(m->NewLocalOnlyQuestions == NULL);
UNITTEST_ASSERT(q->LOAddressAnswers == 0);
len = get_reply_len(qname_cstr, 0);
UNITTEST_ASSERT(reply->next == mDNSNULL);
UNITTEST_ASSERT(reply->totallen == reply->mhdr->datalen + sizeof(ipc_msg_hdr));
UNITTEST_ASSERT(reply->mhdr->version == VERSION);
UNITTEST_ASSERT(reply->mhdr->datalen == len);
UNITTEST_ASSERT(reply->mhdr->ipc_flags == 0);
UNITTEST_ASSERT(reply->mhdr->op == query_reply_op);
UNITTEST_ASSERT(reply->rhdr->flags == htonl(kDNSServiceFlagsAdd));
UNITTEST_ASSERT(reply->rhdr->ifi == kDNSServiceInterfaceIndexLocalOnly); // Regress <rdar://problem/27340874>
UNITTEST_ASSERT(reply->rhdr->error ==
(DNSServiceErrorType)htonl(kDNSServiceErr_NoSuchRecord)); // Regress <rdar://problem/24827555>
// Simulate what udsserver_idle normally does for clean up
freeL("StartLocalOnlyClientQueryRequest:reply", reply);
req->replies = NULL;
// Simulate the query time out of the local-only question.
// The expected behavior is a negative answer with time out error
m->NextScheduledEvent = mDNS_TimeNow_NoLock(m);
q->StopTime = mDNS_TimeNow_NoLock(m);
m->NextScheduledStopTime -= mDNSPlatformOneSecond*5;
mDNS_Execute(m);
// Verify the reply is a negative response with timeout error.
reply = req->replies;
UNITTEST_ASSERT(reply != NULL);
UNITTEST_ASSERT(m->NewLocalOnlyQuestions == NULL);
UNITTEST_ASSERT(q->LOAddressAnswers == 0);
len = get_reply_len(qname_cstr, 0);
UNITTEST_ASSERT(reply->next == mDNSNULL);
UNITTEST_ASSERT(reply->totallen == len + sizeof(ipc_msg_hdr));
UNITTEST_ASSERT(reply->mhdr->version == VERSION);
UNITTEST_ASSERT(reply->mhdr->datalen == len);
UNITTEST_ASSERT(reply->mhdr->ipc_flags == 0);
UNITTEST_ASSERT(reply->mhdr->op == query_reply_op);
UNITTEST_ASSERT(reply->rhdr->flags == htonl(kDNSServiceFlagsAdd));
UNITTEST_ASSERT(reply->rhdr->ifi == kDNSServiceInterfaceIndexLocalOnly); // Regress <rdar://problem/27340874>
UNITTEST_ASSERT(reply->rhdr->error ==
(DNSServiceErrorType)htonl(kDNSServiceErr_Timeout)); // Regress <rdar://problem/27562965>
// Free request and reallocate to use when query is restarted
free_req(req);
client_request_message = calloc(1, sizeof(request_state));
UNITTEST_FOOTER
// This unit test populates the cache with four /etc/hosts records and then
// verifies there are four entries in the cache.
UNITTEST_HEADER(PopulateCacheWithClientLOResponseRecords)
mDNS *const m = &mDNSStorage;
// Verify cache is empty
int count = LogEtcHosts_ut(m);
UNITTEST_ASSERT(count == 0);
// Populate /etc/hosts
mStatus result = InitEtcHostsRecords();
UNITTEST_ASSERT(result == mStatus_NoError);
// mDNS_Execute is called to populate the /etc/hosts cache.
m->NextScheduledEvent = mDNS_TimeNow_NoLock(m);
mDNS_Execute(m);
count = LogEtcHosts_ut(m);
UNITTEST_ASSERT(count == 4);
UNITTEST_FOOTER
// This unit test starts a local only request for "cardinal2.apple.com.". It first
// calls start_client_request to start a query, it then verifies the
// req and query data structures are set as expected. Next, the cache is verified to
// contain the answer by AnswerNewLocalOnlyQuestion() and so results in setting up an
// answer reply to the client. On return from mDNS_Execute, the client's reply structure
// is verified to be set as expected. Lastly the timeout is simulated and mDNS_Execute is
// called. This results in a call to TimeoutQuestions(). And this time, the
// GenerateNegativeResponse() is called which returns a negative response to the client
// which specifies the timeout occurred. Again, the answer reply is verified to
// to specify a timeout.
UNITTEST_HEADER(RestartLocalOnlyClientQueryRequest)
mDNS *const m = &mDNSStorage;
request_state* req = client_request_message;
char *msgptr = (char *)query_req_msgbuf;
size_t msgsz = sizeof(query_req_msgbuf); DNSQuestion *q;
mDNSs32 min_size = sizeof(DNSServiceFlags) + sizeof(mDNSu32) + 4;
mStatus err = mStatus_NoError;
char qname_cstr[MAX_ESCAPED_DOMAIN_NAME];
struct reply_state *reply;
size_t len;
// Process the unit test's client request
start_client_request(req, msgptr, msgsz, query_request, local_socket);
UNITTEST_ASSERT(err == mStatus_NoError);
UNITTEST_ASSERT(err == mStatus_NoError);
UNITTEST_ASSERT(req->hdr.version == VERSION);
UNITTEST_ASSERT((mDNSs32)req->data_bytes > min_size);
UNITTEST_ASSERT(req->flags == (kDNSServiceFlagsSuppressUnusable | kDNSServiceFlagsReturnIntermediates | kDNSServiceFlagsTimeout));
UNITTEST_ASSERT(req->interfaceIndex == kDNSServiceInterfaceIndexLocalOnly);
UNITTEST_ASSERT(req->terminate != mDNSNULL);
UNITTEST_ASSERT(m->Questions == NULL);
q = &req->u.queryrecord.q;
UNITTEST_ASSERT(q == m->NewLocalOnlyQuestions);
UNITTEST_ASSERT(q->SuppressUnusable == 1);
UNITTEST_ASSERT(q->ReturnIntermed == 1);
UNITTEST_ASSERT(q->SuppressQuery == 0); // Regress <rdar://problem/27571734>
UNITTEST_ASSERT(q->qnamehash == DomainNameHashValue(&q->qname));
UNITTEST_ASSERT(q->InterfaceID == mDNSInterface_LocalOnly);
UNITTEST_ASSERT(q->flags == req->flags);
UNITTEST_ASSERT(q->qtype == 1);
UNITTEST_ASSERT(q->qclass == 1);
UNITTEST_ASSERT(q->LongLived == 0);
UNITTEST_ASSERT(q->ExpectUnique == mDNSfalse);
UNITTEST_ASSERT(q->ForceMCast == 0);
UNITTEST_ASSERT(q->TimeoutQuestion == 1);
UNITTEST_ASSERT(q->WakeOnResolve == 0);
UNITTEST_ASSERT(q->UseBackgroundTrafficClass == 0);
UNITTEST_ASSERT(q->ValidationRequired == 0);
UNITTEST_ASSERT(q->ValidatingResponse == 0);
UNITTEST_ASSERT(q->ProxyQuestion == 0);
UNITTEST_ASSERT(q->AnonInfo == mDNSNULL);
UNITTEST_ASSERT(q->QuestionCallback != mDNSNULL);
UNITTEST_ASSERT(q->QuestionContext == req);
UNITTEST_ASSERT(q->SearchListIndex == 0);
UNITTEST_ASSERT(q->DNSSECAuthInfo == mDNSNULL);
UNITTEST_ASSERT(q->DAIFreeCallback == mDNSNULL);
UNITTEST_ASSERT(q->RetryWithSearchDomains == 0);
UNITTEST_ASSERT(q->StopTime != 0);
UNITTEST_ASSERT(q->AppendSearchDomains == 0);
UNITTEST_ASSERT(q->AppendLocalSearchDomains == 0);
UNITTEST_ASSERT(q->DuplicateOf == mDNSNULL);
ConvertDomainNameToCString(&q->qname, qname_cstr);
UNITTEST_ASSERT(!strcmp(qname_cstr, domainname_cstr));
// Answer local-only question with found cache entry
m->NextScheduledEvent = mDNS_TimeNow_NoLock(m);
mDNS_Execute(m); // Regress <rdar://problem/28721294>
UNITTEST_ASSERT(m->NewLocalOnlyQuestions == NULL);
UNITTEST_ASSERT(req->u.queryrecord.ans == 1);
UNITTEST_ASSERT(q->LOAddressAnswers == 1);
UNITTEST_ASSERT(q == m->LocalOnlyQuestions);
reply = req->replies;
len = get_reply_len(qname_cstr, 4);
UNITTEST_ASSERT(reply->next == mDNSNULL);
UNITTEST_ASSERT(reply->totallen == len + sizeof(ipc_msg_hdr));
UNITTEST_ASSERT(reply->mhdr->version == VERSION);
UNITTEST_ASSERT(reply->mhdr->datalen == len);
UNITTEST_ASSERT(reply->mhdr->ipc_flags == 0);
UNITTEST_ASSERT(reply->mhdr->op == query_reply_op);
UNITTEST_ASSERT(reply->rhdr->flags == htonl(kDNSServiceFlagsAdd));
UNITTEST_ASSERT(reply->rhdr->ifi == kDNSServiceInterfaceIndexLocalOnly); // Regress <rdar://problem/27340874>
UNITTEST_ASSERT(reply->rhdr->error == kDNSServiceErr_NoError);
// Simulate the query time out of the local-only question.
// The expected behavior is a negative answer with time out error
m->NextScheduledEvent = mDNS_TimeNow_NoLock(m);
q->StopTime = mDNS_TimeNow_NoLock(m);
m->NextScheduledStopTime -= mDNSPlatformOneSecond*5;
mDNS_Execute(m);
reply = req->replies->next;
UNITTEST_ASSERT(reply != NULL);
UNITTEST_ASSERT(reply->next == NULL);
UNITTEST_ASSERT(m->NewLocalOnlyQuestions == NULL);
UNITTEST_ASSERT(q->LOAddressAnswers == 0);
len = get_reply_len(qname_cstr, 0);
UNITTEST_ASSERT(reply->next == mDNSNULL);
UNITTEST_ASSERT(reply->totallen == len + + sizeof(ipc_msg_hdr));
UNITTEST_ASSERT(reply->mhdr->version == VERSION);
UNITTEST_ASSERT(reply->mhdr->datalen == len);
UNITTEST_ASSERT(reply->mhdr->ipc_flags == 0);
UNITTEST_ASSERT(reply->mhdr->op == query_reply_op);
UNITTEST_ASSERT(reply->rhdr->flags == htonl(kDNSServiceFlagsAdd));
UNITTEST_ASSERT(reply->rhdr->ifi == kDNSServiceInterfaceIndexLocalOnly); // Regress <rdar://problem/27340874>
UNITTEST_ASSERT(reply->rhdr->error ==
(DNSServiceErrorType)htonl(kDNSServiceErr_Timeout)); // Regress <rdar://problem/27562965>
free_req(req);
UNITTEST_FOOTER
// This function does memory cleanup and no verification.
UNITTEST_HEADER(FinalizeUnitTest)
mDNSPlatformMemFree(local_socket);
UNITTEST_FOOTER
mDNSlocal mStatus InitEtcHostsRecords(void)
{
mDNS *m = &mDNSStorage;
struct sockaddr_storage hostaddr;
AuthHash newhosts;
mDNSPlatformMemZero(&newhosts, sizeof(AuthHash));
memset(&hostaddr, 0, sizeof(hostaddr));
get_ip("127.0.0.1", &hostaddr);
domainname domain;
MakeDomainNameFromDNSNameString(&domain, "localhost");
mDNSMacOSXCreateEtcHostsEntry_ut(&domain, (struct sockaddr *) &hostaddr, mDNSNULL, mDNSNULL, &newhosts);
memset(&hostaddr, 0, sizeof(hostaddr));
get_ip("0000:0000:0000:0000:0000:0000:0000:0001", &hostaddr);
MakeDomainNameFromDNSNameString(&domain, "localhost");
mDNSMacOSXCreateEtcHostsEntry_ut(&domain, (struct sockaddr *) &hostaddr, mDNSNULL, mDNSNULL, &newhosts);
memset(&hostaddr, 0, sizeof(hostaddr));
get_ip("255.255.255.255", &hostaddr);
MakeDomainNameFromDNSNameString(&domain, "broadcasthost");
mDNSMacOSXCreateEtcHostsEntry_ut(&domain, (struct sockaddr *) &hostaddr, mDNSNULL, mDNSNULL, &newhosts);
memset(&hostaddr, 0, sizeof(hostaddr));
get_ip("17.226.40.200", &hostaddr);
MakeDomainNameFromDNSNameString(&domain, "cardinal2.apple.com");
mDNSMacOSXCreateEtcHostsEntry_ut(&domain, (struct sockaddr *) &hostaddr, mDNSNULL, mDNSNULL, &newhosts);
UpdateEtcHosts_ut(&newhosts);
m->NextScheduledEvent = mDNS_TimeNow_NoLock(m);
mDNS_Execute(m);
return mStatus_NoError;
}

View File

@ -0,0 +1,9 @@
#ifndef LocalOnlyTimeoutTests_h
#define LocalOnlyTimeoutTests_h
#include "unittest.h"
int LocalOnlyTimeoutTests(void);
#endif /* LocalOnlyTimeoutTests_h */

View File

@ -0,0 +1,61 @@
#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);
// This fails >> 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);
// This fails >> 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

View File

@ -0,0 +1,10 @@
#ifndef ResourceRecordTest_h
#define ResourceRecordTest_h
#include "unittest.h"
int ResourceRecordTest(void);
#endif /* ResourceRecordTest_h */

View File

@ -0,0 +1,35 @@
#include "DNSCommon.h"
mDNSexport void init_logging_ut(void)
{
#if APPLE_OSX_mDNSResponder
init_logging();
/* When doing unit testing, it is likely that some local functions and
* variables will not be needed to do unit testing validation. So to get
* around compiler warnings about unused functions or variables, each
* warning work-around is handled explicitly below.
*/
/* The next three LogOperation() are used to trick the compiler into
* suppressing unused function and variable warnings. This is done by
* outputting the function or variable pointer to a log message.
*/
LogOperation("Quiet compiler warnings for KQueueLoop= %p, "
"KQWokenFlushBytes= %p, SignalCallback= %p, "
"mDNS_StatusCallback= %p, LaunchdCheckin= %p",
KQueueLoop, KQWokenFlushBytes,
SignalCallback, mDNS_StatusCallback,
LaunchdCheckin);
LogOperation("Quiet compiler warnings for SandboxProcess= %p, "
"mDNSDaemonInitialize= %p, HandleSIG= %p, "
"PreferencesGetValueInt= %p, PreferencesGetValueBool= %p",
SandboxProcess, mDNSDaemonInitialize,
HandleSIG, PreferencesGetValueInt,
PreferencesGetValueBool);
LogOperation("Quiet compiler warnings for rrcachestorage= %p, "
"NoMulticastAdvertisements= %p",
rrcachestorage, NoMulticastAdvertisements);
#endif // APPLE_OSX_mDNSResponder
}

View File

@ -0,0 +1,151 @@
#include "mDNSCoreReceiveTest.h"
#include "unittest_common.h"
int InitmDNSCoreReceiveTest(void);
int ValidQueryReqTest(void);
int NullDstQueryReqTest(void);
int ReceiveArpLogMsgTest(void);
void InitmDNSStorage(mDNS *const m);
// This DNS message was gleaned from a uDNS query request packet that was captured with Wireshark.
uint8_t udns_query_request_message[28] = { // contains 1 question for www.f5.com
0x31, 0xca, // transaction id
0x01, 0x00, // flags
0x00, 0x01, // 1 question
0x00, 0x00, // no anwsers
0x00, 0x00, // no authoritative answers
0x00, 0x00, // no additionals
0x03, 0x77, 0x77, 0x77, 0x02, 0x66, 0x35, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
};
// This DNS message was gleaned from a uDNS query request packet that was captured with Wireshark.
// Then the header id (more specifically, the msg->h.id) was deliberately cleared to force code
// path to traverse regression case, <rdar://problem/28556513>.
uint8_t udns_query_request_message_with_invalid_id[28] = { // contains 1 question for www.f5.com, msg->h.id = 0
0x00, 0x00, // transaction id
0x01, 0x00, // flags
0x00, 0x01, // 1 question
0x00, 0x00, // no anwsers
0x00, 0x00, // no authoritative answers
0x00, 0x00, // no additionals
0x03, 0x77, 0x77, 0x77, 0x02, 0x66, 0x35, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
};
uint8_t arp_request_packet[28] = { // contains 1 question for www.f5.com, msg->h.id = 0
0x00, 0x01, // hardware type: enet
0x08, 0x00, // protocol type: IP
0x06, // hardware size
0x04, // Protcol size
0x00, 0x01, // opcode request
0x24, 0x01, 0xc7, 0x24, 0x35, 0x00, // Sender mac addr
0x11, 0xe2, 0x14, 0x01, // Sender ip addr
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // target mac addr
0x11, 0xe2, 0x17, 0xbe // target ip addr
};
UNITTEST_HEADER(mDNSCoreReceiveTest)
UNITTEST_TEST(InitmDNSCoreReceiveTest)
UNITTEST_TEST(ValidQueryReqTest)
UNITTEST_TEST(NullDstQueryReqTest)
UNITTEST_TEST(ReceiveArpLogMsgTest)
UNITTEST_FOOTER
UNITTEST_HEADER(InitmDNSCoreReceiveTest)
mDNSPlatformTimeInit();
init_logging_ut();
mDNS_LoggingEnabled = 0;
mDNS_PacketLoggingEnabled = 0;
UNITTEST_FOOTER
UNITTEST_HEADER(ReceiveArpLogMsgTest)
// Init unit test environment and verify no error occurred.
mStatus result = init_mdns_environment(mDNStrue);
UNITTEST_ASSERT(result == mStatus_NoError);
UNITTEST_ASSERT(result == mStatus_NoError);
ArpLogMsgTest(&mDNSStorage, (const ARP_EthIP *) arp_request_packet, primary_interfaceID);
UNITTEST_ASSERT(result == mStatus_NoError);
UNITTEST_FOOTER
UNITTEST_HEADER(ValidQueryReqTest)
mDNS *const m = &mDNSStorage;
mDNSAddr srcaddr, dstaddr;
mDNSIPPort srcport, dstport;
DNSMessage * msg;
const mDNSu8 * end;
// This test case does not require setup of interfaces, the record's cache, or pending questions
// so m is initialized to all zeros.
InitmDNSStorage(m);
// Used random values for srcaddr and srcport
srcaddr.type = mDNSAddrType_IPv4;
srcaddr.ip.v4.b[0] = 192;
srcaddr.ip.v4.b[1] = 168;
srcaddr.ip.v4.b[2] = 1;
srcaddr.ip.v4.b[3] = 10;
srcport.NotAnInteger = swap16((mDNSu16)53);
// Used random values for dstaddr and dstport
dstaddr.type = mDNSAddrType_IPv4;
dstaddr.ip.v4.b[0] = 192;
dstaddr.ip.v4.b[1] = 168;
dstaddr.ip.v4.b[2] = 1;
dstaddr.ip.v4.b[3] = 20;
dstport.NotAnInteger = swap16((mDNSu16)49339);
// Set message to a DNS message (copied from a WireShark packet)
msg = (DNSMessage *)udns_query_request_message;
end = udns_query_request_message + sizeof(udns_query_request_message);
// Execute mDNSCoreReceive using a valid DNS message
mDNSCoreReceive(m, msg, end, &srcaddr, srcport, &dstaddr, dstport, if_nametoindex("en0"));
// Verify that mDNSCoreReceiveQuery traversed the normal code path
UNITTEST_ASSERT(m->mDNSStats.NormalQueries == 1);
UNITTEST_FOOTER
UNITTEST_HEADER(NullDstQueryReqTest)
mDNS *const m = &mDNSStorage;
mDNSAddr srcaddr;
mDNSIPPort srcport, dstport;
DNSMessage * msg;
const mDNSu8 * end;
// This test case does not require setup of interfaces, the record's cache, or pending questions
// so m is initialized to all zeros.
InitmDNSStorage(m);
// Used random values for srcaddr and srcport
srcaddr.type = mDNSAddrType_IPv4;
srcaddr.ip.v4.b[0] = 192;
srcaddr.ip.v4.b[1] = 168;
srcaddr.ip.v4.b[2] = 1;
srcaddr.ip.v4.b[3] = 10;
srcport.NotAnInteger = swap16((mDNSu16)53);
// Used random value for dstport
dstport.NotAnInteger = swap16((mDNSu16)49339);
// Set message to a DNS message (copied from a WireShark packet)
msg = (DNSMessage *)udns_query_request_message_with_invalid_id;
end = udns_query_request_message_with_invalid_id + sizeof(udns_query_request_message_with_invalid_id);
// Execute mDNSCoreReceive to regress <rdar://problem/28556513>
mDNSCoreReceive(m, msg, end, &srcaddr, srcport, NULL, dstport, if_nametoindex("en0"));
// Verify that mDNSCoreReceiveQuery was NOT traversed through the normal code path
UNITTEST_ASSERT(m->mDNSStats.NormalQueries == 0);
// Verify code path that previously crashed, in <rdar://problem/28556513>, now traverses successfully
// by checking a counter that was incremented on code path that crashed.
UNITTEST_ASSERT(m->MPktNum == 1);
UNITTEST_FOOTER
void InitmDNSStorage(mDNS *const m)
{
memset(m, 0, sizeof(mDNS));
}

View File

@ -0,0 +1,9 @@
#ifndef mDNSCoreReceiveTest_h
#define mDNSCoreReceiveTest_h
#include "unittest.h"
int mDNSCoreReceiveTest(void);
#endif /* mDNSCoreReceiveTest_h */

View File

@ -0,0 +1,42 @@
/* -*- 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"
#include "ResourceRecordTest.h"
#include "mDNSCoreReceiveTest.h"
#include "CNameRecordTests.h"
#include "LocalOnlyTimeoutTests.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)";
UNITTEST_HEADER(run_tests)
UNITTEST_GROUP(DNSMessageTest)
UNITTEST_GROUP(ResourceRecordTest)
UNITTEST_GROUP(mDNSCoreReceiveTest)
//UNITTEST_GROUP(CNameRecordTests) // Commenting out until issue reported in <rdar://problem/30589360> is debugged.
UNITTEST_GROUP(LocalOnlyTimeoutTests)
UNITTEST_FOOTER
// UNITTEST_MAIN is run in daemon.c

View File

@ -0,0 +1,66 @@
#include "DNSCommon.h" // Defines general DNS utility routines
// To match *either* a v4 or v6 instance of this interface
mDNSlocal mDNSInterfaceID SearchForInterfaceByAddr(mDNSAddr* addr)
{
NetworkInterfaceInfoOSX *i;
for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
if (i->Exists)
{
if ((i->ifinfo.ip.type == mDNSAddrType_IPv4) &&
i->ifinfo.ip.ip.v4.NotAnInteger == addr->ip.v4.NotAnInteger)
return i->ifinfo.InterfaceID;
else if ((i->ifinfo.ip.type == mDNSAddrType_IPv6) &&
(i->ifinfo.ip.ip.v6.l[0] == addr->ip.v6.l[0] &&
i->ifinfo.ip.ip.v6.l[1] == addr->ip.v6.l[1] &&
i->ifinfo.ip.ip.v6.l[2] == addr->ip.v6.l[2] &&
i->ifinfo.ip.ip.v6.l[3] == addr->ip.v6.l[3])
)
return i->ifinfo.InterfaceID;
}
return(NULL);
}
mDNSexport void SetInterfaces_ut(mDNSInterfaceID* pri_id, mDNSAddr *pri_v4, mDNSAddr* pri_v6, mDNSAddr* pri_router)
{
mDNSs32 utc = mDNSPlatformUTC();
MarkAllInterfacesInactive(utc);
UpdateInterfaceList(utc);
ClearInactiveInterfaces(utc);
SetupActiveInterfaces(utc);
// set primary interface info
{
mDNSAddr* addr;
NetworkChangedKey_IPv4 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
NetworkChangedKey_IPv6 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6);
NetworkChangedKey_Hostnames = SCDynamicStoreKeyCreateHostNames(NULL);
NetworkChangedKey_Computername = SCDynamicStoreKeyCreateComputerName(NULL);
NetworkChangedKey_DNS = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetDNS);
NetworkChangedKey_StateInterfacePrefix = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, CFSTR(""), NULL);
mDNSPlatformGetPrimaryInterface(pri_v4, pri_v6, pri_router);
addr = (pri_v4->type == mDNSAddrType_IPv4) ? pri_v4 : pri_v6;
*pri_id = SearchForInterfaceByAddr(addr);
CFRelease(NetworkChangedKey_IPv4);
CFRelease(NetworkChangedKey_IPv6);
CFRelease(NetworkChangedKey_Hostnames);
CFRelease(NetworkChangedKey_Computername);
CFRelease(NetworkChangedKey_DNS);
CFRelease(NetworkChangedKey_StateInterfacePrefix);
}
}
mDNSexport mDNSBool mDNSMacOSXCreateEtcHostsEntry_ut(const domainname *domain, const struct sockaddr *sa, const domainname *cname, char *ifname, AuthHash *auth)
{
return mDNSMacOSXCreateEtcHostsEntry(domain, sa, cname, ifname, auth);
}
mDNSexport void UpdateEtcHosts_ut(void *context)
{
mDNS_Lock(&mDNSStorage);
UpdateEtcHosts(&mDNSStorage, context);
mDNS_Unlock(&mDNSStorage);
}

View File

@ -0,0 +1,17 @@
#include "DNSCommon.h" // Defines general DNS utility routines
mDNSexport mStatus mDNS_InitStorage_ut(mDNS *const m, mDNS_PlatformSupport *const p,
CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context)
{
return mDNS_InitStorage(m, p, rrcachestorage, rrcachesize, AdvertiseLocalAddresses, Callback, Context);
}
mDNSexport mStatus ArpLogMsgTest(mDNS *const m, const ARP_EthIP *const arp, const mDNSInterfaceID InterfaceID)
{
NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
static const char msg[] = "ARP Req message";
LogMsg("Arp %-7s %s %.6a %.4a for %.4a",
intf->ifname, msg, arp->sha.b, arp->spa.b, arp->tpa.b);
return mStatus_NoError;
}

View File

@ -0,0 +1,43 @@
#include "DNSCommon.h" // Defines general DNS utility routines
mDNSexport mStatus handle_client_request_ut(void *req)
{
return handle_client_request((request_state*)req);
}
mDNSexport void LogCacheRecords_ut(mDNSs32 now, mDNSu32* retCacheUsed, mDNSu32* retCacheActive)
{
mDNSu32 CacheUsed =0, CacheActive =0, slot;
const CacheGroup *cg;
const CacheRecord *cr;
LogMsgNoIdent("------------ Cache -------------");
LogMsgNoIdent("Slt Q TTL if U Type rdlen");
for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
{
for (cg = mDNSStorage.rrcache_hash[slot]; cg; cg=cg->next)
{
CacheUsed++; // Count one cache entity for the CacheGroup object
for (cr = cg->members; cr; cr=cr->next)
{
const mDNSs32 remain = cr->resrec.rroriginalttl - (now - cr->TimeRcvd) / mDNSPlatformOneSecond;
const char *ifname;
mDNSInterfaceID InterfaceID = cr->resrec.InterfaceID;
if (!InterfaceID && cr->resrec.rDNSServer && cr->resrec.rDNSServer->scoped)
InterfaceID = cr->resrec.rDNSServer->interface;
ifname = InterfaceNameForID(&mDNSStorage, InterfaceID);
if (cr->CRActiveQuestion) CacheActive++;
PrintOneCacheRecord(cr, slot, remain, ifname, &CacheUsed);
PrintCachedRecords(cr, slot, remain, ifname, &CacheUsed);
}
}
}
*retCacheUsed = CacheUsed;
*retCacheActive = CacheActive;
}
mDNSexport int LogEtcHosts_ut(mDNS *const m)
{
return LogEtcHosts(m);
}

View File

@ -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

View File

@ -0,0 +1,124 @@
/* -*- 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>
#include "unittest_common.h"
#include <MacTypes.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;
int run_tests(void);
#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()) \
{ \
printf("unit test FAILED\n"); \
return -1; \
} \
fp = fopen("unittest_success", "w"); \
if (!fp) return -2; \
fprintf(fp, "unit test %s\n", "SUCCEEDED"); \
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_SENDDNSMESSAGE mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNSu8 *end, \
mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, \
mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo, \
mDNSBool useBackgroundTrafficClass) \
{ \
(void)(m); \
(void)(msg); \
(void)(end); \
(void)(InterfaceID); \
(void)(src); \
(void)(dst); \
(void)(dstport); \
(void)(sock); \
(void)(authInfo); \
(void)(useBackgroundTrafficClass); \
return 0; \
}
#define UNITTEST_SETSOCKOPT void mDNSPlatformSetSocktOpt(void *sockCxt, mDNSTransport_Type transType, \
mDNSAddr_Type addrType, const DNSQuestion *q) \
{ \
(void)(sockCxt); \
(void)(transType); \
(void)(addrType); \
(void)(q); \
return; \
}
#define UNITTEST_UDPCLOSE void mDNSPlatformUDPClose(UDPSocket *sock) \
{ \
(void)(sock); \
}
#define UNITTEST_FAIL_ASSERT { assert(((void*)__func__) == 0); }
#ifdef __cplusplus
}
#endif
#endif // ndef _UNITTEST_H_

View File

@ -0,0 +1,157 @@
#include "unittest_common.h"
#include "dns_sd.h"
#include "mDNSEmbeddedAPI.h"
#include "mDNSMacOSX.h"
static mDNS_PlatformSupport PlatformStorage;
#define RR_CACHE_SIZE ((32*1024) / sizeof(CacheRecord))
static CacheEntity gRrcachestorage[RR_CACHE_SIZE];
// Primary interface info that is used when simulating the receive of the response packet
mDNSInterfaceID primary_interfaceID;
mDNSAddr primary_v4;
mDNSAddr primary_v6;
mDNSAddr primary_router;
// This function sets up the minimum environement to run a unit test. It
// initializes logging, interfaces, and timenow.
mDNSexport mStatus init_mdns_environment(mDNSBool enableLogging)
{
mDNS *m = &mDNSStorage;
init_logging_ut();
mDNS_LoggingEnabled = enableLogging;
mDNS_PacketLoggingEnabled = enableLogging;
mStatus result = mDNS_InitStorage_ut(m, &PlatformStorage, gRrcachestorage, RR_CACHE_SIZE, mDNSfalse, mDNSNULL, mDNSNULL);
if (result != mStatus_NoError)
return result;
primary_v4 = primary_v6 = primary_router = zeroAddr;
SetInterfaces_ut(&primary_interfaceID, &primary_v4, &primary_v6, &primary_router);
m->timenow = mDNS_TimeNow_NoLock(m);
return mStatus_NoError;
}
// This function sets up the minimum environement to run a unit test. It
// initializes logging and timenow. This is the call to use if your
// unit test does not use interfaces.
mDNSexport mStatus init_mdns_storage()
{
mDNS *m = &mDNSStorage;
init_logging_ut();
mDNS_LoggingEnabled = 1;
mDNS_PacketLoggingEnabled = 1;
mStatus result = mDNS_InitStorage_ut(m, &PlatformStorage, gRrcachestorage, RR_CACHE_SIZE, mDNSfalse, mDNSNULL, mDNSNULL);
if (result != mStatus_NoError)
return result;
return mStatus_NoError;
}
mDNSlocal void init_client_request(request_state* req, char *msgbuf, size_t msgSize, uint32_t op)
{
// Simulate read_msg behavior since unit test does not open a socket
memset(req, 0, sizeof(request_state));
req->ts = t_complete;
req->msgbuf = mDNSNULL;
req->msgptr = msgbuf;
req->msgend = msgbuf + msgSize;
// The rest of the request values are set in order to simulate a request
req->sd = client_req_sd;
req->uid = client_req_uid;
req->hdr_bytes = client_req_hdr_bytes;
req->hdr.version = client_req_hdr_version;
req->hdr.op = op; // query_request
req->hdr.datalen = msgSize;
req->data_bytes = msgSize;
req->process_id = client_req_process_id;
memcpy(req->pid_name, client_req_pid_name, strlen(client_req_pid_name));
}
// This function calls the mDNSResponder handle_client_request() API. It initializes
// the request and query data structures.
mDNSexport mStatus start_client_request(request_state* req, char *msgbuf, size_t msgsz, uint32_t op, UDPSocket* socket)
{
// Process the unit test's client request
init_client_request(req, msgbuf, msgsz, op);
mStatus result = handle_client_request_ut((void*)req);
DNSQuestion* q = &req->u.queryrecord.q;
q->LocalSocket = socket;
return result;
}
// This function calls the mDNSResponder mDNSCoreReceive() API.
mDNSexport void receive_response(const request_state* req, DNSMessage *msg, size_t msgSize)
{
mDNS *m = &mDNSStorage;
mDNSAddr srcaddr;
mDNSIPPort srcport, dstport;
const mDNSu8 * end;
DNSQuestion *q = (DNSQuestion *)&req->u.queryrecord.q;
UInt8* data = (UInt8*)msg;
// Used same values for DNS server as specified during init of unit test
srcaddr.type = mDNSAddrType_IPv4;
srcaddr.ip.v4.NotAnInteger = dns_server_ipv4.NotAnInteger;
srcport.NotAnInteger = client_resp_src_port;
// Used random value for dstport
dstport.NotAnInteger = swap16((mDNSu16)client_resp_dst_port);
// Set DNS message (that was copied from a WireShark packet)
end = (const mDNSu8 *)msg + msgSize;
// Set socket info that mDNSCoreReceive uses to verify socket context
q->LocalSocket->ss.port.NotAnInteger = swap16((mDNSu16)client_resp_dst_port);
q->TargetQID.b[0] = data[0];
q->TargetQID.b[1] = data[1];
// Execute mDNSCoreReceive which copies two DNS records into the cache
mDNSCoreReceive(m, msg, end, &srcaddr, srcport, &primary_v4, dstport, primary_interfaceID);
}
mDNSexport size_t get_reply_len(char* name, uint16_t rdlen)
{
size_t len = sizeof(DNSServiceFlags);
len += sizeof(mDNSu32); // interface index
len += sizeof(DNSServiceErrorType);
len += strlen(name) + 1;
len += 3 * sizeof(mDNSu16); // type, class, rdlen
len += rdlen;
len += sizeof(mDNSu32); // TTL
return len;
}
void free_req(request_state* req)
{
// Cleanup request's memory usage
while (req->replies)
{
reply_state *reply = req->replies;
req->replies = req->replies->next;
mDNSPlatformMemFree(reply);
}
req->replies = NULL;
mDNSPlatformMemFree(req);
}
// Unit test support functions follow
#define SA_LEN(addr) (((addr)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
mDNSexport void get_ip(const char *const name, struct sockaddr_storage *result)
{
struct addrinfo* aiList;
int err = getaddrinfo(name, NULL, NULL, &aiList);
if (err) fprintf(stderr, "getaddrinfo error %d for %s", err, name);
else memcpy(result, aiList->ai_addr, SA_LEN(aiList->ai_addr));
if (aiList) freeaddrinfo(aiList);
}

View File

@ -0,0 +1,57 @@
#ifndef UNITTEST_COMMON_H
#define UNITTEST_COMMON_H
#include "dns_sd.h"
#include "uds_daemon.h"
#include "uDNS.h"
#include "dnssd_ipc.h"
#include <netdb.h> // for getaddrinfo
#include <net/if.h>
#include <pthread.h>
// Primary interface info that is used when simulating the receive of the response packet
extern mDNSInterfaceID primary_interfaceID;
extern mDNSAddr primary_v4;
extern mDNSAddr primary_v6;
extern mDNSAddr primary_router;
// Arbitrary values to simulate a client_request request
#define client_req_sd 12
#define client_req_uid 502
#define client_req_hdr_bytes 28
#define client_req_hdr_version 1
#define client_resp_src_port 13568
#define client_resp_dst_port 49339
#define uDNS_TargetQID 16745
#define client_req_process_id 15418
static char client_req_pid_name[MAXCOMLEN] = "mDNSUnitTest";
//Arbitrary values to simulate a DNS server
#define dns_server_timeout 30
#define dns_server_resGroupID 12
static const mDNSv4Addr dns_server_ipv4 = {{ 192, 168, 1, 20 }};
extern mStatus init_mdns_environment(mDNSBool enableLogging);
extern mStatus init_mdns_storage(void);
extern size_t get_reply_len(char* name, uint16_t rdlen);
extern mStatus start_client_request(request_state* req, char *msgbuf, size_t msgsz, uint32_t op, UDPSocket* socket);
extern void receive_response(const request_state* req, DNSMessage *msg, size_t msgSize);
extern void get_ip(const char *const name, struct sockaddr_storage *result);
extern void free_req(request_state* req);
extern mStatus mDNS_InitStorage_ut(mDNS *const m, mDNS_PlatformSupport *const p,
CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context);
extern void init_logging_ut(void);
extern void SetInterfaces_ut(mDNSInterfaceID* primary_interfaceID, mDNSAddr *primary_v4,
mDNSAddr* primary_v6, mDNSAddr* primary_router);
extern mStatus handle_client_request_ut(void *req);
extern void LogCacheRecords_ut(mDNSs32 now, mDNSu32* retCacheUsed, mDNSu32* retCacheActive);
extern int LogEtcHosts_ut(mDNS *const m);
extern mDNSBool mDNSMacOSXCreateEtcHostsEntry_ut(const domainname *domain, const struct sockaddr *sa,
const domainname *cname, char *ifname, AuthHash *auth);
extern void UpdateEtcHosts_ut(void *context);
extern mStatus ArpLogMsgTest(mDNS *const m, const ARP_EthIP *const arp, const mDNSInterfaceID InterfaceID);
#endif /* UNITTEST_COMMON_H */