+ } else if ((targetPrivate->dnsMP == MACH_PORT_NULL) && !targetPrivate->needResolve) {
+ struct timeval elapsed;
+ const struct timeval retry_limit = { EAI_NONAME_RETRY_LIMIT_USEC / USEC_PER_SEC,
+ EAI_NONAME_RETRY_LIMIT_USEC % USEC_PER_SEC };
+
+ /*
+ * if this is an async request (i.e. someone is watching the reachability
+ * of this target), if no query active, and if no query is needed
+ */
+
+ if ((error != EAI_NONAME)
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ && (error != EAI_NODATA)
+#endif
+ ) {
+ /* if not "host not found" */
+ goto checkResolvedAddress;
+ }
+
+ /*
+ * if our last DNS query returned EAI_NONAME then we
+ * "may" want to retry.
+ *
+ * Specifically, if the [DNS] configuration was updated a while
+ * back then we'll trust the EAI_NONAME reply. Otherwise, we
+ * want to try again to ensure that we didn't get caught in a
+ * race between the time when the configuration was changed and
+ * when mDNSResponder is really ready to handle the query.
+ *
+ * Retry handling details :
+ *
+ * Compare the time when the DNS configuration was last changed and
+ * when our DNS reply was started (->last_dns vs ->dnsQueryStart).
+ *
+ * Expected: 0 < last_dns (t1) < dnsQueryStart (t2)
+ *
+ * last start end description action
+ * ==== ===== ==== ================================= ========
+ * 0 N/A N/A no change, query error no retry
+ * 0 N/A N/A no change, query complete no retry
+ * N/A N/A 0 changed, query in-flight or error no retry
+ * t1 > t2 query started, then [DNS] changed no retry
+ * t1 == t2 changed & query started together no retry
+ * t1 < t2 changed, then query started retry
+ */
+
+ if (!timerisset(&targetPrivate->last_dns)) {
+ /*
+ * if we have not yet seen a DNS configuration
+ * change
+ */
+ goto checkResolvedAddress;
+ }
+
+ if (!timerisset(&targetPrivate->dnsQueryEnd)) {
+ /*
+ * if no query end time (new request in flight)
+ */
+ goto checkResolvedAddress;
+ }
+
+ if (timercmp(&targetPrivate->last_dns,
+ &targetPrivate->dnsQueryStart,
+ >=)) {
+ /*
+ * if our DNS query started and then, a
+ * short time later, the DNS configuration
+ * was changed we don't need to retry
+ * because we will be re-issuing (and not
+ * retrying) the query.
+ */
+ goto checkResolvedAddress;
+ }
+
+ timersub(&targetPrivate->dnsQueryStart,
+ &targetPrivate->last_dns,
+ &elapsed);
+ if (timercmp(&elapsed, &retry_limit, >)) {
+ /*
+ * if the DNS query started after mDNSResponder
+ * had a chance to apply the last configuration
+ * then we should trust the EAI_NONAME reply.
+ */
+ goto checkResolvedAddress;
+ }
+
+ /* retry the DNS query */
+
+ if (targetPrivate->dnsRetry != NULL) {
+ // no need to schedule if we already have a
+ // retry query in flight
+ break;
+ }
+
+ targetPrivate->dnsRetryCount++;
+
+ SCLog(_sc_debug, LOG_INFO,
+ CFSTR("%sretry [%d] DNS query for %s%s%s%s%s"),
+ targetPrivate->log_prefix,
+ targetPrivate->dnsRetryCount,
+ targetPrivate->name != NULL ? "name = " : "",
+ targetPrivate->name != NULL ? targetPrivate->name : "",
+ targetPrivate->name != NULL && targetPrivate->serv != NULL ? ", " : "",
+ targetPrivate->serv != NULL ? "serv = " : "",
+ targetPrivate->serv != NULL ? targetPrivate->serv : "");
+
+ enqueueAsyncDNSRetry(target);
+
+ break;