{
if(!qstate)
return;
- while(qstate->subquery_first) {
- /* put subqueries on slumber list */
- struct module_qstate* s = qstate->subquery_first;
- module_subreq_remove(&qstate->subquery_first, s);
- s->parent = NULL;
- s->work_info = NULL;
- s->subquery_next = worker->slumber_list;
- s->subquery_prev = NULL;
- worker->slumber_list = s;
- }
- verbose(VERB_ALGO, "worker: slumber list has %d entries",
- module_subreq_num(worker->slumber_list));
+ if(qstate->subquery_first) {
+ while(qstate->subquery_first) {
+ /* put subqueries on slumber list */
+ struct module_qstate* s = qstate->subquery_first;
+ module_subreq_remove(&qstate->subquery_first, s);
+ s->parent = NULL;
+ s->work_info = NULL;
+ s->subquery_next = worker->slumber_list;
+ s->subquery_prev = NULL;
+ worker->slumber_list = s;
+ }
+ verbose(VERB_ALGO, "worker: slumber list has %d entries",
+ module_subreq_num(worker->slumber_list));
+ }
qstate_cleanup(worker, qstate);
}
- subrequests without parent store in cache and stop.
- worker slumber list for ongoing promiscuous queries.
- subrequest error handling.
+ - priming failure returns SERVFAIL.
+ - priming gives LAME result, returns SERVFAIL.
+ - debug routine to print dns_msg as handled by iterator.
+ - memleak in config file stubs fixup.
4 June 2007: Wouter
- random selection of equally preferred nameserver targets.
NSEC/NSEC3 will result in proper negative responses.
o fallback without EDNS if result is NOTIMPL, now only on FORMERR like in java.
o scrubber has slow pkt_subdomain and pkt_strict_subdomain functions.
+o get serverselection algorithm out of local optimum.
/* Other response codes mean (so far) to throw the response away as
* meaningless and move on to the next nameserver. */
- if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NOERROR)
+ if(FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NOERROR)
return RESPONSE_TYPE_THROWAWAY;
/* Note: TC bit has already been handled */
memset(&edns, 0, sizeof(edns));
pkt = qstate->reply->c->buffer;
ldns_buffer_set_position(pkt, 0);
- if(!parse_packet(pkt, prs, qstate->scratch))
+ if(parse_packet(pkt, prs, qstate->scratch) != LDNS_RCODE_NOERROR) {
+ verbose(VERB_ALGO, "parse error on reply packet");
goto handle_it;
+ }
/* edns is not examined, but removed from message to help cache */
- if(!parse_extract_edns(prs, &edns))
+ if(parse_extract_edns(prs, &edns) != LDNS_RCODE_NOERROR)
goto handle_it;
/* normalize and sanitize: easy to delete items from linked lists */
iq->response = dns_alloc_msg(pkt, prs, qstate->region);
if(!iq->response)
goto handle_it;
+ log_dns_msg("incoming scrubbed packet", &iq->response->qinfo,
+ iq->response->rep);
handle_it:
outbound_list_remove(&iq->outlist, outbound);
}
if(errinf.qtype == LDNS_RR_TYPE_NS) {
/* a priming query has failed. */
- iter_handle(qstate, iq, ie, id);
+ (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return;
}
if(errinf.qtype != LDNS_RR_TYPE_A &&
struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id];
verbose(VERB_ALGO, "iterator[module %d] operate: extstate:%s event:%s",
id, strextstate(qstate->ext_state[id]), strmodulevent(event));
+ if(iq) log_nametypeclass("for qstate", qstate->qinfo.qname,
+ qstate->qinfo.qtype, qstate->qinfo.qclass);
if(ie->fwd_addrlen != 0) {
perform_forward(qstate, event, id, outbound);
return;
if(!qstate)
return;
iq = (struct iter_qstate*)qstate->minfo[id];
- if(iq->orig_qname) {
+ if(iq && iq->orig_qname) {
/* so the correct qname gets free'd */
qstate->qinfo.qname = iq->orig_qname;
qstate->qinfo.qname_len = iq->orig_qnamelen;
}
- outbound_list_clear(&iq->outlist);
+ if(iq) {
+ outbound_list_clear(&iq->outlist);
+ }
qstate->minfo[id] = NULL;
}
serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
struct comm_reply* rep)
{
- struct service_callback* p = sq->cblist;
+ struct service_callback* p = sq->cblist, *n;
while(p) {
+ n = p->next;
(void)(*p->cb)(c, p->cb_arg, error, rep);
- p = p->next;
+ p = n;
}
}
free(p->name);
config_delstrlist(p->hosts);
config_delstrlist(p->addrs);
+ free(p);
p = np;
}
}
#include "util/data/dname.h"
#include "util/region-allocator.h"
#include "util/data/msgparse.h"
+#include "util/data/msgencode.h"
/** allocate qinfo, return 0 on error. */
static int
/* minimum size: header + \0 + qtype + qclass */
if(ldns_buffer_limit(query) < LDNS_HEADER_SIZE + 5)
return 0;
- log_assert(!LDNS_QR_WIRE(q));
log_assert(LDNS_OPCODE_WIRE(q) == LDNS_PACKET_QUERY);
log_assert(LDNS_QDCOUNT(q) == 1);
log_assert(ldns_buffer_position(query) == 0);
}
return NULL;
}
+
+void
+log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep)
+{
+ /* not particularly fast but flexible, make wireformat and print */
+ ldns_buffer* buf = ldns_buffer_new(65535);
+ struct region* region = region_create(malloc, free);
+ if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0,
+ region, 65535)) {
+ log_info("%s: log_dns_msg: out of memory", str);
+ } else {
+ ldns_status s;
+ ldns_pkt* pkt = NULL;
+ s = ldns_buffer2pkt_wire(&pkt, buf);
+ if(s != LDNS_STATUS_OK) {
+ log_info("%s: log_dns_msg: ldns parse gave: %s",
+ str, ldns_get_errorstr_by_id(s));
+ } else {
+ ldns_buffer_clear(buf);
+ s = ldns_pkt2buffer_str(buf, pkt);
+ if(s != LDNS_STATUS_OK) {
+ log_info("%s: log_dns_msg: ldns tostr gave: %s",
+ str, ldns_get_errorstr_by_id(s));
+ } else {
+ log_info("%s %s",
+ str, (char*)ldns_buffer_begin(buf));
+ }
+ }
+ ldns_pkt_free(pkt);
+ }
+ ldns_buffer_free(buf);
+ region_destroy(region);
+}
struct ub_packed_rrset_key* reply_find_answer_rrset(struct query_info* qinfo,
struct reply_info* rep);
+/**
+ * Debug send the query info and reply info to the log in readable form.
+ * @param str: descriptive string printed with packet content.
+ * @param qinfo: query section.
+ * @param rep: rest of message.
+ */
+void log_dns_msg(const char* str, struct query_info* qinfo,
+ struct reply_info* rep);
+
#endif /* UTIL_DATA_MSGREPLY_H */