return error_response(qstate, id, rcode);
/* if that fails (not in cache), fall through to store err */
}
+ if(qstate->env->cfg->serve_expired) {
+ /* if serving expired contents, and such content is
+ * already available, don't overwrite this servfail */
+ struct msgreply_entry* msg;
+ if((msg=msg_cache_lookup(qstate->env,
+ qstate->qinfo.qname, qstate->qinfo.qname_len,
+ qstate->qinfo.qtype, qstate->qinfo.qclass,
+ qstate->query_flags, 0, 0))
+ != NULL) {
+ lock_rw_unlock(&msg->entry.lock);
+ return error_response(qstate, id, rcode);
+ }
+ /* serving expired contents, but nothing is cached
+ * at all, so the servfail cache entry is useful
+ * (stops waste of time on this servfail NORR_TTL) */
+ }
memset(&err, 0, sizeof(err));
err.flags = (uint16_t)(BIT_QR | BIT_RA);
FLAGS_SET_RCODE(err.flags, rcode);
}
/** lookup message in message cache */
-static struct msgreply_entry*
+struct msgreply_entry*
msg_cache_lookup(struct module_env* env, uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, time_t now, int wr)
{
int dns_cache_prefetch_adjust(struct module_env* env, struct query_info* qinfo,
time_t adjust, uint16_t flags);
+/** lookup message in message cache
+ * the returned nonNULL entry is locked and has to be unlocked by the caller */
+struct msgreply_entry* msg_cache_lookup(struct module_env* env,
+ uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
+ uint16_t flags, time_t now, int wr);
+
#endif /* SERVICES_CACHE_DNS_H */