Home | History | Annotate | Download | only in mDNSCore

Lines Matching refs:question

163 // Question default timeout values
348 LogMemCorruption("Questions list: Duplicate Question %p should not have LocalSocket set %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
380 // A, AAAA , CNAME, or PTR. The caller should answer the question with this record and not send out
381 // the question on the wire if LocalOnlyRecordAnswersQuestion() also returns true.
403 // Depending on whether this is a multicast or unicast question we want to set either:
642 // Do not follow CNAME if the question asks for CNAME record.
662 // 1. The question is not DNSSEC question, or
663 // 2. The question is DNSSEC question and the CNAME being followed has been validated by DNSSEC.
682 "[Q%d] GenerateNegativeResponse: Generating negative response for question", mDNSVal16(q->TargetQID));
689 // b) Append search domains and retry the question
691 // The question may not have set Intermediates in which case we don't deliver negative responses. So, to force
694 if (m->CurrentQuestion == q) { q->ThisQInterval = 0; } // Deactivate this question
695 // Don't touch the question after this
723 // A and B, and when we stop question A, UpdateQuestionDuplicates copies the value of CNAMEReferrals
725 // the target name is still the same), and then when we stop question B, UpdateQuestionDuplicates
728 // those cases the newly re-appended question A has a different target name and therefore cannot be
729 // a duplicate of any other question ('B') which was itself a duplicate of the previous question A.
743 // The metrics will be transplanted to the restarted question, so zero out the old copy instead of using
790 // Transplant the old socket into the new question, and copy the query ID across too.
873 // Note: All the callers should use the m->CurrentQuestion to see if the question is still valid or not
912 // The callback above could have caused the question to stop. Detect that
953 // our main question list, delivering answers to mDNSInterface_Any questions as appropriate,
1048 // Number of wakeups we send if WakeOnResolve is set in the question
2233 // Note: mDNS_Deregister_internal can call a user callback, which may change the record list and/or question list.
2368 // The AnswerAllLocalQuestionsWithLocalAuthRecord routine walks the question list invoking client callbacks, using the "m->CurrentQuestion"
2369 // mechanism to cope with the client callback modifying the question list while that's happening.
2816 // which may change the record list and/or question list.
3148 // the record list and/or question list.
3737 // If we have an active question, then see if we want to schedule a refresher query for this record.
3795 // BuildQuestion puts a question into a DNS Query packet and if successful, updates the value of queryptr.
3807 debugf("BuildQuestion: No more space in this packet for question %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
3822 SameNameCacheRecordAnswersQuestion(cr, q) && // which answers our question
3836 // If we're trying to put more than one question in this packet, and it doesn't fit
3837 // then undo that last question and try again next time
3841 debugf("BuildQuestion: Retracting question %##s (%s) new forecast total %d, total questions %d",
3858 SameNameCacheRecordAnswersQuestion(cr, q)) // which answers our question
4137 LogMsg("mDNSSendWakeOnResolve: ERROR!! Invalid InterfaceID %p for question %##s", InterfaceID, q->qname.c);
4195 SameNameCacheRecordAnswersQuestion(cr, q) && // which answers our question
4239 // If a probe question is being sent for an AuthRecord and the AuthRecord is associated with a TSR record, then
4273 // 1. The Question Section contains the question
4277 // 1. The Question Section contains queries for the name we intend to use, with QType=ANY because
4331 // Indicate that this question was marked for sending
4460 q->SendQNow = mDNSInterfaceMark; // Mark this question for sending on all interfaces
4469 // m->CurrentQuestion point to the right question
4474 LogInfo("SendQueries question loop 1: Skipping NewQuestion %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
4484 // 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.
4505 // If we have reached the answer threshold for this question,
4523 // Mark this question for sending on all interfaces
4559 // If we recorded a duplicate suppression for this question less than half an interval ago,
4692 debugf("SendQueries: %s question for %##s (%s) at %d forecast total %d",
4708 // If we're suppressing this question, or we successfully put it, update its SendQNow state
4747 // use background traffic class if any included question requires it
4760 // If the message being constructed for the current interface contains at least one non-probe question,
4761 // try to opportunistically include the Discovery Proxy browse's question as well.
4768 DNSQuestion question;
4769 questionPtr = getQuestion(&m->omsg, questionPtr, end, mDNSInterface_Any, &question);
4774 question.qclass &= ~kDNSQClass_UnicastResponse;
4775 if ((question.qtype == DPCBrowse.qtype) && (question.qclass == DPCBrowse.qclass) &&
4776 (question.qnamehash == DPCBrowse.qnamehash) && SameDomainName(&question.qname, &DPCBrowse.qname))
4814 {// Determine if this probe question is already in packet's dns message
4816 DNSQuestion question;
4820 questionptr = getQuestion(&m->omsg, questionptr, limit, mDNSInterface_Any, &question);
4821 if (questionptr && (question.qtype == kDNSQType_ANY) && (question.qclass == qclass) &&
4822 (question.qnamehash == ar->resrec.namehash) && SameDomainName(&question.qname, ar->resrec.name))
4849 // There is not enough space for the probe question and its corresponding records
4856 verbosedebugf("SendQueries: Put Question %##s (%s) probecount %d InterfaceID= %d %d %d",
4887 // Put our known answer list (either new one from this question or questions, or remainder of old one from last time)
4904 // If we ran out of space and we have more than one question in the packet, that's an error --
4905 // we shouldn't have put more than one question if there was a risk of us running out of space.
4990 LogMsg("SendQueries: Should not have more than one question (%d) in a truncated packet", m->omsg.h.numQuestions);
4991 debugf("SendQueries: Sending %d Question%s %d Answer%s %d Update%s on %d (%s)",
5058 for (x = m->NewQuestions; x; x=x->next) if (x == q) break; // Check if this question is a NewQuestion
5062 LogInfo("SendQueries: No active interface %d to send %s question: %d %##s (%s)",
5118 // Whenever a question is answered, reset its state so that we don't query
5119 // the network repeatedly. This happens first time when we answer the question and
5161 // was missed. This can happen if the cache record didn't have an active question during any of the times at which
5162 // refresher queries would have been sent if the cache record did have an active question. The cache record's
5165 // active question from the 80% point of its lifetime up to now, with one exception: if the number of expected remaining
5176 // Note: AnswerCurrentQuestionWithResourceRecord can call a user callback, which may change the record list and/or question list.
5178 // In fact, to enforce this, the routine will *only* answer the question currently pointed to by m->CurrentQuestion,
5179 // which will be auto-advanced (possibly to NULL) if the client callback cancels the question.
5190 // When a cache record is used to answer a question, check if we need to enable sensitive logging for it.
5191 if (DNSQuestionNeedsSensitiveLogging(q)) // If the question enables sensitive logging.
5197 // Since this cache record is used to answer a question that enables sensitive logging, it will be
5208 else // q->logPrivacyLevel == dnssd_log_privacy_level_default // If the question does not enable sensitive logging.
5210 // If this cache record is used to answer a question that does not enable sensitive logging, it will be printed
5226 LogInfo("AnswerCurrentQuestionWithResourceRecord: Question %p %##s (%s) not answering with record %s due to "
5255 // For now, do not use optimistic DNS for DNSSEC response and DNSSEC question.
5341 // If DNS64StateMachine() returns true, then the question was restarted as a different question, so return.
5349 if (PerformNextPunycodeConversion(q, &newname)) // Itertative Punycode conversion succeeded, so reissue question with new name
5370 // for the purpose of retrying search domains/timeout OR the question is suppressed
5379 // positive record that answers the question coming. The add event of the positive record will
5382 // However, if the question is the primary DNSSEC requestor that will validate the records with DNSSEC,
5396 // If the question does not want the intermediate result (for example, NXDomain or NoSuchRecord)
5489 // don't follow them. If it is a ValidationRequired question, wait for the CNAME to be validated
5553 // the end of the question list, and m->NewQuestions will be set to indicate the first new question.
5557 // which may change the record list and/or question list.
5569 // If this question is one that's actively sending queries, and it's received ten answers within one
5588 verbosedebugf("CacheRecordAdd %p %##s (%s) %lu %#a:%d question %p", cr, cr->resrec.name->c,
5632 // the end of the question list, and m->NewQuestions will be set to indicate the first new question.
5634 // but we don't have any place to cache it. We'll deliver question 'add' events now, but we won't have any
5638 // which may change the record list and/or question list.
5660 // Note that CacheRecordRmv is *only* called for records that are referenced by at least one active question.
5662 // the end of the question list, and m->NewQuestions will be set to indicate the first new question.
5666 // which may change the record list and/or question list.
5680 // When a question enters suppressed state, we generate RMV events and generate a negative
5681 // response. A cache may be present that answers this question e.g., cache entry generated
5682 // before the question became suppressed. We need to skip the suppressed questions here as
5705 // If we have dropped below the answer threshold for this mDNS question,
5882 // before we pick a new DNS server. As the question interval is set to MaxQuestionInterval, we may
5883 // not send out a query anytime soon. Hence, we need to reset the question interval. If this is
5938 else // else trigger our question to go out now
5967 // If "CheckOnly" is set to "true", the question won't be answered but just check to see if there is an answer and
5970 // If "CheckOnly" is set to "false", the question will be answered if there is a LocalOnly/P2P record and
5989 // If the question is mDNSInterface_LocalOnly, all records local to the machine should be used
6001 LogInfo("AnswerQuestionWithLORecord: question %##s (%s) answered by %s", q->qname.c, DNSTypeName(q->qtype),
6016 LogInfo("AnswerQuestionWithLORecord: Question deleted while while answering LocalOnly record answers");
6022 LogInfo("AnswerQuestionWithLORecord: Question %p %##s (%s) answered using local auth records LOAddressAnswers %d",
6028 // no local records that could possibly answer this question. As we did not check the NewLocalRecords, we
6029 // need to just peek at them to see whether it will answer this question. If it would answer, pretend
6031 // when we add new /etc/hosts entries and restart the question. It is a new question and also a new record.
6039 LogInfo("AnswerQuestionWithLORecord: Question %p %##s (%s) will be answered using new local auth records "
6069 DNSQuestion *const q = m->NewQuestions; // Grab the question we're going to answer
6078 if (m->NewQuestions != q) { LogInfo("AnswerNewQuestion: Question deleted while doing CheckCacheExpiration"); goto exit; }
6081 // then CheckCacheExpiration may give this question add/remove callbacks, and it's not yet ready for that.
6084 // client callbacks, which may delete their own or any other question. Our mechanism for detecting
6085 // whether our current m->NewQuestions question got deleted by one of these callbacks is to store the
6088 // advanced it), that means the question was deleted, so we no longer need to worry about answering
6090 // values we computed for slot and cg are now stale and relate to a question that no longer exists).
6095 // deleting a question, so luckily we have an easy alternative way of detecting if our question got deleted.
6098 // This should be safe, because calling the client's question callback may cause the
6099 // question list to be modified, but should not ever cause the rrcache list to be modified.
6100 // If the client's question callback deletes the question, then m->CurrentQuestion will
6109 m->CurrentQuestion = q; // Indicate which question we're answering, so we'll know if it gets deleted
6112 LogInfo("AnswerNewQuestion: Question deleted while generating NoAnswer_Fail response");
6216 "[Q%u] Continue sending out query for the primary DNSSEC question
6245 // We don't use LogInfo for this "Question deleted" message because it happens so routinely that
6247 if (m->CurrentQuestion != q) { debugf("AnswerNewQuestion: Question deleted while giving cache answers"); goto exit; }
6254 // Note: When a query gets suppressed or retried with search domains, we de-activate the question.
6286 // answers for this question until *after* its scheduled transmission time, in which case
6301 DNSQuestion *q = m->NewLocalOnlyQuestions; // Grab the question we're going to answer
6310 m->CurrentQuestion = q; // Indicate which question we're answering, so we'll know if it gets deleted
6315 // 1. First walk the LocalOnly records answering the LocalOnly question
6626 LogInfo("TimeoutQuestions: question %p %##s timed out, time %d", q, q->qname.c, m->timenow - q->StopTime);
6627 q->LOAddressAnswers = 0; // unset since timing out the question
6639 // depends on having m->CurrentQuestion point to the right question
7060 LogInfo("QuestionHasLocalAnswers: Question %p %##s (%s) has local answer %s", q, q->qname.c, DNSTypeName(q->qtype), ARDisplayString(m, rr));
7068 // 1. When a new question is created
7072 // In cases 2 and 3 we do want to cause the question to be resent immediately (ScheduleImmediately is true)
7073 mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question, mDNSBool ScheduleImmediately)
7075 if (!question->DuplicateOf)
7078 question->qname.c, DNSTypeName(question->qtype), ScheduleImmediately ? " ScheduleImmediately" : "");
7079 question->CNAMEReferrals = 0;
7080 if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; }
7081 if (question->LongLived)
7083 question->state = LLQ_Init;
7084 question->id = zeroOpaque64;
7085 question->servPort = zeroIPPort;
7086 if (question->tcp) { DisposeTCPConn(question->tcp); question->tcp = mDNSNULL; }
7088 // If the question has local answers, then we don't want answers from outside
7089 if (ScheduleImmediately && !QuestionHasLocalAnswers(m, question))
7091 question->ThisQInterval = InitialQuestionInterval;
7092 question->LastQTime = m->timenow - question->ThisQInterval;
7093 SetNextQueryTime(m, question);
7111 // we are going to stop the question. Hence we need to deliver the RMV event before we
7112 // stop the question.
7115 // application callback can potentially stop the current question (detected by CurrentQuestion) or
7116 // *any* other question which could be the next one that we may process here. RestartQuestion
7117 // points to the "next" question which will be automatically advanced in mDNS_StopQuery_internal
7118 // if the "next" question is stopped while the CurrentQuestion is stopped
7130 // question) through their "nta" pointer. Normally when the original query stops, it stops the
7131 // GetZoneData question and also frees the memory (See CancelGetZoneData). If we stop the GetZoneData
7132 // question followed by the original query that refers to this GetZoneData question, we will end up
7133 // freeing the GetZoneData question and then start the "freed" question at the end.
7139 // debug stuff, we just try to find the referencing question and don't do much with it
7142 if (q == &refq->nta->question)
7144 LogInfo("mDNSCoreRestartAddressQueries: Question %p %##s (%s) referring to GetZoneDataQuestion %p, not stopping", refq, refq->qname.c, DNSTypeName(refq->qtype), q);
7169 if (!CacheRecordRmvEventsForQuestion(m, q)) { LogInfo("mDNSCoreRestartAddressQueries: Question deleted while delivering Cache Record RMV events"); continue; }
7172 if (!LocalRecordRmvEventsForQuestion(m, q)) { LogInfo("mDNSCoreRestartAddressQueries: Question deleted while delivering Local Record RMV events"); continue; }
7174 LogInfo("mDNSCoreRestartAddressQueries: Stop question %p %##s (%s), AppendSearchDomains %d", q,
7192 LogInfo("mDNSCoreRestartAddressQueries: Start question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
7226 // restart question if it's multicast and currently active
7231 q->ThisQInterval = InitialQuestionInterval; // MUST be > zero for an active question
7823 mDNSlocal void NetWakeResolve(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
7825 NetworkInterfaceInfo *intf = (NetworkInterfaceInfo *)question->QuestionContext;
7826 int sps = (int)(question - intf->NetWakeResolve);
7831 if (answer->rrtype != question->qtype) return; // Don't care about CNAMEs
7838 mDNS_StopQuery(m, question);
7840 AssignDomainName(&question->qname, &answer->rdata->u.srv.target);
7841 question->qtype = kDNSType_A;
7842 mDNS_StartQuery(m, question);
7847 mDNS_StopQuery(m, question);
7848 question->ThisQInterval = -1;
7858 mDNS_StopQuery(m, question);
7859 LogSPS("NetWakeResolve: SPS %d %##s has no IPv4 address, will try IPv6 instead", sps, question->qname.c);
7860 question->qtype = kDNSType_AAAA;
7861 mDNS_StartQuery(m, question);
7866 mDNS_StopQuery(m, question);
7867 question->ThisQInterval = -1;
8535 for (i=0; i<query->h.numQuestions; i++) // For each question...
8538 ptr = getQuestion(query, ptr, end, InterfaceID, &q); // get the question...
8543 if (rr->NR_AnswerTo == ptr) // If we're going to generate a record answering this question
8544 { // then put the question in the question section
8547 break; // break out of the ResponseRecords loop, and go on to the next question
8747 // the record list and/or question list.
9139 // *** 2. Parse Question Section and mark potential answers
9142 for (i=0; i<query->h.numQuestions; i++) // For each question...
9148 ptr = getQuestion(query, ptr, end, InterfaceID, &pktq); // get the question...
9171 // can result in user callbacks which may change the record list and/or question list.
9221 // We only mark this question for sending if it is at least one second since the last time we multicast it
9233 // If we don't have any answers for this question, but we do own another record with the same name,
9247 // If we couldn't answer this question, someone else might be able to,
9253 // We only do the following accelerated cache expiration and duplicate question suppression processing
9282 // Check if this question is the same as any of mine.
9619 "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes (%s)",
9629 "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes",
9648 debugf("Unicast Response: %d Question%s, %d Answer%s, %d Additional%s to %#-15a:%d on %p/%ld",
9675 const mDNSOpaque16 id, const DNSQuestion *const question, mDNSBool tcp)
9682 q->qtype == question->qtype &&
9683 q->qclass == question->qclass &&
9684 q->qnamehash == question->qnamehash &&
9685 SameDomainName(&q->qname, &question->qname))
10065 // When the response does not match the question directly, we still want to cache them sometimes. The current response is
10077 // match the question and we already created a cache entry in the previous pass of this loop. Now when we process
10078 // the A record, it does not match the question because the record name here is the CNAME. Hence we try to
10166 // The CNAME chain always starts with the original question name.
10485 // The CNAME chain always starts from the original question name.
10492 // When we use querier, it is possible we receive a response whose question has already gone, in which case
10508 // If we need to process denial of existence record for DNSSEC-enabled question, get the CNAME chain from
10516 // If the question has required DNSSEC RRs, iterate through all the CNAMEs in the chain.
10519 // 1. If the question is a normal non-DNSSEC question, currentQNameInCNameChain will be set to the original
10520 // question name. It will be set to mDNSNULL after the first iteration.
10521 // 2. If the question is a DNSSEC question, currentQNameInCNameChain will be set to the original question
10522 // name as well, and the question name is the start of a CNAME chain. It will be set to the next name
10528 // The following code checks if the newly added or existing records in the cache that answer the question is
10530 // question name.
10556 // We only care about the non-negative record that answers our question positively.
10647 // If the matched question is a wildcard match (by looking into the labels field of RRSIG)
10648 // then we need a new or existing negative record to deny the original question name.
10674 // By suppressing negative responses, it might take longer to timeout a .local question as it might be expecting a
10801 // Only parse the SOA, NSEC/NSEC3, RRSIG out if the question requires DNSSEC RRs and we have not
10818 // If the question requires DNSSEC RRs, and we found an existing negative record that denies the
10819 // question (which means the negative record is DNSSEC-aware), check to see if we need to make it
10866 // the question callback needs to be notified about this change, therefore, we mark it
10902 // When we created the cache for the first time and answered the question, the question's
10906 // we should reset its question interval here to MaxQuestionInterval.
11010 // 2. If we do not know if the question requires DNSSEC RRs.
11011 // 3. If the question does not require DNSSEC RRs. (No one will use the denial object)
11036 // positive record for the question, we can be sure that it is not a wildcard data response.
11073 // However, if the question has required DNSSEC RRs, we need to traverse the CNAME chain to create the
11273 // record in the list that answers the question so that it can be used for validation
11275 // that would answer the question. It is possible that we might cache additional things
11276 // e.g., MX question might cache A records also, and we want to cache the NSEC on
11277 // the record that answers the question.
11292 // We have to reset the question interval to MaxQuestionInterval so that we don't keep
11296 // configuration changed, without flushing the cache, we reset the question interval here.
11492 // the record list and/or question list.
11520 mDNSBool recordAcceptedInResponse = mDNSfalse; // Set if a record is accepted from a unicast mDNS response that answers an existing question.
11550 "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes LLQType %d",
11667 // mDNSCoreReceiveResponse() needs to create negative cache entries for the unanwered question, so totalrecords
11679 // answer questions in this packet's question section, but which aren't tagged with this packet's
11839 // answers an active question.
11846 // to any specific question -- any code reading records from the cache needs to make that determination for itself.)
11957 // queries to get ADD/RMV events. To lookup the question, we can't use
11959 // has already matched the question using the 64 bit Id in the packet and we use that here.
11993 // on the "id" and "source port", then this response answers the question and assume the response
12016 // If we can't find a matching question, we need to see whether we have seen records earlier that matched
12017 // the question. The code below does that. So, make this record unacceptable for now
12020 debugf("mDNSCoreReceiveResponse: Can't find question for record name %##s", m->rec.r.resrec.name->c);
13312 "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes",
13752 // is suppressed. If it is not suppressed, we do try all the DNS servers for valid answers like any other question.
13753 // The main reason for this design is that cache entries point to a *single* question and that question is responsible
13754 // for keeping the cache fresh as long as it is active. Having multiple active question for a single cache entry
13758 // If IsLLQ(Q) is true, it means the question is both:
13766 mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuestion *const question)
13770 const mDNSBool questionSendsUnicastMDNSQueries = QuestionSendsMDNSQueriesViaUnicast(question);
13772 // Note: A question can only be marked as a duplicate of one that occurs *earlier* in the list.
13774 // Accordingly, we break out of the loop when we get to 'question', because there's no point searching
13776 for (q = m->Questions; q && (q != question); q = q->next)
13778 if (!SameQuestionKind(q, question)) continue;
13779 if (q->qnamehash != question->qnamehash) continue;
13780 if (q->InterfaceID != question->InterfaceID) continue;
13781 if (q->qtype != question->qtype) continue;
13782 if (q->qclass != question->qclass) continue;
13783 if (IsLLQ(q) != IsLLQ(question)) continue;
13784 if (q->AuthInfo && !question->AuthInfo) continue;
13785 if (!q->Suppressed != !question->Suppressed) continue;
13786 if (q->BrowseThreshold != question->BrowseThreshold) continue;
13787 if (AWDLIsIncluded(q) != AWDLIsIncluded(question)) continue;
13789 if (q->dnsservice != question->dnsservice) continue;
13792 // DNSSEC-disabled question cannot be duped to DNSSEC-enabled question, vice versa.
13793 if (!q->enableDNSSEC != !question->enableDNSSEC) continue;
13794 // If enables DNSSEC, the question being duped to must be a primary DNSSEC requestor.
13797 if (!SameDomainName(&q->qname, &question->qname)) continue;
13801 // If question sends mDNS queries via unicast, then q must also send mDNS queries via
13803 const mDNSAddr *const addr1 = &question->UnicastMDNSResolver;
13816 // Only the DNS push enabled question can be dupped to a DNS push enabled question.
13817 if (dns_question_uses_dns_push(q) != dns_question_uses_dns_push(question))
13828 // This is called after a question is deleted, in case other identical questions were being suppressed as duplicates
13829 mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const question)
13834 // This is referring to some other question as duplicate. No other question can refer to this
13835 // question as a duplicate.
13836 if (question->DuplicateOf)
13838 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "[R%d->DupQ%d->Q%d] UpdateQuestionDuplicates: question %p " PRI_DM_NAME " (" PUB_S
13840 question->request_id, mDNSVal16(question->TargetQID), mDNSVal16(question->DuplicateOf->TargetQID),
13841 question, DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype), question->DuplicateOf,
13842 DM_NAME_PARAM(&question->DuplicateOf->qname), DNSTypeName(question->DuplicateOf->qtype));
13847 if (q->DuplicateOf == question) // To see if any questions were referencing this as their duplicate
13854 // then inherit the state from the question that's going away
13855 q->LastQTime = question->LastQTime;
13856 q->ThisQInterval = question->ThisQInterval;
13857 q->ExpectUnicastResp = question->ExpectUnicastResp;
13858 q->LastAnswerPktNum = question->LastAnswerPktNum;
13859 q->RecentAnswerPkts = question->RecentAnswerPkts;
13860 q->RequestUnicast = question->RequestUnicast;
13861 q->LastQTxTime = question->LastQTxTime;
13862 q->CNAMEReferrals = question->CNAMEReferrals;
13863 q->nta = question->nta;
13864 q->servAddr = question->servAddr;
13865 q->servPort = question->servPort;
13867 mdns_replace(&q->dnsservice, question->dnsservice);
13868 mdns_forget(&question->dnsservice);
13870 mdns_replace(&q->client, question->client);
13871 mdns_forget(&question->client);
13873 q->qDNSServer = question->qDNSServer;
13874 q->validDNSServers = question->validDNSServers;
13875 q->unansweredQueries = question->unansweredQueries;
13876 q->noServerResponse = question->noServerResponse;
13877 q->triedAllServersOnce = question->triedAllServersOnce;
13881 // handoff from the former lead question to the new lead is sufficient.
13882 q->DPSubscribers = question->DPSubscribers;
13883 question->DPSubscribers = mDNSNULL;
13887 // If this question is a primary DNSSEC question that does the validation work, transfer the work to
13888 // its duplicate question, by making the duplicate question the primary one.
13889 if (dns_question_is_primary_dnssec_requestor(question))
13891 LogRedact(MDNS_LOG_CATEGORY_DNSSEC, MDNS_LOG_INFO, "[Q%u->Q%u] Non-primary DNSSEC question becomes primary due to primary question cancelation.",
13892 mDNSVal16(q->TargetQID), mDNSVal16(question->TargetQID));
13894 dns_question_update_primary_dnssec_requestor(q, question);
13898 q->TargetQID = question->TargetQID;
13900 q->LocalSocket = question->LocalSocket;
13904 q->state = question->state;
13905 // q->tcp = question->tcp;
13906 q->ReqLease = question->ReqLease;
13907 q->expire = question->expire;
13908 q->ntries = question->ntries;
13909 q->id = question->id;
13912 DNSPushUpdateQuestionDuplicate(question, q);
13916 question->LocalSocket = mDNSNULL;
13918 question->nta = mDNSNULL; // If we've got a GetZoneData in progress, transfer it to the newly active question
13919 // question->tcp = mDNSNULL;
13927 // If the question being stopped collects mDNS metric, the new primary should take it.
13928 if (DNSQuestionCollectsMDNSMetric(question))
13930 first->metrics = question->metrics;
13941 if (question->tcp) LogInfo("UpdateQuestionDuplicates did not transfer tcp pointer");
13943 if (question->state == LLQ_Established)
13947 question->state = LLQ_Invalid; // Must zero question->state, or mDNS_StopQuery_internal will clean up and cancel our LLQ from the server
14055 mDNSlocal mDNSu32 GetTimeoutForMcastQuestion(mDNS *m, DNSQuestion *question)
14058 int bestmatchlen = -1, namecount = CountLabels(&question->qname);
14064 bettermatch = BetterMatchForName(&question->qname, namecount, &curr->domain, currcount, bestmatchlen);
14073 LogInfo("GetTimeoutForMcastQuestion: question %##s curmatch %p, Timeout %d", question->qname.c, curmatch,
14088 if (CountLabels(qname) < 4) { debugf("DomainEnumQuery: question %##s, not enough labels", qname->c); return mDNSfalse; }
14122 debugf("DomainEnumQuery: Question %##s is a Domain Enumeration query", qname->c);
14128 // Note: InterfaceID is the InterfaceID of the question
14140 // The first condition in the "if" statement checks to see if both the question and the DNSServer are
14141 // unscoped. The question is unscoped only if InterfaceID is zero and ServiceID is -1.
14150 // unscoped question should not match scoped DNSServer (Refer to (1) above). The InterfaceID check
14153 // - DNSServer is scoped and InterfaceID is not NULL - the InterfaceID of the question and the DNSServer
14165 // Sets all the Valid DNS servers for a question
14166 mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question)
14168 int bestmatchlen = -1, namecount = CountLabels(&question->qname);
14175 question->validDNSServers = zeroOpaque128;
14176 DEQuery = DomainEnumQuery(&question->qname);
14205 if ((!DEQuery || !curr->isCell) && DNSServerMatch(curr, question->InterfaceID, question->ServiceID))
14207 bettermatch = BetterMatchForName(&question->qname, namecount, &curr->domain, currcount, bestmatchlen);
14219 question->validDNSServers = zeroOpaque128;
14222 debugf("SetValidDNSServers: question %##s Setting the bit for DNS server Address %#a (Domain %##s), Scoped:%d index %d,"
14223 " Timeout %d, interface %p", question->qname.c, &curr->addr, curr->domain.c, curr->scopeType, index, curr->timeout,
14227 debugf("DomainEnumQuery: Question %##s, DNSServer %#a, cell %d", question->qname.c, &curr->addr, curr->isCell);
14228 bit_set_opaque128(question->validDNSServers, index);
14233 question->noServerResponse = 0;
14235 debugf("SetValidDNSServers: ValidDNSServer bits 0x%08x%08x%08x%08x for question %p %##s (%s)",
14236 question->validDNSServers.l[3], question->validDNSServers.l[2], question->validDNSServers.l[1], question->validDNSServers.l[0], question, question->qname.c, DNSTypeName(question->qtype));
14279 // If there are multiple best servers for a given question, we will pick the first one
14290 // This happens when we initially walk all the DNS servers and set the validity bit on the question.
14344 // Look up a DNS Server for a question within its valid DNSServer bits
14345 mDNSexport DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question)
14349 mDNSInterfaceID InterfaceID = question->InterfaceID;
14350 const domainname *name = &question->qname;
14359 if (!mDNSOpaque128IsZero(&question->validDNSServers))
14361 curmatch = GetBestServer(m, name, InterfaceID, question->ServiceID, question->validDNSServers, &currindex, mDNSfalse);
14363 bit_clr_opaque128(question->validDNSServers, currindex);
14370 question->request_id, mDNSVal16(question->TargetQID), question, curmatch, &curmatch->addr,
14372 ifname ? ifname : "None", InterfaceID, question->ServiceID, DM_NAME_PARAM(name),
14373 DNSTypeName(question->qtype));
14378 PRI_DM_NAME " (" PUB_S ")", question->request_id, mDNSVal16(question->TargetQID), question,
14379 ifname ? ifname : "None", InterfaceID, question->ServiceID, DM_NAME_PARAM(name),
14380 DNSTypeName(question->qtype));
14558 // Don't deliver RMV events for negative records if the question has not required DNSSEC RRs.
14566 "[Q%u] CacheRecordRmvEventsForCurrentQuestion: Suppressing RMV events for question - "
14567 "rr name: " PRI_DM_NAME ", rr type: " PUB_DNS_TYPE ", current active question: Q%u, current answers: %u", mDNSVal16(q->TargetQID),
14577 "[Q%u] CacheRecordRmvEventsForCurrentQuestion: Calling AnswerCurrentQuestionWithResourceRecord (RMV) for question - "
14590 mDNSlocal mDNSBool IsQuestionInList(const DNSQuestion *const list, const DNSQuestion *const question)
14594 if (q == question)
14602 mDNSlocal mDNSBool IsQuestionNew(const mDNS *const m, const DNSQuestion *const question)
14604 return IsQuestionInList(m->NewQuestions, question);
14622 LogInfo("LocalRecordRmvEventsForQuestion: New Question %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
14650 // Returns false if the question got deleted while delivering the RMV events
14658 // If it is a new question, we have not delivered any ADD events yet. So, don't deliver RMV events.
14659 // If this question was answered using local auth records, then you can't deliver RMVs using cache
14667 else { LogInfo("CacheRecordRmvEventsForQuestion: Question %p %##s (%s) is a new question", q, q->qname.c, DNSTypeName(q->qtype)); }
14681 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u] SuppressStatusChanged: Question deleted while delivering RMV events from cache",
14690 // question below, we need to deliver the RMV events so that the ADDs that will be delivered during
14695 "[R%u->Q%u] SuppressStatusChanged: Question deleted while delivering RMV events from Local AuthRecords",
14702 // 1. Previously it was suppressed and now it is not suppressed, restart the question so
14703 // that it will start as a new question. Note that we can't just call ActivateUnicastQuery
14705 // this question if the cache entry did not change. Hence, we need to restart
14709 // so that we redo the duplicate checks in mDNS_StartQuery_internal. A SuppressUnusable question
14710 // is a duplicate of non-SuppressUnusable question if it is not suppressed (Suppressed is false).
14711 // A SuppressUnusable question is not a duplicate of non-SuppressUnusable question if it is suppressed
14712 // (Suppressed is true). The reason for this is that when a question is suppressed, we want an
14713 // immediate response and not want to be blocked behind a question that is querying DNS servers. When
14714 // the question is not suppressed, we don't want two active questions sending packets on the wire.
14715 // This affects both efficiency and also the current design where there is only one active question
14720 // If there are duplicate questions, calling stop inherits the values from another question on the list (which
14721 // will soon become the real question) including q->ThisQInterval which might be zero if it was
14727 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u] SuppressStatusChanged: Stop question %p " PRI_DM_NAME " (" PUB_S ")",
14756 // application callback can potentially stop the current question (detected by CurrentQuestion) or
14757 // *any* other question which could be the next one that we may process here. RestartQuestion
14758 // points to the "next" question which will be automatically advanced in mDNS_StopQuery_internal
14759 // if the "next" question is stopped while the CurrentQuestion is stopped
14776 // AnswerCurrentQuestionWithResourceRecord can answer the question
14786 LogInfo("CheckSuppressUnusableQuestions: Start question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
14808 LogMsg("RestartUnicastQuestions: ERROR!! Restart set for multicast question %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
14818 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->Q%u] RestartUnicastQuestions: Start question %p " PRI_DM_NAME " (" PUB_S ")",
14826 // DNS Question that are already set by the client before calling mDNS_StartQuery()
14827 mDNSlocal mStatus ValidateParameters(mDNS *const m, DNSQuestion *const question)
14829 if (!ValidateDomainName(&question->qname))
14831 LogMsg("ValidateParameters: Attempt to start query with invalid qname %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
14835 // If this question is referencing a specific interface, verify it exists
14836 if (question->InterfaceID && !LocalOnlyOrP2PInterface(question->InterfaceID))
14838 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, question->InterfaceID);
14840 question %##s (%s) not currently found in active interface list",
14841 IIDPrintable(question->InterfaceID), question->qname.c, DNSTypeName(question->qtype));
14847 // InitDNSConfig() is called by InitCommonState() to initialize the DNS configuration of the Question.
14849 mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question)
14853 mdns_forget(&question->dnsservice);
14854 question->NeedUpdatedQuerier = mDNSfalse;
14856 question->qDNSServer = mDNSNULL;
14857 question->validDNSServers = zeroOpaque128;
14858 question->triedAllServersOnce = mDNSfalse;
14859 question->noServerResponse = mDNSfalse;
14861 question->StopTime = (question->TimeoutQuestion) ? question->StopTime : 0;
14863 mDNSPlatformMemZero(&question->metrics, sizeof(question->metrics));
14867 if (LocalOnlyOrP2PInterface(question->InterfaceID) && !question->TimeoutQuestion)
14870 if (!mDNSOpaque16IsZero(question->TargetQID))
14875 mDNSu32 timeout = SetValidDNSServers(m, question);
14877 // We set the timeout value the first time mDNS_StartQuery_internal is called for a question.
14878 // So if a question is restarted when a network change occurs, the StopTime is not reset.
14880 // it gets a full timeout value even if the original question times out earlier.
14881 if (question->TimeoutQuestion && !question->StopTime)
14883 question->StopTime = NonZeroTime(m->timenow + timeout * mDNSPlatformOneSecond);
14885 "[Q%u] InitDNSConfig: Setting StopTime on the uDNS question %p " PRI_DM_NAME " (" PUB_S ")",
14886 mDNSVal16(question->TargetQID), question, DM_NAME_PARAM(&question->qname),
14887 DNSTypeName(question->qtype));
14891 Querier_SetDNSServiceForQuestion(question);
14893 question->qDNSServer = GetServerForQuestion(m, question);
14894 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEBUG, "[R%u->Q%u] InitDNSConfig: question %p " PRI_DM_NAME " " PUB_S " Timeout %d, DNS Server "
14896 question->request_id, mDNSVal16(question->TargetQID), question, DM_NAME_PARAM(&question->qname),
14897 DNSTypeName(question->qtype), timeout, question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL,
14898 mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort));
14901 else if (question->TimeoutQuestion && !question->StopTime)
14903 // If the question is to be timed out and its a multicast, local-only or P2P case,
14905 mDNSu32 timeout = LocalOnlyOrP2PInterface(question->InterfaceID) ?
14906 DEFAULT_LO_OR_P2P_TIMEOUT : GetTimeoutForMcastQuestion(m, question);
14907 question->StopTime = NonZeroTime(m->timenow + timeout * mDNSPlatformOneSecond);
14909 "[R%u->Q%u] InitDNSConfig: Setting StopTime on the uDNS question %p " PRI_DM_NAME " (" PUB_S ")",
14910 question->request_id, mDNSVal16(question->TargetQID), question, DM_NAME_PARAM(&question->qname),
14911 DNSTypeName(question->qtype));
14914 if (question->StopTime)
14915 SetNextQueryStopTime(m, question);
14916 // Don't call SetNextQueryTime() if a LocalOnly OR P2P Question since those questions
14918 if (!(LocalOnlyOrP2PInterface(question->InterfaceID)))
14919 SetNextQueryTime(m,question);
14923 // state fields of the DNS Question. These are independent of the Client layer.
14924 mDNSlocal void InitCommonState(mDNS *const m, DNSQuestion *const question)
14926 // Note: In the case where we already have the answer to this question in our cache, that may be all the client
14927 // wanted, and they may immediately cancel their question. In this case, sending an actual query on the wire would
14931 question->next = mDNSNULL;
14934 // the question list to check if ThisQInterval is negative which means the question has been
14935 // stopped and can't be on the list. The question is already on the list and ThisQInterval
14939 question->ThisQInterval = InitialQuestionInterval; // MUST be > zero for an active question
14940 question->qnamehash = DomainNameHashValue(&question->qname);
14942 if (mDNSOpaque16IsZero(question->TargetQID))
14944 delay = CheckForSoonToExpireRecordsEx(m, &question->qname, question->qnamehash, question->qtype, question->qclass);
14946 question->DelayAnswering = delay;
14947 question->LastQTime = m->timenow;
14948 question->ExpectUnicastResp = 0;
14949 question->LastAnswerPktNum = m->PktNum;
14950 question->RecentAnswerPkts = 0;
14951 question->CurrentAnswers = 0;
14953 question->BrowseThreshold = 0;
14954 question->CachedAnswerNeedsUpdate = mDNSfalse;
14956 question->LargeAnswers = 0;
14957 question->UniqueAnswers = 0;
14958 question->LOAddressAnswers = 0;
14959 question->FlappingInterface1 = mDNSNULL;
14960 question->FlappingInterface2 = mDNSNULL;
14964 question->BlockedByPolicy = mDNSfalse;
14967 // since we would already have the question->ServiceID in that case.
14968 if (!(question->flags & kDNSServiceFlagsServiceIndex))
14970 question->ServiceID = -1;
14973 LogInfo("InitCommonState: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] is already set by client", question->qname.c,
14974 DNSTypeName(question->qtype), question->pid, question->euid, question->ServiceID);
14976 InitDNSConfig(m, question);
14977 question->AuthInfo = GetAuthInfoForQuestion(m, question);
14978 const mDNSSuppression suppress = DetermineSuppression(question);
14979 question->Suppressed = (suppress != mDNSSuppression_None);
14980 question->ForceCNAMEFollows = question->PersistWhenRecordsUnusable && (suppress == mDNSSuppression_RecordsUnusable);
14981 question->NextInDQList = mDNSNULL;
14982 question->SendQNow = mDNSNULL;
14983 question->SendOnAll = mDNSfalse;
14984 question->RequestUnicast = kDefaultRequestUnicastCount;
14987 question->LastQTxTime = m->timenow;
14988 question->CNAMEReferrals = 0;
14990 question->WakeOnResolveCount = 0;
14991 if (question->WakeOnResolve)
14993 question->WakeOnResolveCount = InitialWakeOnResolveCount;
14996 question->Restart = mDNSfalse;
15000 question->dnssec = mDNSNULL;
15003 debugf("InitCommonState: Question %##s (%s) Interface %p Now %d Send in %d Answer in %d (%p) %s (%p)",
15004 question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, m->timenow,
15005 NextQSendTime(question) - m->timenow,
15006 question->DelayAnswering ? question->DelayAnswering - m->timenow : 0,
15007 question, question->DuplicateOf ? "duplicate of" : "not duplicate", question->DuplicateOf);
15009 if (question->DelayAnswering)
15011 question->DelayAnswering - m->timenow, question->qname.c, DNSTypeName(question->qtype));
15015 mDNSlocal void InitWABState(DNSQuestion *const question)
15017 // We'll create our question->LocalSocket on demand, if needed.
15021 question->LocalSocket = mDNSNULL;
15023 mdns_client_forget(&question->client);
15025 question->unansweredQueries = 0;
15027 question->nta = mDNSNULL;
15028 question->servAddr = zeroAddr;
15029 question->servPort = zeroIPPort;
15030 question->tcp = mDNSNULL;
15049 mDNSlocal void InitLLQState(DNSQuestion *const question)
15051 question->state = LLQ_Init;
15052 question->ReqLease = 0;
15053 question->expire = 0;
15054 question->ntries = 0;
15055 question->id = zeroOpaque64;
15059 // DNSSEC & DNS Proxy fields of the DNS Question.
15060 mDNSlocal void InitDNSSECProxyState(mDNS *const m, DNSQuestion *const question)
15063 question->responseFlags = zeroID;
15066 // Once the question is completely initialized including the duplicate logic, this function
15067 // is called to finalize the unicast question which requires flushing the cache if needed,
15069 mDNSlocal void FinalizeUnicastQuestion(mDNS *const m, DNSQuestion *question)
15071 // Ensure DNS related info of duplicate question is same as the orig question
15072 if (question->DuplicateOf)
15075 const DNSQuestion *const duplicateOf = question->DuplicateOf;
15076 mdns_replace(&question->dnsservice, duplicateOf->dnsservice);
15077 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%u->DupQ%u->Q%u] Duplicate question " PRI_DM_NAME " (" PUB_S ")",
15078 question->request_id, mDNSVal16(question->TargetQID), mDNSVal16(duplicateOf->TargetQID),
15079 DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype));
15081 question->validDNSServers = question->DuplicateOf->validDNSServers;
15082 // If current(dup) question has DNS Server assigned but the original question has no DNS Server assigned to it,
15084 if (question->DuplicateOf->qDNSServer == mDNSNULL)
15086 if (question->qDNSServer)
15088 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->Q%d] FinalizeUnicastQuestion: Current(dup) question %p has DNSServer(" PRI_IP_ADDR
15089 ":%d) but original question(%p) has no DNS Server! " PRI_DM_NAME " (" PUB_S ")",
15090 question->request_id, mDNSVal16(question->TargetQID), question,
15091 question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL,
15092 mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort), question->DuplicateOf,
15093 DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype));
15096 question->qDNSServer = question->DuplicateOf->qDNSServer;
15097 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "[R%d->DupQ%d->Q%d] FinalizeUnicastQuestion: Duplicate question %p (%p) " PRI_DM_NAME " (" PUB_S
15099 question->request_id, mDNSVal16(question->TargetQID), mDNSVal16(question->DuplicateOf->TargetQID),
15100 question, question->DuplicateOf, DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype),
15101 question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL,
15102 mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort));
15106 ActivateUnicastQuery(m, question, mDNSfalse);
15109 if (question->LongLived)
15112 // we determine that it is a unicast question. LongLived is set for
15121 mDNSlocal void InsertNewQuestionInList(DNSQuestion *const question)
15125 const mDNSBool localOnlyOrP2P = LocalOnlyOrP2PInterface(question->InterfaceID);
15133 // If there's no new question sublist, then keep going until the end of the question list so that the new
15134 // question can be appended. Otherwise, the new question needs to be carefully inserted in the sublist such that
15139 // We've entered the new question sublist when we encounter the head of the sublist.
15144 // If we're in the new question sublist, check if it's appropriate to insert the new question before the
15145 // current question:
15147 // 1. The current question must also have a delayed answering time.
15148 // 2. For questions that are duplicates, make sure that the new question is inserted after its primary
15149 // question because the rest of the code expects a duplicate question to always come after its primary
15150 // question in a question list.
15151 if (inNewQSublist && (q->DelayAnswering != 0) && (!question->DuplicateOf || passedPrimary))
15153 // Determine when the new question's answering should begin.
15154 question->DelayAnswering != 0) ? question->DelayAnswering : m->timenow;
15155 // If the current question's answering time is later, then the new question should be inserted before.
15161 if (!passedPrimary && question->DuplicateOf && (q == question->DuplicateOf))
15167 // Insert the new question in the list.
15168 question->next = q;
15169 *qptr = question;
15170 // If there was no new question sublist, or the new question was inserted right before the head of the sublist, then
15171 // the new question becomes the head of the new question sublist.
15174 *newQSublistPtr = question;
15178 mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const question)
15185 err = ValidateParameters(m, question);
15193 if (IsHighASCIILabel(LastLabel(&question->qname)))
15196 if (PerformNextPunycodeConversion(question, &newname))
15197 AssignDomainName(&question->qname, &newname);
15202 question->TargetQID = Question_uDNS(question) ? mDNS_NewMessageID(m) : zeroID;
15204 question->TargetQID = zeroID;
15206 debugf("mDNS_StartQuery_internal: %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
15211 if (DNSQuestionIsEligibleForMDNSAlternativeService(question) &&
15212 Querier_IsMDNSAlternativeServiceAvailableForQuestion(question))
15215 question->TargetQID = mDNS_NewMessageID(m);
15217 // question is an mDNS question but requests an mDNS alternative service to be used.
15223 // 1. Be put after question ID is assigned.
15225 if (DNSQuestionNeedsSensitiveLogging(question))
15232 "[Q%u] Question enables sensitive logging, all the sensitive level logs and the state dump of the question will now be redacted.",
15233 mDNSVal16(question->TargetQID));
15238 "[Q%u] Question enables sensitive logging, redaction already in effect. - "
15239 "number of enabled questions: %d.", mDNSVal16(question->TargetQID),
15245 const mDNSBool localOnlyOrP2P = LocalOnlyOrP2PInterface(question->InterfaceID);
15248 !mDNSOpaque16IsZero(question->TargetQID) &&
15249 question->qclass == kDNSClass_IN &&
15251 (question->qtype == kDNSType_AAAA ||
15252 question->qtype == kDNSType_A ||
15253 question->qtype == kDNSType_CNAME))
15255 resolved_cache_prepend_name(question, &question->qname);
15259 if (IsQuestionInList(qlist, question))
15261 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StartQuery_internal: Error! Tried to add a question " PRI_DM_NAME " (" PUB_S ") %p "
15263 DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype), question);
15269 // If the question has requested using DNS push, check if it already has DNS push context initialized:
15270 // 1. If it is initialized, then it is a restarted DNS push question, so we do not reinitialize DNS push context.
15272 if (dns_question_enables_dns_push(question) &&
15273 !Querier_IsCustomPushServiceAvailableForQuestion(question) &&
15274 !dns_question_uses_dns_push(question))
15276 const dns_obj_error_t dns_push_err = dns_push_handle_question_start(m, question);
15281 // Intialize the question. The only ordering constraint we have today is that
15286 InitCommonState(m, question);
15287 InitWABState(question);
15288 InitLLQState(question);
15289 InitDNSSECProxyState(m, question);
15293 // question.
15294 question->DuplicateOf = FindDuplicateQuestion(m, question);
15295 if (question->DuplicateOf)
15296 question->AuthInfo = question->DuplicateOf->AuthInfo;
15298 InsertNewQuestionInList(question);
15300 if (question->enableDNSSEC)
15302 const dnssec_error_t dnssec_err = dnssec_handle_question_start(m, question);
15306 if (question->request_id == 0)
15314 mDNSVal16(question->TargetQID), DM_NAME_PARAM_NONNULL(&question->qname),
15315 mDNS_DomainNameFNV1aHash(&question->qname), DNS_TYPE_PARAM(question->qtype));
15319 // If the question's id is non-zero, then it's Wide Area
15322 // NS, etc.) and if we haven't finished setting up our own question and setting
15324 // this routine with the question list data structures in an inconsistent state.
15325 if (!mDNSOpaque16IsZero(question->TargetQID))
15327 FinalizeUnicastQuestion(m, question);
15345 if (question->WakeOnResolve)
15349 mDNSVal16(question->TargetQID));
15350 mDNS_PurgeBeforeResolve(m, question);
15356 // Only start the resolver discovery if the question meets condition to do so.
15359 if (dns_question_requires_resolver_discovery(question, &domain_to_discover_resolver))
15373 debugf("CancelGetZoneData %##s (%s)", nta->question.qname.c, DNSTypeName(nta->question.qtype));
15374 // This function may be called anytime to free the zone information.The question may or may not have stopped.
15377 if (nta->question.ThisQInterval != -1)
15379 mDNS_StopQuery_internal(m, &nta->question);
15380 if (nta->question.ThisQInterval != -1)
15382 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "CancelGetZoneData: Question "PRI_DM_NAME" (" PUB_S ") ThisQInterval %d not -1",
15383 DM_NAME_PARAM(&nta->question.qname), DNSTypeName(nta->question.qtype), nta->question.ThisQInterval);
15389 mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const question)
15392 // Must reset the question's parameters to the original values if it is a DNSSEC question.
15393 dnssec_handle_question_stop(question);
15397 // Do not stop DNS push activity if we are restarting this question.
15398 if (m->RestartQuestion != question && dns_question_uses_dns_push(question))
15400 dns_push_handle_question_stop(m, question);
15404 CacheGroup *cg = CacheGroupForName(m, question->qnamehash, &question->qname);
15407 const mDNSu32 request_id = question->request_id;
15408 const mDNSu16 question_id = mDNSVal16(question->TargetQID);
15410 //LogInfo("mDNS_StopQuery_internal %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
15412 if (LocalOnlyOrP2PInterface(question->InterfaceID))
15414 while (*qp && *qp != question) qp=&(*qp)->next;
15419 if (question->ThisQInterval >= 0) // Only log error message if the query was supposed to be active
15423 "[R%u->Q%u] mDNS_StopQuery_internal: Question " PRI_DM_NAME " (" PUB_S ") not found in active list.",
15424 request_id, question_id, DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype));
15430 if (!LocalOnlyOrP2PInterface(question->InterfaceID) && mDNSOpaque16IsZero(question->TargetQID))
15437 if (question->request_id == 0)
15444 mDNSVal16(question->TargetQID), mDNS_DomainNameFNV1aHash(&question->qname));
15447 // Take care to cut question from list *before* calling UpdateQuestionDuplicates
15448 UpdateQuestionDuplicates(m, question);
15450 question->ThisQInterval = -1;
15452 // If there are any cache records referencing this as their active question, then see if there is any
15453 // other question that is also referencing them, else their CRActiveQuestion needs to get set to NULL.
15456 if (cr->CRActiveQuestion == question)
15460 // If we find an active question that is answered by this cached record, use it as the cache record's
15462 // question that is answered by this cache record, then use an inactive one to not forgo generating RMV events
15480 debugf("mDNS_StopQuery_internal: Updating CRActiveQuestion to %p for cache record %s, Original question CurrentAnswers %d, new question "
15481 "CurrentAnswers %d, Suppressed %d", replacement, CRDisplayString(m,cr), question->CurrentAnswers, replacement->CurrentAnswers, replacement->Suppressed);
15482 cr->CRActiveQuestion = replacement; // Question used to be active; new value may or may not be null
15487 // If we just deleted the question that CacheRecordAdd() or CacheRecordRmv() is about to look at,
15488 // bump its pointer forward one question.
15489 if (m->CurrentQuestion == question)
15491 debugf("mDNS_StopQuery_internal: Just deleted the currently active question: %##s (%s)",
15492 question->qname.c, DNSTypeName(question->qtype));
15493 m->CurrentQuestion = question->next;
15496 if (m->NewQuestions == question)
15498 debugf("mDNS_StopQuery_internal: Just deleted a new question that wasn't even answered yet: %##s (%s)",
15499 question->qname.c, DNSTypeName(question->qtype));
15500 m->NewQuestions = question->next;
15503 question) m->NewLocalOnlyQuestions = question->next;
15505 if (m->RestartQuestion == question)
15507 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_DEFAULT, "mDNS_StopQuery_internal: Just deleted the current restart question: " PRI_DM_NAME " (" PUB_S ")",
15508 DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype));
15509 m->RestartQuestion = question->next;
15512 // Take care not to trash question->next until *after* we've updated m->CurrentQuestion and m->NewQuestions
15513 question->next = mDNSNULL;
15515 // LogMsg("mDNS_StopQuery_internal: Question %##s (%s) removed", question->qname.c, DNSTypeName(question->qtype));
15518 // Must not do this until last, because there's a good chance the GetZoneData question is the next in the list,
15519 // so if we delete it earlier in this routine, we could find that our "question->next" pointer above is already
15522 if (question->tcp) { DisposeTCPConn(question->tcp); question->tcp = mDNSNULL; }
15523 if (question->LocalSocket) { mDNSPlatformUDPClose(question->LocalSocket); question->LocalSocket = mDNSNULL; }
15525 if (!mDNSOpaque16IsZero(question->TargetQID) && question->LongLived)
15550 else if (question->state == LLQ_Established)
15552 question->ReqLease = 0;
15553 sendLLQRefresh(m, question);
15555 // We clear the tcp->question backpointer so that when the TCP connection completes, it doesn't
15556 // crash trying to access our cancelled question, but we don't cancel the TCP operation itself --
15558 if (question->tcp)
15560 question->tcp->question = mDNSNULL;
15561 question->tcp = mDNSNULL;
15567 else if (question->dnsPushServer != mDNSNULL)
15571 UnsubscribeQuestionFromDNSPushServer(m, question, mDNSfalse);
15576 if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; }
15579 Querier_HandleStoppedDNSQuestion(question);
15583 DPCHandleStoppedDNSQuestion(question);
15587 DNSMetricsClear(&question->metrics);
15591 DNS64ResetState(question);
15596 // Only stop the resolver discover if the question has required the discovery when it is started.
15597 if (dns_question_requires_resolver_discovery(question, &domain_to_discover_resolver))
15605 if (DNSQuestionNeedsSensitiveLogging(question))
15612 "[Q%u] Last question that enables sensitive logging is stopped.", mDNSVal16(question->TargetQID));
15618 "%u.", mDNSVal16(question->TargetQID), gNumOfSensitiveLoggingEnabledQuestions);
15631 MDNS_DISPOSE_DNSSEC_OBJ(question->dnssec);
15634 if (question->DupSuppress)
15636 mDNSPlatformMemFree(question->DupSuppress);
15637 question->DupSuppress = mDNSNULL;
15642 mDNSexport mStatus mDNS_StartQuery(mDNS *const m, DNSQuestion *const question)
15646 status = mDNS_StartQuery_internal(m, question);
15651 mDNSexport mStatus mDNS_StopQuery(mDNS *const m, DNSQuestion *const question)
15655 status = mDNS_StopQuery_internal(m, question);
15660 mDNSlocal mStatus mDNS_CheckQuestionBeforeStoppingQuery(const mDNS *const m, const DNSQuestion *const question)
15664 DNSQuestion *const *qp = LocalOnlyOrP2PInterface(question->InterfaceID) ? &m->LocalOnlyQuestions : &m->Questions;
15666 // Check if the current question is in mDNSResponder's question list.
15667 for (; *qp != mDNSNULL && *qp != question; qp = &(*qp)->next)
15672 if (question->ThisQInterval >= 0)
15675 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_FAULT, "Question not found in the active list - "
15676 "qname: " PRI_DM_NAME ", qtype: " PUB_S ".", DM_NAME_PARAM(&question->qname),
15677 DNSTypeName(question->qtype));
15686 // Specifically, question callbacks invoked as a result of this call cannot themselves make API calls.
15689 mDNSexport mStatus mDNS_StopQueryWithRemoves(mDNS *const m, DNSQuestion *const question)
15694 // Check if question is new -- don't want to give remove events for a question we haven't even answered yet
15695 for (qq = m->NewQuestions; qq; qq=qq->next) if (qq == question) break;
15697 // Ensure that the question is still in the mDNSResponder's question list, or there is no point to deliver RMV
15699 const mStatus err = mDNS_CheckQuestionBeforeStoppingQuery(m, question);
15705 if (qq == mDNSNULL) // The question being stopped is not a new question.
15708 CacheGroup *const cg = CacheGroupForName(m, question->qnamehash, &question->qname);
15710 "[Q%u] Generating RMV events because the question will be stopped - "
15711 "qname: " PRI_DM_NAME ", qtype: " PUB_S ".", mDNSVal16(question->TargetQID),
15712 DM_NAME_PARAM(&question->qname), DNSTypeName(question->qtype));
15715 if (cr->resrec.RecordType != kDNSRecordTypePacketNegative && SameNameCacheRecordAnswersQuestion(cr, question))
15718 if (question->QuestionCallback)
15720 question->QuestionCallback(m, question, &cr->resrec, QC_rmv);
15726 mDNS_StopQuery_internal(m, question);
15756 mDNSlocal mStatus mDNS_StartBrowse_internal(mDNS *const m, DNSQuestion *const question,
15762 question->InterfaceID = InterfaceID;
15763 question->flags = flags;
15764 question->qtype = kDNSType_PTR;
15765 question->qclass = kDNSClass_IN;
15766 question->LongLived = mDNStrue;
15767 question->ExpectUnique = mDNSfalse;
15768 question->ForceMCast = ForceMCast;
15769 question->ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
15770 question->SuppressUnusable = mDNSfalse;
15771 question->AppendSearchDomains = mDNSfalse;
15772 question->TimeoutQuestion = 0;
15773 question->WakeOnResolve = 0;
15774 question->UseBackgroundTraffic = useBackgroundTrafficClass;
15775 question->ProxyQuestion = 0;
15776 question->QuestionCallback = Callback;
15777 question->QuestionContext = Context;
15779 if (!ConstructServiceName(&question->qname, mDNSNULL, srv, domain))
15782 if (question->request_id != 0)
15788 question->request_id, DM_NAME_PARAM(&question->qname), mDNS_DomainNameFNV1aHash(&question->qname));
15791 return(mDNS_StartQuery_internal(m, question));
15794 mDNSexport mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
15802 status = mDNS_StartBrowse_internal(m, question, srv, domain, InterfaceID, flags, ForceMCast, useBackgroundTrafficClass, Callback, Context);
15807 mDNSlocal mStatus mDNS_GetDomains_Internal(mDNS *const m, DNSQuestion *const question, const mDNS_DomainType DomainType,
15811 question->InterfaceID = InterfaceID;
15812 question->flags = 0;
15813 question->qtype = kDNSType_PTR;
15814 question->qclass = kDNSClass_IN;
15815 question->LongLived = mDNSfalse;
15816 question->ExpectUnique = mDNSfalse;
15817 question->ForceMCast = mDNSfalse;
15818 question->ReturnIntermed = mDNSfalse;
15819 question->SuppressUnusable = mDNSfalse;
15820 question->AppendSearchDomains = mDNSfalse;
15821 question->TimeoutQuestion = 0;
15822 question->WakeOnResolve = 0;
15823 question->UseBackgroundTraffic = mDNSfalse;
15824 question->ProxyQuestion = 0;
15825 question->pid = mDNSPlatformGetPID();
15826 question->euid = 0;
15827 question->QuestionCallback = Callback;
15828 question->QuestionContext = Context;
15830 if (!MakeDomainNameFromDNSNameString(&question->qname, mDNS_DomainTypeNames[DomainType])) return(mStatus_BadParamErr);
15832 if (!AppendDomainName(&question->qname, domain)) return(mStatus_BadParamErr);
15833 return(mDNS_StartQuery_internal(m, question));
15836 mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, const mDNS_DomainType DomainType,
15841 const mStatus err = mDNS_GetDomains_Internal(m, question, DomainType, domain, InterfaceID, Callback, Context);
15893 err = mDNS_GetDomains_Internal(m, &enumeration->question, type, &op->name, mDNSInterface_Any,
15936 err = mDNS_StopGetDomains_Internal(m, &enumeration->question);
16235 // the record list and/or question list.
16618 // We initialize ThisQInterval to -1 indicating that the question has not been started
16619 // yet. If the question (browse) is started later during interface registration, it will
16621 // question has been stopped or not before initializing it to -1 because we need to
16882 LogRedact(MDNS_LOG_CATEGORY_MDNS, MDNS_LOG_DEFAULT, "No cache records expired for the question " PRI_DM_NAME " (" PUB_S ");"
16952 // the record list and/or question list.
17517 // which may change the record list and/or question list.
17706 // (i) as an indication that the host in question has not gone to sleep yet (so we should delay beginning to proxy for it) or
18566 LogMsg("DNSServerChangeForQuestion: ERROR: Called for duplicate question %##s", q->qname.c);
18569 // of events for all of them are consistent. Duplicates for a question are always inserted
18686 // questions here. Neither question nor cache point to mcast resolvers. Questions
18715 // - A non-scoped question picks DNSServer X, creates a cache entry with X. If a new resolver gets added later that
18716 // is a better match, we pick the new DNSServer for the question and activate the unicast query. We may or may not
18721 // we don't update the cache record's DNSServer pointer to match the question's DNSSever, as they both point to
18727 // - A non-scoped question picks DNSServer X, creates a cache entry with X. If the resolver gets removed later, we will
18728 // pick a new DNSServer for the question which may or may not be NULL and set the cache record's pointer to the same
18729 // as in question's qDNSServer if the cache record is not flushed. If there is no active question, it will be set to NULL.
18733 // non-scoped question and vice versa.
18739 // First, restart questions whose suppression status will change. The suppression status of each question in a given
18740 // question set, i.e., a non-duplicate question and all of its duplicates, if any, may or may not change. For example,
18741 // a suppressed (or non-suppressed) question that is currently a duplicate of a suppressed (or non-suppressed) question
18742 // may become a non-suppressed (or suppressed) question, while the question that it's a duplicate of may remain
18760 PRI_IP_ADDR ":%d (" PRI_DM_NAME ") for question " PRI_DM_NAME " (" PUB_S ") (scope:%p)",
18766 // If this question had a DNS Push server associated with it, substitute the new server for the
18788 // Now, change the server for each question set, if necessary. Note that questions whose suppression status changed
18848 // change affected the question. That should take care of updating the cache. But
18849 // what if there is no active question at this point when the DNS server change
18851 // them, a new question after the DNS server change could pick up these stale
18857 // active question's InterfaceID/ServiceID for looking up the right DNS server.
18860 // DNS servers or no matching DNS servers for this question. In either case,
18874 // If a cache record's DNSServer pointer is NULL, but its active question got a DNSServer in this DNS configuration
18875 // update, then use its DNSServer. This way, the active question and its duplicates don't miss out on RMV events.
18878 LogInfo("uDNS_SetupDNSConfig: Using active question's DNS server %#a for cache record %s", &cr->CRActiveQuestion->qDNSServer->addr, CRDisplayString(m, cr));
18888 LogMsg("uDNS_SetupDNSConfig: ERROR!! Cache Record %s Active question %##s (%s) (scope:%p) pointing to DNSServer Address %#a"
18898 LogInfo("uDNS_SetupDNSConfig: Cache Record %s, Active question %##s (%s) (scope:%p), pointing to DNSServer %#a (to be deleted),"
18899 " resetting to question's DNSServer Address %#a", CRDisplayString(m, cr),