From: Apple Date: Thu, 14 Aug 2008 20:51:50 +0000 (+0000) Subject: mDNSResponder-176.2.tar.gz X-Git-Tag: mac-os-x-1055^0 X-Git-Url: https://git.saurik.com/apple/mdnsresponder.git/commitdiff_plain/9f29194f7a02323429e8e56b2fc31e7d6b175a06 mDNSResponder-176.2.tar.gz --- diff --git a/Makefile b/Makefile index ef3c0ee..8f6dfb8 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ include /Developer/Makefiles/pb_makefiles/platform.make -MVERS = "mDNSResponder-171.4" +MVERS = "mDNSResponder-176.2" DDNSWRITECONFIG = "$(DSTROOT)/Library/Application Support/Bonjour/ddnswriteconfig" diff --git a/mDNSCore/DNSCommon.c b/mDNSCore/DNSCommon.c index bffef7b..deda1b9 100644 --- a/mDNSCore/DNSCommon.c +++ b/mDNSCore/DNSCommon.c @@ -17,6 +17,9 @@ Change History (most recent first): $Log: DNSCommon.c,v $ +Revision 1.199.2.1 2008/07/25 07:25:08 mcguire +merge of to SUSB for + 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 @@ -586,6 +589,17 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *rr, RDataBody *rd, return(buffer); } +// Long-term we need to make this cross-platform, either by using our own embedded RC4 code +// to generate the pseudo-random sequence, or by adding another mDNSPlatformXXX() call. +// The former would be preferable because it makes our code self-contained, so it will run anywhere. +// The latter is less desirable because it increases the burden on people writing platform support layers +// to now implement one more function (and an important one at that, that needs to be cryptographically strong). +// For now, as a temporary fix, if we're building mDNSResponder for OS X we just use arc4random() directly here. + +#if _BUILDING_XCODE_PROJECT_ +#include +#endif + mDNSexport mDNSu32 mDNSRandom(mDNSu32 max) // Returns pseudo-random result from zero to max inclusive { static mDNSu32 seed = 0; @@ -598,7 +612,14 @@ mDNSexport mDNSu32 mDNSRandom(mDNSu32 max) // Returns pseudo-random result from for (i=0; i<100; i++) seed = seed * 21 + 1; // And mix it up a bit } while (mask < max) mask = (mask << 1) | 1; - do seed = seed * 21 + 1; while ((seed & mask) > max); + +#if _BUILDING_XCODE_PROJECT_ + do seed = arc4random(); +#else + do seed = seed * 21 + 1; +#endif + while ((seed & mask) > max); + return (seed & mask); } @@ -2525,14 +2546,21 @@ mDNSlocal const mDNSu8 *DumpRecords(mDNS *const m, const DNSMessage *const msg, (X) == kDNSFlag1_RC_NotZone ? "NotZone" : "??" ) // Note: DumpPacket expects the packet header fields in host byte order, not network byte order -mDNSexport void DumpPacket(mDNS *const m, mDNSBool sent, char *transport, const mDNSAddr *addr, mDNSIPPort port, const DNSMessage *const msg, const mDNSu8 *const end) +mDNSexport void DumpPacket(mDNS *const m, mDNSBool sent, char *transport, + const mDNSAddr *srcaddr, mDNSIPPort srcport, + const mDNSAddr *dstaddr, mDNSIPPort dstport, const DNSMessage *const msg, const mDNSu8 *const end) { mDNSBool IsUpdate = ((msg->h.flags.b[0] & kDNSFlag0_OP_Mask) == kDNSFlag0_OP_Update); const mDNSu8 *ptr = msg->data; int i; DNSQuestion q; + char sbuffer[64], dbuffer[64] = ""; + if (sent) sbuffer[mDNS_snprintf(sbuffer, sizeof(sbuffer), "port " )] = 0; + else sbuffer[mDNS_snprintf(sbuffer, sizeof(sbuffer), "%#a:", srcaddr)] = 0; + if (dstaddr || !mDNSIPPortIsZero(dstport)) + dbuffer[mDNS_snprintf(dbuffer, sizeof(dbuffer), " to %#a:%d", dstaddr, mDNSVal16(dstport))] = 0; - LogMsg("-- %s %s DNS %s%s (flags %02X%02X) RCODE: %s (%d) %s%s%s%s%s%sID: %d %d bytes %s %#a:%d%s --", + LogMsg("-- %s %s DNS %s%s (flags %02X%02X) RCODE: %s (%d) %s%s%s%s%s%sID: %d %d bytes from %s%d%s%s --", sent ? "Sent" : "Received", transport, DNS_OP_Name(msg->h.flags.b[0] & kDNSFlag0_OP_Mask), msg->h.flags.b[0] & kDNSFlag0_QR_Response ? "Response" : "Query", @@ -2547,7 +2575,7 @@ mDNSexport void DumpPacket(mDNS *const m, mDNSBool sent, char *transport, const msg->h.flags.b[1] & kDNSFlag1_CD ? "CD " : "", mDNSVal16(msg->h.id), end - msg->data, - sent ? "to" : "from", addr, mDNSVal16(port), + sbuffer, mDNSVal16(srcport), dbuffer, (msg->h.flags.b[0] & kDNSFlag0_TC) ? " (truncated)" : "" ); @@ -2572,10 +2600,15 @@ mDNSexport void DumpPacket(mDNS *const m, mDNSBool sent, char *transport, const // Stub definition of TCPSocket_struct so we can access flags field. (Rest of TCPSocket_struct is platform-dependent.) struct TCPSocket_struct { TCPSocketFlags flags; /* ... */ }; +struct UDPSocket_struct + { + mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port + }; + // Note: When we sign a DNS message using DNSDigest_SignMessage(), the current real-time clock value is used, which // is why we generally defer signing until we send the message, to ensure the signature is as fresh as possible. mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNSu8 *end, - mDNSInterfaceID InterfaceID, const mDNSAddr *dst, mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo) + mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo) { mStatus status = mStatus_NoError; const mDNSu16 numQuestions = msg->h.numQuestions; @@ -2613,7 +2646,7 @@ mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNS { // Send the packet on the wire if (!sock) - status = mDNSPlatformSendUDP(m, msg, end, InterfaceID, dst, dstport); + status = mDNSPlatformSendUDP(m, msg, end, InterfaceID, src, dst, dstport); else { mDNSu16 msglen = (mDNSu16)(end - (mDNSu8 *)msg); @@ -2639,7 +2672,7 @@ mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNS { 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); + DumpPacket(m, mDNStrue, sock && (sock->flags & kTCPSocketFlags_UseTLS) ? "TLS" : sock ? "TCP" : "UDP", mDNSNULL, src ? src->port : MulticastDNSPort, dst, dstport, msg, end); } // put the final integer value back the way it was diff --git a/mDNSCore/DNSCommon.h b/mDNSCore/DNSCommon.h index 6556031..52169de 100644 --- a/mDNSCore/DNSCommon.h +++ b/mDNSCore/DNSCommon.h @@ -17,6 +17,9 @@ Change History (most recent first): $Log: DNSCommon.h,v $ +Revision 1.60 2008/07/24 20:23:03 cheshire + Should use randomized source ports and transaction IDs to avoid DNS cache poisoning + 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 @@ -321,7 +324,9 @@ extern const mDNSu8 *LocateLLQOptData(const DNSMessage *const msg, const mDNSu8 extern const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end); extern const mDNSu8 *LocateLeaseOptData(const DNSMessage *const msg, const mDNSu8 *const end); extern mDNSu32 GetPktLease(mDNS *m, DNSMessage *msg, const mDNSu8 *end); -extern void DumpPacket(mDNS *const m, mDNSBool sent, char *type, const mDNSAddr *addr, mDNSIPPort port, const DNSMessage *const msg, const mDNSu8 *const end); +extern void DumpPacket(mDNS *const m, mDNSBool sent, char *transport, + const mDNSAddr *srcaddr, mDNSIPPort srcport, + const mDNSAddr *dstaddr, mDNSIPPort dstport, const DNSMessage *const msg, const mDNSu8 *const end); // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK @@ -330,7 +335,7 @@ extern void DumpPacket(mDNS *const m, mDNSBool sent, char *type, const mDNSAddr #endif extern mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNSu8 *end, - mDNSInterfaceID InterfaceID, const mDNSAddr *dst, mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo); + mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo); // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK diff --git a/mDNSCore/mDNS.c b/mDNSCore/mDNS.c index 34a3c7c..e8323b7 100755 --- a/mDNSCore/mDNS.c +++ b/mDNSCore/mDNS.c @@ -38,6 +38,24 @@ Change History (most recent first): $Log: mDNS.c,v $ +Revision 1.777.4.4 2008/08/14 20:43:59 cheshire + Back to My Mac not working with Time Capsule shared volume + +Revision 1.777.4.3 2008/07/29 20:46:05 mcguire + Should use randomized source ports and transaction IDs to avoid DNS cache poisoning +merge r1.782 & r1.783 from + +Revision 1.777.4.2 2008/07/29 20:13:52 mcguire + BTMM: alternate SSDP queries between multicast & unicast +merged r1.781 for + +Revision 1.777.4.1 2008/07/29 19:17:55 mcguire + Only trigger reconfirm on hostname if both A and AAAA query fail to elicit a response +merge r1.779, r.1780 from + +Revision 1.777 2008/06/19 01:20:48 mcguire + Use all configured DNS servers + Revision 1.776 2008/04/17 20:14:14 cheshire CurrentAnswers/LargeAnswers/UniqueAnswers counter mismatch @@ -1793,7 +1811,7 @@ mDNSlocal void SendDelayedUnicastResponse(mDNS *const m, const mDNSAddr *const d rr->NR_AdditionalTo = mDNSNULL; } - if (m->omsg.h.numAnswers) mDNSSendDNSMessage(m, &m->omsg, responseptr, mDNSInterface_Any, dest, MulticastDNSPort, mDNSNULL, mDNSNULL); + if (m->omsg.h.numAnswers) mDNSSendDNSMessage(m, &m->omsg, responseptr, mDNSInterface_Any, mDNSNULL, dest, MulticastDNSPort, mDNSNULL, mDNSNULL); } } @@ -2101,8 +2119,8 @@ mDNSlocal void SendResponses(mDNS *const m) numAnnounce, numAnnounce == 1 ? "" : "s", numAnswer, numAnswer == 1 ? "" : "s", m->omsg.h.numAdditionals, m->omsg.h.numAdditionals == 1 ? "" : "s", intf->InterfaceID); - if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSNULL); - if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSNULL); + if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSNULL); + if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSNULL); if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+9)/10); if (++pktcount >= 1000) { LogMsg("SendResponses exceeded loop limit %d: giving up", pktcount); break; } // There might be more things to send on this interface, so go around one more time and try again. @@ -2340,6 +2358,18 @@ mDNSlocal void ReconfirmAntecedents(mDNS *const m, const domainname *const name, } } +// If we get no answer for a AAAA query, then before doing an automatic implicit ReconfirmAntecedents +// we check if we have an address record for the same name. If we do have an IPv4 address for a given +// name but not an IPv6 address, that's okay (it just means the device doesn't do IPv6) so the failure +// to get a AAAA response is not grounds to doubt the PTR/SRV chain that lead us to that name. +mDNSlocal CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const domainname *const name, const mDNSu32 namehash) + { + CacheGroup *const cg = CacheGroupForName(m, HashSlot(name), namehash, name); + CacheRecord *cr = cg ? cg->members : mDNSNULL; + while (cr && !RRTypeIsAddressType(cr->resrec.rrtype)) cr=cr->next; + return(cr); + } + // Only DupSuppressInfos newer than the specified 'time' are allowed to remain active mDNSlocal void ExpireDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 time) { @@ -2489,7 +2519,7 @@ mDNSlocal void SendQueries(mDNS *const m) const mDNSu8 *const limit = m->omsg.data + sizeof(m->omsg.data); InitializeDNSMessage(&m->omsg.h, q->TargetQID, QueryFlags); qptr = putQuestion(&m->omsg, qptr, limit, &q->qname, q->qtype, q->qclass); - mDNSSendDNSMessage(m, &m->omsg, qptr, mDNSInterface_Any, &q->Target, q->TargetPort, mDNSNULL, mDNSNULL); + mDNSSendDNSMessage(m, &m->omsg, qptr, mDNSInterface_Any, q->LocalSocket, &q->Target, q->TargetPort, mDNSNULL, mDNSNULL); q->ThisQInterval *= QuestionIntervalStep; if (q->ThisQInterval > MaxQuestionInterval) q->ThisQInterval = MaxQuestionInterval; @@ -2532,10 +2562,13 @@ mDNSlocal void SendQueries(mDNS *const m) { //LogOperation("Accelerating %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - (q->LastQTime + q->ThisQInterval)); q->SendQNow = mDNSInterfaceMark; // Mark this question for sending on all interfaces + debugf("SendQueries: %##s (%s) next interval %d seconds RequestUnicast = %d", + q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval / InitialQuestionInterval, q->RequestUnicast); q->ThisQInterval *= QuestionIntervalStep; if (q->ThisQInterval > MaxQuestionInterval) q->ThisQInterval = MaxQuestionInterval; - else if (q->CurrentAnswers == 0 && q->ThisQInterval == InitialQuestionInterval * QuestionIntervalStep2) + else if (q->CurrentAnswers == 0 && q->ThisQInterval == InitialQuestionInterval * QuestionIntervalStep3 && !q->RequestUnicast && + !(RRTypeIsAddressType(q->qtype) && CacheHasAddressTypeForName(m, &q->qname, q->qnamehash))) { // Generally don't need to log this. // It's not especially noteworthy if a query finds no results -- this usually happens for domain @@ -2738,8 +2771,8 @@ mDNSlocal void SendQueries(mDNS *const m) m->omsg.h.numQuestions, m->omsg.h.numQuestions == 1 ? "" : "s", m->omsg.h.numAnswers, m->omsg.h.numAnswers == 1 ? "" : "s", m->omsg.h.numAuthorities, m->omsg.h.numAuthorities == 1 ? "" : "s", intf->InterfaceID); - if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSNULL); - if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSNULL); + if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSNULL); + if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSNULL); if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+9)/10); if (++pktcount >= 1000) { LogMsg("SendQueries exceeded loop limit %d: giving up", pktcount); break; } @@ -2934,8 +2967,8 @@ mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr) if (mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q) && ++q->RecentAnswerPkts >= 10 && q->ThisQInterval > InitialQuestionInterval * QuestionIntervalStep3 && m->timenow - q->LastQTxTime < mDNSPlatformOneSecond) { - LogMsg("CacheRecordAdd: %##s (%s) got immediate answer burst; restarting exponential backoff sequence", - q->qname.c, DNSTypeName(q->qtype)); + LogMsg("CacheRecordAdd: %##s (%s) got immediate answer burst (%d); restarting exponential backoff sequence (%d)", + q->qname.c, DNSTypeName(q->qtype), q->RecentAnswerPkts, q->ThisQInterval); q->LastQTime = m->timenow - InitialQuestionInterval + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*4); q->ThisQInterval = InitialQuestionInterval; SetNextQueryTime(m,q); @@ -2944,6 +2977,7 @@ mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr) verbosedebugf("CacheRecordAdd %p %##s (%s) %lu", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl); q->CurrentAnswers++; + q->unansweredQueries = 0; if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++; if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++; if (q->CurrentAnswers > 4000) @@ -4400,10 +4434,11 @@ mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg, m->omsg.h.numAnswers, m->omsg.h.numAnswers == 1 ? "" : "s", m->omsg.h.numAdditionals, m->omsg.h.numAdditionals == 1 ? "" : "s", srcaddr, mDNSVal16(srcport), InterfaceID, srcaddr->type); - mDNSSendDNSMessage(m, &m->omsg, responseend, InterfaceID, srcaddr, srcport, mDNSNULL, mDNSNULL); + mDNSSendDNSMessage(m, &m->omsg, responseend, InterfaceID, mDNSNULL, srcaddr, srcport, mDNSNULL, mDNSNULL); } } +#if 0 mDNSlocal mDNSBool TrustedSource(const mDNS *const m, const mDNSAddr *const srcaddr) { DNSServer *s; @@ -4413,12 +4448,19 @@ mDNSlocal mDNSBool TrustedSource(const mDNS *const m, const mDNSAddr *const srca if (mDNSSameAddress(srcaddr, &s->addr)) return(mDNStrue); return(mDNSfalse); } +#endif + +struct UDPSocket_struct + { + mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port + }; -mDNSlocal const DNSQuestion *ExpectingUnicastResponseForQuestion(const mDNS *const m, const mDNSOpaque16 id, const DNSQuestion *const question) +mDNSlocal const DNSQuestion *ExpectingUnicastResponseForQuestion(const mDNS *const m, const mDNSIPPort port, const mDNSOpaque16 id, const DNSQuestion *const question) { DNSQuestion *q; for (q = m->Questions; q; q=q->next) - if (mDNSSameOpaque16(q->TargetQID, id) && + if (mDNSSameIPPort(q->LocalSocket ? q->LocalSocket->port : MulticastDNSPort, port) && + mDNSSameOpaque16(q->TargetQID, id) && q->qtype == question->qtype && q->qclass == question->qclass && q->qnamehash == question->qnamehash && @@ -4427,22 +4469,23 @@ mDNSlocal const DNSQuestion *ExpectingUnicastResponseForQuestion(const mDNS *con return(mDNSNULL); } -mDNSlocal mDNSBool ExpectingUnicastResponseForRecord(mDNS *const m, const mDNSAddr *const srcaddr, const mDNSBool SrcLocal, const mDNSOpaque16 id, const CacheRecord *const rr) +mDNSlocal mDNSBool ExpectingUnicastResponseForRecord(mDNS *const m, const mDNSAddr *const srcaddr, const mDNSBool SrcLocal, const mDNSIPPort port, const mDNSOpaque16 id, const CacheRecord *const rr) { DNSQuestion *q; (void)id; + (void)srcaddr; for (q = m->Questions; q; q=q->next) if (ResourceRecordAnswersQuestion(&rr->resrec, q)) { if (!mDNSOpaque16IsZero(q->TargetQID)) { - // For now we don't do this check -- for LLQ updates, the ID doesn't seem to match the ID in the question - // if (mDNSSameOpaque16(q->TargetQID, id) + debugf("ExpectingUnicastResponseForRecord msg->h.id %d q->TargetQID %d for %s", mDNSVal16(id), mDNSVal16(q->TargetQID), CRDisplayString(m, rr)); + if (mDNSSameOpaque16(q->TargetQID, id)) { - if (mDNSSameAddress(srcaddr, &q->Target)) return(mDNStrue); - if (mDNSSameOpaque16(q->TargetQID, id)) return(mDNStrue); + if (mDNSSameIPPort(q->LocalSocket ? q->LocalSocket->port : MulticastDNSPort, port)) return(mDNStrue); + // if (mDNSSameAddress(srcaddr, &q->Target)) return(mDNStrue); // if (q->LongLived && mDNSSameAddress(srcaddr, &q->servAddr)) return(mDNStrue); Shouldn't need this now that we have LLQType checking - if (TrustedSource(m, srcaddr)) return(mDNStrue); + // if (TrustedSource(m, srcaddr)) return(mDNStrue); LogOperation("WARNING: Ignoring suspect uDNS response for %##s (%s) [q->Target %#a] from %#a: %s", q->qname.c, DNSTypeName(q->qtype), &q->Target, srcaddr, CRDisplayString(m, rr)); return(mDNSfalse); @@ -4635,7 +4678,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, { DNSQuestion q; ptr = getQuestion(response, ptr, end, InterfaceID, &q); - if (ptr && ExpectingUnicastResponseForQuestion(m, response->h.id, &q)) + if (ptr && (!dstaddr || ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q))) { CacheRecord *rr; const mDNSu32 slot = HashSlot(&q.qname); @@ -4678,7 +4721,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, // If response was not sent via LL multicast, // then see if it answers a recent query of ours, which would also make it acceptable for caching. - if (!AcceptableResponse) AcceptableResponse = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, response->h.id, &m->rec.r); + if (!AcceptableResponse) AcceptableResponse = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, dstport, response->h.id, &m->rec.r); // 1. Check that this packet resource record does not conflict with any of ours if (mDNSOpaque16IsZero(response->h.id)) @@ -4964,7 +5007,7 @@ exit: { DNSQuestion q; ptr = getQuestion(response, ptr, end, InterfaceID, &q); - if (ptr && ExpectingUnicastResponseForQuestion(m, response->h.id, &q)) + if (ptr && (!dstaddr || ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q))) { CacheRecord *rr, *neg = mDNSNULL; mDNSu32 slot = HashSlot(&q.qname); @@ -5084,11 +5127,6 @@ mDNSexport void MakeNegativeCacheRecord(mDNS *const m, const domainname *const n m->rec.r.NextInCFList = mDNSNULL; } -struct UDPSocket_struct - { - mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port - }; - mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID) @@ -5147,7 +5185,7 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co { ifid = mDNSInterface_Any; if (mDNS_LogLevel >= MDNS_LOG_VERBOSE_DEBUG) - DumpPacket(m, mDNSfalse, TLS ? "TLS" : !dstaddr ? "TCP" : "UDP", srcaddr, srcport, msg, end); + DumpPacket(m, mDNSfalse, TLS ? "TLS" : !dstaddr ? "TCP" : "UDP", srcaddr, srcport, dstaddr, dstport, msg, end); uDNS_ReceiveMsg(m, msg, end, srcaddr, srcport); // Note: mDNSCore also needs to get access to received unicast responses } @@ -5226,6 +5264,11 @@ mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const questi q->nta = question->nta; q->servAddr = question->servAddr; q->servPort = question->servPort; + q->qDNSServer = question->qDNSServer; + q->unansweredQueries = question->unansweredQueries; + + q->TargetQID = question->TargetQID; + q->LocalSocket = question->LocalSocket; q->state = question->state; // q->tcp = question->tcp; @@ -5234,8 +5277,13 @@ mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const questi q->ntries = question->ntries; q->id = question->id; + question->LocalSocket = mDNSNULL; question->nta = mDNSNULL; // If we've got a GetZoneData in progress, transfer it to the newly active question // question->tcp = mDNSNULL; + + if (q->LocalSocket) + LogOperation("UpdateQuestionDuplicates transferred LocalSocket pointer for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); + if (q->nta) { LogOperation("UpdateQuestionDuplicates transferred nta pointer for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); @@ -5256,7 +5304,7 @@ mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const questi } // Look up a DNS Server, matching by name in split-dns configurations. -mDNSlocal DNSServer *GetServerForName(mDNS *m, const domainname *name) +mDNSexport DNSServer *GetServerForName(mDNS *m, const domainname *name) { DNSServer *curmatch = mDNSNULL, *p; int curmatchlen = -1, ncount = name ? CountLabels(name) : 0; @@ -5379,6 +5427,7 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu question->CNAMEReferrals = 0; question->qDNSServer = mDNSNULL; + question->unansweredQueries = 0; question->nta = mDNSNULL; question->servAddr = zeroAddr; question->servPort = zeroIPPort; @@ -5391,6 +5440,8 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu question->ntries = 0; question->id = zeroOpaque64; + question->LocalSocket = mDNSNULL; + if (question->DuplicateOf) question->AuthInfo = question->DuplicateOf->AuthInfo; for (i=0; iTargetQID)) { + // We don't want to make a separate UDP socket for LLQs because (when we're using NAT) + // they all share a single NAT mapping for receiving inbound add/remove events. + if (!question->DuplicateOf && !question->LongLived) + { + question->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort); + debugf("mDNS_StartQuery_internal: dup %p %##s (%s) port %d", + question->DuplicateOf, question->qname.c, DNSTypeName(question->qtype), question->LocalSocket ? mDNSVal16(question->LocalSocket->port) : -1); + // If we fail to get a new on-demand socket (should only happen cases of the most extreme resource exhaustion) + // then we don't fail the query; we just let it use our pre-canned permanent socket, which is okay (it should + // never happen in normal operation, and even if it does we still have our cryptographically strong transaction ID). + } + question->qDNSServer = GetServerForName(m, &question->qname); ActivateUnicastQuery(m, question, mDNSfalse); @@ -5529,6 +5592,7 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que // *first*, then they're all ready to be updated a second time if necessary when we cancel our GetZoneData query. if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; } if (question->tcp) { DisposeTCPConn(question->tcp); question->tcp = mDNSNULL; } + if (question->LocalSocket) { mDNSPlatformUDPClose(question->LocalSocket); question->LocalSocket = mDNSNULL; } if (!mDNSOpaque16IsZero(question->TargetQID) && question->LongLived) { // Scan our list to see if any more wide-area LLQs remain. If not, stop our NAT Traversal. @@ -6929,13 +6993,21 @@ mDNSexport mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, return(mDNS_Register(m, rr)); } -mDNSOpaque16 mDNS_NewMessageID(mDNS * const m) +mDNSexport mDNSOpaque16 mDNS_NewMessageID(mDNS * const m) { - static mDNSBool randomized = mDNSfalse; - - if (!randomized) { m->NextMessageID = (mDNSu16)mDNSRandom(0xFFFF); randomized = mDNStrue; } - if (m->NextMessageID == 0) m->NextMessageID++; - return mDNSOpaque16fromIntVal(m->NextMessageID++); + mDNSOpaque16 id; + int i; + for (i=0; i<10; i++) + { + AuthRecord *r; + DNSQuestion *q; + id = mDNSOpaque16fromIntVal(1 + mDNSRandom(0xFFFE)); + for (r = m->ResourceRecords; r; r=r->next) if (mDNSSameOpaque16(id, r->id )) continue; + for (q = m->Questions; q; q=q->next) if (mDNSSameOpaque16(id, q->TargetQID)) continue; + break; + } + debugf("mDNS_NewMessageID: %5d", mDNSVal16(id)); + return id; } // *************************************************************************** @@ -7052,7 +7124,6 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->SuppressStdPort53Queries = 0; m->ServiceRegistrations = mDNSNULL; - m->NextMessageID = 0; m->DNSServers = mDNSNULL; m->Router = zeroAddr; @@ -7085,6 +7156,7 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->UPnPInterfaceID = 0; m->SSDPSocket = mDNSNULL; + m->SSDPMulticast = mDNSfalse; m->UPnPRouterPort = zeroIPPort; m->UPnPSOAPPort = zeroIPPort; m->UPnPRouterURL = mDNSNULL; @@ -7152,6 +7224,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; + q->unansweredQueries = 0; ActivateUnicastQuery(m, q, mDNStrue); } } diff --git a/mDNSCore/mDNSEmbeddedAPI.h b/mDNSCore/mDNSEmbeddedAPI.h index 72b9e1f..1f1c52f 100755 --- a/mDNSCore/mDNSEmbeddedAPI.h +++ b/mDNSCore/mDNSEmbeddedAPI.h @@ -54,6 +54,18 @@ Change History (most recent first): $Log: mDNSEmbeddedAPI.h,v $ +Revision 1.468.2.3 2008/07/29 20:46:57 mcguire + Should use randomized source ports and transaction IDs to avoid DNS cache poisoning +merge r1.474 from + +Revision 1.468.2.2 2008/07/29 19:44:38 mcguire + BTMM: alternate SSDP queries between multicast & unicast +merge r1.472, r1.473 for + +Revision 1.468.2.1 2008/07/29 19:10:53 mcguire + Use all configured DNS servers +merege 1.470 from + Revision 1.468 2008/03/06 02:48:34 mcguire write status to the DS @@ -1801,6 +1813,7 @@ struct DNSQuestion_struct // Wide Area fields. These are used internally by the uDNS core DNSServer *qDNSServer; // Caching server for this query (in the absence of an SRV saying otherwise) + mDNSu8 unansweredQueries;// The number of unanswered queries to this server ZoneData *nta; // Used for getting zone data for private or LLQ query mDNSAddr servAddr; // Address and port learned from _dns-llq, _dns-llq-tls or _dns-query-tls SRV query @@ -1820,6 +1833,7 @@ struct DNSQuestion_struct mDNSAddr Target; // Non-zero if you want to direct queries to a specific unicast target address mDNSIPPort TargetPort; // Must be set if Target is set mDNSOpaque16 TargetQID; // Must be set if Target is set + UDPSocket *LocalSocket; domainname qname; mDNSu16 qtype; mDNSu16 qclass; @@ -2007,7 +2021,6 @@ struct mDNS_struct mDNSs32 SuppressStdPort53Queries; // Wait before allowing the next standard unicast query to the user's configured DNS server ServiceRecordSet *ServiceRegistrations; - mDNSu16 NextMessageID; DNSServer *DNSServers; // list of DNS servers mDNSAddr Router; @@ -2045,6 +2058,7 @@ struct mDNS_struct tcpLNTInfo *tcpInfoUnmapList; // list of pending unmap requests mDNSInterfaceID UPnPInterfaceID; UDPSocket *SSDPSocket; // For SSDP request/response + mDNSBool SSDPMulticast; // whether we should send the SSDP query via multicast mDNSIPPort UPnPRouterPort; // port we send discovery messages to mDNSIPPort UPnPSOAPPort; // port we send SOAP messages to mDNSu8 *UPnPRouterURL; // router's URL string @@ -2325,6 +2339,8 @@ extern mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, mDNS_DomainT #define mDNS_StopAdvertiseDomains mDNS_Deregister extern mDNSOpaque16 mDNS_NewMessageID(mDNS *const m); + +extern DNSServer *GetServerForName(mDNS *m, const domainname *name); // *************************************************************************** #if 0 @@ -2578,7 +2594,7 @@ extern mDNSBool DNSDigest_VerifyMessage(DNSMessage *msg, mDNSu8 *end, LargeCache extern mStatus mDNSPlatformInit (mDNS *const m); extern void mDNSPlatformClose (mDNS *const m); extern mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end, -mDNSInterfaceID InterfaceID, const mDNSAddr *dst, mDNSIPPort dstport); +mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstport); extern void mDNSPlatformLock (const mDNS *const m); extern void mDNSPlatformUnlock (const mDNS *const m); @@ -2643,7 +2659,7 @@ extern mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, m extern void mDNSPlatformTCPCloseConnection(TCPSocket *sock); extern long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed); extern long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len); -extern UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, mDNSIPPort port); +extern UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport); extern void mDNSPlatformUDPClose(UDPSocket *sock); extern void mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst); @@ -2762,21 +2778,21 @@ struct CompileTimeAssertionChecks_mDNS // Check our structures are reasonable sizes. Including overly-large buffers, or embedding // other overly-large structures instead of having a pointer to them, can inadvertently // cause structure sizes (and therefore memory usage) to balloon unreasonably. - char sizecheck_ResourceRecord [(sizeof(ResourceRecord) <= 40) ? 1 : -1]; - char sizecheck_AuthRecord [(sizeof(AuthRecord) <= 1290) ? 1 : -1]; - char sizecheck_CacheRecord [(sizeof(CacheRecord) <= 170) ? 1 : -1]; - char sizecheck_CacheGroup [(sizeof(CacheGroup) <= 170) ? 1 : -1]; - char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 560) ? 1 : -1]; - char sizecheck_ZoneData [(sizeof(ZoneData) <= 1600) ? 1 : -1]; - char sizecheck_NATTraversalInfo [(sizeof(NATTraversalInfo) <= 140) ? 1 : -1]; - char sizecheck_HostnameInfo [(sizeof(HostnameInfo) <= 3000) ? 1 : -1]; - char sizecheck_DNSServer [(sizeof(DNSServer) <= 300) ? 1 : -1]; - char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 4000) ? 1 : -1]; - char sizecheck_ServiceRecordSet [(sizeof(ServiceRecordSet) <= 5700) ? 1 : -1]; - char sizecheck_DomainAuthInfo [(sizeof(DomainAuthInfo) <= 6000) ? 1 : -1]; - char sizecheck_ServiceInfoQuery [(sizeof(ServiceInfoQuery) <= 2900) ? 1 : -1]; + char sizecheck_ResourceRecord [(sizeof(ResourceRecord) <= 56) ? 1 : -1]; + char sizecheck_AuthRecord [(sizeof(AuthRecord) <= 1416) ? 1 : -1]; + char sizecheck_CacheRecord [(sizeof(CacheRecord) <= 200) ? 1 : -1]; + char sizecheck_CacheGroup [(sizeof(CacheGroup) <= 184) ? 1 : -1]; + char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 720) ? 1 : -1]; + char sizecheck_ZoneData [(sizeof(ZoneData) <= 1552) ? 1 : -1]; + char sizecheck_NATTraversalInfo [(sizeof(NATTraversalInfo) <= 192) ? 1 : -1]; + char sizecheck_HostnameInfo [(sizeof(HostnameInfo) <= 3304) ? 1 : -1]; + char sizecheck_DNSServer [(sizeof(DNSServer) <= 312) ? 1 : -1]; + char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 4392) ? 1 : -1]; + char sizecheck_ServiceRecordSet [(sizeof(ServiceRecordSet) <= 6248) ? 1 : -1]; + char sizecheck_DomainAuthInfo [(sizeof(DomainAuthInfo) <= 6544) ? 1 : -1]; + char sizecheck_ServiceInfoQuery [(sizeof(ServiceInfoQuery) <= 2912) ? 1 : -1]; #if APPLE_OSX_mDNSResponder - char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1040) ? 1 : -1]; + char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1064) ? 1 : -1]; #endif }; diff --git a/mDNSCore/uDNS.c b/mDNSCore/uDNS.c index e063fc5..d649f19 100755 --- a/mDNSCore/uDNS.c +++ b/mDNSCore/uDNS.c @@ -22,6 +22,18 @@ Change History (most recent first): $Log: uDNS.c,v $ +Revision 1.553.2.4 2008/07/29 20:47:44 mcguire + Should use randomized source ports and transaction IDs to avoid DNS cache poisoning +merge r1.567 & r1.568 from + +Revision 1.553.2.3 2008/07/29 19:09:21 mcguire + Use all configured DNS servers +merge r1.558-r1.565 from + +Revision 1.553.2.2 2008/07/29 18:50:09 mcguire + LLQ refresh randomization not working properly +merge r1.555 & r1.556 from + 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 @@ -1297,6 +1309,31 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons return(*p); } +mDNSlocal void PushDNSServerToEnd(mDNS *const m, DNSQuestion *q) + { + DNSServer **p = &m->DNSServers; + + if (m->mDNS_busy != m->mDNS_reentrancy+1) + LogMsg("PushDNSServerToEnd: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); + + if (!q->qDNSServer) + { + LogMsg("PushDNSServerToEnd: Null DNS server for %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), q->unansweredQueries); + return; + } + + LogOperation("PushDNSServerToEnd: Pushing DNS server %#a:%d (%##s) due to %d unanswered queries for %##s (%s)", &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qDNSServer->domain.c, q->unansweredQueries, q->qname.c, DNSTypeName(q->qtype)); + + while (*p) + { + if (*p == q->qDNSServer) *p = q->qDNSServer->next; + else p=&(*p)->next; + } + + *p = q->qDNSServer; + q->qDNSServer->next = mDNSNULL; + } + // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK #pragma mark - authorization management @@ -1452,7 +1489,7 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info) end = (mDNSu8 *)&u + sizeof(NATPortMapRequest); } - err = mDNSPlatformSendUDP(m, (mDNSu8 *)&u, end, 0, &m->Router, NATPMPPort); + err = mDNSPlatformSendUDP(m, (mDNSu8 *)&u, end, 0, mDNSNULL, &m->Router, NATPMPPort); #ifdef _LEGACY_NAT_TRAVERSAL_ if (mDNSIPPortIsZero(m->UPnPSOAPPort)) LNT_SendDiscoveryMsg(m); @@ -1759,7 +1796,7 @@ mDNSlocal void sendChallengeResponse(mDNS *const m, DNSQuestion *const q, const if (responsePtr) responsePtr = putLLQ(&m->omsg, responsePtr, q, llq, mDNSfalse); if (responsePtr) { - mStatus err = mDNSSendDNSMessage(m, &m->omsg, responsePtr, mDNSInterface_Any, &q->servAddr, q->servPort, q->tcp ? q->tcp->sock : mDNSNULL, q->AuthInfo); + mStatus err = mDNSSendDNSMessage(m, &m->omsg, responsePtr, mDNSInterface_Any, q->LocalSocket, &q->servAddr, q->servPort, q->tcp ? q->tcp->sock : mDNSNULL, q->AuthInfo); if (err) { LogMsg("sendChallengeResponse: mDNSSendDNSMessage%s failed: %d", q->tcp ? " (TCP)" : "", err); @@ -1776,19 +1813,20 @@ mDNSlocal void SetLLQTimer(mDNS *const m, DNSQuestion *const q, const LLQOptData q->LastQTime = m->timenow; q->expire = m->timenow + lease; q->ThisQInterval = lease/2 + mDNSRandom(lease/10); + debugf("SetLLQTimer setting %##s (%s) to %d %d", q->qname.c, DNSTypeName(q->qtype), lease/mDNSPlatformOneSecond, q->ThisQInterval/mDNSPlatformOneSecond); SetNextQueryTime(m, q); } mDNSlocal void recvSetupResponse(mDNS *const m, mDNSu8 rcode, DNSQuestion *const q, const LLQOptData *const llq) { if (rcode && rcode != kDNSFlag1_RC_NXDomain) - { LogMsg("ERROR: recvSetupResponse %##s - rcode && rcode != kDNSFlag1_RC_NXDomain", q->qname.c); return; } + { LogMsg("ERROR: recvSetupResponse %##s (%s) - rcode && rcode != kDNSFlag1_RC_NXDomain", q->qname.c, DNSTypeName(q->qtype)); return; } if (llq->llqOp != kLLQOp_Setup) - { LogMsg("ERROR: recvSetupResponse %##s - bad op %d", q->qname.c, llq->llqOp); return; } + { LogMsg("ERROR: recvSetupResponse %##s (%s) - bad op %d", q->qname.c, DNSTypeName(q->qtype), llq->llqOp); return; } if (llq->vers != kLLQ_Vers) - { LogMsg("ERROR: recvSetupResponse %##s - bad vers %d", q->qname.c, llq->vers); return; } + { LogMsg("ERROR: recvSetupResponse %##s (%s) - bad vers %d", q->qname.c, DNSTypeName(q->qtype), llq->vers); return; } if (q->state == LLQ_InitialRequest) { @@ -1823,7 +1861,7 @@ mDNSlocal void recvSetupResponse(mDNS *const m, mDNSu8 rcode, DNSQuestion *const q->id = llq->id; } - if (llq->err) { LogMsg("ERROR: recvSetupResponse %##s code %d from server", q->qname.c, llq->err); StartLLQPolling(m,q); return; } + if (llq->err) { LogMsg("ERROR: recvSetupResponse %##s (%s) code %d from server", q->qname.c, DNSTypeName(q->qtype), llq->err); StartLLQPolling(m,q); return; } if (!mDNSSameOpaque64(&q->id, &llq->id)) { LogMsg("recvSetupResponse - ID changed. discarding"); return; } // this can happen rarely (on packet loss + reordering) q->state = LLQ_Established; @@ -1849,7 +1887,8 @@ mDNSexport uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *co debugf("uDNS_recvLLQResponse found %##s (%s) %d %#a %#a %X %X %X %X %d", q->qname.c, DNSTypeName(q->qtype), q->state, srcaddr, &q->servAddr, opt->OptData.llq.id.l[0], opt->OptData.llq.id.l[1], q->id.l[0], q->id.l[1], opt->OptData.llq.llqOp); - if (q->state == LLQ_Poll) + if (q->state == LLQ_Poll) debugf("uDNS_LLQ_Events: q->state == LLQ_Poll msg->h.id %d q->TargetQID %d", mDNSVal16(msg->h.id), mDNSVal16(q->TargetQID)); + if (q->state == LLQ_Poll && mDNSSameOpaque16(msg->h.id, q->TargetQID)) { m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it LogOperation("uDNS_recvLLQResponse got poll response; moving to LLQ_InitialRequest for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); @@ -1860,15 +1899,16 @@ mDNSexport uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *co SetNextQueryTime(m, q); return uDNS_LLQ_Entire; // uDNS_LLQ_Entire means flush stale records; assume a large effective TTL } + // Note: In LLQ Event packets, the msg->h.id does not match our q->TargetQID, because in that case the msg->h.id nonce is selected by the server else if (opt && q->state == LLQ_Established && opt->OptData.llq.llqOp == kLLQOp_Event && mDNSSameOpaque64(&opt->OptData.llq.id, &q->id)) { mDNSu8 *ackEnd; - if (q->ThisQInterval < MAX_UCAST_POLL_INTERVAL) q->ThisQInterval = MAX_UCAST_POLL_INTERVAL; //debugf("Sending LLQ ack for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); InitializeDNSMessage(&m->omsg.h, msg->h.id, ResponseFlags); ackEnd = putLLQ(&m->omsg, m->omsg.data, mDNSNULL, &opt->OptData.llq, mDNSfalse); - if (ackEnd) mDNSSendDNSMessage(m, &m->omsg, ackEnd, mDNSInterface_Any, srcaddr, srcport, mDNSNULL, mDNSNULL); + if (ackEnd) mDNSSendDNSMessage(m, &m->omsg, ackEnd, mDNSInterface_Any, q->LocalSocket, srcaddr, srcport, mDNSNULL, mDNSNULL); m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it + debugf("uDNS_LLQ_Events: q->state == LLQ_Established msg->h.id %d q->TargetQID %d", mDNSVal16(msg->h.id), mDNSVal16(q->TargetQID)); return uDNS_LLQ_Events; } if (opt && mDNSSameOpaque16(msg->h.id, q->TargetQID)) @@ -1978,7 +2018,7 @@ mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEs AuthInfo = q->AuthInfo; // Need to add TSIG to this message } - err = mDNSSendDNSMessage(m, &tcpInfo->request, end, mDNSInterface_Any, &tcpInfo->Addr, tcpInfo->Port, sock, AuthInfo); + err = mDNSSendDNSMessage(m, &tcpInfo->request, end, mDNSInterface_Any, mDNSNULL, &tcpInfo->Addr, tcpInfo->Port, sock, AuthInfo); if (err) { debugf("ERROR: tcpCallback: mDNSSendDNSMessage - %ld", err); err = mStatus_UnknownErr; goto exit; } // Record time we sent this question @@ -1986,7 +2026,8 @@ mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEs { mDNS_Lock(m); q->LastQTime = m->timenow; - q->ThisQInterval = MAX_UCAST_POLL_INTERVAL; + if (q->ThisQInterval < (256 * mDNSPlatformOneSecond)) // Now we have a TCP connection open, make sure we wait at least 256 seconds before retrying + q->ThisQInterval = (256 * mDNSPlatformOneSecond); SetNextQueryTime(m, q); mDNS_Unlock(m); } @@ -1998,7 +2039,7 @@ mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEs { mDNSu8 *lenptr = (mDNSu8 *)&tcpInfo->replylen; n = mDNSPlatformReadTCP(sock, lenptr + tcpInfo->nread, 2 - tcpInfo->nread, &closed); - if (n < 0) { LogMsg("ERROR:tcpCallback - attempt to read message length failed (%d)", n); err = mStatus_ConnFailed; goto exit; } + if (n < 0) { LogMsg("ERROR: tcpCallback - attempt to read message length failed (%d)", n); err = mStatus_ConnFailed; goto exit; } else if (closed) { // It's perfectly fine for this socket to close after the first reply. The server might @@ -2081,7 +2122,7 @@ exit: q->ThisQInterval = MAX_UCAST_POLL_INTERVAL; SetNextQueryTime(m, q); } - // ConnFailed is actually okay. It just means that the server closed the connection but the LLQ is still okay. + // ConnFailed may be actually okay. It just means that the server closed the connection but the LLQ may still be okay. // If the error isn't ConnFailed, then the LLQ is in bad shape. if (err != mStatus_ConnFailed) { @@ -2128,7 +2169,7 @@ mDNSlocal tcpInfo_t *MakeTCPConn(mDNS *const m, const DNSMessage *const msg, con mDNSPlatformMemCopy(&info->request, msg, info->requestLen); } - if (!info->sock) { LogMsg("SendServiceRegistration: uanble to create TCP socket"); mDNSPlatformMemFree(info); return(mDNSNULL); } + if (!info->sock) { LogMsg("SendServiceRegistration: unable to create TCP socket"); mDNSPlatformMemFree(info); return(mDNSNULL); } err = mDNSPlatformTCPConnect(info->sock, Addr, Port, 0, tcpCallback, info); // Probably suboptimal here. @@ -2226,7 +2267,7 @@ mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q) end = putLLQ(&m->omsg, m->omsg.data, q, &llqData, mDNStrue); if (!end) { LogMsg("ERROR: startLLQHandshake - putLLQ"); StartLLQPolling(m,q); return; } - mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, &q->servAddr, q->servPort, mDNSNULL, mDNSNULL); + mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, q->LocalSocket, &q->servAddr, q->servPort, mDNSNULL, mDNSNULL); // update question state q->state = LLQ_InitialRequest; @@ -2392,7 +2433,7 @@ mDNSlocal void SendServiceRegistration(mDNS *m, ServiceRecordSet *srs) } else { - err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, srs->RR_SRV.resrec.name)); + err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, srs->RR_SRV.resrec.name)); if (err) debugf("ERROR: SendServiceRegistration - mDNSSendDNSMessage - %ld", err); } @@ -2726,7 +2767,7 @@ mDNSlocal void SendServiceDeregistration(mDNS *m, ServiceRecordSet *srs) } else { - err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, srs->RR_SRV.resrec.name)); + err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, srs->RR_SRV.resrec.name)); if (err && err != mStatus_TransientErr) { debugf("ERROR: SendServiceDeregistration - mDNSSendDNSMessage - %ld", err); goto exit; } } @@ -2872,7 +2913,7 @@ mDNSlocal void hostnameGetPublicAddressCallback(mDNS *m, NATTraversalInfo *n) if (h->arv4.resrec.RecordType) { if (mDNSSameIPv4Address(h->arv4.resrec.rdata->u.ipv4, n->ExternalAddress)) return; // If address unchanged, do nothing - LogMsg("Updating hostname %##s IPv4 from %.4a to %.4a (NAT gateway's external address)", h->arv4.resrec.name->c, &h->arv4.resrec.rdata->u.ipv4, &n->ExternalAddress); + LogOperation("Updating hostname %##s IPv4 from %.4a to %.4a (NAT gateway's external address)", h->arv4.resrec.name->c, &h->arv4.resrec.rdata->u.ipv4, &n->ExternalAddress); mDNS_Deregister(m, &h->arv4); // mStatus_MemFree callback will re-register with new address } else @@ -3360,7 +3401,7 @@ mDNSlocal void SendRecordRegistration(mDNS *const m, AuthRecord *rr) } else { - err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, &rr->UpdateServer, rr->UpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, rr->resrec.name)); + err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &rr->UpdateServer, rr->UpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, rr->resrec.name)); if (err) debugf("ERROR: SendRecordRegistration - mDNSSendDNSMessage - %ld", err); } @@ -3828,7 +3869,12 @@ mDNSlocal mDNSBool uDNS_ReceiveTestQuestionResponse(mDNS *const m, DNSMessage *c 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 && !NoTestQuery(q)) - { q->LastQTime = m->timenow - q->ThisQInterval; m->NextScheduledQuery = m->timenow; } + { + q->ThisQInterval = INIT_UCAST_POLL_INTERVAL / QuestionIntervalStep; + q->unansweredQueries = 0; + q->LastQTime = m->timenow - q->ThisQInterval; + m->NextScheduledQuery = m->timenow; + } } return(mDNStrue); // Return mDNStrue to tell uDNS_ReceiveMsg it doesn't need to process this packet further @@ -3940,7 +3986,7 @@ mDNSexport void sendLLQRefresh(mDNS *m, DNSQuestion *q) if (q->ReqLease) if ((q->state == LLQ_Established && q->ntries >= kLLQ_MAX_TRIES) || q->expire - m->timenow < 0) { - LogMsg("Unable to refresh LLQ %##s (%s) - will retry in %d minutes", q->qname.c, DNSTypeName(q->qtype), LLQ_POLL_INTERVAL/3600); + LogMsg("Unable to refresh LLQ %##s (%s) - will retry in %d seconds", q->qname.c, DNSTypeName(q->qtype), LLQ_POLL_INTERVAL / mDNSPlatformOneSecond); StartLLQPolling(m,q); return; } @@ -3973,7 +4019,7 @@ mDNSexport void sendLLQRefresh(mDNS *m, DNSQuestion *q) } else { - mStatus err = mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, &q->servAddr, q->servPort, q->tcp ? q->tcp->sock : mDNSNULL, mDNSNULL); + mStatus err = mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, q->LocalSocket, &q->servAddr, q->servPort, q->tcp ? q->tcp->sock : mDNSNULL, mDNSNULL); if (err) { LogMsg("sendLLQRefresh: mDNSSendDNSMessage%s failed: %d", q->tcp ? " (TCP)" : "", err); @@ -4168,7 +4214,7 @@ mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr) } else { - mStatus err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, &rr->UpdateServer, rr->UpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, rr->resrec.name)); + mStatus err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &rr->UpdateServer, rr->UpdatePort, mDNSNULL, GetAuthInfoForName_internal(m, rr->resrec.name)); if (err) debugf("ERROR: SendRecordDeregistration - mDNSSendDNSMessage - %ld", err); if (rr->state == regState_DeregPending) CompleteDeregistration(m, rr); // Don't touch rr after this } @@ -4356,15 +4402,42 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) // We repeat the check above (rather than just making this the "else" case) because startLLQHandshake can change q->state to LLQ_Poll if (!(q->LongLived && q->state != LLQ_Poll)) { + if (q->unansweredQueries >= MAX_UCAST_UNANSWERED_QUERIES) + { + DNSServer *orig = q->qDNSServer; + +#if LogAllOperations || MDNS_DEBUGMSGS + char buffer[1024]; + + mDNS_snprintf(buffer, sizeof(buffer), orig ? "%#a:%d (%##s)" : "null", &orig->addr, mDNSVal16(orig->port), orig->domain.c); + LogOperation("Sent %d unanswered queries for %##s (%s) to %s", q->unansweredQueries, q->qname.c, DNSTypeName(q->qtype), buffer); +#endif + + PushDNSServerToEnd(m, q); + q->qDNSServer = GetServerForName(m, &q->qname); + + if (q->qDNSServer != orig) + { +#if LogAllOperations || MDNS_DEBUGMSGS + mDNS_snprintf(buffer, sizeof(buffer), q->qDNSServer ? "%#a:%d (%##s)" : "null", &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port), q->qDNSServer->domain.c); + LogOperation("Server for %##s (%s) changed to %s", q->qname.c, DNSTypeName(q->qtype), buffer); +#endif + q->ThisQInterval = q->ThisQInterval / QuestionIntervalStep; // Decrease interval one step so we don't quickly bounce between servers for queries that will not be answered. + } + + q->unansweredQueries = 0; + } + if (q->qDNSServer && q->qDNSServer->teststate != DNSServer_Disabled) { mDNSu8 *end = m->omsg.data; mStatus err = mStatus_NoError; mDNSBool private = mDNSfalse; + InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags); + 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 && q->AuthInfo->AutoTunnel); } @@ -4373,13 +4446,12 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) LogOperation("Sending DNS test query to %#a:%d", &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port)); q->ThisQInterval = INIT_UCAST_POLL_INTERVAL / QuestionIntervalStep; q->qDNSServer->lasttest = m->timenow; - InitializeDNSMessage(&m->omsg.h, mDNS_NewMessageID(m), uQueryFlags); end = putQuestion(&m->omsg, m->omsg.data, m->omsg.data + AbsoluteMaxDNSMessageData, DNSRelayTestQuestion, kDNSType_PTR, kDNSClass_IN); } if (end > m->omsg.data && (q->qDNSServer->teststate != DNSServer_Failed || NoTestQuery(q))) { - //LogMsg("uDNS_CheckCurrentQuestion %d %p %##s (%s)", sendtime - m->timenow, private, q->qname.c, DNSTypeName(q->qtype)); + //LogMsg("uDNS_CheckCurrentQuestion %p %d %p %##s (%s)", q, sendtime - m->timenow, private, q->qname.c, DNSTypeName(q->qtype)); if (private) { if (q->nta) CancelGetZoneData(m, q->nta); @@ -4388,7 +4460,7 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) } else { - err = mDNSSendDNSMessage(m, &m->omsg, end, q->qDNSServer->interface, &q->qDNSServer->addr, q->qDNSServer->port, mDNSNULL, mDNSNULL); + err = mDNSSendDNSMessage(m, &m->omsg, end, q->qDNSServer->interface, q->LocalSocket, &q->qDNSServer->addr, q->qDNSServer->port, mDNSNULL, mDNSNULL); m->SuppressStdPort53Queries = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+99)/100); } } @@ -4397,6 +4469,7 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) else { q->ThisQInterval = q->ThisQInterval * QuestionIntervalStep; // Only increase interval if send succeeded + q->unansweredQueries++; if (q->ThisQInterval > MAX_UCAST_POLL_INTERVAL) q->ThisQInterval = MAX_UCAST_POLL_INTERVAL; LogOperation("Increased ThisQInterval to %d for %##s (%s)", q->ThisQInterval, q->qname.c, DNSTypeName(q->qtype)); @@ -4428,6 +4501,7 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) MakeNegativeCacheRecord(m, &q->qname, q->qnamehash, q->qtype, q->qclass, 60); // Inactivate this question until the next change of DNS servers (do this before AnswerCurrentQuestionWithResourceRecord) q->ThisQInterval = 0; + q->unansweredQueries = 0; CreateNewCacheEntry(m, slot, cg); m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it // MUST NOT touch m->CurrentQuestion (or q) after this -- client callback could have deleted it @@ -4912,6 +4986,6 @@ struct CompileTimeAssertionChecks_uDNS // Check our structures are reasonable sizes. Including overly-large buffers, or embedding // other overly-large structures instead of having a pointer to them, can inadvertently // cause structure sizes (and therefore memory usage) to balloon unreasonably. - char sizecheck_tcpInfo_t [(sizeof(tcpInfo_t) <= 9100) ? 1 : -1]; - char sizecheck_SearchListElem[(sizeof(SearchListElem) <= 3800) ? 1 : -1]; + char sizecheck_tcpInfo_t [(sizeof(tcpInfo_t) <= 9056) ? 1 : -1]; + char sizecheck_SearchListElem[(sizeof(SearchListElem) <= 3880) ? 1 : -1]; }; diff --git a/mDNSCore/uDNS.h b/mDNSCore/uDNS.h index 2676a2c..3a66ab6 100755 --- a/mDNSCore/uDNS.h +++ b/mDNSCore/uDNS.h @@ -17,6 +17,12 @@ Change History (most recent first): $Log: uDNS.h,v $ +Revision 1.92 2008/06/19 23:42:03 mcguire + Use all configured DNS servers + +Revision 1.91 2008/06/19 01:20:50 mcguire + Use all configured DNS servers + Revision 1.90 2007/12/22 02:25:30 cheshire Records and Services sometimes not re-registering on wake from sleep @@ -225,6 +231,7 @@ Revision 1.33 2006/07/05 22:53:28 cheshire //#define MAX_UCAST_POLL_INTERVAL (1 * 60 * mDNSPlatformOneSecond) #define LLQ_POLL_INTERVAL (15 * 60 * mDNSPlatformOneSecond) // Polling interval for zones w/ an advertised LLQ port (ie not static zones) if LLQ fails due to NAT, etc. #define RESPONSE_WINDOW (60 * mDNSPlatformOneSecond) // require server responses within one minute of request +#define MAX_UCAST_UNANSWERED_QUERIES 2 // the number of unanswered queries from any one uDNS server before trying another server #define DEFAULT_UPDATE_LEASE 7200 diff --git a/mDNSMacOSX/LegacyNATTraversal.c b/mDNSMacOSX/LegacyNATTraversal.c index b1a23b6..0653dfc 100644 --- a/mDNSMacOSX/LegacyNATTraversal.c +++ b/mDNSMacOSX/LegacyNATTraversal.c @@ -17,6 +17,15 @@ Change History (most recent first): $Log: LegacyNATTraversal.c,v $ +Revision 1.48 2008/07/24 20:23:04 cheshire + Should use randomized source ports and transaction IDs to avoid DNS cache poisoning + +Revision 1.47 2008/07/18 21:37:46 mcguire + BTMM: alternate SSDP queries between multicast & unicast + +Revision 1.46 2008/05/13 01:51:12 mcguire + UPnP compatibility workaround for Netgear WGT624 + Revision 1.45 2007/12/06 00:22:27 mcguire BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp) @@ -206,9 +215,10 @@ mDNSlocal mStatus SendPortMapRequest(mDNS *m, NATTraversalInfo *n); // referencing a service we care about (WANIPConnection), look for the "controlURL" header immediately following, and copy the addressing and URL info we need mDNSlocal void handleLNTDeviceDescriptionResponse(tcpLNTInfo *tcpInfo) { - mDNS *m = tcpInfo->m; - char *ptr = (char *)tcpInfo->Reply; - char *end = (char *)tcpInfo->Reply + tcpInfo->nread; + mDNS *m = tcpInfo->m; + char *ptr = (char *)tcpInfo->Reply; + char *end = (char *)tcpInfo->Reply + tcpInfo->nread; + char *stop = mDNSNULL; // find the service we care about while (ptr && ptr != end) @@ -228,7 +238,13 @@ mDNSlocal void handleLNTDeviceDescriptionResponse(tcpLNTInfo *tcpInfo) ptr += 11; // skip over "controlURL>" if (ptr >= end) { LogOperation("handleLNTDeviceDescriptionResponse: past end of buffer and no body!"); return; } // check ptr again in case we skipped over the end of the buffer - // is there an address string "http://"? starting from where we left off + // find the end of the controlURL element + for (stop = ptr; stop != end; stop++) { if (*stop == '<') { end = stop; break; } } + + // fill in default port + m->UPnPSOAPPort = m->UPnPRouterPort; + + // is there an address string "http://"? if (strncasecmp(ptr, "http://", 7) == 0) { int i; @@ -246,50 +262,41 @@ mDNSlocal void handleLNTDeviceDescriptionResponse(tcpLNTInfo *tcpInfo) strncpy((char *)m->UPnPSOAPAddressString, ptr, i); // copy the address string m->UPnPSOAPAddressString[i] = '\0'; // terminate the string + + stop = ptr; // remember where to stop (just after "http://") + ptr = addrPtr; // move ptr past the rest of what we just processed + + // find the port number in the string + for (addrPtr--;addrPtr>stop;addrPtr--) + { + if (*addrPtr == ':') + { + int port; + addrPtr++; // skip over ':' + port = (int)strtol(addrPtr, mDNSNULL, 10); + m->UPnPSOAPPort = mDNSOpaque16fromIntVal(port); // store it properly converted + break; + } + } } - + if (m->UPnPSOAPAddressString == mDNSNULL) m->UPnPSOAPAddressString = m->UPnPRouterAddressString; // just copy the pointer, don't allocate more memory LogOperation("handleLNTDeviceDescriptionResponse: SOAP address string [%s]", m->UPnPSOAPAddressString); - // find port and router URL, starting after the "http://" if it was there - while (ptr && ptr != end) + // ptr should now point to the first character we haven't yet processed + if (ptr != end) { - if (*ptr == ':') // found the port number - { - int port; - ptr++; // skip over ':' - if (ptr == end) { LogOperation("handleLNTDeviceDescriptionResponse: reached end of buffer and no address!"); return; } - port = (int)strtol(ptr, (char **)mDNSNULL, 10); // get the port - m->UPnPSOAPPort = mDNSOpaque16fromIntVal(port); // store it properly converted - } - else if (*ptr == '/') // found SOAP URL - { - int j; - char *urlPtr = mDNSNULL; - if (mDNSIPPortIsZero(m->UPnPSOAPPort)) m->UPnPSOAPPort = m->UPnPRouterPort; // fill in default port if we didn't find one before - - urlPtr = ptr; - for (j = 0; urlPtr && urlPtr != end; j++, urlPtr++) if (*urlPtr == '<') break; // first find the next '<' and count the chars - if (urlPtr == mDNSNULL || urlPtr == end) { LogOperation("handleLNTDeviceDescriptionResponse: didn't find SOAP URL string"); return; } - - // allocate the buffer (len j+2 because we're copying from the first '/' and so we have space to terminate the string) - if (m->UPnPSOAPURL != mDNSNULL) mDNSPlatformMemFree(m->UPnPSOAPURL); - if ((m->UPnPSOAPURL = (mDNSu8 *)mDNSPlatformMemAllocate(j+1)) == mDNSNULL) { LogMsg("can't mDNSPlatformMemAllocate SOAP URL"); return; } - - // now copy - strncpy((char *)m->UPnPSOAPURL, ptr, j); // this URL looks something like "/uuid:0013-108c-4b3f0000f3dc" - m->UPnPSOAPURL[j] = '\0'; // terminate the string - break; // we've got everything we need, so get out here - } - ptr++; // continue + // allocate the buffer + if (m->UPnPSOAPURL != mDNSNULL) mDNSPlatformMemFree(m->UPnPSOAPURL); + if ((m->UPnPSOAPURL = (mDNSu8 *)mDNSPlatformMemAllocate(end - ptr + 1)) == mDNSNULL) { LogMsg("can't mDNSPlatformMemAllocate SOAP URL"); return; } + + // now copy + strncpy((char *)m->UPnPSOAPURL, ptr, end - ptr); // this URL looks something like "/uuid:0013-108c-4b3f0000f3dc" + m->UPnPSOAPURL[end - ptr] = '\0'; // terminate the string } // if we get to the end and haven't found the URL fill in the defaults - if (m->UPnPSOAPURL == mDNSNULL) - { - m->UPnPSOAPURL = m->UPnPRouterURL; // just copy the pointer, don't allocate more memory - m->UPnPSOAPPort = m->UPnPRouterPort; - } + if (m->UPnPSOAPURL == mDNSNULL) m->UPnPSOAPURL = m->UPnPRouterURL; // just copy the pointer, don't allocate more memory LogOperation("handleLNTDeviceDescriptionResponse: SOAP URL [%s] port %d", m->UPnPSOAPURL, mDNSVal16(m->UPnPSOAPPort)); } @@ -825,14 +832,20 @@ mDNSexport void LNT_SendDiscoveryMsg(mDNS *m) "ST:urn:schemas-upnp-org:service:WANIPConnection:1\r\n" "Man:\"ssdp:discover\"\r\n" "MX:3\r\n\r\n"; + static const mDNSAddr multicastDest = { mDNSAddrType_IPv4, { { { 239, 255, 255, 250 } } } }; + + // Always send the first SSDP packet via unicast + if (m->retryIntervalGetAddr <= NATMAP_INIT_RETRY) m->SSDPMulticast = mDNSfalse; LogOperation("LNT_SendDiscoveryMsg Router %.4a Current External Address %.4a", &m->Router.ip.v4, &m->ExternalAddress); if (!mDNSIPv4AddressIsZero(m->Router.ip.v4) && mDNSIPv4AddressIsZero(m->ExternalAddress)) { if (!m->SSDPSocket) { m->SSDPSocket = mDNSPlatformUDPSocket(m, zeroIPPort); LogOperation("LNT_SendDiscoveryMsg created SSDPSocket %p", &m->SSDPSocket); } - mDNSPlatformSendUDP(m, msg, msg + sizeof(msg) - 1, 0, &m->Router, SSDPPort); + mDNSPlatformSendUDP(m, msg, msg + sizeof(msg) - 1, 0, m->SSDPSocket, m->SSDPMulticast ? &multicastDest : &m->Router, SSDPPort); } + + m->SSDPMulticast = !m->SSDPMulticast; } #endif /* _LEGACY_NAT_TRAVERSAL_ */ diff --git a/mDNSMacOSX/daemon.c b/mDNSMacOSX/daemon.c index f36174f..25b2e43 100644 --- a/mDNSMacOSX/daemon.c +++ b/mDNSMacOSX/daemon.c @@ -30,6 +30,13 @@ Change History (most recent first): $Log: daemon.c,v $ +Revision 1.360 2008/03/13 20:55:16 mcguire + fix deprecated warnings/errors +Additional cleanup: use a conditional macro instead of lots of #if + +Revision 1.359 2008/03/12 23:02:58 mcguire + fix deprecated warnings/errors + Revision 1.358 2008/03/06 21:26:11 cheshire Moved duplicated STRINGIFY macro from individual C files to DNSCommon.h @@ -372,6 +379,12 @@ Revision 1.261 2006/01/06 01:22:28 cheshire #include #include +#if TARGET_OS_EMBEDDED +#include + +#define bootstrap_register(A,B,C) bootstrap_register2((A),(B),(C),0) +#endif + #include "DNSServiceDiscoveryRequestServer.h" #include "DNSServiceDiscoveryReply.h" @@ -2137,14 +2150,14 @@ mDNSlocal kern_return_t mDNSDaemonInitialize(void) s_port = CFMachPortCreate(NULL, DNSserverCallback, NULL, NULL); m_port = CFMachPortGetPort(s_port); char *MachServerName = OSXVers < 7 ? "DNSServiceDiscoveryServer" : "com.apple.mDNSResponder"; - kern_return_t status = bootstrap_register(bootstrap_port, MachServerName, m_port); + kern_return_t status = bootstrap_register(bootstrap_port, MachServerName, m_port); if (status) { if (status == 1103) - LogMsg("Bootstrap_register failed(): A copy of the daemon is apparently already running"); + LogMsg("bootstrap_register() failed: A copy of the daemon is apparently already running"); else - LogMsg("Bootstrap_register failed(): %s %d", mach_error_string(status), status); + LogMsg("bootstrap_register() failed: %s %d", mach_error_string(status), status); return(status); } } diff --git a/mDNSMacOSX/helper-main.c b/mDNSMacOSX/helper-main.c index 03efad4..af019b3 100644 --- a/mDNSMacOSX/helper-main.c +++ b/mDNSMacOSX/helper-main.c @@ -17,6 +17,13 @@ Change History (most recent first): $Log: helper-main.c,v $ +Revision 1.15 2008/03/13 20:55:16 mcguire + fix deprecated warnings/errors +Additional cleanup: use a conditional macro instead of lots of #if + +Revision 1.14 2008/03/12 23:02:59 mcguire + fix deprecated warnings/errors + Revision 1.13 2007/09/21 16:13:14 cheshire Additional Tiger compatibility fix: After bootstrap_check_in, we need to give ourselves a Mach "send" right to the port, otherwise our ten-second idle timeout @@ -84,7 +91,10 @@ Revision 1.1 2007/08/08 22:34:58 mcguire #include "helpermsgServer.h" #if TARGET_OS_EMBEDDED +#include #define NO_SECURITYFRAMEWORK 1 + +#define bootstrap_register(A,B,C) bootstrap_register2((A),(B),(C),0) #endif #ifndef LAUNCH_JOBKEY_MACHSERVICES @@ -247,9 +257,11 @@ static mach_port_t register_service(const char *service_name) { helplog(ASL_LEVEL_ERR, "mach_port_allocate: %s", mach_error_string(kr)); goto error; } if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND))) { helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %s", mach_error_string(kr)); goto error; } + // XXX bootstrap_register does not modify its second argument, but the prototype does not include const. if (KERN_SUCCESS != (kr = bootstrap_register(bootstrap_port, (char *)service_name, port))) { helplog(ASL_LEVEL_ERR, "bootstrap_register failed: %s", mach_error_string(kr)); goto error; } + return port; error: if (MACH_PORT_NULL != port) mach_port_deallocate(mach_task_self(), port); @@ -291,12 +303,12 @@ int main(int ac, char *av[]) // Explicitly ensure that our Keychain operations utilize the system domain. SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem); #endif - if (!opt_debug) + port = checkin(kmDNSHelperServiceName); + if (!port) { - port = checkin(kmDNSHelperServiceName); - if (!port) helplog(ASL_LEVEL_ERR, "Launchd provided no launchdata; will open Mach port explicitly"); + helplog(ASL_LEVEL_ERR, "Launchd provided no launchdata; will open Mach port explicitly"); + port = register_service(kmDNSHelperServiceName); } - if (!port) port = register_service(kmDNSHelperServiceName); if (maxidle) actualidle = maxidle; initialize_timer(port); diff --git a/mDNSMacOSX/mDNSMacOSX.c b/mDNSMacOSX/mDNSMacOSX.c index 6cfb6a4..cc13980 100644 --- a/mDNSMacOSX/mDNSMacOSX.c +++ b/mDNSMacOSX/mDNSMacOSX.c @@ -17,6 +17,14 @@ Change History (most recent first): $Log: mDNSMacOSX.c,v $ +Revision 1.536.2.2 2008/07/30 01:08:17 mcguire + Should use randomized source ports and transaction IDs to avoid DNS cache poisoning +merge r1.540 from + +Revision 1.536.2.1 2008/07/29 20:48:10 mcguire + Should use randomized source ports and transaction IDs to avoid DNS cache poisoning +merge r1.539 from + Revision 1.536 2008/03/25 01:27:30 mcguire Status sometimes wrong when link goes down @@ -1002,17 +1010,12 @@ mDNSlocal mDNSBool AddrRequiresPPPConnection(const struct sockaddr *addr) return result; } -struct UDPSocket_struct - { - mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCore expects every UDPSocket_struct to begin with mDNSIPPort port - KQSocketSet ss; - }; - // NOTE: If InterfaceID is NULL, it means, "send this packet through our anonymous unicast socket" // NOTE: If InterfaceID is non-NULL it means, "send this packet through our port 5353 socket on the specified interface" // OR send via our primary v4 unicast socket +// UPDATE: The UDPSocket *src parameter now allows the caller to specify the source socket mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end, - mDNSInterfaceID InterfaceID, const mDNSAddr *dst, mDNSIPPort dstPort) + mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstPort) { // Note: For this platform we've adopted the convention that InterfaceIDs are secretly pointers // to the NetworkInterfaceInfoOSX structure that holds the active sockets. The mDNSCore code @@ -1032,10 +1035,7 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms sin_to->sin_addr.s_addr = dst->ip.v4.NotAnInteger; s = m->p->permanentsockets.sktv4; -#ifdef _LEGACY_NAT_TRAVERSAL_ - if (m->SSDPSocket && mDNSSameIPPort(dstPort, SSDPPort)) - s = m->SSDPSocket->ss.sktv4; -#endif _LEGACY_NAT_TRAVERSAL_ + if (src) { s = src->ss.sktv4; debugf("mDNSPlatformSendUDP using port %d %d %d", mDNSVal16(src->ss.port), m->p->permanentsockets.sktv4, s); } if (info) // Specify outgoing interface { @@ -1216,9 +1216,9 @@ mDNSlocal ssize_t myrecvfrom(const int s, void *const buffer, const size_t max, mDNSlocal void myKQSocketCallBack(int s1, short filter, void *context) { - const KQSocketSet *const ss = (const KQSocketSet *)context; + KQSocketSet *const ss = (KQSocketSet *)context; mDNS *const m = ss->m; - int err, count = 0; + int err = 0, count = 0, closed = 0; if (filter != EVFILT_READ) LogMsg("myKQSocketCallBack: Why is filter %d not EVFILT_READ (%d)?", filter, EVFILT_READ); @@ -1230,10 +1230,10 @@ mDNSlocal void myKQSocketCallBack(int s1, short filter, void *context) LogMsg("myKQSocketCallBack: sktv6 %d", ss->sktv6); } - while (1) + while (!closed) { mDNSAddr senderAddr, destAddr; - mDNSIPPort senderPort, destPort = (m->SSDPSocket && ss == &m->SSDPSocket->ss ? m->SSDPSocket->port : MulticastDNSPort); + mDNSIPPort senderPort; struct sockaddr_storage from; size_t fromlen = sizeof(from); char packetifname[IF_NAMESIZE] = ""; @@ -1279,7 +1279,17 @@ mDNSlocal void myKQSocketCallBack(int s1, short filter, void *context) // LogMsg("myKQSocketCallBack got packet from %#a to %#a on interface %#a/%s", // &senderAddr, &destAddr, &ss->info->ifinfo.ip, ss->info->ifa_name); - mDNSCoreReceive(m, &m->imsg, (unsigned char*)&m->imsg + err, &senderAddr, senderPort, &destAddr, destPort, InterfaceID); + // mDNSCoreReceive may close the socket we're reading from. We must break out of our + // loop when that happens, or we may try to read from an invalid FD. We do this by + // setting the closeFlag pointer in the socketset, so CloseSocketSet can inform us + // if it closes the socketset. + ss->closeFlag = &closed; + + mDNSCoreReceive(m, &m->imsg, (unsigned char*)&m->imsg + err, &senderAddr, senderPort, &destAddr, ss->port, InterfaceID); + + // if we didn't close, we can safely dereference the socketset, and should to + // reset the closeFlag, since it points to something on the stack + if (!closed) ss->closeFlag = mDNSNULL; } if (err < 0 && (errno != EWOULDBLOCK || count == 0)) @@ -1740,6 +1750,8 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa const int twofivefive = 255; mStatus err = mStatus_NoError; char *errstr = mDNSNULL; + + cp->closeFlag = mDNSNULL; int skt = socket(sa_family, SOCK_DGRAM, IPPROTO_UDP); if (skt < 3) { if (errno != EAFNOSUPPORT) LogMsg("SetupSocket: socket error %d errno %d (%s)", skt, errno, strerror(errno)); return(skt); } @@ -1777,7 +1789,7 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa // And start listening for packets struct sockaddr_in listening_sockaddr; listening_sockaddr.sin_family = AF_INET; - listening_sockaddr.sin_port = port.NotAnInteger; + listening_sockaddr.sin_port = port.NotAnInteger; // Pass in opaque ID without any byte swapping listening_sockaddr.sin_addr.s_addr = 0; // Want to receive multicasts AND unicasts on this socket err = bind(skt, (struct sockaddr *) &listening_sockaddr, sizeof(listening_sockaddr)); if (err) { errstr = "bind"; goto fail; } @@ -1823,7 +1835,7 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa mDNSPlatformMemZero(&listening_sockaddr6, sizeof(listening_sockaddr6)); listening_sockaddr6.sin6_len = sizeof(listening_sockaddr6); listening_sockaddr6.sin6_family = AF_INET6; - listening_sockaddr6.sin6_port = port.NotAnInteger; + listening_sockaddr6.sin6_port = port.NotAnInteger; // Pass in opaque ID without any byte swapping listening_sockaddr6.sin6_flowinfo = 0; listening_sockaddr6.sin6_addr = in6addr_any; // Want to receive multicasts AND unicasts on this socket listening_sockaddr6.sin6_scope_id = 0; @@ -1845,7 +1857,7 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa fail: // For "bind" failures, only write log messages for our shared mDNS port, or for binding to zero if (strcmp(errstr, "bind") || mDNSSameIPPort(port, MulticastDNSPort) || mDNSIPPortIsZero(port)) - LogMsg("%s error %ld errno %d (%s)", errstr, err, errno, strerror(errno)); + LogMsg("%s skt %d port %d error %ld errno %d (%s)", errstr, skt, mDNSVal16(port), err, errno, strerror(errno)); // If we got a "bind" failure with an EADDRINUSE error for our shared mDNS port, display error alert if (!strcmp(errstr, "bind") && mDNSSameIPPort(port, MulticastDNSPort) && errno == EADDRINUSE) @@ -1859,24 +1871,33 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa return(err); } -mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort port) +mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport) { + int i; mStatus err; + mDNSIPPort port = requestedport; UDPSocket *p = mallocL("UDPSocket", sizeof(UDPSocket)); if (!p) { LogMsg("mDNSPlatformUDPSocket: memory exhausted"); return(mDNSNULL); } memset(p, 0, sizeof(UDPSocket)); + p->ss.port = zeroIPPort; p->ss.m = m; p->ss.sktv4 = -1; p->ss.sktv6 = -1; - p->port = zeroIPPort; - err = SetupSocket(&p->ss, port, AF_INET, &p->port); + + for (i=0; i<10000; i++) // Try at most 10000 times to get a unique random port + { + // The kernel doesn't do cryptographically strong random port allocation, so we do it ourselves here + if (mDNSIPPortIsZero(requestedport)) port = mDNSOpaque16fromIntVal(0xC000 + mDNSRandom(0x3FFF)); + err = SetupSocket(&p->ss, port, AF_INET, &p->ss.port); + if (!err) break; + } if (err) { // In customer builds we don't want to log failures with port 5351, because this is a known issue // of failing to bind to this port when Internet Sharing has already bound to it - if (mDNSSameIPPort(port, NATPMPPort)) - LogOperation("mDNSPlatformUDPSocket: SetupSocket %d failed", mDNSVal16(port)); - else LogMsg ("mDNSPlatformUDPSocket: SetupSocket %d failed", mDNSVal16(port)); + if (mDNSSameIPPort(requestedport, NATPMPPort)) + LogOperation("mDNSPlatformUDPSocket: SetupSocket %d failed error %ld errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno)); + else LogMsg ("mDNSPlatformUDPSocket: SetupSocket %d failed error %ld errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno)); freeL("UDPSocket", p); return(mDNSNULL); } @@ -1895,6 +1916,7 @@ mDNSlocal void CloseSocketSet(KQSocketSet *ss) close(ss->sktv6); ss->sktv6 = -1; } + if (ss->closeFlag) *ss->closeFlag = 1; } mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock) @@ -4311,6 +4333,7 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m) mDNSPlatformMemCopy(&m->HISoftware.c[1], HINFO_SWstring, slen); } + m->p->permanentsockets.port = MulticastDNSPort; m->p->permanentsockets.m = m; m->p->permanentsockets.sktv4 = m->p->permanentsockets.sktv6 = -1; m->p->permanentsockets.kqsv4.KQcallback = m->p->permanentsockets.kqsv6.KQcallback = myKQSocketCallBack; diff --git a/mDNSMacOSX/mDNSMacOSX.h b/mDNSMacOSX/mDNSMacOSX.h index a721c11..17fd2b9 100644 --- a/mDNSMacOSX/mDNSMacOSX.h +++ b/mDNSMacOSX/mDNSMacOSX.h @@ -17,6 +17,19 @@ Change History (most recent first): $Log: mDNSMacOSX.h,v $ +Revision 1.79 2008/07/30 00:55:56 mcguire + Should use randomized source ports and transaction IDs to avoid DNS cache poisoning +Additional fixes so that we know when a socket has been closed while in a loop reading from it + +Revision 1.78 2008/07/25 22:34:11 mcguire +fix sizecheck issues for 64bit + +Revision 1.77 2008/07/24 20:23:04 cheshire + Should use randomized source ports and transaction IDs to avoid DNS cache poisoning + +Revision 1.76 2008/07/01 01:40:01 mcguire + 64-bit fixes + Revision 1.75 2007/12/14 00:45:21 cheshire Add SleepLimit and SleepCookie, for when we need to delay sleep until TLS/TCP record deregistration completes @@ -124,13 +137,21 @@ typedef struct typedef struct { + mDNSIPPort port; // MUST BE FIRST FIELD -- UDPSocket_struct begins with a KQSocketSet, + // and mDNSCore requires every UDPSocket_struct to begin with a mDNSIPPort port mDNS *m; int sktv4; KQueueEntry kqsv4; int sktv6; KQueueEntry kqsv6; + int *closeFlag; } KQSocketSet; +struct UDPSocket_struct + { + KQSocketSet ss; // First field of KQSocketSet has to be mDNSIPPort -- mDNSCore requires every UDPSocket_struct to begin with mDNSIPPort port + }; + struct NetworkInterfaceInfoOSX_struct { NetworkInterfaceInfo ifinfo; // MUST be the first element in this structure @@ -222,8 +243,8 @@ struct CompileTimeAssertionChecks_mDNSMacOSX // Check our structures are reasonable sizes. Including overly-large buffers, or embedding // other overly-large structures instead of having a pointer to them, can inadvertently // cause structure sizes (and therefore memory usage) to balloon unreasonably. - char sizecheck_NetworkInterfaceInfoOSX[(sizeof(NetworkInterfaceInfoOSX) <= 4100) ? 1 : -1]; - char sizecheck_mDNS_PlatformSupport [(sizeof(mDNS_PlatformSupport) <= 268) ? 1 : -1]; + char sizecheck_NetworkInterfaceInfoOSX[(sizeof(NetworkInterfaceInfoOSX) <= 4456) ? 1 : -1]; + char sizecheck_mDNS_PlatformSupport [(sizeof(mDNS_PlatformSupport) <= 368) ? 1 : -1]; }; #ifdef __cplusplus diff --git a/mDNSMacOSX/mDNSResponder.sb b/mDNSMacOSX/mDNSResponder.sb index b0307f9..8f8ab2c 100644 --- a/mDNSMacOSX/mDNSResponder.sb +++ b/mDNSMacOSX/mDNSResponder.sb @@ -26,6 +26,10 @@ ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; ; $Log: mDNSResponder.sb,v $ +; Revision 1.25.2.1 2008/07/29 20:48:34 mcguire +; Should use randomized source ports and transaction IDs to avoid DNS cache poisoning +; merge r1.27 from +; ; Revision 1.25 2008/03/17 18:04:41 mcguire ; SC now reads preference file ; @@ -164,15 +168,16 @@ (allow file-read* file-write* (regex "^/private/var/run/mDNSResponder\$")) ; Allow us to read system version, settings, and other miscellaneous necessary file system accesses +(allow file-read-data (regex "^/dev/urandom$")) (allow file-read-data (regex "^/usr/sbin(/mDNSResponder)?\$")) ; Needed for CFCopyVersionDictionary() (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\$")) (allow file-read-data (regex "^/Library/Security/Trust Settings/Admin\.plist\$")) +(allow file-read-data (regex "^/System/Library/CoreServices/SystemVersion.*\$")) (allow file-read-data (regex "^/System/Library/Preferences/com\.apple\.security.*\.plist\$")) (allow file-read-data (regex "^/System/Library/Preferences/com\.apple\.crypto\.plist\$")) diff --git a/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj b/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj index df36500..cb961b8 100644 --- a/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj +++ b/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj @@ -1838,9 +1838,11 @@ "__MigTypeCheck=1", "mDNSResponderVersion=${MVERS}", _LEGACY_NAT_TRAVERSAL_, + "_BUILDING_XCODE_PROJECT_=1", ); GCC_TREAT_WARNINGS_AS_ERRORS = YES; MVERS = "\"(Engineering Build)\""; + OTHER_CFLAGS = "-DUSE_SYSTEMCONFIGURATION_PRIVATE_HEADERS"; PREBINDING = NO; WARNING_CFLAGS = ( "-W", diff --git a/mDNSPosix/mDNSUNP.c b/mDNSPosix/mDNSUNP.c index 2c9f32f..852883d 100755 --- a/mDNSPosix/mDNSUNP.c +++ b/mDNSPosix/mDNSUNP.c @@ -17,6 +17,10 @@ Change History (most recent first): $Log: mDNSUNP.c,v $ +Revision 1.36 2008/04/21 18:21:22 mkrochma + Need to free ifi_netmask +Submitted by Igor Seleznev + Revision 1.35 2007/11/15 21:36:19 cheshire POSIX: Off by one overflow in get_ifi_info_linuxv6() @@ -550,6 +554,8 @@ free_ifi_info(struct ifi_info *ifihead) for (ifi = ifihead; ifi != NULL; ifi = ifinext) { if (ifi->ifi_addr != NULL) free(ifi->ifi_addr); + if (ifi->ifi_netmask != NULL) + free(ifi->ifi_netmask); if (ifi->ifi_brdaddr != NULL) free(ifi->ifi_brdaddr); if (ifi->ifi_dstaddr != NULL) diff --git a/mDNSShared/dns_sd.h b/mDNSShared/dns_sd.h index cc4169b..b5ecbb6 100644 --- a/mDNSShared/dns_sd.h +++ b/mDNSShared/dns_sd.h @@ -77,7 +77,7 @@ */ #ifndef _DNS_SD_H -#define _DNS_SD_H 1710400 +#define _DNS_SD_H 1760200 #ifdef __cplusplus extern "C" {