From: Wouter Wijngaards Date: Fri, 7 Dec 2007 10:43:10 +0000 (+0000) Subject: cname handling improved. X-Git-Tag: release-0.9~121 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=abf85e9270e728451e53c380f1f7ebfe81410e56;p=thirdparty%2Funbound.git cname handling improved. git-svn-id: file:///svn/unbound/trunk@815 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 63e7a9712..8ade6427a 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,7 @@ 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 diff --git a/libunbound/worker.c b/libunbound/worker.c index c0294aafd..7be64dd6a 100644 --- a/libunbound/worker.c +++ b/libunbound/worker.c @@ -58,6 +58,7 @@ #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 @@ -206,24 +207,35 @@ parse_reply(ldns_buffer* pkt, struct regional* region, struct query_info* qi) 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; @@ -272,8 +284,8 @@ libworker_fg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s) 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); diff --git a/smallapp/unbound-host.c b/smallapp/unbound-host.c index fdd16cc4d..7326c7d67 100644 --- a/smallapp/unbound-host.c +++ b/smallapp/unbound-host.c @@ -288,12 +288,16 @@ pretty_output(char* q, int t, int c, int sec, int haved, 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) diff --git a/util/data/msgreply.c b/util/data/msgreply.c index 7c4dab060..924ba64e3 100644 --- a/util/data/msgreply.c +++ b/util/data/msgreply.c @@ -648,6 +648,27 @@ reply_info_copy(struct reply_info* rep, struct alloc_cache* alloc, 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; ian_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) { diff --git a/util/data/msgreply.h b/util/data/msgreply.h index 23e35e131..3d17cbe40 100644 --- a/util/data/msgreply.h +++ b/util/data/msgreply.h @@ -315,6 +315,15 @@ int parse_copy_decompress_rrset(ldns_buffer* pkt, struct msg_parse* msg, 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.