aboutsummaryrefslogtreecommitdiff
path: root/contrib/ldns/host2wire.c
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2018-05-12 12:00:18 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2018-05-12 12:00:18 +0000
commit986ba33c7a3bc8f5ba13c7a9d6512602f6e32c61 (patch)
treedd23d78391142ca52f5e216e5338a5253cf6bec3 /contrib/ldns/host2wire.c
parentb3092f3cf05b8e45465e5b240d7ab231ec884c5a (diff)
parentc6342fe2e90510d8d2296423f2ca92818a7b3d18 (diff)
downloadsrc-986ba33c7a3bc8f5ba13c7a9d6512602f6e32c61.tar.gz
src-986ba33c7a3bc8f5ba13c7a9d6512602f6e32c61.zip
Upgrade LDNS to 1.7.0.
I've been holding back on this because 1.7.0 requires OpenSSL 1.1.0 or newer for full DANE support. But we can't wait forever, and nothing in base uses DANE anyway, so here we go.
Notes
Notes: svn path=/head/; revision=333551
Diffstat (limited to 'contrib/ldns/host2wire.c')
-rw-r--r--contrib/ldns/host2wire.c162
1 files changed, 133 insertions, 29 deletions
diff --git a/contrib/ldns/host2wire.c b/contrib/ldns/host2wire.c
index 8fb5c3a2ba59..4d8aa30f2d85 100644
--- a/contrib/ldns/host2wire.c
+++ b/contrib/ldns/host2wire.c
@@ -16,25 +16,100 @@
#include <ldns/ldns.h>
-/* TODO Jelte
- add a pointer to a 'possiblecompression' structure
- to all the needed functions?
- something like an array of name, pointer values?
- every dname part could be added to it
-*/
-
ldns_status
ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name)
{
- if (ldns_buffer_reserve(buffer, ldns_rdf_size(name))) {
- ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name));
+ return ldns_dname2buffer_wire_compress(buffer, name, NULL);
+}
+
+ldns_status
+ldns_dname2buffer_wire_compress(ldns_buffer *buffer, const ldns_rdf *name, ldns_rbtree_t *compression_data)
+{
+ ldns_rbnode_t *node;
+ uint8_t *data;
+ size_t size;
+ ldns_rdf *label;
+ ldns_rdf *rest;
+ ldns_status s;
+
+ /* If no tree, just add the data */
+ if(!compression_data)
+ {
+ if (ldns_buffer_reserve(buffer, ldns_rdf_size(name)))
+ {
+ ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name));
+ }
+ return ldns_buffer_status(buffer);
+ }
+
+ /* No labels left, write final zero */
+ if(ldns_dname_label_count(name)==0)
+ {
+ if(ldns_buffer_reserve(buffer,1))
+ {
+ ldns_buffer_write_u8(buffer, 0);
+ }
+ return ldns_buffer_status(buffer);
+ }
+
+ /* Can we find the name in the tree? */
+ if((node = ldns_rbtree_search(compression_data, name)) != NULL)
+ {
+ /* Found */
+ uint16_t position = (uint16_t) (intptr_t) node->data | 0xC000;
+ if (ldns_buffer_reserve(buffer, 2))
+ {
+ ldns_buffer_write_u16(buffer, position);
+ }
+ return ldns_buffer_status(buffer);
+ }
+ else
+ {
+ /* Not found. Write cache entry, take off first label, write it, */
+ /* try again with the rest of the name. */
+ node = LDNS_MALLOC(ldns_rbnode_t);
+ if(!node)
+ {
+ return LDNS_STATUS_MEM_ERR;
+ }
+ if (ldns_buffer_position(buffer) < 16384) {
+ node->key = ldns_rdf_clone(name);
+ node->data = (void *) (intptr_t) ldns_buffer_position(buffer);
+ if(!ldns_rbtree_insert(compression_data,node))
+ {
+ /* fprintf(stderr,"Name not found but now it's there?\n"); */
+ }
+ }
+ label = ldns_dname_label(name, 0);
+ rest = ldns_dname_left_chop(name);
+ size = ldns_rdf_size(label) - 1; /* Don't want the final zero */
+ data = ldns_rdf_data(label);
+ if(ldns_buffer_reserve(buffer, size))
+ {
+ ldns_buffer_write(buffer, data, size);
+ }
+ ldns_rdf_deep_free(label);
+ s = ldns_dname2buffer_wire_compress(buffer, rest, compression_data);
+ ldns_rdf_deep_free(rest);
+ return s;
}
- return ldns_buffer_status(buffer);
}
ldns_status
ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf)
{
+ return ldns_rdf2buffer_wire_compress(buffer, rdf, NULL);
+}
+
+ldns_status
+ldns_rdf2buffer_wire_compress(ldns_buffer *buffer, const ldns_rdf *rdf, ldns_rbtree_t *compression_data)
+{
+ /* If it's a DNAME, call that function to get compression */
+ if(compression_data && ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME)
+ {
+ return ldns_dname2buffer_wire_compress(buffer,rdf,compression_data);
+ }
+
if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf));
}
@@ -158,11 +233,17 @@ ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
ldns_status
ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
{
+ return ldns_rr2buffer_wire_compress(buffer,rr,section,NULL);
+}
+
+ldns_status
+ldns_rr2buffer_wire_compress(ldns_buffer *buffer, const ldns_rr *rr, int section, ldns_rbtree_t *compression_data)
+{
uint16_t i;
uint16_t rdl_pos = 0;
-
+
if (ldns_rr_owner(rr)) {
- (void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr));
+ (void) ldns_dname2buffer_wire_compress(buffer, ldns_rr_owner(rr), compression_data);
}
if (ldns_buffer_reserve(buffer, 4)) {
@@ -177,9 +258,18 @@ ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
rdl_pos = ldns_buffer_position(buffer);
ldns_buffer_write_u16(buffer, 0);
}
- for (i = 0; i < ldns_rr_rd_count(rr); i++) {
- (void) ldns_rdf2buffer_wire(
- buffer, ldns_rr_rdf(rr, i));
+ if (LDNS_RR_COMPRESS ==
+ ldns_rr_descript(ldns_rr_get_type(rr))->_compress) {
+
+ for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+ (void) ldns_rdf2buffer_wire_compress(buffer,
+ ldns_rr_rdf(rr, i), compression_data);
+ }
+ } else {
+ for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+ (void) ldns_rdf2buffer_wire(
+ buffer, ldns_rr_rdf(rr, i));
+ }
}
if (rdl_pos != 0) {
ldns_buffer_write_u16_at(buffer, rdl_pos,
@@ -214,6 +304,7 @@ ldns_status
ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
{
uint16_t i;
+
/* convert all the rdf's */
for (i = 0; i < ldns_rr_rd_count(rr); i++) {
(void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr,i));
@@ -229,7 +320,7 @@ ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
{
uint8_t flags;
uint16_t arcount;
-
+
if (ldns_buffer_reserve(buffer, 12)) {
ldns_buffer_write_u16(buffer, ldns_pkt_id(packet));
@@ -263,44 +354,54 @@ ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
return ldns_buffer_status(buffer);
}
+static void
+compression_node_free(ldns_rbnode_t *node, void *arg)
+{
+ (void)arg; /* Yes, dear compiler, it is used */
+ ldns_rdf_deep_free((ldns_rdf *)node->key);
+ LDNS_FREE(node);
+}
+
ldns_status
ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
{
ldns_rr_list *rr_list;
uint16_t i;
-
+
/* edns tmp vars */
ldns_rr *edns_rr;
uint8_t edata[4];
+
+ ldns_rbtree_t *compression_data = ldns_rbtree_create((int (*)(const void *, const void *))ldns_dname_compare);
(void) ldns_hdr2buffer_wire(buffer, packet);
rr_list = ldns_pkt_question(packet);
if (rr_list) {
for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
- (void) ldns_rr2buffer_wire(buffer,
- ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION);
+ (void) ldns_rr2buffer_wire_compress(buffer,
+ ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION, compression_data);
}
}
rr_list = ldns_pkt_answer(packet);
if (rr_list) {
for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
- (void) ldns_rr2buffer_wire(buffer,
- ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER);
+ (void) ldns_rr2buffer_wire_compress(buffer,
+ ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER, compression_data);
}
}
rr_list = ldns_pkt_authority(packet);
if (rr_list) {
for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
- (void) ldns_rr2buffer_wire(buffer,
- ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY);
+ (void) ldns_rr2buffer_wire_compress(buffer,
+ ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY, compression_data);
}
}
rr_list = ldns_pkt_additional(packet);
if (rr_list) {
for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
- (void) ldns_rr2buffer_wire(buffer,
- ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL);
+ (void) ldns_rr2buffer_wire_compress(buffer,
+ ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL, compression_data);
}
}
@@ -319,7 +420,7 @@ ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
/* don't forget to add the edns rdata (if any) */
if (packet->_edns_data)
ldns_rr_push_rdf (edns_rr, packet->_edns_data);
- (void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL);
+ (void)ldns_rr2buffer_wire_compress(buffer, edns_rr, LDNS_SECTION_ADDITIONAL, compression_data);
/* take the edns rdata back out of the rr before we free rr */
if (packet->_edns_data)
(void)ldns_rr_pop_rdf (edns_rr);
@@ -328,10 +429,13 @@ ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
/* add TSIG to additional if it is there */
if (ldns_pkt_tsig(packet)) {
- (void) ldns_rr2buffer_wire(buffer,
- ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL);
+ (void) ldns_rr2buffer_wire_compress(buffer,
+ ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL, compression_data);
}
-
+
+ ldns_traverse_postorder(compression_data,compression_node_free,NULL);
+ ldns_rbtree_free(compression_data);
+
return LDNS_STATUS_OK;
}