const mDNSu8 *const limit = response->data + sizeof(response->data);
const mDNSu8 *ptr = query->data;
AuthRecord *rr;
- mDNSu32 maxttl = 0x70000000;
+ mDNSu32 maxttl = mDNSMaximumTTLSeconds;
int i;
// Initialize the response fields so we can answer the questions
mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
};
-mDNSlocal DNSQuestion *ExpectingUnicastResponseForQuestion(const mDNS *const m, const mDNSIPPort port, const mDNSOpaque16 id, const DNSQuestion *const question, mDNSBool tcp)
+mDNSlocal DNSQuestion *ExpectingUnicastResponseForQuestion(const mDNS *const m, const mDNSIPPort port, const mDNSOpaque16 id, const DNSQuestion *const question, mDNSBool tcp, DNSQuestion ** suspiciousQ)
{
DNSQuestion *q;
for (q = m->Questions; q; q=q->next)
{
if (!tcp && !q->LocalSocket) continue;
- if (mDNSSameIPPort(tcp ? q->tcpSrcPort : q->LocalSocket->port, port) &&
- mDNSSameOpaque16(q->TargetQID, id) &&
+ if (mDNSSameIPPort(tcp ? q->tcpSrcPort : q->LocalSocket->port, port) &&
q->qtype == question->qtype &&
q->qclass == question->qclass &&
q->qnamehash == question->qnamehash &&
SameDomainName(&q->qname, &question->qname))
- return(q);
+ {
+ if (mDNSSameOpaque16(q->TargetQID, id)) return(q);
+ else
+ {
+ if (!tcp && suspiciousQ) *suspiciousQ = q;
+ return(mDNSNULL);
+ }
+ }
}
return(mDNSNULL);
}
DNSQuestion pktq;
DNSQuestion *qptr = mDNSNULL;
ptr = getQuestion(response, ptr, end, InterfaceID, &pktq);
- if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &pktq, !dstaddr)) &&
+ if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &pktq, !dstaddr, mDNSNULL)) &&
qptr->ValidatingResponse)
{
DNSQuestion *next, *q;
DNSQuestion q;
DNSQuestion *qptr = mDNSNULL;
ptr = getQuestion(response, ptr, end, InterfaceID, &q);
- if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr)))
+ if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr, mDNSNULL)))
{
CacheRecord *rr, *neg = mDNSNULL;
CacheGroup *cg = CacheGroupForName(m, q.qnamehash, &q.qname);
// packet number, then we deduce they are old and delete them
for (i = 0; i < response->h.numQuestions && ptr && ptr < end; i++)
{
- DNSQuestion q, *qptr = mDNSNULL;
+ DNSQuestion q, *qptr = mDNSNULL, *suspiciousForQ = mDNSNULL;
ptr = getQuestion(response, ptr, end, InterfaceID, &q);
- if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr)))
+ if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr, &suspiciousForQ)))
{
if (!failure)
{
returnEarly = mDNStrue;
}
}
+ else if (!InterfaceID && suspiciousForQ)
+ {
+ // If a response is suspicious for a question, then reissue the question via TCP
+ LogInfo("mDNSCoreReceiveResponse: Server %p responded suspiciously to query %##s (%s) qID %d != rID: %d",
+ suspiciousForQ->qDNSServer, q.qname.c, DNSTypeName(q.qtype),
+ mDNSVal16(suspiciousForQ->TargetQID), mDNSVal16(response->h.id));
+ uDNS_RestartQuestionAsTCP(m, suspiciousForQ, srcaddr, srcport);
+ return;
+ }
}
if (returnEarly)
{
if (msg->h.flags.b[0] & kDNSFlag0_TC && mDNSSameOpaque16(qptr->TargetQID, msg->h.id) && m->timenow - qptr->LastQTime < RESPONSE_WINDOW)
{
if (!srcaddr) LogMsg("uDNS_ReceiveMsg: TCP DNS response had TC bit set: ignoring");
- else
- {
- // Don't reuse TCP connections. We might have failed over to a different DNS server
- // while the first TCP connection is in progress. We need a new TCP connection to the
- // new DNS server. So, always try to establish a new connection.
- if (qptr->tcp) { DisposeTCPConn(qptr->tcp); qptr->tcp = mDNSNULL; }
- qptr->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_Zero, srcaddr, srcport, mDNSNULL, qptr, mDNSNULL);
- }
+ else uDNS_RestartQuestionAsTCP(m, qptr, srcaddr, srcport);
}
}
return mDNSNULL;
}
+mDNSexport void uDNS_RestartQuestionAsTCP(mDNS *m, DNSQuestion *const q, const mDNSAddr *const srcaddr, const mDNSIPPort srcport)
+{
+ // Don't reuse TCP connections. We might have failed over to a different DNS server
+ // while the first TCP connection is in progress. We need a new TCP connection to the
+ // new DNS server. So, always try to establish a new connection.
+ if (q->tcp) { DisposeTCPConn(q->tcp); q->tcp = mDNSNULL; }
+ q->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_Zero, srcaddr, srcport, mDNSNULL, q, mDNSNULL);
+}
+
mDNSlocal void FlushAddressCacheRecords(mDNS *const m)
{
mDNSu32 slot;