diff options
| author | Dag-Erling Smørgrav <des@FreeBSD.org> | 2026-06-19 07:21:58 +0000 |
|---|---|---|
| committer | Dag-Erling Smørgrav <des@FreeBSD.org> | 2026-06-19 07:21:58 +0000 |
| commit | 026e5b88eb0cde54d9fc22b9a1ebc79ea0f67aec (patch) | |
| tree | d7641ef52c03c8ccb815cb62a22eba4d8d22db66 | |
| parent | 5eb18e8576462f5bb33fbd60fcbd752fe5791f33 (diff) | |
| -rw-r--r-- | Changelog | 4 | ||||
| -rwxr-xr-x | config.guess | 17 | ||||
| -rwxr-xr-x | config.sub | 11 | ||||
| -rwxr-xr-x | configure | 28 | ||||
| -rw-r--r-- | configure.ac | 10 | ||||
| -rw-r--r-- | doc/ldns_manpages | 740 | ||||
| -rw-r--r-- | error.c | 6 | ||||
| -rw-r--r-- | examples/ldns-testns.1 | 23 | ||||
| -rw-r--r-- | examples/ldns-testns.c | 183 | ||||
| -rw-r--r-- | examples/ldns-testpkts.c | 20 | ||||
| -rw-r--r-- | examples/ldns-testpkts.h | 8 | ||||
| -rw-r--r-- | ldns/error.h | 5 | ||||
| -rw-r--r-- | net.c | 92 |
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 @@ -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; @@ -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; } |
