From: Apple Date: Fri, 18 Apr 2008 20:33:56 +0000 (+0000) Subject: mDNSResponder-171.4.tar.gz X-Git-Tag: mac-os-x-1053^0 X-Git-Url: https://git.saurik.com/apple/mdnsresponder.git/commitdiff_plain/5e65c77ffff758ef9067d31f408c4334cd03e863 mDNSResponder-171.4.tar.gz --- diff --git a/Clients/dns-sd.c b/Clients/dns-sd.c index e80ee39..497c5dc 100644 --- a/Clients/dns-sd.c +++ b/Clients/dns-sd.c @@ -574,16 +574,16 @@ static void DNSSD_API port_mapping_create_reply(DNSServiceRef sdref, DNSServiceF (void)context; // Unused (void)flags; // Unused - if (num_printed++ == 0) printf("Timestamp if %-20s %-15s %-15s %-15s %s\n", "External Address", "Protocol", "Internal Port", "External Port", "TTL"); + if (num_printed++ == 0) printf("Timestamp if %-20s %-15s %-15s %-15s %-6s\n", "External Address", "Protocol", "Internal Port", "External Port", "TTL"); printtimestamp(); - if (errorCode) printf("Error code %d\n", errorCode); + if (errorCode && errorCode != kDNSServiceErr_DoubleNAT) printf("Error code %d\n", errorCode); else { const unsigned char *digits = (const unsigned char *)&publicAddress; char addr[256]; snprintf(addr, sizeof(addr), "%d.%d.%d.%d", digits[0], digits[1], digits[2], digits[3]); - printf("%-4d %-20s %-15d %-15d %-15d %d\n", ifIndex, addr, protocol, ntohs(privatePort), ntohs(publicPort), ttl); + printf("%-4d %-20s %-15d %-15d %-15d %-6d%s\n", ifIndex, addr, protocol, ntohs(privatePort), ntohs(publicPort), ttl, errorCode == kDNSServiceErr_DoubleNAT ? " Double NAT" : ""); } fflush(stdout); } @@ -597,23 +597,27 @@ static void DNSSD_API addrinfo_reply(DNSServiceRef sdref, DNSServiceFlags flags, (void) sdref; (void) context; - if (num_printed++ == 0) printf("Timestamp A/R Flags if %-25s %-40s %s\n", "Hostname", "Address", "TTL"); + if (num_printed++ == 0) printf("Timestamp A/R Flags if %-25s %-44s %s\n", "Hostname", "Address", "TTL"); printtimestamp(); if (address && address->sa_family == AF_INET) { - const unsigned char *digits = (const unsigned char *) &((struct sockaddr_in *)address)->sin_addr; - snprintf(addr, sizeof(addr), "%d.%d.%d.%d", digits[0], digits[1], digits[2], digits[3]); + const unsigned char *b = (const unsigned char *) &((struct sockaddr_in *)address)->sin_addr; + snprintf(addr, sizeof(addr), "%d.%d.%d.%d", b[0], b[1], b[2], b[3]); } else if (address && address->sa_family == AF_INET6) { - const unsigned char *digits = (const unsigned char *) &((struct sockaddr_in6 *)address)->sin6_addr; - snprintf(addr, sizeof(addr), "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X", - digits[0x0], digits[0x1], digits[0x2], digits[0x3], digits[0x4], digits[0x5], digits[0x6], digits[0x7], - digits[0x8], digits[0x9], digits[0xA], digits[0xB], digits[0xC], digits[0xD], digits[0xE], digits[0xF]); + char if_name[IFNAMSIZ]; // Older Linux distributions don't define IF_NAMESIZE + const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *)address; + const unsigned char *b = (const unsigned char * )&s6->sin6_addr; + if (!if_indextoname(s6->sin6_scope_id, if_name)) + snprintf(if_name, sizeof(if_name), "<%d>", s6->sin6_scope_id); + snprintf(addr, sizeof(addr), "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X%%%s", + b[0x0], b[0x1], b[0x2], b[0x3], b[0x4], b[0x5], b[0x6], b[0x7], + b[0x8], b[0x9], b[0xA], b[0xB], b[0xC], b[0xD], b[0xE], b[0xF], if_name); } - printf("%s%6X%3d %-25s %-40s %d", op, flags, interfaceIndex, hostname, addr, ttl); + printf("%s%6X%3d %-25s %-44s %d", op, flags, interfaceIndex, hostname, addr, ttl); if (errorCode) { if (errorCode == kDNSServiceErr_NoSuchRecord) printf(" No Such Record"); diff --git a/Makefile b/Makefile index c6aca02..ef3c0ee 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ include /Developer/Makefiles/pb_makefiles/platform.make -MVERS = "mDNSResponder-170" +MVERS = "mDNSResponder-171.4" DDNSWRITECONFIG = "$(DSTROOT)/Library/Application Support/Bonjour/ddnswriteconfig" diff --git a/mDNSCore/DNSCommon.c b/mDNSCore/DNSCommon.c index 7c17df6..bffef7b 100644 --- a/mDNSCore/DNSCommon.c +++ b/mDNSCore/DNSCommon.c @@ -17,6 +17,29 @@ Change History (most recent first): $Log: DNSCommon.c,v $ +Revision 1.199 2008/03/14 19:58:38 mcguire + BTMM: Need ability to identify version of mDNSResponder client +Make sure we add the record when sending LLQ refreshes + +Revision 1.198 2008/03/07 23:29:24 cheshire +Fixed cosmetic byte order display issue in DumpPacket output + +Revision 1.197 2008/03/05 22:51:29 mcguire + BTMM: Need ability to identify version of mDNSResponder client +Even further refinements + +Revision 1.196 2008/03/05 22:01:53 cheshire + BTMM: Need ability to identify version of mDNSResponder client +Now that we optionally add the HINFO record, when rewriting the header fields into network byte +order, we need to use our updated msg->h.numAdditionals, not the stack variable numAdditionals + +Revision 1.195 2008/03/05 19:06:30 mcguire + BTMM: Need ability to identify version of mDNSResponder client +further refinements + +Revision 1.194 2008/03/05 00:26:06 cheshire + BTMM: Need ability to identify version of mDNSResponder client + Revision 1.193 2007/12/17 23:42:36 cheshire Added comments about DNSDigest_SignMessage() @@ -527,7 +550,7 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *rr, RDataBody *rd, rd->soa.serial, rd->soa.refresh, rd->soa.retry, rd->soa.expire, rd->soa.min); break; - case kDNSType_HINFO:// Display this the same as TXT (show all constituent string) + case kDNSType_HINFO:// Display this the same as TXT (show all constituent strings) case kDNSType_TXT: { mDNSu8 *t = rd->txt.c; while (t < rd->txt.c + rr->rdlength) @@ -2013,6 +2036,30 @@ mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease) return end; } +mDNSexport mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *end, DomainAuthInfo *authInfo) + { + if (authInfo && authInfo->AutoTunnel) + { + AuthRecord hinfo; + 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); + AppendDomainLabel(&hinfo.namestorage, &m->hostlabel); + AppendDomainName (&hinfo.namestorage, &authInfo->domain); + hinfo.resrec.rroriginalttl = 0; + mDNSPlatformMemCopy(h, &m->HIHardware, 1 + (mDNSu32)m->HIHardware.c[0]); + h += 1 + (int)h[0]; + mDNSPlatformMemCopy(h, &m->HISoftware, 1 + (mDNSu32)m->HISoftware.c[0]); + hinfo.resrec.rdlength = len; + hinfo.resrec.rdestimate = len; + newptr = PutResourceRecord(msg, end, &msg->h.numAdditionals, &hinfo.resrec); + return newptr; + } + else + return end; + } + // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK #pragma mark - @@ -2531,10 +2578,11 @@ mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNS mDNSInterfaceID InterfaceID, const mDNSAddr *dst, mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo) { mStatus status = mStatus_NoError; - mDNSu16 numQuestions = msg->h.numQuestions; - mDNSu16 numAnswers = msg->h.numAnswers; - mDNSu16 numAuthorities = msg->h.numAuthorities; - mDNSu16 numAdditionals = msg->h.numAdditionals; + const mDNSu16 numQuestions = msg->h.numQuestions; + const mDNSu16 numAnswers = msg->h.numAnswers; + const mDNSu16 numAuthorities = msg->h.numAuthorities; + const mDNSu16 numAdditionals = msg->h.numAdditionals; + mDNSu16 tmpNumAdditionals = numAdditionals; mDNSu8 *ptr = (mDNSu8 *)&msg->h.numQuestions; if (end <= msg->data || end - msg->data > AbsoluteMaxDNSMessageData) @@ -2543,33 +2591,40 @@ mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNS return mStatus_BadParamErr; } - // Put all the integer values in IETF byte-order (MSB first, LSB second) - *ptr++ = (mDNSu8)(numQuestions >> 8); - *ptr++ = (mDNSu8)(numQuestions & 0xFF); - *ptr++ = (mDNSu8)(numAnswers >> 8); - *ptr++ = (mDNSu8)(numAnswers & 0xFF); - *ptr++ = (mDNSu8)(numAuthorities >> 8); - *ptr++ = (mDNSu8)(numAuthorities & 0xFF); - *ptr++ = (mDNSu8)(numAdditionals >> 8); - *ptr++ = (mDNSu8)(numAdditionals & 0xFF); - - if (authInfo) DNSDigest_SignMessage(msg, &end, authInfo, 0); // DNSDigest_SignMessage operates on message in network byte order - if (!end) { LogMsg("mDNSSendDNSMessage: DNSDigest_SignMessage failed"); status = mStatus_NoMemoryErr; } + end = putHINFO(m, msg, end, authInfo); + if (!end) { LogMsg("mDNSSendDNSMessage: putHINFO failed"); status = mStatus_NoMemoryErr; } else { - // Send the packet on the wire - if (!sock) - status = mDNSPlatformSendUDP(m, msg, end, InterfaceID, dst, dstport); + tmpNumAdditionals = msg->h.numAdditionals; + + // Put all the integer values in IETF byte-order (MSB first, LSB second) + *ptr++ = (mDNSu8)(numQuestions >> 8); + *ptr++ = (mDNSu8)(numQuestions & 0xFF); + *ptr++ = (mDNSu8)(numAnswers >> 8); + *ptr++ = (mDNSu8)(numAnswers & 0xFF); + *ptr++ = (mDNSu8)(numAuthorities >> 8); + *ptr++ = (mDNSu8)(numAuthorities & 0xFF); + *ptr++ = (mDNSu8)(tmpNumAdditionals >> 8); + *ptr++ = (mDNSu8)(tmpNumAdditionals & 0xFF); + + if (authInfo) DNSDigest_SignMessage(msg, &end, authInfo, 0); // DNSDigest_SignMessage operates on message in network byte order + if (!end) { LogMsg("mDNSSendDNSMessage: DNSDigest_SignMessage failed"); status = mStatus_NoMemoryErr; } else { - mDNSu16 msglen = (mDNSu16)(end - (mDNSu8 *)msg); - mDNSu8 lenbuf[2] = { (mDNSu8)(msglen >> 8), (mDNSu8)(msglen & 0xFF) }; - long nsent = mDNSPlatformWriteTCP(sock, (char*)lenbuf, 2); // Should do scatter/gather here -- this is probably going out as two packets - if (nsent != 2) { LogMsg("mDNSSendDNSMessage: write msg length failed %d/%d", nsent, 2); status = mStatus_ConnFailed; } + // Send the packet on the wire + if (!sock) + status = mDNSPlatformSendUDP(m, msg, end, InterfaceID, dst, dstport); else { - nsent = mDNSPlatformWriteTCP(sock, (char *)msg, msglen); - if (nsent != msglen) { LogMsg("mDNSSendDNSMessage: write msg body failed %d/%d", nsent, msglen); status = mStatus_ConnFailed; } + mDNSu16 msglen = (mDNSu16)(end - (mDNSu8 *)msg); + mDNSu8 lenbuf[2] = { (mDNSu8)(msglen >> 8), (mDNSu8)(msglen & 0xFF) }; + long nsent = mDNSPlatformWriteTCP(sock, (char*)lenbuf, 2); // Should do scatter/gather here -- this is probably going out as two packets + if (nsent != 2) { LogMsg("mDNSSendDNSMessage: write msg length failed %d/%d", nsent, 2); status = mStatus_ConnFailed; } + else + { + nsent = mDNSPlatformWriteTCP(sock, (char *)msg, msglen); + if (nsent != msglen) { LogMsg("mDNSSendDNSMessage: write msg body failed %d/%d", nsent, msglen); status = mStatus_ConnFailed; } + } } } } @@ -2578,15 +2633,18 @@ mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNS msg->h.numQuestions = numQuestions; msg->h.numAnswers = numAnswers; msg->h.numAuthorities = numAuthorities; - msg->h.numAdditionals = numAdditionals; + // Dump the packet with the HINFO and TSIG if (mDNS_LogLevel >= MDNS_LOG_VERBOSE_DEBUG && !mDNSOpaque16IsZero(msg->h.id)) { - if (authInfo) msg->h.numAdditionals++; // Want to include TSIG in DumpPacket output + ptr = (mDNSu8 *)&msg->h.numAdditionals; + msg->h.numAdditionals = (mDNSu16)ptr[0] << 8 | (mDNSu16)ptr[1]; DumpPacket(m, mDNStrue, sock && (sock->flags & kTCPSocketFlags_UseTLS) ? "TLS" : sock ? "TCP" : "UDP", dst, dstport, msg, end); - if (authInfo) msg->h.numAdditionals--; } + // put the final integer value back the way it was + msg->h.numAdditionals = numAdditionals; + return(status); } diff --git a/mDNSCore/DNSCommon.h b/mDNSCore/DNSCommon.h index f186ac6..6556031 100644 --- a/mDNSCore/DNSCommon.h +++ b/mDNSCore/DNSCommon.h @@ -17,6 +17,13 @@ Change History (most recent first): $Log: DNSCommon.h,v $ +Revision 1.59 2008/03/14 19:58:38 mcguire + BTMM: Need ability to identify version of mDNSResponder client +Make sure we add the record when sending LLQ refreshes + +Revision 1.58 2008/03/06 21:26:10 cheshire +Moved duplicated STRINGIFY macro from individual C files to DNSCommon.h + Revision 1.57 2007/12/13 20:20:17 cheshire Minor efficiency tweaks -- converted IdenticalResourceRecord, IdenticalSameNameRecord, and SameRData from functions to macros, which allows the code to be inlined (the compiler can't @@ -111,6 +118,15 @@ Split out SameRDataBody() into a separate routine so it can be called from other extern "C" { #endif +//************************************************************************************************************* +// Macros + +// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion +// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4" +// To expand "version" to its value before making the string, use STRINGIFY(version) instead +#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) #s +#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) + // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK #pragma mark - DNS Protocol Constants @@ -278,6 +294,8 @@ extern mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease); #define PutResourceRecord(MSG, P, C, RR) PutResourceRecordTTL((MSG), (P), (C), (RR), (RR)->rroriginalttl) +extern mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *end, DomainAuthInfo *authInfo); + // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK #pragma mark - diff --git a/mDNSCore/mDNS.c b/mDNSCore/mDNS.c index 2d4f110..34a3c7c 100755 --- a/mDNSCore/mDNS.c +++ b/mDNSCore/mDNS.c @@ -38,6 +38,41 @@ Change History (most recent first): $Log: mDNS.c,v $ +Revision 1.776 2008/04/17 20:14:14 cheshire + CurrentAnswers/LargeAnswers/UniqueAnswers counter mismatch + +Revision 1.775 2008/03/26 01:53:34 mcguire + Can't resolve via uDNS when an interface is specified + +Revision 1.774 2008/03/17 17:46:08 mcguire +When activating an LLQ, reset all the important state and destroy any tcp connection, +so that everything will be restarted as if the question had just been asked. +Also reset servPort, so that the SOA query will be re-issued. + +Revision 1.773 2008/03/14 22:52:36 mcguire + write status to the DS +Update status when any unicast LLQ is started + +Revision 1.772 2008/03/06 02:48:34 mcguire + write status to the DS + +Revision 1.771 2008/02/26 22:04:44 cheshire + BTMM: Too many members.mac.com SOA queries +Additional fixes -- should not be calling uDNS_CheckCurrentQuestion on a +question while it's still in our 'm->NewQuestions' section of the list + +Revision 1.770 2008/02/22 23:09:02 cheshire + BTMM: Not processing additional records +Refinements: +1. Check rdatahash == namehash, to skip expensive SameDomainName check when possible +2. Once we decide a record is acceptable, we can break out of the loop + +Revision 1.769 2008/02/22 00:00:19 cheshire + BTMM: Not processing additional records + +Revision 1.768 2008/02/19 23:26:50 cheshire + BTMM: Too many members.mac.com SOA queries + Revision 1.767 2007/12/22 02:25:29 cheshire Records and Services sometimes not re-registering on wake from sleep @@ -2444,7 +2479,7 @@ mDNSlocal void SendQueries(mDNS *const m) if (m->CurrentQuestion) LogMsg("SendQueries ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); m->CurrentQuestion = m->Questions; - while (m->CurrentQuestion) + while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions) { q = m->CurrentQuestion; if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID)) uDNS_CheckCurrentQuestion(m); @@ -2476,6 +2511,7 @@ mDNSlocal void SendQueries(mDNS *const m) // m->CurrentQuestion point to the right question if (q == m->CurrentQuestion) m->CurrentQuestion = m->CurrentQuestion->next; } + m->CurrentQuestion = mDNSNULL; // Scan our list of questions // (a) to see if there are any more that are worth accelerating, and @@ -2484,7 +2520,7 @@ mDNSlocal void SendQueries(mDNS *const m) // which causes NextScheduledQuery to get (incorrectly) set to m->timenow. Setting it here is the right place, because the very // next thing we do is scan the list and call SetNextQueryTime() for every question we find, so we know we end up with the right value. m->NextScheduledQuery = m->timenow + 0x78000000; - for (q = m->Questions; q; q=q->next) + for (q = m->Questions; q && q != m->NewQuestions; q=q->next) { if (mDNSOpaque16IsZero(q->TargetQID) && (q->SendQNow || (!q->Target.type && ActiveQuestion(q) && q->ThisQInterval <= maxExistingQuestionInterval && AccelerateThisQuery(m,q)))) @@ -2617,7 +2653,7 @@ mDNSlocal void SendQueries(mDNS *const m) mDNSu32 answerforecast = 0; // Put query questions in this packet - for (q = m->Questions; q; q=q->next) + for (q = m->Questions; q && q != m->NewQuestions; q=q->next) { if (mDNSOpaque16IsZero(q->TargetQID) && (q->SendQNow == intf->InterfaceID)) { @@ -2802,6 +2838,7 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco q->RecentAnswerPkts = 0; q->ThisQInterval = MaxQuestionInterval; q->RequestUnicast = mDNSfalse; + debugf("AnswerCurrentQuestionWithResourceRecord: Set MaxQuestionInterval for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); } if (rr->DelayDelivery) return; // We'll come back later when CacheRecordDeferredAdd() calls us @@ -2878,7 +2915,10 @@ mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *c mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr) { DNSQuestion *q; - for (q = m->Questions; q; q=q->next) + + // We stop when we get to NewQuestions -- if we increment their CurrentAnswers/LargeAnswers/UniqueAnswers + // counters here we'll end up double-incrementing them when we do it again in AnswerNewQuestion(). + for (q = m->Questions; q && q != m->NewQuestions; q=q->next) { if (ResourceRecordAnswersQuestion(&rr->resrec, q)) { @@ -2953,6 +2993,8 @@ mDNSlocal void NoCacheAnswer(mDNS *const m, CacheRecord *rr) if (m->CurrentQuestion) LogMsg("NoCacheAnswer ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); m->CurrentQuestion = m->Questions; + // We do this for *all* questions, not stopping when we get to m->NewQuestions, + // since we're not caching the record and we'll get no opportunity to do this later while (m->CurrentQuestion) { DNSQuestion *q = m->CurrentQuestion; @@ -2964,7 +3006,8 @@ mDNSlocal void NoCacheAnswer(mDNS *const m, CacheRecord *rr) m->CurrentQuestion = mDNSNULL; } -// CacheRecordRmv is only called from CheckCacheExpiration, which is called from mDNS_Execute +// CacheRecordRmv is only called from CheckCacheExpiration, which is called from mDNS_Execute. +// Note that CacheRecordRmv is *only* called for records that are referenced by at least one active question. // If new questions are created as a result of invoking client callbacks, they will be added to // the end of the question list, and m->NewQuestions will be set to indicate the first new question. // rr is an existing cache CacheRecord that just expired and is being deleted @@ -2977,6 +3020,9 @@ mDNSlocal void CacheRecordRmv(mDNS *const m, CacheRecord *rr) if (m->CurrentQuestion) LogMsg("CacheRecordRmv ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); m->CurrentQuestion = m->Questions; + + // We stop when we get to NewQuestions -- for new questions their CurrentAnswers/LargeAnswers/UniqueAnswers counters + // will all still be zero because we haven't yet gone through the cache counting how many answers we have for them. while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions) { DNSQuestion *q = m->CurrentQuestion; @@ -3156,6 +3202,8 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m) m->CurrentRecord = mDNSNULL; } + if (m->CurrentQuestion != q) debugf("AnswerNewQuestion: question deleted while giving LocalOnly record answers"); + if (m->CurrentQuestion == q) { CacheRecord *rr; @@ -3186,19 +3234,23 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m) ShouldQueryImmediately = mDNSfalse; } + if (m->CurrentQuestion != q) debugf("AnswerNewQuestion: question deleted while giving cache answers"); + if (m->CurrentQuestion == q && ShouldQueryImmediately && ActiveQuestion(q)) { + debugf("AnswerNewQuestion: ShouldQueryImmediately %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); q->ThisQInterval = InitialQuestionInterval; q->LastQTime = m->timenow - q->ThisQInterval; - if (mDNSOpaque16IsZero(q->TargetQID)) + if (mDNSOpaque16IsZero(q->TargetQID)) // For mDNS, spread packets to avoid a burst of simultaneous queries { // Compute random delay in the range 1-6 seconds, then divide by 50 to get 20-120ms if (!m->RandomQueryDelay) m->RandomQueryDelay = (mDNSPlatformOneSecond + mDNSRandom(mDNSPlatformOneSecond*5) - 1) / 50 + 1; q->LastQTime += m->RandomQueryDelay; } - - m->NextScheduledQuery = m->timenow; + + if (m->NextScheduledQuery - (q->LastQTime + q->ThisQInterval) > 0) + m->NextScheduledQuery = (q->LastQTime + q->ThisQInterval); } m->CurrentQuestion = mDNSNULL; @@ -3210,7 +3262,7 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m) mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m) { DNSQuestion *q = m->NewLocalOnlyQuestions; // Grab the question we're going to answer - m->NewLocalOnlyQuestions = q->next; // Advance NewQuestions to the next (if any) + m->NewLocalOnlyQuestions = q->next; // Advance NewLocalOnlyQuestions to the next (if any) debugf("AnswerNewLocalOnlyQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); @@ -3470,7 +3522,7 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) LogMsg("mDNS_Execute: SendQueries didn't send all its queries (%d - %d = %d) will try again in one second", m->timenow, m->NextScheduledQuery, m->timenow - m->NextScheduledQuery); m->NextScheduledQuery = m->timenow + mDNSPlatformOneSecond; - for (q = m->Questions; q; q=q->next) + for (q = m->Questions; q && q != m->NewQuestions; q=q->next) if (ActiveQuestion(q) && q->LastQTime + q->ThisQInterval - m->timenow <= 0) LogMsg("mDNS_Execute: SendQueries didn't send %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); } @@ -3530,7 +3582,13 @@ mDNSlocal void SuspendLLQs(mDNS *m) { q->ReqLease = 0; sendLLQRefresh(m, q); } } -mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question) +// ActivateUnicastQuery() is called from three places: +// 1. When a new question is created +// 2. On wake from sleep +// 3. When the DNS configuration changes +// In case 1 we don't want to mess with our established ThisQInterval and LastQTime (ScheduleImmediately is false) +// In cases 2 and 3 we do want to cause the question to be resent immediately (ScheduleImmediately is true) +mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question, mDNSBool ScheduleImmediately) { // 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 @@ -3550,13 +3608,22 @@ mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question) if (!question->DuplicateOf) { - LogOperation("ActivateUnicastQuery: %##s %s%s", - question->qname.c, DNSTypeName(question->qtype), question->AuthInfo ? " (Private)" : ""); + LogOperation("ActivateUnicastQuery: %##s %s%s%s", + question->qname.c, DNSTypeName(question->qtype), question->AuthInfo ? " (Private)" : "", ScheduleImmediately ? " ScheduleImmediately" : ""); if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; } - if (question->LongLived) { question->state = LLQ_InitialRequest; question->id = zeroOpaque64; } - question->ThisQInterval = InitialQuestionInterval; - question->LastQTime = m->timenow - question->ThisQInterval; - SetNextQueryTime(m, question); + if (question->LongLived) + { + question->state = LLQ_InitialRequest; + question->id = zeroOpaque64; + question->servPort = zeroIPPort; + if (question->tcp) { DisposeTCPConn(question->tcp); question->tcp = mDNSNULL; } + } + if (ScheduleImmediately) + { + question->ThisQInterval = InitialQuestionInterval; + question->LastQTime = m->timenow - question->ThisQInterval; + SetNextQueryTime(m, question); + } } } @@ -3609,7 +3676,7 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleepstate) { q = m->CurrentQuestion; m->CurrentQuestion = m->CurrentQuestion->next; - if (!mDNSOpaque16IsZero(q->TargetQID)) ActivateUnicastQuery(m, q); + if (!mDNSOpaque16IsZero(q->TargetQID)) ActivateUnicastQuery(m, q, mDNStrue); } // and reactivtate service registrations m->NextSRVUpdate = NonZeroTime(m->timenow + mDNSPlatformOneSecond); @@ -4406,6 +4473,8 @@ mDNSexport CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, C default: RDLength = m->rec.r.resrec.rdlength; break; } + if (!m->rec.r.resrec.InterfaceID) debugf("CreateNewCacheEntry %s", CRDisplayString(m, &m->rec.r)); + //if (RDLength > InlineCacheRDSize) // LogOperation("Rdata len %4d > InlineCacheRDSize %d %s", RDLength, InlineCacheRDSize, CRDisplayString(m, &m->rec.r)); @@ -4525,7 +4594,9 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, // All records in a DNS response packet are treated as equally valid statements of truth. If we want // to guard against spoof responses, then the only credible protection against that is cryptographic // security, e.g. DNSSEC., not worring about which section in the spoof packet contained the record - int totalrecords = response->h.numAnswers + response->h.numAuthorities + response->h.numAdditionals; + int firstauthority = response->h.numAnswers; + int firstadditional = firstauthority + response->h.numAuthorities; + int totalrecords = firstadditional + response->h.numAdditionals; const mDNSu8 *ptr = response->data; // Currently used only for display in debugging message @@ -4589,9 +4660,12 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, // (Note that just because we are willing to cache something, that doesn't necessarily make it a trustworthy answer // to any specific question -- any code reading records from the cache needs to make that determination for itself.) - const mDNSu8 RecordType = (mDNSu8)((i < response->h.numAnswers) ? kDNSRecordTypePacketAns : kDNSRecordTypePacketAdd); + const mDNSu8 RecordType = + (i < firstauthority ) ? (mDNSu8)kDNSRecordTypePacketAns : + (i < firstadditional) ? (mDNSu8)kDNSRecordTypePacketAuth : (mDNSu8)kDNSRecordTypePacketAdd; ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, RecordType, &m->rec); if (!ptr) goto exit; // Break out of the loop and clean up our CacheFlushRecords list before exiting + // Don't want to cache OPT or TSIG pseudo-RRs if (m->rec.r.resrec.rrtype == kDNSType_OPT || m->rec.r.resrec.rrtype == kDNSType_TSIG) { m->rec.r.resrec.RecordType = 0; continue; } @@ -4691,9 +4765,21 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, } } + if (!AcceptableResponse) + { + CacheRecord *cr; + for (cr = CacheFlushRecords; cr != (CacheRecord*)1; cr = cr->NextInCFList) + { + domainname *target = GetRRDomainNameTarget(&cr->resrec); + if (target && cr->resrec.rdatahash == m->rec.r.resrec.namehash && SameDomainName(target, m->rec.r.resrec.name)) + { AcceptableResponse = mDNStrue; break; } + } + } + // 2. See if we want to add this packet resource record to our cache // We only try to cache answers if we have a cache to put them in // Also, we ignore any apparent attempts at cache poisoning unicast to us that do not answer any outstanding active query + if (!AcceptableResponse) debugf("mDNSCoreReceiveResponse ignoring %s", CRDisplayString(m, &m->rec.r)); if (m->rrcache_size && AcceptableResponse) { const mDNSu32 slot = HashSlot(m->rec.r.resrec.name); @@ -5198,6 +5284,9 @@ mDNSlocal void LLQNATCallback(mDNS *m, NATTraversalInfo *n) for (q = m->Questions; q; q=q->next) if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID) && q->LongLived) startLLQHandshake(m, q); // If ExternalPort is zero, will do StartLLQPolling instead +#if APPLE_OSX_mDNSResponder + UpdateAutoTunnelDomainStatuses(m); +#endif mDNS_Unlock(m); } @@ -5216,16 +5305,11 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu question->TargetQID = zeroID; } + question->TargetQID = #ifndef UNICAST_DISABLED - // If the client has specified 'kDNSServiceFlagsForceMulticast' - // then we do a multicast query on that interface, even for unicast domains. - if (question->InterfaceID == mDNSInterface_LocalOnly || question->ForceMCast || IsLocalDomain(&question->qname)) - question->TargetQID = zeroID; - else - question->TargetQID = mDNS_NewMessageID(m); -#else - question->TargetQID = zeroID; + (question->InterfaceID != mDNSInterface_LocalOnly && !question->ForceMCast && !IsLocalDomain(&question->qname)) ? mDNS_NewMessageID(m) : #endif // UNICAST_DISABLED + zeroID; debugf("mDNS_StartQuery: %##s (%s)", question->qname.c, DNSTypeName(question->qtype)); @@ -5312,14 +5396,11 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu for (i=0; iDupSuppress[i].InterfaceID = mDNSNULL; - if (!question->DuplicateOf) - debugf("mDNS_StartQuery: Question %##s (%s) %p %d (%p) started", - question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, - question->LastQTime + question->ThisQInterval - m->timenow, question); - else - debugf("mDNS_StartQuery: Question %##s (%s) %p %d (%p) duplicate of (%p)", - question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, - question->LastQTime + question->ThisQInterval - m->timenow, question, question->DuplicateOf); + debugf("mDNS_StartQuery: Question %##s (%s) Interface %p Now %d Send in %d Answer in %d (%p) %s (%p)", + question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, m->timenow, + question->LastQTime + question->ThisQInterval - m->timenow, + question->DelayAnswering ? question->DelayAnswering - m->timenow : 0, + question, question->DuplicateOf ? "duplicate of" : "not duplicate", question->DuplicateOf); if (question->InterfaceID == mDNSInterface_LocalOnly) { @@ -5338,7 +5419,7 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu if (!mDNSOpaque16IsZero(question->TargetQID)) { question->qDNSServer = GetServerForName(m, &question->qname); - ActivateUnicastQuery(m, question); + ActivateUnicastQuery(m, question, mDNSfalse); // If long-lived query, and we don't have our NAT mapping active, start it now if (question->LongLived && !m->LLQNAT.clientContext) @@ -5350,6 +5431,12 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu m->LLQNAT.clientContext = (void*)1; // Means LLQ NAT Traversal is active mDNS_StartNATOperation_internal(m, &m->LLQNAT); } + +#if APPLE_OSX_mDNSResponder + if (question->LongLived) + UpdateAutoTunnelDomainStatuses(m); +#endif + } SetNextQueryTime(m,question); } @@ -5475,6 +5562,9 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que question->tcp = mDNSNULL; } } +#if APPLE_OSX_mDNSResponder + UpdateAutoTunnelDomainStatuses(m); +#endif } return(mStatus_NoError); @@ -7062,7 +7152,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) s, s ? &s->addr : mDNSNULL, mDNSVal16(s ? s->port : zeroIPPort), s ? s->domain.c : (mDNSu8*)"", q->qname.c, DNSTypeName(q->qtype)); q->qDNSServer = s; - ActivateUnicastQuery(m, q); + ActivateUnicastQuery(m, q, mDNStrue); } } diff --git a/mDNSCore/mDNSDebug.h b/mDNSCore/mDNSDebug.h index 81bcedb..7301087 100755 --- a/mDNSCore/mDNSDebug.h +++ b/mDNSCore/mDNSDebug.h @@ -17,6 +17,9 @@ Change History (most recent first): $Log: mDNSDebug.h,v $ +Revision 1.39 2008/02/26 21:17:11 cheshire +Grouped all user settings together near the start of the file; added LogTimeStamps option + Revision 1.38 2007/12/13 20:27:07 cheshire Remove unused VerifySameNameAssumptions symbol @@ -136,6 +139,32 @@ Merge in license terms from Quinn's copy, in preparation for Darwin release // warning: repeated `#' flag in format (for %##s -- DNS name string format) // warning: double format, pointer arg (arg 2) (for %.4a, %.16a, %#a -- IP address formats) #define MDNS_CHECK_PRINTF_STYLE_FUNCTIONS 0 + +typedef enum + { + MDNS_LOG_NONE, +// MDNS_LOG_ERROR, +// MDNS_LOG_WARN, +// MDNS_LOG_INFO, +// MDNS_LOG_DEBUG, + MDNS_LOG_VERBOSE_DEBUG + } LogLevel_t; + +#define MDNS_LOG_INITIAL_LEVEL MDNS_LOG_NONE + +// Set this symbol to 1 to answer remote queries for our Address, reverse mapping PTR, and HINFO records +#define ANSWER_REMOTE_HOSTNAME_QUERIES 0 + +// Set this symbol to 1 to do extra debug checks on malloc() and free() +// Set this symbol to 2 to write a log message for every malloc() and free() +#define MACOSX_MDNS_MALLOC_DEBUGGING 0 + +#define LogAllOperations 0 +#define LogTimeStamps 0 +#define ForceAlerts 0 + +// Developer-settings section ends here + #if MDNS_CHECK_PRINTF_STYLE_FUNCTIONS #define IS_A_PRINTF_STYLE_FUNCTION(F,A) __attribute__ ((format(printf,F,A))) #else @@ -198,18 +227,6 @@ extern void verbosedebugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1 #endif // LogMsg is used even in shipping code, to write truly serious error messages to syslog (or equivalent) -typedef enum - { - MDNS_LOG_NONE, -// MDNS_LOG_ERROR, -// MDNS_LOG_WARN, -// MDNS_LOG_INFO, -// MDNS_LOG_DEBUG, - MDNS_LOG_VERBOSE_DEBUG - } LogLevel_t; - -#define MDNS_LOG_INITIAL_LEVEL MDNS_LOG_NONE - extern LogLevel_t mDNS_LogLevel; extern int mDNS_DebugMode; // If non-zero, LogMsg() writes to stderr instead of syslog extern const char ProgramName[]; // Program Name for use with LogMsgIdent @@ -219,13 +236,6 @@ extern void LogMsgIdent(const char *ident, const char *format, ...) IS_A_PRINTF_ extern void LogMsgNoIdent(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2); extern void SigLogLevel(void); -// Set this symbol to 1 to answer remote queries for our Address, reverse mapping PTR, and HINFO records -#define ANSWER_REMOTE_HOSTNAME_QUERIES 0 - -// Set this symbol to 1 to do extra debug checks on malloc() and free() -// Set this symbol to 2 to write a log message for every malloc() and free() -#define MACOSX_MDNS_MALLOC_DEBUGGING 0 - #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1 extern void *mallocL(char *msg, unsigned int size); extern void freeL(char *msg, void *x); @@ -237,16 +247,12 @@ extern void udns_validatelists(void *const v); #define freeL(X,Y) free(Y) #endif -#define LogAllOperations 0 - #if LogAllOperations #define LogOperation LogMsg #else #define LogOperation debugf #endif -#define ForceAlerts 0 - #ifdef __cplusplus } #endif diff --git a/mDNSCore/mDNSEmbeddedAPI.h b/mDNSCore/mDNSEmbeddedAPI.h index a67e1f3..72b9e1f 100755 --- a/mDNSCore/mDNSEmbeddedAPI.h +++ b/mDNSCore/mDNSEmbeddedAPI.h @@ -54,6 +54,21 @@ Change History (most recent first): $Log: mDNSEmbeddedAPI.h,v $ +Revision 1.468 2008/03/06 02:48:34 mcguire + write status to the DS + +Revision 1.467 2008/02/26 20:48:46 cheshire +Need parentheses around use of macro argument in mDNS_TimeNow_NoLock(m) + +Revision 1.466 2008/02/21 21:36:32 cheshire +Updated comment about record type values (kDNSRecordTypePacketAns/Auth/Add) + +Revision 1.465 2008/02/20 00:39:05 mcguire + Some device info XML blobs too large + +Revision 1.464 2008/01/31 23:33:29 mcguire + changes to build using gcc 4.2 with -Werror + Revision 1.463 2007/12/17 23:53:25 cheshire Added DNSDigest_SignMessageHostByteOrder, for signing messages not yet converted to network byte order @@ -892,9 +907,11 @@ enum mStatus_BadKey = -65561, mStatus_TransientErr = -65562, // transient failures, e.g. sending packets shortly after a network transition or wake from sleep mStatus_ServiceNotRunning = -65563, // Background daemon not running - mStatus_NATPortMappingUnsupported = -65564, // No NAT or if the NAT doesn't support NAT-PMP or UPnP + mStatus_NATPortMappingUnsupported = -65564, // NAT doesn't support NAT-PMP or UPnP mStatus_NATPortMappingDisabled = -65565, // NAT supports NAT-PMP or UPnP but it's disabled by the administrator - // -65566 to -65786 currently unused; available for allocation + mStatus_NoRouter = -65566, + mStatus_PollingMode = -65567, + // -65568 to -65786 currently unused; available for allocation // tcp connection status mStatus_ConnPending = -65787, @@ -1070,7 +1087,7 @@ typedef struct tcpInfo_t // Cache Resource Records (received from the network): // There are four basic types: Answer, Unique Answer, Additional, Unique Additional // Bit 7 (the top bit) of kDNSRecordType is always set for Cache Resource Records; always clear for Authoritative Resource Records -// Bit 6 (value 0x40) is set for answer records; clear for additional records +// Bit 6 (value 0x40) is set for answer records; clear for authority/additional records // Bit 5 (value 0x20) is set for records received with the kDNSClass_UniqueRRSet enum @@ -1271,7 +1288,7 @@ typedef enum LNTPortMapDeleteOp = 4 } LNTOp_t; -#define LNT_MAXBUFSIZE 4096 +#define LNT_MAXBUFSIZE 8192 typedef struct tcpLNTInfo_struct tcpLNTInfo; struct tcpLNTInfo_struct { @@ -2493,8 +2510,9 @@ extern void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, const extern DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port); extern void mDNS_AddSearchDomain(const domainname *const domain); +// 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) && MakeDomainNameFromDNSNameString(&d__, (X)) && d__.c[0]) mDNS_AddSearchDomain(&d__); } while(0) + do { domainname d__; if (((X) != (void*)0) && MakeDomainNameFromDNSNameString(&d__, (X)) && d__.c[0]) mDNS_AddSearchDomain(&d__); } while(0) // Routines called by the core, exported by DNSDigest.c @@ -2580,7 +2598,7 @@ extern mDNSu32 mDNSPlatformRandomSeed (void); extern mStatus mDNSPlatformTimeInit (void); extern mDNSs32 mDNSPlatformRawTime (void); extern mDNSs32 mDNSPlatformUTC (void); -#define mDNS_TimeNow_NoLock(m) (mDNSPlatformRawTime() + m->timenow_adjust) +#define mDNS_TimeNow_NoLock(m) (mDNSPlatformRawTime() + (m)->timenow_adjust) #if MDNS_DEBUGMSGS extern void mDNSPlatformWriteDebugMsg(const char *msg); @@ -2707,6 +2725,7 @@ extern void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord * extern void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord); extern void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q); extern void SetupLocalAutoTunnelInterface_internal(mDNS *const m); +extern void UpdateAutoTunnelDomainStatuses(const mDNS *const m); #endif // *************************************************************************** diff --git a/mDNSCore/uDNS.c b/mDNSCore/uDNS.c index bcf8ddf..e063fc5 100755 --- a/mDNSCore/uDNS.c +++ b/mDNSCore/uDNS.c @@ -22,6 +22,37 @@ Change History (most recent first): $Log: uDNS.c,v $ +Revision 1.553.2.1 2008/03/14 20:11:25 mcguire + BTMM: Need ability to identify version of mDNSResponder client +Make sure we add the record when sending LLQ refreshes + +Revision 1.553 2008/03/06 02:48:34 mcguire + write status to the DS + +Revision 1.552 2008/03/05 01:56:42 cheshire + BTMM: Don't fallback to unencrypted operations when SRV lookup fails + +Revision 1.551 2008/03/01 01:43:04 cheshire + BTMM: Lots of "Error getting external address 3" when double-NATed prevents sleep +Added code to suppress logging of multiple identical error results + +Revision 1.550 2008/03/01 01:34:47 cheshire + BTMM: Double-NAT'd machines register all but AutoTunnel v4 address records +Further refinements + +Revision 1.549 2008/02/29 01:35:37 mcguire + BTMM: Double-NAT'd machines register all but AutoTunnel v4 address records + +Revision 1.548 2008/02/20 23:54:18 cheshire + "Failed to obtain NAT port mapping" syslog messages +Improved log message so it tells us more about what's going on + +Revision 1.547 2008/02/20 00:41:09 cheshire +Change "PrivateQueryGotZoneData ... invoked with error code" from LogMsg to LogOperation + +Revision 1.546 2008/02/19 23:26:50 cheshire + BTMM: Too many members.mac.com SOA queries + Revision 1.545 2007/12/22 02:25:29 cheshire Records and Services sometimes not re-registering on wake from sleep @@ -1461,7 +1492,11 @@ mDNSlocal void ClearUPnPState(mDNS *const m) mDNSexport void natTraversalHandleAddressReply(mDNS *const m, mDNSu16 err, mDNSv4Addr ExtAddr) { - if (err) LogMsg("Error getting external address %d", err); + static mDNSu16 last_err; + if (err) + { + if (err != last_err) LogMsg("Error getting external address %d", err); + } else if (!mDNSSameIPv4Address(m->ExternalAddress, ExtAddr)) { LogOperation("Received external IP address %.4a from NAT", &ExtAddr); @@ -1477,6 +1512,8 @@ mDNSexport void natTraversalHandleAddressReply(mDNS *const m, mDNSu16 err, mDNSv m->retryGetAddr = m->timenow + m->retryIntervalGetAddr; if (m->NextScheduledNATOp - m->retryIntervalGetAddr > 0) m->NextScheduledNATOp = m->retryIntervalGetAddr; + + last_err = err; } // Both places that call NATSetNextRenewalTime() update m->NextScheduledNATOp correctly afterwards @@ -1635,6 +1672,9 @@ mDNSlocal void StartLLQPolling(mDNS *const m, DNSQuestion *q) // we risk causing spurious "SendQueries didn't send all its queries" log messages q->LastQTime = m->timenow - q->ThisQInterval + 1; SetNextQueryTime(m, q); +#if APPLE_OSX_mDNSResponder + UpdateAutoTunnelDomainStatuses(m); +#endif } mDNSlocal mDNSu8 *putLLQ(DNSMessage *const msg, mDNSu8 *ptr, const DNSQuestion *const question, const LLQOptData *const data, mDNSBool includeQuestion) @@ -1789,6 +1829,9 @@ mDNSlocal void recvSetupResponse(mDNS *const m, mDNSu8 rcode, DNSQuestion *const q->state = LLQ_Established; q->ntries = 0; SetLLQTimer(m, q, llq); +#if APPLE_OSX_mDNSResponder + UpdateAutoTunnelDomainStatuses(m); +#endif } } @@ -2426,12 +2469,17 @@ mDNSlocal void GetZoneData_QuestionCallback(mDNS *const m, DNSQuestion *question { debugf("GetZoneData GOT SRV %s", RRDisplayString(m, answer)); mDNS_StopQuery(m, question); +// Right now we don't want to fail back to non-encrypted operations +// If the AuthInfo has the AutoTunnel field set, then we want private or nothing +// BTMM: Don't fallback to unencrypted operations when SRV lookup fails +#if 0 if (!answer->rdlength && zd->ZonePrivate && zd->ZoneService != ZoneServiceQuery) { zd->ZonePrivate = mDNSfalse; // Causes ZoneDataSRV() to yield a different SRV name when building the query GetZoneData_StartQuery(m, zd, kDNSType_SRV); // Try again, non-private this time } else +#endif { if (answer->rdlength) { @@ -2515,7 +2563,7 @@ mDNSexport ZoneData *StartGetZoneData(mDNS *const m, const domainname *const nam zd->Host.c[0] = 0; zd->Port = zeroIPPort; zd->Addr = zeroAddr; - zd->ZonePrivate = AuthInfo ? mDNStrue : mDNSfalse; + zd->ZonePrivate = AuthInfo && AuthInfo->AutoTunnel ? mDNStrue : mDNSfalse; zd->ZoneDataCallback = callback; zd->ZoneDataContext = ZoneDataContext; @@ -3131,6 +3179,9 @@ mDNSexport void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, co UpdateSRVRecords(m); GetStaticHostname(m); // look up reverse map record to find any static hostnames for our IP address +#if APPLE_OSX_mDNSResponder + UpdateAutoTunnelDomainStatuses(m); +#endif } mDNS_Unlock(m); @@ -3719,6 +3770,27 @@ mDNSlocal const domainname *DNSRelayTestQuestion = (const domainname*) "\x1" "1" "\x1" "0" "\x1" "0" "\x3" "127" "\xa" "dnsbugtest" "\x1" "1" "\x1" "0" "\x1" "0" "\x3" "127" "\x7" "in-addr" "\x4" "arpa"; +// See comments above for DNSRelayTestQuestion +// If this is the kind of query that has the risk of crashing buggy DNS servers, we do a test question first +mDNSlocal mDNSBool NoTestQuery(DNSQuestion *q) + { + int i; + mDNSu8 *p = q->qname.c; + if (q->AuthInfo) return(mDNStrue); // Don't need a test query for private queries sent directly to authoritative server over TLS/TCP + if (q->qtype != kDNSType_PTR) return(mDNStrue); // Don't need a test query for any non-PTR queries + for (i=0; i<4; i++) // If qname does not begin with num.num.num.num, can't skip the test query + { + if (p[0] < 1 || p[0] > 3) return(mDNSfalse); + if ( p[1] < '0' || p[1] > '9' ) return(mDNSfalse); + if (p[0] >= 2 && (p[2] < '0' || p[2] > '9')) return(mDNSfalse); + if (p[0] >= 3 && (p[3] < '0' || p[3] > '9')) return(mDNSfalse); + p += 1 + p[0]; + } + // If remainder of qname is ".in-addr.arpa.", this is a vanilla reverse-mapping query and + // we can safely do it without needing a test query first, otherwise we need the test query. + return(SameDomainName((domainname*)p, (const domainname*)"\x7" "in-addr" "\x4" "arpa")); + } + // Returns mDNStrue if response was handled mDNSlocal mDNSBool uDNS_ReceiveTestQuestionResponse(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport) @@ -3747,15 +3819,15 @@ mDNSlocal mDNSBool uDNS_ReceiveTestQuestionResponse(mDNS *const m, DNSMessage *c if (mDNSSameAddress(srcaddr, &s->addr) && mDNSSameIPPort(srcport, s->port) && s->teststate != result) { DNSQuestion *q; - if (s->teststate != result) - { - s->teststate = result; - if (result == DNSServer_Passed) LogOperation("DNS Server %#a:%d passed", srcaddr, mDNSVal16(srcport)); - else LogMsg("NOTE: Wide-Area Service Discovery disabled to avoid crashing defective DNS relay %#a:%d", srcaddr, mDNSVal16(srcport)); - } + s->teststate = result; + if (result == DNSServer_Passed) LogOperation("DNS Server %#a:%d passed", srcaddr, mDNSVal16(srcport)); + else LogMsg("NOTE: Wide-Area Service Discovery disabled to avoid crashing defective DNS relay %#a:%d", srcaddr, mDNSVal16(srcport)); + + // If this server has just changed state from DNSServer_Untested to DNSServer_Passed, then retrigger any waiting questions. + // We use the NoTestQuery() test so that we only retrigger questions that were actually blocked waiting for this test to complete. if (result == DNSServer_Passed) // Unblock any questions that were waiting for this result for (q = m->Questions; q; q=q->next) - if (q->qDNSServer == s) + if (q->qDNSServer == s && !NoTestQuery(q)) { q->LastQTime = m->timenow - q->ThisQInterval; m->NextScheduledQuery = m->timenow; } } @@ -3882,6 +3954,12 @@ mDNSexport void sendLLQRefresh(mDNS *m, DNSQuestion *q) InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags); end = putLLQ(&m->omsg, m->omsg.data, q, &llq, mDNStrue); if (!end) { LogMsg("sendLLQRefresh: putLLQ failed %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); return; } + + // Note that we (conditionally) add HINFO and TSIG here, since the question might be going away, + // so we may not be able to reference it (most importantly it's AuthInfo) when we actually send the message + end = putHINFO(m, &m->omsg, end, q->AuthInfo); + if (!end) { LogMsg("sendLLQRefresh: putHINFO failed %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); return; } + if (q->AuthInfo) { DNSDigest_SignMessageHostByteOrder(&m->omsg, &end, q->AuthInfo); @@ -3951,9 +4029,12 @@ mDNSlocal void PrivateQueryGotZoneData(mDNS *const m, mStatus err, const ZoneDat // we use for cleaning up if our LLQ is cancelled *before* the GetZoneData operation has completes). q->nta = mDNSNULL; - if (err) + if (err || !zoneInfo || mDNSAddressIsZero(&zoneInfo->Addr) || mDNSIPPortIsZero(zoneInfo->Port)) { - LogMsg("ERROR: PrivateQueryGotZoneData %##s (%s) invoked with error code %ld", q->qname.c, DNSTypeName(q->qtype), err); + LogOperation("ERROR: PrivateQueryGotZoneData %##s (%s) invoked with error code %ld %p %#a:%d", + q->qname.c, DNSTypeName(q->qtype), err, zoneInfo, + zoneInfo ? &zoneInfo->Addr : mDNSNULL, + zoneInfo ? mDNSVal16(zoneInfo->Port) : 0); return; } @@ -4250,27 +4331,6 @@ mDNSexport mStatus uDNS_UpdateRecord(mDNS *m, AuthRecord *rr) #pragma mark - Periodic Execution Routines #endif -// See comments above for DNSRelayTestQuestion -// If this is the kind of query that has the risk of crashing buggy DNS servers, we do a test question first -mDNSlocal mDNSBool NoTestQuery(DNSQuestion *q) - { - int i; - mDNSu8 *p = q->qname.c; - if (q->AuthInfo) return(mDNStrue); // Don't need a test query for private queries sent directly to authoritative server over TLS/TCP - if (q->qtype != kDNSType_PTR) return(mDNStrue); // Don't need a test query for any non-PTR queries - for (i=0; i<4; i++) // If qname does not begin with num.num.num.num, can't skip the test query - { - if (p[0] < 1 || p[0] > 3) return(mDNSfalse); - if ( p[1] < '0' || p[1] > '9' ) return(mDNSfalse); - if (p[0] >= 2 && (p[2] < '0' || p[2] > '9')) return(mDNSfalse); - if (p[0] >= 3 && (p[3] < '0' || p[3] > '9')) return(mDNSfalse); - p += 1 + p[0]; - } - // If remainder of qname is ".in-addr.arpa.", this is a vanilla reverse-mapping query and - // we can safely do it without needing a test query first, otherwise we need the test query. - return(SameDomainName((domainname*)p, (const domainname*)"\x7" "in-addr" "\x4" "arpa")); - } - // The question to be checked is not passed in as an explicit parameter; // instead it is implicit that the question to be checked is m->CurrentQuestion. mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) @@ -4300,13 +4360,13 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) { mDNSu8 *end = m->omsg.data; mStatus err = mStatus_NoError; - DomainAuthInfo *private = mDNSNULL; + mDNSBool private = mDNSfalse; if (q->qDNSServer->teststate != DNSServer_Untested || NoTestQuery(q)) { InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags); end = putQuestion(&m->omsg, m->omsg.data, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass); - private = q->AuthInfo; + private = (q->AuthInfo && q->AuthInfo->AutoTunnel); } else if (m->timenow - q->qDNSServer->lasttest >= INIT_UCAST_POLL_INTERVAL) // Make sure at least three seconds has elapsed since last test query { @@ -4468,22 +4528,24 @@ mDNSlocal void CheckNATMappings(mDNS *m) // and (3) we have new data to give the client that's changed since the last callback if (!mDNSIPv4AddressIsZero(m->ExternalAddress) || m->retryIntervalGetAddr > NATMAP_INIT_RETRY * 8) { + const mStatus EffectiveResult = cur->NewResult ? cur->NewResult : mDNSv4AddrIsRFC1918(&m->ExternalAddress) ? mStatus_DoubleNAT : mStatus_NoError; const mDNSIPPort ExternalPort = HaveRoutable ? cur->IntPort : !mDNSIPv4AddressIsZero(m->ExternalAddress) && cur->ExpiryTime ? cur->RequestedPort : zeroIPPort; if (!cur->Protocol || HaveRoutable || cur->ExpiryTime || cur->retryInterval > NATMAP_INIT_RETRY * 8) if (!mDNSSameIPv4Address(cur->ExternalAddress, m->ExternalAddress) || !mDNSSameIPPort (cur->ExternalPort, ExternalPort) || - cur->Result != cur->NewResult) + cur->Result != EffectiveResult) { //LogMsg("NAT callback %d %d %d", cur->Protocol, cur->ExpiryTime, cur->retryInterval); if (cur->Protocol && mDNSIPPortIsZero(ExternalPort) && !mDNSIPv4AddressIsZero(m->Router.ip.v4)) - LogMsg("Failed to obtain NAT port mapping from router %#a external address %.4a internal port %d", - &m->Router, &m->ExternalAddress, mDNSVal16(cur->IntPort)); + LogMsg("Failed to obtain NAT port mapping %p from router %#a external address %.4a internal port %d error %d", + cur, &m->Router, &m->ExternalAddress, mDNSVal16(cur->IntPort), EffectiveResult); + cur->ExternalAddress = m->ExternalAddress; cur->ExternalPort = ExternalPort; cur->Lifetime = cur->ExpiryTime && !mDNSIPPortIsZero(ExternalPort) ? (cur->ExpiryTime - m->timenow + mDNSPlatformOneSecond/2) / mDNSPlatformOneSecond : 0; - cur->Result = cur->NewResult; + cur->Result = EffectiveResult; mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback if (cur->clientCallback) cur->clientCallback(m, cur); diff --git a/mDNSMacOSX/LaunchDaemonInfo.helper.plist b/mDNSMacOSX/LaunchDaemonInfo.helper.plist index 5039775..cb01007 100644 --- a/mDNSMacOSX/LaunchDaemonInfo.helper.plist +++ b/mDNSMacOSX/LaunchDaemonInfo.helper.plist @@ -6,6 +6,8 @@ com.apple.mDNSResponderHelper OnDemand + HopefullyExitsLast + ProgramArguments /usr/sbin/mDNSResponderHelper diff --git a/mDNSMacOSX/LaunchDaemonInfo.plist b/mDNSMacOSX/LaunchDaemonInfo.plist index 8f35709..a36f31d 100644 --- a/mDNSMacOSX/LaunchDaemonInfo.plist +++ b/mDNSMacOSX/LaunchDaemonInfo.plist @@ -6,10 +6,12 @@ com.apple.mDNSResponder OnDemand - UserName - _mdnsresponder - GroupName - _mdnsresponder + HopefullyExitsFirst + + UserName + _mdnsresponder + GroupName + _mdnsresponder ProgramArguments /usr/sbin/mDNSResponder diff --git a/mDNSMacOSX/daemon.c b/mDNSMacOSX/daemon.c index 8acaf29..f36174f 100644 --- a/mDNSMacOSX/daemon.c +++ b/mDNSMacOSX/daemon.c @@ -30,6 +30,12 @@ Change History (most recent first): $Log: daemon.c,v $ +Revision 1.358 2008/03/06 21:26:11 cheshire +Moved duplicated STRINGIFY macro from individual C files to DNSCommon.h + +Revision 1.357 2008/02/13 17:40:43 cheshire + Investigate mysterious SIGABRTs in mDNSResponder + Revision 1.356 2007/12/18 00:28:56 cheshire BTMM: Need to deregister records and services on shutdown/sleep Error in ReadyForSleep() logic -- missing "not" in "!mDNSOpaque16IsZero(q->TargetQID)" @@ -378,15 +384,6 @@ Revision 1.261 2006/01/06 01:22:28 cheshire #include #include "helper.h" -//************************************************************************************************************* -// Macros - -// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion -// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4" -// To expand "version" to its value before making the string, use STRINGIFY(version) instead -#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) #s -#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) - //************************************************************************************************************* // Globals @@ -1985,6 +1982,13 @@ mDNSlocal void HandleSIG(int sig) } } +mDNSlocal void CatchABRT(int sig) + { + LogMsg("Received SIGABRT %d", sig); + sleep(1); // Pause to make sure syslog gets the message + while(1) *(long*)0 = 0; // Generate a CrashReporter stack trace so we can find out what library called abort(); + } + mDNSlocal void INFOCallback(void) { mDNSs32 utc = mDNSPlatformUTC(); @@ -2611,6 +2615,7 @@ mDNSexport int main(int argc, char **argv) signal(SIGHUP, HandleSIG); // (Debugging) Purge the cache to check for cache handling bugs signal(SIGINT, HandleSIG); // Ctrl-C: Detach from Mach BootstrapService and exit cleanly + signal(SIGABRT, CatchABRT); // For debugging -- SIGABRT should never happen signal(SIGPIPE, SIG_IGN ); // Don't want SIGPIPE signals -- we'll handle EPIPE errors directly signal(SIGTERM, HandleSIG); // Machine shutting down: Detach from and exit cleanly like Ctrl-C signal(SIGINFO, HandleSIG); // (Debugging) Write state snapshot to syslog diff --git a/mDNSMacOSX/helper.c b/mDNSMacOSX/helper.c index 8f4b8f8..d3ad6b1 100644 --- a/mDNSMacOSX/helper.c +++ b/mDNSMacOSX/helper.c @@ -17,6 +17,9 @@ Change History (most recent first): $Log: helper.c,v $ +Revision 1.24 2008/01/30 19:01:51 mcguire + Crash in mDNSResponderHelper + Revision 1.23 2007/11/30 23:21:51 cheshire Rename variables to eliminate "declaration of 'sin_loc' shadows a previous local" warning @@ -139,14 +142,11 @@ debug_(const char *func, const char *fmt, ...) { char buf[2048]; va_list ap; - ssize_t n = snprintf(buf, sizeof(buf), "%s: ", func); - if (n >= (int)sizeof(buf)) - return; va_start(ap, fmt); - vsnprintf(&buf[n], sizeof(buf)-n, fmt, ap); + vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); - helplog(ASL_LEVEL_DEBUG, buf); + helplog(ASL_LEVEL_DEBUG, "%s: %s", func, buf); } static int diff --git a/mDNSMacOSX/mDNSMacOSX.c b/mDNSMacOSX/mDNSMacOSX.c index a198741..6cfb6a4 100644 --- a/mDNSMacOSX/mDNSMacOSX.c +++ b/mDNSMacOSX/mDNSMacOSX.c @@ -17,6 +17,65 @@ Change History (most recent first): $Log: mDNSMacOSX.c,v $ +Revision 1.536 2008/03/25 01:27:30 mcguire + Status sometimes wrong when link goes down + +Revision 1.535 2008/03/14 22:52:51 mcguire + write status to the DS +Ignore duplicate queries, which don't get established (since they're duplicates) + +Revision 1.534 2008/03/12 22:58:15 mcguire + write status to the DS +Fixes for NO_SECURITYFRAMEWORK + +Revision 1.533 2008/03/07 00:48:54 mcguire + write status to the DS +cleanup strings + +Revision 1.532 2008/03/06 23:44:39 mcguire + write status to the DS +cleanup function names & log messages +add external port numbers to dictionary +add defensive code in case CF*Create fails +don't output NAT statuses if zero + +Revision 1.531 2008/03/06 21:27:47 cheshire + BTMM: Need ability to identify version of mDNSResponder client +To save network bandwidth, removed unnecessary redundant information from HINFO record + +Revision 1.530 2008/03/06 03:15:48 mcguire + write status to the DS +use mStatus_* instead of kDNSServiceErr_* + +Revision 1.529 2008/03/06 02:48:35 mcguire + write status to the DS + +Revision 1.528 2008/02/29 01:33:57 mcguire + BTMM: Services stay registered after previously successful NAT Port mapping fails + +Revision 1.527 2008/02/28 03:25:26 mcguire + config cleanup on shutdown/reboot + +Revision 1.526 2008/02/26 21:43:54 cheshire +Renamed 'clockdivisor' to 'mDNSPlatformClockDivisor' (LogTimeStamps code needs to be able to access it) + +Revision 1.525 2008/02/20 00:53:20 cheshire + getifaddrs is returning invalid netmask family for fw0 and vmnet +Removed overly alarming syslog message + +Revision 1.524 2008/01/31 22:25:10 jgraessley + using default Macintosh-0016CBF62EFD.local +Use sysctlbyname to get hardware type for the default name. + +Revision 1.523 2008/01/15 01:32:56 jgraessley +Bug #: 5595309 +Reviewed by: Stuart Cheshire +Additional change to print warning message up to 1000 times to make it more visible + +Revision 1.522 2008/01/15 01:14:02 mcguire + mDNSPlatformSendUDP should allow unicast queries on specific interfaces +removed check and log message, as they are no longer relevant + Revision 1.521 2007/12/14 00:58:28 cheshire BTMM: Need to deregister records and services on shutdown/sleep Additional fixes: When going to sleep, mDNSResponder needs to postpone sleep @@ -778,8 +837,6 @@ Add (commented out) trigger value for testing "mach_absolute_time went backwards #pragma mark - Globals #endif -static mDNSu32 clockdivisor = 0; - mDNSexport int KQueueFD; #ifndef NO_SECURITYFRAMEWORK @@ -966,13 +1023,6 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms int s = -1, err; mStatus result = mStatus_NoError; - // Sanity check: Make sure that if we're sending a query via unicast, we're sending it using our - // anonymous socket created for this purpose, so that we'll receive the response. - // If we use one of the many multicast sockets bound to port 5353 then we may not receive responses reliably. - if (InterfaceID && !mDNSAddrIsDNSMulticast(dst)) - if ((((DNSMessage *)msg)->h.flags.b[0] & kDNSFlag0_QR_Mask) == kDNSFlag0_QR_Query) - LogMsg("mDNSPlatformSendUDP: ERROR: Sending query OP from mDNS port to non-mDNS destination %#a:%d", dst, mDNSVal16(dstPort)); - if (dst->type == mDNSAddrType_IPv4) { struct sockaddr_in *sin_to = (struct sockaddr_in*)&to; @@ -996,9 +1046,9 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms #else { static int displayed = 0; - if (!displayed) + if (displayed < 1000) { - displayed = 1; + displayed++; LogOperation("IP_FORCE_OUT_IFP Socket option not defined -- cannot specify interface for unicast packets"); } } @@ -2127,6 +2177,230 @@ mDNSlocal NetworkInterfaceInfoOSX *FindRoutableIPv4(mDNS *const m, mDNSu32 scope static mDNSBool AnonymousRacoonConfig = mDNSfalse; +#ifndef NO_SECURITYFRAMEWORK + +static CFMutableDictionaryRef domainStatusDict = NULL; + +// MUST be called with lock held +mDNSlocal void RemoveAutoTunnelDomainStatus(const DomainAuthInfo *const info) + { + char buffer[1024]; + CFStringRef domain; + + LogOperation("RemoveAutoTunnelDomainStatus: %##s", info->domain.c); + + if (!domainStatusDict) { LogMsg("RemoveAutoTunnelDomainStatus: No domainStatusDict"); return; } + + buffer[mDNS_snprintf(buffer, sizeof(buffer), "%##s", info->domain.c) - 1] = 0; + domain = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8); + if (!domain) { LogMsg("RemoveAutoTunnelDomainStatus: Could not create CFString domain"); return; } + + if (CFDictionaryContainsKey(domainStatusDict, domain)) + { + CFDictionaryRemoveValue(domainStatusDict, domain); + mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, domainStatusDict); + } + CFRelease(domain); + } + +#endif // ndef NO_SECURITYFRAMEWORK + +// MUST be called with lock held +mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAuthInfo *const info) + { +#ifdef NO_SECURITYFRAMEWORK + (void)m; + (void)info; +#else + const NATTraversalInfo *const llq = m->LLQNAT.clientContext ? &m->LLQNAT : mDNSNULL; + const NATTraversalInfo *const tun = info->AutoTunnelNAT.clientContext ? &info->AutoTunnelNAT : mDNSNULL; + char buffer[1024]; + CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFStringRef domain = NULL; + CFStringRef tmp = NULL; + CFNumberRef num = NULL; + mStatus status = mStatus_NoError; + + if (!domainStatusDict) + { + domainStatusDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!domainStatusDict) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFDictionary domainStatusDict"); return; } + } + + if (!dict) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFDictionary dict"); return; } + + buffer[mDNS_snprintf(buffer, sizeof(buffer), "%##s", info->domain.c) - 1] = 0; + domain = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8); + if (!domain) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString domain"); return; } + + mDNS_snprintf(buffer, sizeof(buffer), "%#a", &m->Router); + tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8); + if (!tmp) + LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString RouterAddress"); + else + { + CFDictionarySetValue(dict, CFSTR("RouterAddress"), tmp); + CFRelease(tmp); + } + + mDNS_snprintf(buffer, sizeof(buffer), "%.4a", &m->ExternalAddress); + tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8); + if (!tmp) + LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString ExternalAddress"); + else + { + CFDictionarySetValue(dict, CFSTR("ExternalAddress"), tmp); + CFRelease(tmp); + } + + if (llq) + { + mDNSu32 port = mDNSVal16(llq->ExternalPort); + + num = CFNumberCreate(NULL, kCFNumberSInt32Type, &port); + if (!num) + LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LLQExternalPort"); + else + { + CFDictionarySetValue(dict, CFSTR("LLQExternalPort"), num); + CFRelease(num); + } + + if (llq->Result) + { + num = CFNumberCreate(NULL, kCFNumberSInt32Type, &llq->Result); + if (!num) + LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LLQNPMStatus"); + else + { + CFDictionarySetValue(dict, CFSTR("LLQNPMStatus"), num); + CFRelease(num); + } + } + } + + if (tun) + { + mDNSu32 port = mDNSVal16(tun->ExternalPort); + + num = CFNumberCreate(NULL, kCFNumberSInt32Type, &port); + if (!num) + LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber AutoTunnelExternalPort"); + else + { + CFDictionarySetValue(dict, CFSTR("AutoTunnelExternalPort"), num); + CFRelease(num); + } + + if (tun->Result) + { + num = CFNumberCreate(NULL, kCFNumberSInt32Type, &tun->Result); + if (!num) + LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber AutoTunnelNPMStatus"); + else + { + CFDictionarySetValue(dict, CFSTR("AutoTunnelNPMStatus"), num); + CFRelease(num); + } + } + } + + if (!llq && !tun) + { + status = mStatus_NotInitializedErr; + mDNS_snprintf(buffer, sizeof(buffer), "Neither LLQ nor AutoTunnel NAT port mapping is currently active"); + } + else if ((llq && llq->Result == mStatus_DoubleNAT) || (tun && tun->Result == mStatus_DoubleNAT)) + { + status = mStatus_DoubleNAT; + mDNS_snprintf(buffer, sizeof(buffer), "Double NAT: Router is reporting an external address"); + } + else if ((llq && llq->Result) || (tun && tun->Result)) + { + status = mStatus_NATTraversal; + mDNS_snprintf(buffer, sizeof(buffer), "Error obtaining NAT port mapping from router"); + } + else if (m->Router.type == mDNSAddrType_None) + { + status = mStatus_NoRouter; + mDNS_snprintf(buffer, sizeof(buffer), "No network connection - none"); + } + else if (m->Router.type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsZero(m->Router.ip.v4)) + { + status = mStatus_NoRouter; + mDNS_snprintf(buffer, sizeof(buffer), "No network connection - v4 zero"); + } + else if ((llq && mDNSIPPortIsZero(llq->ExternalPort)) || (tun && mDNSIPPortIsZero(tun->ExternalPort))) + { + status = mStatus_NATTraversal; + mDNS_snprintf(buffer, sizeof(buffer), "Unable to obtain NAT port mapping from router"); + } + else + { + DNSQuestion* q; + for (q = m->Questions; q; q=q->next) + if (q->LongLived && q->AuthInfo == info && q->state == LLQ_Poll) + { + status = mStatus_PollingMode; + mDNS_snprintf(buffer, sizeof(buffer), "Query polling %##s", q->qname.c); + break; + } + if (status == mStatus_NoError) + for (q = m->Questions; q; q=q->next) + if (q->LongLived && q->AuthInfo == info && q->state != LLQ_Established && !q->DuplicateOf) + { + status = mStatus_TransientErr; + mDNS_snprintf(buffer, sizeof(buffer), "Query not yet established %##s", q->qname.c); + break; + } + if (status == mStatus_NoError) mDNS_snprintf(buffer, sizeof(buffer), "Success"); + } + + num = CFNumberCreate(NULL, kCFNumberSInt32Type, &status); + if (!num) + LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber StatusCode"); + else + { + CFDictionarySetValue(dict, CFSTR("StatusCode"), num); + CFRelease(num); + } + + tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8); + if (!tmp) + LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString StatusMessage"); + else + { + CFDictionarySetValue(dict, CFSTR("StatusMessage"), tmp); + CFRelease(tmp); + } + + if (!CFDictionaryContainsKey(domainStatusDict, domain) || + !CFEqual(dict, (CFMutableDictionaryRef)CFDictionaryGetValue(domainStatusDict, domain))) + { + CFDictionarySetValue(domainStatusDict, domain, dict); + mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, domainStatusDict); + } + + CFRelease(domain); + CFRelease(dict); + + LogOperation("UpdateAutoTunnelDomainStatus: %s", buffer); +#endif // def NO_SECURITYFRAMEWORK + } + +// MUST be called with lock held +mDNSexport void UpdateAutoTunnelDomainStatuses(const mDNS *const m) + { +#ifdef NO_SECURITYFRAMEWORK + (void)m; +#else + DomainAuthInfo* info; + for (info = m->AuthInfoList; info; info = info->next) + if (info->AutoTunnel && !info->deltime) + UpdateAutoTunnelDomainStatus(m, info); +#endif // def NO_SECURITYFRAMEWORK + } + // MUST be called with lock held mDNSlocal mDNSBool TunnelServers(mDNS *const m) { @@ -2250,6 +2524,12 @@ mDNSlocal void AutoTunnelRecordCallback(mDNS *const m, AuthRecord *const rr, mSt if (result == mStatus_MemFree) { LogOperation("AutoTunnelRecordCallback MemFree %s", ARDisplayString(m, rr)); + // Reset the host record namestorage to force high-level PTR/SRV/TXT to deregister + if (rr == &info->AutoTunnelHostRecord) + { + rr->namestorage.c[0] = 0; + m->NextSRVUpdate = NonZeroTime(m->timenow); + } RegisterAutoTunnelRecords(m,info); } } @@ -2275,6 +2555,8 @@ mDNSlocal void AutoTunnelNATCallback(mDNS *m, NATTraversalInfo *n) // Create or revert configuration file, and start (or SIGHUP) Racoon (void)mDNSConfigureServer(AnonymousRacoonConfig ? kmDNSUp : kmDNSDown, info ? info->b64keydata : ""); } + + UpdateAutoTunnelDomainStatus(m, (DomainAuthInfo *)n->clientContext); } mDNSlocal void AbortDeregistration(mDNS *const m, AuthRecord *rr) @@ -2522,6 +2804,32 @@ mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q) #pragma mark - Power State & Configuration Change Management #endif +mDNSlocal void GenerateDefaultName(const mDNSEthAddr PrimaryMAC, char *buffer, mDNSu32 length) +{ + char hwName[32]; + size_t hwNameLen = sizeof(hwName); + + hwName[0] = 0; + if (sysctlbyname("hw.model", &hwName, &hwNameLen, NULL, 0) == 0) + { + // hw.model contains a number like iMac6,1. We want the "iMac" part. + hwName[sizeof(hwName) - 1] = 0; + char *ptr; + for (ptr = hwName; *ptr != 0; ptr++) + { + if (*ptr >= '0' && *ptr <= '9') *ptr = 0; + if (*ptr == ',') break; + } + // Prototype model names do not contain commas, do not use prototype names + if (*ptr != ',') hwName[0] = 0; + } + + if (hwName[0] == 0) strlcpy(hwName, "Device", sizeof(hwName)); + + mDNS_snprintf(buffer, length, "%s-%02X%02X%02X%02X%02X%02X", hwName, + PrimaryMAC.b[0], PrimaryMAC.b[1], PrimaryMAC.b[2], PrimaryMAC.b[3], PrimaryMAC.b[4], PrimaryMAC.b[5]); +} + mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc) { mDNSBool foundav4 = mDNSfalse; @@ -2530,7 +2838,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc) struct ifaddrs *v4Loopback = NULL; struct ifaddrs *v6Loopback = NULL; mDNSEthAddr PrimaryMAC = zeroEthAddr; - char defaultname[32]; + char defaultname[64]; #ifndef NO_IPV6 int InfoSocket = socket(AF_INET6, SOCK_DGRAM, 0); if (InfoSocket < 3 && errno != EAFNOSUPPORT) LogMsg("UpdateInterfaceList: InfoSocket error %d errno %d (%s)", InfoSocket, errno, strerror(errno)); @@ -2580,7 +2888,9 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc) LogMsg("getifaddrs: ifa_netmask is NULL for %5s(%d) Flags %04X Family %2d %#a", ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family, &ip); } - else if (ifa->ifa_addr->sa_family != ifa->ifa_netmask->sa_family) + // Apparently it's normal for the sa_family of an ifa_netmask to sometimes be zero, so we don't complain about that + // getifaddrs is returning invalid netmask family for fw0 and vmnet + else if (ifa->ifa_netmask->sa_family != ifa->ifa_addr->sa_family && ifa->ifa_netmask->sa_family != 0) { mDNSAddr ip; SetupAddr(&ip, ifa->ifa_addr); @@ -2589,6 +2899,9 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc) } else { + // Make sure ifa_netmask->sa_family is set correctly + // getifaddrs is returning invalid netmask family for fw0 and vmnet + ifa->ifa_netmask->sa_family = ifa->ifa_addr->sa_family; int ifru_flags6 = 0; #ifndef NO_IPV6 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; @@ -2675,12 +2988,8 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc) m->AutoTunnelHostAddr.b[0xC], m->AutoTunnelHostAddr.b[0xD], m->AutoTunnelHostAddr.b[0xE], m->AutoTunnelHostAddr.b[0xF]); LogOperation("m->AutoTunnelLabel %#s", m->AutoTunnelLabel.c); } - - #ifndef kDefaultLocalHostNamePrefix - #define kDefaultLocalHostNamePrefix "Macintosh" - #endif - mDNS_snprintf(defaultname, sizeof(defaultname), kDefaultLocalHostNamePrefix "-%02X%02X%02X%02X%02X%02X", - PrimaryMAC.b[0], PrimaryMAC.b[1], PrimaryMAC.b[2], PrimaryMAC.b[3], PrimaryMAC.b[4], PrimaryMAC.b[5]); + + GenerateDefaultName(PrimaryMAC, defaultname, sizeof(defaultname)); // Set up the nice label domainlabel nicelabel; @@ -2977,9 +3286,12 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN ifa->ifa_netmask && !(ifa->ifa_flags & IFF_LOOPBACK) && !SetupAddr(&a, ifa->ifa_addr) && - !SetupAddr(&n, ifa->ifa_netmask) && !mDNSv4AddressIsLinkLocal(&a.ip.v4) ) { + // Apparently it's normal for the sa_family of an ifa_netmask to sometimes be incorrect, so we explicitly fix it here before calling SetupAddr + // getifaddrs is returning invalid netmask family for fw0 and vmnet + ifa->ifa_netmask->sa_family = ifa->ifa_addr->sa_family; // Make sure ifa_netmask->sa_family is set correctly + SetupAddr(&n, ifa->ifa_netmask); // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code mDNS_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa.", a.ip.v4.b[3] & n.ip.v4.b[3], a.ip.v4.b[2] & n.ip.v4.b[2], @@ -3546,6 +3858,8 @@ mDNSexport void SetDomainSecrets(mDNS *m) LogOperation("SetDomainSecrets: secret changed for %##s", &domain); (void)mDNSConfigureServer(kmDNSUp, stringbuf); } + + if (ptr->AutoTunnel) UpdateAutoTunnelDomainStatus(m, ptr); #endif APPLE_OSX_mDNSResponder ConvertDomainNameToCString(&domain, stringbuf); @@ -3579,22 +3893,26 @@ mDNSexport void SetDomainSecrets(mDNS *m) DomainAuthInfo *info = m->AuthInfoList; while (info) { - if (info->AutoTunnel && info->deltime && info->AutoTunnelNAT.clientContext) + if (info->AutoTunnel && info->deltime) { - // stop the NAT operation - mDNS_StopNATOperation_internal(m, &info->AutoTunnelNAT); - if (info->AutoTunnelNAT.clientCallback) + if (info->AutoTunnelNAT.clientContext) { - // Reset port and let the AutoTunnelNATCallback handle cleanup - info->AutoTunnelNAT.ExternalAddress = m->ExternalAddress; - info->AutoTunnelNAT.ExternalPort = zeroIPPort; - info->AutoTunnelNAT.Lifetime = 0; - info->AutoTunnelNAT.Result = mStatus_NoError; - mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback - info->AutoTunnelNAT.clientCallback(m, &info->AutoTunnelNAT); - mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again + // stop the NAT operation + mDNS_StopNATOperation_internal(m, &info->AutoTunnelNAT); + if (info->AutoTunnelNAT.clientCallback) + { + // Reset port and let the AutoTunnelNATCallback handle cleanup + info->AutoTunnelNAT.ExternalAddress = m->ExternalAddress; + info->AutoTunnelNAT.ExternalPort = zeroIPPort; + info->AutoTunnelNAT.Lifetime = 0; + info->AutoTunnelNAT.Result = mStatus_NoError; + mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback + info->AutoTunnelNAT.clientCallback(m, &info->AutoTunnelNAT); + mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again + } + info->AutoTunnelNAT.clientContext = mDNSNULL; } - info->AutoTunnelNAT.clientContext = mDNSNULL; + RemoveAutoTunnelDomainStatus(info); } info = info->next; } @@ -3916,7 +4234,7 @@ mDNSexport int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring) CFRelease(vers); } if (!major) { major=8; LogMsg("Note: No Major Build Version number found; assuming 8"); } - if (HINFO_SWstring) mDNS_snprintf(HINFO_SWstring, 256, "%s %s (%s), %s", prodname, prodvers, buildver, mDNSResponderVersionString); + if (HINFO_SWstring) mDNS_snprintf(HINFO_SWstring, 256, "%s %s (%s), %s", prodname, prodvers, buildver, STRINGIFY(mDNSResponderVersion)); return(major); } @@ -4111,10 +4429,28 @@ mDNSexport void mDNSPlatformClose(mDNS *const m) CloseSocketSet(&m->p->permanentsockets); #if APPLE_OSX_mDNSResponder + // clean up tunnels + while (m->TunnelClients) + { + ClientTunnel *cur = m->TunnelClients; + LogOperation("mDNSPlatformClose: removing client tunnel %p %##s from list", cur, cur->dstname.c); + if (cur->q.ThisQInterval >= 0) mDNS_StopQuery(m, &cur->q); + AutoTunnelSetKeys(cur, mDNSfalse); + m->TunnelClients = cur->next; + freeL("ClientTunnel", cur); + } + + if (AnonymousRacoonConfig) + { + AnonymousRacoonConfig = mDNSfalse; + LogOperation("mDNSPlatformClose: Deconfiguring autotunnel"); + (void)mDNSConfigureServer(kmDNSDown, ""); + } + if (m->AutoTunnelHostAddrActive && m->AutoTunnelHostAddr.b[0]) { m->AutoTunnelHostAddrActive = mDNSfalse; - LogMsg("Removing AutoTunnel address %.16a", &m->AutoTunnelHostAddr); + LogOperation("mDNSPlatformClose: Removing AutoTunnel address %.16a", &m->AutoTunnelHostAddr); (void)mDNSAutoTunnelInterfaceUpDown(kmDNSDown, m->AutoTunnelHostAddr.b); } #endif // APPLE_OSX_mDNSResponder @@ -4131,6 +4467,7 @@ mDNSexport mDNSu32 mDNSPlatformRandomSeed(void) } mDNSexport mDNSs32 mDNSPlatformOneSecond = 1000; +mDNSexport mDNSu32 mDNSPlatformClockDivisor = 0; mDNSexport mStatus mDNSPlatformTimeInit(void) { @@ -4154,13 +4491,13 @@ mDNSexport mStatus mDNSPlatformTimeInit(void) // When we ship Macs with clock frequencies above 1000GHz, we may have to update this code. struct mach_timebase_info tbi; kern_return_t result = mach_timebase_info(&tbi); - if (result == KERN_SUCCESS) clockdivisor = ((uint64_t)tbi.denom * 1000000) / tbi.numer; + if (result == KERN_SUCCESS) mDNSPlatformClockDivisor = ((uint64_t)tbi.denom * 1000000) / tbi.numer; return(result); } mDNSexport mDNSs32 mDNSPlatformRawTime(void) { - if (clockdivisor == 0) { LogMsg("mDNSPlatformRawTime called before mDNSPlatformTimeInit"); return(0); } + if (mDNSPlatformClockDivisor == 0) { LogMsg("mDNSPlatformRawTime called before mDNSPlatformTimeInit"); return(0); } static uint64_t last_mach_absolute_time = 0; //static uint64_t last_mach_absolute_time = 0x8000000000000000LL; // Use this value for testing the alert display @@ -4182,7 +4519,7 @@ mDNSexport mDNSs32 mDNSPlatformRawTime(void) } last_mach_absolute_time = this_mach_absolute_time; - return((mDNSs32)(this_mach_absolute_time / clockdivisor)); + return((mDNSs32)(this_mach_absolute_time / mDNSPlatformClockDivisor)); } mDNSexport mDNSs32 mDNSPlatformUTC(void) diff --git a/mDNSMacOSX/mDNSResponder.sb b/mDNSMacOSX/mDNSResponder.sb index 97ba7e1..b0307f9 100644 --- a/mDNSMacOSX/mDNSResponder.sb +++ b/mDNSMacOSX/mDNSResponder.sb @@ -26,6 +26,9 @@ ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; ; $Log: mDNSResponder.sb,v $ +; Revision 1.25 2008/03/17 18:04:41 mcguire +; SC now reads preference file +; ; Revision 1.24 2007/09/20 22:33:17 cheshire ; Tidied up inconsistent and error-prone naming -- used to be mDNSResponderHelper in ; some places and mDNSResponder.helper in others; now mDNSResponderHelper everywhere @@ -165,6 +168,7 @@ (allow file-read-data (regex "^/usr/share/icu/.*\$")) (allow file-read-data (regex "^/usr/share/zoneinfo/.*\$")) (allow file-read-data (regex "^/System/Library/CoreServices/SystemVersion.*\$")) +(allow file-read-data (regex "^/Library/Preferences/SystemConfiguration/preferences\.plist\$")) (allow file-read-data (regex "^/Library/Preferences/(ByHost/)?\.GlobalPreferences.*\.plist\$")) (allow file-read-data (regex "^/Library/Preferences/com\.apple\.security.*\.plist\$")) (allow file-read-data (regex "^/Library/Preferences/com\.apple\.crypto\.plist\$")) diff --git a/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj b/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj index 904efc0..df36500 100644 --- a/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj +++ b/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj @@ -1865,6 +1865,7 @@ GCC_GENERATE_DEBUGGING_SYMBOLS = YES; HEADER_SEARCH_PATHS = ( ../mDNSShared, + "${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders", "${APPLE_INTERNAL_DEVELOPER_DIR}/Headers", "${CONFIGURATION_TEMP_DIR}", ); @@ -1905,6 +1906,7 @@ ); HEADER_SEARCH_PATHS = ( ../mDNSShared, + "${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders", "${APPLE_INTERNAL_DEVELOPER_DIR}/Headers", "${CONFIGURATION_TEMP_DIR}", ); @@ -1958,7 +1960,7 @@ GCC_GENERATE_DEBUGGING_SYMBOLS = YES; HEADER_SEARCH_PATHS = ../mDNSShared; INSTALL_PATH = /usr/bin; - MACOSX_DEPLOYMENT_TARGET = 10.3; + MACOSX_DEPLOYMENT_TARGET = 10.4; OTHER_CFLAGS = "-no-cpp-precomp"; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; diff --git a/mDNSShared/PlatformCommon.c b/mDNSShared/PlatformCommon.c index 61c5361..434c2f1 100644 --- a/mDNSShared/PlatformCommon.c +++ b/mDNSShared/PlatformCommon.c @@ -17,6 +17,15 @@ Change History (most recent first): $Log: PlatformCommon.c,v $ +Revision 1.17 2008/03/05 00:19:09 cheshire +Conditionalize LogTimeStamps so it's specific to APPLE_OSX, for now + +Revision 1.16 2008/02/26 21:47:45 cheshire +Added cast to avoid compiler warning + +Revision 1.15 2008/02/26 21:42:26 cheshire +Added 'LogTimeStamps' option, to show ms-granularity timestamps on every log message + Revision 1.14 2007/12/03 18:37:26 cheshire Moved mDNSPlatformWriteLogMsg & mDNSPlatformWriteDebugMsg from mDNSMacOSX.c to PlatformCommon.c, so that Posix build can use them @@ -160,7 +169,7 @@ mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const fi if (hostname && GetConfigOption(buf, "hostname", f) && !MakeDomainNameFromDNSNameString(hostname, buf)) goto badf; if (domain && GetConfigOption(buf, "zone", f) && !MakeDomainNameFromDNSNameString(domain, buf)) goto badf; buf[0] = 0; - GetConfigOption(buf, "secret-64", f); // failure means no authentication + GetConfigOption(buf, "secret-64", f); // failure means no authentication fclose(f); f = NULL; } @@ -182,28 +191,45 @@ mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const fi badf: LogMsg("ERROR: malformatted config file"); - if (f) fclose(f); + if (f) fclose(f); } #if MDNS_DEBUGMSGS -mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg) +mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg) { fprintf(stderr,"%s\n", msg); fflush(stderr); } #endif -mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, int logoptflags) +mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, int logoptflags) { +#if APPLE_OSX_mDNSResponder && LogTimeStamps + extern mDNS mDNSStorage; + extern mDNSu32 mDNSPlatformClockDivisor; + mDNSs32 t = mDNSStorage.timenow ? mDNSStorage.timenow : mDNSPlatformClockDivisor ? mDNS_TimeNow_NoLock(&mDNSStorage) : 0; + int ms = ((t < 0) ? -t : t) % 1000; +#endif + if (mDNS_DebugMode) // In debug mode we write to stderr { - fprintf(stderr,"%s\n", buffer); +#if APPLE_OSX_mDNSResponder && LogTimeStamps + if (mDNSPlatformClockDivisor) + fprintf(stderr,"%8d.%03d: %s\n", (int)(t/1000), ms, buffer); + else +#endif + fprintf(stderr,"%s\n", buffer); fflush(stderr); } else // else, in production mode, we write to syslog { openlog(ident, LOG_CONS | logoptflags, LOG_DAEMON); - syslog(LOG_ERR, "%s", buffer); +#if APPLE_OSX_mDNSResponder && LogTimeStamps + if (mDNSPlatformClockDivisor) + syslog(LOG_ERR, "%8d.%03d: %s", (int)(t/1000), ms, buffer); + else +#endif + syslog(LOG_ERR, "%s", buffer); closelog(); } } diff --git a/mDNSShared/dns_sd.h b/mDNSShared/dns_sd.h index da571b2..cc4169b 100644 --- a/mDNSShared/dns_sd.h +++ b/mDNSShared/dns_sd.h @@ -77,7 +77,7 @@ */ #ifndef _DNS_SD_H -#define _DNS_SD_H 1700000 +#define _DNS_SD_H 1710400 #ifdef __cplusplus extern "C" { @@ -443,8 +443,10 @@ enum kDNSServiceErr_BadKey = -65561, kDNSServiceErr_Transient = -65562, kDNSServiceErr_ServiceNotRunning = -65563, /* Background daemon not running */ - kDNSServiceErr_NATPortMappingUnsupported = -65564, /* No NAT or if the 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_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 /* mDNS Error codes are in the range * FFFE FF00 (-65792) to FFFE FFFF (-65537) */ @@ -1729,9 +1731,11 @@ DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord * * interfaceIndex: The interface through which the NAT gateway is reached. * - * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will - * indicate the failure that occurred. Other parameters are - * undefined if errorCode is nonzero. + * errorCode: Will be kDNSServiceErr_NoError on success. + * Will be kDNSServiceErr_DoubleNAT when the NAT gateway is itself behind one or + * more layers of NAT, in which case the other parameters have the defined values. + * For other failures, will indicate the failure that occurred, and the other + * parameters are undefined. * * publicAddress: Four byte IPv4 address in network byte order. * diff --git a/mDNSShared/dnsextd.c b/mDNSShared/dnsextd.c index 5a6541c..807ced9 100644 --- a/mDNSShared/dnsextd.c +++ b/mDNSShared/dnsextd.c @@ -17,6 +17,9 @@ Change History (most recent first): $Log: dnsextd.c,v $ +Revision 1.88 2008/03/06 21:26:11 cheshire +Moved duplicated STRINGIFY macro from individual C files to DNSCommon.h + Revision 1.87 2007/12/17 23:34:50 cheshire Don't need to set ptr to result of DNSDigest_SignMessage -- ptr is updated anyway (it's passed by reference) @@ -3255,12 +3258,6 @@ mStatus mDNS_StopQuery(mDNS *const m, DNSQuestion *const question) { ( void ) m; mDNS mDNSStorage; -// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion -// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4" -// To expand "version" to its value before making the string, use STRINGIFY(version) instead -#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) #s -#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) - // For convenience when using the "strings" command, this is the last thing in the file // The "@(#) " pattern is a special prefix the "what" command looks for const char mDNSResponderVersionString_SCCS[] = "@(#) dnsextd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")"; diff --git a/mDNSShared/dnssd_clientstub.c b/mDNSShared/dnssd_clientstub.c index d197344..3aac7ed 100644 --- a/mDNSShared/dnssd_clientstub.c +++ b/mDNSShared/dnssd_clientstub.c @@ -28,6 +28,13 @@ Change History (most recent first): $Log: dnssd_clientstub.c,v $ +Revision 1.102 2008/02/25 19:16:19 cheshire + Problems with DNSServiceGetAddrInfo API +Was returning a bogus result (NULL pointer) when following a CNAME referral + +Revision 1.101 2008/02/20 21:18:21 cheshire + DNSServiceGetAddrInfo doesn't set the scope ID of returned IPv6 link local addresses + Revision 1.100 2007/11/02 17:56:37 cheshire Bonjour API broken for 64-bit apps (SCM_RIGHTS sendmsg fails) Wrap hack code in "#if APPLE_OSX_mDNSResponder" since (as far as we know right now) @@ -1081,43 +1088,53 @@ DNSServiceErrorType DNSSD_API DNSServiceQueryRecord static void handle_addrinfo_response(DNSServiceOp *sdr, CallbackHeader *cbh, char *data, char *end) { - uint32_t ttl; char hostname[kDNSServiceMaxDomainName]; uint16_t rrtype, rrclass, rdlen; char *rdata; - struct sockaddr_in sa4; - struct sockaddr_in6 sa6; - struct sockaddr * sa = NULL; + uint32_t ttl; get_string(&data, end, hostname, kDNSServiceMaxDomainName); rrtype = get_uint16(&data, end); rrclass = get_uint16(&data, end); rdlen = get_uint16(&data, end); - rdata = get_rdata(&data, end, rdlen); + rdata = get_rdata (&data, end, rdlen); ttl = get_uint32(&data, end); - + + // We only generate client callbacks for A and AAAA results (including NXDOMAIN results for + // those types, if the client has requested those with the kDNSServiceFlagsReturnIntermediates). + // Other result types, specifically CNAME referrals, are not communicated to the client, because + // the DNSServiceGetAddrInfoReply interface doesn't have any meaningful way to communiate CNAME referrals. if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_addrinfo_response: error reading result from daemon"); - else + else if (rrtype == kDNSServiceType_A || rrtype == kDNSServiceType_AAAA) { + struct sockaddr_in sa4; + struct sockaddr_in6 sa6; + const struct sockaddr *const sa = (rrtype == kDNSServiceType_A) ? (struct sockaddr*)&sa4 : (struct sockaddr*)&sa6; if (rrtype == kDNSServiceType_A) { - sa = (struct sockaddr *)&sa4; bzero(&sa4, sizeof(sa4)); #ifndef NOT_HAVE_SA_LEN - sa->sa_len = sizeof(struct sockaddr_in); + sa4.sin_len = sizeof(struct sockaddr_in); #endif - sa->sa_family = AF_INET; + sa4.sin_family = AF_INET; + // sin_port = 0; if (!cbh->cb_err) memcpy(&sa4.sin_addr, rdata, rdlen); } - else if (rrtype == kDNSServiceType_AAAA) + else { - sa = (struct sockaddr *)&sa6; bzero(&sa6, sizeof(sa6)); #ifndef NOT_HAVE_SA_LEN - sa->sa_len = sizeof(struct sockaddr_in6); + sa6.sin6_len = sizeof(struct sockaddr_in6); #endif - sa->sa_family = AF_INET6; - if (!cbh->cb_err) memcpy(&sa6.sin6_addr, rdata, rdlen); + sa6.sin6_family = AF_INET6; + // sin6_port = 0; + // sin6_flowinfo = 0; + // sin6_scope_id = 0; + if (!cbh->cb_err) + { + memcpy(&sa6.sin6_addr, rdata, rdlen); + if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr)) sa6.sin6_scope_id = cbh->cb_interface; + } } ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, hostname, sa, ttl, sdr->AppContext); // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function diff --git a/mDNSShared/uds_daemon.c b/mDNSShared/uds_daemon.c index 3e0a601..a01eb08 100644 --- a/mDNSShared/uds_daemon.c +++ b/mDNSShared/uds_daemon.c @@ -17,6 +17,15 @@ Change History (most recent first): $Log: uds_daemon.c,v $ +Revision 1.387 2008/02/26 21:24:13 cheshire +Fixed spelling mistake in comment + +Revision 1.386 2008/02/26 20:23:15 cheshire +Updated comments + +Revision 1.385 2008/02/19 21:50:52 cheshire +Shortened some overly-long lines + Revision 1.384 2007/12/22 01:38:05 cheshire Improve display of "Auth Records" SIGINFO output @@ -722,7 +731,7 @@ typedef struct registered_record_entry { struct registered_record_entry *next; mDNSu32 key; - AuthRecord *rr; // Variable-sized AuthRecord + AuthRecord *rr; // Pointer to variable-sized AuthRecord client_context_t client_context; request_state *request; } registered_record_entry; @@ -740,7 +749,7 @@ typedef struct service_instance mDNSBool clientnotified; // Has client been notified of successful registration yet? mDNSBool default_local; // is this the "local." from an empty-string registration? domainname domain; - ServiceRecordSet srs; // note - must be last field in struct + ServiceRecordSet srs; // note -- variable-sized object -- must be last field in struct } service_instance; // for multi-domain default browsing @@ -766,7 +775,7 @@ struct request_state transfer_state ts; mDNSu32 hdr_bytes; // bytes of header already read ipc_msg_hdr hdr; - mDNSu32 data_bytes; // bytes of message data already read + mDNSu32 data_bytes; // bytes of message data already read char *msgbuf; // pointer to data storage to pass to free() char *msgptr; // pointer to data to be read from (may be modified) char *msgend; // pointer to byte after last byte of message @@ -1709,7 +1718,8 @@ mDNSlocal mStatus register_service_instance(request_state *request, const domain { LogMsg("register_service_instance: domain %##s already registered", domain->c); return mStatus_AlreadyRegistered; } } - // Special-case hack: We don't advertise SMB service in AutoTunnel domains, because AutoTunnel services have to support IPv6, and our SMB server does not + // Special-case hack: We don't advertise SMB service in AutoTunnel domains, because AutoTunnel + // services have to support IPv6, and our SMB server does not // BTMM: Don't advertise SMB with BTMM because it doesn't support IPv6 if (SameDomainName(&request->u.servicereg.type, (const domainname *) "\x4" "_smb" "\x4" "_tcp")) { @@ -2545,11 +2555,6 @@ mDNSlocal mStatus handle_resolve_request(request_state *request) // to the mDNSCore routine) that sends results back to the client, and a termination routine that aborts // the mDNSCore operation if the client dies or closes its socket. -// query and resolve calls have separate request handlers that parse the arguments from the client and -// massage the name parameters appropriately, but the rest of the operations (making the query call, -// delivering the result to the client, and termination) are identical. - -// what gets called when a resolve is completed and we need to send the data back to the client mDNSlocal void queryrecord_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) { char name[MAX_ESCAPED_DOMAIN_NAME]; @@ -2636,7 +2641,8 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request) rrtype = get_uint16(&request->msgptr, request->msgend); rrclass = get_uint16(&request->msgptr, request->msgend); - if (!request->msgptr) { LogMsg("%3d: DNSServiceQueryRecord(unreadable parameters)", request->sd); return(mStatus_BadParamErr); } + if (!request->msgptr) + { LogMsg("%3d: DNSServiceQueryRecord(unreadable parameters)", request->sd); return(mStatus_BadParamErr); } mDNSPlatformMemZero(&request->u.queryrecord.q, sizeof(&request->u.queryrecord.q)); @@ -2736,7 +2742,8 @@ mDNSlocal mStatus handle_enum_request(request_state *request) mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex); if (interfaceIndex && !InterfaceID) return(mStatus_BadParamErr); - if (!request->msgptr) { LogMsg("%3d: DNSServiceEnumerateDomains(unreadable parameters)", request->sd); return(mStatus_BadParamErr); } + if (!request->msgptr) + { LogMsg("%3d: DNSServiceEnumerateDomains(unreadable parameters)", request->sd); return(mStatus_BadParamErr); } // allocate context structures uDNS_RegisterSearchDomains(&mDNSStorage); @@ -2909,7 +2916,8 @@ mDNSlocal mStatus handle_port_mapping_request(request_state *request) ttl = get_uint32(&request->msgptr, request->msgend); } - if (!request->msgptr) { LogMsg("%3d: DNSServiceNATPortMappingCreate(unreadable parameters)", request->sd); return(mStatus_BadParamErr); } + if (!request->msgptr) + { LogMsg("%3d: DNSServiceNATPortMappingCreate(unreadable parameters)", request->sd); return(mStatus_BadParamErr); } if (protocol == 0) // If protocol == 0 (i.e. just request public address) then IntPort, ExtPort, ttl must be zero too { @@ -3554,9 +3562,10 @@ mDNSexport int udsserver_init(dnssd_sock_t skt) mDNS_GetDomains(&mDNSStorage, &mDNSStorage.AutomaticBrowseDomainQ, mDNS_DomainTypeBrowseAutomatic, mDNSNULL, mDNSInterface_LocalOnly, AutomaticBrowseDomainChange, mDNSNULL); - RegisterLocalOnlyDomainEnumPTR(&mDNSStorage, &localdomain, mDNS_DomainTypeRegistration); // Add "local" as recommended registration domain ("dns-sd -E") - RegisterLocalOnlyDomainEnumPTR(&mDNSStorage, &localdomain, mDNS_DomainTypeBrowse); // Add "local" as recommended browsing domain ("dns-sd -F") - AddAutoBrowseDomain(0, &localdomain); // Add "local" as automatic browsing domain + // Add "local" as recommended registration domain ("dns-sd -E"), recommended browsing domain ("dns-sd -F"), and automatic browsing domain + RegisterLocalOnlyDomainEnumPTR(&mDNSStorage, &localdomain, mDNS_DomainTypeRegistration); + RegisterLocalOnlyDomainEnumPTR(&mDNSStorage, &localdomain, mDNS_DomainTypeBrowse); + AddAutoBrowseDomain(0, &localdomain); udsserver_handle_configchange(&mDNSStorage); return 0; @@ -3787,7 +3796,8 @@ mDNSexport void udsserver_info(mDNS *const m) { ClientTunnel *c; for (c = m->TunnelClients; c; c = c->next) - LogMsgNoIdent("%##s local %.16a %.4a remote %.16a %.4a %5d interval %d", c->dstname.c, &c->loc_inner, &c->loc_outer, &c->rmt_inner, &c->rmt_outer, mDNSVal16(c->rmt_outer_port), c->q.ThisQInterval); + LogMsgNoIdent("%##s local %.16a %.4a remote %.16a %.4a %5d interval %d", + c->dstname.c, &c->loc_inner, &c->loc_outer, &c->rmt_inner, &c->rmt_outer, mDNSVal16(c->rmt_outer_port), c->q.ThisQInterval); } #endif }