Generalize getdns_rrset for raw pkt, not netreq

This commit is contained in:
Willem Toorop 2015-06-23 16:41:34 +02:00
parent 1babc715b7
commit c7c7884350
1 changed files with 125 additions and 81 deletions

View File

@ -152,11 +152,12 @@ static priv_getdns_rr_iter *rr_iter_rrsig_covering(priv_getdns_rr_iter *rr,
} }
typedef struct getdns_rrset { typedef struct getdns_rrset {
uint8_t *name; uint8_t *name;
uint16_t rr_class; uint16_t rr_class;
uint16_t rr_type; uint16_t rr_type;
getdns_network_req *netreq; uint8_t *pkt;
uint8_t name_spc[]; size_t pkt_len;
uint8_t name_spc[];
} getdns_rrset; } getdns_rrset;
typedef struct rrtype_iter { typedef struct rrtype_iter {
@ -180,8 +181,7 @@ static rrtype_iter *rrtype_iter_init(rrtype_iter *i, getdns_rrset *rrset)
{ {
i->rrset = rrset; i->rrset = rrset;
return (rrtype_iter *) rr_iter_name_class_type( return (rrtype_iter *) rr_iter_name_class_type(
priv_getdns_rr_iter_init(&i->rr_i, rrset->netreq->response priv_getdns_rr_iter_init(&i->rr_i, rrset->pkt, rrset->pkt_len ),
, rrset->netreq->response_len),
i->rrset->name, i->rrset->rr_class, i->rrset->rr_type); i->rrset->name, i->rrset->rr_class, i->rrset->rr_type);
} }
@ -196,8 +196,7 @@ static rrsig_iter *rrsig_iter_init(rrsig_iter *i, getdns_rrset *rrset)
{ {
i->rrset = rrset; i->rrset = rrset;
return (rrsig_iter *) rr_iter_rrsig_covering( return (rrsig_iter *) rr_iter_rrsig_covering(
priv_getdns_rr_iter_init(&i->rr_i, rrset->netreq->response priv_getdns_rr_iter_init(&i->rr_i, rrset->pkt, rrset->pkt_len),
, rrset->netreq->response_len),
i->rrset->name, i->rrset->rr_class, i->rrset->rr_type); i->rrset->name, i->rrset->rr_class, i->rrset->rr_type);
} }
@ -256,8 +255,6 @@ static void debug_sec_print_rrset(const char *msg, getdns_rrset *rrset)
#define debug_sec_print_rrset(...) DEBUG_OFF(__VA_ARGS__) #define debug_sec_print_rrset(...) DEBUG_OFF(__VA_ARGS__)
#endif #endif
typedef struct rrset_iter rrset_iter; typedef struct rrset_iter rrset_iter;
struct rrset_iter { struct rrset_iter {
getdns_rrset rrset; getdns_rrset rrset;
@ -266,17 +263,16 @@ struct rrset_iter {
priv_getdns_rr_iter rr_i; priv_getdns_rr_iter rr_i;
}; };
static rrset_iter *rrset_iter_init(rrset_iter *i, getdns_network_req *netreq) static rrset_iter *rrset_iter_init(rrset_iter *i, uint8_t *pkt, size_t pkt_len)
{ {
priv_getdns_rr_iter *rr; priv_getdns_rr_iter *rr;
i->rrset.name = i->name_spc; i->rrset.name = i->name_spc;
i->rrset.netreq = netreq; i->rrset.pkt = pkt;
i->rrset.pkt_len = pkt_len;
i->name_len = 0; i->name_len = 0;
for ( rr = priv_getdns_rr_iter_init(&i->rr_i for ( rr = priv_getdns_rr_iter_init(&i->rr_i, pkt, pkt_len)
, netreq->response
, netreq->response_len)
;(rr = rr_iter_ansauth(rr)) ;(rr = rr_iter_ansauth(rr))
; rr = priv_getdns_rr_iter_next(rr)) { ; rr = priv_getdns_rr_iter_next(rr)) {
@ -295,7 +291,6 @@ static rrset_iter *rrset_iter_init(rrset_iter *i, getdns_network_req *netreq)
return NULL; return NULL;
} }
static rrset_iter *rrset_iter_next(rrset_iter *i) static rrset_iter *rrset_iter_next(rrset_iter *i)
{ {
priv_getdns_rr_iter *rr; priv_getdns_rr_iter *rr;
@ -325,30 +320,58 @@ static getdns_rrset *rrset_iter_value(rrset_iter *i)
return &i->rrset; return &i->rrset;
} }
/* ------------------------------------------------------------------------- */
typedef struct chain_head chain_head; typedef struct chain_head chain_head;
typedef struct chain_node chain_node; typedef struct chain_node chain_node;
struct chain_head { struct chain_head {
struct mem_funcs my_mf; struct mem_funcs my_mf;
chain_head *next; chain_head *next;
chain_node *parent; chain_node *parent;
size_t node_count; /* Number of nodes attached directly size_t node_count; /* Number of nodes attached directly
* to this head. For cleaning. */ * to this head. For cleaning. */
getdns_rrset rrset; getdns_network_req *netreq;
uint8_t name_spc[]; getdns_rrset rrset;
uint8_t name_spc[];
}; };
struct chain_node { struct chain_node {
chain_node *parent; chain_node *parent;
getdns_rrset dnskey; getdns_network_req *dnskey_req;
getdns_rrset ds ; getdns_rrset dnskey;
getdns_rrset soa ; getdns_network_req *ds_req;
getdns_rrset ds;
getdns_network_req *soa_req;
chain_head *chains; chain_head *chains;
}; };
#ifdef STUB_NATIVE_DNSSEC
static int chain_head_validate_dnssec(chain_head *head, getdns_list *tas)
{
return GETDNS_DNSSEC_INSECURE;
}
static void chain_validate_dnssec(chain_head *chain)
{
chain_head *head;
getdns_list *tas =
chain->netreq->owner->context->dnssec_trust_anchors;
for (head = chain; head; head = head->next) {
switch (chain_head_validate_dnssec(head, tas)) {
case GETDNS_DNSSEC_SECURE: break;
case GETDNS_DNSSEC_BOGUS : head->netreq->bogus = 1;
default : continue;
}
/* TODO: Validate head->rrset */
}
}
#endif
static size_t count_outstanding_requests(chain_head *head) static size_t count_outstanding_requests(chain_head *head)
{ {
size_t count; size_t count;
@ -361,19 +384,19 @@ static size_t count_outstanding_requests(chain_head *head)
; node ; node
; node = node->parent) { ; node = node->parent) {
if (node->dnskey.netreq && if (node->dnskey_req &&
node->dnskey.netreq->state != NET_REQ_FINISHED && node->dnskey_req->state != NET_REQ_FINISHED &&
node->dnskey.netreq->state != NET_REQ_CANCELED) node->dnskey_req->state != NET_REQ_CANCELED)
count++; count++;
if (node->ds.netreq && if (node->ds_req &&
node->ds.netreq->state != NET_REQ_FINISHED && node->ds_req->state != NET_REQ_FINISHED &&
node->ds.netreq->state != NET_REQ_CANCELED) node->ds_req->state != NET_REQ_CANCELED)
count++; count++;
if (node->soa.netreq && if (node->soa_req &&
node->soa.netreq->state != NET_REQ_FINISHED && node->soa_req->state != NET_REQ_FINISHED &&
node->soa.netreq->state != NET_REQ_CANCELED) node->soa_req->state != NET_REQ_CANCELED)
count++; count++;
} }
return count + count_outstanding_requests(head->next); return count + count_outstanding_requests(head->next);
@ -388,7 +411,10 @@ static void append_rrs2val_chain_list(getdns_context *ctxt,
rrsig_iter *rrsig, rrsig_spc; rrsig_iter *rrsig, rrsig_spc;
getdns_dict *rr_dict; getdns_dict *rr_dict;
for (i = rrset_iter_init(&i_spc, netreq); i; i = rrset_iter_next(i)) { for ( i = rrset_iter_init(&i_spc,netreq->response,netreq->response_len)
; i
; i = rrset_iter_next(i)) {
rrset = rrset_iter_value(i); rrset = rrset_iter_value(i);
if (rrset->rr_type != GETDNS_RRTYPE_DNSKEY && if (rrset->rr_type != GETDNS_RRTYPE_DNSKEY &&
@ -432,28 +458,31 @@ static void check_chain_complete(chain_head *chain)
return; return;
} }
DEBUG_SEC("Chain done!\n"); DEBUG_SEC("Chain done!\n");
dnsreq = chain->rrset.netreq->owner; dnsreq = chain->netreq->owner;
/* TODO: DNSSEC validation of netreq! */
#ifdef STUB_NATIVE_DNSSEC
chain_validate_dnssec(chain);
#endif
val_chain_list = dnsreq->dnssec_return_validation_chain val_chain_list = dnsreq->dnssec_return_validation_chain
? getdns_list_create_with_context(dnsreq->context) : NULL; ? getdns_list_create_with_context(dnsreq->context) : NULL;
/* Cleanup the chain */ /* Walk chain to add values to val_chain_list and to cleanup */
for ( head = chain; head ; head = next ) { for ( head = chain; head ; head = next ) {
next = head->next; next = head->next;
for ( node_count = head->node_count, node = head->parent for ( node_count = head->node_count, node = head->parent
; node_count ; node_count
; node_count--, node = node->parent ) { ; node_count--, node = node->parent ) {
if (node->dnskey.netreq) { if (node->dnskey_req) {
append_rrs2val_chain_list(dnsreq->context, append_rrs2val_chain_list(dnsreq->context,
val_chain_list, node->dnskey.netreq); val_chain_list, node->dnskey_req);
dns_req_free(node->dnskey.netreq->owner); dns_req_free(node->dnskey_req->owner);
} }
if (node->ds.netreq) { if (node->ds_req) {
append_rrs2val_chain_list(dnsreq->context, append_rrs2val_chain_list(dnsreq->context,
val_chain_list, node->ds.netreq); val_chain_list, node->ds_req);
dns_req_free(node->ds.netreq->owner); dns_req_free(node->ds_req->owner);
} }
} }
GETDNS_FREE(head->my_mf, head); GETDNS_FREE(head->my_mf, head);
@ -477,18 +506,18 @@ static void val_chain_sched_soa_node(chain_node *node)
getdns_dns_req *dnsreq; getdns_dns_req *dnsreq;
char name[1024]; char name[1024];
context = node->chains->rrset.netreq->owner->context; context = node->chains->netreq->owner->context;
loop = node->chains->rrset.netreq->owner->loop; loop = node->chains->netreq->owner->loop;
if (!gldns_wire2str_dname_buf(node->soa.name, 256, name, sizeof(name))) if (!gldns_wire2str_dname_buf(node->ds.name, 256, name, sizeof(name)))
return; return;
if (! node->soa.netreq && if (! node->soa_req &&
! priv_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_SOA, ! priv_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_SOA,
dnssec_ok_checking_disabled, node, &dnsreq, NULL, dnssec_ok_checking_disabled, node, &dnsreq, NULL,
val_chain_node_soa_cb)) val_chain_node_soa_cb))
node->soa.netreq = *dnsreq->netreqs; node->soa_req = dnsreq->netreqs[0];
} }
static void val_chain_sched_soa(chain_head *head, uint8_t *dname) static void val_chain_sched_soa(chain_head *head, uint8_t *dname)
@ -499,7 +528,7 @@ static void val_chain_sched_soa(chain_head *head, uint8_t *dname)
return; return;
for ( node = head->parent for ( node = head->parent
; node && !priv_getdns_dname_equal(dname, node->dnskey.name) ; node && !priv_getdns_dname_equal(dname, node->ds.name)
; node = node->parent); ; node = node->parent);
if (node) if (node)
@ -514,25 +543,25 @@ static void val_chain_sched_node(chain_node *node)
getdns_dns_req *dnsreq; getdns_dns_req *dnsreq;
char name[1024]; char name[1024];
context = node->chains->rrset.netreq->owner->context; context = node->chains->netreq->owner->context;
loop = node->chains->rrset.netreq->owner->loop; loop = node->chains->netreq->owner->loop;
if (!gldns_wire2str_dname_buf(node->dnskey.name, 256, name, sizeof(name))) if (!gldns_wire2str_dname_buf(node->ds.name, 256, name, sizeof(name)))
return; return;
DEBUG_SEC("schedule DS & DNSKEY lookup for %s\n", name); DEBUG_SEC("schedule DS & DNSKEY lookup for %s\n", name);
if (! node->dnskey.netreq /* not scheduled */ && if (! node->dnskey_req /* not scheduled */ &&
! priv_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DNSKEY, ! priv_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DNSKEY,
dnssec_ok_checking_disabled, node, &dnsreq, NULL, val_chain_node_cb)) dnssec_ok_checking_disabled, node, &dnsreq, NULL, val_chain_node_cb))
node->dnskey.netreq = *dnsreq->netreqs; node->dnskey_req = dnsreq->netreqs[0];
if (! node->ds.netreq && node->parent /* not root */ && if (! node->ds_req && node->parent /* not root */ &&
! priv_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS, ! priv_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS,
dnssec_ok_checking_disabled, node, &dnsreq, NULL, val_chain_node_cb)) dnssec_ok_checking_disabled, node, &dnsreq, NULL, val_chain_node_cb))
node->ds.netreq = *dnsreq->netreqs; node->ds_req = dnsreq->netreqs[0];
} }
static void val_chain_sched(chain_head *head, uint8_t *dname) static void val_chain_sched(chain_head *head, uint8_t *dname)
@ -540,7 +569,7 @@ static void val_chain_sched(chain_head *head, uint8_t *dname)
chain_node *node; chain_node *node;
for ( node = head->parent for ( node = head->parent
; node && !priv_getdns_dname_equal(dname, node->dnskey.name) ; node && !priv_getdns_dname_equal(dname, node->ds.name)
; node = node->parent); ; node = node->parent);
if (node) if (node)
val_chain_sched_node(node); val_chain_sched_node(node);
@ -559,7 +588,7 @@ static void val_chain_sched_signer_node(chain_node *node, rrsig_iter *rrsig)
rdf, signer_spc, &signer_len))) rdf, signer_spc, &signer_len)))
return; return;
while (node && !priv_getdns_dname_equal(signer, node->dnskey.name)) while (node && !priv_getdns_dname_equal(signer, node->ds.name))
node = node->parent; node = node->parent;
if (node) if (node)
val_chain_sched_node(node); val_chain_sched_node(node);
@ -580,12 +609,18 @@ static void val_chain_node_cb(getdns_dns_req *dnsreq)
getdns_context_clear_outbound_request(dnsreq); getdns_context_clear_outbound_request(dnsreq);
switch (netreq->request_type) { switch (netreq->request_type) {
case GETDNS_RRTYPE_DS : break; case GETDNS_RRTYPE_DS : node->ds.pkt = netreq->response;
case GETDNS_RRTYPE_DNSKEY: node->dnskey.netreq = netreq; node->ds.pkt_len = netreq->response_len;
break;
case GETDNS_RRTYPE_DNSKEY: node->dnskey.pkt = netreq->response;
node->dnskey.pkt_len = netreq->response_len;
default : check_chain_complete(node->chains); default : check_chain_complete(node->chains);
return; return;
} }
for (i = rrset_iter_init(&i_spc, netreq); i; i = rrset_iter_next(i)) { for ( i = rrset_iter_init(&i_spc,netreq->response,netreq->response_len)
; i
; i = rrset_iter_next(i)) {
rrset = rrset_iter_value(i); rrset = rrset_iter_value(i);
if (rrset->rr_type != GETDNS_RRTYPE_DS && if (rrset->rr_type != GETDNS_RRTYPE_DS &&
@ -608,9 +643,12 @@ static getdns_rrset *rrset_by_type(
rrset_iter *i; rrset_iter *i;
getdns_rrset *rrset; getdns_rrset *rrset;
for (i = rrset_iter_init(i_spc, netreq); i; i = rrset_iter_next(i)) { for ( i = rrset_iter_init(i_spc,netreq->response,netreq->response_len)
; i
; i = rrset_iter_next(i)) {
rrset = rrset_iter_value(i); rrset = rrset_iter_value(i);
if (rrset->rr_type == rr_type) if (rrset->rr_type == rr_type) /* Check class too? */
return rrset; return rrset;
} }
return NULL; return NULL;
@ -628,7 +666,7 @@ static void val_chain_node_soa_cb(getdns_dns_req *dnsreq)
if ((rrset = rrset_by_type(&i_spc, netreq, GETDNS_RRTYPE_SOA))) { if ((rrset = rrset_by_type(&i_spc, netreq, GETDNS_RRTYPE_SOA))) {
while (node && while (node &&
! priv_getdns_dname_equal(node->soa.name, rrset->name)) ! priv_getdns_dname_equal(node->ds.name, rrset->name))
node = node->parent; node = node->parent;
val_chain_sched_node(node); val_chain_sched_node(node);
@ -658,8 +696,8 @@ static uint8_t **reverse_labels(uint8_t *dname, uint8_t **labels)
return labels + 1; return labels + 1;
} }
static chain_head *add_rrset2val_chain( static chain_head *add_rrset2val_chain(struct mem_funcs *mf,
struct mem_funcs *mf, chain_head **chain_p, getdns_rrset *rrset) chain_head **chain_p, getdns_rrset *rrset, getdns_network_req *netreq)
{ {
chain_head *head; chain_head *head;
uint8_t *labels[128], **last_label, **label; uint8_t *labels[128], **last_label, **label;
@ -731,7 +769,9 @@ static chain_head *add_rrset2val_chain(
memcpy(head->name_spc, rrset->name, dname_len); memcpy(head->name_spc, rrset->name, dname_len);
head->rrset.rr_class = rrset->rr_class; head->rrset.rr_class = rrset->rr_class;
head->rrset.rr_type = rrset->rr_type; head->rrset.rr_type = rrset->rr_type;
head->rrset.netreq = rrset->netreq; head->rrset.pkt = rrset->pkt;
head->rrset.pkt_len = rrset->pkt_len;
head->netreq = netreq;
head->node_count = node_count; head->node_count = node_count;
if (!node_count) { if (!node_count) {
@ -748,21 +788,21 @@ static chain_head *add_rrset2val_chain(
; node_count ; node_count
; node_count--, node = node->parent =&node[1], dname += *dname + 1) { ; node_count--, node = node->parent =&node[1], dname += *dname + 1) {
node->chains = *chain_p;
node->ds.name = dname; node->ds.name = dname;
node->dnskey.name = dname; node->dnskey.name = dname;
node->soa.name = dname;
node->ds.rr_class = head->rrset.rr_class; node->ds.rr_class = head->rrset.rr_class;
node->dnskey.rr_class = head->rrset.rr_class; node->dnskey.rr_class = head->rrset.rr_class;
node->soa.rr_class = head->rrset.rr_class;
node->ds.rr_type = GETDNS_RRTYPE_DS; node->ds.rr_type = GETDNS_RRTYPE_DS;
node->dnskey.rr_type = GETDNS_RRTYPE_DNSKEY; node->dnskey.rr_type = GETDNS_RRTYPE_DNSKEY;
node->soa.rr_type = GETDNS_RRTYPE_SOA; node->ds.pkt = NULL;
node->ds.netreq = NULL; node->ds.pkt_len = 0;
node->dnskey.netreq = NULL; node->dnskey.pkt = NULL;
node->soa.netreq = NULL; node->dnskey.pkt_len = 0;
node->ds_req = NULL;
node->dnskey_req = NULL;
node->soa_req = NULL;
node->soa.rr_class = head->rrset.rr_class; node->chains = *chain_p;
} }
/* On the first chain, max_node == NULL. /* On the first chain, max_node == NULL.
* Schedule a root DNSKEY query, we always need that. * Schedule a root DNSKEY query, we always need that.
@ -801,17 +841,21 @@ static void add_netreq2val_chain(
empty_rrset.name = netreq->query + GLDNS_HEADER_SIZE; empty_rrset.name = netreq->query + GLDNS_HEADER_SIZE;
empty_rrset.rr_class = GETDNS_RRCLASS_IN; empty_rrset.rr_class = GETDNS_RRCLASS_IN;
empty_rrset.rr_type = 0; empty_rrset.rr_type = 0;
empty_rrset.netreq = netreq; empty_rrset.pkt = netreq->response;
empty_rrset.pkt_len = netreq->response_len;
head = add_rrset2val_chain(mf, chain_p, &empty_rrset); head = add_rrset2val_chain(mf, chain_p, &empty_rrset, netreq);
val_chain_sched_soa(head, empty_rrset.name); val_chain_sched_soa(head, empty_rrset.name);
return; return;
} }
for (i = rrset_iter_init(&i_spc, netreq); i; i = rrset_iter_next(i)) { for ( i = rrset_iter_init(&i_spc,netreq->response,netreq->response_len)
; i
; i = rrset_iter_next(i)) {
rrset = rrset_iter_value(i); rrset = rrset_iter_value(i);
debug_sec_print_rrset("rrset: ", rrset); debug_sec_print_rrset("rrset: ", rrset);
head = add_rrset2val_chain(mf, chain_p, rrset); head = add_rrset2val_chain(mf, chain_p, rrset, netreq);
for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset), n_rrsigs = 0 for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset), n_rrsigs = 0
; rrsig ; rrsig
; rrsig = rrsig_iter_next(rrsig), n_rrsigs++) { ; rrsig = rrsig_iter_next(rrsig), n_rrsigs++) {