Import mDNSResponder-320.16, as previous import (258.14) is quite old
This commit is contained in:
parent
dff5f859c8
commit
ee071a7a97
|
@ -736,7 +736,12 @@ static void DNSSD_API qr_reply(DNSServiceRef sdref, const DNSServiceFlags flags,
|
|||
if (errorCode)
|
||||
{
|
||||
if (errorCode == kDNSServiceErr_NoSuchRecord) printf("No Such Record");
|
||||
else printf("Error code %d", errorCode);
|
||||
else if (errorCode == kDNSServiceErr_Timeout)
|
||||
{
|
||||
printf("No Such Record\n");
|
||||
printf("Query Timed Out\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
|
@ -947,7 +952,7 @@ static void getip(const char *const name, struct sockaddr_storage *result)
|
|||
if (addrs) freeaddrinfo(addrs);
|
||||
}
|
||||
|
||||
static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef sdref, const char *host, const char *ip)
|
||||
static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef sdref, const char *host, const char *ip, DNSServiceFlags flags)
|
||||
{
|
||||
// Call getip() after the call DNSServiceCreateConnection().
|
||||
// On the Win32 platform, WinSock must be initialized for getip() to succeed.
|
||||
|
@ -955,11 +960,12 @@ static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef sdref, const
|
|||
// DNSServiceCreateConnection() is called before getip() is.
|
||||
struct sockaddr_storage hostaddr;
|
||||
getip(ip, &hostaddr);
|
||||
flags |= kDNSServiceFlagsUnique;
|
||||
if (hostaddr.ss_family == AF_INET)
|
||||
return(DNSServiceRegisterRecord(sdref, &record, kDNSServiceFlagsUnique, opinterface, host,
|
||||
return(DNSServiceRegisterRecord(sdref, &record, flags, opinterface, host,
|
||||
kDNSServiceType_A, kDNSServiceClass_IN, 4, &((struct sockaddr_in *)&hostaddr)->sin_addr, 240, MyRegisterRecordCallback, (void*)host));
|
||||
else if (hostaddr.ss_family == AF_INET6)
|
||||
return(DNSServiceRegisterRecord(sdref, &record, kDNSServiceFlagsUnique, opinterface, host,
|
||||
return(DNSServiceRegisterRecord(sdref, &record, flags, opinterface, host,
|
||||
kDNSServiceType_AAAA, kDNSServiceClass_IN, 16, &((struct sockaddr_in6*)&hostaddr)->sin6_addr, 240, MyRegisterRecordCallback, (void*)host));
|
||||
else return(kDNSServiceErr_BadParam);
|
||||
}
|
||||
|
@ -971,9 +977,8 @@ static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef sdref, const
|
|||
#define HexPair(P) ((HexVal((P)[0]) << 4) | HexVal((P)[1]))
|
||||
|
||||
static DNSServiceErrorType RegisterService(DNSServiceRef *sdref,
|
||||
const char *nam, const char *typ, const char *dom, const char *host, const char *port, int argc, char **argv)
|
||||
const char *nam, const char *typ, const char *dom, const char *host, const char *port, int argc, char **argv, DNSServiceFlags flags)
|
||||
{
|
||||
DNSServiceFlags flags = 0;
|
||||
uint16_t PortAsNumber = atoi(port);
|
||||
Opaque16 registerPort = { { PortAsNumber >> 8, PortAsNumber & 0xFF } };
|
||||
unsigned char txt[2048] = "";
|
||||
|
@ -1008,7 +1013,7 @@ static DNSServiceErrorType RegisterService(DNSServiceRef *sdref,
|
|||
|
||||
//flags |= kDNSServiceFlagsAllowRemoteQuery;
|
||||
//flags |= kDNSServiceFlagsNoAutoRename;
|
||||
|
||||
|
||||
return(DNSServiceRegister(sdref, flags, opinterface, nam, typ, dom, host, registerPort.NotAnInteger, (uint16_t) (ptr-txt), txt, reg_reply, NULL));
|
||||
}
|
||||
|
||||
|
@ -1025,6 +1030,7 @@ int main(int argc, char **argv)
|
|||
DNSServiceErrorType err;
|
||||
char buffer[TypeBufferSize], *typ, *dom;
|
||||
int opi;
|
||||
DNSServiceFlags flags = 0;
|
||||
|
||||
// Extract the program name from argv[0], which by convention contains the path to this executable.
|
||||
// Note that this is just a voluntary convention, not enforced by the kernel --
|
||||
|
@ -1063,6 +1069,14 @@ int main(int argc, char **argv)
|
|||
printf("Using P2P\n");
|
||||
}
|
||||
|
||||
if (argc > 1 && !strcasecmp(argv[1], "-includep2p"))
|
||||
{
|
||||
argc--;
|
||||
argv++;
|
||||
flags |= kDNSServiceFlagsIncludeP2P;
|
||||
printf("Including P2P\n");
|
||||
}
|
||||
|
||||
if (argc > 2 && !strcmp(argv[1], "-i"))
|
||||
{
|
||||
opinterface = if_nametoindex(argv[2]);
|
||||
|
@ -1073,7 +1087,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
if (argc < 2) goto Fail; // Minimum command line is the command name and one argument
|
||||
operation = getfirstoption(argc, argv, "EFBZLRPQqCAUNTMISV"
|
||||
operation = getfirstoption(argc, argv, "EFBZLlRPQqtCAUNTMISV"
|
||||
#if HAS_NAT_PMP_API
|
||||
"X"
|
||||
#endif
|
||||
|
@ -1104,7 +1118,7 @@ int main(int argc, char **argv)
|
|||
typ = gettype(buffer, typ);
|
||||
if (dom[0] == '.' && dom[1] == 0) dom[0] = 0; // We allow '.' on the command line as a synonym for empty string
|
||||
printf("Browsing for %s%s%s\n", typ, dom[0] ? "." : "", dom);
|
||||
err = DNSServiceBrowse(&client, 0, opinterface, typ, dom, browse_reply, NULL);
|
||||
err = DNSServiceBrowse(&client, flags, opinterface, typ, dom, browse_reply, NULL);
|
||||
break;
|
||||
|
||||
case 'Z': typ = (argc < opi+1) ? "" : argv[opi+0];
|
||||
|
@ -1117,40 +1131,44 @@ int main(int argc, char **argv)
|
|||
err = DNSServiceBrowse(&sc1, kDNSServiceFlagsShareConnection, opinterface, typ, dom, zonedata_browse, NULL);
|
||||
break;
|
||||
|
||||
case 'L': if (argc < opi+2) goto Fail;
|
||||
typ = (argc < opi+2) ? "" : argv[opi+1];
|
||||
dom = (argc < opi+3) ? "local" : argv[opi+2];
|
||||
typ = gettype(buffer, typ);
|
||||
if (dom[0] == '.' && dom[1] == 0) dom = "local"; // We allow '.' on the command line as a synonym for "local"
|
||||
printf("Lookup %s.%s.%s\n", argv[opi+0], typ, dom);
|
||||
err = DNSServiceResolve(&client, 0, opinterface, argv[opi+0], typ, dom, resolve_reply, NULL);
|
||||
break;
|
||||
case 'l':
|
||||
case 'L': {
|
||||
DNSServiceFlags rflags = 0;
|
||||
if (argc < opi+2) goto Fail;
|
||||
typ = (argc < opi+2) ? "" : argv[opi+1];
|
||||
dom = (argc < opi+3) ? "local" : argv[opi+2];
|
||||
typ = gettype(buffer, typ);
|
||||
if (dom[0] == '.' && dom[1] == 0) dom = "local"; // We allow '.' on the command line as a synonym for "local"
|
||||
printf("Lookup %s.%s.%s\n", argv[opi+0], typ, dom);
|
||||
if (operation == 'l') rflags |= kDNSServiceFlagsWakeOnResolve;
|
||||
err = DNSServiceResolve(&client, rflags, opinterface, argv[opi+0], typ, dom, resolve_reply, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'R': if (argc < opi+4) goto Fail;
|
||||
typ = (argc < opi+2) ? "" : argv[opi+1];
|
||||
dom = (argc < opi+3) ? "" : argv[opi+2];
|
||||
typ = gettype(buffer, typ);
|
||||
if (dom[0] == '.' && dom[1] == 0) dom[0] = 0; // We allow '.' on the command line as a synonym for empty string
|
||||
err = RegisterService(&client, argv[opi+0], typ, dom, NULL, argv[opi+3], argc-(opi+4), argv+(opi+4));
|
||||
err = RegisterService(&client, argv[opi+0], typ, dom, NULL, argv[opi+3], argc-(opi+4), argv+(opi+4), flags);
|
||||
break;
|
||||
|
||||
case 'P': if (argc < opi+6) goto Fail;
|
||||
err = DNSServiceCreateConnection(&client_pa);
|
||||
if (err) { fprintf(stderr, "DNSServiceCreateConnection returned %d\n", err); return(err); }
|
||||
err = RegisterProxyAddressRecord(client_pa, argv[opi+4], argv[opi+5]);
|
||||
//err = RegisterProxyAddressRecord(client_pa, "two", argv[opi+5]);
|
||||
err = RegisterProxyAddressRecord(client_pa, argv[opi+4], argv[opi+5], flags);
|
||||
if (err) break;
|
||||
err = RegisterService(&client, argv[opi+0], gettype(buffer, argv[opi+1]), argv[opi+2], argv[opi+4], argv[opi+3], argc-(opi+6), argv+(opi+6));
|
||||
//DNSServiceRemoveRecord(client_pa, record, 0);
|
||||
//DNSServiceRemoveRecord(client_pa, record, 0);
|
||||
err = RegisterService(&client, argv[opi+0], gettype(buffer, argv[opi+1]), argv[opi+2], argv[opi+4], argv[opi+3], argc-(opi+6), argv+(opi+6), flags);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
case 'q':
|
||||
case 'Q':
|
||||
case 'C': {
|
||||
uint16_t rrtype, rrclass;
|
||||
DNSServiceFlags flags = kDNSServiceFlagsReturnIntermediates;
|
||||
flags |= kDNSServiceFlagsReturnIntermediates;
|
||||
if (operation == 'q') flags |= kDNSServiceFlagsSuppressUnusable;
|
||||
if (operation == 't') flags |= (kDNSServiceFlagsSuppressUnusable | kDNSServiceFlagsTimeout);
|
||||
if (argc < opi+1) goto Fail;
|
||||
rrtype = (argc <= opi+1) ? kDNSServiceType_A : GetRRType(argv[opi+1]);
|
||||
rrclass = (argc <= opi+2) ? kDNSServiceClass_IN : atoi(argv[opi+2]);
|
||||
|
@ -1186,8 +1204,8 @@ int main(int argc, char **argv)
|
|||
static const char TXT1[] = "\xC" "First String" "\xD" "Second String" "\xC" "Third String";
|
||||
static const char TXT2[] = "\xD" "Fourth String" "\xC" "Fifth String" "\xC" "Sixth String";
|
||||
printf("Registering Service Test._testdualtxt._tcp.local.\n");
|
||||
err = DNSServiceRegister(&client, 0, opinterface, "Test", "_testdualtxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT1)-1, TXT1, reg_reply, NULL);
|
||||
if (!err) err = DNSServiceAddRecord(client, &record, 0, kDNSServiceType_TXT, sizeof(TXT2)-1, TXT2, 0);
|
||||
err = DNSServiceRegister(&client, flags, opinterface, "Test", "_testdualtxt._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT1)-1, TXT1, reg_reply, NULL);
|
||||
if (!err) err = DNSServiceAddRecord(client, &record, flags, kDNSServiceType_TXT, sizeof(TXT2)-1, TXT2, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1318,7 +1336,7 @@ Fail:
|
|||
|
||||
// NOT static -- otherwise the compiler may optimize it out
|
||||
// The "@(#) " pattern is a special prefix the "what" command looks for
|
||||
const char VersionString_SCCS[] = "@(#) dns-sd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
|
||||
const char VersionString_SCCS[] = "@(#) dns-sd " STRINGIFY(mDNSResponderVersion);
|
||||
|
||||
#if _BUILDING_XCODE_PROJECT_
|
||||
// If the process crashes, then this string will be magically included in the automatically-generated crash log
|
||||
|
|
|
@ -989,8 +989,31 @@ mDNSexport void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText)
|
|||
// Set up a AuthRecord with sensible default values.
|
||||
// These defaults may be overwritten with new values before mDNS_Register is called
|
||||
mDNSexport void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID,
|
||||
mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, mDNSRecordCallback Callback, void *Context)
|
||||
mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, AuthRecType artype, mDNSRecordCallback Callback, void *Context)
|
||||
{
|
||||
//
|
||||
// LocalOnly auth record can be created with LocalOnly InterfaceID or a valid InterfaceID.
|
||||
// Most of the applications normally create with LocalOnly InterfaceID and we store them as
|
||||
// such, so that we can deliver the response to questions that specify LocalOnly InterfaceID.
|
||||
// LocalOnly resource records can also be created with valid InterfaceID which happens today
|
||||
// when we create LocalOnly records for /etc/hosts.
|
||||
|
||||
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
|
||||
if (ttl > 0x7FFFFFFFUL / mDNSPlatformOneSecond)
|
||||
ttl = 0x7FFFFFFFUL / mDNSPlatformOneSecond;
|
||||
|
@ -1033,6 +1056,7 @@ mDNSexport void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mD
|
|||
rr->AddressProxy = zeroAddr;
|
||||
rr->TimeRcvd = 0;
|
||||
rr->TimeExpire = 0;
|
||||
rr->ARType = artype;
|
||||
|
||||
// Field Group 3: Transient state for Authoritative Records (set in mDNS_Register_internal)
|
||||
// Field Group 4: Transient uDNS state for Authoritative Records (set in mDNS_Register_internal)
|
||||
|
@ -1074,6 +1098,12 @@ mDNSexport void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID I
|
|||
q->ForceMCast = mDNSfalse;
|
||||
q->ReturnIntermed = mDNSfalse;
|
||||
q->SuppressUnusable = mDNSfalse;
|
||||
q->SearchListIndex = 0;
|
||||
q->AppendSearchDomains = 0;
|
||||
q->RetryWithSearchDomains = mDNSfalse;
|
||||
q->TimeoutQuestion = 0;
|
||||
q->WakeOnResolve = 0;
|
||||
q->qnameOrig = mDNSNULL;
|
||||
q->QuestionCallback = callback;
|
||||
q->QuestionContext = context;
|
||||
}
|
||||
|
@ -1186,6 +1216,13 @@ mDNSexport mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBod
|
|||
|
||||
mDNSexport mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
LogMsg("SameNameRecordAnswersQuestion: ERROR!! called with LocalOnly ResourceRecord %p, Question %p", rr->InterfaceID, q->InterfaceID);
|
||||
return mDNSfalse;
|
||||
}
|
||||
if (rr->InterfaceID &&
|
||||
q ->InterfaceID && q->InterfaceID != mDNSInterface_LocalOnly &&
|
||||
rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
|
||||
|
@ -1205,6 +1242,14 @@ mDNSexport mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr
|
|||
|
||||
mDNSexport mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
LogMsg("ResourceRecordAnswersQuestion: ERROR!! called with LocalOnly/P2P ResourceRecord %p, Question %p", rr->InterfaceID, q->InterfaceID);
|
||||
return mDNSfalse;
|
||||
}
|
||||
|
||||
if (rr->InterfaceID &&
|
||||
q ->InterfaceID && q->InterfaceID != mDNSInterface_LocalOnly &&
|
||||
rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
|
||||
|
@ -1213,10 +1258,6 @@ mDNSexport mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr
|
|||
if (!rr->InterfaceID && rr->rDNSServer != q->qDNSServer) return(mDNSfalse);
|
||||
|
||||
// If ResourceRecord received via multicast, but question was unicast, then shouldn't use record to answer this question.
|
||||
// This also covers the case where the ResourceRecord is mDNSInterface_LocalOnly and the question is expecting a unicast
|
||||
// DNS response. We don't want a local process to be able to create a fake LocalOnly address record for "www.bigbank.com"
|
||||
// which would then cause other applications (e.g. Safari) to connect to the wrong address. If we decide to support this later,
|
||||
// the restrictions need to be at least as strict as the restrictions on who can edit /etc/hosts and put fake addresses there.
|
||||
if (rr->InterfaceID && !mDNSOpaque16IsZero(q->TargetQID)) return(mDNSfalse);
|
||||
|
||||
// RR type CNAME matches any query type. QTYPE ANY matches any RR type. QCLASS ANY matches any RR class.
|
||||
|
@ -1226,8 +1267,91 @@ mDNSexport mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr
|
|||
return(rr->namehash == q->qnamehash && SameDomainName(rr->name, &q->qname));
|
||||
}
|
||||
|
||||
// We have a separate function to handle LocalOnly AuthRecords because they can be created with
|
||||
// a valid InterfaceID (e.g., scoped /etc/hosts) and can be used to answer unicast questions unlike
|
||||
// multicast resource records (which has a valid InterfaceID) which can't be used to answer
|
||||
// unicast questions. ResourceRecordAnswersQuestion/SameNameRecordAnswersQuestion can't tell whether
|
||||
// a resource record is multicast or LocalOnly by just looking at the ResourceRecord because
|
||||
// LocalOnly records are truly identified by ARType in the AuthRecord. As P2P and LocalOnly record
|
||||
// are kept in the same hash table, we use the same function to make it easy for the callers when
|
||||
// they walk the hash table to answer LocalOnly/P2P questions
|
||||
//
|
||||
mDNSexport mDNSBool LocalOnlyRecordAnswersQuestion(AuthRecord *const ar, const DNSQuestion *const q)
|
||||
{
|
||||
ResourceRecord *rr = &ar->resrec;
|
||||
|
||||
// mDNSInterface_Any questions can be answered with LocalOnly/P2P records in this function. AuthRecord_Any
|
||||
// records are handled in ResourceRecordAnswersQuestion/SameNameRecordAnswersQuestion
|
||||
if (RRAny(ar))
|
||||
{
|
||||
LogMsg("LocalOnlyRecordAnswersQuestion: ERROR!! called with regular AuthRecordAny %##s", rr->name->c);
|
||||
return mDNSfalse;
|
||||
}
|
||||
|
||||
// Questions with mDNSInterface_LocalOnly InterfaceID should be answered with all resource records that are
|
||||
// *local* to the machine. These include resource records that have InterfaceID set to mDNSInterface_LocalOnly,
|
||||
// mDNSInterface_Any and any other real InterfaceID. Hence, LocalOnly questions should not be checked against
|
||||
// the InterfaceID in the resource record.
|
||||
//
|
||||
// mDNSInterface_Unicast does not indicate any scope and hence treat them like mDNSInterface_Any.
|
||||
|
||||
if (rr->InterfaceID &&
|
||||
q->InterfaceID && q->InterfaceID != mDNSInterface_LocalOnly && q->InterfaceID != mDNSInterface_Unicast &&
|
||||
rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
|
||||
|
||||
// Entries in /etc/hosts are added as LocalOnly resource records. The LocalOnly resource records
|
||||
// may have a scope e.g., fe80::1%en0. The question may be scoped or not: the InterfaceID may be set
|
||||
// to mDNSInterface_Any, mDNSInterface_LocalOnly or a real InterfaceID (scoped).
|
||||
//
|
||||
// 1) Question: Any, LocalOnly Record: no scope. This question should be answered with this record.
|
||||
//
|
||||
// 2) Question: Any, LocalOnly Record: scoped. This question should be answered with the record because
|
||||
// traditionally applications never specify scope e.g., getaddrinfo, but need to be able
|
||||
// to get to /etc/hosts entries.
|
||||
//
|
||||
// 3) Question: Scoped (LocalOnly or InterfaceID), LocalOnly Record: no scope. This is the inverse of (2).
|
||||
// If we register a LocalOnly record, we need to answer a LocalOnly question. If the /etc/hosts has a
|
||||
// non scoped entry, it may not make sense to answer a scoped question. But we can't tell these two
|
||||
// cases apart. As we currently answer LocalOnly question with LocalOnly record, we continue to do so.
|
||||
//
|
||||
// 4) Question: Scoped (LocalOnly or InterfaceID), LocalOnly Record: scoped. LocalOnly questions should be
|
||||
// answered with any resource record where as if it has a valid InterfaceID, the scope should match.
|
||||
//
|
||||
// (1) and (2) is bypassed because we check for a non-NULL InterfaceID above. For (3), the InterfaceID is NULL
|
||||
// and hence bypassed above. For (4) we bypassed LocalOnly questions and checked the scope of the record
|
||||
// against the question.
|
||||
//
|
||||
// For P2P, InterfaceIDs of the question and the record should match.
|
||||
|
||||
// If ResourceRecord received via multicast, but question was unicast, then shouldn't use record to answer this question.
|
||||
// LocalOnly authoritative answers are exempt. LocalOnly authoritative answers are used for /etc/host entries.
|
||||
// We don't want a local process to be able to create a fake LocalOnly address record for "www.bigbank.com" which would then
|
||||
// cause other applications (e.g. Safari) to connect to the wrong address. The rpc to register records filters out records
|
||||
// with names that don't end in local and have mDNSInterface_LocalOnly set.
|
||||
//
|
||||
// Note: The check is bypassed for LocalOnly and for P2P it is not needed as only .local records are registered and for
|
||||
// a question to match its names, it also has to end in .local and that question can't be a unicast question (See
|
||||
// Question_uDNS macro and its usage). As P2P does not enforce .local only registrations we still make this check
|
||||
// and also makes it future proof.
|
||||
|
||||
if (ar->ARType != AuthRecordLocalOnly && rr->InterfaceID && !mDNSOpaque16IsZero(q->TargetQID)) return(mDNSfalse);
|
||||
|
||||
// RR type CNAME matches any query type. QTYPE ANY matches any RR type. QCLASS ANY matches any RR class.
|
||||
if (!RRTypeAnswersQuestionType(rr,q->qtype)) return(mDNSfalse);
|
||||
if (rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
|
||||
|
||||
return(rr->namehash == q->qnamehash && SameDomainName(rr->name, &q->qname));
|
||||
}
|
||||
|
||||
mDNSexport mDNSBool AnyTypeRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
LogMsg("AnyTypeRecordAnswersQuestion: ERROR!! called with LocalOnly ResourceRecord %p, Question %p", rr->InterfaceID, q->InterfaceID);
|
||||
return mDNSfalse;
|
||||
}
|
||||
if (rr->InterfaceID &&
|
||||
q ->InterfaceID && q->InterfaceID != mDNSInterface_LocalOnly &&
|
||||
rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
|
||||
|
@ -1245,12 +1369,20 @@ mDNSexport mDNSBool AnyTypeRecordAnswersQuestion(const ResourceRecord *const rr,
|
|||
return(rr->namehash == q->qnamehash && SameDomainName(rr->name, &q->qname));
|
||||
}
|
||||
|
||||
// This is called only when the caller knows that it is a Unicast Resource Record and it is a Unicast Question
|
||||
// and hence we don't need InterfaceID checks like above. Though this may not be a big optimization, the main
|
||||
// reason we need this is that we can't compare DNSServers between the question and the resource record because
|
||||
// the resource record may not be completely initialized e.g., mDNSCoreReceiveResponse
|
||||
mDNSexport mDNSBool UnicastResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
|
||||
// This is called with both unicast resource record and multicast resource record. The question that
|
||||
// received the unicast response could be the regular unicast response from a DNS server or a response
|
||||
// to a mDNS QU query. The main reason we need this function is that we can't compare DNSServers between the
|
||||
// question and the resource record because the resource record is not completely initialized in
|
||||
// mDNSCoreReceiveResponse when this function is called.
|
||||
mDNSexport mDNSBool ResourceRecordAnswersUnicastResponse(const ResourceRecord *const rr, const DNSQuestion *const q)
|
||||
{
|
||||
// For resource records created using multicast, the InterfaceIDs have to match
|
||||
if (rr->InterfaceID &&
|
||||
q->InterfaceID && rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
|
||||
|
||||
// If ResourceRecord received via multicast, but question was unicast, then shouldn't use record to answer this question.
|
||||
if (rr->InterfaceID && !mDNSOpaque16IsZero(q->TargetQID)) return(mDNSfalse);
|
||||
|
||||
// RR type CNAME matches any query type. QTYPE ANY matches any RR type. QCLASS ANY matches any RR class.
|
||||
if (!RRTypeAnswersQuestionType(rr,q->qtype)) return(mDNSfalse);
|
||||
|
||||
|
@ -1746,7 +1878,7 @@ mDNSexport mDNSu8 *putZone(DNSMessage *const msg, mDNSu8 *ptr, mDNSu8 *limit, co
|
|||
mDNSexport mDNSu8 *putPrereqNameNotInUse(const domainname *const name, DNSMessage *const msg, mDNSu8 *const ptr, mDNSu8 *const end)
|
||||
{
|
||||
AuthRecord prereq;
|
||||
mDNS_SetupResourceRecord(&prereq, mDNSNULL, mDNSInterface_Any, kDNSQType_ANY, kStandardTTL, 0, mDNSNULL, mDNSNULL);
|
||||
mDNS_SetupResourceRecord(&prereq, mDNSNULL, mDNSInterface_Any, kDNSQType_ANY, kStandardTTL, 0, AuthRecordAny, mDNSNULL, mDNSNULL);
|
||||
AssignDomainName(&prereq.namestorage, name);
|
||||
prereq.resrec.rrtype = kDNSQType_ANY;
|
||||
prereq.resrec.rrclass = kDNSClass_NONE;
|
||||
|
@ -1816,7 +1948,7 @@ mDNSexport mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domain
|
|||
mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease)
|
||||
{
|
||||
AuthRecord rr;
|
||||
mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
|
||||
mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
|
||||
rr.resrec.rrclass = NormalMaxDNSMessageData;
|
||||
rr.resrec.rdlength = sizeof(rdataOPT); // One option in this OPT record
|
||||
rr.resrec.rdestimate = sizeof(rdataOPT);
|
||||
|
@ -1831,7 +1963,7 @@ mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease)
|
|||
mDNSexport mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease, mDNSu8 *limit)
|
||||
{
|
||||
AuthRecord rr;
|
||||
mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
|
||||
mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
|
||||
rr.resrec.rrclass = NormalMaxDNSMessageData;
|
||||
rr.resrec.rdlength = sizeof(rdataOPT); // One option in this OPT record
|
||||
rr.resrec.rdestimate = sizeof(rdataOPT);
|
||||
|
@ -1850,7 +1982,7 @@ mDNSexport mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *
|
|||
mDNSu8 *h = hinfo.rdatastorage.u.data;
|
||||
mDNSu16 len = 2 + m->HIHardware.c[0] + m->HISoftware.c[0];
|
||||
mDNSu8 *newptr;
|
||||
mDNS_SetupResourceRecord(&hinfo, mDNSNULL, mDNSInterface_Any, kDNSType_HINFO, 0, kDNSRecordTypeUnique, mDNSNULL, mDNSNULL);
|
||||
mDNS_SetupResourceRecord(&hinfo, mDNSNULL, mDNSInterface_Any, kDNSType_HINFO, 0, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
|
||||
AppendDomainLabel(&hinfo.namestorage, &m->hostlabel);
|
||||
AppendDomainName (&hinfo.namestorage, &authInfo->domain);
|
||||
hinfo.resrec.rroriginalttl = 0;
|
||||
|
@ -2156,7 +2288,7 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage
|
|||
case kDNSType_OPT: {
|
||||
rdataOPT *opt = rr->resrec.rdata->u.opt;
|
||||
rr->resrec.rdlength = 0;
|
||||
while (ptr < end && (mDNSu8 *)(opt+1) < &rr->resrec.rdata->u.data[MaximumRDSize])
|
||||
while (ptr < end && (mDNSu8 *)(opt+1) < rr->resrec.rdata->u.data + MaximumRDSize)
|
||||
{
|
||||
const rdataOPT *const currentopt = opt;
|
||||
if (ptr + 4 > end) { LogInfo("GetLargeResourceRecord: OPT RDATA ptr + 4 > end"); goto fail; }
|
||||
|
@ -2593,6 +2725,7 @@ mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m)
|
|||
}
|
||||
if (m->NewLocalOnlyQuestions) return(m->timenow);
|
||||
if (m->NewLocalRecords && AnyLocalRecordReady(m)) return(m->timenow);
|
||||
if (m->NewLocalOnlyRecords) return(m->timenow);
|
||||
if (m->SPSProxyListChanged) return(m->timenow);
|
||||
if (m->LocalRemoveEvents) return(m->timenow);
|
||||
|
||||
|
@ -2618,12 +2751,13 @@ mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m)
|
|||
if (e - m->NextScheduledProbe > 0) e = m->NextScheduledProbe;
|
||||
if (e - m->NextScheduledResponse > 0) e = m->NextScheduledResponse;
|
||||
}
|
||||
|
||||
if (e - m->NextScheduledStopTime > 0) e = m->NextScheduledStopTime;
|
||||
return(e);
|
||||
}
|
||||
|
||||
mDNSexport void ShowTaskSchedulingError(mDNS *const m)
|
||||
{
|
||||
AuthRecord *rr;
|
||||
mDNS_Lock(m);
|
||||
|
||||
LogMsg("Task Scheduling Error: Continuously busy for more than a second");
|
||||
|
@ -2640,9 +2774,11 @@ mDNSexport void ShowTaskSchedulingError(mDNS *const m)
|
|||
|
||||
if (m->NewLocalRecords)
|
||||
{
|
||||
AuthRecord *rr = AnyLocalRecordReady(m);
|
||||
rr = AnyLocalRecordReady(m);
|
||||
if (rr) LogMsg("Task Scheduling Error: NewLocalRecords %s", ARDisplayString(m, rr));
|
||||
}
|
||||
|
||||
if (m->NewLocalOnlyRecords) LogMsg("Task Scheduling Error: NewLocalOnlyRecords");
|
||||
|
||||
if (m->SPSProxyListChanged) LogMsg("Task Scheduling Error: SPSProxyListChanged");
|
||||
if (m->LocalRemoveEvents) LogMsg("Task Scheduling Error: LocalRemoveEvents");
|
||||
|
|
|
@ -164,7 +164,8 @@ extern mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *c
|
|||
extern mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
|
||||
extern mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
|
||||
extern mDNSBool AnyTypeRecordAnswersQuestion (const ResourceRecord *const rr, const DNSQuestion *const q);
|
||||
extern mDNSBool UnicastResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
|
||||
extern mDNSBool ResourceRecordAnswersUnicastResponse(const ResourceRecord *const rr, const DNSQuestion *const q);
|
||||
extern mDNSBool LocalOnlyRecordAnswersQuestion(AuthRecord *const rr, const DNSQuestion *const q);
|
||||
extern mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate);
|
||||
extern mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd);
|
||||
|
||||
|
@ -226,6 +227,7 @@ extern mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *ptr,
|
|||
#pragma mark - DNS Message Parsing Functions
|
||||
#endif
|
||||
|
||||
#define AuthHashSlot(X) (DomainNameHashValue(X) % AUTH_HASH_SLOTS)
|
||||
#define HashSlot(X) (DomainNameHashValue(X) % CACHE_HASH_SLOTS)
|
||||
extern mDNSu32 DomainNameHashValue(const domainname *const name);
|
||||
extern void SetNewRData(ResourceRecord *const rr, RData *NewRData, mDNSu16 rdlength);
|
||||
|
|
|
@ -1345,7 +1345,7 @@ mDNSexport void DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, DomainAuthI
|
|||
MD5_Update(&c, (mDNSu8 *)msg, (unsigned long)(*end - (mDNSu8 *)msg));
|
||||
|
||||
// Construct TSIG RR, digesting variables as apporpriate
|
||||
mDNS_SetupResourceRecord(&tsig, mDNSNULL, 0, kDNSType_TSIG, 0, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
|
||||
mDNS_SetupResourceRecord(&tsig, mDNSNULL, 0, kDNSType_TSIG, 0, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
|
||||
|
||||
// key name
|
||||
AssignDomainName(&tsig.namestorage, &info->keyname);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -112,7 +112,10 @@
|
|||
// In the event that structures are not packed correctly, mDNS_Init() will detect this and report an error, so the
|
||||
// developer will know what's wrong, and can investigate what needs to be done on that compiler to provide proper packing.
|
||||
#ifndef packedstruct
|
||||
#if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
|
||||
#ifdef __packed
|
||||
#define packedstruct struct __packed
|
||||
#define packedunion union __packed
|
||||
#elif ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
|
||||
#define packedstruct struct __attribute__((__packed__))
|
||||
#define packedunion union __attribute__((__packed__))
|
||||
#else
|
||||
|
@ -348,6 +351,7 @@ enum
|
|||
mStatus_NATPortMappingDisabled = -65565, // NAT supports NAT-PMP or UPnP but it's disabled by the administrator
|
||||
mStatus_NoRouter = -65566,
|
||||
mStatus_PollingMode = -65567,
|
||||
mStatus_Timeout = -65568,
|
||||
// -65568 to -65786 currently unused; available for allocation
|
||||
|
||||
// tcp connection status
|
||||
|
@ -406,6 +410,13 @@ typedef struct { mDNSu8 c[256]; } UTF8str255; // Null-terminated C string
|
|||
#define kStandardTTL (3600UL * 100 / 80)
|
||||
#define kHostNameTTL 120UL
|
||||
|
||||
// Some applications want to register their SRV records with a lower ttl so that in case the server
|
||||
// using a dynamic port number restarts, the clients will not have stale information for more than
|
||||
// 10 seconds
|
||||
|
||||
#define kHostNameSmallTTL 10UL
|
||||
|
||||
|
||||
// Multicast DNS uses announcements (gratuitous responses) to update peer caches.
|
||||
// This means it is feasible to use relatively larger TTL values than we might otherwise
|
||||
// use, because we have a cache coherency protocol to keep the peer caches up to date.
|
||||
|
@ -424,6 +435,7 @@ typedef struct AuthRecord_struct AuthRecord;
|
|||
typedef struct ServiceRecordSet_struct ServiceRecordSet;
|
||||
typedef struct CacheRecord_struct CacheRecord;
|
||||
typedef struct CacheGroup_struct CacheGroup;
|
||||
typedef struct AuthGroup_struct AuthGroup;
|
||||
typedef struct DNSQuestion_struct DNSQuestion;
|
||||
typedef struct ZoneData_struct ZoneData;
|
||||
typedef struct mDNS_struct mDNS;
|
||||
|
@ -1036,6 +1048,21 @@ enum
|
|||
DNSServer_FlagNew = 2
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
McastResolver_FlagDelete = 1,
|
||||
McastResolver_FlagNew = 2
|
||||
};
|
||||
|
||||
typedef struct McastResolver
|
||||
{
|
||||
struct McastResolver *next;
|
||||
mDNSInterfaceID interface;
|
||||
mDNSu32 flags; // Set when we're planning to delete this from the list
|
||||
domainname domain;
|
||||
mDNSu32 timeout; // timeout value for questions
|
||||
} McastResolver;
|
||||
|
||||
typedef struct DNSServer
|
||||
{
|
||||
struct DNSServer *next;
|
||||
|
@ -1050,6 +1077,7 @@ typedef struct DNSServer
|
|||
mDNSs32 penaltyTime; // amount of time this server is penalized
|
||||
mDNSBool scoped; // interface should be matched against question only
|
||||
// if scoped is set
|
||||
mDNSu32 timeout; // timeout value for questions
|
||||
} DNSServer;
|
||||
|
||||
typedef struct // Size is 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit
|
||||
|
@ -1108,6 +1136,45 @@ typedef enum
|
|||
mergeState_DontMerge = 1 // Set on fatal error conditions to disable merging
|
||||
} mergeState_t;
|
||||
|
||||
struct AuthGroup_struct // Header object for a list of AuthRecords with the same name
|
||||
{
|
||||
AuthGroup *next; // Next AuthGroup object in this hash table bucket
|
||||
mDNSu32 namehash; // Name-based (i.e. case insensitive) hash of name
|
||||
AuthRecord *members; // List of CacheRecords with this same name
|
||||
AuthRecord **rrauth_tail; // Tail end of that list
|
||||
domainname *name; // Common name for all AuthRecords in this list
|
||||
AuthRecord *NewLocalOnlyRecords;
|
||||
// Size to here is 20 bytes when compiling 32-bit; 40 bytes when compiling 64-bit
|
||||
mDNSu8 namestorage[InlineCacheGroupNameSize];
|
||||
};
|
||||
|
||||
#define AUTH_HASH_SLOTS 499
|
||||
#define FORALL_AUTHRECORDS(SLOT,AG,AR) \
|
||||
for ((SLOT) = 0; (SLOT) < AUTH_HASH_SLOTS; (SLOT)++) \
|
||||
for ((AG)=m->rrauth.rrauth_hash[(SLOT)]; (AG); (AG)=(AG)->next) \
|
||||
for ((AR) = (AG)->members; (AR); (AR)=(AR)->next)
|
||||
|
||||
typedef union AuthEntity_union AuthEntity;
|
||||
union AuthEntity_union { AuthEntity *next; AuthGroup ag; };
|
||||
typedef struct {
|
||||
mDNSu32 rrauth_size; // Total number of available auth entries
|
||||
mDNSu32 rrauth_totalused; // Number of auth entries currently occupied
|
||||
mDNSu32 rrauth_report;
|
||||
mDNSu8 rrauth_lock; // For debugging: Set at times when these lists may not be modified
|
||||
AuthEntity *rrauth_free;
|
||||
AuthGroup *rrauth_hash[AUTH_HASH_SLOTS];
|
||||
}AuthHash;
|
||||
|
||||
// AuthRecordAny includes mDNSInterface_Any and interface specific auth records (anything
|
||||
// other than P2P or LocalOnly)
|
||||
typedef enum
|
||||
{
|
||||
AuthRecordAny, // registered for *Any, NOT including P2P interfaces
|
||||
AuthRecordAnyIncludeP2P, // registered for *Any, including P2P interfaces
|
||||
AuthRecordLocalOnly,
|
||||
AuthRecordP2P // discovered over D2D/P2P framework
|
||||
} AuthRecType;
|
||||
|
||||
struct AuthRecord_struct
|
||||
{
|
||||
// For examples of how to set up this structure for use in mDNS_Register(),
|
||||
|
@ -1134,6 +1201,7 @@ struct AuthRecord_struct
|
|||
mDNSAddr AddressProxy; // For reverse-mapping Sleep Proxy PTR records, address in question
|
||||
mDNSs32 TimeRcvd; // In platform time units
|
||||
mDNSs32 TimeExpire; // In platform time units
|
||||
AuthRecType ARType; // LocalOnly, P2P or Normal ?
|
||||
|
||||
// Field Group 3: Transient state for Authoritative Records
|
||||
mDNSu8 Acknowledged; // Set if we've given the success callback to the client
|
||||
|
@ -1218,12 +1286,21 @@ struct AuthRecord_struct
|
|||
#define Question_uDNS(Q) ((Q)->InterfaceID == mDNSInterface_Unicast || \
|
||||
((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname)))
|
||||
|
||||
#define RRLocalOnly(rr) ((rr)->ARType == AuthRecordLocalOnly || (rr)->ARType == AuthRecordP2P)
|
||||
|
||||
#define RRAny(rr) ((rr)->ARType == AuthRecordAny || (rr)->ARType == AuthRecordAnyIncludeP2P)
|
||||
|
||||
// Question (A or AAAA) that is suppressed currently because IPv4 or IPv6 address
|
||||
// is not available locally for A or AAAA question respectively
|
||||
#define QuerySuppressed(Q) ((Q)->SuppressUnusable && (Q)->SuppressQuery)
|
||||
|
||||
#define PrivateQuery(Q) ((Q)->AuthInfo && (Q)->AuthInfo->AutoTunnel)
|
||||
|
||||
// Normally we always lookup the cache and /etc/hosts before sending the query on the wire. For single label
|
||||
// queries (A and AAAA) that are unqualified (indicated by AppendSearchDomains), we want to append search
|
||||
// domains before we try them as such
|
||||
#define ApplySearchDomainsFirst(q) ((q)->AppendSearchDomains && (CountLabels(&((q)->qname))) == 1)
|
||||
|
||||
// Wrapper struct for Auth Records for higher-level code that cannot use the AuthRecord's ->next pointer field
|
||||
typedef struct ARListElem
|
||||
{
|
||||
|
@ -1242,6 +1319,7 @@ struct CacheGroup_struct // Header object for a list of CacheRecords with the
|
|||
mDNSu8 namestorage[InlineCacheGroupNameSize];
|
||||
};
|
||||
|
||||
|
||||
struct CacheRecord_struct
|
||||
{
|
||||
CacheRecord *next; // Next in list; first element of structure for efficiency reasons
|
||||
|
@ -1391,25 +1469,29 @@ enum { NoAnswer_Normal = 0, NoAnswer_Suspended = 1, NoAnswer_Fail = 2 };
|
|||
#define MD5_LEN 16
|
||||
|
||||
#define AutoTunnelUnregistered(X) ( \
|
||||
(X)->AutoTunnelHostRecord.resrec.RecordType == kDNSRecordTypeUnregistered && \
|
||||
(X)->AutoTunnelDeviceInfo.resrec.RecordType == kDNSRecordTypeUnregistered && \
|
||||
(X)->AutoTunnelService. resrec.RecordType == kDNSRecordTypeUnregistered && \
|
||||
(X)->AutoTunnel6Record. resrec.RecordType == kDNSRecordTypeUnregistered )
|
||||
(X)->AutoTunnelHostRecord. resrec.RecordType == kDNSRecordTypeUnregistered && \
|
||||
(X)->AutoTunnelDeviceInfo. resrec.RecordType == kDNSRecordTypeUnregistered && \
|
||||
(X)->AutoTunnelService. resrec.RecordType == kDNSRecordTypeUnregistered && \
|
||||
(X)->AutoTunnel6Record. resrec.RecordType == kDNSRecordTypeUnregistered && \
|
||||
(X)->AutoTunnel6MetaRecord.resrec.RecordType == kDNSRecordTypeUnregistered )
|
||||
|
||||
// Internal data structure to maintain authentication information
|
||||
typedef struct DomainAuthInfo
|
||||
{
|
||||
struct DomainAuthInfo *next;
|
||||
mDNSs32 deltime; // If we're planning to delete this DomainAuthInfo, the time we want it deleted
|
||||
mDNSBool AutoTunnel;
|
||||
const char* AutoTunnel; // If NULL, this is not an AutoTunnel DAI. Otherwise, this is prepended to the IPSec identifier
|
||||
AuthRecord AutoTunnelHostRecord; // User-visible hostname; used as SRV target for AutoTunnel services
|
||||
AuthRecord AutoTunnelTarget; // Opaque hostname of tunnel endpoint; used as SRV target for AutoTunnelService record
|
||||
AuthRecord AutoTunnelDeviceInfo; // Device info of tunnel endpoint
|
||||
AuthRecord AutoTunnelService; // Service record (possibly NAT-Mapped) of IKE daemon implementing tunnel endpoint
|
||||
AuthRecord AutoTunnel6Record; // AutoTunnel AAAA Record obtained from Connectivityd
|
||||
AuthRecord AutoTunnel6Record; // AutoTunnel AAAA record obtained from awacsd
|
||||
AuthRecord AutoTunnel6MetaRecord; // Notify remote peers to connect to the relay servers for potential outbound connections from this host
|
||||
NATTraversalInfo AutoTunnelNAT;
|
||||
domainname domain;
|
||||
domainname keyname;
|
||||
domainname hostname;
|
||||
mDNSIPPort port;
|
||||
char b64keydata[32];
|
||||
mDNSu8 keydata_ipad[HMAC_LEN]; // padded key for inner hash rounds
|
||||
mDNSu8 keydata_opad[HMAC_LEN]; // padded key for outer hash rounds
|
||||
|
@ -1452,6 +1534,10 @@ struct DNSQuestion_struct
|
|||
mDNSs32 LastQTxTime; // Last time this Q was sent on one (but not necessarily all) interfaces
|
||||
mDNSu32 CNAMEReferrals; // Count of how many CNAME redirections we've done
|
||||
mDNSBool SuppressQuery; // This query should be suppressed and not sent on the wire
|
||||
mDNSu8 LOAddressAnswers; // Number of answers from the local only auth records that are
|
||||
// answering A, AAAA and CNAME (/etc/hosts)
|
||||
mDNSu8 WakeOnResolveCount; // Number of wakes that should be sent on resolve
|
||||
mDNSs32 StopTime; // Time this question should be stopped by giving them a negative answer
|
||||
|
||||
// Wide Area fields. These are used internally by the uDNS core
|
||||
UDPSocket *LocalSocket;
|
||||
|
@ -1460,7 +1546,7 @@ struct DNSQuestion_struct
|
|||
mDNSOpaque64 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
|
||||
mDNSu8 unansweredQueries;// The number of unanswered queries to this server
|
||||
|
||||
ZoneData *nta; // Used for getting zone data for private or LLQ query
|
||||
mDNSAddr servAddr; // Address and port learned from _dns-llq, _dns-llq-tls or _dns-query-tls SRV query
|
||||
|
@ -1493,6 +1579,13 @@ 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 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
|
||||
mDNSs8 SearchListIndex; // Index into SearchList; Used by the client layer but not touched by core
|
||||
mDNSs8 AppendSearchDomains; // Search domains can be appended for this query
|
||||
mDNSs8 AppendLocalSearchDomains; // Search domains ending in .local can be appended for this query
|
||||
domainname *qnameOrig; // Copy of the original question name if it is not fully qualified
|
||||
mDNSQuestionCallback *QuestionCallback;
|
||||
void *QuestionContext;
|
||||
};
|
||||
|
@ -1555,6 +1648,7 @@ struct ZoneData_struct
|
|||
|
||||
extern ZoneData *StartGetZoneData(mDNS *const m, const domainname *const name, const ZoneService target, ZoneDataCallback callback, void *callbackInfo);
|
||||
extern void CancelGetZoneData(mDNS *const m, ZoneData *nta);
|
||||
extern mDNSBool IsGetZoneDataQuestion(DNSQuestion *q);
|
||||
|
||||
typedef struct DNameListElem
|
||||
{
|
||||
|
@ -1573,6 +1667,7 @@ typedef struct DNameListElem
|
|||
typedef struct ClientTunnel
|
||||
{
|
||||
struct ClientTunnel *next;
|
||||
const char *prefix;
|
||||
domainname dstname;
|
||||
mDNSBool MarkedForDeletion;
|
||||
mDNSv6Addr loc_inner;
|
||||
|
@ -1634,20 +1729,24 @@ struct NetworkInterfaceInfo_struct
|
|||
mDNSu8 Advertise; // False if you are only searching on this interface
|
||||
mDNSu8 McastTxRx; // Send/Receive multicast on this { InterfaceID, address family } ?
|
||||
mDNSu8 NetWake; // Set if Wake-On-Magic-Packet is enabled on this interface
|
||||
mDNSu8 Loopback; // Set if this is the loopback interface
|
||||
};
|
||||
|
||||
#define SLE_DELETE 0x00000001
|
||||
#define SLE_WAB_QUERY_STARTED 0x00000002
|
||||
|
||||
typedef struct SearchListElem
|
||||
{
|
||||
struct SearchListElem *next;
|
||||
domainname domain;
|
||||
int flag; // -1 means delete, 0 means unchanged, +1 means newly added
|
||||
int flag;
|
||||
mDNSInterfaceID InterfaceID;
|
||||
DNSQuestion BrowseQ;
|
||||
DNSQuestion DefBrowseQ;
|
||||
DNSQuestion AutomaticBrowseQ;
|
||||
DNSQuestion RegisterQ;
|
||||
DNSQuestion DefRegisterQ;
|
||||
DNSQuestion DirQ;
|
||||
int numDirAnswers;
|
||||
int numCfAnswers;
|
||||
ARListElem *AuthRecs;
|
||||
} SearchListElem;
|
||||
|
||||
|
@ -1670,9 +1769,8 @@ typedef void mDNSCallback(mDNS *const m, mStatus result);
|
|||
|
||||
enum // Bit flags -- i.e. values should be 1, 2, 4, 8, etc.
|
||||
{
|
||||
mDNS_KnownBug_PhantomInterfaces = 1,
|
||||
mDNS_KnownBug_LimitedIPv6 = 2,
|
||||
mDNS_KnownBug_LossySyslog = 4 // <rdar://problem/6561888>
|
||||
mDNS_KnownBug_LimitedIPv6 = 1,
|
||||
mDNS_KnownBug_LossySyslog = 2 // <rdar://problem/6561888>
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -1741,12 +1839,15 @@ struct mDNS_struct
|
|||
mDNSs32 NextScheduledSPRetry; // Time next sleep proxy registration action is required.
|
||||
// Only valid if SleepLimit is nonzero and DelaySleep is zero.
|
||||
|
||||
mDNSs32 NextScheduledStopTime; // Next time to stop a question
|
||||
|
||||
// These fields only required for mDNS Searcher...
|
||||
DNSQuestion *Questions; // List of all registered questions, active and inactive
|
||||
DNSQuestion *NewQuestions; // Fresh questions not yet answered from cache
|
||||
DNSQuestion *CurrentQuestion; // Next question about to be examined in AnswerLocalQuestions()
|
||||
DNSQuestion *LocalOnlyQuestions; // Questions with InterfaceID set to mDNSInterface_LocalOnly or mDNSInterface_P2P
|
||||
DNSQuestion *NewLocalOnlyQuestions; // Fresh local-only or P2P questions not yet answered
|
||||
DNSQuestion *RestartQuestion; // Questions that are being restarted (stop followed by start)
|
||||
mDNSu32 rrcache_size; // Total number of available cache entries
|
||||
mDNSu32 rrcache_totalused; // Number of cache entries currently occupied
|
||||
mDNSu32 rrcache_active; // Number of cache entries currently occupied by records that answer active questions
|
||||
|
@ -1755,6 +1856,8 @@ struct mDNS_struct
|
|||
CacheGroup *rrcache_hash[CACHE_HASH_SLOTS];
|
||||
mDNSs32 rrcache_nextcheck[CACHE_HASH_SLOTS];
|
||||
|
||||
AuthHash rrauth;
|
||||
|
||||
// Fields below only required for mDNS Responder...
|
||||
domainlabel nicelabel; // Rich text label encoded using canonically precomposed UTF-8
|
||||
domainlabel hostlabel; // Conforms to RFC 1034 "letter-digit-hyphen" ARPANET host name rules
|
||||
|
@ -1764,8 +1867,9 @@ struct mDNS_struct
|
|||
AuthRecord DeviceInfo;
|
||||
AuthRecord *ResourceRecords;
|
||||
AuthRecord *DuplicateRecords; // Records currently 'on hold' because they are duplicates of existing records
|
||||
AuthRecord *NewLocalRecords; // Fresh AuthRecords (both local-only and public) not yet delivered to our local-only questions
|
||||
AuthRecord *NewLocalRecords; // Fresh AuthRecords (public) not yet delivered to our local-only questions
|
||||
AuthRecord *CurrentRecord; // Next AuthRecord about to be examined
|
||||
mDNSBool NewLocalOnlyRecords; // Fresh AuthRecords (local only) not yet delivered to our local questions
|
||||
NetworkInterfaceInfo *HostInterfaces;
|
||||
mDNSs32 ProbeFailTime;
|
||||
mDNSu32 NumFailedProbes;
|
||||
|
@ -1776,6 +1880,7 @@ struct mDNS_struct
|
|||
mDNSs32 NextSRVUpdate; // Time to perform delayed update
|
||||
|
||||
DNSServer *DNSServers; // list of DNS servers
|
||||
McastResolver *McastResolvers; // list of Mcast Resolvers
|
||||
|
||||
mDNSAddr Router;
|
||||
mDNSAddr AdvertisedV4; // IPv4 address pointed to by hostname
|
||||
|
@ -1790,10 +1895,15 @@ struct mDNS_struct
|
|||
HostnameInfo *Hostnames; // List of registered hostnames + hostname metadata
|
||||
mDNSv6Addr AutoTunnelHostAddr; // IPv6 address advertised for AutoTunnel services on this machine
|
||||
mDNSBool AutoTunnelHostAddrActive;
|
||||
mDNSv6Addr AutoTunnelRelayAddr; // IPv6 address advertised for AutoTunnel Relay services on this machine
|
||||
// AutoTunnel Relay address has two distinct uses
|
||||
// AutoTunnelRelayAddrIn: If non-zero, it means that this host can be reached (inbound connection) through the relay
|
||||
// AutoTunnelRelayAddrOut: If non-zero, it means that this host can use the relay to reach (outbound connection) the
|
||||
// other hosts through the relay
|
||||
mDNSv6Addr AutoTunnelRelayAddrIn;
|
||||
mDNSv6Addr AutoTunnelRelayAddrOut;
|
||||
domainlabel AutoTunnelLabel; // Used to construct hostname for *IPv4* address of tunnel endpoints
|
||||
|
||||
mDNSBool RegisterSearchDomains;
|
||||
mDNSBool StartWABQueries; // Start WAB queries for the purpose of domain enumeration
|
||||
mDNSBool RegisterAutoTunnel6;
|
||||
|
||||
// NAT-Traversal fields
|
||||
|
@ -2027,6 +2137,7 @@ 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)
|
||||
|
@ -2098,14 +2209,21 @@ typedef enum { mDNS_Dereg_normal, mDNS_Dereg_rapid, mDNS_Dereg_conflict, mDNS_De
|
|||
// and the default domain in which to register in the case where the user has made no selection.
|
||||
|
||||
extern void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID,
|
||||
mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, mDNSRecordCallback Callback, void *Context);
|
||||
mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, AuthRecType artype, mDNSRecordCallback Callback, void *Context);
|
||||
|
||||
// mDNS_RegisterService() flags parameter bit definitions
|
||||
enum
|
||||
{
|
||||
regFlagIncludeP2P = 0x1, // include P2P interfaces when using mDNSInterface_Any
|
||||
regFlagKnownUnique = 0x2 // client guarantees that SRV and TXT record names are unique
|
||||
};
|
||||
|
||||
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,
|
||||
AuthRecord *SubTypes, mDNSu32 NumSubTypes,
|
||||
const mDNSInterfaceID InterfaceID, mDNSServiceCallback Callback, void *Context);
|
||||
extern mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl);
|
||||
mDNSInterfaceID InterfaceID, mDNSServiceCallback Callback, void *Context, mDNSu32 flags);
|
||||
extern mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl, mDNSu32 includeP2P);
|
||||
extern mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, mDNSRecordCallback MemFreeCallback, void *Context);
|
||||
extern mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname);
|
||||
extern mStatus mDNS_DeregisterService_drt(mDNS *const m, ServiceRecordSet *sr, mDNS_Dereg_type drt);
|
||||
|
@ -2114,7 +2232,7 @@ extern mStatus mDNS_DeregisterService_drt(mDNS *const m, ServiceRecordSet *sr, m
|
|||
extern mStatus mDNS_RegisterNoSuchService(mDNS *const m, AuthRecord *const rr,
|
||||
const domainlabel *const name, const domainname *const type, const domainname *const domain,
|
||||
const domainname *const host,
|
||||
const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context);
|
||||
const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context, mDNSBool includeP2P);
|
||||
#define mDNS_DeregisterNoSuchService mDNS_Deregister
|
||||
|
||||
extern void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID InterfaceID, const domainname *const name,
|
||||
|
@ -2152,7 +2270,7 @@ extern mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID I
|
|||
|
||||
extern DNSServer *GetServerForName(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID);
|
||||
extern DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question);
|
||||
extern void SetValidDNSServers(mDNS *m, DNSQuestion *question);
|
||||
extern mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question);
|
||||
|
||||
// ***************************************************************************
|
||||
#if 0
|
||||
|
@ -2314,9 +2432,6 @@ extern mDNSBool mDNSv4AddrIsRFC1918(mDNSv4Addr *addr); // returns true for RFC1
|
|||
#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
|
||||
#pragma mark -
|
||||
|
@ -2330,10 +2445,11 @@ extern mDNSBool mDNSv4AddrIsRFC1918(mDNSv4Addr *addr); // returns true for RFC1
|
|||
// domain name format. The shared secret must be a null-terminated base64 encoded string. A minimum size of
|
||||
// 16 bytes (128 bits) is recommended for an MD5 hash as per RFC 2485.
|
||||
// Calling this routine multiple times for a zone replaces previously entered values. Call with a NULL key
|
||||
// to dissable authentication for the zone.
|
||||
// to disable authentication for the zone. A non-NULL autoTunnelPrefix means this is an AutoTunnel domain,
|
||||
// and the value is prepended to the IPSec identifier (used for key lookup)
|
||||
|
||||
extern mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
|
||||
const domainname *domain, const domainname *keyname, const char *b64keydata, mDNSBool AutoTunnel);
|
||||
const domainname *domain, const domainname *keyname, const char *b64keydata, const domainname *hostname, mDNSIPPort *port, const char *autoTunnelPrefix);
|
||||
|
||||
extern void RecreateNATMappings(mDNS *const m);
|
||||
|
||||
|
@ -2357,13 +2473,15 @@ extern void RecreateNATMappings(mDNS *const m);
|
|||
extern void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext);
|
||||
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, const mDNSAddr *addr, const mDNSIPPort port, mDNSBool scoped);
|
||||
extern DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port, mDNSBool scoped, mDNSu32 timeout);
|
||||
extern void PenalizeDNSServer(mDNS *const m, DNSQuestion *q);
|
||||
extern void mDNS_AddSearchDomain(const domainname *const domain);
|
||||
extern void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID);
|
||||
|
||||
extern McastResolver *mDNS_AddMcastResolver(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSu32 timeout);
|
||||
|
||||
// We use ((void *)0) here instead of mDNSNULL to avoid compile warnings on gcc 4.2
|
||||
#define mDNS_AddSearchDomain_CString(X) \
|
||||
do { domainname d__; if (((X) != (void*)0) && MakeDomainNameFromDNSNameString(&d__, (X)) && d__.c[0]) mDNS_AddSearchDomain(&d__); } while(0)
|
||||
#define mDNS_AddSearchDomain_CString(X, I) \
|
||||
do { domainname d__; if (((X) != (void*)0) && MakeDomainNameFromDNSNameString(&d__, (X)) && d__.c[0]) mDNS_AddSearchDomain(&d__, I); } while(0)
|
||||
|
||||
// Routines called by the core, exported by DNSDigest.c
|
||||
|
||||
|
@ -2478,7 +2596,7 @@ mDNSexport void mDNSASLLog(uuid_t *uuid, const char *subdomain, const char *resu
|
|||
// 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.
|
||||
extern mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex);
|
||||
extern mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id);
|
||||
extern mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange);
|
||||
|
||||
// Every platform support module must provide the following functions if it is to support unicast DNS
|
||||
// and Dynamic Update.
|
||||
|
@ -2531,7 +2649,9 @@ extern void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, m
|
|||
extern mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *router);
|
||||
extern void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status);
|
||||
|
||||
extern void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep);
|
||||
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 mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf);
|
||||
|
||||
#ifdef _LEGACY_NAT_TRAVERSAL_
|
||||
// Support for legacy NAT traversal protocols, implemented by the platform layer and callable by the core.
|
||||
|
@ -2587,7 +2707,11 @@ extern void mDNSCoreInitComplete(mDNS *const m, mStatus result);
|
|||
extern void mDNSCoreReceive(mDNS *const m, void *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);
|
||||
extern void mDNSCoreRestartQueries(mDNS *const m);
|
||||
typedef void (*FlushCache)(mDNS *const m);
|
||||
typedef void (*CallbackBeforeStartQuery)(mDNS *const m, void *context);
|
||||
extern void mDNSCoreRestartAddressQueries(mDNS *const m, mDNSBool SearchDomainsChanged, FlushCache flushCacheRecords,
|
||||
CallbackBeforeStartQuery beforeQueryStart, void *context);
|
||||
extern mDNSBool mDNSCoreHaveAdvertisedMulticastServices(mDNS *const m);
|
||||
extern void mDNSCoreMachineSleep(mDNS *const m, mDNSBool wake);
|
||||
extern mDNSBool mDNSCoreReadyForSleep(mDNS *m, mDNSs32 now);
|
||||
|
@ -2606,9 +2730,19 @@ extern void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr,
|
|||
extern void CompleteDeregistration(mDNS *const m, AuthRecord *rr);
|
||||
extern void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord);
|
||||
extern char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID);
|
||||
extern void DNSServerChangeForQuestion(mDNS *const m, DNSQuestion *q, DNSServer *new);
|
||||
extern void DNSServerChangeForQuestion(mDNS *const m, DNSQuestion *q, DNSServer *newServer);
|
||||
extern void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr);
|
||||
extern void CheckSuppressUnusableQuestions(mDNS *const m);
|
||||
extern void RetrySearchDomainQuestions(mDNS *const m);
|
||||
|
||||
// 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 *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);
|
||||
|
||||
// For now this AutoTunnel 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
|
||||
|
@ -2619,7 +2753,6 @@ extern void SetupLocalAutoTunnelInterface_internal(mDNS *const m, mDNSBool servi
|
|||
extern void UpdateAutoTunnelDomainStatuses(const mDNS *const m);
|
||||
extern mStatus ActivateLocalProxy(mDNS *const m, char *ifname);
|
||||
extern void RemoveAutoTunnel6Record(mDNS *const m);
|
||||
extern void SetupConndConfigChanges(mDNS *const m);
|
||||
extern mDNSBool RecordReadyForSleep(mDNS *const m, AuthRecord *rr);
|
||||
#endif
|
||||
|
||||
|
@ -2741,6 +2874,17 @@ extern mDNSBool RecordReadyForSleep(mDNS *const m, AuthRecord *rr);
|
|||
// 60 = 1 W
|
||||
// 90 = 1 kW
|
||||
|
||||
typedef enum
|
||||
{
|
||||
mDNSSleepProxyMetric_Dedicated = 20,
|
||||
mDNSSleepProxyMetric_PrimaryHardware = 30,
|
||||
mDNSSleepProxyMetric_PrimarySoftware = 40,
|
||||
mDNSSleepProxyMetric_SecondaryHardware = 50,
|
||||
mDNSSleepProxyMetric_SecondarySoftware = 60,
|
||||
mDNSSleepProxyMetric_IncidentalHardware = 70,
|
||||
mDNSSleepProxyMetric_IncidentalSoftware = 80
|
||||
} mDNSSleepProxyMetric;
|
||||
|
||||
extern void mDNSCoreBeSleepProxyServer_internal(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower);
|
||||
#define mDNSCoreBeSleepProxyServer(M,S,P,MP,TP) \
|
||||
do { mDNS_Lock(m); mDNSCoreBeSleepProxyServer_internal((M),(S),(P),(MP),(TP)); mDNS_Unlock(m); } while(0)
|
||||
|
@ -2801,17 +2945,17 @@ struct CompileTimeAssertionChecks_mDNS
|
|||
char sizecheck_AuthRecord [(sizeof(AuthRecord) <= 1208) ? 1 : -1];
|
||||
char sizecheck_CacheRecord [(sizeof(CacheRecord) <= 184) ? 1 : -1];
|
||||
char sizecheck_CacheGroup [(sizeof(CacheGroup) <= 184) ? 1 : -1];
|
||||
char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 752) ? 1 : -1];
|
||||
char sizecheck_ZoneData [(sizeof(ZoneData) <= 1588) ? 1 : -1];
|
||||
char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 786) ? 1 : -1];
|
||||
char sizecheck_ZoneData [(sizeof(ZoneData) <= 1624) ? 1 : -1];
|
||||
char sizecheck_NATTraversalInfo [(sizeof(NATTraversalInfo) <= 192) ? 1 : -1];
|
||||
char sizecheck_HostnameInfo [(sizeof(HostnameInfo) <= 3050) ? 1 : -1];
|
||||
char sizecheck_DNSServer [(sizeof(DNSServer) <= 320) ? 1 : -1];
|
||||
char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 6750) ? 1 : -1];
|
||||
char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 6850) ? 1 : -1];
|
||||
char sizecheck_ServiceRecordSet [(sizeof(ServiceRecordSet) <= 5500) ? 1 : -1];
|
||||
char sizecheck_DomainAuthInfo [(sizeof(DomainAuthInfo) <= 7550) ? 1 : -1];
|
||||
char sizecheck_ServiceInfoQuery [(sizeof(ServiceInfoQuery) <= 3050) ? 1 : -1];
|
||||
char sizecheck_DomainAuthInfo [(sizeof(DomainAuthInfo) <= 7968) ? 1 : -1];
|
||||
char sizecheck_ServiceInfoQuery [(sizeof(ServiceInfoQuery) <= 3200) ? 1 : -1];
|
||||
#if APPLE_OSX_mDNSResponder
|
||||
char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1104) ? 1 : -1];
|
||||
char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1148) ? 1 : -1];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
* Any dynamic run-time requirements should be handled by the platform layer below or client layer above
|
||||
*/
|
||||
|
||||
#if APPLE_OSX_mDNSResponder
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
#include "uDNS.h"
|
||||
|
||||
#if(defined(_MSC_VER))
|
||||
|
@ -98,7 +101,7 @@ mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mDNSu32 random)
|
|||
#pragma mark - Name Server List Management
|
||||
#endif
|
||||
|
||||
mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port, mDNSBool scoped)
|
||||
mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port, mDNSBool scoped, mDNSu32 timeout)
|
||||
{
|
||||
DNSServer **p = &m->DNSServers;
|
||||
DNSServer *tmp = mDNSNULL;
|
||||
|
@ -146,6 +149,7 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons
|
|||
(*p)->flags = DNSServer_FlagNew;
|
||||
(*p)->teststate = /* DNSServer_Untested */ DNSServer_Passed;
|
||||
(*p)->lasttest = m->timenow - INIT_UCAST_POLL_INTERVAL;
|
||||
(*p)->timeout = timeout;
|
||||
AssignDomainName(&(*p)->domain, d);
|
||||
(*p)->next = mDNSNULL;
|
||||
}
|
||||
|
@ -345,17 +349,25 @@ mDNSexport DomainAuthInfo *GetAuthInfoForName(mDNS *m, const domainname *const n
|
|||
|
||||
// MUST be called with the lock held
|
||||
mDNSexport mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
|
||||
const domainname *domain, const domainname *keyname, const char *b64keydata, mDNSBool AutoTunnel)
|
||||
const domainname *domain, const domainname *keyname, const char *b64keydata, const domainname *hostname, mDNSIPPort *port, const char *autoTunnelPrefix)
|
||||
{
|
||||
DNSQuestion *q;
|
||||
DomainAuthInfo **p = &m->AuthInfoList;
|
||||
if (!info || !b64keydata) { LogMsg("mDNS_SetSecretForDomain: ERROR: info %p b64keydata %p", info, b64keydata); return(mStatus_BadParamErr); }
|
||||
|
||||
LogInfo("mDNS_SetSecretForDomain: domain %##s key %##s%s", domain->c, keyname->c, AutoTunnel ? " AutoTunnel" : "");
|
||||
LogInfo("mDNS_SetSecretForDomain: domain %##s key %##s%s%s", domain->c, keyname->c, autoTunnelPrefix ? " prefix " : "", autoTunnelPrefix ? autoTunnelPrefix : "");
|
||||
|
||||
info->AutoTunnel = AutoTunnel;
|
||||
info->AutoTunnel = autoTunnelPrefix;
|
||||
AssignDomainName(&info->domain, domain);
|
||||
AssignDomainName(&info->keyname, keyname);
|
||||
if (hostname)
|
||||
AssignDomainName(&info->hostname, hostname);
|
||||
else
|
||||
info->hostname.c[0] = 0;
|
||||
if (port)
|
||||
info->port = *port;
|
||||
else
|
||||
info->port = zeroIPPort;
|
||||
mDNS_snprintf(info->b64keydata, sizeof(info->b64keydata), "%s", b64keydata);
|
||||
|
||||
if (DNSDigest_ConstructHMACKeyfromBase64(info, b64keydata) < 0)
|
||||
|
@ -372,12 +384,13 @@ mDNSexport mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
|
|||
|
||||
// Caution: Only zero AutoTunnelHostRecord.namestorage and AutoTunnelNAT.clientContext AFTER we've determined that this is a NEW DomainAuthInfo
|
||||
// being added to the list. Otherwise we risk smashing our AutoTunnel host records and NATOperation that are already active and in use.
|
||||
info->AutoTunnelHostRecord.resrec.RecordType = kDNSRecordTypeUnregistered;
|
||||
info->AutoTunnelHostRecord.namestorage.c[0] = 0;
|
||||
info->AutoTunnelTarget .resrec.RecordType = kDNSRecordTypeUnregistered;
|
||||
info->AutoTunnelDeviceInfo.resrec.RecordType = kDNSRecordTypeUnregistered;
|
||||
info->AutoTunnelService .resrec.RecordType = kDNSRecordTypeUnregistered;
|
||||
info->AutoTunnel6Record .resrec.RecordType = kDNSRecordTypeUnregistered;
|
||||
info->AutoTunnelHostRecord .resrec.RecordType = kDNSRecordTypeUnregistered;
|
||||
info->AutoTunnelHostRecord .namestorage.c[0] = 0;
|
||||
info->AutoTunnelTarget .resrec.RecordType = kDNSRecordTypeUnregistered;
|
||||
info->AutoTunnelDeviceInfo .resrec.RecordType = kDNSRecordTypeUnregistered;
|
||||
info->AutoTunnelService .resrec.RecordType = kDNSRecordTypeUnregistered;
|
||||
info->AutoTunnel6Record .resrec.RecordType = kDNSRecordTypeUnregistered;
|
||||
info->AutoTunnel6MetaRecord.resrec.RecordType = kDNSRecordTypeUnregistered;
|
||||
info->AutoTunnelNAT.clientContext = mDNSNULL;
|
||||
info->next = mDNSNULL;
|
||||
*p = info;
|
||||
|
@ -553,6 +566,9 @@ mDNSexport mStatus mDNS_StartNATOperation_internal(mDNS *const m, NATTraversalIn
|
|||
{
|
||||
LogMsg("Error! Tried to add a NAT traversal that's already in the active list: request %p Prot %d Int %d TTL %d",
|
||||
traversal, traversal->Protocol, mDNSVal16(traversal->IntPort), traversal->NATLease);
|
||||
#if ForceAlerts
|
||||
*(long*)0 = 0;
|
||||
#endif
|
||||
return(mStatus_AlreadyRegistered);
|
||||
}
|
||||
if (traversal->Protocol && traversal->Protocol == (*n)->Protocol && mDNSSameIPPort(traversal->IntPort, (*n)->IntPort) &&
|
||||
|
@ -698,7 +714,7 @@ mDNSlocal mDNSu8 *putLLQ(DNSMessage *const msg, mDNSu8 *ptr, const DNSQuestion *
|
|||
// !!!KRS implement me
|
||||
|
||||
// format opt rr (fields not specified are zero-valued)
|
||||
mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
|
||||
mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
|
||||
opt->rrclass = NormalMaxDNSMessageData;
|
||||
opt->rdlength = sizeof(rdataOPT); // One option in this OPT record
|
||||
opt->rdestimate = sizeof(rdataOPT);
|
||||
|
@ -1572,6 +1588,12 @@ mDNSlocal mStatus GetZoneData_StartQuery(mDNS *const m, ZoneData *zd, mDNSu16 qt
|
|||
zd->question.ForceMCast = mDNSfalse;
|
||||
zd->question.ReturnIntermed = mDNStrue;
|
||||
zd->question.SuppressUnusable = mDNSfalse;
|
||||
zd->question.SearchListIndex = 0;
|
||||
zd->question.AppendSearchDomains = 0;
|
||||
zd->question.RetryWithSearchDomains = mDNSfalse;
|
||||
zd->question.TimeoutQuestion = 0;
|
||||
zd->question.WakeOnResolve = 0;
|
||||
zd->question.qnameOrig = mDNSNULL;
|
||||
zd->question.QuestionCallback = GetZoneData_QuestionCallback;
|
||||
zd->question.QuestionContext = zd;
|
||||
|
||||
|
@ -1600,15 +1622,46 @@ mDNSexport ZoneData *StartGetZoneData(mDNS *const m, const domainname *const nam
|
|||
zd->ZoneDataContext = ZoneDataContext;
|
||||
|
||||
zd->question.QuestionContext = zd;
|
||||
AssignDomainName(&zd->question.qname, zd->CurrentSOA);
|
||||
|
||||
mDNS_DropLockBeforeCallback(); // GetZoneData_StartQuery expects to be called from a normal callback, so we emulate that here
|
||||
GetZoneData_StartQuery(m, zd, kDNSType_SOA);
|
||||
if (AuthInfo && AuthInfo->AutoTunnel && !mDNSIPPortIsZero(AuthInfo->port))
|
||||
{
|
||||
LogInfo("StartGetZoneData: Bypassing SOA, SRV query for %##s", AuthInfo->domain.c);
|
||||
// We bypass SOA and SRV queries if we know the hostname and port already from the configuration.
|
||||
// Today this is only true for AutoTunnel. As we bypass, we need to infer a few things:
|
||||
//
|
||||
// 1. Zone name is the same as the AuthInfo domain
|
||||
// 2. ZoneClass is kDNSClass_IN which should be a safe assumption
|
||||
//
|
||||
// If we want to make this bypass mechanism work for non-AutoTunnels also, (1) has to hold
|
||||
// good. Otherwise, it has to be configured also.
|
||||
|
||||
AssignDomainName(&zd->ZoneName, &AuthInfo->domain);
|
||||
zd->ZoneClass = kDNSClass_IN;
|
||||
AssignDomainName(&zd->Host, &AuthInfo->hostname);
|
||||
zd->Port = AuthInfo->port;
|
||||
AssignDomainName(&zd->question.qname, &zd->Host);
|
||||
GetZoneData_StartQuery(m, zd, kDNSType_A);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AuthInfo && AuthInfo->AutoTunnel) LogInfo("StartGetZoneData: Not Bypassing SOA, SRV query for %##s", AuthInfo->domain.c);
|
||||
AssignDomainName(&zd->question.qname, zd->CurrentSOA);
|
||||
GetZoneData_StartQuery(m, zd, kDNSType_SOA);
|
||||
}
|
||||
mDNS_ReclaimLockAfterCallback();
|
||||
|
||||
return zd;
|
||||
}
|
||||
|
||||
// Returns if the question is a GetZoneData question. These questions are special in
|
||||
// that they are created internally while resolving a private query or LLQs.
|
||||
mDNSexport mDNSBool IsGetZoneDataQuestion(DNSQuestion *q)
|
||||
{
|
||||
if (q->QuestionCallback == GetZoneData_QuestionCallback) return(mDNStrue);
|
||||
else return(mDNSfalse);
|
||||
}
|
||||
|
||||
// GetZoneData queries are a special case -- even if we have a key for them, we don't do them privately,
|
||||
// because that would result in an infinite loop (i.e. to do a private query we first need to get
|
||||
// the _dns-query-tls SRV record for the zone, and we can't do *that* privately because to do so
|
||||
|
@ -1664,7 +1717,7 @@ mDNSlocal void UpdateAllServiceRecords(mDNS *const m, AuthRecord *rr, mDNSBool r
|
|||
}
|
||||
else
|
||||
{
|
||||
// Clearing SRVchanged is a safety measure. If our pewvious dereg never
|
||||
// Clearing SRVchanged is a safety measure. If our pevious dereg never
|
||||
// came back and we had a target change, we are starting fresh
|
||||
r->SRVChanged = mDNSfalse;
|
||||
// if it is already registered or in the process of registering, then don't
|
||||
|
@ -1709,7 +1762,7 @@ mDNSlocal void CompleteRecordNatMap(mDNS *m, NATTraversalInfo *n)
|
|||
if (!rr->nta || mDNSIPv4AddressIsZero(rr->nta->Addr.ip.v4))
|
||||
{
|
||||
LogInfo("CompleteRecordNatMap called for %s but no zone information!", ARDisplayString(m, rr));
|
||||
// We need to clear out the NATinfo state so that it will result in re-acuqiring the mapping
|
||||
// We need to clear out the NATinfo state so that it will result in re-acquiring the mapping
|
||||
// and hence this callback called again.
|
||||
if (rr->NATinfo.clientContext)
|
||||
{
|
||||
|
@ -1802,8 +1855,13 @@ mDNSlocal void StartRecordNatMap(mDNS *m, AuthRecord *rr)
|
|||
else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp")) protocol = NATOp_MapUDP;
|
||||
else { LogMsg("StartRecordNatMap: could not determine transport protocol of service %##s", rr->resrec.name->c); return; }
|
||||
|
||||
//LogMsg("StartRecordNatMap: clientContext %p IntPort %d srv.port %d %s",
|
||||
// rr->NATinfo.clientContext, mDNSVal16(rr->NATinfo.IntPort), mDNSVal16(rr->resrec.rdata->u.srv.port), ARDisplayString(m, rr));
|
||||
if (rr->NATinfo.clientContext) mDNS_StopNATOperation_internal(m, &rr->NATinfo);
|
||||
rr->NATinfo.Protocol = protocol;
|
||||
|
||||
// Shouldn't be trying to set IntPort here --
|
||||
// BuildUpdateMessage overwrites srs->RR_SRV.resrec.rdata->u.srv.port with external (mapped) port number
|
||||
rr->NATinfo.IntPort = rr->resrec.rdata->u.srv.port;
|
||||
rr->NATinfo.RequestedPort = rr->resrec.rdata->u.srv.port;
|
||||
rr->NATinfo.NATLease = 0; // Request default lease
|
||||
|
@ -1818,6 +1876,19 @@ mDNSlocal void StartRecordNatMap(mDNS *m, AuthRecord *rr)
|
|||
// record is temporarily left in the ResourceRecords list so that we can initialize later
|
||||
// when the target is resolvable. Similarly, when host name changes, we enter regState_NoTarget
|
||||
// and we do the same.
|
||||
|
||||
// This UnlinkResourceRecord routine is very worrying. It bypasses all the normal cleanup performed
|
||||
// by mDNS_Deregister_internal and just unceremoniously cuts the record from the active list.
|
||||
// This is why re-regsitering this record was producing syslog messages like this:
|
||||
// "Error! Tried to add a NAT traversal that's already in the active list"
|
||||
// Right now UnlinkResourceRecord is fortunately only called by RegisterAllServiceRecords,
|
||||
// which then immediately calls mDNS_Register_internal to re-register the record, which probably
|
||||
// masked more serious problems. Any other use of UnlinkResourceRecord is likely to lead to crashes.
|
||||
// For now we'll workaround that specific problem by explicitly calling mDNS_StopNATOperation_internal,
|
||||
// but long-term we should either stop cancelling the record registration and then re-registering it,
|
||||
// or if we really do need to do this for some reason it should be done via the usual
|
||||
// mDNS_Deregister_internal path instead of just cutting the record from the list.
|
||||
|
||||
mDNSlocal mStatus UnlinkResourceRecord(mDNS *const m, AuthRecord *const rr)
|
||||
{
|
||||
AuthRecord **list = &m->ResourceRecords;
|
||||
|
@ -1826,6 +1897,15 @@ mDNSlocal mStatus UnlinkResourceRecord(mDNS *const m, AuthRecord *const rr)
|
|||
{
|
||||
*list = rr->next;
|
||||
rr->next = mDNSNULL;
|
||||
|
||||
// Temporary workaround to cancel any active NAT mapping operation
|
||||
if (rr->NATinfo.clientContext)
|
||||
{
|
||||
mDNS_StopNATOperation_internal(m, &rr->NATinfo);
|
||||
rr->NATinfo.clientContext = mDNSNULL;
|
||||
if (rr->resrec.rrtype == kDNSType_SRV) rr->resrec.rdata->u.srv.port = rr->NATinfo.IntPort;
|
||||
}
|
||||
|
||||
return(mStatus_NoError);
|
||||
}
|
||||
LogMsg("UnlinkResourceRecord:ERROR!! - no such active record %##s", rr->resrec.name->c);
|
||||
|
@ -2022,7 +2102,7 @@ mDNSlocal void AdvertiseHostname(mDNS *m, HostnameInfo *h)
|
|||
{
|
||||
if (!mDNSIPv4AddressIsZero(m->AdvertisedV4.ip.v4) && h->arv4.resrec.RecordType == kDNSRecordTypeUnregistered)
|
||||
{
|
||||
mDNS_SetupResourceRecord(&h->arv4, mDNSNULL, mDNSInterface_Any, kDNSType_A, kHostNameTTL, kDNSRecordTypeUnregistered, HostnameCallback, h);
|
||||
mDNS_SetupResourceRecord(&h->arv4, mDNSNULL, mDNSInterface_Any, kDNSType_A, kHostNameTTL, kDNSRecordTypeUnregistered, AuthRecordAny, HostnameCallback, h);
|
||||
AssignDomainName(&h->arv4.namestorage, &h->fqdn);
|
||||
h->arv4.resrec.rdata->u.ipv4 = m->AdvertisedV4.ip.v4;
|
||||
h->arv4.state = regState_Unregistered;
|
||||
|
@ -2048,7 +2128,7 @@ mDNSlocal void AdvertiseHostname(mDNS *m, HostnameInfo *h)
|
|||
|
||||
if (!mDNSIPv6AddressIsZero(m->AdvertisedV6.ip.v6) && h->arv6.resrec.RecordType == kDNSRecordTypeUnregistered)
|
||||
{
|
||||
mDNS_SetupResourceRecord(&h->arv6, mDNSNULL, mDNSInterface_Any, kDNSType_AAAA, kHostNameTTL, kDNSRecordTypeKnownUnique, HostnameCallback, h);
|
||||
mDNS_SetupResourceRecord(&h->arv6, mDNSNULL, mDNSInterface_Any, kDNSType_AAAA, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, HostnameCallback, h);
|
||||
AssignDomainName(&h->arv6.namestorage, &h->fqdn);
|
||||
h->arv6.resrec.rdata->u.ipv6 = m->AdvertisedV6.ip.v6;
|
||||
h->arv6.state = regState_Unregistered;
|
||||
|
@ -2189,6 +2269,12 @@ mDNSlocal void GetStaticHostname(mDNS *m)
|
|||
q->ForceMCast = mDNSfalse;
|
||||
q->ReturnIntermed = mDNStrue;
|
||||
q->SuppressUnusable = mDNSfalse;
|
||||
q->SearchListIndex = 0;
|
||||
q->AppendSearchDomains = 0;
|
||||
q->RetryWithSearchDomains = mDNSfalse;
|
||||
q->TimeoutQuestion = 0;
|
||||
q->WakeOnResolve = 0;
|
||||
q->qnameOrig = mDNSNULL;
|
||||
q->QuestionCallback = FoundStaticHostname;
|
||||
q->QuestionContext = mDNSNULL;
|
||||
|
||||
|
@ -2927,7 +3013,7 @@ mDNSlocal mDNSBool SendGroupUpdates(mDNS *const m)
|
|||
}
|
||||
spaceleft -= rrSize;
|
||||
oldnext = next;
|
||||
LogInfo("SendGroupUpdates: Building a message with resource record %s, next %p, state %d", ARDisplayString(m, rr), next, rr->state);
|
||||
LogInfo("SendGroupUpdates: Building a message with resource record %s, next %p, state %d, ttl %d", ARDisplayString(m, rr), next, rr->state, rr->resrec.rroriginalttl);
|
||||
if (!(next = BuildUpdateMessage(m, next, rr, limit)))
|
||||
{
|
||||
// We calculated the space and if we can't fit in, we had some bug in the calculation,
|
||||
|
@ -3071,7 +3157,7 @@ mDNSlocal void hndlRecordUpdateReply(mDNS *m, AuthRecord *rr, mStatus err, mDNSu
|
|||
|
||||
rr->updateError = err;
|
||||
#if APPLE_OSX_mDNSResponder
|
||||
if (err == mStatus_BadSig) UpdateAutoTunnelDomainStatuses(m);
|
||||
if (err == mStatus_BadSig || err == mStatus_BadKey) UpdateAutoTunnelDomainStatuses(m);
|
||||
#endif
|
||||
|
||||
SetRecordRetry(m, rr, random);
|
||||
|
@ -4030,7 +4116,6 @@ mDNSlocal const mDNSu8 *mDNS_WABLabels[] =
|
|||
(const mDNSu8 *)"\002lb",
|
||||
(const mDNSu8 *)"\001r",
|
||||
(const mDNSu8 *)"\002dr",
|
||||
(const mDNSu8 *)"\002cf",
|
||||
(const mDNSu8 *)mDNSNULL,
|
||||
};
|
||||
|
||||
|
@ -4569,28 +4654,41 @@ mDNSexport void SleepRecordRegistrations(mDNS *m)
|
|||
}
|
||||
}
|
||||
|
||||
mDNSexport void mDNS_AddSearchDomain(const domainname *const domain)
|
||||
mDNSexport void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID)
|
||||
{
|
||||
SearchListElem **p;
|
||||
SearchListElem *tmp = mDNSNULL;
|
||||
|
||||
// Check to see if we already have this domain in our list
|
||||
for (p = &SearchList; *p; p = &(*p)->next)
|
||||
if (SameDomainName(&(*p)->domain, domain))
|
||||
if (((*p)->InterfaceID == InterfaceID) && SameDomainName(&(*p)->domain, domain))
|
||||
{
|
||||
// If domain is already in list, and marked for deletion, change it to "leave alone"
|
||||
if ((*p)->flag == -1) (*p)->flag = 0;
|
||||
// If domain is already in list, and marked for deletion, unmark the delete
|
||||
// Be careful not to touch the other flags that may be present
|
||||
LogInfo("mDNS_AddSearchDomain already in list %##s", domain->c);
|
||||
return;
|
||||
if ((*p)->flag & SLE_DELETE) (*p)->flag &= ~SLE_DELETE;
|
||||
tmp = *p;
|
||||
*p = tmp->next;
|
||||
tmp->next = mDNSNULL;
|
||||
break;
|
||||
}
|
||||
|
||||
// if domain not in list, add to list, mark as add (1)
|
||||
*p = mDNSPlatformMemAllocate(sizeof(SearchListElem));
|
||||
if (!*p) { LogMsg("ERROR: mDNS_AddSearchDomain - malloc"); return; }
|
||||
mDNSPlatformMemZero(*p, sizeof(SearchListElem));
|
||||
AssignDomainName(&(*p)->domain, domain);
|
||||
(*p)->flag = 1; // add
|
||||
(*p)->next = mDNSNULL;
|
||||
LogInfo("mDNS_AddSearchDomain created new %##s", domain->c);
|
||||
|
||||
// move to end of list so that we maintain the same order
|
||||
while (*p) p = &(*p)->next;
|
||||
|
||||
if (tmp) *p = tmp;
|
||||
else
|
||||
{
|
||||
// if domain not in list, add to list, mark as add (1)
|
||||
*p = mDNSPlatformMemAllocate(sizeof(SearchListElem));
|
||||
if (!*p) { LogMsg("ERROR: mDNS_AddSearchDomain - malloc"); return; }
|
||||
mDNSPlatformMemZero(*p, sizeof(SearchListElem));
|
||||
AssignDomainName(&(*p)->domain, domain);
|
||||
(*p)->next = mDNSNULL;
|
||||
(*p)->InterfaceID = InterfaceID;
|
||||
LogInfo("mDNS_AddSearchDomain created new %##s, InterfaceID %p", domain->c, InterfaceID);
|
||||
}
|
||||
}
|
||||
|
||||
mDNSlocal void FreeARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
|
||||
|
@ -4599,95 +4697,6 @@ mDNSlocal void FreeARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus r
|
|||
if (result == mStatus_MemFree) mDNSPlatformMemFree(rr->RecordContext);
|
||||
}
|
||||
|
||||
#if APPLE_OSX_mDNSResponder
|
||||
mDNSlocal void CheckAutoTunnel6Registration(mDNS *const m, mDNSBool RegisterAutoTunnel6)
|
||||
{
|
||||
LogInfo("CheckAutoTunnel6Registration: Current value RegisterAutoTunnel6 %d, New value %d", m->RegisterAutoTunnel6, RegisterAutoTunnel6);
|
||||
if (!RegisterAutoTunnel6)
|
||||
{
|
||||
// We are not supposed to register autotunnel6. If we had previously registered
|
||||
// autotunnel6, deregister it now.
|
||||
if (m->RegisterAutoTunnel6)
|
||||
{
|
||||
m->RegisterAutoTunnel6 = mDNSfalse;
|
||||
LogInfo("CheckAutoTunnel6Registration: Removing AutoTunnel6");
|
||||
RemoveAutoTunnel6Record(m);
|
||||
}
|
||||
else LogInfo("CheckAutoTunnel6Registration: Already Removed AutoTunnel6");
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are supposed to register autotunnel6. If we had previously de-registered
|
||||
// autotunnel6, re-register it now.
|
||||
if (!m->RegisterAutoTunnel6)
|
||||
{
|
||||
m->RegisterAutoTunnel6 = mDNStrue;
|
||||
LogInfo("CheckAutoTunnel6Registration: Adding AutoTunnel6");
|
||||
SetupConndConfigChanges(m);
|
||||
}
|
||||
else LogInfo("CheckAutoTunnel6Registration: already Added AutoTunnel6");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mDNSlocal void FoundDirDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
|
||||
{
|
||||
SearchListElem *slElem = question->QuestionContext;
|
||||
mDNSBool RegisterAutoTunnel6 = mDNStrue;
|
||||
char *res = "DisableInboundRelay";
|
||||
|
||||
LogInfo("FoundDirDomain: InterfaceID %p %s Question %##s Answer %s", answer->InterfaceID, AddRecord ? "Add" : "Rmv", question->qname.c, RRDisplayString(m, answer));
|
||||
if (answer->rrtype != kDNSType_TXT)
|
||||
{
|
||||
LogMsg("FoundDirDomain: answer type is not TXT %s for question %##s", DNSTypeName(answer->rrtype), question->qname.c);
|
||||
return;
|
||||
}
|
||||
if (answer->RecordType == kDNSRecordTypePacketNegative)
|
||||
{
|
||||
LogInfo("FoundDirDomain: Negative answer for %##s", question->qname.c);
|
||||
return;
|
||||
}
|
||||
if (answer->InterfaceID == mDNSInterface_LocalOnly)
|
||||
{
|
||||
LogInfo("FoundDirDomain: LocalOnly interfaceID for %##s", question->qname.c);
|
||||
return;
|
||||
}
|
||||
|
||||
// TXT record is encoded as <len><data>
|
||||
if (answer->rdlength != mDNSPlatformStrLen(res) + 1)
|
||||
{
|
||||
LogInfo("FoundDirDomain: Invalid TXT record to disable %##s, length %d", question->qname.c, answer->rdlength);
|
||||
return;
|
||||
}
|
||||
|
||||
// Compare the data (excluding the len byte)
|
||||
if (!mDNSPlatformMemSame(&answer->rdata->u.txt.c[1], res, answer->rdlength - 1))
|
||||
{
|
||||
LogInfo("FoundDirDomain: Invalid TXT record to disable %##s", question->qname.c);
|
||||
return;
|
||||
}
|
||||
|
||||
// It is sufficient for one answer to disable registration of autotunnel6. But we should
|
||||
// have zero answers across all domains to register autotunnel6.
|
||||
if (AddRecord)
|
||||
{
|
||||
slElem->numDirAnswers++;
|
||||
RegisterAutoTunnel6 = mDNSfalse;
|
||||
}
|
||||
else
|
||||
{
|
||||
const SearchListElem *s;
|
||||
slElem->numDirAnswers--;
|
||||
if (slElem->numDirAnswers < 0) LogMsg("FoundDirDomain: numDirAnswers less than zero %d", slElem->numDirAnswers);
|
||||
// See if any domain (including the slElem) has any answers
|
||||
for (s=SearchList; s; s=s->next)
|
||||
if (s->numDirAnswers) { RegisterAutoTunnel6 = mDNSfalse; break; }
|
||||
}
|
||||
#if APPLE_OSX_mDNSResponder
|
||||
CheckAutoTunnel6Registration(m, RegisterAutoTunnel6);
|
||||
#endif
|
||||
}
|
||||
|
||||
mDNSlocal void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
|
||||
{
|
||||
SearchListElem *slElem = question->QuestionContext;
|
||||
|
@ -4711,7 +4720,7 @@ mDNSlocal void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceR
|
|||
{
|
||||
ARListElem *arElem = mDNSPlatformMemAllocate(sizeof(ARListElem));
|
||||
if (!arElem) { LogMsg("ERROR: FoundDomain out of memory"); return; }
|
||||
mDNS_SetupResourceRecord(&arElem->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, FreeARElemCallback, arElem);
|
||||
mDNS_SetupResourceRecord(&arElem->ar, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, 7200, kDNSRecordTypeShared, AuthRecordLocalOnly, FreeARElemCallback, arElem);
|
||||
MakeDomainNameFromDNSNameString(&arElem->ar.namestorage, name);
|
||||
AppendDNSNameString (&arElem->ar.namestorage, "local");
|
||||
AssignDomainName(&arElem->ar.resrec.rdata->u.name, &answer->rdata->u.name);
|
||||
|
@ -4758,7 +4767,7 @@ mDNSexport void udns_validatelists(void *const v)
|
|||
|
||||
DomainAuthInfo *info;
|
||||
for (info = m->AuthInfoList; info; info = info->next)
|
||||
if (info->next == (DomainAuthInfo *)~0 || info->AutoTunnel == (mDNSBool)~0)
|
||||
if (info->next == (DomainAuthInfo *)~0 || info->AutoTunnel == (const char*)~0)
|
||||
LogMemCorruption("m->AuthInfoList: %p is garbage (%X)", info, info->AutoTunnel);
|
||||
|
||||
HostnameInfo *hi;
|
||||
|
@ -4773,68 +4782,50 @@ mDNSexport void udns_validatelists(void *const v)
|
|||
}
|
||||
#endif
|
||||
|
||||
mDNSlocal void mDNS_StartDirQuestion(mDNS *const m, DNSQuestion *question, domainname *domain, void *context)
|
||||
{
|
||||
AssignDomainName (&question->qname, (const domainname*)"\002cf" "\007_dns-sd" "\x04_udp");
|
||||
AppendDomainName (&question->qname, domain);
|
||||
question->InterfaceID = mDNSInterface_Any;
|
||||
question->Target = zeroAddr;
|
||||
question->qtype = kDNSType_TXT;
|
||||
question->qclass = kDNSClass_IN;
|
||||
question->LongLived = mDNSfalse;
|
||||
question->ExpectUnique = mDNStrue;
|
||||
question->ForceMCast = mDNSfalse;
|
||||
question->ReturnIntermed = mDNSfalse;
|
||||
question->SuppressUnusable = mDNSfalse;
|
||||
question->QuestionCallback = FoundDirDomain;
|
||||
question->QuestionContext = context;
|
||||
LogInfo("mDNS_StartDirQuestion: Start DIR domain question %##s", question->qname.c);
|
||||
if (mDNS_StartQuery(m, question))
|
||||
LogMsg("mDNS_StartDirQuestion: ERROR!! cannot start _dir._dns-sd query");
|
||||
}
|
||||
|
||||
// This should probably move to the UDS daemon -- the concept of legacy clients and automatic registration / automatic browsing
|
||||
// is really a UDS API issue, not something intrinsic to uDNS
|
||||
mDNSexport mStatus uDNS_RegisterSearchDomains(mDNS *const m)
|
||||
|
||||
mDNSexport mStatus uDNS_SetupSearchDomains(mDNS *const m, int action)
|
||||
{
|
||||
SearchListElem **p = &SearchList, *ptr;
|
||||
const SearchListElem *s;
|
||||
mDNSBool RegisterAutoTunnel6 = mDNStrue;
|
||||
mStatus err;
|
||||
|
||||
// step 1: mark each element for removal (-1)
|
||||
for (ptr = SearchList; ptr; ptr = ptr->next) ptr->flag = -1;
|
||||
// step 1: mark each element for removal
|
||||
for (ptr = SearchList; ptr; ptr = ptr->next) ptr->flag |= SLE_DELETE;
|
||||
|
||||
// Client has requested domain enumeration or automatic browse -- time to make sure we have the search domains from the platform layer
|
||||
// Make sure we have the search domains from the platform layer so that if we start the WAB
|
||||
// queries below, we have the latest information
|
||||
mDNS_Lock(m);
|
||||
m->RegisterSearchDomains = mDNStrue;
|
||||
mDNSPlatformSetDNSConfig(m, mDNSfalse, m->RegisterSearchDomains, mDNSNULL, mDNSNULL, mDNSNULL);
|
||||
mDNSPlatformSetDNSConfig(m, mDNSfalse, mDNStrue, mDNSNULL, mDNSNULL, mDNSNULL);
|
||||
mDNS_Unlock(m);
|
||||
|
||||
if (action & UDNS_START_WAB_QUERY)
|
||||
m->StartWABQueries = mDNStrue;
|
||||
|
||||
// delete elems marked for removal, do queries for elems marked add
|
||||
while (*p)
|
||||
{
|
||||
ptr = *p;
|
||||
LogInfo("RegisterSearchDomains %d %p %##s", ptr->flag, ptr->AuthRecs, ptr->domain.c);
|
||||
if (ptr->flag == -1) // remove
|
||||
LogInfo("uDNS_SetupSearchDomains:action %d: Flags %d, AuthRecs %p, InterfaceID %p %##s", action, ptr->flag, ptr->AuthRecs, ptr->InterfaceID, ptr->domain.c);
|
||||
if (ptr->flag & SLE_DELETE)
|
||||
{
|
||||
ARListElem *arList = ptr->AuthRecs;
|
||||
ptr->AuthRecs = mDNSNULL;
|
||||
*p = ptr->next;
|
||||
|
||||
// If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries
|
||||
// Note: Stopping a question will not generate the RMV events for the question (handled in FoundDirDomain)
|
||||
// and hence we need to recheck all the domains to see if we need to register/deregister _autotunnel6.
|
||||
// This is done at the end.
|
||||
if (!SameDomainName(&ptr->domain, &localdomain))
|
||||
// We suppressed the domain enumeration for scoped search domains below. When we enable that
|
||||
// enable this.
|
||||
if ((ptr->flag & SLE_WAB_QUERY_STARTED) &&
|
||||
!SameDomainName(&ptr->domain, &localdomain) && (ptr->InterfaceID == mDNSInterface_Any))
|
||||
{
|
||||
mDNS_StopGetDomains(m, &ptr->BrowseQ);
|
||||
mDNS_StopGetDomains(m, &ptr->RegisterQ);
|
||||
mDNS_StopGetDomains(m, &ptr->DefBrowseQ);
|
||||
mDNS_StopGetDomains(m, &ptr->DefRegisterQ);
|
||||
mDNS_StopGetDomains(m, &ptr->AutomaticBrowseQ);
|
||||
mDNS_StopGetDomains(m, &ptr->DirQ);
|
||||
}
|
||||
|
||||
mDNSPlatformMemFree(ptr);
|
||||
|
||||
// deregister records generated from answers to the query
|
||||
|
@ -4844,49 +4835,121 @@ mDNSexport mStatus uDNS_RegisterSearchDomains(mDNS *const m)
|
|||
arList = arList->next;
|
||||
debugf("Deregistering PTR %##s -> %##s", dereg->ar.resrec.name->c, dereg->ar.resrec.rdata->u.name.c);
|
||||
err = mDNS_Deregister(m, &dereg->ar);
|
||||
if (err) LogMsg("uDNS_RegisterSearchDomains ERROR!! mDNS_Deregister returned %d", err);
|
||||
if (err) LogMsg("uDNS_SetupSearchDomains:: ERROR!! mDNS_Deregister returned %d", err);
|
||||
// Memory will be freed in the FreeARElemCallback
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ptr->flag == 1) // add
|
||||
if ((action & UDNS_START_WAB_QUERY) && !(ptr->flag & SLE_WAB_QUERY_STARTED))
|
||||
{
|
||||
// If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries
|
||||
if (!SameDomainName(&ptr->domain, &localdomain))
|
||||
// If the user has "local" in their DNS searchlist, we ignore that for the purposes of domain enumeration queries.
|
||||
// Also, suppress the domain enumeration for scoped search domains for now until there is a need.
|
||||
if (!SameDomainName(&ptr->domain, &localdomain) && (ptr->InterfaceID == mDNSInterface_Any))
|
||||
{
|
||||
mStatus err1, err2, err3, err4, err5;
|
||||
err1 = mDNS_GetDomains(m, &ptr->BrowseQ, mDNS_DomainTypeBrowse, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
|
||||
err2 = mDNS_GetDomains(m, &ptr->DefBrowseQ, mDNS_DomainTypeBrowseDefault, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
|
||||
err3 = mDNS_GetDomains(m, &ptr->RegisterQ, mDNS_DomainTypeRegistration, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
|
||||
err4 = mDNS_GetDomains(m, &ptr->DefRegisterQ, mDNS_DomainTypeRegistrationDefault, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
|
||||
err5 = mDNS_GetDomains(m, &ptr->AutomaticBrowseQ, mDNS_DomainTypeBrowseAutomatic, &ptr->domain, mDNSInterface_Any, FoundDomain, ptr);
|
||||
err1 = mDNS_GetDomains(m, &ptr->BrowseQ, mDNS_DomainTypeBrowse, &ptr->domain, ptr->InterfaceID, FoundDomain, ptr);
|
||||
err2 = mDNS_GetDomains(m, &ptr->DefBrowseQ, mDNS_DomainTypeBrowseDefault, &ptr->domain, ptr->InterfaceID, FoundDomain, ptr);
|
||||
err3 = mDNS_GetDomains(m, &ptr->RegisterQ, mDNS_DomainTypeRegistration, &ptr->domain, ptr->InterfaceID, FoundDomain, ptr);
|
||||
err4 = mDNS_GetDomains(m, &ptr->DefRegisterQ, mDNS_DomainTypeRegistrationDefault, &ptr->domain, ptr->InterfaceID, FoundDomain, ptr);
|
||||
err5 = mDNS_GetDomains(m, &ptr->AutomaticBrowseQ, mDNS_DomainTypeBrowseAutomatic, &ptr->domain, ptr->InterfaceID, FoundDomain, ptr);
|
||||
if (err1 || err2 || err3 || err4 || err5)
|
||||
LogMsg("uDNS_RegisterSearchDomains: GetDomains for domain %##s returned error(s):\n"
|
||||
LogMsg("uDNS_SetupSearchDomains: GetDomains for domain %##s returned error(s):\n"
|
||||
"%d (mDNS_DomainTypeBrowse)\n"
|
||||
"%d (mDNS_DomainTypeBrowseDefault)\n"
|
||||
"%d (mDNS_DomainTypeRegistration)\n"
|
||||
"%d (mDNS_DomainTypeRegistrationDefault)"
|
||||
"%d (mDNS_DomainTypeBrowseAutomatic)\n",
|
||||
ptr->domain.c, err1, err2, err3, err4, err5);
|
||||
mDNS_StartDirQuestion(m, &ptr->DirQ, &ptr->domain, ptr);
|
||||
ptr->flag |= SLE_WAB_QUERY_STARTED;
|
||||
}
|
||||
ptr->flag = 0;
|
||||
}
|
||||
|
||||
if (ptr->flag) { LogMsg("uDNS_RegisterSearchDomains - unknown flag %d. Skipping.", ptr->flag); }
|
||||
|
||||
p = &ptr->next;
|
||||
}
|
||||
// if there is any domain has answers, need to deregister autotunnel6
|
||||
for (s=SearchList; s; s=s->next)
|
||||
if (s->numDirAnswers) { RegisterAutoTunnel6 = mDNSfalse; break; }
|
||||
#if APPLE_OSX_mDNSResponder
|
||||
CheckAutoTunnel6Registration(m, RegisterAutoTunnel6);
|
||||
#endif
|
||||
return mStatus_NoError;
|
||||
}
|
||||
|
||||
mDNSexport domainname *uDNS_GetNextSearchDomain(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal)
|
||||
{
|
||||
SearchListElem *p = SearchList;
|
||||
int count = *searchIndex;
|
||||
(void) m; // unused
|
||||
|
||||
if (count < 0) { LogMsg("uDNS_GetNextSearchDomain: count %d less than zero", count); return mDNSNULL; }
|
||||
|
||||
// skip the domains that we already looked at before
|
||||
for (; count; count--) p = p->next;
|
||||
|
||||
while (p)
|
||||
{
|
||||
int labels = CountLabels(&p->domain);
|
||||
if (labels > 0)
|
||||
{
|
||||
const domainname *d = SkipLeadingLabels(&p->domain, labels - 1);
|
||||
if (SameDomainLabel(d->c, (const mDNSu8 *)"\x4""arpa"))
|
||||
{
|
||||
LogInfo("uDNS_GetNextSearchDomain: skipping search domain %##s, InterfaceID %p", p->domain.c, p->InterfaceID);
|
||||
(*searchIndex)++;
|
||||
p = p->next;
|
||||
continue;
|
||||
}
|
||||
if (ignoreDotLocal && SameDomainLabel(d->c, (const mDNSu8 *)"\x5""local"))
|
||||
{
|
||||
LogInfo("uDNS_GetNextSearchDomain: skipping local domain %##s, InterfaceID %p", p->domain.c, p->InterfaceID);
|
||||
(*searchIndex)++;
|
||||
p = p->next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Point to the next one in the list which we will look at next time.
|
||||
(*searchIndex)++;
|
||||
// When we are appending search domains in a ActiveDirectory domain, the question's InterfaceID
|
||||
// set to mDNSInterface_Unicast. Match the unscoped entries in that case.
|
||||
if (((InterfaceID == mDNSInterface_Unicast) && (p->InterfaceID == mDNSInterface_Any)) ||
|
||||
p->InterfaceID == InterfaceID)
|
||||
{
|
||||
LogInfo("uDNS_GetNextSearchDomain returning domain %##s, InterfaceID %p", p->domain.c, p->InterfaceID);
|
||||
return &p->domain;
|
||||
}
|
||||
LogInfo("uDNS_GetNextSearchDomain skipping domain %##s, InterfaceID %p", p->domain.c, p->InterfaceID);
|
||||
p = p->next;
|
||||
}
|
||||
return mDNSNULL;
|
||||
}
|
||||
|
||||
mDNSlocal void FlushAddressCacheRecords(mDNS *const m)
|
||||
{
|
||||
mDNSu32 slot;
|
||||
CacheGroup *cg;
|
||||
CacheRecord *cr;
|
||||
FORALL_CACHERECORDS(slot, cg, cr)
|
||||
{
|
||||
if (cr->resrec.InterfaceID) continue;
|
||||
|
||||
// If a resource record can answer A or AAAA, they need to be flushed so that we will
|
||||
// never used to deliver an ADD or RMV
|
||||
if (RRTypeAnswersQuestionType(&cr->resrec, kDNSType_A) ||
|
||||
RRTypeAnswersQuestionType(&cr->resrec, kDNSType_AAAA))
|
||||
{
|
||||
LogInfo("FlushAddressCacheRecords: Purging Resourcerecord %s", CRDisplayString(m, cr));
|
||||
mDNS_PurgeCacheResourceRecord(m, cr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retry questions which has seach domains appended
|
||||
mDNSexport void RetrySearchDomainQuestions(mDNS *const m)
|
||||
{
|
||||
// Purge all the A/AAAA cache records and restart the queries. mDNSCoreRestartAddressQueries
|
||||
// does this. When we restart the question, we first want to try the new search domains rather
|
||||
// than use the entries that is already in the cache. When we appended search domains, we might
|
||||
// have created cache entries which is no longer valid as there are new search domains now
|
||||
|
||||
LogInfo("RetrySearchDomainQuestions: Calling mDNSCoreRestartAddressQueries");
|
||||
mDNSCoreRestartAddressQueries(m, mDNStrue, FlushAddressCacheRecords, mDNSNULL, mDNSNULL);
|
||||
}
|
||||
|
||||
// Construction of Default Browse domain list (i.e. when clients pass NULL) is as follows:
|
||||
// 1) query for b._dns-sd._udp.local on LocalOnly interface
|
||||
// (.local manually generated via explicit callback)
|
||||
|
@ -4903,5 +4966,5 @@ struct CompileTimeAssertionChecks_uDNS
|
|||
// other overly-large structures instead of having a pointer to them, can inadvertently
|
||||
// cause structure sizes (and therefore memory usage) to balloon unreasonably.
|
||||
char sizecheck_tcpInfo_t [(sizeof(tcpInfo_t) <= 9056) ? 1 : -1];
|
||||
char sizecheck_SearchListElem[(sizeof(SearchListElem) <= 4800) ? 1 : -1];
|
||||
char sizecheck_SearchListElem[(sizeof(SearchListElem) <= 5000) ? 1 : -1];
|
||||
};
|
||||
|
|
|
@ -53,6 +53,11 @@
|
|||
// 5 minutes
|
||||
#define MAX_UPDATE_REFRESH_COUNT 5
|
||||
#define MIN_UPDATE_REFRESH_TIME (5 * 60 * mDNSPlatformOneSecond)
|
||||
|
||||
// For questions that use kDNSServiceFlagsTimeout and we don't have a matching resolver e.g., no dns servers,
|
||||
// then use the default value of 30 seconds
|
||||
#define DEFAULT_UDNS_TIMEOUT 30 // in seconds
|
||||
|
||||
// Entry points into unicast-specific routines
|
||||
|
||||
extern void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo);
|
||||
|
@ -91,7 +96,16 @@ extern void UpdateAllSRVRecords(mDNS *m);
|
|||
extern void CheckNATMappings(mDNS *m);
|
||||
|
||||
extern mStatus uDNS_SetupDNSConfig(mDNS *const m);
|
||||
extern mStatus uDNS_RegisterSearchDomains(mDNS *const m);
|
||||
|
||||
// uDNS_SetupSearchDomains by default adds search domains. It also can be called with one or
|
||||
// more values for "action" which does the following:
|
||||
//
|
||||
// -UDNS_START_WAB_QUERY - start Wide Area Bonjour (domain enumeration) queries
|
||||
|
||||
#define UDNS_START_WAB_QUERY 0x00000001
|
||||
|
||||
extern mStatus uDNS_SetupSearchDomains(mDNS *const m, int action);
|
||||
extern domainname *uDNS_GetNextSearchDomain(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
|
|
@ -47,8 +47,13 @@ extern int daemon(int, int);
|
|||
#include "mDNSPosix.h"
|
||||
#include "mDNSUNP.h" // For daemon()
|
||||
#include "uds_daemon.h"
|
||||
#include "DNSCommon.h"
|
||||
#include "PlatformCommon.h"
|
||||
|
||||
#ifndef MDNSD_USER
|
||||
#define MDNSD_USER "nobody"
|
||||
#endif
|
||||
|
||||
#define CONFIG_FILE "/etc/mdnsd.conf"
|
||||
static domainname DynDNSZone; // Default wide-area zone for service registration
|
||||
static domainname DynDNSHostname;
|
||||
|
@ -89,8 +94,10 @@ static void Reconfigure(mDNS *m)
|
|||
mDNSAddr DynDNSIP;
|
||||
const mDNSAddr dummy = { mDNSAddrType_IPv4, { { { 1, 1, 1, 1 } } } };;
|
||||
mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL, NULL);
|
||||
mDNS_Lock(m);
|
||||
if (ParseDNSServers(m, uDNS_SERVERS_FILE) < 0)
|
||||
LogMsg("Unable to parse DNS server list. Unicast DNS-SD unavailable");
|
||||
mDNS_Unlock(m);
|
||||
ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &DynDNSHostname, &DynDNSZone, NULL);
|
||||
mDNSPlatformSourceAddrForDest(&DynDNSIP, &dummy);
|
||||
if (DynDNSHostname.c[0]) mDNS_AddDynDNSHostName(m, &DynDNSHostname, NULL, NULL);
|
||||
|
@ -121,8 +128,40 @@ mDNSlocal void ParseCmdLinArgs(int argc, char **argv)
|
|||
mDNSlocal void DumpStateLog(mDNS *const m)
|
||||
// Dump a little log of what we've been up to.
|
||||
{
|
||||
DNSServer *s;
|
||||
PosixNetworkInterface *i;
|
||||
|
||||
LogMsg("---- BEGIN STATE LOG ----");
|
||||
udsserver_info(m);
|
||||
|
||||
LogMsgNoIdent("----- Network Interfaces -------");
|
||||
for (i = (PosixNetworkInterface*)(m->HostInterfaces);
|
||||
i; i = (PosixNetworkInterface *)(i->coreIntf.next)) {
|
||||
LogMsg("%p %p %d %s%s%s%s%s %-8s %#a", i,
|
||||
(void *)(i->coreIntf.InterfaceID), i->index,
|
||||
i->coreIntf.InterfaceActive ? "-" : "D",
|
||||
i->coreIntf.IPv4Available ? "4" : "-",
|
||||
i->coreIntf.IPv6Available ? "6" : "-",
|
||||
i->coreIntf.Advertise ? "A" : "-",
|
||||
i->coreIntf.McastTxRx ? "M" : "-",
|
||||
i->intfName, &(i->coreIntf.ip));
|
||||
}
|
||||
|
||||
LogMsgNoIdent("--------- DNS Servers ----------");
|
||||
if (!mDNSStorage.DNSServers) LogMsgNoIdent("<None>");
|
||||
else
|
||||
{
|
||||
for (s = m->DNSServers; s; s = s->next)
|
||||
{
|
||||
LogMsgNoIdent("DNS Server %##s %#a:%d %s",
|
||||
s->domain.c, &s->addr, mDNSVal16(s->port),
|
||||
s->teststate == DNSServer_Untested ? "(Untested)" :
|
||||
s->teststate == DNSServer_Passed ? "" :
|
||||
s->teststate == DNSServer_Failed ? "(Failed)" :
|
||||
s->teststate == DNSServer_Disabled ? "(Disabled)" : "(Unknown state)");
|
||||
}
|
||||
}
|
||||
|
||||
LogMsg("---- END STATE LOG ----");
|
||||
}
|
||||
|
||||
|
@ -134,6 +173,10 @@ mDNSlocal mStatus MainLoop(mDNS *m) // Loop until we quit.
|
|||
mDNSPosixListenForSignalInEventLoop(SIGINT);
|
||||
mDNSPosixListenForSignalInEventLoop(SIGTERM);
|
||||
mDNSPosixListenForSignalInEventLoop(SIGUSR1);
|
||||
#ifdef HAVE_SIGINFO
|
||||
mDNSPosixListenForSignalInEventLoop(SIGUSR2);
|
||||
mDNSPosixListenForSignalInEventLoop(SIGINFO);
|
||||
#endif
|
||||
mDNSPosixListenForSignalInEventLoop(SIGPIPE);
|
||||
mDNSPosixListenForSignalInEventLoop(SIGHUP) ;
|
||||
|
||||
|
@ -160,7 +203,22 @@ mDNSlocal mStatus MainLoop(mDNS *m) // Loop until we quit.
|
|||
(void) mDNSPosixRunEventLoopOnce(m, &timeout, &signals, &gotData);
|
||||
|
||||
if (sigismember(&signals, SIGHUP )) Reconfigure(m);
|
||||
#ifdef HAVE_SIGINFO
|
||||
/* use OSX-compatible signals since we can, and gain enhanced debugging */
|
||||
if (sigismember(&signals, SIGINFO)) DumpStateLog(m);
|
||||
if (sigismember(&signals, SIGUSR1))
|
||||
{
|
||||
mDNS_LoggingEnabled = mDNS_LoggingEnabled ? 0 : 1;
|
||||
LogMsg("SIGUSR1: Logging %s", mDNS_LoggingEnabled ? "Enabled" : "Disabled");
|
||||
}
|
||||
if (sigismember(&signals, SIGUSR2))
|
||||
{
|
||||
mDNS_PacketLoggingEnabled = mDNS_PacketLoggingEnabled ? 0 : 1;
|
||||
LogMsg("SIGUSR2: Packet Logging %s", mDNS_PacketLoggingEnabled ? "Enabled" : "Disabled");
|
||||
}
|
||||
#else
|
||||
if (sigismember(&signals, SIGUSR1)) DumpStateLog(m);
|
||||
#endif
|
||||
// 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;
|
||||
|
@ -187,11 +245,21 @@ int main(int argc, char **argv)
|
|||
// Now that we're finished with anything privileged, switch over to running as "nobody"
|
||||
if (mStatus_NoError == err)
|
||||
{
|
||||
const struct passwd *pw = getpwnam("nobody");
|
||||
const struct passwd *pw = getpwnam(MDNSD_USER);
|
||||
if (pw != NULL)
|
||||
{
|
||||
setgid(pw->pw_gid);
|
||||
setuid(pw->pw_uid);
|
||||
}
|
||||
else
|
||||
LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
|
||||
#ifdef MDNSD_NOROOT
|
||||
{
|
||||
LogMsg("WARNING: mdnsd exiting because user \""MDNSD_USER"\" does not exist");
|
||||
err = mStatus_Invalid;
|
||||
}
|
||||
#else
|
||||
LogMsg("WARNING: mdnsd continuing as root because user \""MDNSD_USER"\" does not exist");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mStatus_NoError == err)
|
||||
|
@ -250,9 +318,9 @@ asm(".desc ___crashreporter_info__, 0x10");
|
|||
|
||||
// For convenience when using the "strings" command, this is the last thing in the file
|
||||
#if mDNSResponderVersion > 1
|
||||
mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder-" STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
|
||||
mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder-" STRINGIFY(mDNSResponderVersion);
|
||||
#elif MDNS_VERSIONSTR_NODTS
|
||||
mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder (Engineering Build)";
|
||||
#else
|
||||
mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder (Engineering Build) (" __DATE__ " " __TIME__ ")";
|
||||
mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder (Engineering Build)";
|
||||
#endif
|
||||
|
|
|
@ -411,6 +411,26 @@ mDNSexport void mDNSPlatformTLSTearDownCerts(void)
|
|||
{
|
||||
}
|
||||
|
||||
mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason)
|
||||
{
|
||||
(void) m;
|
||||
(void) allowSleep;
|
||||
(void) reason;
|
||||
}
|
||||
|
||||
#if COMPILER_LIKES_PRAGMA_MARK
|
||||
#pragma mark -
|
||||
#pragma mark - /etc/hosts support
|
||||
#endif
|
||||
|
||||
mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result)
|
||||
{
|
||||
(void)m; // unused
|
||||
(void)rr;
|
||||
(void)result;
|
||||
}
|
||||
|
||||
|
||||
#if COMPILER_LIKES_PRAGMA_MARK
|
||||
#pragma mark ***** DDNS Config Platform Functions
|
||||
#endif
|
||||
|
@ -482,7 +502,7 @@ 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, &DNSAddr, UnicastDNSPort, mDNSfalse);
|
||||
mDNS_AddDNSServer(m, NULL, mDNSInterface_Any, &DNSAddr, UnicastDNSPort, mDNSfalse, 0);
|
||||
numOfServers++;
|
||||
}
|
||||
}
|
||||
|
@ -523,9 +543,10 @@ mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const
|
|||
return (mDNSInterfaceID) intf;
|
||||
}
|
||||
|
||||
mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id)
|
||||
mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange)
|
||||
{
|
||||
PosixNetworkInterface *intf;
|
||||
(void) suppressNetworkChange; // Unused
|
||||
|
||||
assert(m != NULL);
|
||||
|
||||
|
@ -1406,6 +1427,23 @@ mDNSexport mDNSs32 mDNSPlatformUTC(void)
|
|||
return time(NULL);
|
||||
}
|
||||
|
||||
mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, 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)
|
||||
{
|
||||
(void) rr;
|
||||
(void) intf;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
mDNSlocal void mDNSPosixAddToFDSet(int *nfds, fd_set *readfds, int s)
|
||||
{
|
||||
if (*nfds < s + 1) *nfds = s + 1;
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
#endif
|
||||
|
||||
#if defined(AF_INET6) && HAVE_IPV6 && !HAVE_LINUX && !defined(sun)
|
||||
#if !defined(__NetBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
#include <net/if_var.h>
|
||||
#endif
|
||||
#include <netinet/in_var.h>
|
||||
|
@ -278,6 +278,24 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
|
|||
if ((flags & IFF_UP) == 0)
|
||||
continue; /* ignore if interface not up */
|
||||
|
||||
/* Skip addresses we can't use */
|
||||
#ifdef SIOCGIFAFLAG_IN6
|
||||
if (ifr->ifr_addr.sa_family == AF_INET6) {
|
||||
struct in6_ifreq ifr6;
|
||||
|
||||
if (sockf6 == -1)
|
||||
sockf6 = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
memset(&ifr6, 0, sizeof(ifr6));
|
||||
memcpy(&ifr6.ifr_name, &ifr->ifr_name, sizeof(ifr6.ifr_name));
|
||||
memcpy(&ifr6.ifr_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_addr));
|
||||
if (ioctl(sockf6, SIOCGIFAFLAG_IN6, &ifr6) < 0)
|
||||
goto gotError;
|
||||
if (ifr6.ifr_ifru.ifru_flags6 &
|
||||
(IN6_IFF_NOTREADY | IN6_IFF_DETACHED))
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
|
||||
if (ifi == NULL) {
|
||||
goto gotError;
|
||||
|
|
|
@ -129,7 +129,7 @@ mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const fi
|
|||
{
|
||||
DomainAuthInfo *info = (DomainAuthInfo*)mDNSPlatformMemAllocate(sizeof(*info));
|
||||
// for now we assume keyname = service reg domain and we use same key for service and hostname registration
|
||||
err = mDNS_SetSecretForDomain(m, info, domain, domain, buf, mDNSfalse);
|
||||
err = mDNS_SetSecretForDomain(m, info, domain, domain, buf, NULL, 0, NULL);
|
||||
if (err) LogMsg("ERROR: mDNS_SetSecretForDomain returned %d for domain %##s", err, domain->c);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
.\"
|
||||
.Dd April 2004 \" Date
|
||||
.Dt dns-sd 1 \" Document Title
|
||||
.Os Darwin \" Operating System
|
||||
.Os NetBSD \" Operating System
|
||||
.\"
|
||||
.Sh NAME
|
||||
.Nm dns-sd
|
||||
|
@ -43,11 +43,6 @@ The library API that
|
|||
.Nm
|
||||
uses is documented in
|
||||
.Pa /usr/include/dns_sd.h .
|
||||
The
|
||||
.Nm
|
||||
command replaces the older
|
||||
.Xr mDNS 1
|
||||
command.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
|
@ -181,14 +176,11 @@ window.
|
|||
.Pa /usr/bin/dns-sd \" Pathname
|
||||
.\"
|
||||
.Sh SEE ALSO
|
||||
.Xr mDNS 1
|
||||
.Xr mDNSResponder 8
|
||||
.\"
|
||||
.Sh BUGS
|
||||
.Nm
|
||||
bugs are tracked in Apple Radar component "mDNSResponder".
|
||||
.Xr mdnsd 8
|
||||
.\"
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command first appeared in Mac OS X 10.4 (Tiger).
|
||||
command first appeared in
|
||||
.Nx 6.0 ,
|
||||
having originated in Mac OS X 10.4 (Tiger).
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
*/
|
||||
|
||||
#ifndef _DNS_SD_H
|
||||
#define _DNS_SD_H 2581400
|
||||
#define _DNS_SD_H 3201600
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -341,7 +341,7 @@ enum
|
|||
* lock or take similar appropriate precautions to serialize those calls.
|
||||
*/
|
||||
|
||||
kDNSServiceFlagsSuppressUnusable = 0x8000
|
||||
kDNSServiceFlagsSuppressUnusable = 0x8000,
|
||||
/*
|
||||
* This flag is meaningful only in DNSServiceQueryRecord which suppresses unusable queries on the
|
||||
* wire. If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name)
|
||||
|
@ -351,6 +351,26 @@ enum
|
|||
* "hostname".
|
||||
*/
|
||||
|
||||
kDNSServiceFlagsTimeout = 0x10000,
|
||||
/*
|
||||
* When kDNServiceFlagsTimeout is passed to DNSServiceQueryRecord or DNSServiceGetAddrInfo, the query is
|
||||
* stopped after a certain number of seconds have elapsed. The time at which the query will be stopped
|
||||
* is determined by the system and cannot be configured by the user. The query will be stopped irrespective
|
||||
* of whether a response was given earlier or not. When the query is stopped, the callback will be called
|
||||
* with an error code of kDNSServiceErr_Timeout and a NULL sockaddr will be returned for DNSServiceGetAddrInfo
|
||||
* and zero length rdata will be returned for DNSServiceQueryRecord.
|
||||
*/
|
||||
|
||||
kDNSServiceFlagsIncludeP2P = 0x20000,
|
||||
/*
|
||||
* Include P2P interfaces when kDNSServiceInterfaceIndexAny is specified.
|
||||
* By default, specifying kDNSServiceInterfaceIndexAny does not include P2P interfaces.
|
||||
*/
|
||||
kDNSServiceFlagsWakeOnResolve = 0x40000
|
||||
/*
|
||||
* This flag is meaningful only in DNSServiceResolve. When set, it tries to send a magic packet
|
||||
* to wake up the client.
|
||||
*/
|
||||
};
|
||||
|
||||
/* Possible protocols for DNSServiceNATPortMappingCreate(). */
|
||||
|
@ -488,7 +508,8 @@ enum
|
|||
kDNSServiceErr_NATPortMappingUnsupported = -65564, /* NAT doesn't support NAT-PMP or UPnP */
|
||||
kDNSServiceErr_NATPortMappingDisabled = -65565, /* NAT supports NAT-PMP or UPnP but it's disabled by the administrator */
|
||||
kDNSServiceErr_NoRouter = -65566, /* No router currently configured (probably no network connectivity) */
|
||||
kDNSServiceErr_PollingMode = -65567
|
||||
kDNSServiceErr_PollingMode = -65567,
|
||||
kDNSServiceErr_Timeout = -65568
|
||||
|
||||
/* mDNS Error codes are in the range
|
||||
* FFFE FF00 (-65792) to FFFE FFFF (-65537) */
|
||||
|
@ -599,10 +620,10 @@ enum
|
|||
* interface via which the service can be accessed.
|
||||
*
|
||||
* If applications pass kDNSServiceInterfaceIndexAny to DNSServiceBrowse
|
||||
* or DNSServiceQueryRecord, the operation will also include P2P. In this
|
||||
* case, if a service instance or the record being queried is found over P2P,
|
||||
* the resulting ADD event will indicate kDNSServiceInterfaceIndexP2P as the
|
||||
* interface index.
|
||||
* or DNSServiceQueryRecord, they must set the kDNSServiceFlagsIncludeP2P flag
|
||||
* to include P2P. In this case, if a service instance or the record being queried
|
||||
* is found over P2P, the resulting ADD event will indicate kDNSServiceInterfaceIndexP2P
|
||||
* as the interface index.
|
||||
*/
|
||||
|
||||
#define kDNSServiceInterfaceIndexAny 0
|
||||
|
@ -2394,6 +2415,7 @@ DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue
|
|||
|
||||
#endif //__APPLE_API_PRIVATE
|
||||
|
||||
#if !defined(__NetBSD__)
|
||||
/* 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
|
||||
|
@ -2405,6 +2427,7 @@ struct CompileTimeAssertionChecks_DNS_SD
|
|||
{
|
||||
char assert0[(sizeof(union _TXTRecordRef_t) == 16) ? 1 : -1];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -363,4 +363,4 @@ DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
|
|||
|
||||
// NOT static -- otherwise the compiler may optimize it out
|
||||
// The "@(#) " pattern is a special prefix the "what" command looks for
|
||||
const char VersionString_SCCS_libdnssd[] = "@(#) libdns_sd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
|
||||
const char VersionString_SCCS_libdnssd[] = "@(#) libdns_sd " STRINGIFY(mDNSResponderVersion);
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#include "dnssd_ipc.h"
|
||||
|
||||
static int gDaemonErr = kDNSServiceErr_NoError;
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#define _SSIZE_T
|
||||
|
@ -56,6 +58,7 @@
|
|||
|
||||
static int g_initWinsock = 0;
|
||||
#define LOG_WARNING kDebugLevelWarning
|
||||
#define LOG_INFO kDebugLevelInfo
|
||||
static void syslog( int priority, const char * message, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
@ -88,6 +91,8 @@
|
|||
// Uncomment the line below to use the old error return mechanism of creating a temporary named socket (e.g. in /var/tmp)
|
||||
//#define USE_NAMED_ERROR_RETURN_SOCKET 1
|
||||
|
||||
#define DNSSD_CLIENT_TIMEOUT 10 // In seconds
|
||||
|
||||
#ifndef CTL_PATH_PREFIX
|
||||
#define CTL_PATH_PREFIX "/var/tmp/dnssd_result_socket."
|
||||
#endif
|
||||
|
@ -165,14 +170,14 @@ static int write_all(dnssd_sock_t sd, char *buf, size_t len)
|
|||
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));
|
||||
if (!defunct)
|
||||
syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd,
|
||||
syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %zd/%ld %d %s", sd,
|
||||
(long)num_written, (long)len,
|
||||
(num_written < 0) ? dnssd_errno : 0,
|
||||
(num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
|
||||
else
|
||||
syslog(LOG_INFO, "dnssd_clientstub write_all(%d) DEFUNCT", sd);
|
||||
#else
|
||||
syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd,
|
||||
syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %zd/%ld %d %s", sd,
|
||||
(long)num_written, (long)len,
|
||||
(num_written < 0) ? dnssd_errno : 0,
|
||||
(num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
|
||||
|
@ -196,6 +201,9 @@ static int read_all(dnssd_sock_t sd, char *buf, int len)
|
|||
while (len)
|
||||
{
|
||||
ssize_t num_read = recv(sd, buf, len, 0);
|
||||
// It is valid to get an interrupted system call error e.g., somebody attaching
|
||||
// in a debugger, retry without failing
|
||||
if ((num_read < 0) && (errno == EINTR)) { syslog(LOG_INFO, "dnssd_clientstub read_all: EINTR continue"); continue; }
|
||||
if ((num_read == 0) || (num_read < 0) || (num_read > len))
|
||||
{
|
||||
int printWarn = 0;
|
||||
|
@ -262,6 +270,39 @@ static int more_bytes(dnssd_sock_t sd)
|
|||
return (ret > 0);
|
||||
}
|
||||
|
||||
// Wait for daemon to write to socket
|
||||
static int wait_for_daemon(dnssd_sock_t sock, int timeout)
|
||||
{
|
||||
#ifndef WIN32
|
||||
// At this point the next operation (accept() or read()) on this socket may block for a few milliseconds waiting
|
||||
// for the daemon to respond, but that's okay -- the daemon is a trusted service and we know if won't take more
|
||||
// than a few milliseconds to respond. So we'll forego checking for readability of the socket.
|
||||
(void) sock;
|
||||
(void) timeout;
|
||||
#else
|
||||
// Windows on the other hand suffers from 3rd party software (primarily 3rd party firewall software) that
|
||||
// interferes with proper functioning of the TCP protocol stack. Because of this and because we depend on TCP
|
||||
// to communicate with the system service, we want to make sure that the next operation on this socket (accept() or
|
||||
// read()) doesn't block indefinitely.
|
||||
if (!gDaemonErr)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set set;
|
||||
|
||||
FD_ZERO(&set);
|
||||
FD_SET(sock, &set);
|
||||
tv.tv_sec = timeout;
|
||||
tv.tv_usec = 0;
|
||||
if (!select((int)(sock + 1), &set, NULL, NULL, &tv))
|
||||
{
|
||||
syslog(LOG_WARNING, "dnssd_clientstub wait_for_daemon timed out");
|
||||
gDaemonErr = kDNSServiceErr_Timeout;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return gDaemonErr;
|
||||
}
|
||||
|
||||
/* create_hdr
|
||||
*
|
||||
* allocate and initialize an ipc message header. Value of len should initially be the
|
||||
|
@ -353,7 +394,6 @@ static void FreeDNSServiceOp(DNSServiceOp *x)
|
|||
x->ProcessReply = NULL;
|
||||
x->AppCallback = NULL;
|
||||
x->AppContext = NULL;
|
||||
x->rec = NULL;
|
||||
#if _DNS_SD_LIBDISPATCH
|
||||
if (x->disp_source) dispatch_release(x->disp_source);
|
||||
x->disp_source = NULL;
|
||||
|
@ -445,7 +485,7 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f
|
|||
else
|
||||
{
|
||||
#ifdef SO_NOSIGPIPE
|
||||
const unsigned long optval = 1;
|
||||
int optval = 1;
|
||||
#endif
|
||||
*ref = NULL;
|
||||
sdr->sockfd = socket(AF_DNSSD, SOCK_STREAM, 0);
|
||||
|
@ -612,7 +652,10 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
|
|||
#else
|
||||
if (write_all(sdr->sockfd, (char *)hdr, datalen + sizeof(ipc_msg_hdr)) < 0)
|
||||
{
|
||||
syslog(LOG_WARNING, "dnssd_clientstub deliver_request ERROR: write_all(%d, %lu bytes) failed",
|
||||
// write_all already prints an error message if there is an error writing to
|
||||
// the socket except for DEFUNCT. Logging here is unnecessary and also wrong
|
||||
// in the case of DEFUNCT sockets
|
||||
syslog(LOG_INFO, "dnssd_clientstub deliver_request ERROR: write_all(%d, %lu bytes) failed",
|
||||
sdr->sockfd, (unsigned long)(datalen + sizeof(ipc_msg_hdr)));
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -626,6 +669,7 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
|
|||
// but that's okay -- the daemon is a trusted service and we know if won't take more than a few milliseconds to respond.
|
||||
dnssd_sockaddr_t daddr;
|
||||
dnssd_socklen_t len = sizeof(daddr);
|
||||
if ((err = wait_for_daemon(listenfd, DNSSD_CLIENT_TIMEOUT)) != kDNSServiceErr_NoError) goto cleanup;
|
||||
errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
|
||||
if (!dnssd_SocketValid(errsd)) deliver_request_bailout("accept");
|
||||
#else
|
||||
|
@ -711,10 +755,13 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
|
|||
// but that's okay -- the daemon is a trusted service and we know if won't take more than a few milliseconds to respond.
|
||||
if (sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf
|
||||
err = kDNSServiceErr_NoError;
|
||||
else if (read_all(errsd, (char*)&err, (int)sizeof(err)) < 0)
|
||||
err = kDNSServiceErr_ServiceNotRunning; // On failure read_all will have written a message to syslog for us
|
||||
else
|
||||
err = ntohl(err);
|
||||
else if ((err = wait_for_daemon(errsd, DNSSD_CLIENT_TIMEOUT)) == kDNSServiceErr_NoError)
|
||||
{
|
||||
if (read_all(errsd, (char*)&err, (int)sizeof(err)) < 0)
|
||||
err = kDNSServiceErr_ServiceNotRunning; // On failure read_all will have written a message to syslog for us
|
||||
else
|
||||
err = ntohl(err);
|
||||
}
|
||||
|
||||
//syslog(LOG_WARNING, "dnssd_clientstub deliver_request: retrieved error code %d", err);
|
||||
|
||||
|
@ -1094,6 +1141,16 @@ DNSServiceErrorType DNSSD_API DNSServiceResolve
|
|||
|
||||
if (!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)))
|
||||
{
|
||||
return kDNSServiceErr_BadParam;
|
||||
}
|
||||
|
||||
err = ConnectToServer(sdRef, flags, resolve_request, handle_resolve_response, callBack, context);
|
||||
if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
# define dnssd_SocketValid(s) ((s) != INVALID_SOCKET)
|
||||
# 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)
|
||||
|
@ -63,6 +64,7 @@ extern char *win32_strerror(int inErrorCode);
|
|||
# define dnssd_SocketValid(s) ((s) >= 0)
|
||||
# define dnssd_EWOULDBLOCK EWOULDBLOCK
|
||||
# define dnssd_EINTR EINTR
|
||||
# define dnssd_ECONNRESET ECONNRESET
|
||||
# define dnssd_EPIPE EPIPE
|
||||
# define dnssd_sock_t int
|
||||
# define dnssd_socklen_t unsigned int
|
||||
|
@ -104,7 +106,10 @@ extern char *win32_strerror(int inErrorCode);
|
|||
// structures correctly anyway, so a plain "struct" is usually fine. In the event that structures are not packed
|
||||
// correctly, our compile-time assertion checks will catch it and prevent inadvertent generation of non-working code.
|
||||
#ifndef packedstruct
|
||||
#if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
|
||||
#ifdef __packed
|
||||
#define packedstruct struct __packed
|
||||
#define packedunion union __packed
|
||||
#elif ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
|
||||
#define packedstruct struct __attribute__((__packed__))
|
||||
#define packedunion union __attribute__((__packed__))
|
||||
#else
|
||||
|
@ -116,7 +121,7 @@ extern char *win32_strerror(int inErrorCode);
|
|||
typedef enum
|
||||
{
|
||||
request_op_none = 0, // No request yet received on this connection
|
||||
connection_request = 1, // connected socket via DNSServiceCreateConnection()
|
||||
connection_request = 1, // connected socket via DNSServiceConnect()
|
||||
reg_record_request, // reg/remove record only valid for connected sockets
|
||||
remove_record_request,
|
||||
enumeration_request,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -60,6 +60,7 @@ extern int CountPeerRegistrations(mDNS *const m, ServiceRecordSet *const srs);
|
|||
extern void machserver_automatic_browse_domain_changed(const domainname *d, mDNSBool add);
|
||||
extern void machserver_automatic_registration_domain_changed(const domainname *d, mDNSBool add);
|
||||
// External support
|
||||
extern void mDNSInitPacketFilter(void);
|
||||
extern void external_start_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype);
|
||||
extern void external_stop_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype);
|
||||
extern void external_start_advertising_service(const ResourceRecord *const resourceRecord);
|
||||
|
|
Loading…
Reference in New Issue