From mboxrd@z Thu Jan 1 00:00:00 1970 From: Michael Tremer <michael.tremer@ipfire.org> To: development@lists.ipfire.org Subject: Re: [PATCH] dnsmasq: 2.76test10 with latest patches (001-004) Date: Sun, 28 Feb 2016 12:19:25 -0800 Message-ID: <1456690765.2371.10.camel@ipfire.org> In-Reply-To: <1456507768-1796-1-git-send-email-matthias.fischer@ipfire.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============2142730740329272608==" List-Id: <development.lists.ipfire.org> --===============2142730740329272608== Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Hi, I merged this patch and the one after. Please give this version a good test as it is a pre-release version. You can maintain a branch where you integrate all new changes, but I think it is not required to send every single one to the mailing list. It creates a bit of noise and I think that unfortunately nobody is testing every single one any ways. Which is sad. Can we have maybe one aggregated patch after every release of a Core Update? So we always have the latest version of dnsmasq in the updates? Best, -Michael On Fri, 2016-02-26 at 18:29 +0100, Matthias Fischer wrote: > This is 'dnsmasq 2.76test10', based on current 'next', containing > latest patches. >=20 > Signed-off-by: Matthias Fischer <matthias.fischer(a)ipfire.org> > --- > =C2=A0lfs/dnsmasq=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A039 +- > =C2=A0...TL_parameter_to_--host-record_and_--cname.patch |=C2=A0=C2=A0265 += ++ > =C2=A0...01-include_0_0_0_0_8_in_DNS_rebind_checks.patch |=C2=A0=C2=A0=C2= =A041 - > =C2=A0.../dnsmasq/002-Add_--dhcp-ttl_option.patch=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0117 ++ > =C2=A0...subnet_to_allow_arbitary_subnet_addresses.patch |=C2=A0=C2=A0271 -= -- > =C2=A0src/patches/dnsmasq/003-Update_CHANGELOG.patch=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0|=C2=A0=C2=A0=C2=A017 + > =C2=A0...h_zones_locally_when_localise_queries_set.patch |=C2=A0=C2=A0=C2= =A034 - > =C2=A0.../dnsmasq/004-Add_--tftp-mtu_option.patch=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0136 ++ > =C2=A0.../004-fix_behaviour_of_empty_dhcp-option.patch=C2=A0=C2=A0=C2=A0|= =C2=A0=C2=A0=C2=A038 - > =C2=A0...ution_to_ENOMEM_error_with_IPv6_multicast.patch |=C2=A0=C2=A0=C2= =A050 - > =C2=A0...page_on_RDNSS_set_in_router_advertisement.patch |=C2=A0=C2=A0=C2= =A035 - > =C2=A0...gned_dangling_CNAME_replies_to_DS_queries.patch |=C2=A0=C2=A0=C2= =A030 - > =C2=A0...6_option_56_does_not_hold_an_address_list.patch |=C2=A0=C2=A0=C2= =A025 - > =C2=A0...pect_the_--no_resolv_flag_in_inotify_code.patch |=C2=A0=C2=A0=C2= =A047 - > =C2=A0..._5e3e464ac4022ee0b3794513abe510817e2cf3ca.patch |=C2=A0=C2=A0=C2= =A026 - > =C2=A0...11-Catch_errors_from_sendmsg_in_DHCP_code.patch |=C2=A0=C2=A0=C2= =A032 - > =C2=A0...12-Update_list_of_subnet_for_--bogus-priv.patch |=C2=A0=C2=A0=C2= =A048 - > =C2=A0...y_address_from_DNS_overlays_A_record_from.patch |=C2=A0=C2=A0=C2= =A043 - > =C2=A0...14-Handle_unknown_DS_hash_algos_correctly.patch |=C2=A0=C2=A0=C2= =A039 - > =C2=A0.../015-Fix_crash_at_start_up_with_conf-dir.patch=C2=A0=C2=A0|=C2=A0= =C2=A0=C2=A038 - > =C2=A0...ajor_rationalisation_of_DNSSEC_validation.patch | 2209 ---------- > ---------- > =C2=A0...hing_RRSIGs_and_returning_them_from_cache.patch |=C2=A0=C2=A0612 -= ----- > =C2=A0...caches_DS_records_to_a_more_logical_place.patch |=C2=A0=C2=A0269 -= -- > =C2=A0...lise_RR-filtering_code_for_use_with_EDNS0.patch |=C2=A0=C2=A0755 -= ------ > =C2=A0.../dnsmasq/020-DNSSEC_validation_tweak.patch=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0|=C2=A0=C2=A0134 -- > =C2=A0...1-Tweaks_to_EDNS0_handling_in_DNS_replies.patch |=C2=A0=C2=A0133 -- > =C2=A0..._code_Check_zone_status_is_NSEC_proof_bad.patch |=C2=A0=C2=A0409 -= --- > =C2=A0...023-Fix_brace_botch_in_dnssec_validate_ds.patch |=C2=A0=C2=A0=C2= =A098 - > =C2=A0...ning_which_DNSSEC_sig_algos_are_supported.patch |=C2=A0=C2=A0145 -- > =C2=A0...EDNS0_handling_and_computation_use_of_udp.patch |=C2=A0=C2=A0643 -= ----- > =C2=A0...aks_in_handling_unknown_DNSSEC_algorithms.patch |=C2=A0=C2=A0262 -= -- > =C2=A0...obscure_off-by-one_in_DNSSEC_hostname_cmp.patch |=C2=A0=C2=A0=C2= =A027 - > =C2=A0.../028-Minor_tweak_to_previous_commit.patch=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A039 - > =C2=A0.../dnsmasq/029-NSEC3_check_RFC5155_para_8_2.patch |=C2=A0=C2=A0=C2= =A039 - > =C2=A034 files changed, 542 insertions(+), 6603 deletions(-) > =C2=A0create mode 100644 src/patches/dnsmasq/001-Add_TTL_parameter_to_ > --host-record_and_--cname.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/001- > include_0_0_0_0_8_in_DNS_rebind_checks.patch > =C2=A0create mode 100644 src/patches/dnsmasq/002-Add_--dhcp- > ttl_option.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/002- > enhance_add_subnet_to_allow_arbitary_subnet_addresses.patch > =C2=A0create mode 100644 src/patches/dnsmasq/003-Update_CHANGELOG.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/003- > dont_answer_non_auth_queries_for_auth_zones_locally_when_localise_que > ries_set.patch > =C2=A0create mode 100644 src/patches/dnsmasq/004-Add_--tftp- > mtu_option.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/004- > fix_behaviour_of_empty_dhcp-option.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/005- > suggest_solution_to_ENOMEM_error_with_IPv6_multicast.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/006- > clarify_man_page_on_RDNSS_set_in_router_advertisement.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/007- > handle_signed_dangling_CNAME_replies_to_DS_queries.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/008- > DHCPv6_option_56_does_not_hold_an_address_list.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/009-Respect_the_ > --no_resolv_flag_in_inotify_code.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/010- > Rationalise_5e3e464ac4022ee0b3794513abe510817e2cf3ca.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/011- > Catch_errors_from_sendmsg_in_DHCP_code.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/012- > Update_list_of_subnet_for_--bogus-priv.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/013- > Fix_crash_when_empty_address_from_DNS_overlays_A_record_from.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/014- > Handle_unknown_DS_hash_algos_correctly.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/015- > Fix_crash_at_start_up_with_conf-dir.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/016- > Major_rationalisation_of_DNSSEC_validation.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/017- > Abandon_caching_RRSIGs_and_returning_them_from_cache.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/018- > Move_code_which_caches_DS_records_to_a_more_logical_place.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/019-Generalise_RR- > filtering_code_for_use_with_EDNS0.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/020- > DNSSEC_validation_tweak.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/021- > Tweaks_to_EDNS0_handling_in_DNS_replies.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/022-Tidy_up_DNSSEC_non- > existence_code_Check_zone_status_is_NSEC_proof_bad.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/023- > Fix_brace_botch_in_dnssec_validate_ds.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/024- > Do_a_better_job_of_determining_which_DNSSEC_sig_algos_are_supported.p > atch > =C2=A0delete mode 100644 src/patches/dnsmasq/025- > Major_tidy_up_of_EDNS0_handling_and_computation_use_of_udp.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/026- > More_tweaks_in_handling_unknown_DNSSEC_algorithms.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/027- > Nasty_rare_and_obscure_off-by-one_in_DNSSEC_hostname_cmp.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/028- > Minor_tweak_to_previous_commit.patch > =C2=A0delete mode 100644 src/patches/dnsmasq/029- > NSEC3_check_RFC5155_para_8_2.patch >=20 > diff --git a/lfs/dnsmasq b/lfs/dnsmasq > index 8058663..29d7895 100644 > --- a/lfs/dnsmasq > +++ b/lfs/dnsmasq > @@ -1,7 +1,7 @@ > =C2=A0#################################################################### > ########### > =C2=A0#=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0# > =C2=A0# IPFire.org - A linux based > firewall=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0# > -# Copyright (C) 2015=C2=A0=C2=A0Michael Tremer & Christian > Schmidt=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0# > +# Copyright (C) 2016=C2=A0=C2=A0Michael Tremer & Christian > Schmidt=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0# > =C2=A0#=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0# > =C2=A0# This program is free software: you can redistribute it and/or > modify=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0# > =C2=A0# it under the terms of the GNU General Public License as published > by=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0# > @@ -24,7 +24,7 @@ > =C2=A0 > =C2=A0include Config > =C2=A0 > -VER=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=3D 2.75 > +VER=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=3D 2.76test10 > =C2=A0 > =C2=A0THISAPP=C2=A0=C2=A0=C2=A0=C2=A0=3D dnsmasq-$(VER) > =C2=A0DL_FILE=C2=A0=C2=A0=C2=A0=C2=A0=3D $(THISAPP).tar.xz > @@ -43,7 +43,7 @@ objects =3D $(DL_FILE) > =C2=A0 > =C2=A0$(DL_FILE) =3D $(DL_FROM)/$(DL_FILE) > =C2=A0 > -$(DL_FILE)_MD5 =3D 887236f1ddde6eb57cdb9d01916c9f72 > +$(DL_FILE)_MD5 =3D 4b51474ed6081b18c61407077f254cf7 > =C2=A0 > =C2=A0install : $(TARGET) > =C2=A0 > @@ -73,35 +73,10 @@ $(subst %,%_MD5,$(objects)) : > =C2=A0$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) > =C2=A0 @$(PREBUILD) > =C2=A0 @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf > $(DIR_DL)/$(DL_FILE) > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/001- > include_0_0_0_0_8_in_DNS_rebind_checks.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/002- > enhance_add_subnet_to_allow_arbitary_subnet_addresses.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/003- > dont_answer_non_auth_queries_for_auth_zones_locally_when_localise_que > ries_set.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/004-fix_behaviour_of_empty_dhcp- > option.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/005- > suggest_solution_to_ENOMEM_error_with_IPv6_multicast.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/006- > clarify_man_page_on_RDNSS_set_in_router_advertisement.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/007- > handle_signed_dangling_CNAME_replies_to_DS_queries.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/008- > DHCPv6_option_56_does_not_hold_an_address_list.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/009-Respect_the_ > --no_resolv_flag_in_inotify_code.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/010- > Rationalise_5e3e464ac4022ee0b3794513abe510817e2cf3ca.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/011- > Catch_errors_from_sendmsg_in_DHCP_code.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/012-Update_list_of_subnet_for_--bogus- > priv.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/013- > Fix_crash_when_empty_address_from_DNS_overlays_A_record_from.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/014- > Handle_unknown_DS_hash_algos_correctly.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/015-Fix_crash_at_start_up_with_conf- > dir.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/016- > Major_rationalisation_of_DNSSEC_validation.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/017- > Abandon_caching_RRSIGs_and_returning_them_from_cache.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/018- > Move_code_which_caches_DS_records_to_a_more_logical_place.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/019-Generalise_RR- > filtering_code_for_use_with_EDNS0.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/020-DNSSEC_validation_tweak.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/021- > Tweaks_to_EDNS0_handling_in_DNS_replies.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/022-Tidy_up_DNSSEC_non- > existence_code_Check_zone_status_is_NSEC_proof_bad.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/023- > Fix_brace_botch_in_dnssec_validate_ds.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/024- > Do_a_better_job_of_determining_which_DNSSEC_sig_algos_are_supported.p > atch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/025- > Major_tidy_up_of_EDNS0_handling_and_computation_use_of_udp.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/026- > More_tweaks_in_handling_unknown_DNSSEC_algorithms.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/027-Nasty_rare_and_obscure_off-by- > one_in_DNSSEC_hostname_cmp.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/028- > Minor_tweak_to_previous_commit.patch > - cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/029-NSEC3_check_RFC5155_para_8_2.patch > + cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/001-Add_TTL_parameter_to_--host- > record_and_--cname.patch > + cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/002-Add_--dhcp-ttl_option.patch > + cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/003-Update_CHANGELOG.patch > + cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq/004-Add_--tftp-mtu_option.patch > =C2=A0 cd $(DIR_APP) && patch -Np1 -i > $(DIR_SRC)/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease- > file.patch > =C2=A0 > =C2=A0 cd $(DIR_APP) && sed -i src/config.h \ > diff --git a/src/patches/dnsmasq/001-Add_TTL_parameter_to_--host- > record_and_--cname.patch b/src/patches/dnsmasq/001- > Add_TTL_parameter_to_--host-record_and_--cname.patch > new file mode 100644 > index 0000000..86fbc9c > --- /dev/null > +++ b/src/patches/dnsmasq/001-Add_TTL_parameter_to_--host- > record_and_--cname.patch > @@ -0,0 +1,265 @@ > +From df3d54f776a3c9b60735b45c0b7fd88b66a2d5c4 Mon Sep 17 00:00:00 > 2001 > +From: Simon Kelley <simon(a)thekelleys.org.uk> > +Date: Wed, 24 Feb 2016 21:03:38 +0000 > +Subject: [PATCH] Add TTL parameter to --host-record and --cname. > + > +--- > + man/dnsmasq.8 |=C2=A0=C2=A0=C2=A012 ++++++++++-- > + src/cache.c=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A0=C2=A07 +++++++ > + src/dnsmasq.h |=C2=A0=C2=A0=C2=A0=C2=A02 ++ > + src/option.c=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A046 +++++++++++++++++++++++++++= +++++++++++-------- > + src/rfc1035.c |=C2=A0=C2=A0=C2=A0=C2=A06 +++++- > + 5 files changed, 62 insertions(+), 11 deletions(-) > + > +diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 > +index b782eaf..7bc1394 100644 > +--- a/man/dnsmasq.8 > ++++ b/man/dnsmasq.8 > +@@ -529,7 +529,7 @@ zone files: the port, weight and priority > numbers are in a different > + order. More than one SRV record for a given service/domain is > allowed, > + all that match are returned. > + .TP > +-.B --host-record=3D<name>[,<name>....],[<IPv4-address>],[<IPv6- > address>] > ++.B --host-record=3D<name>[,<name>....],[<IPv4-address>],[<IPv6- > address>][,<TTL>] > + Add A, AAAA and PTR records to the DNS. This adds one or more names > to > + the DNS with associated IPv4 (A) and IPv6 (AAAA) records. A name > may > + appear in more than one=C2=A0 > +@@ -546,6 +546,10 @@ is in effect. Short and long names may appear > in the same > + .B host-record, > + eg.=C2=A0 > + .B --host-record=3Dlaptop,laptop.thekelleys.org,192.168.0.1,1234::100 > ++ > ++If the time-to-live is given, it overrides the default, which is > zero > ++or the value of --local-ttl. The value is a positive integer and > gives=C2=A0 > ++the time-to-live in seconds. > + .TP > + .B \-Y, --txt-record=3D<name>[[,<text>],<text>] > + Return a TXT DNS record. The value of TXT record is a set of > strings, > +@@ -559,7 +563,7 @@ Return a PTR DNS record. > + .B --naptr- > record=3D<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<repla > cement>] > + Return an NAPTR DNS record, as specified in RFC3403. > + .TP > +-.B --cname=3D<cname>,<target> > ++.B --cname=3D<cname>,<target>[,<TTL>] > + Return a CNAME record which indicates that <cname> is really > + <target>. There are significant limitations on the target; it must > be a > + DNS name which is known to dnsmasq from /etc/hosts (or additional > +@@ -568,6 +572,10 @@ hosts files), from DHCP, from --interface-name > or from another > + If the target does not satisfy this > + criteria, the whole cname is ignored. The cname must be unique, but > it > + is permissable to have more than one cname pointing to the same > target. > ++ > ++If the time-to-live is given, it overrides the default, which is > zero > ++or the value of -local-ttl. The value is a positive integer and > gives=C2=A0 > ++the time-to-live in seconds. > + .TP > + .B --dns-rr=3D<name>,<RR-number>,[<hex data>] > + Return an arbitrary DNS Resource Record. The number is the type of > the > +diff --git a/src/cache.c b/src/cache.c > +index a9eaa65..4ecd535 100644 > +--- a/src/cache.c > ++++ b/src/cache.c > +@@ -778,6 +778,7 @@ static void add_hosts_cname(struct crec *target) > +=C2=A0 (crec =3D whine_malloc(sizeof(struct crec)))) > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > +=C2=A0 crec->flags =3D F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | > F_CNAME; > ++ crec->ttd =3D a->ttl; > +=C2=A0 crec->name.namep =3D a->alias; > +=C2=A0 crec->addr.cname.target.cache =3D target; > +=C2=A0 crec->addr.cname.uid =3D target->uid; > +@@ -981,6 +982,7 @@ int read_hostsfile(char *filename, unsigned int > index, int cache_size, struct cr > +=C2=A0 =C2=A0=C2=A0strcat(cache->name.sname, "."); > +=C2=A0 =C2=A0=C2=A0strcat(cache->name.sname, domain_suffix); > +=C2=A0 =C2=A0=C2=A0cache->flags =3D flags; > ++ =C2=A0=C2=A0cache->ttd =3D daemon->local_ttl; > +=C2=A0 =C2=A0=C2=A0add_hosts_entry(cache, &addr, addrlen, index, > rhash, hashsz); > +=C2=A0 =C2=A0=C2=A0name_count++; > +=C2=A0 } > +@@ -988,6 +990,7 @@ int read_hostsfile(char *filename, unsigned int > index, int cache_size, struct cr > +=C2=A0 { > +=C2=A0 =C2=A0=C2=A0strcpy(cache->name.sname, canon); > +=C2=A0 =C2=A0=C2=A0cache->flags =3D flags; > ++ =C2=A0=C2=A0cache->ttd =3D daemon->local_ttl; > +=C2=A0 =C2=A0=C2=A0add_hosts_entry(cache, &addr, addrlen, index, > rhash, hashsz); > +=C2=A0 =C2=A0=C2=A0name_count++; > +=C2=A0 } > +@@ -1057,6 +1060,7 @@ void cache_reload(void) > +=C2=A0 =C2=A0=C2=A0((cache =3D whine_malloc(sizeof(struct crec))))) > +=C2=A0 { > +=C2=A0 =C2=A0=C2=A0cache->flags =3D F_FORWARD | F_NAMEP | F_CNAME | F_IMMO= RTAL > | F_CONFIG; > ++ =C2=A0=C2=A0cache->ttd =3D a->ttl; > +=C2=A0 =C2=A0=C2=A0cache->name.namep =3D a->alias; > +=C2=A0 =C2=A0=C2=A0cache->addr.cname.target.int_name =3D intr; > +=C2=A0 =C2=A0=C2=A0cache->addr.cname.uid =3D SRC_INTERFACE; > +@@ -1071,6 +1075,7 @@ void cache_reload(void) > +=C2=A0 (cache->addr.ds.keydata =3D blockdata_alloc(ds->digest, ds- > >digestlen))) > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > +=C2=A0 cache->flags =3D F_FORWARD | F_IMMORTAL | F_DS | F_CONFIG | > F_NAMEP; > ++ cache->ttd =3D daemon->local_ttl; > +=C2=A0 cache->name.namep =3D ds->name; > +=C2=A0 cache->addr.ds.keylen =3D ds->digestlen; > +=C2=A0 cache->addr.ds.algo =3D ds->algo; > +@@ -1095,6 +1100,7 @@ void cache_reload(void) > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0(cache =3D whine_malloc(sizeof(struct crec)= ))) > +=C2=A0 =C2=A0=C2=A0{ > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0cache->name.namep =3D nl->name; > ++ =C2=A0=C2=A0=C2=A0=C2=A0cache->ttd =3D hr->ttl; > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0cache->flags =3D F_HOSTS | F_IMMORTAL | F_F= ORWARD | > F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG; > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0add_hosts_entry(cache, (struct all_addr *)&= hr->addr, > INADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz); > +=C2=A0 =C2=A0=C2=A0} > +@@ -1103,6 +1109,7 @@ void cache_reload(void) > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0(cache =3D whine_malloc(sizeof(struct crec)= ))) > +=C2=A0 =C2=A0=C2=A0{ > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0cache->name.namep =3D nl->name; > ++ =C2=A0=C2=A0=C2=A0=C2=A0cache->ttd =3D hr->ttl; > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0cache->flags =3D F_HOSTS | F_IMMORTAL | F_F= ORWARD | > F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG; > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0add_hosts_entry(cache, (struct all_addr *)&= hr->addr6, > IN6ADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz); > +=C2=A0 =C2=A0=C2=A0} > +diff --git a/src/dnsmasq.h b/src/dnsmasq.h > +index 6d1c5ae..6344df5 100644 > +--- a/src/dnsmasq.h > ++++ b/src/dnsmasq.h > +@@ -308,6 +308,7 @@ struct ptr_record { > + }; > +=C2=A0 > + struct cname { > ++=C2=A0=C2=A0int ttl; > +=C2=A0=C2=A0=C2=A0char *alias, *target; > +=C2=A0=C2=A0=C2=A0struct cname *next; > + };=C2=A0 > +@@ -344,6 +345,7 @@ struct auth_zone { > +=C2=A0 > +=C2=A0 > + struct host_record { > ++=C2=A0=C2=A0int ttl; > +=C2=A0=C2=A0=C2=A0struct name_list { > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0char *name; > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct name_list *next; > +diff --git a/src/option.c b/src/option.c > +index c98bdc9..7c5e6bc 100644 > +--- a/src/option.c > ++++ b/src/option.c > +@@ -448,20 +448,20 @@ static struct { > +=C2=A0=C2=A0=C2=A0{ LOPT_GEN_NAMES, ARG_DUP, "[=3Dtag:<tag>]", gettext_noo= p("Generate > hostnames based on MAC address for nameless clients."), NULL}, > +=C2=A0=C2=A0=C2=A0{ LOPT_PROXY, ARG_DUP, "[=3D<ipaddr>]...", gettext_noop(= "Use these > DHCP relays as full proxies."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<interfac= e>]", > gettext_noop("Relay DHCP requests to a remote server"), NULL}, > +-=C2=A0=C2=A0{ LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Spec= ify > alias name for LOCAL DNS name."), NULL }, > ++=C2=A0=C2=A0{ LOPT_CNAME, ARG_DUP, "<alias>,<target>[,<ttl>]", > gettext_noop("Specify alias name for LOCAL DNS name."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", > gettext_noop("Prompt to send to PXE clients."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boo= t service > for PXE menu."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_TEST, 0, NULL, gettext_noop("Check configuration > syntax."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_ADD_MAC, ARG_DUP, "[=3Dbase64|text]", gettext_noo= p("Add > requestor's MAC address to forwarded DNS queries."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", > gettext_noop("Add specified IP subnet to forwarded DNS queries."), > NULL }, > +-=C2=A0=C2=A0=C2=A0{ LOPT_CPE_ID, ARG_ONE, "<text>", gettext_noop("Add cli= ent > identification to forwarded DNS queries."), NULL }, > ++=C2=A0=C2=A0{ LOPT_CPE_ID, ARG_ONE, "<text>", gettext_noop("Add client > identification to forwarded DNS queries."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Pro= xy DNSSEC > validation results from upstream nameservers."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("A= ttempt to > allocate sequential IP addresses to DHCP clients."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy > connection-track mark from queries to upstream connections."), NULL > }, > +=C2=A0=C2=A0=C2=A0{ LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow = DHCP > clients to do their own DDNS updates."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-adver= tisements=20 > for interfaces doing DHCPv6"), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", > gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL }, > +-=C2=A0=C2=A0{ LOPT_HOST_REC, ARG_DUP, "<name>,<address>", > gettext_noop("Specify host (A/AAAA and PTR) records"), NULL }, > ++=C2=A0=C2=A0{ LOPT_HOST_REC, ARG_DUP, "<name>,<address>[,<ttl>]", > gettext_noop("Specify host (A/AAAA and PTR) records"), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", > gettext_noop("Specify arbitrary DNS resource record"), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bi= nd to > interfaces in use - check for new interfaces"), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", > gettext_noop("Export local names to global DNS"), NULL }, > +@@ -3692,12 +3692,15 @@ static int one_opt(int option, char *arg, > char *errstr, char *gen_err, int comma > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case LOPT_CNAME: /* --cname */ > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > +=C2=A0 struct cname *new; > +- char *alias; > +- char *target; > ++ char *alias, *target, *ttls; > ++ int ttl =3D -1; > +=C2=A0 > +=C2=A0 if (!(comma =3D split(arg))) > +=C2=A0 =C2=A0=C2=A0ret_err(gen_err); > +=C2=A0=09 > ++ if ((ttls =3D split(comma)) && !atoi_check(ttls, &ttl)) > ++ =C2=A0=C2=A0ret_err(_("bad TTL")); > ++=09 > +=C2=A0 alias =3D canonicalise_opt(arg); > +=C2=A0 target =3D canonicalise_opt(comma); > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > +@@ -3713,6 +3716,7 @@ static int one_opt(int option, char *arg, char > *errstr, char *gen_err, int comma > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0daemon->cnames =3D new; > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0new->alias =3D alias; > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0new->target =3D target; > ++ =C2=A0=C2=A0=C2=A0=C2=A0new->ttl =3D ttl; > +=C2=A0 =C2=A0=C2=A0} > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > +=C2=A0 break; > +@@ -3913,14 +3917,22 @@ static int one_opt(int option, char *arg, > char *errstr, char *gen_err, int comma > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > +=C2=A0 struct host_record *new =3D opt_malloc(sizeof(struct > host_record)); > +=C2=A0 memset(new, 0, sizeof(struct host_record)); > +-=09 > ++ new->ttl =3D -1; > ++ > +=C2=A0 if (!arg || !(comma =3D split(arg))) > +=C2=A0 =C2=A0=C2=A0ret_err(_("Bad host-record")); > +=C2=A0=09 > +=C2=A0 while (arg) > +=C2=A0 =C2=A0=C2=A0{ > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0struct all_addr addr; > +- =C2=A0=C2=A0=C2=A0=C2=A0if (inet_pton(AF_INET, arg, &addr)) > ++ =C2=A0=C2=A0=C2=A0=C2=A0char *dig; > ++ > ++ =C2=A0=C2=A0=C2=A0=C2=A0for (dig =3D arg; *dig !=3D 0; dig++) > ++ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (*dig < '0' || *dig > '9') > ++ break; > ++ =C2=A0=C2=A0=C2=A0=C2=A0if (*dig =3D=3D 0) > ++ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->ttl =3D atoi(arg); > ++ =C2=A0=C2=A0=C2=A0=C2=A0else if (inet_pton(AF_INET, arg, &addr)) > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->addr =3D addr.addr.addr4; > + #ifdef HAVE_IPV6 > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0else if (inet_pton(AF_INET6, arg, &addr)) > +@@ -4601,7 +4613,25 @@ void read_opts(int argc, char **argv, char > *compile_opts) > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > +=C2=A0 }=C2=A0 > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > +-=C2=A0=C2=A0 > ++ > ++=C2=A0=C2=A0if (daemon->host_records) > ++=C2=A0=C2=A0=C2=A0=C2=A0{ > ++=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct host_record *hr; > ++=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > ++=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (hr =3D daemon->host_records; hr;= hr =3D hr->next) > ++ if (hr->ttl =3D=3D -1) > ++ =C2=A0=C2=A0hr->ttl =3D daemon->local_ttl; > ++=C2=A0=C2=A0=C2=A0=C2=A0} > ++ > ++=C2=A0=C2=A0if (daemon->cnames) > ++=C2=A0=C2=A0=C2=A0=C2=A0{ > ++=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct cname *cn; > ++=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > ++=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (cn =3D daemon->cnames; cn; cn = =3D cn->next) > ++ if (cn->ttl =3D=3D -1) > ++ =C2=A0=C2=A0cn->ttl =3D daemon->local_ttl; > ++=C2=A0=C2=A0=C2=A0=C2=A0} > ++ > +=C2=A0=C2=A0=C2=A0if (daemon->if_addrs) > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{=C2=A0=C2=A0 > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct iname *tmp; > +diff --git a/src/rfc1035.c b/src/rfc1035.c > +index 9c0ddb5..3535a71 100644 > +--- a/src/rfc1035.c > ++++ b/src/rfc1035.c > +@@ -1169,9 +1169,13 @@ static unsigned long crec_ttl(struct crec > *crecp, time_t now) > +=C2=A0=C2=A0=C2=A0/* Return 0 ttl for DHCP entries, which might change > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0before the lease expires. */ > +=C2=A0 > +-=C2=A0=C2=A0if=C2=A0=C2=A0(crecp->flags & (F_IMMORTAL | F_DHCP)) > ++=C2=A0=C2=A0if (crecp->flags & F_DHCP) > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return daemon->local_ttl; > +=C2=A0=C2=A0=C2=A0 > ++=C2=A0=C2=A0/* Immortal entries other than DHCP are local, and hold TTL in > TTD field. */ > ++=C2=A0=C2=A0if (crecp->flags & F_IMMORTAL) > ++=C2=A0=C2=A0=C2=A0=C2=A0return crecp->ttd; > ++ > +=C2=A0=C2=A0=C2=A0/* Return the Max TTL value if it is lower then the actu= al TTL */ > +=C2=A0=C2=A0=C2=A0if (daemon->max_ttl =3D=3D 0 || ((unsigned)(crecp->ttd -= now) < > daemon->max_ttl)) > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return crecp->ttd - now; > +--=C2=A0 > +1.7.10.4 > + > diff --git a/src/patches/dnsmasq/001- > include_0_0_0_0_8_in_DNS_rebind_checks.patch > b/src/patches/dnsmasq/001- > include_0_0_0_0_8_in_DNS_rebind_checks.patch > deleted file mode 100644 > index 8a2557a..0000000 > --- a/src/patches/dnsmasq/001- > include_0_0_0_0_8_in_DNS_rebind_checks.patch > +++ /dev/null > @@ -1,41 +0,0 @@ > -From d2aa7dfbb6d1088dcbea9fecc61b9293b320eb95 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Mon, 3 Aug 2015 21:52:12 +0100 > -Subject: [PATCH] Include 0.0.0.0/8 in DNS rebind checks. > - > ---- > - CHANGELOG=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A0=C2=A07 +++++++ > - src/rfc1035.c |=C2=A0=C2=A0=C2=A0=C2=A03 ++- > - 2 files changed, 9 insertions(+), 1 deletion(-) > - > -diff --git a/CHANGELOG b/CHANGELOG > -index 901da47..3f4026d 100644 > ---- a/CHANGELOG > -+++ b/CHANGELOG > -@@ -1,3 +1,10 @@ > -+version 2.76 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0I= nclude 0.0.0.0/8 in DNS rebind checks. This range=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0translates to hosts on=C2=A0=C2=A0the local netw= ork, or, at=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0least, 0.0.0.0 accesses the local host, so could > -+ =C2=A0=C2=A0=C2=A0=C2=A0be targets for DNS rebinding. See RFC 5735 secti= on 3=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0for details. Thanks to Stephen R=C3=83=C2=B6ttge= r for the bug > report. > -+ =C2=A0=C2=A0=C2=A0=C2=A0 > - version 2.75 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0Fix reversion on 2.74 which caused 100% CPU use when a=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0dhcp-script is configured. Thanks to Adrian= Davey for > -diff --git a/src/rfc1035.c b/src/rfc1035.c > -index 56647b0..29e9e65 100644 > ---- a/src/rfc1035.c > -+++ b/src/rfc1035.c > -@@ -728,7 +728,8 @@ int private_net(struct in_addr addr, int > ban_localhost) > -=C2=A0=C2=A0=C2=A0in_addr_t ip_addr =3D ntohl(addr.s_addr); > -=C2=A0 > -=C2=A0=C2=A0=C2=A0return > --=C2=A0=C2=A0=C2=A0=C2=A0(((ip_addr & 0xFF000000) =3D=3D 0x7F000000) && ba= n_localhost)=C2=A0=C2=A0/* > 127.0.0.0/8=C2=A0=C2=A0=C2=A0=C2=A0(loopback) */ ||=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0(((ip_addr & 0xFF000000) =3D=3D 0x7F000000) && ba= n_localhost)=C2=A0=C2=A0/* > 127.0.0.0/8=C2=A0=C2=A0=C2=A0=C2=A0(loopback) */ || > -+=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFF000000) =3D=3D 0x00000000)=C2=A0= =C2=A0/* RFC 5735 section 3. > "here" network */ || > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFFFF0000) =3D=3D 0xC0A80000)= =C2=A0=C2=A0/* 192.168.0.0/16 > (private)=C2=A0=C2=A0*/ || > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFF000000) =3D=3D 0x0A000000)= =C2=A0=C2=A0/* > 10.0.0.0/8=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(private)=C2=A0=C2=A0*/ || > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFFF00000) =3D=3D 0xAC100000)= =C2=A0=C2=A0/* > 172.16.0.0/12=C2=A0=C2=A0(private)=C2=A0=C2=A0*/ || > ---=C2=A0 > -1.7.10.4 > diff --git a/src/patches/dnsmasq/002-Add_--dhcp-ttl_option.patch > b/src/patches/dnsmasq/002-Add_--dhcp-ttl_option.patch > new file mode 100644 > index 0000000..45e3b9b > --- /dev/null > +++ b/src/patches/dnsmasq/002-Add_--dhcp-ttl_option.patch > @@ -0,0 +1,117 @@ > +From 832e47beab95c2918b5264f0504f2fe6fe523e4c Mon Sep 17 00:00:00 > 2001 > +From: Simon Kelley <simon(a)thekelleys.org.uk> > +Date: Wed, 24 Feb 2016 21:24:45 +0000 > +Subject: [PATCH] Add --dhcp-ttl option. > + > +--- > + man/dnsmasq.8 |=C2=A0=C2=A0=C2=A0=C2=A05 ++++- > + src/dnsmasq.h |=C2=A0=C2=A0=C2=A0=C2=A02 +- > + src/option.c=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A013 +++++++++++-- > + src/rfc1035.c |=C2=A0=C2=A0=C2=A0=C2=A02 +- > + 4 files changed, 17 insertions(+), 5 deletions(-) > + > +diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 > +index 7bc1394..2bcce20 100644 > +--- a/man/dnsmasq.8 > ++++ b/man/dnsmasq.8 > +@@ -60,7 +60,7 @@ in the same way as for DHCP-derived names. Note > that this does not > + apply to domain names in cnames, PTR records, TXT records etc. > + .TP > + .B \-T, --local-ttl=3D<time> > +-When replying with information from /etc/hosts or the DHCP leases > ++When replying with information from /etc/hosts or configuration or > the DHCP leases > + file dnsmasq by default sets the time-to-live field to zero, > meaning > + that the requester should not itself cache the information. This is > + the correct thing to do in almost all situations. This option > allows a > +@@ -68,6 +68,9 @@ time-to-live (in seconds) to be given for these > replies. This will > + reduce the load on the server at the expense of clients using stale > + data under some circumstances. > + .TP > ++.B --dhcp-ttl=3D<time> > ++As for --local-ttl, but affects only replies with information from > DHCP leases. If both are given, --dhcp-ttl applies for DHCP > information, and --local-ttl for others. Setting this to zero > eliminates the effect of --local-ttl for DHCP. > ++.TP > + .B --neg-ttl=3D<time> > + Negative replies from upstream servers normally contain time-to- > live > + information in SOA records which dnsmasq uses for caching. If the > +diff --git a/src/dnsmasq.h b/src/dnsmasq.h > +index 6344df5..9f73c3b 100644 > +--- a/src/dnsmasq.h > ++++ b/src/dnsmasq.h > +@@ -955,7 +955,7 @@ extern struct daemon { > +=C2=A0=C2=A0=C2=A0int max_logs;=C2=A0=C2=A0/* queue limit */ > +=C2=A0=C2=A0=C2=A0int cachesize, ftabsize; > +=C2=A0=C2=A0=C2=A0int port, query_port, min_port, max_port; > +-=C2=A0=C2=A0unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, > max_cache_ttl, auth_ttl; > ++=C2=A0=C2=A0unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, > max_cache_ttl, auth_ttl, dhcp_ttl, use_dhcp_ttl; > +=C2=A0=C2=A0=C2=A0char *dns_client_id; > +=C2=A0=C2=A0=C2=A0struct hostsfile *addn_hosts; > +=C2=A0=C2=A0=C2=A0struct dhcp_context *dhcp, *dhcp6; > +diff --git a/src/option.c b/src/option.c > +index 7c5e6bc..3f6d162 100644 > +--- a/src/option.c > ++++ b/src/option.c > +@@ -157,6 +157,7 @@ struct myoption { > + #define LOPT_MAXPORT=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0345 > + #define LOPT_CPE_ID=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0346 > + #define LOPT_SCRIPT_ARP=C2=A0=C2=A0=C2=A0=C2=A0347 > ++#define LOPT_DHCPTTL=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0348 > +=C2=A0 > + #ifdef HAVE_GETOPT_LONG > + static const struct option opts[] =3D=C2=A0=C2=A0 > +@@ -319,6 +320,7 @@ static const struct myoption opts[] =3D > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ "quiet-ra", 0, 0, LOPT_QUIET_RA }, > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ "dns-loop-detect", 0, 0, LOPT_LOOP_DETECT = }, > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ "script-arp", 0, 0, LOPT_SCRIPT_ARP }, > ++=C2=A0=C2=A0=C2=A0=C2=A0{ "dhcp-ttl", 1, 0 , LOPT_DHCPTTL }, > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ NULL, 0, 0, 0 } > +=C2=A0=C2=A0=C2=A0}; > +=C2=A0 > +@@ -485,9 +487,10 @@ static struct { > +=C2=A0=C2=A0=C2=A0{ LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("D= o not log > routine DHCP."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop(= "Do not > log routine DHCPv6."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do no= t log > RA."), NULL }, > +-=C2=A0=C2=A0{ LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, > gettext_noop("Accept queries only from directly-connected networks"), > NULL }, > +-=C2=A0=C2=A0{ LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Dete= ct > and remove DNS forwarding loops"), NULL }, > ++=C2=A0=C2=A0{ LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, > gettext_noop("Accept queries only from directly-connected > networks."), NULL }, > ++=C2=A0=C2=A0{ LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Dete= ct > and remove DNS forwarding loops."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>", gettext_noop("I= gnore DNS > responses containing ipaddr."), NULL },=C2=A0 > ++=C2=A0=C2=A0{ LOPT_DHCPTTL, ARG_ONE, "<ttl>", gettext_noop("Set TTL in DNS > responses with DHCP-derived addresses."), NULL },=C2=A0 > +=C2=A0=C2=A0=C2=A0{ 0, 0, NULL, NULL, NULL } > + };=C2=A0 > +=C2=A0 > +@@ -2580,6 +2583,7 @@ static int one_opt(int option, char *arg, char > *errstr, char *gen_err, int comma > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case LOPT_MINCTTL: /* --min-cache-ttl */ > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case LOPT_MAXCTTL: /* --max-cache-ttl */ > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case LOPT_AUTHTTL: /* --auth-ttl */ > ++=C2=A0=C2=A0=C2=A0=C2=A0case LOPT_DHCPTTL: /* --dhcp-ttl */ > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > +=C2=A0 int ttl; > +=C2=A0 if (!atoi_check(arg, &ttl)) > +@@ -2598,6 +2602,11 @@ static int one_opt(int option, char *arg, > char *errstr, char *gen_err, int comma > +=C2=A0 =C2=A0=C2=A0daemon->max_cache_ttl =3D (unsigned long)ttl; > +=C2=A0 else if (option =3D=3D LOPT_AUTHTTL) > +=C2=A0 =C2=A0=C2=A0daemon->auth_ttl =3D (unsigned long)ttl; > ++ else if (option =3D=3D LOPT_DHCPTTL) > ++ =C2=A0=C2=A0{ > ++ =C2=A0=C2=A0=C2=A0=C2=A0daemon->dhcp_ttl =3D (unsigned long)ttl; > ++ =C2=A0=C2=A0=C2=A0=C2=A0daemon->use_dhcp_ttl =3D 1; > ++ =C2=A0=C2=A0} > +=C2=A0 else > +=C2=A0 =C2=A0=C2=A0daemon->local_ttl =3D (unsigned long)ttl; > +=C2=A0 break; > +diff --git a/src/rfc1035.c b/src/rfc1035.c > +index 3535a71..8f1e3b4 100644 > +--- a/src/rfc1035.c > ++++ b/src/rfc1035.c > +@@ -1170,7 +1170,7 @@ static unsigned long crec_ttl(struct crec > *crecp, time_t now) > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0before the lease expires. */ > +=C2=A0 > +=C2=A0=C2=A0=C2=A0if (crecp->flags & F_DHCP) > +-=C2=A0=C2=A0=C2=A0=C2=A0return daemon->local_ttl; > ++=C2=A0=C2=A0=C2=A0=C2=A0return daemon->use_dhcp_ttl ? daemon->dhcp_ttl : = daemon- > >local_ttl; > +=C2=A0=C2=A0=C2=A0 > +=C2=A0=C2=A0=C2=A0/* Immortal entries other than DHCP are local, and hold = TTL in > TTD field. */ > +=C2=A0=C2=A0=C2=A0if (crecp->flags & F_IMMORTAL) > +--=C2=A0 > +1.7.10.4 > + > diff --git a/src/patches/dnsmasq/002- > enhance_add_subnet_to_allow_arbitary_subnet_addresses.patch > b/src/patches/dnsmasq/002- > enhance_add_subnet_to_allow_arbitary_subnet_addresses.patch > deleted file mode 100644 > index 2d3d6e4..0000000 > --- a/src/patches/dnsmasq/002- > enhance_add_subnet_to_allow_arbitary_subnet_addresses.patch > +++ /dev/null > @@ -1,271 +0,0 @@ > -From a7369bef8abd241c3d85633fa9c870943f091e76 Mon Sep 17 00:00:00 > 2001 > -From: Ed Bardsley <ebardsley(a)google.com> > -Date: Wed, 5 Aug 2015 21:17:18 +0100 > -Subject: [PATCH] Enhance --add-subnet to allow arbitary subnet > addresses. > - > ---- > - CHANGELOG=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A0=C2=A04 ++++ > - man/dnsmasq.8 |=C2=A0=C2=A0=C2=A032 ++++++++++++++++++++----------- > - src/dnsmasq.h |=C2=A0=C2=A0=C2=A013 ++++++++++--- > - src/option.c=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A059 > ++++++++++++++++++++++++++++++++++++++++++++++++++++----- > - src/rfc1035.c |=C2=A0=C2=A0=C2=A039 +++++++++++++++++++++++++++++++------- > - 5 files changed, 121 insertions(+), 26 deletions(-) > - > -diff --git a/CHANGELOG b/CHANGELOG > -index 3f4026d..bbc2834 100644 > ---- a/CHANGELOG > -+++ b/CHANGELOG > -@@ -4,6 +4,10 @@ version 2.76 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0least, 0.0.0.0 accesses the local host, so = could > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0be targets for DNS rebinding. See RFC 5735 = section 3=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0for details. Thanks to Stephen R=C3=83=C2= =B6ttger for the bug > report. > -+ > -+ =C2=A0=C2=A0=C2=A0=C2=A0Enhance --add-subnet to allow arbitrary subnet > addresses. > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T= hanks to Ed Barsley for the patch. > -+=09 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > - version 2.75 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0Fix reversion on 2.74 which caused 100% CPU use when a=C2=A0 > -diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 > -index c8913b5..a23c898 100644 > ---- a/man/dnsmasq.8 > -+++ b/man/dnsmasq.8 > -@@ -604,17 +604,27 @@ experimental. Also note that exposing MAC > addresses in this way may > - have security and privacy implications. The warning about caching > - given for --add-subnet applies to --add-mac too. > - .TP=C2=A0 > --.B --add-subnet[[=3D<IPv4 prefix length>],<IPv6 prefix length>] > --Add the subnet address of the requestor to the DNS queries which > are > --forwarded upstream. The amount of the address forwarded depends on > the > --prefix length parameter: 32 (128 for IPv6) forwards the whole > address, > --zero forwards none of it but still marks the request so that no > --upstream nameserver will add client address information either. The > --default is zero for both IPv4 and IPv6. Note that upstream > nameservers > --may be configured to return different results based on this > --information, but the dnsmasq cache does not take account. If a > dnsmasq > --instance is configured such that different results may be > encountered, > --caching should be disabled. > -+.B --add-subnet[[=3D[<IPv4 address>/]<IPv4 prefix length>][,[<IPv6 > address>/]<IPv6 prefix length>]] > -+Add a subnet address to the DNS queries which are forwarded > -+upstream. If an address is specified in the flag, it will be used, > -+otherwise, the address of the requestor will be used. The amount of > -+the address forwarded depends on the prefix length parameter: 32 > (128 > -+for IPv6) forwards the whole address, zero forwards none of it but > -+still marks the request so that no upstream nameserver will add > client > -+address information either. The default is zero for both IPv4 and > -+IPv6. Note that upstream nameservers may be configured to return > -+different results based on this information, but the dnsmasq cache > -+does not take account. If a dnsmasq instance is configured such > that > -+different results may be encountered, caching should be disabled. > -+ > -+For example, > -+.B --add-subnet=3D24,96 > -+will add the /24 and /96 subnets of the requestor for IPv4 and IPv6 > requestors, respectively. > -+.B --add-subnet=3D1.2.3.4/24 > -+will add 1.2.3.0/24 for IPv4 requestors and ::/0 for IPv6 > requestors. > -+.B --add-subnet=3D1.2.3.4/24,1.2.3.4/24 > -+will add 1.2.3.0/24 for both IPv4 and IPv6 requestors. > -+ > - .TP > - .B \-c, --cache-size=3D<cachesize> > - Set the size of dnsmasq's cache. The default is 150 names. Setting > the cache size to zero disables caching. > -diff --git a/src/dnsmasq.h b/src/dnsmasq.h > -index cf1a782..f42acdb 100644 > ---- a/src/dnsmasq.h > -+++ b/src/dnsmasq.h > -@@ -541,6 +541,13 @@ struct iname { > -=C2=A0=C2=A0=C2=A0struct iname *next; > - }; > -=C2=A0 > -+/* subnet parameters from command line */ > -+struct mysubnet { > -+=C2=A0=C2=A0union mysockaddr addr; > -+=C2=A0=C2=A0int addr_used; > -+=C2=A0=C2=A0int mask; > -+}; > -+ > - /* resolv-file parms from command-line */ > - struct resolvc { > -=C2=A0=C2=A0=C2=A0struct resolvc *next; > -@@ -935,9 +942,9 @@ extern struct daemon { > -=C2=A0=C2=A0=C2=A0struct auth_zone *auth_zones; > -=C2=A0=C2=A0=C2=A0struct interface_name *int_names; > -=C2=A0=C2=A0=C2=A0char *mxtarget; > --=C2=A0=C2=A0int addr4_netmask; > --=C2=A0=C2=A0int addr6_netmask; > --=C2=A0=C2=A0char *lease_file;=C2=A0 > -+=C2=A0=C2=A0struct mysubnet *add_subnet4; > -+=C2=A0=C2=A0struct mysubnet *add_subnet6; > -+=C2=A0=C2=A0char *lease_file; > -=C2=A0=C2=A0=C2=A0char *username, *groupname, *scriptuser; > -=C2=A0=C2=A0=C2=A0char *luascript; > -=C2=A0=C2=A0=C2=A0char *authserver, *hostmaster; > -diff --git a/src/option.c b/src/option.c > -index ecc2619..746cd11 100644 > ---- a/src/option.c > -+++ b/src/option.c > -@@ -445,7 +445,7 @@ static struct { > -=C2=A0=C2=A0=C2=A0{ LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boo= t service > for PXE menu."), NULL }, > -=C2=A0=C2=A0=C2=A0{ LOPT_TEST, 0, NULL, gettext_noop("Check configuration > syntax."), NULL }, > -=C2=A0=C2=A0=C2=A0{ LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add req= uestor's > MAC address to forwarded DNS queries."), NULL }, > --=C2=A0=C2=A0{ LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", > gettext_noop("Add requestor's IP subnet to forwarded DNS queries."), > NULL }, > -+=C2=A0=C2=A0{ LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", > gettext_noop("Add specified IP subnet to forwarded DNS queries."), > NULL }, > -=C2=A0=C2=A0=C2=A0{ LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Pro= xy DNSSEC > validation results from upstream nameservers."), NULL }, > -=C2=A0=C2=A0=C2=A0{ LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("A= ttempt to > allocate sequential IP addresses to DHCP clients."), NULL }, > -=C2=A0=C2=A0=C2=A0{ LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy > connection-track mark from queries to upstream connections."), NULL > }, > -@@ -722,6 +722,20 @@ static void do_usage(void) > -=C2=A0 > - #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0) > -=C2=A0 > -+static char *parse_mysockaddr(char *arg, union mysockaddr *addr)=C2=A0 > -+{ > -+=C2=A0=C2=A0if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0) > -+=C2=A0=C2=A0=C2=A0=C2=A0addr->sa.sa_family =3D AF_INET; > -+#ifdef HAVE_IPV6 > -+=C2=A0=C2=A0else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0) > -+=C2=A0=C2=A0=C2=A0=C2=A0addr->sa.sa_family =3D AF_INET6; > -+#endif > -+=C2=A0=C2=A0else > -+=C2=A0=C2=A0=C2=A0=C2=A0return _("bad address"); > -+=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0return NULL; > -+} > -+ > - char *parse_server(char *arg, union mysockaddr *addr, union > mysockaddr *source_addr, char *interface, int *flags) > - { > -=C2=A0=C2=A0=C2=A0int source_port =3D 0, serv_port =3D NAMESERVER_PORT; > -@@ -1585,7 +1599,7 @@ static int one_opt(int option, char *arg, char > *errstr, char *gen_err, int comma > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0li =3D match_suffix->next; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0free(match_suffix->suffix); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0free(match_suffix); > -- =C2=A0=C2=A0}=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0} > -=C2=A0 break; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > -@@ -1593,10 +1607,45 @@ static int one_opt(int option, char *arg, > char *errstr, char *gen_err, int comma > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0set_option_bool(OPT_CLIENT_SUBNE= T); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (arg) > -=C2=A0 { > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0char *err, *e= nd; > -=C2=A0 =C2=A0=C2=A0comma =3D split(arg); > -- =C2=A0=C2=A0if (!atoi_check(arg, &daemon->addr4_netmask) ||=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(comma && !atoi_check(comma, &daemon- > >addr6_netmask))) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ret_err(gen_err); > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct mysubn= et* new =3D opt_malloc(sizeof(struct > mysubnet)); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((end =3D = split_chr(arg, '/'))) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* has subnet+len */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0err =3D parse_mysockaddr(arg, &new->= addr); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (err) > -+ ret_err(err); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!atoi_check(end, &new->mask)) > -+ ret_err(gen_err); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->addr_used =3D 1; > -+ =C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -+ =C2=A0=C2=A0else if (!atoi_check(arg, &new->mask)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0ret_err(gen_err); > -+ =C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0daemon->add_s= ubnet4 =3D new; > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new =3D opt_m= alloc(sizeof(struct mysubnet)); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (comma) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0if ((end =3D split_chr(comma, '/'))) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* has subnet+len */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0err =3D parse_mysockaddr(comma, &new->add= r); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (err) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ret_err(err); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!atoi_check(end, &new->mask)) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ret_err(gen_err); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->addr_used =3D 1; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0else > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!atoi_check(comma, &new->mask)) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ret_err(gen_err); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0daemon->add_s= ubnet6 =3D new; > -=C2=A0 } > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0break; > -=C2=A0 > -diff --git a/src/rfc1035.c b/src/rfc1035.c > -index 29e9e65..6a51b30 100644 > ---- a/src/rfc1035.c > -+++ b/src/rfc1035.c > -@@ -629,26 +629,47 @@ struct subnet_opt { > - #endif > - }; > -=C2=A0 > -+static void *get_addrp(union mysockaddr *addr, const short family)=C2=A0 > -+{ > -+#ifdef HAVE_IPV6 > -+=C2=A0=C2=A0if (family =3D=3D AF_INET6) > -+=C2=A0=C2=A0=C2=A0=C2=A0return &addr->in6.sin6_addr; > -+#endif > -+ > -+=C2=A0=C2=A0return &addr->in.sin_addr; > -+} > -+ > - static size_t calc_subnet_opt(struct subnet_opt *opt, union > mysockaddr *source) > - { > -=C2=A0=C2=A0=C2=A0/* http://tools.ietf.org/html/draft-vandergaast-edns-cli= ent-subne > t-02 */ > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0int len; > -=C2=A0=C2=A0=C2=A0void *addrp; > -+=C2=A0=C2=A0int sa_family =3D source->sa.sa_family; > -=C2=A0 > - #ifdef HAVE_IPV6 > -=C2=A0=C2=A0=C2=A0if (source->sa.sa_family =3D=3D AF_INET6) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0opt->family =3D htons(2); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0opt->source_netmask =3D daemon->addr6= _netmask; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0addrp =3D &source->in6.sin6_addr; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0opt->source_netmask =3D daemon->add_s= ubnet6->mask; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (daemon->add_subnet6->addr_used)= =C2=A0 > -+ { > -+ =C2=A0=C2=A0sa_family =3D daemon->add_subnet6->addr.sa.sa_family; > -+ =C2=A0=C2=A0addrp =3D get_addrp(&daemon->add_subnet6->addr, sa_family); > -+ }=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else=C2=A0 > -+ addrp =3D &source->in6.sin6_addr; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0else > - #endif > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0opt->family =3D htons(1); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0opt->source_netmask =3D daemon->addr4= _netmask; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0addrp =3D &source->in.sin_addr; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0opt->source_netmask =3D daemon->add_s= ubnet4->mask; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (daemon->add_subnet4->addr_used) > -+ { > -+ =C2=A0=C2=A0sa_family =3D daemon->add_subnet4->addr.sa.sa_family; > -+ =C2=A0=C2=A0addrp =3D get_addrp(&daemon->add_subnet4->addr, sa_family); > -+ }=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else=C2=A0 > -+ addrp =3D &source->in.sin_addr; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0opt->scope_netmask =3D 0; > -@@ -656,6 +677,11 @@ static size_t calc_subnet_opt(struct subnet_opt > *opt, union mysockaddr *source) > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0if (opt->source_netmask !=3D 0) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -+#ifdef HAVE_IPV6 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0opt->family =3D htons(sa_family =3D= =3D AF_INET6 ? 2 : 1); > -+#else > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0opt->family =3D htons(1); > -+#endif > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0len =3D ((opt->source_netmask - = 1) >> 3) + 1; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0memcpy(opt->addr, addrp, len); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (opt->source_netmask & 7) > -@@ -2335,4 +2361,3 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0return len; > - } > -- > ---=C2=A0 > -1.7.10.4 > diff --git a/src/patches/dnsmasq/003-Update_CHANGELOG.patch > b/src/patches/dnsmasq/003-Update_CHANGELOG.patch > new file mode 100644 > index 0000000..f04f943 > --- /dev/null > +++ b/src/patches/dnsmasq/003-Update_CHANGELOG.patch > @@ -0,0 +1,17 @@ > +X-Git-Url: http://thekelleys.org.uk/gitweb/?p=3Ddnsmasq.git;a=3Dblobdiff > _plain;f=3DCHANGELOG;h=3D6d9ba490488f80ef565f459cef3c110bdf31212c;hp=3D1435 > 4f2506a7fbf8360cd32c96e1d7ce1bfeb3f9;hb=3De06e6e34bffd781b7cefa49b25fb8 > ae863654ca2;hpb=3D832e47beab95c2918b5264f0504f2fe6fe523e4c > + > +diff --git a/CHANGELOG b/CHANGELOG > +index 14354f2..6d9ba49 100644 > +--- a/CHANGELOG > ++++ b/CHANGELOG > +@@ -48,6 +48,10 @@ version 2.76 > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0(ie xx::0 to xx::ffff:ffff:ffff:ffff)=C2=A0 > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0Thanks to Laurent Bendel for spotting this = problem. > +=C2=A0 > ++ =C2=A0=C2=A0=C2=A0=C2=A0Add support for a TTL parameter in --host-record= and > ++ =C2=A0=C2=A0=C2=A0=C2=A0--cname. > ++ > ++ =C2=A0=C2=A0=C2=A0=C2=A0Add --dhcp-ttl option. > +=C2=A0 > + version 2.75 > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0Fix reversion on 2.74 which caused 100% CPU use when a=C2=A0 > diff --git a/src/patches/dnsmasq/003- > dont_answer_non_auth_queries_for_auth_zones_locally_when_localise_que > ries_set.patch b/src/patches/dnsmasq/003- > dont_answer_non_auth_queries_for_auth_zones_locally_when_localise_que > ries_set.patch > deleted file mode 100644 > index cfbcdfb..0000000 > --- a/src/patches/dnsmasq/003- > dont_answer_non_auth_queries_for_auth_zones_locally_when_localise_que > ries_set.patch > +++ /dev/null > @@ -1,34 +0,0 @@ > -From 3a3965ac21b1b759eab8799b6edb09195b671306 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Sun, 9 Aug 2015 17:45:06 +0100 > -Subject: [PATCH] Don't answer non-auth queries for auth zones > locally when > - --localise-queries set. > - > ---- > - src/forward.c |=C2=A0=C2=A0=C2=A0=C2=A04 ++-- > - 1 file changed, 2 insertions(+), 2 deletions(-) > - > -diff --git a/src/forward.c b/src/forward.c > -index 2731b90..b76a974 100644 > ---- a/src/forward.c > -+++ b/src/forward.c > -@@ -1365,7 +1365,7 @@ void receive_query(struct listener *listen, > time_t now) > -=C2=A0 > - #ifdef HAVE_AUTH > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* find queries for zones we're = authoritative for, and answer > them directly */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!auth_dns) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!auth_dns && !option_bool(OPT_LOC= ALISE)) > -=C2=A0 for (zone =3D daemon->auth_zones; zone; zone =3D zone->next) > -=C2=A0 =C2=A0=C2=A0if (in_zone(zone, daemon->namebuff, NULL)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -@@ -1904,7 +1904,7 @@ unsigned char *tcp_request(int confd, time_t > now, > -=C2=A0 =C2=A0=C2=A0 > - #ifdef HAVE_AUTH > -=C2=A0 =C2=A0=C2=A0/* find queries for zones we're authoritative for, and > answer them directly */ > -- =C2=A0=C2=A0if (!auth_dns) > -+ =C2=A0=C2=A0if (!auth_dns && !option_bool(OPT_LOCALISE)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0for (zone =3D daemon->auth_zones; zone; zon= e =3D zone- > >next) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (in_zone(zone, daemon->nameb= uff, NULL)) > -=C2=A0 { > ---=C2=A0 > -1.7.10.4 > diff --git a/src/patches/dnsmasq/004-Add_--tftp-mtu_option.patch > b/src/patches/dnsmasq/004-Add_--tftp-mtu_option.patch > new file mode 100644 > index 0000000..c06705a > --- /dev/null > +++ b/src/patches/dnsmasq/004-Add_--tftp-mtu_option.patch > @@ -0,0 +1,136 @@ > +From bec366b4041df72b559e713f1c924177676e6eb0 Mon Sep 17 00:00:00 > 2001 > +From: Simon Kelley <simon(a)thekelleys.org.uk> > +Date: Wed, 24 Feb 2016 22:03:26 +0000 > +Subject: [PATCH] Add --tftp-mtu option. > + > +--- > + CHANGELOG=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A0=C2=A04 ++++ > + man/dnsmasq.8 |=C2=A0=C2=A0=C2=A0=C2=A04 ++++ > + src/dnsmasq.h |=C2=A0=C2=A0=C2=A0=C2=A02 +- > + src/option.c=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A010 +++++++++- > + src/tftp.c=C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A014 ++++++++++++-- > + 5 files changed, 30 insertions(+), 4 deletions(-) > + > +diff --git a/CHANGELOG b/CHANGELOG > +index 6d9ba49..9218b8c 100644 > +--- a/CHANGELOG > ++++ b/CHANGELOG > +@@ -53,6 +53,10 @@ version 2.76 > +=C2=A0 > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0Add --dhcp-ttl option. > +=C2=A0 > ++ =C2=A0=C2=A0=C2=A0=C2=A0Add --tftp-mtu option. Thanks to Patrick McLean = for > the=C2=A0 > ++ =C2=A0=C2=A0=C2=A0=C2=A0initial patch. > ++ > ++ > + version 2.75 > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0Fix reversion on 2.74 which caused 100% CPU use when a=C2=A0 > +=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0dhcp-script is configured. Thanks to Adrian= Davey for > +diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 > +index 2bcce20..3cf48cd 100644 > +--- a/man/dnsmasq.8 > ++++ b/man/dnsmasq.8 > +@@ -1810,6 +1810,10 @@ require about (2*n) + 10 descriptors. If > + .B --tftp-port-range > + is given, that can affect the number of concurrent connections. > + .TP > ++.B --tftp-mtu=3D<mtu size> > ++Use size as the ceiling of the MTU supported by the intervening > network when=C2=A0 > ++negotiating TFTP blocksize, overriding the MTU setting of the local > interface=C2=A0=C2=A0if it is larger. > ++.TP > + .B --tftp-no-blocksize > + Stop the TFTP server from negotiating the "blocksize" option with a > + client. Some buggy clients request this option but then behave > badly > +diff --git a/src/dnsmasq.h b/src/dnsmasq.h > +index 9f73c3b..280ad9d 100644 > +--- a/src/dnsmasq.h > ++++ b/src/dnsmasq.h > +@@ -975,7 +975,7 @@ extern struct daemon { > +=C2=A0=C2=A0=C2=A0struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, > *dhcp_gen_names;=C2=A0 > +=C2=A0=C2=A0=C2=A0struct dhcp_netid_list *force_broadcast, *bootp_dynamic; > +=C2=A0=C2=A0=C2=A0struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, > *dynamic_dirs; > +-=C2=A0=C2=A0int dhcp_max, tftp_max; > ++=C2=A0=C2=A0int dhcp_max, tftp_max, tftp_mtu; > +=C2=A0=C2=A0=C2=A0int dhcp_server_port, dhcp_client_port; > +=C2=A0=C2=A0=C2=A0int start_tftp_port, end_tftp_port;=C2=A0 > +=C2=A0=C2=A0=C2=A0unsigned int min_leasetime; > +diff --git a/src/option.c b/src/option.c > +index 3f6d162..765965f 100644 > +--- a/src/option.c > ++++ b/src/option.c > +@@ -158,7 +158,8 @@ struct myoption { > + #define LOPT_CPE_ID=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0346 > + #define LOPT_SCRIPT_ARP=C2=A0=C2=A0=C2=A0=C2=A0347 > + #define LOPT_DHCPTTL=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0348 > +- > ++#define LOPT_TFTP_MTU=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0349 > ++=C2=A0 > + #ifdef HAVE_GETOPT_LONG > + static const struct option opts[] =3D=C2=A0=C2=A0 > + #else > +@@ -244,6 +245,7 @@ static const struct myoption opts[] =3D > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ "tftp-unique-root", 0, 0, LOPT_APREF }, > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ "tftp-root", 1, 0, LOPT_PREFIX }, > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ "tftp-max", 1, 0, LOPT_TFTP_MAX }, > ++=C2=A0=C2=A0=C2=A0=C2=A0{ "tftp-mtu", 1, 0, LOPT_TFTP_MTU }, > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ "tftp-lowercase", 0, 0, LOPT_TFTP_LC }, > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ "ptr-record", 1, 0, LOPT_PTR }, > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ "naptr-record", 1, 0, LOPT_NAPTR }, > +@@ -432,6 +434,7 @@ static struct { > +=C2=A0=C2=A0=C2=A0{ LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allo= w access > only to files owned by the user running dnsmasq."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_TFTP_NO_FAIL, OPT_TFTP_NO_FAIL, NULL, gettext_noo= p("Do not > terminate the service if TFTP directories are inaccessible."), NULL > }, > +=C2=A0=C2=A0=C2=A0{ LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Max= imum > number of conncurrent TFTP transfers (defaults to %s)."), "#" }, > ++=C2=A0=C2=A0{ LOPT_TFTP_MTU, ARG_ONE, "<integer>", gettext_noop("Maximum = MTU > to use for TFTP transfers."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Di= sable the > TFTP blocksize extension."), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert= TFTP > filenames to lowercase"), NULL }, > +=C2=A0=C2=A0=C2=A0{ LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", > gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL > }, > +@@ -2625,6 +2628,11 @@ static int one_opt(int option, char *arg, > char *errstr, char *gen_err, int comma > +=C2=A0 ret_err(gen_err); > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0break;=C2=A0=C2=A0 > +=C2=A0 > ++=C2=A0=C2=A0=C2=A0=C2=A0case LOPT_TFTP_MTU:=C2=A0=C2=A0/*=C2=A0=C2=A0--tf= tp-mtu */ > ++=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!atoi_check(arg, &daemon->tftp_mt= u)) > ++ ret_err(gen_err); > ++=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0break; > ++ > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case LOPT_PREFIX: /* --tftp-prefix */ > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0comma =3D split(arg); > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (comma) > +diff --git a/src/tftp.c b/src/tftp.c > +index 00ed2fc..dc4aa85 100644 > +--- a/src/tftp.c > ++++ b/src/tftp.c > +@@ -103,8 +103,10 @@ void tftp_request(struct listener *listen, > time_t now) > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (listen->iface) > +=C2=A0 { > +=C2=A0 =C2=A0=C2=A0addr =3D listen->iface->addr; > +- =C2=A0=C2=A0mtu =3D listen->iface->mtu; > +=C2=A0 =C2=A0=C2=A0name =3D listen->iface->name; > ++ =C2=A0=C2=A0mtu =3D listen->iface->mtu; > ++ =C2=A0=C2=A0if (daemon->tftp_mtu !=3D 0 && daemon->tftp_mtu < mtu) > ++ =C2=A0=C2=A0=C2=A0=C2=A0mtu =3D daemon->tftp_mtu; > +=C2=A0 } > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > +=C2=A0 { > +@@ -234,9 +236,17 @@ void tftp_request(struct listener *listen, > time_t now) > +=C2=A0 > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0strncpy(ifr.ifr_name, name, IF_N= AMESIZE); > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (ioctl(listen->tftpfd, SIOCGI= FMTU, &ifr) !=3D -1) > +- mtu =3D ifr.ifr_mtu;=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > ++ { > ++ =C2=A0=C2=A0mtu =3D ifr.ifr_mtu;=C2=A0=C2=A0 > ++ =C2=A0=C2=A0if (daemon->tftp_mtu !=3D 0 && daemon->tftp_mtu < mtu) > ++ =C2=A0=C2=A0=C2=A0=C2=A0mtu =3D daemon->tftp_mtu;=C2=A0=C2=A0=C2=A0=C2=A0 > ++ } > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > +=C2=A0 > ++=C2=A0=C2=A0/* Failed to get interface mtu - can use configured value. */ > ++=C2=A0=C2=A0if (mtu =3D=3D 0) > ++=C2=A0=C2=A0=C2=A0=C2=A0mtu =3D daemon->tftp_mtu; > ++ > +=C2=A0=C2=A0=C2=A0if (name) > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* check for per-interface prefi= x */=C2=A0 > +--=C2=A0 > +1.7.10.4 > + > diff --git a/src/patches/dnsmasq/004-fix_behaviour_of_empty_dhcp- > option.patch b/src/patches/dnsmasq/004-fix_behaviour_of_empty_dhcp- > option.patch > deleted file mode 100644 > index 492ada9..0000000 > --- a/src/patches/dnsmasq/004-fix_behaviour_of_empty_dhcp- > option.patch > +++ /dev/null > @@ -1,38 +0,0 @@ > -From 5e3e464ac4022ee0b3794513abe510817e2cf3ca Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Tue, 25 Aug 2015 23:08:39 +0100 > -Subject: [PATCH] Fix behaviour of empty dhcp-option=3Doption6:dns- > server, which > - should inhibit sending option. > - > ---- > - src/rfc3315.c |=C2=A0=C2=A0=C2=A0=C2=A09 +++++---- > - 1 file changed, 5 insertions(+), 4 deletions(-) > - > -diff --git a/src/rfc3315.c b/src/rfc3315.c > -index 2665d0d..3f1f9ee 100644 > ---- a/src/rfc3315.c > -+++ b/src/rfc3315.c > -@@ -1320,15 +1320,16 @@ static struct dhcp_netid *add_options(struct > state *state, int do_refresh) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (opt_cfg->opt =3D=3D OPTION6_= REFRESH_TIME) > -=C2=A0 done_refresh =3D 1; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (opt_cfg->opt =3D=3D OPTION6_DNS_S= ERVER) > -+ done_dns =3D 1; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (opt_cfg->flags & DHOPT_ADDR6) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Empty DNS_SERVER option will not s= et DHOPT_ADDR6 */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((opt_cfg->flags & DHOPT_ADDR6) ||= opt_cfg->opt =3D=3D > OPTION6_DNS_SERVER) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0int len, j; > -=C2=A0 =C2=A0=C2=A0struct in6_addr *a; > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (opt_cfg->opt =3D=3D OPTION6_DNS_SERVER) > -- =C2=A0=C2=A0=C2=A0=C2=A0done_dns =3D 1; > -- =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0for (a =3D (struct in6_addr *)opt_cfg->val, len =3D opt= _cfg- > >len, j =3D 0;=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0j < opt_cfg->len; j +=3D = IN6ADDRSZ, a++) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0if ((IN6_IS_ADDR_ULA_ZERO(a) && > IN6_IS_ADDR_UNSPECIFIED(state->ula_addr)) || > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/005- > suggest_solution_to_ENOMEM_error_with_IPv6_multicast.patch > b/src/patches/dnsmasq/005- > suggest_solution_to_ENOMEM_error_with_IPv6_multicast.patch > deleted file mode 100644 > index c7cee60..0000000 > --- a/src/patches/dnsmasq/005- > suggest_solution_to_ENOMEM_error_with_IPv6_multicast.patch > +++ /dev/null > @@ -1,50 +0,0 @@ > -From 9cdcfe9f19ffd45bac4e5b459879bf7c50a287ed Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Wed, 26 Aug 2015 22:38:08 +0100 > -Subject: [PATCH] Suggest solution to ENOMEM error with IPv6 > multicast. > - > ---- > - src/network.c |=C2=A0=C2=A0=C2=A013 ++++++++++--- > - 1 file changed, 10 insertions(+), 3 deletions(-) > - > -diff --git a/src/network.c b/src/network.c > -index a1d90c8..819302f 100644 > ---- a/src/network.c > -+++ b/src/network.c > -@@ -1076,23 +1076,30 @@ void join_multicast(int dienow) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0if ((daemon->doing_dhcp6 || daemon->relay6)= && > -=C2=A0 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, > IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) =3D=3D -1) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0err =3D 1; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0err =3D errno; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0inet_pton(AF_INET6, ALL_SERVERS, > &mreq.ipv6mr_multiaddr); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0if (daemon->doing_dhcp6 &&=C2=A0 > -=C2=A0 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, > IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) =3D=3D -1) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0err =3D 1; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0err =3D errno; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0inet_pton(AF_INET6, ALL_ROUTERS, > &mreq.ipv6mr_multiaddr); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0if (daemon->doing_ra && > -=C2=A0 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, > IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) =3D=3D -1) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0err =3D 1; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0err =3D errno; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0if (err) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 char *s =3D _("interface %s failed to join DHCPv6 > multicast group: %s"); > -+ errno =3D err; > -+ > -+#ifdef HAVE_LINUX_NETWORK > -+ if (errno =3D=3D ENOMEM) > -+ =C2=A0=C2=A0my_syslog(LOG_ERR, _("try increasing > /proc/sys/net/core/optmem_max")); > -+#endif > -+ > -=C2=A0 if (dienow) > -=C2=A0 =C2=A0=C2=A0die(s, iface->name, EC_BADNET); > -=C2=A0 else > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/006- > clarify_man_page_on_RDNSS_set_in_router_advertisement.patch > b/src/patches/dnsmasq/006- > clarify_man_page_on_RDNSS_set_in_router_advertisement.patch > deleted file mode 100644 > index 19c76e6..0000000 > --- a/src/patches/dnsmasq/006- > clarify_man_page_on_RDNSS_set_in_router_advertisement.patch > +++ /dev/null > @@ -1,35 +0,0 @@ > -From 20fd11e11a9d09edcea94de135396ae1541fbbab Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Wed, 26 Aug 2015 22:48:13 +0100 > -Subject: [PATCH] Clarify man page on RDNSS set in router > advertisement. > - > ---- > - man/dnsmasq.8 |=C2=A0=C2=A0=C2=A0=C2=A06 +++--- > - 1 file changed, 3 insertions(+), 3 deletions(-) > - > -diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 > -index a23c898..d51b10f 100644 > ---- a/man/dnsmasq.8 > -+++ b/man/dnsmasq.8 > -@@ -1687,15 +1687,15 @@ creation are handled by a different > protocol. When DHCP is in use, > - only a subset of this is needed, and dnsmasq can handle it, using > - existing DHCP configuration to provide most data. When RA is > enabled, > - dnsmasq will advertise a prefix for each dhcp-range, with default > --router and recursive DNS server as the relevant link-local address > on=C2=A0 > --the machine running dnsmasq. By default, he "managed address" bits > are set, and > -+router=C2=A0=C2=A0as the relevant link-local address on=C2=A0 > -+the machine running dnsmasq. By default, the "managed address" bits > are set, and > - the "use SLAAC" bit is reset. This can be changed for individual > - subnets with the mode keywords described in > - .B --dhcp-range. > - RFC6106 DNS parameters are included in the advertisements. By > default, > - the relevant link-local address of the machine running dnsmasq is > sent > - as recursive DNS server. If provided, the DHCPv6 options dns-server=20 > and > --domain-search are used for RDNSS and DNSSL. > -+domain-search are used for the DNS server (RDNSS) and the domain > serach list (DNSSL). > - .TP > - .B --ra-param=3D<interface>,[high|low],[[<ra-interval>],<router > lifetime>] > - Set non-default values for router advertisements sent via an > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/007- > handle_signed_dangling_CNAME_replies_to_DS_queries.patch > b/src/patches/dnsmasq/007- > handle_signed_dangling_CNAME_replies_to_DS_queries.patch > deleted file mode 100644 > index 832a22e..0000000 > --- a/src/patches/dnsmasq/007- > handle_signed_dangling_CNAME_replies_to_DS_queries.patch > +++ /dev/null > @@ -1,30 +0,0 @@ > -From 6de81f1250fd323c9155de065d5a9dc200a6f20b Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Wed, 9 Sep 2015 22:51:13 +0100 > -Subject: [PATCH] Handle signed dangling CNAME replies to DS queries. > - > ---- > - src/dnssec.c |=C2=A0=C2=A0=C2=A0=C2=A07 ++----- > - 1 file changed, 2 insertions(+), 5 deletions(-) > - > -diff --git a/src/dnssec.c b/src/dnssec.c > -index 4deda24..67ce486 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -1232,11 +1232,8 @@ int dnssec_validate_ds(time_t now, struct > dns_header *header, size_t plen, char > -=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0/* If we return STAT_NO_SIG, name contains the name of t= he DS > query */ > -=C2=A0=C2=A0=C2=A0if (val =3D=3D STAT_NO_SIG) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*keyname =3D 0; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return val; > --=C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0=C2=A0 > -- > -+=C2=A0=C2=A0=C2=A0=C2=A0return val; > -+=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0/* If the key needed to validate the DS is on the same d= omain as > the DS, we'll > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0loop getting nowhere. Stop that now. T= his can happen of the DS > answer comes > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0from the DS's zone, and not the parent= zone. */ > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/008- > DHCPv6_option_56_does_not_hold_an_address_list.patch > b/src/patches/dnsmasq/008- > DHCPv6_option_56_does_not_hold_an_address_list.patch > deleted file mode 100644 > index fdccd0e..0000000 > --- a/src/patches/dnsmasq/008- > DHCPv6_option_56_does_not_hold_an_address_list.patch > +++ /dev/null > @@ -1,25 +0,0 @@ > -From 102208df695e886a3086754d32bf7f8c541fbe46 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Thu, 10 Sep 2015 21:50:00 +0100 > -Subject: [PATCH] DHCPv6 option 56 does not hold an address list. > (RFC 5908). > - > ---- > - src/dhcp-common.c |=C2=A0=C2=A0=C2=A0=C2=A02 +- > - 1 file changed, 1 insertion(+), 1 deletion(-) > - > -diff --git a/src/dhcp-common.c b/src/dhcp-common.c > -index bc48f41..8fc171a 100644 > ---- a/src/dhcp-common.c > -+++ b/src/dhcp-common.c > -@@ -599,7 +599,7 @@ static const struct opttab_t opttab6[] =3D { > -=C2=A0=C2=A0=C2=A0{ "sntp-server", 31,=C2=A0=C2=A0OT_ADDR_LIST }, > -=C2=A0=C2=A0=C2=A0{ "information-refresh-time", 32, OT_TIME }, > -=C2=A0=C2=A0=C2=A0{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME }, > --=C2=A0=C2=A0{ "ntp-server", 56,=C2=A0=C2=A0OT_ADDR_LIST }, > -+=C2=A0=C2=A0{ "ntp-server", 56,=C2=A0=C2=A00 }, > -=C2=A0=C2=A0=C2=A0{ "bootfile-url", 59, OT_NAME }, > -=C2=A0=C2=A0=C2=A0{ "bootfile-param", 60, OT_CSTRING }, > -=C2=A0=C2=A0=C2=A0{ NULL, 0, 0 } > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/009-Respect_the_ > --no_resolv_flag_in_inotify_code.patch b/src/patches/dnsmasq/009- > Respect_the_--no_resolv_flag_in_inotify_code.patch > deleted file mode 100644 > index 2014fdb..0000000 > --- a/src/patches/dnsmasq/009-Respect_the_ > --no_resolv_flag_in_inotify_code.patch > +++ /dev/null > @@ -1,47 +0,0 @@ > -From 77607cbea0ad0f876dfb79c8b2c121ee400d57d0 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Thu, 10 Sep 2015 23:08:43 +0100 > -Subject: [PATCH] Respect the --no-resolv flag in inotify code. > - > ---- > - CHANGELOG=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2= =A0=C2=A07 ++++++- > - debian/changelog |=C2=A0=C2=A0=C2=A0=C2=A06 ++++++ > - src/inotify.c=C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A0=C2=A03 +++ > - 3 files changed, 15 insertions(+), 1 deletion(-) > - > -diff --git a/CHANGELOG b/CHANGELOG > -index bbc2834..d6e309f 100644 > ---- a/CHANGELOG > -+++ b/CHANGELOG > -@@ -7,8 +7,13 @@ version 2.76 > -=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0Enhance --add-subnet to allow arbitrary sub= net > addresses. > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0Thanks to Ed Barsley for the patch. > -+ > -+ =C2=A0=C2=A0=C2=A0=C2=A0Respect the --no-resolv flag in inotify code. Fi= xes bug > -+ =C2=A0=C2=A0=C2=A0=C2=A0which caused dnsmasq to fail to start if a resol= v-file=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0was a dangling symbolic link, even of --no-resol= v set. > -+ =C2=A0=C2=A0=C2=A0=C2=A0Thanks to Alexander Kurtz for spotting the probl= em. > -+ > -=C2=A0=09 > -- =C2=A0=C2=A0=C2=A0=C2=A0 > - version 2.75 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0Fix reversion on 2.74 which caused 100% CPU use when a=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0dhcp-script is configured. Thanks to Adrian= Davey for > -diff --git a/src/inotify.c b/src/inotify.c > -index 52d412f..ef05c58 100644 > ---- a/src/inotify.c > -+++ b/src/inotify.c > -@@ -90,6 +90,9 @@ void inotify_dnsmasq_init() > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0if (daemon->inotifyfd =3D=3D -1) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0die(_("failed to create inotify: %s"), NULL,= EC_MISC); > -+ > -+=C2=A0=C2=A0if (option_bool(OPT_NO_RESOLV)) > -+=C2=A0=C2=A0=C2=A0=C2=A0return; > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0for (res =3D daemon->resolv_files; res; res =3D res->nex= t) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/010- > Rationalise_5e3e464ac4022ee0b3794513abe510817e2cf3ca.patch > b/src/patches/dnsmasq/010- > Rationalise_5e3e464ac4022ee0b3794513abe510817e2cf3ca.patch > deleted file mode 100644 > index 281697f..0000000 > --- a/src/patches/dnsmasq/010- > Rationalise_5e3e464ac4022ee0b3794513abe510817e2cf3ca.patch > +++ /dev/null > @@ -1,26 +0,0 @@ > -From 27b78d990b7cd901866ad6f1a17b9d633a95fdce Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Sat, 26 Sep 2015 21:40:45 +0100 > -Subject: [PATCH] Rationalise > 5e3e464ac4022ee0b3794513abe510817e2cf3ca > - > ---- > - src/rfc3315.c |=C2=A0=C2=A0=C2=A0=C2=A03 +-- > - 1 file changed, 1 insertion(+), 2 deletions(-) > - > -diff --git a/src/rfc3315.c b/src/rfc3315.c > -index 3f1f9ee..3ed8623 100644 > ---- a/src/rfc3315.c > -+++ b/src/rfc3315.c > -@@ -1324,8 +1324,7 @@ static struct dhcp_netid *add_options(struct > state *state, int do_refresh) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (opt_cfg->opt =3D=3D OPTION6_= DNS_SERVER) > -=C2=A0 done_dns =3D 1; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Empty DNS_SERVER option will not s= et DHOPT_ADDR6 */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((opt_cfg->flags & DHOPT_ADDR6) ||= opt_cfg->opt =3D=3D > OPTION6_DNS_SERVER) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (opt_cfg->flags & DHOPT_ADDR6) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0int len, j; > -=C2=A0 =C2=A0=C2=A0struct in6_addr *a; > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/011- > Catch_errors_from_sendmsg_in_DHCP_code.patch > b/src/patches/dnsmasq/011- > Catch_errors_from_sendmsg_in_DHCP_code.patch > deleted file mode 100644 > index 631495f..0000000 > --- a/src/patches/dnsmasq/011- > Catch_errors_from_sendmsg_in_DHCP_code.patch > +++ /dev/null > @@ -1,32 +0,0 @@ > -From 98079ea89851da1df4966dfdfa1852a98da02912 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Tue, 13 Oct 2015 20:30:32 +0100 > -Subject: [PATCH] Catch errors from sendmsg in DHCP code.=C2=A0=C2=A0Logs, > eg,=C2=A0=C2=A0iptables > - DROPS of dest 255.255.255.255 > - > ---- > - src/dhcp.c |=C2=A0=C2=A0=C2=A0=C2=A07 ++++++- > - 1 file changed, 6 insertions(+), 1 deletion(-) > - > -diff --git a/src/dhcp.c b/src/dhcp.c > -index e6fceb1..1c85e42 100644 > ---- a/src/dhcp.c > -+++ b/src/dhcp.c > -@@ -452,8 +452,13 @@ void dhcp_packet(time_t now, int pxe_fd) > - #endif > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0while(retry_send(sendmsg(fd, &msg, 0))); > -+ > -+=C2=A0=C2=A0/* This can fail when, eg, iptables DROPS destination > 255.255.255.255 */ > -+=C2=A0=C2=A0if (errno !=3D 0) > -+=C2=A0=C2=A0=C2=A0=C2=A0my_syslog(MS_DHCP | LOG_WARNING, _("Error sending= DHCP packet > to %s: %s"), > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0inet_ntoa(dest.sin_addr), strerror(e= rrno)); > - } > --=C2=A0 > -+ > - /* check against secondary interface addresses */ > - static int check_listen_addrs(struct in_addr local, int if_index, > char *label, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct in_addr netmask, struct > in_addr broadcast, void *vparam) > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/012-Update_list_of_subnet_for_ > --bogus-priv.patch b/src/patches/dnsmasq/012- > Update_list_of_subnet_for_--bogus-priv.patch > deleted file mode 100644 > index 3ba98fc..0000000 > --- a/src/patches/dnsmasq/012-Update_list_of_subnet_for_--bogus- > priv.patch > +++ /dev/null > @@ -1,48 +0,0 @@ > -From 90477fb79420a34124b66ebd808c578817a30e4c Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Tue, 20 Oct 2015 21:21:32 +0100 > -Subject: [PATCH] Update list of subnet for --bogus-priv > - > -RFC6303 specifies & recommends following zones not be forwarded > -to globally facing servers. > -+------------------------------+-----------------------+ > -| Zone=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0| Description=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0| > -+------------------------------+-----------------------+ > -| 0.IN-ADDR.ARPA=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0| IPv4 "THIS" NETWORK=C2=A0=C2=A0=C2=A0| > -| 127.IN-ADDR.ARPA=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0| IPv4 Loopback NETWORK | > -| 254.169.IN-ADDR.ARPA=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0| IPv4 LINK LOCAL=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0| > -| 2.0.192.IN-ADDR.ARPA=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0| IPv4 TEST-NET-1=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0| > -| 100.51.198.IN-ADDR.ARPA=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0| IPv4 TEST-N= ET-2=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0| > -| 113.0.203.IN-ADDR.ARPA=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0| IPv4 T= EST-NET-3=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0| > -| 255.255.255.255.IN-ADDR.ARPA | IPv4 BROADCAST=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0| > -+------------------------------+-----------------------+ > - > -Signed-off-by: Kevin Darbyshire-Bryant <kevin(a)darbyshire-bryant.me.u > k> > ---- > - src/rfc1035.c |=C2=A0=C2=A0=C2=A0=C2=A08 ++++++-- > - 1 file changed, 6 insertions(+), 2 deletions(-) > - > -diff --git a/src/rfc1035.c b/src/rfc1035.c > -index 6a51b30..4eb1772 100644 > ---- a/src/rfc1035.c > -+++ b/src/rfc1035.c > -@@ -756,10 +756,14 @@ int private_net(struct in_addr addr, int > ban_localhost) > -=C2=A0=C2=A0=C2=A0return > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(((ip_addr & 0xFF000000) =3D=3D 0x7F000000) = && ban_localhost)=C2=A0=C2=A0/* > 127.0.0.0/8=C2=A0=C2=A0=C2=A0=C2=A0(loopback) */ || > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFF000000) =3D=3D 0x00000000)= =C2=A0=C2=A0/* RFC 5735 section 3. > "here" network */ || > --=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFFFF0000) =3D=3D 0xC0A80000)=C2=A0= =C2=A0/* 192.168.0.0/16 > (private)=C2=A0=C2=A0*/ || > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFF000000) =3D=3D 0x0A000000)= =C2=A0=C2=A0/* > 10.0.0.0/8=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(private)=C2=A0=C2=A0*/ || > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFFF00000) =3D=3D 0xAC100000)= =C2=A0=C2=A0/* > 172.16.0.0/12=C2=A0=C2=A0(private)=C2=A0=C2=A0*/ || > --=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFFFF0000) =3D=3D 0xA9FE0000)=C2=A0= =C2=A0/* 169.254.0.0/16 > (zeroconf) */ ; > -+=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFFFF0000) =3D=3D 0xC0A80000)=C2=A0= =C2=A0/* 192.168.0.0/16 > (private)=C2=A0=C2=A0*/ || > -+=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFFFF0000) =3D=3D 0xA9FE0000)=C2=A0= =C2=A0/* 169.254.0.0/16 > (zeroconf) */ || > -+=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFFFFFF00) =3D=3D 0xC0000200)=C2=A0= =C2=A0/* > 192.0.2.0/24=C2=A0=C2=A0=C2=A0(test-net) */ || > -+=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFFFFFF00) =3D=3D 0xC6336400)=C2=A0= =C2=A0/* > 198.51.100.0/24(test-net) */ || > -+=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFFFFFF00) =3D=3D 0xCB007100)=C2=A0= =C2=A0/* 203.0.113.0/24 > (test-net) */ || > -+=C2=A0=C2=A0=C2=A0=C2=A0((ip_addr & 0xFFFFFFFF) =3D=3D 0xFFFFFFFF)=C2=A0= =C2=A0/* 255.255.255.255/32 > (broadcast)*/ ; > - } > -=C2=A0 > - static unsigned char *do_doctor(unsigned char *p, int count, struct > dns_header *header, size_t qlen, char *name, int *doctored) > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/013- > Fix_crash_when_empty_address_from_DNS_overlays_A_record_from.patch > b/src/patches/dnsmasq/013- > Fix_crash_when_empty_address_from_DNS_overlays_A_record_from.patch > deleted file mode 100644 > index 736cf38..0000000 > --- a/src/patches/dnsmasq/013- > Fix_crash_when_empty_address_from_DNS_overlays_A_record_from.patch > +++ /dev/null > @@ -1,43 +0,0 @@ > -From 41a8d9e99be9f2cc8b02051dd322cb45e0faac87 Mon Sep 17 00:00:00 > 2001 > -From: =3D?utf8?q?Edwin=3D20T=3DC3=3DB6r=3DC3=3DB6k?=3D <edwin+ml-cerowrt(a= )etorok.ne > t> > -Date: Sat, 14 Nov 2015 17:45:48 +0000 > -Subject: [PATCH] Fix crash when empty address from DNS overlays A > record from > - hosts. > - > ---- > - CHANGELOG=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A0=C2=A05 +++++ > - src/cache.c |=C2=A0=C2=A0=C2=A0=C2=A02 +- > - 2 files changed, 6 insertions(+), 1 deletion(-) > - > -diff --git a/CHANGELOG b/CHANGELOG > -index d6e309f..93c73d0 100644 > ---- a/CHANGELOG > -+++ b/CHANGELOG > -@@ -13,6 +13,11 @@ version 2.76 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0was a dangling symbolic link, even of --no-= resolv set. > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0Thanks to Alexander Kurtz for spotting the = problem. > -=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0Fix crash when an A or AAAA record is defined lo= cally, > -+ =C2=A0=C2=A0=C2=A0=C2=A0in a hosts file, and an upstream server sends a = reply > -+ =C2=A0=C2=A0=C2=A0=C2=A0that the same name is empty. Thanks to Edwin T= =C3=83=C2=B6r=C3=83=C2=B6k > for > -+ =C2=A0=C2=A0=C2=A0=C2=A0the patch. > -+ > -=C2=A0=09 > - version 2.75 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0Fix reversion on 2.74 which caused 100% CPU use when a=C2=A0 > -diff --git a/src/cache.c b/src/cache.c > -index 178d654..1b76b67 100644 > ---- a/src/cache.c > -+++ b/src/cache.c > -@@ -481,7 +481,7 @@ struct crec *cache_insert(char *name, struct > all_addr *addr, > -=C2=A0 =C2=A0existing record is for an A or AAAA and > -=C2=A0 =C2=A0the record we're trying to insert is the same,=C2=A0 > -=C2=A0 =C2=A0just drop the insert, but don't error the whole process. > */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((flags & (F_IPV4 | F_IPV6)) && (f= lags & F_FORWARD)) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((flags & (F_IPV4 | F_IPV6)) && (f= lags & F_FORWARD) && > addr) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0if ((flags & F_IPV4) && (new->flags & F_IPV4) && > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->addr.addr.addr.addr4.s_add= r =3D=3D addr- > >addr.addr4.s_addr) > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/014- > Handle_unknown_DS_hash_algos_correctly.patch > b/src/patches/dnsmasq/014- > Handle_unknown_DS_hash_algos_correctly.patch > deleted file mode 100644 > index 8b17431..0000000 > --- a/src/patches/dnsmasq/014- > Handle_unknown_DS_hash_algos_correctly.patch > +++ /dev/null > @@ -1,39 +0,0 @@ > -From 67ab3285b5d9a1b1e20e034cf272867fdab8a0f9 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Fri, 20 Nov 2015 23:20:47 +0000 > -Subject: [PATCH] Handle unknown DS hash algos correctly. > - > -When we can validate a DS RRset, but don't speak the hash algo it > -contains, treat that the same as an NSEC/3 proving that the DS > -doesn't exist. 4025 5.2 > ---- > - src/dnssec.c |=C2=A0=C2=A0=C2=A013 +++++++++++++ > - 1 file changed, 13 insertions(+) > - > -diff --git a/src/dnssec.c b/src/dnssec.c > -index 67ce486..b4dc14e 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -1005,6 +1005,19 @@ int dnssec_validate_by_ds(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0=C2=A0=C2=A0if (crecp->flags & F_NEG) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE_DS; > -=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0/* 4035 5.2=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0If the validator does not support any of th= e algorithms listed > in an > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0authenticated DS RRset, then the resolver h= as no supported > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0authentication path leading from the parent= to the child.=C2=A0=C2=A0The > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0resolver should treat this case as it would= the case of an > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0authenticated NSEC RRset proving that no DS= RRset exists,=C2=A0=C2=A0*/ > -+=C2=A0=C2=A0for (recp1 =3D crecp; recp1; recp1 =3D cache_find_by_name(rec= p1, > name, now, F_DS)) > -+=C2=A0=C2=A0=C2=A0=C2=A0if (hash_find(ds_digest_name(recp1->addr.ds.diges= t))) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0break; > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0if (!recp1) > -+=C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE_DS; > -+ > -=C2=A0=C2=A0=C2=A0/* NOTE, we need to find ONE DNSKEY which matches the DS= */ > -=C2=A0=C2=A0=C2=A0for (valid =3D 0, j =3D ntohs(header->ancount); j !=3D 0= && !valid; j > --)=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/015-Fix_crash_at_start_up_with_conf- > dir.patch b/src/patches/dnsmasq/015-Fix_crash_at_start_up_with_conf- > dir.patch > deleted file mode 100644 > index a9102c1..0000000 > --- a/src/patches/dnsmasq/015-Fix_crash_at_start_up_with_conf- > dir.patch > +++ /dev/null > @@ -1,38 +0,0 @@ > -From 0007ee90646a5a78a96ee729932e89d31c69513a Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Sat, 21 Nov 2015 21:47:41 +0000 > -Subject: [PATCH] Fix crash at start up with conf-dir=3D/path,* > - > -Thanks to Brian Carpenter and American Fuzzy Lop for finding the > bug. > ---- > - src/option.c |=C2=A0=C2=A0=C2=A014 ++++++++++---- > - 1 file changed, 10 insertions(+), 4 deletions(-) > - > -diff --git a/src/option.c b/src/option.c > -index 746cd11..71beb98 100644 > ---- a/src/option.c > -+++ b/src/option.c > -@@ -1515,10 +1515,16 @@ static int one_opt(int option, char *arg, > char *errstr, char *gen_err, int comma > -=C2=A0 li =3D opt_malloc(sizeof(struct list)); > -=C2=A0 if (*arg =3D=3D '*') > -=C2=A0 =C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0li->next =3D match_suffix; > -- =C2=A0=C2=A0=C2=A0=C2=A0match_suffix =3D li; > -- =C2=A0=C2=A0=C2=A0=C2=A0/* Have to copy: buffer is overwritten */ > -- =C2=A0=C2=A0=C2=A0=C2=A0li->suffix =3D opt_string_alloc(arg+1); > -+ =C2=A0=C2=A0=C2=A0=C2=A0/* "*" with no suffix is a no-op */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0if (arg[1] =3D=3D 0) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free(li); > -+ =C2=A0=C2=A0=C2=A0=C2=A0else > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -+ li->next =3D match_suffix; > -+ match_suffix =3D li; > -+ /* Have to copy: buffer is overwritten */ > -+ li->suffix =3D opt_string_alloc(arg+1); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0} > -=C2=A0 else > -=C2=A0 =C2=A0=C2=A0{ > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/016- > Major_rationalisation_of_DNSSEC_validation.patch > b/src/patches/dnsmasq/016- > Major_rationalisation_of_DNSSEC_validation.patch > deleted file mode 100644 > index 7f25066..0000000 > --- a/src/patches/dnsmasq/016- > Major_rationalisation_of_DNSSEC_validation.patch > +++ /dev/null > @@ -1,2209 +0,0 @@ > -From 9a31b68b59adcac01016d4026d906b69c4216c01 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Tue, 15 Dec 2015 10:20:39 +0000 > -Subject: [PATCH] Major rationalisation of DNSSEC validation. > - > -Much gnarly special-case code removed and replaced with correct > -general implementaion. Checking of zone-status moved to DNSSEC code, > -where it should be, vastly simplifying query-forwarding code. > ---- > - src/dnsmasq.h |=C2=A0=C2=A0=C2=A019 +- > - src/dnssec.c=C2=A0=C2=A0|=C2=A0=C2=A0926 ++++++++++++++++++++++++++++++--= ------------ > ------------- > - src/forward.c |=C2=A0=C2=A0741 ++++++++++--------------------------------= --- > - 3 files changed, 653 insertions(+), 1033 deletions(-) > - > -diff --git a/src/dnsmasq.h b/src/dnsmasq.h > -index f42acdb..023a1cf 100644 > ---- a/src/dnsmasq.h > -+++ b/src/dnsmasq.h > -@@ -586,12 +586,8 @@ struct hostsfile { > - #define STAT_NEED_KEY=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A05 > - #define STAT_TRUNCATED=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A06 > - #define STAT_SECURE_WILDCARD=C2=A0=C2=A0=C2=A0=C2=A07 > --#define STAT_NO_SIG=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A08 > --#define STAT_NO_DS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A09 > --#define STAT_NO_NS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A010 > --#define STAT_NEED_DS_NEG=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A011 > --#define STAT_CHASE_CNAME=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A012 > --#define STAT_INSECURE_DS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A013 > -+#define STAT_OK=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A08 > -+#define STAT_ABANDONED=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A09 > -=C2=A0 > - #define FREC_NOREBIND=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A01 > - #define FREC_CHECKING_DISABLED=C2=A0=C2=A02 > -@@ -601,8 +597,7 @@ struct hostsfile { > - #define FREC_AD_QUESTION=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A032 > - #define FREC_DO_QUESTION=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A064 > - #define FREC_ADDED_PHEADER=C2=A0=C2=A0=C2=A0=C2=A0128 > --#define FREC_CHECK_NOSIGN=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0256 > --#define FREC_TEST_PKTSZ=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0512 > -+#define FREC_TEST_PKTSZ=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0256 > -=C2=A0 > - #ifdef HAVE_DNSSEC > - #define HASH_SIZE 20 /* SHA-1 digest size */ > -@@ -626,9 +621,7 @@ struct frec { > - #ifdef HAVE_DNSSEC=C2=A0 > -=C2=A0=C2=A0=C2=A0int class, work_counter; > -=C2=A0=C2=A0=C2=A0struct blockdata *stash; /* Saved reply, whilst we valid= ate */ > --=C2=A0=C2=A0struct blockdata *orig_domain; /* domain of original query, > whilst > -- =C2=A0=C2=A0=C2=A0=C2=A0we're seeing is if in unsigned > domain */ > --=C2=A0=C2=A0size_t stash_len, name_start, name_len; > -+=C2=A0=C2=A0size_t stash_len; > -=C2=A0=C2=A0=C2=A0struct frec *dependent; /* Query awaiting internally-gen= erated > DNSKEY or DS query */ > -=C2=A0=C2=A0=C2=A0struct frec *blocking_query; /* Query which is blocking = us. */ > - #endif > -@@ -1162,8 +1155,8 @@ int in_zone(struct auth_zone *zone, char > *name, char **cut); > - size_t dnssec_generate_query(struct dns_header *header, char *end, > char *name, int class, int type, union mysockaddr *addr, int > edns_pktsz); > - int dnssec_validate_by_ds(time_t now, struct dns_header *header, > size_t n, char *name, char *keyname, int class); > - int dnssec_validate_ds(time_t now, struct dns_header *header, > size_t plen, char *name, char *keyname, int class); > --int dnssec_validate_reply(time_t now, struct dns_header *header, > size_t plen, char *name, char *keyname, int *class, int *neganswer, > int *nons); > --int dnssec_chase_cname(time_t now, struct dns_header *header, > size_t plen, char *name, char *keyname); > -+int dnssec_validate_reply(time_t now, struct dns_header *header, > size_t plen, char *name, char *keyname, int *class, > -+ =C2=A0=C2=A0int check_unsigned, int *neganswer, int > *nons); > - int dnskey_keytag(int alg, int flags, unsigned char *rdata, int > rdlen); > - size_t filter_rrsigs(struct dns_header *header, size_t plen); > - unsigned char* hash_questions(struct dns_header *header, size_t > plen, char *name); > -diff --git a/src/dnssec.c b/src/dnssec.c > -index b4dc14e..de7b335 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -65,8 +65,10 @@ static char *algo_digest_name(int algo) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 8: return "sha256"; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 10: return "sha512"; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 12: return "gosthash94"; > -+#ifndef NO_NETTLE_ECC > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 13: return "sha256"; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 14: return "sha384"; > -+#endif > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0default: return NULL; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > - } > -@@ -592,30 +594,30 @@ static int get_rdata(struct dns_header > *header, size_t plen, unsigned char *end, > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > - } > -=C2=A0 > --static int expand_workspace(unsigned char ***wkspc, int *sz, int > new) > -+static int expand_workspace(unsigned char ***wkspc, int *szp, int > new) > - { > -=C2=A0=C2=A0=C2=A0unsigned char **p; > --=C2=A0=C2=A0int new_sz =3D *sz; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0if (new_sz > new) > -+=C2=A0=C2=A0int old =3D *szp; > -+ > -+=C2=A0=C2=A0if (old >=3D new+1) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return 1; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if (new >=3D 100) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -=C2=A0 > --=C2=A0=C2=A0new_sz +=3D 5; > -+=C2=A0=C2=A0new +=3D 5; > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0if (!(p =3D whine_malloc((new_sz) * sizeof(unsigned char **))= )) > -+=C2=A0=C2=A0if (!(p =3D whine_malloc(new * sizeof(unsigned char **)))) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return 0;=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0if (*wkspc) > -+=C2=A0=C2=A0if (old !=3D 0 && *wkspc) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0memcpy(p, *wkspc, *sz * sizeof(unsign= ed char **)); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0memcpy(p, *wkspc, old * sizeof(unsign= ed char **)); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free(*wkspc); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0*wkspc =3D p; > --=C2=A0=C2=A0*sz =3D new_sz; > -+=C2=A0=C2=A0*szp =3D new; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0return 1; > - } > -@@ -706,47 +708,28 @@ static void sort_rrset(struct dns_header > *header, size_t plen, u16 *rr_desc, int > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} while (swap); > - } > -=C2=A0 > --/* Validate a single RRset (class, type, name) in the supplied DNS > reply=C2=A0 > --=C2=A0=C2=A0=C2=A0Return code: > --=C2=A0=C2=A0=C2=A0STAT_SECURE=C2=A0=C2=A0=C2=A0if it validates. > --=C2=A0=C2=A0=C2=A0STAT_SECURE_WILDCARD if it validates and is the result = of > wildcard expansion. > --=C2=A0=C2=A0=C2=A0(In this case *wildcard_out points to the "body" of the= wildcard > within name.)=C2=A0 > --=C2=A0=C2=A0=C2=A0STAT_NO_SIG no RRsigs found. > --=C2=A0=C2=A0=C2=A0STAT_INSECURE RRset empty. > --=C2=A0=C2=A0=C2=A0STAT_BOGUS=C2=A0=C2=A0=C2=A0=C2=A0signature is wrong, b= ad packet. > --=C2=A0=C2=A0=C2=A0STAT_NEED_KEY need DNSKEY to complete validation (name = is > returned in keyname) > -- > --=C2=A0=C2=A0=C2=A0if key is non-NULL, use that key, which has the algo an= d tag > given in the params of those names, > --=C2=A0=C2=A0=C2=A0otherwise find the key in the cache. > -+static unsigned char **rrset =3D NULL, **sigs =3D NULL; > -=C2=A0 > --=C2=A0=C2=A0=C2=A0name is unchanged on exit. keyname is used as workspace= and > trashed. > --*/ > --static int validate_rrset(time_t now, struct dns_header *header, > size_t plen, int class, int type,=C2=A0 > -- =C2=A0=C2=A0char *name, char *keyname, char > **wildcard_out, struct blockdata *key, int keylen, int algo_in, int > keytag_in) > -+/* Get pointers to RRset menbers and signature(s) for same. > -+=C2=A0=C2=A0=C2=A0Check signatures, and return keyname associated in keyn= ame. */ > -+static int explore_rrset(struct dns_header *header, size_t plen, > int class, int type,=C2=A0 > -+ =C2=A0char *name, char *keyname, int *sigcnt, > int *rrcnt) > - { > --=C2=A0=C2=A0static unsigned char **rrset =3D NULL, **sigs =3D NULL; > --=C2=A0=C2=A0static int rrset_sz =3D 0, sig_sz =3D 0; > --=C2=A0=C2=A0 > -+=C2=A0=C2=A0static int rrset_sz =3D 0, sig_sz =3D 0;=C2=A0 > -=C2=A0=C2=A0=C2=A0unsigned char *p; > --=C2=A0=C2=A0int rrsetidx, sigidx, res, rdlen, j, name_labels; > --=C2=A0=C2=A0struct crec *crecp =3D NULL; > --=C2=A0=C2=A0int type_covered, algo, labels, orig_ttl, sig_expiration, > sig_inception, key_tag; > --=C2=A0=C2=A0u16 *rr_desc =3D get_desc(type); > --=C2=A0 > --=C2=A0=C2=A0if (wildcard_out) > --=C2=A0=C2=A0=C2=A0=C2=A0*wildcard_out =3D NULL; > --=C2=A0=C2=A0 > -+=C2=A0=C2=A0int rrsetidx, sigidx, j, rdlen, res; > -+=C2=A0=C2=A0int name_labels =3D count_labels(name); /* For 4035 5.3.2 che= ck */ > -+=C2=A0=C2=A0int gotkey =3D 0; > -+ > -=C2=A0=C2=A0=C2=A0if (!(p =3D skip_questions(header, plen))) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0name_labels =3D count_labels(name); /* For 4035 5.3.2 check */ > -=C2=A0 > --=C2=A0=C2=A0/* look for RRSIGs for this RRset and get pointers to each RR= in > the set. */ > -+=C2=A0=C2=A0=C2=A0/* look for RRSIGs for this RRset and get pointers to e= ach RR in > the set. */ > -=C2=A0=C2=A0=C2=A0for (rrsetidx =3D 0, sigidx =3D 0, j =3D ntohs(header->a= ncount) + > ntohs(header->nscount);=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0j !=3D 0; j--)=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *pstart, *pdata; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int stype, sclass; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int stype, sclass, algo, type_covered= , labels, > sig_expiration, sig_inception; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0pstart =3D p; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -@@ -762,14 +745,14 @@ static int validate_rrset(time_t now, struct > dns_header *header, size_t plen, in > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(rdlen, p); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!CHECK_LEN(header, p, plen, = rdlen)) > -- return STAT_BOGUS;=C2=A0 > -+ return 0;=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (res =3D=3D 1 && sclass =3D= =3D class) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0if (stype =3D=3D type) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!expand_workspace(&rrset, &= rrset_sz, rrsetidx)) > -- return STAT_BOGUS;=C2=A0 > -+ return 0;=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0rrset[rrsetidx++] =3D pstart; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -@@ -777,14 +760,54 @@ static int validate_rrset(time_t now, struct > dns_header *header, size_t plen, in > -=C2=A0 =C2=A0=C2=A0if (stype =3D=3D T_RRSIG) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rdlen < 18) > -- return STAT_BOGUS; /* bad packet */=C2=A0 > -+ return 0; /* bad packet */=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(type_covered, p); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0algo =3D *p++; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0labels =3D *p++; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 4; /* orig_ttl */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETLONG(sig_expiration, p); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETLONG(sig_inception, p); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 2; /* key_tag */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (type_covered =3D=3D type) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (gotkey) > -+ { > -+ =C2=A0=C2=A0/* If there's more than one SIG, ensure they all > have same keyname */ > -+ =C2=A0=C2=A0if (extract_name(header, plen, &p, keyname, 0, 0) > !=3D 1) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+ } > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -+ { > -+ =C2=A0=C2=A0gotkey =3D 1; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (!extract_name(header, plen, &p, keyname, 1, > 0)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0/* RFC 4035 5.3.1 says that the Signer's Name > field MUST equal > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0the name of the zone containing the RRset= . We > can't tell that > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for certain, but we can check that=C2=A0= =C2=A0the RRset > name is equal to > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0or encloses the signers name, which shoul= d be > enough to stop=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0an attacker using signatures made with th= e key > of an unrelated=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0zone he controls. Note that the root key = is > always allowed. */ > -+ =C2=A0=C2=A0if (*keyname !=3D 0) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0char *name_start; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (name_start =3D name; > !hostname_isequal(name_start, keyname); ) > -+ if ((name_start =3D strchr(name_start, '.'))) > -+ =C2=A0=C2=A0name_start++; /* chop a label off and try > again */ > -+ else > -+ =C2=A0=C2=A0return 0; > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ } > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Don't count signatures for algos = we don't support > */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (check_date_range(sig_inception, = sig_expiration) > && > -+ =C2=A0=C2=A0labels <=3D name_labels && > -+ =C2=A0=C2=A0type_covered =3D=3D type &&=C2=A0 > -+ =C2=A0=C2=A0algo_digest_name(algo)) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0if (!expand_workspace(&sigs, &sig_sz, sigidx)) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS;=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 0;=C2=A0 > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0sigs[sigidx++] =3D pdata; > -=C2=A0 }=C2=A0 > -@@ -794,17 +817,45 @@ static int validate_rrset(time_t now, struct > dns_header *header, size_t plen, in > -=C2=A0 } > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!ADD_RDLEN(header, p, plen, = rdlen)) > -- return STAT_BOGUS; > -+ return 0; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0/* RRset empty */ > --=C2=A0=C2=A0if (rrsetidx =3D=3D 0) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE;=C2=A0 > -+=C2=A0=C2=A0*sigcnt =3D sigidx; > -+=C2=A0=C2=A0*rrcnt =3D rrsetidx; > -+ > -+=C2=A0=C2=A0return 1; > -+} > -+ > -+/* Validate a single RRset (class, type, name) in the supplied DNS > reply=C2=A0 > -+=C2=A0=C2=A0=C2=A0Return code: > -+=C2=A0=C2=A0=C2=A0STAT_SECURE=C2=A0=C2=A0=C2=A0if it validates. > -+=C2=A0=C2=A0=C2=A0STAT_SECURE_WILDCARD if it validates and is the result = of > wildcard expansion. > -+=C2=A0=C2=A0=C2=A0(In this case *wildcard_out points to the "body" of the= wildcard > within name.)=C2=A0 > -+=C2=A0=C2=A0=C2=A0STAT_BOGUS=C2=A0=C2=A0=C2=A0=C2=A0signature is wrong, b= ad packet. > -+=C2=A0=C2=A0=C2=A0STAT_NEED_KEY need DNSKEY to complete validation (name = is > returned in keyname) > -+=C2=A0=C2=A0=C2=A0STAT_NEED_DS=C2=A0=C2=A0need DS to complete validation = (name is returned > in keyname) > -+ > -+=C2=A0=C2=A0=C2=A0if key is non-NULL, use that key, which has the algo an= d tag > given in the params of those names, > -+=C2=A0=C2=A0=C2=A0otherwise find the key in the cache. > -=C2=A0 > --=C2=A0=C2=A0/* no RRSIGs */ > --=C2=A0=C2=A0if (sigidx =3D=3D 0) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_NO_SIG;=C2=A0 > -+=C2=A0=C2=A0=C2=A0name is unchanged on exit. keyname is used as workspace= and > trashed. > -+ > -+=C2=A0=C2=A0=C2=A0Call explore_rrset first to find and count RRs and sigs. > -+*/ > -+static int validate_rrset(time_t now, struct dns_header *header, > size_t plen, int class, int type, int sigidx, int rrsetidx,=C2=A0 > -+ =C2=A0=C2=A0char *name, char *keyname, char > **wildcard_out, struct blockdata *key, int keylen, int algo_in, int > keytag_in) > -+{ > -+=C2=A0=C2=A0unsigned char *p; > -+=C2=A0=C2=A0int rdlen, j, name_labels; > -+=C2=A0=C2=A0struct crec *crecp =3D NULL; > -+=C2=A0=C2=A0int algo, labels, orig_ttl, key_tag; > -+=C2=A0=C2=A0u16 *rr_desc =3D get_desc(type); > -+=C2=A0 > -+=C2=A0=C2=A0if (wildcard_out) > -+=C2=A0=C2=A0=C2=A0=C2=A0*wildcard_out =3D NULL; > -=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0name_labels =3D count_labels(name); /* For 4035 5.3.2 check */ > -+ > -=C2=A0=C2=A0=C2=A0/* Sort RRset records into canonical order.=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Note that at this point keyname and da= emon->workspacename > buffs are > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unused, and used as workspace by the s= ort. */ > -@@ -828,44 +879,16 @@ static int validate_rrset(time_t now, struct > dns_header *header, size_t plen, in > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0algo =3D *p++; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0labels =3D *p++; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETLONG(orig_ttl, p); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETLONG(sig_expiration, p); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETLONG(sig_inception, p); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 8; /* sig_expiration, sig_ince= ption already checked */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(key_tag, p); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!extract_name(header, plen, = &p, keyname, 1, 0)) > -=C2=A0 return STAT_BOGUS; > -=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* RFC 4035 5.3.1 says that the Signe= r's Name field MUST > equal > -- =C2=A0the name of the zone containing the RRset. We can't tell > that > -- =C2=A0for certain, but we can check that=C2=A0=C2=A0the RRset name is > equal to > -- =C2=A0or encloses the signers name, which should be enough to > stop=C2=A0 > -- =C2=A0an attacker using signatures made with the key of an > unrelated=C2=A0 > -- =C2=A0zone he controls. Note that the root key is always > allowed. */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (*keyname !=3D 0) > -- { > -- =C2=A0=C2=A0int failed =3D 0; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0for (name_start =3D name; !hostname_isequal(name_start, > keyname); ) > -- =C2=A0=C2=A0=C2=A0=C2=A0if ((name_start =3D strchr(name_start, '.'))) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0name_start++; /* chop a label off an= d try again */ > -- =C2=A0=C2=A0=C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- failed =3D 1; > -- break; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -- > -- =C2=A0=C2=A0/* Bad sig, try another */ > -- =C2=A0=C2=A0if (failed) > -- =C2=A0=C2=A0=C2=A0=C2=A0continue; > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Other 5.3.1 checks */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!check_date_range(sig_inception, = sig_expiration) || > -- =C2=A0=C2=A0labels > name_labels || > -- =C2=A0=C2=A0!(hash =3D hash_find(algo_digest_name(algo))) || > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(hash =3D hash_find(algo_digest_= name(algo))) || > -=C2=A0 =C2=A0=C2=A0!hash_init(hash, &ctx, &digest)) > -=C2=A0 continue; > --=09 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* OK, we have the signature rec= ord, see if the relevant > DNSKEY is in the cache. */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!key && !(crecp =3D cache_fi= nd_by_name(NULL, keyname, now, > F_DNSKEY))) > -=C2=A0 return STAT_NEED_KEY; > -@@ -971,10 +994,11 @@ static int validate_rrset(time_t now, struct > dns_header *header, size_t plen, in > - /* The DNS packet is expected to contain the answer to a DNSKEY > query. > -=C2=A0=C2=A0=C2=A0=C2=A0Put all DNSKEYs in the answer which are valid into= the cache. > -=C2=A0=C2=A0=C2=A0=C2=A0return codes: > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0STAT_SECURE=C2=A0= =C2=A0=C2=A0At least one valid DNSKEY found and in > cache. > -- =C2=A0STAT_BOGUS=C2=A0=C2=A0=C2=A0=C2=A0No DNSKEYs found, which=C2=A0=C2= =A0can be validated > with DS, > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0or self-sign for DNSKEY RRset is not valid, > bad packet. > -- =C2=A0STAT_NEED_DS=C2=A0=C2=A0DS records to validate a key not found, na= me > in keyname=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0STAT_OK=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Done, key(s) in cache. > -+ =C2=A0STAT_BOGUS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0No DNSKE= Ys found, which=C2=A0=C2=A0can be > validated with DS, > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0or self-sign for DNSKEY RRset is not > valid, bad packet. > -+ =C2=A0STAT_NEED_DS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0DS records to vali= date a key not found, > name in keyname=C2=A0 > -+ =C2=A0STAT_NEED_DNSKEY=C2=A0=C2=A0DNSKEY records to validate a key not > found, name in keyname=C2=A0 > - */ > - int dnssec_validate_by_ds(time_t now, struct dns_header *header, > size_t plen, char *name, char *keyname, int class) > - { > -@@ -1001,23 +1025,6 @@ int dnssec_validate_by_ds(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_NEED_DS; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0/* If we've cached that DS provably doesn't exist, result mus= t be > INSECURE */ > --=C2=A0=C2=A0if (crecp->flags & F_NEG) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE_DS; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0/* 4035 5.2=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0If the validator does not support any of th= e algorithms listed > in an > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0authenticated DS RRset, then the resolver h= as no supported > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0authentication path leading from the parent= to the child.=C2=A0=C2=A0The > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0resolver should treat this case as it would= the case of an > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0authenticated NSEC RRset proving that no DS= RRset exists,=C2=A0=C2=A0*/ > --=C2=A0=C2=A0for (recp1 =3D crecp; recp1; recp1 =3D cache_find_by_name(rec= p1, > name, now, F_DS)) > --=C2=A0=C2=A0=C2=A0=C2=A0if (hash_find(ds_digest_name(recp1->addr.ds.diges= t))) > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0break; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0if (!recp1) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE_DS; > -- > -=C2=A0=C2=A0=C2=A0/* NOTE, we need to find ONE DNSKEY which matches the DS= */ > -=C2=A0=C2=A0=C2=A0for (valid =3D 0, j =3D ntohs(header->ancount); j !=3D 0= && !valid; j > --)=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -@@ -1070,7 +1077,8 @@ int dnssec_validate_by_ds(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0void *ctx; > -=C2=A0 =C2=A0=C2=A0unsigned char *digest, *ds_digest; > -=C2=A0 =C2=A0=C2=A0const struct nettle_hash *hash; > -- =C2=A0=C2=A0 > -+ =C2=A0=C2=A0int sigcnt, rrcnt; > -+ > -=C2=A0 =C2=A0=C2=A0if (recp1->addr.ds.algo =3D=3D algo &&=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0recp1->addr.ds.keytag =3D=3D ke= ytag && > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0recp1->uid =3D=3D (unsigned int= )class && > -@@ -1088,10 +1096,14 @@ int dnssec_validate_by_ds(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0from_wire(name); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (recp1->addr.ds.keylen =3D=3D (in= t)hash->digest_size > && > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(recp1->flags & F_NEG) && > -+ =C2=A0=C2=A0recp1->addr.ds.keylen =3D=3D (int)hash->digest_size > && > -=C2=A0 =C2=A0=C2=A0(ds_digest =3D blockdata_retrieve(recp1- > >addr.key.keydata, recp1->addr.ds.keylen, NULL)) && > -=C2=A0 =C2=A0=C2=A0memcmp(ds_digest, digest, recp1->addr.ds.keylen) > =3D=3D 0 && > -- =C2=A0=C2=A0validate_rrset(now, header, plen, class, > T_DNSKEY, name, keyname, NULL, key, rdlen - 4, algo, keytag) =3D=3D > STAT_SECURE) > -+ =C2=A0=C2=A0explore_rrset(header, plen, class, T_DNSKEY, > name, keyname, &sigcnt, &rrcnt) && > -+ =C2=A0=C2=A0sigcnt !=3D 0 && rrcnt !=3D 0 && > -+ =C2=A0=C2=A0validate_rrset(now, header, plen, class, > T_DNSKEY, sigcnt, rrcnt, name, keyname,=C2=A0 > -+ =C2=A0NULL, key, rdlen - 4, algo, > keytag) =3D=3D STAT_SECURE) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0valid =3D 1; > -=C2=A0 =C2=A0=C2=A0break; > -@@ -1112,7 +1124,7 @@ int dnssec_validate_by_ds(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0/* Ensure we have type, class=C2=A0=C2=A0TTL and length= */ > -=C2=A0 =C2=A0=C2=A0if (!(rc =3D extract_name(header, plen, &p, name, 0, 10= ))) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; /* bad packet */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0GETSHORT(qtype, p);=C2=A0 > -=C2=A0 =C2=A0=C2=A0GETSHORT(qclass, p); > -@@ -1198,7 +1210,7 @@ int dnssec_validate_by_ds(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* commit cache insert. */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0cache_end_insert(); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_SECURE; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_OK; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > -=C2=A0=C2=A0=C2=A0log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DNS= KEY"); > -@@ -1207,12 +1219,14 @@ int dnssec_validate_by_ds(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 > - /* The DNS packet is expected to contain the answer to a DS query > -=C2=A0=C2=A0=C2=A0=C2=A0Put all DSs in the answer which are valid into the= cache. > -+=C2=A0=C2=A0=C2=A0Also handles replies which prove that there's no DS at = this > location,=C2=A0 > -+=C2=A0=C2=A0=C2=A0either because the zone is unsigned or this isn't a zon= e cut. > These are > -+=C2=A0=C2=A0=C2=A0cached too. > -=C2=A0=C2=A0=C2=A0=C2=A0return codes: > --=C2=A0=C2=A0=C2=A0STAT_SECURE=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0At least= one valid DS found and in cache. > --=C2=A0=C2=A0=C2=A0STAT_NO_DS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0It'= s proved there's no DS here. > --=C2=A0=C2=A0=C2=A0STAT_NO_NS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0It'= s proved there's no DS _or_ NS here. > -+=C2=A0=C2=A0=C2=A0STAT_OK=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0At least one valid DS found and in cache. > -=C2=A0=C2=A0=C2=A0=C2=A0STAT_BOGUS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0no DS in reply or not signed, fails validation, > bad packet. > -=C2=A0=C2=A0=C2=A0=C2=A0STAT_NEED_KEY=C2=A0=C2=A0=C2=A0=C2=A0DNSKEY record= s to validate a DS not found, name > in keyname > -+=C2=A0=C2=A0=C2=A0STAT_NEED_DS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0DS record nee= ded. > - */ > -=C2=A0 > - int dnssec_validate_ds(time_t now, struct dns_header *header, > size_t plen, char *name, char *keyname, int class) > -@@ -1230,7 +1244,7 @@ int dnssec_validate_ds(time_t now, struct > dns_header *header, size_t plen, char > -=C2=A0=C2=A0=C2=A0if (qtype !=3D T_DS || qclass !=3D class) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0val =3D STAT_BOGUS; > -=C2=A0=C2=A0=C2=A0else > --=C2=A0=C2=A0=C2=A0=C2=A0val =3D dnssec_validate_reply(now, header, plen, = name, keyname, > NULL, &neganswer, &nons); > -+=C2=A0=C2=A0=C2=A0=C2=A0val =3D dnssec_validate_reply(now, header, plen, = name, keyname, > NULL, 0, &neganswer, &nons); > -=C2=A0=C2=A0=C2=A0/* Note dnssec_validate_reply() will have cached positiv= e answers > */ > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0if (val =3D=3D STAT_INSECURE) > -@@ -1242,22 +1256,21 @@ int dnssec_validate_ds(time_t now, struct > dns_header *header, size_t plen, char > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0if (!(p =3D skip_section(p, ntohs(header->ancount), head= er, plen))) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0val =3D STAT_BOGUS; > --=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0/* If we return STAT_NO_SIG, name contains the name of the DS > query */ > --=C2=A0=C2=A0if (val =3D=3D STAT_NO_SIG) > --=C2=A0=C2=A0=C2=A0=C2=A0return val; > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0/* If the key needed to validate the DS is on the same d= omain as > the DS, we'll > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0loop getting nowhere. Stop that now. T= his can happen of the DS > answer comes > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0from the DS's zone, and not the parent= zone. */ > --=C2=A0=C2=A0if (val =3D=3D STAT_BOGUS ||=C2=A0=C2=A0(val =3D=3D STAT_NEED= _KEY && > hostname_isequal(name, keyname))) > -+=C2=A0=C2=A0if (val =3D=3D STAT_BOGUS || (val =3D=3D STAT_NEED_KEY && > hostname_isequal(name, keyname))) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0log_query(F_NOEXTRA | F_UPSTREAM= , name, NULL, "BOGUS DS"); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0if (val !=3D STAT_SECURE) > -+=C2=A0=C2=A0=C2=A0=C2=A0return val; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0/* By here, the answer is proved secure, and a positive = answer > has been cached. */ > --=C2=A0=C2=A0if (val =3D=3D STAT_SECURE && neganswer) > -+=C2=A0=C2=A0if (neganswer) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int rdlen, flags =3D F_FORWARD |= F_DS | F_NEG | F_DNSSECOK; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned long ttl, minttl =3D UL= ONG_MAX; > -@@ -1317,15 +1330,14 @@ int dnssec_validate_ds(time_t now, struct > dns_header *header, size_t plen, char > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0cache_end_insert();=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no > delegation" : "no DS"); > -+ =C2=A0=C2=A0log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "no DS"); > -=C2=A0 } > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return nons ? STAT_NO_NS : STAT_NO_DS= ;=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > --=C2=A0=C2=A0return val; > -+=C2=A0=C2=A0return STAT_OK; > - } > -=C2=A0 > -+ > - /* 4034 6.1 */ > - static int hostname_cmp(const char *a, const char *b) > - { > -@@ -1452,7 +1464,7 @@ static int prove_non_existence_nsec(struct > dns_header *header, size_t plen, unsi > -=C2=A0=C2=A0=C2=A0int mask =3D 0x80 >> (type & 0x07); > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if (nons) > --=C2=A0=C2=A0=C2=A0=C2=A0*nons =3D 0; > -+=C2=A0=C2=A0=C2=A0=C2=A0*nons =3D 1; > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0/* Find NSEC record that proves name doesn't exist */ > -=C2=A0=C2=A0=C2=A0for (i =3D 0; i < nsec_count; i++) > -@@ -1480,9 +1492,22 @@ static int prove_non_existence_nsec(struct > dns_header *header, size_t plen, unsi > -=C2=A0 =C2=A0=C2=A0/* rdlen is now length of type map, and p points to it = */ > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0/* If we can prove that there's no NS record, return th= at > information. */ > -- =C2=A0=C2=A0if (nons && rdlen >=3D 2 && p[0] =3D=3D 0 && (p[2] & (0x80 >> > T_NS)) =3D=3D 0) > -- =C2=A0=C2=A0=C2=A0=C2=A0*nons =3D 1; > -+ =C2=A0=C2=A0if (nons && rdlen >=3D 2 && p[0] =3D=3D 0 && (p[2] & (0x80 >> > T_NS)) !=3D 0) > -+ =C2=A0=C2=A0=C2=A0=C2=A0*nons =3D 0; > -=C2=A0 =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (rdlen >=3D 2 && p[0] =3D=3D 0) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* A CNAME answer would also be vali= d, so if there's > a CNAME is should=C2=A0 > -+ =C2=A0have been returned. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((p[2] & (0x80 >> T_CNAME)) !=3D = 0) > -+ return STAT_BOGUS; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* If the SOA bit is set for a DS re= cord, then we > have the > -+ =C2=A0DS from the wrong side of the delegation. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (type =3D=3D T_DS && (p[2] & (0x8= 0 >> T_SOA)) !=3D 0) > -+ return STAT_BOGUS; > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ > -=C2=A0 =C2=A0=C2=A0while (rdlen >=3D 2) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!CHECK_LEN(header, p, plen,= rdlen)) > -@@ -1586,7 +1611,7 @@ static int base32_decode(char *in, unsigned > char *out) > - static int check_nsec3_coverage(struct dns_header *header, size_t > plen, int digest_len, unsigned char *digest, int type, > -=C2=A0 char *workspace1, char *workspace2, > unsigned char **nsecs, int nsec_count, int *nons) > - { > --=C2=A0=C2=A0int i, hash_len, salt_len, base32_len, rdlen; > -+=C2=A0=C2=A0int i, hash_len, salt_len, base32_len, rdlen, flags; > -=C2=A0=C2=A0=C2=A0unsigned char *p, *psave; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0for (i =3D 0; i < nsec_count; i++) > -@@ -1599,7 +1624,9 @@ static int check_nsec3_coverage(struct > dns_header *header, size_t plen, int dige > -=C2=A0 p +=3D 8; /* class, type, TTL */ > -=C2=A0 GETSHORT(rdlen, p); > -=C2=A0 psave =3D p; > -- p +=3D 4; /* algo, flags, iterations */ > -+ p++; /* algo */ > -+ flags =3D *p++; /* flags */ > -+ p +=3D 2; /* iterations */ > -=C2=A0 salt_len =3D *p++; /* salt_len */ > -=C2=A0 p +=3D salt_len; /* salt */ > -=C2=A0 hash_len =3D *p++; /* p now points to next hashed name */ > -@@ -1626,16 +1653,29 @@ static int check_nsec3_coverage(struct > dns_header *header, size_t plen, int dige > -=C2=A0 =C2=A0=C2=A0return 0; > -=C2=A0 =09 > -=C2=A0 /* If we can prove that there's no NS record, > return that information. */ > -- if (nons && rdlen >=3D 2 && p[0] =3D=3D 0 && (p[2] & > (0x80 >> T_NS)) =3D=3D 0) > -- =C2=A0=C2=A0*nons =3D 1; > -+ if (nons && rdlen >=3D 2 && p[0] =3D=3D 0 && (p[2] & > (0x80 >> T_NS)) !=3D 0) > -+ =C2=A0=C2=A0*nons =3D 0; > -=C2=A0 =09 > -+ if (rdlen >=3D 2 && p[0] =3D=3D 0) > -+ =C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0/* A CNAME answer would also be valid, so if > there's a CNAME is should=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0have been returned. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0if ((p[2] & (0x80 >> T_CNAME)) !=3D 0) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+ =C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0/* If the SOA bit is set for a DS record, then > we have the > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0DS from the wrong side of the= delegation. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0if (type =3D=3D T_DS && (p[2] & (0x80 >> T_SOA)= ) !=3D > 0) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+ =C2=A0=C2=A0} > -+ > -=C2=A0 while (rdlen >=3D 2) > -=C2=A0 =C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0if (p[0] =3D=3D type >> 8) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 /* Does the NSEC3 say our type exists? */ > -=C2=A0 if (offset < p[1] && (p[offset+2] & mask) > !=3D 0) > -- =C2=A0=C2=A0return STAT_BOGUS; > -+ =C2=A0=C2=A0return 0; > -=C2=A0 =09 > -=C2=A0 break; /* finshed checking */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -@@ -1643,7 +1683,7 @@ static int check_nsec3_coverage(struct > dns_header *header, size_t plen, int dige > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0rdlen -=3D p[1]; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0p +=3D=C2=A0=C2=A0p[1]; > -=C2=A0 =C2=A0=C2=A0} > -- > -+ =09 > -=C2=A0 return 1; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0else if (rc < 0) > -@@ -1651,16 +1691,27 @@ static int check_nsec3_coverage(struct > dns_header *header, size_t plen, int dige > -=C2=A0 /* Normal case, hash falls between NSEC3 name-hash > and next domain name-hash, > -=C2=A0 =C2=A0=C2=A0=C2=A0wrap around case, name-hash falls between NSEC3 > name-hash and end */ > -=C2=A0 if (memcmp(p, digest, digest_len) >=3D 0 || > memcmp(workspace2, p, digest_len) >=3D 0) > -- =C2=A0=C2=A0return 1; > -+ =C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0if ((flags & 0x01) && nons) /* opt out */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*nons =3D 0; > -+ > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 1; > -+ =C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0else=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 /* wrap around case, name falls between start and > next domain name */ > -=C2=A0 if (memcmp(workspace2, p, digest_len) >=3D 0 && > memcmp(p, digest, digest_len) >=3D 0) > -- =C2=A0=C2=A0return 1; > -+ =C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0if ((flags & 0x01) && nons) /* opt out */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*nons =3D 0; > -+ > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 1; > -+ =C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -+ > -=C2=A0=C2=A0=C2=A0return 0; > - } > -=C2=A0 > -@@ -1673,7 +1724,7 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0=C2=A0=C2=A0char *closest_encloser, *next_closest, *wildcard; > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0if (nons) > --=C2=A0=C2=A0=C2=A0=C2=A0*nons =3D 0; > -+=C2=A0=C2=A0=C2=A0=C2=A0*nons =3D 1; > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0/* Look though the NSEC3 records to find the first one w= ith=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0an algorithm we support (currently onl= y algo =3D=3D 1). > -@@ -1813,16 +1864,81 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0return STAT_SECURE; > - } > --=C2=A0=C2=A0=C2=A0=C2=A0 > --/* Validate all the RRsets in the answer and authority sections of > the reply (4035:3.2.3) */ > --/* Returns are the same as validate_rrset, plus the class if the > missing key is in *class */ > -+ > -+/* Check signing status of name. > -+=C2=A0=C2=A0=C2=A0returns: > -+=C2=A0=C2=A0=C2=A0STAT_SECURE zone is signed. > -+=C2=A0=C2=A0=C2=A0STAT_INSECURE zone proved unsigned. > -+=C2=A0=C2=A0=C2=A0STAT_NEED_DS require DS record of name returned in keyn= ame. > -+=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0name returned unaltered. > -+*/ > -+static int zone_status(char *name, int class, char *keyname, time_t > now) > -+{ > -+=C2=A0=C2=A0int name_start =3D strlen(name); > -+=C2=A0=C2=A0struct crec *crecp; > -+=C2=A0=C2=A0char *p; > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0while (1) > -+=C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0strcpy(keyname, &name[name_start]); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(crecp =3D cache_find_by_name(NU= LL, keyname, now, F_DS))) > -+ return STAT_NEED_DS; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -+ do=C2=A0 > -+ =C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0if (crecp->uid =3D=3D (unsigned int)class) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -+ /* F_DNSSECOK misused in DS cache records to non- > existance of NS record. > -+ =C2=A0=C2=A0=C2=A0F_NEG && !F_DNSSECOK implies that we've proved > there's no DS record here, > -+ =C2=A0=C2=A0=C2=A0but that's because there's no NS record either, > ie this isn't the start > -+ =C2=A0=C2=A0=C2=A0of a zone. We only prove that the DNS tree below > a node is unsigned when > -+ =C2=A0=C2=A0=C2=A0we prove that we're at a zone cut AND there's no > DS record. > -+ */ =C2=A0=C2=A0 > -+ if (crecp->flags & F_NEG) > -+ =C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0if (crecp->flags & F_DNSSECOK) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; /* proved no = DS here */ > -+ =C2=A0=C2=A0} > -+ else if (!ds_digest_name(crecp->addr.ds.digest) || > !algo_digest_name(crecp->addr.ds.algo)) > -+ =C2=A0=C2=A0return STAT_INSECURE; /* algo we can't use - > insecure */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0} > -+ while ((crecp =3D cache_find_by_name(crecp, keyname, now, > F_DS))); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (name_start =3D=3D 0) > -+ break; > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (p =3D &name[name_start-2]; (*p != =3D '.') && (p !=3D name); p > --); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (p !=3D name) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p++; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0name_start =3D p - name; > -+=C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -+ > -+=C2=A0=C2=A0return STAT_SECURE; > -+} > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+/* Validate all the RRsets in the answer and authority sections of > the reply (4035:3.2.3)=C2=A0 > -+=C2=A0=C2=A0=C2=A0Return code: > -+=C2=A0=C2=A0=C2=A0STAT_SECURE=C2=A0=C2=A0=C2=A0if it validates. > -+=C2=A0=C2=A0=C2=A0STAT_INSECURE at least one RRset not validated, because= in > unsigned zone. > -+=C2=A0=C2=A0=C2=A0STAT_BOGUS=C2=A0=C2=A0=C2=A0=C2=A0signature is wrong, b= ad packet, no validation > where there should be. > -+=C2=A0=C2=A0=C2=A0STAT_NEED_KEY need DNSKEY to complete validation (name = is > returned in keyname, class in *class) > -+=C2=A0=C2=A0=C2=A0STAT_NEED_DS=C2=A0=C2=A0need DS to complete validation = (name is returned > in keyname)=C2=A0 > -+*/ > - int dnssec_validate_reply(time_t now, struct dns_header *header, > size_t plen, char *name, char *keyname,=C2=A0 > -- =C2=A0=C2=A0int *class, int *neganswer, int *nons) > -+ =C2=A0=C2=A0int *class, int check_unsigned, int > *neganswer, int *nons) > - { > --=C2=A0=C2=A0unsigned char *ans_start, *qname, *p1, *p2, **nsecs; > --=C2=A0=C2=A0int type1, class1, rdlen1, type2, class2, rdlen2, qclass, qty= pe; > --=C2=A0=C2=A0int i, j, rc, nsec_count, cname_count =3D CNAME_CHAIN; > --=C2=A0=C2=A0int nsec_type =3D 0, have_answer =3D 0; > -+=C2=A0=C2=A0static unsigned char **targets =3D NULL; > -+=C2=A0=C2=A0static int target_sz =3D 0; > -+ > -+=C2=A0=C2=A0unsigned char *ans_start, *p1, *p2, **nsecs; > -+=C2=A0=C2=A0int type1, class1, rdlen1, type2, class2, rdlen2, qclass, qty= pe, > targetidx; > -+=C2=A0=C2=A0int i, j, rc, nsec_count; > -+=C2=A0=C2=A0int nsec_type; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if (neganswer) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*neganswer =3D 0; > -@@ -1833,70 +1949,51 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0=C2=A0=C2=A0if (RCODE(header) !=3D NXDOMAIN && RCODE(header) !=3D NO= ERROR) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; > -=C2=A0 > --=C2=A0=C2=A0qname =3D p1 =3D (unsigned char *)(header+1); > -+=C2=A0=C2=A0p1 =3D (unsigned char *)(header+1); > -=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0/* Find all the targets we're looking for answers to. > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0The zeroth array element is for the query, = subsequent ones > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for CNAME targets, unless the query is for = a CNAME. */ > -+ > -+=C2=A0=C2=A0if (!expand_workspace(&targets, &target_sz, 0)) > -+=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0targets[0] =3D p1; > -+=C2=A0=C2=A0targetidx =3D 1; > -+=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0if (!extract_name(header, plen, &p1, name, 1, 4)) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -- > -+=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0GETSHORT(qtype, p1); > -=C2=A0=C2=A0=C2=A0GETSHORT(qclass, p1); > -=C2=A0=C2=A0=C2=A0ans_start =3D p1; > -- > --=C2=A0=C2=A0if (qtype =3D=3D T_ANY) > --=C2=A0=C2=A0=C2=A0=C2=A0have_answer =3D 1; > -=C2=A0=C2=A0 > --=C2=A0=C2=A0/* Can't validate an RRISG query */ > -+=C2=A0=C2=A0/* Can't validate an RRSIG query */ > -=C2=A0=C2=A0=C2=A0if (qtype =3D=3D T_RRSIG) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; > --=C2=A0 > -- cname_loop: > --=C2=A0=C2=A0for (j =3D ntohs(header->ancount); j !=3D 0; j--)=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* leave pointer to missing name in q= name */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(rc =3D extract_name(header, ple= n, &p1, name, 0, 10))) > -- return STAT_BOGUS; /* bad packet */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(type2, p1);=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(class2, p1); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p1 +=3D 4; /* TTL */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(rdlen2, p1); > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rc =3D=3D 1 && qclass =3D=3D clas= s2) > -- { > -- =C2=A0=C2=A0/* Do we have an answer for the question? */ > -- =C2=A0=C2=A0if (type2 =3D=3D qtype) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0have_answer =3D 1; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0break; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else if (type2 =3D=3D T_CNAME) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0qname =3D p1; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* looped CNAMES */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!cname_count-- || !extract_name(= header, plen, > &p1, name, 1, 0)) > -- return STAT_BOGUS; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p1 =3D ans_start; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0goto cname_loop; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- }=C2=A0 > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!ADD_RDLEN(header, p1, plen, rdle= n2)) > -- return STAT_BOGUS; > --=C2=A0=C2=A0=C2=A0=C2=A0} > --=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0if (neganswer && !have_answer) > --=C2=A0=C2=A0=C2=A0=C2=A0*neganswer =3D 1; > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0/* No data, therefore no sigs */ > --=C2=A0=C2=A0if (ntohs(header->ancount) + ntohs(header->nscount) =3D=3D 0) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*keyname =3D 0; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_NO_SIG; > --=C2=A0=C2=A0=C2=A0=C2=A0} > -- > -+=C2=A0=C2=A0if (qtype !=3D T_CNAME) > -+=C2=A0=C2=A0=C2=A0=C2=A0for (j =3D ntohs(header->ancount); j !=3D 0; j--)= =C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -+ if (!(p1 =3D skip_name(p1, header, plen, 10))) > -+ =C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -+=09 > -+ GETSHORT(type2, p1);=C2=A0 > -+ p1 +=3D 6; /* class, TTL */ > -+ GETSHORT(rdlen2, p1);=C2=A0=C2=A0 > -+=09 > -+ if (type2 =3D=3D T_CNAME) > -+ =C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0if (!expand_workspace(&targets, &target_sz, targ= etidx)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -+ =C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0targets[targetidx++] =3D p1; /* pointer to targe= t name */ > -+ =C2=A0=C2=A0} > -+=09 > -+ if (!ADD_RDLEN(header, p1, plen, rdlen2)) > -+ =C2=A0=C2=A0return STAT_BOGUS; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0for (p1 =3D ans_start, i =3D 0; i < ntohs(header->ancoun= t) + > ntohs(header->nscount); i++) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!extract_name(header, plen, = &p1, name, 1, 10)) > -@@ -1931,7 +2028,7 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0/* Not done, validate now */ > -=C2=A0 =C2=A0=C2=A0if (j =3D=3D i) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int ttl, keytag, algo, digest, type_= covered; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int ttl, keytag, algo, digest, type_= covered, sigcnt, > rrcnt; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *psave; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct all_addr a; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct blockdata *key; > -@@ -1939,143 +2036,186 @@ int dnssec_validate_reply(time_t now, > struct dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0char *wildname; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int have_wildcard =3D 0; > -=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0rc =3D validate_rrset(now, header, p= len, class1, type1, > name, keyname, &wildname, NULL, 0, 0, 0); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rc =3D=3D STAT_SECURE_WILDCARD) > -- { > -- =C2=A0=C2=A0have_wildcard =3D 1; > -- > -- =C2=A0=C2=A0/* An attacker replay a wildcard answer with a > different > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0answer and overlay a genuine RR. To prove= this > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0hasn't happened, the answer must prove th= at > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0the gennuine record doesn't exist. Check = that > here. */ > -- =C2=A0=C2=A0if (!nsec_type && !(nsec_type =3D > find_nsec_records(header, plen, &nsecs, &nsec_count, class1))) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* No NSECs or bad packet */ > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (nsec_type =3D=3D T_NSEC) > -- =C2=A0=C2=A0=C2=A0=C2=A0rc =3D prove_non_existence_nsec(header, plen, > nsecs, nsec_count, daemon->workspacename, keyname, name, type1, > NULL); > -- =C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0rc =3D prove_non_existence_nsec3(header, plen, > nsecs, nsec_count, daemon->workspacename,=C2=A0 > -- =C2=A0=C2=A0=C2=A0keyname, name, > type1, wildname, NULL); > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (rc !=3D STAT_SECURE) > -- =C2=A0=C2=A0=C2=A0=C2=A0return rc; > -- }=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (rc !=3D STAT_SECURE) > -- { > -- =C2=A0=C2=A0if (class) > -- =C2=A0=C2=A0=C2=A0=C2=A0*class =3D class1; /* Class for DS or DNSKEY */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!explore_rrset(header, plen, cla= ss1, type1, name, > keyname, &sigcnt, &rrcnt)) > -+ return STAT_BOGUS; > -=C2=A0 > -- =C2=A0=C2=A0if (rc =3D=3D STAT_NO_SIG) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* No signatures for RRset. We can b= e configured to > assume this is OK and return a INSECURE result. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (sigcnt =3D=3D 0) > -+ { > -+ =C2=A0=C2=A0if (check_unsigned) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* If we dropped off the end of a C= NAME > chain, return > -- =C2=A0STAT_NO_SIG and the last name is keyname. > This is used for proving non-existence > -- =C2=A0if DS records in CNAME chains. */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (cname_count =3D=3D CNAME_CHAIN = || i < > ntohs(header->ancount))=C2=A0 > -- /* No CNAME chain, or no sig in answer > section, return empty name. */ > -- *keyname =3D 0; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (!extract_name(header, plen= , &qname, > keyname, 1, 0)) > -- return STAT_BOGUS; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0rc =3D zone_status(name, class1, ke= yname, now); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rc =3D=3D STAT_SECURE) > -+ rc =3D STAT_BOGUS; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (class) > -+ =C2=A0*class =3D class1; /* Class for NEED_DS or > NEED_DNSKEY */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > --=C2=A0 > -+ =C2=A0=C2=A0else=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0rc =3D STAT_INSECURE;=C2=A0 > -+ =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0return rc; > -=C2=A0 } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Cache RRsigs in answer section, a= nd if we just > validated a DS RRset, cache it */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0cache_start_insert(); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* explore_rrset() gives us key name= from sigs in > keyname. > -+ =C2=A0Can't overwrite name here. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0strcpy(daemon->workspacename, keynam= e); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0rc =3D zone_status(daemon->workspace= name, class1, > keyname, now); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rc !=3D STAT_SECURE) > -+ { > -+ =C2=A0=C2=A0/* Zone is insecure, don't need to validate RRset > */ > -+ =C2=A0=C2=A0if (class) > -+ =C2=A0=C2=A0=C2=A0=C2=A0*class =3D class1; /* Class for NEED_DS or > NEED_DNSKEY */ > -+ =C2=A0=C2=A0return rc; > -+ }=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0rc =3D validate_rrset(now, header, p= len, class1, type1, > sigcnt, rrcnt, name, keyname, &wildname, NULL, 0, 0, 0); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (p2 =3D ans_start, j =3D 0; j < = ntohs(header- > >ancount); j++) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rc =3D=3D STAT_BOGUS || rc =3D= =3D STAT_NEED_KEY || rc =3D=3D > STAT_NEED_DS) > -=C2=A0 { > -- =C2=A0=C2=A0if (!(rc =3D extract_name(header, plen, &p2, name, > 0, 10))) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -+ =C2=A0=C2=A0if (class) > -+ =C2=A0=C2=A0=C2=A0=C2=A0*class =3D class1; /* Class for DS or DNSKEY */ > -+ =C2=A0=C2=A0return rc; > -+ }=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else=C2=A0 > -+ { > -+ =C2=A0=C2=A0/* rc is now STAT_SECURE or STAT_SECURE_WILDCARD > */ > -+ =C2=A0 > -+ =C2=A0=C2=A0/* Note if we've validated either the answer to > the question > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0or the target of a CNAME. Any not noted w= ill > need NSEC or > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0to be in unsigned space. */ > -+ > -+ =C2=A0=C2=A0for (j =3D 0; j <targetidx; j++) > -+ =C2=A0=C2=A0=C2=A0=C2=A0if ((p2 =3D targets[j])) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -+ if (!(rc =3D extract_name(header, plen, &p2, > name, 0, 10))) > -+ =C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -+ =09 > -+ if (class1 =3D=3D qclass && rc =3D=3D 1 && (type1 > =3D=3D T_CNAME || type1 =3D=3D qtype || qtype =3D=3D T_ANY )) > -+ =C2=A0=C2=A0targets[j] =3D NULL; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (rc =3D=3D STAT_SECURE_WILDCARD) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0have_wildcard =3D 1; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0GETSHORT(type2, p2); > -- =C2=A0=C2=A0GETSHORT(class2, p2); > -- =C2=A0=C2=A0GETLONG(ttl, p2); > -- =C2=A0=C2=A0GETSHORT(rdlen2, p2); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0if (!CHECK_LEN(header, p2, plen, rdlen2)) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (class2 =3D=3D class1 && rc =3D=3D 1) > -- =C2=A0=C2=A0=C2=A0=C2=A0{=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0psave =3D p2; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* An attacker replay a wildcard an= swer with > a different > -+ =C2=A0answer and overlay a genuine RR. To prove > this > -+ =C2=A0hasn't happened, the answer must prove > that > -+ =C2=A0the gennuine record doesn't exist. Check > that here. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(nsec_type =3D find_nsec_recor= ds(header, > plen, &nsecs, &nsec_count, class1))) > -+ return STAT_BOGUS; /* No NSECs or bad > packet */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Note that we may not yet have va= lidated > the NSEC/NSEC3 RRsets. Since the check > -+ =C2=A0below returns either SECURE or BOGUS, > that's not a problem. If the RRsets later fail > -+ =C2=A0we'll return BOGUS then. */ > -=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (type1 =3D=3D T_DS && type2 =3D= =3D T_DS) > -- { > -- =C2=A0=C2=A0if (rdlen2 < 4) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0GETSHORT(keytag, p2); > -- =C2=A0=C2=A0algo =3D *p2++; > -- =C2=A0=C2=A0digest =3D *p2++; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0/* Cache needs to known class for DNSSEC > stuff */ > -- =C2=A0=C2=A0a.addr.dnssec.class =3D class2; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if ((key =3D blockdata_alloc((char*)p2, > rdlen2 - 4))) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(crecp =3D cache_insert(name,= &a, > now, ttl, F_FORWARD | F_DS | F_DNSSECOK))) > -- blockdata_free(key); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -- { > -- =C2=A0=C2=A0a.addr.keytag =3D keytag; > -- =C2=A0=C2=A0log_query(F_NOEXTRA | F_KEYTAG | > F_UPSTREAM, name, &a, "DS keytag %u"); > -- =C2=A0=C2=A0crecp->addr.ds.digest =3D digest; > -- =C2=A0=C2=A0crecp->addr.ds.keydata =3D key; > -- =C2=A0=C2=A0crecp->addr.ds.algo =3D algo; > -- =C2=A0=C2=A0crecp->addr.ds.keytag =3D keytag; > -- =C2=A0=C2=A0crecp->addr.ds.keylen =3D rdlen2 - > 4;=C2=A0 > -- }=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (type2 =3D=3D T_RRSIG) > -- { > -- =C2=A0=C2=A0if (rdlen2 < 18) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (nsec_type =3D=3D T_NSEC) > -+ rc =3D prove_non_existence_nsec(header, plen, > nsecs, nsec_count, daemon->workspacename, keyname, name, type1, > NULL); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -+ rc =3D prove_non_existence_nsec3(header, > plen, nsecs, nsec_count, daemon->workspacename,=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0keyname, > name, type1, wildname, NULL); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rc =3D=3D STAT_BOGUS) > -+ return rc; > -+ =C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0/* Cache RRsigs in answer section, and if we just > validated a DS RRset, cache it */ > -+ =C2=A0=C2=A0/* Also note if the RRset is the answer to the > question, or the target of a CNAME */ > -+ =C2=A0=C2=A0cache_start_insert(); > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0for (p2 =3D ans_start, j =3D 0; j < ntohs(header- > >ancount); j++) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(rc =3D extract_name(header, p= len, &p2, > name, 0, 10))) > -+ return STAT_BOGUS; /* bad packet */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(type2, p2); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(class2, p2); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETLONG(ttl, p2); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(rdlen2, p2); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!CHECK_LEN(header, p2, plen, rd= len2)) > -+ return STAT_BOGUS; /* bad packet */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (class2 =3D=3D class1 && rc =3D= =3D 1) > -+ {=C2=A0 > -+ =C2=A0=C2=A0psave =3D p2; > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0GETSHORT(type_covered, p2); > -- > -- =C2=A0=C2=A0if (type_covered =3D=3D type1 &&=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(type_covered =3D=3D T_A || type_c= overed > =3D=3D T_AAAA || > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0type_covered =3D=3D T_CNAME = || > type_covered =3D=3D T_DS ||=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0type_covered =3D=3D T_DNSKEY= || > type_covered =3D=3D T_PTR))=C2=A0 > -+ =C2=A0=C2=A0if (type1 =3D=3D T_DS && type2 =3D=3D T_DS) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0a.addr.dnssec.type =3D type_covere= d; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0a.addr.dnssec.class =3D class1; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rdlen2 < 4) > -+ return STAT_BOGUS; /* bad packet */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0algo =3D *p2++; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p2 +=3D 13; /* labels, orig_ttl, > expiration, inception */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(keytag, p2); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0algo =3D *p2++; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0digest =3D *p2++; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Cache needs to known class for > DNSSEC stuff */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0a.addr.dnssec.class =3D class2; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* We don't cache sigs for wildcard > answers, because to reproduce the > -- =C2=A0answer from the cache will require > one or more NSEC/NSEC3 records=C2=A0 > -- =C2=A0which we don't cache. The lack of > the RRSIG ensures that a query for > -- =C2=A0this RRset asking for a secure > answer will always be forwarded. */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!have_wildcard && (key =3D > blockdata_alloc((char*)psave, rdlen2))) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((key =3D blockdata_alloc((char= *)p2, > rdlen2 - 4))) > -=C2=A0 { > -- =C2=A0=C2=A0if (!(crecp =3D cache_insert(name, > &a, now, ttl,=C2=A0=C2=A0F_FORWARD | F_DNSKEY | F_DS))) > -+ =C2=A0=C2=A0if (!(crecp =3D cache_insert(name, > &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK))) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(key); > -=C2=A0 =C2=A0=C2=A0else > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.sig.keydata =3D > key; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.sig.keylen =3D > rdlen2; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.sig.keytag =3D > keytag; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.sig.type_covered > =3D type_covered; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.sig.algo =3D algo; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0a.addr.keytag =3D keytag; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0log_query(F_NOEXTRA | > F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u"); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.digest =3D > digest; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.keydata =3D key; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.algo =3D algo; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.keytag =3D > keytag; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.keylen =3D > rdlen2 - 4;=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -+ } > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0else if (type2 =3D=3D T_RRSIG) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rdlen2 < 18) > -+ return STAT_BOGUS; /* bad packet */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(type_covered, p2); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (type_covered =3D=3D type1 &&= =C2=A0 > -+ =C2=A0=C2=A0(type_covered =3D=3D T_A || > type_covered =3D=3D T_AAAA || > -+ =C2=A0=C2=A0=C2=A0type_covered =3D=3D T_CNAME || > type_covered =3D=3D T_DS ||=C2=A0 > -+ =C2=A0=C2=A0=C2=A0type_covered =3D=3D T_DNSKEY || > type_covered =3D=3D T_PTR))=C2=A0 > -+ { > -+ =C2=A0=C2=A0a.addr.dnssec.type =3D > type_covered; > -+ =C2=A0=C2=A0a.addr.dnssec.class =3D class1; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0algo =3D *p2++; > -+ =C2=A0=C2=A0p2 +=3D 13; /* labels, orig_ttl, > expiration, inception */ > -+ =C2=A0=C2=A0GETSHORT(keytag, p2); > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0/* We don't cache sigs for > wildcard answers, because to reproduce the > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0answer from the cache will > require one or more NSEC/NSEC3 records=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0which we don't cache. The lack > of the RRSIG ensures that a query for > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0this RRset asking for a secure > answer will always be forwarded. */ > -+ =C2=A0=C2=A0if (!have_wildcard && (key =3D > blockdata_alloc((char*)psave, rdlen2))) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(crecp =3D > cache_insert(name, &a, now, ttl,=C2=A0=C2=A0F_FORWARD | F_DNSKEY | F_DS))) > -+ blockdata_free(key); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -+ { > -+ =C2=A0=C2=A0crecp->addr.sig.keydata =3D > key; > -+ =C2=A0=C2=A0crecp->addr.sig.keylen =3D > rdlen2; > -+ =C2=A0=C2=A0crecp->addr.sig.keytag =3D > keytag; > -+ =C2=A0=C2=A0crecp- > >addr.sig.type_covered =3D type_covered; > -+ =C2=A0=C2=A0crecp->addr.sig.algo =3D > algo; > -+ } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0p2 =3D psave; > -=C2=A0 } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p2 =3D psave; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!ADD_RDLEN(header, p2, plen, rd= len2)) > -+ return STAT_BOGUS; /* bad packet */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (!ADD_RDLEN(header, p2, plen, rdlen2)) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -+ =C2=A0=C2=A0cache_end_insert(); > -=C2=A0 } > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0cache_end_insert(); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 } > -=C2=A0 > -@@ -2083,143 +2223,49 @@ int dnssec_validate_reply(time_t now, > struct dns_header *header, size_t plen, ch > -=C2=A0 return STAT_BOGUS; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > --=C2=A0=C2=A0/* OK, all the RRsets validate, now see if we have a NODATA or > NXDOMAIN reply */ > --=C2=A0=C2=A0if (have_answer) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_SECURE; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0/* NXDOMAIN or NODATA reply, prove that (name, class1, type1) > can't exist */ > --=C2=A0=C2=A0/* First marshall the NSEC records, if we've not done it > previously */ > --=C2=A0=C2=A0if (!nsec_type && !(nsec_type =3D find_nsec_records(header, p= len, > &nsecs, &nsec_count, qclass))) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* No NSEC records. If we dropped off= the end of a CNAME > chain, return > -- =C2=A0STAT_NO_SIG and the last name is keyname. This is used for > proving non-existence > -- =C2=A0if DS records in CNAME chains. */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (cname_count =3D=3D CNAME_CHAIN) /= * No CNAME chain, return > empty name. */ > -- *keyname =3D 0; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (!extract_name(header, plen, = &qname, keyname, 1, 0)) > -- return STAT_BOGUS; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_NO_SIG; /* No NSECs, this= is probably a dangling > CNAME pointing into > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0an unsigned zone. Return STAT_NO_SIG > to cause this to be proved. */ > --=C2=A0=C2=A0=C2=A0=C2=A0} > --=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0/* Get name of missing answer */ > --=C2=A0=C2=A0if (!extract_name(header, plen, &qname, name, 1, 0)) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0if (nsec_type =3D=3D T_NSEC) > --=C2=A0=C2=A0=C2=A0=C2=A0return prove_non_existence_nsec(header, plen, nse= cs, > nsec_count, daemon->workspacename, keyname, name, qtype, nons); > --=C2=A0=C2=A0else > --=C2=A0=C2=A0=C2=A0=C2=A0return prove_non_existence_nsec3(header, plen, ns= ecs, > nsec_count, daemon->workspacename, keyname, name, qtype, NULL, nons); > --} > -- > --/* Chase the CNAME chain in the packet until the first record which > _doesn't validate. > --=C2=A0=C2=A0=C2=A0Needed for proving answer in unsigned space. > --=C2=A0=C2=A0=C2=A0Return STAT_NEED_*=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0STAT_BOGUS - = error > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0STAT_INSECURE= - name of first non-secure record in name=C2=A0 > --*/ > --int dnssec_chase_cname(time_t now, struct dns_header *header, > size_t plen, char *name, char *keyname) > --{ > --=C2=A0=C2=A0unsigned char *p =3D (unsigned char *)(header+1); > --=C2=A0=C2=A0int type, class, qclass, rdlen, j, rc; > --=C2=A0=C2=A0int cname_count =3D CNAME_CHAIN; > --=C2=A0=C2=A0char *wildname; > -- > --=C2=A0=C2=A0/* Get question */ > --=C2=A0=C2=A0if (!extract_name(header, plen, &p, name, 1, 4)) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0p +=3D2; /* type */ > --=C2=A0=C2=A0GETSHORT(qclass, p); > -- > --=C2=A0=C2=A0while (1) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (j =3D ntohs(header->ancount); j = !=3D 0; j--)=C2=A0 > -- { > -- =C2=A0=C2=A0if (!(rc =3D extract_name(header, plen, &p, name, 0, 10))) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0GETSHORT(type, p);=C2=A0 > -- =C2=A0=C2=A0GETSHORT(class, p); > -- =C2=A0=C2=A0p +=3D 4; /* TTL */ > -- =C2=A0=C2=A0GETSHORT(rdlen, p); > -- > -- =C2=A0=C2=A0/* Not target, loop */ > -- =C2=A0=C2=A0if (rc =3D=3D 2 || qclass !=3D class) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!ADD_RDLEN(header, p, plen, rdle= n)) > -- return STAT_BOGUS; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0continue; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0/* Got to end of CNAME chain. */ > -- =C2=A0=C2=A0if (type !=3D T_CNAME) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0/* validate CNAME chain, return if insecure or need more > data */ > -- =C2=A0=C2=A0rc =3D validate_rrset(now, header, plen, class, type, name, > keyname, &wildname, NULL, 0, 0, 0); > -- =C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0if (rc =3D=3D STAT_SECURE_WILDCARD) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int nsec_type, nsec_count, i; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char **nsecs; > -- > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* An attacker can replay a wildcard= answer with a > different > -- =C2=A0answer and overlay a genuine RR. To prove this > -- =C2=A0hasn't happened, the answer must prove that > -- =C2=A0the genuine record doesn't exist. Check that here. > */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(nsec_type =3D find_nsec_record= s(header, plen, > &nsecs, &nsec_count, class))) > -- return STAT_BOGUS; /* No NSECs or bad packet */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Note that we're called here becau= se something > didn't validate in validate_reply, > -- =C2=A0so we can't assume that any NSEC records have been > validated. We do them by steam here */ > -- > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (i =3D 0; i < nsec_count; i++) > -- { > -- =C2=A0=C2=A0unsigned char *p1 =3D nsecs[i]; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (!extract_name(header, plen, &p1, daemon- > >workspacename, 1, 0)) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -- > -- =C2=A0=C2=A0rc =3D validate_rrset(now, header, plen, class, > nsec_type, daemon->workspacename, keyname, NULL, NULL, 0, 0, 0); > -+=C2=A0=C2=A0/* OK, all the RRsets validate, now see if we have a missing > answer or CNAME target. */ > -+=C2=A0=C2=A0for (j =3D 0; j <targetidx; j++) > -+=C2=A0=C2=A0=C2=A0=C2=A0if ((p2 =3D targets[j])) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -+ if (neganswer) > -+ =C2=A0=C2=A0*neganswer =3D 1; > -=C2=A0 > -- =C2=A0=C2=A0/* NSECs can't be wildcards. */ > -- =C2=A0=C2=A0if (rc =3D=3D STAT_SECURE_WILDCARD) > -- =C2=A0=C2=A0=C2=A0=C2=A0rc =3D STAT_BOGUS; > -+ if (!extract_name(header, plen, &p2, name, 1, 10)) > -+ =C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0 > -+ /* NXDOMAIN or NODATA reply, unanswered question is (name, > qclass, qtype) */ > -=C2=A0 > -- =C2=A0=C2=A0if (rc !=3D STAT_SECURE) > -+ /* For anything other than a DS record, this situation is > OK if either > -+ =C2=A0=C2=A0=C2=A0the answer is in an unsigned zone, or there's a NSEC > records. */ > -+ if (!(nsec_type =3D find_nsec_records(header, plen, &nsecs, > &nsec_count, qclass))) > -+ =C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0/* Empty DS without NSECS */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0if (qtype =3D=3D T_DS) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -+ =C2=A0=C2=A0=C2=A0=C2=A0else > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -+ rc =3D zone_status(name, qclass, keyname, now); > -+ if (rc !=3D STAT_SECURE) > -+ =C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0if (class) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*class =3D qclass; /* Class for NEE= D_DS or > NEED_DNSKEY */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0return rc; > -- } > -- > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (nsec_type =3D=3D T_NSEC) > -- rc =3D prove_non_existence_nsec(header, plen, nsecs, > nsec_count, daemon->workspacename, keyname, name, type, NULL); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -- rc =3D prove_non_existence_nsec3(header, plen, nsecs, > nsec_count, daemon->workspacename,=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0keyname, name, type, > wildname, NULL); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rc !=3D STAT_SECURE) > -- return rc; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (rc !=3D STAT_SECURE) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rc =3D=3D STAT_NO_SIG) > -- rc =3D STAT_INSECURE; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return rc; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0}=C2=A0 > -+ =09 > -+ return STAT_BOGUS; /* signed zone, no NSECs */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0} > -=C2=A0 > -- =C2=A0=C2=A0/* Loop down CNAME chain/ */ > -- =C2=A0=C2=A0if (!cname_count-- ||=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0!extract_name(header, plen, &p, name= , 1, 0) || > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0!(p =3D skip_questions(header, plen)= )) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0break; > -- } > -+ =C2=A0=C2=A0if (nsec_type =3D=3D T_NSEC) > -+ =C2=A0=C2=A0rc =3D prove_non_existence_nsec(header, plen, nsecs, > nsec_count, daemon->workspacename, keyname, name, qtype, nons); > -+ else > -+ =C2=A0=C2=A0rc =3D prove_non_existence_nsec3(header, plen, nsecs, > nsec_count, daemon->workspacename, keyname, name, qtype, NULL, nons); > -=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* End of CNAME chain */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE;=09 > --=C2=A0=C2=A0=C2=A0=C2=A0} > -+ if (rc !=3D STAT_SECURE) > -+ =C2=A0=C2=A0return rc; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0return STAT_SECURE; > - } > -=C2=A0 > -=C2=A0 > -diff --git a/src/forward.c b/src/forward.c > -index b76a974..dd22a62 100644 > ---- a/src/forward.c > -+++ b/src/forward.c > -@@ -23,15 +23,6 @@ static struct frec > *lookup_frec_by_sender(unsigned short id, > - static unsigned short get_id(void); > - static void free_frec(struct frec *f); > -=C2=A0 > --#ifdef HAVE_DNSSEC > --static int tcp_key_recurse(time_t now, int status, struct > dns_header *header, size_t n,=C2=A0 > -- =C2=A0=C2=A0=C2=A0int class, char *name, char *keyname, > struct server *server, int *keycount); > --static int do_check_sign(struct frec *forward, int status, time_t > now, char *name, char *keyname); > --static int send_check_sign(struct frec *forward, time_t now, struct > dns_header *header, size_t plen,=C2=A0 > -- =C2=A0=C2=A0=C2=A0char *name, char *keyname); > --#endif > -- > -- > - /* Send a UDP packet with its source address set as "source"=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0unless nowild is true, when we just send it with t= he kernel > default */ > - int send_from(int fd, int nowild, char *packet, size_t len,=C2=A0 > -@@ -825,236 +816,142 @@ void reply_query(int fd, int family, time_t > now) > - #ifdef HAVE_DNSSEC > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (server && option_bool(OPT_DN= SSEC_VALID) && !(forward- > >flags & FREC_CHECKING_DISABLED)) > -=C2=A0 { > -- =C2=A0=C2=A0int status; > -+ =C2=A0=C2=A0int status =3D 0; > -=C2=A0 > -=C2=A0 =C2=A0=C2=A0/* We've had a reply already, which we're validating. > Ignore this duplicate */ > -=C2=A0 =C2=A0=C2=A0if (forward->blocking_query) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0return; > -- > -- =C2=A0=C2=A0if (header->hb3 & HB3_TC) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Truncated answer can't be validat= ed. > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0/* Truncated answer can't be validated. > -=C2=A0 =C2=A0If this is an answer to a DNSSEC-generated query, > we still > -=C2=A0 =C2=A0need to get the client to retry over TCP, so > return > -=C2=A0 =C2=A0an answer with the TC bit set, even if the actual > answer fits. > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*/ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D STAT_TRUNCATED; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else if (forward->flags & FREC_DNSKEY_QUERY) > -- =C2=A0=C2=A0=C2=A0=C2=A0status =3D dnssec_validate_by_ds(now, header, n,= daemon- > >namebuff, daemon->keyname, forward->class); > -- =C2=A0=C2=A0else if (forward->flags & FREC_DS_QUERY) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D dnssec_validate_ds(now, h= eader, n, daemon- > >namebuff, daemon->keyname, forward->class); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Provably no DS, everything below = is insecure, even > if signatures are offered */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_NO_DS) > -- /* We only cache sigs when we've validated a reply. > -- =C2=A0=C2=A0=C2=A0Avoid caching a reply with sigs if there's a > vaildated break in the=C2=A0 > -- =C2=A0=C2=A0=C2=A0DS chain, so we don't return replies from cache > missing sigs. */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0 status =3D STAT_INSECURE_DS; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (status =3D=3D STAT_NO_SIG) > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (option_bool(OPT_DNSSEC_NO_SIGN)) > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D send_check_sign(forward,= now, > header, n, daemon->namebuff, daemon->keyname); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_INSECURE) > -- status =3D STAT_INSECURE_DS; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0status =3D STAT_INSECURE_DS; > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0else if (status =3D=3D STAT_NO_NS) > -- status =3D STAT_BOGUS; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else if (forward->flags & FREC_CHECK_NOSIGN) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D dnssec_validate_ds(now, h= eader, n, daemon- > >namebuff, daemon->keyname, forward->class); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status !=3D STAT_NEED_KEY) > -- status =3D do_check_sign(forward, status, now, > daemon->namebuff, daemon->keyname); > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else > -+ =C2=A0=C2=A0if (header->hb3 & HB3_TC) > -+ =C2=A0=C2=A0=C2=A0=C2=A0status =3D STAT_TRUNCATED; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0while (1) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D dnssec_validate_reply(now= , header, n, > daemon->namebuff, daemon->keyname, &forward->class, NULL, NULL); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_NO_SIG) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* As soon as anything returns BOGUS= , we stop and > unwind, to do otherwise > -+ =C2=A0would invite infinite loops, since the answers to > DNSKEY and DS queries > -+ =C2=A0will not be cached, so they'll be repeated. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status !=3D STAT_BOGUS && status= !=3D STAT_TRUNCATED > && status !=3D STAT_ABANDONED) > -=C2=A0 { > -- =C2=A0=C2=A0if (option_bool(OPT_DNSSEC_NO_SIGN)) > -- =C2=A0=C2=A0=C2=A0=C2=A0status =3D send_check_sign(forward, now, header, > n, daemon->namebuff, daemon->keyname); > -+ =C2=A0=C2=A0if (forward->flags & FREC_DNSKEY_QUERY) > -+ =C2=A0=C2=A0=C2=A0=C2=A0status =3D dnssec_validate_by_ds(now, header, n, > daemon->namebuff, daemon->keyname, forward->class); > -+ =C2=A0=C2=A0else if (forward->flags & FREC_DS_QUERY) > -+ =C2=A0=C2=A0=C2=A0=C2=A0status =3D dnssec_validate_ds(now, header, n, > daemon->namebuff, daemon->keyname, forward->class); > -=C2=A0 =C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0status =3D STAT_INSECURE; > -+ =C2=A0=C2=A0=C2=A0=C2=A0status =3D dnssec_validate_reply(now, header, n, > daemon->namebuff, daemon->keyname, &forward->class,=C2=A0 > -+ =C2=A0=C2=A0=C2=A0option_bool(OPT_ > DNSSEC_NO_SIGN), NULL, NULL); > -=C2=A0 } > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0/* Can't validate, as we're missing key data. Put this > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0answer aside, whilst we get that. */=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0if (status =3D=3D STAT_NEED_DS || status =3D=3D STAT_NEED_DS= _NEG > || status =3D=3D STAT_NEED_KEY) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct frec *new, *orig; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Free any saved query */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (forward->stash) > -- blockdata_free(forward->stash); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Now save reply pending receipt of= key data */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(forward->stash =3D blockdata_a= lloc((char > *)header, n))) > -- return; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0forward->stash_len =3D n; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0anotherkey: =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Find the original query that star= ted it all.... */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (orig =3D forward; orig->depende= nt; orig =3D orig- > >dependent); > -- > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (--orig->work_counter =3D=3D 0 ||= !(new =3D > get_new_frec(now, NULL, 1))) > -- status =3D STAT_INSECURE; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Can't validate, as we're missing = key data. Put > this > -+ =C2=A0answer aside, whilst we get that. */=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_NEED_DS || st= atus =3D=3D > STAT_NEED_KEY) > -=C2=A0 { > -- =C2=A0=C2=A0int fd; > -- =C2=A0=C2=A0struct frec *next =3D new->next; > -- =C2=A0=C2=A0*new =3D *forward; /* copy everything, then > overwrite */ > -- =C2=A0=C2=A0new->next =3D next; > -- =C2=A0=C2=A0new->blocking_query =3D NULL; > -- =C2=A0=C2=A0new->sentto =3D server; > -- =C2=A0=C2=A0new->rfd4 =3D NULL; > -- =C2=A0=C2=A0new->orig_domain =3D NULL; > --#ifdef HAVE_IPV6 > -- =C2=A0=C2=A0new->rfd6 =3D NULL; > --#endif > -- =C2=A0=C2=A0new->flags &=3D ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY > | FREC_CHECK_NOSIGN); > -+ =C2=A0=C2=A0struct frec *new, *orig; > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0new->dependent =3D forward; /* to find query > awaiting new one. */ > -- =C2=A0=C2=A0forward->blocking_query =3D new; /* for garbage > cleaning */ > -- =C2=A0=C2=A0/* validate routines leave name of required > record in daemon->keyname */ > -- =C2=A0=C2=A0if (status =3D=3D STAT_NEED_KEY) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->flags |=3D FREC_DNSKEY_QUERY;= =C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0nn =3D dnssec_generate_query(header= , ((char *) > header) + daemon->packet_buff_sz, > -- =C2=A0daemon->keyname, > forward->class, T_DNSKEY, &server->addr, server->edns_pktsz); > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_NEED_DS_NEG) > -- new->flags |=3D FREC_CHECK_NOSIGN; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -- new->flags |=3D FREC_DS_QUERY; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0nn =3D dnssec_generate_query(header= ,((char *) > header) + daemon->packet_buff_sz, > -- =C2=A0daemon->keyname, > forward->class, T_DS, &server->addr, server->edns_pktsz); > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0if ((hash =3D hash_questions(header, nn, daemon- > >namebuff))) > -- =C2=A0=C2=A0=C2=A0=C2=A0memcpy(new->hash, hash, HASH_SIZE); > -- =C2=A0=C2=A0new->new_id =3D get_id(); > -- =C2=A0=C2=A0header->id =3D htons(new->new_id); > -- =C2=A0=C2=A0/* Save query for retransmission */ > -- =C2=A0=C2=A0if (!(new->stash =3D blockdata_alloc((char > *)header, nn))) > -+ =C2=A0=C2=A0/* Free any saved query */ > -+ =C2=A0=C2=A0if (forward->stash) > -+ =C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(forward->stash); > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0/* Now save reply pending receipt of key data */ > -+ =C2=A0=C2=A0if (!(forward->stash =3D blockdata_alloc((char > *)header, n))) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0return; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0new->stash_len =3D nn; > -+ =C2=A0=C2=A0forward->stash_len =3D n; > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0/* Don't resend this. */ > -- =C2=A0=C2=A0daemon->srv_save =3D NULL; > -+ =C2=A0=C2=A0/* Find the original query that started it > all.... */ > -+ =C2=A0=C2=A0for (orig =3D forward; orig->dependent; orig =3D > orig->dependent); > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (server->sfd) > -- =C2=A0=C2=A0=C2=A0=C2=A0fd =3D server->sfd->fd; > -+ =C2=A0=C2=A0if (--orig->work_counter =3D=3D 0 || !(new =3D > get_new_frec(now, NULL, 1))) > -+ =C2=A0=C2=A0=C2=A0=C2=A0status =3D STAT_ABANDONED; > -=C2=A0 =C2=A0=C2=A0else > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0fd =3D -1; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int fd; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct frec *next =3D new->next; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*new =3D *forward; /* copy everythi= ng, then > overwrite */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->next =3D next; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->blocking_query =3D NULL; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->sentto =3D server; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->rfd4 =3D NULL; > - #ifdef HAVE_IPV6 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (server->addr.sa.sa_family =3D= =3D AF_INET6) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->rfd6 =3D NULL; > -+#endif > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->flags &=3D ~(FREC_DNSKEY_QUERY= | > FREC_DS_QUERY); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->dependent =3D forward; /* to f= ind query > awaiting new one. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0forward->blocking_query =3D new; /*= for garbage > cleaning */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* validate routines leave name of = required > record in daemon->keyname */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_NEED_KEY) > -+ { > -+ =C2=A0=C2=A0new->flags |=3D FREC_DNSKEY_QUERY;=C2=A0 > -+ =C2=A0=C2=A0nn =3D dnssec_generate_query(header, ((char > *) header) + daemon->packet_buff_sz, > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0daemon- > >keyname, forward->class, T_DNSKEY, &server->addr, server- > >edns_pktsz); > -+ } > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else=C2=A0 > -=C2=A0 { > -- =C2=A0=C2=A0if (new->rfd6 || (new->rfd6 =3D > allocate_rfd(AF_INET6))) > -- =C2=A0=C2=A0=C2=A0=C2=A0fd =3D new->rfd6->fd; > -+ =C2=A0=C2=A0new->flags |=3D FREC_DS_QUERY; > -+ =C2=A0=C2=A0nn =3D dnssec_generate_query(header,((char > *) header) + daemon->packet_buff_sz, > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0daemon- > >keyname, forward->class, T_DS, &server->addr, server->edns_pktsz); > -=C2=A0 } > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((hash =3D hash_questions(header= , nn, > daemon->namebuff))) > -+ memcpy(new->hash, hash, HASH_SIZE); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->new_id =3D get_id(); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0header->id =3D htons(new->new_id); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Save query for retransmission */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->stash =3D blockdata_alloc((cha= r *)header, > nn); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new->stash_len =3D nn; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Don't resend this. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0daemon->srv_save =3D NULL; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (server->sfd) > -+ fd =3D server->sfd->fd; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -+ { > -+ =C2=A0=C2=A0fd =3D -1; > -+#ifdef HAVE_IPV6 > -+ =C2=A0=C2=A0if (server->addr.sa.sa_family =3D=3D > AF_INET6) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (new->rfd6 || (new->rfd6 =3D > allocate_rfd(AF_INET6))) > -+ fd =3D new->rfd6->fd; > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0else > - #endif > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (new->rfd4 || (new->rfd4 =3D > allocate_rfd(AF_INET))) > -+ fd =3D new->rfd4->fd; > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ } > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (fd !=3D -1) > -=C2=A0 { > -- =C2=A0=C2=A0if (new->rfd4 || (new->rfd4 =3D > allocate_rfd(AF_INET))) > -- =C2=A0=C2=A0=C2=A0=C2=A0fd =3D new->rfd4->fd; > -+ =C2=A0=C2=A0while (retry_send(sendto(fd, (char > *)header, nn, 0,=C2=A0 > -+ =C2=A0=C2=A0=C2=A0&server- > >addr.sa,=C2=A0 > -+ =C2=A0=C2=A0=C2=A0sa_len(&server- > >addr))));=C2=A0 > -+ =C2=A0=C2=A0server->queries++; > -=C2=A0 } > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (fd !=3D -1) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0while (retry_send(sendto(fd, (char = *)header, > nn, 0,=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0&server->addr.sa,=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0sa_len(&server- > >addr))));=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0server->queries++; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0} =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0return; > -=C2=A0 } > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0/* Ok, we reached far enough up the chain-of-trust that > we can validate something. > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Now wind back down, pulling back answers w= hich > wouldn't previously validate > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0and validate them with the new data. Note = that if an > answer needs multiple > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0keys to validate, we may find another key = is needed, > in which case we set off > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0down another branch of the tree. Once we g= et to the > original answer=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(FREC_DNSSEC_QUERY not set) and it validat= es, return > it to the original requestor. */ > -- =C2=A0=C2=A0while (forward->dependent) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Validated original answer, all do= ne. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!forward->dependent) > -+ break; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* validated subsdiary query, (and c= ached result) > -+ =C2=A0pop that and return to the previous query we were > working on. */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct frec *prev =3D forward->= dependent; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free_frec(forward); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0forward =3D prev; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0forward->blocking_query =3D NUL= L; /* already gone */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0blockdata_retrieve(forward->sta= sh, forward- > >stash_len, (void *)header); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0n =3D forward->stash_len; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_SECURE) > -- { > -- =C2=A0=C2=A0if (forward->flags & FREC_DNSKEY_QUERY) > -- =C2=A0=C2=A0=C2=A0=C2=A0status =3D dnssec_validate_by_ds(now, header, n, > daemon->namebuff, daemon->keyname, forward->class); > -- =C2=A0=C2=A0else if (forward->flags & FREC_DS_QUERY) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D dnssec_validate_ds(now, = header, n, > daemon->namebuff, daemon->keyname, forward->class); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Provably no DS, everything= below is > insecure, even if signatures are offered */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_NO_DS) > -- /* We only cache sigs when we've validated > a reply. > -- =C2=A0=C2=A0=C2=A0Avoid caching a reply with sigs if > there's a vaildated break in the=C2=A0 > -- =C2=A0=C2=A0=C2=A0DS chain, so we don't return replies > from cache missing sigs. */ > -- status =3D STAT_INSECURE_DS; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (status =3D=3D STAT_N= O_SIG) > -- =C2=A0{ > -- =C2=A0=C2=A0=C2=A0if (option_bool(OPT_DNSSEC_NO_SIGN)) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D send_check_sign(f= orward, > now, header, n, daemon->namebuff, daemon->keyname);=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_INSEC= URE) > -- =C2=A0status =3D STAT_INSECURE_DS; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D STAT_INSECURE_DS; > -- =C2=A0} > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (status =3D=3D STAT_N= O_NS) > -- =C2=A0status =3D STAT_BOGUS; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else if (forward->flags & FREC_CHECK_NOSIGN) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D dnssec_validate_ds(now, = header, n, > daemon->namebuff, daemon->keyname, forward->class); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status !=3D STAT_NEED_KEY) > -- status =3D do_check_sign(forward, status, > now, daemon->namebuff, daemon->keyname); > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D dnssec_validate_reply(no= w, header, > n, daemon->namebuff, daemon->keyname, &forward->class, NULL, NULL);=09 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_NO_SIG) > -- { > -- =C2=A0=C2=A0if (option_bool(OPT_DNSSEC_NO_SIGN)) > -- =C2=A0=C2=A0=C2=A0=C2=A0status =3D send_check_sign(forward, now, > header, n, daemon->namebuff, daemon->keyname); > -- =C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0status =3D STAT_INSECURE; > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0if (status =3D=3D STAT_NEED_DS || status =3D=3D > STAT_NEED_DS_NEG || status =3D=3D STAT_NEED_KEY) > -- =C2=A0=C2=A0=C2=A0=C2=A0goto anotherkey; > -- } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -+=09 > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0no_cache_dnssec =3D 0; > -- > -- =C2=A0=C2=A0if (status =3D=3D STAT_INSECURE_DS) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* We only cache sigs when we've val= idated a reply. > -- =C2=A0Avoid caching a reply with sigs if there's a > vaildated break in the=C2=A0 > -- =C2=A0DS chain, so we don't return replies from cache > missing sigs. */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D STAT_INSECURE; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0no_cache_dnssec =3D 1; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0if (status =3D=3D STAT_TRUNCATED) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0header->hb3 |=3D HB3_TC; > -@@ -1062,7 +959,7 @@ void reply_query(int fd, int family, time_t > now) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0char *result, *domain =3D "resu= lt"; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (forward->work_counter =3D=3D 0) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_ABANDONED) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0result =3D "ABANDONED"; > -=C2=A0 =C2=A0=C2=A0status =3D STAT_BOGUS; > -@@ -1072,7 +969,7 @@ void reply_query(int fd, int family, time_t > now) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_BOGUS &&= extract_request(header, > n, daemon->namebuff, NULL)) > -=C2=A0 domain =3D daemon->namebuff; > -- > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0log_query(F_KEYTAG | F_SECSTAT,= domain, NULL, > result); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0 > -@@ -1415,315 +1312,49 @@ void receive_query(struct listener *listen, > time_t now) > - } > -=C2=A0 > - #ifdef HAVE_DNSSEC > -- > --/* UDP: we've got an unsigned answer, return STAT_INSECURE if we > can prove there's no DS > --=C2=A0=C2=A0=C2=A0and therefore the answer shouldn't be signed, or STAT_B= OGUS if > it should be, or=C2=A0 > --=C2=A0=C2=A0=C2=A0STAT_NEED_DS_NEG and keyname if we need to do the query= . */ > --static int send_check_sign(struct frec *forward, time_t now, struct > dns_header *header, size_t plen,=C2=A0 > -- =C2=A0=C2=A0=C2=A0char *name, char *keyname) > --{ > --=C2=A0=C2=A0int status =3D dnssec_chase_cname(now, header, plen, name, > keyname); > --=C2=A0=C2=A0 > --=C2=A0=C2=A0if (status !=3D STAT_INSECURE) > --=C2=A0=C2=A0=C2=A0=C2=A0return status; > -- > --=C2=A0=C2=A0/* Store the domain we're trying to check. */ > --=C2=A0=C2=A0forward->name_start =3D strlen(name); > --=C2=A0=C2=A0forward->name_len =3D forward->name_start + 1; > --=C2=A0=C2=A0if (!(forward->orig_domain =3D blockdata_alloc(name, forward- > >name_len))) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0return do_check_sign(forward, 0, now, name, keyname); > --} > --=C2=A0 > --/* We either have a a reply (header non-NULL, or we need to start > by looking in the cache */=C2=A0 > --static int do_check_sign(struct frec *forward, int status, time_t > now, char *name, char *keyname) > --{ > --=C2=A0=C2=A0/* get domain we're checking back from blockdata store, it's > stored on the original query. */ > --=C2=A0=C2=A0while (forward->dependent && !forward->orig_domain) > --=C2=A0=C2=A0=C2=A0=C2=A0forward =3D forward->dependent; > -- > --=C2=A0=C2=A0blockdata_retrieve(forward->orig_domain, forward->name_len, > name); > --=C2=A0=C2=A0 > --=C2=A0=C2=A0while (1) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0char *p;=C2=A0 > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D 0) > -- { > -- =C2=A0=C2=A0struct crec *crecp; > -- > -- =C2=A0=C2=A0/* Haven't received answer, see if in cache */ > -- =C2=A0=C2=A0if (!(crecp =3D cache_find_by_name(NULL, &name[forward- > >name_start], now, F_DS))) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* put name of DS record we're missi= ng into keyname > */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0strcpy(keyname, &name[forward->name_= start]); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* and wait for reply to arrive */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_NEED_DS_NEG; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- > -- =C2=A0=C2=A0/* F_DNSSECOK misused in DS cache records to non- > existance of NS record */=C2=A0 > -- =C2=A0=C2=A0if (!(crecp->flags & F_NEG)) > -- =C2=A0=C2=A0=C2=A0=C2=A0status =3D STAT_SECURE; > -- =C2=A0=C2=A0else if (crecp->flags & F_DNSSECOK) > -- =C2=A0=C2=A0=C2=A0=C2=A0status =3D STAT_NO_DS; > -- =C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0status =3D STAT_NO_NS; > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Have entered non-signed part of DN= S tree. */=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_NO_DS) > -- return forward->dependent ? STAT_INSECURE_DS : > STAT_INSECURE; > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_BOGUS) > -- return STAT_BOGUS; > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_NO_SIG && *key= name !=3D 0) > -- { > -- =C2=A0=C2=A0/* There is a validated CNAME chain that doesn't end in a > DS record. Start=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0the search again in that domain. */ > -- =C2=A0=C2=A0blockdata_free(forward->orig_domain); > -- =C2=A0=C2=A0forward->name_start =3D strlen(keyname); > -- =C2=A0=C2=A0forward->name_len =3D forward->name_start + 1; > -- =C2=A0=C2=A0if (!(forward->orig_domain =3D blockdata_alloc(keyname, > forward->name_len))) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0strcpy(name, keyname); > -- =C2=A0=C2=A0status =3D 0; /* force to cache when we iterate. */ > -- =C2=A0=C2=A0continue; > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* There's a proven DS record, or we'= re within a zone, where > there doesn't need > -- =C2=A0to be a DS record. Add a name and try again.=C2=A0 > -- =C2=A0If we've already tried the whole name, then fail */ > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (forward->name_start =3D=3D 0) > -- return STAT_BOGUS; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (p =3D &name[forward->name_start-= 2]; (*p !=3D '.') && (p !=3D > name); p--); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (p !=3D name) > -- p++; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0forward->name_start =3D p - name; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D 0; /* force to cache when = we iterate. */ > --=C2=A0=C2=A0=C2=A0=C2=A0} > --} > -- > --/* Move down from the root, until we find a signed non-existance of > a DS, in which case > --=C2=A0=C2=A0=C2=A0an unsigned answer is OK, or we find a signed DS, in wh= ich case > there should be=C2=A0 > --=C2=A0=C2=A0=C2=A0a signature, and the answer is BOGUS */ > --static int=C2=A0=C2=A0tcp_check_for_unsigned_zone(time_t now, struct > dns_header *header, size_t plen, int class, char *name,=C2=A0 > -- char *keyname, struct > server *server, int *keycount) > --{ > --=C2=A0=C2=A0size_t m; > --=C2=A0=C2=A0unsigned char *packet, *payload; > --=C2=A0=C2=A0u16 *length; > --=C2=A0=C2=A0int status, name_len; > --=C2=A0=C2=A0struct blockdata *block; > -- > --=C2=A0=C2=A0char *name_start; > -- > --=C2=A0=C2=A0/* Get first insecure entry in CNAME chain */ > --=C2=A0=C2=A0status =3D tcp_key_recurse(now, STAT_CHASE_CNAME, header, ple= n, > class, name, keyname, server, keycount); > --=C2=A0=C2=A0if (status =3D=3D STAT_BOGUS) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0if (!(packet =3D whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + > sizeof(u16)))) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0payload =3D &packet[2]; > --=C2=A0=C2=A0header =3D (struct dns_header *)payload; > --=C2=A0=C2=A0length =3D (u16 *)packet; > -- > --=C2=A0=C2=A0/* Stash the name away, since the buffer will be trashed when= we > recurse */ > --=C2=A0=C2=A0name_len =3D strlen(name) + 1; > --=C2=A0=C2=A0name_start =3D name + name_len - 1; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0if (!(block =3D blockdata_alloc(name, name_len))) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free(packet); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > --=C2=A0=C2=A0=C2=A0=C2=A0} > -- > --=C2=A0=C2=A0while (1) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char c1, c2; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct crec *crecp; > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (--(*keycount) =3D=3D 0) > -- { > -- =C2=A0=C2=A0free(packet); > -- =C2=A0=C2=A0blockdata_free(block); > -- =C2=A0=C2=A0return STAT_BOGUS;=C2=A0=C2=A0=C2=A0=C2=A0 > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0while ((crecp =3D cache_find_by_name(= NULL, name_start, now, > F_DS))) > -- {=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0if ((crecp->flags & F_NEG) && (crecp->flags & > F_DNSSECOK)) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Found a secure denial of DS - del= egation is indeed > insecure */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free(packet); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(block); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0/* Here, either there's a secure DS, or no NS and no DS, > and therefore no delegation. > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Add another label and continue. */ > --=C2=A0 > -- =C2=A0=C2=A0if (name_start =3D=3D name) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free(packet); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(block); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* run out of lab= els */ > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0name_start -=3D 2; > -- =C2=A0=C2=A0while (*name_start !=3D '.' && name_start !=3D name)=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0name_start--; > -- =C2=A0=C2=A0if (name_start !=3D name) > -- =C2=A0=C2=A0=C2=A0=C2=A0name_start++; > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Can't find it in the cache, have t= o send a query */ > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0m =3D dnssec_generate_query(header, (= (char *) header) + 65536, > name_start, class, T_DS, &server->addr, server->edns_pktsz); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*length =3D htons(m); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (read_write(server->tcpfd, packet,= m + sizeof(u16), 0) && > -- =C2=A0=C2=A0read_write(server->tcpfd, &c1, 1, 1) && > -- =C2=A0=C2=A0read_write(server->tcpfd, &c2, 1, 1) && > -- =C2=A0=C2=A0read_write(server->tcpfd, payload, (c1 << 8) | c2, 1)) > -- { > -- =C2=A0=C2=A0m =3D (c1 << 8) | c2; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0/* Note this trashes all three name workspaces */ > -- =C2=A0=C2=A0status =3D tcp_key_recurse(now, STAT_NEED_DS_NEG, header, > m, class, name, keyname, server, keycount); > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (status =3D=3D STAT_NO_DS) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Found a secure denial of DS - del= egation is indeed > insecure */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free(packet); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(block); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (status =3D=3D STAT_NO_SIG && *keyname !=3D 0) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* There is a validated CNAME chain = that doesn't end > in a DS record. Start=C2=A0 > -- =C2=A0the search again in that domain. */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(block); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0name_len =3D strlen(keyname) + 1; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0name_start =3D name + name_len - 1; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(block =3D blockdata_alloc(keyn= ame, name_len))) > -- return STAT_BOGUS; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0strcpy(name, keyname); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0continue; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (status =3D=3D STAT_BOGUS) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free(packet); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(block); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0/* Here, either there's a secure DS, or no NS and no DS, > and therefore no delegation. > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Add another label and continue. */ > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0/* Get name we're checking back. */ > -- =C2=A0=C2=A0blockdata_retrieve(block, name_len, name); > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (name_start =3D=3D name) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free(packet); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(block); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* run out of lab= els */ > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0name_start -=3D 2; > -- =C2=A0=C2=A0while (*name_start !=3D '.' && name_start !=3D name)=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0name_start--; > -- =C2=A0=C2=A0if (name_start !=3D name) > -- =C2=A0=C2=A0=C2=A0=C2=A0name_start++; > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -- { > -- =C2=A0=C2=A0/* IO failure */ > -- =C2=A0=C2=A0free(packet); > -- =C2=A0=C2=A0blockdata_free(block); > -- =C2=A0=C2=A0return STAT_BOGUS; /* run out of labels */ > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0} > --} > -- > - static int tcp_key_recurse(time_t now, int status, struct > dns_header *header, size_t n,=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0int class, char *name, char *keyname, > struct server *server, int *keycount) > - { > -=C2=A0=C2=A0=C2=A0/* Recurse up the key heirarchy */ > -=C2=A0=C2=A0=C2=A0int new_status; > -+=C2=A0=C2=A0unsigned char *packet =3D NULL; > -+=C2=A0=C2=A0size_t m;=C2=A0 > -+=C2=A0=C2=A0unsigned char *payload =3D NULL; > -+=C2=A0=C2=A0struct dns_header *new_header =3D NULL; > -+=C2=A0=C2=A0u16 *length =3D NULL; > -+=C2=A0=C2=A0unsigned char c1, c2; > -=C2=A0 > --=C2=A0=C2=A0/* limit the amount of work we do, to avoid cycling forever on > loops in the DNS */ > --=C2=A0=C2=A0if (--(*keycount) =3D=3D 0) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0if (status =3D=3D STAT_NEED_KEY) > --=C2=A0=C2=A0=C2=A0=C2=A0new_status =3D dnssec_validate_by_ds(now, header,= n, name, > keyname, class); > --=C2=A0=C2=A0else if (status =3D=3D STAT_NEED_DS || status =3D=3D STAT_NEE= D_DS_NEG) > -+=C2=A0=C2=A0while (1) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new_status =3D dnssec_validate_ds(now= , header, n, name, > keyname, class); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_NEED_DS) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* limit the amount of work we do, to= avoid cycling forever > on loops in the DNS */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (--(*keycount) =3D=3D 0) > -+ new_status =3D STAT_ABANDONED; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (status =3D=3D STAT_NEED_KEY) > -+ new_status =3D dnssec_validate_by_ds(now, header, n, name, > keyname, class); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (status =3D=3D STAT_NEED_DS) > -+ new_status =3D dnssec_validate_ds(now, header, n, name, > keyname, class); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else=C2=A0 > -+ new_status =3D dnssec_validate_reply(now, header, n, name, > keyname, &class, option_bool(OPT_DNSSEC_NO_SIGN), NULL, NULL); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (new_status !=3D STAT_NEED_DS && n= ew_status !=3D > STAT_NEED_KEY) > -+ break; > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Can't validate because we need a k= ey/DS whose name now in > keyname. > -+ =C2=A0Make query for same, and recurse to validate */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!packet) > -=C2=A0 { > -- =C2=A0=C2=A0if (new_status =3D=3D STAT_NO_DS) > -- =C2=A0=C2=A0=C2=A0=C2=A0new_status =3D STAT_INSECURE_DS; > -- =C2=A0=C2=A0if (new_status =3D=3D STAT_NO_SIG) > -- =C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (option_bool(OPT_DNSSEC_NO_SIGN)) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0new_status =3D tcp_check_for_unsigned_zone(now, > header, n, class, name, keyname, server, keycount); > -- =C2=A0if (new_status =3D=3D STAT_INSECURE) > -- =C2=A0=C2=A0=C2=A0new_status =3D STAT_INSECURE_DS; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new_status =3D STAT_INSECURE_D= S; > -- =C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else if (new_status =3D=3D STAT_NO_NS) > -- =C2=A0=C2=A0=C2=A0=C2=A0new_status =3D STAT_BOGUS; > -+ =C2=A0=C2=A0packet =3D whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + > sizeof(u16)); > -+ =C2=A0=C2=A0payload =3D &packet[2]; > -+ =C2=A0=C2=A0new_header =3D (struct dns_header *)payload; > -+ =C2=A0=C2=A0length =3D (u16 *)packet; > -=C2=A0 } > --=C2=A0=C2=A0=C2=A0=C2=A0} > --=C2=A0=C2=A0else if (status =3D=3D STAT_CHASE_CNAME) > --=C2=A0=C2=A0=C2=A0=C2=A0new_status =3D dnssec_chase_cname(now, header, n,= name, keyname); > --=C2=A0=C2=A0else=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new_status =3D dnssec_validate_reply(= now, header, n, name, > keyname, &class, NULL, NULL); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (new_status =3D=3D STAT_NO_SIG) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!packet) > -=C2=A0 { > -- =C2=A0=C2=A0if (option_bool(OPT_DNSSEC_NO_SIGN)) > -- =C2=A0=C2=A0=C2=A0=C2=A0new_status =3D tcp_check_for_unsigned_zone(now, = header, > n, class, name, keyname, server, keycount); > -- =C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0new_status =3D STAT_INSECURE; > -+ =C2=A0=C2=A0new_status =3D STAT_ABANDONED; > -+ =C2=A0=C2=A0break; > -=C2=A0 } > --=C2=A0=C2=A0=C2=A0=C2=A0} > -- > --=C2=A0=C2=A0/* Can't validate because we need a key/DS whose name now in > keyname. > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Make query for same, and recurse to validat= e */ > --=C2=A0=C2=A0if (new_status =3D=3D STAT_NEED_DS || new_status =3D=3D STAT_= NEED_KEY) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0size_t m;=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *packet =3D whine_mallo= c(65536 + MAXDNAME + > RRFIXEDSZ + sizeof(u16)); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *payload =3D &packet[2]; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct dns_header *new_header =3D (st= ruct dns_header *)payload; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0u16 *length =3D (u16 *)packet; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char c1, c2; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!packet) > -- return STAT_INSECURE; > -- > --=C2=A0=C2=A0=C2=A0=C2=A0another_tcp_key: > -+ =C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0m =3D dnssec_generate_query(new_= header, ((char *) new_header) + > 65536, keyname, class,=C2=A0 > -=C2=A0 new_status =3D=3D STAT_NEED_KEY ? > T_DNSKEY : T_DS, &server->addr, server->edns_pktsz); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -@@ -1733,65 +1364,22 @@ static int tcp_key_recurse(time_t now, int > status, struct dns_header *header, si > -=C2=A0 =C2=A0=C2=A0!read_write(server->tcpfd, &c1, 1, 1) || > -=C2=A0 =C2=A0=C2=A0!read_write(server->tcpfd, &c2, 1, 1) || > -=C2=A0 =C2=A0=C2=A0!read_write(server->tcpfd, payload, (c1 << 8) | c2, 1)) > -- new_status =3D STAT_INSECURE; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -=C2=A0 { > -- =C2=A0=C2=A0m =3D (c1 << 8) | c2; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0new_status =3D tcp_key_recurse(now, new_status, new_header, > m, class, name, keyname, server, keycount); > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (new_status =3D=3D STAT_SECURE) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Reached a validated record, now t= ry again at this > level. > -- =C2=A0Note that we may get ANOTHER NEED_* if an answer > needs more than one key. > -- =C2=A0If so, go round again. */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (status =3D=3D STAT_NEED_KEY) > -- new_status =3D dnssec_validate_by_ds(now, header, n, > name, keyname, class); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (status =3D=3D STAT_NEED_DS = || status =3D=3D > STAT_NEED_DS_NEG) > -- { > -- =C2=A0=C2=A0new_status =3D dnssec_validate_ds(now, header, n, > name, keyname, class); > -- =C2=A0=C2=A0if (status =3D=3D STAT_NEED_DS) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (new_status =3D=3D STAT_NO_DS) > -- new_status =3D STAT_INSECURE_DS; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (new_status =3D=3D STAT_NO_= SIG) > -- { > -- =C2=A0=C2=A0if (option_bool(OPT_DNSSEC_NO_SIGN)) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new_status =3D > tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, > server, keycount);=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (new_status =3D=3D STAT_INSECUR= E) > -- new_status =3D STAT_INSECURE_DS; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0new_status =3D STAT_INSECURE_DS; > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (new_status =3D=3D STAT_NO_= NS) > -- new_status =3D STAT_BOGUS; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (status =3D=3D STAT_CHASE_CN= AME) > -- new_status =3D dnssec_chase_cname(now, header, n, > name, keyname); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else=C2=A0 > -- { > -- =C2=A0=C2=A0new_status =3D dnssec_validate_reply(now, header, > n, name, keyname, &class, NULL, NULL); > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (new_status =3D=3D STAT_NO_SIG) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (option_bool(OPT_DNSSEC_NO_SIGN)) > -- new_status =3D > tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, > server, keycount); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -- new_status =3D STAT_INSECURE; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (new_status =3D=3D STAT_NEED_DS |= | new_status =3D=3D > STAT_NEED_KEY) > -- goto another_tcp_key; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0new_status =3D STAT_ABANDONED; > -+ =C2=A0=C2=A0break; > -=C2=A0 } > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0m =3D (c1 << 8) | c2; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free(packet); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0new_status =3D tcp_key_recurse(now, n= ew_status, new_header, m, > class, name, keyname, server, keycount); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (new_status !=3D STAT_OK) > -+ break; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -+ > -+=C2=A0=C2=A0if (packet) > -+=C2=A0=C2=A0=C2=A0=C2=A0free(packet); > -+=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0return new_status; > - } > - #endif > -@@ -2075,19 +1663,10 @@ unsigned char *tcp_request(int confd, time_t > now, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (option_bool(OPT_DNSSEC_VAL= ID) && > !checking_disabled) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0int keycount =3D DNSSEC_WORK; /* Limit to > number of DNSSEC questions, to catch loops and avoid filling cache. > */ > -- =C2=A0=C2=A0int status =3D tcp_key_recurse(now, > STAT_TRUNCATED, header, m, 0, daemon->namebuff, daemon->keyname, > last_server, &keycount); > -+ =C2=A0=C2=A0int status =3D tcp_key_recurse(now, > STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname, > last_server, &keycount); > -=C2=A0 =C2=A0=C2=A0char *result, *domain =3D "result"; > -- > -- =C2=A0=C2=A0if (status =3D=3D STAT_INSECURE_DS) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* We only cache sigs when we've > validated a reply. > -- =C2=A0Avoid caching a reply with sigs if > there's a vaildated break in the=C2=A0 > -- =C2=A0DS chain, so we don't return > replies from cache missing sigs. */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D STAT_INSECURE; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0no_cache_dnssec =3D 1; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (keycount =3D=3D 0) > -+ =C2=A0=C2=A0if (status =3D=3D STAT_ABANDONED) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0result =3D "ABANDONED"; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0status =3D STAT_BOGUS; > -@@ -2179,7 +1758,6 @@ static struct frec *allocate_frec(time_t now) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0f->dependent =3D NULL; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0f->blocking_query =3D NULL; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0f->stash =3D NULL; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0f->orig_domain =3D NULL; > - #endif > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0daemon->frec_list =3D f; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -@@ -2248,12 +1826,6 @@ static void free_frec(struct frec *f) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0f->stash =3D NULL; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > --=C2=A0=C2=A0if (f->orig_domain) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(f->orig_domain); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0f->orig_domain =3D NULL; > --=C2=A0=C2=A0=C2=A0=C2=A0} > -- > -=C2=A0=C2=A0=C2=A0/* Anything we're waiting on is pointless now, too */ > -=C2=A0=C2=A0=C2=A0if (f->blocking_query) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free_frec(f->blocking_query); > -@@ -2281,14 +1853,23 @@ struct frec *get_new_frec(time_t now, int > *wait, int force) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0target =3D f; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- if (difftime(now, f->time) >=3D 4*TIMEOUT) > -- =C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0free_frec(f); > -- =C2=A0=C2=A0=C2=A0=C2=A0target =3D f; > -- =C2=A0=C2=A0} > --=09 > -- if (!oldest || difftime(f->time, oldest->time) <=3D 0) > -- =C2=A0=C2=A0oldest =3D f; > -+#ifdef HAVE_DNSSEC > -+ =C2=A0=C2=A0=C2=A0=C2=A0/* Don't free DNSSEC sub-queries here, as we may= end up > with > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0dangling references to them. T= hey'll go when their > "real" query=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0is freed. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0if (!f->dependent) > -+#endif > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -+ if (difftime(now, f->time) >=3D 4*TIMEOUT) > -+ =C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0free_frec(f); > -+ =C2=A0=C2=A0=C2=A0=C2=A0target =3D f; > -+ =C2=A0=C2=A0} > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0 > -+ if (!oldest || difftime(f->time, oldest->time) <=3D > 0) > -+ =C2=A0=C2=A0oldest =3D f; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if (target) > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/017- > Abandon_caching_RRSIGs_and_returning_them_from_cache.patch > b/src/patches/dnsmasq/017- > Abandon_caching_RRSIGs_and_returning_them_from_cache.patch > deleted file mode 100644 > index 5ffaf97..0000000 > --- a/src/patches/dnsmasq/017- > Abandon_caching_RRSIGs_and_returning_them_from_cache.patch > +++ /dev/null > @@ -1,612 +0,0 @@ > -From 93be5b1e023b0c661e1ec2cd6d811a8ec9055c49 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Tue, 15 Dec 2015 12:04:40 +0000 > -Subject: [PATCH] Abandon caching RRSIGs and returning them from > cache. > - > -The list of exceptions to being able to locally answer > -cached data for validated records when DNSSEC data is requested > -was getting too long, so don't ever do that. This means > -that the cache no longer has to hold RRSIGS and allows > -us to lose lots of code. Note that cached validated > -answers are still returned as long as do=3D0 > ---- > - src/cache.c=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A038 ++--------- > - src/dnsmasq.h |=C2=A0=C2=A0=C2=A010 +-- > - src/dnssec.c=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A094 ++++----------------------- > - src/rfc1035.c |=C2=A0=C2=A0197 ++++++------------------------------------= -- > ------------- > - 4 files changed, 42 insertions(+), 297 deletions(-) > - > -diff --git a/src/cache.c b/src/cache.c > -index 1b76b67..51ba7cc 100644 > ---- a/src/cache.c > -+++ b/src/cache.c > -@@ -189,12 +189,7 @@ static void cache_hash(struct crec *crecp) > - static void cache_blockdata_free(struct crec *crecp) > - { > -=C2=A0=C2=A0=C2=A0if (crecp->flags & F_DNSKEY) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->flags & F_DS) > -- blockdata_free(crecp->addr.sig.keydata); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -- blockdata_free(crecp->addr.key.keydata); > --=C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(crecp->addr.key.keydata); > -=C2=A0=C2=A0=C2=A0else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG= )) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(crecp->addr.ds.keydata); > - } > -@@ -369,13 +364,8 @@ static struct crec *cache_scan_free(char *name, > struct all_addr *addr, time_t no > -=C2=A0 } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > - #ifdef HAVE_DNSSEC > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Deletion has to be class-sensitiv= e for DS, DNSKEY, > RRSIG, also=C2=A0 > -- =C2=A0type-covered sensitive for=C2=A0=C2=A0RRSIG */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((flags & (F_DNSKEY | F_DS)) && > -- =C2=A0=C2=A0(flags & (F_DNSKEY | F_DS)) =3D=3D (crecp->flags & > (F_DNSKEY | F_DS)) && > -- =C2=A0=C2=A0crecp->uid =3D=3D addr->addr.dnssec.class && > -- =C2=A0=C2=A0(!((flags & (F_DS | F_DNSKEY)) =3D=3D (F_DS | > F_DNSKEY)) ||=C2=A0 > -- =C2=A0=C2=A0=C2=A0crecp->addr.sig.type_covered =3D=3D addr- > >addr.dnssec.type)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Deletion has to be class-sensitiv= e for DS and > DNSKEY */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((flags & crecp->flags & (F_DNSKE= Y | F_DS)) && > crecp->uid =3D=3D addr->addr.dnssec.class) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0if (crecp->flags & F_CONFIG) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0return crecp; > -@@ -532,13 +522,9 @@ struct crec *cache_insert(char *name, struct > all_addr *addr, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0struct all_addr free_addr =3D new->addr.add= r;; > -=C2=A0 > - #ifdef HAVE_DNSSEC > -- =C2=A0=C2=A0=C2=A0=C2=A0/* For DNSSEC records, addr holds class and > type_covered for RRSIG */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0/* For DNSSEC records, addr holds class. */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0if (new->flags & (F_DS | F_DNSKEY)) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- free_addr.addr.dnssec.class =3D new->uid; > -- if ((new->flags & (F_DS | F_DNSKEY)) =3D=3D (F_DS | > F_DNSKEY)) > -- =C2=A0=C2=A0free_addr.addr.dnssec.type =3D new- > >addr.sig.type_covered; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free_addr.addr.dnssec.class =3D new-= >uid; > - #endif > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0free_avail =3D 1; /* Must be free space now= . */ > -@@ -653,9 +639,6 @@ struct crec *cache_find_by_name(struct crec > *crecp, char *name, time_t now, unsi > -=C2=A0 =C2=A0=C2=A0if (!is_expired(now, crecp) && > !is_outdated_cname_pointer(crecp)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((crecp->flags & F_FORWARD) = &&=C2=A0 > --#ifdef HAVE_DNSSEC > -- =C2=A0=C2=A0(((crecp->flags & (F_DNSKEY | F_DS)) =3D=3D (prot & > (F_DNSKEY | F_DS))) || (prot & F_NSIGMATCH)) && > --#endif > -=C2=A0 =C2=A0=C2=A0(crecp->flags & prot) && > -=C2=A0 =C2=A0=C2=A0hostname_isequal(cache_get_name(crecp), name)) > -=C2=A0 { > -@@ -713,9 +696,6 @@ struct crec *cache_find_by_name(struct crec > *crecp, char *name, time_t now, unsi > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if (ans &&=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(ans->flags & F_FORWARD) && > --#ifdef HAVE_DNSSEC > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(((ans->flags & (F_DNSKEY | F_DS)) = =3D=3D (prot & (F_DNSKEY | > F_DS))) || (prot & F_NSIGMATCH)) && > --#endif > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(ans->flags & prot) &&=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0hostname_isequal(cache_get_name(= ans), name)) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return ans; > -@@ -1472,11 +1452,7 @@ void dump_cache(time_t now) > - #ifdef HAVE_DNSSEC > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0else if (cache->flags & F_DS) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- if (cache->flags & F_DNSKEY) > -- =C2=A0=C2=A0/* RRSIG */ > -- =C2=A0=C2=A0sprintf(a, "%5u %3u %s", cache->addr.sig.keytag, > -- =C2=A0=C2=A0cache->addr.sig.algo, querystr("", cache- > >addr.sig.type_covered)); > -- else if (!(cache->flags & F_NEG)) > -+ if (!(cache->flags & F_NEG)) > -=C2=A0 =C2=A0=C2=A0sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag, > -=C2=A0 =C2=A0=C2=A0cache->addr.ds.algo, cache- > >addr.ds.digest); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -@@ -1502,8 +1478,6 @@ void dump_cache(time_t now) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0else if (cache->flags & F_CNAME) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0t =3D "C"; > - #ifdef HAVE_DNSSEC > -- =C2=A0=C2=A0=C2=A0=C2=A0else if ((cache->flags & (F_DS | F_DNSKEY)) =3D= =3D (F_DS | > F_DNSKEY)) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0t =3D "G"; /* DNSKEY and DS set -> R= RISG */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0else if (cache->flags & F_DS) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0t =3D "S"; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0else if (cache->flags & F_DNSKEY) > -diff --git a/src/dnsmasq.h b/src/dnsmasq.h > -index 023a1cf..4344cae 100644 > ---- a/src/dnsmasq.h > -+++ b/src/dnsmasq.h > -@@ -398,14 +398,9 @@ struct crec { > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char algo; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char digest;=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} ds;=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0struct { > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct blockdata *keydata; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned short keylen, type_covered, = keytag; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0char algo; > --=C2=A0=C2=A0=C2=A0=C2=A0} sig; > -=C2=A0=C2=A0=C2=A0} addr; > -=C2=A0=C2=A0=C2=A0time_t ttd; /* time to die */ > --=C2=A0=C2=A0/* used as class if DNSKEY/DS/RRSIG, index to source for F_HO= STS > */ > -+=C2=A0=C2=A0/* used as class if DNSKEY/DS, index to source for F_HOSTS */ > -=C2=A0=C2=A0=C2=A0unsigned int uid;=C2=A0 > -=C2=A0=C2=A0=C2=A0unsigned short flags; > -=C2=A0=C2=A0=C2=A0union { > -@@ -445,8 +440,7 @@ struct crec { > - #define F_SECSTAT=C2=A0=C2=A0=C2=A0(1u<<24) > - #define F_NO_RR=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(1u<<25) > - #define F_IPSET=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(1u<<26) > --#define F_NSIGMATCH (1u<<27) > --#define F_NOEXTRA=C2=A0=C2=A0=C2=A0(1u<<28) > -+#define F_NOEXTRA=C2=A0=C2=A0=C2=A0(1u<<27) > -=C2=A0 > - /* Values of uid in crecs with F_CONFIG bit set. */ > - #define SRC_INTERFACE 0 > -diff --git a/src/dnssec.c b/src/dnssec.c > -index de7b335..1ae03a6 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -1004,7 +1004,7 @@ int dnssec_validate_by_ds(time_t now, struct > dns_header *header, size_t plen, ch > - { > -=C2=A0=C2=A0=C2=A0unsigned char *psave, *p =3D (unsigned char *)(header+1); > -=C2=A0=C2=A0=C2=A0struct crec *crecp, *recp1; > --=C2=A0=C2=A0int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, key= tag, > type_covered; > -+=C2=A0=C2=A0int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, key= tag; > -=C2=A0=C2=A0=C2=A0struct blockdata *key; > -=C2=A0=C2=A0=C2=A0struct all_addr a; > -=C2=A0 > -@@ -1115,7 +1115,7 @@ int dnssec_validate_by_ds(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if (valid) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* DNSKEY RRset determined to be OK, = now cache it and the > RRsigs that sign it. */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* DNSKEY RRset determined to be OK, = now cache it. */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0cache_start_insert(); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p =3D skip_questions(header, ple= n); > -@@ -1155,7 +1155,10 @@ int dnssec_validate_by_ds(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0if ((key =3D blockdata_alloc((char*)p, rdlen - 4))) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(recp1 =3D cache_insert(n= ame, &a, now, > ttl, F_FORWARD | F_DNSKEY | F_DNSSECOK))) > -- blockdata_free(key); > -+ { > -+ =C2=A0=C2=A0blockdata_free(key); > -+ =C2=A0=C2=A0return STAT_BOGUS; > -+ } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0a.addr.keytag =3D keytag; > -@@ -1169,38 +1172,7 @@ int dnssec_validate_by_ds(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 } > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (qtype =3D=3D T_RRSIG) > -- { > -- =C2=A0=C2=A0/* RRSIG, cache if covers DNSKEY RRset */ > -- =C2=A0=C2=A0if (rdlen < 18) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0GETSHORT(type_covered, p); > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (type_covered =3D=3D T_DNSKEY) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0a.addr.dnssec.class =3D class; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0a.addr.dnssec.type =3D type_covered; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0algo =3D *p++; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 13; /* labels, orig_ttl, exp= iration, > inception */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(keytag, p);=09 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((key =3D blockdata_alloc((char*= )psave, > rdlen))) > -- { > -- =C2=A0=C2=A0if (!(crecp =3D cache_insert(name, &a, now, > ttl,=C2=A0=C2=A0F_FORWARD | F_DNSKEY | F_DS))) > -- =C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(key); > -- =C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.sig.keydata =3D key; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.sig.keylen =3D rdlen; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.sig.keytag =3D keytag; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.sig.type_covered =3D > type_covered; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.sig.algo =3D algo; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p =3D psave; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > -@@ -1326,7 +1298,8 @@ int dnssec_validate_ds(time_t now, struct > dns_header *header, size_t plen, char > -=C2=A0 =C2=A0=C2=A0cache_start_insert(); > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0a.addr.dnssec.class =3D class; > -- =C2=A0=C2=A0cache_insert(name, &a, now, ttl, flags); > -+ =C2=A0=C2=A0if (!cache_insert(name, &a, now, ttl, flags)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0cache_end_insert();=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0 > -@@ -2028,14 +2001,13 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0/* Not done, validate now */ > -=C2=A0 =C2=A0=C2=A0if (j =3D=3D i) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int ttl, keytag, algo, digest, type_= covered, sigcnt, > rrcnt; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int ttl, keytag, algo, digest, sigcn= t, rrcnt; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *psave; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct all_addr a; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct blockdata *key; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct crec *crecp; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0char *wildname; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int have_wildcard =3D 0; > -- > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!explore_rrset(header, plen= , class1, type1, name, > keyname, &sigcnt, &rrcnt)) > -=C2=A0 return STAT_BOGUS; > -=C2=A0 > -@@ -2096,8 +2068,6 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0if (rc =3D=3D STAT_SECURE_WILDCARD) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0have_wildcard =3D 1; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* An attacker replay a wildca= rd answer with > a different > -=C2=A0 =C2=A0answer and overlay a genuine RR. To prove > this > -=C2=A0 =C2=A0hasn't happened, the answer must prove > that > -@@ -2119,7 +2089,7 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 return rc; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0/* Cache RRsigs in answer section, and if we just > validated a DS RRset, cache it */ > -+ =C2=A0=C2=A0/* If we just validated a DS RRset, cache it */ > -=C2=A0 =C2=A0=C2=A0/* Also note if the RRset is the answer to the > question, or the target of a CNAME */ > -=C2=A0 =C2=A0=C2=A0cache_start_insert(); > -=C2=A0 =C2=A0=C2=A0 > -@@ -2168,45 +2138,7 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -=C2=A0 } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else if (type2 =3D=3D T_RRSIG) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rdlen2 < 18) > -- return STAT_BOGUS; /* bad packet */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(type_covered, p2); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (type_covered =3D=3D type1 &&= =C2=A0 > -- =C2=A0=C2=A0(type_covered =3D=3D T_A || > type_covered =3D=3D T_AAAA || > -- =C2=A0=C2=A0=C2=A0type_covered =3D=3D T_CNAME || > type_covered =3D=3D T_DS ||=C2=A0 > -- =C2=A0=C2=A0=C2=A0type_covered =3D=3D T_DNSKEY || > type_covered =3D=3D T_PTR))=C2=A0 > -- { > -- =C2=A0=C2=A0a.addr.dnssec.type =3D > type_covered; > -- =C2=A0=C2=A0a.addr.dnssec.class =3D class1; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0algo =3D *p2++; > -- =C2=A0=C2=A0p2 +=3D 13; /* labels, orig_ttl, > expiration, inception */ > -- =C2=A0=C2=A0GETSHORT(keytag, p2); > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0/* We don't cache sigs for > wildcard answers, because to reproduce the > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0answer from the cache will > require one or more NSEC/NSEC3 records=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0which we don't cache. The lack > of the RRSIG ensures that a query for > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0this RRset asking for a secure > answer will always be forwarded. */ > -- =C2=A0=C2=A0if (!have_wildcard && (key =3D > blockdata_alloc((char*)psave, rdlen2))) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(crecp =3D > cache_insert(name, &a, now, ttl,=C2=A0=C2=A0F_FORWARD | F_DNSKEY | F_DS))) > -- blockdata_free(key); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -- { > -- =C2=A0=C2=A0crecp->addr.sig.keydata =3D > key; > -- =C2=A0=C2=A0crecp->addr.sig.keylen =3D > rdlen2; > -- =C2=A0=C2=A0crecp->addr.sig.keytag =3D > keytag; > -- =C2=A0=C2=A0crecp- > >addr.sig.type_covered =3D type_covered; > -- =C2=A0=C2=A0crecp->addr.sig.algo =3D > algo; > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -+ > -=C2=A0 =C2=A0=C2=A0p2 =3D psave; > -=C2=A0 } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -diff --git a/src/rfc1035.c b/src/rfc1035.c > -index 4eb1772..def8fa0 100644 > ---- a/src/rfc1035.c > -+++ b/src/rfc1035.c > -@@ -1275,11 +1275,9 @@ int check_for_local_domain(char *name, time_t > now) > -=C2=A0=C2=A0=C2=A0struct naptr *naptr; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0/* Note: the call to cache_find_by_name is intended to f= ind any > record which matches > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ie A, AAAA, CNAME, DS. Because RRSIG record= s are marked by > setting both F_DS and F_DNSKEY, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0cache_find_by name ordinarily only returns = records with an > exact match on those bits (ie > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for the call below, only DS records). The F= _NSIGMATCH bit > changes this behaviour */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ie A, AAAA, CNAME. */ > -=C2=A0 > --=C2=A0=C2=A0if ((crecp =3D cache_find_by_name(NULL, name, now, F_IPV4 | F= _IPV6 > | F_CNAME | F_DS | F_NO_RR | F_NSIGMATCH)) && > -+=C2=A0=C2=A0if ((crecp =3D cache_find_by_name(NULL, name, now, F_IPV4 | F= _IPV6 > | F_CNAME |F_NO_RR)) && > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(crecp->flags & (F_HOSTS | F_DHC= P | F_CONFIG))) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return 1; > -=C2=A0=C2=A0=C2=A0 > -@@ -1566,9 +1564,11 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(flags, pheader); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((sec_reqd =3D flags & 0x8000= )) > -- *do_bit =3D 1;/* do bit */=C2=A0 > -+ { > -+ =C2=A0=C2=A0*do_bit =3D 1;/* do bit */=C2=A0 > -+ =C2=A0=C2=A0*ad_reqd =3D 1; > -+ } > -=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*ad_reqd =3D 1; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0dryrun =3D 1; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > -@@ -1636,98 +1636,6 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 } > -=C2=A0 > --#ifdef HAVE_DNSSEC > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (option_bool(OPT_DNSSEC_VALID) && = (qtype =3D=3D T_DNSKEY || > qtype =3D=3D T_DS)) > -- { > -- =C2=A0=C2=A0int gotone =3D 0; > -- =C2=A0=C2=A0struct blockdata *keydata; > -- > -- =C2=A0=C2=A0/* Do we have RRSIG? Can't do DS or DNSKEY otherwise. */ > -- =C2=A0=C2=A0if (sec_reqd) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp =3D NULL; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0while ((crecp =3D cache_find_by_name= (crecp, name, now, > F_DNSKEY | F_DS))) > -- if (crecp->uid =3D=3D qclass && crecp- > >addr.sig.type_covered =3D=3D qtype) > -- =C2=A0=C2=A0break; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (!sec_reqd || crecp) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (qtype =3D=3D T_DS) > -- { > -- =C2=A0=C2=A0crecp =3D NULL; > -- =C2=A0=C2=A0while ((crecp =3D cache_find_by_name(crecp, name, > now, F_DS))) > -- =C2=A0=C2=A0=C2=A0=C2=A0if (crecp->uid =3D=3D qclass) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- gotone =3D 1;=C2=A0 > -- if (!dryrun) > -- =C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0if (crecp->flags & F_NEG) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- if (crecp->flags & F_NXDOMAIN) > -- =C2=A0=C2=A0nxdomain =3D 1; > -- log_query(F_UPSTREAM, name, NULL, > "no DS");=09 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0=C2=A0=C2=A0else if ((keydata =3D > blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, > NULL))) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =09 > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- struct all_addr a; > -- a.addr.keytag =3D=C2=A0=C2=A0crecp- > >addr.ds.keytag; > -- log_query(F_KEYTAG | (crecp->flags > & F_CONFIG), name, &a, "DS keytag %u"); > -- if (add_resource_record(header, > limit, &trunc, nameoffset, &ansp,=C2=A0 > -- crec_ttl(cr > ecp, now), &nameoffset, > -- T_DS, > qclass, "sbbt",=C2=A0 > -- crecp- > >addr.ds.keytag, crecp->addr.ds.algo,=C2=A0 > -- crecp- > >addr.ds.digest, crecp->addr.ds.keylen, keydata)) > -- =C2=A0=C2=A0anscount++; > -- =09 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -- =C2=A0=C2=A0} > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else /* DNSKEY */ > -- { > -- =C2=A0=C2=A0crecp =3D NULL; > -- =C2=A0=C2=A0while ((crecp =3D cache_find_by_name(crecp, name, > now, F_DNSKEY))) > -- =C2=A0=C2=A0=C2=A0=C2=A0if (crecp->uid =3D=3D qclass) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- gotone =3D 1; > -- if (!dryrun && (keydata =3D > blockdata_retrieve(crecp->addr.key.keydata, crecp->addr.key.keylen, > NULL))) > -- =C2=A0=C2=A0{ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =09 > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0struct all_addr a; > -- =C2=A0=C2=A0=C2=A0=C2=A0a.addr.keytag =3D=C2=A0=C2=A0crecp- > >addr.key.keytag; > -- =C2=A0=C2=A0=C2=A0=C2=A0log_query(F_KEYTAG | (crecp->flags & > F_CONFIG), name, &a, "DNSKEY keytag %u"); > -- =C2=A0=C2=A0=C2=A0=C2=A0if (add_resource_record(header, limit, > &trunc, nameoffset, &ansp,=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0crec_ttl(crecp, > now), &nameoffset, > -- =C2=A0=C2=A0=C2=A0=C2=A0T_DNSKEY, > qclass, "sbbt",=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0crecp- > >addr.key.flags, 3, crecp->addr.key.algo, crecp->addr.key.keylen, > keydata)) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0anscount++; > -- =C2=A0=C2=A0} > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0/* Now do RRSIGs */ > -- =C2=A0=C2=A0if (gotone) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ans =3D 1; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0auth =3D 0; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!dryrun && sec_reqd) > -- { > -- =C2=A0=C2=A0crecp =3D NULL; > -- =C2=A0=C2=A0while ((crecp =3D cache_find_by_name(crecp, name, > now, F_DNSKEY | F_DS))) > -- =C2=A0=C2=A0=C2=A0=C2=A0if (crecp->uid =3D=3D qclass && crecp- > >addr.sig.type_covered =3D=3D qtype && > -- (keydata =3D blockdata_retrieve(crecp- > >addr.sig.keydata, crecp->addr.sig.keylen, NULL))) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- add_resource_record(header, limit, &trunc, > nameoffset, &ansp,=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0crec_ttl(crecp, now), > &nameoffset, > -- =C2=A0=C2=A0=C2=A0=C2=A0T_RRSIG, qclass, "t", > crecp->addr.sig.keylen, keydata); > -- anscount++; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- } > --#endif =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (qclass =3D=3D C_IN) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0struct txt_record *t; > -@@ -1736,6 +1644,7 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0if ((t->class =3D=3D qtype || qtype =3D=3D = T_ANY) && > hostname_isequal(name, t->name)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 ans =3D 1; > -+ sec_data =3D 0; > -=C2=A0 if (!dryrun) > -=C2=A0 =C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0log_query(F_CONFIG | F_RRNAME, name, NULL, > "<RR>"); > -@@ -1792,6 +1701,7 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (intr) > -=C2=A0 { > -+ =C2=A0=C2=A0sec_data =3D 0; > -=C2=A0 =C2=A0=C2=A0ans =3D 1; > -=C2=A0 =C2=A0=C2=A0if (!dryrun) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -@@ -1805,6 +1715,7 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (ptr) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0ans =3D 1; > -+ =C2=A0=C2=A0sec_data =3D 0; > -=C2=A0 =C2=A0=C2=A0if (!dryrun) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0log_query(F_CONFIG | F_RRNAME,= name, NULL, > "<PTR>"); > -@@ -1819,38 +1730,8 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if ((crecp =3D cache_find_= by_addr(NULL, &addr, > now, is_arpa))) > -=C2=A0 { > -- =C2=A0=C2=A0if (!(crecp->flags & (F_HOSTS | F_DHCP | > F_CONFIG)) && sec_reqd) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!option_bool(OPT_DNSSEC_VALID) = || > ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK))) > -- crecp =3D NULL; > --#ifdef HAVE_DNSSEC > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (crecp->flags & F_DNSSECOK) > -- { > -- =C2=A0=C2=A0int gotsig =3D 0; > -- =C2=A0=C2=A0struct crec *rr_crec =3D NULL; > -- > -- =C2=A0=C2=A0while ((rr_crec =3D > cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY))) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rr_crec->addr.sig.type_covered= =3D=3D > T_PTR && rr_crec->uid =3D=3D C_IN) > -- { > -- =C2=A0=C2=A0char *sigdata =3D > blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec- > >addr.sig.keylen, NULL); > -- =C2=A0=C2=A0gotsig =3D 1; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (!dryrun &&=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0add_resource_record(header, > limit, &trunc, nameoffset, &ansp,=C2=A0 > -- =C2=A0=C2=A0rr_crec- > >ttd - now, &nameoffset, > -- =C2=A0=C2=A0T_RRSIG, > C_IN, "t", crecp->addr.sig.keylen, sigdata)) > -- =C2=A0=C2=A0=C2=A0=C2=A0anscount++; > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (!gotsig) > -- =C2=A0=C2=A0=C2=A0=C2=A0crecp =3D NULL; > -- } > --#endif > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- > -- =C2=A0=C2=A0if (crecp) > -+ =C2=A0=C2=A0/* Don't use cache when DNSSEC data required. */ > -+ =C2=A0=C2=A0if ((crecp->flags & (F_HOSTS | F_DHCP | > F_CONFIG)) || !sec_reqd || !(crecp->flags & F_DNSSECOK)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0do=C2=A0 > -=C2=A0 {=C2=A0 > -@@ -1860,19 +1741,19 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0if (!(crecp->flags & F_DNSSECOK)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0sec_data =3D 0; > -- =C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0ans =3D 1; > -+ =C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0if (crecp->flags & F_NEG) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ans =3D 1; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0auth =3D 0; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->flags & F_NXDOMAIN) > -=C2=A0 nxdomain =3D 1; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!dryrun) > -=C2=A0 log_query(crecp->flags & > ~F_FORWARD, name, &addr, NULL); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else if ((crecp->flags & (F_HOSTS | > F_DHCP)) || !sec_reqd || option_bool(OPT_DNSSEC_VALID)) > -+ =C2=A0=C2=A0else > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ans =3D 1; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(crecp->flags & (F_HOSTS= | > F_DHCP))) > -=C2=A0 auth =3D 0; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!dryrun) > -@@ -1892,6 +1773,7 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (is_rev_synth(is_arpa, = &addr, name)) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0ans =3D 1; > -+ =C2=A0=C2=A0sec_data =3D 0; > -=C2=A0 =C2=A0=C2=A0if (!dryrun) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0log_query(F_CONFIG | F_REVERSE= | is_arpa, > name, &addr, NULL);=C2=A0 > -@@ -1908,6 +1790,7 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0/* if not in cache, enabled and private IPV4 > address, return NXDOMAIN */ > -=C2=A0 =C2=A0=C2=A0ans =3D 1; > -+ =C2=A0=C2=A0sec_data =3D 0; > -=C2=A0 =C2=A0=C2=A0nxdomain =3D 1; > -=C2=A0 =C2=A0=C2=A0if (!dryrun) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0log_query(F_CONFIG | F_REVERSE | F_IPV4 | = F_NEG > | F_NXDOMAIN,=C2=A0 > -@@ -1955,6 +1838,7 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 =C2=A0=C2=A0if (i =3D=3D 4) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ans =3D 1; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0sec_data =3D 0; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!dryrun) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0addr.addr.addr4.s_addr =3D htonl(a); > -@@ -1993,6 +1877,7 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 continue; > - #endif=09 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ans =3D 1;=09 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0sec_data =3D 0; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!dryrun) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0gotit =3D 1; > -@@ -2032,48 +1917,8 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp =3D save; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > -- =C2=A0=C2=A0/* If the client asked for DNSSEC and we can't > provide RRSIGs, either > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0because we've not doing DNSSEC or the cac= hed > answer is signed by negative, > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0don't answer from the cache, forward inst= ead. > */ > -- =C2=A0=C2=A0if (!(crecp->flags & (F_HOSTS | F_DHCP | > F_CONFIG)) && sec_reqd) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!option_bool(OPT_DNSSEC_VALID) = || > ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK))) > -- crecp =3D NULL; > --#ifdef HAVE_DNSSEC > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (crecp->flags & F_DNSSECOK) > -- { > -- =C2=A0=C2=A0/* We're returning validated data, need > to return the RRSIG too. */ > -- =C2=A0=C2=A0struct crec *rr_crec =3D NULL; > -- =C2=A0=C2=A0int sigtype =3D type; > -- =C2=A0=C2=A0/* The signature may have expired even > though the data is still in cache,=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0forward instead of answering from > cache if so. */ > -- =C2=A0=C2=A0int gotsig =3D 0; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (crecp->flags & F_CNAME) > -- =C2=A0=C2=A0=C2=A0=C2=A0sigtype =3D T_CNAME; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0while ((rr_crec =3D > cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY))) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rr_crec->addr.sig.type_covered= =3D=3D > sigtype && rr_crec->uid =3D=3D C_IN) > -- { > -- =C2=A0=C2=A0char *sigdata =3D > blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec- > >addr.sig.keylen, NULL); > -- =C2=A0=C2=A0gotsig =3D 1; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (!dryrun &&=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0add_resource_record(header, > limit, &trunc, nameoffset, &ansp,=C2=A0 > -- =C2=A0=C2=A0rr_crec- > >ttd - now, &nameoffset, > -- =C2=A0=C2=A0T_RRSIG, > C_IN, "t", rr_crec->addr.sig.keylen, sigdata)) > -- =C2=A0=C2=A0=C2=A0=C2=A0anscount++; > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (!gotsig) > -- =C2=A0=C2=A0=C2=A0=C2=A0crecp =3D NULL; > -- } > --#endif > -- =C2=A0=C2=A0=C2=A0=C2=A0} =C2=A0 > -- > -- =C2=A0=C2=A0if (crecp) > -+ =C2=A0=C2=A0/* If the client asked for DNSSEC=C2=A0=C2=A0don't use > cached data. */ > -+ =C2=A0=C2=A0if ((crecp->flags & (F_HOSTS | F_DHCP | > F_CONFIG)) || !sec_reqd || !(crecp->flags & F_DNSSECOK)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0do > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{=C2=A0 > -=C2=A0 /* don't answer wildcard queries with data > not from /etc/hosts > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/018- > Move_code_which_caches_DS_records_to_a_more_logical_place.patch > b/src/patches/dnsmasq/018- > Move_code_which_caches_DS_records_to_a_more_logical_place.patch > deleted file mode 100644 > index ff055f7..0000000 > --- a/src/patches/dnsmasq/018- > Move_code_which_caches_DS_records_to_a_more_logical_place.patch > +++ /dev/null > @@ -1,269 +0,0 @@ > -From d64c81fff7faf4392b688223ef3a617c5c07e7dc Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Tue, 15 Dec 2015 16:11:06 +0000 > -Subject: [PATCH] Move code which caches DS records to a more logical > place. > - > ---- > - src/dnssec.c |=C2=A0=C2=A0179 +++++++++++++++++++++++++++++--------------= -- > ------------- > - 1 file changed, 90 insertions(+), 89 deletions(-) > - > -diff --git a/src/dnssec.c b/src/dnssec.c > -index 1ae03a6..359231f 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -1204,7 +1204,10 @@ int dnssec_validate_by_ds(time_t now, struct > dns_header *header, size_t plen, ch > - int dnssec_validate_ds(time_t now, struct dns_header *header, > size_t plen, char *name, char *keyname, int class) > - { > -=C2=A0=C2=A0=C2=A0unsigned char *p =3D (unsigned char *)(header+1); > --=C2=A0=C2=A0int qtype, qclass, val, i, neganswer, nons; > -+=C2=A0=C2=A0int qtype, qclass, rc, i, neganswer, nons; > -+=C2=A0=C2=A0int aclass, atype, rdlen; > -+=C2=A0=C2=A0unsigned long ttl; > -+=C2=A0=C2=A0struct all_addr a; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if (ntohs(header->qdcount) !=3D 1 || > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0!(p =3D skip_name(p, header, ple= n, 4))) > -@@ -1214,40 +1217,100 @@ int dnssec_validate_ds(time_t now, struct > dns_header *header, size_t plen, char > -=C2=A0=C2=A0=C2=A0GETSHORT(qclass, p); > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if (qtype !=3D T_DS || qclass !=3D class) > --=C2=A0=C2=A0=C2=A0=C2=A0val =3D STAT_BOGUS; > -+=C2=A0=C2=A0=C2=A0=C2=A0rc =3D STAT_BOGUS; > -=C2=A0=C2=A0=C2=A0else > --=C2=A0=C2=A0=C2=A0=C2=A0val =3D dnssec_validate_reply(now, header, plen, = name, keyname, > NULL, 0, &neganswer, &nons); > -+=C2=A0=C2=A0=C2=A0=C2=A0rc =3D dnssec_validate_reply(now, header, plen, n= ame, keyname, > NULL, 0, &neganswer, &nons); > -=C2=A0=C2=A0=C2=A0/* Note dnssec_validate_reply() will have cached positiv= e answers > */ > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0if (val =3D=3D STAT_INSECURE) > --=C2=A0=C2=A0=C2=A0=C2=A0val =3D STAT_BOGUS; > -- > -+=C2=A0=C2=A0if (rc =3D=3D STAT_INSECURE) > -+=C2=A0=C2=A0=C2=A0=C2=A0rc =3D STAT_BOGUS; > -+=C2=A0 > -=C2=A0=C2=A0=C2=A0p =3D (unsigned char *)(header+1); > -=C2=A0=C2=A0=C2=A0extract_name(header, plen, &p, name, 1, 4); > -=C2=A0=C2=A0=C2=A0p +=3D 4; /* qtype, qclass */ > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0if (!(p =3D skip_section(p, ntohs(header->ancount), header, p= len))) > --=C2=A0=C2=A0=C2=A0=C2=A0val =3D STAT_BOGUS; > --=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0/* If the key needed to validate the DS is on the same d= omain as > the DS, we'll > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0loop getting nowhere. Stop that now. T= his can happen of the DS > answer comes > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0from the DS's zone, and not the parent= zone. */ > --=C2=A0=C2=A0if (val =3D=3D STAT_BOGUS || (val =3D=3D STAT_NEED_KEY && > hostname_isequal(name, keyname))) > -+=C2=A0=C2=A0if (rc =3D=3D STAT_BOGUS || (rc =3D=3D STAT_NEED_KEY && > hostname_isequal(name, keyname))) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0log_query(F_NOEXTRA | F_UPSTREAM= , name, NULL, "BOGUS DS"); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0if (val !=3D STAT_SECURE) > --=C2=A0=C2=A0=C2=A0=C2=A0return val; > -- > --=C2=A0=C2=A0/* By here, the answer is proved secure, and a positive answer > has been cached. */ > --=C2=A0=C2=A0if (neganswer) > -+=C2=A0=C2=A0if (rc !=3D STAT_SECURE) > -+=C2=A0=C2=A0=C2=A0=C2=A0return rc; > -+=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0if (!neganswer) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int rdlen, flags =3D F_FORWARD | F_DS= | F_NEG | F_DNSSECOK; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned long ttl, minttl =3D ULONG_M= AX; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct all_addr a; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0cache_start_insert(); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (i =3D 0; i < ntohs(header->ancou= nt); i++) > -+ { > -+ =C2=A0=C2=A0if (!(rc =3D extract_name(header, plen, &p, name, 0, 10))) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0GETSHORT(atype, p); > -+ =C2=A0=C2=A0GETSHORT(aclass, p); > -+ =C2=A0=C2=A0GETLONG(ttl, p); > -+ =C2=A0=C2=A0GETSHORT(rdlen, p); > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (!CHECK_LEN(header, p, plen, rdlen)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (aclass =3D=3D class && atype =3D=3D T_DS && rc =3D=3D 1) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int algo, digest, keytag; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *psave =3D p; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct blockdata *key; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct crec *crecp; > -=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rdlen < 4) > -+ return STAT_BOGUS; /* bad packet */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(keytag, p); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0algo =3D *p++; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0digest =3D *p++; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Cache needs to known class for DN= SSEC stuff */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0a.addr.dnssec.class =3D class; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((key =3D blockdata_alloc((char*)= p, rdlen - 4))) > -+ { > -+ =C2=A0=C2=A0if (!(crecp =3D cache_insert(name, &a, now, ttl, > F_FORWARD | F_DS | F_DNSSECOK))) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(key); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0else > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0a.addr.keytag =3D keytag; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0log_query(F_NOEXTRA | F_KEYTAG | F_= UPSTREAM, > name, &a, "DS keytag %u"); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.digest =3D digest; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.keydata =3D key; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.algo =3D algo; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.keytag =3D keytag; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.keylen =3D rdlen - 4= ;=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -+ } > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p =3D psave; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!ADD_RDLEN(header, p, plen, rdle= n)) > -+ return STAT_BOGUS; /* bad packet */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0cache_end_insert(); > -+ } > -+=C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0else > -+=C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int flags =3D F_FORWARD | F_DS | F_NE= G | F_DNSSECOK; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned long minttl =3D ULONG_MAX; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(p =3D skip_section(p, ntohs(hea= der->ancount), header, > plen))) > -+ return STAT_BOGUS; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (RCODE(header) =3D=3D NXDOMAI= N) > -=C2=A0 flags |=3D F_NXDOMAIN; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -@@ -1261,20 +1324,20 @@ int dnssec_validate_ds(time_t now, struct > dns_header *header, size_t plen, char > -=C2=A0 =C2=A0=C2=A0if (!(p =3D skip_name(p, header, plen, 0))) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0GETSHORT(qtype, p);=C2=A0 > -- =C2=A0=C2=A0GETSHORT(qclass, p); > -+ =C2=A0=C2=A0GETSHORT(atype, p);=C2=A0 > -+ =C2=A0=C2=A0GETSHORT(aclass, p); > -=C2=A0 =C2=A0=C2=A0GETLONG(ttl, p); > -=C2=A0 =C2=A0=C2=A0GETSHORT(rdlen, p); > -- > -+ =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0if (!CHECK_LEN(header, p, plen, rdlen)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -- =C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0if (qclass !=3D class || qtype !=3D T_SOA) > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (aclass !=3D class || atype !=3D T_SOA) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D rdlen; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0continue; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0if (ttl < minttl) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0minttl =3D ttl; > -=C2=A0 =C2=A0=C2=A0 > -@@ -1306,7 +1369,7 @@ int dnssec_validate_ds(time_t now, struct > dns_header *header, size_t plen, char > -=C2=A0 =C2=A0=C2=A0log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "no DS"); > -=C2=A0 } > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -- > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0return STAT_OK; > - } > -=C2=A0 > -@@ -2001,11 +2064,7 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0/* Not done, validate now */ > -=C2=A0 =C2=A0=C2=A0if (j =3D=3D i) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int ttl, keytag, algo, digest, sigcn= t, rrcnt; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *psave; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct all_addr a; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct blockdata *key; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct crec *crecp; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int sigcnt, rrcnt; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0char *wildname; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!explore_rrset(header, plen= , class1, type1, name, > keyname, &sigcnt, &rrcnt)) > -@@ -2032,6 +2091,7 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0Can't overwrite name here. */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0strcpy(daemon->workspacename, k= eyname); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0rc =3D zone_status(daemon->work= spacename, class1, > keyname, now); > -+ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rc !=3D STAT_SECURE) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0/* Zone is insecure, don't need to validate RRset > */ > -@@ -2088,65 +2148,6 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rc =3D=3D STAT_BOGUS) > -=C2=A0 return rc; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0/* If we just validated a DS RRset, cache it */ > -- =C2=A0=C2=A0/* Also note if the RRset is the answer to the > question, or the target of a CNAME */ > -- =C2=A0=C2=A0cache_start_insert(); > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0for (p2 =3D ans_start, j =3D 0; j < ntohs(header- > >ancount); j++) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(rc =3D extract_name(header, p= len, &p2, > name, 0, 10))) > -- return STAT_BOGUS; /* bad packet */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(type2, p2); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(class2, p2); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETLONG(ttl, p2); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(rdlen2, p2); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!CHECK_LEN(header, p2, plen, rd= len2)) > -- return STAT_BOGUS; /* bad packet */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (class2 =3D=3D class1 && rc =3D= =3D 1) > -- {=C2=A0 > -- =C2=A0=C2=A0psave =3D p2; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (type1 =3D=3D T_DS && type2 =3D=3D T_DS) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rdlen2 < 4) > -- return STAT_BOGUS; /* bad packet */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(keytag, p2); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0algo =3D *p2++; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0digest =3D *p2++; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Cache needs to known class for > DNSSEC stuff */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0a.addr.dnssec.class =3D class2; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((key =3D blockdata_alloc((char= *)p2, > rdlen2 - 4))) > -- { > -- =C2=A0=C2=A0if (!(crecp =3D cache_insert(name, > &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK))) > -- =C2=A0=C2=A0=C2=A0=C2=A0blockdata_free(key); > -- =C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0a.addr.keytag =3D keytag; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0log_query(F_NOEXTRA | > F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u"); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.digest =3D > digest; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.keydata =3D key; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.algo =3D algo; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.keytag =3D > keytag; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.keylen =3D > rdlen2 - 4;=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- > -- =C2=A0=C2=A0p2 =3D psave; > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!ADD_RDLEN(header, p2, plen, rd= len2)) > -- return STAT_BOGUS; /* bad packet */ > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0cache_end_insert(); > -=C2=A0 } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 } > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/019-Generalise_RR- > filtering_code_for_use_with_EDNS0.patch b/src/patches/dnsmasq/019- > Generalise_RR-filtering_code_for_use_with_EDNS0.patch > deleted file mode 100644 > index 0a4942a..0000000 > --- a/src/patches/dnsmasq/019-Generalise_RR- > filtering_code_for_use_with_EDNS0.patch > +++ /dev/null > @@ -1,755 +0,0 @@ > -From c2bcd1e183bcc5fdd63811c045355fc57e36ecfd Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Tue, 15 Dec 2015 17:25:21 +0000 > -Subject: [PATCH] Generalise RR-filtering code, for use with EDNS0. > - > ---- > - Makefile=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A0=C2= =A03 +- > - bld/Android.mk |=C2=A0=C2=A0=C2=A0=C2=A02 +- > - src/dnsmasq.h=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A0=C2=A05 + > - src/dnssec.c=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0307 +-------------------------= ----------------- > ------- > - src/forward.c=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A0=C2=A02 +- > - src/rrfilter.c |=C2=A0=C2=A0339 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > - 6 files changed, 349 insertions(+), 309 deletions(-) > - create mode 100644 src/rrfilter.c > - > -diff --git a/Makefile b/Makefile > -index 4c87ea9..b664160 100644 > ---- a/Makefile > -+++ b/Makefile > -@@ -73,7 +73,8 @@ objs =3D cache.o rfc1035.o util.o option.o forward.o > network.o \ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0dnsmasq.o dhcp.o lease.o r= fc2131.o netlink.o dbus.o bpf.o \ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0helper.o tftp.o log.o conn= track.o dhcp6.o rfc3315.o \ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0dhcp-common.o outpacket.o = radv.o slaac.o auth.o ipset.o \ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0domain.o dnssec.o blockdata.o t= ables.o loop.o inotify.o > poll.o > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0domain.o dnssec.o blockdata.o t= ables.o loop.o inotify.o \ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0poll.o rrfilter.o > -=C2=A0 > - hdrs =3D dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0dns-protocol.h radv-protoc= ol.h ip6addr.h > -diff --git a/bld/Android.mk b/bld/Android.mk > -index 5364ee7..67b9c4b 100644 > ---- a/bld/Android.mk > -+++ b/bld/Android.mk > -@@ -10,7 +10,7 @@ LOCAL_SRC_FILES :=3D=C2=A0=C2=A0bpf.c cache.c dbus.c dhc= p.c > dnsmasq.c \ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0dhcp6.c rfc3315.c dhcp-common.c outpacket.= c \ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0radv.c slaac.c auth.c ipset.c domain.c \ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0dnssec.c dnssec-openssl.c blockdata.c tables.c > \ > -- =C2=A0=C2=A0=C2=A0=C2=A0loop.c inotify.c poll.c > -+ =C2=A0=C2=A0=C2=A0=C2=A0loop.c inotify.c poll.c rrfilter.c > -=C2=A0 > - LOCAL_MODULE :=3D dnsmasq > -=C2=A0 > -diff --git a/src/dnsmasq.h b/src/dnsmasq.h > -index 4344cae..39a930c 100644 > ---- a/src/dnsmasq.h > -+++ b/src/dnsmasq.h > -@@ -1513,3 +1513,8 @@ int poll_check(int fd, short event); > - void poll_listen(int fd, short event); > - int do_poll(int timeout); > -=C2=A0 > -+/* rrfilter.c */ > -+size_t rrfilter(struct dns_header *header, size_t plen, int mode); > -+u16 *rrfilter_desc(int type); > -+int expand_workspace(unsigned char ***wkspc, int *szp, int new); > -+ > -diff --git a/src/dnssec.c b/src/dnssec.c > -index 359231f..fa3eb81 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -507,50 +507,6 @@ static int check_date_range(unsigned long > date_start, unsigned long date_end) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0&& serial_compare_32(curtime, date_end) =3D= =3D SERIAL_LT; > - } > -=C2=A0 > --static u16 *get_desc(int type) > --{ > --=C2=A0=C2=A0/* List of RRtypes which include domains in the data. > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A00 -> domain > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0integer -> no of plain bytes > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0-1 -> end > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0zero is not a valid RRtype, so the final en= try is returned for > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0anything which needs no mangling. > --=C2=A0=C2=A0*/ > --=C2=A0=C2=A0 > --=C2=A0=C2=A0static u16 rr_desc[] =3D=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0{=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_NS, 0, -1,=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MD, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MF, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_CNAME, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_SOA, 0, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MB, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MG, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MR, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_PTR, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MINFO, 0, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MX, 2, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_RP, 0, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_AFSDB, 2, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_RT, 2, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_SIG, 18, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_PX, 2, 0, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_NXT, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_KX, 2, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_SRV, 6, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_DNAME, 0, -1, > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A00, -1 /* wildcard/catchall */ > --=C2=A0=C2=A0=C2=A0=C2=A0};=C2=A0 > --=C2=A0=C2=A0 > --=C2=A0=C2=A0u16 *p =3D rr_desc; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0while (*p !=3D type && *p !=3D 0) > --=C2=A0=C2=A0=C2=A0=C2=A0while (*p++ !=3D (u16)-1); > -- > --=C2=A0=C2=A0return p+1; > --} > -- > - /* Return bytes of canonicalised rdata, when the return value is > zero, the remaining=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0data, pointed to by *p, should be used raw. */ > - static int get_rdata(struct dns_header *header, size_t plen, > unsigned char *end, char *buff, int bufflen, > -@@ -594,34 +550,6 @@ static int get_rdata(struct dns_header *header, > size_t plen, unsigned char *end, > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > - } > -=C2=A0 > --static int expand_workspace(unsigned char ***wkspc, int *szp, int > new) > --{ > --=C2=A0=C2=A0unsigned char **p; > --=C2=A0=C2=A0int old =3D *szp; > -- > --=C2=A0=C2=A0if (old >=3D new+1) > --=C2=A0=C2=A0=C2=A0=C2=A0return 1; > -- > --=C2=A0=C2=A0if (new >=3D 100) > --=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -- > --=C2=A0=C2=A0new +=3D 5; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0if (!(p =3D whine_malloc(new * sizeof(unsigned char **)))) > --=C2=A0=C2=A0=C2=A0=C2=A0return 0;=C2=A0=C2=A0 > --=C2=A0=C2=A0 > --=C2=A0=C2=A0if (old !=3D 0 && *wkspc) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0memcpy(p, *wkspc, old * sizeof(unsign= ed char **)); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free(*wkspc); > --=C2=A0=C2=A0=C2=A0=C2=A0} > --=C2=A0=C2=A0 > --=C2=A0=C2=A0*wkspc =3D p; > --=C2=A0=C2=A0*szp =3D new; > -- > --=C2=A0=C2=A0return 1; > --} > -- > - /* Bubble sort the RRset into the canonical order.=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0Note that the byte-streams from two RRs may get un= synced: > consider=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0RRs which have two domain-names at the start and t= hen other > data. > -@@ -849,7 +777,7 @@ static int validate_rrset(time_t now, struct > dns_header *header, size_t plen, in > -=C2=A0=C2=A0=C2=A0int rdlen, j, name_labels; > -=C2=A0=C2=A0=C2=A0struct crec *crecp =3D NULL; > -=C2=A0=C2=A0=C2=A0int algo, labels, orig_ttl, key_tag; > --=C2=A0=C2=A0u16 *rr_desc =3D get_desc(type); > -+=C2=A0=C2=A0u16 *rr_desc =3D rrfilter_desc(type); > -=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0if (wildcard_out) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*wildcard_out =3D NULL; > -@@ -2266,239 +2194,6 @@ size_t dnssec_generate_query(struct > dns_header *header, char *end, char *name, i > -=C2=A0=C2=A0=C2=A0return ret; > - } > -=C2=A0 > --/* Go through a domain name, find "pointers" and fix them up based > on how many bytes > --=C2=A0=C2=A0=C2=A0we've chopped out of the packet, or check they don't po= int into > an elided part.=C2=A0=C2=A0*/ > --static int check_name(unsigned char **namep, struct dns_header > *header, size_t plen, int fixup, unsigned char **rrs, int rr_count) > --{ > --=C2=A0=C2=A0unsigned char *ansp =3D *namep; > -- > --=C2=A0=C2=A0while(1) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned int label_type; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!CHECK_LEN(header, ansp, plen, 1)) > -- return 0; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0label_type =3D (*ansp) & 0xc0; > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (label_type =3D=3D 0xc0) > -- { > -- =C2=A0=C2=A0/* pointer for compression. */ > -- =C2=A0=C2=A0unsigned int offset; > -- =C2=A0=C2=A0int i; > -- =C2=A0=C2=A0unsigned char *p; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (!CHECK_LEN(header, ansp, plen, 2)) > -- =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -- > -- =C2=A0=C2=A0offset =3D ((*ansp++) & 0x3f) << 8; > -- =C2=A0=C2=A0offset |=3D *ansp++; > -- > -- =C2=A0=C2=A0p =3D offset + (unsigned char *)header; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0for (i =3D 0; i < rr_count; i++) > -- =C2=A0=C2=A0=C2=A0=C2=A0if (p < rrs[i]) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0break; > -- =C2=A0=C2=A0=C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (i & 1) > -- offset -=3D rrs[i] - rrs[i-1]; > -- > -- =C2=A0=C2=A0/* does the pointer end up in an elided RR? */ > -- =C2=A0=C2=A0if (i & 1) > -- =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -- > -- =C2=A0=C2=A0/* No, scale the pointer */ > -- =C2=A0=C2=A0if (fixup) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ansp -=3D 2; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*ansp++ =3D (offset >> 8) | 0xc0; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*ansp++ =3D offset & 0xff; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0break; > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (label_type =3D=3D 0x80) > -- return 0; /* reserved */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (label_type =3D=3D 0x40) > -- { > -- =C2=A0=C2=A0/* Extended label type */ > -- =C2=A0=C2=A0unsigned int count; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (!CHECK_LEN(header, ansp, plen, 2)) > -- =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (((*ansp++) & 0x3f) !=3D 1) > -- =C2=A0=C2=A0=C2=A0=C2=A0return 0; /* we only understand bitstrings */ > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0count =3D *(ansp++); /* Bits in bitstring */ > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (count =3D=3D 0) /* count =3D=3D 0 means 256 bits */ > -- =C2=A0=C2=A0=C2=A0=C2=A0ansp +=3D 32; > -- =C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0ansp +=3D ((count-1)>>3)+1; > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -- { /* label type =3D=3D 0 Bottom six bits is length */ > -- =C2=A0=C2=A0unsigned int len =3D (*ansp++) & 0x3f; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (!ADD_RDLEN(header, ansp, plen, len)) > -- =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -- > -- =C2=A0=C2=A0if (len =3D=3D 0) > -- =C2=A0=C2=A0=C2=A0=C2=A0break; /* zero length label marks the end. */ > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0} > -- > --=C2=A0=C2=A0*namep =3D ansp; > -- > --=C2=A0=C2=A0return 1; > --} > -- > --/* Go through RRs and check or fixup the domain names contained > within */ > --static int check_rrs(unsigned char *p, struct dns_header *header, > size_t plen, int fixup, unsigned char **rrs, int rr_count) > --{ > --=C2=A0=C2=A0int i, type, class, rdlen; > --=C2=A0=C2=A0unsigned char *pp; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0for (i =3D 0; i < ntohs(header->ancount) + ntohs(header->nsco= unt) + > ntohs(header->arcount); i++) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0pp =3D p; > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(p =3D skip_name(p, header, plen= , 10))) > -- return 0; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(type, p);=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(class, p); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 4; /* TTL */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(rdlen, p); > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (type !=3D T_NSEC && type !=3D T_N= SEC3 && type !=3D T_RRSIG) > -- { > -- =C2=A0=C2=A0/* fixup name of RR */ > -- =C2=A0=C2=A0if (!check_name(&pp, header, plen, fixup, rrs, rr_count)) > -- =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (class =3D=3D C_IN) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0u16 *d; > --=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (pp =3D p, d =3D get_desc(type);= *d !=3D (u16)-1; d++) > -- { > -- =C2=A0=C2=A0if (*d !=3D 0) > -- =C2=A0=C2=A0=C2=A0=C2=A0pp +=3D *d; > -- =C2=A0=C2=A0else if (!check_name(&pp, header, plen, fixup, > rrs, rr_count)) > -- =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -- } > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!ADD_RDLEN(header, p, plen, rdlen= )) > -- return 0; > --=C2=A0=C2=A0=C2=A0=C2=A0} > --=C2=A0=C2=A0 > --=C2=A0=C2=A0return 1; > --} > --=09 > -- > --size_t filter_rrsigs(struct dns_header *header, size_t plen) > --{ > --=C2=A0=C2=A0static unsigned char **rrs; > --=C2=A0=C2=A0static int rr_sz =3D 0; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0unsigned char *p =3D (unsigned char *)(header+1); > --=C2=A0=C2=A0int i, rdlen, qtype, qclass, rr_found, chop_an, chop_ns, chop= _ar; > -- > --=C2=A0=C2=A0if (ntohs(header->qdcount) !=3D 1 || > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0!(p =3D skip_name(p, header, plen, 4)= )) > --=C2=A0=C2=A0=C2=A0=C2=A0return plen; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0GETSHORT(qtype, p); > --=C2=A0=C2=A0GETSHORT(qclass, p); > -- > --=C2=A0=C2=A0/* First pass, find pointers to start and end of all the reco= rds > we wish to elide: > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0records added for DNSSEC, unless explicity = queried for */ > --=C2=A0=C2=A0for (rr_found =3D 0, chop_ns =3D 0, chop_an =3D 0, chop_ar = =3D 0, i =3D 0;=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0i < ntohs(header->ancount) + nt= ohs(header->nscount) + > ntohs(header->arcount); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0i++) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *pstart =3D p; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int type, class; > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(p =3D skip_name(p, header, plen= , 10))) > -- return plen; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(type, p);=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(class, p); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 4; /* TTL */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(rdlen, p); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((type =3D=3D T_NSEC || type =3D= =3D T_NSEC3 || type =3D=3D T_RRSIG) > &&=C2=A0 > -- =C2=A0=C2=A0(type !=3D qtype || class !=3D qclass)) > -- { > -- =C2=A0=C2=A0if (!expand_workspace(&rrs, &rr_sz, rr_found + 1)) > -- =C2=A0=C2=A0=C2=A0=C2=A0return plen;=C2=A0 > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0rrs[rr_found++] =3D pstart; > -- > -- =C2=A0=C2=A0if (!ADD_RDLEN(header, p, plen, rdlen)) > -- =C2=A0=C2=A0=C2=A0=C2=A0return plen; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0rrs[rr_found++] =3D p; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (i < ntohs(header->ancount)) > -- =C2=A0=C2=A0=C2=A0=C2=A0chop_an++; > -- =C2=A0=C2=A0else if (i < (ntohs(header->nscount) + ntohs(header- > >ancount))) > -- =C2=A0=C2=A0=C2=A0=C2=A0chop_ns++; > -- =C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0chop_ar++; > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (!ADD_RDLEN(header, p, plen, = rdlen)) > -- return plen; > --=C2=A0=C2=A0=C2=A0=C2=A0} > --=C2=A0=C2=A0 > --=C2=A0=C2=A0/* Nothing to do. */ > --=C2=A0=C2=A0if (rr_found =3D=3D 0) > --=C2=A0=C2=A0=C2=A0=C2=A0return plen; > -- > --=C2=A0=C2=A0/* Second pass, look for pointers in names in the records we'= re > keeping and make sure they don't > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0point to records we're going to elide. This= is theoretically > possible, but unlikely. If > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0it happens, we give up and leave the answer= unchanged. */ > --=C2=A0=C2=A0p =3D (unsigned char *)(header+1); > --=C2=A0=C2=A0 > --=C2=A0=C2=A0/* question first */ > --=C2=A0=C2=A0if (!check_name(&p, header, plen, 0, rrs, rr_found)) > --=C2=A0=C2=A0=C2=A0=C2=A0return plen; > --=C2=A0=C2=A0p +=3D 4; /* qclass, qtype */ > --=C2=A0=C2=A0 > --=C2=A0=C2=A0/* Now answers and NS */ > --=C2=A0=C2=A0if (!check_rrs(p, header, plen, 0, rrs, rr_found)) > --=C2=A0=C2=A0=C2=A0=C2=A0return plen; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0/* Third pass, elide records */ > --=C2=A0=C2=A0for (p =3D rrs[0], i =3D 1; i < rr_found; i +=3D 2) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *start =3D rrs[i]; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *end =3D (i !=3D rr_fou= nd - 1) ? rrs[i+1] : > ((unsigned char *)(header+1)) + plen; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0memmove(p, start, end-start); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D end-start; > --=C2=A0=C2=A0=C2=A0=C2=A0} > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0plen =3D p - (unsigned char *)header; > --=C2=A0=C2=A0header->ancount =3D htons(ntohs(header->ancount) - chop_an); > --=C2=A0=C2=A0header->nscount =3D htons(ntohs(header->nscount) - chop_ns); > --=C2=A0=C2=A0header->arcount =3D htons(ntohs(header->arcount) - chop_ar); > -- > --=C2=A0=C2=A0/* Fourth pass, fix up pointers in the remaining records */ > --=C2=A0=C2=A0p =3D (unsigned char *)(header+1); > --=C2=A0=C2=A0 > --=C2=A0=C2=A0check_name(&p, header, plen, 1, rrs, rr_found); > --=C2=A0=C2=A0p +=3D 4; /* qclass, qtype */ > --=C2=A0=C2=A0 > --=C2=A0=C2=A0check_rrs(p, header, plen, 1, rrs, rr_found); > --=C2=A0=C2=A0 > --=C2=A0=C2=A0return plen; > --} > -- > - unsigned char* hash_questions(struct dns_header *header, size_t > plen, char *name) > - { > -=C2=A0=C2=A0=C2=A0int q; > -diff --git a/src/forward.c b/src/forward.c > -index dd22a62..3e801c8 100644 > ---- a/src/forward.c > -+++ b/src/forward.c > -@@ -662,7 +662,7 @@ static size_t process_reply(struct dns_header > *header, time_t now, struct server > -=C2=A0 > -=C2=A0=C2=A0=C2=A0/* If the requestor didn't set the DO bit, don't return = DNSSEC > info. */ > -=C2=A0=C2=A0=C2=A0if (!do_bit) > --=C2=A0=C2=A0=C2=A0=C2=A0n =3D filter_rrsigs(header, n); > -+=C2=A0=C2=A0=C2=A0=C2=A0n =3D rrfilter(header, n, 1); > - #endif > -=C2=A0 > -=C2=A0=C2=A0=C2=A0/* do this after extract_addresses. Ensure NODATA reply = and > remove > -diff --git a/src/rrfilter.c b/src/rrfilter.c > -new file mode 100644 > -index 0000000..ae12261 > ---- /dev/null > -+++ b/src/rrfilter.c > -@@ -0,0 +1,339 @@ > -+/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley > -+ > -+=C2=A0=C2=A0=C2=A0This program is free software; you can redistribute it = and/or > modify > -+=C2=A0=C2=A0=C2=A0it under the terms of the GNU General Public License as > published by > -+=C2=A0=C2=A0=C2=A0the Free Software Foundation; version 2 dated June, 199= 1, or > -+=C2=A0=C2=A0=C2=A0(at your option) version 3 dated 29 June, 2007. > -+=C2=A0 > -+=C2=A0=C2=A0=C2=A0This program is distributed in the hope that it will be= useful, > -+=C2=A0=C2=A0=C2=A0but WITHOUT ANY WARRANTY; without even the implied warr= anty of > -+=C2=A0=C2=A0=C2=A0MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.=C2= =A0=C2=A0See the > -+=C2=A0=C2=A0=C2=A0GNU General Public License for more details. > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0You should have received a copy of the GNU General Publ= ic > License > -+=C2=A0=C2=A0=C2=A0along with this program.=C2=A0=C2=A0If not, see <http:/= /www.gnu.org/licens > es/>. > -+*/ > -+ > -+/* Code to safely remove RRs from an DNS answer */=C2=A0 > -+ > -+#include "dnsmasq.h" > -+ > -+/* Go through a domain name, find "pointers" and fix them up based > on how many bytes > -+=C2=A0=C2=A0=C2=A0we've chopped out of the packet, or check they don't po= int into > an elided part.=C2=A0=C2=A0*/ > -+static int check_name(unsigned char **namep, struct dns_header > *header, size_t plen, int fixup, unsigned char **rrs, int rr_count) > -+{ > -+=C2=A0=C2=A0unsigned char *ansp =3D *namep; > -+ > -+=C2=A0=C2=A0while(1) > -+=C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned int label_type; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!CHECK_LEN(header, ansp, plen, 1)) > -+ return 0; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0label_type =3D (*ansp) & 0xc0; > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (label_type =3D=3D 0xc0) > -+ { > -+ =C2=A0=C2=A0/* pointer for compression. */ > -+ =C2=A0=C2=A0unsigned int offset; > -+ =C2=A0=C2=A0int i; > -+ =C2=A0=C2=A0unsigned char *p; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (!CHECK_LEN(header, ansp, plen, 2)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+ > -+ =C2=A0=C2=A0offset =3D ((*ansp++) & 0x3f) << 8; > -+ =C2=A0=C2=A0offset |=3D *ansp++; > -+ > -+ =C2=A0=C2=A0p =3D offset + (unsigned char *)header; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0for (i =3D 0; i < rr_count; i++) > -+ =C2=A0=C2=A0=C2=A0=C2=A0if (p < rrs[i]) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0break; > -+ =C2=A0=C2=A0=C2=A0=C2=A0else > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (i & 1) > -+ offset -=3D rrs[i] - rrs[i-1]; > -+ > -+ =C2=A0=C2=A0/* does the pointer end up in an elided RR? */ > -+ =C2=A0=C2=A0if (i & 1) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+ > -+ =C2=A0=C2=A0/* No, scale the pointer */ > -+ =C2=A0=C2=A0if (fixup) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ansp -=3D 2; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*ansp++ =3D (offset >> 8) | 0xc0; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*ansp++ =3D offset & 0xff; > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0break; > -+ } > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (label_type =3D=3D 0x80) > -+ return 0; /* reserved */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (label_type =3D=3D 0x40) > -+ { > -+ =C2=A0=C2=A0/* Extended label type */ > -+ =C2=A0=C2=A0unsigned int count; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (!CHECK_LEN(header, ansp, plen, 2)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (((*ansp++) & 0x3f) !=3D 1) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 0; /* we only understand bitstrings */ > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0count =3D *(ansp++); /* Bits in bitstring */ > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (count =3D=3D 0) /* count =3D=3D 0 means 256 bits */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0ansp +=3D 32; > -+ =C2=A0=C2=A0else > -+ =C2=A0=C2=A0=C2=A0=C2=A0ansp +=3D ((count-1)>>3)+1; > -+ } > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -+ { /* label type =3D=3D 0 Bottom six bits is length */ > -+ =C2=A0=C2=A0unsigned int len =3D (*ansp++) & 0x3f; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (!ADD_RDLEN(header, ansp, plen, len)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+ > -+ =C2=A0=C2=A0if (len =3D=3D 0) > -+ =C2=A0=C2=A0=C2=A0=C2=A0break; /* zero length label marks the end. */ > -+ } > -+=C2=A0=C2=A0=C2=A0=C2=A0} > -+ > -+=C2=A0=C2=A0*namep =3D ansp; > -+ > -+=C2=A0=C2=A0return 1; > -+} > -+ > -+/* Go through RRs and check or fixup the domain names contained > within */ > -+static int check_rrs(unsigned char *p, struct dns_header *header, > size_t plen, int fixup, unsigned char **rrs, int rr_count) > -+{ > -+=C2=A0=C2=A0int i, j, type, class, rdlen; > -+=C2=A0=C2=A0unsigned char *pp; > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0for (i =3D 0; i < ntohs(header->ancount) + ntohs(header->nsco= unt) + > ntohs(header->arcount); i++) > -+=C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0pp =3D p; > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(p =3D skip_name(p, header, plen= , 10))) > -+ return 0; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(type, p);=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(class, p); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 4; /* TTL */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(rdlen, p); > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* If this RR is to be elided, don't = fix up its contents */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (j =3D 0; j < rr_count; j +=3D 2) > -+ if (rrs[j] =3D=3D pp) > -+ =C2=A0=C2=A0break; > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (j >=3D rr_count) > -+ { > -+ =C2=A0=C2=A0/* fixup name of RR */ > -+ =C2=A0=C2=A0if (!check_name(&pp, header, plen, fixup, rrs, rr_count)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (class =3D=3D C_IN) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0u16 *d; > -+=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (pp =3D p, d =3D rrfilter_desc(t= ype); *d !=3D (u16)-1; > d++) > -+ { > -+ =C2=A0=C2=A0if (*d !=3D 0) > -+ =C2=A0=C2=A0=C2=A0=C2=A0pp +=3D *d; > -+ =C2=A0=C2=A0else if (!check_name(&pp, header, plen, fixup, > rrs, rr_count)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+ } > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ } > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!ADD_RDLEN(header, p, plen, rdlen= )) > -+ return 0; > -+=C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0return 1; > -+} > -+=09 > -+ > -+/* mode is 0 to remove EDNS0, 1 to filter DNSSEC RRs */ > -+size_t rrfilter(struct dns_header *header, size_t plen, int mode) > -+{ > -+=C2=A0=C2=A0static unsigned char **rrs; > -+=C2=A0=C2=A0static int rr_sz =3D 0; > -+ > -+=C2=A0=C2=A0unsigned char *p =3D (unsigned char *)(header+1); > -+=C2=A0=C2=A0int i, rdlen, qtype, qclass, rr_found, chop_an, chop_ns, chop= _ar; > -+ > -+=C2=A0=C2=A0if (ntohs(header->qdcount) !=3D 1 || > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0!(p =3D skip_name(p, header, plen, 4)= )) > -+=C2=A0=C2=A0=C2=A0=C2=A0return plen; > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0GETSHORT(qtype, p); > -+=C2=A0=C2=A0GETSHORT(qclass, p); > -+ > -+=C2=A0=C2=A0/* First pass, find pointers to start and end of all the reco= rds > we wish to elide: > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0records added for DNSSEC, unless explicity = queried for */ > -+=C2=A0=C2=A0for (rr_found =3D 0, chop_ns =3D 0, chop_an =3D 0, chop_ar = =3D 0, i =3D 0;=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0i < ntohs(header->ancount) + nt= ohs(header->nscount) + > ntohs(header->arcount); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0i++) > -+=C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *pstart =3D p; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int type, class; > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(p =3D skip_name(p, header, plen= , 10))) > -+ return plen; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(type, p);=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(class, p); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 4; /* TTL */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(rdlen, p); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!ADD_RDLEN(header, p, plen, rdlen= )) > -+ return plen; > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Don't remove the answer. */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (i < ntohs(header->ancount) && typ= e =3D=3D qtype && class =3D=3D > qclass) > -+ continue; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (mode =3D=3D 0) /* EDNS */ > -+ { > -+ =C2=A0=C2=A0/* EDNS mode, remove T_OPT from additional section only > */ > -+ =C2=A0=C2=A0if (i < (ntohs(header->nscount) + ntohs(header->ancount))=20 > || type !=3D T_OPT) > -+ =C2=A0=C2=A0=C2=A0=C2=A0continue; > -+ } > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (type !=3D T_NSEC && type != =3D T_NSEC3 && type !=3D > T_RRSIG) > -+ /* DNSSEC mode, remove SIGs and NSECs from all three > sections. */ > -+ continue; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!expand_workspace(&rrs, &rr_sz, r= r_found + 1)) > -+ return plen;=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0rrs[rr_found++] =3D pstart; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0rrs[rr_found++] =3D p; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (i < ntohs(header->ancount)) > -+ chop_an++; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (i < (ntohs(header->nscount) = + ntohs(header- > >ancount))) > -+ chop_ns++; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -+ chop_ar++; > -+=C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0/* Nothing to do. */ > -+=C2=A0=C2=A0if (rr_found =3D=3D 0) > -+=C2=A0=C2=A0=C2=A0=C2=A0return plen; > -+ > -+=C2=A0=C2=A0/* Second pass, look for pointers in names in the records we'= re > keeping and make sure they don't > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0point to records we're going to elide. This= is theoretically > possible, but unlikely. If > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0it happens, we give up and leave the answer= unchanged. */ > -+=C2=A0=C2=A0p =3D (unsigned char *)(header+1); > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0/* question first */ > -+=C2=A0=C2=A0if (!check_name(&p, header, plen, 0, rrs, rr_found)) > -+=C2=A0=C2=A0=C2=A0=C2=A0return plen; > -+=C2=A0=C2=A0p +=3D 4; /* qclass, qtype */ > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0/* Now answers and NS */ > -+=C2=A0=C2=A0if (!check_rrs(p, header, plen, 0, rrs, rr_found)) > -+=C2=A0=C2=A0=C2=A0=C2=A0return plen; > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0/* Third pass, elide records */ > -+=C2=A0=C2=A0for (p =3D rrs[0], i =3D 1; i < rr_found; i +=3D 2) > -+=C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *start =3D rrs[i]; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *end =3D (i !=3D rr_fou= nd - 1) ? rrs[i+1] : > ((unsigned char *)(header+1)) + plen; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0memmove(p, start, end-start); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D end-start; > -+=C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0plen =3D p - (unsigned char *)header; > -+=C2=A0=C2=A0header->ancount =3D htons(ntohs(header->ancount) - chop_an); > -+=C2=A0=C2=A0header->nscount =3D htons(ntohs(header->nscount) - chop_ns); > -+=C2=A0=C2=A0header->arcount =3D htons(ntohs(header->arcount) - chop_ar); > -+ > -+=C2=A0=C2=A0/* Fourth pass, fix up pointers in the remaining records */ > -+=C2=A0=C2=A0p =3D (unsigned char *)(header+1); > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0check_name(&p, header, plen, 1, rrs, rr_found); > -+=C2=A0=C2=A0p +=3D 4; /* qclass, qtype */ > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0check_rrs(p, header, plen, 1, rrs, rr_found); > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0return plen; > -+} > -+ > -+/* This is used in the DNSSEC code too, hence it's exported */ > -+u16 *rrfilter_desc(int type) > -+{ > -+=C2=A0=C2=A0/* List of RRtypes which include domains in the data. > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A00 -> domain > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0integer -> no of plain bytes > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0-1 -> end > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0zero is not a valid RRtype, so the final en= try is returned for > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0anything which needs no mangling. > -+=C2=A0=C2=A0*/ > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0static u16 rr_desc[] =3D=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0{=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_NS, 0, -1,=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MD, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MF, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_CNAME, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_SOA, 0, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MB, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MG, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MR, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_PTR, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MINFO, 0, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_MX, 2, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_RP, 0, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_AFSDB, 2, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_RT, 2, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_SIG, 18, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_PX, 2, 0, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_NXT, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_KX, 2, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_SRV, 6, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0T_DNAME, 0, -1, > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A00, -1 /* wildcard/catchall */ > -+=C2=A0=C2=A0=C2=A0=C2=A0};=C2=A0 > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0u16 *p =3D rr_desc; > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0while (*p !=3D type && *p !=3D 0) > -+=C2=A0=C2=A0=C2=A0=C2=A0while (*p++ !=3D (u16)-1); > -+ > -+=C2=A0=C2=A0return p+1; > -+} > -+ > -+int expand_workspace(unsigned char ***wkspc, int *szp, int new) > -+{ > -+=C2=A0=C2=A0unsigned char **p; > -+=C2=A0=C2=A0int old =3D *szp; > -+ > -+=C2=A0=C2=A0if (old >=3D new+1) > -+=C2=A0=C2=A0=C2=A0=C2=A0return 1; > -+ > -+=C2=A0=C2=A0if (new >=3D 100) > -+=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+ > -+=C2=A0=C2=A0new +=3D 5; > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0if (!(p =3D whine_malloc(new * sizeof(unsigned char **)))) > -+=C2=A0=C2=A0=C2=A0=C2=A0return 0;=C2=A0=C2=A0 > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0if (old !=3D 0 && *wkspc) > -+=C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0memcpy(p, *wkspc, old * sizeof(unsign= ed char **)); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0free(*wkspc); > -+=C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0*wkspc =3D p; > -+=C2=A0=C2=A0*szp =3D new; > -+ > -+=C2=A0=C2=A0return 1; > -+} > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/020-DNSSEC_validation_tweak.patch > b/src/patches/dnsmasq/020-DNSSEC_validation_tweak.patch > deleted file mode 100644 > index ffb412b..0000000 > --- a/src/patches/dnsmasq/020-DNSSEC_validation_tweak.patch > +++ /dev/null > @@ -1,134 +0,0 @@ > -From 2dbba34b2c1289a108f876c78b84889f2a93115d Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Wed, 16 Dec 2015 13:41:58 +0000 > -Subject: [PATCH] DNSSEC validation tweak. > - > -A zone which has at least one key with an algorithm we don't > -support should be considered as insecure. > ---- > - src/dnssec.c |=C2=A0=C2=A0=C2=A082 ++++++++++++++++++++++++++++++++++++++= --------- > ----------- > - 1 file changed, 54 insertions(+), 28 deletions(-) > - > -diff --git a/src/dnssec.c b/src/dnssec.c > -index fa3eb81..dc563e0 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -763,10 +763,10 @@ static int explore_rrset(struct dns_header > *header, size_t plen, int class, int > -=C2=A0=C2=A0=C2=A0=C2=A0STAT_NEED_KEY need DNSKEY to complete validation (= name is > returned in keyname) > -=C2=A0=C2=A0=C2=A0=C2=A0STAT_NEED_DS=C2=A0=C2=A0need DS to complete valida= tion (name is returned > in keyname) > -=C2=A0 > --=C2=A0=C2=A0=C2=A0if key is non-NULL, use that key, which has the algo an= d tag > given in the params of those names, > -+=C2=A0=C2=A0=C2=A0If key is non-NULL, use that key, which has the algo an= d tag > given in the params of those names, > -=C2=A0=C2=A0=C2=A0=C2=A0otherwise find the key in the cache. > -=C2=A0 > --=C2=A0=C2=A0=C2=A0name is unchanged on exit. keyname is used as workspace= and > trashed. > -+=C2=A0=C2=A0=C2=A0Name is unchanged on exit. keyname is used as workspace= and > trashed. > -=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0Call explore_rrset first to find and count RRs and= sigs. > - */ > -@@ -919,6 +919,7 @@ static int validate_rrset(time_t now, struct > dns_header *header, size_t plen, in > -=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > - } > -=C2=A0=C2=A0 > -+ > - /* The DNS packet is expected to contain the answer to a DNSKEY > query. > -=C2=A0=C2=A0=C2=A0=C2=A0Put all DNSKEYs in the answer which are valid into= the cache. > -=C2=A0=C2=A0=C2=A0=C2=A0return codes: > -@@ -1831,15 +1832,15 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0 > - /* Check signing status of name. > -=C2=A0=C2=A0=C2=A0=C2=A0returns: > --=C2=A0=C2=A0=C2=A0STAT_SECURE zone is signed. > --=C2=A0=C2=A0=C2=A0STAT_INSECURE zone proved unsigned. > --=C2=A0=C2=A0=C2=A0STAT_NEED_DS require DS record of name returned in keyn= ame. > --=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0STAT_SECURE=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0zone is = signed. > -+=C2=A0=C2=A0=C2=A0STAT_INSECURE=C2=A0=C2=A0=C2=A0=C2=A0zone proved unsign= ed. > -+=C2=A0=C2=A0=C2=A0STAT_NEED_DS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0require DS re= cord of name returned in keyname. > -+=C2=A0=C2=A0=C2=A0STAT_NEED_DNSKEY require DNSKEY record of name returned= in > keyname. > -=C2=A0=C2=A0=C2=A0=C2=A0name returned unaltered. > - */ > - static int zone_status(char *name, int class, char *keyname, time_t > now) > - { > --=C2=A0=C2=A0int name_start =3D strlen(name); > -+=C2=A0=C2=A0int secure_ds, name_start =3D strlen(name); > -=C2=A0=C2=A0=C2=A0struct crec *crecp; > -=C2=A0=C2=A0=C2=A0char *p; > -=C2=A0=C2=A0=C2=A0 > -@@ -1850,27 +1851,52 @@ static int zone_status(char *name, int > class, char *keyname, time_t now) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(crecp =3D cache_find_by_na= me(NULL, keyname, now, F_DS))) > -=C2=A0 return STAT_NEED_DS; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -- do=C2=A0 > -- =C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0if (crecp->uid =3D=3D (unsigned int)class) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- /* F_DNSSECOK misused in DS cache records to non- > existance of NS record. > -- =C2=A0=C2=A0=C2=A0F_NEG && !F_DNSSECOK implies that we've proved > there's no DS record here, > -- =C2=A0=C2=A0=C2=A0but that's because there's no NS record either, > ie this isn't the start > -- =C2=A0=C2=A0=C2=A0of a zone. We only prove that the DNS tree below > a node is unsigned when > -- =C2=A0=C2=A0=C2=A0we prove that we're at a zone cut AND there's no > DS record. > -- */ =C2=A0=C2=A0 > -- if (crecp->flags & F_NEG) > -- =C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0if (crecp->flags & F_DNSSECOK) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; /* proved no = DS here */ > -- =C2=A0=C2=A0} > -- else if (!ds_digest_name(crecp->addr.ds.digest) || > !algo_digest_name(crecp->addr.ds.algo)) > -- =C2=A0=C2=A0return STAT_INSECURE; /* algo we can't use - > insecure */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0} > -- while ((crecp =3D cache_find_by_name(crecp, keyname, now, > F_DS))); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ { > -+ =C2=A0=C2=A0secure_ds =3D 0; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0do=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->uid =3D=3D (unsigned int)= class) > -+ { > -+ =C2=A0=C2=A0/* F_DNSSECOK misused in DS cache records to non- > existance of NS record. > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0F_NEG && !F_DNSSECOK implies that we've p= roved > there's no DS record here, > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0but that's because there's no NS record > either, ie this isn't the start > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0of a zone. We only prove that the DNS tree > below a node is unsigned when > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0we prove that we're at a zone cut AND the= re's > no DS record. > -+ =C2=A0=C2=A0*/ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (crecp->flags & F_NEG) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->flags & F_DNSSECOK) > -+ return STAT_INSECURE; /* proved no DS here > */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0else if (!ds_digest_name(crecp->addr.ds.digest) > || !algo_digest_name(crecp->addr.ds.algo)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; /* algo we can't use - > insecure */ > -+ =C2=A0=C2=A0else > -+ =C2=A0=C2=A0=C2=A0=C2=A0secure_ds =3D 1; > -+ } > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0while ((crecp =3D cache_find_by_name(crecp, keyname, now, > F_DS))); > -+ } > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (secure_ds) > -+ { > -+ =C2=A0=C2=A0/* We've found only DS records that attest to the DNSKEY > RRset in the zone, so we believe > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0that RRset is good. Furthermore the DNSKEY= whose hash > is proved by the DS record is > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0one we can use. However the DNSKEY RRset m= ay contain > more than one key and > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0one of the other keys may use an algorithm= we don't > support. If that's=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0the case the zone is insecure for us. */ > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (!(crecp =3D cache_find_by_name(NULL, keyname, now, > F_DNSKEY))) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return STAT_NEED_KEY; > -+ > -+ =C2=A0=C2=A0do=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->uid =3D=3D (unsigned int)= class && > !algo_digest_name(crecp->addr.key.algo)) > -+ return STAT_INSECURE; > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0while ((crecp =3D cache_find_by_name(crecp, keyname, now, > F_DNSKEY))); > -+ } > -+ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (name_start =3D=3D 0) > -=C2=A0 break; > -=C2=A0 > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/021- > Tweaks_to_EDNS0_handling_in_DNS_replies.patch > b/src/patches/dnsmasq/021- > Tweaks_to_EDNS0_handling_in_DNS_replies.patch > deleted file mode 100644 > index c3c74cc..0000000 > --- a/src/patches/dnsmasq/021- > Tweaks_to_EDNS0_handling_in_DNS_replies.patch > +++ /dev/null > @@ -1,133 +0,0 @@ > -From dd4ad9ac7ea6d51dcc34a1f2cd2da14efbb87714 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Thu, 17 Dec 2015 10:44:58 +0000 > -Subject: [PATCH] Tweaks to EDNS0 handling in DNS replies. > - > ---- > - src/dnssec.c=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A020 +++++++++----------- > - src/rfc1035.c |=C2=A0=C2=A0=C2=A057 +++++++++++++++++++++++++++++++++----= --------- > ----------- > - 2 files changed, 42 insertions(+), 35 deletions(-) > - > -diff --git a/src/dnssec.c b/src/dnssec.c > -index dc563e0..012b2a6 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -2129,18 +2129,16 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0/* Empty DS without NSECS */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0if (qtype =3D=3D T_DS) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -- =C2=A0=C2=A0=C2=A0=C2=A0else > -+ =C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0rc =3D zone_status(name, qclass, keyname, now); > -+ =C2=A0=C2=A0=C2=A0=C2=A0if (rc !=3D STAT_SECURE) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- rc =3D zone_status(name, qclass, keyname, now); > -- if (rc !=3D STAT_SECURE) > -- =C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0if (class) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*class =3D qclass; /* Class for NEE= D_DS or > NEED_DNSKEY */ > -- =C2=A0=C2=A0=C2=A0=C2=A0return rc; > -- =C2=A0=C2=A0}=C2=A0 > -- =09 > -- return STAT_BOGUS; /* signed zone, no NSECs */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -+ if (class) > -+ =C2=A0=C2=A0*class =3D qclass; /* Class for NEED_DS or > NEED_DNSKEY */ > -+ return rc; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* signed zone, no NSECs */ > -=C2=A0 =C2=A0=C2=A0} > -=C2=A0 > -=C2=A0 =C2=A0=C2=A0if (nsec_type =3D=3D T_NSEC) > -diff --git a/src/rfc1035.c b/src/rfc1035.c > -index def8fa0..188d05f 100644 > ---- a/src/rfc1035.c > -+++ b/src/rfc1035.c > -@@ -1539,7 +1539,13 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0=C2=A0=C2=A0int nxdomain =3D 0, auth =3D 1, trunc =3D 0, sec_data = =3D 1; > -=C2=A0=C2=A0=C2=A0struct mx_srv_record *rec; > -=C2=A0=C2=A0=C2=A0size_t len; > --=C2=A0 > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0if (ntohs(header->ancount) !=3D 0 || > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ntohs(header->nscount) !=3D 0 || > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ntohs(header->qdcount) =3D=3D 0 ||=C2= =A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0OPCODE(header) !=3D QUERY ) > -+=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0/* Don't return AD set if checking disabled. */ > -=C2=A0=C2=A0=C2=A0if (header->hb4 & HB4_CD) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0sec_data =3D 0; > -@@ -1548,33 +1554,32 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0=C2=A0=C2=A0*ad_reqd =3D header->hb4 & HB4_AD; > -=C2=A0=C2=A0=C2=A0*do_bit =3D 0; > -=C2=A0 > --=C2=A0=C2=A0/* If there is an RFC2671 pseudoheader then it will be > overwritten by > -+=C2=A0=C2=A0/* If there is an=C2=A0=C2=A0additional data section then it = will be > overwritten by > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0partial replies, so we have to do a dr= y run to see if we can > answer > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0the query. We check to see if the do bit is= set, if so we > always > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0forward rather than answering from the cach= e, which doesn't > include > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0security information, unless we're in DNSSE= C validation mode. > */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0the query. */ > -=C2=A0 > --=C2=A0=C2=A0if (find_pseudoheader(header, qlen, NULL, &pheader, NULL)) > --=C2=A0=C2=A0=C2=A0=C2=A0{=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned short flags; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0have_pseudoheader =3D 1; > -+=C2=A0=C2=A0if (ntohs(header->arcount) !=3D 0) > -+=C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0dryrun =3D 1; > -=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0pheader +=3D 4; /* udp size, ext_rcod= e */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(flags, pheader); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((sec_reqd =3D flags & 0x8000)) > -- { > -- =C2=A0=C2=A0*do_bit =3D 1;/* do bit */=C2=A0 > -- =C2=A0=C2=A0*ad_reqd =3D 1; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* If there's an additional section, = there might be an > EDNS(0) pseudoheader */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (find_pseudoheader(header, qlen, N= ULL, &pheader, NULL)) > -+ {=C2=A0 > -+ =C2=A0=C2=A0unsigned short flags; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0have_pseudoheader =3D 1; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0pheader +=3D 4; /* udp size, ext_rcode */ > -+ =C2=A0=C2=A0GETSHORT(flags, pheader); > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0if ((sec_reqd =3D flags & 0x8000)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*do_bit =3D 1;/* do bit */=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*ad_reqd =3D 1; > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 } > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0dryrun =3D 1; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > --=C2=A0=C2=A0if (ntohs(header->qdcount) =3D=3D 0 || OPCODE(header) !=3D QU= ERY ) > --=C2=A0=C2=A0=C2=A0=C2=A0return 0; > --=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0for (rec =3D daemon->mxnames; rec; rec =3D rec->next) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0rec->offset =3D 0; > -=C2=A0=C2=A0=C2=A0 > -@@ -1730,8 +1735,12 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if ((crecp =3D cache_find_= by_addr(NULL, &addr, > now, is_arpa))) > -=C2=A0 { > -- =C2=A0=C2=A0/* Don't use cache when DNSSEC data required. */ > -- =C2=A0=C2=A0if ((crecp->flags & (F_HOSTS | F_DHCP | > F_CONFIG)) || !sec_reqd || !(crecp->flags & F_DNSSECOK)) > -+ =C2=A0=C2=A0/* Don't use cache when DNSSEC data required, > unless we know that > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0the zone is unsigned, which implies that = we're > doing > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0validation. */ > -+ =C2=A0=C2=A0if ((crecp->flags & (F_HOSTS | F_DHCP | > F_CONFIG)) ||=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0!sec_reqd ||=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(option_bool(OPT_DNSSEC_VALID) && != (crecp- > >flags & F_DNSSECOK))) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0do=C2=A0 > -=C2=A0 {=C2=A0 > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/022-Tidy_up_DNSSEC_non- > existence_code_Check_zone_status_is_NSEC_proof_bad.patch > b/src/patches/dnsmasq/022-Tidy_up_DNSSEC_non- > existence_code_Check_zone_status_is_NSEC_proof_bad.patch > deleted file mode 100644 > index 60503e9..0000000 > --- a/src/patches/dnsmasq/022-Tidy_up_DNSSEC_non- > existence_code_Check_zone_status_is_NSEC_proof_bad.patch > +++ /dev/null > @@ -1,409 +0,0 @@ > -From b40f26c0199235073abc37e1e1d6ed93bed372f5 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Thu, 17 Dec 2015 11:57:26 +0000 > -Subject: [PATCH] Tidy up DNSSEC non-existence code. Check zone > status is NSEC > - proof bad. > - > ---- > - src/dnssec.c |=C2=A0=C2=A0207 +++++++++++++++++++++++++------------------= -- > ------------- > - 1 file changed, 90 insertions(+), 117 deletions(-) > - > -diff --git a/src/dnssec.c b/src/dnssec.c > -index 012b2a6..ddae497 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -1367,59 +1367,6 @@ static int hostname_cmp(const char *a, const > char *b) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > - } > -=C2=A0 > --/* Find all the NSEC or NSEC3 records in a reply. > --=C2=A0=C2=A0=C2=A0return an array of pointers to them. */ > --static int find_nsec_records(struct dns_header *header, size_t > plen, unsigned char ***nsecsetp, int *nsecsetl, int class_reqd) > --{ > --=C2=A0=C2=A0static unsigned char **nsecset =3D NULL; > --=C2=A0=C2=A0static int nsecset_sz =3D 0; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0int type_found =3D 0; > --=C2=A0=C2=A0unsigned char *p =3D skip_questions(header, plen); > --=C2=A0=C2=A0int type, class, rdlen, i, nsecs_found; > -- > --=C2=A0=C2=A0/* Move to NS section */ > --=C2=A0=C2=A0if (!p || !(p =3D skip_section(p, ntohs(header->ancount), hea= der, > plen))) > --=C2=A0=C2=A0=C2=A0=C2=A0return 0; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0for (nsecs_found =3D 0, i =3D ntohs(header->nscount); i !=3D = 0; i--) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *pstart =3D p; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(p =3D skip_name(p, header, plen= , 10))) > -- return 0; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(type, p);=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(class, p); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 4; /* TTL */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(rdlen, p); > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (class =3D=3D class_reqd && (type = =3D=3D T_NSEC || type =3D=3D > T_NSEC3)) > -- { > -- =C2=A0=C2=A0/* No mixed NSECing 'round here, thankyouverymuch */ > -- =C2=A0=C2=A0if (type_found =3D=3D T_NSEC && type =3D=3D T_NSEC3) > -- =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -- =C2=A0=C2=A0if (type_found =3D=3D T_NSEC3 && type =3D=3D T_NSEC) > -- =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -- > -- =C2=A0=C2=A0type_found =3D type; > -- > -- =C2=A0=C2=A0if (!expand_workspace(&nsecset, &nsecset_sz, > nsecs_found)) > -- =C2=A0=C2=A0=C2=A0=C2=A0return 0;=C2=A0 > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0nsecset[nsecs_found++] =3D pstart; > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!ADD_RDLEN(header, p, plen, rdlen= )) > -- return 0; > --=C2=A0=C2=A0=C2=A0=C2=A0} > --=C2=A0=C2=A0 > --=C2=A0=C2=A0*nsecsetp =3D nsecset; > --=C2=A0=C2=A0*nsecsetl =3D nsecs_found; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0return type_found; > --} > -- > - static int prove_non_existence_nsec(struct dns_header *header, > size_t plen, unsigned char **nsecs, int nsec_count, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0char *workspace1, char > *workspace2, char *name, int type, int *nons) > - { > -@@ -1436,12 +1383,12 @@ static int prove_non_existence_nsec(struct > dns_header *header, size_t plen, unsi > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p =3D nsecs[i]; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!extract_name(header, plen, = &p, workspace1, 1, 10)) > -- return STAT_BOGUS; > -+ return 0; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 8; /* class, type, TTL */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(rdlen, p); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0psave =3D p; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!extract_name(header, plen, = &p, workspace2, 1, 10)) > -- return STAT_BOGUS; > -+ return 0; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0rc =3D hostname_cmp(workspace1, = name); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -@@ -1449,7 +1396,7 @@ static int prove_non_existence_nsec(struct > dns_header *header, size_t plen, unsi > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0/* 4035 para 5.4. Last sentence */ > -=C2=A0 =C2=A0=C2=A0if (type =3D=3D T_NSEC || type =3D=3D T_RRSIG) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_SECURE; > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 1; > -=C2=A0 > -=C2=A0 =C2=A0=C2=A0/* NSEC with the same name as the RR we're testing, che= ck > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0that the type in question doesn't app= ear in the type > map */ > -@@ -1465,24 +1412,24 @@ static int prove_non_existence_nsec(struct > dns_header *header, size_t plen, unsi > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* A CNAME answer would also be= valid, so if there's > a CNAME is should=C2=A0 > -=C2=A0 =C2=A0have been returned. */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((p[2] & (0x80 >> T_CNAME)) = !=3D 0) > -- return STAT_BOGUS; > -+ return 0; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* If the SOA bit is set for a = DS record, then we > have the > -=C2=A0 =C2=A0DS from the wrong side of the delegation. */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (type =3D=3D T_DS && (p[2] &= (0x80 >> T_SOA)) !=3D 0) > -- return STAT_BOGUS; > -+ return 0; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > -=C2=A0 =C2=A0=C2=A0while (rdlen >=3D 2) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!CHECK_LEN(header, p, plen,= rdlen)) > -- return STAT_BOGUS; > -+ return 0; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (p[0] =3D=3D type >> 8) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0/* Does the NSEC say our type exists? */ > -=C2=A0 =C2=A0=C2=A0if (offset < p[1] && (p[offset+2] & mask) !=3D 0) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0break; /* finshed checking */ > -=C2=A0 } > -@@ -1491,24 +1438,24 @@ static int prove_non_existence_nsec(struct > dns_header *header, size_t plen, unsi > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D=C2=A0=C2=A0p[1]; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0return STAT_SECURE; > -+ =C2=A0=C2=A0return 1; > -=C2=A0 } > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else if (rc =3D=3D -1) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0/* Normal case, name falls between NSEC name and next > domain name, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0wrap around case, name falls between = NSEC name (rc =3D=3D > -1) and end */ > -=C2=A0 =C2=A0=C2=A0if (hostname_cmp(workspace2, name) >=3D 0 || > hostname_cmp(workspace1, workspace2) >=3D 0) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_SECURE; > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 1; > -=C2=A0 } > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else=C2=A0 > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0/* wrap around case, name falls between start and next > domain name */ > -=C2=A0 =C2=A0=C2=A0if (hostname_cmp(workspace1, workspace2) >=3D 0 && > hostname_cmp(workspace2, name) >=3D0 ) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_SECURE; > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 1; > -=C2=A0 } > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0return STAT_BOGUS; > -+=C2=A0=C2=A0return 0; > - } > -=C2=A0 > - /* return digest length, or zero on error */ > -@@ -1701,7 +1648,7 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0=C2=A0=C2=A0for (i =3D 0; i < nsec_count; i++) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(p =3D skip_name(nsecs[i], = header, plen, 15))) > -- return STAT_BOGUS; /* bad packet */ > -+ return 0; /* bad packet */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 10; /* type, class, TTL, = rdlen */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0algo =3D *p++; > -@@ -1712,14 +1659,14 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0 > -=C2=A0=C2=A0=C2=A0/* No usable NSEC3s */ > -=C2=A0=C2=A0=C2=A0if (i =3D=3D nsec_count) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -+=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0p++; /* flags */ > -=C2=A0=C2=A0=C2=A0GETSHORT (iterations, p); > -=C2=A0=C2=A0=C2=A0salt_len =3D *p++; > -=C2=A0=C2=A0=C2=A0salt =3D p; > -=C2=A0=C2=A0=C2=A0if (!CHECK_LEN(header, salt, plen, salt_len)) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -+=C2=A0=C2=A0=C2=A0=C2=A0return 0; /* bad packet */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0/* Now prune so we only have NSEC3 records with same ite= rations, > salt and algo */ > -=C2=A0=C2=A0=C2=A0for (i =3D 0; i < nsec_count; i++) > -@@ -1730,7 +1677,7 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0nsecs[i] =3D NULL; /* Speculativ= e, will be restored if OK. */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(p =3D skip_name(nsec3p, he= ader, plen, 15))) > -- return STAT_BOGUS; /* bad packet */ > -+ return 0; /* bad packet */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 10; /* type, class, TTL, = rdlen */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -@@ -1747,7 +1694,7 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0 continue; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!CHECK_LEN(header, p, plen, = salt_len)) > -- return STAT_BOGUS; /* bad packet */ > -+ return 0; /* bad packet */ > -=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (memcmp(p, salt, salt_len) != =3D 0) > -=C2=A0 continue; > -@@ -1758,13 +1705,13 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0 > -=C2=A0=C2=A0=C2=A0/* Algo is checked as 1 above */ > -=C2=A0=C2=A0=C2=A0if (!(hash =3D hash_find("sha1"))) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -+=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if ((digest_len =3D hash_name(name, &digest, hash, salt,= salt_len, > iterations)) =3D=3D 0) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -+=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0if (check_nsec3_coverage(header, plen, digest_len, diges= t, type, > workspace1, workspace2, nsecs, nsec_count, nons)) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_SECURE; > -+=C2=A0=C2=A0=C2=A0=C2=A0return 1; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0/* Can't find an NSEC3 which covers the name directly, w= e need > the "closest encloser NSEC3"=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0or an answer inferred from a wildcard = record. */ > -@@ -1780,14 +1727,14 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0 break; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((digest_len =3D hash_name(cl= osest_encloser, &digest, hash, > salt, salt_len, iterations)) =3D=3D 0) > -- return STAT_BOGUS; > -+ return 0; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0for (i =3D 0; i < nsec_count; i+= +) > -=C2=A0 if ((p =3D nsecs[i])) > -=C2=A0 =C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0if (!extract_name(header, plen, &p, workspa= ce1, 1, 0) > || > -=C2=A0 !(base32_len =3D base32_decode(workspace1, (unsigned > char *)workspace2))) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0if (digest_len =3D=3D base32_len && > -=C2=A0 memcmp(digest, workspace2, digest_len) =3D=3D 0) > -@@ -1802,32 +1749,81 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0=C2=A0=C2=A0while ((closest_encloser =3D strchr(closest_encloser, '.= '))); > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0if (!closest_encloser) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -+=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0/* Look for NSEC3 that proves the non-existence of the n= ext- > closest encloser */ > -=C2=A0=C2=A0=C2=A0if ((digest_len =3D hash_name(next_closest, &digest, has= h, salt, > salt_len, iterations)) =3D=3D 0) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -+=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if (!check_nsec3_coverage(header, plen, digest_len, dige= st, type, > workspace1, workspace2, nsecs, nsec_count, NULL)) > --=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -+=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0/* Finally, check that there's no seat of wildcard synth= esis */ > -=C2=A0=C2=A0=C2=A0if (!wildname) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(wildcard =3D strchr(next_c= losest, '.')) || wildcard =3D=3D > next_closest) > -- return STAT_BOGUS; > -+ return 0; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0wildcard--; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*wildcard =3D '*'; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((digest_len =3D hash_name(wi= ldcard, &digest, hash, salt, > salt_len, iterations)) =3D=3D 0) > -- return STAT_BOGUS; > -+ return 0; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!check_nsec3_coverage(header= , plen, digest_len, digest, > type, workspace1, workspace2, nsecs, nsec_count, NULL)) > -- return STAT_BOGUS; > -+ return 0; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0return STAT_SECURE; > -+=C2=A0=C2=A0return 1; > -+} > -+ > -+static int prove_non_existence(struct dns_header *header, size_t > plen, char *keyname, char *name, int qtype, int qclass, char > *wildname, int *nons) > -+{ > -+=C2=A0=C2=A0static unsigned char **nsecset =3D NULL; > -+=C2=A0=C2=A0static int nsecset_sz =3D 0; > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0int type_found =3D 0; > -+=C2=A0=C2=A0unsigned char *p =3D skip_questions(header, plen); > -+=C2=A0=C2=A0int type, class, rdlen, i, nsecs_found; > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0/* Move to NS section */ > -+=C2=A0=C2=A0if (!p || !(p =3D skip_section(p, ntohs(header->ancount), hea= der, > plen))) > -+=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0for (nsecs_found =3D 0, i =3D ntohs(header->nscount); i !=3D = 0; i--) > -+=C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *pstart =3D p; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(p =3D skip_name(p, header, plen= , 10))) > -+ return 0; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(type, p);=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(class, p); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 4; /* TTL */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(rdlen, p); > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (class =3D=3D qclass && (type =3D= =3D T_NSEC || type =3D=3D T_NSEC3)) > -+ { > -+ =C2=A0=C2=A0/* No mixed NSECing 'round here, thankyouverymuch */ > -+ =C2=A0=C2=A0if (type_found !=3D 0 && type_found !=3D type) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+ > -+ =C2=A0=C2=A0type_found =3D type; > -+ > -+ =C2=A0=C2=A0if (!expand_workspace(&nsecset, &nsecset_sz, > nsecs_found)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return 0;=C2=A0 > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0nsecset[nsecs_found++] =3D pstart; > -+ } > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!ADD_RDLEN(header, p, plen, rdlen= )) > -+ return 0; > -+=C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0if (type_found =3D=3D T_NSEC) > -+=C2=A0=C2=A0=C2=A0=C2=A0return prove_non_existence_nsec(header, plen, nse= cset, > nsecs_found, daemon->workspacename, keyname, name, qtype, nons); > -+=C2=A0=C2=A0else > -+=C2=A0=C2=A0=C2=A0=C2=A0return prove_non_existence_nsec3(header, plen, ns= ecset, > nsecs_found, daemon->workspacename, keyname, name, qtype, wildname, > nons); > - } > -=C2=A0 > - /* Check signing status of name. > -@@ -1925,10 +1921,9 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0=C2=A0=C2=A0static unsigned char **targets =3D NULL; > -=C2=A0=C2=A0=C2=A0static int target_sz =3D 0; > -=C2=A0 > --=C2=A0=C2=A0unsigned char *ans_start, *p1, *p2, **nsecs; > -+=C2=A0=C2=A0unsigned char *ans_start, *p1, *p2; > -=C2=A0=C2=A0=C2=A0int type1, class1, rdlen1, type2, class2, rdlen2, qclass= , qtype, > targetidx; > --=C2=A0=C2=A0int i, j, rc, nsec_count; > --=C2=A0=C2=A0int nsec_type; > -+=C2=A0=C2=A0int i, j, rc; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if (neganswer) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*neganswer =3D 0; > -@@ -2080,28 +2075,15 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0targets[j] =3D NULL; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0if (rc =3D=3D STAT_SECURE_WILDCARD) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* An attacker replay a wildcard an= swer with > a different > -- =C2=A0answer and overlay a genuine RR. To prove > this > -- =C2=A0hasn't happened, the answer must prove > that > -- =C2=A0the gennuine record doesn't exist. Check > that here. */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(nsec_type =3D find_nsec_recor= ds(header, > plen, &nsecs, &nsec_count, class1))) > -- return STAT_BOGUS; /* No NSECs or bad > packet */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Note that we may not yet have va= lidated > the NSEC/NSEC3 RRsets. Since the check > -- =C2=A0below returns either SECURE or BOGUS, > that's not a problem. If the RRsets later fail > -- =C2=A0we'll return BOGUS then. */ > -- > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (nsec_type =3D=3D T_NSEC) > -- rc =3D prove_non_existence_nsec(header, plen, > nsecs, nsec_count, daemon->workspacename, keyname, name, type1, > NULL); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -- rc =3D prove_non_existence_nsec3(header, > plen, nsecs, nsec_count, daemon->workspacename,=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0keyname, > name, type1, wildname, NULL); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rc =3D=3D STAT_BOGUS) > -- return rc; > -- =C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -+ =C2=A0=C2=A0=C2=A0/* An attacker replay a wildcard answer with a > different > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0answer and overlay a genuine RR. To= prove > this > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0hasn't happened, the answer must pr= ove that > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0the gennuine record doesn't exist. = Check that > here.=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Note that we may not yet have valid= ated the > NSEC/NSEC3 RRsets.=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0That's not a problem since if the R= Rsets > later fail > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0we'll return BOGUS then. */ > -+ =C2=A0=C2=A0if (rc =3D=3D STAT_SECURE_WILDCARD && > !prove_non_existence(header, plen, keyname, name, type1, class1, > wildname, NULL)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -=C2=A0 } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 } > -@@ -2124,14 +2106,13 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 > -=C2=A0 /* For anything other than a DS record, this situation is > OK if either > -=C2=A0 =C2=A0=C2=A0=C2=A0the answer is in an unsigned zone, or there's a N= SEC > records. */ > -- if (!(nsec_type =3D find_nsec_records(header, plen, &nsecs, > &nsec_count, qclass))) > -+ if (!prove_non_existence(header, plen, keyname, name, > qtype, qclass, NULL, nons)) > -=C2=A0 =C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0/* Empty DS without NSECS */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0if (qtype =3D=3D T_DS) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0rc =3D zone_status(name, qclass, keyname, now); > -- =C2=A0=C2=A0=C2=A0=C2=A0if (rc !=3D STAT_SECURE) > -+ =C2=A0=C2=A0=C2=A0=C2=A0if ((rc =3D zone_status(name, qclass, keyname, n= ow)) !=3D > STAT_SECURE) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 if (class) > -=C2=A0 =C2=A0=C2=A0*class =3D qclass; /* Class for NEED_DS or > NEED_DNSKEY */ > -@@ -2140,14 +2121,6 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* signed zone, no NSECs= */ > -=C2=A0 =C2=A0=C2=A0} > -- > -- =C2=A0=C2=A0if (nsec_type =3D=3D T_NSEC) > -- =C2=A0=C2=A0rc =3D prove_non_existence_nsec(header, plen, nsecs, > nsec_count, daemon->workspacename, keyname, name, qtype, nons); > -- else > -- =C2=A0=C2=A0rc =3D prove_non_existence_nsec3(header, plen, nsecs, > nsec_count, daemon->workspacename, keyname, name, qtype, NULL, nons); > -- > -- if (rc !=3D STAT_SECURE) > -- =C2=A0=C2=A0return rc; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0return STAT_SECURE; > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/023- > Fix_brace_botch_in_dnssec_validate_ds.patch > b/src/patches/dnsmasq/023-Fix_brace_botch_in_dnssec_validate_ds.patch > deleted file mode 100644 > index eda6fbd..0000000 > --- a/src/patches/dnsmasq/023- > Fix_brace_botch_in_dnssec_validate_ds.patch > +++ /dev/null > @@ -1,98 +0,0 @@ > -From 3b799c826db05fc2da1c6d15cbe372e394209d27 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Thu, 17 Dec 2015 16:58:04 +0000 > -Subject: [PATCH] Fix brace botch in dnssec_validate_ds() > -MIME-Version: 1.0 > -Content-Type: text/plain; charset=3Dutf8 > -Content-Transfer-Encoding: 8bit > - > -Thanks to Micha=C3=85=E2=80=9A K=C3=84=E2=84=A2pie=C3=85=E2=80=9E for spot= ting this. > ---- > - src/dnssec.c |=C2=A0=C2=A0=C2=A034 +++++++++++++++++----------------- > - 1 file changed, 17 insertions(+), 17 deletions(-) > - > -diff --git a/src/dnssec.c b/src/dnssec.c > -index ddae497..1f8c954 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -923,11 +923,11 @@ static int validate_rrset(time_t now, struct > dns_header *header, size_t plen, in > - /* The DNS packet is expected to contain the answer to a DNSKEY > query. > -=C2=A0=C2=A0=C2=A0=C2=A0Put all DNSKEYs in the answer which are valid into= the cache. > -=C2=A0=C2=A0=C2=A0=C2=A0return codes: > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0STAT_OK=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Done, key(s) in cache. > -- =C2=A0STAT_BOGUS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0No DNSKE= Ys found, which=C2=A0=C2=A0can be > validated with DS, > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0or self-sign for DNSKEY RRset is not > valid, bad packet. > -- =C2=A0STAT_NEED_DS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0DS records to vali= date a key not found, > name in keyname=C2=A0 > -- =C2=A0STAT_NEED_DNSKEY=C2=A0=C2=A0DNSKEY records to validate a key not > found, name in keyname=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0STAT_OK=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Done, key(s) in cache. > -+ =C2=A0STAT_BOGUS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0No DNSKEYs found, which=C2= =A0=C2=A0can be validated > with DS, > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0or self-sign for DNSKEY RRset is not valid, > bad packet. > -+ =C2=A0STAT_NEED_DS=C2=A0=C2=A0=C2=A0DS records to validate a key not fou= nd, > name in keyname=C2=A0 > -+ =C2=A0STAT_NEED_KEY=C2=A0=C2=A0DNSKEY records to validate a key not foun= d, > name in keyname=C2=A0 > - */ > - int dnssec_validate_by_ds(time_t now, struct dns_header *header, > size_t plen, char *name, char *keyname, int class) > - { > -@@ -1224,13 +1224,13 @@ int dnssec_validate_ds(time_t now, struct > dns_header *header, size_t plen, char > -=C2=A0 } > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p =3D psave; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!ADD_RDLEN(header, p, plen, rdle= n)) > -- return STAT_BOGUS; /* bad packet */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0cache_end_insert(); > -+ =C2=A0=C2=A0if (!ADD_RDLEN(header, p, plen, rdlen)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return STAT_BOGUS; /* bad packet */ > -=C2=A0 } > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0cache_end_insert(); > -+ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0else > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -@@ -1828,10 +1828,10 @@ static int prove_non_existence(struct > dns_header *header, size_t plen, char *key > -=C2=A0 > - /* Check signing status of name. > -=C2=A0=C2=A0=C2=A0=C2=A0returns: > --=C2=A0=C2=A0=C2=A0STAT_SECURE=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0zone is = signed. > --=C2=A0=C2=A0=C2=A0STAT_INSECURE=C2=A0=C2=A0=C2=A0=C2=A0zone proved unsign= ed. > --=C2=A0=C2=A0=C2=A0STAT_NEED_DS=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0require DS re= cord of name returned in keyname. > --=C2=A0=C2=A0=C2=A0STAT_NEED_DNSKEY require DNSKEY record of name returned= in > keyname. > -+=C2=A0=C2=A0=C2=A0STAT_SECURE=C2=A0=C2=A0=C2=A0zone is signed. > -+=C2=A0=C2=A0=C2=A0STAT_INSECURE zone proved unsigned. > -+=C2=A0=C2=A0=C2=A0STAT_NEED_DS=C2=A0=C2=A0require DS record of name retur= ned in keyname. > -+=C2=A0=C2=A0=C2=A0STAT_NEED_KEY require DNSKEY record of name returned in= keyname. > -=C2=A0=C2=A0=C2=A0=C2=A0name returned unaltered. > - */ > - static int zone_status(char *name, int class, char *keyname, time_t > now) > -@@ -2028,7 +2028,7 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (rc =3D=3D STAT_SECURE) > -=C2=A0 rc =3D STAT_BOGUS; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (class) > -- =C2=A0*class =3D class1; /* Class for NEED_DS or > NEED_DNSKEY */ > -+ =C2=A0*class =3D class1; /* Class for NEED_DS or > NEED_KEY */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0else=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0rc =3D STAT_INSECURE;=C2=A0 > -@@ -2045,7 +2045,7 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0/* Zone is insecure, don't need to validate RRset > */ > -=C2=A0 =C2=A0=C2=A0if (class) > -- =C2=A0=C2=A0=C2=A0=C2=A0*class =3D class1; /* Class for NEED_DS or > NEED_DNSKEY */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0*class =3D class1; /* Class for NEED_DS or > NEED_KEY */ > -=C2=A0 =C2=A0=C2=A0return rc; > -=C2=A0 }=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -@@ -2115,7 +2115,7 @@ int dnssec_validate_reply(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0if ((rc =3D zone_status(name, qclass, keyna= me, now)) !=3D > STAT_SECURE) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 if (class) > -- =C2=A0=C2=A0*class =3D qclass; /* Class for NEED_DS or > NEED_DNSKEY */ > -+ =C2=A0=C2=A0*class =3D qclass; /* Class for NEED_DS or NEED_KEY > */ > -=C2=A0 return rc; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0}=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0 > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/024- > Do_a_better_job_of_determining_which_DNSSEC_sig_algos_are_supported.p > atch b/src/patches/dnsmasq/024- > Do_a_better_job_of_determining_which_DNSSEC_sig_algos_are_supported.p > atch > deleted file mode 100644 > index abcae5c..0000000 > --- a/src/patches/dnsmasq/024- > Do_a_better_job_of_determining_which_DNSSEC_sig_algos_are_supported.p > atch > +++ /dev/null > @@ -1,145 +0,0 @@ > -From 14a4ae883d51130d33da7133287e8867c64bab65 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Thu, 17 Dec 2015 17:23:03 +0000 > -Subject: [PATCH] Do a better job of determining which DNSSEC sig > algos are > - supported. > - > ---- > - src/dnssec.c |=C2=A0=C2=A0=C2=A052 +++++++++++++++++++++++++++++++++++++-= ------- > ------- > - 1 file changed, 37 insertions(+), 15 deletions(-) > - > -diff --git a/src/dnssec.c b/src/dnssec.c > -index 1f8c954..82394ee 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -65,10 +65,9 @@ static char *algo_digest_name(int algo) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 8: return "sha256"; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 10: return "sha512"; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 12: return "gosthash94"; > --#ifndef NO_NETTLE_ECC > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 13: return "sha256"; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 14: return "sha384"; > --#endif > -+ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0default: return NULL; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > - } > -@@ -129,13 +128,15 @@ static int hash_init(const struct nettle_hash > *hash, void **ctxp, unsigned char > - } > -=C2=A0=C2=A0=C2=A0 > - static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned > int key_len, unsigned char *sig, size_t sig_len, > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *digest, int algo) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *digest, size_t > digest_len, int algo) > - { > -=C2=A0=C2=A0=C2=A0unsigned char *p; > -=C2=A0=C2=A0=C2=A0size_t exp_len; > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0static struct rsa_public_key *key =3D NULL; > -=C2=A0=C2=A0=C2=A0static mpz_t sig_mpz; > -+ > -+=C2=A0=C2=A0(void)digest_len; > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0if (key =3D=3D NULL) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -@@ -181,7 +182,7 @@ static int dnsmasq_rsa_verify(struct blockdata > *key_data, unsigned int key_len, > - }=C2=A0=C2=A0 > -=C2=A0 > - static int dnsmasq_dsa_verify(struct blockdata *key_data, unsigned > int key_len, unsigned char *sig, size_t sig_len, > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *digest, int algo) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *digest, size_t > digest_len, int algo) > - { > -=C2=A0=C2=A0=C2=A0unsigned char *p; > -=C2=A0=C2=A0=C2=A0unsigned int t; > -@@ -189,6 +190,8 @@ static int dnsmasq_dsa_verify(struct blockdata > *key_data, unsigned int key_len, > -=C2=A0=C2=A0=C2=A0static struct dsa_public_key *key =3D NULL; > -=C2=A0=C2=A0=C2=A0static struct dsa_signature *sig_struct; > -=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0(void)digest_len; > -+ > -=C2=A0=C2=A0=C2=A0if (key =3D=3D NULL) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(sig_struct =3D whine_mallo= c(sizeof(struct > dsa_signature))) ||=C2=A0 > -@@ -292,26 +295,45 @@ static int dnsmasq_ecdsa_verify(struct > blockdata *key_data, unsigned int key_len > - }=C2=A0 > - #endif=C2=A0 > -=C2=A0 > --static int verify(struct blockdata *key_data, unsigned int key_len, > unsigned char *sig, size_t sig_len, > -- =C2=A0=C2=A0unsigned char *digest, size_t digest_len, int > algo) > -+static int (*verify_func(int algo))(struct blockdata *key_data, > unsigned int key_len, unsigned char *sig, size_t sig_len, > -+ =C2=A0=C2=A0=C2=A0=C2=A0unsigned char *digest, size_t > digest_len, int algo) > - { > --=C2=A0=C2=A0(void)digest_len; > -- > -+=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0/* Enure at runtime that we have support for this digest */ > -+=C2=A0=C2=A0if (!hash_find(algo_digest_name(algo))) > -+=C2=A0=C2=A0=C2=A0=C2=A0return NULL; > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0/* This switch defines which sig algorithms we support, can't > introspect Nettle for that. */ > -=C2=A0=C2=A0=C2=A0switch (algo) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 1: case 5: case 7: case 8: case 10: > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return dnsmasq_rsa_verify(key_data, k= ey_len, sig, sig_len, > digest, algo); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return dnsmasq_rsa_verify; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 3: case 6:=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return dnsmasq_dsa_verify(key_data, k= ey_len, sig, sig_len, > digest, algo); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return dnsmasq_dsa_verify; > -=C2=A0=C2=A0 > - #ifndef NO_NETTLE_ECC=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 13: case 14: > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return dnsmasq_ecdsa_verify(key_data,= key_len, sig, sig_len, > digest, digest_len, algo); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return dnsmasq_ecdsa_verify; > - #endif > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0return 0; > -+=C2=A0=C2=A0return NULL; > -+} > -+ > -+static int verify(struct blockdata *key_data, unsigned int key_len, > unsigned char *sig, size_t sig_len, > -+ =C2=A0=C2=A0unsigned char *digest, size_t digest_len, int > algo) > -+{ > -+ > -+=C2=A0=C2=A0int (*func)(struct blockdata *key_data, unsigned int key_len, > unsigned char *sig, size_t sig_len, > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *digest, size_t digest= _len, int algo); > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0func =3D verify_func(algo); > -+=C2=A0=C2=A0 > -+=C2=A0=C2=A0if (!func) > -+=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -+ > -+=C2=A0=C2=A0return (*func)(key_data, key_len, sig, sig_len, digest, > digest_len, algo); > - } > -=C2=A0 > - /* Convert from presentation format to wire format, in place. > -@@ -732,7 +754,7 @@ static int explore_rrset(struct dns_header > *header, size_t plen, int class, int > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (check_date_range(sig_incept= ion, sig_expiration) > && > -=C2=A0 =C2=A0=C2=A0labels <=3D name_labels && > -=C2=A0 =C2=A0=C2=A0type_covered =3D=3D type &&=C2=A0 > -- =C2=A0=C2=A0algo_digest_name(algo)) > -+ =C2=A0=C2=A0verify_func(algo)) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0if (!expand_workspace(&sigs, &sig_sz, sigidx)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0return 0;=C2=A0 > -@@ -1865,7 +1887,7 @@ static int zone_status(char *name, int class, > char *keyname, time_t now) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->flags & F_DNSSECOK) > -=C2=A0 return STAT_INSECURE; /* proved no DS here > */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else if (!ds_digest_name(crecp->addr.ds.digest) > || !algo_digest_name(crecp->addr.ds.algo)) > -+ =C2=A0=C2=A0else if (!hash_find(ds_digest_name(crecp- > >addr.ds.digest)) || !verify_func(crecp->addr.ds.algo)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; /* algo we can't use= - > insecure */ > -=C2=A0 =C2=A0=C2=A0else > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0secure_ds =3D 1; > -@@ -1887,7 +1909,7 @@ static int zone_status(char *name, int class, > char *keyname, time_t now) > -=C2=A0 > -=C2=A0 =C2=A0=C2=A0do=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->uid =3D=3D (unsigned int)= class && > !algo_digest_name(crecp->addr.key.algo)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->uid =3D=3D (unsigned int)= class && > !verify_func(crecp->addr.key.algo)) > -=C2=A0 return STAT_INSECURE; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0while ((crecp =3D cache_find_by_name(crecp, keyname, no= w, > F_DNSKEY))); > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/025- > Major_tidy_up_of_EDNS0_handling_and_computation_use_of_udp.patch > b/src/patches/dnsmasq/025- > Major_tidy_up_of_EDNS0_handling_and_computation_use_of_udp.patch > deleted file mode 100644 > index c016e73..0000000 > --- a/src/patches/dnsmasq/025- > Major_tidy_up_of_EDNS0_handling_and_computation_use_of_udp.patch > +++ /dev/null > @@ -1,643 +0,0 @@ > -From fa14bec83b2db010fd076910fddab56957b9375d Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Sun, 20 Dec 2015 17:12:16 +0000 > -Subject: [PATCH] Major tidy up of EDNS0 handling and computation/use > of udp > - packet size. > - > ---- > - src/auth.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A0=C2=A08 ++- > - src/dnsmasq.h=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A0=C2=A07 ++- > - src/dnssec.c=C2=A0=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A0=C2=A01 - > - src/forward.c=C2=A0=C2=A0|=C2=A0=C2=A0184 +++++++++++++++++++++++++++++++= +++++++++----- > ----------- > - src/netlink.c=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A0=C2=A03 +- > - src/rfc1035.c=C2=A0=C2=A0|=C2=A0=C2=A0=C2=A081 +++++++------------------ > - src/rrfilter.c |=C2=A0=C2=A0=C2=A0=C2=A02 +- > - 7 files changed, 168 insertions(+), 118 deletions(-) > - > -diff --git a/src/auth.c b/src/auth.c > -index 2b0b7d6..85bd5e7 100644 > ---- a/src/auth.c > -+++ b/src/auth.c > -@@ -81,7 +81,8 @@ int in_zone(struct auth_zone *zone, char *name, > char **cut) > - } > -=C2=A0 > -=C2=A0 > --size_t answer_auth(struct dns_header *header, char *limit, size_t > qlen, time_t now, union mysockaddr *peer_addr, int local_query)=C2=A0 > -+size_t answer_auth(struct dns_header *header, char *limit, size_t > qlen, time_t now, union mysockaddr *peer_addr,=C2=A0 > -+ =C2=A0=C2=A0=C2=A0int local_query, int do_bit, int > have_pseudoheader)=C2=A0 > - { > -=C2=A0=C2=A0=C2=A0char *name =3D daemon->namebuff; > -=C2=A0=C2=A0=C2=A0unsigned char *p, *ansp; > -@@ -820,6 +821,11 @@ size_t answer_auth(struct dns_header *header, > char *limit, size_t qlen, time_t n > -=C2=A0=C2=A0=C2=A0header->ancount =3D htons(anscount); > -=C2=A0=C2=A0=C2=A0header->nscount =3D htons(authcount); > -=C2=A0=C2=A0=C2=A0header->arcount =3D htons(0); > -+ > -+=C2=A0=C2=A0/* Advertise our packet size limit in our reply */ > -+=C2=A0=C2=A0if (have_pseudoheader) > -+=C2=A0=C2=A0=C2=A0=C2=A0return add_pseudoheader(header,=C2=A0=C2=A0ansp -= (unsigned char > *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, > do_bit); > -+ > -=C2=A0=C2=A0=C2=A0return ansp - (unsigned char *)header; > - } > -=C2=A0=C2=A0=C2=A0 > -diff --git a/src/dnsmasq.h b/src/dnsmasq.h > -index 39a930c..abb34c5 100644 > ---- a/src/dnsmasq.h > -+++ b/src/dnsmasq.h > -@@ -1113,7 +1113,7 @@ int extract_addresses(struct dns_header > *header, size_t qlen, char *namebuff, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int no_cache, int secure, int = *doctored); > - size_t answer_request(struct dns_header *header, char *limit, > size_t qlen,=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct in_addr local_addr, str= uct in_addr > local_netmask,=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0time_t now, int *ad_reqd, int *do_b= it); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0time_t now, int ad_reqd, int do_bit= , int > have_pseudoheader); > - int check_for_bogus_wildcard(struct dns_header *header, size_t > qlen, char *name,=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct bogus_addr *addr, time_t now= ); > - int check_for_ignored_address(struct dns_header *header, size_t > qlen, struct bogus_addr *baddr); > -@@ -1123,6 +1123,8 @@ int check_for_local_domain(char *name, time_t > now); > - unsigned int questions_crc(struct dns_header *header, size_t plen, > char *buff); > - size_t resize_packet(struct dns_header *header, size_t plen,=C2=A0 > -=C2=A0 =C2=A0=C2=A0unsigned char *pheader, size_t hlen); > -+size_t add_pseudoheader(struct dns_header *header, size_t plen, > unsigned char *limit,=C2=A0 > -+ unsigned short udp_sz, int optno, unsigned > char *opt, size_t optlen, int set_do); > - size_t add_mac(struct dns_header *header, size_t plen, char *limit, > union mysockaddr *l3); > - size_t add_source_addr(struct dns_header *header, size_t plen, char > *limit, union mysockaddr *source); > - #ifdef HAVE_DNSSEC > -@@ -1141,7 +1143,8 @@ int private_net(struct in_addr addr, int > ban_localhost); > - /* auth.c */ > - #ifdef HAVE_AUTH > - size_t answer_auth(struct dns_header *header, char *limit, size_t > qlen,=C2=A0 > -- =C2=A0=C2=A0=C2=A0time_t now, union mysockaddr *peer_addr, int > local_query); > -+ =C2=A0=C2=A0=C2=A0time_t now, union mysockaddr *peer_addr, int > local_query, > -+ =C2=A0=C2=A0=C2=A0int do_bit, int have_pseudoheader); > - int in_zone(struct auth_zone *zone, char *name, char **cut); > - #endif > -=C2=A0 > -diff --git a/src/dnssec.c b/src/dnssec.c > -index 82394ee..299ca64 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -67,7 +67,6 @@ static char *algo_digest_name(int algo) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 12: return "gosthash94"; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 13: return "sha256"; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case 14: return "sha384"; > -- > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0default: return NULL; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > - } > -diff --git a/src/forward.c b/src/forward.c > -index 3e801c8..041353c 100644 > ---- a/src/forward.c > -+++ b/src/forward.c > -@@ -244,7 +244,6 @@ static int forward_query(int udpfd, union > mysockaddr *udpaddr, > -=C2=A0=C2=A0=C2=A0void *hash =3D &crc; > - #endif > -=C2=A0=C2=A0unsigned int gotname =3D extract_request(header, plen, daemon- > >namebuff, NULL); > -- unsigned char *pheader; > -=C2=A0 > -=C2=A0=C2=A0(void)do_bit; > -=C2=A0 > -@@ -264,7 +263,8 @@ static int forward_query(int udpfd, union > mysockaddr *udpaddr, > -=C2=A0 =C2=A0there's no point retrying the query, retry the key query > instead...... */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (forward->blocking_query) > -=C2=A0 { > -- =C2=A0=C2=A0int fd; > -+ =C2=A0=C2=A0int fd, is_sign; > -+ =C2=A0=C2=A0unsigned char *pheader; > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0forward->flags &=3D ~FREC_TEST_PKTSZ; > -=C2=A0 =C2=A0=C2=A0 > -@@ -276,8 +276,8 @@ static int forward_query(int udpfd, union > mysockaddr *udpaddr, > -=C2=A0 =C2=A0=C2=A0blockdata_retrieve(forward->stash, forward->stash_len, > (void *)header); > -=C2=A0 =C2=A0=C2=A0plen =3D forward->stash_len; > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (find_pseudoheader(header, plen, NULL, &pheader, > NULL)) > -- =C2=A0=C2=A0=C2=A0=C2=A0PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? > SAFE_PKTSZ : forward->sentto->edns_pktsz, pheader); > -+ =C2=A0=C2=A0if (find_pseudoheader(header, plen, NULL, &pheader, > &is_sign) && !is_sign) > -+ =C2=A0=C2=A0=C2=A0=C2=A0PUTSHORT(SAFE_PKTSZ, pheader); > -=C2=A0 > -=C2=A0 =C2=A0=C2=A0if (forward->sentto->addr.sa.sa_family =3D=3D AF_INET)= =C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "r= etry", > (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec"); > -@@ -394,32 +394,40 @@ static int forward_query(int udpfd, union > mysockaddr *udpaddr, > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0forward->log_id =3D daemon->log_= id; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (option_bool(OPT_ADD_MAC)) > -- plen =3D add_mac(header, plen, ((char *) header) + daemon- > >packet_buff_sz, &forward->source); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ { > -+ =C2=A0=C2=A0size_t new =3D add_mac(header, plen, ((char *) header) + > daemon->packet_buff_sz, &forward->source); > -+ =C2=A0=C2=A0if (new !=3D plen) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0plen =3D new; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0forward->flags |=3D FREC_ADDED_PHEAD= ER; > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ } > -+ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (option_bool(OPT_CLIENT_SUBNE= T)) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0size_t new =3D add_source_addr(header, plen, ((char *) > header) + daemon->packet_buff_sz, &forward->source);=C2=A0 > -=C2=A0 =C2=A0=C2=A0if (new !=3D plen) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0plen =3D new; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0forward->flags |=3D FREC_HAS_SUBNET; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0forward->flags |=3D FREC_HAS_SUBNET | > FREC_ADDED_PHEADER; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 } > -=C2=A0 > - #ifdef HAVE_DNSSEC > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (option_bool(OPT_DNSSEC_VALID= )) > -=C2=A0 { > -- =C2=A0=C2=A0size_t new_plen =3D add_do_bit(header, plen, ((char *) > header) + daemon->packet_buff_sz); > -+ =C2=A0=C2=A0size_t new =3D add_do_bit(header, plen, ((char *) header) + > daemon->packet_buff_sz); > -=C2=A0 =C2=A0 > -+ =C2=A0=C2=A0if (new !=3D plen) > -+ =C2=A0=C2=A0=C2=A0=C2=A0forward->flags |=3D FREC_ADDED_PHEADER; > -+ > -+ =C2=A0=C2=A0plen =3D new; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0/* For debugging, set Checking Disabled, otherwise, have > the upstream check too, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0this allows it to select auth servers= when one is > returning bad data. */ > -=C2=A0 =C2=A0=C2=A0if (option_bool(OPT_DNSSEC_DEBUG)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0header->hb4 |=3D HB4_CD; > -=C2=A0 > -- =C2=A0=C2=A0if (new_plen !=3D plen) > -- =C2=A0=C2=A0=C2=A0=C2=A0forward->flags |=3D FREC_ADDED_PHEADER; > -- > -- =C2=A0=C2=A0plen =3D new_plen; > -=C2=A0 } > - #endif > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -@@ -469,10 +477,23 @@ static int forward_query(int udpfd, union > mysockaddr *udpaddr, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > - #endif > -=C2=A0 } > -- > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (find_pseudoheader(header, plen, = NULL, &pheader, > NULL)) > -- PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? > SAFE_PKTSZ : start->edns_pktsz, pheader); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+#ifdef HAVE_DNSSEC > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (option_bool(OPT_DNSSEC_VALID) &&= !do_bit) > -+ { > -+ =C2=A0=C2=A0/* Difficult one here. If our client didn't send > EDNS0, we will have set the UDP > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0packet size to 512. But that won't provide > space for the RRSIGS in many cases. > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0The RRSIGS will be stripped out before the > answer goes back, so the packet should > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0shrink again. So, if we added a do-bit, b= ump > the udp packet size to the value > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0known to be OK for this server. Maybe che= ck > returned size after stripping and set > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0the truncated bit? */ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0unsigned char *pheader; > -+ =C2=A0=C2=A0int is_sign; > -+ =C2=A0=C2=A0if (find_pseudoheader(header, plen, NULL, > &pheader, &is_sign)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0PUTSHORT(start->edns_pktsz, pheader); > -+ } > -+#endif > -+ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (retry_send(sendto(fd, (char= *)header, plen, 0, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0&start->addr.sa, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0sa_len(&start->addr)))) > -@@ -563,30 +584,34 @@ static size_t process_reply(struct dns_header > *header, time_t now, struct server > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > - #endif > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0/* If upstream is advertising a larger UDP packet size > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0than we allow, trim it so that we don't get= overlarge > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0requests for the client. We can't do this f= or signed packets. > */ > -- > -=C2=A0=C2=A0=C2=A0if ((pheader =3D find_pseudoheader(header, n, &plen, &si= zep, > &is_sign))) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned short udpsz; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *psave =3D sizep; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(udpsz, sizep); > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!is_sign && udpsz > daemon->edns_= pktsz) > -- PUTSHORT(daemon->edns_pktsz, psave); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (check_subnet && !check_sourc= e(header, plen, pheader, > query_source)) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0my_syslog(LOG_WARNING, _("discarding DNS reply: subnet > option mismatch")); > -=C2=A0 =C2=A0=C2=A0return 0; > -=C2=A0 } > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (added_pheader) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!is_sign) > -=C2=A0 { > -- =C2=A0=C2=A0pheader =3D 0;=C2=A0 > -- =C2=A0=C2=A0header->arcount =3D htons(0); > -+ =C2=A0=C2=A0if (added_pheader) > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* client didn't send EDNS0, we adde= d one, strip it > off before returning answer. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0n =3D rrfilter(header, n, 0); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0pheader =3D NULL; > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0else > -+ =C2=A0=C2=A0=C2=A0=C2=A0{ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* If upstream is advertising a larg= er UDP packet > size > -+ =C2=A0than we allow, trim it so that we don't get > overlarge > -+ =C2=A0requests for the client. We can't do this for > signed packets. */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned short udpsz; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *psave =3D sizep; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(udpsz, sizep); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (udpsz > daemon->edns_pktsz) > -+ PUTSHORT(daemon->edns_pktsz, psave); > -+ =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 } > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0 > -@@ -655,14 +680,16 @@ static size_t process_reply(struct dns_header > *header, time_t now, struct server > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if (option_bool(OPT_DNSSEC_VALID)) > --=C2=A0=C2=A0=C2=A0=C2=A0header->hb4 &=3D ~HB4_AD; > --=C2=A0=C2=A0 > --=C2=A0=C2=A0if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure) > --=C2=A0=C2=A0=C2=A0=C2=A0header->hb4 |=3D HB4_AD; > -- > --=C2=A0=C2=A0/* If the requestor didn't set the DO bit, don't return DNSSEC > info. */ > --=C2=A0=C2=A0if (!do_bit) > --=C2=A0=C2=A0=C2=A0=C2=A0n =3D rrfilter(header, n, 1); > -+=C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0header->hb4 &=3D ~HB4_AD; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(header->hb4 & HB4_CD) && ad_req= d && cache_secure) > -+ header->hb4 |=3D HB4_AD; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* If the requestor didn't set the DO= bit, don't return > DNSSEC info. */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!do_bit) > -+ n =3D rrfilter(header, n, 1); > -+=C2=A0=C2=A0=C2=A0=C2=A0} > - #endif > -=C2=A0 > -=C2=A0=C2=A0=C2=A0/* do this after extract_addresses. Ensure NODATA reply = and > remove > -@@ -761,8 +788,14 @@ void reply_query(int fd, int family, time_t > now) > -=C2=A0 =C2=A0=C2=A0if ((nn =3D resize_packet(header, (size_t)n, pheader, > plen))) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0header->hb3 &=3D ~(HB3_QR | HB3= _AA | HB3_TC); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0header->hb4 &=3D ~(HB4_RA | HB4_RCOD= E); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0forward_query(-1, NULL, NULL, 0, hea= der, nn, now, > forward, 0, 0); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0header->hb4 &=3D ~(HB4_RA | HB4_RCOD= E | HB4_CD | > HB4_AD); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (forward->flags |=3D FREC_CHECKIN= G_DISABLED) > -+ header->hb4 |=3D HB4_CD; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (forward->flags |=3D FREC_AD_QUES= TION) > -+ header->hb4 |=3D HB4_AD; > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (forward->flags & FREC_DO_QUESTIO= N) > -+ add_do_bit(header, nn,=C2=A0=C2=A0(char *)pheader + plen); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0forward_query(-1, NULL, NULL, 0, hea= der, nn, now, > forward, forward->flags & FREC_AD_QUESTION, forward->flags & > FREC_DO_QUESTION); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 } > -@@ -1007,12 +1040,13 @@ void receive_query(struct listener *listen, > time_t now) > - { > -=C2=A0=C2=A0=C2=A0struct dns_header *header =3D (struct dns_header *)daemo= n->packet; > -=C2=A0=C2=A0=C2=A0union mysockaddr source_addr; > --=C2=A0=C2=A0unsigned short type; > -+=C2=A0=C2=A0unsigned char *pheader; > -+=C2=A0=C2=A0unsigned short type, udp_size =3D PACKETSZ; /* default if no = EDNS0 > */ > -=C2=A0=C2=A0=C2=A0struct all_addr dst_addr; > -=C2=A0=C2=A0=C2=A0struct in_addr netmask, dst_addr_4; > -=C2=A0=C2=A0=C2=A0size_t m; > -=C2=A0=C2=A0=C2=A0ssize_t n; > --=C2=A0=C2=A0int if_index =3D 0, auth_dns =3D 0; > -+=C2=A0=C2=A0int if_index =3D 0, auth_dns =3D 0, do_bit =3D 0, have_pseudo= header =3D > 0; > - #ifdef HAVE_AUTH > -=C2=A0=C2=A0=C2=A0int local_auth =3D 0; > - #endif > -@@ -1279,10 +1313,30 @@ void receive_query(struct listener *listen, > time_t now) > - #endif > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL= )) > -+=C2=A0=C2=A0=C2=A0=C2=A0{=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned short flags; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0have_pseudoheader =3D 1; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(udp_size, pheader); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0pheader +=3D 2; /* ext_rcode */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(flags, pheader); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (flags & 0x8000) > -+ do_bit =3D 1;/* do bit */=C2=A0 > -+=09 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* If the client provides an EDNS0 UD= P size, use that to > limit our reply. > -+ =C2=A0(bounded by the maximum configured). If no EDNS0, then it > -+ =C2=A0defaults to 512 */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (udp_size > daemon->edns_pktsz) > -+ udp_size =3D daemon->edns_pktsz; > -+=C2=A0=C2=A0=C2=A0=C2=A0} > -+ > - #ifdef HAVE_AUTH > -=C2=A0=C2=A0=C2=A0if (auth_dns) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0m =3D answer_auth(header, ((char *) h= eader) + daemon- > >packet_buff_sz, (size_t)n, now, &source_addr, local_auth); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0m =3D answer_auth(header, ((char *) h= eader) + udp_size, > (size_t)n, now, &source_addr,=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0local_auth, do_bit, have_pseudohead= er); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (m >=3D 1) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0send_from(listen->fd, option_bool(OPT_NOWILD) || > option_bool(OPT_CLEVERBIND), > -@@ -1293,9 +1347,13 @@ void receive_query(struct listener *listen, > time_t now) > -=C2=A0=C2=A0=C2=A0else > - #endif > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int ad_reqd, do_bit; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0m =3D answer_request(header, ((char *= ) header) + daemon- > >packet_buff_sz, (size_t)n,=C2=A0 > -- =C2=A0dst_addr_4, netmask, now, &ad_reqd, > &do_bit); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int ad_reqd =3D do_bit; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* RFC 6840 5.7 */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (header->hb4 & HB4_AD) > -+ ad_reqd =3D 1; > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0m =3D answer_request(header, ((char *= ) header) + udp_size, > (size_t)n,=C2=A0 > -+ =C2=A0dst_addr_4, netmask, now, ad_reqd, do_bit, > have_pseudoheader); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (m >=3D 1) > -=C2=A0 { > -@@ -1397,7 +1455,7 @@ unsigned char *tcp_request(int confd, time_t > now, > - #ifdef HAVE_AUTH > -=C2=A0=C2=A0=C2=A0int local_auth =3D 0; > - #endif > --=C2=A0=C2=A0int checking_disabled, ad_question, do_bit, added_pheader =3D= 0; > -+=C2=A0=C2=A0int checking_disabled, do_bit, added_pheader =3D 0, > have_pseudoheader =3D 0; > -=C2=A0=C2=A0=C2=A0int check_subnet, no_cache_dnssec =3D 0, cache_secure = =3D 0, > bogusanswer =3D 0; > -=C2=A0=C2=A0=C2=A0size_t m; > -=C2=A0=C2=A0=C2=A0unsigned short qtype; > -@@ -1414,6 +1472,7 @@ unsigned char *tcp_request(int confd, time_t > now, > -=C2=A0=C2=A0=C2=A0union mysockaddr peer_addr; > -=C2=A0=C2=A0=C2=A0socklen_t peer_len =3D sizeof(union mysockaddr); > -=C2=A0=C2=A0=C2=A0int query_count =3D 0; > -+=C2=A0=C2=A0unsigned char *pheader; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if (getpeername(confd, (struct sockaddr *)&peer_addr, &p= eer_len) > =3D=3D -1) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return packet; > -@@ -1508,15 +1567,35 @@ unsigned char *tcp_request(int confd, time_t > now, > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -=C2=A0 dst_addr_4.s_addr =3D 0; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0do_bit =3D 0; > -+ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (find_pseudoheader(header, (size_t= )size, NULL, &pheader, > NULL)) > -+ {=C2=A0 > -+ =C2=A0=C2=A0unsigned short flags; > -+ =C2=A0=C2=A0 > -+ =C2=A0=C2=A0have_pseudoheader =3D 1; > -+ =C2=A0=C2=A0pheader +=3D 4; /* udp_size, ext_rcode */ > -+ =C2=A0=C2=A0GETSHORT(flags, pheader); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0if (flags & 0x8000) > -+ =C2=A0=C2=A0=C2=A0=C2=A0do_bit =3D 1;/* do bit */=C2=A0 > -+ } > -+ > - #ifdef HAVE_AUTH > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (auth_dns) > -- m =3D answer_auth(header, ((char *) header) + 65536, > (size_t)size, now, &peer_addr, local_auth); > -+ m =3D answer_auth(header, ((char *) header) + 65536, > (size_t)size, now, &peer_addr,=C2=A0 > -+ local_auth, do_bit, have_pseudoheader); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > - #endif > -=C2=A0 { > -- =C2=A0=C2=A0/* m > 0 if answered from cache */ > -- =C2=A0=C2=A0m =3D answer_request(header, ((char *) header) + 65536, > (size_t)size,=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0dst_addr_4, netmask, now, > &ad_question, &do_bit); > -+ =C2=A0=C2=A0=C2=A0int ad_reqd =3D do_bit; > -+ =C2=A0=C2=A0=C2=A0/* RFC 6840 5.7 */ > -+ =C2=A0=C2=A0=C2=A0if (header->hb4 & HB4_AD) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ad_reqd =3D 1; > -+ =C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0/* m > 0 if answered from cache */ > -+ =C2=A0=C2=A0=C2=A0m =3D answer_request(header, ((char *) header) + 65536, > (size_t)size,=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0dst_addr_4, netmask, now, ad_reqd, > do_bit, have_pseudoheader); > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0/* Do this by steam now we're not in the select() loop = */ > -=C2=A0 =C2=A0=C2=A0check_log_writer(1);=C2=A0 > -@@ -1615,6 +1694,7 @@ unsigned char *tcp_request(int confd, time_t > now, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0 > - #ifdef HAVE_DNSSEC > -+ =C2=A0=C2=A0added_pheader =3D 0; =09 > =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0if (option_bool(OPT_DNSSEC_VALID)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0size_t new_size =3D add_do_bi= t(header, > size, ((char *) header) + 65536); > -@@ -1719,7 +1799,7 @@ unsigned char *tcp_request(int confd, time_t > now, > -=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0m =3D process_reply(header, no= w, last_server, > (unsigned int)m,=C2=A0 > -=C2=A0 option_bool(OPT_NO_REBIND) > && !norebind, no_cache_dnssec, cache_secure, bogusanswer, > -- ad_question, do_bit, > added_pheader, check_subnet, &peer_addr);=C2=A0 > -+ ad_reqd, do_bit, > added_pheader, check_subnet, &peer_addr);=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0break; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -diff --git a/src/netlink.c b/src/netlink.c > -index 753784d..3376d68 100644 > ---- a/src/netlink.c > -+++ b/src/netlink.c > -@@ -288,7 +288,8 @@ int iface_enumerate(int family, void *parm, int > (*callback)()) > -=C2=A0 rta =3D RTA_NEXT(rta, len1); > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0if (inaddr && mac && callback_ok) > -+ =C2=A0=C2=A0=C2=A0=C2=A0if (!(neigh->ndm_state & (NUD_NOARP | NUD_INCOMP= LETE | > NUD_FAILED)) && > -+ inaddr && mac && callback_ok) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!((*callback)(neigh->ndm_fa= mily, inaddr, mac, > maclen, parm))) > -=C2=A0 callback_ok =3D 0; > -=C2=A0 =C2=A0=C2=A0} > -diff --git a/src/rfc1035.c b/src/rfc1035.c > -index 188d05f..18858a8 100644 > ---- a/src/rfc1035.c > -+++ b/src/rfc1035.c > -@@ -489,8 +489,8 @@ struct macparm { > -=C2=A0=C2=A0=C2=A0union mysockaddr *l3; > - }; > -=C2=A0=C2=A0 > --static size_t add_pseudoheader(struct dns_header *header, size_t > plen, unsigned char *limit,=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int optno, unsigned char *op= t, > size_t optlen, int set_do) > -+size_t add_pseudoheader(struct dns_header *header, size_t plen, > unsigned char *limit,=C2=A0 > -+ unsigned short udp_sz, int optno, unsigned > char *opt, size_t optlen, int set_do) > - {=C2=A0 > -=C2=A0=C2=A0=C2=A0unsigned char *lenp, *datap, *p; > -=C2=A0=C2=A0=C2=A0int rdlen, is_sign; > -@@ -508,7 +508,7 @@ static size_t add_pseudoheader(struct dns_header > *header, size_t plen, unsigned > -=C2=A0 return plen; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*p++ =3D 0; /* empty name */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0PUTSHORT(T_OPT, p); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0PUTSHORT(SAFE_PKTSZ, p); /* max packe= t length, this will be > overwritten */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0PUTSHORT(udp_sz, p); /* max packet le= ngth, 512 if not given > in EDNS0 header */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0PUTSHORT(0, p);=C2=A0=C2=A0=C2= =A0=C2=A0/* extended RCODE and version */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0PUTSHORT(set_do ? 0x8000 : 0, p)= ; /* DO flag */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0lenp =3D p; > -@@ -594,7 +594,7 @@ static int filter_mac(int family, char *addrp, > char *mac, size_t maclen, void *p > -=C2=A0=C2=A0=C2=A0if (!match) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return 1; /* continue */ > -=C2=A0 > --=C2=A0=C2=A0parm->plen =3D add_pseudoheader(parm->header, parm->plen, par= m- > >limit,=C2=A0=C2=A0EDNS0_OPTION_MAC, (unsigned char *)mac, maclen, 0); > -+=C2=A0=C2=A0parm->plen =3D add_pseudoheader(parm->header, parm->plen, par= m- > >limit, PACKETSZ, EDNS0_OPTION_MAC, (unsigned char *)mac, maclen, 0); > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0return 0; /* done */ > - } =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -@@ -603,12 +603,6 @@ size_t add_mac(struct dns_header *header, > size_t plen, char *limit, union mysock > - { > -=C2=A0=C2=A0=C2=A0struct macparm parm; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --/* Must have an existing pseudoheader as the only ar-record,=C2=A0 > --=C2=A0=C2=A0=C2=A0or have no ar-records. Must also not be signed */ > --=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0if (ntohs(header->arcount) > 1) > --=C2=A0=C2=A0=C2=A0=C2=A0return plen; > -- > -=C2=A0=C2=A0=C2=A0parm.header =3D header; > -=C2=A0=C2=A0=C2=A0parm.limit =3D (unsigned char *)limit; > -=C2=A0=C2=A0=C2=A0parm.plen =3D plen; > -@@ -699,13 +693,13 @@ size_t add_source_addr(struct dns_header > *header, size_t plen, char *limit, unio > -=C2=A0=C2=A0=C2=A0struct subnet_opt opt; > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0len =3D calc_subnet_opt(&opt, source); > --=C2=A0=C2=A0return add_pseudoheader(header, plen, (unsigned char *)limit, > EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0); > -+=C2=A0=C2=A0return add_pseudoheader(header, plen, (unsigned char *)limit, > PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0); > - } > -=C2=A0 > - #ifdef HAVE_DNSSEC > - size_t add_do_bit(struct dns_header *header, size_t plen, char > *limit) > - { > --=C2=A0=C2=A0return add_pseudoheader(header, plen, (unsigned char *)limit,= 0, > NULL, 0, 1); > -+=C2=A0=C2=A0return add_pseudoheader(header, plen, (unsigned char *)limit, > PACKETSZ, 0, NULL, 0, 1); > - } > - #endif > -=C2=A0 > -@@ -1525,16 +1519,16 @@ static unsigned long crec_ttl(struct crec > *crecp, time_t now) > - /* return zero if we can't answer from cache, or packet size if we > can */ > - size_t answer_request(struct dns_header *header, char *limit, > size_t qlen,=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0struct in_addr local_addr, str= uct in_addr > local_netmask,=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0time_t now, int *ad_reqd, int *do_b= it)=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0time_t now, int ad_reqd, int do_bit= , int > have_pseudoheader)=C2=A0 > - { > -=C2=A0=C2=A0=C2=A0char *name =3D daemon->namebuff; > --=C2=A0=C2=A0unsigned char *p, *ansp, *pheader; > -+=C2=A0=C2=A0unsigned char *p, *ansp; > -=C2=A0=C2=A0=C2=A0unsigned int qtype, qclass; > -=C2=A0=C2=A0=C2=A0struct all_addr addr; > -=C2=A0=C2=A0=C2=A0int nameoffset; > -=C2=A0=C2=A0=C2=A0unsigned short flag; > -=C2=A0=C2=A0=C2=A0int q, ans, anscount =3D 0, addncount =3D 0; > --=C2=A0=C2=A0int dryrun =3D 0, sec_reqd =3D 0, have_pseudoheader =3D 0; > -+=C2=A0=C2=A0int dryrun =3D 0; > -=C2=A0=C2=A0=C2=A0struct crec *crecp; > -=C2=A0=C2=A0=C2=A0int nxdomain =3D 0, auth =3D 1, trunc =3D 0, sec_data = =3D 1; > -=C2=A0=C2=A0=C2=A0struct mx_srv_record *rec; > -@@ -1550,35 +1544,11 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0=C2=A0=C2=A0if (header->hb4 & HB4_CD) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0sec_data =3D 0; > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0/* RFC 6840 5.7 */ > --=C2=A0=C2=A0*ad_reqd =3D header->hb4 & HB4_AD; > --=C2=A0=C2=A0*do_bit =3D 0; > -- > -=C2=A0=C2=A0=C2=A0/* If there is an=C2=A0=C2=A0additional data section the= n it will be > overwritten by > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0partial replies, so we have to do a dr= y run to see if we can > answer > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0the query. */ > -- > -=C2=A0=C2=A0=C2=A0if (ntohs(header->arcount) !=3D 0) > --=C2=A0=C2=A0=C2=A0=C2=A0{ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0dryrun =3D 1; > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* If there's an additional section, = there might be an > EDNS(0) pseudoheader */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (find_pseudoheader(header, qlen, N= ULL, &pheader, NULL)) > -- {=C2=A0 > -- =C2=A0=C2=A0unsigned short flags; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0have_pseudoheader =3D 1; > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0pheader +=3D 4; /* udp size, ext_rcode */ > -- =C2=A0=C2=A0GETSHORT(flags, pheader); > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if ((sec_reqd =3D flags & 0x8000)) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*do_bit =3D 1;/* do bit */=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*ad_reqd =3D 1; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- } > --=C2=A0=C2=A0=C2=A0=C2=A0} > -+=C2=A0=C2=A0=C2=A0=C2=A0dryrun =3D 1; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0for (rec =3D daemon->mxnames; rec; rec =3D rec->next) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0rec->offset =3D 0; > -@@ -1603,11 +1573,6 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(qtype, p);=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(qclass, p); > -=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Don't filter RRSIGS from answers t= o ANY queries, even if > do-bit > -- =C2=A0not set. */ > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (qtype =3D=3D T_ANY) > -- *do_bit =3D 1; > -- > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ans =3D 0; /* have we answered t= his question */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (qtype =3D=3D T_TXT || qtype = =3D=3D T_ANY) > -@@ -1739,7 +1704,7 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0the zone is unsigned, which implies = that we're > doing > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0validation. */ > -=C2=A0 =C2=A0=C2=A0if ((crecp->flags & (F_HOSTS | F_DHCP | > F_CONFIG)) ||=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0!sec_reqd ||=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0!do_bit ||=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(option_bool(OPT_DNSSEC_VALID)= && !(crecp- > >flags & F_DNSSECOK))) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0do=C2=A0 > -@@ -1927,7 +1892,7 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > -=C2=A0 =C2=A0=C2=A0/* If the client asked for DNSSEC=C2=A0=C2=A0don't use > cached data. */ > -- =C2=A0=C2=A0if ((crecp->flags & (F_HOSTS | F_DHCP | > F_CONFIG)) || !sec_reqd || !(crecp->flags & F_DNSSECOK)) > -+ =C2=A0=C2=A0if ((crecp->flags & (F_HOSTS | F_DHCP | > F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0do > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{=C2=A0 > -=C2=A0 /* don't answer wildcard queries with data > not from /etc/hosts > -@@ -1961,17 +1926,12 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 =09 > -=C2=A0 if (crecp->flags & F_NEG) > -=C2=A0 =C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0/* We don't cache NSEC records, so if a > DNSSEC-validated negative answer > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0is cached and the client wan= ts > DNSSEC, forward rather than answering from the cache */ > -- =C2=A0=C2=A0=C2=A0=C2=A0if (!sec_reqd || !(crecp->flags & > F_DNSSECOK)) > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -- ans =3D 1; > -- auth =3D 0; > -- if (crecp->flags & F_NXDOMAIN) > -- =C2=A0=C2=A0nxdomain =3D 1; > -- if (!dryrun) > -- =C2=A0=C2=A0log_query(crecp->flags, name, > NULL, NULL); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -+ =C2=A0=C2=A0=C2=A0=C2=A0ans =3D 1; > -+ =C2=A0=C2=A0=C2=A0=C2=A0auth =3D 0; > -+ =C2=A0=C2=A0=C2=A0=C2=A0if (crecp->flags & F_NXDOMAIN) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0nxdomain =3D 1; > -+ =C2=A0=C2=A0=C2=A0=C2=A0if (!dryrun) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0log_query(crecp->flags, name, NULL, > NULL); > -=C2=A0 =C2=A0=C2=A0} > -=C2=A0 else=C2=A0 > -=C2=A0 =C2=A0=C2=A0{ > -@@ -2209,10 +2169,11 @@ size_t answer_request(struct dns_header > *header, char *limit, size_t qlen, > -=C2=A0 > -=C2=A0=C2=A0=C2=A0len =3D ansp - (unsigned char *)header; > -=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0/* Advertise our packet size limit in our reply */ > -=C2=A0=C2=A0=C2=A0if (have_pseudoheader) > --=C2=A0=C2=A0=C2=A0=C2=A0len =3D add_pseudoheader(header, len, (unsigned c= har *)limit, 0, > NULL, 0, sec_reqd); > -+=C2=A0=C2=A0=C2=A0=C2=A0len =3D add_pseudoheader(header, len, (unsigned c= har *)limit, > daemon->edns_pktsz, 0, NULL, 0, do_bit); > -=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0if (*ad_reqd && sec_data) > -+=C2=A0=C2=A0if (ad_reqd && sec_data) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0header->hb4 |=3D HB4_AD; > -=C2=A0=C2=A0=C2=A0else > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0header->hb4 &=3D ~HB4_AD; > -diff --git a/src/rrfilter.c b/src/rrfilter.c > -index ae12261..b26b39f 100644 > ---- a/src/rrfilter.c > -+++ b/src/rrfilter.c > -@@ -243,7 +243,7 @@ size_t rrfilter(struct dns_header *header, > size_t plen, int mode) > -=C2=A0=C2=A0=C2=A0for (p =3D rrs[0], i =3D 1; i < rr_found; i +=3D 2) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *start =3D rrs[i]; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *end =3D (i !=3D rr_fou= nd - 1) ? rrs[i+1] : > ((unsigned char *)(header+1)) + plen; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *end =3D (i !=3D rr_fou= nd - 1) ? rrs[i+1] : > ((unsigned char *)header) + plen; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0memmove(p, start, end-start); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D end-start; > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/026- > More_tweaks_in_handling_unknown_DNSSEC_algorithms.patch > b/src/patches/dnsmasq/026- > More_tweaks_in_handling_unknown_DNSSEC_algorithms.patch > deleted file mode 100644 > index 910921b..0000000 > --- a/src/patches/dnsmasq/026- > More_tweaks_in_handling_unknown_DNSSEC_algorithms.patch > +++ /dev/null > @@ -1,262 +0,0 @@ > -From d67ecac59d58f249707d26e38d49c29b552af4d8 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Sun, 20 Dec 2015 20:44:23 +0000 > -Subject: [PATCH] More tweaks in handling unknown DNSSEC algorithms. > - > ---- > - src/dnssec.c |=C2=A0=C2=A0128 +++++++++++++++++++++++++++++--------------= -- > ------------- > - 1 file changed, 63 insertions(+), 65 deletions(-) > - > -diff --git a/src/dnssec.c b/src/dnssec.c > -index 299ca64..e09f304 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -70,7 +70,17 @@ static char *algo_digest_name(int algo) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0default: return NULL; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > - } > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0 > -+/* http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-n > sec3-parameters.xhtml */ > -+static char *nsec3_digest_name(int digest) > -+{ > -+=C2=A0=C2=A0switch (digest) > -+=C2=A0=C2=A0=C2=A0=C2=A0{ > -+=C2=A0=C2=A0=C2=A0=C2=A0case 1: return "sha1"; > -+=C2=A0=C2=A0=C2=A0=C2=A0default: return NULL; > -+=C2=A0=C2=A0=C2=A0=C2=A0} > -+} > -+=C2=A0 > - /* Find pointer to correct hash function in nettle library */ > - static const struct nettle_hash *hash_find(char *name) > - { > -@@ -667,7 +677,6 @@ static int explore_rrset(struct dns_header > *header, size_t plen, int class, int > -=C2=A0=C2=A0=C2=A0static int rrset_sz =3D 0, sig_sz =3D 0;=C2=A0 > -=C2=A0=C2=A0=C2=A0unsigned char *p; > -=C2=A0=C2=A0=C2=A0int rrsetidx, sigidx, j, rdlen, res; > --=C2=A0=C2=A0int name_labels =3D count_labels(name); /* For 4035 5.3.2 che= ck */ > -=C2=A0=C2=A0=C2=A0int gotkey =3D 0; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0if (!(p =3D skip_questions(header, plen))) > -@@ -678,7 +687,7 @@ static int explore_rrset(struct dns_header > *header, size_t plen, int class, int > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0j !=3D 0; j--)=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *pstart, *pdata; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int stype, sclass, algo, type_covered= , labels, > sig_expiration, sig_inception; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int stype, sclass, type_covered; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0pstart =3D p; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -@@ -712,12 +721,7 @@ static int explore_rrset(struct dns_header > *header, size_t plen, int class, int > -=C2=A0 return 0; /* bad packet */=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(type_covered, p); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0algo =3D *p++; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0labels =3D *p++; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 4; /* orig_ttl */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETLONG(sig_expiration, p); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETLONG(sig_inception, p); > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 2; /* key_tag */ > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 16; /* algo, labels, orig_ttl= , sig_expiration, > sig_inception, key_tag */ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (gotkey) > -=C2=A0 { > -@@ -749,11 +753,8 @@ static int explore_rrset(struct dns_header > *header, size_t plen, int class, int > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 } > -=C2=A0 =C2=A0=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* Don't count signatures for algos = we don't support > */ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (check_date_range(sig_inception, = sig_expiration) > && > -- =C2=A0=C2=A0labels <=3D name_labels && > -- =C2=A0=C2=A0type_covered =3D=3D type &&=C2=A0 > -- =C2=A0=C2=A0verify_func(algo)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (type_covered =3D=3D type) > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0if (!expand_workspace(&sigs, &sig_sz, sigidx)) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0return 0;=C2=A0 > -@@ -795,7 +796,7 @@ static int validate_rrset(time_t now, struct > dns_header *header, size_t plen, in > -=C2=A0 =C2=A0=C2=A0char *name, char *keyname, char > **wildcard_out, struct blockdata *key, int keylen, int algo_in, int > keytag_in) > - { > -=C2=A0=C2=A0=C2=A0unsigned char *p; > --=C2=A0=C2=A0int rdlen, j, name_labels; > -+=C2=A0=C2=A0int rdlen, j, name_labels, sig_expiration, sig_inception; > -=C2=A0=C2=A0=C2=A0struct crec *crecp =3D NULL; > -=C2=A0=C2=A0=C2=A0int algo, labels, orig_ttl, key_tag; > -=C2=A0=C2=A0=C2=A0u16 *rr_desc =3D rrfilter_desc(type); > -@@ -828,13 +829,16 @@ static int validate_rrset(time_t now, struct > dns_header *header, size_t plen, in > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0algo =3D *p++; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0labels =3D *p++; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETLONG(orig_ttl, p); > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 8; /* sig_expiration, sig_ince= ption already checked */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETLONG(sig_expiration, p); > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETLONG(sig_inception, p); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(key_tag, p); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!extract_name(header, plen, = &p, keyname, 1, 0)) > -=C2=A0 return STAT_BOGUS; > -=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(hash =3D hash_find(algo_digest_= name(algo))) || > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!check_date_range(sig_inception, = sig_expiration) || > -+ =C2=A0=C2=A0labels > name_labels || > -+ =C2=A0=C2=A0!(hash =3D hash_find(algo_digest_name(algo))) || > -=C2=A0 =C2=A0=C2=A0!hash_init(hash, &ctx, &digest)) > -=C2=A0 continue; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -@@ -1112,7 +1116,10 @@ int dnssec_validate_by_ds(time_t now, struct > dns_header *header, size_t plen, ch > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -=C2=A0 { > -=C2=A0 =C2=A0=C2=A0a.addr.keytag =3D keytag; > -- =C2=A0=C2=A0log_query(F_NOEXTRA | F_KEYTAG | > F_UPSTREAM, name, &a, "DNSKEY keytag %u"); > -+ =C2=A0=C2=A0if (verify_func(algo)) > -+ =C2=A0=C2=A0=C2=A0=C2=A0log_query(F_NOEXTRA | F_KEYTAG | > F_UPSTREAM, name, &a, "DNSKEY keytag %u"); > -+ =C2=A0=C2=A0else > -+ =C2=A0=C2=A0=C2=A0=C2=A0log_query(F_NOEXTRA | F_KEYTAG | > F_UPSTREAM, name, &a, "DNSKEY keytag %u (not supported)"); > -=C2=A0 =C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0recp1->addr.key.keylen =3D rdlen - 4; > -=C2=A0 =C2=A0=C2=A0recp1->addr.key.keydata =3D key; > -@@ -1235,7 +1242,11 @@ int dnssec_validate_ds(time_t now, struct > dns_header *header, size_t plen, char > -=C2=A0 =C2=A0=C2=A0else > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0a.addr.keytag =3D keytag; > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0log_query(F_NOEXTRA | F_KEYTAG | F_= UPSTREAM, > name, &a, "DS keytag %u"); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (hash_find(ds_digest_name(digest= )) && > verify_func(algo)) > -+ log_query(F_NOEXTRA | F_KEYTAG | > F_UPSTREAM, name, &a, "DS keytag %u"); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -+ log_query(F_NOEXTRA | F_KEYTAG | > F_UPSTREAM, name, &a, "DS keytag %u (not supported)"); > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.digest =3D dige= st; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.keydata =3D key; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0crecp->addr.ds.algo =3D algo; > -@@ -1660,7 +1671,7 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0*nons =3D 1; > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0/* Look though the NSEC3 records to find the first one w= ith=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0an algorithm we support (currently only alg= o =3D=3D 1). > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0an algorithm we support. > -=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Take the algo, iterations, and salt of= that record > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0as the ones we're going to use, and pr= une any=C2=A0 > -@@ -1674,7 +1685,7 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p +=3D 10; /* type, class, TTL, = rdlen */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0algo =3D *p++; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (algo =3D=3D 1) > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if ((hash =3D hash_find(nsec3_digest_= name(algo)))) > -=C2=A0 break; /* known algo */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > -@@ -1724,10 +1735,6 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0nsecs[i] =3D nsec3p; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 > --=C2=A0=C2=A0/* Algo is checked as 1 above */ > --=C2=A0=C2=A0if (!(hash =3D hash_find("sha1"))) > --=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -- > -=C2=A0=C2=A0=C2=A0if ((digest_len =3D hash_name(name, &digest, hash, salt,= salt_len, > iterations)) =3D=3D 0) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return 0; > -=C2=A0=C2=A0=C2=A0 > -@@ -1843,8 +1850,10 @@ static int prove_non_existence(struct > dns_header *header, size_t plen, char *key > -=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0if (type_found =3D=3D T_NSEC) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return prove_non_existence_nsec(header, plen= , nsecset, > nsecs_found, daemon->workspacename, keyname, name, qtype, nons); > --=C2=A0=C2=A0else > -+=C2=A0=C2=A0else if (type_found =3D=3D T_NSEC3) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return prove_non_existence_nsec3(header, ple= n, nsecset, > nsecs_found, daemon->workspacename, keyname, name, qtype, wildname, > nons); > -+=C2=A0=C2=A0else > -+=C2=A0=C2=A0=C2=A0=C2=A0return 0; > - } > -=C2=A0 > - /* Check signing status of name. > -@@ -1857,7 +1866,7 @@ static int prove_non_existence(struct > dns_header *header, size_t plen, char *key > - */ > - static int zone_status(char *name, int class, char *keyname, time_t > now) > - { > --=C2=A0=C2=A0int secure_ds, name_start =3D strlen(name); > -+=C2=A0=C2=A0int name_start =3D strlen(name); > -=C2=A0=C2=A0=C2=A0struct crec *crecp; > -=C2=A0=C2=A0=C2=A0char *p; > -=C2=A0=C2=A0=C2=A0 > -@@ -1867,51 +1876,40 @@ static int zone_status(char *name, int > class, char *keyname, time_t now) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (!(crecp =3D cache_find_by_na= me(NULL, keyname, now, F_DS))) > -=C2=A0 return STAT_NEED_DS; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* F_DNSSECOK misused in DS cac= he records to non-existance > of NS record. > -+ =C2=A0=C2=A0F_NEG && !F_DNSSECOK implies that we've proved there's no > DS record here, > -+ =C2=A0=C2=A0but that's because there's no NS record either, ie this > isn't the start > -+ =C2=A0=C2=A0of a zone. We only prove that the DNS tree below a node > is unsigned when > -+ =C2=A0=C2=A0we prove that we're at a zone cut AND there's no DS > record. */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->flags & F_NEG) > -+ { > -+ =C2=A0=C2=A0if (crecp->flags & F_DNSSECOK) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; /* proved no DS here */ > -+ } > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -=C2=A0 { > -- =C2=A0=C2=A0secure_ds =3D 0; > -- =C2=A0=C2=A0 > -+ =C2=A0=C2=A0int gotone =3D 0; > -+ > -+ =C2=A0=C2=A0/* If all the DS records have digest and/or sig algos we > don't support, > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0then the zone is insecure. Note that if an= algo > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0appears in the DS, then RRSIGs for that al= go MUST > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0exist for each RRset: 4035 para 2.2=C2=A0= =C2=A0So if we find > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0a DS here with digest and sig we can do, w= e're > entitled > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0to assume we can validate the zone and if = we can't > later, > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0because an RRSIG is missing we return BOGU= S. > -+ =C2=A0=C2=A0*/ > -=C2=A0 =C2=A0=C2=A0do=C2=A0 > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->uid =3D=3D (unsigned int)= class) > -- { > -- =C2=A0=C2=A0/* F_DNSSECOK misused in DS cache records to non- > existance of NS record. > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0F_NEG && !F_DNSSECOK implies that we've p= roved > there's no DS record here, > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0but that's because there's no NS record > either, ie this isn't the start > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0of a zone. We only prove that the DNS tree > below a node is unsigned when > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0we prove that we're at a zone cut AND the= re's > no DS record. > -- =C2=A0=C2=A0*/ =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (crecp->flags & F_NEG) > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->flags & F_DNSSECOK) > -- return STAT_INSECURE; /* proved no DS here > */ > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0else if (!hash_find(ds_digest_name(crecp- > >addr.ds.digest)) || !verify_func(crecp->addr.ds.algo)) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; /* algo we can't use - > insecure */ > -- =C2=A0=C2=A0else > -- =C2=A0=C2=A0=C2=A0=C2=A0secure_ds =3D 1; > -- } > -+ =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->uid =3D=3D (unsigned int)= class && > -+ =C2=A0=C2=A0hash_find(ds_digest_name(crecp->addr.ds.digest)) > && > -+ =C2=A0=C2=A0verify_func(crecp->addr.ds.algo)) > -+ gotone =3D 1; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0while ((crecp =3D cache_find_by_name(crecp, keyname, no= w, > F_DS))); > -- } > -- > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (secure_ds) > -- { > -- =C2=A0=C2=A0/* We've found only DS records that attest to the DNSKEY > RRset in the zone, so we believe > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0that RRset is good. Furthermore the DNSKEY= whose hash > is proved by the DS record is > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0one we can use. However the DNSKEY RRset m= ay contain > more than one key and > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0one of the other keys may use an algorithm= we don't > support. If that's=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0the case the zone is insecure for us. */ > -- =C2=A0=C2=A0 > -- =C2=A0=C2=A0if (!(crecp =3D cache_find_by_name(NULL, keyname, now, > F_DNSKEY))) > -- =C2=A0=C2=A0=C2=A0=C2=A0return STAT_NEED_KEY; > -=C2=A0 > -- =C2=A0=C2=A0do=C2=A0 > -- =C2=A0=C2=A0=C2=A0=C2=A0{ > -- =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->uid =3D=3D (unsigned int)= class && > !verify_func(crecp->addr.key.algo)) > -- return STAT_INSECURE; > -- =C2=A0=C2=A0=C2=A0=C2=A0} > -- =C2=A0=C2=A0while ((crecp =3D cache_find_by_name(crecp, keyname, now, > F_DNSKEY))); > -+ =C2=A0=C2=A0if (!gotone) > -+ =C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; > -=C2=A0 } > -=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (name_start =3D=3D 0) > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/027-Nasty_rare_and_obscure_off-by- > one_in_DNSSEC_hostname_cmp.patch b/src/patches/dnsmasq/027- > Nasty_rare_and_obscure_off-by-one_in_DNSSEC_hostname_cmp.patch > deleted file mode 100644 > index 031339e..0000000 > --- a/src/patches/dnsmasq/027-Nasty_rare_and_obscure_off-by- > one_in_DNSSEC_hostname_cmp.patch > +++ /dev/null > @@ -1,27 +0,0 @@ > -From 3e86d316c4bb406ed813aa5256615c8a95cac6d8 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Sun, 20 Dec 2015 20:50:05 +0000 > -Subject: [PATCH] Nasty, rare and obscure off-by-one in DNSSEC > hostname_cmp(). > - > ---- > - src/dnssec.c |=C2=A0=C2=A0=C2=A0=C2=A04 ++-- > - 1 file changed, 2 insertions(+), 2 deletions(-) > - > -diff --git a/src/dnssec.c b/src/dnssec.c > -index e09f304..29848e1 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -1394,8 +1394,8 @@ static int hostname_cmp(const char *a, const > char *b) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (sb =3D=3D b) > -=C2=A0 return 1; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ea =3D sa--; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0eb =3D sb--; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ea =3D --sa; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0eb =3D --sb; > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > - } > -=C2=A0 > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/028- > Minor_tweak_to_previous_commit.patch b/src/patches/dnsmasq/028- > Minor_tweak_to_previous_commit.patch > deleted file mode 100644 > index f3758fc..0000000 > --- a/src/patches/dnsmasq/028-Minor_tweak_to_previous_commit.patch > +++ /dev/null > @@ -1,39 +0,0 @@ > -From a86fdf437ecc29398f9715ceb5240442a17ac014 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Sun, 20 Dec 2015 21:19:20 +0000 > -Subject: [PATCH] Minor tweak to previous commit. > - > ---- > - src/dnssec.c |=C2=A0=C2=A0=C2=A0=C2=A06 ++---- > - 1 file changed, 2 insertions(+), 4 deletions(-) > - > -diff --git a/src/dnssec.c b/src/dnssec.c > -index 29848e1..9fa64b6 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -1889,8 +1889,6 @@ static int zone_status(char *name, int class, > char *keyname, time_t now) > -=C2=A0 } > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0else > -=C2=A0 { > -- =C2=A0=C2=A0int gotone =3D 0; > -- > -=C2=A0 =C2=A0=C2=A0/* If all the DS records have digest and/or sig algos we > don't support, > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0then the zone is insecure. Note that = if an algo > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0appears in the DS, then RRSIGs for th= at algo MUST > -@@ -1904,11 +1902,11 @@ static int zone_status(char *name, int > class, char *keyname, time_t now) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (crecp->uid =3D=3D (unsigned= int)class && > -=C2=A0 =C2=A0=C2=A0hash_find(ds_digest_name(crecp->addr.ds.digest)) > && > -=C2=A0 =C2=A0=C2=A0verify_func(crecp->addr.ds.algo)) > -- gotone =3D 1; > -+ break; > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0} > -=C2=A0 =C2=A0=C2=A0while ((crecp =3D cache_find_by_name(crecp, keyname, no= w, > F_DS))); > -=C2=A0 > -- =C2=A0=C2=A0if (!gotone) > -+ =C2=A0=C2=A0if (!crecp) > -=C2=A0 =C2=A0=C2=A0=C2=A0=C2=A0return STAT_INSECURE; > -=C2=A0 } > -=C2=A0 > ---=C2=A0 > -1.7.10.4 > - > diff --git a/src/patches/dnsmasq/029- > NSEC3_check_RFC5155_para_8_2.patch b/src/patches/dnsmasq/029- > NSEC3_check_RFC5155_para_8_2.patch > deleted file mode 100644 > index 33219d2..0000000 > --- a/src/patches/dnsmasq/029-NSEC3_check_RFC5155_para_8_2.patch > +++ /dev/null > @@ -1,39 +0,0 @@ > -From ce5732e84fc46d7f99c152f736cfb4ef5ec98a01 Mon Sep 17 00:00:00 > 2001 > -From: Simon Kelley <simon(a)thekelleys.org.uk> > -Date: Sun, 20 Dec 2015 21:39:19 +0000 > -Subject: [PATCH] NSEC3 check: RFC5155 para 8.2 > - > ---- > - src/dnssec.c |=C2=A0=C2=A0=C2=A0=C2=A08 ++++++-- > - 1 file changed, 6 insertions(+), 2 deletions(-) > - > -diff --git a/src/dnssec.c b/src/dnssec.c > -index 9fa64b6..486e422 100644 > ---- a/src/dnssec.c > -+++ b/src/dnssec.c > -@@ -1704,7 +1704,7 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0=C2=A0=C2=A0for (i =3D 0; i < nsec_count; i++) > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0unsigned char *nsec3p =3D nsecs[= i]; > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int this_iter; > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0int this_iter, flags; > -=C2=A0 > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0nsecs[i] =3D NULL; /* Speculativ= e, will be restored if OK. */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -@@ -1716,8 +1716,12 @@ static int prove_non_existence_nsec3(struct > dns_header *header, size_t plen, uns > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (*p++ !=3D algo) > -=C2=A0 continue; > -=C2=A0=C2=A0 > --=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0p++; /* flags */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0flags =3D *p++; /* flags */ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0/* 5155 8.2 */ > -+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (flags !=3D 0 && flags !=3D 1) > -+ continue; > -+ > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0GETSHORT(this_iter, p); > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (this_iter !=3D iterations) > -=C2=A0 continue; > ---=C2=A0 > -1.7.10.4 > - --===============2142730740329272608== Content-Type: application/pgp-signature Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="signature.asc" MIME-Version: 1.0 LS0tLS1CRUdJTiBQR1AgU0lHTkFUVVJFLS0tLS0KVmVyc2lvbjogR251UEcgdjIKCmlRSWNCQUFC Q2dBR0JRSlcwMVprQUFvSkVJQjU4UDl2a0FrSEhsUVAvajVZK05DM3cyNCtnWnhuMU50a1FpeUEK d3dCU1gzNXNJcmdzcU5YcjJxamx3eWQxbHgxYWdCaGZiTmU1T05CYm1Pd2tZUi91SVZWNkdNajBo UmVXcnl5MQpJem9uMysyTHAzM2ZiUlpOcXhhOW9wcHNFUE8veG9Zak8vU3pzZUs5Y1JZM1BUR2FG K2RUN3lKd3pXejZ4ck5QClZBWnUxazdRbmFhZTR4ZGlzckY4RnNIOVZwd3RYTkFITzMxRGN3MmUw RFV3OWN2SHJqUUhudTdTOTBOZnhnRDYKS1RhbjdFcDNMNnNLNG5lYWdkYTlTOThzOEJjUjJHbWp5 aTdmeDVLN3JVVXQvclBiUWx5OGhnMGpob2pLeVNhcwpuV2pDWFBLZDVjcTlNcWZWaE81Mmp5bzNM VThoSTJjeU5Pa1BMYXViOE9FQllCTXRrZkFkTHZJUFZ2RVJERE5ICkpZM1JzY3o4V2dNd0paZEVw d0ZWUHV3QjBmZWlFdXJYQ3ArWXNxNXIyeW1iaTNmeTBMNGpLb2FmRzF4SFdnT0EKNU1JUTF3UWpD ZmJUdGxnT1NURVJKcXFjb2dSdEtoYURYREJkVVViMWkzN2VRU0lxWkxpaGZsWERUWWlxcmZRNQpF VGxpSW1lc2dQRm01d1pJWmpnM2YwOER0YWZ2VkJmdGJWd0dWOVlCRDFONGlEMTVwZnAzaSs2L3Jy YjVQVmFOCkFWS09OdlhmWDJHOTMxU2ZLZDN6ck1WK0cvVHBiaFV0MmJCMWwrWkttWjAzQXVSVGJB WmpaajFoVFNhSmowdVcKNldKU0cxOSs5WWI3NldzRHBQdWhDczdrZElnQlNjWitUcThsKzViVVk5 Q1lVYllvMTIyN2grOXkvczA2YzA4dgoyZHlMVFBGS1dqVkViRmdnWmVwWgo9b1hkagotLS0tLUVO RCBQR1AgU0lHTkFUVVJFLS0tLS0K --===============2142730740329272608==--