Import mDNSResponder-320.16, merge, fix conflicts

This commit is contained in:
pettai 2014-03-31 23:26:30 +00:00
parent e28a8d2c02
commit 3b429a7601
10 changed files with 3024 additions and 650 deletions

View File

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

View File

@ -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");

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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