This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "IPFire 2.x development tree".
The branch, next has been updated via e5ca5063049bda41483221e7df1e8544ea128aff (commit) via c651121f4dab2fbc091c3c9c8a77f0793e034dab (commit) via 274ebe1d9d3390b94afe42e5b96273e171c3c6d3 (commit) via 8d289021d3c20f82b08d87fb9ee7296cedd705fe (commit) via 6644c1c7f24262b2040d05cbb877ba36658d70e7 (commit) via 80b0f82fef5a75b8ebc547f8ba40c8bf5b268b73 (commit) via 165b25b2dc8fce3dbba64711eab1eed709ffb0a5 (commit) via 09e3b0fa356c087b27ca7197024bf0210455a73c (commit) via ef8b6053f332bd0c5dc7c5ad2d756b735c1383f8 (commit) via 3ec88e97cdcafe2818fec9826e46dc08a35ca9c3 (commit) via 5bbf213dc72faabb59f7ed14b79f76d9bde7ca1a (commit) via a403ce7cca3d1d9a0abb0704de1e35de0d7de2e6 (commit) from d7dac20c17964758e53d13558ceb2f1535954b67 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit e5ca5063049bda41483221e7df1e8544ea128aff Author: Michael Tremer michael.tremer@ipfire.org Date: Wed Mar 4 23:59:43 2015 +0100
ntfs-3g: Ship all user-space tools with the package
commit c651121f4dab2fbc091c3c9c8a77f0793e034dab Merge: 274ebe1 ef8b605 Author: Michael Tremer michael.tremer@ipfire.org Date: Wed Mar 4 23:58:58 2015 +0100
Merge remote-tracking branch 'mfischer/ntfs-3g' into next
commit 274ebe1d9d3390b94afe42e5b96273e171c3c6d3 Merge: 8d28902 80b0f82 Author: Michael Tremer michael.tremer@ipfire.org Date: Wed Mar 4 23:58:47 2015 +0100
Merge remote-tracking branch 'origin/master' into next
Conflicts: config/rootfiles/packages/clamav lfs/clamav
commit 8d289021d3c20f82b08d87fb9ee7296cedd705fe Author: Michael Tremer michael.tremer@ipfire.org Date: Wed Mar 4 23:54:10 2015 +0100
strongswan: Update solution for strongswan bug #816
commit 6644c1c7f24262b2040d05cbb877ba36658d70e7 Author: Michael Tremer michael.tremer@ipfire.org Date: Wed Mar 4 23:27:27 2015 +0100
dnsmasq: Import latest git version of dnsmasq
commit ef8b6053f332bd0c5dc7c5ad2d756b735c1383f8 Author: Matthias Fischer fischerm@ipfire.org Date: Mon Mar 2 21:12:20 2015 +0100
ntfs-3g: Update to 2014.2.15 fuse: Update to 2.9.3
-----------------------------------------------------------------------
Summary of changes: config/rootfiles/common/fuse | 6 +- config/rootfiles/common/ntfs-3g | 36 +- config/rootfiles/packages/clamav | 7 +- html/cgi-bin/vpnmain.cgi | 8 + lfs/clamav | 8 +- lfs/dnsmasq | 61 +- lfs/fuse | 6 +- lfs/ntfs-3g | 8 +- lfs/samba | 8 +- lfs/strongswan | 5 +- make.sh | 2 +- ...newline-at-the-end-of-example-config-file.patch | 23 + ...artup-when-an-empty-suffix-is-supplied-to.patch | 86 +++ .../0003-Debian-build-fixes-for-kFreeBSD.patch | 36 + ...04-Set-conntrack-mark-before-connect-call.patch | 68 ++ .../dnsmasq/0005-Fix-typo-in-new-Dbus-code.patch | 26 + .../dnsmasq/0006-Fit-example-conf-file-typo.patch | 22 + ...-compliance-when-unable-to-supply-address.patch | 107 +++ .../0008-Fix-conntrack-with-bind-interfaces.patch | 39 + ...9-Use-inotify-instead-of-polling-on-Linux.patch | 257 +++++++ ...Teach-the-new-inotify-code-about-symlinks.patch | 73 ++ ...ve-floor-on-EDNS0-packet-size-with-DNSSEC.patch | 46 ++ .../dnsmasq/0012-CHANGELOG-re.-inotify.patch | 27 + ...ix-breakage-of-domain-domain-subnet-local.patch | 70 ++ ...ve-redundant-IN6_IS_ADDR_ULA-a-macro-defn.patch | 27 + ...Pv6-privacy-addresses-from-interface-name.patch | 148 ++++ ...-width-in-cache-dump-to-avoid-truncating-.patch | 35 + ...n-DNSSEC-code-when-attempting-to-verify-l.patch | 100 +++ ...g-work-for-CNAMEs-pointing-to-A-AAAA-reco.patch | 99 +++ ...x-problems-validating-NSEC3-and-wildcards.patch | 365 ++++++++++ .../dnsmasq/0020-Initialise-return-value.patch | 32 + .../dnsmasq/0021-Add-ignore-address-option.patch | 192 +++++ .../dnsmasq/0022-Bad-packet-protection.patch | 25 + ...-build-failure-in-new-inotify-code-on-BSD.patch | 29 + ...t-makefile-dependencies-on-COPTS-variable.patch | 68 ++ ...0025-Fix-race-condition-issue-in-makefile.patch | 30 + ...op-down-search-for-limit-of-secure-delega.patch | 792 +++++++++++++++++++++ ...ries-extra-option-for-more-complete-loggi.patch | 346 +++++++++ .../dnsmasq/0028-Add-min-cache-ttl-option.patch | 144 ++++ ...ort-of-requestor-when-doing-extra-logging.patch | 31 + ...r-from-cache-RRsets-from-wildcards-as-we-.patch | 45 ++ .../0031-Logs-for-DS-records-consistent.patch | 25 + ...ultiple-interfaces-with-the-same-LL-addre.patch | 57 ++ ...n-t-treat-SERVFAIL-as-a-recoverable-error.patch | 25 + .../0034-Add-dhcp-hostsdir-config-option.patch | 419 +++++++++++ .../dnsmasq/0035-Update-German-translation.patch | 327 +++++++++ ...-to-DHCPv6-SOLICIT-messages-when-not-conf.patch | 53 ++ ...fy-to-be-disabled-at-compile-time-on-Linu.patch | 213 ++++++ ...ify-code-to-dhcp-hostsdir-dhcp-optsdir-an.patch | 562 +++++++++++++++ .../0039-Update-copyrights-for-dawn-of-2015.patch | 428 +++++++++++ .../0040-inotify-documentation-updates.patch | 53 ++ .../0041-Fix-broken-ECDSA-DNSSEC-signatures.patch | 39 + src/patches/dnsmasq/0042-BSD-make-support.patch | 29 + .../0043-Fix-build-failure-on-openBSD.patch | 25 + src/patches/dnsmasq/0044-Manpage-typo-fix.patch | 25 + ...configs-after-reading-extra-hostfiles-wit.patch | 38 + .../0046-Extra-logging-for-inotify-code.patch | 68 ++ src/patches/dnsmasq/0047-man-page-typo.patch | 24 + ...sion-script-which-returned-wrong-tag-in-s.patch | 26 + src/patches/dnsmasq/0049-Typos.patch | 26 + ...ynamic-hosts-files-work-when-no-hosts-set.patch | 45 ++ ...-trivial-memory-leaks-to-quieten-valgrind.patch | 55 ++ ...ninitialized-value-used-in-get_client_mac.patch | 27 + ...-Log-parsing-utils-in-contrib-reverse-dns.patch | 110 +++ ...-Add-dnssec-timestamp-option-and-facility.patch | 252 +++++++ ...mmit-to-not-crash-if-uid-changing-not-con.patch | 63 ++ .../strongswan-5.2.2-issue-816-650a3ad.patch | 35 + .../strongswan-5.2.2-issue-816-dd0ebb.patch | 42 ++ .../strongswan-5.2.2-issue-816-eb25190.patch | 31 + src/patches/strongswan-5.2.2-issue-816.patch | 13 - 70 files changed, 6635 insertions(+), 43 deletions(-) create mode 100644 src/patches/dnsmasq/0001-Add-newline-at-the-end-of-example-config-file.patch create mode 100644 src/patches/dnsmasq/0002-crash-at-startup-when-an-empty-suffix-is-supplied-to.patch create mode 100644 src/patches/dnsmasq/0003-Debian-build-fixes-for-kFreeBSD.patch create mode 100644 src/patches/dnsmasq/0004-Set-conntrack-mark-before-connect-call.patch create mode 100644 src/patches/dnsmasq/0005-Fix-typo-in-new-Dbus-code.patch create mode 100644 src/patches/dnsmasq/0006-Fit-example-conf-file-typo.patch create mode 100644 src/patches/dnsmasq/0007-Improve-RFC-compliance-when-unable-to-supply-address.patch create mode 100644 src/patches/dnsmasq/0008-Fix-conntrack-with-bind-interfaces.patch create mode 100644 src/patches/dnsmasq/0009-Use-inotify-instead-of-polling-on-Linux.patch create mode 100644 src/patches/dnsmasq/0010-Teach-the-new-inotify-code-about-symlinks.patch create mode 100644 src/patches/dnsmasq/0011-Remove-floor-on-EDNS0-packet-size-with-DNSSEC.patch create mode 100644 src/patches/dnsmasq/0012-CHANGELOG-re.-inotify.patch create mode 100644 src/patches/dnsmasq/0013-Fix-breakage-of-domain-domain-subnet-local.patch create mode 100644 src/patches/dnsmasq/0014-Remove-redundant-IN6_IS_ADDR_ULA-a-macro-defn.patch create mode 100644 src/patches/dnsmasq/0015-Eliminate-IPv6-privacy-addresses-from-interface-name.patch create mode 100644 src/patches/dnsmasq/0016-Tweak-field-width-in-cache-dump-to-avoid-truncating-.patch create mode 100644 src/patches/dnsmasq/0017-Fix-crash-in-DNSSEC-code-when-attempting-to-verify-l.patch create mode 100644 src/patches/dnsmasq/0018-Make-caching-work-for-CNAMEs-pointing-to-A-AAAA-reco.patch create mode 100644 src/patches/dnsmasq/0019-Fix-problems-validating-NSEC3-and-wildcards.patch create mode 100644 src/patches/dnsmasq/0020-Initialise-return-value.patch create mode 100644 src/patches/dnsmasq/0021-Add-ignore-address-option.patch create mode 100644 src/patches/dnsmasq/0022-Bad-packet-protection.patch create mode 100644 src/patches/dnsmasq/0023-Fix-build-failure-in-new-inotify-code-on-BSD.patch create mode 100644 src/patches/dnsmasq/0024-Implement-makefile-dependencies-on-COPTS-variable.patch create mode 100644 src/patches/dnsmasq/0025-Fix-race-condition-issue-in-makefile.patch create mode 100644 src/patches/dnsmasq/0026-DNSSEC-do-top-down-search-for-limit-of-secure-delega.patch create mode 100644 src/patches/dnsmasq/0027-Add-log-queries-extra-option-for-more-complete-loggi.patch create mode 100644 src/patches/dnsmasq/0028-Add-min-cache-ttl-option.patch create mode 100644 src/patches/dnsmasq/0029-Log-port-of-requestor-when-doing-extra-logging.patch create mode 100644 src/patches/dnsmasq/0030-Don-t-answer-from-cache-RRsets-from-wildcards-as-we-.patch create mode 100644 src/patches/dnsmasq/0031-Logs-for-DS-records-consistent.patch create mode 100644 src/patches/dnsmasq/0032-Cope-with-multiple-interfaces-with-the-same-LL-addre.patch create mode 100644 src/patches/dnsmasq/0033-Don-t-treat-SERVFAIL-as-a-recoverable-error.patch create mode 100644 src/patches/dnsmasq/0034-Add-dhcp-hostsdir-config-option.patch create mode 100644 src/patches/dnsmasq/0035-Update-German-translation.patch create mode 100644 src/patches/dnsmasq/0036-Don-t-reply-to-DHCPv6-SOLICIT-messages-when-not-conf.patch create mode 100644 src/patches/dnsmasq/0037-Allow-inotify-to-be-disabled-at-compile-time-on-Linu.patch create mode 100644 src/patches/dnsmasq/0038-Expand-inotify-code-to-dhcp-hostsdir-dhcp-optsdir-an.patch create mode 100644 src/patches/dnsmasq/0039-Update-copyrights-for-dawn-of-2015.patch create mode 100644 src/patches/dnsmasq/0040-inotify-documentation-updates.patch create mode 100644 src/patches/dnsmasq/0041-Fix-broken-ECDSA-DNSSEC-signatures.patch create mode 100644 src/patches/dnsmasq/0042-BSD-make-support.patch create mode 100644 src/patches/dnsmasq/0043-Fix-build-failure-on-openBSD.patch create mode 100644 src/patches/dnsmasq/0044-Manpage-typo-fix.patch create mode 100644 src/patches/dnsmasq/0045-Fixup-dhcp-configs-after-reading-extra-hostfiles-wit.patch create mode 100644 src/patches/dnsmasq/0046-Extra-logging-for-inotify-code.patch create mode 100644 src/patches/dnsmasq/0047-man-page-typo.patch create mode 100644 src/patches/dnsmasq/0048-Fix-get-version-script-which-returned-wrong-tag-in-s.patch create mode 100644 src/patches/dnsmasq/0049-Typos.patch create mode 100644 src/patches/dnsmasq/0050-Make-dynamic-hosts-files-work-when-no-hosts-set.patch create mode 100644 src/patches/dnsmasq/0051-Fix-trivial-memory-leaks-to-quieten-valgrind.patch create mode 100644 src/patches/dnsmasq/0052-Fix-uninitialized-value-used-in-get_client_mac.patch create mode 100644 src/patches/dnsmasq/0053-Log-parsing-utils-in-contrib-reverse-dns.patch create mode 100644 src/patches/dnsmasq/0054-Add-dnssec-timestamp-option-and-facility.patch create mode 100644 src/patches/dnsmasq/0055-Fix-last-commit-to-not-crash-if-uid-changing-not-con.patch create mode 100644 src/patches/strongswan-5.2.2-issue-816-650a3ad.patch create mode 100644 src/patches/strongswan-5.2.2-issue-816-dd0ebb.patch create mode 100644 src/patches/strongswan-5.2.2-issue-816-eb25190.patch delete mode 100644 src/patches/strongswan-5.2.2-issue-816.patch
Difference in files: diff --git a/config/rootfiles/common/fuse b/config/rootfiles/common/fuse index 3b7ad59..1ab1d48 100644 --- a/config/rootfiles/common/fuse +++ b/config/rootfiles/common/fuse @@ -1,5 +1,6 @@ #etc/init.d #etc/init.d/fuse +#etc/rc.d/init.d/fuse etc/udev/rules.d/99-fuse.rules sbin/mount.fuse usr/bin/fusermount @@ -19,10 +20,13 @@ usr/bin/ulockmgr_server #usr/lib/libfuse.la usr/lib/libfuse.so usr/lib/libfuse.so.2 -usr/lib/libfuse.so.2.8.3 +usr/lib/libfuse.so.2.9.3 #usr/lib/libulockmgr.a #usr/lib/libulockmgr.la usr/lib/libulockmgr.so usr/lib/libulockmgr.so.1 usr/lib/libulockmgr.so.1.0.1 #usr/lib/pkgconfig/fuse.pc +#usr/share/man/man1/fusermount.1 +#usr/share/man/man1/ulockmgr_server.1 +#usr/share/man/man8/mount.fuse.8 diff --git a/config/rootfiles/common/ntfs-3g b/config/rootfiles/common/ntfs-3g index 186e12b..44f13c3 100644 --- a/config/rootfiles/common/ntfs-3g +++ b/config/rootfiles/common/ntfs-3g @@ -1,13 +1,20 @@ bin/lowntfs-3g bin/ntfs-3g -lib/libntfs-3g.so -lib/libntfs-3g.so.80 -lib/libntfs-3g.so.80.0.0 +#lib/libntfs-3g.so +lib/libntfs-3g.so.85 +lib/libntfs-3g.so.85.0.0 +sbin/mkfs.ntfs sbin/mount.lowntfs-3g sbin/mount.ntfs-3g usr/bin/ntfs-3g.probe usr/bin/ntfs-3g.secaudit usr/bin/ntfs-3g.usermap +usr/bin/ntfscat +usr/bin/ntfscluster +usr/bin/ntfscmp +usr/bin/ntfsfix +usr/bin/ntfsinfo +usr/bin/ntfsls #usr/include/ntfs-3g #usr/include/ntfs-3g/acls.h #usr/include/ntfs-3g/attrib.h @@ -36,6 +43,7 @@ usr/bin/ntfs-3g.usermap #usr/include/ntfs-3g/ntfstime.h #usr/include/ntfs-3g/object_id.h #usr/include/ntfs-3g/param.h +#usr/include/ntfs-3g/realpath.h #usr/include/ntfs-3g/reparse.h #usr/include/ntfs-3g/runlist.h #usr/include/ntfs-3g/security.h @@ -46,13 +54,33 @@ usr/bin/ntfs-3g.usermap #usr/include/ntfs-3g/xattrs.h #usr/lib/libntfs-3g.a #usr/lib/libntfs-3g.la -usr/lib/libntfs-3g.so +#usr/lib/libntfs-3g.so usr/lib/pkgconfig/libntfs-3g.pc +usr/sbin/mkntfs +usr/sbin/ntfsclone +usr/sbin/ntfscp +usr/sbin/ntfslabel +usr/sbin/ntfsresize +usr/sbin/ntfsundelete #usr/share/doc/ntfs-3g #usr/share/doc/ntfs-3g/README +#usr/share/man/man8/mkfs.ntfs.8 +#usr/share/man/man8/mkntfs.8 #usr/share/man/man8/mount.lowntfs-3g.8 #usr/share/man/man8/mount.ntfs-3g.8 #usr/share/man/man8/ntfs-3g.8 #usr/share/man/man8/ntfs-3g.probe.8 #usr/share/man/man8/ntfs-3g.secaudit.8 #usr/share/man/man8/ntfs-3g.usermap.8 +#usr/share/man/man8/ntfscat.8 +#usr/share/man/man8/ntfsclone.8 +#usr/share/man/man8/ntfscluster.8 +#usr/share/man/man8/ntfscmp.8 +#usr/share/man/man8/ntfscp.8 +#usr/share/man/man8/ntfsfix.8 +#usr/share/man/man8/ntfsinfo.8 +#usr/share/man/man8/ntfslabel.8 +#usr/share/man/man8/ntfsls.8 +#usr/share/man/man8/ntfsprogs.8 +#usr/share/man/man8/ntfsresize.8 +#usr/share/man/man8/ntfsundelete.8 diff --git a/config/rootfiles/packages/clamav b/config/rootfiles/packages/clamav index 60a3a9f..7353313 100644 --- a/config/rootfiles/packages/clamav +++ b/config/rootfiles/packages/clamav @@ -11,15 +11,15 @@ usr/bin/sigtool #usr/lib/libclamav.la usr/lib/libclamav.so usr/lib/libclamav.so.6 -usr/lib/libclamav.so.6.1.22 +usr/lib/libclamav.so.6.1.25 #usr/lib/libclamunrar.la usr/lib/libclamunrar.so usr/lib/libclamunrar.so.6 -usr/lib/libclamunrar.so.6.1.22 +usr/lib/libclamunrar.so.6.1.25 #usr/lib/libclamunrar_iface.la usr/lib/libclamunrar_iface.so usr/lib/libclamunrar_iface.so.6 -usr/lib/libclamunrar_iface.so.6.1.22 +usr/lib/libclamunrar_iface.so.6.1.25 #usr/lib/pkgconfig/libclamav.pc usr/sbin/clamd usr/share/clamav @@ -41,6 +41,5 @@ var/ipfire/clamav/clamd.conf var/ipfire/clamav/clamd.conf.sample var/ipfire/clamav/freshclam.conf var/ipfire/clamav/freshclam.conf.sample -#var/run/clamav etc/rc.d/init.d/clamav usr/local/bin/clamavctrl diff --git a/html/cgi-bin/vpnmain.cgi b/html/cgi-bin/vpnmain.cgi index 380ae26..a6d7056 100644 --- a/html/cgi-bin/vpnmain.cgi +++ b/html/cgi-bin/vpnmain.cgi @@ -437,6 +437,14 @@ sub writeipsecfiles { } print CONF "\n"; }#foreach key + + # Add post user includes to config file + # After the GUI-connections allows to patch connections. + if (-e "/etc/ipsec.user-post.conf") { + print CONF "include /etc/ipsec.user-post.conf\n"; + print CONF "\n"; + } + print SECRETS $last_secrets if ($last_secrets); close(CONF); close(SECRETS); diff --git a/lfs/clamav b/lfs/clamav index 2c996b2..43b5060 100644 --- a/lfs/clamav +++ b/lfs/clamav @@ -1,7 +1,7 @@ ############################################################################### # # # IPFire.org - A linux based firewall # -# Copyright (C) 2007-2014 IPFire Team info@ipfire.org # +# Copyright (C) 2007-2015 IPFire Team info@ipfire.org # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # @@ -24,7 +24,7 @@
include Config
-VER = 0.98.5 +VER = 0.98.6
THISAPP = clamav-$(VER) DL_FILE = $(THISAPP).tar.gz @@ -32,7 +32,7 @@ DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP) TARGET = $(DIR_INFO)/$(THISAPP) PROG = clamav -PAK_VER = 27 +PAK_VER = 28
DEPS = ""
@@ -48,7 +48,7 @@ objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
-$(DL_FILE)_MD5 = abb5c7efaff3394c0a49ff970841a2ac +$(DL_FILE)_MD5 = 7f4f7e82a09e42c4ebf153d6d452d9d8
install : $(TARGET)
diff --git a/lfs/dnsmasq b/lfs/dnsmasq index d4eb9d4..c256f75 100644 --- a/lfs/dnsmasq +++ b/lfs/dnsmasq @@ -24,10 +24,10 @@
include Config
-VER = 1062667 +VER = 2.72
THISAPP = dnsmasq-$(VER) -DL_FILE = $(THISAPP)-20150201.tar.gz +DL_FILE = $(THISAPP).tar.xz DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP) TARGET = $(DIR_INFO)/$(THISAPP) @@ -43,7 +43,7 @@ objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
-$(DL_FILE)_MD5 = ee58d033a892faa69b099ed598f500c2 +$(DL_FILE)_MD5 = 0256e0a71e27c8d8a5c89a0d18f3cfe2
install : $(TARGET)
@@ -73,6 +73,61 @@ $(subst %,%_MD5,$(objects)) : $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) @$(PREBUILD) @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE) + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0001-Add-newline-at-the-end-of-example-config-file.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0002-crash-at-startup-when-an-empty-suffix-is-supplied-to.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0003-Debian-build-fixes-for-kFreeBSD.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0004-Set-conntrack-mark-before-connect-call.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0005-Fix-typo-in-new-Dbus-code.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0006-Fit-example-conf-file-typo.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0007-Improve-RFC-compliance-when-unable-to-supply-address.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0008-Fix-conntrack-with-bind-interfaces.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0009-Use-inotify-instead-of-polling-on-Linux.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0010-Teach-the-new-inotify-code-about-symlinks.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0011-Remove-floor-on-EDNS0-packet-size-with-DNSSEC.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0012-CHANGELOG-re.-inotify.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0013-Fix-breakage-of-domain-domain-subnet-local.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0014-Remove-redundant-IN6_IS_ADDR_ULA-a-macro-defn.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0015-Eliminate-IPv6-privacy-addresses-from-interface-name.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0016-Tweak-field-width-in-cache-dump-to-avoid-truncating-.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0017-Fix-crash-in-DNSSEC-code-when-attempting-to-verify-l.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0018-Make-caching-work-for-CNAMEs-pointing-to-A-AAAA-reco.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0019-Fix-problems-validating-NSEC3-and-wildcards.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0020-Initialise-return-value.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0021-Add-ignore-address-option.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0022-Bad-packet-protection.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0023-Fix-build-failure-in-new-inotify-code-on-BSD.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0024-Implement-makefile-dependencies-on-COPTS-variable.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0025-Fix-race-condition-issue-in-makefile.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0026-DNSSEC-do-top-down-search-for-limit-of-secure-delega.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0027-Add-log-queries-extra-option-for-more-complete-loggi.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0028-Add-min-cache-ttl-option.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0029-Log-port-of-requestor-when-doing-extra-logging.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0030-Don-t-answer-from-cache-RRsets-from-wildcards-as-we-.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0031-Logs-for-DS-records-consistent.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0032-Cope-with-multiple-interfaces-with-the-same-LL-addre.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0033-Don-t-treat-SERVFAIL-as-a-recoverable-error.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0034-Add-dhcp-hostsdir-config-option.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0035-Update-German-translation.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0036-Don-t-reply-to-DHCPv6-SOLICIT-messages-when-not-conf.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0037-Allow-inotify-to-be-disabled-at-compile-time-on-Linu.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0038-Expand-inotify-code-to-dhcp-hostsdir-dhcp-optsdir-an.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0039-Update-copyrights-for-dawn-of-2015.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0040-inotify-documentation-updates.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0041-Fix-broken-ECDSA-DNSSEC-signatures.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0042-BSD-make-support.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0043-Fix-build-failure-on-openBSD.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0044-Manpage-typo-fix.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0045-Fixup-dhcp-configs-after-reading-extra-hostfiles-wit.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0046-Extra-logging-for-inotify-code.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0047-man-page-typo.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0048-Fix-get-version-script-which-returned-wrong-tag-in-s.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0049-Typos.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0050-Make-dynamic-hosts-files-work-when-no-hosts-set.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0051-Fix-trivial-memory-leaks-to-quieten-valgrind.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0052-Fix-uninitialized-value-used-in-get_client_mac.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0053-Log-parsing-utils-in-contrib-reverse-dns.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0054-Add-dnssec-timestamp-option-and-facility.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/0055-Fix-last-commit-to-not-crash-if-uid-changing-not-con.patch cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease-file.patch cd $(DIR_APP) && sed -i src/config.h \ -e 's|/* #define HAVE_IDN */|#define HAVE_IDN|g' \ diff --git a/lfs/fuse b/lfs/fuse index 69e8f01..a875fb3 100644 --- a/lfs/fuse +++ b/lfs/fuse @@ -1,7 +1,7 @@ ############################################################################### # # # IPFire.org - A linux based firewall # -# Copyright (C) 2007 Michael Tremer & Christian Schmidt # +# Copyright (C) 2015 Michael Tremer & Christian Schmidt # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # @@ -24,7 +24,7 @@
include Config
-VER = 2.8.3 +VER = 2.9.3
THISAPP = fuse-$(VER) DL_FILE = $(THISAPP).tar.gz @@ -40,7 +40,7 @@ objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
-$(DL_FILE)_MD5 = 517c8384f915e40647bda9f71579fd97 +$(DL_FILE)_MD5 = 33cae22ca50311446400daf8a6255c6a
install : $(TARGET)
diff --git a/lfs/ntfs-3g b/lfs/ntfs-3g index 4d65137..0ed890f 100644 --- a/lfs/ntfs-3g +++ b/lfs/ntfs-3g @@ -1,7 +1,7 @@ ############################################################################### # # # IPFire.org - A linux based firewall # -# Copyright (C) 2009 Michael Tremer & Christian Schmidt # +# Copyright (C) 2015 Michael Tremer & Christian Schmidt # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # @@ -24,9 +24,9 @@
include Config
-VER = 2011.1.15 +VER = 2014.2.15
-THISAPP = ntfs-3g-$(VER) +THISAPP = ntfs-3g_ntfsprogs-$(VER) DL_FILE = $(THISAPP).tgz DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP) @@ -40,7 +40,7 @@ objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
-$(DL_FILE)_MD5 = 15a5cf5752012269fa168c24191f00e2 +$(DL_FILE)_MD5 = f11d563816249d730a00498983485f3a
install : $(TARGET)
diff --git a/lfs/samba b/lfs/samba index 213f8eb..f0dcf83 100644 --- a/lfs/samba +++ b/lfs/samba @@ -1,7 +1,7 @@ ############################################################################### # # # IPFire.org - A linux based firewall # -# Copyright (C) 2007-2014 IPFire Team info@ipfire.org # +# Copyright (C) 2007-2015 IPFire Team info@ipfire.org # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # @@ -24,7 +24,7 @@
include Config
-VER = 3.6.24 +VER = 3.6.25
THISAPP = samba-$(VER) DL_FILE = $(THISAPP).tar.gz @@ -32,7 +32,7 @@ DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP) TARGET = $(DIR_INFO)/$(THISAPP) PROG = samba -PAK_VER = 59 +PAK_VER = 60
DEPS = "cups krb5"
@@ -44,7 +44,7 @@ objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
-$(DL_FILE)_MD5 = d98425c0c2b73e08f048d31ffc727fb0 +$(DL_FILE)_MD5 = 76da2fa64edd94a0188531e7ecb27c4e
install : $(TARGET)
diff --git a/lfs/strongswan b/lfs/strongswan index ff97ab8..43995b5 100644 --- a/lfs/strongswan +++ b/lfs/strongswan @@ -79,8 +79,9 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) @$(PREBUILD) @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE) cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/strongswan-5.0.2_ipfire.patch - cd $(DIR_APP) && patch -Np1 --ignore-whitespace \ - -i $(DIR_SRC)/src/patches/strongswan-5.2.2-issue-816.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/strongswan-5.2.2-issue-816-eb25190.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/strongswan-5.2.2-issue-816-650a3ad.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/strongswan-5.2.2-issue-816-dd0ebb.patch cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/strongswan-5.2.2-issue-819-cd2c30a.patch
cd $(DIR_APP) && [ -x "configure" ] || ./autogen.sh diff --git a/make.sh b/make.sh index 386403e..9309dda 100755 --- a/make.sh +++ b/make.sh @@ -649,7 +649,7 @@ buildipfire() { ipfiremake libevent2 ipfiremake portmap ipfiremake nfs - ipfiremake nmap + #ipfiremake nmap ipfiremake ncftp ipfiremake etherwake ipfiremake bwm-ng diff --git a/src/patches/dnsmasq/0001-Add-newline-at-the-end-of-example-config-file.patch b/src/patches/dnsmasq/0001-Add-newline-at-the-end-of-example-config-file.patch new file mode 100644 index 0000000..adcb44f --- /dev/null +++ b/src/patches/dnsmasq/0001-Add-newline-at-the-end-of-example-config-file.patch @@ -0,0 +1,23 @@ +From f2658275b25ebfe691cdcb9fede85a3088cca168 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Thu, 25 Sep 2014 21:51:25 +0100 +Subject: [PATCH 01/55] Add newline at the end of example config file. + +--- + dnsmasq.conf.example | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dnsmasq.conf.example b/dnsmasq.conf.example +index 83924fc4a9b4..6b00bd34fbb5 100644 +--- a/dnsmasq.conf.example ++++ b/dnsmasq.conf.example +@@ -645,4 +645,4 @@ + #conf-dir=/etc/dnsmasq.d,.bak + + # Include all files in a directory which end in .conf +-#conf-dir=/etc/dnsmasq.d/*.conf +\ No newline at end of file ++#conf-dir=/etc/dnsmasq.d/*.conf +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0002-crash-at-startup-when-an-empty-suffix-is-supplied-to.patch b/src/patches/dnsmasq/0002-crash-at-startup-when-an-empty-suffix-is-supplied-to.patch new file mode 100644 index 0000000..b84440b --- /dev/null +++ b/src/patches/dnsmasq/0002-crash-at-startup-when-an-empty-suffix-is-supplied-to.patch @@ -0,0 +1,86 @@ +From 00cd9d551998307225312fd21f761cfa8868bd2c Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Thu, 2 Oct 2014 21:44:21 +0100 +Subject: [PATCH 02/55] crash at startup when an empty suffix is supplied to + --conf-dir + +--- + CHANGELOG | 6 ++++++ + src/option.c | 38 +++++++++++++++++++++++--------------- + 2 files changed, 29 insertions(+), 15 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 768e2aaca42a..13ab41c05fc3 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -1,3 +1,9 @@ ++version 2.73 ++ Fix crash at startup when an empty suffix is supplied to ++ --conf-dir, also trivial memory leak. Thanks to ++ Tomas Hozza for spotting this. ++ ++ + version 2.72 + Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. + +diff --git a/src/option.c b/src/option.c +index 45d8875fb7f9..b08e98e16f84 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -1474,22 +1474,25 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + for (arg = comma; arg; arg = comma) + { + comma = split(arg); +- li = opt_malloc(sizeof(struct list)); +- if (*arg == '*') ++ if (strlen(arg) != 0) + { +- li->next = match_suffix; +- match_suffix = li; +- /* Have to copy: buffer is overwritten */ +- li->suffix = opt_string_alloc(arg+1); +- } +- else +- { +- li->next = ignore_suffix; +- ignore_suffix = li; +- /* Have to copy: buffer is overwritten */ +- li->suffix = opt_string_alloc(arg); ++ li = opt_malloc(sizeof(struct list)); ++ if (*arg == '*') ++ { ++ li->next = match_suffix; ++ match_suffix = li; ++ /* Have to copy: buffer is overwritten */ ++ li->suffix = opt_string_alloc(arg+1); ++ } ++ else ++ { ++ li->next = ignore_suffix; ++ ignore_suffix = li; ++ /* Have to copy: buffer is overwritten */ ++ li->suffix = opt_string_alloc(arg); ++ } + } +- }; ++ } + + if (!(dir_stream = opendir(directory))) + die(_("cannot access directory %s: %s"), directory, EC_FILE); +@@ -1555,7 +1558,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + free(ignore_suffix->suffix); + free(ignore_suffix); + } +- ++ for(; match_suffix; match_suffix = li) ++ { ++ li = match_suffix->next; ++ free(match_suffix->suffix); ++ free(match_suffix); ++ } + break; + } + +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0003-Debian-build-fixes-for-kFreeBSD.patch b/src/patches/dnsmasq/0003-Debian-build-fixes-for-kFreeBSD.patch new file mode 100644 index 0000000..fe73acd --- /dev/null +++ b/src/patches/dnsmasq/0003-Debian-build-fixes-for-kFreeBSD.patch @@ -0,0 +1,36 @@ +From 6ac3bc0452a74e16e3d620a0757b0f8caab182ec Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Fri, 3 Oct 2014 08:48:11 +0100 +Subject: [PATCH 03/55] Debian build fixes for kFreeBSD + +--- + src/tables.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/tables.c b/src/tables.c +index 834f11944cd0..dcdef794c4d2 100644 +--- a/src/tables.c ++++ b/src/tables.c +@@ -20,6 +20,10 @@ + + #if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK) + ++#ifndef __FreeBSD__ ++#include <bsd/string.h> ++#endif ++ + #include <sys/types.h> + #include <sys/ioctl.h> + +@@ -136,7 +140,7 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr, + return -1; + } + +- if (rc = pfr_add_tables(&table, 1, &n, 0)) ++ if ((rc = pfr_add_tables(&table, 1, &n, 0))) + { + my_syslog(LOG_WARNING, _("warning: pfr_add_tables: %s(%d)"), + pfr_strerror(errno),rc); +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0004-Set-conntrack-mark-before-connect-call.patch b/src/patches/dnsmasq/0004-Set-conntrack-mark-before-connect-call.patch new file mode 100644 index 0000000..5d7c3c4 --- /dev/null +++ b/src/patches/dnsmasq/0004-Set-conntrack-mark-before-connect-call.patch @@ -0,0 +1,68 @@ +From e9828b6f66b22ce8873f8d30a773137d1aef1b92 Mon Sep 17 00:00:00 2001 +From: Karl Vogel karl.vogel@gmail.com +Date: Fri, 3 Oct 2014 21:45:15 +0100 +Subject: [PATCH 04/55] Set conntrack mark before connect() call. + +SO_MARK has to be done before issuing the connect() call on the +TCP socket. +--- + src/forward.c | 36 ++++++++++++++++++------------------ + 1 file changed, 18 insertions(+), 18 deletions(-) + +diff --git a/src/forward.c b/src/forward.c +index 4895efeba89a..2cf29eba6e26 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -1796,6 +1796,24 @@ unsigned char *tcp_request(int confd, time_t now, + if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1) + continue; + ++#ifdef HAVE_CONNTRACK ++ /* Copy connection mark of incoming query to outgoing connection. */ ++ if (option_bool(OPT_CONNTRACK)) ++ { ++ unsigned int mark; ++ struct all_addr local; ++#ifdef HAVE_IPV6 ++ if (local_addr->sa.sa_family == AF_INET6) ++ local.addr.addr6 = local_addr->in6.sin6_addr; ++ else ++#endif ++ local.addr.addr4 = local_addr->in.sin_addr; ++ ++ if (get_incoming_mark(&peer_addr, &local, 1, &mark)) ++ setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int)); ++ } ++#endif ++ + if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 1) || + connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)) + { +@@ -1820,24 +1838,6 @@ unsigned char *tcp_request(int confd, time_t now, + size = new_size; + } + #endif +- +-#ifdef HAVE_CONNTRACK +- /* Copy connection mark of incoming query to outgoing connection. */ +- if (option_bool(OPT_CONNTRACK)) +- { +- unsigned int mark; +- struct all_addr local; +-#ifdef HAVE_IPV6 +- if (local_addr->sa.sa_family == AF_INET6) +- local.addr.addr6 = local_addr->in6.sin6_addr; +- else +-#endif +- local.addr.addr4 = local_addr->in.sin_addr; +- +- if (get_incoming_mark(&peer_addr, &local, 1, &mark)) +- setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int)); +- } +-#endif + } + + *length = htons(size); +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0005-Fix-typo-in-new-Dbus-code.patch b/src/patches/dnsmasq/0005-Fix-typo-in-new-Dbus-code.patch new file mode 100644 index 0000000..80c55f6 --- /dev/null +++ b/src/patches/dnsmasq/0005-Fix-typo-in-new-Dbus-code.patch @@ -0,0 +1,26 @@ +From 17b475912f6a4e72797a543dad59d4d5dde6bb1b Mon Sep 17 00:00:00 2001 +From: Daniel Collins daniel.collins@smoothwall.net +Date: Fri, 3 Oct 2014 21:58:43 +0100 +Subject: [PATCH 05/55] Fix typo in new Dbus code. + +Simon's fault. +--- + src/dbus.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/dbus.c b/src/dbus.c +index 15fed906bd90..a2a94dc85dac 100644 +--- a/src/dbus.c ++++ b/src/dbus.c +@@ -426,7 +426,7 @@ static DBusMessage *dbus_set_bool(DBusMessage *message, int flag, char *name) + } + else + { +- my_syslog(LOG_INFO, "Disabling --$s option from D-Bus", name); ++ my_syslog(LOG_INFO, "Disabling --%s option from D-Bus", name); + reset_option_bool(flag); + } + +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0006-Fit-example-conf-file-typo.patch b/src/patches/dnsmasq/0006-Fit-example-conf-file-typo.patch new file mode 100644 index 0000000..5f9f572 --- /dev/null +++ b/src/patches/dnsmasq/0006-Fit-example-conf-file-typo.patch @@ -0,0 +1,22 @@ +From 3d9d2dd0018603a2ae4b9cd65ac6ff959f4fd8c7 Mon Sep 17 00:00:00 2001 +From: Tomas Hozza thozza@redhat.com +Date: Mon, 6 Oct 2014 10:46:48 +0100 +Subject: [PATCH 06/55] Fit example conf file typo. + +--- + dnsmasq.conf.example | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dnsmasq.conf.example b/dnsmasq.conf.example +index 6b00bd34fbb5..1bd305dbdbad 100644 +--- a/dnsmasq.conf.example ++++ b/dnsmasq.conf.example +@@ -645,4 +645,4 @@ + #conf-dir=/etc/dnsmasq.d,.bak + + # Include all files in a directory which end in .conf +-#conf-dir=/etc/dnsmasq.d/*.conf ++#conf-dir=/etc/dnsmasq.d/,*.conf +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0007-Improve-RFC-compliance-when-unable-to-supply-address.patch b/src/patches/dnsmasq/0007-Improve-RFC-compliance-when-unable-to-supply-address.patch new file mode 100644 index 0000000..370d106 --- /dev/null +++ b/src/patches/dnsmasq/0007-Improve-RFC-compliance-when-unable-to-supply-address.patch @@ -0,0 +1,107 @@ +From b9ff5c8f435173cfa616e3c398bdc089ef690a07 Mon Sep 17 00:00:00 2001 +From: Vladislav Grishenko themiron@mail.ru +Date: Mon, 6 Oct 2014 14:34:24 +0100 +Subject: [PATCH 07/55] Improve RFC-compliance when unable to supply addresses + in DHCPv6 + +While testing https://github.com/sbyx/odhcp6c client I have noticed it +permanently crashes after startup. + +The reason was it (odhcp6c) doesn't expect empty IA options in ADVERTISE +message without any suboptions. + +Despite this validation bug of odhcp6c, dnsmasq should not generate +ADVERTISE messages with IA if there's nothing to advert per RFC 3315 +17.2.2: + + If the server will not assign any addresses to any IAs in a + + subsequent Request from the client, the server MUST send an Advertise + + message to the client that includes only a Status Code option with + + code NoAddrsAvail and a status message for the user, a Server + + Identifier option with the server's DUID, and a Client Identifier + + option with the client's DUID. + +Meanwhile it's need to add status code for every IA in REPLY message per +RFC3315 18.2.1: + + If the server cannot assign any addresses to an IA in the message + from the client, the server MUST include the IA in the Reply message + with no addresses in the IA and a Status Code option in the IA + containing status code NoAddrsAvail. + +So, I've changed the logic to skip IA completely from ADVERTISE messages and +to add NoAddrsAvail subcode into IA of REPLY messages. + +As for overhead, yes, I believe it's ok to return NoAddrsAvail twice in IA +and in global section for compatibility with all old and new clients. +--- + src/rfc3315.c | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +diff --git a/src/rfc3315.c b/src/rfc3315.c +index 5ebf09d50ac1..ddb390bf1136 100644 +--- a/src/rfc3315.c ++++ b/src/rfc3315.c +@@ -691,6 +691,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + #endif + + o = build_ia(state, &t1cntr); ++ if (address_assigned) ++ address_assigned = 2; + + for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24)) + { +@@ -781,6 +783,27 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + address_assigned = 1; + } + ++ if (address_assigned != 1) ++ { ++ /* If the server will not assign any addresses to any IAs in a ++ subsequent Request from the client, the server MUST send an Advertise ++ message to the client that doesn't include any IA options. */ ++ if (!state->lease_allocate) ++ { ++ save_counter(o); ++ continue; ++ } ++ ++ /* If the server cannot assign any addresses to an IA in the message ++ from the client, the server MUST include the IA in the Reply message ++ with no addresses in the IA and a Status Code option in the IA ++ containing status code NoAddrsAvail. */ ++ o1 = new_opt6(OPTION6_STATUS_CODE); ++ put_opt6_short(DHCP6NOADDRS); ++ put_opt6_string(_("address unavailable")); ++ end_opt6(o1); ++ } ++ + end_ia(t1cntr, min_time, 0); + end_opt6(o); + } +@@ -806,7 +829,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + put_opt6_short(DHCP6NOADDRS); + put_opt6_string(_("no addresses available")); + end_opt6(o1); +- log6_packet(state, "DHCPADVERTISE", NULL, _("no addresses available")); ++ log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", NULL, _("no addresses available")); + } + + break; +@@ -862,7 +885,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + { + /* Static range, not configured. */ + o1 = new_opt6(OPTION6_STATUS_CODE); +- put_opt6_short(DHCP6UNSPEC); ++ put_opt6_short(DHCP6NOADDRS); + put_opt6_string(_("address unavailable")); + end_opt6(o1); + } +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0008-Fix-conntrack-with-bind-interfaces.patch b/src/patches/dnsmasq/0008-Fix-conntrack-with-bind-interfaces.patch new file mode 100644 index 0000000..3f8bad3 --- /dev/null +++ b/src/patches/dnsmasq/0008-Fix-conntrack-with-bind-interfaces.patch @@ -0,0 +1,39 @@ +From 98906275a02ae260fe3f82133bd79054f8315f06 Mon Sep 17 00:00:00 2001 +From: Hans Dedecker dedeckeh@gmail.com +Date: Tue, 9 Dec 2014 22:22:53 +0000 +Subject: [PATCH 08/55] Fix conntrack with --bind-interfaces + +Make sure dst_addr is assigned the correct address in receive_query when OPTNOWILD is +enabled so the assigned mark can be correctly retrieved and set in forward_query when +conntrack is enabled. + +Signed-off-by: Hans Dedecker dedeckeh@gmail.com +--- + src/forward.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/forward.c b/src/forward.c +index 2cf29eba6e26..408a179a20f4 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -1048,7 +1048,7 @@ void receive_query(struct listener *listen, time_t now) + /* packet buffer overwritten */ + daemon->srv_save = NULL; + +- dst_addr_4.s_addr = 0; ++ dst_addr_4.s_addr = dst_addr.addr.addr4.s_addr = 0; + netmask.s_addr = 0; + + if (option_bool(OPT_NOWILD) && listen->iface) +@@ -1057,7 +1057,7 @@ void receive_query(struct listener *listen, time_t now) + + if (listen->family == AF_INET) + { +- dst_addr_4 = listen->iface->addr.in.sin_addr; ++ dst_addr_4 = dst_addr.addr.addr4 = listen->iface->addr.in.sin_addr; + netmask = listen->iface->netmask; + } + } +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0009-Use-inotify-instead-of-polling-on-Linux.patch b/src/patches/dnsmasq/0009-Use-inotify-instead-of-polling-on-Linux.patch new file mode 100644 index 0000000..8193920 --- /dev/null +++ b/src/patches/dnsmasq/0009-Use-inotify-instead-of-polling-on-Linux.patch @@ -0,0 +1,257 @@ +From 193de4abf59e49c6b70d54cfe9720fcb95ca2f71 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Wed, 10 Dec 2014 17:32:16 +0000 +Subject: [PATCH 09/55] Use inotify instead of polling on Linux. + +This should solve problems people are seeing when a file changes +twice within a second and thus is missed for polling. +--- + Makefile | 2 +- + bld/Android.mk | 2 +- + src/dnsmasq.c | 25 ++++++++++++-- + src/dnsmasq.h | 11 ++++++- + src/inotify.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 137 insertions(+), 5 deletions(-) + create mode 100644 src/inotify.c + +diff --git a/Makefile b/Makefile +index 58a7975f60b5..c340f1c7b59a 100644 +--- a/Makefile ++++ b/Makefile +@@ -69,7 +69,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \ + dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \ + helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \ + dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \ +- domain.o dnssec.o blockdata.o tables.o loop.o ++ domain.o dnssec.o blockdata.o tables.o loop.o inotify.o + + hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \ + dns-protocol.h radv-protocol.h ip6addr.h +diff --git a/bld/Android.mk b/bld/Android.mk +index d855094eb264..d627796e8edc 100644 +--- a/bld/Android.mk ++++ b/bld/Android.mk +@@ -10,7 +10,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \ + dhcp6.c rfc3315.c dhcp-common.c outpacket.c \ + radv.c slaac.c auth.c ipset.c domain.c \ + dnssec.c dnssec-openssl.c blockdata.c tables.c \ +- loop.c ++ loop.c inotify.c + + LOCAL_MODULE := dnsmasq + +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index f4a89fc38183..bf2e25a55780 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -315,9 +315,15 @@ int main (int argc, char **argv) + if (daemon->port != 0) + { + cache_init(); ++ + #ifdef HAVE_DNSSEC + blockdata_init(); + #endif ++ ++#ifdef HAVE_LINUX_NETWORK ++ if (!option_bool(OPT_NO_POLL)) ++ inotify_dnsmasq_init(); ++#endif + } + + if (option_bool(OPT_DBUS)) +@@ -793,6 +799,11 @@ int main (int argc, char **argv) + + pid = getpid(); + ++#ifdef HAVE_LINUX_NETWORK ++ /* Using inotify, have to select a resolv file at startup */ ++ poll_resolv(1, 0, now); ++#endif ++ + while (1) + { + int maxfd = -1; +@@ -862,11 +873,16 @@ int main (int argc, char **argv) + #if defined(HAVE_LINUX_NETWORK) + FD_SET(daemon->netlinkfd, &rset); + bump_maxfd(daemon->netlinkfd, &maxfd); ++ if (daemon->port != 0 && !option_bool(OPT_NO_POLL)) ++ { ++ FD_SET(daemon->inotifyfd, &rset); ++ bump_maxfd(daemon->inotifyfd, &maxfd); ++ } + #elif defined(HAVE_BSD_NETWORK) + FD_SET(daemon->routefd, &rset); + bump_maxfd(daemon->routefd, &maxfd); + #endif +- ++ + FD_SET(piperead, &rset); + bump_maxfd(piperead, &maxfd); + +@@ -929,6 +945,10 @@ int main (int argc, char **argv) + route_sock(); + #endif + ++#ifdef HAVE_LINUX_NETWORK ++ if (daemon->port != 0 && !option_bool(OPT_NO_POLL) && FD_ISSET(daemon->inotifyfd, &rset) && inotify_check()) ++ poll_resolv(1, 1, now); ++#else + /* Check for changes to resolv files once per second max. */ + /* Don't go silent for long periods if the clock goes backwards. */ + if (daemon->last_resolv == 0 || +@@ -941,7 +961,8 @@ int main (int argc, char **argv) + poll_resolv(0, daemon->last_resolv != 0, now); + daemon->last_resolv = now; + } +- ++#endif ++ + if (FD_ISSET(piperead, &rset)) + async_event(piperead, now); + +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index e74b15a5459a..ebb6b957812f 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -541,6 +541,10 @@ struct resolvc { + int is_default, logged; + time_t mtime; + char *name; ++#ifdef HAVE_LINUX_NETWORK ++ int wd; /* inotify watch descriptor */ ++ char *file; /* pointer to file part if path */ ++#endif + }; + + /* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile */ +@@ -998,7 +1002,7 @@ extern struct daemon { + /* DHCP state */ + int dhcpfd, helperfd, pxefd; + #if defined(HAVE_LINUX_NETWORK) +- int netlinkfd; ++ int netlinkfd, inotifyfd; + #elif defined(HAVE_BSD_NETWORK) + int dhcp_raw_fd, dhcp_icmp_fd, routefd; + #endif +@@ -1469,3 +1473,8 @@ void loop_send_probes(); + int detect_loop(char *query, int type); + #endif + ++/* inotify.c */ ++#ifdef HAVE_LINUX_NETWORK ++void inotify_dnsmasq_init(); ++int inotify_check(void); ++#endif +diff --git a/src/inotify.c b/src/inotify.c +new file mode 100644 +index 000000000000..a0223443d6b6 +--- /dev/null ++++ b/src/inotify.c +@@ -0,0 +1,102 @@ ++/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; version 2 dated June, 1991, or ++ (at your option) version 3 dated 29 June, 2007. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see http://www.gnu.org/licenses/. ++*/ ++ ++#include "dnsmasq.h" ++#include <sys/inotify.h> ++ ++#ifdef HAVE_LINUX_NETWORK ++ ++/* the strategy is to set a inotify on the directories containing ++ resolv files, for any files in the directory which are close-write ++ or moved into the directory. ++ ++ When either of those happen, we look to see if the file involved ++ is actually a resolv-file, and if so, call poll-resolv with ++ the "force" argument, to ensure it's read. ++ ++ This adds one new error condition: the directories containing ++ all specified resolv-files must exist at start-up, even if the actual ++ files don't. ++*/ ++ ++static char *inotify_buffer; ++#define INOTIFY_SZ (sizeof(struct inotify_event) + NAME_MAX + 1) ++ ++void inotify_dnsmasq_init() ++{ ++ struct resolvc *res; ++ ++ inotify_buffer = safe_malloc(INOTIFY_SZ); ++ ++ daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); ++ ++ if (daemon->inotifyfd == -1) ++ die(_("failed to create inotify: %s"), NULL, EC_MISC); ++ ++ for (res = daemon->resolv_files; res; res = res->next) ++ { ++ char *d = strrchr(res->name, '/'); ++ ++ if (!d) ++ die(_("resolv-file %s not an absolute path"), res->name, EC_MISC); ++ ++ *d = 0; /* make ->name just directory */ ++ res->wd = inotify_add_watch(daemon->inotifyfd, res->name, IN_CLOSE_WRITE | IN_MOVED_TO); ++ res->file = d+1; /* pointer to filename */ ++ ++ if (res->wd == -1 && errno == ENOENT) ++ die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC); ++ ++ *d = '/'; /* restore name */ ++ ++ if (res->wd == -1) ++ die(_("failed to create inotify for %s: %s"), res->name, EC_MISC); ++ } ++} ++ ++int inotify_check(void) ++{ ++ int hit = 0; ++ ++ while (1) ++ { ++ int rc; ++ char *p; ++ struct resolvc *res; ++ struct inotify_event *in; ++ ++ while ((rc = read(daemon->inotifyfd, inotify_buffer, INOTIFY_SZ)) == -1 && errno == EINTR); ++ ++ if (rc <= 0) ++ break; ++ ++ for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len) ++ { ++ in = (struct inotify_event*)p; ++ ++ for (res = daemon->resolv_files; res; res = res->next) ++ if (res->wd == in->wd && in->len != 0 && strcmp(res->file, in->name) == 0) ++ hit = 1; ++ } ++ } ++ ++ return hit; ++} ++ ++#endif ++ ++ ++ +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0010-Teach-the-new-inotify-code-about-symlinks.patch b/src/patches/dnsmasq/0010-Teach-the-new-inotify-code-about-symlinks.patch new file mode 100644 index 0000000..70fc5c3 --- /dev/null +++ b/src/patches/dnsmasq/0010-Teach-the-new-inotify-code-about-symlinks.patch @@ -0,0 +1,73 @@ +From 857973e6f7e0a3d03535a9df7f9373fd7a0b65cc Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Mon, 15 Dec 2014 15:58:13 +0000 +Subject: [PATCH 10/55] Teach the new inotify code about symlinks. + +--- + src/inotify.c | 43 +++++++++++++++++++++++++++---------------- + 1 file changed, 27 insertions(+), 16 deletions(-) + +diff --git a/src/inotify.c b/src/inotify.c +index a0223443d6b6..960bf5efb41f 100644 +--- a/src/inotify.c ++++ b/src/inotify.c +@@ -41,29 +41,40 @@ void inotify_dnsmasq_init() + + inotify_buffer = safe_malloc(INOTIFY_SZ); + +- daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); + ++ daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); ++ + if (daemon->inotifyfd == -1) + die(_("failed to create inotify: %s"), NULL, EC_MISC); +- ++ + for (res = daemon->resolv_files; res; res = res->next) + { +- char *d = strrchr(res->name, '/'); +- +- if (!d) +- die(_("resolv-file %s not an absolute path"), res->name, EC_MISC); +- +- *d = 0; /* make ->name just directory */ +- res->wd = inotify_add_watch(daemon->inotifyfd, res->name, IN_CLOSE_WRITE | IN_MOVED_TO); +- res->file = d+1; /* pointer to filename */ +- +- if (res->wd == -1 && errno == ENOENT) +- die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC); ++ char *d = NULL, *path; + +- *d = '/'; /* restore name */ ++ if (!(path = realpath(res->name, NULL))) ++ { ++ /* realpath will fail if the file doesn't exist, but ++ dnsmasq copes with missing files, so fall back ++ and assume that symlinks are not in use in that case. */ ++ if (errno == ENOENT) ++ path = res->name; ++ else ++ die(_("cannot cannonicalise resolv-file %s: %s"), res->name, EC_MISC); ++ } + +- if (res->wd == -1) +- die(_("failed to create inotify for %s: %s"), res->name, EC_MISC); ++ if ((d = strrchr(path, '/'))) ++ { ++ *d = 0; /* make path just directory */ ++ res->wd = inotify_add_watch(daemon->inotifyfd, path, IN_CLOSE_WRITE | IN_MOVED_TO); ++ res->file = d+1; /* pointer to filename */ ++ *d = '/'; ++ ++ if (res->wd == -1 && errno == ENOENT) ++ die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC); ++ ++ if (res->wd == -1) ++ die(_("failed to create inotify for %s: %s"), res->name, EC_MISC); ++ } + } + } + +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0011-Remove-floor-on-EDNS0-packet-size-with-DNSSEC.patch b/src/patches/dnsmasq/0011-Remove-floor-on-EDNS0-packet-size-with-DNSSEC.patch new file mode 100644 index 0000000..095253b --- /dev/null +++ b/src/patches/dnsmasq/0011-Remove-floor-on-EDNS0-packet-size-with-DNSSEC.patch @@ -0,0 +1,46 @@ +From 800c5cc1e7438818fd80f08c2d472df249a6942d Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Mon, 15 Dec 2014 17:50:15 +0000 +Subject: [PATCH 11/55] Remove floor on EDNS0 packet size with DNSSEC. + +--- + CHANGELOG | 6 +++++- + src/dnsmasq.c | 5 ----- + 2 files changed, 5 insertions(+), 6 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 13ab41c05fc3..68252924e743 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -2,7 +2,11 @@ version 2.73 + Fix crash at startup when an empty suffix is supplied to + --conf-dir, also trivial memory leak. Thanks to + Tomas Hozza for spotting this. +- ++ ++ Remove floor of 4096 on advertised EDNS0 packet size when ++ DNSSEC in use, the original rationale for this has long gone. ++ Thanks to Anders Kaseorg for spotting this. ++ + + version 2.72 + Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index bf2e25a55780..5c7750d365fa 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -87,11 +87,6 @@ int main (int argc, char **argv) + + if (daemon->edns_pktsz < PACKETSZ) + daemon->edns_pktsz = PACKETSZ; +-#ifdef HAVE_DNSSEC +- /* Enforce min packet big enough for DNSSEC */ +- if (option_bool(OPT_DNSSEC_VALID) && daemon->edns_pktsz < EDNS_PKTSZ) +- daemon->edns_pktsz = EDNS_PKTSZ; +-#endif + + daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ? + daemon->edns_pktsz : DNSMASQ_PACKETSZ; +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0012-CHANGELOG-re.-inotify.patch b/src/patches/dnsmasq/0012-CHANGELOG-re.-inotify.patch new file mode 100644 index 0000000..b71e58b --- /dev/null +++ b/src/patches/dnsmasq/0012-CHANGELOG-re.-inotify.patch @@ -0,0 +1,27 @@ +From ad946d555dce44eb690c7699933b6ff40ab85bb6 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Mon, 15 Dec 2014 17:52:22 +0000 +Subject: [PATCH 12/55] CHANGELOG re. inotify. + +--- + CHANGELOG | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/CHANGELOG b/CHANGELOG +index 68252924e743..9174b0bd75dc 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -7,6 +7,10 @@ version 2.73 + DNSSEC in use, the original rationale for this has long gone. + Thanks to Anders Kaseorg for spotting this. + ++ Use inotify for checking on updates to /etc/resolv.conf and ++ friends under Linux. This fixes race conditions when the files are ++ updated rapidly and saves CPU by noy polling. ++ + + version 2.72 + Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0013-Fix-breakage-of-domain-domain-subnet-local.patch b/src/patches/dnsmasq/0013-Fix-breakage-of-domain-domain-subnet-local.patch new file mode 100644 index 0000000..2ff5acd --- /dev/null +++ b/src/patches/dnsmasq/0013-Fix-breakage-of-domain-domain-subnet-local.patch @@ -0,0 +1,70 @@ +From 3ad3f3bbd4ee716a7d2fb1e115cf89bd1b1a5de9 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Tue, 16 Dec 2014 18:25:17 +0000 +Subject: [PATCH 13/55] Fix breakage of --domain=<domain>,<subnet>,local + +--- + CHANGELOG | 4 ++++ + src/option.c | 18 ++++++++++++++++-- + 2 files changed, 20 insertions(+), 2 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 9174b0bd75dc..9e6c7aa4fd68 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -10,6 +10,10 @@ version 2.73 + Use inotify for checking on updates to /etc/resolv.conf and + friends under Linux. This fixes race conditions when the files are + updated rapidly and saves CPU by noy polling. ++ ++ Fix breakage of --domain=<domain>,<subnet>,local - only reverse ++ queries were intercepted. THis appears to have been broken ++ since 2.69. Thanks to Josh Stone for finding the bug. + + + version 2.72 +diff --git a/src/option.c b/src/option.c +index b08e98e16f84..209fa6976609 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -1941,10 +1941,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + else + { + /* generate the equivalent of +- local=/<domain>/ + local=/xxx.yyy.zzz.in-addr.arpa/ */ + struct server *serv = add_rev4(new->start, msize); + serv->flags |= SERV_NO_ADDR; ++ ++ /* local=/<domain>/ */ ++ serv = opt_malloc(sizeof(struct server)); ++ memset(serv, 0, sizeof(struct server)); ++ serv->domain = d; ++ serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR; ++ serv->next = daemon->servers; ++ daemon->servers = serv; + } + } + } +@@ -1978,10 +1985,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + else + { + /* generate the equivalent of +- local=/<domain>/ + local=/xxx.yyy.zzz.ip6.arpa/ */ + struct server *serv = add_rev6(&new->start6, msize); + serv->flags |= SERV_NO_ADDR; ++ ++ /* local=/<domain>/ */ ++ serv = opt_malloc(sizeof(struct server)); ++ memset(serv, 0, sizeof(struct server)); ++ serv->domain = d; ++ serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR; ++ serv->next = daemon->servers; ++ daemon->servers = serv; + } + } + } +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0014-Remove-redundant-IN6_IS_ADDR_ULA-a-macro-defn.patch b/src/patches/dnsmasq/0014-Remove-redundant-IN6_IS_ADDR_ULA-a-macro-defn.patch new file mode 100644 index 0000000..a0e647f --- /dev/null +++ b/src/patches/dnsmasq/0014-Remove-redundant-IN6_IS_ADDR_ULA-a-macro-defn.patch @@ -0,0 +1,27 @@ +From bd9520b7ade7098ee423acc38965376aa57feb07 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Tue, 16 Dec 2014 20:41:29 +0000 +Subject: [PATCH 14/55] Remove redundant IN6_IS_ADDR_ULA(a) macro defn. + +--- + src/network.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/src/network.c b/src/network.c +index 5067007c5cbc..99419f57951e 100644 +--- a/src/network.c ++++ b/src/network.c +@@ -16,10 +16,6 @@ + + #include "dnsmasq.h" + +-#ifndef IN6_IS_ADDR_ULA +-#define IN6_IS_ADDR_ULA(a) ((((__const uint32_t *) (a))[0] & htonl (0xfe00000)) == htonl (0xfc000000)) +-#endif +- + #ifdef HAVE_LINUX_NETWORK + + int indextoname(int fd, int index, char *name) +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0015-Eliminate-IPv6-privacy-addresses-from-interface-name.patch b/src/patches/dnsmasq/0015-Eliminate-IPv6-privacy-addresses-from-interface-name.patch new file mode 100644 index 0000000..114a4f3 --- /dev/null +++ b/src/patches/dnsmasq/0015-Eliminate-IPv6-privacy-addresses-from-interface-name.patch @@ -0,0 +1,148 @@ +From 476693678e778886b64d0b56e27eb7695cbcca99 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Wed, 17 Dec 2014 12:41:56 +0000 +Subject: [PATCH 15/55] Eliminate IPv6 privacy addresses from --interface-name + answers. + +--- + CHANGELOG | 5 +++++ + src/auth.c | 4 ++++ + src/dnsmasq.h | 1 + + src/network.c | 12 ++++++++---- + src/rfc1035.c | 17 ++++++++++------- + 5 files changed, 28 insertions(+), 11 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 9e6c7aa4fd68..01f5208ec006 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -14,6 +14,11 @@ version 2.73 + Fix breakage of --domain=<domain>,<subnet>,local - only reverse + queries were intercepted. THis appears to have been broken + since 2.69. Thanks to Josh Stone for finding the bug. ++ ++ Eliminate IPv6 privacy addresses and deprecated addresses from ++ the answers given by --interface-name. Note that reverse queries ++ (ie looking for names, given addresses) are not affected. ++ Thanks to Michael Gorbach for the suggestion. + + + version 2.72 +diff --git a/src/auth.c b/src/auth.c +index dd46566ec2cc..a327f16d8c0b 100644 +--- a/src/auth.c ++++ b/src/auth.c +@@ -363,6 +363,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n + if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype && + (local_query || filter_zone(zone, flag, &addrlist->addr))) + { ++#ifdef HAVE_IPV6 ++ if (addrlist->flags & ADDRLIST_REVONLY) ++ continue; ++#endif + found = 1; + log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL); + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index ebb6b957812f..1dd61c5edba3 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -318,6 +318,7 @@ struct ds_config { + + #define ADDRLIST_LITERAL 1 + #define ADDRLIST_IPV6 2 ++#define ADDRLIST_REVONLY 4 + + struct addrlist { + struct all_addr addr; +diff --git a/src/network.c b/src/network.c +index 99419f57951e..14d2af2ce313 100644 +--- a/src/network.c ++++ b/src/network.c +@@ -236,7 +236,7 @@ struct iface_param { + }; + + static int iface_allowed(struct iface_param *param, int if_index, char *label, +- union mysockaddr *addr, struct in_addr netmask, int prefixlen, int dad) ++ union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags) + { + struct irec *iface; + int mtu = 0, loopback; +@@ -388,6 +388,10 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label, + { + al->addr.addr.addr6 = addr->in6.sin6_addr; + al->flags = ADDRLIST_IPV6; ++ /* Privacy addresses and addresses still undergoing DAD and deprecated addresses ++ don't appear in forward queries, but will in reverse ones. */ ++ if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE))) ++ al->flags |= ADDRLIST_REVONLY; + } + #endif + } +@@ -399,7 +403,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label, + for (iface = daemon->interfaces; iface; iface = iface->next) + if (sockaddr_isequal(&iface->addr, addr)) + { +- iface->dad = dad; ++ iface->dad = !!(iface_flags & IFACE_TENTATIVE); + iface->found = 1; /* for garbage collection */ + return 1; + } +@@ -474,7 +478,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label, + iface->dhcp_ok = dhcp_ok; + iface->dns_auth = auth_dns; + iface->mtu = mtu; +- iface->dad = dad; ++ iface->dad = !!(iface_flags & IFACE_TENTATIVE); + iface->found = 1; + iface->done = iface->multicast_done = iface->warned = 0; + iface->index = if_index; +@@ -519,7 +523,7 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix, + else + addr.in6.sin6_scope_id = 0; + +- return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, !!(flags & IFACE_TENTATIVE)); ++ return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags); + } + #endif + +diff --git a/src/rfc1035.c b/src/rfc1035.c +index 8a7d2608dac5..bdeb3fb10e68 100644 +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -1923,14 +1923,17 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + for (intr = daemon->int_names; intr; intr = intr->next) + if (hostname_isequal(name, intr->name)) + { +- ans = 1; +- if (!dryrun) +- { +- +- for (addrlist = intr->addr; addrlist; addrlist = addrlist->next) ++ for (addrlist = intr->addr; addrlist; addrlist = addrlist->next) + #ifdef HAVE_IPV6 +- if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type) ++ if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type) + #endif ++ { ++#ifdef HAVE_IPV6 ++ if (addrlist->flags & ADDRLIST_REVONLY) ++ continue; ++#endif ++ ans = 1; ++ if (!dryrun) + { + gotit = 1; + log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL); +@@ -1939,7 +1942,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + type == T_A ? "4" : "6", &addrlist->addr)) + anscount++; + } +- } ++ } + } + + if (!dryrun && !gotit) +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0016-Tweak-field-width-in-cache-dump-to-avoid-truncating-.patch b/src/patches/dnsmasq/0016-Tweak-field-width-in-cache-dump-to-avoid-truncating-.patch new file mode 100644 index 0000000..d072c03 --- /dev/null +++ b/src/patches/dnsmasq/0016-Tweak-field-width-in-cache-dump-to-avoid-truncating-.patch @@ -0,0 +1,35 @@ +From 3267804598047bd1781cab91508d1bc516e5ddbb Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Wed, 17 Dec 2014 20:38:20 +0000 +Subject: [PATCH 16/55] Tweak field width in cache dump to avoid truncating + IPv6 addresses. + +--- + src/cache.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/cache.c b/src/cache.c +index 2c3a49887053..f9e1d31e8c99 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -1411,7 +1411,7 @@ void dump_cache(time_t now) + *a = 0; + if (strlen(n) == 0 && !(cache->flags & F_REVERSE)) + n = "<Root>"; +- p += sprintf(p, "%-40.40s ", n); ++ p += sprintf(p, "%-30.30s ", n); + if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache)) + a = cache_get_cname_target(cache); + #ifdef HAVE_DNSSEC +@@ -1454,7 +1454,7 @@ void dump_cache(time_t now) + else if (cache->flags & F_DNSKEY) + t = "K"; + #endif +- p += sprintf(p, "%-30.30s %s%s%s%s%s%s%s%s%s ", a, t, ++ p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s ", a, t, + cache->flags & F_FORWARD ? "F" : " ", + cache->flags & F_REVERSE ? "R" : " ", + cache->flags & F_IMMORTAL ? "I" : " ", +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0017-Fix-crash-in-DNSSEC-code-when-attempting-to-verify-l.patch b/src/patches/dnsmasq/0017-Fix-crash-in-DNSSEC-code-when-attempting-to-verify-l.patch new file mode 100644 index 0000000..944afaf --- /dev/null +++ b/src/patches/dnsmasq/0017-Fix-crash-in-DNSSEC-code-when-attempting-to-verify-l.patch @@ -0,0 +1,100 @@ +From 094b5c3d904bae9aeb3206d9f3b8348926b84975 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sun, 21 Dec 2014 16:11:52 +0000 +Subject: [PATCH 17/55] Fix crash in DNSSEC code when attempting to verify + large RRs. + +--- + CHANGELOG | 3 +++ + src/dnssec.c | 27 +++++++++++++++++++-------- + 2 files changed, 22 insertions(+), 8 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 01f5208ec006..956b71a151db 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -19,6 +19,9 @@ version 2.73 + the answers given by --interface-name. Note that reverse queries + (ie looking for names, given addresses) are not affected. + Thanks to Michael Gorbach for the suggestion. ++ ++ Fix crash in DNSSEC code with long RRs. Thanks to Marco Davids ++ for the bug report. + + + version 2.72 +diff --git a/src/dnssec.c b/src/dnssec.c +index 69bfc29e355f..3208ac701149 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -456,16 +456,27 @@ static u16 *get_desc(int type) + + /* Return bytes of canonicalised rdata, when the return value is zero, the remaining + data, pointed to by *p, should be used raw. */ +-static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, ++static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, int bufflen, + unsigned char **p, u16 **desc) + { + int d = **desc; + +- (*desc)++; +- + /* No more data needs mangling */ + if (d == (u16)-1) +- return 0; ++ { ++ /* If there's more data than we have space for, just return what fits, ++ we'll get called again for more chunks */ ++ if (end - *p > bufflen) ++ { ++ memcpy(buff, *p, bufflen); ++ *p += bufflen; ++ return bufflen; ++ } ++ ++ return 0; ++ } ++ ++ (*desc)++; + + if (d == 0 && extract_name(header, plen, p, buff, 1, 0)) + /* domain-name, canonicalise */ +@@ -560,7 +571,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int + if (left1 != 0) + memmove(buff1, buff1 + len1 - left1, left1); + +- if ((len1 = get_rdata(header, plen, end1, buff1 + left1, &p1, &dp1)) == 0) ++ if ((len1 = get_rdata(header, plen, end1, buff1 + left1, MAXDNAME - left1, &p1, &dp1)) == 0) + { + quit = 1; + len1 = end1 - p1; +@@ -571,7 +582,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int + if (left2 != 0) + memmove(buff2, buff2 + len2 - left2, left2); + +- if ((len2 = get_rdata(header, plen, end2, buff2 + left2, &p2, &dp2)) == 0) ++ if ((len2 = get_rdata(header, plen, end2, buff2 + left2, MAXDNAME - left2, &p2, &dp2)) == 0) + { + quit = 1; + len2 = end2 - p2; +@@ -808,7 +819,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in + /* canonicalise rdata and calculate length of same, use name buffer as workspace */ + cp = p; + dp = rr_desc; +- for (len = 0; (seg = get_rdata(header, plen, end, name, &cp, &dp)) != 0; len += seg); ++ for (len = 0; (seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp)) != 0; len += seg); + len += end - cp; + len = htons(len); + hash->update(ctx, 2, (unsigned char *)&len); +@@ -816,7 +827,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in + /* Now canonicalise again and digest. */ + cp = p; + dp = rr_desc; +- while ((seg = get_rdata(header, plen, end, name, &cp, &dp))) ++ while ((seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp))) + hash->update(ctx, seg, (unsigned char *)name); + if (cp != end) + hash->update(ctx, end - cp, cp); +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0018-Make-caching-work-for-CNAMEs-pointing-to-A-AAAA-reco.patch b/src/patches/dnsmasq/0018-Make-caching-work-for-CNAMEs-pointing-to-A-AAAA-reco.patch new file mode 100644 index 0000000..de66adb --- /dev/null +++ b/src/patches/dnsmasq/0018-Make-caching-work-for-CNAMEs-pointing-to-A-AAAA-reco.patch @@ -0,0 +1,99 @@ +From cbc652423403e3cef00e00240f6beef713142246 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sun, 21 Dec 2014 21:21:53 +0000 +Subject: [PATCH 18/55] Make caching work for CNAMEs pointing to A/AAAA records + shadowed in /etc/hosts + +If the answer to an upstream query is a CNAME which points to an +A/AAAA record which also exists in /etc/hosts and friends, then +caching is suppressed, to avoid inconsistent answers. This is +now modified to allow caching when the upstream and local A/AAAA +records have the same value. +--- + src/cache.c | 34 +++++++++++++++++++++++++--------- + 1 file changed, 25 insertions(+), 9 deletions(-) + +diff --git a/src/cache.c b/src/cache.c +index f9e1d31e8c99..ff1ca6f1c352 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -322,7 +322,7 @@ static int is_expired(time_t now, struct crec *crecp) + return 1; + } + +-static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags) ++static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags) + { + /* Scan and remove old entries. + If (flags & F_FORWARD) then remove any forward entries for name and any expired +@@ -331,8 +331,8 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign + entries in the whole cache. + If (flags == 0) remove any expired entries in the whole cache. + +- In the flags & F_FORWARD case, the return code is valid, and returns zero if the +- name exists in the cache as a HOSTS or DHCP entry (these are never deleted) ++ In the flags & F_FORWARD case, the return code is valid, and returns a non-NULL pointer ++ to a cache entry if the name exists in the cache as a HOSTS or DHCP entry (these are never deleted) + + We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal> + so that when we hit an entry which isn't reverse and is immortal, we're done. */ +@@ -361,7 +361,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign + (((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS)))) + { + if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) +- return 0; ++ return crecp; + *up = crecp->hash_next; + cache_unlink(crecp); + cache_free(crecp); +@@ -378,7 +378,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign + crecp->addr.sig.type_covered == addr->addr.dnssec.type)) + { + if (crecp->flags & F_CONFIG) +- return 0; ++ return crecp; + *up = crecp->hash_next; + cache_unlink(crecp); + cache_free(crecp); +@@ -423,7 +423,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign + up = &crecp->hash_next; + } + +- return 1; ++ return NULL; + } + + /* Note: The normal calling sequence is +@@ -471,10 +471,26 @@ struct crec *cache_insert(char *name, struct all_addr *addr, + return NULL; + + /* First remove any expired entries and entries for the name/address we +- are currently inserting. Fail if we attempt to delete a name from +- /etc/hosts or DHCP. */ +- if (!cache_scan_free(name, addr, now, flags)) ++ are currently inserting. */ ++ if ((new = cache_scan_free(name, addr, now, flags))) + { ++ /* We're trying to insert a record over one from ++ /etc/hosts or DHCP, or other config. If the ++ existing record is for an A or AAAA and ++ the record we're trying to insert is the same, ++ just drop the insert, but don't error the whole process. */ ++ if ((flags & (F_IPV4 | F_IPV6)) && (flags & F_FORWARD)) ++ { ++ if ((flags & F_IPV4) && (new->flags & F_IPV4) && ++ new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr) ++ return new; ++#ifdef HAVE_IPV6 ++ else if ((flags & F_IPV6) && (new->flags & F_IPV6) && ++ IN6_ARE_ADDR_EQUAL(&new->addr.addr.addr.addr6, &addr->addr.addr6)) ++ return new; ++#endif ++ } ++ + insert_error = 1; + return NULL; + } +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0019-Fix-problems-validating-NSEC3-and-wildcards.patch b/src/patches/dnsmasq/0019-Fix-problems-validating-NSEC3-and-wildcards.patch new file mode 100644 index 0000000..0ee2e65 --- /dev/null +++ b/src/patches/dnsmasq/0019-Fix-problems-validating-NSEC3-and-wildcards.patch @@ -0,0 +1,365 @@ +From fbc5205702c7f6f431d9f1043c553d7fb62ddfdb Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Tue, 23 Dec 2014 15:46:08 +0000 +Subject: [PATCH 19/55] Fix problems validating NSEC3 and wildcards. + +--- + src/dnssec.c | 253 ++++++++++++++++++++++++++++++----------------------------- + 1 file changed, 128 insertions(+), 125 deletions(-) + +diff --git a/src/dnssec.c b/src/dnssec.c +index 3208ac701149..9350d3e8c963 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -615,6 +615,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int + Return code: + STAT_SECURE if it validates. + STAT_SECURE_WILDCARD if it validates and is the result of wildcard expansion. ++ (In this case *wildcard_out points to the "body" of the wildcard within name.) + STAT_NO_SIG no RRsigs found. + STAT_INSECURE RRset empty. + STAT_BOGUS signature is wrong, bad packet. +@@ -625,8 +626,8 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int + + name 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, char *name, char *keyname, struct blockdata *key, int keylen, int algo_in, int keytag_in) ++static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class, int type, ++ char *name, char *keyname, char **wildcard_out, struct blockdata *key, int keylen, int algo_in, int keytag_in) + { + static unsigned char **rrset = NULL, **sigs = NULL; + static int rrset_sz = 0, sig_sz = 0; +@@ -798,8 +799,16 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in + { + int k; + for (k = name_labels - labels; k != 0; k--) +- while (*name_start != '.' && *name_start != 0) +- name_start++; ++ { ++ while (*name_start != '.' && *name_start != 0) ++ name_start++; ++ if (k != 1) ++ name_start++; ++ } ++ ++ if (wildcard_out) ++ *wildcard_out = name_start+1; ++ + name_start--; + *name_start = '*'; + } +@@ -974,7 +983,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch + if (recp1->addr.ds.keylen == (int)hash->digest_size && + (ds_digest = blockdata_retrieve(recp1->addr.key.keydata, recp1->addr.ds.keylen, NULL)) && + memcmp(ds_digest, digest, recp1->addr.ds.keylen) == 0 && +- validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, key, rdlen - 4, algo, keytag) == STAT_SECURE) ++ validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, NULL, key, rdlen - 4, algo, keytag) == STAT_SECURE) + { + valid = 1; + break; +@@ -1443,11 +1452,88 @@ static int base32_decode(char *in, unsigned char *out) + return p - out; + } + ++static int check_nsec3_coverage(struct dns_header *header, size_t plen, int digest_len, unsigned char *digest, int type, ++ char *workspace1, char *workspace2, unsigned char **nsecs, int nsec_count) ++{ ++ int i, hash_len, salt_len, base32_len, rdlen; ++ unsigned char *p, *psave; ++ ++ for (i = 0; i < nsec_count; i++) ++ if ((p = nsecs[i])) ++ { ++ if (!extract_name(header, plen, &p, workspace1, 1, 0) || ++ !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2))) ++ return 0; ++ ++ p += 8; /* class, type, TTL */ ++ GETSHORT(rdlen, p); ++ psave = p; ++ p += 4; /* algo, flags, iterations */ ++ salt_len = *p++; /* salt_len */ ++ p += salt_len; /* salt */ ++ hash_len = *p++; /* p now points to next hashed name */ ++ ++ if (!CHECK_LEN(header, p, plen, hash_len)) ++ return 0; ++ ++ if (digest_len == base32_len && hash_len == base32_len) ++ { ++ int rc = memcmp(workspace2, digest, digest_len); ++ ++ if (rc == 0) ++ { ++ /* We found an NSEC3 whose hashed name exactly matches the query, so ++ we just need to check the type map. p points to the RR data for the record. */ ++ ++ int offset = (type & 0xff) >> 3; ++ int mask = 0x80 >> (type & 0x07); ++ ++ p += hash_len; /* skip next-domain hash */ ++ rdlen -= p - psave; ++ ++ if (!CHECK_LEN(header, p, plen, rdlen)) ++ return 0; ++ ++ while (rdlen >= 2) ++ { ++ if (p[0] == type >> 8) ++ { ++ /* Does the NSEC3 say our type exists? */ ++ if (offset < p[1] && (p[offset+2] & mask) != 0) ++ return STAT_BOGUS; ++ ++ break; /* finshed checking */ ++ } ++ ++ rdlen -= p[1]; ++ p += p[1]; ++ } ++ ++ return 1; ++ } ++ else if (rc <= 0) ++ { ++ /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash, ++ wrap around case, name-hash falls between NSEC3 name-hash and end */ ++ if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0) ++ return 1; ++ } ++ else ++ { ++ /* wrap around case, name falls between start and next domain name */ ++ if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0) ++ return 1; ++ } ++ } ++ } ++ return 0; ++} ++ + static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count, +- char *workspace1, char *workspace2, char *name, int type) ++ char *workspace1, char *workspace2, char *name, int type, char *wildname) + { + unsigned char *salt, *p, *digest; +- int digest_len, i, iterations, salt_len, hash_len, base32_len, algo = 0; ++ int digest_len, i, iterations, salt_len, base32_len, algo = 0; + struct nettle_hash const *hash; + char *closest_encloser, *next_closest, *wildcard; + +@@ -1520,7 +1606,14 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns + if (!(hash = hash_find("sha1"))) + return STAT_BOGUS; + +- /* Now, we need the "closest encloser NSEC3" */ ++ if ((digest_len = hash_name(name, &digest, hash, salt, salt_len, iterations)) == 0) ++ return STAT_BOGUS; ++ ++ if (check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count)) ++ return STAT_SECURE; ++ ++ /* Can't find an NSEC3 which covers the name directly, we need the "closest encloser NSEC3" ++ or an answer inferred from a wildcard record. */ + closest_encloser = name; + next_closest = NULL; + +@@ -1529,6 +1622,9 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns + if (*closest_encloser == '.') + closest_encloser++; + ++ if (wildname && hostname_isequal(closest_encloser, wildname)) ++ break; ++ + if ((digest_len = hash_name(closest_encloser, &digest, hash, salt, salt_len, iterations)) == 0) + return STAT_BOGUS; + +@@ -1551,127 +1647,33 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns + } + while ((closest_encloser = strchr(closest_encloser, '.'))); + +- /* No usable NSEC3s */ +- if (i == nsec_count) ++ if (!closest_encloser) + return STAT_BOGUS; + +- if (!next_closest) +- { +- /* We found an NSEC3 whose hashed name exactly matches the query, so +- Now we just need to check the type map. p points to the RR data for the record. */ +- int rdlen; +- unsigned char *psave; +- int offset = (type & 0xff) >> 3; +- int mask = 0x80 >> (type & 0x07); +- +- p += 8; /* class, type, TTL */ +- GETSHORT(rdlen, p); +- psave = p; +- p += 5 + salt_len; /* algo, flags, iterations, salt_len, salt */ +- hash_len = *p++; +- if (!CHECK_LEN(header, p, plen, hash_len)) +- return STAT_BOGUS; /* bad packet */ +- p += hash_len; +- rdlen -= p - psave; +- +- while (rdlen >= 2) +- { +- if (!CHECK_LEN(header, p, plen, rdlen)) +- return STAT_BOGUS; +- +- if (p[0] == type >> 8) +- { +- /* Does the NSEC3 say our type exists? */ +- if (offset < p[1] && (p[offset+2] & mask) != 0) +- return STAT_BOGUS; +- +- break; /* finshed checking */ +- } +- +- rdlen -= p[1]; +- p += p[1]; +- } +- +- return STAT_SECURE; +- } +- + /* Look for NSEC3 that proves the non-existence of the next-closest encloser */ + if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0) + return STAT_BOGUS; + +- for (i = 0; i < nsec_count; i++) +- if ((p = nsecs[i])) +- { +- if (!extract_name(header, plen, &p, workspace1, 1, 0) || +- !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2))) +- return STAT_BOGUS; +- +- p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */ +- hash_len = *p++; /* p now points to next hashed name */ +- +- if (!CHECK_LEN(header, p, plen, hash_len)) +- return STAT_BOGUS; +- +- if (digest_len == base32_len && hash_len == base32_len) +- { +- if (memcmp(workspace2, digest, digest_len) <= 0) +- { +- /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash, +- wrap around case, name-hash falls between NSEC3 name-hash and end */ +- if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0) +- return STAT_SECURE; +- } +- else +- { +- /* wrap around case, name falls between start and next domain name */ +- if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0) +- return STAT_SECURE; +- } +- } +- } +- +- /* Finally, check that there's no seat of wildcard synthesis */ +- if (!(wildcard = strchr(next_closest, '.')) || wildcard == next_closest) +- return STAT_BOGUS; +- +- wildcard--; +- *wildcard = '*'; +- +- if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0) ++ if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count)) + return STAT_BOGUS; + +- for (i = 0; i < nsec_count; i++) +- if ((p = nsecs[i])) +- { +- if (!extract_name(header, plen, &p, workspace1, 1, 0) || +- !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2))) +- return STAT_BOGUS; +- +- p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */ +- hash_len = *p++; /* p now points to next hashed name */ +- +- if (!CHECK_LEN(header, p, plen, hash_len)) +- return STAT_BOGUS; +- +- if (digest_len == base32_len && hash_len == base32_len) +- { +- if (memcmp(workspace2, digest, digest_len) <= 0) +- { +- /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash, +- wrap around case, name-hash falls between NSEC3 name-hash and end */ +- if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0) +- return STAT_SECURE; +- } +- else +- { +- /* wrap around case, name falls between start and next domain name */ +- if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0) +- return STAT_SECURE; +- } +- } +- } ++ /* Finally, check that there's no seat of wildcard synthesis */ ++ if (!wildname) ++ { ++ if (!(wildcard = strchr(next_closest, '.')) || wildcard == next_closest) ++ return STAT_BOGUS; ++ ++ wildcard--; ++ *wildcard = '*'; ++ ++ if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0) ++ return STAT_BOGUS; ++ ++ if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count)) ++ return STAT_BOGUS; ++ } + +- return STAT_BOGUS; ++ return STAT_SECURE; + } + + /* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3) */ +@@ -1792,8 +1794,9 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch + struct all_addr a; + struct blockdata *key; + struct crec *crecp; +- +- rc = validate_rrset(now, header, plen, class1, type1, name, keyname, NULL, 0, 0, 0); ++ char *wildname; ++ ++ rc = validate_rrset(now, header, plen, class1, type1, name, keyname, &wildname, NULL, 0, 0, 0); + + if (rc == STAT_SECURE_WILDCARD) + { +@@ -1807,7 +1810,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch + if (nsec_type == T_NSEC) + rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1); + else +- rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1); ++ rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1, wildname); + + if (rc != STAT_SECURE) + return rc; +@@ -1933,7 +1936,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch + if (nsec_type == T_NSEC) + return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype); + else +- return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype); ++ return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, NULL); + } + + /* Chase the CNAME chain in the packet until the first record which _doesn't validate. +@@ -1980,7 +1983,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char + return STAT_INSECURE; + + /* validate CNAME chain, return if insecure or need more data */ +- rc = validate_rrset(now, header, plen, class, type, name, keyname, NULL, 0, 0, 0); ++ rc = validate_rrset(now, header, plen, class, type, name, keyname, NULL, NULL, 0, 0, 0); + if (rc != STAT_SECURE) + { + if (rc == STAT_NO_SIG) +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0020-Initialise-return-value.patch b/src/patches/dnsmasq/0020-Initialise-return-value.patch new file mode 100644 index 0000000..2f70ee5 --- /dev/null +++ b/src/patches/dnsmasq/0020-Initialise-return-value.patch @@ -0,0 +1,32 @@ +From 83d2ed09fc0216b567d7fb2197e4ff3eae150b0d Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Tue, 23 Dec 2014 18:42:38 +0000 +Subject: [PATCH 20/55] Initialise return value. + +--- + src/dnssec.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/dnssec.c b/src/dnssec.c +index 9350d3e8c963..ed8cf893bad2 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -637,10 +637,13 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in + struct crec *crecp = NULL; + int type_covered, algo, labels, orig_ttl, sig_expiration, sig_inception, key_tag; + u16 *rr_desc = get_desc(type); +- ++ ++ if (wildcard_out) ++ *wildcard_out = NULL; ++ + if (!(p = skip_questions(header, plen))) + return STAT_BOGUS; +- ++ + name_labels = count_labels(name); /* For 4035 5.3.2 check */ + + /* look for RRSIGs for this RRset and get pointers to each RR in the set. */ +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0021-Add-ignore-address-option.patch b/src/patches/dnsmasq/0021-Add-ignore-address-option.patch new file mode 100644 index 0000000..6c88f2d --- /dev/null +++ b/src/patches/dnsmasq/0021-Add-ignore-address-option.patch @@ -0,0 +1,192 @@ +From 32fc6dbe03569d70dd394420ceb73532cf303c33 Mon Sep 17 00:00:00 2001 +From: Glen Huang curvedmark@gmail.com +Date: Sat, 27 Dec 2014 15:28:12 +0000 +Subject: [PATCH 21/55] Add --ignore-address option. + +--- + CHANGELOG | 8 ++++++++ + man/dnsmasq.8 | 6 ++++++ + src/dnsmasq.h | 3 ++- + src/forward.c | 4 ++++ + src/option.c | 18 +++++++++++++++--- + src/rfc1035.c | 37 +++++++++++++++++++++++++++++++++++++ + 6 files changed, 72 insertions(+), 4 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 956b71a151db..2b6356bcfb02 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -22,6 +22,14 @@ version 2.73 + + Fix crash in DNSSEC code with long RRs. Thanks to Marco Davids + for the bug report. ++ ++ Add --ignore-address option. Ignore replies to A-record ++ queries which include the specified address. No error is ++ generated, dnsmasq simply continues to listen for another ++ reply. This is useful to defeat blocking strategies which ++ rely on quickly supplying a forged answer to a DNS ++ request for certain domains, before the correct answer can ++ arrive. Thanks to Glen Huang for the patch. + + + version 2.72 +diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 +index 0b8e04f0a897..4236ba307df3 100644 +--- a/man/dnsmasq.8 ++++ b/man/dnsmasq.8 +@@ -293,6 +293,12 @@ an advertising web page in response to queries for unregistered names, + instead of the correct NXDOMAIN response. This option tells dnsmasq to + fake the correct response when it sees this behaviour. As at Sept 2003 + the IP address being returned by Verisign is 64.94.110.11 ++.TP ++.B -B, --ignore-address=<ipaddr> ++Ignore replies to A-record queries which include the specified address. ++No error is generated, dnsmasq simply continues to listen for another reply. ++This is useful to defeat blocking strategies which rely on quickly supplying a ++forged answer to a DNS request for certain domain, before the correct answer can arrive. + .TP + .B -f, --filterwin2k + Later versions of windows make periodic DNS requests which don't get sensible answers from +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 1dd61c5edba3..7bc982ddf73c 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -930,7 +930,7 @@ extern struct daemon { + char *runfile; + char *lease_change_command; + struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces; +- struct bogus_addr *bogus_addr; ++ struct bogus_addr *bogus_addr, *ignore_addr; + struct server *servers; + struct ipsets *ipsets; + int log_fac; /* log facility */ +@@ -1093,6 +1093,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + time_t now, int *ad_reqd, int *do_bit); + int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, + struct bogus_addr *addr, time_t now); ++int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr); + unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, + size_t *len, unsigned char **p, int *is_sign); + int check_for_local_domain(char *name, time_t now); +diff --git a/src/forward.c b/src/forward.c +index 408a179a20f4..f28c7d51f708 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -724,6 +724,10 @@ void reply_query(int fd, int family, time_t now) + if (!(forward = lookup_frec(ntohs(header->id), hash))) + return; + ++ if (daemon->ignore_addr && RCODE(header) == NOERROR && ++ check_for_ignored_address(header, n, daemon->ignore_addr)) ++ return; ++ + if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) && + !option_bool(OPT_ORDER) && + forward->forwardall == 0) +diff --git a/src/option.c b/src/option.c +index 209fa6976609..907d0cf88de9 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -147,6 +147,7 @@ struct myoption { + #define LOPT_LOCAL_SERVICE 335 + #define LOPT_DNSSEC_TIME 336 + #define LOPT_LOOP_DETECT 337 ++#define LOPT_IGNORE_ADDR 338 + + #ifdef HAVE_GETOPT_LONG + static const struct option opts[] = +@@ -181,6 +182,7 @@ static const struct myoption opts[] = + { "local-service", 0, 0, LOPT_LOCAL_SERVICE }, + { "bogus-priv", 0, 0, 'b' }, + { "bogus-nxdomain", 1, 0, 'B' }, ++ { "ignore-address", 1, 0, LOPT_IGNORE_ADDR }, + { "selfmx", 0, 0, 'e' }, + { "filterwin2k", 0, 0, 'f' }, + { "pid-file", 2, 0, 'x' }, +@@ -457,6 +459,7 @@ static struct { + { LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL }, + { LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, gettext_noop("Accept queries only from directly-connected networks"), NULL }, + { LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Detect and remove DNS forwarding loops"), NULL }, ++ { LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>", gettext_noop("Ignore DNS responses containing ipaddr."), NULL }, + { 0, 0, NULL, NULL, NULL } + }; + +@@ -2119,14 +2122,23 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + break; + + case 'B': /* --bogus-nxdomain */ +- { ++ case LOPT_IGNORE_ADDR: /* --ignore-address */ ++ { + struct in_addr addr; + unhide_metas(arg); + if (arg && (inet_pton(AF_INET, arg, &addr) > 0)) + { + struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr)); +- baddr->next = daemon->bogus_addr; +- daemon->bogus_addr = baddr; ++ if (option == 'B') ++ { ++ baddr->next = daemon->bogus_addr; ++ daemon->bogus_addr = baddr; ++ } ++ else ++ { ++ baddr->next = daemon->ignore_addr; ++ daemon->ignore_addr = baddr; ++ } + baddr->addr = addr; + } + else +diff --git a/src/rfc1035.c b/src/rfc1035.c +index bdeb3fb10e68..75c4266b47dd 100644 +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -1328,6 +1328,43 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, + return 0; + } + ++int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr) ++{ ++ unsigned char *p; ++ int i, qtype, qclass, rdlen; ++ struct bogus_addr *baddrp; ++ ++ /* skip over questions */ ++ if (!(p = skip_questions(header, qlen))) ++ return 0; /* bad packet */ ++ ++ for (i = ntohs(header->ancount); i != 0; i--) ++ { ++ if (!(p = skip_name(p, header, qlen, 10))) ++ return 0; /* bad packet */ ++ ++ GETSHORT(qtype, p); ++ GETSHORT(qclass, p); ++ p += 4; /* TTL */ ++ GETSHORT(rdlen, p); ++ ++ if (qclass == C_IN && qtype == T_A) ++ { ++ if (!CHECK_LEN(header, p, qlen, INADDRSZ)) ++ return 0; ++ ++ for (baddrp = baddr; baddrp; baddrp = baddrp->next) ++ if (memcmp(&baddrp->addr, p, INADDRSZ) == 0) ++ return 1; ++ } ++ ++ if (!ADD_RDLEN(header, p, qlen, rdlen)) ++ return 0; ++ } ++ ++ return 0; ++} ++ + int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp, + unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...) + { +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0022-Bad-packet-protection.patch b/src/patches/dnsmasq/0022-Bad-packet-protection.patch new file mode 100644 index 0000000..1b37202 --- /dev/null +++ b/src/patches/dnsmasq/0022-Bad-packet-protection.patch @@ -0,0 +1,25 @@ +From 0b1008d367d44e77352134a4c5178f896f0db3e7 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sat, 27 Dec 2014 15:33:32 +0000 +Subject: [PATCH 22/55] Bad packet protection. + +--- + src/dnssec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/dnssec.c b/src/dnssec.c +index ed8cf893bad2..026794b077e5 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -805,7 +805,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in + { + while (*name_start != '.' && *name_start != 0) + name_start++; +- if (k != 1) ++ if (k != 1 && *name_start == '.') + name_start++; + } + +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0023-Fix-build-failure-in-new-inotify-code-on-BSD.patch b/src/patches/dnsmasq/0023-Fix-build-failure-in-new-inotify-code-on-BSD.patch new file mode 100644 index 0000000..3bc3f79 --- /dev/null +++ b/src/patches/dnsmasq/0023-Fix-build-failure-in-new-inotify-code-on-BSD.patch @@ -0,0 +1,29 @@ +From d310ab7ecbffce79d3d90debba621e0222f9bced Mon Sep 17 00:00:00 2001 +From: Matthias Andree matthias.andree@gmx.de +Date: Sat, 27 Dec 2014 15:36:38 +0000 +Subject: [PATCH 23/55] Fix build failure in new inotify code on BSD. + +--- + src/inotify.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/inotify.c b/src/inotify.c +index 960bf5efb41f..83730008c11b 100644 +--- a/src/inotify.c ++++ b/src/inotify.c +@@ -15,10 +15,10 @@ + */ + + #include "dnsmasq.h" +-#include <sys/inotify.h> +- + #ifdef HAVE_LINUX_NETWORK + ++#include <sys/inotify.h> ++ + /* the strategy is to set a inotify on the directories containing + resolv files, for any files in the directory which are close-write + or moved into the directory. +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0024-Implement-makefile-dependencies-on-COPTS-variable.patch b/src/patches/dnsmasq/0024-Implement-makefile-dependencies-on-COPTS-variable.patch new file mode 100644 index 0000000..e3074fa --- /dev/null +++ b/src/patches/dnsmasq/0024-Implement-makefile-dependencies-on-COPTS-variable.patch @@ -0,0 +1,68 @@ +From 81c538efcebfce2ce4a1d3a420b6c885b8f08df9 Mon Sep 17 00:00:00 2001 +From: Yousong Zhou yszhou4tech@gmail.com +Date: Sat, 3 Jan 2015 16:36:14 +0000 +Subject: [PATCH 24/55] Implement makefile dependencies on COPTS variable. + +--- + .gitignore | 2 +- + Makefile | 10 ++++++---- + 2 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/.gitignore b/.gitignore +index fcdbcbd135ae..23f11488ab4c 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -3,7 +3,7 @@ src/*.mo + src/dnsmasq.pot + src/dnsmasq + src/dnsmasq_baseline +-src/.configured ++src/.copts_* + contrib/wrt/dhcp_lease_time + contrib/wrt/dhcp_release + debian/base/ +diff --git a/Makefile b/Makefile +index c340f1c7b59a..5675f60c2036 100644 +--- a/Makefile ++++ b/Makefile +@@ -64,6 +64,8 @@ nettle_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG + gmp_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC NO_GMP --copy -lgmp` + sunos_libs = `if uname | grep SunOS >/dev/null 2>&1; then echo -lsocket -lnsl -lposix4; fi` + version = -DVERSION='"`$(top)/bld/get-version $(top)`"' ++copts_conf = .copts_$(shell $(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | \ ++ ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' ') + + objs = cache.o rfc1035.o util.o option.o forward.o network.o \ + dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \ +@@ -83,7 +85,7 @@ all : $(BUILDDIR) + + mostly_clean : + rm -f $(BUILDDIR)/*.mo $(BUILDDIR)/*.pot +- rm -f $(BUILDDIR)/.configured $(BUILDDIR)/*.o $(BUILDDIR)/dnsmasq.a $(BUILDDIR)/dnsmasq ++ rm -f $(BUILDDIR)/.copts_* $(BUILDDIR)/*.o $(BUILDDIR)/dnsmasq.a $(BUILDDIR)/dnsmasq + + clean : mostly_clean + rm -f $(BUILDDIR)/dnsmasq_baseline +@@ -139,8 +141,8 @@ bloatcheck : $(BUILDDIR)/dnsmasq_baseline mostly_clean all + + # rules below are targets in recusive makes with cwd=$(BUILDDIR) + +-.configured: $(hdrs) +- @rm -f *.o ++$(copts_conf): $(hdrs) ++ @rm -f *.o .copts_* + @touch $@ + + $(objs:.o=.c) $(hdrs): +@@ -149,7 +151,7 @@ $(objs:.o=.c) $(hdrs): + .c.o: + $(CC) $(CFLAGS) $(COPTS) $(i18n) $(build_cflags) $(RPM_OPT_FLAGS) -c $< + +-dnsmasq : .configured $(hdrs) $(objs) ++dnsmasq : $(copts_conf) $(hdrs) $(objs) + $(CC) $(LDFLAGS) -o $@ $(objs) $(build_libs) $(LIBS) + + dnsmasq.pot : $(objs:.o=.c) $(hdrs) +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0025-Fix-race-condition-issue-in-makefile.patch b/src/patches/dnsmasq/0025-Fix-race-condition-issue-in-makefile.patch new file mode 100644 index 0000000..b1c42ae --- /dev/null +++ b/src/patches/dnsmasq/0025-Fix-race-condition-issue-in-makefile.patch @@ -0,0 +1,30 @@ +From d8dbd903d024f84a149dac2f8a674a68dfed47a3 Mon Sep 17 00:00:00 2001 +From: Yousong Zhou yszhou4tech@gmail.com +Date: Mon, 5 Jan 2015 17:03:35 +0000 +Subject: [PATCH 25/55] Fix race condition issue in makefile. + +--- + Makefile | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 5675f60c2036..bcbd5571671d 100644 +--- a/Makefile ++++ b/Makefile +@@ -148,10 +148,12 @@ $(copts_conf): $(hdrs) + $(objs:.o=.c) $(hdrs): + ln -s $(top)/$(SRC)/$@ . + ++$(objs): $(copts_conf) $(hdrs) ++ + .c.o: + $(CC) $(CFLAGS) $(COPTS) $(i18n) $(build_cflags) $(RPM_OPT_FLAGS) -c $< + +-dnsmasq : $(copts_conf) $(hdrs) $(objs) ++dnsmasq : $(objs) + $(CC) $(LDFLAGS) -o $@ $(objs) $(build_libs) $(LIBS) + + dnsmasq.pot : $(objs:.o=.c) $(hdrs) +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0026-DNSSEC-do-top-down-search-for-limit-of-secure-delega.patch b/src/patches/dnsmasq/0026-DNSSEC-do-top-down-search-for-limit-of-secure-delega.patch new file mode 100644 index 0000000..7f01ee7 --- /dev/null +++ b/src/patches/dnsmasq/0026-DNSSEC-do-top-down-search-for-limit-of-secure-delega.patch @@ -0,0 +1,792 @@ +From 97e618a0e3f29465acc689d87288596b006f197e Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Wed, 7 Jan 2015 21:55:43 +0000 +Subject: [PATCH 26/55] DNSSEC: do top-down search for limit of secure + delegation. + +--- + CHANGELOG | 9 ++ + src/dnsmasq.h | 11 +- + src/dnssec.c | 91 +++++++++------- + src/forward.c | 327 +++++++++++++++++++++++++++++++++------------------------- + 4 files changed, 260 insertions(+), 178 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 2b6356bcfb02..e8bf80f81baa 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -31,7 +31,16 @@ version 2.73 + request for certain domains, before the correct answer can + arrive. Thanks to Glen Huang for the patch. + ++ Revisit the part of DNSSEC validation which determines if an ++ unsigned answer is legit, or is in some part of the DNS ++ tree which should be signed. Dnsmasq now works from the ++ DNS root downward looking for the limit of signed ++ delegations, rather than working bottom up. This is ++ both more correct, and less likely to trip over broken ++ nameservers in the unsigned parts of the DNS tree ++ which don't respond well to DNSSEC queries. + ++ + version 2.72 + Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. + +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 7bc982ddf73c..2f4597294a56 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -569,8 +569,9 @@ struct hostsfile { + #define STAT_SECURE_WILDCARD 7 + #define STAT_NO_SIG 8 + #define STAT_NO_DS 9 +-#define STAT_NEED_DS_NEG 10 +-#define STAT_CHASE_CNAME 11 ++#define STAT_NO_NS 10 ++#define STAT_NEED_DS_NEG 11 ++#define STAT_CHASE_CNAME 12 + + #define FREC_NOREBIND 1 + #define FREC_CHECKING_DISABLED 2 +@@ -604,7 +605,9 @@ struct frec { + #ifdef HAVE_DNSSEC + int class, work_counter; + struct blockdata *stash; /* Saved reply, whilst we validate */ +- size_t stash_len; ++ struct blockdata *orig_domain; /* domain of original query, whilst ++ we're seeing is if in unsigned domain */ ++ size_t stash_len, name_start, name_len; + struct frec *dependent; /* Query awaiting internally-generated DNSKEY or DS query */ + struct frec *blocking_query; /* Query which is blocking us. */ + #endif +@@ -1126,7 +1129,7 @@ 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 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 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 dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen); + size_t filter_rrsigs(struct dns_header *header, size_t plen); +diff --git a/src/dnssec.c b/src/dnssec.c +index 026794b077e5..8f27677628b2 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -875,8 +875,7 @@ 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. + Put all DNSKEYs in the answer which are valid into the cache. + return codes: +- STAT_INSECURE No DNSKEYs in reply. +- STAT_SECURE At least one valid DNSKEY found and in cache. ++ STAT_SECURE At least one valid DNSKEY found and in cache. + STAT_BOGUS No DNSKEYs found, which can be validated with DS, + or self-sign for DNSKEY RRset is not valid, bad packet. + STAT_NEED_DS DS records to validate a key not found, name in keyname +@@ -896,11 +895,8 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch + GETSHORT(qtype, p); + GETSHORT(qclass, p); + +- if (qtype != T_DNSKEY || qclass != class) ++ if (qtype != T_DNSKEY || qclass != class || ntohs(header->ancount) == 0) + return STAT_BOGUS; +- +- if (ntohs(header->ancount) == 0) +- return STAT_INSECURE; + + /* See if we have cached a DS record which validates this key */ + if (!(crecp = cache_find_by_name(NULL, name, now, F_DS))) +@@ -1103,17 +1099,17 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch + /* The DNS packet is expected to contain the answer to a DS query + Put all DSs in the answer which are valid into the cache. + return codes: +- STAT_INSECURE no DS in reply or not signed. + STAT_SECURE At least one valid DS found and in cache. + STAT_NO_DS It's proved there's no DS here. +- STAT_BOGUS At least one DS found, which fails validation, bad packet. ++ STAT_NO_NS It's proved there's no DS _or_ NS here. ++ STAT_BOGUS no DS in reply or not signed, fails validation, bad packet. + STAT_NEED_DNSKEY DNSKEY records to validate a DS not found, name in keyname + */ + + int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class) + { + unsigned char *p = (unsigned char *)(header+1); +- int qtype, qclass, val, i, neganswer; ++ int qtype, qclass, val, i, neganswer, nons; + + if (ntohs(header->qdcount) != 1 || + !(p = skip_name(p, header, plen, 4))) +@@ -1125,32 +1121,39 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char + if (qtype != T_DS || qclass != class) + val = STAT_BOGUS; + else +- val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, &neganswer); +- +- if (val == STAT_NO_SIG) +- val = STAT_INSECURE; ++ val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, &neganswer, &nons); ++ /* Note dnssec_validate_reply() will have cached positive answers */ ++ ++ if (val == STAT_NO_SIG || val == STAT_INSECURE) ++ val = STAT_BOGUS; + + p = (unsigned char *)(header+1); + extract_name(header, plen, &p, name, 1, 4); + p += 4; /* qtype, qclass */ + + if (!(p = skip_section(p, ntohs(header->ancount), header, plen))) +- return STAT_BOGUS; ++ val = STAT_BOGUS; + + if (val == STAT_BOGUS) +- log_query(F_UPSTREAM, name, NULL, "BOGUS DS"); +- +- if ((val == STAT_SECURE || val == STAT_INSECURE) && neganswer) + { +- int rdlen, flags = F_FORWARD | F_DS | F_NEG; ++ log_query(F_UPSTREAM, name, NULL, "BOGUS DS"); ++ return STAT_BOGUS; ++ } ++ ++ /* By here, the answer is proved secure, and a positive answer has been cached. */ ++ if (val == STAT_SECURE && neganswer) ++ { ++ int rdlen, flags = F_FORWARD | F_DS | F_NEG | F_DNSSECOK; + unsigned long ttl, minttl = ULONG_MAX; + struct all_addr a; + + if (RCODE(header) == NXDOMAIN) + flags |= F_NXDOMAIN; + +- if (val == STAT_SECURE) +- flags |= F_DNSSECOK; ++ /* We only cache validated DS records, DNSSECOK flag hijacked ++ to store presence/absence of NS. */ ++ if (nons) ++ flags &= ~F_DNSSECOK; + + for (i = ntohs(header->nscount); i != 0; i--) + { +@@ -1196,10 +1199,12 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char + a.addr.dnssec.class = class; + cache_insert(name, &a, now, ttl, flags); + +- cache_end_insert(); ++ cache_end_insert(); ++ ++ log_query(F_UPSTREAM, name, NULL, nons ? "no delegation" : "no DS"); + } + +- return (val == STAT_SECURE) ? STAT_NO_DS : STAT_INSECURE; ++ return nons ? STAT_NO_NS : STAT_NO_DS; + } + + return val; +@@ -1323,12 +1328,15 @@ static int find_nsec_records(struct dns_header *header, size_t plen, unsigned ch + } + + static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count, +- char *workspace1, char *workspace2, char *name, int type) ++ char *workspace1, char *workspace2, char *name, int type, int *nons) + { + int i, rc, rdlen; + unsigned char *p, *psave; + int offset = (type & 0xff) >> 3; + int mask = 0x80 >> (type & 0x07); ++ ++ if (nons) ++ *nons = 0; + + /* Find NSEC record that proves name doesn't exist */ + for (i = 0; i < nsec_count; i++) +@@ -1355,6 +1363,10 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi + rdlen -= p - psave; + /* rdlen is now length of type map, and p points to it */ + ++ /* If we can prove that there's no NS record, return that information. */ ++ if (nons && rdlen >= 2 && p[0] == 0 && (p[2] & (0x80 >> T_NS)) == 0) ++ *nons = 1; ++ + while (rdlen >= 2) + { + if (!CHECK_LEN(header, p, plen, rdlen)) +@@ -1456,7 +1468,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, +- char *workspace1, char *workspace2, unsigned char **nsecs, int nsec_count) ++ char *workspace1, char *workspace2, unsigned char **nsecs, int nsec_count, int *nons) + { + int i, hash_len, salt_len, base32_len, rdlen; + unsigned char *p, *psave; +@@ -1497,6 +1509,10 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige + if (!CHECK_LEN(header, p, plen, rdlen)) + return 0; + ++ /* If we can prove that there's no NS record, return that information. */ ++ if (nons && rdlen >= 2 && p[0] == 0 && (p[2] & (0x80 >> T_NS)) == 0) ++ *nons = 1; ++ + while (rdlen >= 2) + { + if (p[0] == type >> 8) +@@ -1533,13 +1549,16 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige + } + + static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count, +- char *workspace1, char *workspace2, char *name, int type, char *wildname) ++ char *workspace1, char *workspace2, char *name, int type, char *wildname, int *nons) + { + unsigned char *salt, *p, *digest; + int digest_len, i, iterations, salt_len, base32_len, algo = 0; + struct nettle_hash const *hash; + char *closest_encloser, *next_closest, *wildcard; +- ++ ++ if (nons) ++ *nons = 0; ++ + /* Look though the NSEC3 records to find the first one with + an algorithm we support (currently only algo == 1). + +@@ -1612,7 +1631,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns + if ((digest_len = hash_name(name, &digest, hash, salt, salt_len, iterations)) == 0) + return STAT_BOGUS; + +- if (check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count)) ++ if (check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, nons)) + return STAT_SECURE; + + /* Can't find an NSEC3 which covers the name directly, we need the "closest encloser NSEC3" +@@ -1657,7 +1676,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns + if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0) + return STAT_BOGUS; + +- if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count)) ++ if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, NULL)) + return STAT_BOGUS; + + /* Finally, check that there's no seat of wildcard synthesis */ +@@ -1672,7 +1691,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns + if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0) + return STAT_BOGUS; + +- if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count)) ++ if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, NULL)) + return STAT_BOGUS; + } + +@@ -1681,7 +1700,8 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns + + /* 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 */ +-int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int *neganswer) ++int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, ++ int *class, int *neganswer, int *nons) + { + unsigned char *ans_start, *qname, *p1, *p2, **nsecs; + int type1, class1, rdlen1, type2, class2, rdlen2, qclass, qtype; +@@ -1811,10 +1831,11 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch + return STAT_BOGUS; /* No NSECs or bad packet */ + + if (nsec_type == T_NSEC) +- rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1); ++ rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1, NULL); + else +- rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1, wildname); +- ++ rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, ++ keyname, name, type1, wildname, NULL); ++ + if (rc != STAT_SECURE) + return rc; + } +@@ -1937,9 +1958,9 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch + return STAT_BOGUS; + + if (nsec_type == T_NSEC) +- return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype); ++ return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, nons); + else +- return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, NULL); ++ return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, NULL, nons); + } + + /* Chase the CNAME chain in the packet until the first record which _doesn't validate. +diff --git a/src/forward.c b/src/forward.c +index f28c7d51f708..ee8d7b52d5e5 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -26,8 +26,9 @@ static void free_frec(struct frec *f); + #ifdef HAVE_DNSSEC + static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n, + int class, char *name, char *keyname, struct server *server, int *keycount); +-static int do_check_sign(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class); +-static int send_check_sign(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname); ++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, ++ char *name, char *keyname); + #endif + + +@@ -815,18 +816,22 @@ void reply_query(int fd, int family, time_t now) + else if (forward->flags & FREC_DS_QUERY) + { + status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class); +- if (status == STAT_NO_DS) +- status = STAT_INSECURE; ++ if (status == STAT_NO_DS || status == STAT_NO_NS) ++ status = STAT_BOGUS; + } + else if (forward->flags & FREC_CHECK_NOSIGN) +- status = do_check_sign(now, header, n, daemon->namebuff, daemon->keyname, forward->class); ++ { ++ status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class); ++ if (status != STAT_NEED_KEY) ++ status = do_check_sign(forward, status, now, daemon->namebuff, daemon->keyname); ++ } + else + { +- status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, NULL); ++ status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, NULL, NULL); + if (status == STAT_NO_SIG) + { + if (option_bool(OPT_DNSSEC_NO_SIGN)) +- status = send_check_sign(now, header, n, daemon->namebuff, daemon->keyname); ++ status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname); + else + status = STAT_INSECURE; + } +@@ -861,6 +866,7 @@ void reply_query(int fd, int family, time_t now) + new->blocking_query = NULL; + new->sentto = server; + new->rfd4 = NULL; ++ new->orig_domain = NULL; + #ifdef HAVE_IPV6 + new->rfd6 = NULL; + #endif +@@ -889,7 +895,9 @@ void reply_query(int fd, int family, time_t now) + new->new_id = get_id(); + header->id = htons(new->new_id); + /* Save query for retransmission */ +- new->stash = blockdata_alloc((char *)header, nn); ++ if (!(new->stash = blockdata_alloc((char *)header, nn))) ++ return; ++ + new->stash_len = nn; + + /* Don't resend this. */ +@@ -946,18 +954,22 @@ void reply_query(int fd, int family, time_t now) + else if (forward->flags & FREC_DS_QUERY) + { + status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class); +- if (status == STAT_NO_DS) +- status = STAT_INSECURE; ++ if (status == STAT_NO_DS || status == STAT_NO_NS) ++ status = STAT_BOGUS; + } + else if (forward->flags & FREC_CHECK_NOSIGN) +- status = do_check_sign(now, header, n, daemon->namebuff, daemon->keyname, forward->class); ++ { ++ status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class); ++ if (status != STAT_NEED_KEY) ++ status = do_check_sign(forward, status, now, daemon->namebuff, daemon->keyname); ++ } + else + { +- status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, NULL); ++ status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, NULL, NULL); + if (status == STAT_NO_SIG) + { + if (option_bool(OPT_DNSSEC_NO_SIGN)) +- status = send_check_sign(now, header, n, daemon->namebuff, daemon->keyname); ++ status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname); + else + status = STAT_INSECURE; + } +@@ -1319,70 +1331,80 @@ void receive_query(struct listener *listen, time_t now) + /* UDP: we've got an unsigned answer, return STAT_INSECURE if we can prove there's no DS + and therefore the answer shouldn't be signed, or STAT_BOGUS if it should be, or + STAT_NEED_DS_NEG and keyname if we need to do the query. */ +-static int send_check_sign(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname) ++static int send_check_sign(struct frec *forward, time_t now, struct dns_header *header, size_t plen, ++ char *name, char *keyname) + { +- struct crec *crecp; +- char *name_start = name; + int status = dnssec_chase_cname(now, header, plen, name, keyname); + + if (status != STAT_INSECURE) + return status; + ++ /* Store the domain we're trying to check. */ ++ forward->name_start = strlen(name); ++ forward->name_len = forward->name_start + 1; ++ if (!(forward->orig_domain = blockdata_alloc(name, forward->name_len))) ++ return STAT_BOGUS; ++ ++ return do_check_sign(forward, 0, now, name, keyname); ++} ++ ++/* We either have a a reply (header non-NULL, or we need to start by looking in the cache */ ++static int do_check_sign(struct frec *forward, int status, time_t now, char *name, char *keyname) ++{ ++ /* get domain we're checking back from blockdata store, it's stored on the original query. */ ++ while (forward->dependent) ++ forward = forward->dependent; ++ ++ blockdata_retrieve(forward->orig_domain, forward->name_len, name); ++ + while (1) + { +- crecp = cache_find_by_name(NULL, name_start, now, F_DS); +- +- if (crecp && (crecp->flags & F_DNSSECOK)) +- return (crecp->flags & F_NEG) ? STAT_INSECURE : STAT_BOGUS; +- +- if (crecp && (crecp->flags & F_NEG) && (name_start = strchr(name_start, '.'))) ++ char *p; ++ ++ if (status == 0) + { +- name_start++; /* chop a label off and try again */ +- continue; ++ struct crec *crecp; ++ ++ /* Haven't received answer, see if in cache */ ++ if (!(crecp = cache_find_by_name(NULL, &name[forward->name_start], now, F_DS))) ++ { ++ /* put name of DS record we're missing into keyname */ ++ strcpy(keyname, &name[forward->name_start]); ++ /* and wait for reply to arrive */ ++ return STAT_NEED_DS_NEG; ++ } ++ ++ /* F_DNSSECOK misused in DS cache records to non-existance of NS record */ ++ if (!(crecp->flags & F_NEG)) ++ status = STAT_SECURE; ++ else if (crecp->flags & F_DNSSECOK) ++ status = STAT_NO_DS; ++ else ++ status = STAT_NO_NS; + } ++ ++ /* Have entered non-signed part of DNS tree. */ ++ if (status == STAT_NO_DS) ++ return STAT_INSECURE; + +- /* Reached the root */ +- if (!name_start) ++ if (status == STAT_BOGUS) + return STAT_BOGUS; + +- strcpy(keyname, name_start); +- return STAT_NEED_DS_NEG; +- } +-} +- +-/* Got answer to DS query from send_check_sign, check for proven non-existence, or make the next DS query to try. */ +-static int do_check_sign(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class) +- +-{ +- char *name_start; +- unsigned char *p; +- int status; ++ /* There's a proven DS record, or we're within a zone, where there doesn't need ++ to be a DS record. Add a name and try again. ++ If we've already tried the whole name, then fail */ + +- /* In this case only, a SERVFAIL reply allows us to continue up the tree, looking for a +- suitable NSEC reply to DS queries. */ +- if (RCODE(header) != SERVFAIL) +- { +- status = dnssec_validate_ds(now, header, plen, name, keyname, class); ++ if (forward->name_start == 0) ++ return STAT_BOGUS; + +- if (status != STAT_INSECURE) +- { +- if (status == STAT_NO_DS) +- status = STAT_INSECURE; +- return status; +- } +- } +- +- p = (unsigned char *)(header+1); +- +- if (extract_name(header, plen, &p, name, 1, 4) && +- (name_start = strchr(name, '.'))) +- { +- name_start++; /* chop a label off and try again */ +- strcpy(keyname, name_start); +- return STAT_NEED_DS_NEG; ++ for (p = &name[forward->name_start-2]; (*p != '.') && (p != name); p--); ++ ++ if (p != name) ++ p++; ++ ++ forward->name_start = p - name; ++ status = 0; /* force to cache when we iterate. */ + } +- +- return STAT_BOGUS; + } + + /* Move toward the root, until we find a signed non-existance of a DS, in which case +@@ -1395,8 +1417,10 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s + unsigned char *packet, *payload; + u16 *length; + unsigned char *p = (unsigned char *)(header+1); +- int status; +- char *name_start = name; ++ int status, name_len; ++ struct blockdata *block; ++ ++ char *name_start; + + /* Get first insecure entry in CNAME chain */ + status = tcp_key_recurse(now, STAT_CHASE_CNAME, header, plen, class, name, keyname, server, keycount); +@@ -1409,95 +1433,113 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s + payload = &packet[2]; + header = (struct dns_header *)payload; + length = (u16 *)packet; ++ ++ /* Stash the name away, since the buffer will be trashed when we recurse */ ++ name_len = strlen(name) + 1; ++ name_start = name + name_len - 1; + ++ if (!(block = blockdata_alloc(name, name_len))) ++ { ++ free(packet); ++ return STAT_BOGUS; ++ } ++ + while (1) + { +- unsigned char *newhash, hash[HASH_SIZE]; + unsigned char c1, c2; +- struct crec *crecp = cache_find_by_name(NULL, name_start, now, F_DS); +- ++ struct crec *crecp; ++ + if (--(*keycount) == 0) + { + free(packet); ++ blockdata_free(block); + return STAT_BOGUS; + } +- +- if (crecp && (crecp->flags & F_DNSSECOK)) +- { +- free(packet); +- return (crecp->flags & F_NEG) ? STAT_INSECURE : STAT_BOGUS; +- } + +- /* If we have cached insecurely that a DS doesn't exist, +- ise that is a hit for where to start looking for the secure one */ +- if (crecp && (crecp->flags & F_NEG) && (name_start = strchr(name_start, '.'))) +- { +- name_start++; /* chop a label off and try again */ +- continue; +- } +- +- /* reached the root */ +- if (!name_start) +- { +- free(packet); +- return STAT_BOGUS; ++ while (crecp = cache_find_by_name(NULL, name_start, now, F_DS)) ++ { ++ if ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK)) ++ { ++ /* Found a secure denial of DS - delegation is indeed insecure */ ++ free(packet); ++ blockdata_free(block); ++ return STAT_INSECURE; ++ } ++ ++ /* Here, either there's a secure DS, or no NS and no DS, and therefore no delegation. ++ Add another label and continue. */ ++ ++ if (name_start == name) ++ { ++ free(packet); ++ blockdata_free(block); ++ return STAT_BOGUS; /* run out of labels */ ++ } ++ ++ name_start -= 2; ++ while (*name_start != '.' && name_start != name) ++ name_start--; ++ if (name_start != name) ++ name_start++; + } ++ ++ /* Can't find it in the cache, have to send a query */ + + m = dnssec_generate_query(header, ((char *) header) + 65536, name_start, class, T_DS, &server->addr); + +- /* We rely on the question section coming back unchanged, ensure it is with the hash. */ +- if ((newhash = hash_questions(header, (unsigned int)m, name))) +- { +- memcpy(hash, newhash, HASH_SIZE); ++ *length = htons(m); + +- *length = htons(m); ++ if (read_write(server->tcpfd, packet, m + sizeof(u16), 0) && ++ read_write(server->tcpfd, &c1, 1, 1) && ++ read_write(server->tcpfd, &c2, 1, 1) && ++ read_write(server->tcpfd, payload, (c1 << 8) | c2, 1)) ++ { ++ m = (c1 << 8) | c2; ++ ++ /* Note this trashes all three name workspaces */ ++ status = tcp_key_recurse(now, STAT_NEED_DS_NEG, header, m, class, name, keyname, server, keycount); + +- if (read_write(server->tcpfd, packet, m + sizeof(u16), 0) && +- read_write(server->tcpfd, &c1, 1, 1) && +- read_write(server->tcpfd, &c2, 1, 1) && +- read_write(server->tcpfd, payload, (c1 << 8) | c2, 1)) ++ if (status == STAT_NO_DS) + { +- m = (c1 << 8) | c2; +- +- newhash = hash_questions(header, (unsigned int)m, name); +- if (newhash && memcmp(hash, newhash, HASH_SIZE) == 0) +- { +- /* In this case only, a SERVFAIL reply allows us to continue up the tree, looking for a +- suitable NSEC reply to DS queries. */ +- if (RCODE(header) == SERVFAIL) +- status = STAT_INSECURE; +- else +- /* Note this trashes all three name workspaces */ +- status = tcp_key_recurse(now, STAT_NEED_DS_NEG, header, m, class, name, keyname, server, keycount); +- +- /* We've found a DS which proves the bit of the DNS where the +- original query is, is unsigned, so the answer is OK, +- if unvalidated. */ +- if (status == STAT_NO_DS) +- { +- free(packet); +- return STAT_INSECURE; +- } +- +- /* No DS, not got to DNSSEC-land yet, go up. */ +- if (status == STAT_INSECURE) +- { +- p = (unsigned char *)(header+1); +- +- if (extract_name(header, plen, &p, name, 1, 4) && +- (name_start = strchr(name, '.'))) +- { +- name_start++; /* chop a label off and try again */ +- continue; +- } +- } +- } ++ /* Found a secure denial of DS - delegation is indeed insecure */ ++ free(packet); ++ blockdata_free(block); ++ return STAT_INSECURE; ++ } ++ ++ if (status == STAT_BOGUS) ++ { ++ free(packet); ++ blockdata_free(block); ++ return STAT_BOGUS; ++ } ++ ++ /* Here, either there's a secure DS, or no NS and no DS, and therefore no delegation. ++ Add another label and continue. */ ++ ++ /* Get name we're checking back. */ ++ blockdata_retrieve(block, name_len, name); ++ ++ if (name_start == name) ++ { ++ free(packet); ++ blockdata_free(block); ++ return STAT_BOGUS; /* run out of labels */ + } ++ ++ name_start -= 2; ++ while (*name_start != '.' && name_start != name) ++ name_start--; ++ if (name_start != name) ++ name_start++; ++ } ++ else ++ { ++ /* IO failure */ ++ free(packet); ++ blockdata_free(block); ++ return STAT_BOGUS; /* run out of labels */ + } +- +- free(packet); +- +- return STAT_BOGUS; + } + } + +@@ -1516,14 +1558,14 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si + else if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG) + { + new_status = dnssec_validate_ds(now, header, n, name, keyname, class); +- if (status == STAT_NEED_DS && new_status == STAT_NO_DS) +- new_status = STAT_INSECURE; ++ if (status == STAT_NEED_DS && (new_status == STAT_NO_DS || new_status == STAT_NO_NS)) ++ new_status = STAT_BOGUS; + } + else if (status == STAT_CHASE_CNAME) + new_status = dnssec_chase_cname(now, header, n, name, keyname); + else + { +- new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, NULL); ++ new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, NULL, NULL); + + if (new_status == STAT_NO_SIG) + { +@@ -1576,14 +1618,14 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si + else if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG) + { + new_status = dnssec_validate_ds(now, header, n, name, keyname, class); +- if (status == STAT_NEED_DS && new_status == STAT_NO_DS) +- new_status = STAT_INSECURE; /* Validated no DS */ ++ if (status == STAT_NEED_DS && (new_status == STAT_NO_DS || new_status == STAT_NO_NS)) ++ new_status = STAT_BOGUS; /* Validated no DS */ + } + else if (status == STAT_CHASE_CNAME) + new_status = dnssec_chase_cname(now, header, n, name, keyname); + else + { +- new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, NULL); ++ new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, NULL, NULL); + + if (new_status == STAT_NO_SIG) + { +@@ -1961,6 +2003,7 @@ static struct frec *allocate_frec(time_t now) + f->dependent = NULL; + f->blocking_query = NULL; + f->stash = NULL; ++ f->orig_domain = NULL; + #endif + daemon->frec_list = f; + } +@@ -2029,6 +2072,12 @@ static void free_frec(struct frec *f) + f->stash = NULL; + } + ++ if (f->orig_domain) ++ { ++ blockdata_free(f->orig_domain); ++ f->orig_domain = NULL; ++ } ++ + /* Anything we're waiting on is pointless now, too */ + if (f->blocking_query) + free_frec(f->blocking_query); +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0027-Add-log-queries-extra-option-for-more-complete-loggi.patch b/src/patches/dnsmasq/0027-Add-log-queries-extra-option-for-more-complete-loggi.patch new file mode 100644 index 0000000..e258d56 --- /dev/null +++ b/src/patches/dnsmasq/0027-Add-log-queries-extra-option-for-more-complete-loggi.patch @@ -0,0 +1,346 @@ +From 25cf5e373eb41c088d4ee5e625209c4cf6a5659e Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Fri, 9 Jan 2015 15:53:03 +0000 +Subject: [PATCH 27/55] Add --log-queries=extra option for more complete + logging. + +--- + CHANGELOG | 3 +++ + man/dnsmasq.8 | 5 ++++- + src/cache.c | 11 ++++++++++- + src/config.h | 1 + + src/dnsmasq.c | 5 +++++ + src/dnsmasq.h | 9 +++++++-- + src/dnssec.c | 14 +++++++------- + src/forward.c | 30 ++++++++++++++++++++++++++---- + src/option.c | 11 +++++++++-- + 9 files changed, 72 insertions(+), 17 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index e8bf80f81baa..0bbb7835df4f 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -40,6 +40,9 @@ version 2.73 + nameservers in the unsigned parts of the DNS tree + which don't respond well to DNSSEC queries. + ++ Add --log-queries=extra option, which makes logs easier ++ to search automatically. ++ + + version 2.72 + Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. +diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 +index 4236ba307df3..227d74bd80e7 100644 +--- a/man/dnsmasq.8 ++++ b/man/dnsmasq.8 +@@ -98,7 +98,10 @@ only, to stop dnsmasq daemonising in production, use + .B -k. + .TP + .B -q, --log-queries +-Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1. ++Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1. If the argument "extra" is supplied, ie ++.B --log-queries=extra ++then the log has extra information at the start of each line. ++This consists of a serial number which ties together the log lines associated with an individual query, and the IP address of the requestor. + .TP + .B -8, --log-facility=<facility> + Set the facility to which dnsmasq will send syslog entries, this +diff --git a/src/cache.c b/src/cache.c +index ff1ca6f1c352..960bb7938778 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -1638,7 +1638,16 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg) + if (strlen(name) == 0) + name = "."; + +- my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest); ++ if (option_bool(OPT_EXTRALOG)) ++ { ++ prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2); ++ if (flags & F_NOEXTRA) ++ my_syslog(LOG_INFO, "* %s %s %s %s %s", daemon->addrbuff2, source, name, verb, dest); ++ else ++ my_syslog(LOG_INFO, "%u %s %s %s %s %s", daemon->log_display_id, daemon->addrbuff2, source, name, verb, dest); ++ } ++ else ++ my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest); + } + + +diff --git a/src/config.h b/src/config.h +index 145820ad2510..3b88d8193dca 100644 +--- a/src/config.h ++++ b/src/config.h +@@ -17,6 +17,7 @@ + #define FTABSIZ 150 /* max number of outstanding requests (default) */ + #define MAX_PROCS 20 /* max no children for TCP requests */ + #define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */ ++#define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */ + #define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */ + #define KEYBLOCK_LEN 40 /* choose to mininise fragmentation when storing DNSSEC keys */ + #define DNSSEC_WORK 50 /* Max number of queries to validate one question */ +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index 5c7750d365fa..c0c0589d4ce1 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -93,6 +93,8 @@ int main (int argc, char **argv) + daemon->packet = safe_malloc(daemon->packet_buff_sz); + + daemon->addrbuff = safe_malloc(ADDRSTRLEN); ++ if (option_bool(OPT_EXTRALOG)) ++ daemon->addrbuff2 = safe_malloc(ADDRSTRLEN); + + #ifdef HAVE_DNSSEC + if (option_bool(OPT_DNSSEC_VALID)) +@@ -1587,6 +1589,9 @@ static void check_dns_listeners(fd_set *set, time_t now) + } + } + close(confd); ++ ++ /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */ ++ daemon->log_id += TCP_MAX_QUERIES; + } + #endif + else +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 2f4597294a56..4e9aea401b75 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -238,7 +238,8 @@ struct event_desc { + #define OPT_DNSSEC_NO_SIGN 48 + #define OPT_LOCAL_SERVICE 49 + #define OPT_LOOP_DETECT 50 +-#define OPT_LAST 51 ++#define OPT_EXTRALOG 51 ++#define OPT_LAST 52 + + /* extra flags for my_syslog, we use a couple of facilities since they are known + not to occupy the same bits as priorities, no matter how syslog.h is set up. */ +@@ -442,6 +443,7 @@ struct crec { + #define F_NO_RR (1u<<25) + #define F_IPSET (1u<<26) + #define F_NSIGMATCH (1u<<27) ++#define F_NOEXTRA (1u<<28) + + /* Values of uid in crecs with F_CONFIG bit set. */ + #define SRC_INTERFACE 0 +@@ -599,7 +601,7 @@ struct frec { + #endif + unsigned int iface; + unsigned short orig_id, new_id; +- int fd, forwardall, flags; ++ int log_id, fd, forwardall, flags; + time_t time; + unsigned char *hash[HASH_SIZE]; + #ifdef HAVE_DNSSEC +@@ -1002,6 +1004,8 @@ extern struct daemon { + struct randfd randomsocks[RANDOM_SOCKS]; + int v6pktinfo; + struct addrlist *interface_addrs; /* list of all addresses/prefix lengths associated with all local interfaces */ ++ int log_id, log_display_id; /* ids of transactions for logging */ ++ union mysockaddr *log_source_addr; + + /* DHCP state */ + int dhcpfd, helperfd, pxefd; +@@ -1033,6 +1037,7 @@ extern struct daemon { + + /* utility string buffer, hold max sized IP address as string */ + char *addrbuff; ++ char *addrbuff2; /* only allocated when OPT_EXTRALOG */ + + } *daemon; + +diff --git a/src/dnssec.c b/src/dnssec.c +index 8f27677628b2..afb3dca38cb1 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -1038,7 +1038,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch + else + { + a.addr.keytag = keytag; +- log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u"); ++ log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u"); + + recp1->addr.key.keylen = rdlen - 4; + recp1->addr.key.keydata = key; +@@ -1092,7 +1092,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch + return STAT_SECURE; + } + +- log_query(F_UPSTREAM, name, NULL, "BOGUS DNSKEY"); ++ log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DNSKEY"); + return STAT_BOGUS; + } + +@@ -1136,7 +1136,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char + + if (val == STAT_BOGUS) + { +- log_query(F_UPSTREAM, name, NULL, "BOGUS DS"); ++ log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS"); + return STAT_BOGUS; + } + +@@ -1201,7 +1201,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char + + cache_end_insert(); + +- log_query(F_UPSTREAM, name, NULL, nons ? "no delegation" : "no DS"); ++ log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no delegation" : "no DS"); + } + + return nons ? STAT_NO_NS : STAT_NO_DS; +@@ -1885,7 +1885,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch + else + { + a.addr.keytag = keytag; +- log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u"); ++ log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u"); + crecp->addr.ds.digest = digest; + crecp->addr.ds.keydata = key; + crecp->addr.ds.algo = algo; +@@ -2058,10 +2058,10 @@ size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, i + char *types = querystr("dnssec-query", type); + + if (addr->sa.sa_family == AF_INET) +- log_query(F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types); ++ log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types); + #ifdef HAVE_IPV6 + else +- log_query(F_DNSSEC | F_IPV6, name, (struct all_addr *)&addr->in6.sin6_addr, types); ++ log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, name, (struct all_addr *)&addr->in6.sin6_addr, types); + #endif + + header->qdcount = htons(1); +diff --git a/src/forward.c b/src/forward.c +index 55f583383bc6..713a64c0fa58 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -279,10 +279,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, + plen = forward->stash_len; + + if (forward->sentto->addr.sa.sa_family == AF_INET) +- log_query(F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec"); ++ log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec"); + #ifdef HAVE_IPV6 + else +- log_query(F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec"); ++ log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec"); + #endif + + if (forward->sentto->sfd) +@@ -389,6 +389,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, + struct server *firstsentto = start; + int forwarded = 0; + ++ /* If a query is retried, use the log_id for the retry when logging the answer. */ ++ forward->log_id = daemon->log_id; ++ + if (option_bool(OPT_ADD_MAC)) + plen = add_mac(header, plen, ((char *) header) + daemon->packet_buff_sz, &forward->source); + +@@ -725,6 +728,11 @@ void reply_query(int fd, int family, time_t now) + if (!(forward = lookup_frec(ntohs(header->id), hash))) + return; + ++ /* log_query gets called indirectly all over the place, so ++ pass these in global variables - sorry. */ ++ daemon->log_display_id = forward->log_id; ++ daemon->log_source_addr = &forward->source; ++ + if (daemon->ignore_addr && RCODE(header) == NOERROR && + check_for_ignored_address(header, n, daemon->ignore_addr)) + return; +@@ -1258,6 +1266,11 @@ void receive_query(struct listener *listen, time_t now) + dst_addr_4.s_addr = 0; + } + } ++ ++ /* log_query gets called indirectly all over the place, so ++ pass these in global variables - sorry. */ ++ daemon->log_display_id = ++daemon->log_id; ++ daemon->log_source_addr = &source_addr; + + if (extract_request(header, (size_t)n, daemon->namebuff, &type)) + { +@@ -1675,7 +1688,8 @@ unsigned char *tcp_request(int confd, time_t now, + struct in_addr dst_addr_4; + union mysockaddr peer_addr; + socklen_t peer_len = sizeof(union mysockaddr); +- ++ int query_count = 0; ++ + if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1) + return packet; + +@@ -1712,7 +1726,8 @@ unsigned char *tcp_request(int confd, time_t now, + + while (1) + { +- if (!packet || ++ if (query_count == TCP_MAX_QUERIES || ++ !packet || + !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) || + !(size = c1 << 8 | c2) || + !read_write(confd, payload, size, 1)) +@@ -1721,6 +1736,13 @@ unsigned char *tcp_request(int confd, time_t now, + if (size < (int)sizeof(struct dns_header)) + continue; + ++ query_count++; ++ ++ /* log_query gets called indirectly all over the place, so ++ pass these in global variables - sorry. */ ++ daemon->log_display_id = ++daemon->log_id; ++ daemon->log_source_addr = &peer_addr; ++ + check_subnet = 0; + + /* save state of "cd" flag in query */ +diff --git a/src/option.c b/src/option.c +index 907d0cf88de9..b7372be0a090 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -149,6 +149,7 @@ struct myoption { + #define LOPT_LOOP_DETECT 337 + #define LOPT_IGNORE_ADDR 338 + ++ + #ifdef HAVE_GETOPT_LONG + static const struct option opts[] = + #else +@@ -160,7 +161,7 @@ static const struct myoption opts[] = + { "no-poll", 0, 0, 'n' }, + { "help", 0, 0, 'w' }, + { "no-daemon", 0, 0, 'd' }, +- { "log-queries", 0, 0, 'q' }, ++ { "log-queries", 2, 0, 'q' }, + { "user", 2, 0, 'u' }, + { "group", 2, 0, 'g' }, + { "resolv-file", 2, 0, 'r' }, +@@ -357,7 +358,7 @@ static struct { + { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL}, + { 'p', ARG_ONE, "<integer>", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL }, + { 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" }, +- { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL }, ++ { 'q', ARG_DUP, NULL, gettext_noop("Log DNS queries."), NULL }, + { 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL }, + { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL }, + { 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE }, +@@ -2421,6 +2422,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + ret_err(gen_err); + break; + ++ case 'q': /* --log-queries */ ++ set_option_bool(OPT_LOG); ++ if (arg && strcmp(arg, "extra") == 0) ++ set_option_bool(OPT_EXTRALOG); ++ break; ++ + case LOPT_MAX_LOGS: /* --log-async */ + daemon->max_logs = LOG_MAX; /* default */ + if (arg && !atoi_check(arg, &daemon->max_logs)) +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0028-Add-min-cache-ttl-option.patch b/src/patches/dnsmasq/0028-Add-min-cache-ttl-option.patch new file mode 100644 index 0000000..e8a61b7 --- /dev/null +++ b/src/patches/dnsmasq/0028-Add-min-cache-ttl-option.patch @@ -0,0 +1,144 @@ +From 28de38768e2c7d763b9aa5b7a4d251d5e56bab0b Mon Sep 17 00:00:00 2001 +From: RinSatsuki aa65535@live.com +Date: Sat, 10 Jan 2015 15:22:21 +0000 +Subject: [PATCH 28/55] Add --min-cache-ttl option. + +--- + CHANGELOG | 7 +++++++ + man/dnsmasq.8 | 6 ++++++ + src/cache.c | 4 +++- + src/config.h | 1 + + src/dnsmasq.h | 2 +- + src/option.c | 11 +++++++++++ + 6 files changed, 29 insertions(+), 2 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 0bbb7835df4f..23fc6d0530cf 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -43,6 +43,13 @@ version 2.73 + Add --log-queries=extra option, which makes logs easier + to search automatically. + ++ Add --min-cache-ttl option. I've resisted this for a long ++ time, on the grounds that disbelieving TTLs is never a ++ good idea, but I've been persuaded that there are ++ sometimes reasons to do it. (Step forward, GFW). ++ To avoid misuse, there's a hard limit on the TTL ++ floor of one hour. Thansk to RinSatsuki for the patch. ++ + + version 2.72 + Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. +diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 +index 227d74bd80e7..5cfa355dea4a 100644 +--- a/man/dnsmasq.8 ++++ b/man/dnsmasq.8 +@@ -81,6 +81,12 @@ the upstream DNS servers. + .B --max-cache-ttl=<time> + Set a maximum TTL value for entries in the cache. + .TP ++.B --min-cache-ttl=<time> ++Extend short TTL values to the time given when caching them. Note that ++artificially extending TTL values is in general a bad idea, do not do it ++unless you have a good reason, and understand what you are doing. ++Dnsmasq limits the value of this option to one hour, unless recompiled. ++.TP + .B --auth-ttl=<time> + Set the TTL value returned in answers from the authoritative server. + .TP +diff --git a/src/cache.c b/src/cache.c +index 960bb7938778..945be071a0b6 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -461,9 +461,11 @@ struct crec *cache_insert(char *name, struct all_addr *addr, + if (flags & (F_IPV4 | F_IPV6 | F_CNAME)) + { + log_query(flags | F_UPSTREAM, name, addr, NULL); +- /* Don;t mess with TTL for DNSSEC records. */ ++ /* Don't mess with TTL for DNSSEC records. */ + if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl) + ttl = daemon->max_cache_ttl; ++ if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl) ++ ttl = daemon->min_cache_ttl; + } + + /* if previous insertion failed give up now. */ +diff --git a/src/config.h b/src/config.h +index 3b88d8193dca..cdca231b4079 100644 +--- a/src/config.h ++++ b/src/config.h +@@ -27,6 +27,7 @@ + #define RANDOM_SOCKS 64 /* max simultaneous random ports */ + #define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */ + #define CACHESIZ 150 /* default cache size */ ++#define TTL_FLOOR_LIMIT 3600 /* don't allow --min-cache-ttl to raise TTL above this under any circumstances */ + #define MAXLEASES 1000 /* maximum number of DHCP leases */ + #define PING_WAIT 3 /* wait for ping address-in-use test */ + #define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */ +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 4e9aea401b75..f8275e3ac479 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -943,7 +943,7 @@ extern struct daemon { + int max_logs; /* queue limit */ + int cachesize, ftabsize; + int port, query_port, min_port; +- unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl, auth_ttl; ++ unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl; + struct hostsfile *addn_hosts; + struct dhcp_context *dhcp, *dhcp6; + struct ra_interface *ra_interfaces; +diff --git a/src/option.c b/src/option.c +index b7372be0a090..8b994098cc9f 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -148,6 +148,7 @@ struct myoption { + #define LOPT_DNSSEC_TIME 336 + #define LOPT_LOOP_DETECT 337 + #define LOPT_IGNORE_ADDR 338 ++#define LOPT_MINCTTL 339 + + + #ifdef HAVE_GETOPT_LONG +@@ -256,6 +257,7 @@ static const struct myoption opts[] = + { "dhcp-broadcast", 2, 0, LOPT_BROADCAST }, + { "neg-ttl", 1, 0, LOPT_NEGTTL }, + { "max-ttl", 1, 0, LOPT_MAXTTL }, ++ { "min-cache-ttl", 1, 0, LOPT_MINCTTL }, + { "max-cache-ttl", 1, 0, LOPT_MAXCTTL }, + { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT }, + { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR }, +@@ -371,6 +373,8 @@ static struct { + { 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL }, + { LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL }, + { LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL }, ++ { LOPT_MAXCTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live ceiling for cache."), NULL }, ++ { LOPT_MINCTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live floor for cache."), NULL }, + { 'u', ARG_ONE, "<username>", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER }, + { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL }, + { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL }, +@@ -2457,6 +2461,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + case 'T': /* --local-ttl */ + case LOPT_NEGTTL: /* --neg-ttl */ + case LOPT_MAXTTL: /* --max-ttl */ ++ case LOPT_MINCTTL: /* --min-cache-ttl */ + case LOPT_MAXCTTL: /* --max-cache-ttl */ + case LOPT_AUTHTTL: /* --auth-ttl */ + { +@@ -2467,6 +2472,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + daemon->neg_ttl = (unsigned long)ttl; + else if (option == LOPT_MAXTTL) + daemon->max_ttl = (unsigned long)ttl; ++ else if (option == LOPT_MINCTTL) ++ { ++ if (ttl > TTL_FLOOR_LIMIT) ++ ttl = TTL_FLOOR_LIMIT; ++ daemon->min_cache_ttl = (unsigned long)ttl; ++ } + else if (option == LOPT_MAXCTTL) + daemon->max_cache_ttl = (unsigned long)ttl; + else if (option == LOPT_AUTHTTL) +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0029-Log-port-of-requestor-when-doing-extra-logging.patch b/src/patches/dnsmasq/0029-Log-port-of-requestor-when-doing-extra-logging.patch new file mode 100644 index 0000000..d3c4847 --- /dev/null +++ b/src/patches/dnsmasq/0029-Log-port-of-requestor-when-doing-extra-logging.patch @@ -0,0 +1,31 @@ +From 9f79ee4ae34886c0319f06d8f162b81ef79d62fb Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Mon, 12 Jan 2015 20:18:18 +0000 +Subject: [PATCH 29/55] Log port of requestor when doing extra logging. + +--- + src/cache.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/cache.c b/src/cache.c +index 945be071a0b6..09b6dbf8087a 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -1642,11 +1642,11 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg) + + if (option_bool(OPT_EXTRALOG)) + { +- prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2); ++ int port = prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2); + if (flags & F_NOEXTRA) +- my_syslog(LOG_INFO, "* %s %s %s %s %s", daemon->addrbuff2, source, name, verb, dest); ++ my_syslog(LOG_INFO, "* %s/%u %s %s %s %s", daemon->addrbuff2, port, source, name, verb, dest); + else +- my_syslog(LOG_INFO, "%u %s %s %s %s %s", daemon->log_display_id, daemon->addrbuff2, source, name, verb, dest); ++ my_syslog(LOG_INFO, "%u %s/%u %s %s %s %s", daemon->log_display_id, daemon->addrbuff2, port, source, name, verb, dest); + } + else + my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest); +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0030-Don-t-answer-from-cache-RRsets-from-wildcards-as-we-.patch b/src/patches/dnsmasq/0030-Don-t-answer-from-cache-RRsets-from-wildcards-as-we-.patch new file mode 100644 index 0000000..5f489e2 --- /dev/null +++ b/src/patches/dnsmasq/0030-Don-t-answer-from-cache-RRsets-from-wildcards-as-we-.patch @@ -0,0 +1,45 @@ +From 5e321739db381a1d7b5964d76e9c81471d2564c9 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Mon, 12 Jan 2015 23:16:56 +0000 +Subject: [PATCH 30/55] Don't answer from cache RRsets from wildcards, as we + don't have NSECs. + +--- + src/dnssec.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/src/dnssec.c b/src/dnssec.c +index afb3dca38cb1..d39ab85ed966 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -1818,11 +1818,14 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch + struct blockdata *key; + struct crec *crecp; + char *wildname; ++ int have_wildcard = 0; + + rc = validate_rrset(now, header, plen, class1, type1, name, keyname, &wildname, NULL, 0, 0, 0); + + if (rc == STAT_SECURE_WILDCARD) + { ++ have_wildcard = 1; ++ + /* An attacker replay a wildcard answer with a different + answer and overlay a genuine RR. To prove this + hasn't happened, the answer must prove that +@@ -1913,7 +1916,11 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch + p2 += 13; /* labels, orig_ttl, expiration, inception */ + GETSHORT(keytag, p2); + +- if ((key = blockdata_alloc((char*)psave, rdlen2))) ++ /* We don't cache sigs for wildcard answers, because to reproduce the ++ answer from the cache will require one or more NSEC/NSEC3 records ++ which we don't cache. The lack of the RRSIG ensures that a query for ++ this RRset asking for a secure answer will always be forwarded. */ ++ if (!have_wildcard && (key = blockdata_alloc((char*)psave, rdlen2))) + { + if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DS))) + blockdata_free(key); +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0031-Logs-for-DS-records-consistent.patch b/src/patches/dnsmasq/0031-Logs-for-DS-records-consistent.patch new file mode 100644 index 0000000..1a2d3e4 --- /dev/null +++ b/src/patches/dnsmasq/0031-Logs-for-DS-records-consistent.patch @@ -0,0 +1,25 @@ +From ae4624bf46b5e37ff1a9a2ba3c927e0dede95adb Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Mon, 12 Jan 2015 23:22:08 +0000 +Subject: [PATCH 31/55] Logs for DS records consistent. + +--- + src/rfc1035.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/rfc1035.c b/src/rfc1035.c +index 75c4266b47dd..262274fc5b80 100644 +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -1643,7 +1643,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + { + if (crecp->flags & F_NXDOMAIN) + nxdomain = 1; +- log_query(F_UPSTREAM, name, NULL, "secure no DS"); ++ log_query(F_UPSTREAM, name, NULL, "no DS"); + } + else if ((keydata = blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, NULL))) + { +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0032-Cope-with-multiple-interfaces-with-the-same-LL-addre.patch b/src/patches/dnsmasq/0032-Cope-with-multiple-interfaces-with-the-same-LL-addre.patch new file mode 100644 index 0000000..81b02cc --- /dev/null +++ b/src/patches/dnsmasq/0032-Cope-with-multiple-interfaces-with-the-same-LL-addre.patch @@ -0,0 +1,57 @@ +From 393415597c8b5b09558b789ab9ac238dbe3db65d Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sun, 18 Jan 2015 22:11:10 +0000 +Subject: [PATCH 32/55] Cope with multiple interfaces with the same LL address. + +--- + CHANGELOG | 4 ++++ + src/auth.c | 5 ++++- + src/util.c | 1 + + 3 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 23fc6d0530cf..bbd7e6619689 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -49,6 +49,10 @@ version 2.73 + sometimes reasons to do it. (Step forward, GFW). + To avoid misuse, there's a hard limit on the TTL + floor of one hour. Thansk to RinSatsuki for the patch. ++ ++ Cope with multiple interfaces with the same link-local ++ address. (IPv6 addresses are scoped, so this is allowed.) ++ Thanks to Cory Benfield for help with this. + + + version 2.72 +diff --git a/src/auth.c b/src/auth.c +index a327f16d8c0b..59e05d3da38e 100644 +--- a/src/auth.c ++++ b/src/auth.c +@@ -413,7 +413,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n + peer_addr->in.sin_port = 0; + #ifdef HAVE_IPV6 + else +- peer_addr->in6.sin6_port = 0; ++ { ++ peer_addr->in6.sin6_port = 0; ++ peer_addr->in6.sin6_scope_id = 0; ++ } + #endif + + for (peers = daemon->auth_peers; peers; peers = peers->next) +diff --git a/src/util.c b/src/util.c +index a729f339e219..d532444da207 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -274,6 +274,7 @@ int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2) + #ifdef HAVE_IPV6 + if (s1->sa.sa_family == AF_INET6 && + s1->in6.sin6_port == s2->in6.sin6_port && ++ s1->in6.sin6_scope_id == s2->in6.sin6_scope_id && + IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr)) + return 1; + #endif +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0033-Don-t-treat-SERVFAIL-as-a-recoverable-error.patch b/src/patches/dnsmasq/0033-Don-t-treat-SERVFAIL-as-a-recoverable-error.patch new file mode 100644 index 0000000..e88a94b --- /dev/null +++ b/src/patches/dnsmasq/0033-Don-t-treat-SERVFAIL-as-a-recoverable-error.patch @@ -0,0 +1,25 @@ +From 2ae195f5a71f7c5a75717845de1bd72fc7dd67f3 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sun, 18 Jan 2015 22:20:48 +0000 +Subject: [PATCH 33/55] Don't treat SERVFAIL as a recoverable error..... + +--- + src/forward.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/forward.c b/src/forward.c +index 713a64c0fa58..b17bc34f865f 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -737,7 +737,7 @@ void reply_query(int fd, int family, time_t now) + check_for_ignored_address(header, n, daemon->ignore_addr)) + return; + +- if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) && ++ if (RCODE(header) == REFUSED && + !option_bool(OPT_ORDER) && + forward->forwardall == 0) + /* for broken servers, attempt to send to another one. */ +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0034-Add-dhcp-hostsdir-config-option.patch b/src/patches/dnsmasq/0034-Add-dhcp-hostsdir-config-option.patch new file mode 100644 index 0000000..c6b6703 --- /dev/null +++ b/src/patches/dnsmasq/0034-Add-dhcp-hostsdir-config-option.patch @@ -0,0 +1,419 @@ +From 5f4dc5c6ca50655ab14f572c7e30815ed74cd51a Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Tue, 20 Jan 2015 20:51:02 +0000 +Subject: [PATCH 34/55] Add --dhcp-hostsdir config option. + +--- + CHANGELOG | 5 +++ + man/dnsmasq.8 | 9 +++++ + src/dnsmasq.c | 28 ++++++++++---- + src/dnsmasq.h | 15 ++++++-- + src/inotify.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- + src/option.c | 22 +++++++++-- + 6 files changed, 177 insertions(+), 21 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index bbd7e6619689..0076b557e95e 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -53,6 +53,11 @@ version 2.73 + Cope with multiple interfaces with the same link-local + address. (IPv6 addresses are scoped, so this is allowed.) + Thanks to Cory Benfield for help with this. ++ ++ Add --dhcp-hostsdir. This allows addition of new host ++ configurations to a running dnsmasq instance much more ++ cheaply than having dnsmasq re-read all its existing ++ configuration each time. + + + version 2.72 +diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 +index 5cfa355dea4a..005b5cca8d1f 100644 +--- a/man/dnsmasq.8 ++++ b/man/dnsmasq.8 +@@ -977,6 +977,15 @@ is given, then read all the files contained in that directory. The advantage of + using this option is the same as for --dhcp-hostsfile: the + dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that + it is possible to encode the information in a ++.TP ++.B --dhcp-hostsdir=<path> ++This is exactly equivalent to dhcp-hostfile, except for the following. The path MUST be a ++directory, and not an individual file. Changed or new files within ++the directory are read automatically, without the need to send SIGHUP. ++If a file is deleted for changed after it has been read by dnsmasq, then the ++host record it contained will remain until dnsmasq recieves a SIGHUP, or ++is restarted; ie host records are only added dynamically. ++.TP + .B --dhcp-boot + flag as DHCP options, using the options names bootfile-name, + server-ip-address and tftp-server. This allows these to be included +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index c0c0589d4ce1..04cc98278f62 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -142,6 +142,9 @@ int main (int argc, char **argv) + set_option_bool(OPT_NOWILD); + reset_option_bool(OPT_CLEVERBIND); + } ++ ++ if (daemon->inotify_hosts) ++ die(_("dhcp-hostsdir not supported on this platform"), NULL, EC_BADCONF); + #endif + + if (option_bool(OPT_DNSSEC_VALID)) +@@ -316,13 +319,16 @@ int main (int argc, char **argv) + #ifdef HAVE_DNSSEC + blockdata_init(); + #endif ++ } + + #ifdef HAVE_LINUX_NETWORK +- if (!option_bool(OPT_NO_POLL)) +- inotify_dnsmasq_init(); ++ if ((!option_bool(OPT_NO_POLL) && daemon->port != 0) || ++ daemon->dhcp || daemon->doing_dhcp6) ++ inotify_dnsmasq_init(); ++ else ++ daemon->inotifyfd = -1; + #endif +- } +- ++ + if (option_bool(OPT_DBUS)) + #ifdef HAVE_DBUS + { +@@ -745,7 +751,7 @@ int main (int argc, char **argv) + #endif + + #ifdef HAVE_TFTP +- if (option_bool(OPT_TFTP)) ++ if (option_bool(OPT_TFTP)) + { + #ifdef FD_SETSIZE + if (FD_SETSIZE < (unsigned)max_fd) +@@ -870,7 +876,7 @@ int main (int argc, char **argv) + #if defined(HAVE_LINUX_NETWORK) + FD_SET(daemon->netlinkfd, &rset); + bump_maxfd(daemon->netlinkfd, &maxfd); +- if (daemon->port != 0 && !option_bool(OPT_NO_POLL)) ++ if (daemon->inotifyfd != -1) + { + FD_SET(daemon->inotifyfd, &rset); + bump_maxfd(daemon->inotifyfd, &maxfd); +@@ -943,8 +949,11 @@ int main (int argc, char **argv) + #endif + + #ifdef HAVE_LINUX_NETWORK +- if (daemon->port != 0 && !option_bool(OPT_NO_POLL) && FD_ISSET(daemon->inotifyfd, &rset) && inotify_check()) +- poll_resolv(1, 1, now); ++ if (daemon->inotifyfd != -1 && FD_ISSET(daemon->inotifyfd, &rset) && inotify_check(now)) ++ { ++ if (daemon->port != 0 && !option_bool(OPT_NO_POLL)) ++ poll_resolv(1, 1, now); ++ } + #else + /* Check for changes to resolv files once per second max. */ + /* Don't go silent for long periods if the clock goes backwards. */ +@@ -1385,6 +1394,9 @@ void clear_cache_and_reload(time_t now) + if (option_bool(OPT_ETHERS)) + dhcp_read_ethers(); + reread_dhcp(); ++#ifdef HAVE_LINUX_NETWORK ++ set_dhcp_inotify(); ++#endif + dhcp_update_configs(daemon->dhcp_conf); + lease_update_from_configs(); + lease_update_file(now); +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index f8275e3ac479..d841fdc064ad 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -550,13 +550,17 @@ struct resolvc { + #endif + }; + +-/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile */ ++/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile and dhcp-hostsdir*/ + #define AH_DIR 1 + #define AH_INACTIVE 2 ++#define AH_WD_DONE 4 + struct hostsfile { + struct hostsfile *next; + int flags; + char *fname; ++#ifdef HAVE_LINUX_NETWORK ++ int wd; /* inotify watch descriptor */ ++#endif + unsigned int index; /* matches to cache entries for logging */ + }; + +@@ -961,7 +965,7 @@ extern struct daemon { + int doing_ra, doing_dhcp6; + struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names; + struct dhcp_netid_list *force_broadcast, *bootp_dynamic; +- struct hostsfile *dhcp_hosts_file, *dhcp_opts_file; ++ struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *inotify_hosts; + int dhcp_max, tftp_max; + int dhcp_server_port, dhcp_client_port; + int start_tftp_port, end_tftp_port; +@@ -1197,7 +1201,7 @@ void reset_option_bool(unsigned int opt); + struct hostsfile *expand_filelist(struct hostsfile *list); + char *parse_server(char *arg, union mysockaddr *addr, + union mysockaddr *source_addr, char *interface, int *flags); +- ++int option_read_hostsfile(char *file); + /* forward.c */ + void reply_query(int fd, int family, time_t now); + void receive_query(struct listener *listen, time_t now); +@@ -1486,5 +1490,8 @@ int detect_loop(char *query, int type); + /* inotify.c */ + #ifdef HAVE_LINUX_NETWORK + void inotify_dnsmasq_init(); +-int inotify_check(void); ++int inotify_check(time_t now); ++# ifdef HAVE_DHCP ++void set_dhcp_inotify(void); ++# endif + #endif +diff --git a/src/inotify.c b/src/inotify.c +index 83730008c11b..52a30d7f44db 100644 +--- a/src/inotify.c ++++ b/src/inotify.c +@@ -19,6 +19,11 @@ + + #include <sys/inotify.h> + ++#ifdef HAVE_DHCP ++static void check_for_dhcp_inotify(struct inotify_event *in, time_t now); ++#endif ++ ++ + /* the strategy is to set a inotify on the directories containing + resolv files, for any files in the directory which are close-write + or moved into the directory. +@@ -40,8 +45,6 @@ void inotify_dnsmasq_init() + struct resolvc *res; + + inotify_buffer = safe_malloc(INOTIFY_SZ); +- +- + daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); + + if (daemon->inotifyfd == -1) +@@ -66,6 +69,7 @@ void inotify_dnsmasq_init() + { + *d = 0; /* make path just directory */ + res->wd = inotify_add_watch(daemon->inotifyfd, path, IN_CLOSE_WRITE | IN_MOVED_TO); ++ + res->file = d+1; /* pointer to filename */ + *d = '/'; + +@@ -78,7 +82,7 @@ void inotify_dnsmasq_init() + } + } + +-int inotify_check(void) ++int inotify_check(time_t now) + { + int hit = 0; + +@@ -101,13 +105,116 @@ int inotify_check(void) + for (res = daemon->resolv_files; res; res = res->next) + if (res->wd == in->wd && in->len != 0 && strcmp(res->file, in->name) == 0) + hit = 1; ++ ++#ifdef HAVE_DHCP ++ if (daemon->dhcp || daemon->doing_dhcp6) ++ check_for_dhcp_inotify(in, now); ++#endif + } + } +- + return hit; + } + +-#endif ++#ifdef HAVE_DHCP ++/* initialisation for dhcp-hostdir. Set inotify watch for each directory, and read pre-existing files */ ++void set_dhcp_inotify(void) ++{ ++ struct hostsfile *ah; + +- ++ for (ah = daemon->inotify_hosts; ah; ah = ah->next) ++ { ++ DIR *dir_stream = NULL; ++ struct dirent *ent; ++ struct stat buf; ++ ++ if (stat(ah->fname, &buf) == -1 || !(S_ISDIR(buf.st_mode))) ++ { ++ my_syslog(LOG_ERR, _("bad directory in dhcp-hostsdir %s"), ah->fname); ++ continue; ++ } ++ ++ if (!(ah->flags & AH_WD_DONE)) ++ { ++ ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO); ++ ah->flags |= AH_WD_DONE; ++ } ++ /* Read contents of dir _after_ calling add_watch, in the ho[e of avoiding ++ a race which misses files being added as we start */ ++ if (ah->wd == -1 || !(dir_stream = opendir(ah->fname))) ++ { ++ my_syslog(LOG_ERR, _("failed to create inotify for %s"), ah->fname); ++ continue; ++ } ++ ++ while ((ent = readdir(dir_stream))) ++ { ++ size_t lendir = strlen(ah->fname); ++ size_t lenfile = strlen(ent->d_name); ++ char *path; ++ ++ /* ignore emacs backups and dotfiles */ ++ if (lenfile == 0 || ++ ent->d_name[lenfile - 1] == '~' || ++ (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') || ++ ent->d_name[0] == '.') ++ continue; ++ ++ if ((path = whine_malloc(lendir + lenfile + 2))) ++ { ++ strcpy(path, ah->fname); ++ strcat(path, "/"); ++ strcat(path, ent->d_name); ++ ++ /* ignore non-regular files */ ++ if (stat(path, &buf) != -1 && S_ISREG(buf.st_mode)) ++ option_read_hostsfile(path); ++ ++ free(path); ++ } ++ } ++ } ++} ++ ++static void check_for_dhcp_inotify(struct inotify_event *in, time_t now) ++{ ++ struct hostsfile *ah; ++ ++ /* ignore emacs backups and dotfiles */ ++ if (in->len == 0 || ++ in->name[in->len - 1] == '~' || ++ (in->name[0] == '#' && in->name[in->len - 1] == '#') || ++ in->name[0] == '.') ++ return; ++ ++ for (ah = daemon->inotify_hosts; ah; ah = ah->next) ++ if (ah->wd == in->wd) ++ { ++ size_t lendir = strlen(ah->fname); ++ char *path; ++ ++ if ((path = whine_malloc(lendir + in->len + 2))) ++ { ++ strcpy(path, ah->fname); ++ strcat(path, "/"); ++ strcat(path, in->name); ++ ++ if (option_read_hostsfile(path)) ++ { ++ /* Propogate the consequences of loading a new dhcp-host */ ++ dhcp_update_configs(daemon->dhcp_conf); ++ lease_update_from_configs(); ++ lease_update_file(now); ++ lease_update_dns(1); ++ } ++ ++ free(path); ++ } ++ ++ return; ++ } ++} ++ ++#endif /* DHCP */ ++ ++#endif /* LINUX_NETWORK */ + +diff --git a/src/option.c b/src/option.c +index 8b994098cc9f..22e11c37d374 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -149,7 +149,7 @@ struct myoption { + #define LOPT_LOOP_DETECT 337 + #define LOPT_IGNORE_ADDR 338 + #define LOPT_MINCTTL 339 +- ++#define LOPT_DHCP_INOTIFY 340 + + #ifdef HAVE_GETOPT_LONG + static const struct option opts[] = +@@ -248,6 +248,7 @@ static const struct myoption opts[] = + { "interface-name", 1, 0, LOPT_INTNAME }, + { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST }, + { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS }, ++ { "dhcp-hostsdir", 1, 0, LOPT_DHCP_INOTIFY }, + { "dhcp-no-override", 0, 0, LOPT_OVERRIDE }, + { "tftp-port-range", 1, 0, LOPT_TFTPPORTS }, + { "stop-dns-rebind", 0, 0, LOPT_REBIND }, +@@ -336,6 +337,7 @@ static struct { + { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL }, + { LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL }, + { LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL }, ++ { LOPT_DHCP_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from a directory."), NULL }, + { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL }, + { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE }, + { 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE }, +@@ -1710,8 +1712,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + break; + #endif /* HAVE_DHCP */ + +- case LOPT_DHCP_HOST: /* --dhcp-hostfile */ ++ case LOPT_DHCP_HOST: /* --dhcp-hostsfile */ + case LOPT_DHCP_OPTS: /* --dhcp-optsfile */ ++ case LOPT_DHCP_INOTIFY: /* dhcp-hostsdir */ + case 'H': /* --addn-hosts */ + { + struct hostsfile *new = opt_malloc(sizeof(struct hostsfile)); +@@ -1734,6 +1737,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + new->next = daemon->dhcp_opts_file; + daemon->dhcp_opts_file = new; + } ++ else if (option == LOPT_DHCP_INOTIFY) ++ { ++ new->next = daemon->inotify_hosts; ++ daemon->inotify_hosts = new; ++ } ++ + break; + } + +@@ -4042,6 +4051,13 @@ static void read_file(char *file, FILE *f, int hard_opt) + fclose(f); + } + ++#ifdef HAVE_DHCP ++int option_read_hostsfile(char *file) ++{ ++ return one_file(file, LOPT_BANK); ++} ++#endif ++ + static int one_file(char *file, int hard_opt) + { + FILE *f; +@@ -4139,7 +4155,7 @@ struct hostsfile *expand_filelist(struct hostsfile *list) + + /* don't read this as a file */ + ah->flags |= AH_INACTIVE; +- ++ + if (!(dir_stream = opendir(ah->fname))) + my_syslog(LOG_ERR, _("cannot access directory %s: %s"), + ah->fname, strerror(errno)); +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0035-Update-German-translation.patch b/src/patches/dnsmasq/0035-Update-German-translation.patch new file mode 100644 index 0000000..af45a1c --- /dev/null +++ b/src/patches/dnsmasq/0035-Update-German-translation.patch @@ -0,0 +1,327 @@ +From fbf01f7046e75f9aa73fd4aab2a94e43386d9052 Mon Sep 17 00:00:00 2001 +From: Conrad Kostecki ck@conrad-kostecki.de +Date: Tue, 20 Jan 2015 21:07:56 +0000 +Subject: [PATCH 35/55] Update German translation. + +--- + po/de.po | 101 +++++++++++++++++++++++++++++---------------------------------- + 1 file changed, 47 insertions(+), 54 deletions(-) + +diff --git a/po/de.po b/po/de.po +index e2317376d8a9..4c93c5b28ef2 100644 +--- a/po/de.po ++++ b/po/de.po +@@ -9,10 +9,10 @@ + # Simon Kelley simon@thekelleys.org.uk, 2005. + msgid "" + msgstr "" +-"Project-Id-Version: dnsmasq 2.70\n" ++"Project-Id-Version: dnsmasq 2.73\n" + "Report-Msgid-Bugs-To: \n" + "POT-Creation-Date: 2009-06-18 12:24+0100\n" +-"PO-Revision-Date: 2014-05-01 22:51+0100\n" ++"PO-Revision-Date: 2015-01-19 15:43+0100\n" + "Last-Translator: Conrad Kostecki ck@conrad-kostecki.de\n" + "Language-Team: German de@li.org\n" + "Language: de\n" +@@ -20,12 +20,12 @@ msgstr "" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" +-"X-Generator: Poedit 1.6.5\n" ++"X-Generator: Poedit 1.7.3\n" + "X-Poedit-SourceCharset: UTF-8\n" + + #: cache.c:505 + msgid "Internal error in cache." +-msgstr "" ++msgstr "Interner Fehler im Cache." + + #: cache.c:908 + #, c-format +@@ -126,7 +126,7 @@ msgstr "Lokale abzuhörende Adresse(n) angeben." + + #: option.c:319 + msgid "Return ipaddr for all hosts in specified domains." +-msgstr "IP-Adresse für alle Hosts in angebenen Domänen festlegen." ++msgstr "IP-Adresse für alle Hosts in angegebenen Domänen festlegen." + + # FIXME: the English test is not to the point. Just use a shortened description + # from the manpage instead. -- MA +@@ -310,18 +310,16 @@ msgid "Specify path to resolv.conf (defaults to %s)." + msgstr "Pfad zu resolv.conf festlegen (%s voreingestellt)." + + #: option.c:362 +-#, fuzzy + msgid "Specify path to file with server= options" +-msgstr "Dateipfad für Prozesskennung (PID) festlegen (Voreinstellung: %s)." ++msgstr " Dateipfad mit der Option server= angeben" + + #: option.c:363 + msgid "Specify address(es) of upstream servers with optional domains." + msgstr "Adresse(n) vorgelagerter Server festlegen, optional mit Domänen." + + #: option.c:364 +-#, fuzzy + msgid "Specify address of upstream servers for reverse address queries" +-msgstr "Adresse(n) vorgelagerter Server festlegen, optional mit Domänen." ++msgstr "Adresse(n) vorgelagerter Server festlegen, für reverse Adressanfragen" + + #: option.c:365 + msgid "Never forward queries to specified domains." +@@ -657,23 +655,23 @@ msgstr "Spezifiziere eine Domain und Adressbereich für synthetisierte Namen" + + #: option.c:446 + msgid "Activate DNSSEC validation" +-msgstr "" ++msgstr "Aktiviere DNSSEC-Validierung" + + #: option.c:447 + msgid "Specify trust anchor key digest." +-msgstr "" ++msgstr "Spezifiziere Vertrauensursprung (Trust Anchor) der Schlüssel-Prüfdaten (Key Digest)." + + #: option.c:448 + msgid "Disable upstream checking for DNSSEC debugging." +-msgstr "" ++msgstr "Deaktiviere die Überprüfung vorgelagerter Server für DNSSEC-Debugging" + + #: option.c:449 + msgid "Ensure answers without DNSSEC are in unsigned zones." +-msgstr "" ++msgstr "Stellt sicher, dass Antworten ohne DNSSEC sich in einer unsignierten Zone befinden." + + #: option.c:450 + msgid "Don't check DNSSEC signature timestamps until first cache-reload" +-msgstr "" ++msgstr "DNSSEC Signatur-Zeitstempel nicht prüfen, bis erstmalig der Cache neugeladen wird" + + #: option.c:452 + msgid "Specify DHCPv6 prefix class" +@@ -697,11 +695,11 @@ msgstr "RA nicht protokollieren." + + #: option.c:458 + msgid "Accept queries only from directly-connected networks" +-msgstr "" ++msgstr "Akzeptiere nur Anfragen von direkt verbundenen Netzwerken" + + #: option.c:459 + msgid "Detect and remove DNS forwarding loops" +-msgstr "" ++msgstr "Erkennen und Entfernen von DNS-Weiterleitungsschleifen" + + #: option.c:661 + #, c-format +@@ -958,18 +956,16 @@ msgid "Bad name in host-record" + msgstr "Unzulässiger Name in host-record" + + #: option.c:3826 +-#, fuzzy + msgid "bad trust anchor" +-msgstr "unzulässiger Portbereich" ++msgstr "unzulässiger Vertrauensursprung (Trust Anchor)" + + #: option.c:3840 + msgid "bad HEX in trust anchor" +-msgstr "" ++msgstr "unzulässiger Hexwert in Vertrauensursprung (Trust Anchor)" + + #: option.c:3850 +-#, fuzzy + msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)" +-msgstr "unzulässige Option (prüfen Sie, ob dnsmasq mit DHCP/TFTP/DBus-Unterstützt übersetzt wurde)" ++msgstr "Nicht unterstützte Option (prüfen Sie, ob DNSMasq mit DHCP/TFTP/DNSSEC/DBus-Unterstützung übersetzt wurde)" + + #: option.c:3909 + msgid "missing "" +@@ -988,7 +984,6 @@ msgid "missing parameter" + msgstr "fehler Parameter" + + #: option.c:3972 +-#, fuzzy + msgid "illegal option" + msgstr "unzulässige Option" + +@@ -1110,7 +1105,7 @@ msgstr "möglichen DNS-Rebind-Angriff entdeckt: %s" + + #: forward.c:1132 forward.c:1663 + msgid "Ignoring query from non-local network" +-msgstr "" ++msgstr "Ignoriere Anfragen vom nicht lokalen Netzwerk" + + #: forward.c:2101 + #, c-format +@@ -1189,9 +1184,9 @@ msgid "using nameserver %s#%d for %s %s" + msgstr "Benutze Namensserver %s#%d für %s %s" + + #: network.c:1483 +-#, fuzzy, c-format ++#, c-format + msgid "NOT using nameserver %s#%d - query loop detected" +-msgstr "Benutze Namensserver %s#%d für %s %s" ++msgstr "Benutze Namensserver %s#%d NICHT - Anfragenschleife festgetellt" + + #: network.c:1486 + #, c-format +@@ -1205,16 +1200,15 @@ msgstr "Benutze Namensserver %s#%d" + + #: dnsmasq.c:154 + msgid "No trust anchors provided for DNSSEC" +-msgstr "" ++msgstr "Keine Vertrauensursprünge (Trust Anchor) für DNSSEC verfügbar" + + #: dnsmasq.c:157 + msgid "Cannot reduce cache size from default when DNSSEC enabled" +-msgstr "" ++msgstr "Kann die Standard Cachegröße nicht verkleinern, wenn DNSSEC aktiviert ist" + + #: dnsmasq.c:159 +-#, fuzzy + msgid "DNSSEC not available: set HAVE_DNSSEC in src/config.h" +-msgstr "DBus nicht verfügbar: setzen Sie HAVE_DBUS in src/config.h" ++msgstr "DNSSEC nicht verfügbar: setzen Sie HAVE_DNSSEC in src/config.h" + + #: dnsmasq.c:165 + msgid "TFTP server not available: set HAVE_TFTP in src/config.h" +@@ -1241,9 +1235,8 @@ msgid "authoritative DNS not available: set HAVE_AUTH in src/config.h" + msgstr "Authoritatives DNS nicht verfügbar: Es muss HAVE_AUTH in src/config.h gesetzt sein" + + #: dnsmasq.c:193 +-#, fuzzy + msgid "Loop detection not available: set HAVE_LOOP in src/config.h" +-msgstr "TFTP-Server nicht verfügbar, setzen Sie HAVE_TFTP in src/config.h" ++msgstr "Loop-Erkennung nicht verfügbar, setzen Sie HAVE_LOOP in src/config.h" + + #: dnsmasq.c:201 + msgid "zone serial must be configured in --auth-soa" +@@ -1317,15 +1310,15 @@ msgstr "DBus-Unterstützung eingeschaltet: warte auf Systembus-Verbindung" + + #: dnsmasq.c:672 + msgid "DNS service limited to local subnets" +-msgstr "" ++msgstr "DNS-Dienst auf lokale Subnetze eingeschränkt" + + #: dnsmasq.c:677 + msgid "DNSSEC validation enabled" +-msgstr "" ++msgstr "DNSSEC-Validierung aktiviert" + + #: dnsmasq.c:679 + msgid "DNSSEC signature timestamps not checked until first cache reload" +-msgstr "" ++msgstr "DNSSEC Signatur-Zeitstempel werden erst ab dem ersten Neuladen des Caches überprüft" + + #: dnsmasq.c:684 + #, c-format +@@ -1366,7 +1359,7 @@ msgstr "DHCP, Sockets exklusiv an das Interface %s gebunden" + # FIXME: this and the next few must be full strings to be translatable - do not assemble in code" + #: dnsmasq.c:753 + msgid "root is " +-msgstr "Wurzel ist" ++msgstr "Wurzel ist " + + #: dnsmasq.c:753 + msgid "enabled" +@@ -1432,7 +1425,7 @@ msgstr "Das TFTP-Verzeichnis %s ist nicht zugreifbar: %s" + + #: dnsmasq.c:1151 + msgid "now checking DNSSEC signature timestamps" +-msgstr "" ++msgstr "Prüfe jetzt DNSSEC Signatur-Zeitstempel" + + #: dnsmasq.c:1218 + #, c-format +@@ -1506,7 +1499,7 @@ msgstr "DHCP-Paket ohne Adresse an Schnittstelle %s empfangen" + #: dhcp.c:408 + #, c-format + msgid "ARP-cache injection failed: %s" +-msgstr "" ++msgstr "APR-Cache Injektion fehlgeschlagen: %s" + + #: dhcp.c:506 + #, c-format +@@ -1763,13 +1756,13 @@ msgid "DHCP request for unsupported hardware type (%d) received on %s" + msgstr "DHCP-Anfrage für nicht unterstützen Hardwaretyp (%d) auf %s empfangen" + + #: bpf.c:376 +-#, fuzzy, c-format ++#, c-format + msgid "cannot create PF_ROUTE socket: %s" +-msgstr "kann DHCP-Socket nicht erzeugen: %s" ++msgstr "Kann PF_ROUTE socket nicht erzeugen: %s" + + #: bpf.c:397 + msgid "Unknown protocol version from route socket" +-msgstr "" ++msgstr "Unbekannte Protokollversion vom Route Socket" + + #: helper.c:153 + msgid "lease() function missing in Lua script" +@@ -2020,50 +2013,50 @@ msgstr "konnte IPset-Kontroll-Socket nicht erzeugen: %s" + #: blockdata.c:58 + #, c-format + msgid "DNSSEC memory in use %u, max %u, allocated %u" +-msgstr "" ++msgstr "DNSSEC Speicher in Benutzung %u, Max %u, zugewiesen %u" + + #: tables.c:76 + msgid "error: fill_addr missused" +-msgstr "" ++msgstr "Fehler: fill_addr falsch verwendet" + + #: tables.c:105 +-#, fuzzy, c-format ++#, c-format + msgid "failed to access pf devices: %s" +-msgstr "konnte auf %s nicht zugreifen: %s" ++msgstr "konnte auf pf Geräte nicht zugreifen: %s" + + #: tables.c:119 +-#, fuzzy, c-format ++#, c-format + msgid "warning: no opened pf devices %s" +-msgstr "Warnung: Keine Adresse für die Schnittstelle %s gefunden" ++msgstr "Warnung: Keine geöffneten pf Geräte %s" + + #: tables.c:127 +-#, fuzzy, c-format ++#, c-format + msgid "error: cannot use table name %s" +-msgstr "kann Hostnamen nicht ermitteln: %s" ++msgstr "Fehler: Kann Tabellenname %s nicht benutzen" + + #: tables.c:135 + #, c-format + msgid "error: cannot strlcpy table name %s" +-msgstr "" ++msgstr "Fehler: Kann den Tabellennamen %s nicht strlcpy" + + #: tables.c:141 + #, c-format + msgid "warning: pfr_add_tables: %s(%d)" +-msgstr "" ++msgstr "Warnung: pfr_add_tables: %s(%d)" + + #: tables.c:147 + msgid "info: table created" +-msgstr "" ++msgstr "Info: Tabelle erstellt" + + #: tables.c:158 + #, c-format + msgid "warning: DIOCR%sADDRS: %s" +-msgstr "" ++msgstr "Warnung: DIOCR%sADDRS: %s" + + #: tables.c:162 +-#, fuzzy, c-format ++#, c-format + msgid "%d addresses %s" +-msgstr "Fehlerhafte Adresse" ++msgstr "%d Adressen %s" + + #~ msgid "no interface with address %s" + #~ msgstr "keine Schnittstelle mit Adresse %s" +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0036-Don-t-reply-to-DHCPv6-SOLICIT-messages-when-not-conf.patch b/src/patches/dnsmasq/0036-Don-t-reply-to-DHCPv6-SOLICIT-messages-when-not-conf.patch new file mode 100644 index 0000000..25007de --- /dev/null +++ b/src/patches/dnsmasq/0036-Don-t-reply-to-DHCPv6-SOLICIT-messages-when-not-conf.patch @@ -0,0 +1,53 @@ +From 61b838dd574c51d96fef100285a0d225824534f9 Mon Sep 17 00:00:00 2001 +From: Win King Wan pinwing+dnsmasq@gmail.com +Date: Wed, 21 Jan 2015 20:41:48 +0000 +Subject: [PATCH 36/55] Don't reply to DHCPv6 SOLICIT messages when not + configured for statefull DHCPv6. + +--- + CHANGELOG | 4 ++++ + src/rfc3315.c | 13 +++++++++++++ + 2 files changed, 17 insertions(+) + +diff --git a/CHANGELOG b/CHANGELOG +index 0076b557e95e..a4cb901e83ae 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -59,6 +59,10 @@ version 2.73 + cheaply than having dnsmasq re-read all its existing + configuration each time. + ++ Don't reply to DHCPv6 SOLICIT messages if we're not ++ configured to do stateful DHCPv6. Thanks to Win King Wan ++ for the patch. ++ + + version 2.72 + Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. +diff --git a/src/rfc3315.c b/src/rfc3315.c +index ddb390bf1136..e593ec9c362c 100644 +--- a/src/rfc3315.c ++++ b/src/rfc3315.c +@@ -824,6 +824,19 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + } + else + { ++ /* Windows 8 always requests an address even if the Managed bit ++ in RA is 0 and it keeps retrying if it receives a reply ++ stating that no addresses are available. We solve this ++ by not replying at all if we're not configured to give any ++ addresses by DHCPv6. RFC 3315 17.2.1. appears to allow this. */ ++ ++ for (c = state->context; c; c = c->current) ++ if (!(c->flags & CONTEXT_RA_STATELESS)) ++ break; ++ ++ if (!c) ++ return 0; ++ + /* no address, return error */ + o1 = new_opt6(OPTION6_STATUS_CODE); + put_opt6_short(DHCP6NOADDRS); +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0037-Allow-inotify-to-be-disabled-at-compile-time-on-Linu.patch b/src/patches/dnsmasq/0037-Allow-inotify-to-be-disabled-at-compile-time-on-Linu.patch new file mode 100644 index 0000000..7318688 --- /dev/null +++ b/src/patches/dnsmasq/0037-Allow-inotify-to-be-disabled-at-compile-time-on-Linu.patch @@ -0,0 +1,213 @@ +From 0491805d2ff6e7727f0272c94fd97d9897d1e22c Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Mon, 26 Jan 2015 11:23:43 +0000 +Subject: [PATCH 37/55] Allow inotify to be disabled at compile time on Linux. + +--- + CHANGELOG | 4 +++- + src/config.h | 13 ++++++++++++- + src/dnsmasq.c | 21 +++++++++++++-------- + src/dnsmasq.h | 11 +++++++---- + src/inotify.c | 4 ++-- + 5 files changed, 37 insertions(+), 16 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index a4cb901e83ae..c05dec63c587 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -9,7 +9,9 @@ version 2.73 + + Use inotify for checking on updates to /etc/resolv.conf and + friends under Linux. This fixes race conditions when the files are +- updated rapidly and saves CPU by noy polling. ++ updated rapidly and saves CPU by noy polling. To build ++ a binary that runs on old Linux kernels without inotify, ++ use make COPTS=-DNO_INOTIFY + + Fix breakage of --domain=<domain>,<subnet>,local - only reverse + queries were intercepted. THis appears to have been broken +diff --git a/src/config.h b/src/config.h +index cdca231b4079..5e5009271eba 100644 +--- a/src/config.h ++++ b/src/config.h +@@ -115,6 +115,8 @@ HAVE_DNSSEC + HAVE_LOOP + include functionality to probe for and remove DNS forwarding loops. + ++HAVE_INOTIFY ++ use the Linux inotify facility to efficiently re-read configuration files. + + NO_IPV6 + NO_TFTP +@@ -123,6 +125,7 @@ NO_DHCP6 + NO_SCRIPT + NO_LARGEFILE + NO_AUTH ++NO_INOTIFY + these are avilable to explictly disable compile time options which would + otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or + which are enabled by default in the distributed source tree. Building dnsmasq +@@ -355,6 +358,10 @@ HAVE_SOCKADDR_SA_LEN + #undef HAVE_LOOP + #endif + ++#if defined (HAVE_LINUX_NETWORK) && !defined(NO_INOTIFY) ++#define HAVE_INOTIFY ++#endif ++ + /* Define a string indicating which options are in use. + DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */ + +@@ -428,7 +435,11 @@ static char *compile_opts = + #ifndef HAVE_LOOP + "no-" + #endif +-"loop-detect"; ++"loop-detect " ++#ifndef HAVE_INOTIFY ++"no-" ++#endif ++"inotify"; + + + #endif +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index 04cc98278f62..bc4f47170705 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -142,7 +142,9 @@ int main (int argc, char **argv) + set_option_bool(OPT_NOWILD); + reset_option_bool(OPT_CLEVERBIND); + } ++#endif + ++#ifndef HAVE_INOTIFY + if (daemon->inotify_hosts) + die(_("dhcp-hostsdir not supported on this platform"), NULL, EC_BADCONF); + #endif +@@ -321,7 +323,7 @@ int main (int argc, char **argv) + #endif + } + +-#ifdef HAVE_LINUX_NETWORK ++#ifdef HAVE_INOTIFY + if ((!option_bool(OPT_NO_POLL) && daemon->port != 0) || + daemon->dhcp || daemon->doing_dhcp6) + inotify_dnsmasq_init(); +@@ -802,7 +804,7 @@ int main (int argc, char **argv) + + pid = getpid(); + +-#ifdef HAVE_LINUX_NETWORK ++#ifdef HAVE_INOTIFY + /* Using inotify, have to select a resolv file at startup */ + poll_resolv(1, 0, now); + #endif +@@ -872,15 +874,18 @@ int main (int argc, char **argv) + bump_maxfd(daemon->icmp6fd, &maxfd); + } + #endif +- +-#if defined(HAVE_LINUX_NETWORK) +- FD_SET(daemon->netlinkfd, &rset); +- bump_maxfd(daemon->netlinkfd, &maxfd); ++ ++#ifdef HAVE_INOTIFY + if (daemon->inotifyfd != -1) + { + FD_SET(daemon->inotifyfd, &rset); + bump_maxfd(daemon->inotifyfd, &maxfd); + } ++#endif ++ ++#if defined(HAVE_LINUX_NETWORK) ++ FD_SET(daemon->netlinkfd, &rset); ++ bump_maxfd(daemon->netlinkfd, &maxfd); + #elif defined(HAVE_BSD_NETWORK) + FD_SET(daemon->routefd, &rset); + bump_maxfd(daemon->routefd, &maxfd); +@@ -948,7 +953,7 @@ int main (int argc, char **argv) + route_sock(); + #endif + +-#ifdef HAVE_LINUX_NETWORK ++#ifdef HAVE_INOTIFY + if (daemon->inotifyfd != -1 && FD_ISSET(daemon->inotifyfd, &rset) && inotify_check(now)) + { + if (daemon->port != 0 && !option_bool(OPT_NO_POLL)) +@@ -1394,7 +1399,7 @@ void clear_cache_and_reload(time_t now) + if (option_bool(OPT_ETHERS)) + dhcp_read_ethers(); + reread_dhcp(); +-#ifdef HAVE_LINUX_NETWORK ++#ifdef HAVE_INOTIFY + set_dhcp_inotify(); + #endif + dhcp_update_configs(daemon->dhcp_conf); +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index d841fdc064ad..8091634f69db 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -544,7 +544,7 @@ struct resolvc { + int is_default, logged; + time_t mtime; + char *name; +-#ifdef HAVE_LINUX_NETWORK ++#ifdef HAVE_INOTIFY + int wd; /* inotify watch descriptor */ + char *file; /* pointer to file part if path */ + #endif +@@ -558,7 +558,7 @@ struct hostsfile { + struct hostsfile *next; + int flags; + char *fname; +-#ifdef HAVE_LINUX_NETWORK ++#ifdef HAVE_INOTIFY + int wd; /* inotify watch descriptor */ + #endif + unsigned int index; /* matches to cache entries for logging */ +@@ -1013,8 +1013,11 @@ extern struct daemon { + + /* DHCP state */ + int dhcpfd, helperfd, pxefd; ++#ifdef HAVE_INOTIFY ++ int inotifyfd; ++#endif + #if defined(HAVE_LINUX_NETWORK) +- int netlinkfd, inotifyfd; ++ int netlinkfd; + #elif defined(HAVE_BSD_NETWORK) + int dhcp_raw_fd, dhcp_icmp_fd, routefd; + #endif +@@ -1488,7 +1491,7 @@ int detect_loop(char *query, int type); + #endif + + /* inotify.c */ +-#ifdef HAVE_LINUX_NETWORK ++#ifdef HAVE_INOTIFY + void inotify_dnsmasq_init(); + int inotify_check(time_t now); + # ifdef HAVE_DHCP +diff --git a/src/inotify.c b/src/inotify.c +index 52a30d7f44db..818fe8eddda4 100644 +--- a/src/inotify.c ++++ b/src/inotify.c +@@ -15,7 +15,7 @@ + */ + + #include "dnsmasq.h" +-#ifdef HAVE_LINUX_NETWORK ++#ifdef HAVE_INOTIFY + + #include <sys/inotify.h> + +@@ -216,5 +216,5 @@ static void check_for_dhcp_inotify(struct inotify_event *in, time_t now) + + #endif /* DHCP */ + +-#endif /* LINUX_NETWORK */ ++#endif /* INOTIFY */ + +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0038-Expand-inotify-code-to-dhcp-hostsdir-dhcp-optsdir-an.patch b/src/patches/dnsmasq/0038-Expand-inotify-code-to-dhcp-hostsdir-dhcp-optsdir-an.patch new file mode 100644 index 0000000..7514034 --- /dev/null +++ b/src/patches/dnsmasq/0038-Expand-inotify-code-to-dhcp-hostsdir-dhcp-optsdir-an.patch @@ -0,0 +1,562 @@ +From 70d1873dd9e70041ed4bb88c69d5b886b7cc634c Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sat, 31 Jan 2015 19:59:29 +0000 +Subject: [PATCH 38/55] Expand inotify code to dhcp-hostsdir, dhcp-optsdir and + hostsdir. + +--- + src/cache.c | 81 +++++++++++++++++--------- + src/dnsmasq.c | 9 ++- + src/dnsmasq.h | 14 +++-- + src/inotify.c | 179 +++++++++++++++++++++++++++++----------------------------- + src/option.c | 37 +++++++++--- + 5 files changed, 187 insertions(+), 133 deletions(-) + +diff --git a/src/cache.c b/src/cache.c +index 09b6dbf8087a..abaf25ec0f18 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -835,27 +835,42 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl + Only insert each unique address once into this hashing structure. + + This complexity avoids O(n^2) divergent CPU use whilst reading +- large (10000 entry) hosts files. */ +- +- /* hash address */ +- for (j = 0, i = 0; i < addrlen; i++) +- j = (j*2 +((unsigned char *)addr)[i]) % hashsz; +- +- for (lookup = rhash[j]; lookup; lookup = lookup->next) +- if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) && +- memcmp(&lookup->addr.addr, addr, addrlen) == 0) +- { +- cache->flags &= ~F_REVERSE; +- break; +- } ++ large (10000 entry) hosts files. ++ ++ Note that we only do this process when bulk-reading hosts files, ++ for incremental reads, rhash is NULL, and we use cache lookups ++ instead. ++ */ + +- /* maintain address hash chain, insert new unique address */ +- if (!lookup) ++ if (rhash) + { +- cache->next = rhash[j]; +- rhash[j] = cache; ++ /* hash address */ ++ for (j = 0, i = 0; i < addrlen; i++) ++ j = (j*2 +((unsigned char *)addr)[i]) % hashsz; ++ ++ for (lookup = rhash[j]; lookup; lookup = lookup->next) ++ if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) && ++ memcmp(&lookup->addr.addr, addr, addrlen) == 0) ++ { ++ cache->flags &= ~F_REVERSE; ++ break; ++ } ++ ++ /* maintain address hash chain, insert new unique address */ ++ if (!lookup) ++ { ++ cache->next = rhash[j]; ++ rhash[j] = cache; ++ } + } +- ++ else ++ { ++ /* incremental read, lookup in cache */ ++ lookup = cache_find_by_addr(NULL, addr, 0, cache->flags & (F_IPV4 | F_IPV6)); ++ if (lookup && lookup->flags & F_HOSTS) ++ cache->flags &= ~F_REVERSE; ++ } ++ + cache->uid = index; + memcpy(&cache->addr.addr, addr, addrlen); + cache_hash(cache); +@@ -912,7 +927,7 @@ static int gettok(FILE *f, char *token) + } + } + +-static int read_hostsfile(char *filename, unsigned int index, int cache_size, struct crec **rhash, int hashsz) ++int read_hostsfile(char *filename, unsigned int index, int cache_size, struct crec **rhash, int hashsz) + { + FILE *f = fopen(filename, "r"); + char *token = daemon->namebuff, *domain_suffix = NULL; +@@ -958,7 +973,7 @@ static int read_hostsfile(char *filename, unsigned int index, int cache_size, st + addr_count++; + + /* rehash every 1000 names. */ +- if ((name_count - cache_size) > 1000) ++ if (rhash && ((name_count - cache_size) > 1000)) + { + rehash(name_count); + cache_size = name_count; +@@ -1005,10 +1020,13 @@ static int read_hostsfile(char *filename, unsigned int index, int cache_size, st + } + + fclose(f); +- rehash(name_count); +- +- my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count); + ++ if (rhash) ++ { ++ rehash(name_count); ++ my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count); ++ } ++ + return name_count; + } + +@@ -1118,14 +1136,19 @@ void cache_reload(void) + my_syslog(LOG_INFO, _("cleared cache")); + return; + } +- ++ + if (!option_bool(OPT_NO_HOSTS)) + total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz); +- ++ + daemon->addn_hosts = expand_filelist(daemon->addn_hosts); + for (ah = daemon->addn_hosts; ah; ah = ah->next) + if (!(ah->flags & AH_INACTIVE)) + total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz); ++ ++#ifdef HAVE_INOTIFY ++ set_dynamic_inotify(AH_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz); ++#endif ++ + } + + #ifdef HAVE_DHCP +@@ -1505,7 +1528,13 @@ char *record_source(unsigned int index) + for (ah = daemon->addn_hosts; ah; ah = ah->next) + if (ah->index == index) + return ah->fname; +- ++ ++#ifdef HAVE_INOTIFY ++ for (ah = daemon->dynamic_dirs; ah; ah = ah->next) ++ if (ah->index == index) ++ return ah->fname; ++#endif ++ + return "<unknown>"; + } + +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index bc4f47170705..2c629fe422aa 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -145,8 +145,8 @@ int main (int argc, char **argv) + #endif + + #ifndef HAVE_INOTIFY +- if (daemon->inotify_hosts) +- die(_("dhcp-hostsdir not supported on this platform"), NULL, EC_BADCONF); ++ if (daemon->dynamic_dirs) ++ die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF); + #endif + + if (option_bool(OPT_DNSSEC_VALID)) +@@ -324,8 +324,7 @@ int main (int argc, char **argv) + } + + #ifdef HAVE_INOTIFY +- if ((!option_bool(OPT_NO_POLL) && daemon->port != 0) || +- daemon->dhcp || daemon->doing_dhcp6) ++ if (daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6) + inotify_dnsmasq_init(); + else + daemon->inotifyfd = -1; +@@ -1400,7 +1399,7 @@ void clear_cache_and_reload(time_t now) + dhcp_read_ethers(); + reread_dhcp(); + #ifdef HAVE_INOTIFY +- set_dhcp_inotify(); ++ set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0); + #endif + dhcp_update_configs(daemon->dhcp_conf); + lease_update_from_configs(); +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 8091634f69db..0c322a93993e 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -554,6 +554,9 @@ struct resolvc { + #define AH_DIR 1 + #define AH_INACTIVE 2 + #define AH_WD_DONE 4 ++#define AH_HOSTS 8 ++#define AH_DHCP_HST 16 ++#define AH_DHCP_OPT 32 + struct hostsfile { + struct hostsfile *next; + int flags; +@@ -965,7 +968,7 @@ extern struct daemon { + int doing_ra, doing_dhcp6; + struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names; + struct dhcp_netid_list *force_broadcast, *bootp_dynamic; +- struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *inotify_hosts; ++ struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *dynamic_dirs; + int dhcp_max, tftp_max; + int dhcp_server_port, dhcp_client_port; + int start_tftp_port, end_tftp_port; +@@ -1071,6 +1074,8 @@ int cache_make_stat(struct txt_record *t); + char *cache_get_name(struct crec *crecp); + char *cache_get_cname_target(struct crec *crecp); + struct crec *cache_enumerate(int init); ++int read_hostsfile(char *filename, unsigned int index, int cache_size, ++ struct crec **rhash, int hashsz); + + /* blockdata.c */ + #ifdef HAVE_DNSSEC +@@ -1204,7 +1209,8 @@ void reset_option_bool(unsigned int opt); + struct hostsfile *expand_filelist(struct hostsfile *list); + char *parse_server(char *arg, union mysockaddr *addr, + union mysockaddr *source_addr, char *interface, int *flags); +-int option_read_hostsfile(char *file); ++int option_read_dynfile(char *file, int flags); ++ + /* forward.c */ + void reply_query(int fd, int family, time_t now); + void receive_query(struct listener *listen, time_t now); +@@ -1494,7 +1500,5 @@ int detect_loop(char *query, int type); + #ifdef HAVE_INOTIFY + void inotify_dnsmasq_init(); + int inotify_check(time_t now); +-# ifdef HAVE_DHCP +-void set_dhcp_inotify(void); +-# endif ++void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz); + #endif +diff --git a/src/inotify.c b/src/inotify.c +index 818fe8eddda4..c537f4c1562a 100644 +--- a/src/inotify.c ++++ b/src/inotify.c +@@ -19,11 +19,6 @@ + + #include <sys/inotify.h> + +-#ifdef HAVE_DHCP +-static void check_for_dhcp_inotify(struct inotify_event *in, time_t now); +-#endif +- +- + /* the strategy is to set a inotify on the directories containing + resolv files, for any files in the directory which are close-write + or moved into the directory. +@@ -82,57 +77,28 @@ void inotify_dnsmasq_init() + } + } + +-int inotify_check(time_t now) ++ ++/* initialisation for dynamic-dir. Set inotify watch for each directory, and read pre-existing files */ ++void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz) + { +- int hit = 0; ++ struct hostsfile *ah; + +- while (1) ++ for (ah = daemon->dynamic_dirs; ah; ah = ah->next) + { +- int rc; +- char *p; +- struct resolvc *res; +- struct inotify_event *in; +- +- while ((rc = read(daemon->inotifyfd, inotify_buffer, INOTIFY_SZ)) == -1 && errno == EINTR); +- +- if (rc <= 0) +- break; +- +- for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len) ++ DIR *dir_stream = NULL; ++ struct dirent *ent; ++ struct stat buf; ++ ++ if (!(ah->flags & flag)) ++ continue; ++ ++ if (stat(ah->fname, &buf) == -1 || !(S_ISDIR(buf.st_mode))) + { +- in = (struct inotify_event*)p; +- +- for (res = daemon->resolv_files; res; res = res->next) +- if (res->wd == in->wd && in->len != 0 && strcmp(res->file, in->name) == 0) +- hit = 1; +- +-#ifdef HAVE_DHCP +- if (daemon->dhcp || daemon->doing_dhcp6) +- check_for_dhcp_inotify(in, now); +-#endif ++ my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"), ++ ah->fname, strerror(errno)); ++ continue; + } +- } +- return hit; +-} +- +-#ifdef HAVE_DHCP +-/* initialisation for dhcp-hostdir. Set inotify watch for each directory, and read pre-existing files */ +-void set_dhcp_inotify(void) +-{ +- struct hostsfile *ah; +- +- for (ah = daemon->inotify_hosts; ah; ah = ah->next) +- { +- DIR *dir_stream = NULL; +- struct dirent *ent; +- struct stat buf; +- +- if (stat(ah->fname, &buf) == -1 || !(S_ISDIR(buf.st_mode))) +- { +- my_syslog(LOG_ERR, _("bad directory in dhcp-hostsdir %s"), ah->fname); +- continue; +- } +- ++ + if (!(ah->flags & AH_WD_DONE)) + { + ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO); +@@ -142,7 +108,8 @@ void set_dhcp_inotify(void) + a race which misses files being added as we start */ + if (ah->wd == -1 || !(dir_stream = opendir(ah->fname))) + { +- my_syslog(LOG_ERR, _("failed to create inotify for %s"), ah->fname); ++ my_syslog(LOG_ERR, _("failed to create inotify for %s: %s"), ++ ah->fname, strerror(errno)); + continue; + } + +@@ -167,54 +134,90 @@ void set_dhcp_inotify(void) + + /* ignore non-regular files */ + if (stat(path, &buf) != -1 && S_ISREG(buf.st_mode)) +- option_read_hostsfile(path); +- ++ { ++ if (ah->flags & AH_HOSTS) ++ total_size = read_hostsfile(path, ah->index, total_size, rhash, revhashsz); ++#ifdef HAVE_DHCP ++ else if (ah->flags & (AH_DHCP_HST | AH_DHCP_OPT)) ++ option_read_dynfile(path, ah->flags); ++#endif ++ } ++ + free(path); + } + } + } + } + +-static void check_for_dhcp_inotify(struct inotify_event *in, time_t now) ++int inotify_check(time_t now) + { ++ int hit = 0; + struct hostsfile *ah; + +- /* ignore emacs backups and dotfiles */ +- if (in->len == 0 || +- in->name[in->len - 1] == '~' || +- (in->name[0] == '#' && in->name[in->len - 1] == '#') || +- in->name[0] == '.') +- return; +- +- for (ah = daemon->inotify_hosts; ah; ah = ah->next) +- if (ah->wd == in->wd) +- { +- size_t lendir = strlen(ah->fname); +- char *path; +- +- if ((path = whine_malloc(lendir + in->len + 2))) +- { +- strcpy(path, ah->fname); +- strcat(path, "/"); +- strcat(path, in->name); +- +- if (option_read_hostsfile(path)) ++ while (1) ++ { ++ int rc; ++ char *p; ++ struct resolvc *res; ++ struct inotify_event *in; ++ ++ while ((rc = read(daemon->inotifyfd, inotify_buffer, INOTIFY_SZ)) == -1 && errno == EINTR); ++ ++ if (rc <= 0) ++ break; ++ ++ for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len) ++ { ++ in = (struct inotify_event*)p; ++ ++ for (res = daemon->resolv_files; res; res = res->next) ++ if (res->wd == in->wd && in->len != 0 && strcmp(res->file, in->name) == 0) ++ hit = 1; ++ ++ /* ignore emacs backups and dotfiles */ ++ if (in->len == 0 || ++ in->name[in->len - 1] == '~' || ++ (in->name[0] == '#' && in->name[in->len - 1] == '#') || ++ in->name[0] == '.') ++ continue; ++ ++ for (ah = daemon->dynamic_dirs; ah; ah = ah->next) ++ if (ah->wd == in->wd) + { +- /* Propogate the consequences of loading a new dhcp-host */ +- dhcp_update_configs(daemon->dhcp_conf); +- lease_update_from_configs(); +- lease_update_file(now); +- lease_update_dns(1); ++ size_t lendir = strlen(ah->fname); ++ char *path; ++ ++ if ((path = whine_malloc(lendir + in->len + 2))) ++ { ++ strcpy(path, ah->fname); ++ strcat(path, "/"); ++ strcat(path, in->name); ++ ++ if (ah->flags & AH_HOSTS) ++ read_hostsfile(path, ah->index, 0, NULL, 0); ++#ifdef HAVE_DHCP ++ else if (ah->flags & AH_DHCP_HST) ++ { ++ if (option_read_dynfile(path, AH_DHCP_HST)) ++ { ++ /* Propogate the consequences of loading a new dhcp-host */ ++ dhcp_update_configs(daemon->dhcp_conf); ++ lease_update_from_configs(); ++ lease_update_file(now); ++ lease_update_dns(1); ++ } ++ } ++ else if (ah->flags & AH_DHCP_OPT) ++ option_read_dynfile(path, AH_DHCP_OPT); ++#endif ++ ++ free(path); ++ } + } +- +- free(path); +- } +- +- return; +- } ++ } ++ } ++ return hit; + } + +-#endif /* DHCP */ +- + #endif /* INOTIFY */ + +diff --git a/src/option.c b/src/option.c +index 22e11c37d374..6ef80117cc8c 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -150,6 +150,8 @@ struct myoption { + #define LOPT_IGNORE_ADDR 338 + #define LOPT_MINCTTL 339 + #define LOPT_DHCP_INOTIFY 340 ++#define LOPT_DHOPT_INOTIFY 341 ++#define LOPT_HOST_INOTIFY 342 + + #ifdef HAVE_GETOPT_LONG + static const struct option opts[] = +@@ -200,6 +202,7 @@ static const struct myoption opts[] = + { "local-ttl", 1, 0, 'T' }, + { "no-negcache", 0, 0, 'N' }, + { "addn-hosts", 1, 0, 'H' }, ++ { "hostsdir", 1, 0, LOPT_HOST_INOTIFY }, + { "query-port", 1, 0, 'Q' }, + { "except-interface", 1, 0, 'I' }, + { "no-dhcp-interface", 1, 0, '2' }, +@@ -249,6 +252,7 @@ static const struct myoption opts[] = + { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST }, + { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS }, + { "dhcp-hostsdir", 1, 0, LOPT_DHCP_INOTIFY }, ++ { "dhcp-optsdir", 1, 0, LOPT_DHOPT_INOTIFY }, + { "dhcp-no-override", 0, 0, LOPT_OVERRIDE }, + { "tftp-port-range", 1, 0, LOPT_TFTPPORTS }, + { "stop-dns-rebind", 0, 0, LOPT_REBIND }, +@@ -338,9 +342,11 @@ static struct { + { LOPT_DHCP_HOST, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from file."), NULL }, + { LOPT_DHCP_OPTS, ARG_DUP, "<path>", gettext_noop("Read DHCP option specs from file."), NULL }, + { LOPT_DHCP_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read DHCP host specs from a directory."), NULL }, ++ { LOPT_DHOPT_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read DHCP options from a directory."), NULL }, + { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL }, + { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE }, + { 'H', ARG_DUP, "<path>", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE }, ++ { LOPT_HOST_INOTIFY, ARG_DUP, "<path>", gettext_noop("Read hosts files from a directory."), NULL }, + { 'i', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) to listen on."), NULL }, + { 'I', ARG_DUP, "<interface>", gettext_noop("Specify interface(s) NOT to listen on.") , NULL }, + { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL }, +@@ -1712,10 +1718,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + break; + #endif /* HAVE_DHCP */ + +- case LOPT_DHCP_HOST: /* --dhcp-hostsfile */ +- case LOPT_DHCP_OPTS: /* --dhcp-optsfile */ +- case LOPT_DHCP_INOTIFY: /* dhcp-hostsdir */ +- case 'H': /* --addn-hosts */ ++ case LOPT_DHCP_HOST: /* --dhcp-hostsfile */ ++ case LOPT_DHCP_OPTS: /* --dhcp-optsfile */ ++ case LOPT_DHCP_INOTIFY: /* --dhcp-hostsdir */ ++ case LOPT_DHOPT_INOTIFY: /* --dhcp-optsdir */ ++ case LOPT_HOST_INOTIFY: /* --hostsdir */ ++ case 'H': /* --addn-hosts */ + { + struct hostsfile *new = opt_malloc(sizeof(struct hostsfile)); + static unsigned int hosts_index = SRC_AH; +@@ -1737,10 +1745,16 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + new->next = daemon->dhcp_opts_file; + daemon->dhcp_opts_file = new; + } +- else if (option == LOPT_DHCP_INOTIFY) ++ else + { +- new->next = daemon->inotify_hosts; +- daemon->inotify_hosts = new; ++ new->next = daemon->dynamic_dirs; ++ daemon->dynamic_dirs = new; ++ if (option == LOPT_DHCP_INOTIFY) ++ new->flags |= AH_DHCP_HST; ++ else if (option == LOPT_DHOPT_INOTIFY) ++ new->flags |= AH_DHCP_OPT; ++ else if (option == LOPT_HOST_INOTIFY) ++ new->flags |= AH_HOSTS; + } + + break; +@@ -4052,9 +4066,14 @@ static void read_file(char *file, FILE *f, int hard_opt) + } + + #ifdef HAVE_DHCP +-int option_read_hostsfile(char *file) ++int option_read_dynfile(char *file, int flags) + { +- return one_file(file, LOPT_BANK); ++ if (flags & AH_DHCP_HST) ++ return one_file(file, LOPT_BANK); ++ else if (flags & AH_DHCP_OPT) ++ return one_file(file, LOPT_OPTS); ++ ++ return 0; + } + #endif + +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0039-Update-copyrights-for-dawn-of-2015.patch b/src/patches/dnsmasq/0039-Update-copyrights-for-dawn-of-2015.patch new file mode 100644 index 0000000..11bde00 --- /dev/null +++ b/src/patches/dnsmasq/0039-Update-copyrights-for-dawn-of-2015.patch @@ -0,0 +1,428 @@ +From aff3396280e944833f0e23d834aa6acd5fe2605a Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sat, 31 Jan 2015 20:13:40 +0000 +Subject: [PATCH 39/55] Update copyrights for dawn of 2015. + +--- + Makefile | 2 +- + src/auth.c | 2 +- + src/blockdata.c | 2 +- + src/bpf.c | 2 +- + src/cache.c | 2 +- + src/config.h | 2 +- + src/conntrack.c | 2 +- + src/dbus.c | 2 +- + src/dhcp-common.c | 2 +- + src/dhcp-protocol.h | 2 +- + src/dhcp.c | 2 +- + src/dhcp6-protocol.h | 2 +- + src/dhcp6.c | 2 +- + src/dns-protocol.h | 2 +- + src/dnsmasq.c | 2 +- + src/dnsmasq.h | 4 ++-- + src/dnssec.c | 2 +- + src/domain.c | 2 +- + src/forward.c | 2 +- + src/helper.c | 2 +- + src/inotify.c | 2 +- + src/ip6addr.h | 2 +- + src/lease.c | 2 +- + src/log.c | 2 +- + src/loop.c | 2 +- + src/netlink.c | 2 +- + src/network.c | 2 +- + src/option.c | 2 +- + src/outpacket.c | 2 +- + src/radv-protocol.h | 2 +- + src/radv.c | 2 +- + src/rfc1035.c | 2 +- + src/rfc2131.c | 2 +- + src/rfc3315.c | 2 +- + src/slaac.c | 2 +- + src/tftp.c | 2 +- + src/util.c | 2 +- + 37 files changed, 38 insertions(+), 38 deletions(-) + +diff --git a/Makefile b/Makefile +index bcbd5571671d..21e4a5c4101c 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,4 +1,4 @@ +-# dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++# dnsmasq is Copyright (c) 2000-2015 Simon Kelley + # + # This program is free software; you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by +diff --git a/src/auth.c b/src/auth.c +index 59e05d3da38e..15721e52793f 100644 +--- a/src/auth.c ++++ b/src/auth.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/blockdata.c b/src/blockdata.c +index 5a70a7967fa3..c8f5eae811eb 100644 +--- a/src/blockdata.c ++++ b/src/blockdata.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/bpf.c b/src/bpf.c +index 4416b1c07287..997d87421bed 100644 +--- a/src/bpf.c ++++ b/src/bpf.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/cache.c b/src/cache.c +index abaf25ec0f18..117ae279fd4e 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/config.h b/src/config.h +index 5e5009271eba..8def6f200461 100644 +--- a/src/config.h ++++ b/src/config.h +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/conntrack.c b/src/conntrack.c +index 6a5133ab93af..0fa2da903b03 100644 +--- a/src/conntrack.c ++++ b/src/conntrack.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/dbus.c b/src/dbus.c +index a2a94dc85dac..5b69de518beb 100644 +--- a/src/dbus.c ++++ b/src/dbus.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/dhcp-common.c b/src/dhcp-common.c +index 9d13ac8df6f1..ce115202a646 100644 +--- a/src/dhcp-common.c ++++ b/src/dhcp-common.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/dhcp-protocol.h b/src/dhcp-protocol.h +index 4c0961472482..701b6cb3346e 100644 +--- a/src/dhcp-protocol.h ++++ b/src/dhcp-protocol.h +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/dhcp.c b/src/dhcp.c +index 7acf2c4311a9..f29be9b489a7 100644 +--- a/src/dhcp.c ++++ b/src/dhcp.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/dhcp6-protocol.h b/src/dhcp6-protocol.h +index 5927dc32f6af..928a2fa162ed 100644 +--- a/src/dhcp6-protocol.h ++++ b/src/dhcp6-protocol.h +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/dhcp6.c b/src/dhcp6.c +index bc48fdddd3de..3c56e77c6085 100644 +--- a/src/dhcp6.c ++++ b/src/dhcp6.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/dns-protocol.h b/src/dns-protocol.h +index 0aced3ce6952..16fade33d98c 100644 +--- a/src/dns-protocol.h ++++ b/src/dns-protocol.h +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index 2c629fe422aa..e903a24c8105 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 0c322a93993e..89e758b56a0a 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +@@ -14,7 +14,7 @@ + along with this program. If not, see http://www.gnu.org/licenses/. + */ + +-#define COPYRIGHT "Copyright (c) 2000-2014 Simon Kelley" ++#define COPYRIGHT "Copyright (c) 2000-2015 Simon Kelley" + + #ifndef NO_LARGEFILE + /* Ensure we can use files >2GB (log files may grow this big) */ +diff --git a/src/dnssec.c b/src/dnssec.c +index d39ab85ed966..a8dfe3871c85 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -1,5 +1,5 @@ + /* dnssec.c is Copyright (c) 2012 Giovanni Bajo rasky@develer.com +- and Copyright (c) 2012-2014 Simon Kelley ++ and Copyright (c) 2012-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/domain.c b/src/domain.c +index fdd5e4f0838f..278698ca04b3 100644 +--- a/src/domain.c ++++ b/src/domain.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/forward.c b/src/forward.c +index b17bc34f865f..438e9fa490b8 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/helper.c b/src/helper.c +index 4be53c361ee1..1fee72dead8c 100644 +--- a/src/helper.c ++++ b/src/helper.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/inotify.c b/src/inotify.c +index c537f4c1562a..470d6ed99213 100644 +--- a/src/inotify.c ++++ b/src/inotify.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/ip6addr.h b/src/ip6addr.h +index c7dcb39c33fa..f0b7e820e227 100644 +--- a/src/ip6addr.h ++++ b/src/ip6addr.h +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/lease.c b/src/lease.c +index 5d56b1b9147e..545bbb7fd09c 100644 +--- a/src/lease.c ++++ b/src/lease.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/log.c b/src/log.c +index 8083a8697323..a5ac605c7c5d 100644 +--- a/src/log.c ++++ b/src/log.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/loop.c b/src/loop.c +index bb377ad12644..565f7d8e58e0 100644 +--- a/src/loop.c ++++ b/src/loop.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/netlink.c b/src/netlink.c +index b39328376389..10f94db25a14 100644 +--- a/src/netlink.c ++++ b/src/netlink.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/network.c b/src/network.c +index 14d2af2ce313..7045253d467b 100644 +--- a/src/network.c ++++ b/src/network.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/option.c b/src/option.c +index 6ef80117cc8c..cb4e76ba0aa2 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/outpacket.c b/src/outpacket.c +index dce68f7cb09f..5b1ff9318bbd 100644 +--- a/src/outpacket.c ++++ b/src/outpacket.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/radv-protocol.h b/src/radv-protocol.h +index 72ccda49d7fe..4cc1ea426e69 100644 +--- a/src/radv-protocol.h ++++ b/src/radv-protocol.h +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/radv.c b/src/radv.c +index 3c8b162dbd8e..6da125b864ae 100644 +--- a/src/radv.c ++++ b/src/radv.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/rfc1035.c b/src/rfc1035.c +index 262274fc5b80..5ef5ddb7485e 100644 +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/rfc2131.c b/src/rfc2131.c +index 5c9040892f1d..55526443dc84 100644 +--- a/src/rfc2131.c ++++ b/src/rfc2131.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/rfc3315.c b/src/rfc3315.c +index e593ec9c362c..c1ddc805988d 100644 +--- a/src/rfc3315.c ++++ b/src/rfc3315.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/slaac.c b/src/slaac.c +index 351d6802f85e..abaad537e25a 100644 +--- a/src/slaac.c ++++ b/src/slaac.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/tftp.c b/src/tftp.c +index a527911fc0df..a57a31514f44 100644 +--- a/src/tftp.c ++++ b/src/tftp.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +diff --git a/src/util.c b/src/util.c +index d532444da207..91d02410b13f 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -1,4 +1,4 @@ +-/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley ++/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0040-inotify-documentation-updates.patch b/src/patches/dnsmasq/0040-inotify-documentation-updates.patch new file mode 100644 index 0000000..981e553 --- /dev/null +++ b/src/patches/dnsmasq/0040-inotify-documentation-updates.patch @@ -0,0 +1,53 @@ +From 3d04f46334d0e345f589eda1372e638b946fe637 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sat, 31 Jan 2015 21:59:13 +0000 +Subject: [PATCH 40/55] inotify documentation updates. + +--- + man/dnsmasq.8 | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 +index 005b5cca8d1f..c858323d78bd 100644 +--- a/man/dnsmasq.8 ++++ b/man/dnsmasq.8 +@@ -50,6 +50,10 @@ Additional hosts file. Read the specified file as well as /etc/hosts. If -h is g + only the specified file. This option may be repeated for more than one + additional hosts file. If a directory is given, then read all the files contained in that directory. + .TP ++.B --hostsdir=<path> ++Read all the hosts files contained in the directory. New or changed files ++are read automatically. See --dhcp-hostsdir for details. ++.TP + .B -E, --expand-hosts + Add the domain to simple names (without a period) in /etc/hosts + in the same way as for DHCP-derived names. Note that this does not +@@ -979,12 +983,14 @@ dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that + it is possible to encode the information in a + .TP + .B --dhcp-hostsdir=<path> +-This is exactly equivalent to dhcp-hostfile, except for the following. The path MUST be a ++This is equivalent to dhcp-hostsfile, except for the following. The path MUST be a + directory, and not an individual file. Changed or new files within + the directory are read automatically, without the need to send SIGHUP. + If a file is deleted for changed after it has been read by dnsmasq, then the + host record it contained will remain until dnsmasq recieves a SIGHUP, or + is restarted; ie host records are only added dynamically. ++.B --dhcp-optsdir=<path> ++This is equivalent to dhcp-optsfile, with the differences noted for --dhcp-hostsdir. + .TP + .B --dhcp-boot + flag as DHCP options, using the options names bootfile-name, +@@ -1791,7 +1797,8 @@ clears its cache and then re-loads + .I /etc/hosts + and + .I /etc/ethers +-and any file given by --dhcp-hostsfile, --dhcp-optsfile or --addn-hosts. ++and any file given by --dhcp-hostsfile, --dhcp-hostsdir, --dhcp-optsfile, ++--dhcp-optsdir, --addn-hosts or --hostsdir. + The dhcp lease change script is called for all + existing DHCP leases. If + .B +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0041-Fix-broken-ECDSA-DNSSEC-signatures.patch b/src/patches/dnsmasq/0041-Fix-broken-ECDSA-DNSSEC-signatures.patch new file mode 100644 index 0000000..0c8aa9b --- /dev/null +++ b/src/patches/dnsmasq/0041-Fix-broken-ECDSA-DNSSEC-signatures.patch @@ -0,0 +1,39 @@ +From 6ef15b34ca83c62a939f69356d5c3f7a6bfef3d0 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sat, 31 Jan 2015 22:44:26 +0000 +Subject: [PATCH 41/55] Fix broken ECDSA DNSSEC signatures. + +--- + CHANGELOG | 2 ++ + src/dnssec.c | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG b/CHANGELOG +index c05dec63c587..c80dc0fdbe9e 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -65,6 +65,8 @@ version 2.73 + configured to do stateful DHCPv6. Thanks to Win King Wan + for the patch. + ++ Fix broken DNSSEC validation of ECDSA signatures. ++ + + version 2.72 + Add ra-advrouter mode, for RFC-3775 mobile IPv6 support. +diff --git a/src/dnssec.c b/src/dnssec.c +index a8dfe3871c85..26932373cd3e 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -275,7 +275,7 @@ static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len + } + + if (sig_len != 2*t || key_len != 2*t || +- (p = blockdata_retrieve(key_data, key_len, NULL))) ++ !(p = blockdata_retrieve(key_data, key_len, NULL))) + return 0; + + mpz_import(x, t , 1, 1, 0, 0, p); +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0042-BSD-make-support.patch b/src/patches/dnsmasq/0042-BSD-make-support.patch new file mode 100644 index 0000000..76f76ef --- /dev/null +++ b/src/patches/dnsmasq/0042-BSD-make-support.patch @@ -0,0 +1,29 @@ +From 106266761828a0acb006346ae47bf031dee46a5d Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sun, 1 Feb 2015 00:15:16 +0000 +Subject: [PATCH 42/55] BSD make support + +--- + Makefile | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/Makefile b/Makefile +index 21e4a5c4101c..2910320b6452 100644 +--- a/Makefile ++++ b/Makefile +@@ -64,8 +64,10 @@ nettle_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG + gmp_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC NO_GMP --copy -lgmp` + sunos_libs = `if uname | grep SunOS >/dev/null 2>&1; then echo -lsocket -lnsl -lposix4; fi` + version = -DVERSION='"`$(top)/bld/get-version $(top)`"' +-copts_conf = .copts_$(shell $(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | \ +- ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' ') ++ ++sum?=$(shell $(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' ') ++sum!=$(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' ' ++copts_conf = .copts_$(sum) + + objs = cache.o rfc1035.o util.o option.o forward.o network.o \ + dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \ +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0043-Fix-build-failure-on-openBSD.patch b/src/patches/dnsmasq/0043-Fix-build-failure-on-openBSD.patch new file mode 100644 index 0000000..a3df61b --- /dev/null +++ b/src/patches/dnsmasq/0043-Fix-build-failure-on-openBSD.patch @@ -0,0 +1,25 @@ +From 8d8a54ec79d9f96979fabbd97b1dd2ddebc7d78f Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sun, 1 Feb 2015 21:48:46 +0000 +Subject: [PATCH 43/55] Fix build failure on openBSD. + +--- + src/tables.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/tables.c b/src/tables.c +index dcdef794c4d2..aae1252708db 100644 +--- a/src/tables.c ++++ b/src/tables.c +@@ -21,7 +21,7 @@ + #if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK) + + #ifndef __FreeBSD__ +-#include <bsd/string.h> ++#include <string.h> + #endif + + #include <sys/types.h> +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0044-Manpage-typo-fix.patch b/src/patches/dnsmasq/0044-Manpage-typo-fix.patch new file mode 100644 index 0000000..e0e384f --- /dev/null +++ b/src/patches/dnsmasq/0044-Manpage-typo-fix.patch @@ -0,0 +1,25 @@ +From d36b732c4cfa91ea09af64b5dc0f3a85a075e5bc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Thi=C3=A9baud=20Weksteen?= thiebaud@weksteen.fr +Date: Mon, 2 Feb 2015 21:37:27 +0000 +Subject: [PATCH 44/55] Manpage typo fix. + +--- + man/dnsmasq.8 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 +index c858323d78bd..27f85d40fbbb 100644 +--- a/man/dnsmasq.8 ++++ b/man/dnsmasq.8 +@@ -516,7 +516,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=<name>[,<name>....][<IPv4-address>],[<IPv6-address>] ++.B --host-record=<name>[,<name>....],[<IPv4-address>],[<IPv6-address>] + 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 +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0045-Fixup-dhcp-configs-after-reading-extra-hostfiles-wit.patch b/src/patches/dnsmasq/0045-Fixup-dhcp-configs-after-reading-extra-hostfiles-wit.patch new file mode 100644 index 0000000..fc1b98a --- /dev/null +++ b/src/patches/dnsmasq/0045-Fixup-dhcp-configs-after-reading-extra-hostfiles-wit.patch @@ -0,0 +1,38 @@ +From 2941d3ac898cf84b544e47c9735c5e4111711db1 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Mon, 2 Feb 2015 22:36:42 +0000 +Subject: [PATCH 45/55] Fixup dhcp-configs after reading extra hostfiles with + inotify. + +--- + src/inotify.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/src/inotify.c b/src/inotify.c +index 470d6ed99213..6f4cd79e0030 100644 +--- a/src/inotify.c ++++ b/src/inotify.c +@@ -194,7 +194,19 @@ int inotify_check(time_t now) + strcat(path, in->name); + + if (ah->flags & AH_HOSTS) +- read_hostsfile(path, ah->index, 0, NULL, 0); ++ { ++ read_hostsfile(path, ah->index, 0, NULL, 0); ++#ifdef HAVE_DHCP ++ if (daemon->dhcp || daemon->doing_dhcp6) ++ { ++ /* Propogate the consequences of loading a new dhcp-host */ ++ dhcp_update_configs(daemon->dhcp_conf); ++ lease_update_from_configs(); ++ lease_update_file(now); ++ lease_update_dns(1); ++ } ++#endif ++ } + #ifdef HAVE_DHCP + else if (ah->flags & AH_DHCP_HST) + { +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0046-Extra-logging-for-inotify-code.patch b/src/patches/dnsmasq/0046-Extra-logging-for-inotify-code.patch new file mode 100644 index 0000000..803174a --- /dev/null +++ b/src/patches/dnsmasq/0046-Extra-logging-for-inotify-code.patch @@ -0,0 +1,68 @@ +From f9c863708c6b0aea31ff7a466647685dc739de50 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Tue, 3 Feb 2015 21:52:48 +0000 +Subject: [PATCH 46/55] Extra logging for inotify code. + +--- + src/cache.c | 9 ++++----- + src/inotify.c | 4 +++- + src/option.c | 4 +++- + 3 files changed, 10 insertions(+), 7 deletions(-) + +diff --git a/src/cache.c b/src/cache.c +index 117ae279fd4e..43245b771b53 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -1022,11 +1022,10 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr + fclose(f); + + if (rhash) +- { +- rehash(name_count); +- my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count); +- } +- ++ rehash(name_count); ++ ++ my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count); ++ + return name_count; + } + +diff --git a/src/inotify.c b/src/inotify.c +index 6f4cd79e0030..44ce0c9af051 100644 +--- a/src/inotify.c ++++ b/src/inotify.c +@@ -192,7 +192,9 @@ int inotify_check(time_t now) + strcpy(path, ah->fname); + strcat(path, "/"); + strcat(path, in->name); +- ++ ++ my_syslog(LOG_INFO, _("inotify, new or changed file %s"), path); ++ + if (ah->flags & AH_HOSTS) + { + read_hostsfile(path, ah->index, 0, NULL, 0); +diff --git a/src/option.c b/src/option.c +index cb4e76ba0aa2..e4b4865d07a5 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -4068,11 +4068,13 @@ static void read_file(char *file, FILE *f, int hard_opt) + #ifdef HAVE_DHCP + int option_read_dynfile(char *file, int flags) + { ++ my_syslog(MS_DHCP | LOG_INFO, _("read %s"), file); ++ + if (flags & AH_DHCP_HST) + return one_file(file, LOPT_BANK); + else if (flags & AH_DHCP_OPT) + return one_file(file, LOPT_OPTS); +- ++ + return 0; + } + #endif +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0047-man-page-typo.patch b/src/patches/dnsmasq/0047-man-page-typo.patch new file mode 100644 index 0000000..6606a7a --- /dev/null +++ b/src/patches/dnsmasq/0047-man-page-typo.patch @@ -0,0 +1,24 @@ +From efb8b5566aafc1f3ce18514a2df93af5a2e4998c Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sat, 7 Feb 2015 22:36:34 +0000 +Subject: [PATCH 47/55] man page typo. + +--- + man/dnsmasq.8 | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 +index 27f85d40fbbb..5cdd186afaa0 100644 +--- a/man/dnsmasq.8 ++++ b/man/dnsmasq.8 +@@ -989,6 +989,7 @@ the directory are read automatically, without the need to send SIGHUP. + If a file is deleted for changed after it has been read by dnsmasq, then the + host record it contained will remain until dnsmasq recieves a SIGHUP, or + is restarted; ie host records are only added dynamically. ++.TP + .B --dhcp-optsdir=<path> + This is equivalent to dhcp-optsfile, with the differences noted for --dhcp-hostsdir. + .TP +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0048-Fix-get-version-script-which-returned-wrong-tag-in-s.patch b/src/patches/dnsmasq/0048-Fix-get-version-script-which-returned-wrong-tag-in-s.patch new file mode 100644 index 0000000..5633d9d --- /dev/null +++ b/src/patches/dnsmasq/0048-Fix-get-version-script-which-returned-wrong-tag-in-s.patch @@ -0,0 +1,26 @@ +From f4f400776b3c1aa303d1a0fcd500f0ab5bc970f2 Mon Sep 17 00:00:00 2001 +From: Shantanu Gadgil shantanugadgil@yahoo.com +Date: Wed, 11 Feb 2015 20:16:59 +0000 +Subject: [PATCH 48/55] Fix get-version script which returned wrong tag in some + situations. + +--- + bld/get-version | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/bld/get-version b/bld/get-version +index c246a3cc6a47..7ab75db729ac 100755 +--- a/bld/get-version ++++ b/bld/get-version +@@ -20,7 +20,7 @@ else + vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep ^v[0-9]` + + if [ $? -eq 0 ]; then +- echo "${vers}" | sort | head -n 1 | sed 's/^v//' ++ echo "${vers}" | sort -r | head -n 1 | sed 's/^v//' + else + cat $1/VERSION + fi +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0049-Typos.patch b/src/patches/dnsmasq/0049-Typos.patch new file mode 100644 index 0000000..8f64b39 --- /dev/null +++ b/src/patches/dnsmasq/0049-Typos.patch @@ -0,0 +1,26 @@ +From 8ff70de618eb7de9147dbfbd4deca4a2dd62f0cb Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sat, 14 Feb 2015 20:02:37 +0000 +Subject: [PATCH 49/55] Typos. + +--- + src/inotify.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/inotify.c b/src/inotify.c +index 44ce0c9af051..9422066257f5 100644 +--- a/src/inotify.c ++++ b/src/inotify.c +@@ -104,7 +104,8 @@ void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revh + ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO); + ah->flags |= AH_WD_DONE; + } +- /* Read contents of dir _after_ calling add_watch, in the ho[e of avoiding ++ ++ /* Read contents of dir _after_ calling add_watch, in the hope of avoiding + a race which misses files being added as we start */ + if (ah->wd == -1 || !(dir_stream = opendir(ah->fname))) + { +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0050-Make-dynamic-hosts-files-work-when-no-hosts-set.patch b/src/patches/dnsmasq/0050-Make-dynamic-hosts-files-work-when-no-hosts-set.patch new file mode 100644 index 0000000..af79802 --- /dev/null +++ b/src/patches/dnsmasq/0050-Make-dynamic-hosts-files-work-when-no-hosts-set.patch @@ -0,0 +1,45 @@ +From caeea190f12efd20139f694aac4942d1ac00019f Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sat, 14 Feb 2015 20:08:56 +0000 +Subject: [PATCH 50/55] Make dynamic hosts files work when --no-hosts set. + +--- + src/cache.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/src/cache.c b/src/cache.c +index 43245b771b53..c95624c42b1c 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -1133,17 +1133,18 @@ void cache_reload(void) + { + if (daemon->cachesize > 0) + my_syslog(LOG_INFO, _("cleared cache")); +- return; + } +- +- if (!option_bool(OPT_NO_HOSTS)) +- total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz); +- +- daemon->addn_hosts = expand_filelist(daemon->addn_hosts); +- for (ah = daemon->addn_hosts; ah; ah = ah->next) +- if (!(ah->flags & AH_INACTIVE)) +- total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz); +- ++ else ++ { ++ if (!option_bool(OPT_NO_HOSTS)) ++ total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz); ++ ++ daemon->addn_hosts = expand_filelist(daemon->addn_hosts); ++ for (ah = daemon->addn_hosts; ah; ah = ah->next) ++ if (!(ah->flags & AH_INACTIVE)) ++ total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz); ++ } ++ + #ifdef HAVE_INOTIFY + set_dynamic_inotify(AH_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz); + #endif +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0051-Fix-trivial-memory-leaks-to-quieten-valgrind.patch b/src/patches/dnsmasq/0051-Fix-trivial-memory-leaks-to-quieten-valgrind.patch new file mode 100644 index 0000000..2c38cfc --- /dev/null +++ b/src/patches/dnsmasq/0051-Fix-trivial-memory-leaks-to-quieten-valgrind.patch @@ -0,0 +1,55 @@ +From 28b879ac47b872af6e8c5e86d76806c69338434d Mon Sep 17 00:00:00 2001 +From: Chen Wei weichen302@icloud.com +Date: Tue, 17 Feb 2015 22:07:35 +0000 +Subject: [PATCH 51/55] Fix trivial memory leaks to quieten valgrind. + +--- + src/dnsmasq.c | 2 ++ + src/option.c | 11 +++++++++-- + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index e903a24c8105..e6dabbf556f7 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -627,6 +627,8 @@ int main (int argc, char **argv) + } + + #ifdef HAVE_LINUX_NETWORK ++ free(hdr); ++ free(data); + if (option_bool(OPT_DEBUG)) + prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); + #endif +diff --git a/src/option.c b/src/option.c +index e4b4865d07a5..ae0ad002d8b8 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -4361,7 +4361,7 @@ void read_opts(int argc, char **argv, char *compile_opts) + { + char *buff = opt_malloc(MAXDNAME); + int option, conffile_opt = '7', testmode = 0; +- char *arg, *conffile = CONFFILE; ++ char *arg, *conffile = NULL; + + opterr = 0; + +@@ -4476,7 +4476,14 @@ void read_opts(int argc, char **argv, char *compile_opts) + } + + if (conffile) +- one_file(conffile, conffile_opt); ++ { ++ one_file(conffile, conffile_opt); ++ free(conffile); ++ } ++ else ++ { ++ one_file(CONFFILE, conffile_opt); ++ } + + /* port might not be known when the address is parsed - fill in here */ + if (daemon->servers) +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0052-Fix-uninitialized-value-used-in-get_client_mac.patch b/src/patches/dnsmasq/0052-Fix-uninitialized-value-used-in-get_client_mac.patch new file mode 100644 index 0000000..46277fb --- /dev/null +++ b/src/patches/dnsmasq/0052-Fix-uninitialized-value-used-in-get_client_mac.patch @@ -0,0 +1,27 @@ +From 0705a7e2d57654b27c7e14f35ca77241c1821f4d Mon Sep 17 00:00:00 2001 +From: Tomas Hozza thozza@redhat.com +Date: Mon, 23 Feb 2015 21:26:26 +0000 +Subject: [PATCH 52/55] Fix uninitialized value used in get_client_mac() + +--- + src/dhcp6.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/dhcp6.c b/src/dhcp6.c +index 3c56e77c6085..c7144f5fee7c 100644 +--- a/src/dhcp6.c ++++ b/src/dhcp6.c +@@ -246,7 +246,9 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsi + neigh.code = 0; + neigh.reserved = 0; + neigh.target = *client; +- ++ /* RFC4443 section-2.3: checksum has to be zero to be calculated */ ++ neigh.checksum = 0; ++ + memset(&addr, 0, sizeof(addr)); + #ifdef HAVE_SOCKADDR_SA_LEN + addr.sin6_len = sizeof(struct sockaddr_in6); +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0053-Log-parsing-utils-in-contrib-reverse-dns.patch b/src/patches/dnsmasq/0053-Log-parsing-utils-in-contrib-reverse-dns.patch new file mode 100644 index 0000000..9527030 --- /dev/null +++ b/src/patches/dnsmasq/0053-Log-parsing-utils-in-contrib-reverse-dns.patch @@ -0,0 +1,110 @@ +From 47b9ac59c715827252ae6e6732903c3dabb697fb Mon Sep 17 00:00:00 2001 +From: Joachim Zobel jz-2014@heute-morgen.de +Date: Mon, 23 Feb 2015 21:38:11 +0000 +Subject: [PATCH 53/55] Log parsing utils in contrib/reverse-dns + +--- + contrib/reverse-dns/README | 18 ++++++++++++++++++ + contrib/reverse-dns/reverse_dns.sh | 29 +++++++++++++++++++++++++++++ + contrib/reverse-dns/reverse_replace.sh | 28 ++++++++++++++++++++++++++++ + 3 files changed, 75 insertions(+) + create mode 100644 contrib/reverse-dns/README + create mode 100644 contrib/reverse-dns/reverse_dns.sh + create mode 100644 contrib/reverse-dns/reverse_replace.sh + +diff --git a/contrib/reverse-dns/README b/contrib/reverse-dns/README +new file mode 100644 +index 000000000000..f87eb77c4c22 +--- /dev/null ++++ b/contrib/reverse-dns/README +@@ -0,0 +1,18 @@ ++Hi. ++ ++To translate my routers netstat-nat output into names that actually talk ++to me I have started writing to simple shell scripts. They require ++ ++log-queries ++log-facility=/var/log/dnsmasq.log ++ ++to be set. With ++ ++netstat-nat -n -4 | reverse_replace.sh ++ ++I get retranslated output. ++ ++Sincerely, ++Joachim ++ ++ +diff --git a/contrib/reverse-dns/reverse_dns.sh b/contrib/reverse-dns/reverse_dns.sh +new file mode 100644 +index 000000000000..c0fff300a947 +--- /dev/null ++++ b/contrib/reverse-dns/reverse_dns.sh +@@ -0,0 +1,29 @@ ++#!/bin/bash ++# $Id: reverse_dns.sh 4 2015-02-17 20:14:59Z jo $ ++# ++# Usage: reverse_dns.sh IP ++# Uses the dnsmasq query log to lookup the name ++# that was last queried to return the given IP. ++# ++ ++IP=$1 ++qmIP=`echo $IP | sed 's#.#\.#g'` ++LOG=/var/log/dnsmasq.log ++ ++IP_regex='^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$' ++ ++if ! [[ $IP =~ $IP_regex ]]; then ++ echo -n $IP ++ exit ++fi ++ ++NAME=`tac $LOG | \ ++ grep " is $IP" | head -1 | \ ++ sed "s#.* ([^ ]*) is $qmIP.*#\1#" ` ++ ++if [ -z "$NAME" ]; then ++ echo -n $IP ++else ++ echo -n $NAME ++fi ++ +diff --git a/contrib/reverse-dns/reverse_replace.sh b/contrib/reverse-dns/reverse_replace.sh +new file mode 100644 +index 000000000000..a11c164b7f19 +--- /dev/null ++++ b/contrib/reverse-dns/reverse_replace.sh +@@ -0,0 +1,28 @@ ++#!/bin/bash ++# $Id: reverse_replace.sh 4 2015-02-17 20:14:59Z jo $ ++# ++# Usage e.g.: netstat -n -4 | reverse_replace.sh ++# Parses stdin for IP4 addresses and replaces them ++# with names retrieved by reverse_dns.sh ++# ++ ++DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) ++DNS=$DIR/reverse_dns.sh ++ ++# sed regex ++IP_regex='[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}' ++ ++while read LINE; do ++ if grep --quiet $IP_regex <<< "$LINE"; then ++ IPs=`sed "s#.*\b($IP_regex)\b.*#\1 #g" <<< "$LINE"` ++ IPs=($IPs) ++ for IP in "${IPs[@]}" ++ do ++ NAME=`$DNS $IP` ++ # echo "$NAME is $IP"; ++ LINE="${LINE/$IP/$NAME}" ++ done ++ fi ++ echo $LINE ++done < /dev/stdin ++ +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0054-Add-dnssec-timestamp-option-and-facility.patch b/src/patches/dnsmasq/0054-Add-dnssec-timestamp-option-and-facility.patch new file mode 100644 index 0000000..2ff79d5 --- /dev/null +++ b/src/patches/dnsmasq/0054-Add-dnssec-timestamp-option-and-facility.patch @@ -0,0 +1,252 @@ +From f6e62e2af96f5fa0d1e3d93167a93a8f09bf6e61 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sun, 1 Mar 2015 18:17:54 +0000 +Subject: [PATCH 54/55] Add --dnssec-timestamp option and facility. + +--- + CHANGELOG | 6 +++++ + man/dnsmasq.8 | 6 +++++ + src/dnsmasq.c | 11 +++++++- + src/dnsmasq.h | 2 ++ + src/dnssec.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- + src/option.c | 7 +++++ + 6 files changed, 108 insertions(+), 6 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index c80dc0fdbe9e..4f4fa305deaa 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -66,6 +66,12 @@ version 2.73 + for the patch. + + Fix broken DNSSEC validation of ECDSA signatures. ++ ++ Add --dnssec-timestamp option, which provides an automatic ++ way to detect when the system time becomes valid after boot ++ on systems without an RTC, whilst allowing DNS queries before the ++ clock is valid so that NTP can run. Thanks to ++ Kevin Darbyshire-Bryant for developing this idea. + + + version 2.72 +diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 +index 5cdd186afaa0..097e7d75145c 100644 +--- a/man/dnsmasq.8 ++++ b/man/dnsmasq.8 +@@ -674,6 +674,12 @@ that dnsmasq should be started with this flag when the platform determines that + reliable time is established, a SIGHUP should be sent to dnsmasq, which enables time checking, and purges the cache of DNS records + which have not been throughly checked. + .TP ++.B --dnssec-timestamp=<path> ++Enables an alternative way of checking the validity of the system time for DNSSEC (see --dnssec-no-timecheck). In this case, the ++system time is considered to be valid once it becomes later than the timestamp on the specified file. The file is created and ++its timestamp set automatically by dnsmasq. The file must be stored on a persistent filesystem, so that it and its mtime are carried ++over system restarts. ++.TP + .B --proxy-dnssec + Copy the DNSSEC Authenticated Data bit from upstream servers to downstream clients and cache it. This is an + alternative to having dnsmasq validate DNSSEC, but it depends on the security of the network between +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index e6dabbf556f7..769a19afe6c5 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -58,6 +58,9 @@ int main (int argc, char **argv) + struct dhcp_context *context; + struct dhcp_relay *relay; + #endif ++#ifdef HAVE_DNSSEC ++ int badtime; ++#endif + + #ifdef LOCALEDIR + setlocale(LC_ALL, ""); +@@ -369,7 +372,11 @@ int main (int argc, char **argv) + + if (baduser) + die(_("unknown user or group: %s"), baduser, EC_BADCONF); +- ++ ++#ifdef HAVE_DNSSEC ++ badtime = setup_timestamp(ent_pw->pw_uid); ++#endif ++ + /* implement group defaults, "dip" if available, or group associated with uid */ + if (!daemon->group_set && !gp) + { +@@ -689,6 +696,8 @@ int main (int argc, char **argv) + my_syslog(LOG_INFO, _("DNSSEC validation enabled")); + if (option_bool(OPT_DNSSEC_TIME)) + my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload")); ++ if (badtime) ++ my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid")); + } + #endif + +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 89e758b56a0a..b2f02dda63f0 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -986,6 +986,7 @@ extern struct daemon { + #endif + #ifdef HAVE_DNSSEC + struct ds_config *ds; ++ char *timestamp_file; + #endif + + /* globally used stuff for DNS */ +@@ -1151,6 +1152,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char + 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); ++int setup_timestamp(uid_t uid); + + /* util.c */ + void rand_init(void); +diff --git a/src/dnssec.c b/src/dnssec.c +index 26932373cd3e..bf4406469de0 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -34,6 +34,7 @@ + #include <nettle/dsa-compat.h> + #endif + ++#include <utime.h> + + #define SERIAL_UNDEF -100 + #define SERIAL_EQ 0 +@@ -394,17 +395,88 @@ static int serial_compare_32(unsigned long s1, unsigned long s2) + return SERIAL_UNDEF; + } + ++/* Called at startup. If the timestamp file is configured and exists, put its mtime on ++ timestamp_time. If it doesn't exist, create it, and set the mtime to 1-1-2015. ++ Change the ownership to the user we'll be running as, so that we can update the mtime. ++*/ ++static time_t timestamp_time; ++static int back_to_the_future; ++ ++int setup_timestamp(uid_t uid) ++{ ++ struct stat statbuf; ++ ++ back_to_the_future = 0; ++ ++ if (!option_bool(OPT_DNSSEC_VALID) || !daemon->timestamp_file) ++ return 0; ++ ++ if (stat(daemon->timestamp_file, &statbuf) != -1) ++ { ++ timestamp_time = statbuf.st_mtime; ++ check_and_exit: ++ if (difftime(timestamp_time, time(0)) <= 0) ++ { ++ /* time already OK, update timestamp, and do key checking from the start. */ ++ if (utime(daemon->timestamp_file, NULL) == -1) ++ my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno)); ++ back_to_the_future = 1; ++ return 0; ++ } ++ return 1; ++ } ++ ++ if (errno == ENOENT) ++ { ++ int fd = open(daemon->timestamp_file, O_WRONLY | O_CREAT | O_NONBLOCK, 0666); ++ if (fd != -1) ++ { ++ struct utimbuf timbuf; ++ ++ close(fd); ++ ++ timestamp_time = timbuf.actime = timbuf.modtime = 1420070400; /* 1-1-2015 */ ++ if (utime(daemon->timestamp_file, &timbuf) == 0 && ++ (getuid() != 0 || chown(daemon->timestamp_file, uid, -1) == 0)) ++ goto check_and_exit; ++ } ++ } ++ ++ die(_("Cannot create timestamp file %s: %s" ), daemon->timestamp_file, EC_BADCONF); ++ return 0; ++} ++ + /* Check whether today/now is between date_start and date_end */ + static int check_date_range(unsigned long date_start, unsigned long date_end) + { +- unsigned long curtime; +- ++ unsigned long curtime = time(0); ++ + /* Checking timestamps may be temporarily disabled */ +- if (option_bool(OPT_DNSSEC_TIME)) ++ ++ /* If the current time if _before_ the timestamp ++ on our persistent timestamp file, then assume the ++ time if not yet correct, and don't check the ++ key timestamps. As soon as the current time is ++ later then the timestamp, update the timestamp ++ and start checking keys */ ++ if (daemon->timestamp_file) ++ { ++ if (back_to_the_future == 0 && difftime(timestamp_time, curtime) <= 0) ++ { ++ if (utime(daemon->timestamp_file, NULL) != 0) ++ my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno)); ++ ++ back_to_the_future = 1; ++ set_option_bool(OPT_DNSSEC_TIME); ++ queue_event(EVENT_RELOAD); /* purge cache */ ++ } ++ ++ if (back_to_the_future == 0) ++ return 1; ++ } ++ else if (option_bool(OPT_DNSSEC_TIME)) + return 1; + +- curtime = time(0); +- + /* We must explicitly check against wanted values, because of SERIAL_UNDEF */ + return serial_compare_32(curtime, date_start) == SERIAL_GT + && serial_compare_32(curtime, date_end) == SERIAL_LT; +diff --git a/src/option.c b/src/option.c +index ae0ad002d8b8..eace40bb566c 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -152,6 +152,7 @@ struct myoption { + #define LOPT_DHCP_INOTIFY 340 + #define LOPT_DHOPT_INOTIFY 341 + #define LOPT_HOST_INOTIFY 342 ++#define LOPT_DNSSEC_STAMP 343 + + #ifdef HAVE_GETOPT_LONG + static const struct option opts[] = +@@ -300,6 +301,7 @@ static const struct myoption opts[] = + { "dnssec-debug", 0, 0, LOPT_DNSSEC_DEBUG }, + { "dnssec-check-unsigned", 0, 0, LOPT_DNSSEC_CHECK }, + { "dnssec-no-timecheck", 0, 0, LOPT_DNSSEC_TIME }, ++ { "dnssec-timestamp", 1, 0, LOPT_DNSSEC_STAMP }, + #ifdef OPTION6_PREFIX_CLASS + { "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS }, + #endif +@@ -463,6 +465,7 @@ static struct { + { LOPT_DNSSEC_DEBUG, OPT_DNSSEC_DEBUG, NULL, gettext_noop("Disable upstream checking for DNSSEC debugging."), NULL }, + { LOPT_DNSSEC_CHECK, OPT_DNSSEC_NO_SIGN, NULL, gettext_noop("Ensure answers without DNSSEC are in unsigned zones."), NULL }, + { LOPT_DNSSEC_TIME, OPT_DNSSEC_TIME, NULL, gettext_noop("Don't check DNSSEC signature timestamps until first cache-reload"), NULL }, ++ { LOPT_DNSSEC_STAMP, ARG_ONE, "<path>", gettext_noop("Timestamp file to verify system clock for DNSSEC"), NULL }, + #ifdef OPTION6_PREFIX_CLASS + { LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL }, + #endif +@@ -3867,6 +3870,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + } + + #ifdef HAVE_DNSSEC ++ case LOPT_DNSSEC_STAMP: ++ daemon->timestamp_file = opt_string_alloc(arg); ++ break; ++ + case LOPT_TRUST_ANCHOR: + { + struct ds_config *new = opt_malloc(sizeof(struct ds_config)); +-- +2.1.0 + diff --git a/src/patches/dnsmasq/0055-Fix-last-commit-to-not-crash-if-uid-changing-not-con.patch b/src/patches/dnsmasq/0055-Fix-last-commit-to-not-crash-if-uid-changing-not-con.patch new file mode 100644 index 0000000..54bb5d5 --- /dev/null +++ b/src/patches/dnsmasq/0055-Fix-last-commit-to-not-crash-if-uid-changing-not-con.patch @@ -0,0 +1,63 @@ +From 9003b50b13da624ca45f3e0cf99abb623b8d026b Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Mon, 2 Mar 2015 22:47:23 +0000 +Subject: [PATCH 55/55] Fix last commit to not crash if uid changing not + configured. + +--- + src/dnsmasq.c | 2 +- + src/dnsmasq.h | 2 +- + src/dnssec.c | 4 ++-- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index 769a19afe6c5..9e05c0e31569 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -374,7 +374,7 @@ int main (int argc, char **argv) + die(_("unknown user or group: %s"), baduser, EC_BADCONF); + + #ifdef HAVE_DNSSEC +- badtime = setup_timestamp(ent_pw->pw_uid); ++ badtime = setup_timestamp(ent_pw); + #endif + + /* implement group defaults, "dip" if available, or group associated with uid */ +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index b2f02dda63f0..a451cb4dd03c 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -1152,7 +1152,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char + 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); +-int setup_timestamp(uid_t uid); ++int setup_timestamp(struct passwd *ent_pw); + + /* util.c */ + void rand_init(void); +diff --git a/src/dnssec.c b/src/dnssec.c +index bf4406469de0..c60eacf73c6b 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -402,7 +402,7 @@ static int serial_compare_32(unsigned long s1, unsigned long s2) + static time_t timestamp_time; + static int back_to_the_future; + +-int setup_timestamp(uid_t uid) ++int setup_timestamp(struct passwd *ent_pw) + { + struct stat statbuf; + +@@ -437,7 +437,7 @@ int setup_timestamp(uid_t uid) + + timestamp_time = timbuf.actime = timbuf.modtime = 1420070400; /* 1-1-2015 */ + if (utime(daemon->timestamp_file, &timbuf) == 0 && +- (getuid() != 0 || chown(daemon->timestamp_file, uid, -1) == 0)) ++ (!ent_pw || getuid() != 0 || chown(daemon->timestamp_file, ent_pw->pw_uid, -1) == 0)) + goto check_and_exit; + } + } +-- +2.1.0 + diff --git a/src/patches/strongswan-5.2.2-issue-816-650a3ad.patch b/src/patches/strongswan-5.2.2-issue-816-650a3ad.patch new file mode 100644 index 0000000..44b247e --- /dev/null +++ b/src/patches/strongswan-5.2.2-issue-816-650a3ad.patch @@ -0,0 +1,35 @@ +commit 650a3ad5151958b99a95836fb8b84b8aa18da1be +Author: Tobias Brunner tobias@strongswan.org +Date: Wed Feb 25 08:09:11 2015 +0100 + + ike-sa-manager: Make sure the message ID of initial messages is 0 + + It is mandated by the RFCs and it is expected by the task managers. + + Initial messages with invalid MID will be treated like regular messages, + so no IKE_SA will be created for them. Instead, if the responder SPI is 0 + no SA will be found and the message is rejected with ALERT_INVALID_IKE_SPI. + If an SPI is set and we do find an SA, then we either ignore the message + because the MID is unexpected, or because we don't allow initial messages + on established connections. + + There is one exception, though, if an attacker can slip in an IKE_SA_INIT + with both SPIs set before the client's IKE_AUTH is handled by the server, + it does get processed (see next commit). + + References #816. + +diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c +index d0cbd47..5e2b925 100644 +--- a/src/libcharon/sa/ike_sa_manager.c ++++ b/src/libcharon/sa/ike_sa_manager.c +@@ -1184,7 +1184,8 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, + + DBG2(DBG_MGR, "checkout IKE_SA by message"); + +- if (id->get_responder_spi(id) == 0) ++ if (id->get_responder_spi(id) == 0 && ++ message->get_message_id(message) == 0) + { + if (message->get_major_version(message) == IKEV2_MAJOR_VERSION) + { diff --git a/src/patches/strongswan-5.2.2-issue-816-dd0ebb.patch b/src/patches/strongswan-5.2.2-issue-816-dd0ebb.patch new file mode 100644 index 0000000..4d76e7c --- /dev/null +++ b/src/patches/strongswan-5.2.2-issue-816-dd0ebb.patch @@ -0,0 +1,42 @@ +commit dd0ebb54837298c869389d36a0b42eefdb893dd6 +Author: Tobias Brunner tobias@strongswan.org +Date: Wed Feb 25 08:30:33 2015 +0100 + + ikev2: Only accept initial messages in specific states + + The previous code allowed an attacker to slip in an IKE_SA_INIT with + both SPIs and MID 1 set when an IKE_AUTH would be expected instead. + + References #816. + +diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c +index be84e71..540d4dc 100644 +--- a/src/libcharon/sa/ikev2/task_manager_v2.c ++++ b/src/libcharon/sa/ikev2/task_manager_v2.c +@@ -1304,17 +1304,16 @@ METHOD(task_manager_t, process_message, status_t, + { + if (mid == this->responding.mid) + { +- /* reject initial messages once established */ +- if (msg->get_exchange_type(msg) == IKE_SA_INIT || +- msg->get_exchange_type(msg) == IKE_AUTH) ++ /* reject initial messages if not received in specific states */ ++ if ((msg->get_exchange_type(msg) == IKE_SA_INIT && ++ this->ike_sa->get_state(this->ike_sa) != IKE_CREATED) || ++ (msg->get_exchange_type(msg) == IKE_AUTH && ++ this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)) + { +- if (this->ike_sa->get_state(this->ike_sa) != IKE_CREATED && +- this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING) +- { +- DBG1(DBG_IKE, "ignoring %N in established IKE_SA state", +- exchange_type_names, msg->get_exchange_type(msg)); +- return FAILED; +- } ++ DBG1(DBG_IKE, "ignoring %N in IKE_SA state %N", ++ exchange_type_names, msg->get_exchange_type(msg), ++ ike_sa_state_names, this->ike_sa->get_state(this->ike_sa)); ++ return FAILED; + } + if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE)) + { /* with MOBIKE, we do no implicit updates */ diff --git a/src/patches/strongswan-5.2.2-issue-816-eb25190.patch b/src/patches/strongswan-5.2.2-issue-816-eb25190.patch new file mode 100644 index 0000000..8dcb32b --- /dev/null +++ b/src/patches/strongswan-5.2.2-issue-816-eb25190.patch @@ -0,0 +1,31 @@ +commit eb251906298b529fa53b8a99746a9a7a9f318dd5 +Author: Tobias Brunner tobias@strongswan.org +Date: Wed Feb 25 08:18:58 2015 +0100 + + ikev2: Don't destroy the SA if an IKE_SA_INIT with unexpected MID is received + + This reverts 8f727d800751 ("Clean up IKE_SA state if IKE_SA_INIT request + does not have message ID 0") because it allowed to close any IKE_SA by + sending an IKE_SA_INIT with an unexpected MID and both SPIs set to those + of that SA. + + The next commit will prevent SAs from getting created for IKE_SA_INIT messages + with invalid MID. + + Fixes #816. + +diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c +index 48266aa..be84e71 100644 +--- a/src/libcharon/sa/ikev2/task_manager_v2.c ++++ b/src/libcharon/sa/ikev2/task_manager_v2.c +@@ -1355,10 +1355,6 @@ METHOD(task_manager_t, process_message, status_t, + { + DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored", + mid, this->responding.mid); +- if (msg->get_exchange_type(msg) == IKE_SA_INIT) +- { /* clean up IKE_SA state if IKE_SA_INIT has invalid msg ID */ +- return DESTROY_ME; +- } + } + } + else diff --git a/src/patches/strongswan-5.2.2-issue-816.patch b/src/patches/strongswan-5.2.2-issue-816.patch deleted file mode 100644 index d9dfc8a..0000000 --- a/src/patches/strongswan-5.2.2-issue-816.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/t -index e9a677a655e4..69118abe78df 100644 ---- a/src/libcharon/sa/ikev2/task_manager_v2.c -+++ b/src/libcharon/sa/ikev2/task_manager_v2.c -@@ -1339,7 +1339,7 @@ METHOD(task_manager_t, process_message, status_t, - { - DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored", - mid, this->responding.mid); -- if (msg->get_exchange_type(msg) == IKE_SA_INIT) -+ if (mid != 0 && msg->get_exchange_type(msg) == IKE_SA_INIT) - { /* clean up IKE_SA state if IKE_SA_INIT has invalid msg ID */ - return DESTROY_ME; - }
hooks/post-receive -- IPFire 2.x development tree