aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2026-06-19 07:21:58 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2026-06-19 07:21:58 +0000
commit026e5b88eb0cde54d9fc22b9a1ebc79ea0f67aec (patch)
treed7641ef52c03c8ccb815cb62a22eba4d8d22db66
parent5eb18e8576462f5bb33fbd60fcbd752fe5791f33 (diff)
-rw-r--r--Changelog4
-rwxr-xr-xconfig.guess17
-rwxr-xr-xconfig.sub11
-rwxr-xr-xconfigure28
-rw-r--r--configure.ac10
-rw-r--r--doc/ldns_manpages740
-rw-r--r--error.c6
-rw-r--r--examples/ldns-testns.123
-rw-r--r--examples/ldns-testns.c183
-rw-r--r--examples/ldns-testpkts.c20
-rw-r--r--examples/ldns-testpkts.h8
-rw-r--r--ldns/error.h5
-rw-r--r--net.c92
13 files changed, 705 insertions, 442 deletions
diff --git a/Changelog b/Changelog
index 74e2631af72d..cd056f0c089d 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,7 @@
+1.9.1 2026-06-10
+ * Bugfix: Insufficient verification that responses belong to a
+ query (CVE-2026-10846). Thanks Pablo Ruiz from 'codecome.ai'
+
1.9.0 2025-12-04
* PR #246: Make ldns_calc_keytag() available for CDNSKEY RR
Thanks tgreenx and pnax
diff --git a/config.guess b/config.guess
index a9d01fde4617..c7f4c3294a63 100755
--- a/config.guess
+++ b/config.guess
@@ -1,10 +1,10 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2025 Free Software Foundation, Inc.
+# Copyright 1992-2026 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
-timestamp='2025-07-10'
+timestamp='2026-05-17'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -60,7 +60,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2025 Free Software Foundation, Inc.
+Copyright 1992-2026 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -150,7 +150,7 @@ UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case $UNAME_SYSTEM in
-Linux|GNU|GNU/*)
+Ironclad|Linux|GNU|GNU/*)
LIBC=unknown
set_cc_for_build
@@ -167,6 +167,8 @@ Linux|GNU|GNU/*)
LIBC=gnu
#elif defined(__LLVM_LIBC__)
LIBC=llvm
+ #elif defined(__mlibc__)
+ LIBC=mlibc
#else
#include <stdarg.h>
/* First heuristic to detect musl libc. */
@@ -1186,6 +1188,9 @@ EOF
sparc:Linux:*:* | sparc64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
+ sw_64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
tile*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
@@ -1598,10 +1603,10 @@ EOF
GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
;;
x86_64:[Ii]ronclad:*:*|i?86:[Ii]ronclad:*:*)
- GUESS=$UNAME_MACHINE-pc-ironclad-mlibc
+ GUESS=$UNAME_MACHINE-pc-ironclad-$LIBC
;;
*:[Ii]ronclad:*:*)
- GUESS=$UNAME_MACHINE-unknown-ironclad-mlibc
+ GUESS=$UNAME_MACHINE-unknown-ironclad-$LIBC
;;
esac
diff --git a/config.sub b/config.sub
index 3d35cde174de..404aa0824443 100755
--- a/config.sub
+++ b/config.sub
@@ -1,10 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2025 Free Software Foundation, Inc.
+# Copyright 1992-2026 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268,SC2162 # see below for rationale
-timestamp='2025-07-10'
+timestamp='2026-05-17'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -76,7 +76,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2025 Free Software Foundation, Inc.
+Copyright 1992-2026 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -1432,6 +1432,7 @@ case $cpu-$vendor in
| sparcv9v \
| spu \
| sv1 \
+ | sw_64 \
| sx* \
| tahoe \
| thumbv7* \
@@ -1525,7 +1526,7 @@ EOF
;;
ironclad*)
kernel=ironclad
- os=`echo "$basic_os" | sed -e 's|ironclad|mlibc|'`
+ os=`echo "$basic_os" | sed -e 's|ironclad|gnu|'`
;;
linux*)
kernel=linux
@@ -2220,7 +2221,7 @@ case $kernel-$os-$obj in
;;
uclinux-uclibc*- | uclinux-gnu*- )
;;
- ironclad-mlibc*-)
+ ironclad-gnu*- | ironclad-mlibc*- )
;;
managarm-mlibc*- | managarm-kernel*- )
;;
diff --git a/configure b/configure
index 7585de58d622..d8433532556f 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for ldns 1.9.0.
+# Generated by GNU Autoconf 2.71 for ldns 1.9.1.
#
# Report bugs to <dns-team@nlnetlabs.nl>.
#
@@ -621,8 +621,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='ldns'
PACKAGE_TARNAME='libdns'
-PACKAGE_VERSION='1.9.0'
-PACKAGE_STRING='ldns 1.9.0'
+PACKAGE_VERSION='1.9.1'
+PACKAGE_STRING='ldns 1.9.1'
PACKAGE_BUGREPORT='dns-team@nlnetlabs.nl'
PACKAGE_URL=''
@@ -1428,7 +1428,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures ldns 1.9.0 to adapt to many kinds of systems.
+\`configure' configures ldns 1.9.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1494,7 +1494,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of ldns 1.9.0:";;
+ short | recursive ) echo "Configuration of ldns 1.9.1:";;
esac
cat <<\_ACEOF
@@ -1656,7 +1656,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-ldns configure 1.9.0
+ldns configure 1.9.1
generated by GNU Autoconf 2.71
Copyright (C) 2021 Free Software Foundation, Inc.
@@ -2275,7 +2275,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by ldns $as_me 1.9.0, which was
+It was created by ldns $as_me 1.9.1, which was
generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw
@@ -3041,7 +3041,7 @@ LDNS_VERSION_MAJOR=1
LDNS_VERSION_MINOR=9
-LDNS_VERSION_MICRO=0
+LDNS_VERSION_MICRO=1
# Library version
@@ -3062,10 +3062,12 @@ LDNS_VERSION_MICRO=0
# ldns-1.8.1 had libversion 5:0:2
# ldns-1.8.1 had libversion 6:0:3
# ldns-1.8.2 had libversion 7:0:4
-# ldns-1.8.3 has libversion 8:0:5
-# ldns-1.9.0 will have libversion 9:0:6 (new behaviour for dnssec_rrs_add_rr)
+# ldns-1.8.3 had libversion 8:0:5
+# ldns-1.8.4 had libversion 9:0:6
+# ldns-1.9.0 had libversion 9:0:6 (though it should have had 10:0:0)
+# ldns-1.9.1 will have libversion 11:0:0
#
-VERSION_INFO=9:0:6
+VERSION_INFO=11:0:0
@@ -20537,7 +20539,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by ldns $as_me 1.9.0, which was
+This file was extended by ldns $as_me 1.9.1, which was
generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -20605,7 +20607,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
-ldns config.status 1.9.0
+ldns config.status 1.9.1
configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 91938e4a3430..a820720d615e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@ sinclude(acx_nlnetlabs.m4)
# must be numbers. ac_defun because of later processing.
m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[9])
-m4_define([VERSION_MICRO],[0])
+m4_define([VERSION_MICRO],[1])
AC_INIT([ldns],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[dns-team@nlnetlabs.nl],[libdns])
AC_CONFIG_SRCDIR([packet.c])
# needed to build correct soname
@@ -32,10 +32,12 @@ AC_SUBST(LDNS_VERSION_MICRO, [VERSION_MICRO])
# ldns-1.8.1 had libversion 5:0:2
# ldns-1.8.1 had libversion 6:0:3
# ldns-1.8.2 had libversion 7:0:4
-# ldns-1.8.3 has libversion 8:0:5
-# ldns-1.9.0 will have libversion 9:0:6 (new behaviour for dnssec_rrs_add_rr)
+# ldns-1.8.3 had libversion 8:0:5
+# ldns-1.8.4 had libversion 9:0:6
+# ldns-1.9.0 had libversion 9:0:6 (though it should have had 10:0:0)
+# ldns-1.9.1 will have libversion 11:0:0
#
-AC_SUBST(VERSION_INFO, [9:0:6])
+AC_SUBST(VERSION_INFO, [11:0:0])
AC_USE_SYSTEM_EXTENSIONS
if test "$ac_cv_header_minix_config_h" = "yes"; then
diff --git a/doc/ldns_manpages b/doc/ldns_manpages
index fe99fbb101fe..349bba179b55 100644
--- a/doc/ldns_manpages
+++ b/doc/ldns_manpages
@@ -1,43 +1,66 @@
-ldns_rr_mx_preference
-ldns_rr_mx_exchange
-ldns_rdf2buffer_str_a
-ldns_rdf2buffer_str_aaaa
-ldns_rdf2buffer_str_str
-ldns_rdf2buffer_str_b64
-ldns_rdf2buffer_str_hex
-ldns_rdf2buffer_str_type
-ldns_rdf2buffer_str_class
-ldns_rdf2buffer_str_alg
-ldns_rdf2buffer_str_loc
-ldns_rdf2buffer_str_unknown
-ldns_rdf2buffer_str_nsap
-ldns_rdf2buffer_str_wks
-ldns_rdf2buffer_str_nsec
-ldns_rdf2buffer_str_period
-ldns_rdf2buffer_str_tsigtime
-ldns_rdf2buffer_str_apl
-ldns_rdf2buffer_str_int16_data
-ldns_rdf2buffer_str_int16
-ldns_rdf2buffer_str_ipseckey
-ldns_rdf_address_reverse
-ldns_duration_type
-ldns_duration_create
-ldns_duration_create_from_string
-ldns_duration_cleanup
-ldns_duration_compare
-ldns_duration2string
-ldns_duration2time
-ldns_rr_descriptor
-ldns_rr_descript
-ldns_rr_descriptor_minimum
-ldns_rr_descriptor_maximum
-ldns_rr_descriptor_field_type
-ldns_str2period
-ldns_get_rr_class_by_name
-ldns_get_rr_type_by_name
-ldns_rr_list_cat
-ldns_rr_list_push_rr
-ldns_rr_list_pop_rr
+ldns_zone_set_rrs
+ldns_zone_set_soa
+ldns_verify_rrsig_dsa
+ldns_verify_rrsig_rsasha1
+ldns_verify_rrsig_rsamd5
+ldns_sign_public_dsa
+ldns_sign_public_rsamd5
+ldns_sign_public_rsasha1
+ldns_init_random
+ldns_rr2str
+ldns_pkt2str
+ldns_rdf2str
+ldns_rr_list2str
+ldns_key2str
+ldns_zone_sort
+ldns_zone_glue_rr_list
+ldns_pkt_id
+ldns_pkt_qr
+ldns_pkt_aa
+ldns_pkt_tc
+ldns_pkt_rd
+ldns_pkt_cd
+ldns_pkt_ra
+ldns_pkt_ad
+ldns_pkt_get_opcode
+ldns_pkt_get_rcode
+ldns_pkt_qdcount
+ldns_pkt_ancount
+ldns_pkt_nscount
+ldns_pkt_arcount
+ldns_pkt_answerfrom
+ldns_pkt_querytime
+ldns_pkt_size
+ldns_pkt_tsig
+ldns_pkt_question
+ldns_pkt_answer
+ldns_pkt_authority
+ldns_pkt_additional
+ldns_pkt_get_section_clone
+ldns_pkt_rr_list_by_name
+ldns_pkt_rr_list_by_type
+ldns_pkt_rr_list_by_name_and_type
+ldns_rr2wire
+ldns_pkt2wire
+ldns_rdf2wire
+ldns_update_pkt_tsig_add
+ldns_verify
+ldns_verify_rrsig
+ldns_verify_rrsig_keylist
+ldns_verify_rrsig_keylist_notime
+ldns_verify_notime
+ldns_key_new
+ldns_key_new_frm_algorithm
+ldns_key_new_frm_fp
+ldns_key_new_frm_fp_l
+ldns_key_new_frm_fp_rsa
+ldns_key_new_frm_fp_rsa_l
+ldns_key_new_frm_fp_dsa
+ldns_key_new_frm_fp_dsa_l
+ldns_rdf_set_size
+ldns_rdf_set_type
+ldns_rdf_set_data
+ldns_key2rr
ldns_buffer
ldns_buffer_new
ldns_buffer_new_frm_data
@@ -48,32 +71,126 @@ ldns_buffer_copy
ldns_buffer_export
ldns_buffer_export2str
ldns_buffer2str
-ldns_rr_push_rdf
-ldns_rr_pop_rdf
-ldns_update_zocount
-ldns_update_prcount
-ldns_update_upcount
-ldns_update_adcount
+ldns_get_rr_class_by_name
+ldns_get_rr_type_by_name
+ldns_dname2canonical
+ldns_rdf_new
+ldns_rdf_clone
+ldns_rdf_new_frm_data
+ldns_rdf_new_frm_str
+ldns_rdf_new_frm_fp
+ldns_rdf_free
+ldns_rdf_deep_free
+ldns_rdf_print
+ldns_zone_sign
+ldns_zone_sign_nsec3
+ldns_rr_list_new
+ldns_rr_list_free
+ldns_key_buf2dsa
+ldns_key_buf2rsa
+ldns_rdf_address_reverse
+ldns_dnssec_zone_sign
+ldns_dnssec_zone_sign_nsec3
+ldns_dnssec_zone_mark_glue
+ldns_dnssec_name_node_next_nonglue
+ldns_dnssec_zone_create_nsecs
+ldns_dnssec_remove_signatures
+ldns_dnssec_zone_create_rrsigs
+ldns_buffer2pkt_wire
+ldns_dnssec_rrs_new
+ldns_dnssec_rrs_free
+ldns_dnssec_rrs_add_rr
+ldns_dnssec_rrs_print
+ldns_dnssec_data_chain
+ldns_dnssec_data_chain_struct
+ldns_dnssec_trust_tree
+ldns_rr_set_owner
+ldns_rr_set_ttl
+ldns_rr_set_type
+ldns_rr_set_rd_count
+ldns_rr_set_class
+ldns_rr_set_rdf
+ldns_key_rr2ds
+ldns_dnssec_zone
+ldns_dnssec_name
+ldns_dnssec_rrs
+ldns_dnssec_rrsets
+ldns_dname_new
+ldns_dname_new_frm_str
+ldns_dname_new_frm_data
+ldns_pkt_new
+ldns_pkt_free
+ldns_pkt_print
+ldns_pkt_query_new
+ldns_pkt_query_new_frm_str
+ldns_pkt_reply_type
+ldns_rr2canonical
+ldns_sign_public
+ldns_create_nsec
+ldns_native2rdf_int8
+ldns_native2rdf_int16
+ldns_native2rdf_int32
+ldns_native2rdf_int16_data
+ldns_rdf2native_int8
+ldns_rdf2native_int16
+ldns_rdf2native_int32
+ldns_rdf2native_sockaddr_storage
+ldns_rdf2native_time_t
+ldns_rr_compare
+ldns_rr_compare_ds
+ldns_version
+ldns_getaddrinfo
+ldns_key_set_algorithm
+ldns_key_set_rsa_key
+ldns_key_set_dsa_key
+ldns_key_set_hmac_key
+ldns_key_set_origttl
+ldns_key_set_inception
+ldns_key_set_expiration
+ldns_key_set_pubkey_owner
+ldns_key_set_keytag
+ldns_key_set_flags
+ldns_key_list_set_key_count
+ldns_key_algo_supported
+ldns_dnssec_trust_tree_new
+ldns_dnssec_trust_tree_free
+ldns_dnssec_trust_tree_depth
+ldns_dnssec_derive_trust_tree
+ldns_dnssec_trust_tree_contains_keys
+ldns_dnssec_trust_tree_print
+ldns_dnssec_trust_tree_print_sm
+ldns_dnssec_trust_tree_add_parent
+ldns_dnssec_derive_trust_tree_normal_rrset
+ldns_dnssec_derive_trust_tree_dnskey_rrset
+ldns_dnssec_derive_trust_tree_ds_rrset
+ldns_dnssec_derive_trust_tree_no_sig
+ldns_rr
+ldns_rr_class
+ldns_rr_type
+ldns_rr_compress
+ldns_rr_list
+ldns_rr_uncompressed_size
+ldns_pkt_tsig_verify
+ldns_pkt_tsig_sign
+ldns_fget_token
+ldns_fskipcs
+ldns_key_list_new
+ldns_tcp_send_query
+ldns_tcp_read_wire
+ldns_tcp_connect
ldns_algorithm
-ldns_rr_dnskey_flags
-ldns_rr_dnskey_set_flags
-ldns_rr_dnskey_protocol
-ldns_rr_dnskey_set_protocol
-ldns_rr_dnskey_algorithm
-ldns_rr_dnskey_set_algorithm
-ldns_rr_dnskey_key
-ldns_rr_dnskey_set_key
-ldns_buffer_limit
-ldns_buffer_set_limit
-ldns_buffer_capacity
-ldns_buffer_set_capacity
-ldns_buffer_reserve
-ldns_buffer_at
-ldns_buffer_begin
-ldns_buffer_end
-ldns_buffer_current
-ldns_zone_rrs
-ldns_zone_soa
+ldns_dnssec_zone_find_rrset
+ldns_dnssec_zone_new
+ldns_dnssec_zone_free
+ldns_dnssec_zone_add_rr
+ldns_dnssec_zone_names_print
+ldns_dnssec_zone_print
+ldns_dnssec_zone_add_empty_nonterminals
+ldns_update_set_zocount
+ldns_update_set_prcount
+ldns_update_set_upcount
+ldns_update_set_adcount
+ldns_key_print
ldns_pkt_set_flags
ldns_pkt_set_id
ldns_pkt_set_qr
@@ -94,60 +211,24 @@ ldns_pkt_set_querytime
ldns_pkt_set_size
ldns_pkt_set_section_count
ldns_pkt_set_tsig
-ldns_pkt_verify
-ldns_rr2str
-ldns_pkt2str
-ldns_rdf2str
-ldns_rr_list2str
-ldns_key2str
-ldns_fget_token
-ldns_fskipcs
-ldns_pkt
-ldns_pkt_section
-ldns_pkt_type
-ldns_zone_sort
-ldns_zone_glue_rr_list
-ldns_rr2canonical
-ldns_rdf_size
-ldns_rdf_get_type
-ldns_rdf_data
-ldns_rdf_compare
-ldns_rr_list_rr_count
-ldns_rr_list_set_rr_count
-ldns_dnssec_trust_tree_new
-ldns_dnssec_trust_tree_free
-ldns_dnssec_trust_tree_depth
-ldns_dnssec_derive_trust_tree
-ldns_dnssec_trust_tree_contains_keys
-ldns_dnssec_trust_tree_print
-ldns_dnssec_trust_tree_print_sm
-ldns_dnssec_trust_tree_add_parent
-ldns_dnssec_derive_trust_tree_normal_rrset
-ldns_dnssec_derive_trust_tree_dnskey_rrset
-ldns_dnssec_derive_trust_tree_ds_rrset
-ldns_dnssec_derive_trust_tree_no_sig
-ldns_rr_ns_nsdname
-ldns_dname_left_chop
-ldns_dname_label_count
-ldns_dname_new
-ldns_dname_new_frm_str
-ldns_dname_new_frm_data
-ldns_rr_list_new
-ldns_rr_list_free
-ldns_pkt_new
-ldns_pkt_free
-ldns_pkt_print
-ldns_pkt_query_new
-ldns_pkt_query_new_frm_str
-ldns_pkt_reply_type
-ldns_zone_set_rrs
-ldns_zone_set_soa
-ldns_dnssec_rrs_new
-ldns_dnssec_rrs_free
-ldns_dnssec_rrs_add_rr
-ldns_dnssec_rrs_print
-ldns_key2rr
-ldns_update_pkt_new
+ldns_is_rrset
+ldns_buffer_remaining_at
+ldns_buffer_remaining
+ldns_buffer_available_at
+ldns_buffer_available
+ldns_buffer_status
+ldns_buffer_status_ok
+ldns_axfr_start
+ldns_axfr_next
+ldns_axfr_abort
+ldns_axfr_complete
+ldns_axfr_last_pkt
+ldns_rr_label_count
+ldns_rr_descriptor
+ldns_rr_descript
+ldns_rr_descriptor_minimum
+ldns_rr_descriptor_maximum
+ldns_rr_descriptor_field_type
ldns_rr_rrsig_typecovered
ldns_rr_rrsig_set_typecovered
ldns_rr_rrsig_algorithm
@@ -166,6 +247,75 @@ ldns_rr_rrsig_signame
ldns_rr_rrsig_set_signame
ldns_rr_rrsig_sig
ldns_rr_rrsig_set_sig
+ldns_duration_type
+ldns_duration_create
+ldns_duration_create_from_string
+ldns_duration_cleanup
+ldns_duration_compare
+ldns_duration2string
+ldns_duration2time
+ldns_dnssec_verify_denial
+ldns_dnssec_verify_denial_nsec3
+ldns_rr_set_push_rr
+ldns_rr_set_pop_rr
+ldns_rr_list_sort
+ldns_pkt_edns
+ldns_pkt_edns_udp_size
+ldns_pkt_edns_extended_rcode
+ldns_pkt_edns_version
+ldns_pkt_edns_z
+ldns_pkt_edns_data
+ldns_pkt_set_edns_udp_size
+ldns_pkt_set_edns_extended_rcode
+ldns_pkt_set_edns_version
+ldns_pkt_set_edns_z
+ldns_pkt_set_edns_data
+ldns_key_free
+ldns_key_deep_free
+ldns_key_list_free
+ldns_key_list_key_count
+ldns_key_list_key
+ldns_key_rsa_key
+ldns_key_dsa_key
+ldns_key_algorithm
+ldns_key_hmac_key
+ldns_key_origttl
+ldns_key_inception
+ldns_key_expiration
+ldns_key_keytag
+ldns_key_pubkey_owner
+ldns_key_flags
+ldns_update_zocount
+ldns_update_prcount
+ldns_update_upcount
+ldns_update_adcount
+ldns_rr_rdf
+ldns_rr_owner
+ldns_rr_rd_count
+ldns_rr_ttl
+ldns_rr_get_class
+ldns_rr_list_rr_count
+ldns_rr_list_set_rr_count
+ldns_rr_ns_nsdname
+ldns_rr_dnskey_flags
+ldns_rr_dnskey_set_flags
+ldns_rr_dnskey_protocol
+ldns_rr_dnskey_set_protocol
+ldns_rr_dnskey_algorithm
+ldns_rr_dnskey_set_algorithm
+ldns_rr_dnskey_key
+ldns_rr_dnskey_set_key
+ldns_calc_keytag
+ldns_calc_keytag_raw
+ldns_zone_rrs
+ldns_zone_soa
+ldns_rr_mx_preference
+ldns_rr_mx_exchange
+ldns_dname_is_subdomain
+ldns_dname_str_absolute
+ldns_dname_label
+ldns_dane_verify
+ldns_dane_verify_rr
ldns_buffer_write_at
ldns_buffer_write
ldns_buffer_write_string_at
@@ -184,57 +334,53 @@ ldns_buffer_read_u32_at
ldns_buffer_read_u32
ldns_buffer_write_u32
ldns_buffer_write_u32_at
-ldns_key_list_key_count
-ldns_key_list_key
-ldns_key_rsa_key
-ldns_key_dsa_key
-ldns_key_algorithm
-ldns_key_hmac_key
-ldns_key_origttl
-ldns_key_inception
-ldns_key_expiration
-ldns_key_keytag
-ldns_key_pubkey_owner
-ldns_key_flags
-ldns_rr2wire
-ldns_pkt2wire
-ldns_rdf2wire
-ldns_zone_push_rr
-ldns_zone_push_rr_list
-ldns_dname_cat_clone
-ldns_dname_cat
-ldns_key_list_push_key
-ldns_key_list_pop_key
-ldns_init_random
-ldns_sign_public_dsa
-ldns_sign_public_rsamd5
-ldns_sign_public_rsasha1
-ldns_buffer2pkt_wire
+ldns_zone_rr_count
+ldns_rr_list_clone
+ldns_bget_token
+ldns_bgetc
+ldns_bskipcs
+ldns_update_pkt_new
+ldns_b32_ntop_calculate_size
+ldns_b32_pton_calculate_size
+ldns_b64_ntop_calculate_size
+ldns_b64_pton_calculate_size
ldns_rr_new
ldns_rr_new_frm_type
ldns_rr_new_frm_str
ldns_rr_new_frm_fp
ldns_rr_free
ldns_rr_print
-ldns_rr
-ldns_rr_class
-ldns_rr_type
-ldns_rr_compress
-ldns_rr_list
-ldns_zone_sign
-ldns_zone_sign_nsec3
-ldns_get_rr_list_addr_by_name
-ldns_get_rr_list_name_by_addr
-ldns_key_rr2ds
-ldns_native2rdf_int8
-ldns_native2rdf_int16
-ldns_native2rdf_int32
-ldns_native2rdf_int16_data
-ldns_rdf2native_int8
-ldns_rdf2native_int16
-ldns_rdf2native_int32
-ldns_rdf2native_sockaddr_storage
-ldns_rdf2native_time_t
+ldns_zone_push_rr
+ldns_zone_push_rr_list
+ldns_dnssec_rrsets_new
+ldns_dnssec_rrsets_free
+ldns_dnssec_rrsets_type
+ldns_dnssec_rrsets_set_type
+ldns_dnssec_rrsets_add_rr
+ldns_dnssec_rrsets_print
+ldns_dane_create_tlsa_rr
+ldns_dane_create_tlsa_owner
+ldns_dane_cert2rdf
+ldns_dane_select_certificate
+ldns_str2period
+ldns_bubblebabble
+ldns_dname_cat_clone
+ldns_dname_cat
+ldns_rr_list_cat
+ldns_rr_list_push_rr
+ldns_rr_list_pop_rr
+ldns_wire2rr
+ldns_wire2pkt
+ldns_wire2rdf
+ldns_wire2dname
+ldns_rdf
+ldns_rdf_type
+ldns_octet
+ldns_dname_compare
+ldns_dname_interval
+ldns_key_list_push_key
+ldns_key_list_pop_key
+ldns_key
ldns_zone
ldns_zone_new
ldns_zone_free
@@ -243,46 +389,17 @@ ldns_zone_new_frm_fp
ldns_zone_new_frm_fp_l
ldns_zone_print
ldns_zone_print_fmt
-ldns_wire2rr
-ldns_wire2pkt
-ldns_wire2rdf
-ldns_wire2dname
-ldns_dane_verify
-ldns_dane_verify_rr
-ldns_verify
-ldns_verify_rrsig
-ldns_verify_rrsig_keylist
-ldns_verify_rrsig_keylist_notime
-ldns_verify_notime
-ldns_zone_rr_count
-ldns_key_set_algorithm
-ldns_key_set_rsa_key
-ldns_key_set_dsa_key
-ldns_key_set_hmac_key
-ldns_key_set_origttl
-ldns_key_set_inception
-ldns_key_set_expiration
-ldns_key_set_pubkey_owner
-ldns_key_set_keytag
-ldns_key_set_flags
-ldns_key_list_set_key_count
-ldns_key_algo_supported
-ldns_dnssec_name_new
-ldns_dnssec_name_new_frm_rr
-ldns_dnssec_name_free
-ldns_dnssec_name_name
-ldns_dnssec_name_set_name
-ldns_dnssec_name_set_nsec
-ldns_dnssec_name_cmp
-ldns_dnssec_name_add_rr
-ldns_dnssec_name_find_rrset
-ldns_dnssec_name_print
-ldns_bubblebabble
-ldns_key
-ldns_key_list_new
-ldns_tcp_send_query
-ldns_tcp_read_wire
-ldns_tcp_connect
+ldns_get_rr_list_hosts_frm_file
+ldns_get_rr_list_hosts_frm_fp
+ldns_get_rr_list_hosts_frm_fp_l
+ldns_pkt
+ldns_pkt_section
+ldns_pkt_type
+ldns_dnssec_data_chain_new
+ldns_dnssec_data_chain_free
+ldns_dnssec_data_chain_deep_free
+ldns_dnssec_build_data_chain
+ldns_dnssec_data_chain_print
ldns_pkt2buffer_str
ldns_pktheader2buffer_str
ldns_rr2buffer_str
@@ -294,177 +411,60 @@ ldns_rr2buffer_wire
ldns_rdf2buffer_wire
ldns_rrsig2buffer_wire
ldns_rr_rdata2buffer_wire
+ldns_buffer_limit
+ldns_buffer_set_limit
+ldns_buffer_capacity
+ldns_buffer_set_capacity
+ldns_buffer_reserve
+ldns_buffer_at
+ldns_buffer_begin
+ldns_buffer_end
+ldns_buffer_current
ldns_send
-ldns_update_pkt_tsig_add
-ldns_dnssec_data_chain_new
-ldns_dnssec_data_chain_free
-ldns_dnssec_data_chain_deep_free
-ldns_dnssec_build_data_chain
-ldns_dnssec_data_chain_print
-ldns_get_rr_list_hosts_frm_file
-ldns_get_rr_list_hosts_frm_fp
-ldns_get_rr_list_hosts_frm_fp_l
-ldns_dnssec_rrsets_new
-ldns_dnssec_rrsets_free
-ldns_dnssec_rrsets_type
-ldns_dnssec_rrsets_set_type
-ldns_dnssec_rrsets_add_rr
-ldns_dnssec_rrsets_print
-ldns_dnssec_verify_denial
-ldns_dnssec_verify_denial_nsec3
-ldns_pkt_tsig_verify
-ldns_pkt_tsig_sign
+ldns_get_rr_list_addr_by_name
+ldns_get_rr_list_name_by_addr
+ldns_rdf2buffer_str_a
+ldns_rdf2buffer_str_aaaa
+ldns_rdf2buffer_str_str
+ldns_rdf2buffer_str_b64
+ldns_rdf2buffer_str_hex
+ldns_rdf2buffer_str_type
+ldns_rdf2buffer_str_class
+ldns_rdf2buffer_str_alg
+ldns_rdf2buffer_str_loc
+ldns_rdf2buffer_str_unknown
+ldns_rdf2buffer_str_nsap
+ldns_rdf2buffer_str_wks
+ldns_rdf2buffer_str_nsec
+ldns_rdf2buffer_str_period
+ldns_rdf2buffer_str_tsigtime
+ldns_rdf2buffer_str_apl
+ldns_rdf2buffer_str_int16_data
+ldns_rdf2buffer_str_int16
+ldns_rdf2buffer_str_ipseckey
ldns_buffer_flip
ldns_buffer_rewind
ldns_buffer_position
ldns_buffer_set_position
ldns_buffer_skip
-ldns_rdf_new
-ldns_rdf_clone
-ldns_rdf_new_frm_data
-ldns_rdf_new_frm_str
-ldns_rdf_new_frm_fp
-ldns_rdf_free
-ldns_rdf_deep_free
-ldns_rdf_print
-ldns_rr_label_count
-ldns_dname2canonical
-ldns_axfr_start
-ldns_axfr_next
-ldns_axfr_abort
-ldns_axfr_complete
-ldns_axfr_last_pkt
-ldns_bget_token
-ldns_bgetc
-ldns_bskipcs
-ldns_pkt_id
-ldns_pkt_qr
-ldns_pkt_aa
-ldns_pkt_tc
-ldns_pkt_rd
-ldns_pkt_cd
-ldns_pkt_ra
-ldns_pkt_ad
-ldns_pkt_get_opcode
-ldns_pkt_get_rcode
-ldns_pkt_qdcount
-ldns_pkt_ancount
-ldns_pkt_nscount
-ldns_pkt_arcount
-ldns_pkt_answerfrom
-ldns_pkt_querytime
-ldns_pkt_size
-ldns_pkt_tsig
-ldns_pkt_question
-ldns_pkt_answer
-ldns_pkt_authority
-ldns_pkt_additional
-ldns_pkt_get_section_clone
-ldns_pkt_rr_list_by_name
-ldns_pkt_rr_list_by_type
-ldns_pkt_rr_list_by_name_and_type
-ldns_dname_compare
-ldns_dname_interval
-ldns_update_set_zocount
-ldns_update_set_prcount
-ldns_update_set_upcount
-ldns_update_set_adcount
+ldns_dname_left_chop
+ldns_dname_label_count
+ldns_rdf_size
+ldns_rdf_get_type
+ldns_rdf_data
+ldns_rdf_compare
+ldns_rr_push_rdf
+ldns_rr_pop_rdf
+ldns_pkt_verify
ldns_get_errorstr_by_id
ldns_status
-ldns_key_free
-ldns_key_deep_free
-ldns_key_list_free
-ldns_rr_list_sort
-ldns_dnssec_zone_sign
-ldns_dnssec_zone_sign_nsec3
-ldns_dnssec_zone_mark_glue
-ldns_dnssec_name_node_next_nonglue
-ldns_dnssec_zone_create_nsecs
-ldns_dnssec_remove_signatures
-ldns_dnssec_zone_create_rrsigs
-ldns_key_print
-ldns_buffer_remaining_at
-ldns_buffer_remaining
-ldns_buffer_available_at
-ldns_buffer_available
-ldns_buffer_status
-ldns_buffer_status_ok
-ldns_rdf_set_size
-ldns_rdf_set_type
-ldns_rdf_set_data
-ldns_key_buf2dsa
-ldns_key_buf2rsa
-ldns_b32_ntop_calculate_size
-ldns_b32_pton_calculate_size
-ldns_b64_ntop_calculate_size
-ldns_b64_pton_calculate_size
-ldns_rr_compare
-ldns_rr_compare_ds
-ldns_calc_keytag
-ldns_calc_keytag_raw
-ldns_rdf
-ldns_rdf_type
-ldns_dnssec_zone_find_rrset
-ldns_dnssec_zone_new
-ldns_dnssec_zone_free
-ldns_dnssec_zone_add_rr
-ldns_dnssec_zone_names_print
-ldns_dnssec_zone_print
-ldns_dnssec_zone_add_empty_nonterminals
-ldns_create_nsec
-ldns_dane_create_tlsa_rr
-ldns_dane_create_tlsa_owner
-ldns_dane_cert2rdf
-ldns_dane_select_certificate
-ldns_getaddrinfo
-ldns_rr_set_push_rr
-ldns_rr_set_pop_rr
-ldns_key_new
-ldns_key_new_frm_algorithm
-ldns_key_new_frm_fp
-ldns_key_new_frm_fp_l
-ldns_key_new_frm_fp_rsa
-ldns_key_new_frm_fp_rsa_l
-ldns_key_new_frm_fp_dsa
-ldns_key_new_frm_fp_dsa_l
-ldns_octet
-ldns_rr_list_clone
-ldns_dnssec_zone
-ldns_dnssec_name
-ldns_dnssec_rrs
-ldns_dnssec_rrsets
-ldns_version
-ldns_rr_rdf
-ldns_rr_owner
-ldns_rr_rd_count
-ldns_rr_ttl
-ldns_rr_get_class
-ldns_rr_set_owner
-ldns_rr_set_ttl
-ldns_rr_set_type
-ldns_rr_set_rd_count
-ldns_rr_set_class
-ldns_rr_set_rdf
-ldns_pkt_edns
-ldns_pkt_edns_udp_size
-ldns_pkt_edns_extended_rcode
-ldns_pkt_edns_version
-ldns_pkt_edns_z
-ldns_pkt_edns_data
-ldns_pkt_set_edns_udp_size
-ldns_pkt_set_edns_extended_rcode
-ldns_pkt_set_edns_version
-ldns_pkt_set_edns_z
-ldns_pkt_set_edns_data
-ldns_sign_public
-ldns_dnssec_data_chain
-ldns_dnssec_data_chain_struct
-ldns_dnssec_trust_tree
-ldns_verify_rrsig_dsa
-ldns_verify_rrsig_rsasha1
-ldns_verify_rrsig_rsamd5
-ldns_dname_is_subdomain
-ldns_dname_str_absolute
-ldns_dname_label
-ldns_is_rrset
-ldns_rr_uncompressed_size
+ldns_dnssec_name_new
+ldns_dnssec_name_new_frm_rr
+ldns_dnssec_name_free
+ldns_dnssec_name_name
+ldns_dnssec_name_set_name
+ldns_dnssec_name_set_nsec
+ldns_dnssec_name_cmp
+ldns_dnssec_name_add_rr
+ldns_dnssec_name_find_rrset
+ldns_dnssec_name_print
diff --git a/error.c b/error.c
index 5723aea9b4c2..4fc05d6d0d8f 100644
--- a/error.c
+++ b/error.c
@@ -191,6 +191,12 @@ ldns_lookup_table ldns_error_str[] = {
"at least 2 bytes of option data" },
{ LDNS_STATUS_EQUAL_RR,
"An identical RR already existed in the zone" },
+ { LDNS_STATUS_ID_DID_NOT_MATCH,
+ "Response ID did not match the query ID" },
+ { LDNS_STATUS_QDCOUNT_MUST_BE_ONE,
+ "The query section MUST contain exactly one question" },
+ { LDNS_STATUS_QUERY_DID_NOT_MATCH,
+ "The question in the response did not match the query" },
{ 0, NULL }
};
diff --git a/examples/ldns-testns.1 b/examples/ldns-testns.1
index 4164690bfffb..86d12fe46ac5 100644
--- a/examples/ldns-testns.1
+++ b/examples/ldns-testns.1
@@ -47,6 +47,16 @@ times to increase verbosity level.
Bind to IP6 address instead of IP4. Use together with -p.
.TP
+\fB-l\fR \fIIP address\fR
+Bind to the specified IPv4 or IPv6 address.
+
+.TP
+\fB-a\fR \fIIP address\fR
+IPv4 or IPv6 address to answer from withthe ADJUST change_address directory
+(see below). This can only be used in combination with the \fB-l\fR option
+with an address of the same family.
+
+.TP
\fBdatafile\fR
The data file is read on start up. It contains queries and the packets
that should be sent in answer to those queries. The data file format is
@@ -92,9 +102,18 @@ REPLY ...
ADJUST copy_id ; 'copy_id' copies the ID from the query to the answer.
-; 'sleep=10' sleeps for 10 seconds before giving the answer (TCP is open)
+ADJUST change_id ; answer with a different ID than the query had
+
+ADJUST change_port ; answer from a different port than the query was
+ ; sent to. UDP only (silently ignored on TCP)
+
+ADJUST change_address ; answer from a different address than the query
+ ; was sent to. UDP only (silently ignored on TCP)
+
+ADJUST [sleep=<num>] ; sleep before giving any reply
+ ; 'sleep=10' sleeps for 10 seconds before giving
+ ; the answer (TCP is open)
-ADJUST [sleep=<num>] ; sleep before giving any reply
ADJUST [packet_sleep=<num>] ; sleep before this packet in sequence
SECTION QUESTION
diff --git a/examples/ldns-testns.c b/examples/ldns-testns.c
index 689bbd1c9342..3ec95a6f23b9 100644
--- a/examples/ldns-testns.c
+++ b/examples/ldns-testns.c
@@ -126,7 +126,6 @@ ENTRY_END
*/
-struct sockaddr_storage;
#include "config.h"
#include <ldns/ldns.h>
#include "ldns-testpkts.h"
@@ -181,6 +180,8 @@ static void usage(void)
printf(" -f forks given number extra instances, default none.\n");
printf(" -v more verbose, prints queries, answers and matching.\n");
printf(" -6 listen on IP6 any address, instead of IP4 any address.\n");
+ printf(" -l listen on the specified address.\n");
+ printf(" -a alternative address to answer from with MATCH change_address (-l MUST be provided too).\n");
printf("The program answers queries with canned replies from the datafile.\n");
exit(EXIT_FAILURE);
}
@@ -217,45 +218,85 @@ void verbose(int ATTR_UNUSED(lvl), const char* msg, ...)
va_end(args);
}
-static int bind_port(int sock, int port, int fam)
-{
- struct sockaddr_in addr;
-#if defined(AF_INET6) && defined(HAVE_GETADDRINFO)
- if(fam == AF_INET6) {
- struct sockaddr_in6 addr6;
- memset(&addr6, 0, sizeof(addr6));
- addr6.sin6_family = AF_INET6;
- addr6.sin6_port = (in_port_t)htons((uint16_t)port);
-# if HAVE_DECL_IN6ADDR_ANY
- addr6.sin6_addr = in6addr_any;
-# else
- memset(&addr6.sin6_addr, 0, sizeof(addr6.sin6_addr));
-# endif
- return bind(sock, (struct sockaddr *)&addr6, (socklen_t) sizeof(addr6));
- }
-#endif
+typedef union {
+ struct sockaddr_storage ss;
+ struct sockaddr sa;
+ struct sockaddr_in s4;
+ struct sockaddr_in6 s6;
+} addr_type;
-#ifndef S_SPLINT_S
- addr.sin_family = AF_INET;
-#endif
- addr.sin_port = (in_port_t)htons((uint16_t)port);
- addr.sin_addr.s_addr = INADDR_ANY;
- return bind(sock, (struct sockaddr *)&addr, (socklen_t) sizeof(addr));
+static int bind_addr_port(int sock, addr_type* addr, int port)
+{
+ switch(addr->ss.ss_family) {
+ case AF_INET:
+ addr->s4.sin_port = (in_port_t)htons((uint16_t)port);
+ break;
+ case AF_INET6:
+ addr->s6.sin6_port = (in_port_t)htons((uint16_t)port);
+ break;
+ default:
+ break;
+ }
+ return bind( sock, &addr->sa
+ , (socklen_t)( addr->ss.ss_family == AF_INET
+ ? sizeof(struct sockaddr_in)
+ : addr->ss.ss_family == AF_INET6
+ ? sizeof(struct sockaddr_in6)
+ : 0));
}
+/** shared by the service, main and send_udp routines (forked and threaded) */
+static int alt_addr_udp_sock;
struct handle_udp_userdata {
int udp_sock;
struct sockaddr_storage addr_him;
socklen_t hislen;
};
+
static void
-send_udp(uint8_t* buf, size_t len, void* data)
+send_udp(uint8_t* buf, size_t len, void* data, bool change_port, bool change_addr)
{
struct handle_udp_userdata *userdata = (struct handle_udp_userdata*)data;
/* udp send reply */
ssize_t nb;
- nb = sendto(userdata->udp_sock, (void*)buf, len, 0,
- (struct sockaddr*)&userdata->addr_him, userdata->hislen);
+ if(!change_port && !change_addr)
+ nb = sendto(userdata->udp_sock, (void*)buf, len, 0,
+ (struct sockaddr*)&userdata->addr_him, userdata->hislen);
+ else if(change_port) {
+ int fam = ((struct sockaddr*)&userdata->addr_him)->sa_family;
+ int alt_udp_sock = socket(fam, SOCK_DGRAM, 0);
+ bool random_port_success = false;
+ addr_type any_addr;
+
+ memset(&any_addr.ss, 0, sizeof(any_addr.ss));
+ any_addr.ss.ss_family = fam;
+
+ while (!random_port_success) {
+ int port = (random() % 64510) + 1025;
+ log_msg("trying to bind to port %d\n", port);
+ random_port_success = true;
+ if (bind_addr_port(alt_udp_sock, &any_addr, port)) {
+#ifdef EADDRINUSE
+ if (errno != EADDRINUSE) {
+#elif defined(USE_WINSOCK)
+ if (WSAGetLastError() != WSAEADDRINUSE) {
+#else
+ if (1) {
+#endif
+ perror("bind()");
+ exit(-1);
+ } else {
+ random_port_success = false;
+ }
+ }
+ }
+ nb = sendto(alt_udp_sock, (void*)buf, len, 0,
+ (struct sockaddr*)&userdata->addr_him, userdata->hislen);
+ close(alt_udp_sock);
+ } else {
+ nb = sendto(alt_addr_udp_sock, (void*)buf, len, 0,
+ (struct sockaddr*)&userdata->addr_him, userdata->hislen);
+ }
if(nb == -1)
log_msg("sendto(): %s\n", strerror(errno));
else if((size_t)nb != len)
@@ -326,10 +367,12 @@ struct handle_tcp_userdata {
int s;
};
static void
-send_tcp(uint8_t* buf, size_t len, void* data)
+send_tcp(uint8_t* buf, size_t len, void* data, bool change_port, bool change_addr)
{
struct handle_tcp_userdata *userdata = (struct handle_tcp_userdata*)data;
uint16_t tcplen;
+ (void)change_port; /* change_port is not applicable to TCP */
+ (void)change_addr; /* change_addr is not applicable to TCP */
/* tcp send reply */
tcplen = htons(len);
write_n_bytes(userdata->s, (uint8_t*)&tcplen, sizeof(tcplen));
@@ -500,26 +543,65 @@ main(int argc, char **argv)
/* network */
int fam = AF_INET;
bool random_port_success;
+ bool have_addr = false;
+ bool have_alt_addr = false;
+ addr_type addr;
+ addr_type alt_addr;
#ifdef USE_WINSOCK
WSADATA wsa_data;
#endif
-
+ memset(&addr, 0, sizeof(addr));
+ addr.s4.sin_family = AF_INET;
+ addr.s4.sin_addr.s_addr = INADDR_ANY;
+ memset(&alt_addr, 0, sizeof(alt_addr));
+ alt_addr_udp_sock = -1;
+
/* parse arguments */
srandom(time(NULL) ^ getpid());
logfile = stdout;
prog_name = argv[0];
log_msg("%s: start\n", prog_name);
- while((c = getopt(argc, argv, "6f:p:rv")) != -1) {
+ while((c = getopt(argc, argv, "6a:f:l:p:rv")) != -1) {
switch(c) {
case '6':
#ifdef AF_INET6
fam = AF_INET6;
+ addr.s6.sin6_family = AF_INET;
+# if HAVE_DECL_IN6ADDR_ANY
+ addr.s6.sin6_addr = in6addr_any;
+# endif
#else
log_msg("cannot -6: no IP6 available\n");
exit(1);
#endif
break;
+ case 'a':
+ if(inet_pton(AF_INET, optarg, (void*)&alt_addr.s4.sin_addr) == 1) {
+ alt_addr.s4.sin_family = AF_INET;
+ have_alt_addr = true;
+ break; /* correct alternative ipv4 address */
+ } else if(inet_pton(AF_INET6, optarg, (void*)&alt_addr.s6.sin6_addr) == 1) {
+ alt_addr.s6.sin6_family = AF_INET6;
+ have_alt_addr = true;
+ break; /* correct alternative ipv6 address */
+ }
+ log_msg("error: cannot parse alternative address\n");
+ exit(1);
+ break;
+ case 'l':
+ if(inet_pton(AF_INET, optarg, (void*)&addr.s4.sin_addr) == 1) {
+ addr.s4.sin_family = AF_INET;
+ have_addr = true;
+ break; /* correct ipv4 address */
+ } else if(inet_pton(AF_INET6, optarg, (void*)&addr.s6.sin6_addr) == 1) {
+ addr.s6.sin6_family = AF_INET6;
+ have_addr = true;
+ break; /* correct ipv6 address */
+ }
+ log_msg("error: cannot parse address\n");
+ exit(1);
+ break;
case 'r':
port = 0;
break;
@@ -547,6 +629,13 @@ main(int argc, char **argv)
if(argc == 0 || argc > 1)
usage();
+
+ if(have_alt_addr && !have_addr)
+ error("Alternative address MUST be configured next to an address specified with -l\n");
+
+ if(have_alt_addr && have_addr
+ && addr.ss.ss_family != alt_addr.ss.ss_family)
+ error("A specified and alternative address MUST be of same IP family\n");
datafile = argv[0];
log_msg("Reading datafile %s\n", datafile);
@@ -566,6 +655,9 @@ main(int argc, char **argv)
if((tcp_sock = socket(fam, SOCK_STREAM, 0)) < 0) {
error("tcp socket(): %s\n", strerror(errno));
}
+ if(have_alt_addr && (alt_addr_udp_sock = socket(fam, SOCK_DGRAM, 0)) < 0) {
+ error("alt_addr_udp socket(): %s\n", strerror(errno));
+ }
c = 1;
if(setsockopt(tcp_sock, SOL_SOCKET, SO_REUSEADDR, (void*)&c, (socklen_t) sizeof(int)) < 0) {
error("setsockopt(SO_REUSEADDR): %s\n", strerror(errno));
@@ -573,22 +665,25 @@ main(int argc, char **argv)
/* bind ip4 */
if (port > 0) {
- if (bind_port(udp_sock, port, fam)) {
+ if (bind_addr_port(udp_sock, &addr, port)) {
error("cannot bind(): %s\n", strerror(errno));
}
- if (bind_port(tcp_sock, port, fam)) {
+ if (bind_addr_port(tcp_sock, &addr, port)) {
error("cannot bind(): %s\n", strerror(errno));
}
if (listen(tcp_sock, CONN_BACKLOG) < 0) {
error("listen(): %s\n", strerror(errno));
}
+ if(have_alt_addr && bind_addr_port(alt_addr_udp_sock, &alt_addr, port)) {
+ error("cannot bind(): %s\n", strerror(errno));
+ }
} else {
random_port_success = false;
while (!random_port_success) {
port = (random() % 64510) + 1025;
log_msg("trying to bind to port %d\n", port);
random_port_success = true;
- if (bind_port(udp_sock, port, fam)) {
+ if (bind_addr_port(udp_sock, &addr, port)) {
#ifdef EADDRINUSE
if (errno != EADDRINUSE) {
#elif defined(USE_WINSOCK)
@@ -603,7 +698,7 @@ main(int argc, char **argv)
}
}
if (random_port_success) {
- if (bind_port(tcp_sock, port, fam)) {
+ if (bind_addr_port(tcp_sock, &addr, port)) {
#ifdef EADDRINUSE
if (errno != EADDRINUSE) {
#elif defined(USE_WINSOCK)
@@ -622,12 +717,28 @@ main(int argc, char **argv)
if (listen(tcp_sock, CONN_BACKLOG) < 0) {
error("listen(): %s\n", strerror(errno));
}
+ if (have_alt_addr && bind_addr_port(alt_addr_udp_sock, &alt_addr, port)) {
+#ifdef EADDRINUSE
+ if (errno != EADDRINUSE) {
+#elif defined(USE_WINSOCK)
+ if (WSAGetLastError()!=WSAEADDRINUSE){
+#else
+ if (1) {
+#endif
+ perror("bind()");
+ return -1;
+ } else {
+ random_port_success = false;
+ }
+ }
}
-
}
}
log_msg("Listening on port %d\n", port);
-
+ if(alt_addr.ss.ss_family == AF_INET)
+ alt_addr.s4.sin_port = (in_port_t)htons((uint16_t)port);
+ else if(alt_addr.ss.ss_family == AF_INET6)
+ alt_addr.s6.sin6_port = (in_port_t)htons((uint16_t)port);
/* forky! */
if(forknum > 0)
forkit(forknum);
diff --git a/examples/ldns-testpkts.c b/examples/ldns-testpkts.c
index c74f0f75477f..b18f73276cd1 100644
--- a/examples/ldns-testpkts.c
+++ b/examples/ldns-testpkts.c
@@ -223,6 +223,12 @@ static void adjustline(char* line, struct entry* e,
return;
if(str_keyword(&parse, "copy_id")) {
e->copy_id = true;
+ } else if(str_keyword(&parse, "change_id")) {
+ e->change_id = true;
+ } else if(str_keyword(&parse, "change_port")) {
+ e->change_port = true;
+ } else if(str_keyword(&parse, "change_address")) {
+ e->change_addr = true;
} else if(str_keyword(&parse, "copy_query")) {
e->copy_query = true;
} else if(str_keyword(&parse, "sleep=")) {
@@ -259,6 +265,9 @@ static struct entry* new_entry(void)
e->match_udp_size = 0;
e->reply_list = NULL;
e->copy_id = false;
+ e->change_id = false;
+ e->change_port = false;
+ e->change_addr = false;
e->copy_query = false;
e->sleeptime = 0;
e->next = NULL;
@@ -839,6 +848,8 @@ adjust_packet(struct entry* match, ldns_pkt* answer_pkt, ldns_pkt* query_pkt)
/* copy & adjust packet */
if(match->copy_id)
ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt));
+ if(match->change_id)
+ ldns_pkt_set_id(answer_pkt, 65535 - ldns_pkt_id(query_pkt));
if(match->copy_query) {
ldns_rr_list* list = ldns_pkt_get_section_clone(query_pkt,
LDNS_SECTION_QUESTION);
@@ -861,7 +872,8 @@ adjust_packet(struct entry* match, ldns_pkt* answer_pkt, ldns_pkt* query_pkt)
*/
void
handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count,
- enum transport_type transport, void (*sendfunc)(uint8_t*, size_t, void*),
+ enum transport_type transport,
+ void (*sendfunc)(uint8_t*, size_t, void*, bool, bool),
void* userdata, FILE* verbose_out)
{
ldns_status status;
@@ -932,6 +944,10 @@ handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count,
ldns_write_uint16(outbuf,
ldns_pkt_id(query_pkt));
}
+ if(entry->change_id) {
+ ldns_write_uint16(outbuf,
+ 65535 - ldns_pkt_id(query_pkt));
+ }
}
} else {
answer_pkt = ldns_pkt_clone(p->reply);
@@ -959,7 +975,7 @@ handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count,
verbose(3, "wakeup for next packet "
"(slept %d secs)\n", p->packet_sleep);
}
- sendfunc(outbuf, answer_size, userdata);
+ sendfunc(outbuf, answer_size, userdata, entry->change_port, entry->change_addr);
LDNS_FREE(outbuf);
outbuf = NULL;
answer_size = 0;
diff --git a/examples/ldns-testpkts.h b/examples/ldns-testpkts.h
index 33b58740ee16..cd577d5131e3 100644
--- a/examples/ldns-testpkts.h
+++ b/examples/ldns-testpkts.h
@@ -199,6 +199,12 @@ struct entry {
/** how to adjust the reply packet */
/** copy over the ID from the query into the answer */
bool copy_id;
+ /** answer with a different ID than the query had */
+ bool change_id;
+ /** answer from a different port than the query was sent to */
+ bool change_port;
+ /** answer from a different address than the query was sent to */
+ bool change_addr;
/** copy the query nametypeclass from query into the answer */
bool copy_query;
/** in seconds */
@@ -270,7 +276,7 @@ void adjust_packet(struct entry* match, ldns_pkt* answer_pkt,
*/
void handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries,
int* count, enum transport_type transport,
- void (*sendfunc)(uint8_t*, size_t, void*), void* userdata,
+ void (*sendfunc)(uint8_t*, size_t, void*, bool, bool), void* userdata,
FILE* verbose_out);
#endif /* LDNS_TESTPKTS_H */
diff --git a/ldns/error.h b/ldns/error.h
index a76eb2ecab5d..41d64cc0815f 100644
--- a/ldns/error.h
+++ b/ldns/error.h
@@ -144,7 +144,10 @@ enum ldns_enum_status {
LDNS_STATUS_INVALID_SVCPARAM_VALUE,
LDNS_STATUS_NOT_EDE,
LDNS_STATUS_EDE_OPTION_MALFORMED,
- LDNS_STATUS_EQUAL_RR
+ LDNS_STATUS_EQUAL_RR,
+ LDNS_STATUS_ID_DID_NOT_MATCH,
+ LDNS_STATUS_QDCOUNT_MUST_BE_ONE,
+ LDNS_STATUS_QUERY_DID_NOT_MATCH
};
typedef enum ldns_enum_status ldns_status;
diff --git a/net.c b/net.c
index e944d018b357..4c1f405419fb 100644
--- a/net.c
+++ b/net.c
@@ -441,6 +441,50 @@ ldns_udp_bgsend2(ldns_buffer *qbin,
return ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
}
+/** helper sockaddr compare function. returns -1, 0 or 1. */
+static int
+ldns_sockaddr_cmp(const struct sockaddr_storage* addr1, socklen_t len1,
+ const struct sockaddr_storage* addr2, socklen_t len2)
+{
+ struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
+ struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
+ struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
+ struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
+ if(len1 < len2)
+ return -1;
+ if(len1 > len2)
+ return 1;
+ assert(len1 == len2);
+ if( p1_in->sin_family < p2_in->sin_family)
+ return -1;
+ if( p1_in->sin_family > p2_in->sin_family)
+ return 1;
+ assert( p1_in->sin_family == p2_in->sin_family );
+ /* compare ip4 */
+ if( p1_in->sin_family == AF_INET ) {
+ /* just order it, ntohs not required */
+ if(p1_in->sin_port < p2_in->sin_port)
+ return -1;
+ if(p1_in->sin_port > p2_in->sin_port)
+ return 1;
+ assert(p1_in->sin_port == p2_in->sin_port);
+ return memcmp(&p1_in->sin_addr, &p2_in->sin_addr,
+ sizeof(p1_in->sin_addr));
+ } else if (p1_in6->sin6_family == AF_INET6) {
+ /* just order it, ntohs not required */
+ if(p1_in6->sin6_port < p2_in6->sin6_port)
+ return -1;
+ if(p1_in6->sin6_port > p2_in6->sin6_port)
+ return 1;
+ assert(p1_in6->sin6_port == p2_in6->sin6_port);
+ return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
+ sizeof(p1_in6->sin6_addr));
+ } else {
+ /* eek unknown type, perform this comparison for sanity. */
+ return memcmp(addr1, addr2, len1);
+ }
+}
+
static ldns_status
ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
const struct sockaddr_storage *to , socklen_t tolen,
@@ -449,6 +493,8 @@ ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
{
int sockfd;
uint8_t *answer;
+ struct sockaddr_storage reply_addr;
+ socklen_t reply_addr_len;
sockfd = ldns_udp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
@@ -467,13 +513,21 @@ ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
* but returns a 'NETWORK_ERROR' much like a timeout. */
ldns_sock_nonblock(sockfd);
- answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
+ reply_addr_len = sizeof(reply_addr);
+ memset(&reply_addr, 0, reply_addr_len);
+ answer = ldns_udp_read_wire(sockfd, answer_size, &reply_addr,
+ &reply_addr_len);
close_socket(sockfd);
if (!answer) {
/* oops */
return LDNS_STATUS_NETWORK_ERR;
}
+ /* Check that the reply came from the to addr. */
+ if(ldns_sockaddr_cmp(to, tolen, &reply_addr, reply_addr_len) != 0) {
+ free(answer);
+ return LDNS_STATUS_NETWORK_ERR;
+ }
*result = answer;
return LDNS_STATUS_OK;
@@ -512,6 +566,10 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf
assert(r != NULL);
+ /* The query should at least have one question */
+ if(ldns_buffer_limit(qb) < 6 || ldns_buffer_read_u16_at(qb, 4) != 1)
+ return LDNS_STATUS_QDCOUNT_MUST_BE_ONE;
+
status = LDNS_STATUS_OK;
rtt = ldns_resolver_rtt(r);
ns_array = ldns_resolver_nameservers(r);
@@ -599,6 +657,16 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf
ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF);
status = send_status;
}
+ if(reply_bytes && ldns_buffer_limit(qb) >= 2) {
+ uint16_t txid = ldns_buffer_read_u16_at(qb, 0);
+ if(reply_size < 2 ||
+ ldns_read_uint16(reply_bytes) != txid) {
+ status = LDNS_STATUS_ID_DID_NOT_MATCH;
+ LDNS_FREE(reply_bytes);
+ reply_bytes = NULL;
+ reply_size = 0;
+ }
+ }
/* obey the fail directive */
if (!reply_bytes) {
@@ -608,7 +676,7 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf
LDNS_FREE(src);
}
LDNS_FREE(ns);
- return LDNS_STATUS_ERR;
+ return status ? status : LDNS_STATUS_ERR;
} else {
LDNS_FREE(ns);
continue;
@@ -670,6 +738,26 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf
#endif /* HAVE_SSL */
LDNS_FREE(reply_bytes);
+ if (reply) {
+ ldns_pkt *query = NULL;
+
+ if(ldns_pkt_qdcount(reply) != 1) {
+ status = LDNS_STATUS_QDCOUNT_MUST_BE_ONE;
+ ldns_pkt_free(reply);
+ reply = NULL;
+
+ } else if(ldns_wire2pkt(&query
+ , ldns_buffer_begin(qb)
+ , ldns_buffer_position(qb)) != LDNS_STATUS_OK
+ || ldns_pkt_qdcount(query) != 1
+ || ldns_rr_compare(ldns_rr_list_rr(ldns_pkt_question(query),0)
+ ,ldns_rr_list_rr(ldns_pkt_question(reply),0))){
+ status = LDNS_STATUS_QUERY_DID_NOT_MATCH;
+ ldns_pkt_free(reply);
+ reply = NULL;
+ }
+ ldns_pkt_free(query);
+ }
if (result) {
*result = reply;
}