Commit 957cd007 authored by Ondrej Sury's avatar Ondrej Sury

Imported Upstream version 1.5.1

parent ac8f69d4
1.5.1
Example tools:
* ldns-signzone was broken in 1.5.0 for multiple keys, this
has been repaired
Build system:
* Removed a small erroneous output warning in
examples/configure and drill/configure
1.5.0
Bug fixes:
* fixed a possible memory overflow in the RR parser
* build flag fix for Sun Studio
* fixed a building race condition in the copying of header
files
* EDNS0 extended rcode; the correct assembled code number
is now printed (still in the EDNS0 field, though)
* ldns_pkt_rr no longer leaks memory (in fact, it no longer
copies anything all)
API addition:
* ldns_key now has support for 'external' data, in which
case the OpenSSL EVP structures are not used;
ldns_key_set_external_key() and ldns_key_external_key()
* added ldns_key_get_file_base_name() which creates a
'default' filename base string for key storage, of the
form "K<zone>+<algorithm>+<keytag>"
* the ldns_dnssec_* family of structures now have deep_free()
functions, which also free the ldns_rr's contained in them
* there is now an ldns_match_wildcard() function, which checks
whether a domain name matches a wildcard name
* ldns_sign_public has been split up; this resulted in the
addition of ldns_create_empty_rrsig() and
ldns_sign_public_buffer()
Examples:
* ldns-signzone can now automatically add DNSKEY records when
using an OpenSSL engine, as it already did when using key
files
* added new example tool: ldns-nsec3-hash
* ldns-dpa can now filter on specific query name and types
* ldnsd has fixes for the zone name, a fix for the return
value of recvfrom(), and an memory initialization fix
(Thanks to Colm MacCárthaigh for the patch)
* Fixed memory leaks in ldnsd
1.4.1
Bug fixes:
* fixed a build issue where ldns lib existence was done too early
* removed unnecessary check for pcap.h
* NSEC3 optout flag now correctly printed in string output
* inttypes.h moved to configured inclusion
* fixed NSEC3 type bitmaps for empty nonterminals and unsigned
delegations
API addition:
* for that last fix, we added a new function
ldns_dname_add_from() that can clone parts of a dname
1.4.0
Bug fixes:
* sig chase return code fix (patch from Rafael Justo, bug id 189)
......
......@@ -102,7 +102,7 @@ libldns.la-export-all: $(LIBDNS_OBJECTS)
$(addprefix include/ldns/, $(notdir $(LIBDNS_HEADERS))): include/ldns/%.h: $(srcdir)/ldns/%.h
@if [ ! -d include ] ; then ($(INSTALL) -d include || echo "include exists") ; fi ;
@if [ ! -d include/ldns ] ; then (cd include; ln -s ../ldns ./ldns || echo "include/ldns exists") ; fi ;
MVPROG=/bin/cp $(INSTALL) -m 644 $< ./include/ldns/
$(INSTALL) -m 644 $< ./include/ldns/
copy-headers: $(addprefix include/ldns/, $(notdir $(LIBDNS_HEADERS)))
......@@ -114,7 +114,7 @@ doxygen: manpages
ifdef doxygen
# if we are not in base we need to copy some html files too
if [ ! -e doc/header.html ] ; then \
MVPROG=/bin/cp $(INSTALL) -m 644 $(srcdir)/doc/header.html doc/ ; \
$(INSTALL) -m 644 $(srcdir)/doc/header.html doc/ ; \
fi ;
$(doxygen) $(srcdir)/libdns.doxygen
endif
......@@ -142,9 +142,9 @@ uninstall-manpages:
install-h: lib
$(INSTALL) -m 755 -d $(DESTDIR)$(includedir)/ldns
for i in $(LIBDNS_HEADERS); do \
MVPROG=/bin/cp $(INSTALL) -m 644 $$i $(DESTDIR)$(includedir)/ldns/; done
MVPROG=/bin/cp $(INSTALL) -m 644 include/ldns/util.h $(DESTDIR)$(includedir)/ldns/
MVPROG=/bin/cp $(INSTALL) -m 644 include/ldns/net.h $(DESTDIR)$(includedir)/ldns/
$(INSTALL) -m 644 $$i $(DESTDIR)$(includedir)/ldns/; done
$(INSTALL) -m 644 include/ldns/util.h $(DESTDIR)$(includedir)/ldns/
$(INSTALL) -m 644 include/ldns/net.h $(DESTDIR)$(includedir)/ldns/
uninstall-h:
for i in $(LIBDNS_HEADERS); do \
......
......@@ -66,9 +66,11 @@ commands may be a little bit different on your machine. Most notable, you'll nee
ldns is developed by the ldns team at NLnet Labs. This team currently
consists of:
o Jelte Jansen
o Miek Gieben
o Wouter Wijngaards
Former main developers:
o Miek Gieben
* Credits
We have received patches from the following people, thanks!
o Erik Rozendaal
......
......@@ -4,7 +4,11 @@
# small list of commands to build all on a linux system
# libtoolize is needed for most other targets
libtoolize -c
# older versions of libtoolize do not support --install
# so you might need to remove that (with newer versions
# it is needed)
libtoolize -c --install
autoreconf
./configure
make
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -2,10 +2,10 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.56)
AC_INIT(ldns, 1.4.0, libdns@nlnetlabs.nl, libdns)
AC_INIT(ldns, 1.5.1, libdns@nlnetlabs.nl, libdns)
AC_CONFIG_SRCDIR([packet.c])
# needed to build correct soname
AC_SUBST(LIBTOOL_VERSION_INFO, "1:4:0")
AC_SUBST(LIBTOOL_VERSION_INFO, "1:5:1")
PACKAGE_VERSION="$PACKAGE_VERSION"
......@@ -47,6 +47,29 @@ $3
fi
])
CHECK_COMPILER_FLAG(std=c99, [C99FLAG="-std=c99"])
CHECK_COMPILER_FLAG(xc99, [C99FLAG="-xc99"])
# routine to copy files
# argument 1 is a list of files (relative to the source dir)
# argument 2 is a destination directory (relative to the current
# working directory
AC_DEFUN([COPY_FILES],
[
for file in $1; do
$srcdir/install-sh -m 644 $file $2
done
])
# copy all .h files in the dir at argument 1
# (relative to source) to the dir at argument 2
# (relative to current dir)
AC_DEFUN([COPY_HEADER_FILES],
[
echo "copying header files"
COPY_FILES($srcdir/$1/*.h, $2)
])
dnl routine to help check for needed compiler flags.
# if the given code compiles without the flag, execute argument 4
# if the given code only compiles with the flag, execute argument 3
......@@ -117,7 +140,7 @@ AC_CHECK_HEADERS([getopt.h time.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT])
# end mingw32 tests
CHECK_COMPILER_FLAG_NEEDED(-std=c99 -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600,
CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600,
[
#include "confdefs.h"
#include <stdlib.h>
......@@ -145,9 +168,9 @@ int test() {
a = isascii(32);
return a;
}
], [CFLAGS="$CFLAGS -std=c99 -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600"])
], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600"])
CHECK_COMPILER_FLAG_NEEDED(-std=c99,
CHECK_COMPILER_FLAG_NEEDED($C99FLAG,
[
#include <stdbool.h>
#include <ctype.h>
......@@ -156,7 +179,7 @@ int test() {
a = isblank(12);
return a;
}
], [CFLAGS="$CFLAGS -std=c99"])
], [CFLAGS="$CFLAGS $C99FLAG"])
CHECK_COMPILER_FLAG_NEEDED(-D_BSD_SOURCE,
[
......@@ -416,6 +439,15 @@ include_sys_socket_h=''
]
])
AC_SUBST(include_sys_socket_h)
AC_CHECK_HEADER(inttypes.h,
[
include_inttypes_h='#include <inttypes.h>'
AC_DEFINE(HAVE_INTTYPES_H, 1, [define if you have inttypes.h])
],[
include_inttypes_h=''
],[AC_INCLUDES_DEFAULT
])
AC_SUBST(include_inttypes_h)
AC_CHECK_TYPE(socklen_t, ,
[AC_DEFINE([socklen_t], [int], [Define to 'int' if not defined])], [
......@@ -675,7 +707,9 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
])
AC_CONFIG_FILES([Makefile ldns/net.h ldns/util.h])
AC_CONFIG_HEADER([ldns/config.h])
AC_OUTPUT
COPY_HEADER_FILES(ldns/, ldns/)
AC_CONFIG_SUBDIRS([drill])
......@@ -123,6 +123,35 @@ ldns_dname_reverse(const ldns_rdf *d)
return new;
}
ldns_rdf *
ldns_dname_clone_from(const ldns_rdf *d, uint16_t n)
{
uint8_t *data;
uint8_t label_size;
size_t data_size;
if (!d ||
ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME ||
ldns_dname_label_count(d) < n) {
return NULL;
}
data = ldns_rdf_data(d);
data_size = ldns_rdf_size(d);
while (n > 0) {
label_size = data[0] + 1;
data += label_size;
if (data_size < label_size) {
/* this label is very broken */
return NULL;
}
data_size -= label_size;
n--;
}
return ldns_dname_new_frm_data(data_size, data);
}
ldns_rdf *
ldns_dname_left_chop(const ldns_rdf *d)
{
......@@ -370,6 +399,27 @@ ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2)
return result;
}
int
ldns_dname_match_wildcard(const ldns_rdf *dname, const ldns_rdf *wildcard)
{
ldns_rdf *wc_chopped;
int result;
/* check whether it really is a wildcard */
if (ldns_dname_label_count(wildcard) > 0 &&
ldns_rdf_data(wildcard)[0] == 1 &&
ldns_rdf_data(wildcard)[1] == '*') {
/* ok, so the dname needs to be a subdomain of the wildcard
* without the *
*/
wc_chopped = ldns_dname_left_chop(wildcard);
result = (int) ldns_dname_is_subdomain(dname, wc_chopped);
ldns_rdf_deep_free(wc_chopped);
} else {
result = (ldns_dname_compare(dname, wildcard) == 0);
}
return result;
}
/* nsec test: does prev <= middle < next
* -1 = yes
* 0 = error/can't tell
......
......@@ -460,17 +460,16 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h)
}
break;
case LDNS_SHA256:
#ifdef USE_SHA2
#ifdef SHA256_DIGEST_LENGTH
digest = LDNS_XMALLOC(uint8_t, SHA256_DIGEST_LENGTH);
if (!digest) {
ldns_rr_free(ds);
return NULL;
}
#else
printf("[XX] SHA2 disabled\n");
return NULL;
#endif
break;
break;
}
data_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
......@@ -530,7 +529,7 @@ break;
break;
case LDNS_SHA256:
#ifdef USE_SHA2
#ifdef SHA256_DIGEST_LENGTH
(void) SHA256((unsigned char *) ldns_buffer_begin(data_buf),
ldns_buffer_position(data_buf),
(unsigned char*) digest);
......@@ -548,8 +547,8 @@ break;
ldns_rdf *
ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[],
size_t size,
ldns_rr_type nsec_type)
size_t size,
ldns_rr_type nsec_type)
{
size_t i;
uint8_t *bitmap;
......@@ -586,15 +585,6 @@ ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[],
(int) (7 - (i_type % 8)),
true);
}
/* always add nsec (if this is not nsec3 and rrsig */
i_type = LDNS_RR_TYPE_RRSIG;
ldns_set_bit(bitmap + (int) i_type / 8, (int) (7 - (i_type % 8)), true);
i_type = nsec_type;
if (i_type != LDNS_RR_TYPE_NSEC3) {
ldns_set_bit(bitmap + (int) i_type / 8,
(int) (7 - (i_type % 8)),
true);
}
/* fold it into windows TODO: can this be done directly? */
memset(cur_data, 0, 32);
......@@ -616,14 +606,13 @@ ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[],
cur_window++;
cur_window_max = 0;
memset(cur_data, 0, 32);
} else {
cur_data[i%32] = bitmap[i];
if (bitmap[i] > 0) {
cur_window_max = i%32;
}
}
cur_data[i%32] = bitmap[i];
if (bitmap[i] > 0) {
cur_window_max = i%32;
}
}
if (cur_window_max > 0) {
if (cur_window_max > 0 || cur_data[0] != 0) {
/* this window has stuff, add it */
data = LDNS_XREALLOC(data,
uint8_t,
......@@ -670,10 +659,14 @@ ldns_dnssec_create_nsec(ldns_dnssec_name *from,
type_count++;
cur_rrsets = cur_rrsets->next;
}
types[type_count] = LDNS_RR_TYPE_RRSIG;
type_count++;
types[type_count] = LDNS_RR_TYPE_NSEC;
type_count++;
ldns_rr_push_rdf(nsec_rr, ldns_dnssec_create_nsec_bitmap(types,
type_count,
nsec_type));
type_count,
nsec_type));
return nsec_rr;
}
......@@ -702,18 +695,18 @@ ldns_dnssec_create_nsec3(ldns_dnssec_name *from,
nsec_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3);
ldns_rr_set_owner(nsec_rr,
ldns_nsec3_hash_name(ldns_dnssec_name_name(from),
algorithm,
iterations,
salt_length,
salt));
ldns_nsec3_hash_name(ldns_dnssec_name_name(from),
algorithm,
iterations,
salt_length,
salt));
status = ldns_dname_cat(ldns_rr_owner(nsec_rr), zone_name);
ldns_nsec3_add_param_rdfs(nsec_rr,
algorithm,
flags,
iterations,
salt_length,
salt);
algorithm,
flags,
iterations,
salt_length,
salt);
cur_rrsets = from->rrsets;
while (cur_rrsets) {
......@@ -721,12 +714,20 @@ ldns_dnssec_create_nsec3(ldns_dnssec_name *from,
type_count++;
cur_rrsets = cur_rrsets->next;
}
/* always add rrsig type if this is not an unsigned
* delegation
*/
if (type_count > 0 &&
!(type_count == 1 && types[0] == LDNS_RR_TYPE_NS)) {
types[type_count] = LDNS_RR_TYPE_RRSIG;
type_count++;
}
/* leave next rdata empty if they weren't precomputed yet */
if (to && to->hashed_name) {
ldns_rr_set_rdf(nsec_rr,
ldns_rdf_clone(to->hashed_name),
4);
ldns_rdf_clone(to->hashed_name),
4);
} else {
ldns_rr_set_rdf(nsec_rr, NULL, 4);
}
......@@ -922,7 +923,8 @@ ldns_nsec3_hash_name(ldns_rdf *name,
fprintf(stderr, "of hashed owner name (name: ");
ldns_rdf_print(stderr, name);
fprintf(stderr, ", return code: %d)\n", hashed_owner_b32_len);
exit(4);
LDNS_FREE(hashed_owner_b32);
return NULL;
}
hashed_owner_str_len = hashed_owner_b32_len;
hashed_owner_b32[hashed_owner_b32_len] = '\0';
......@@ -930,7 +932,8 @@ ldns_nsec3_hash_name(ldns_rdf *name,
status = ldns_str2rdf_dname(&hashed_owner, hashed_owner_b32);
if (status != LDNS_STATUS_OK) {
fprintf(stderr, "Error creating rdf from %s\n", hashed_owner_b32);
exit(1);
LDNS_FREE(hashed_owner_b32);
return NULL;
}
LDNS_FREE(hashed_owner_b32);
......@@ -947,17 +950,19 @@ ldns_nsec3_add_param_rdfs(ldns_rr *rr,
{
ldns_rdf *salt_rdf = NULL;
uint8_t *salt_data = NULL;
ldns_rr_set_rdf(rr,
ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8,
1,
(void*)&algorithm),
0);
ldns_rr_set_rdf(rr,
ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8,
1,
(void*)&flags),
1);
ldns_rr_set_rdf(rr,
ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
iterations),
......@@ -1140,7 +1145,7 @@ ldns_nsec3_flags(const ldns_rr *nsec3_rr)
if (nsec3_rr && ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 &&
ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 1)) > 0
) {
return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 0));
return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 1));
}
return 0;
}
......
This diff is collapsed.
......@@ -1777,7 +1777,6 @@ ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
case LDNS_DSA:
case LDNS_DSA_NSEC3:
/* EVP takes rfc2459 format, which is a tad longer than dns format */
exit(0);
if (ldns_convert_dsa_rrsig_rdf2asn1(rawsig_buf,
ldns_rr_rdf(rrsig, 8))
!= LDNS_STATUS_OK) {
......
......@@ -16,17 +16,32 @@ ldns_dnssec_rrs_new()
return new_rrs;
}
void
ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
INLINE void
ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
{
if (rrs) {
if (rrs->next) {
ldns_dnssec_rrs_free(rrs->next);
ldns_dnssec_rrs *next;
while (rrs) {
next = rrs->next;
if (deep) {
ldns_rr_free(rrs->rr);
}
LDNS_FREE(rrs);
rrs = next;
}
}
void
ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
{
ldns_dnssec_rrs_free_internal(rrs, 0);
}
void
ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
{
ldns_dnssec_rrs_free_internal(rrs, 1);
}
ldns_status
ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
{
......@@ -88,23 +103,35 @@ ldns_dnssec_rrsets_new()
return new_rrsets;
}
void
ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
INLINE void
ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
{
if (rrsets) {
if (rrsets->rrs) {
ldns_dnssec_rrs_free(rrsets->rrs);
ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
}
if (rrsets->next) {
ldns_dnssec_rrsets_free(rrsets->next);
ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
}
if (rrsets->signatures) {
ldns_dnssec_rrs_free(rrsets->signatures);
ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
}
LDNS_FREE(rrsets);
}
}
void
ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
{
ldns_dnssec_rrsets_free_internal(rrsets, 0);
}
void
ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
{
ldns_dnssec_rrsets_free_internal(rrsets, 1);
}
ldns_rr_type
ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets)
{
......@@ -296,23 +323,39 @@ ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
return new_name;
}
void
ldns_dnssec_name_free(ldns_dnssec_name *name)
INLINE void
ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
int deep)
{
if (name) {
if (name->name_alloced) {
ldns_rdf_deep_free(name->name);
}
if (name->rrsets) {
ldns_dnssec_rrsets_free(name->rrsets);
ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
}
if (name->nsec && deep) {
ldns_rr_free(name->nsec);
}
if (name->nsec_signatures) {
ldns_dnssec_rrs_free(name->nsec_signatures);
ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
}
LDNS_FREE(name);
}
}
void
ldns_dnssec_name_free(ldns_dnssec_name *name)
{
ldns_dnssec_name_free_internal(name, 0);
}
void
ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
{
ldns_dnssec_name_free_internal(name, 1);
}
ldns_rdf *
ldns_dnssec_name_name(ldns_dnssec_name *name)
{
......@@ -512,11 +555,18 @@ ldns_dnssec_zone_new()
void
ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
arg = arg;
(void) arg;
ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
free(node);
}
void
ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
(void) arg;
ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
free(node);
}
void
ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
{
......@@ -532,6 +582,21 @@ ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
}
}
void
ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
{
if (zone) {
if (zone->names) {
/* destroy all name structures within the tree */
ldns_traverse_postorder(zone->names,
ldns_dnssec_name_node_deep_free,
NULL);
free(zone->names);
}
LDNS_FREE(zone);
}
}
/* use for dname comparison in tree */
int
ldns_dname_compare_v(const void *a, const void *b) {
......@@ -580,11 +645,11 @@ ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
if (!zone->names) {
zone->names = ldns_rbtree_create(ldns_dname_compare_v);
}
/* we need the original of the hashed name if this is
an NSEC3, or an RRSIG that covers an NSEC3 */
if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));;
type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
}
if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
type_covered == LDNS_RR_TYPE_NSEC3) {
......@@ -663,96 +728,96 @@ ldns_status
ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
{
ldns_dnssec_name *new_name;
ldns_dnssec_name *cur_name;
ldns_dnssec_name *next_name;
ldns_rdf *cur_name;
ldns_rdf *next_name;
ldns_rbnode_t *cur_node, *next_node, *new_node;
/* for the detection */
uint16_t j, cur_label_count, next_label_count;
ldns_rdf *l1, *l2, *post, *post2;
bool found_difference = false;
uint16_t i, cur_label_count, next_label_count;
uint16_t soa_label_count = 0;
ldns_rdf *l1, *l2;
int lpos;
if (!zone) {
return LDNS_STATUS_ERR;
}
if (zone->soa && zone->soa->name) {
soa_label_count = ldns_dname_label_count(zone->soa->name);
}
cur_node = ldns_rbtree_first(zone->names);
while (cur_node != LDNS_RBTREE_NULL) {
next_node = ldns_rbtree_next(cur_node);
/* skip glue */
while (next_node != LDNS_RBTREE_NULL &&
next_node->data &&
((ldns_dnssec_name *)next_node->data)->is_glue
) {
next_node = ldns_rbtree_next(next_node);
}
if (next_node == LDNS_RBTREE_NULL) {
next_node = ldns_rbtree_first(zone->names);
}
cur_name = (ldns_dnssec_name *)cur_node->data;
next_name = (ldns_dnssec_name *)next_node->data;
found_difference = false;
cur_label_count = ldns_dname_label_count(cur_name->name);
next_label_count = ldns_dname_label_count(next_name->name);
post = ldns_dname_new_frm_str(".");
for (j = 1 + ldns_dname_label_count(zone->soa->name);
j < cur_label_count &&
j <= next_label_count &&
!found_difference;
j++) {
l1 = ldns_dname_label(cur_name->name, cur_label_count - j);
l2 = ldns_dname_label(next_name->name, next_label_count - j);
post2 = ldns_dname_cat_clone(l2, post);
ldns_rdf_deep_free(post);
post = post2;
cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
next_name = ((ldns_dnssec_name *)next_node->data)->name;
cur_label_count = ldns_dname_label_count(cur_name);
next_label_count = ldns_dname_label_count(next_name);
/* Since the names are in canonical order, we can
* recognize empty non-terminals by their labels;
* every label after the first one on the next owner
* name is a non-terminal if it either does not exist
* in the current name or is different from the same
* label in the current name (counting from the end)
*/
for (i = 1; i < next_label_count - soa_label_count; i++) {
lpos = cur_label_count - next_label_count + i;
if (lpos >= 0) {
l1 = ldns_dname_label(cur_name, lpos);
} else {
l1 = NULL;
}
l2 = ldns_dname_label(next_name, i);
if (ldns_dname_compare(l1, l2) != 0 &&
j < next_label_count) {
found_difference = true;
if (!l1 || ldns_dname_compare(l1, l2) != 0) {
/* We have an empty nonterminal, add it to the
* tree
*/