From cf675a92849876f9f7ef785026ad793b3df49eee Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 7 Jun 2016 16:52:10 +0200 Subject: [PATCH 1/9] Add srv_addresses when query was for SRV Moved _getdns_rrset iterators to rr-iter.[ch] in the process --- src/convert.c | 39 +-- src/dnssec.c | 631 ++++++++++++++--------------------------- src/general.c | 8 +- src/request-internal.c | 4 +- src/rr-iter.c | 201 ++++++++++++- src/rr-iter.h | 105 ++++++- src/stub.c | 3 +- src/util-internal.c | 213 ++++++++++---- src/util-internal.h | 5 - 9 files changed, 687 insertions(+), 522 deletions(-) diff --git a/src/convert.c b/src/convert.c index 65af8d79..2539d7bd 100644 --- a/src/convert.c +++ b/src/convert.c @@ -601,8 +601,11 @@ _getdns_wire2msg_dict_scan(struct mem_funcs *mf, getdns_return_t r = GETDNS_RETURN_GOOD; getdns_dict *result = NULL, *header = NULL, *rr_dict = NULL; _getdns_rr_iter rr_iter_storage, *rr_iter; - gldns_pkt_section section; - getdns_list *sections[4] = { NULL, NULL, NULL, NULL }; + _getdns_section section; + getdns_list *sections[16] = { NULL, NULL, NULL, NULL + , NULL, NULL, NULL, NULL + , NULL, NULL, NULL, NULL + , NULL, NULL, NULL, NULL }; const uint8_t *eop; /* end of packet */ if (!wire || !*wire || !wire_len || !msg_dict) @@ -610,11 +613,11 @@ _getdns_wire2msg_dict_scan(struct mem_funcs *mf, if (!(result = _getdns_dict_create_with_mf(mf)) || !(header = _getdns_dict_create_with_mf(mf)) || - !(sections[GLDNS_SECTION_ANSWER] + !(sections[SECTION_ANSWER] = _getdns_list_create_with_mf(mf)) || - !(sections[GLDNS_SECTION_AUTHORITY] + !(sections[SECTION_AUTHORITY] = _getdns_list_create_with_mf(mf)) || - !(sections[GLDNS_SECTION_ADDITIONAL] + !(sections[SECTION_ADDITIONAL] = _getdns_list_create_with_mf(mf))) { r = GETDNS_RETURN_MEMORY_ERROR; goto error; @@ -653,14 +656,14 @@ _getdns_wire2msg_dict_scan(struct mem_funcs *mf, continue; switch ((section = _getdns_rr_iter_section(rr_iter))) { - case GLDNS_SECTION_QUESTION: + case SECTION_QUESTION: if ((r = _getdns_dict_set_this_dict( result, "question", rr_dict))) goto error; break; - case GLDNS_SECTION_ANSWER: - case GLDNS_SECTION_AUTHORITY: - case GLDNS_SECTION_ADDITIONAL: + case SECTION_ANSWER: + case SECTION_AUTHORITY: + case SECTION_ADDITIONAL: if ((r = _getdns_list_append_this_dict( sections[section], rr_dict))) goto error; @@ -672,27 +675,27 @@ _getdns_wire2msg_dict_scan(struct mem_funcs *mf, rr_dict = NULL; } if (!(r = _getdns_dict_set_this_list(result, "answer", - sections[GLDNS_SECTION_ANSWER]))) - sections[GLDNS_SECTION_ANSWER] = NULL; + sections[SECTION_ANSWER]))) + sections[SECTION_ANSWER] = NULL; else goto error; if (!(r = _getdns_dict_set_this_list(result, "authority", - sections[GLDNS_SECTION_AUTHORITY]))) - sections[GLDNS_SECTION_AUTHORITY] = NULL; + sections[SECTION_AUTHORITY]))) + sections[SECTION_AUTHORITY] = NULL; else goto error; if (!(r = _getdns_dict_set_this_list(result, "additional", - sections[GLDNS_SECTION_ADDITIONAL]))) - sections[GLDNS_SECTION_ADDITIONAL] = NULL; + sections[SECTION_ADDITIONAL]))) + sections[SECTION_ADDITIONAL] = NULL; else goto error; *wire_len -= (eop - *wire); *wire = eop; error: getdns_dict_destroy(rr_dict); - getdns_list_destroy(sections[GLDNS_SECTION_ADDITIONAL]); - getdns_list_destroy(sections[GLDNS_SECTION_AUTHORITY]); - getdns_list_destroy(sections[GLDNS_SECTION_ANSWER]); + getdns_list_destroy(sections[SECTION_ADDITIONAL]); + getdns_list_destroy(sections[SECTION_AUTHORITY]); + getdns_list_destroy(sections[SECTION_ANSWER]); getdns_dict_destroy(header); if (r) getdns_dict_destroy(result); diff --git a/src/dnssec.c b/src/dnssec.c index 7c851aba..7bca4881 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -123,34 +123,34 @@ * "Schedule Queries to Provision Validation Chain" * * - * getdns_rrset + * _getdns_rrset * ------------ * RRsets used in the structure described above are represented by the - * getdns_rrset struct. They consist of name/rr_class and rr_type members + * _getdns_rrset struct. They consist of name/rr_class and rr_type members * plus a reference to the wireformat packet that should contain the RRset. * * The actual RR's in the rrset and the signatures are only accessed via * iterators; substantiated with the rrtype_iter struct to iterate over RRs - * in a getdns_rrset, and the rrsig_iter to iterate over the RRSIGs covering - * the RRs in the getdns_rrset. + * in a _getdns_rrset, and the rrsig_iter to iterate over the RRSIGs covering + * the RRs in the _getdns_rrset. * - * The getdns_rrsets are already equiped with name/rr_class and rr_type when + * The _getdns_rrsets are already equiped with name/rr_class and rr_type when * constructing the linked list of chain_nodes up to the root for a chain_head. * They are substantiated with the wireformat packets that are returned with * the queries that were sheduled in the context of the * "dnssec_return_validation_chain" extension. * - * Note that the NSEC(3) RRsets proving the non-existance of a getdns_rrset - * can be found by processing that getdns_rrset, as it contains the pointer + * Note that the NSEC(3) RRsets proving the non-existance of a _getdns_rrset + * can be found by processing that _getdns_rrset, as it contains the pointer * to the wireformat data that should either contain the RRset or the proof * of non-existance. * * The getdns_validate_dnssec() function, after it constructed the chain_heads * hierarchy, creates an artifical packet for the support records and equips - * all the ds and dnskey getdns_rrsets on the chain_nodes with this packet. + * all the ds and dnskey _getdns_rrsets on the chain_nodes with this packet. * - * The getdns_rrset + support function and data types are defined in section: - * "getdns_rrset + Support Iterators" + * The _getdns_rrset + support function and data types are defined in section: + * "_getdns_rrset + Support Iterators" * * * Validation @@ -418,159 +418,18 @@ inline static void debug_sec_print_dname(const char *msg, const uint8_t *label) #endif -/******************* getdns_rrset + Support Iterators ********************** +/******************* _getdns_rrset + Support Iterators ********************** *****************************************************************************/ -/* Utility functions to read rr_type and rr_class from a rr iterator */ -static inline uint16_t rr_iter_type(_getdns_rr_iter *rr) -{ return rr->rr_type + 2 <= rr->nxt ? gldns_read_uint16(rr->rr_type) : 0; } -static inline uint16_t rr_iter_class(_getdns_rr_iter *rr) -{ return rr->rr_type + 4 <= rr->nxt ? gldns_read_uint16(rr->rr_type + 2) : 0; } - -/* Utility function to compare owner name of rr with name */ -static int rr_owner_equal(_getdns_rr_iter *rr, const uint8_t *name) -{ - uint8_t owner_spc[256]; - const uint8_t *owner; - size_t owner_len = sizeof(owner_spc); - - return (owner = _getdns_owner_if_or_as_decompressed(rr, owner_spc - , &owner_len)) - && _dname_equal(owner, name); -} - -/* First a few filter functions that filter a RR iterator to point only - * to RRs with certain constraints (and moves on otherwise). - */ - -/* Filter that only iterates over the ANSWER and AUTHORITY section */ -static _getdns_rr_iter *rr_iter_ansauth(_getdns_rr_iter *rr) -{ - while (rr && rr->pos && !( - _getdns_rr_iter_section(rr) == GLDNS_SECTION_ANSWER || - _getdns_rr_iter_section(rr) == GLDNS_SECTION_AUTHORITY)) - - rr = _getdns_rr_iter_next(rr); - - return rr && rr->pos ? rr : NULL; -} - -/* Filter that only iterates over RRs with a certain name/class/type */ -static _getdns_rr_iter *rr_iter_name_class_type(_getdns_rr_iter *rr, - const uint8_t *name, uint16_t rr_class, uint16_t rr_type) -{ - while (rr_iter_ansauth(rr) && !( - rr_iter_type(rr) == rr_type && - rr_iter_class(rr) == rr_class && - rr_owner_equal(rr, name))) - - rr = _getdns_rr_iter_next(rr); - - return rr && rr->pos ? rr : NULL; -} - -/* Filter that only iterates over RRs that do not have a name/class/type */ -static _getdns_rr_iter *rr_iter_not_name_class_type(_getdns_rr_iter *rr, - const uint8_t *name, uint16_t rr_class, uint16_t rr_type) -{ - while (rr_iter_ansauth(rr) && ( - rr_iter_type(rr) == GETDNS_RRTYPE_RRSIG || ( - rr_iter_type(rr) == rr_type && - rr_iter_class(rr) == rr_class && - rr_owner_equal(rr, name)))) - - rr = _getdns_rr_iter_next(rr); - - return rr && rr->pos ? rr : NULL; -} - -/* Filter that only iterates over RRs that are of type RRSIG, that cover - * a RRset with a certain name/class/type - */ -static _getdns_rr_iter *rr_iter_rrsig_covering(_getdns_rr_iter *rr, - const uint8_t *name, uint16_t rr_class, uint16_t rr_type) -{ - while (rr_iter_ansauth(rr) && !( - rr_iter_type(rr) == GETDNS_RRTYPE_RRSIG && - rr_iter_class(rr) == rr_class && - rr->rr_type + 12 <= rr->nxt && - gldns_read_uint16(rr->rr_type + 10) == rr_type && - rr_owner_equal(rr, name))) - - rr = _getdns_rr_iter_next(rr); - - return rr && rr->pos ? rr : NULL; -} - -typedef struct getdns_rrset { - const uint8_t *name; - uint16_t rr_class; - uint16_t rr_type; - uint8_t *pkt; - size_t pkt_len; -} getdns_rrset; - -typedef struct rrtype_iter { - _getdns_rr_iter rr_i; - getdns_rrset *rrset; -} rrtype_iter; - -typedef struct rrsig_iter { - _getdns_rr_iter rr_i; - getdns_rrset *rrset; -} rrsig_iter; - -static rrtype_iter *rrtype_iter_next(rrtype_iter *i) -{ - return (rrtype_iter *) rr_iter_name_class_type( - _getdns_rr_iter_next(&i->rr_i), - i->rrset->name, i->rrset->rr_class, i->rrset->rr_type); -} - -static rrtype_iter *rrtype_iter_init(rrtype_iter *i, getdns_rrset *rrset) -{ - i->rrset = rrset; - return (rrtype_iter *) rr_iter_name_class_type( - _getdns_rr_iter_init(&i->rr_i, rrset->pkt, rrset->pkt_len ), - i->rrset->name, i->rrset->rr_class, i->rrset->rr_type); -} - -inline static int rrset_has_rrs(getdns_rrset *rrset) -{ - rrtype_iter rr_spc; - return rrtype_iter_init(&rr_spc, rrset) != NULL; -} - -static rrsig_iter *rrsig_iter_next(rrsig_iter *i) -{ - return (rrsig_iter *) rr_iter_rrsig_covering( - _getdns_rr_iter_next(&i->rr_i), - i->rrset->name, i->rrset->rr_class, i->rrset->rr_type); -} - -static rrsig_iter *rrsig_iter_init(rrsig_iter *i, getdns_rrset *rrset) -{ - i->rrset = rrset; - return (rrsig_iter *) rr_iter_rrsig_covering( - _getdns_rr_iter_init(&i->rr_i, rrset->pkt, rrset->pkt_len), - i->rrset->name, i->rrset->rr_class, i->rrset->rr_type); -} - -inline static int rrset_has_rrsigs(getdns_rrset *rrset) -{ - rrsig_iter rrsig; - return rrsig_iter_init(&rrsig, rrset) != NULL; -} - #if defined(SEC_DEBUG) && SEC_DEBUG -static void debug_sec_print_rrset(const char *msg, getdns_rrset *rrset) +static void debug_sec_print_rrset(const char *msg, _getdns_rrset *rrset) { char owner[1024]; char buf_space[2048]; gldns_buffer buf; - rrtype_iter *rr, rr_space; - rrsig_iter *rrsig, rrsig_space; + _getdns_rrtype_iter *rr, rr_space; + _getdns_rrsig_iter *rrsig, rrsig_space; size_t i; if (!rrset) { @@ -596,15 +455,15 @@ static void debug_sec_print_rrset(const char *msg, getdns_rrset *rrset) gldns_buffer_printf(&buf, "%s", _getdns_rr_type_name(rrset->rr_type)); gldns_buffer_printf(&buf, ", rrs:"); - for ( rr = rrtype_iter_init(&rr_space, rrset), i = 1 + for ( rr = _getdns_rrtype_iter_init(&rr_space, rrset), i = 1 ; rr - ; rr = rrtype_iter_next(rr), i++) + ; rr = _getdns_rrtype_iter_next(rr), i++) gldns_buffer_printf(&buf, " %d", (int)i); gldns_buffer_printf(&buf, ", rrsigs:"); - for ( rrsig = rrsig_iter_init(&rrsig_space, rrset), i = 1 + for ( rrsig = _getdns_rrsig_iter_init(&rrsig_space, rrset), i = 1 ; rrsig - ; rrsig = rrsig_iter_next(rrsig), i++) + ; rrsig = _getdns_rrsig_iter_next(rrsig), i++) gldns_buffer_printf(&buf, " %d", (int)i); DEBUG_SEC("%s%s\n", msg, buf_space); @@ -613,102 +472,6 @@ static void debug_sec_print_rrset(const char *msg, getdns_rrset *rrset) #define debug_sec_print_rrset(...) DEBUG_OFF(__VA_ARGS__) #endif -/* The rrset_iter manifests an iterator of a wireformat packet that will return - * all unique rrsets within that packet in turn. - */ -typedef struct rrset_iter rrset_iter; -struct rrset_iter { - getdns_rrset rrset; - uint8_t name_spc[256]; - size_t name_len; - _getdns_rr_iter rr_i; -}; - -static rrset_iter *rrset_iter_init(rrset_iter *i, uint8_t *pkt, size_t pkt_len) -{ - _getdns_rr_iter *rr; - - i->rrset.name = i->name_spc; - i->rrset.pkt = pkt; - i->rrset.pkt_len = pkt_len; - i->name_len = 0; - - for ( rr = _getdns_rr_iter_init(&i->rr_i, pkt, pkt_len) - ;(rr = rr_iter_ansauth(rr)) - ; rr = _getdns_rr_iter_next(rr)) { - - if ((i->rrset.rr_type = rr_iter_type(rr)) - == GETDNS_RRTYPE_RRSIG) - continue; - - i->rrset.rr_class = rr_iter_class(rr); - - if (!(i->rrset.name = _getdns_owner_if_or_as_decompressed( - rr, i->name_spc, &i->name_len))) - continue; - - return i; - } - return NULL; -} - -static rrset_iter *rrset_iter_rewind(rrset_iter *i) -{ - return rrset_iter_init(i, i->rrset.pkt, i->rrset.pkt_len); -} - -static rrset_iter *rrset_iter_next(rrset_iter *i) -{ - _getdns_rr_iter *rr; - - if (!(rr = i && i->rr_i.pos ? &i->rr_i : NULL)) - return NULL; - - if (!(rr = rr_iter_not_name_class_type(rr, - i->rrset.name, i->rrset.rr_class, i->rrset.rr_type))) - return NULL; - - i->rrset.rr_type = rr_iter_type(rr); - i->rrset.rr_class = rr_iter_class(rr); - if (!(i->rrset.name = _getdns_owner_if_or_as_decompressed( - rr, i->name_spc, &i->name_len))) - - /* This is safe, because rr_iter_not_name_class_type will shift - * the iterator forward because at least name does not match. - * Goal is to skip broken compression pointer issues but keep - * processing the packet. - */ - return rrset_iter_next(i); - - return i; -} - -static getdns_rrset *rrset_iter_value(rrset_iter *i) -{ - if (!i) - return NULL; - if (!i->rr_i.pos) - return NULL; - return &i->rrset; -} - -static getdns_rrset *rrset_by_type( - rrset_iter *i_spc, getdns_network_req *netreq, uint16_t rr_type) -{ - rrset_iter *i; - getdns_rrset *rrset; - - for ( i = rrset_iter_init(i_spc,netreq->response,netreq->response_len) - ; i - ; i = rrset_iter_next(i)) { - - rrset = rrset_iter_value(i); - if (rrset->rr_type == rr_type) /* Check class too? */ - return rrset; - } - return NULL; -} - /********************* Validation Chain Data Structs *********************** *****************************************************************************/ @@ -725,7 +488,7 @@ struct chain_head { chain_node *parent; size_t node_count; /* Number of nodes attached directly * to this head. For cleaning. */ - getdns_rrset rrset; + _getdns_rrset rrset; getdns_network_req *netreq; int signer; @@ -737,11 +500,11 @@ struct chain_node { size_t lock; - getdns_rrset dnskey; + _getdns_rrset dnskey; getdns_network_req *dnskey_req; int dnskey_signer; - getdns_rrset ds; + _getdns_rrset ds; getdns_network_req *ds_req; int ds_signer; @@ -759,11 +522,11 @@ struct chain_node { */ static void val_chain_sched(chain_head *head, const uint8_t *dname); static void val_chain_sched_ds(chain_head *head, const uint8_t *dname); -static void val_chain_sched_signer(chain_head *head, rrsig_iter *rrsig); +static void val_chain_sched_signer(chain_head *head, _getdns_rrsig_iter *rrsig); static void val_chain_sched_soa(chain_head *head, const uint8_t *dname); static chain_head *add_rrset2val_chain(struct mem_funcs *mf, - chain_head **chain_p, getdns_rrset *rrset, getdns_network_req *netreq) + chain_head **chain_p, _getdns_rrset *rrset, getdns_network_req *netreq) { chain_head *head; const uint8_t *labels[128], **last_label, **label; @@ -850,6 +613,7 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf, head->rrset.rr_type = rrset->rr_type; head->rrset.pkt = rrset->pkt; head->rrset.pkt_len = rrset->pkt_len; + head->rrset.sections = rrset->sections; head->netreq = netreq; head->signer = -1; head->node_count = node_count; @@ -875,8 +639,10 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf, node->dnskey.rr_type = GETDNS_RRTYPE_DNSKEY; node->ds.pkt = NULL; node->ds.pkt_len = 0; + node->ds.sections = head->rrset.sections; node->dnskey.pkt = NULL; node->dnskey.pkt_len = 0; + node->dnskey.sections = head->rrset.sections; node->ds_req = NULL; node->dnskey_req = NULL; node->soa_req = NULL; @@ -894,13 +660,13 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf, return head; } -static int is_synthesized_cname(getdns_rrset *cname) +static int is_synthesized_cname(_getdns_rrset *cname) { - rrset_iter *i, i_spc; - getdns_rrset *dname; - rrtype_iter rr_spc, *rr; + _getdns_rrset_iter *i, i_spc; + _getdns_rrset *dname; + _getdns_rrtype_iter rr_spc, *rr; _getdns_rdf_iter rdf_spc, *rdf; - rrtype_iter drr_spc, *drr; + _getdns_rrtype_iter drr_spc, *drr; _getdns_rdf_iter drdf_spc, *drdf; uint8_t cname_rdata_spc[256], dname_rdata_spc[256], @@ -913,22 +679,23 @@ static int is_synthesized_cname(getdns_rrset *cname) /* Synthesized CNAMEs don't have RRSIGs */ if ( cname->rr_type != GETDNS_RRTYPE_CNAME - || rrset_has_rrsigs(cname)) + || _getdns_rrset_has_rrsigs(cname)) return 0; /* Get canonical name rdata field */ - if ( !(rr = rrtype_iter_init(&rr_spc, cname)) + if ( !(rr = _getdns_rrtype_iter_init(&rr_spc, cname)) || !(rdf = _getdns_rdf_iter_init(&rdf_spc, &rr->rr_i)) || !(cname_rdata = _getdns_rdf_if_or_as_decompressed( rdf, cname_rdata_spc, &cname_rdata_len))) return 0; /* Find a matching DNAME */ - for ( i = rrset_iter_init(&i_spc, cname->pkt, cname->pkt_len) + for ( i = _getdns_rrset_iter_init(&i_spc, cname->pkt, cname->pkt_len + , SECTION_ANSWER) ; i - ; i = rrset_iter_next(i)) { + ; i = _getdns_rrset_iter_next(i)) { - dname = rrset_iter_value(i); + dname = _getdns_rrset_iter_value(i); if ( dname->rr_type != GETDNS_RRTYPE_DNAME /* DNAME->owner is parent of CNAME->owner */ || !_dname_is_parent(dname->name, cname->name)) @@ -955,7 +722,7 @@ static int is_synthesized_cname(getdns_rrset *cname) continue; /* Get DNAME's rdata field */ - if ( !(drr = rrtype_iter_init(&drr_spc, dname)) + if ( !(drr = _getdns_rrtype_iter_init(&drr_spc, dname)) || !(drdf=_getdns_rdf_iter_init(&drdf_spc,&drr->rr_i)) || !(dname_rdata = _getdns_rdf_if_or_as_decompressed( drdf, dname_rdata_spc, &dname_rdata_len))) @@ -990,9 +757,9 @@ static void add_pkt2val_chain(struct mem_funcs *mf, chain_head **chain_p, uint8_t *pkt, size_t pkt_len, getdns_network_req *netreq) { - rrset_iter *i, i_spc; - getdns_rrset *rrset; - rrsig_iter *rrsig, rrsig_spc; + _getdns_rrset_iter *i, i_spc; + _getdns_rrset *rrset; + _getdns_rrsig_iter *rrsig, rrsig_spc; size_t n_rrsigs; chain_head *head; @@ -1003,11 +770,12 @@ static void add_pkt2val_chain(struct mem_funcs *mf, /* For all things without signature, find SOA (zonecut) and query DS */ - for ( i = rrset_iter_init(&i_spc, pkt, pkt_len) + for ( i = _getdns_rrset_iter_init(&i_spc, pkt, pkt_len + , SECTION_NO_QUESTION) ; i - ; i = rrset_iter_next(i)) { + ; i = _getdns_rrset_iter_next(i)) { - rrset = rrset_iter_value(i); + rrset = _getdns_rrset_iter_value(i); debug_sec_print_rrset("rrset: ", rrset); /* Schedule validation for everything, except from DNAME @@ -1019,9 +787,9 @@ static void add_pkt2val_chain(struct mem_funcs *mf, if (!(head = add_rrset2val_chain(mf, chain_p, rrset, netreq))) continue; - for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset), n_rrsigs = 0 + for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset), n_rrsigs = 0 ; rrsig - ; rrsig = rrsig_iter_next(rrsig), n_rrsigs++) { + ; rrsig = _getdns_rrsig_iter_next(rrsig), n_rrsigs++) { /* Signature, so lookup DS/DNSKEY at signer's name */ val_chain_sched_signer(head, rrsig); @@ -1049,12 +817,12 @@ static void add_question2val_chain(struct mem_funcs *mf, const uint8_t *qname, uint16_t qtype, uint16_t qclass, getdns_network_req *netreq) { - getdns_rrset q_rrset; + _getdns_rrset q_rrset; uint8_t cname_spc[256]; size_t cname_len = sizeof(cname_spc); size_t anti_loop; _getdns_rdf_iter rdf_spc, *rdf; - rrtype_iter *rr, rr_spc; + _getdns_rrtype_iter *rr, rr_spc; chain_head *head; @@ -1070,7 +838,7 @@ static void add_question2val_chain(struct mem_funcs *mf, q_rrset.pkt_len = pkt_len; for (anti_loop = MAX_CNAMES; anti_loop; anti_loop--) { - if (!(rr = rrtype_iter_init(&rr_spc, &q_rrset))) + if (!(rr = _getdns_rrtype_iter_init(&rr_spc, &q_rrset))) break; if (!(rdf = _getdns_rdf_iter_init(&rdf_spc, &rr->rr_i))) break; @@ -1086,7 +854,7 @@ static void add_question2val_chain(struct mem_funcs *mf, return; q_rrset.rr_type = qtype; - if (!(rr = rrtype_iter_init(&rr_spc, &q_rrset))) { + if (!(rr = _getdns_rrtype_iter_init(&rr_spc, &q_rrset))) { /* No answer for the question. Add a head for this rrset * anyway, to validate proof of non-existance, or to find * proof that the packet is insecure. @@ -1258,7 +1026,7 @@ static void val_chain_sched_ds(chain_head *head, const uint8_t *dname) val_chain_sched_ds_node(node); } -static void val_chain_sched_signer_node(chain_node *node, rrsig_iter *rrsig) +static void val_chain_sched_signer_node(chain_node *node, _getdns_rrsig_iter *rrsig) { _getdns_rdf_iter rdf_spc, *rdf; uint8_t signer_spc[256]; @@ -1278,7 +1046,7 @@ static void val_chain_sched_signer_node(chain_node *node, rrsig_iter *rrsig) val_chain_sched_node(node); } -static void val_chain_sched_signer(chain_head *head, rrsig_iter *rrsig) +static void val_chain_sched_signer(chain_head *head, _getdns_rrsig_iter *rrsig) { if (!head->netreq) return; @@ -1290,9 +1058,9 @@ static void val_chain_node_cb(getdns_dns_req *dnsreq) { chain_node *node = (chain_node *)dnsreq->user_pointer; getdns_network_req *netreq = dnsreq->netreqs[0]; - rrset_iter *i, i_spc; - getdns_rrset *rrset; - rrsig_iter *rrsig, rrsig_spc; + _getdns_rrset_iter *i, i_spc; + _getdns_rrset *rrset; + _getdns_rrsig_iter *rrsig, rrsig_spc; size_t n_signers; _getdns_context_clear_outbound_request(dnsreq); @@ -1307,19 +1075,21 @@ static void val_chain_node_cb(getdns_dns_req *dnsreq) } node->lock++; n_signers = 0; - for ( i = rrset_iter_init(&i_spc,netreq->response,netreq->response_len) + for ( i = _getdns_rrset_iter_init(&i_spc, netreq->response + , netreq->response_len + , SECTION_NO_ADDITIONAL) ; i - ; i = rrset_iter_next(i)) { + ; i = _getdns_rrset_iter_next(i)) { - rrset = rrset_iter_value(i); + rrset = _getdns_rrset_iter_value(i); if (rrset->rr_type != GETDNS_RRTYPE_DS && rrset->rr_type != GETDNS_RRTYPE_NSEC && rrset->rr_type != GETDNS_RRTYPE_NSEC3) continue; - for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset) - ; rrsig; rrsig = rrsig_iter_next(rrsig)) { + for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset) + ; rrsig; rrsig = _getdns_rrsig_iter_next(rrsig)) { val_chain_sched_signer_node(node, rrsig); n_signers++; @@ -1340,12 +1110,22 @@ static void val_chain_node_soa_cb(getdns_dns_req *dnsreq) { chain_node *node = (chain_node *)dnsreq->user_pointer; getdns_network_req *netreq = dnsreq->netreqs[0]; - rrset_iter i_spc; - getdns_rrset *rrset; + _getdns_rrset_iter i_spc, *i; + _getdns_rrset *rrset; _getdns_context_clear_outbound_request(dnsreq); - if ((rrset = rrset_by_type(&i_spc, netreq, GETDNS_RRTYPE_SOA))) { + for ( i = _getdns_rrset_iter_init(&i_spc, netreq->response + , netreq->response_len + , SECTION_ANSWER) + ; i + ; i = _getdns_rrset_iter_next(i)) { + + rrset = _getdns_rrset_iter_value(i); + if (rrset->rr_type == GETDNS_RRTYPE_SOA) + break; + } + if (i) { while (node && ! _dname_equal(node->ds.name, rrset->name)) @@ -1377,10 +1157,10 @@ static void val_chain_node_soa_cb(getdns_dns_req *dnsreq) /* Returns whether a key in set dnskey is used to sign rrset. * Only keytag and signer name is compared. The signature is not verified. */ -static int key_matches_signer(getdns_rrset *dnskey, getdns_rrset *rrset) +static int key_matches_signer(_getdns_rrset *dnskey, _getdns_rrset *rrset) { - rrtype_iter rr_spc, *rr; - rrsig_iter rrsig_spc, *rrsig; + _getdns_rrtype_iter rr_spc, *rr; + _getdns_rrsig_iter rrsig_spc, *rrsig; uint16_t keytag; _getdns_rdf_iter rdf_spc, *rdf; uint8_t signer_spc[256]; @@ -1390,8 +1170,8 @@ static int key_matches_signer(getdns_rrset *dnskey, getdns_rrset *rrset) assert(dnskey->rr_type == GETDNS_RRTYPE_DNSKEY); - for ( rr = rrtype_iter_init(&rr_spc, dnskey) - ; rr ; rr = rrtype_iter_next(rr) ) { + for ( rr = _getdns_rrtype_iter_init(&rr_spc, dnskey) + ; rr ; rr = _getdns_rrtype_iter_next(rr) ) { /* Enough space to at least read algorithm field? */ @@ -1403,8 +1183,8 @@ static int key_matches_signer(getdns_rrset *dnskey, getdns_rrset *rrset) (UNCONST_UINT8_p)rr->rr_i.rr_type + 10, rr->rr_i.nxt - rr->rr_i.rr_type - 10); - for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset) - ; rrsig ; rrsig = rrsig_iter_next(rrsig) ) { + for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset) + ; rrsig ; rrsig = _getdns_rrsig_iter_next(rrsig) ) { if (/* Space for keytag & signer in rrsig rdata? */ rrsig->rr_i.nxt >= rrsig->rr_i.rr_type + 28 @@ -1431,7 +1211,7 @@ static int key_matches_signer(getdns_rrset *dnskey, getdns_rrset *rrset) return 0; } -static size_t _rr_uncompressed_rdata_size(rrtype_iter *rr) +static size_t _rr_uncompressed_rdata_size(_getdns_rrtype_iter *rr) { _getdns_rdf_iter *rdf, rdf_spc; uint8_t decompressed[256]; @@ -1452,7 +1232,7 @@ static size_t _rr_uncompressed_rdata_size(rrtype_iter *rr) return sz; } -static size_t _rr_rdata_size(rrtype_iter *rr) +static size_t _rr_rdata_size(_getdns_rrtype_iter *rr) { const _getdns_rr_def *rr_def; size_t i; @@ -1561,13 +1341,13 @@ static int _rr_iter_rdata_cmp(const void *a, const void *b) */ #define VAL_RRSET_SPC_SZ 1024 static int _getdns_verify_rrsig(struct mem_funcs *mf, - getdns_rrset *rrset, rrsig_iter *rrsig, rrtype_iter *key, const uint8_t **nc_name) + _getdns_rrset *rrset, _getdns_rrsig_iter *rrsig, _getdns_rrtype_iter *key, const uint8_t **nc_name) { int r; int to_skip; _getdns_rr_iter val_rrset_spc[VAL_RRSET_SPC_SZ]; _getdns_rr_iter *val_rrset = val_rrset_spc; - rrtype_iter rr_spc, *rr; + _getdns_rrtype_iter rr_spc, *rr; size_t n_rrs, i, valbuf_sz, owner_len; _getdns_rdf_iter *signer, signer_spc, *rdf, rdf_spc; uint8_t valbuf_spc[4096], *valbuf_buf = valbuf_spc; @@ -1590,9 +1370,9 @@ static int _getdns_verify_rrsig(struct mem_funcs *mf, return 0; for (;;) { - for ( rr = rrtype_iter_init(&rr_spc, rrset), n_rrs = 0 + for ( rr = _getdns_rrtype_iter_init(&rr_spc, rrset), n_rrs = 0 ; rr - ; rr = rrtype_iter_next(rr), n_rrs++) { + ; rr = _getdns_rrtype_iter_next(rr), n_rrs++) { if (val_rrset == val_rrset_spc) { valbuf_sz += owner_len @@ -1765,17 +1545,17 @@ static uint8_t *_getdns_nsec3_hash_label(uint8_t *label, size_t label_len, } static uint8_t *name2nsec3_label( - getdns_rrset *nsec3, const uint8_t *name, uint8_t *label, size_t label_len) + _getdns_rrset *nsec3, const uint8_t *name, uint8_t *label, size_t label_len) { - rrsig_iter rrsig_spc, *rrsig; + _getdns_rrsig_iter rrsig_spc, *rrsig; _getdns_rdf_iter rdf_spc, *rdf; uint8_t signer_spc[256]; const uint8_t *signer; size_t signer_len = sizeof(signer_spc); - rrtype_iter rr_spc, *rr; + _getdns_rrtype_iter rr_spc, *rr; if (/* With the "first" signature */ - (rrsig = rrsig_iter_init(&rrsig_spc, nsec3)) + (rrsig = _getdns_rrsig_iter_init(&rrsig_spc, nsec3)) /* Access the signer name rdata field (7th) */ && (rdf = _getdns_rdf_iter_init_at( @@ -1793,7 +1573,7 @@ static uint8_t *name2nsec3_label( && _dname_is_parent(signer, name) /* Initialize rr for getting NSEC3 rdata fields */ - && (rr = rrtype_iter_init(&rr_spc, nsec3)) + && (rr = _getdns_rrtype_iter_init(&rr_spc, nsec3)) /* Check for available space to get rdata fields */ && rr->rr_i.rr_type + 15 <= rr->rr_i.nxt @@ -1808,9 +1588,9 @@ static uint8_t *name2nsec3_label( } -static int nsec3_iteration_count_high(rrtype_iter *dnskey, getdns_rrset *nsec3) +static int nsec3_iteration_count_high(_getdns_rrtype_iter *dnskey, _getdns_rrset *nsec3) { - rrtype_iter rr_spc, *rr; + _getdns_rrtype_iter rr_spc, *rr; size_t bits; /* No NSEC3, then iteration count is not too high */ @@ -1824,7 +1604,7 @@ static int nsec3_iteration_count_high(rrtype_iter *dnskey, getdns_rrset *nsec3) return 1; if (/* Initialize rr for getting NSEC3 rdata fields */ - !(rr = rrtype_iter_init(&rr_spc, nsec3)) + !(rr = _getdns_rrtype_iter_init(&rr_spc, nsec3)) /* Check for available space to get rdata fields */ || rr->rr_i.rr_type + 14 > rr->rr_i.nxt) @@ -1851,9 +1631,9 @@ static int check_dates(int32_t now, int32_t skew, int32_t exp, int32_t inc) * expansion, nc_name will point to the next closer part of the name in rrset. */ static int dnskey_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew, - rrtype_iter *dnskey, getdns_rrset *rrset, const uint8_t **nc_name) + _getdns_rrtype_iter *dnskey, _getdns_rrset *rrset, const uint8_t **nc_name) { - rrsig_iter rrsig_spc, *rrsig; + _getdns_rrsig_iter rrsig_spc, *rrsig; _getdns_rdf_iter rdf_spc, *rdf; uint8_t signer_spc[256]; const uint8_t *signer; @@ -1873,8 +1653,8 @@ static int dnskey_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew, keytag = gldns_calc_keytag_raw((UNCONST_UINT8_p)dnskey->rr_i.rr_type + 10, dnskey->rr_i.nxt - dnskey->rr_i.rr_type - 10); - for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset) - ; rrsig ; rrsig = rrsig_iter_next(rrsig) ) { + for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset) + ; rrsig ; rrsig = _getdns_rrsig_iter_next(rrsig) ) { if (/* Space for keytag & signer in rrsig rdata? */ rrsig->rr_i.nxt >= rrsig->rr_i.rr_type + 28 @@ -1919,21 +1699,21 @@ static int dnskey_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew, } static int find_nsec_covering_name( - struct mem_funcs *mf, time_t now, uint32_t skew, getdns_rrset *dnskey, - getdns_rrset *rrset, const uint8_t *name, int *opt_out); + struct mem_funcs *mf, time_t now, uint32_t skew, _getdns_rrset *dnskey, + _getdns_rrset *rrset, const uint8_t *name, int *opt_out); /* Returns whether a dnskey for keyset signed rrset. */ static int a_key_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew, - getdns_rrset *keyset, getdns_rrset *rrset) + _getdns_rrset *keyset, _getdns_rrset *rrset) { - rrtype_iter dnskey_spc, *dnskey; + _getdns_rrtype_iter dnskey_spc, *dnskey; const uint8_t *nc_name; int keytag; assert(keyset->rr_type == GETDNS_RRTYPE_DNSKEY); - for ( dnskey = rrtype_iter_init(&dnskey_spc, keyset) - ; dnskey ; dnskey = rrtype_iter_next(dnskey) ) { + for ( dnskey = _getdns_rrtype_iter_init(&dnskey_spc, keyset) + ; dnskey ; dnskey = _getdns_rrtype_iter_next(dnskey) ) { if (!(keytag = dnskey_signed_rrset(mf, now, skew, dnskey, rrset, &nc_name))) @@ -1964,10 +1744,10 @@ static int a_key_signed_rrset(struct mem_funcs *mf, time_t now, uint32_t skew, * signed the dnskey set. */ static int ds_authenticates_keys(struct mem_funcs *mf, - time_t now, uint32_t skew, getdns_rrset *ds_set, getdns_rrset *dnskey_set) + time_t now, uint32_t skew, _getdns_rrset *ds_set, _getdns_rrset *dnskey_set) { - rrtype_iter dnskey_spc, *dnskey; - rrtype_iter ds_spc, *ds; + _getdns_rrtype_iter dnskey_spc, *dnskey; + _getdns_rrtype_iter ds_spc, *ds; uint16_t keytag; const uint8_t *nc_name; size_t valid_dsses = 0, supported_dsses = 0; @@ -1994,8 +1774,8 @@ static int ds_authenticates_keys(struct mem_funcs *mf, (void) memcpy(digest_buf_spc, dnskey_set->name, dnskey_owner_len); _dname_canonicalize2(digest_buf_spc); - for ( dnskey = rrtype_iter_init(&dnskey_spc, dnskey_set) - ; dnskey ; dnskey = rrtype_iter_next(dnskey)) { + for ( dnskey = _getdns_rrtype_iter_init(&dnskey_spc, dnskey_set) + ; dnskey ; dnskey = _getdns_rrtype_iter_next(dnskey)) { /* Enough space to at least read algorithm field? */ if (dnskey->rr_i.nxt < dnskey->rr_i.rr_type + 14) @@ -2005,8 +1785,8 @@ static int ds_authenticates_keys(struct mem_funcs *mf, (UNCONST_UINT8_p) dnskey->rr_i.rr_type + 10, dnskey->rr_i.nxt - dnskey->rr_i.rr_type - 10); - for ( ds = rrtype_iter_init(&ds_spc, ds_set) - ; ds ; ds = rrtype_iter_next(ds)) { + for ( ds = _getdns_rrtype_iter_init(&ds_spc, ds_set) + ; ds ; ds = _getdns_rrtype_iter_next(ds)) { if (/* Space for keytag, algorithm & digest type? */ ds->rr_i.nxt < ds->rr_i.rr_type + 14 @@ -2126,19 +1906,19 @@ static int ds_authenticates_keys(struct mem_funcs *mf, } static int nsec_covers_name( - getdns_rrset *nsec, const uint8_t *name, const uint8_t **ce_name) + _getdns_rrset *nsec, const uint8_t *name, const uint8_t **ce_name) { uint8_t owner_spc[256], next_spc[256]; const uint8_t *owner, *next; size_t owner_len = sizeof(owner_spc), next_len = sizeof(next_spc); - rrtype_iter rr_spc, *rr; + _getdns_rrtype_iter rr_spc, *rr; _getdns_rdf_iter rdf_spc, *rdf; int nsec_cmp; const uint8_t *common1, *common2; if (/* Get owner and next, nicely decompressed */ - !(rr = rrtype_iter_init(&rr_spc, nsec)) + !(rr = _getdns_rrtype_iter_init(&rr_spc, nsec)) || !(rdf = _getdns_rdf_iter_init(&rdf_spc, &rr->rr_i)) || !(owner = _getdns_owner_if_or_as_decompressed( &rr->rr_i, owner_spc, &owner_len)) @@ -2184,7 +1964,7 @@ static int nsec_covers_name( } } -static int nsec3_matches_name(getdns_rrset *nsec3, const uint8_t *name) +static int nsec3_matches_name(_getdns_rrset *nsec3, const uint8_t *name) { uint8_t label[64], owner[64]; @@ -2198,10 +1978,10 @@ static int nsec3_matches_name(getdns_rrset *nsec3, const uint8_t *name) } static int nsec3_covers_name( - getdns_rrset *nsec3, const uint8_t *name, int *opt_out) + _getdns_rrset *nsec3, const uint8_t *name, int *opt_out) { uint8_t label[65], next[65], owner[65]; - rrtype_iter rr_spc, *rr; + _getdns_rrtype_iter rr_spc, *rr; _getdns_rdf_iter rdf_spc, *rdf; int nsz = 0, nsec_cmp; @@ -2210,7 +1990,7 @@ static int nsec3_covers_name( label[label[0]+1] = 0; - if ( !(rr = rrtype_iter_init(&rr_spc, nsec3)) + if ( !(rr = _getdns_rrtype_iter_init(&rr_spc, nsec3)) || !(rdf = _getdns_rdf_iter_init_at(&rdf_spc, &rr->rr_i, 4)) || rdf->pos + *rdf->pos + 1 > rdf->nxt || (nsz = gldns_b32_ntop_extended_hex(rdf->pos + 1, *rdf->pos, @@ -2249,25 +2029,26 @@ static int nsec3_covers_name( } static int find_nsec_covering_name( - struct mem_funcs *mf, time_t now, uint32_t skew, getdns_rrset *dnskey, - getdns_rrset *rrset, const uint8_t *name, int *opt_out) + struct mem_funcs *mf, time_t now, uint32_t skew, _getdns_rrset *dnskey, + _getdns_rrset *rrset, const uint8_t *name, int *opt_out) { - rrset_iter i_spc, *i; - getdns_rrset *n; - rrtype_iter nsec_spc, *nsec_rr; + _getdns_rrset_iter i_spc, *i; + _getdns_rrset *n; + _getdns_rrtype_iter nsec_spc, *nsec_rr; _getdns_rdf_iter bitmap_spc, *bitmap; int keytag; if (opt_out) *opt_out = 0; - for ( i = rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len) - ; i ; i = rrset_iter_next(i)) { + for ( i = _getdns_rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len + , SECTION_NO_ADDITIONAL) + ; i ; i = _getdns_rrset_iter_next(i)) { - if ((n = rrset_iter_value(i))->rr_type == GETDNS_RRTYPE_NSEC3 + if ((n = _getdns_rrset_iter_value(i))->rr_type == GETDNS_RRTYPE_NSEC3 /* Get the bitmap rdata field */ - && (nsec_rr = rrtype_iter_init(&nsec_spc, n)) + && (nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, n)) && (bitmap = _getdns_rdf_iter_init_at( &bitmap_spc, &nsec_rr->rr_i, 5)) @@ -2300,11 +2081,11 @@ static int find_nsec_covering_name( return keytag; } - if ((n = rrset_iter_value(i))->rr_type == GETDNS_RRTYPE_NSEC + if ((n = _getdns_rrset_iter_value(i))->rr_type == GETDNS_RRTYPE_NSEC && nsec_covers_name(n, name, NULL) /* Get the bitmap rdata field */ - && (nsec_rr = rrtype_iter_init(&nsec_spc, n)) + && (nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, n)) && (bitmap = _getdns_rdf_iter_init_at( &bitmap_spc, &nsec_rr->rr_i, 1)) @@ -2347,7 +2128,7 @@ static int find_nsec_covering_name( static int nsec3_find_next_closer( struct mem_funcs *mf, time_t now, uint32_t skew, - getdns_rrset *dnskey, getdns_rrset *rrset, + _getdns_rrset *dnskey, _getdns_rrset *rrset, const uint8_t *nc_name, int *opt_out) { uint8_t wc_name[256] = { 1, (uint8_t)'*' }; @@ -2399,12 +2180,12 @@ static int nsec3_find_next_closer( */ static int key_proves_nonexistance( struct mem_funcs *mf, time_t now, uint32_t skew, - getdns_rrset *keyset, getdns_rrset *rrset, int *opt_out) + _getdns_rrset *keyset, _getdns_rrset *rrset, int *opt_out) { - getdns_rrset nsec_rrset, *cover, *ce; - rrtype_iter nsec_spc, *nsec_rr; + _getdns_rrset nsec_rrset, *cover, *ce; + _getdns_rrtype_iter nsec_spc, *nsec_rr; _getdns_rdf_iter bitmap_spc, *bitmap; - rrset_iter i_spc, *i; + _getdns_rrset_iter i_spc, *i; const uint8_t *ce_name, *nc_name; uint8_t wc_name[256] = { 1, (uint8_t)'*' }; int keytag; @@ -2423,7 +2204,7 @@ static int key_proves_nonexistance( nsec_rrset.rr_type = GETDNS_RRTYPE_NSEC; if (/* A NSEC RR exists at the owner name of rrset */ - (nsec_rr = rrtype_iter_init(&nsec_spc, &nsec_rrset)) + (nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, &nsec_rrset)) /* Get the bitmap rdata field */ && (bitmap = _getdns_rdf_iter_init_at( @@ -2479,10 +2260,11 @@ static int key_proves_nonexistance( * ======================== * - First find the NSEC that covers the owner name. */ - for ( i = rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len) - ; i ; i = rrset_iter_next(i)) { + for ( i = _getdns_rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len + , SECTION_NO_ADDITIONAL) + ; i ; i = _getdns_rrset_iter_next(i)) { - cover = rrset_iter_value(i); + cover = _getdns_rrset_iter_value(i); if (/* Is cover an NSEC rrset? */ cover->rr_type != GETDNS_RRTYPE_NSEC @@ -2494,7 +2276,7 @@ static int key_proves_nonexistance( || _dname_equal(cover->name, rrset->name) /* Get the bitmap rdata field */ - || !(nsec_rr = rrtype_iter_init(&nsec_spc, cover)) + || !(nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, cover)) || !(bitmap = _getdns_rdf_iter_init_at( &bitmap_spc, &nsec_rr->rr_i, 1)) @@ -2549,19 +2331,20 @@ static int key_proves_nonexistance( * ===================== * NSEC3 has same (hashed) ownername as the rrset to deny. */ - for ( i = rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len) - ; i ; i = rrset_iter_next(i)) { + for ( i = _getdns_rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len + , SECTION_NO_ADDITIONAL) + ; i ; i = _getdns_rrset_iter_next(i)) { /* ce is potentially the NSEC3 that matches complete qname * (so is also the closest encloser) */ - ce = rrset_iter_value(i); + ce = _getdns_rrset_iter_value(i); if ( ce->rr_type == GETDNS_RRTYPE_NSEC3 /* A NSEC3 RR exists at the owner name of rrset * (this is always true) */ - && (nsec_rr = rrtype_iter_init(&nsec_spc, ce)) + && (nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, ce)) /* Get the bitmap rdata field */ && (bitmap = _getdns_rdf_iter_init_at( @@ -2621,14 +2404,15 @@ static int key_proves_nonexistance( for ( nc_name = rrset->name, ce_name = rrset->name + *rrset->name + 1 ; *ce_name ; nc_name = ce_name, ce_name += *ce_name + 1) { - for ( i = rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len) - ; i ; i = rrset_iter_next(i)) { + for ( i = _getdns_rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len + , SECTION_NO_ADDITIONAL) + ; i ; i = _getdns_rrset_iter_next(i)) { - if ( !(ce = rrset_iter_value(i)) + if ( !(ce = _getdns_rrset_iter_value(i)) || ce->rr_type != GETDNS_RRTYPE_NSEC3 /* Get the bitmap rdata field */ - || !(nsec_rr = rrtype_iter_init(&nsec_spc, ce)) + || !(nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, ce)) || !(bitmap = _getdns_rdf_iter_init_at( &bitmap_spc, &nsec_rr->rr_i, 1)) @@ -2678,7 +2462,7 @@ static int key_proves_nonexistance( */ static int chain_node_get_trusted_keys( struct mem_funcs *mf, time_t now, uint32_t skew, - chain_node *node, getdns_rrset *ta, getdns_rrset **keys) + chain_node *node, _getdns_rrset *ta, _getdns_rrset **keys) { int s, keytag; @@ -2765,7 +2549,7 @@ static int chain_node_get_trusted_keys( * an empty DS for this name in the validation chain... so it can * be used for the support_records parameter. */ - if (node->ds_req || rrset_has_rrs(&node->ds)) + if (node->ds_req || _getdns_rrset_has_rrs(&node->ds)) return GETDNS_DNSSEC_BOGUS; /* Not at a zone cut, the trusted keyset must be authenticating @@ -2779,9 +2563,9 @@ static int chain_node_get_trusted_keys( * evaluated. */ static int chain_head_validate_with_ta(struct mem_funcs *mf, - time_t now, uint32_t skew, chain_head *head, getdns_rrset *ta) + time_t now, uint32_t skew, chain_head *head, _getdns_rrset *ta) { - getdns_rrset *keys; + _getdns_rrset *keys; int s, keytag, opt_out; debug_sec_print_rrset("validating ", &head->rrset); @@ -2791,13 +2575,13 @@ static int chain_head_validate_with_ta(struct mem_funcs *mf, mf, now, skew, head->parent, ta, &keys)) != GETDNS_DNSSEC_SECURE) return s; - if (rrset_has_rrs(&head->rrset)) { + if (_getdns_rrset_has_rrs(&head->rrset)) { if ((keytag = a_key_signed_rrset( mf, now, skew, keys, &head->rrset))) { head->signer = keytag; return GETDNS_DNSSEC_SECURE; - } else if (!rrset_has_rrsigs(&head->rrset) + } else if (!_getdns_rrset_has_rrsigs(&head->rrset) && (keytag = key_proves_nonexistance(mf, now, skew, keys, &head->rrset, &opt_out)) && opt_out) { @@ -2818,19 +2602,19 @@ static int chain_head_validate_with_ta(struct mem_funcs *mf, * anchors in tas in turn. The best outcome counts. */ static int chain_head_validate(struct mem_funcs *mf, time_t now, uint32_t skew, - chain_head *head, rrset_iter *tas) + chain_head *head, _getdns_rrset_iter *tas) { - rrset_iter *i; - getdns_rrset *ta, dnskey_ta, ds_ta; - rrset_iter closest_ta; + _getdns_rrset_iter *i; + _getdns_rrset *ta, dnskey_ta, ds_ta; + _getdns_rrset_iter closest_ta; int closest_labels, s = GETDNS_DNSSEC_INDETERMINATE; size_t ta_labels, supported_algorithms; - rrtype_iter rr_spc, *rr; + _getdns_rrtype_iter rr_spc, *rr; /* Find the TA closest to the head's RRset name */ closest_labels = -1; - for (i = rrset_iter_rewind(tas); i ;i = rrset_iter_next(i)) { - ta = rrset_iter_value(i); + for (i = _getdns_rrset_iter_rewind(tas); i ;i = _getdns_rrset_iter_next(i)) { + ta = _getdns_rrset_iter_value(i); if ((ta->rr_type == GETDNS_RRTYPE_DNSKEY || ta->rr_type == GETDNS_RRTYPE_DS) @@ -2848,19 +2632,19 @@ static int chain_head_validate(struct mem_funcs *mf, time_t now, uint32_t skew, if (closest_labels == -1) return GETDNS_DNSSEC_INDETERMINATE; - ta = rrset_iter_value(&closest_ta); + ta = _getdns_rrset_iter_value(&closest_ta); dnskey_ta = *ta; dnskey_ta.rr_type = GETDNS_RRTYPE_DNSKEY; ds_ta = *ta; ds_ta.rr_type = GETDNS_RRTYPE_DS; - if (!rrset_has_rrs(&dnskey_ta)) + if (!_getdns_rrset_has_rrs(&dnskey_ta)) return chain_head_validate_with_ta(mf,now,skew,head,&ds_ta); /* Does the selected DNSKEY set have supported algorithms? */ supported_algorithms = 0; - for ( rr = rrtype_iter_init(&rr_spc, ta) - ; rr; rr = rrtype_iter_next(rr)) { + for ( rr = _getdns_rrtype_iter_init(&rr_spc, ta) + ; rr; rr = _getdns_rrtype_iter_next(rr)) { if ( rr->rr_i.rr_type + 14 <= rr->rr_i.nxt && _getdns_dnskey_algo_id_is_supported( @@ -2869,14 +2653,14 @@ static int chain_head_validate(struct mem_funcs *mf, time_t now, uint32_t skew, supported_algorithms++; } if (!supported_algorithms) { - if (rrset_has_rrs(&ds_ta)) + if (_getdns_rrset_has_rrs(&ds_ta)) return chain_head_validate_with_ta( mf, now, skew, head, &ds_ta); return GETDNS_DNSSEC_INSECURE; } s = chain_head_validate_with_ta(mf, now, skew, head, &dnskey_ta); - if (rrset_has_rrs(&ds_ta)) { + if (_getdns_rrset_has_rrs(&ds_ta)) { switch (chain_head_validate_with_ta(mf,now,skew,head,&ds_ta)) { case GETDNS_DNSSEC_SECURE : s = GETDNS_DNSSEC_SECURE; case GETDNS_DNSSEC_INSECURE: if (s != GETDNS_DNSSEC_SECURE) @@ -2896,7 +2680,7 @@ static int chain_head_validate(struct mem_funcs *mf, time_t now, uint32_t skew, * evaluated by processing each head in turn. The worst outcome per network request * is the dnssec status for that network request. */ -static void chain_set_netreq_dnssec_status(chain_head *chain, rrset_iter *tas) +static void chain_set_netreq_dnssec_status(chain_head *chain, _getdns_rrset_iter *tas) { chain_head *head; @@ -2938,7 +2722,7 @@ static void chain_set_netreq_dnssec_status(chain_head *chain, rrset_iter *tas) * the whole. */ static int chain_validate_dnssec(struct mem_funcs *mf, - time_t now, uint32_t skew, chain_head *chain, rrset_iter *tas) + time_t now, uint32_t skew, chain_head *chain, _getdns_rrset_iter *tas) { int s = GETDNS_DNSSEC_INDETERMINATE, t; chain_head *head; @@ -3005,7 +2789,7 @@ static size_t count_outstanding_requests(chain_head *head) return count + count_outstanding_requests(head->next); } -static int rrset_in_list(getdns_rrset *rrset, getdns_list *list) +static int rrset_in_list(_getdns_rrset *rrset, getdns_list *list) { size_t i; getdns_dict *rr_dict; @@ -3026,27 +2810,27 @@ static int rrset_in_list(getdns_rrset *rrset, getdns_list *list) } static void append_rrset2val_chain_list( - getdns_list *val_chain_list, getdns_rrset *rrset, int signer) + getdns_list *val_chain_list, _getdns_rrset *rrset, int signer) { _getdns_rr_iter val_rrset_spc[VAL_RRSET_SPC_SZ]; _getdns_rr_iter *val_rrset = val_rrset_spc; - rrtype_iter rr_spc, *rr; + _getdns_rrtype_iter rr_spc, *rr; size_t n_rrs, i; uint32_t orig_ttl; getdns_dict *rr_dict; - rrsig_iter *rrsig, rrsig_spc; + _getdns_rrsig_iter *rrsig, rrsig_spc; assert(val_chain_list && rrset); if (signer < 0) return; - for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset) + for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset) ; rrsig && ( rrsig->rr_i.nxt < rrsig->rr_i.rr_type + 28 || gldns_read_uint16(rrsig->rr_i.rr_type + 26) != (signer & 0xFFFF)) - ; rrsig = rrsig_iter_next(rrsig)) + ; rrsig = _getdns_rrsig_iter_next(rrsig)) ; /* pass */ if (!rrsig) @@ -3058,9 +2842,9 @@ static void append_rrset2val_chain_list( orig_ttl = gldns_read_uint32(rrsig->rr_i.rr_type + 14); for (;;) { - for ( rr = rrtype_iter_init(&rr_spc, rrset), n_rrs = 0 + for ( rr = _getdns_rrtype_iter_init(&rr_spc, rrset), n_rrs = 0 ; rr - ; rr = rrtype_iter_next(rr), n_rrs++) { + ; rr = _getdns_rrtype_iter_next(rr), n_rrs++) { if (n_rrs < VAL_RRSET_SPC_SZ || val_rrset != val_rrset_spc) @@ -3099,17 +2883,19 @@ static void append_rrset2val_chain_list( static void append_rrs2val_chain_list(getdns_context *ctxt, getdns_list *val_chain_list, getdns_network_req *netreq, int signer) { - rrset_iter *i, i_spc; - getdns_rrset *rrset; - rrtype_iter *rr, rr_spc; - rrsig_iter *rrsig, rrsig_spc; + _getdns_rrset_iter *i, i_spc; + _getdns_rrset *rrset; + _getdns_rrtype_iter *rr, rr_spc; + _getdns_rrsig_iter *rrsig, rrsig_spc; getdns_dict *rr_dict; - for ( i = rrset_iter_init(&i_spc,netreq->response,netreq->response_len) + for ( i = _getdns_rrset_iter_init(&i_spc, netreq->response + , netreq->response_len + , SECTION_NO_ADDITIONAL) ; i - ; i = rrset_iter_next(i)) { + ; i = _getdns_rrset_iter_next(i)) { - rrset = rrset_iter_value(i); + rrset = _getdns_rrset_iter_value(i); if (rrset->rr_type == GETDNS_RRTYPE_NSEC || rrset->rr_type == GETDNS_RRTYPE_NSEC3) { @@ -3130,8 +2916,8 @@ static void append_rrs2val_chain_list(getdns_context *ctxt, val_chain_list, rrset, signer); continue; } - for ( rr = rrtype_iter_init(&rr_spc, rrset) - ; rr; rr = rrtype_iter_next(rr)) { + for ( rr = _getdns_rrtype_iter_init(&rr_spc, rrset) + ; rr; rr = _getdns_rrtype_iter_next(rr)) { if (!(rr_dict = _getdns_rr_iter2rr_dict( &ctxt->mf, &rr->rr_i))) @@ -3140,8 +2926,8 @@ static void append_rrs2val_chain_list(getdns_context *ctxt, if (_getdns_list_append_this_dict(val_chain_list, rr_dict)) getdns_dict_destroy(rr_dict); } - for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset) - ; rrsig; rrsig = rrsig_iter_next(rrsig)) { + for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset) + ; rrsig; rrsig = _getdns_rrsig_iter_next(rrsig)) { if (!(rr_dict = _getdns_rr_iter2rr_dict( &ctxt->mf, &rrsig->rr_i))) @@ -3154,7 +2940,7 @@ static void append_rrs2val_chain_list(getdns_context *ctxt, } static void append_empty_ds2val_chain_list( - getdns_context *context, getdns_list *val_chain_list, getdns_rrset *ds) + getdns_context *context, getdns_list *val_chain_list, _getdns_rrset *ds) { getdns_dict *rr_dict; getdns_bindata bindata; @@ -3192,7 +2978,7 @@ static void check_chain_complete(chain_head *chain) chain_node *node; getdns_list *val_chain_list; getdns_dict *response_dict; - rrset_iter tas_iter; + _getdns_rrset_iter tas_iter; if ((o = count_outstanding_requests(chain)) > 0) { DEBUG_SEC(PRIsz" outstanding requests\n", o); @@ -3213,17 +2999,19 @@ static void check_chain_complete(chain_head *chain) || dnsreq->dnssec_return_validation_chain) && context->trust_anchors) - chain_set_netreq_dnssec_status(chain,rrset_iter_init(&tas_iter, - context->trust_anchors, context->trust_anchors_len)); + chain_set_netreq_dnssec_status(chain,_getdns_rrset_iter_init(&tas_iter, + context->trust_anchors, context->trust_anchors_len, + SECTION_ANSWER)); #else if (dnsreq->dnssec_return_validation_chain && context->trust_anchors) (void) chain_validate_dnssec(priv_getdns_context_mf(context), time(NULL), context->dnssec_allowed_skew, - chain, rrset_iter_init( &tas_iter + chain, _getdns_rrset_iter_init( &tas_iter , context->trust_anchors - , context->trust_anchors_len)); + , context->trust_anchors_len + , SECTION_ANSWER)); #endif #ifdef DNSSEC_ROADBLOCK_AVOIDANCE if ( dnsreq->dnssec_roadblock_avoidance @@ -3285,7 +3073,7 @@ static void check_chain_complete(chain_head *chain) node->ds_req, node->ds_signer); if (val_chain_list && node->ds_signer == -1 && - !rrset_has_rrs(&node->ds)) { + !_getdns_rrset_has_rrs(&node->ds)) { /* Add empty DS, to prevent less * specific to be able to authenticate * below a zone cut (closer to head) @@ -3377,7 +3165,7 @@ static int wire_validate_dnssec(struct mem_funcs *mf, uint16_t qtype = 0, qclass = GETDNS_RRCLASS_IN; _getdns_rr_iter rr_spc, *rr; - rrset_iter tas_iter; + _getdns_rrset_iter tas_iter; int s; @@ -3407,7 +3195,7 @@ static int wire_validate_dnssec(struct mem_funcs *mf, /* For each question in the question section add a chain head. */ if ( (rr = _getdns_rr_iter_init(&rr_spc, to_val, to_val_len)) - && _getdns_rr_iter_section(rr) == GLDNS_SECTION_QUESTION + && _getdns_rr_iter_section(rr) == SECTION_QUESTION && (qname = _getdns_owner_if_or_as_decompressed( rr, qname_spc, &qname_len)) && rr->nxt >= rr->rr_type + 4) { @@ -3429,8 +3217,9 @@ static int wire_validate_dnssec(struct mem_funcs *mf, node->ds.pkt_len = support_len; } } - s = chain_validate_dnssec( - mf, now, skew, chain, rrset_iter_init(&tas_iter, tas, tas_len)); + s = chain_validate_dnssec(mf, now, skew, chain, + _getdns_rrset_iter_init( + &tas_iter, tas, tas_len, SECTION_ANSWER)); /* Cleanup the chain */ for (head = chain; head; head = next_head) { diff --git a/src/general.c b/src/general.c index 1119106d..fa07f982 100644 --- a/src/general.c +++ b/src/general.c @@ -108,11 +108,11 @@ no_answer(getdns_dns_req *dns_req) , netreq->response , netreq->response_len) ; rr && _getdns_rr_iter_section(rr) - <= GLDNS_SECTION_ANSWER + <= SECTION_ANSWER ; rr = _getdns_rr_iter_next(rr)) { if (_getdns_rr_iter_section(rr) != - GLDNS_SECTION_ANSWER) + SECTION_ANSWER) continue; if (gldns_read_uint16(rr->rr_type) != @@ -137,11 +137,11 @@ no_answer(getdns_dns_req *dns_req) , netreq->response , netreq->response_len) ; rr && _getdns_rr_iter_section(rr) - <= GLDNS_SECTION_ANSWER + <= SECTION_ANSWER ; rr = _getdns_rr_iter_next(rr)) { if (_getdns_rr_iter_section(rr) != - GLDNS_SECTION_ANSWER) + SECTION_ANSWER) continue; if (gldns_read_uint16(rr->rr_type) != diff --git a/src/request-internal.c b/src/request-internal.c index b36cb85e..df5d14c6 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -478,7 +478,7 @@ _getdns_network_validate_tsig(getdns_network_req *req) ; rr ; rr = _getdns_rr_iter_next(rr)) { - if (_getdns_rr_iter_section(rr) == GLDNS_SECTION_ADDITIONAL && + if (_getdns_rr_iter_section(rr) == SECTION_ADDITIONAL && gldns_read_uint16(rr->rr_type) == GETDNS_RRTYPE_TSIG) break; } @@ -501,7 +501,7 @@ _getdns_network_validate_tsig(getdns_network_req *req) ; rr ; rr = _getdns_rr_iter_next(rr)) { - if (_getdns_rr_iter_section(rr) == GLDNS_SECTION_ADDITIONAL && + if (_getdns_rr_iter_section(rr) == SECTION_ADDITIONAL && gldns_read_uint16(rr->rr_type) == GETDNS_RRTYPE_TSIG) break; } diff --git a/src/rr-iter.c b/src/rr-iter.c index 1615d761..999d9607 100644 --- a/src/rr-iter.c +++ b/src/rr-iter.c @@ -31,8 +31,25 @@ #include "rr-iter.h" #include "config.h" +#include #include "gldns/rrdef.h" +int +_getdns_dname_equal(const uint8_t *s1, const uint8_t *s2) +{ + uint8_t i; + for (;;) { + if (*s1 != *s2) + return 0; + else if (!*s1) + return 1; + for (i = *s1++, s2++; i > 0; i--, s1++, s2++) + if (*s1 != *s2 && tolower((unsigned char)*s1) + != tolower((unsigned char)*s2)) + return 0; + } +} + static void rr_iter_find_nxt(_getdns_rr_iter *i) { @@ -118,15 +135,6 @@ _getdns_single_rr_iter_init( return find_rrtype(i); } - -_getdns_rr_iter * -_getdns_rr_iter_rewind(_getdns_rr_iter *i) -{ - assert(i); - - return _getdns_rr_iter_init(i, i->pkt, i->pkt_end - i->pkt); -} - _getdns_rr_iter * _getdns_rr_iter_next(_getdns_rr_iter *i) { @@ -232,6 +240,179 @@ _getdns_owner_if_or_as_decompressed(_getdns_rr_iter *i, ff_bytes, len, 0); } + +/* Utility function to compare owner name of rr with name */ +static int rr_owner_equal(_getdns_rr_iter *rr, const uint8_t *name) +{ + uint8_t owner_spc[256]; + const uint8_t *owner; + size_t owner_len = sizeof(owner_spc); + + return (owner = _getdns_owner_if_or_as_decompressed(rr, owner_spc + ,&owner_len)) + && _getdns_dname_equal(owner, name); +} + +/* First a few filter functions that filter a RR iterator to point only + * to RRs with certain constraints (and moves on otherwise). + */ + +/* Filter that only iterates over the sections */ +static inline _getdns_rr_iter *rr_iter_section( + _getdns_rr_iter *rr, _getdns_section sections) +{ + while (rr && rr->pos && !(sections & _getdns_rr_iter_section(rr))) + rr = _getdns_rr_iter_next(rr); + + return rr && rr->pos ? rr : NULL; +} + +/* Filter that only iterates over RRs with a certain name/class/type */ +static _getdns_rr_iter *rr_iter_name_class_type(_getdns_rr_iter *rr, + const uint8_t *name, uint16_t rr_class, uint16_t rr_type, + _getdns_section sections) +{ + while (rr_iter_section(rr, sections) && !( + rr_iter_type(rr) == rr_type && + rr_iter_class(rr) == rr_class && + rr_owner_equal(rr, name))) + + rr = _getdns_rr_iter_next(rr); + + return rr && rr->pos ? rr : NULL; +} + +/* Filter that only iterates over RRs that do not have a name/class/type */ +static _getdns_rr_iter *rr_iter_not_name_class_type(_getdns_rr_iter *rr, + const uint8_t *name, uint16_t rr_class, uint16_t rr_type, + _getdns_section sections) +{ + while (rr_iter_section(rr, sections) && ( + rr_iter_type(rr) == GETDNS_RRTYPE_RRSIG || ( + rr_iter_type(rr) == rr_type && + rr_iter_class(rr) == rr_class && + rr_owner_equal(rr, name)))) + + rr = _getdns_rr_iter_next(rr); + + return rr && rr->pos ? rr : NULL; +} + +/* Filter that only iterates over RRs that are of type RRSIG, that cover + * a RRset with a certain name/class/type + */ +static _getdns_rr_iter *rr_iter_rrsig_covering(_getdns_rr_iter *rr, + const uint8_t *name, uint16_t rr_class, uint16_t rr_type, + _getdns_section sections) +{ + while (rr_iter_section(rr, sections) && !( + rr_iter_type(rr) == GETDNS_RRTYPE_RRSIG && + rr_iter_class(rr) == rr_class && + rr->rr_type + 12 <= rr->nxt && + gldns_read_uint16(rr->rr_type + 10) == rr_type && + rr_owner_equal(rr, name))) + + rr = _getdns_rr_iter_next(rr); + + return rr && rr->pos ? rr : NULL; +} + +_getdns_rrtype_iter * +_getdns_rrtype_iter_next(_getdns_rrtype_iter *i) +{ + return (_getdns_rrtype_iter *) rr_iter_name_class_type( + _getdns_rr_iter_next(&i->rr_i), + i->rrset->name, i->rrset->rr_class, i->rrset->rr_type, + i->rrset->sections); +} + +_getdns_rrtype_iter * +_getdns_rrtype_iter_init(_getdns_rrtype_iter *i, _getdns_rrset *rrset) +{ + i->rrset = rrset; + return (_getdns_rrtype_iter *) rr_iter_name_class_type( + _getdns_rr_iter_init(&i->rr_i, rrset->pkt, rrset->pkt_len ), + i->rrset->name, i->rrset->rr_class, i->rrset->rr_type, + i->rrset->sections); +} + +_getdns_rrsig_iter * +_getdns_rrsig_iter_next(_getdns_rrsig_iter *i) +{ + return (_getdns_rrsig_iter *) rr_iter_rrsig_covering( + _getdns_rr_iter_next(&i->rr_i), + i->rrset->name, i->rrset->rr_class, i->rrset->rr_type, + i->rrset->sections); +} + +_getdns_rrsig_iter * +_getdns_rrsig_iter_init(_getdns_rrsig_iter *i, _getdns_rrset *rrset) +{ + i->rrset = rrset; + return (_getdns_rrsig_iter *) rr_iter_rrsig_covering( + _getdns_rr_iter_init(&i->rr_i, rrset->pkt, rrset->pkt_len), + i->rrset->name, i->rrset->rr_class, i->rrset->rr_type, + i->rrset->sections); +} + +_getdns_rrset_iter * +_getdns_rrset_iter_init(_getdns_rrset_iter *i, + const uint8_t *pkt, size_t pkt_len, _getdns_section sections) +{ + _getdns_rr_iter *rr; + + i->rrset.name = i->name_spc; + i->rrset.pkt = pkt; + i->rrset.pkt_len = pkt_len; + i->rrset.sections = sections; + i->name_len = 0; + + for ( rr = _getdns_rr_iter_init(&i->rr_i, pkt, pkt_len) + ;(rr = rr_iter_section(rr, sections)) + ; rr = _getdns_rr_iter_next(rr)) { + + if ((i->rrset.rr_type = rr_iter_type(rr)) + == GETDNS_RRTYPE_RRSIG) + continue; + + i->rrset.rr_class = rr_iter_class(rr); + + if (!(i->rrset.name = _getdns_owner_if_or_as_decompressed( + rr, i->name_spc, &i->name_len))) + continue; + + return i; + } + return NULL; +} + +_getdns_rrset_iter *_getdns_rrset_iter_next(_getdns_rrset_iter *i) +{ + _getdns_rr_iter *rr; + + if (!(rr = i && i->rr_i.pos ? &i->rr_i : NULL)) + return NULL; + + if (!(rr = rr_iter_not_name_class_type(rr, + i->rrset.name, i->rrset.rr_class, i->rrset.rr_type, + i->rrset.sections))) + return NULL; + + i->rrset.rr_type = rr_iter_type(rr); + i->rrset.rr_class = rr_iter_class(rr); + if (!(i->rrset.name = _getdns_owner_if_or_as_decompressed( + rr, i->name_spc, &i->name_len))) + + /* This is safe, because rr_iter_not_name_class_type will shift + * the iterator forward because at least name does not match. + * Goal is to skip broken compression pointer issues but keep + * processing the packet. + */ + return _getdns_rrset_iter_next(i); + + return i; +} + static _getdns_rdf_iter * rdf_iter_find_nxt(_getdns_rdf_iter *i) { @@ -299,7 +480,7 @@ _getdns_rdf_iter_init(_getdns_rdf_iter *i, _getdns_rr_iter *rr) i->end = NULL; /* rr_iter already done or in question section */ - if (!rr->pos || _getdns_rr_iter_section(rr) == GLDNS_SECTION_QUESTION) + if (!rr->pos || _getdns_rr_iter_section(rr) == SECTION_QUESTION) goto done; i->pkt = rr->pkt; diff --git a/src/rr-iter.h b/src/rr-iter.h index 85f70509..d9221df2 100644 --- a/src/rr-iter.h +++ b/src/rr-iter.h @@ -32,10 +32,20 @@ #ifndef RR_ITER_H_ #define RR_ITER_H_ -#include "getdns/getdns.h" #include "rr-dict.h" #include "gldns/pkthdr.h" -#include "gldns/gbuffer.h" + +typedef enum _getdns_section { + SECTION_QUESTION = 1, + SECTION_ANSWER = 2, + SECTION_AUTHORITY = 4, + SECTION_ADDITIONAL = 8, + SECTION_ANY = 15, + SECTION_NO_QUESTION = 14, + SECTION_NO_ADDITIONAL = 6 +} _getdns_section; + +int _getdns_dname_equal(const uint8_t *s1, const uint8_t *s2); typedef struct _getdns_rr_iter { const uint8_t *pkt; @@ -65,32 +75,102 @@ _getdns_rr_iter *_getdns_rr_iter_init(_getdns_rr_iter *i, _getdns_rr_iter *_getdns_single_rr_iter_init(_getdns_rr_iter *i, const uint8_t *wire, const size_t wire_len); -_getdns_rr_iter *_getdns_rr_iter_rewind(_getdns_rr_iter *i); +static inline _getdns_rr_iter *_getdns_rr_iter_rewind(_getdns_rr_iter *i) +{ return _getdns_rr_iter_init(i, i->pkt, i->pkt_end - i->pkt); } _getdns_rr_iter *_getdns_rr_iter_next(_getdns_rr_iter *i); const uint8_t *_getdns_owner_if_or_as_decompressed( _getdns_rr_iter *i, uint8_t *ff_bytes, size_t *len); -static inline gldns_pkt_section +static inline _getdns_section _getdns_rr_iter_section(_getdns_rr_iter *i) { - return !i->pkt ? (i->nxt - i->rr_type == 4 ? GLDNS_SECTION_QUESTION - : GLDNS_SECTION_ANSWER ) - : i->n < GLDNS_QDCOUNT(i->pkt) ? GLDNS_SECTION_QUESTION + return !i->pkt ? (i->nxt - i->rr_type == 4 ? SECTION_QUESTION + : SECTION_ANSWER ) + : i->n < GLDNS_QDCOUNT(i->pkt) ? SECTION_QUESTION : i->n < GLDNS_QDCOUNT(i->pkt) - + GLDNS_ANCOUNT(i->pkt) ? GLDNS_SECTION_ANSWER + + GLDNS_ANCOUNT(i->pkt) ? SECTION_ANSWER : i->n < GLDNS_QDCOUNT(i->pkt) + GLDNS_ANCOUNT(i->pkt) - + GLDNS_NSCOUNT(i->pkt) ? GLDNS_SECTION_AUTHORITY + + GLDNS_NSCOUNT(i->pkt) ? SECTION_AUTHORITY : i->n < GLDNS_QDCOUNT(i->pkt) + GLDNS_ANCOUNT(i->pkt) + GLDNS_NSCOUNT(i->pkt) - + GLDNS_ARCOUNT(i->pkt) ? GLDNS_SECTION_ADDITIONAL - : GLDNS_SECTION_ANY; + + GLDNS_ARCOUNT(i->pkt) ? SECTION_ADDITIONAL + : SECTION_ANY; } -typedef struct piv_getdns_rdf_iter { +/* Utility functions to read rr_type and rr_class from a rr iterator */ +static inline uint16_t rr_iter_type(_getdns_rr_iter *rr) +{ return rr->rr_type + 2 <= rr->nxt ? gldns_read_uint16(rr->rr_type) : 0; } + +static inline uint16_t rr_iter_class(_getdns_rr_iter *rr) +{ return rr->rr_type + 4 <= rr->nxt ? gldns_read_uint16(rr->rr_type + 2) : 0; } + + +typedef struct _getdns_rrset { + const uint8_t *name; + uint16_t rr_class; + uint16_t rr_type; + const uint8_t *pkt; + size_t pkt_len; + _getdns_section sections; +} _getdns_rrset; + +typedef struct _getdns_rrtype_iter { + _getdns_rr_iter rr_i; + _getdns_rrset *rrset; +} _getdns_rrtype_iter; + +_getdns_rrtype_iter *_getdns_rrtype_iter_init( + _getdns_rrtype_iter *i, _getdns_rrset *rrset); +_getdns_rrtype_iter *_getdns_rrtype_iter_next(_getdns_rrtype_iter *i); + +static inline int _getdns_rrset_has_rrs(_getdns_rrset *rrset) +{ + _getdns_rrtype_iter rr_spc; + return _getdns_rrtype_iter_init(&rr_spc, rrset) != NULL; +} + +typedef struct _getdns_rrsig_iter { + _getdns_rr_iter rr_i; + _getdns_rrset *rrset; +} _getdns_rrsig_iter; + +_getdns_rrsig_iter *_getdns_rrsig_iter_init( + _getdns_rrsig_iter *i, _getdns_rrset *rrset); +_getdns_rrsig_iter *_getdns_rrsig_iter_next(_getdns_rrsig_iter *i); + + +static inline int _getdns_rrset_has_rrsigs(_getdns_rrset *rrset) +{ + _getdns_rrsig_iter rrsig; + return _getdns_rrsig_iter_init(&rrsig, rrset) != NULL; +} + +/* The _getdns_rrset_iter manifests an iterator of a wireformat packet that + * will return all unique rrsets within that packet in turn. + */ +typedef struct _getdns_rrset_iter { + _getdns_rrset rrset; + uint8_t name_spc[256]; + size_t name_len; + _getdns_rr_iter rr_i; +} _getdns_rrset_iter; + + +_getdns_rrset_iter *_getdns_rrset_iter_init(_getdns_rrset_iter *i, + const uint8_t *pkt, size_t pkt_len, _getdns_section sections); +_getdns_rrset_iter *_getdns_rrset_iter_next(_getdns_rrset_iter *i); + +static inline _getdns_rrset *_getdns_rrset_iter_value(_getdns_rrset_iter *i) +{ return i && i->rr_i.pos ? &i->rrset : NULL; } + +static inline _getdns_rrset_iter *_getdns_rrset_iter_rewind(_getdns_rrset_iter *i) +{ return _getdns_rrset_iter_init(i, i->rrset.pkt, i->rrset.pkt_len, i->rrset.sections); } + +typedef struct _getdns_rdf_iter { const uint8_t *pkt; const uint8_t *pkt_end; const _getdns_rdata_def *rdd_pos; @@ -112,4 +192,5 @@ _getdns_rdf_iter *_getdns_rdf_iter_init_at(_getdns_rdf_iter *i, const uint8_t *_getdns_rdf_if_or_as_decompressed( _getdns_rdf_iter *i, uint8_t *ff_bytes, size_t *len); + #endif diff --git a/src/stub.c b/src/stub.c index ab7f1805..60ba12bc 100644 --- a/src/stub.c +++ b/src/stub.c @@ -225,8 +225,7 @@ match_edns_opt_rr(uint16_t code, uint8_t *response, size_t response_len, ; rr_iter ; rr_iter = _getdns_rr_iter_next(rr_iter)) { - if (_getdns_rr_iter_section(rr_iter) != - GLDNS_SECTION_ADDITIONAL) + if (_getdns_rr_iter_section(rr_iter) != SECTION_ADDITIONAL) continue; if (gldns_read_uint16(rr_iter->rr_type) != GETDNS_RRTYPE_OPT) diff --git a/src/util-internal.c b/src/util-internal.c index 5731fea9..ed4649c9 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -37,7 +37,6 @@ #include #include -#include #include "config.h" #include "getdns/getdns.h" #include "dict.h" @@ -178,7 +177,7 @@ _getdns_rr_iter2rr_dict_canonical( owner_len = bin_size; } /* question */ - if (_getdns_rr_iter_section(i) == GLDNS_SECTION_QUESTION) { + if (_getdns_rr_iter_section(i) == SECTION_QUESTION) { if (getdns_dict_set_int(rr_dict, "qtype", (uint32_t) gldns_read_uint16(i->rr_type)) || @@ -438,21 +437,6 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i) return _getdns_rr_iter2rr_dict_canonical(mf, i, NULL); } -int -_getdns_dname_equal(const uint8_t *s1, const uint8_t *s2) -{ - uint8_t i; - for (;;) { - if (*s1 != *s2) - return 0; - else if (!*s1) - return 1; - for (i = *s1++, s2++; i > 0; i--, s1++, s2++) - if (*s1 != *s2 && tolower((unsigned char)*s1) - != tolower((unsigned char)*s2)) - return 0; - } -} inline static getdns_dict * set_dict(getdns_dict **var, getdns_dict *value) @@ -478,6 +462,25 @@ inline static int has_all_numeric_label(const uint8_t *dname) return 0; } +typedef struct _srvs { + size_t capacity; + size_t count; + _getdns_rr_iter *rrs; +} _srvs; + +static int _grow_srvs(struct mem_funcs *mf, _srvs *srvs) +{ + _getdns_rr_iter *new_rrs; + + if (!(new_rrs = GETDNS_XREALLOC( + *mf, srvs->rrs, _getdns_rr_iter, srvs->capacity * 2))) + return 0; /* Memory error */ + + srvs->capacity *= 2; + srvs->rrs = new_rrs; + return 1; /* Success */ +} + #define SET_WIRE_INT(X,Y) if (getdns_dict_set_int(header, #X , (int) \ GLDNS_ ## Y ## _WIRE(req->response))) goto error #define SET_WIRE_BIT(X,Y) if (getdns_dict_set_int(header, #X , \ @@ -485,9 +488,9 @@ inline static int has_all_numeric_label(const uint8_t *dname) #define SET_WIRE_CNT(X,Y) if (getdns_dict_set_int(header, #X , (int) \ GLDNS_ ## Y (req->response))) goto error -getdns_dict * +static getdns_dict * _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, - getdns_list *just_addrs, int *rrsigs_in_answer) + getdns_list *just_addrs, int *rrsigs_in_answer, _srvs *srvs) { /* turn a packet into this glorious structure * @@ -531,17 +534,20 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, getdns_return_t r = GETDNS_RETURN_GOOD; getdns_dict *result = getdns_dict_create_with_context(context); getdns_dict *question = NULL; - getdns_list *sections[4] = { NULL - , getdns_list_create_with_context(context) - , getdns_list_create_with_context(context) - , getdns_list_create_with_context(context) - }; + getdns_list *sections[16] = { NULL, NULL + , getdns_list_create_with_context(context) + , NULL + , getdns_list_create_with_context(context) + , NULL, NULL, NULL + , getdns_list_create_with_context(context) + , NULL, NULL, NULL, NULL, NULL, NULL, NULL + }; getdns_dict *rr_dict = NULL; _getdns_rr_iter rr_iter_storage, *rr_iter; _getdns_rdf_iter rdf_iter_storage, *rdf_iter; size_t bin_size; const uint8_t *bin_data; - gldns_pkt_section section; + _getdns_section section; uint8_t canonical_name_space[256], owner_name_space[256], query_name_space[256]; const uint8_t *canonical_name, *owner_name, *query_name; @@ -605,7 +611,7 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, continue; section = _getdns_rr_iter_section(rr_iter); - if (section == GLDNS_SECTION_QUESTION) { + if (section == SECTION_QUESTION) { if (!query_name) query_name = _getdns_owner_if_or_as_decompressed( @@ -617,11 +623,11 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, continue; } rr_type = gldns_read_uint16(rr_iter->rr_type); - if (section > GLDNS_SECTION_QUESTION && + if (section > SECTION_QUESTION && rr_type == GETDNS_RRTYPE_RRSIG && rrsigs_in_answer) *rrsigs_in_answer = 1; - if (section != GLDNS_SECTION_ANSWER) { + if (section != SECTION_ANSWER) { if (_getdns_list_append_this_dict( sections[section], rr_dict)) goto error; @@ -637,7 +643,7 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, continue; } if (_getdns_list_append_this_dict( - sections[GLDNS_SECTION_ANSWER], rr_dict)) + sections[SECTION_ANSWER], rr_dict)) goto error; else rr_dict = NULL; @@ -658,17 +664,24 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, rdf_iter,canonical_name_space,&canonical_name_len); continue; } + if (srvs->capacity && rr_type == GETDNS_RRTYPE_SRV) { + if (srvs->count >= srvs->capacity && + !_grow_srvs(&context->mf, srvs)) + goto error; + srvs->rrs[srvs->count++] = *rr_iter; + continue; + } if (rr_type != GETDNS_RRTYPE_A && rr_type != GETDNS_RRTYPE_AAAA) continue; + if (!just_addrs) + continue; + if (!(rdf_iter = _getdns_rdf_iter_init( &rdf_iter_storage, rr_iter))) continue; - if (!just_addrs) - continue; - bin_size = rdf_iter->nxt - rdf_iter->pos; bin_data = rdf_iter->pos; if (!set_dict(&rr_dict, getdns_dict_create_with_context(context)) || @@ -686,18 +699,18 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, rr_dict = NULL; } if (!_getdns_dict_set_this_list(result, "answer", - sections[GLDNS_SECTION_ANSWER])) - sections[GLDNS_SECTION_ANSWER] = NULL; + sections[SECTION_ANSWER])) + sections[SECTION_ANSWER] = NULL; else goto error; if (!_getdns_dict_set_this_list(result, "authority", - sections[GLDNS_SECTION_AUTHORITY])) - sections[GLDNS_SECTION_AUTHORITY] = NULL; + sections[SECTION_AUTHORITY])) + sections[SECTION_AUTHORITY] = NULL; else goto error; if (!_getdns_dict_set_this_list(result, "additional", - sections[GLDNS_SECTION_ADDITIONAL])) - sections[GLDNS_SECTION_ADDITIONAL] = NULL; + sections[SECTION_ADDITIONAL])) + sections[SECTION_ADDITIONAL] = NULL; else goto error; /* other stuff @@ -714,11 +727,11 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, , req->response , req->response_len) ; rr_iter && _getdns_rr_iter_section(rr_iter) - <= GLDNS_SECTION_ANSWER + <= SECTION_ANSWER ; rr_iter = _getdns_rr_iter_next(rr_iter)) { if (_getdns_rr_iter_section(rr_iter) != - GLDNS_SECTION_ANSWER) + SECTION_ANSWER) continue; if (gldns_read_uint16(rr_iter->rr_type) != @@ -755,11 +768,11 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, , req->response , req->response_len) ; rr_iter && _getdns_rr_iter_section(rr_iter) - <= GLDNS_SECTION_ANSWER + <= SECTION_ANSWER ; rr_iter = _getdns_rr_iter_next(rr_iter)) { if (_getdns_rr_iter_section(rr_iter) != - GLDNS_SECTION_ANSWER) + SECTION_ANSWER) continue; if (gldns_read_uint16(rr_iter->rr_type) != req->request_type) @@ -793,7 +806,7 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, break; } if (_getdns_rr_iter_section(rr_iter) == - GLDNS_SECTION_QUESTION) + SECTION_QUESTION) continue; for ( rdf_iter = _getdns_rdf_iter_init(&rdf_iter_storage, rr_iter) @@ -826,15 +839,15 @@ error: success: getdns_dict_destroy(header); getdns_dict_destroy(rr_dict); - getdns_list_destroy(sections[GLDNS_SECTION_ADDITIONAL]); - getdns_list_destroy(sections[GLDNS_SECTION_AUTHORITY]); - getdns_list_destroy(sections[GLDNS_SECTION_ANSWER]); + getdns_list_destroy(sections[SECTION_ADDITIONAL]); + getdns_list_destroy(sections[SECTION_AUTHORITY]); + getdns_list_destroy(sections[SECTION_ANSWER]); getdns_dict_destroy(question); getdns_list_destroy(bad_dns); return result; } -getdns_dict * +static getdns_dict * _getdns_create_call_reporting_dict( getdns_context *context, getdns_network_req *netreq) { @@ -918,11 +931,93 @@ _getdns_create_call_reporting_dict( return netreq_debug; } +static getdns_list * +_create_srv_addrs(getdns_context *context, _srvs *srvs) +{ + getdns_list *srv_addrs; + size_t i; + + if (!(srv_addrs = getdns_list_create_with_context(context))) + return NULL; + + for (i = 0; i < srvs->count; i++) { + _getdns_rr_iter *rr = srvs->rrs + i; + getdns_dict *d; + _getdns_rdf_iter rdf_storage, *rdf; + + const uint8_t *dname; + uint8_t dname_spc[256]; + size_t dname_sz = sizeof(dname_spc); + + _getdns_rrset a; + _getdns_rrtype_iter a_rr_spc, *a_rr; + int addresses_found = 0; + + if ( !(d = getdns_dict_create_with_context(context)) + || !(rdf = _getdns_rdf_iter_init_at(&rdf_storage, rr, 2)) + || !(rdf->rdd_pos->type & GETDNS_RDF_INTEGER) + || (rdf->rdd_pos->type & GETDNS_RDF_FIXEDSZ) != 2 + || getdns_dict_set_int(d, "port", (uint32_t) + gldns_read_uint16(rdf->pos)) + + || !(rdf = _getdns_rdf_iter_init_at(&rdf_storage, rr, 3)) + || !(rdf->rdd_pos->type & GETDNS_RDF_DNAME) + || !(dname = _getdns_rdf_if_or_as_decompressed( + rdf, dname_spc, &dname_sz)) + || _getdns_dict_set_const_bindata( + d, "domain_name", dname_sz, dname)) { + + /* error */ + getdns_dict_destroy(d); + continue; + } + + a.name = dname; + a.rr_class = rr_iter_class(rr); + a.rr_type = GETDNS_RRTYPE_AAAA; + a.pkt = rr->pkt; + a.pkt_len = rr->pkt_end - rr->pkt; + a.sections = SECTION_ADDITIONAL; + + for ( a_rr = _getdns_rrtype_iter_init(&a_rr_spc, &a) + ; a_rr ; a_rr = _getdns_rrtype_iter_next(a_rr)) { + + if ( a_rr->rr_i.nxt - (a_rr->rr_i.rr_type + 10) == 16 + && !getdns_dict_util_set_string( + d, "address_type", "IPv6") + && !_getdns_dict_set_const_bindata( + d, "address_data", 16, + a_rr->rr_i.rr_type + 10) + && !_getdns_list_append_dict(srv_addrs, d)) + addresses_found++; + } + a.rr_type = GETDNS_RRTYPE_A; + + for ( a_rr = _getdns_rrtype_iter_init(&a_rr_spc, &a) + ; a_rr ; a_rr = _getdns_rrtype_iter_next(a_rr)) { + + if ( a_rr->rr_i.nxt - (a_rr->rr_i.rr_type + 10) ==4 + && !getdns_dict_util_set_string( + d, "address_type", "IPv4") + && !_getdns_dict_set_const_bindata( + d, "address_data", 4, + a_rr->rr_i.rr_type + 10) + && !_getdns_list_append_dict(srv_addrs, d)) + addresses_found++; + } + if ( addresses_found + || _getdns_list_append_this_dict(srv_addrs, d)) + getdns_dict_destroy(d); + } + return srv_addrs; +} + getdns_dict * _getdns_create_getdns_response(getdns_dns_req *completed_request) { getdns_dict *result; getdns_list *just_addrs = NULL; + getdns_list *srv_addrs = NULL; getdns_list *replies_full; getdns_list *replies_tree; getdns_list *call_reporting = NULL; @@ -932,6 +1027,7 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) getdns_bindata *canonical_name = NULL; int nreplies = 0, nanswers = 0, nsecure = 0, ninsecure = 0, nbogus = 0; getdns_dict *netreq_debug; + _srvs srvs = { 0, 0, NULL }; /* info (bools) about dns_req */ int dnssec_return_status; @@ -956,6 +1052,16 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) just_addrs = getdns_list_create_with_context( completed_request->context); + else if ( + completed_request->netreqs[0]->request_type == GETDNS_RRTYPE_SRV) { + + srvs.capacity = 100; + if (!(srvs.rrs = GETDNS_XMALLOC( + context->mf, _getdns_rr_iter, srvs.capacity))) { + srvs.capacity = 0; + goto error_free_result; + } + } if (getdns_dict_set_int(result, GETDNS_STR_KEY_ANSWER_TYPE, GETDNS_NAMETYPE_DNS)) goto error_free_result; @@ -1002,7 +1108,7 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) continue; } if (!(reply = _getdns_create_reply_dict(context, - netreq, just_addrs, &rrsigs_in_answer))) + netreq, just_addrs, &rrsigs_in_answer, &srvs))) goto error; if (!canonical_name) { @@ -1074,6 +1180,14 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) goto error_free_result; just_addrs = NULL; } + if (srvs.capacity) { + if (!(srv_addrs = _create_srv_addrs(context, &srvs)) || + _getdns_dict_set_this_list( + result, "srv_addresses", srv_addrs)) + goto error_free_result; + + GETDNS_FREE(context->mf, srvs.rrs); + } if (getdns_dict_set_int(result, GETDNS_STR_KEY_STATUS, nreplies == 0 ? GETDNS_RESPSTATUS_ALL_TIMEOUT : completed_request->dnssec_return_only_secure && nsecure == 0 && ninsecure > 0 @@ -1093,6 +1207,9 @@ error_free_call_reporting: error_free_replies_full: getdns_list_destroy(replies_full); error_free_result: + if (srvs.capacity) + GETDNS_FREE(context->mf, srvs.rrs); + getdns_list_destroy(srv_addrs); getdns_list_destroy(just_addrs); getdns_dict_destroy(result); return NULL; diff --git a/src/util-internal.h b/src/util-internal.h index d3c05ab7..6c2b6dab 100644 --- a/src/util-internal.h +++ b/src/util-internal.h @@ -149,13 +149,8 @@ _getdns_rr_iter2rr_dict_canonical( struct getdns_dns_req; struct getdns_dict *_getdns_create_getdns_response(struct getdns_dns_req *completed_request); -getdns_dict *_getdns_create_reply_dict(getdns_context *context, - getdns_network_req *req, getdns_list *just_addrs, int *rrsigs_in_answer); - getdns_return_t _getdns_validate_dname(const char* dname); -int _getdns_dname_equal(const uint8_t *s1, const uint8_t *s2); - uint8_t *_getdns_list2wire( getdns_list *l, uint8_t *buf, size_t *buf_len, struct mem_funcs *mf); From e16efbbeee90862dee34720ca05276788f98bd4c Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 7 Jun 2016 17:08:35 +0200 Subject: [PATCH 2/9] Small bugs from the _getdns_rrset move --- src/dnssec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dnssec.c b/src/dnssec.c index 7bca4881..a46a1947 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -771,7 +771,7 @@ static void add_pkt2val_chain(struct mem_funcs *mf, /* For all things without signature, find SOA (zonecut) and query DS */ for ( i = _getdns_rrset_iter_init(&i_spc, pkt, pkt_len - , SECTION_NO_QUESTION) + , SECTION_NO_ADDITIONAL) ; i ; i = _getdns_rrset_iter_next(i)) { @@ -836,6 +836,7 @@ static void add_question2val_chain(struct mem_funcs *mf, q_rrset.rr_class = qclass; q_rrset.pkt = pkt; q_rrset.pkt_len = pkt_len; + q_rrset.sections = SECTION_ANSWER; for (anti_loop = MAX_CNAMES; anti_loop; anti_loop--) { if (!(rr = _getdns_rrtype_iter_init(&rr_spc, &q_rrset))) From 2d22b8729d7524e2a79f47e91e4f2417f183c2e7 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 7 Jun 2016 17:21:10 +0200 Subject: [PATCH 3/9] Locks must be >= 0 --- src/dnssec.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/dnssec.c b/src/dnssec.c index a46a1947..877e3ea5 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -912,7 +912,7 @@ static void val_chain_sched_soa_node(chain_node *node) node->soa_req = NULL; - node->lock--; + if (node->lock) node->lock--; } /* A SOA lookup is scheduled as a last resort. No signatures were found and @@ -969,7 +969,7 @@ static void val_chain_sched_node(chain_node *node) node->ds_req = NULL; - node->lock--; + if (node->lock) node->lock--; } static void val_chain_sched(chain_head *head, const uint8_t *dname) @@ -1010,7 +1010,7 @@ static void val_chain_sched_ds_node(chain_node *node) node->ds_req = NULL; - node->lock--; + if (node->lock) node->lock--; } static void val_chain_sched_ds(chain_head *head, const uint8_t *dname) @@ -1102,7 +1102,7 @@ static void val_chain_node_cb(getdns_dns_req *dnsreq) */ val_chain_sched_soa_node(node->parent); - node->lock--; + if (node->lock) node->lock--; check_chain_complete(node->chains); } @@ -1146,7 +1146,7 @@ static void val_chain_node_soa_cb(getdns_dns_req *dnsreq) node->lock++; val_chain_sched_soa_node(node->parent); } - node->lock--; + if (node->lock) node->lock--; check_chain_complete(node->chains); } @@ -3138,8 +3138,9 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq) ); } if (chain) { - for (chain_p = chain; chain_p; chain_p = chain_p->next) - chain_p->lock--; + for (chain_p = chain; chain_p; chain_p = chain_p->next) { + if (chain_p->lock) chain_p->lock--; + } check_chain_complete(chain); } else { dnsreq->validating = 0; From 457a4bec92a73cdccda2877aa65dd959d886b1cf Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 8 Jun 2016 10:57:03 +0200 Subject: [PATCH 4/9] develop merge fix --- src/dnssec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dnssec.c b/src/dnssec.c index dab808c3..a37f7296 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -835,7 +835,7 @@ static void add_question2val_chain(struct mem_funcs *mf, q_rrset.pkt_len = pkt_len; q_rrset.sections = SECTION_ANSWER; - for (anti_loop = MAX_CNAMES; anti_loop; anti_loop--) { + for (anti_loop = MAX_CNAME_REFERRALS; anti_loop; anti_loop--) { if (!(rr = _getdns_rrtype_iter_init(&rr_spc, &q_rrset))) break; if (!(rdf = _getdns_rdf_iter_init(&rdf_spc, &rr->rr_i))) From 6e7f66b21672574b5b3138ec4e4d744cbb91b82e Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 8 Jun 2016 12:44:23 +0200 Subject: [PATCH 5/9] Sorting of SRVs according to RFC2782 Could be optimized... but alas --- src/util-internal.c | 110 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 9 deletions(-) diff --git a/src/util-internal.c b/src/util-internal.c index 4661e46a..508ff1f4 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -462,18 +462,23 @@ inline static int has_all_numeric_label(const uint8_t *dname) return 0; } +typedef struct _srv_rr { + _getdns_rr_iter i; + unsigned running_sum; +} _srv_rr; + typedef struct _srvs { - size_t capacity; - size_t count; - _getdns_rr_iter *rrs; + size_t capacity; + size_t count; + _srv_rr *rrs; } _srvs; static int _grow_srvs(struct mem_funcs *mf, _srvs *srvs) { - _getdns_rr_iter *new_rrs; + _srv_rr *new_rrs; if (!(new_rrs = GETDNS_XREALLOC( - *mf, srvs->rrs, _getdns_rr_iter, srvs->capacity * 2))) + *mf, srvs->rrs, _srv_rr, srvs->capacity * 2))) return 0; /* Memory error */ srvs->capacity *= 2; @@ -669,7 +674,7 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, !_grow_srvs(&context->mf, srvs)) goto error; - srvs->rrs[srvs->count++] = *rr_iter; + srvs->rrs[srvs->count++].i = *rr_iter; continue; } if (rr_type != GETDNS_RRTYPE_A && rr_type != GETDNS_RRTYPE_AAAA) @@ -932,17 +937,104 @@ _getdns_create_call_reporting_dict( return netreq_debug; } +static inline int _srv_prio(_getdns_rr_iter *x) +{ return x->nxt < x->rr_type+12 + ? 65536 : (int)gldns_read_uint16(x->rr_type+10); } + +static inline int _srv_weight(_getdns_rr_iter *x) +{ return x->nxt < x->rr_type+14 ? 0 : (int)gldns_read_uint16(x->rr_type+12); } + + +static int _srv_cmp(const void *a, const void *b) +{ + return _srv_prio((_getdns_rr_iter *)a) + - _srv_prio((_getdns_rr_iter *)b); +} + +static void _rfc2782_sort(_srv_rr *start, _srv_rr *end) +{ + int running_sum, n; + _srv_rr *i, *j, swap; + + /* First move all SRVs with weight 0 to the beginning of the list */ + + for (i = start; i < end && _srv_weight(&i->i) == 0; i++) + ; /* pass */ + + for (j = i + 1; j < end; j++) { + if (_srv_weight(&j->i) == 0) { + swap = *i; + *i = *j; + *j = swap; + i++; + } + } + /* Now all SRVs are at the beginning, calculate running_sum */ + running_sum = 0; + for (i = start; i < end; i++) { + running_sum += _srv_weight(&i->i); + i->running_sum = running_sum; + } + n = arc4random_uniform(running_sum); + for (i = start; i < end; i++) { + if (i->running_sum >= n) + break; + } + if (i > start && i < end) { + swap = *start; + *start = *i; + *i = swap; + _rfc2782_sort(start + 1, end); + } +} + static getdns_list * _create_srv_addrs(getdns_context *context, _srvs *srvs) { getdns_list *srv_addrs; - size_t i; + size_t i, j; + qsort(srvs->rrs, srvs->count, sizeof(_srv_rr), _srv_cmp); + /* The SRVs are now sorted by priority (lowest first). Now determine + * server selection order for the SRVs with the same priority with + * the algorithm described in RFC2782: + * + * To select a target to be contacted next, arrange all SRV RRs + * (that have not been ordered yet) in any order, except that all + * those with weight 0 are placed at the beginning of the list. + * + * Compute the sum of the weights of those RRs, and with each RR + * associate the running sum in the selected order. Then choose a + * uniform random number between 0 and the sum computed + * (inclusive), and select the RR whose running sum value is the + * first in the selected order which is greater than or equal to + * the random number selected. The target host specified in the + * selected SRV RR is the next one to be contacted by the client. + * Remove this SRV RR from the set of the unordered SRV RRs and + * apply the described algorithm to the unordered SRV RRs to select + * the next target host. Continue the ordering process until there + * are no unordered SRV RRs. This process is repeated for each + * Priority. + */ + for (i = 0; i < srvs->count; i = j) { + /* Determine range of SRVs with same priority */ + for ( j = i + 1 + ; j < srvs->count && _srv_prio(&srvs->rrs[i].i) + == _srv_prio(&srvs->rrs[j].i) + ; j++) + ; /* pass */ + + if (j == i + 1) + continue; + + /* SRVs with same prio range from i till j (exclusive). */ + _rfc2782_sort(srvs->rrs + i, srvs->rrs + j); + } if (!(srv_addrs = getdns_list_create_with_context(context))) return NULL; for (i = 0; i < srvs->count; i++) { - _getdns_rr_iter *rr = srvs->rrs + i; + _getdns_rr_iter *rr = &srvs->rrs[i].i; getdns_dict *d; _getdns_rdf_iter rdf_storage, *rdf; @@ -1058,7 +1150,7 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) srvs.capacity = 100; if (!(srvs.rrs = GETDNS_XMALLOC( - context->mf, _getdns_rr_iter, srvs.capacity))) { + context->mf, _srv_rr, srvs.capacity))) { srvs.capacity = 0; goto error_free_result; } From 8679633cd92889ae96a307b8ec5821e1327933b3 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 8 Jun 2016 16:03:45 +0200 Subject: [PATCH 6/9] One more _getdns_rrset caused dnssec fix --- src/dnssec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dnssec.c b/src/dnssec.c index a37f7296..0dbd58d6 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -2200,6 +2200,7 @@ static int key_proves_nonexistance( */ nsec_rrset = *rrset; nsec_rrset.rr_type = GETDNS_RRTYPE_NSEC; + nsec_rrset.sections = SECTION_NO_ADDITIONAL; if (/* A NSEC RR exists at the owner name of rrset */ (nsec_rr = _getdns_rrtype_iter_init(&nsec_spc, &nsec_rrset)) From 49840c9a8565033227279811a9f00d351901c991 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 9 Jun 2016 15:03:51 +0200 Subject: [PATCH 7/9] Some more uniform _getdns_rrset usage --- src/dnssec.c | 57 +++++++---------------- src/general.c | 73 +++-------------------------- src/rr-iter.c | 56 ++++++++++++++++++++++ src/rr-iter.h | 15 +++++- src/util-internal.c | 111 +++++++++----------------------------------- 5 files changed, 114 insertions(+), 198 deletions(-) diff --git a/src/dnssec.c b/src/dnssec.c index 26d14cca..95c8cbbf 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -814,13 +814,7 @@ static void add_question2val_chain(struct mem_funcs *mf, const uint8_t *qname, uint16_t qtype, uint16_t qclass, getdns_network_req *netreq) { - _getdns_rrset q_rrset; - uint8_t cname_spc[256]; - size_t cname_len = sizeof(cname_spc); - size_t anti_loop; - _getdns_rdf_iter rdf_spc, *rdf; - _getdns_rrtype_iter *rr, rr_spc; - + _getdns_rrset_spc q_rrset; chain_head *head; assert(pkt); @@ -828,43 +822,26 @@ static void add_question2val_chain(struct mem_funcs *mf, assert(qname); /* First find the canonical name for the question */ - q_rrset.name = qname; - q_rrset.rr_type = GETDNS_RRTYPE_CNAME; - q_rrset.rr_class = qclass; - q_rrset.pkt = pkt; - q_rrset.pkt_len = pkt_len; - q_rrset.sections = SECTION_ANSWER; + q_rrset.rrset.name = qname; + q_rrset.rrset.rr_type = qtype; + q_rrset.rrset.rr_class = qclass; + q_rrset.rrset.pkt = pkt; + q_rrset.rrset.pkt_len = pkt_len; + q_rrset.rrset.sections = SECTION_ANSWER; - for (anti_loop = MAX_CNAME_REFERRALS; anti_loop; anti_loop--) { - if (!(rr = _getdns_rrtype_iter_init(&rr_spc, &q_rrset))) - break; - if (!(rdf = _getdns_rdf_iter_init(&rdf_spc, &rr->rr_i))) - break; - q_rrset.name = _getdns_rdf_if_or_as_decompressed( - rdf, cname_spc, &cname_len); - } - - /* If the qtype was a CNAME, and we got one, we'r done. - * We asked for it directly, so no redirection applies. - * Otherwise we have to check the referred to name/qtype. - */ - if (qtype == GETDNS_RRTYPE_CNAME && q_rrset.name != qname) + if (_getdns_initialized_rrset_answer(&q_rrset)) return; - q_rrset.rr_type = qtype; - if (!(rr = _getdns_rrtype_iter_init(&rr_spc, &q_rrset))) { - /* No answer for the question. Add a head for this rrset - * anyway, to validate proof of non-existance, or to find - * proof that the packet is insecure. - */ - debug_sec_print_rrset("Adding NX rrset: ", &q_rrset); - head = add_rrset2val_chain(mf, chain_p, &q_rrset, netreq); + /* No answer for the question. Add a head for this rrset + * anyway, to validate proof of non-existance, or to find + * proof that the packet is insecure. + */ + debug_sec_print_rrset("Adding NX rrset: ", &q_rrset.rrset); + head = add_rrset2val_chain(mf, chain_p, &q_rrset.rrset, netreq); - /* On empty packet, find SOA (zonecut) for the qname */ - if (head && GLDNS_ANCOUNT(pkt) == 0 && GLDNS_NSCOUNT(pkt) == 0) - - val_chain_sched_soa(head, q_rrset.name); - } + /* On empty packet, find SOA (zonecut) for the qname */ + if (head && GLDNS_ANCOUNT(pkt) == 0 && GLDNS_NSCOUNT(pkt) == 0) + val_chain_sched_soa(head, q_rrset.rrset.name); } diff --git a/src/general.c b/src/general.c index a497fda3..4b80dbdd 100644 --- a/src/general.c +++ b/src/general.c @@ -84,76 +84,15 @@ static int no_answer(getdns_dns_req *dns_req) { getdns_network_req **netreq_p, *netreq; - int new_canonical = 0, cnames_followed; - uint8_t canon_spc[256]; - const uint8_t *canon; - size_t canon_len; - uint8_t owner_spc[256]; - const uint8_t *owner; - size_t owner_len; - - _getdns_rr_iter rr_spc, *rr; - _getdns_rdf_iter rdf_spc, *rdf; for (netreq_p = dns_req->netreqs; (netreq = *netreq_p); netreq_p++) { - if (netreq->response_len == 0 || - GLDNS_ANCOUNT(netreq->response) == 0) - continue; - canon = netreq->owner->name; - canon_len = netreq->owner->name_len; - if (netreq->request_type != GETDNS_RRTYPE_CNAME - && GLDNS_ANCOUNT(netreq->response) > 1) do { - new_canonical = 0, cnames_followed = 0; - for ( rr = _getdns_rr_iter_init(&rr_spc - , netreq->response - , netreq->response_len) - ; rr && _getdns_rr_iter_section(rr) - <= SECTION_ANSWER - ; rr = _getdns_rr_iter_next(rr)) { + _getdns_rrset_spc answer; - if (_getdns_rr_iter_section(rr) != - SECTION_ANSWER) - continue; - - if (gldns_read_uint16(rr->rr_type) != - GETDNS_RRTYPE_CNAME) - continue; - - owner = _getdns_owner_if_or_as_decompressed( - rr, owner_spc, &owner_len); - if (!_getdns_dname_equal(canon, owner)) - continue; - - if (!(rdf = _getdns_rdf_iter_init( - &rdf_spc, rr))) - continue; - - canon = _getdns_rdf_if_or_as_decompressed( - rdf, canon_spc, &canon_len); - new_canonical = 1; - cnames_followed++; - } - } while (new_canonical && cnames_followedresponse - , netreq->response_len) - ; rr && _getdns_rr_iter_section(rr) - <= SECTION_ANSWER - ; rr = _getdns_rr_iter_next(rr)) { - - if (_getdns_rr_iter_section(rr) != - SECTION_ANSWER) - continue; - - if (gldns_read_uint16(rr->rr_type) != - netreq->request_type) - continue; - - owner = _getdns_owner_if_or_as_decompressed( - rr, owner_spc, &owner_len); - if (_getdns_dname_equal(canon, owner)) - return 0; - } + if (netreq->response_len > 0 && + GLDNS_ANCOUNT(netreq->response) > 0 && + _getdns_rrset_answer(&answer, netreq->response + , netreq->response_len)) + return 0; } return 1; } diff --git a/src/rr-iter.c b/src/rr-iter.c index 999d9607..e6a711de 100644 --- a/src/rr-iter.c +++ b/src/rr-iter.c @@ -240,6 +240,62 @@ _getdns_owner_if_or_as_decompressed(_getdns_rr_iter *i, ff_bytes, len, 0); } +_getdns_rrset * +_getdns_initialized_rrset_answer(_getdns_rrset_spc *query_rrset) +{ + _getdns_rrset *rrset = &query_rrset->rrset; + uint16_t qtype = rrset->rr_type; + size_t cname_loop_protection; + + assert(query_rrset); + + /* Follow CNAMEs */ + rrset->rr_type = GETDNS_RRTYPE_CNAME; + for ( cname_loop_protection = MAX_CNAME_REFERRALS + ; cname_loop_protection > 0 + ; cname_loop_protection-- ) { + _getdns_rrtype_iter rr_spc, *rr; + _getdns_rdf_iter rdf_spc, *rdf; + + if (!(rr = _getdns_rrtype_iter_init(&rr_spc, rrset))) + break; + if (!(rdf = _getdns_rdf_iter_init(&rdf_spc, &rr->rr_i))) + break; + query_rrset->name_len = sizeof(query_rrset->name_spc); + rrset->name = _getdns_rdf_if_or_as_decompressed( + rdf, query_rrset->name_spc, &query_rrset->name_len); + } + rrset->rr_type = qtype; + if (qtype == GETDNS_RRTYPE_CNAME && + cname_loop_protection < MAX_CNAME_REFERRALS) + return rrset; /* The CNAME was the answer */ + + return _getdns_rrset_has_rrs(rrset) ? rrset : NULL; +} + +_getdns_rrset * +_getdns_rrset_answer(_getdns_rrset_spc *spc, const uint8_t *pkt, size_t len) +{ + _getdns_rr_iter rr_spc, *rr; + + assert(spc); + + spc->rrset.name = NULL; + spc->name_len = sizeof(spc->name_spc); + if ( !(rr = _getdns_rr_iter_init(&rr_spc, pkt, len)) + || _getdns_rr_iter_section(rr) != SECTION_QUESTION + || !(spc->rrset.name = _getdns_owner_if_or_as_decompressed( + rr, spc->name_spc, &spc->name_len)) + || rr->nxt < rr->rr_type + 4) + return NULL; + + spc->rrset.rr_class = rr_iter_class(rr); + spc->rrset.rr_type = rr_iter_type(rr); + spc->rrset.pkt = pkt; + spc->rrset.pkt_len = len; + spc->rrset.sections = SECTION_ANSWER; + return _getdns_initialized_rrset_answer(spc); +} /* Utility function to compare owner name of rr with name */ static int rr_owner_equal(_getdns_rr_iter *rr, const uint8_t *name) diff --git a/src/rr-iter.h b/src/rr-iter.h index d9221df2..d657d484 100644 --- a/src/rr-iter.h +++ b/src/rr-iter.h @@ -108,7 +108,6 @@ static inline uint16_t rr_iter_type(_getdns_rr_iter *rr) static inline uint16_t rr_iter_class(_getdns_rr_iter *rr) { return rr->rr_type + 4 <= rr->nxt ? gldns_read_uint16(rr->rr_type + 2) : 0; } - typedef struct _getdns_rrset { const uint8_t *name; uint16_t rr_class; @@ -118,6 +117,18 @@ typedef struct _getdns_rrset { _getdns_section sections; } _getdns_rrset; +typedef struct _getdns_rrset_spc { + _getdns_rrset rrset; + uint8_t name_spc[256]; + size_t name_len; +} _getdns_rrset_spc; + +_getdns_rrset *_getdns_rrset_answer( + _getdns_rrset_spc *rrset2init, const uint8_t *pkt, size_t pkt_len); + +_getdns_rrset *_getdns_initialized_rrset_answer( + _getdns_rrset_spc *query_rrset); + typedef struct _getdns_rrtype_iter { _getdns_rr_iter rr_i; _getdns_rrset *rrset; @@ -164,6 +175,8 @@ _getdns_rrset_iter *_getdns_rrset_iter_init(_getdns_rrset_iter *i, const uint8_t *pkt, size_t pkt_len, _getdns_section sections); _getdns_rrset_iter *_getdns_rrset_iter_next(_getdns_rrset_iter *i); + + static inline _getdns_rrset *_getdns_rrset_iter_value(_getdns_rrset_iter *i) { return i && i->rr_i.pos ? &i->rrset : NULL; } diff --git a/src/util-internal.c b/src/util-internal.c index 508ff1f4..22a5e0a8 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -553,17 +553,16 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, size_t bin_size; const uint8_t *bin_data; _getdns_section section; - uint8_t canonical_name_space[256], owner_name_space[256], - query_name_space[256]; - const uint8_t *canonical_name, *owner_name, *query_name; - size_t canonical_name_len = sizeof(canonical_name_space), - owner_name_len = sizeof(owner_name_space), + uint8_t owner_name_space[256], query_name_space[256]; + const uint8_t *owner_name, *query_name; + size_t owner_name_len = sizeof(owner_name_space), query_name_len = sizeof(query_name_space); - int new_canonical = 0, cnames_followed, - request_answered, all_numeric_label; + int all_numeric_label; uint16_t rr_type; getdns_dict *header = NULL; getdns_list *bad_dns = NULL; + _getdns_rrset_spc answer_spc; + _getdns_rrset *answer; if (!result) goto error; @@ -593,9 +592,6 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, goto error; header = NULL; - canonical_name = req->owner->name; - canonical_name_len = req->owner->name_len; - if (req->query && (rr_iter = _getdns_rr_iter_init(&rr_iter_storage, req->query , req->response - req->query))) @@ -652,23 +648,6 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, goto error; else rr_dict = NULL; - if (rr_type == GETDNS_RRTYPE_CNAME) { - - owner_name_len = sizeof(owner_name_space); - owner_name = _getdns_owner_if_or_as_decompressed( - rr_iter, owner_name_space, &owner_name_len); - if (!_getdns_dname_equal(canonical_name, owner_name)) - continue; - - if (!(rdf_iter = _getdns_rdf_iter_init( - &rdf_iter_storage, rr_iter))) - continue; - - new_canonical = 1; - canonical_name = _getdns_rdf_if_or_as_decompressed( - rdf_iter,canonical_name_space,&canonical_name_len); - continue; - } if (srvs->capacity && rr_type == GETDNS_RRTYPE_SRV) { if (srvs->count >= srvs->capacity && !_grow_srvs(&context->mf, srvs)) @@ -724,42 +703,14 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, if (getdns_dict_set_int(result, "answer_type", GETDNS_NAMETYPE_DNS)) goto error; - cnames_followed = new_canonical; - while (cnames_followed < MAX_CNAME_REFERRALS && new_canonical) { - new_canonical = 0; + + answer = _getdns_rrset_answer(&answer_spc, req->response + , req->response_len); - for ( rr_iter = _getdns_rr_iter_init(&rr_iter_storage - , req->response - , req->response_len) - ; rr_iter && _getdns_rr_iter_section(rr_iter) - <= SECTION_ANSWER - ; rr_iter = _getdns_rr_iter_next(rr_iter)) { - - if (_getdns_rr_iter_section(rr_iter) != - SECTION_ANSWER) - continue; - - if (gldns_read_uint16(rr_iter->rr_type) != - GETDNS_RRTYPE_CNAME) - continue; - - owner_name = _getdns_owner_if_or_as_decompressed( - rr_iter, owner_name_space, &owner_name_len); - if (!_getdns_dname_equal(canonical_name, owner_name)) - continue; - - if (!(rdf_iter = _getdns_rdf_iter_init( - &rdf_iter_storage, rr_iter))) - continue; - - canonical_name = _getdns_rdf_if_or_as_decompressed( - rdf_iter,canonical_name_space,&canonical_name_len); - new_canonical = 1; - cnames_followed++; - } - } - if (_getdns_dict_set_const_bindata( - result, "canonical_name", canonical_name_len, canonical_name)) + if (answer_spc.rrset.name && + _getdns_dict_set_const_bindata(result, "canonical_name" + , answer_spc.name_len + , answer_spc.rrset.name)) goto error; if (!req->owner->add_warning_for_bad_dns) @@ -768,35 +719,15 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, if (!(bad_dns = getdns_list_create_with_context(context))) goto error; - if (cnames_followed && req->request_type != GETDNS_RRTYPE_CNAME) { - request_answered = 0; - for ( rr_iter = _getdns_rr_iter_init(&rr_iter_storage - , req->response - , req->response_len) - ; rr_iter && _getdns_rr_iter_section(rr_iter) - <= SECTION_ANSWER - ; rr_iter = _getdns_rr_iter_next(rr_iter)) { + if ( !answer + && req->request_type != GETDNS_RRTYPE_CNAME + && query_name + && answer_spc.rrset.name + && !_getdns_dname_equal(query_name, answer_spc.rrset.name) + && _getdns_list_append_int(bad_dns + , GETDNS_BAD_DNS_CNAME_RETURNED_FOR_OTHER_TYPE)) + goto error; - if (_getdns_rr_iter_section(rr_iter) != - SECTION_ANSWER) - continue; - if (gldns_read_uint16(rr_iter->rr_type) != - req->request_type) - continue; - - owner_name=_getdns_owner_if_or_as_decompressed( - rr_iter, owner_name_space,&owner_name_len); - if (_getdns_dname_equal( - canonical_name, owner_name)) { - request_answered = 1; - break; - } - } - if (!request_answered && - _getdns_list_append_int(bad_dns, - GETDNS_BAD_DNS_CNAME_RETURNED_FOR_OTHER_TYPE)) - goto error; - } all_numeric_label = 0; for ( rr_iter = _getdns_rr_iter_init(&rr_iter_storage , req->response From e228f526a362f6df4ed771205ea7731fea29356c Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 9 Jun 2016 16:12:06 +0200 Subject: [PATCH 8/9] when nothing else, result[canonical_name] is qname --- src/util-internal.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/util-internal.c b/src/util-internal.c index 22a5e0a8..aa255e0e 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -703,7 +703,6 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, if (getdns_dict_set_int(result, "answer_type", GETDNS_NAMETYPE_DNS)) goto error; - answer = _getdns_rrset_answer(&answer_spc, req->response , req->response_len); @@ -1136,10 +1135,9 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) goto error; if (!canonical_name) { - if (getdns_dict_get_bindata( - reply, "canonical_name", &canonical_name)) - goto error; - if (getdns_dict_set_bindata( + if (!getdns_dict_get_bindata( + reply, "canonical_name", &canonical_name) && + getdns_dict_set_bindata( result, "canonical_name", canonical_name)) goto error; } @@ -1188,6 +1186,11 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) goto error; replies_tree = NULL; + if (!canonical_name && + _getdns_dict_set_const_bindata(result, "canonical_name", + completed_request->name_len, completed_request->name)) + goto error; + if (call_reporting) { if (_getdns_dict_set_this_list( result, "call_reporting", call_reporting)) From 2ed28badfdf33f87f865af6a86fdb0f750cf36ac Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 9 Jun 2016 16:47:00 +0200 Subject: [PATCH 9/9] Replies without answer don't have a canonical name --- .../tpkg/270-header-extension.tpkg/270-header-extension.good | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/tpkg/270-header-extension.tpkg/270-header-extension.good b/src/test/tpkg/270-header-extension.tpkg/270-header-extension.good index 0e829f2b..bd3d1b62 100644 --- a/src/test/tpkg/270-header-extension.tpkg/270-header-extension.good +++ b/src/test/tpkg/270-header-extension.tpkg/270-header-extension.good @@ -8,7 +8,6 @@ "answer": [], "answer_type": GETDNS_NAMETYPE_DNS, "authority": [], - "canonical_name": , "header": { "aa": 0,