mirror of https://github.com/getdnsapi/getdns.git
Add srv_addresses when query was for SRV
Moved _getdns_rrset iterators to rr-iter.[ch] in the process
This commit is contained in:
parent
5e74185327
commit
cf675a9284
|
@ -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);
|
||||
|
|
631
src/dnssec.c
631
src/dnssec.c
File diff suppressed because it is too large
Load Diff
|
@ -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) !=
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
201
src/rr-iter.c
201
src/rr-iter.c
|
@ -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;
|
||||
|
|
105
src/rr-iter.h
105
src/rr-iter.h
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue