7 December 2007: Wouter
- unbound-host has a -d option to show what happens. This can help
with debugging (why do I get this answer).
+ - fixup CNAME handling, on nodata, sets and display canonname.
6 December 2007: Wouter
- library resolution works in foreground mode, unbound-host app
#include "util/storage/slabhash.h"
#include "util/net_help.h"
#include "util/data/dname.h"
+#include "util/data/msgreply.h"
/** size of table used for random numbers. large to be more secure. */
#define RND_STATE_SIZE 256
return rep;
}
+/** insert canonname */
+static int
+fill_canon(struct ub_val_result* res, uint8_t* s)
+{
+ char buf[255+2];
+ dname_str(s, buf);
+ res->canonname = strdup(buf);
+ return res->canonname != 0;
+}
+
/** fill data into result */
static int
fill_res(struct ub_val_result* res, struct ub_packed_rrset_key* answer,
- struct query_info* rq)
+ uint8_t* finalcname, struct query_info* rq)
{
size_t i;
struct packed_rrset_data* data;
if(!answer) {
+ if(finalcname) {
+ if(!fill_canon(res, finalcname))
+ return 0; /* out of memory */
+ }
res->data = calloc(1, sizeof(char*));
res->len = calloc(1, sizeof(size_t));
return (res->data && res->len);
}
data = (struct packed_rrset_data*)answer->entry.data;
if(query_dname_compare(rq->qname, answer->rk.dname) != 0) {
- char buf[255+2];
- dname_str(answer->rk.dname, buf);
- res->canonname = strdup(buf);
- if(!res->canonname)
+ if(!fill_canon(res, answer->rk.dname))
return 0; /* out of memory */
} else
res->canonname = res->qname;
if(!rep) {
return; /* error parsing buf, or out of memory */
}
- /* log_dns_msg("fg reply", &rq, rep); @@@ DEBUG */
- if(!fill_res(d->q->res, reply_find_answer_rrset(&rq, rep), &rq))
+ if(!fill_res(d->q->res, reply_find_answer_rrset(&rq, rep),
+ reply_find_final_cname_target(&rq, rep), &rq))
return; /* out of memory */
/* rcode, nxdomain, bogus */
d->q->res->rcode = (int)LDNS_RCODE_WIRE(d->q->msg);
return;
}
if(docname && result->canonname &&
- result->canonname != result->qname)
- printf("%s is an alias for %s\n", result->qname,
+ result->canonname != result->qname) {
+ printf("%s is an alias for %s", result->qname,
result->canonname);
+ if(verb > 0)
+ printf(" %s", secstatus);
+ printf("\n");
+ }
if(!haved) {
if(verb > 0) {
- printf("%s", q);
+ printf("%s", result->canonname?result->canonname:q);
if(strcmp(cstr, "IN") != 0)
printf(" in class %s", cstr);
if(t == LDNS_RR_TYPE_A)
return cp;
}
+uint8_t*
+reply_find_final_cname_target(struct query_info* qinfo, struct reply_info* rep)
+{
+ uint8_t* sname = qinfo->qname;
+ size_t snamelen = qinfo->qname_len;
+ size_t i;
+ for(i=0; i<rep->an_numrrsets; i++) {
+ struct ub_packed_rrset_key* s = rep->rrsets[i];
+ /* follow CNAME chain (if any) */
+ if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME &&
+ ntohs(s->rk.rrset_class) == qinfo->qclass &&
+ snamelen == s->rk.dname_len &&
+ query_dname_compare(sname, s->rk.dname) == 0) {
+ get_cname_target(s, &sname, &snamelen);
+ }
+ }
+ if(sname != qinfo->qname)
+ return sname;
+ return NULL;
+}
+
struct ub_packed_rrset_key*
reply_find_answer_rrset(struct query_info* qinfo, struct reply_info* rep)
{
struct rrset_parse *pset, struct regional* region,
struct ub_packed_rrset_key* pk);
+/**
+ * Find final cname target in reply, the one matching qinfo. Follows CNAMEs.
+ * @param qinfo: what to start with.
+ * @param rep: looks in answer section of this message.
+ * @return: pointer dname, or NULL if not found.
+ */
+uint8_t* reply_find_final_cname_target(struct query_info* qinfo,
+ struct reply_info* rep);
+
/**
* Find answer rrset in reply, the one matching qinfo. Follows CNAMEs, so the
* result may have a different owner name.