Some more uniform _getdns_rrset usage

This commit is contained in:
Willem Toorop 2016-06-09 15:03:51 +02:00
parent e27bfcedb6
commit 49840c9a85
5 changed files with 114 additions and 198 deletions

View File

@ -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);
}

View File

@ -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_followed<MAX_CNAME_REFERRALS);
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)) {
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;
}

View File

@ -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)

View File

@ -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; }

View File

@ -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