/** dump message entry */ static int dump_msg(SSL* ssl, struct query_info* k, struct reply_info* d, time_t now) { size_t i; char* nm, *tp, *cl; if(!k || !d) return 1; if(d->ttl < now) return 1; /* expired */ nm = sldns_wire2str_dname(k->qname, k->qname_len); tp = sldns_wire2str_type(k->qtype); cl = sldns_wire2str_class(k->qclass); if(!nm || !tp || !cl) { free(nm); free(tp); free(cl); return 1; /* skip this entry */ } if(!rrset_array_lock(d->ref, d->rrset_count, now)) { /* rrsets have timed out or do not exist */ free(nm); free(tp); free(cl); return 1; /* skip this entry */ } /* meta line */ if(!ssl_printf(ssl, "msg %s %s %s %d %d " ARG_LL "d %d %u %u %u\n", nm, cl, tp, (int)d->flags, (int)d->qdcount, (long long)(d->ttl-now), (int)d->security, (unsigned)d->an_numrrsets, (unsigned)d->ns_numrrsets, (unsigned)d->ar_numrrsets)) { free(nm); free(tp); free(cl); rrset_array_unlock(d->ref, d->rrset_count); return 0; } free(nm); free(tp); free(cl); for(i=0; i<d->rrset_count; i++) { if(!dump_msg_ref(ssl, d->rrsets[i])) { rrset_array_unlock(d->ref, d->rrset_count); return 0; } } rrset_array_unlock(d->ref, d->rrset_count); return 1; }
struct dns_msg* tomsg(struct module_env* env, struct query_info* q, struct reply_info* r, struct regional* region, time_t now, struct regional* scratch) { struct dns_msg* msg; size_t i; if(now > r->ttl) return NULL; msg = gen_dns_msg(region, q, r->rrset_count); if(!msg) return NULL; msg->rep->flags = r->flags; msg->rep->qdcount = r->qdcount; msg->rep->ttl = r->ttl - now; if(r->prefetch_ttl > now) msg->rep->prefetch_ttl = r->prefetch_ttl - now; else msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL; msg->rep->security = r->security; msg->rep->an_numrrsets = r->an_numrrsets; msg->rep->ns_numrrsets = r->ns_numrrsets; msg->rep->ar_numrrsets = r->ar_numrrsets; msg->rep->rrset_count = r->rrset_count; msg->rep->authoritative = r->authoritative; if(!rrset_array_lock(r->ref, r->rrset_count, now)) return NULL; if(r->an_numrrsets > 0 && (r->rrsets[0]->rk.type == htons( LDNS_RR_TYPE_CNAME) || r->rrsets[0]->rk.type == htons( LDNS_RR_TYPE_DNAME)) && !reply_check_cname_chain(q, r)) { /* cname chain is now invalid, reconstruct msg */ rrset_array_unlock(r->ref, r->rrset_count); return NULL; } if(r->security == sec_status_secure && !reply_all_rrsets_secure(r)) { /* message rrsets have changed status, revalidate */ rrset_array_unlock(r->ref, r->rrset_count); return NULL; } for(i=0; i<msg->rep->rrset_count; i++) { msg->rep->rrsets[i] = packed_rrset_copy_region(r->rrsets[i], region, now); if(!msg->rep->rrsets[i]) { rrset_array_unlock(r->ref, r->rrset_count); return NULL; } } if(env) rrset_array_unlock_touch(env->rrset_cache, scratch, r->ref, r->rrset_count); else rrset_array_unlock(r->ref, r->rrset_count); return msg; }
/* Invalidate the message associated with query_info stored in message cache */ void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo) { hashvalue_t h; struct lruhash_entry* e; struct reply_info *r; size_t i, j; h = query_info_hash(qinfo, qstate->query_flags); if ((e=slabhash_lookup(qstate->env->msg_cache, h, qinfo, 0))) { r = (struct reply_info*)(e->data); if (r) { r->ttl = 0; if(rrset_array_lock(r->ref, r->rrset_count, *qstate->env->now)) { for(i=0; i< r->rrset_count; i++) { struct packed_rrset_data* data = (struct packed_rrset_data*) r->ref[i].key->entry.data; if(i>0 && r->ref[i].key == r->ref[i-1].key) continue; data->ttl = r->ttl; for(j=0; j<data->count + data->rrsig_count; j++) data->rr_ttl[j] = r->ttl; } rrset_array_unlock(r->ref, r->rrset_count); } } lock_rw_unlock(&e->lock); } else { log_info("invalidateQueryInCache: qinfo is not in cache"); } }
/** dump message entry */ static int dump_msg(SSL* ssl, struct query_info* k, struct reply_info* d, uint32_t now) { size_t i; char* nm, *tp, *cl; ldns_rdf* rdf; ldns_status status; size_t pos; if(!k || !d) return 1; if(d->ttl < now) return 1; /* expired */ pos = 0; status = ldns_wire2dname(&rdf, k->qname, k->qname_len, &pos); if(status != LDNS_STATUS_OK) { return 1; /* skip this entry */ } nm = ldns_rdf2str(rdf); ldns_rdf_deep_free(rdf); tp = ldns_rr_type2str(k->qtype); cl = ldns_rr_class2str(k->qclass); if(!nm || !tp || !cl) { free(nm); free(tp); free(cl); return 1; /* skip this entry */ } if(!rrset_array_lock(d->ref, d->rrset_count, now)) { /* rrsets have timed out or do not exist */ free(nm); free(tp); free(cl); return 1; /* skip this entry */ } /* meta line */ if(!ssl_printf(ssl, "msg %s %s %s %d %d %u %d %u %u %u\n", nm, cl, tp, (int)d->flags, (int)d->qdcount, (unsigned)(d->ttl-now), (int)d->security, (unsigned)d->an_numrrsets, (unsigned)d->ns_numrrsets, (unsigned)d->ar_numrrsets)) { free(nm); free(tp); free(cl); rrset_array_unlock(d->ref, d->rrset_count); return 0; } free(nm); free(tp); free(cl); for(i=0; i<d->rrset_count; i++) { if(!dump_msg_ref(ssl, d->rrsets[i])) { rrset_array_unlock(d->ref, d->rrset_count); return 0; } } rrset_array_unlock(d->ref, d->rrset_count); return 1; }