Import mDNSResponder-320.16, merge, fix conflicts
This commit is contained in:
parent
e28a8d2c02
commit
3b429a7601
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -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");
|
||||
|
@ -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);
|
||||
|
1904
external/apache2/mDNSResponder/dist/mDNSCore/mDNS.c
vendored
1904
external/apache2/mDNSResponder/dist/mDNSCore/mDNS.c
vendored
File diff suppressed because it is too large
Load Diff
@ -351,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
|
||||
@ -409,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.
|
||||
@ -427,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;
|
||||
@ -1039,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;
|
||||
@ -1053,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
|
||||
@ -1111,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(),
|
||||
@ -1137,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
|
||||
@ -1221,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
|
||||
{
|
||||
@ -1245,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
|
||||
@ -1394,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
|
||||
@ -1455,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;
|
||||
@ -1463,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
|
||||
@ -1496,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;
|
||||
};
|
||||
@ -1558,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
|
||||
{
|
||||
@ -1576,6 +1667,7 @@ typedef struct DNameListElem
|
||||
typedef struct ClientTunnel
|
||||
{
|
||||
struct ClientTunnel *next;
|
||||
const char *prefix;
|
||||
domainname dstname;
|
||||
mDNSBool MarkedForDeletion;
|
||||
mDNSv6Addr loc_inner;
|
||||
@ -1637,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;
|
||||
|
||||
@ -1673,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
|
||||
@ -1744,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
|
||||
@ -1758,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
|
||||
@ -1767,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;
|
||||
@ -1779,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
|
||||
@ -1793,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
|
||||
@ -2030,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)
|
||||
@ -2101,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);
|
||||
@ -2117,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,
|
||||
@ -2155,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
|
||||
@ -2317,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 -
|
||||
@ -2333,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);
|
||||
|
||||
@ -2360,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
|
||||
|
||||
@ -2481,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.
|
||||
@ -2534,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.
|
||||
@ -2590,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);
|
||||
@ -2609,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
|
||||
@ -2622,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
|
||||
|
||||
@ -2744,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)
|
||||
@ -2804,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
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
@ -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;
|
||||
@ -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
|
||||
@ -119,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
Loading…
Reference in New Issue
Block a user