mirror of https://github.com/getdnsapi/getdns.git
Some more uniform _getdns_rrset usage
This commit is contained in:
parent
e27bfcedb6
commit
49840c9a85
57
src/dnssec.c
57
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue