Add srv_addresses when query was for SRV

Moved _getdns_rrset iterators to rr-iter.[ch] in the process
This commit is contained in:
Willem Toorop 2016-06-07 16:52:10 +02:00
parent 5e74185327
commit cf675a9284
9 changed files with 687 additions and 522 deletions

View File

@ -601,8 +601,11 @@ _getdns_wire2msg_dict_scan(struct mem_funcs *mf,
getdns_return_t r = GETDNS_RETURN_GOOD; getdns_return_t r = GETDNS_RETURN_GOOD;
getdns_dict *result = NULL, *header = NULL, *rr_dict = NULL; getdns_dict *result = NULL, *header = NULL, *rr_dict = NULL;
_getdns_rr_iter rr_iter_storage, *rr_iter; _getdns_rr_iter rr_iter_storage, *rr_iter;
gldns_pkt_section section; _getdns_section section;
getdns_list *sections[4] = { NULL, NULL, NULL, NULL }; 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 */ const uint8_t *eop; /* end of packet */
if (!wire || !*wire || !wire_len || !msg_dict) 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)) || if (!(result = _getdns_dict_create_with_mf(mf)) ||
!(header = _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)) || = _getdns_list_create_with_mf(mf)) ||
!(sections[GLDNS_SECTION_AUTHORITY] !(sections[SECTION_AUTHORITY]
= _getdns_list_create_with_mf(mf)) || = _getdns_list_create_with_mf(mf)) ||
!(sections[GLDNS_SECTION_ADDITIONAL] !(sections[SECTION_ADDITIONAL]
= _getdns_list_create_with_mf(mf))) { = _getdns_list_create_with_mf(mf))) {
r = GETDNS_RETURN_MEMORY_ERROR; r = GETDNS_RETURN_MEMORY_ERROR;
goto error; goto error;
@ -653,14 +656,14 @@ _getdns_wire2msg_dict_scan(struct mem_funcs *mf,
continue; continue;
switch ((section = _getdns_rr_iter_section(rr_iter))) { switch ((section = _getdns_rr_iter_section(rr_iter))) {
case GLDNS_SECTION_QUESTION: case SECTION_QUESTION:
if ((r = _getdns_dict_set_this_dict( if ((r = _getdns_dict_set_this_dict(
result, "question", rr_dict))) result, "question", rr_dict)))
goto error; goto error;
break; break;
case GLDNS_SECTION_ANSWER: case SECTION_ANSWER:
case GLDNS_SECTION_AUTHORITY: case SECTION_AUTHORITY:
case GLDNS_SECTION_ADDITIONAL: case SECTION_ADDITIONAL:
if ((r = _getdns_list_append_this_dict( if ((r = _getdns_list_append_this_dict(
sections[section], rr_dict))) sections[section], rr_dict)))
goto error; goto error;
@ -672,27 +675,27 @@ _getdns_wire2msg_dict_scan(struct mem_funcs *mf,
rr_dict = NULL; rr_dict = NULL;
} }
if (!(r = _getdns_dict_set_this_list(result, "answer", if (!(r = _getdns_dict_set_this_list(result, "answer",
sections[GLDNS_SECTION_ANSWER]))) sections[SECTION_ANSWER])))
sections[GLDNS_SECTION_ANSWER] = NULL; sections[SECTION_ANSWER] = NULL;
else goto error; else goto error;
if (!(r = _getdns_dict_set_this_list(result, "authority", if (!(r = _getdns_dict_set_this_list(result, "authority",
sections[GLDNS_SECTION_AUTHORITY]))) sections[SECTION_AUTHORITY])))
sections[GLDNS_SECTION_AUTHORITY] = NULL; sections[SECTION_AUTHORITY] = NULL;
else goto error; else goto error;
if (!(r = _getdns_dict_set_this_list(result, "additional", if (!(r = _getdns_dict_set_this_list(result, "additional",
sections[GLDNS_SECTION_ADDITIONAL]))) sections[SECTION_ADDITIONAL])))
sections[GLDNS_SECTION_ADDITIONAL] = NULL; sections[SECTION_ADDITIONAL] = NULL;
else goto error; else goto error;
*wire_len -= (eop - *wire); *wire_len -= (eop - *wire);
*wire = eop; *wire = eop;
error: error:
getdns_dict_destroy(rr_dict); getdns_dict_destroy(rr_dict);
getdns_list_destroy(sections[GLDNS_SECTION_ADDITIONAL]); getdns_list_destroy(sections[SECTION_ADDITIONAL]);
getdns_list_destroy(sections[GLDNS_SECTION_AUTHORITY]); getdns_list_destroy(sections[SECTION_AUTHORITY]);
getdns_list_destroy(sections[GLDNS_SECTION_ANSWER]); getdns_list_destroy(sections[SECTION_ANSWER]);
getdns_dict_destroy(header); getdns_dict_destroy(header);
if (r) if (r)
getdns_dict_destroy(result); getdns_dict_destroy(result);

File diff suppressed because it is too large Load Diff

View File

@ -108,11 +108,11 @@ no_answer(getdns_dns_req *dns_req)
, netreq->response , netreq->response
, netreq->response_len) , netreq->response_len)
; rr && _getdns_rr_iter_section(rr) ; rr && _getdns_rr_iter_section(rr)
<= GLDNS_SECTION_ANSWER <= SECTION_ANSWER
; rr = _getdns_rr_iter_next(rr)) { ; rr = _getdns_rr_iter_next(rr)) {
if (_getdns_rr_iter_section(rr) != if (_getdns_rr_iter_section(rr) !=
GLDNS_SECTION_ANSWER) SECTION_ANSWER)
continue; continue;
if (gldns_read_uint16(rr->rr_type) != if (gldns_read_uint16(rr->rr_type) !=
@ -137,11 +137,11 @@ no_answer(getdns_dns_req *dns_req)
, netreq->response , netreq->response
, netreq->response_len) , netreq->response_len)
; rr && _getdns_rr_iter_section(rr) ; rr && _getdns_rr_iter_section(rr)
<= GLDNS_SECTION_ANSWER <= SECTION_ANSWER
; rr = _getdns_rr_iter_next(rr)) { ; rr = _getdns_rr_iter_next(rr)) {
if (_getdns_rr_iter_section(rr) != if (_getdns_rr_iter_section(rr) !=
GLDNS_SECTION_ANSWER) SECTION_ANSWER)
continue; continue;
if (gldns_read_uint16(rr->rr_type) != if (gldns_read_uint16(rr->rr_type) !=

View File

@ -478,7 +478,7 @@ _getdns_network_validate_tsig(getdns_network_req *req)
; rr ; rr
; rr = _getdns_rr_iter_next(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) gldns_read_uint16(rr->rr_type) == GETDNS_RRTYPE_TSIG)
break; break;
} }
@ -501,7 +501,7 @@ _getdns_network_validate_tsig(getdns_network_req *req)
; rr ; rr
; rr = _getdns_rr_iter_next(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) gldns_read_uint16(rr->rr_type) == GETDNS_RRTYPE_TSIG)
break; break;
} }

View File

@ -31,8 +31,25 @@
#include "rr-iter.h" #include "rr-iter.h"
#include "config.h" #include "config.h"
#include <ctype.h>
#include "gldns/rrdef.h" #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 static void
rr_iter_find_nxt(_getdns_rr_iter *i) rr_iter_find_nxt(_getdns_rr_iter *i)
{ {
@ -118,15 +135,6 @@ _getdns_single_rr_iter_init(
return find_rrtype(i); 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 *
_getdns_rr_iter_next(_getdns_rr_iter *i) _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); 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 * static _getdns_rdf_iter *
rdf_iter_find_nxt(_getdns_rdf_iter *i) 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; i->end = NULL;
/* rr_iter already done or in question section */ /* 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; goto done;
i->pkt = rr->pkt; i->pkt = rr->pkt;

View File

@ -32,10 +32,20 @@
#ifndef RR_ITER_H_ #ifndef RR_ITER_H_
#define RR_ITER_H_ #define RR_ITER_H_
#include "getdns/getdns.h"
#include "rr-dict.h" #include "rr-dict.h"
#include "gldns/pkthdr.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 { typedef struct _getdns_rr_iter {
const uint8_t *pkt; 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, _getdns_rr_iter *_getdns_single_rr_iter_init(_getdns_rr_iter *i,
const uint8_t *wire, const size_t wire_len); 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); _getdns_rr_iter *_getdns_rr_iter_next(_getdns_rr_iter *i);
const uint8_t *_getdns_owner_if_or_as_decompressed( const uint8_t *_getdns_owner_if_or_as_decompressed(
_getdns_rr_iter *i, uint8_t *ff_bytes, size_t *len); _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) _getdns_rr_iter_section(_getdns_rr_iter *i)
{ {
return !i->pkt ? (i->nxt - i->rr_type == 4 ? GLDNS_SECTION_QUESTION return !i->pkt ? (i->nxt - i->rr_type == 4 ? SECTION_QUESTION
: GLDNS_SECTION_ANSWER ) : SECTION_ANSWER )
: i->n < GLDNS_QDCOUNT(i->pkt) ? GLDNS_SECTION_QUESTION : i->n < GLDNS_QDCOUNT(i->pkt) ? SECTION_QUESTION
: i->n < GLDNS_QDCOUNT(i->pkt) : 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) : i->n < GLDNS_QDCOUNT(i->pkt)
+ GLDNS_ANCOUNT(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) : i->n < GLDNS_QDCOUNT(i->pkt)
+ GLDNS_ANCOUNT(i->pkt) + GLDNS_ANCOUNT(i->pkt)
+ GLDNS_NSCOUNT(i->pkt) + GLDNS_NSCOUNT(i->pkt)
+ GLDNS_ARCOUNT(i->pkt) ? GLDNS_SECTION_ADDITIONAL + GLDNS_ARCOUNT(i->pkt) ? SECTION_ADDITIONAL
: GLDNS_SECTION_ANY; : 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;
const uint8_t *pkt_end; const uint8_t *pkt_end;
const _getdns_rdata_def *rdd_pos; 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( const uint8_t *_getdns_rdf_if_or_as_decompressed(
_getdns_rdf_iter *i, uint8_t *ff_bytes, size_t *len); _getdns_rdf_iter *i, uint8_t *ff_bytes, size_t *len);
#endif #endif

View File

@ -225,8 +225,7 @@ match_edns_opt_rr(uint16_t code, uint8_t *response, size_t response_len,
; rr_iter ; rr_iter
; rr_iter = _getdns_rr_iter_next(rr_iter)) { ; rr_iter = _getdns_rr_iter_next(rr_iter)) {
if (_getdns_rr_iter_section(rr_iter) != if (_getdns_rr_iter_section(rr_iter) != SECTION_ADDITIONAL)
GLDNS_SECTION_ADDITIONAL)
continue; continue;
if (gldns_read_uint16(rr_iter->rr_type) != GETDNS_RRTYPE_OPT) if (gldns_read_uint16(rr_iter->rr_type) != GETDNS_RRTYPE_OPT)

View File

@ -37,7 +37,6 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h>
#include "config.h" #include "config.h"
#include "getdns/getdns.h" #include "getdns/getdns.h"
#include "dict.h" #include "dict.h"
@ -178,7 +177,7 @@ _getdns_rr_iter2rr_dict_canonical(
owner_len = bin_size; owner_len = bin_size;
} }
/* question */ /* 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", if (getdns_dict_set_int(rr_dict, "qtype",
(uint32_t) gldns_read_uint16(i->rr_type)) || (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); 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 * inline static getdns_dict *
set_dict(getdns_dict **var, getdns_dict *value) 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; 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) \ #define SET_WIRE_INT(X,Y) if (getdns_dict_set_int(header, #X , (int) \
GLDNS_ ## Y ## _WIRE(req->response))) goto error GLDNS_ ## Y ## _WIRE(req->response))) goto error
#define SET_WIRE_BIT(X,Y) if (getdns_dict_set_int(header, #X , \ #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) \ #define SET_WIRE_CNT(X,Y) if (getdns_dict_set_int(header, #X , (int) \
GLDNS_ ## Y (req->response))) goto error GLDNS_ ## Y (req->response))) goto error
getdns_dict * static getdns_dict *
_getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, _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 /* 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_return_t r = GETDNS_RETURN_GOOD;
getdns_dict *result = getdns_dict_create_with_context(context); getdns_dict *result = getdns_dict_create_with_context(context);
getdns_dict *question = NULL; getdns_dict *question = NULL;
getdns_list *sections[4] = { NULL getdns_list *sections[16] = { NULL, NULL
, getdns_list_create_with_context(context) , getdns_list_create_with_context(context)
, NULL
, getdns_list_create_with_context(context) , getdns_list_create_with_context(context)
, NULL, NULL, NULL
, getdns_list_create_with_context(context) , getdns_list_create_with_context(context)
, NULL, NULL, NULL, NULL, NULL, NULL, NULL
}; };
getdns_dict *rr_dict = NULL; getdns_dict *rr_dict = NULL;
_getdns_rr_iter rr_iter_storage, *rr_iter; _getdns_rr_iter rr_iter_storage, *rr_iter;
_getdns_rdf_iter rdf_iter_storage, *rdf_iter; _getdns_rdf_iter rdf_iter_storage, *rdf_iter;
size_t bin_size; size_t bin_size;
const uint8_t *bin_data; const uint8_t *bin_data;
gldns_pkt_section section; _getdns_section section;
uint8_t canonical_name_space[256], owner_name_space[256], uint8_t canonical_name_space[256], owner_name_space[256],
query_name_space[256]; query_name_space[256];
const uint8_t *canonical_name, *owner_name, *query_name; 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; continue;
section = _getdns_rr_iter_section(rr_iter); section = _getdns_rr_iter_section(rr_iter);
if (section == GLDNS_SECTION_QUESTION) { if (section == SECTION_QUESTION) {
if (!query_name) if (!query_name)
query_name query_name
= _getdns_owner_if_or_as_decompressed( = _getdns_owner_if_or_as_decompressed(
@ -617,11 +623,11 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req,
continue; continue;
} }
rr_type = gldns_read_uint16(rr_iter->rr_type); 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) rr_type == GETDNS_RRTYPE_RRSIG && rrsigs_in_answer)
*rrsigs_in_answer = 1; *rrsigs_in_answer = 1;
if (section != GLDNS_SECTION_ANSWER) { if (section != SECTION_ANSWER) {
if (_getdns_list_append_this_dict( if (_getdns_list_append_this_dict(
sections[section], rr_dict)) sections[section], rr_dict))
goto error; goto error;
@ -637,7 +643,7 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req,
continue; continue;
} }
if (_getdns_list_append_this_dict( if (_getdns_list_append_this_dict(
sections[GLDNS_SECTION_ANSWER], rr_dict)) sections[SECTION_ANSWER], rr_dict))
goto error; goto error;
else rr_dict = NULL; 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); rdf_iter,canonical_name_space,&canonical_name_len);
continue; 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) if (rr_type != GETDNS_RRTYPE_A && rr_type != GETDNS_RRTYPE_AAAA)
continue; continue;
if (!just_addrs)
continue;
if (!(rdf_iter = _getdns_rdf_iter_init( if (!(rdf_iter = _getdns_rdf_iter_init(
&rdf_iter_storage, rr_iter))) &rdf_iter_storage, rr_iter)))
continue; continue;
if (!just_addrs)
continue;
bin_size = rdf_iter->nxt - rdf_iter->pos; bin_size = rdf_iter->nxt - rdf_iter->pos;
bin_data = rdf_iter->pos; bin_data = rdf_iter->pos;
if (!set_dict(&rr_dict, getdns_dict_create_with_context(context)) || 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; rr_dict = NULL;
} }
if (!_getdns_dict_set_this_list(result, "answer", if (!_getdns_dict_set_this_list(result, "answer",
sections[GLDNS_SECTION_ANSWER])) sections[SECTION_ANSWER]))
sections[GLDNS_SECTION_ANSWER] = NULL; sections[SECTION_ANSWER] = NULL;
else goto error; else goto error;
if (!_getdns_dict_set_this_list(result, "authority", if (!_getdns_dict_set_this_list(result, "authority",
sections[GLDNS_SECTION_AUTHORITY])) sections[SECTION_AUTHORITY]))
sections[GLDNS_SECTION_AUTHORITY] = NULL; sections[SECTION_AUTHORITY] = NULL;
else goto error; else goto error;
if (!_getdns_dict_set_this_list(result, "additional", if (!_getdns_dict_set_this_list(result, "additional",
sections[GLDNS_SECTION_ADDITIONAL])) sections[SECTION_ADDITIONAL]))
sections[GLDNS_SECTION_ADDITIONAL] = NULL; sections[SECTION_ADDITIONAL] = NULL;
else goto error; else goto error;
/* other stuff /* other stuff
@ -714,11 +727,11 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req,
, req->response , req->response
, req->response_len) , req->response_len)
; rr_iter && _getdns_rr_iter_section(rr_iter) ; rr_iter && _getdns_rr_iter_section(rr_iter)
<= GLDNS_SECTION_ANSWER <= SECTION_ANSWER
; rr_iter = _getdns_rr_iter_next(rr_iter)) { ; rr_iter = _getdns_rr_iter_next(rr_iter)) {
if (_getdns_rr_iter_section(rr_iter) != if (_getdns_rr_iter_section(rr_iter) !=
GLDNS_SECTION_ANSWER) SECTION_ANSWER)
continue; continue;
if (gldns_read_uint16(rr_iter->rr_type) != 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
, req->response_len) , req->response_len)
; rr_iter && _getdns_rr_iter_section(rr_iter) ; rr_iter && _getdns_rr_iter_section(rr_iter)
<= GLDNS_SECTION_ANSWER <= SECTION_ANSWER
; rr_iter = _getdns_rr_iter_next(rr_iter)) { ; rr_iter = _getdns_rr_iter_next(rr_iter)) {
if (_getdns_rr_iter_section(rr_iter) != if (_getdns_rr_iter_section(rr_iter) !=
GLDNS_SECTION_ANSWER) SECTION_ANSWER)
continue; continue;
if (gldns_read_uint16(rr_iter->rr_type) != if (gldns_read_uint16(rr_iter->rr_type) !=
req->request_type) req->request_type)
@ -793,7 +806,7 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req,
break; break;
} }
if (_getdns_rr_iter_section(rr_iter) == if (_getdns_rr_iter_section(rr_iter) ==
GLDNS_SECTION_QUESTION) SECTION_QUESTION)
continue; continue;
for ( rdf_iter = _getdns_rdf_iter_init(&rdf_iter_storage, rr_iter) for ( rdf_iter = _getdns_rdf_iter_init(&rdf_iter_storage, rr_iter)
@ -826,15 +839,15 @@ error:
success: success:
getdns_dict_destroy(header); getdns_dict_destroy(header);
getdns_dict_destroy(rr_dict); getdns_dict_destroy(rr_dict);
getdns_list_destroy(sections[GLDNS_SECTION_ADDITIONAL]); getdns_list_destroy(sections[SECTION_ADDITIONAL]);
getdns_list_destroy(sections[GLDNS_SECTION_AUTHORITY]); getdns_list_destroy(sections[SECTION_AUTHORITY]);
getdns_list_destroy(sections[GLDNS_SECTION_ANSWER]); getdns_list_destroy(sections[SECTION_ANSWER]);
getdns_dict_destroy(question); getdns_dict_destroy(question);
getdns_list_destroy(bad_dns); getdns_list_destroy(bad_dns);
return result; return result;
} }
getdns_dict * static getdns_dict *
_getdns_create_call_reporting_dict( _getdns_create_call_reporting_dict(
getdns_context *context, getdns_network_req *netreq) getdns_context *context, getdns_network_req *netreq)
{ {
@ -918,11 +931,93 @@ _getdns_create_call_reporting_dict(
return netreq_debug; 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_dict *
_getdns_create_getdns_response(getdns_dns_req *completed_request) _getdns_create_getdns_response(getdns_dns_req *completed_request)
{ {
getdns_dict *result; getdns_dict *result;
getdns_list *just_addrs = NULL; getdns_list *just_addrs = NULL;
getdns_list *srv_addrs = NULL;
getdns_list *replies_full; getdns_list *replies_full;
getdns_list *replies_tree; getdns_list *replies_tree;
getdns_list *call_reporting = NULL; getdns_list *call_reporting = NULL;
@ -932,6 +1027,7 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
getdns_bindata *canonical_name = NULL; getdns_bindata *canonical_name = NULL;
int nreplies = 0, nanswers = 0, nsecure = 0, ninsecure = 0, nbogus = 0; int nreplies = 0, nanswers = 0, nsecure = 0, ninsecure = 0, nbogus = 0;
getdns_dict *netreq_debug; getdns_dict *netreq_debug;
_srvs srvs = { 0, 0, NULL };
/* info (bools) about dns_req */ /* info (bools) about dns_req */
int dnssec_return_status; int dnssec_return_status;
@ -956,6 +1052,16 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
just_addrs = getdns_list_create_with_context( just_addrs = getdns_list_create_with_context(
completed_request->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, if (getdns_dict_set_int(result, GETDNS_STR_KEY_ANSWER_TYPE,
GETDNS_NAMETYPE_DNS)) GETDNS_NAMETYPE_DNS))
goto error_free_result; goto error_free_result;
@ -1002,7 +1108,7 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
continue; continue;
} }
if (!(reply = _getdns_create_reply_dict(context, if (!(reply = _getdns_create_reply_dict(context,
netreq, just_addrs, &rrsigs_in_answer))) netreq, just_addrs, &rrsigs_in_answer, &srvs)))
goto error; goto error;
if (!canonical_name) { if (!canonical_name) {
@ -1074,6 +1180,14 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
goto error_free_result; goto error_free_result;
just_addrs = NULL; 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, if (getdns_dict_set_int(result, GETDNS_STR_KEY_STATUS,
nreplies == 0 ? GETDNS_RESPSTATUS_ALL_TIMEOUT : nreplies == 0 ? GETDNS_RESPSTATUS_ALL_TIMEOUT :
completed_request->dnssec_return_only_secure && nsecure == 0 && ninsecure > 0 completed_request->dnssec_return_only_secure && nsecure == 0 && ninsecure > 0
@ -1093,6 +1207,9 @@ error_free_call_reporting:
error_free_replies_full: error_free_replies_full:
getdns_list_destroy(replies_full); getdns_list_destroy(replies_full);
error_free_result: error_free_result:
if (srvs.capacity)
GETDNS_FREE(context->mf, srvs.rrs);
getdns_list_destroy(srv_addrs);
getdns_list_destroy(just_addrs); getdns_list_destroy(just_addrs);
getdns_dict_destroy(result); getdns_dict_destroy(result);
return NULL; return NULL;

View File

@ -149,13 +149,8 @@ _getdns_rr_iter2rr_dict_canonical(
struct getdns_dns_req; struct getdns_dns_req;
struct getdns_dict *_getdns_create_getdns_response(struct getdns_dns_req *completed_request); 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); 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( uint8_t *_getdns_list2wire(
getdns_list *l, uint8_t *buf, size_t *buf_len, struct mem_funcs *mf); getdns_list *l, uint8_t *buf, size_t *buf_len, struct mem_funcs *mf);