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_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);

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_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) !=

View File

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

View File

@ -31,8 +31,25 @@
#include "rr-iter.h"
#include "config.h"
#include <ctype.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
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;

View File

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

View File

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

View File

@ -37,7 +37,6 @@
#include <stdint.h>
#include <stdlib.h>
#include <ctype.h>
#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;

View File

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