Imported Upstream version 2.79 88/182188/1 upstream/2.79
authorSeonah Moon <seonah1.moon@samsung.com>
Thu, 21 Jun 2018 06:44:41 +0000 (15:44 +0900)
committerSeonah Moon <seonah1.moon@samsung.com>
Thu, 21 Jun 2018 06:45:21 +0000 (15:45 +0900)
Change-Id: I9a2f4c945e0481ab803bdf0c85921433f33a9256
Signed-off-by: Seonah Moon <seonah1.moon@samsung.com>
89 files changed:
.gitattributes [new file with mode: 0644]
CHANGELOG
CHANGELOG.archive
FAQ
Makefile
VERSION
bld/Android.mk
bld/get-version
contrib/MacOSX-launchd/launchd-README.txt
contrib/Suse/README.susefirewall
contrib/conntrack/README
contrib/lease-access/lease.access.patch
contrib/lease-tools/Makefile [new file with mode: 0644]
contrib/lease-tools/dhcp_lease_time.1 [moved from contrib/wrt/dhcp_lease_time.1 with 100% similarity]
contrib/lease-tools/dhcp_lease_time.c [moved from contrib/wrt/dhcp_lease_time.c with 97% similarity]
contrib/lease-tools/dhcp_release.1 [moved from contrib/wrt/dhcp_release.1 with 100% similarity]
contrib/lease-tools/dhcp_release.c [moved from contrib/wrt/dhcp_release.c with 98% similarity]
contrib/lease-tools/dhcp_release6.1 [new file with mode: 0644]
contrib/lease-tools/dhcp_release6.c [new file with mode: 0644]
contrib/mactable/macscript
contrib/port-forward/portforward
contrib/reverse-dns/README
contrib/reverse-dns/reverse_replace.sh
contrib/systemd/dbus_activation
contrib/try-all-ns/README-2.47
contrib/try-all-ns/README-2.78 [new file with mode: 0644]
contrib/try-all-ns/dnsmasq-2.78xx-try-all-ns.patch [new file with mode: 0644]
contrib/webmin/README
contrib/wrt/Makefile [deleted file]
contrib/wrt/README
dnsmasq.conf.example
doc.html
man/dnsmasq.8
man/fr/dnsmasq.8
po/de.po
po/es.po
po/fi.po
po/fr.po
po/id.po
po/it.po
po/no.po
po/pl.po
po/pt_BR.po
po/ro.po
setup.html
src/arp.c [new file with mode: 0644]
src/auth.c
src/blockdata.c
src/bpf.c
src/cache.c
src/config.h
src/conntrack.c
src/crypto.c [new file with mode: 0644]
src/dbus.c
src/dhcp-common.c
src/dhcp-protocol.h
src/dhcp.c
src/dhcp6-protocol.h
src/dhcp6.c
src/dns-protocol.h
src/dnsmasq.c
src/dnsmasq.h
src/dnssec.c
src/domain.c
src/edns0.c [new file with mode: 0644]
src/forward.c
src/helper.c
src/inotify.c
src/ip6addr.h
src/ipset.c
src/lease.c
src/log.c
src/loop.c
src/netlink.c
src/network.c
src/option.c
src/outpacket.c
src/poll.c
src/radv-protocol.h
src/radv.c
src/rfc1035.c
src/rfc2131.c
src/rfc3315.c
src/rrfilter.c [new file with mode: 0644]
src/slaac.c
src/tables.c
src/tftp.c
src/util.c
trust-anchors.conf

diff --git a/.gitattributes b/.gitattributes
new file mode 100644 (file)
index 0000000..5f72683
--- /dev/null
@@ -0,0 +1 @@
+VERSION export-subst
index 7c621e2..b32d95d 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
+version 2.79
+       Fix parsing of CNAME arguments, which are confused by extra spaces.
+       Thanks to Diego Aguirre for spotting the bug.
+
+       Where available, use IP_UNICAST_IF or IPV6_UNICAST_IF to bind
+       upstream servers to an interface, rather than SO_BINDTODEVICE.
+       Thanks to Beniamino Galvani for the patch.
+
+       Always return a SERVFAIL answer to DNS queries without the
+       recursion desired bit set, UNLESS acting as an authoritative
+       DNS server. This avoids a potential route to cache snooping.
+
+       Add support for Ed25519 signatures in DNSSEC validation.
+
+       No longer support RSA/MD5 signatures in DNSSEC validation,
+       since these are not secure. This behaviour is mandated in
+       RFC-6944.
+
+       Fix incorrect error exit code from dhcp_release6 utility.
+       Thanks Gaudenz Steinlin for the bug report.
+
+       Use SIGINT (instead of overloading SIGHUP) to turn on DNSSEC
+       time validation when --dnssec-no-timecheck is in use.
+       Note that this is an incompatible change from earlier releases.
+
+       Allow more than one --bridge-interface option to refer to an
+       interface, so that we can use
+       --bridge-interface=int1,alias1
+       --bridge-interface=int1,alias2
+       as an alternative to
+       --bridge-interface=int1,alias1,alias2
+       Thanks to Neil Jerram for work on this.
+
+       Fix for DNSSEC with wildcard-derived NSEC records.
+       It's OK for NSEC records to be expanded from wildcards,
+       but in that case, the proof of non-existence is only valid
+       starting at the wildcard name, *.<domain> NOT the name expanded
+       from the wildcard. Without this check it's possible for an
+       attacker to craft an NSEC which wrongly proves non-existence.
+       Thanks to Ralph Dolmans for finding this, and co-ordinating 
+       the vulnerability tracking and fix release.
+       CVE-2017-15107 applies.
+
+       Remove special handling of A-for-A DNS queries. These
+       are no longer a significant problem in the global DNS.
+       http://cs.northwestern.edu/~ychen/Papers/DNS_ToN15.pdf
+       Thanks to Mattias Hellström for the initial patch.
+
+       Fix failure to delete dynamically created dhcp options
+       from files in -dhcp-optsdir directories. Thanks to
+       Lindgren Fredrik for the bug report.
+
+       Add to --synth-domain the ability to create names using
+       sequential numbers, as well as encodings of IP addresses.
+       For instance,
+       --synth-domain=thekelleys.org.uk,192.168.0.50,192.168.0.70,internal-*
+       creates 21 domain names of the form
+       internal-4.thekelleys.org.uk over the address range given, with
+       internal-0.thekelleys.org.uk being 192.168.0.50 and
+       internal-20.thekelleys.org.uk being 192.168.0.70
+       Thanks to Andy Hawkins for the suggestion.
+
+       Tidy up Crypto code, removing workarounds for ancient
+       versions of libnettle. We now require libnettle 3.
+
+
+version 2.78
+        Fix logic of appending ".<layer>" to PXE basename. Thanks to Chris
+       Novakovic for the patch.
+
+       Revert ping-check of address in DHCPDISCOVER if there
+       already exists a lease for the address. Under some
+       circumstances, and netbooted windows installation can reply
+       to pings before if has a DHCP lease and block allocation
+       of the address it already used during netboot. Thanks to
+       Jan Psota for spotting this.
+
+       Fix DHCP relaying, broken in 2.76 and 2.77 by commit
+       ff325644c7afae2588583f935f4ea9b9694eb52e. Thanks to
+       John Fitzgibbon for the diagnosis and patch.
+
+        Try other servers if first returns REFUSED when
+       --strict-order active. Thanks to Hans Dedecker
+       for the patch
+
+       Fix regression in 2.77, ironically added as a security
+       improvement, which resulted in a crash when a DNS
+       query exceeded 512 bytes (or the EDNS0 packet size,
+       if different.) Thanks to Christian Kujau, Arne Woerner
+       Juan Manuel Fernandez and Kevin Darbyshire-Bryant for
+       chasing this one down.  CVE-2017-13704 applies.
+
+       Fix heap overflow in DNS code. This is a potentially serious
+       security hole. It allows an attacker who can make DNS
+       requests to dnsmasq, and who controls the contents of
+       a domain, which is thereby queried, to overflow
+       (by 2 bytes) a heap buffer and either crash, or
+       even take control of, dnsmasq.
+       CVE-2017-14491 applies.
+       Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
+       Kevin Hamacher and Ron Bowes of the Google Security Team for
+       finding this.
+
+       Fix heap overflow in IPv6 router advertisement code.
+       This is a potentially serious security hole, as a
+       crafted RA request can overflow a buffer and crash or
+       control dnsmasq. Attacker must be on the local network.
+       CVE-2017-14492 applies.
+        Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
+       and Kevin Hamacher of the Google Security Team for
+       finding this.
+
+       Fix stack overflow in DHCPv6 code. An attacker who can send
+       a DHCPv6 request to dnsmasq can overflow the stack frame and
+       crash or control dnsmasq.
+       CVE-2017-14493 applies.
+       Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
+       Kevin Hamacher and Ron Bowes of the Google Security Team for
+       finding this.
+
+       Fix information leak in DHCPv6. A crafted DHCPv6 packet can
+       cause dnsmasq to forward memory from outside the packet
+       buffer to a DHCPv6 server when acting as a relay.
+       CVE-2017-14494 applies.
+       Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
+       Kevin Hamacher and Ron Bowes of the Google Security Team for
+       finding this.
+
+       Fix DoS in DNS. Invalid boundary checks in the
+       add_pseudoheader function allows a memcpy call with negative
+       size An attacker which can send malicious DNS queries
+       to dnsmasq can trigger a DoS remotely.
+       dnsmasq is vulnerable only if one of the following option is
+       specified: --add-mac, --add-cpe-id or --add-subnet.
+       CVE-2017-14496 applies.
+       Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
+       Kevin Hamacher and Ron Bowes of the Google Security Team for
+       finding this.
+
+       Fix out-of-memory Dos vulnerability. An attacker which can
+       send malicious DNS queries to dnsmasq can trigger memory
+       allocations in the add_pseudoheader function
+       The allocated memory is never freed which leads to a DoS
+       through memory exhaustion. dnsmasq is vulnerable only
+       if one of the following option is specified:
+       --add-mac, --add-cpe-id or --add-subnet.
+       CVE-2017-14495 applies.
+       Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
+       Kevin Hamacher and Ron Bowes of the Google Security Team for
+       finding this.
+
+
+version 2.77
+       Generate an error when configured with a CNAME loop,
+       rather than a crash. Thanks to George Metz for
+       spotting this problem.
+
+       Calculate the length of TFTP error reply packet 
+       correctly. This fixes a problem when the error 
+       message in a TFTP packet exceeds the arbitrary 
+       limit of 500 characters. The message was correctly
+       truncated, but not the packet length, so 
+       extra data was appended. This is a possible
+       security risk, since the extra data comes from
+       a buffer which is also used for DNS, so that
+       previous DNS queries or replies may be leaked.
+       Thanks to Mozilla for funding the security audit 
+       which spotted this bug.
+
+       Fix logic error in Linux netlink code. This could
+       cause dnsmasq to enter a tight loop on systems
+       with a very large number of network interfaces.
+       Thanks to Ivan Kokshaysky for the diagnosis and
+       patch.
+
+       Fix problem with --dnssec-timestamp whereby receipt
+       of SIGHUP would erroneously engage timestamp checking.
+       Thanks to Kevin Darbyshire-Bryant for this work.
+
+       Bump zone serial on reloading /etc/hosts and friends
+       when providing authoritative DNS. Thanks to Harrald
+       Dunkel for spotting this.
+
+       Handle v4-mapped IPv6 addresses sanely in --synth-domain.
+       These have standard representation like ::ffff:1.2.3.4
+       and are now converted to names like
+       <prefix>--ffff-1-2-3-4.<domain>
+
+       Handle binding upstream servers to an interface 
+       (--server=1.2.3.4@eth0) when the named interface
+       is destroyed and recreated in the kernel. Thanks to 
+       Beniamino Galvani for the patch.
+
+       Allow wildcard CNAME records in authoritative zones.
+       For example --cname=*.example.com,default.example.com
+       Thanks to Pro Backup for sponsoring this development.
+
+       Bump the allowed backlog of TCP connections from 5 to 32,
+       and make this a compile-time configurable option. Thanks
+       to Donatas Abraitis for diagnosing this as a potential
+       problem.
+
+       Add DNSMASQ_REQUESTED_OPTIONS environment variable to the 
+       lease-change script. Thanks to ZHAO Yu for the patch.
+
+       Fix foobar in rrfilter code, that could cause malformed 
+       replies, especially when DNSSEC validation on, and 
+       the upstream server returns answer with the RRs in a 
+       particular order. The only DNS server known to tickle
+       this is Nominum's. Thanks to Dave Täht for spotting the
+       bug and assisting in the fix.
+
+       Fix the manpage which lied that only the primary address
+       of an interface is used by --interface-name.
+
+       Make --localise-queries apply to names from --interface-name.
+       Thanks to Kevin Darbyshire-Bryant and Eric Luehrsen
+       for pushing this.
+
+       Improve connection handling when talking to TCP upstream 
+       servers. Specifically, be prepared to open a new TCP
+       connection when we want to make multiple queries
+       but the upstream server accepts fewer queries per connection.
+
+       Improve logging of upstream servers when there are a lot
+       of "local addresses only" entries. Thanks to Hannu Nyman for
+       the patch.
+
+       Make --bogus-priv apply to IPv6, for the prefixes specified
+       in RFC6303. Thanks to Kevin Darbyshire-Bryant for work on this.
+
+       Allow use of MAC addresses with --tftp-unique-root. Thanks
+       to Floris Bos for the patch.
+
+       Add --dhcp-reply-delay option. Thanks to Floris Bos
+       for the patch.
+
+       Add mtu setting facility to --ra-param. Thanks to David
+       Flamand for the patch.
+
+       Capture STDOUT and STDERR output from dhcp-script and log
+       it as part of the dnsmasq log stream. Makes life easier
+       for diagnosing unexpected problems in scripts.
+       Thanks to Petr Mensik for the patch.
+
+       Generate fatal errors when failing to parse the output
+       of the dhcp-script in "init" mode. Avoids strange errors
+       when the script accidentally emits error messages.
+       Thanks to Petr Mensik for the patch.
+
+       Make --rev-server for an RFC1918 subnet work even in the
+       presence of the --bogus-priv flag. Thanks to
+       Vladislav Grishenko for the patch.
+
+       Extend --ra-param mtu: field to allow an interface name.
+       This allows the MTU of a WAN interface to be advertised on
+       the internal interfaces of a router. Thanks to
+       Vladislav Grishenko for the patch.
+
+       Do ICMP-ping check for address-in-use for DHCPv4 when
+       the client specifies an address in DHCPDISCOVER, and when
+       an address in configured locally. Thanks to Alin Năstac
+       for spotting the problem.
+
+       Add new DHCP tag "known-othernet" which is set when only a
+       dhcp-host exists for another subnet. Can be used to ensure
+       that privileged hosts are not given "guest" addresses by
+       accident. Thanks to Todd Sanket for the suggestion.
+
+       Remove historic automatic inclusion of IDN support when
+       building internationalisation support. This doesn't
+       fit now there is a choice of IDN libraries. Be sure
+       to include either -DHAVE_IDN or -DHAVE_LIBIDN2 for
+       IDN support.
+
+
+version 2.76
+       Include 0.0.0.0/8 in DNS rebind checks. This range 
+       translates to hosts on  the local network, or, at 
+       least, 0.0.0.0 accesses the local host, so could
+       be targets for DNS rebinding. See RFC 5735 section 3 
+       for details. Thanks to Stephen Röttger for the bug report.
+
+       Enhance --add-subnet to allow arbitrary subnet addresses.
+       Thanks to Ed Barsley for the patch.
+
+       Respect the --no-resolv flag in inotify code. Fixes bug
+       which caused dnsmasq to fail to start if a resolv-file 
+       was a dangling symbolic link, even of --no-resolv set.
+       Thanks to Alexander Kurtz for spotting the problem.
+
+       Fix crash when an A or AAAA record is defined locally,
+       in a hosts file, and an upstream server sends a reply
+       that the same name is empty. Thanks to Edwin Török for
+       the patch.
+
+       Fix failure to correctly calculate cache-size when 
+       reading a hosts-file fails. Thanks to André Glüpker 
+       for the patch.
+
+       Fix wrong answer to simple name query when --domain-needed
+       set, but no upstream servers configured. Dnsmasq returned
+       REFUSED, in this case, when it should be the same as when
+       upstream servers are configured - NOERROR. Thanks to 
+       Allain Legacy for spotting the problem.
+
+       Return REFUSED when running out of forwarding table slots,
+       not SERVFAIL.
+
+       Add --max-port configuration. Thanks to Hans Dedecker for
+       the patch.
+
+       Add --script-arp and two new functions for the dhcp-script.
+       These are "arp" and "arp-old" which announce the arrival and
+       removal of entries in the ARP or neighbour tables.
+
+       Extend --add-mac to allow a new encoding of the MAC address 
+       as base64, by configuring --add-mac=base64
+
+       Add --add-cpe-id option.
+
+       Don't crash with divide-by-zero if an IPv6 dhcp-range
+       is declared as a whole /64.
+       (ie xx::0 to xx::ffff:ffff:ffff:ffff) 
+       Thanks to Laurent Bendel for spotting this problem.
+
+       Add support for a TTL parameter in --host-record and
+       --cname.
+
+       Add --dhcp-ttl option.
+
+       Add --tftp-mtu option. Thanks to Patrick McLean for the 
+       initial patch.
+
+       Check return-code of inet_pton() when parsing dhcp-option.
+       Bad addresses could fail to generate errors and result in
+       garbage dhcp-options being sent. Thanks to Marc Branchaud 
+       for spotting this.
+
+       Fix wrong value for EDNS UDP packet size when using 
+       --servers-file to define upstream DNS servers. Thanks to
+       Scott Bonar for the bug report.
+
+       Move the dhcp_release and dhcp_lease_time tools from 
+       contrib/wrt to contrib/lease-tools.
+
+       Add dhcp_release6 to contrib/lease-tools. Many thanks 
+       to Sergey Nechaev for this code.
+
+       To avoid filling logs in configurations which define
+       many upstream nameservers, don't log more that 30 servers.
+       The number to be logged can be changed as SERVERS_LOGGED
+       in src/config.h.
+
+       Swap the values if BC_EFI and x86-64_EFI in --pxe-service. 
+       These were previously wrong due to an error in RFC 4578.
+       If you're using BC_EFI to boot 64-bit EFI machines, you
+       will need to update your config.
+
+       Add ARM32_EFI and ARM64_EFI as valid architectures in
+       --pxe-service.
+
+       Fix PXE booting for UEFI architectures. Modify PXE boot
+       sequence in this case to force the client to talk to dnsmasq
+       over port 4011. This makes PXE and especially proxy-DHCP PXE
+       work with these architectures.
+
+       Workaround problems with UEFI PXE clients. There exist
+       in the wild PXE clients which have problems with PXE
+       boot menus. To work around this, when there's a single
+       --pxe-service which applies to client, then that target
+       will be booted directly, rather then sending a
+       single-item boot menu.
+
+       Many thanks to Jarek Polok, Michael Kuron and Dreamcat4 
+       for their work on the long-standing UEFI PXE problem.
+
+       Subtle change in the semantics of "basename" in
+       --pxe-service. The historical behaviour has always been
+       that the actual filename downloaded from the TFTP server
+       is <basename>.<layer> where <layer> is an integer which
+       corresponds to the layer parameter supplied by the client.
+       It's not clear what the function of the "layer" 
+       actually is in the PXE protocol, and in practise layer 
+       is always zero, so the filename is <basename>.0
+       The new behaviour is the same as the old, except when
+       <basename> includes a file suffix, in which case
+       the layer suffix is no longer added. This allows
+       sensible suffices to be used, rather then the
+       meaningless ".0". Only in the unlikely event that you
+       have a config with a basename which already has a
+       suffix, is this an incompatible change, since the file
+       downloaded will change from name.suffix.0 to just 
+       name.suffix
+
+
+version 2.75
+       Fix reversion on 2.74 which caused 100% CPU use when a 
+       dhcp-script is configured. Thanks to Adrian Davey for
+       reporting the bug and testing the fix.
+
+
 version 2.74
-            Fix reversion in 2.73 where --conf-file would attempt to
-           read the default file, rather than no file.
+       Fix reversion in 2.73 where --conf-file would attempt to
+       read the default file, rather than no file.
 
-           Fix inotify code to handle dangling symlinks better and
-           not SEGV in some circumstances.
+       Fix inotify code to handle dangling symlinks better and
+       not SEGV in some circumstances.
+
+       DNSSEC fix. In the case of a signed CNAME generated by a
+       wildcard which pointed to an unsigned domain, the wrong
+       status would be logged, and some necessary checks omitted.
 
-           DNSSEC fix. In the case of a signed CNAME generated by a
-           wildcard which pointed to an unsigned domain, the wrong
-            status would be logged, and some necessary checks omitted.
-       
 
 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.
-
-           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. 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 
-           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.
-
-           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.
-       
-           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.
-
-           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.
-
-           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. 
-       
-           Don't reply to DHCPv6 SOLICIT messages if we're not 
-           configured to do stateful DHCPv6. Thanks to Win King Wan 
-           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.
-
-           Add --tftp-no-fail option. Thanks to Stefan Tomanek for
-           the patch.
-
-           Fix crash caused by looking up servers.bind, CHAOS text 
-           record, when more than about five --servers= lines are 
-           in the dnsmasq config. This causes memory corruption 
-           which causes a crash later. Thanks to Matt Coddington for 
-           sterling work chasing this down.
-
-           Fix crash on receipt of certain malformed DNS requests.
-           Thanks to Nick Sampanis for spotting the problem.
-           Note that this is could allow the dnsmasq process's
-           memory to be read by an attacker under certain
-           circumstances, so it has a CVE, CVE-2015-3294 
-
-            Fix crash in authoritative DNS code, if a .arpa zone 
-           is declared as authoritative, and then a PTR query which
-           is not to be treated as authoritative arrived. Normally, 
-           directly declaring .arpa zone as authoritative is not 
-           done, so this crash wouldn't be seen. Instead the 
-           relevant .arpa zone should be specified as a subnet
-           in the auth-zone declaration. Thanks to Johnny S. Lee
-           for the bugreport and initial patch.
-
-           Fix authoritative DNS code to correctly reply to NS 
-           and SOA queries for .arpa zones for which we are 
-           declared authoritative by means of a subnet in auth-zone.
-           Previously we provided correct answers to PTR queries
-           in such zones (including NS and SOA) but not direct
-           NS and SOA queries. Thanks to Johnny S. Lee for 
-           pointing out the problem.
-
-           Fix logging of DHCPREPLY which should be suppressed 
-           by quiet-dhcp6. Thanks to J. Pablo Abonia for 
-           spotting the problem.
-
-           Try and handle net connections with broken fragmentation 
-           that lose large UDP packets. If a server times out, 
-            reduce the maximum UDP packet size field in the EDNS0
-           header to 1280 bytes. If it then answers, make that
-           change permanent.
-
-           Check IPv4-mapped IPv6 addresses when --stop-rebind
-           is active. Thanks to Jordan Milne for spotting this.
-
-           Allow DHCPv4 options T1 and T2 to be set using --dhcp-option.
-           Thanks to Kevin Benton for patches and work on this.
-
-            Fix code for DHCPCONFIRM DHCPv6 messages to confirm addresses
-           in the correct subnet, even of not in dynamic address 
-           allocation range. Thanks to Steve Hirsch for spotting
-           the problem.
-
-           Add AddDhcpLease and DeleteDhcpLease DBus methods. Thanks
-           to Nicolas Cavallari for the patch.
-
-           Allow configuration of router advertisements without the 
-           "on-link" bit set. Thanks to Neil Jerram for the patch.
-
-           Extend --bridge-interface to DHCPv6 and router 
-           advertisements. Thanks to Neil Jerram for the patch.
-       
-       
+       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.
+
+       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. 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 
+       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.
+
+       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.
+
+       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.
+
+       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. Thanks 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.
+
+       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. 
+
+       Don't reply to DHCPv6 SOLICIT messages if we're not 
+       configured to do stateful DHCPv6. Thanks to Win King Wan 
+       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.
+
+       Add --tftp-no-fail option. Thanks to Stefan Tomanek for
+       the patch.
+
+       Fix crash caused by looking up servers.bind, CHAOS text 
+       record, when more than about five --servers= lines are 
+       in the dnsmasq config. This causes memory corruption 
+       which causes a crash later. Thanks to Matt Coddington for 
+       sterling work chasing this down.
+
+       Fix crash on receipt of certain malformed DNS requests.
+       Thanks to Nick Sampanis for spotting the problem.
+       Note that this is could allow the dnsmasq process's
+       memory to be read by an attacker under certain
+       circumstances, so it has a CVE, CVE-2015-3294 
+
+       Fix crash in authoritative DNS code, if a .arpa zone 
+       is declared as authoritative, and then a PTR query which
+       is not to be treated as authoritative arrived. Normally, 
+       directly declaring .arpa zone as authoritative is not 
+       done, so this crash wouldn't be seen. Instead the 
+       relevant .arpa zone should be specified as a subnet
+       in the auth-zone declaration. Thanks to Johnny S. Lee
+       for the bugreport and initial patch.
+
+       Fix authoritative DNS code to correctly reply to NS 
+       and SOA queries for .arpa zones for which we are 
+       declared authoritative by means of a subnet in auth-zone.
+       Previously we provided correct answers to PTR queries
+       in such zones (including NS and SOA) but not direct
+       NS and SOA queries. Thanks to Johnny S. Lee for 
+       pointing out the problem.
+
+       Fix logging of DHCPREPLY which should be suppressed 
+       by quiet-dhcp6. Thanks to J. Pablo Abonia for 
+       spotting the problem.
+
+       Try and handle net connections with broken fragmentation 
+       that lose large UDP packets. If a server times out, 
+       reduce the maximum UDP packet size field in the EDNS0
+       header to 1280 bytes. If it then answers, make that
+       change permanent.
+
+       Check IPv4-mapped IPv6 addresses when --stop-rebind
+       is active. Thanks to Jordan Milne for spotting this.
+
+       Allow DHCPv4 options T1 and T2 to be set using --dhcp-option.
+       Thanks to Kevin Benton for patches and work on this.
+
+       Fix code for DHCPCONFIRM DHCPv6 messages to confirm addresses
+       in the correct subnet, even of not in dynamic address 
+       allocation range. Thanks to Steve Hirsch for spotting
+       the problem.
+
+       Add AddDhcpLease and DeleteDhcpLease DBus methods. Thanks
+       to Nicolas Cavallari for the patch.
+
+       Allow configuration of router advertisements without the 
+       "on-link" bit set. Thanks to Neil Jerram for the patch.
+
+       Extend --bridge-interface to DHCPv6 and router 
+       advertisements. Thanks to Neil Jerram for the patch.
+
+
 version 2.72
-            Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
-
-           Add support for "ipsets" in *BSD, using pf. Thanks to 
-           Sven Falempim for the patch.
-
-           Fix race condition which could lock up dnsmasq when an 
-           interface goes down and up rapidly. Thanks to Conrad 
-           Kostecki for helping to chase this down.
-
-           Add DBus methods SetFilterWin2KOption and SetBogusPrivOption
-           Thanks to the Smoothwall project for the patch.
-
-           Fix failure to build against Nettle-3.0. Thanks to Steven 
-           Barth for spotting this and finding the fix. 
-           
-           When assigning existing DHCP leases to intefaces by comparing 
-           networks, handle the case that two or more interfaces have the
-           same network part, but different prefix lengths (favour the
-           longer prefix length.) Thanks to Lung-Pin Chang for the 
-           patch.
-           
-           Add a mode which detects and removes DNS forwarding loops, ie 
-           a query sent to an upstream server returns as a new query to 
-           dnsmasq, and would therefore be forwarded again, resulting in 
-           a query which loops many times before being dropped. Upstream
-           servers which loop back are disabled and this event is logged.
-           Thanks to Smoothwall for their sponsorship of this feature.
-
-           Extend --conf-dir to allow filtering of files. So
-           --conf-dir=/etc/dnsmasq.d,\*.conf
-           will load all the files in /etc/dnsmasq.d which end in .conf
-            Fix bug when resulted in NXDOMAIN answers instead of NODATA in
-            some circumstances.
-
-           Fix bug which caused dnsmasq to become unresponsive if it 
-           failed to send packets due to a network interface disappearing.
-           Thanks to Niels Peen for spotting this.
-                   
-            Fix problem with --local-service option on big-endian platforms
-           Thanks to Richard Genoud for the patch.
+       Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
+
+       Add support for "ipsets" in *BSD, using pf. Thanks to 
+       Sven Falempin for the patch.
+
+       Fix race condition which could lock up dnsmasq when an 
+       interface goes down and up rapidly. Thanks to Conrad 
+       Kostecki for helping to chase this down.
+
+       Add DBus methods SetFilterWin2KOption and SetBogusPrivOption
+       Thanks to the Smoothwall project for the patch.
+
+       Fix failure to build against Nettle-3.0. Thanks to Steven 
+       Barth for spotting this and finding the fix. 
+
+       When assigning existing DHCP leases to interfaces by comparing 
+       networks, handle the case that two or more interfaces have the
+       same network part, but different prefix lengths (favour the
+       longer prefix length.) Thanks to Lung-Pin Chang for the 
+       patch.
+
+       Add a mode which detects and removes DNS forwarding loops, ie 
+       a query sent to an upstream server returns as a new query to 
+       dnsmasq, and would therefore be forwarded again, resulting in 
+       a query which loops many times before being dropped. Upstream
+       servers which loop back are disabled and this event is logged.
+       Thanks to Smoothwall for their sponsorship of this feature.
+
+       Extend --conf-dir to allow filtering of files. So
+       --conf-dir=/etc/dnsmasq.d,\*.conf
+       will load all the files in /etc/dnsmasq.d which end in .conf
+
+       Fix bug when resulted in NXDOMAIN answers instead of NODATA in
+       some circumstances.
+
+       Fix bug which caused dnsmasq to become unresponsive if it 
+       failed to send packets due to a network interface disappearing.
+       Thanks to Niels Peen for spotting this.
+
+       Fix problem with --local-service option on big-endian platforms
+       Thanks to Richard Genoud for the patch.
+
 
-       
 version 2.71
-            Subtle change to error handling to help DNSSEC validation 
-           when servers fail to provide NODATA answers for 
-           non-existent DS records.
+       Subtle change to error handling to help DNSSEC validation 
+       when servers fail to provide NODATA answers for 
+       non-existent DS records.
 
-           Tweak code which removes DNSSEC records from answers when
-           not required. Fixes broken answers when additional section
-           has real records in it. Thanks to Marco Davids for the bug 
-           report.
+       Tweak code which removes DNSSEC records from answers when
+       not required. Fixes broken answers when additional section
+       has real records in it. Thanks to Marco Davids for the bug 
+       report.
 
-           Fix DNSSEC validation of ANY queries. Thanks to Marco Davids
-           for spotting that too.
+       Fix DNSSEC validation of ANY queries. Thanks to Marco Davids
+       for spotting that too.
 
-           Fix total DNS failure and 100% CPU use if cachesize set to zero,
-           regression introduced in 2.69. Thanks to James Hunt and
-           the Ubuntu crowd for assistance in fixing this.
+       Fix total DNS failure and 100% CPU use if cachesize set to zero,
+       regression introduced in 2.69. Thanks to James Hunt and
+       the Ubuntu crowd for assistance in fixing this.
 
 
 version 2.70
-            Fix crash, introduced in 2.69, on TCP request when dnsmasq
-           compiled with DNSSEC support, but running without DNSSEC
-           enabled. Thanks to Manish Sing for spotting that one.
+       Fix crash, introduced in 2.69, on TCP request when dnsmasq
+       compiled with DNSSEC support, but running without DNSSEC
+       enabled. Thanks to Manish Sing for spotting that one.
 
-           Fix regression which broke ipset functionality. Thanks to 
-           Wang Jian for the bug report.
+       Fix regression which broke ipset functionality. Thanks to 
+       Wang Jian for the bug report.
 
 
 version 2.69
-           Implement dynamic interface discovery on *BSD. This allows
-           the contructor: syntax to be used in dhcp-range for DHCPv6
-           on the BSD platform. Thanks to Matthias Andree for
-           valuable research on how to implement this.
-
-           Fix infinite loop associated with some --bogus-nxdomain
-           configs. Thanks fogobogo for the bug report.
-
-           Fix missing RA RDNS option with configuration like
-           --dhcp-option=option6:23,[::] Thanks to Tsachi Kimeldorfer
-           for spotting the problem.
-
-           Add [fd00::] and [fe80::] as special addresses in DHCPv6
-           options, analogous to [::]. [fd00::] is replaced with the
-           actual ULA of the interface on the machine running
-           dnsmasq, [fe80::] with the link-local address. 
-           Thanks to Tsachi Kimeldorfer for championing this.
-
-           DNSSEC validation and caching. Dnsmasq needs to be
-           compiled with this enabled, with 
-           
-           make dnsmasq COPTS=-DHAVE_DNSSEC
-           
-           this add dependencies on the nettle crypto library and the 
-           gmp maths library. It's possible to have these linked
-           statically with
-           
-           make dnsmasq COPTS='-DHAVE_DNSSEC -DHAVE_DNSSEC_STATIC'
-           
-           which bloats the dnsmasq binary, but saves the size of 
-           the shared libraries which are much bigger.
-
-           To enable, DNSSEC, you will need a set of
-           trust-anchors. Now that the TLDs are signed, this can be
-           the keys for the root zone, and for convenience they are
-           included in trust-anchors.conf in the dnsmasq
-           distribution. You should of course check that these are
-           legitimate and up-to-date. So, adding
-           
-           conf-file=/path/to/trust-anchors.conf
-           dnssec
-
-           to your config is all thats needed to get things
-           working. The upstream nameservers have to be DNSSEC-capable
-           too, of course. Many ISP nameservers aren't, but the
-           Google public nameservers (8.8.8.8 and 8.8.4.4) are.
-           When DNSSEC is configured, dnsmasq validates any queries 
-           for domains which are signed. Query results which are 
-           bogus are replaced with SERVFAIL replies, and results 
-           which are correctly signed have the AD bit set. In 
-           addition, and just as importantly, dnsmasq supplies 
-           correct DNSSEC information to clients which are doing 
-           their own validation, and caches DNSKEY, DS and RRSIG
-           records, which significantly improve the performance of 
-           downstream validators. Setting --log-queries will show 
-           DNSSEC in action.
-
-           If a domain is returned from an upstream nameserver without 
-           DNSSEC signature, dnsmasq by default trusts this. This 
-           means that for unsigned zone (still the majority) there 
-           is effectively no cost for having DNSSEC enabled. Of course
-           this allows an attacker to replace a signed record with a 
-           false unsigned record. This is addressed by the 
-           --dnssec-check-unsigned flag, which instructs dnsmasq
-           to prove that an unsigned record is legitimate, by finding  
-           a secure proof that the zone containing the record is not
-           signed. Doing this has costs (typically one or two extra
-           upstream queries). It also has a nasty failure mode if
-           dnsmasq's upstream nameservers are not DNSSEC capable. 
-           Without --dnssec-check-unsigned using such an upstream
-           server will simply result in not queries being validated; 
-           with --dnssec-check-unsigned enabled and a 
-           DNSSEC-ignorant upstream server, _all_ queries will fail.
-
-           Note that DNSSEC requires that the local time is valid and 
-           accurate, if not then DNSSEC validation will fail. NTP 
-           should be running. This presents a problem for routers
-           without a battery-backed clock. To set the time needs NTP 
-           to do DNS lookups, but lookups will fail until NTP has run.
-           To address this, there's a flag, --dnssec-no-timecheck 
-           which disables the time checks (only) in DNSSEC. When dnsmasq
-           is started and the clock is not synced, this flag should
-           be used. As soon as the clock is synced, SIGHUP dnsmasq. 
-           The SIGHUP clears the cache of partially-validated data and
-           resets the no-timecheck flag, so that all DNSSEC checks 
-           henceforward will be complete.
-           
-           The development of DNSSEC in dnsmasq was started by 
-           Giovanni Bajo, to whom huge thanks are owed. It has been
-           supported by Comcast, whose techfund grant has allowed for 
-           an invaluable period of full-time work to get it to 
-           a workable state.
-           Add --rev-server. Thanks to Dave Taht for suggesting this.
-           
-           Add --servers-file. Allows dynamic update of upstream servers 
-           full access to configuration. 
-
-           Add --local-service. Accept DNS queries only from hosts 
-            whose address is on a local subnet, ie a subnet for which 
-            an interface exists on the server. This option
-            only has effect if there are no --interface --except-interface,
-            --listen-address or --auth-server options. It is intended 
-            to be set as a default on installation, to allow
-            unconfigured installations to be useful but also safe from 
-           being used for DNS amplification attacks.
-
-           Fix crashes in cache_get_cname_target() when dangling CNAMEs
-           encountered. Thanks to Andy and the rt-n56u project for
-           find this and helping to chase it down.
-
-           Fix wrong RCODE in authoritative DNS replies to PTR queries. The
-           correct answer was included, but the RCODE was set to NXDOMAIN.
-           Thanks to Craig McQueen for spotting this.
-
-           Make statistics available as DNS queries in the .bind TLD as 
-           well as logging them.
+       Implement dynamic interface discovery on *BSD. This allows
+       the constructor: syntax to be used in dhcp-range for DHCPv6
+       on the BSD platform. Thanks to Matthias Andree for
+       valuable research on how to implement this.
+
+       Fix infinite loop associated with some --bogus-nxdomain
+       configs. Thanks fogobogo for the bug report.
+
+       Fix missing RA RDNS option with configuration like
+       --dhcp-option=option6:23,[::] Thanks to Tsachi Kimeldorfer
+       for spotting the problem.
+
+       Add [fd00::] and [fe80::] as special addresses in DHCPv6
+       options, analogous to [::]. [fd00::] is replaced with the
+       actual ULA of the interface on the machine running
+       dnsmasq, [fe80::] with the link-local address. 
+       Thanks to Tsachi Kimeldorfer for championing this.
+
+       DNSSEC validation and caching. Dnsmasq needs to be
+       compiled with this enabled, with 
+
+       make dnsmasq COPTS=-DHAVE_DNSSEC
+
+       this adds dependencies on the nettle crypto library and the 
+       gmp maths library. It's possible to have these linked
+       statically with
+
+       make dnsmasq COPTS='-DHAVE_DNSSEC -DHAVE_DNSSEC_STATIC'
+
+       which bloats the dnsmasq binary, but saves the size of 
+       the shared libraries which are much bigger.
+
+       To enable, DNSSEC, you will need a set of
+       trust-anchors. Now that the TLDs are signed, this can be
+       the keys for the root zone, and for convenience they are
+       included in trust-anchors.conf in the dnsmasq
+       distribution. You should of course check that these are
+       legitimate and up-to-date. So, adding
+
+       conf-file=/path/to/trust-anchors.conf
+       dnssec
+
+       to your config is all that's needed to get things
+       working. The upstream nameservers have to be DNSSEC-capable
+       too, of course. Many ISP nameservers aren't, but the
+       Google public nameservers (8.8.8.8 and 8.8.4.4) are.
+       When DNSSEC is configured, dnsmasq validates any queries 
+       for domains which are signed. Query results which are 
+       bogus are replaced with SERVFAIL replies, and results 
+       which are correctly signed have the AD bit set. In 
+       addition, and just as importantly, dnsmasq supplies 
+       correct DNSSEC information to clients which are doing 
+       their own validation, and caches DNSKEY, DS and RRSIG
+       records, which significantly improve the performance of 
+       downstream validators. Setting --log-queries will show 
+       DNSSEC in action.
+
+       If a domain is returned from an upstream nameserver without 
+       DNSSEC signature, dnsmasq by default trusts this. This 
+       means that for unsigned zone (still the majority) there 
+       is effectively no cost for having DNSSEC enabled. Of course
+       this allows an attacker to replace a signed record with a 
+       false unsigned record. This is addressed by the 
+       --dnssec-check-unsigned flag, which instructs dnsmasq
+       to prove that an unsigned record is legitimate, by finding  
+       a secure proof that the zone containing the record is not
+       signed. Doing this has costs (typically one or two extra
+       upstream queries). It also has a nasty failure mode if
+       dnsmasq's upstream nameservers are not DNSSEC capable. 
+       Without --dnssec-check-unsigned using such an upstream
+       server will simply result in not queries being validated; 
+       with --dnssec-check-unsigned enabled and a 
+       DNSSEC-ignorant upstream server, _all_ queries will fail.
+
+       Note that DNSSEC requires that the local time is valid and 
+       accurate, if not then DNSSEC validation will fail. NTP 
+       should be running. This presents a problem for routers
+       without a battery-backed clock. To set the time needs NTP 
+       to do DNS lookups, but lookups will fail until NTP has run.
+       To address this, there's a flag, --dnssec-no-timecheck 
+       which disables the time checks (only) in DNSSEC. When dnsmasq
+       is started and the clock is not synced, this flag should
+       be used. As soon as the clock is synced, SIGHUP dnsmasq. 
+       The SIGHUP clears the cache of partially-validated data and
+       resets the no-timecheck flag, so that all DNSSEC checks 
+       henceforward will be complete.
+
+       The development of DNSSEC in dnsmasq was started by 
+       Giovanni Bajo, to whom huge thanks are owed. It has been
+       supported by Comcast, whose techfund grant has allowed for 
+       an invaluable period of full-time work to get it to 
+       a workable state.
+
+       Add --rev-server. Thanks to Dave Taht for suggesting this.
+
+       Add --servers-file. Allows dynamic update of upstream servers 
+       full access to configuration. 
+
+       Add --local-service. Accept DNS queries only from hosts 
+       whose address is on a local subnet, ie a subnet for which 
+       an interface exists on the server. This option
+       only has effect if there are no --interface --except-interface,
+       --listen-address or --auth-server options. It is intended 
+       to be set as a default on installation, to allow
+       unconfigured installations to be useful but also safe from 
+       being used for DNS amplification attacks.
+
+       Fix crashes in cache_get_cname_target() when dangling CNAMEs
+       encountered. Thanks to Andy and the rt-n56u project for
+       find this and helping to chase it down.
+
+       Fix wrong RCODE in authoritative DNS replies to PTR queries. The
+       correct answer was included, but the RCODE was set to NXDOMAIN.
+       Thanks to Craig McQueen for spotting this.
+
+       Make statistics available as DNS queries in the .bind TLD as 
+       well as logging them.
 
 
 version 2.68
-            Use random addresses for DHCPv6 temporary address
-            allocations, instead of algorithmically determined stable
-            addresses.
-
-           Fix bug which meant that the DHCPv6 DUID was not available
-           in DHCP script runs during the lifetime of the dnsmasq
-           process which created the DUID de-novo. Once the DUID was
-           created and stored in the lease file and dnsmasq
-           restarted, this bug disappeared.
-
-           Fix bug introduced in 2.67 which could result in erroneous
-           NXDOMAIN returns to CNAME queries.
-
-           Fix build failures on MacOS X and openBSD.
-
-           Allow subnet specifications in --auth-zone to be interface 
-           names as well as address literals. This makes it possible
-           to configure authoritative DNS when local address ranges
-           are dynamic and works much better than the previous
-           work-around which exempted contructed DHCP ranges from the
-           IP address filtering. As a consequence, that work-around
-           is removed. Under certain circumstances, this change wil
-           break existing configuration: if you're relying on the
-           contructed-range exception, you need to change --auth-zone
-           to specify the same interface as is used to construct your
-           DHCP ranges, probably with a trailing "/6" like this: 
-           --auth-zone=example.com,eth0/6 to limit the addresses to
-           IPv6 addresses of eth0.
-
-           Fix problems when advertising deleted IPv6 prefixes. If
-           the prefix is deleted (rather than replaced), it doesn't
-           get advertised with zero preferred time. Thanks to Tsachi
-           for the bug report. 
-
-           Fix segfault with some locally configured CNAMEs. Thanks
-           to Andrew Childs for spotting the problem.
-
-           Fix memory leak on re-reading /etc/hosts and friends,
-           introduced in 2.67.
-
-           Check the arrival interface of incoming DNS and TFTP
-           requests via IPv6, even in --bind-interfaces mode. This
-           isn't possible for IPv4 and can generate scary warnings,
-           but as it's always possible for IPv6 (the API always
-           exists) then we should do it always. 
-           
-           Tweak the rules on prefix-lengths in --dhcp-range for
-           IPv6. The new rule is that the specified prefix length
-           must be larger than or equal to the prefix length of the
-           corresponding address on the local interface. 
+       Use random addresses for DHCPv6 temporary address
+       allocations, instead of algorithmically determined stable
+       addresses.
+
+       Fix bug which meant that the DHCPv6 DUID was not available
+       in DHCP script runs during the lifetime of the dnsmasq
+       process which created the DUID de-novo. Once the DUID was
+       created and stored in the lease file and dnsmasq
+       restarted, this bug disappeared.
+
+       Fix bug introduced in 2.67 which could result in erroneous
+       NXDOMAIN returns to CNAME queries.
+
+       Fix build failures on MacOS X and openBSD.
+
+       Allow subnet specifications in --auth-zone to be interface 
+       names as well as address literals. This makes it possible
+       to configure authoritative DNS when local address ranges
+       are dynamic and works much better than the previous
+       work-around which exempted constructed DHCP ranges from the
+       IP address filtering. As a consequence, that work-around
+       is removed. Under certain circumstances, this change wil
+       break existing configuration: if you're relying on the
+       constructed-range exception, you need to change --auth-zone
+       to specify the same interface as is used to construct your
+       DHCP ranges, probably with a trailing "/6" like this: 
+       --auth-zone=example.com,eth0/6 to limit the addresses to
+       IPv6 addresses of eth0.
+
+       Fix problems when advertising deleted IPv6 prefixes. If
+       the prefix is deleted (rather than replaced), it doesn't
+       get advertised with zero preferred time. Thanks to Tsachi
+       for the bug report. 
+
+       Fix segfault with some locally configured CNAMEs. Thanks
+       to Andrew Childs for spotting the problem.
+
+       Fix memory leak on re-reading /etc/hosts and friends,
+       introduced in 2.67.
+
+       Check the arrival interface of incoming DNS and TFTP
+       requests via IPv6, even in --bind-interfaces mode. This
+       isn't possible for IPv4 and can generate scary warnings,
+       but as it's always possible for IPv6 (the API always
+       exists) then we should do it always. 
+
+       Tweak the rules on prefix-lengths in --dhcp-range for
+       IPv6. The new rule is that the specified prefix length
+       must be larger than or equal to the prefix length of the
+       corresponding address on the local interface. 
 
 
 version 2.67
-           Fix crash if upstream server returns SERVFAIL when
-           --conntrack in use. Thanks to Giacomo Tazzari for finding
-           this and supplying the patch. 
-
-           Repair regression in 2.64. That release stopped sending
-           lease-time information in the reply to DHCPINFORM
-           requests, on the correct grounds that it was a standards
-           violation. However, this broke the dnsmasq-specific
-           dhcp_lease_time utility. Now, DHCPINFORM returns
-           lease-time only if it's specifically requested
-           (maintaining standards) and the dhcp_lease_time utility
-           has been taught to ask for it (restoring functionality). 
-
-           Fix --dhcp-match, --dhcp-vendorclass and --dhcp-userclass
-           to work with BOOTP and well as DHCP. Thanks to Peter
-           Korsgaard for spotting the problem. 
-
-           Add --synth-domain. Thanks to Vishvananda Ishaya for
-           suggesting this.
-
-           Fix failure to compile ipset.c if old kernel headers are
-           in use. Thanks to Eugene Rudoy for pointing this out.
-
-           Handle IPv4 interface-address labels in Linux. These are
-           often used to emulate the old IP-alias addresses. Before,
-           using --interface=eth0 would service all the addresses of
-           eth0, including ones configured as aliases, which appear
-           in ifconfig as eth0:0. Now, only addresses with the label
-           eth0 are active. This is not backwards compatible: if you
-           want to continue to bind the aliases too, you need to add
-           eg. --interface=eth0:0 to the config. 
-       
-           Fix "failed to set SO_BINDTODEVICE on DHCP socket: Socket 
-           operation on non-socket" error on startup with
-           configurations which have exactly one --interface option
-           and do RA but _not_ DHCPv6. Thanks to Trever Adams for the
-           bug report.
+       Fix crash if upstream server returns SERVFAIL when
+       --conntrack in use. Thanks to Giacomo Tazzari for finding
+       this and supplying the patch. 
+
+       Repair regression in 2.64. That release stopped sending
+       lease-time information in the reply to DHCPINFORM
+       requests, on the correct grounds that it was a standards
+       violation. However, this broke the dnsmasq-specific
+       dhcp_lease_time utility. Now, DHCPINFORM returns
+       lease-time only if it's specifically requested
+       (maintaining standards) and the dhcp_lease_time utility
+       has been taught to ask for it (restoring functionality). 
+
+       Fix --dhcp-match, --dhcp-vendorclass and --dhcp-userclass
+       to work with BOOTP and well as DHCP. Thanks to Peter
+       Korsgaard for spotting the problem. 
+
+       Add --synth-domain. Thanks to Vishvananda Ishaya for
+       suggesting this.
+
+       Fix failure to compile ipset.c if old kernel headers are
+       in use. Thanks to Eugene Rudoy for pointing this out.
+
+       Handle IPv4 interface-address labels in Linux. These are
+       often used to emulate the old IP-alias addresses. Before,
+       using --interface=eth0 would service all the addresses of
+       eth0, including ones configured as aliases, which appear
+       in ifconfig as eth0:0. Now, only addresses with the label
+       eth0 are active. This is not backwards compatible: if you
+       want to continue to bind the aliases too, you need to add
+       eg. --interface=eth0:0 to the config. 
+
+       Fix "failed to set SO_BINDTODEVICE on DHCP socket: Socket 
+       operation on non-socket" error on startup with
+       configurations which have exactly one --interface option
+       and do RA but _not_ DHCPv6. Thanks to Trever Adams for the
+       bug report.
+
+       Generalise --interface-name to cope with IPv6 addresses
+       and multiple addresses per interface per address family.
+
+       Fix option parsing for --dhcp-host, which was generating a
+       spurious error when all seven possible items were
+       included. Thanks to Zhiqiang Wang for the bug report.
+
+       Remove restriction on prefix-length in --auth-zone. Thanks
+       to Toke Hoiland-Jorgensen for suggesting this.
+
+       Log when the maximum number of concurrent DNS queries is
+       reached. Thanks to Marcelo Salhab Brogliato for the patch.
+
+       If wildcards are used in --interface, don't assume that 
+       there will only ever be one available interface for DHCP
+       just because there is one at start-up. More may appear, so
+       we can't use SO_BINDTODEVICE. Thanks to Natrio for the bug
+       report. 
 
-           Generalise --interface-name to cope with IPv6 addresses
-           and multiple addresses per interface per address family.
+       Increase timeout/number of retries in TFTP to accommodate
+       AudioCodes Voice Gateways doing streaming writes to flash.
+       Thanks to Damian Kaczkowski for spotting the problem.
 
-           Fix option parsing for --dhcp-host, which was generating a
-           spurious error when all seven possible items were
-           included. Thanks to Zhiqiang Wang for the bug report.
+       Fix crash with empty DHCP string options when adding zero
+       terminator. Thanks to Patrick McLean for the bug report.
 
-           Remove restriction on prefix-length in --auth-zone. Thanks
-           to Toke Hoiland-Jorgensen for suggesting this.
-
-           Log when the maximum number of concurrent DNS queries is
-           reached. Thanks to Marcelo Salhab Brogliato for the patch.
+       Allow hostnames to start with a number, as allowed in
+       RFC-1123. Thanks to Kyle Mestery for the patch. 
 
-           If wildcards are used in --interface, don't assume that 
-           there will only ever be one available interface for DHCP
-           just because there is one at start-up. More may appear, so
-           we can't use SO_BINDTODEVICE. Thanks to Natrio for the bug
-           report. 
+       Fixes to DHCP FQDN option handling: don't terminate FQDN
+       if domain not known and allow a FQDN option with blank
+       name to request that a FQDN option is returned in the
+       reply. Thanks to Roy Marples for the patch.
 
-           Increase timeout/number of retries in TFTP to accomodate
-           AudioCodes Voice Gateways doing streaming writes to flash.
-           Thanks to Damian Kaczkowski for spotting the problem.
+       Make --clear-on-reload apply to setting upstream servers
+       via DBus too.
 
-           Fix crash with empty DHCP string options when adding zero
-           terminator. Thanks to Patrick McLean for the bug report.
+       When the address which triggered the construction of an
+       advertised IPv6 prefix disappears, continue to advertise 
+       the prefix for up to 2 hours, with the preferred lifetime
+       set to zero. This satisfies RFC 6204 4.3 L-13 and makes
+       things work better if a prefix disappears without being
+       deprecated first. Thanks to Uwe Schindler for persuasively
+       arguing for this.
 
-           Allow hostnames to start with a number, as allowed in
-           RFC-1123. Thanks to Kyle Mestery for the patch. 
+       Fix MAC address enumeration on *BSD. Thanks to Brad Smith
+       for the bug report.
 
-           Fixes to DHCP FQDN option handling: don't terminate FQDN
-           if domain not known and allow a FQDN option with blank
-           name to request that a FQDN option is returned in the
-           reply. Thanks to Roy Marples for the patch.
+       Support RFC-4242 information-refresh-time options in the 
+       reply to DHCPv6 information-request. The lease time of the
+       smallest valid dhcp-range is sent. Thanks to Uwe Schindler 
+       for suggesting this.
 
-           Make --clear-on-reload apply to setting upstream servers
-           via DBus too.
+       Make --listen-address higher priority than --except-interface
+       in all circumstances. Thanks to Thomas Hood for the bugreport.
 
-           When the address which triggered the construction of an
-           advertised IPv6 prefix disappears, continue to advertise 
-           the prefix for up to 2 hours, with the preferred lifetime
-           set to zero. This satisfies RFC 6204 4.3 L-13 and makes
-           things work better if a prefix disappears without being
-           deprecated first. Thanks to Uwe Schindler for persuasively
-           arguing for this.
+       Provide independent control over which interfaces get TFTP 
+       service. If enable-tftp is given a list of interfaces, then TFTP 
+       is provided on those. Without the list, the previous behaviour
+       (provide TFTP to the same interfaces we provide DHCP to) 
+       is retained. Thanks to Lonnie Abelbeck for the suggestion.
 
-           Fix MAC address enumeration on *BSD. Thanks to Brad Smith
-           for the bug report.
+       Add --dhcp-relay config option. Many thanks to vtsl.net
+       for sponsoring this development.
 
-           Support RFC-4242 information-refresh-time options in the 
-           reply to DHCPv6 information-request. The lease time of the
-            smallest valid dhcp-range is sent. Thanks to Uwe Schindler 
-           for suggesting this.
+       Fix crash with empty tag: in --dhcp-range. Thanks to
+       Kaspar Schleiser for the bug report.
 
-           Make --listen-address higher priority than --except-interface
-           in all circumstances. Thanks to Thomas Hood for the bugreport.
+       Add "baseline" and "bloatcheck" makefile targets, for 
+       revealing size changes during development. Thanks to
+       Vladislav Grishenko for the patch. 
 
-           Provide independent control over which interfaces get TFTP 
-           service. If enable-tftp is given a list of interfaces, then TFTP 
-           is provided on those. Without the list, the previous behaviour
-           (provide TFTP to the same interfaces we provide DHCP to) 
-           is retained. Thanks to Lonnie Abelbeck for the suggestion.
+       Cope with DHCPv6 clients which send REQUESTs without
+       address options - treat them as SOLICIT with rapid commit.
 
-           Add --dhcp-relay config option. Many thanks to vtsl.net
-           for sponsoring this development.
+       Support identification of clients by MAC address in
+       DHCPv6. When using a relay, the relay must support RFC
+       6939 for this to work. It always works for directly
+       connected clients. Thanks to Vladislav Grishenko
+       for prompting this feature.
 
-           Fix crash with empty tag: in --dhcp-range. Thanks to
-           Kaspar Schleiser for the bug report.
+       Remove the rule for constructed DHCP ranges that the local
+       address must be either the first or last address in the
+       range. This was originally to avoid SLAAC addresses, but
+       we now explicitly autoconfig and privacy addresses instead.  
 
-           Add "baseline" and "bloatcheck" makefile targets, for 
-           revealing size changes during development. Thanks to
-           Vladislav Grishenko for the patch. 
+       Update Polish translation. Thanks to Jan Psota.
 
-           Cope with DHCPv6 clients which send REQUESTs without
-           address options - treat them as SOLICIT with rapid commit.
+       Fix problem in DHCPv6 vendorclass/userclass matching
+       code. Thanks to Tanguy Bouzeloc for the patch.
 
-           Support identification of clients by MAC address in
-           DHCPv6. When using a relay, the relay must support RFC
-           6939 for this to work. It always works for directly
-           connected clients. Thanks to Vladislav Grishenko
-           for prompting this feature.
-           
-           Remove the rule for constructed DHCP ranges that the local
-           address must be either the first or last address in the
-           range. This was originally to avoid SLAAC addresses, but
-           we now explicitly autoconfig and privacy addresses instead.  
+       Update Spanish translation. Thanks to Vicente Soriano.
 
-           Update Polish translation. Thanks to Jan Psota.
+       Add --ra-param option. Thanks to Vladislav Grishenko for
+       inspiration on this.
 
-           Fix problem in DHCPv6 vendorclass/userclass matching
-           code. Thanks to Tanguy Bouzeloc for the patch.
+       Add --add-subnet configuration, to tell upstream DNS
+       servers where the original client is. Thanks to DNSthingy
+       for sponsoring this feature.
 
-           Update Spanish transalation. Thanks to Vicente Soriano.
+       Add --quiet-dhcp, --quiet-dhcp6 and --quiet-ra. Thanks to
+       Kevin Darbyshire-Bryant for the initial patch.
 
-           Add --ra-param option. Thanks to Vladislav Grishenko for
-           inspiration on this.
+       Allow A/AAAA records created by --interface-name to be the
+       target of --cname. Thanks to Hadmut Danisch for the
+       suggestion. 
 
-           Add --add-subnet configuration, to tell upstream DNS
-           servers where the original client is. Thanks to DNSthingy
-           for sponsoring this feature.
+       Avoid treating a --dhcp-host which has an IPv6 address
+       as eligible for use with DHCPv4 on the grounds that it has
+       no address, and vice-versa. Thanks to Yury Konovalov for
+       spotting the problem.
 
-           Add --quiet-dhcp, --quiet-dhcp6 and --quiet-ra. Thanks to
-           Kevin Darbyshire-Bryant for the initial patch.
+       Do a better job caching dangling CNAMEs. Thanks to Yves
+       Dorfsman for spotting the problem.
 
-           Allow A/AAAA records created by --interface-name to be the
-           target of --cname. Thanks to Hadmut Danisch for the
-           suggestion. 
 
-           Avoid treating a --dhcp-host which has an IPv6 address
-           as eligable for use with DHCPv4 on the grounds that it has
-           no address, and vice-versa. Thanks to Yury Konovalov for
-           spotting the problem.
+version 2.66
+       Add the ability to act as an authoritative DNS
+       server. Dnsmasq can now answer queries from the wider 'net
+       with local data, as long as the correct NS records are set
+       up. Only local data is provided, to avoid creating an open
+       DNS relay. Zone transfer is supported, to allow secondary
+       servers to be configured.
+
+       Add "constructed DHCP ranges" for DHCPv6. This is intended
+       for IPv6 routers which get prefixes dynamically via prefix
+       delegation. With suitable configuration, stateful DHCPv6
+       and RA can happen automatically as prefixes are delegated
+       and then deprecated, without having  to re-write the
+       dnsmasq configuration file or restart the daemon. Thanks to
+       Steven Barth for extensive testing and development work on
+       this idea.
+
+       Fix crash on startup on Solaris 11. Regression probably
+       introduced in 2.61.  Thanks to Geoff Johnstone for the
+       patch.
+
+       Add code to make behaviour for TCP DNS requests that same
+       as for UDP requests, when a request arrives for an allowed 
+       address, but via a banned interface. This change is only
+       active on Linux, since the relevant API is missing (AFAIK)
+       on other platforms. Many thanks to Tomas Hozza for
+       spotting the problem, and doing invaluable discovery of
+       the obscure and undocumented API required for the solution.
+
+       Don't send the default DHCP option advertising dnsmasq as
+       the local DNS server if dnsmasq is configured to not act
+       as DNS server, or it's configured to a non-standard port.
+
+       Add DNSMASQ_CIRCUIT_ID, DNSMASQ_SUBSCRIBER_ID,
+       DNSMASQ_REMOTE_ID variables to the environment of the
+       lease-change script (and the corresponding Lua). These hold
+       information inserted into the DHCP request by a DHCP relay
+       agent. Thanks to Lakefield Communications for providing a
+       bounty for this addition.
+
+       Fixed crash, introduced in 2.64, whilst handling DHCPv6
+       information-requests with some common configurations.
+       Thanks to Robert M. Albrecht for the bug report and 
+       chasing the problem.
+
+       Add --ipset option. Thanks to Jason A. Donenfeld for the 
+       patch.
+
+       Don't erroneously reject some option names in --dhcp-match
+       options. Thanks to Benedikt Hochstrasser for the bug report.
+
+       Allow a trailing '*' wildcard in all interface-name
+       configurations. Thanks to Christian Parpart for the patch.
+
+       Handle the situation where libc headers define
+       SO_REUSEPORT, but the kernel in use doesn't, to cope with
+       the introduction of this option to Linux. Thanks to Rich
+       Felker for the bug report.
+
+       Update Polish translation. Thanks to Jan Psota.
+
+       Fix crash if the configured DHCP lease limit is
+       reached. Regression occurred in 2.61. Thanks to Tsachi for
+       the bug report. 
+
+       Update the French translation. Thanks to Gildas le Nadan.
 
-           Do a better job caching dangling CNAMEs. Thanks to Yves
-           Dorfsman for spotting the problem.
 
-version 2.66
-            Add the ability to act as an authoritative DNS
-            server. Dnsmasq can now answer queries from the wider 'net
-            with local data, as long as the correct NS records are set
-            up. Only local data is provided, to avoid creating an open
-            DNS relay. Zone transfer is supported, to allow secondary
-            servers to be configured.
-
-           Add "constructed DHCP ranges" for DHCPv6. This is intended
-           for IPv6 routers which get prefixes dynamically via prefix
-           delegation. With suitable configuration, stateful DHCPv6
-           and RA can happen automatically as prefixes are delegated
-           and then deprecated, without having  to re-write the
-           dnsmasq configuration file or restart the daemon. Thanks to
-           Steven Barth for extensive testing and development work on
-           this idea.
-
-           Fix crash on startup on Solaris 11. Regression probably
-           introduced in 2.61.  Thanks to Geoff Johnstone for the
-           patch.
-
-           Add code to make behaviour for TCP DNS requests that same
-           as for UDP requests, when a request arrives for an allowed 
-           address, but via a banned interface. This change is only
-           active on Linux, since the relevant API is missing (AFAIK)
-           on other platforms. Many thanks to Tomas Hozza for
-           spotting the problem, and doing invaluable discovery of
-           the obscure and undocumented API required for the solution.
-
-           Don't send the default DHCP option advertising dnsmasq as
-           the local DNS server if dnsmasq is configured to not act
-           as DNS server, or it's configured to a non-standard port.
-            Add DNSMASQ_CIRCUIT_ID, DNSMASQ_SUBCRIBER_ID,
-            DNSMASQ_REMOTE_ID variables to the environment of the
-            lease-change script (and the corresponding Lua). These hold
-            information inserted into the DHCP request by a DHCP relay
-            agent. Thanks to Lakefield Communications for providing a
-            bounty for this addition.
-           Fixed crash, introduced in 2.64, whilst handling DHCPv6
-           information-requests with some common configurations.
-           Thanks to Robert M. Albrecht for the bug report and 
-           chasing the problem.
-
-           Add --ipset option. Thanks to Jason A. Donenfeld for the 
-           patch.
-
-           Don't erroneously reject some option names in --dhcp-match
-           options. Thanks to Benedikt Hochstrasser for the bug report.
-           
-           Allow a trailing '*' wildcard in all interface-name
-           configurations. Thanks to Christian Parpart for the patch.
-
-           Handle the situation where libc headers define
-           SO_REUSEPORT, but the kernel in use doesn't, to cope with
-           the introduction of this option to Linux. Thanks to Rich
-           Felker for the bug report.
-
-           Update Polish translation. Thanks to Jan Psota.
-
-           Fix crash if the configured DHCP lease limit is
-           reached. Regression occurred in 2.61. Thanks to Tsachi for
-           the bug report. 
-           
-           Update the French translation. Thanks to Gildas le Nadan.
-
-  
 version 2.65
-           Fix regression which broke forwarding of queries sent via
-           TCP which are not for A and AAAA and which were directed to
-           non-default servers. Thanks to Niax for the bug report.
+       Fix regression which broke forwarding of queries sent via
+       TCP which are not for A and AAAA and which were directed to
+       non-default servers. Thanks to Niax for the bug report.
+
+       Fix failure to build with DHCP support excluded. Thanks to 
+       Gustavo Zacarias for the patch.
 
-           Fix failure to build with DHCP support excluded. Thanks to 
-           Gustavo Zacarias for the patch.
-           
-           Fix nasty regression in 2.64 which completely broke cacheing.
+       Fix nasty regression in 2.64 which completely broke caching.
 
 
 version 2.64
-            Handle DHCP FQDN options with all flag bits zero and
-            --dhcp-client-update set. Thanks to Bernd Krumbroeck for
-            spotting the problem.
+       Handle DHCP FQDN options with all flag bits zero and
+       --dhcp-client-update set. Thanks to Bernd Krumbroeck for
+       spotting the problem.
+
+       Finesse the check for /etc/hosts names which conflict with
+       DHCP names. Previously a name/address pair in /etc/hosts
+       which didn't match the name/address of a DHCP lease would
+       generate a warning. Now that only happens if there is not
+       also a match. This allows multiple addresses for a name in 
+       /etc/hosts with one of them assigned via DHCP.
 
-           Finesse the check for /etc/hosts names which conflict with
-           DHCP names. Previously a name/address pair in /etc/hosts
-           which didn't match the name/address of a DHCP lease would
-           generate a warning. Now that only happesn if there is not
-           also a match. This allows multiple addresses for a name in 
-           /etc/hosts with one of them assigned via DHCP.
+       Fix broken vendor-option processing for BOOTP. Thanks to
+       Hans-Joachim Baader for the bug report.
 
-           Fix broken vendor-option processing for BOOTP. Thanks to
-           Hans-Joachim Baader for the bug report.
+       Don't report spurious netlink errors, regression in
+       2.63. Thanks to Vladislav Grishenko for the patch.
 
-           Don't report spurious netlink errors, regression in
-           2.63. Thanks to Vladislav Grishenko for the patch.
+       Flag DHCP or DHCPv6 in startup logging. Thanks to 
+       Vladislav Grishenko for the patch.
 
-           Flag DHCP or DHCPv6 in starup logging. Thanks to 
-           Vladislav Grishenko for the patch.
+       Add SetServersEx method in DBus interface. Thanks to Dan
+       Williams for the patch.
 
-           Add SetServersEx method in DBus interface. Thanks to Dan
-           Williams for the patch.
+       Add SetDomainServers method in DBus interface. Thanks to
+       Roy Marples for the patch.
 
-           Add SetDomainServers method in DBus interface. Thanks to
-           Roy Marples for the patch.
+       Fix build with later Lua libraries. Thanks to Cristian
+       Rodriguez for the patch.
 
-           Fix build with later Lua libraries. Thansk to Cristian
-           Rodriguez for the patch.
+       Add --max-cache-ttl option. Thanks to Dennis Kaarsemaker
+       for the patch.
 
-           Add --max-cache-ttl option. Thanks to Dennis Kaarsemaker
-           for the patch.
+       Fix breakage of --host-record parsing, resulting in
+       infinite loop at startup. Regression in 2.63. Thanks to
+       Haim Gelfenbeyn for spotting this.
 
-           Fix breakage of --host-record parsing, resulting in
-           infinte loop at startup. Regression in 2.63. Thanks to
-           Haim Gelfenbeyn for spotting this.
+       Set SO_REUSEADDRESS and SO_V6ONLY options on the DHCPv6
+       socket, this allows multiple instances of dnsmasq on a
+       single machine, in the same way as for DHCPv4. Thanks to
+       Gene Czarcinski and Vladislav Grishenko for work on this.
 
-           Set SO_REUSEADDRESS and SO_V6ONLY options on the DHCPv6
-           socket, this allows multiple instances of dnsmasq on a
-           single machine, in the same way as for DHCPv4. Thanks to
-           Gene Czarcinski and Vladislav Grishenko for work on this.
+       Fix DHCPv6 to do access control correctly when it's 
+       configured with --listen-address. Thanks to
+       Gene Czarcinski for sorting this out. 
 
-           Fix DHCPv6 to do access control correctly when it's 
-           configured with --listen-address. Thanks to
-           Gene Czarcinski for sorting this out. 
+       Add a "wildcard" dhcp-range which works for any IPv6
+       subnet, --dhcp-range=::,static Useful for Stateless 
+       DHCPv6. Thanks to Vladislav Grishenko for the patch.
 
-           Add a "wildcard" dhcp-range which works for any IPv6
-           subnet, --dhcp-range=::,static Useful for Stateless 
-           DHCPv6. Thanks to Vladislav Grishenko for the patch.
+       Don't include lease-time in DHCPACK replies to DHCPINFORM
+       queries, since RFC-2131 says we shouldn't. Thanks to
+       Wouter Ibens for pointing this out.  
 
-           Don't include lease-time in DHCPACK replies to DHCPINFORM
-           queries, since RFC-2131 says we shouldn't. Thanks to
-           Wouter Ibens for pointing this out.  
+       Makefile tweak to do dependency checking on header files.
+       Thanks to Johan Peeters for the patch.
 
-           Makefile tweak to do dependency checking on header files.
-           Thanks to Johan Peeters for the patch.
+       Check interface for outgoing unsolicited router 
+       advertisements, rather than relying on interface address 
+       configuration. Thanks to Gene Czarinski for the patch.
 
-           Check interface for outgoing unsolicited router 
-           advertisements, rather than relying on interface address 
-           configuration. Thanks to Gene Czarinski for the patch.
+       Handle better attempts to transmit on interfaces which are
+       still doing DAD, and specifically do not just transmit
+       without setting source address and interface, since this
+       can cause very puzzling effects when a router
+       advertisement goes astray. Thanks again to Gene Czarinski.
 
-           Handle better attempts to transmit on interfaces which are
-           still doing DAD, and specifically do not just transmit
-           without setting source address and interface, since this
-           can cause very puzzling effects when a router
-           advertisement goes astray. Thanks again to Gene Czarinski.
+       Get RA timers right when there is more than one
+       dhcp-range on a subnet.
 
-           Get RA timers right when there is more than one
-           dhcp-range on a subnet.
-           
 
 version 2.63
-            Do duplicate dhcp-host address check in --test mode.
+       Do duplicate dhcp-host address check in --test mode.
 
-           Check that tftp-root directories are accessible before
-           start-up. Thanks to Daniel Veillard for the initial patch.
+       Check that tftp-root directories are accessible before
+       start-up. Thanks to Daniel Veillard for the initial patch.
 
-           Allow more than one --tfp-root flag. The per-interface
-           stuff is pointless without that.
+       Allow more than one --tfp-root flag. The per-interface
+       stuff is pointless without that.
 
-           Add --bind-dynamic. A hybrid mode between the default and
-           --bind-interfaces which copes with dynamically created
-           interfaces. 
-           
-           A couple of fixes to the build system for Android. Thanks
-           to Metin Kaya for the patches.
+       Add --bind-dynamic. A hybrid mode between the default and
+       --bind-interfaces which copes with dynamically created
+       interfaces. 
 
-           Remove the interface:<interface> argument in --dhcp-range, and
-           the interface argument to --enable-tftp. These were a
-           still-born attempt to allow automatic isolated
-           configuration by libvirt, but have never (to my knowledge)
-           been used, had very strange semantics, and have been
-           superceded by other mechanisms. 
+       A couple of fixes to the build system for Android. Thanks
+       to Metin Kaya for the patches.
 
-           Fixed bug logging filenames when duplicate dhcp-host
-           addresses are found. Thanks to John Hanks for the patch.
+       Remove the interface:<interface> argument in --dhcp-range, and
+       the interface argument to --enable-tftp. These were a
+       still-born attempt to allow automatic isolated
+       configuration by libvirt, but have never (to my knowledge)
+       been used, had very strange semantics, and have been
+       superseded by other mechanisms. 
 
-           Fix regression in 2.61 which broke caching of CNAME
-           chains. Thanks to Atul Gupta for the bug report.
+       Fixed bug logging filenames when duplicate dhcp-host
+       addresses are found. Thanks to John Hanks for the patch.
 
-           Allow the target of a --cname flag to be another --cname.
+       Fix regression in 2.61 which broke caching of CNAME
+       chains. Thanks to Atul Gupta for the bug report.
 
-            Teach DHCPv6 about the RFC 4242 information-refresh-time
-           option, and add parsing if the minutes, hours and days
-           format for options. Thanks to Francois-Xavier Le Bail for
-           the suggestion.
+       Allow the target of a --cname flag to be another --cname.
 
-           Allow "w" (for week) as multiplier in lease times, as well
-           as seconds, minutes, hours and days.  Álvaro Gámez Machado 
-           spotted the ommission.
-           Update French translation. Thanks to Gildas Le Nadan.
+       Teach DHCPv6 about the RFC 4242 information-refresh-time
+       option, and add parsing if the minutes, hours and days
+       format for options. Thanks to Francois-Xavier Le Bail for
+       the suggestion.
 
-           Allow a DBus service name to be given with --enable-dbus
-           which overrides the default,
-           uk.org.thekelleys.dnsmasq. Thanks to Mathieu
-           Trudel-Lapierre for the patch. 
+       Allow "w" (for week) as multiplier in lease times, as well
+       as seconds, minutes, hours and days.  Álvaro Gámez Machado 
+       spotted the omission.
 
-           Set the "prefix on-link" bit in Router
-           Advertisements. Thanks to Gui Iribarren for the patch.
+       Update French translation. Thanks to Gildas Le Nadan.
+
+       Allow a DBus service name to be given with --enable-dbus
+       which overrides the default,
+       uk.org.thekelleys.dnsmasq. Thanks to Mathieu
+       Trudel-Lapierre for the patch. 
+
+       Set the "prefix on-link" bit in Router
+       Advertisements. Thanks to Gui Iribarren for the patch.
 
 
 version 2.62
-            Update German translation. Thanks to Conrad Kostecki.
+       Update German translation. Thanks to Conrad Kostecki.
 
-           Cope with router-solict packets wich don't have a valid 
-           source address. Thanks to Vladislav Grishenko for the patch.
+       Cope with router-solict packets which don't have a valid 
+       source address. Thanks to Vladislav Grishenko for the patch.
 
-           Fixed bug which caused missing periodic router
-           advertisements with some configurations. Thanks to
-           Vladislav Grishenko for the patch.
+       Fixed bug which caused missing periodic router
+       advertisements with some configurations. Thanks to
+       Vladislav Grishenko for the patch.
 
-           Fixed bug which broke DHCPv6/RA with prefix lengths 
-           which are not divisible by 8. Thanks to Andre Coetzee 
-           for spotting this.
+       Fixed bug which broke DHCPv6/RA with prefix lengths 
+       which are not divisible by 8. Thanks to Andre Coetzee 
+       for spotting this.
 
-           Fix non-response to router-solicitations when
-           router-advertisement configured, but DHCPv6 not
-           configured. Thanks to Marien Zwart for the patch.
+       Fix non-response to router-solicitations when
+       router-advertisement configured, but DHCPv6 not
+       configured. Thanks to Marien Zwart for the patch.
 
-           Add --dns-rr, to allow arbitrary DNS resource records.
+       Add --dns-rr, to allow arbitrary DNS resource records.
 
-           Fixed bug which broke RA scheduling when an interface had
-           two addresses in the same network. Thanks to Jim Bos for
-           his help nailing this.
+       Fixed bug which broke RA scheduling when an interface had
+       two addresses in the same network. Thanks to Jim Bos for
+       his help nailing this.
 
 version 2.61
-           Re-write interface discovery code on *BSD to use
-           getifaddrs. This is more portable, more straightforward,
-           and allows us to find the prefix length for IPv6
-           addresses.
-
-           Add ra-names, ra-stateless and slaac keywords for DHCPv6.
-           Dnsmasq can now synthesise AAAA records for dual-stack 
-            hosts which get IPv6 addresses via SLAAC. It is also now 
-           possible to use SLAAC and stateless DHCPv6, and to 
-           tell clients to use SLAAC addresses as well as DHCP ones.
-           Thanks to Dave Taht for help with this.
-
-           Add --dhcp-duid to allow DUID-EN uids to be used.
-
-           Explicity send DHCPv6 replies to the correct port, instead
-           of relying on clients to send requests with the correct
-           source address, since at least one client in the wild gets
-           this wrong. Thanks to Conrad Kostecki for help tracking
-           this down.
-
-           Send a preference value of 255 in DHCPv6 replies when 
-           --dhcp-authoritative is in effect. This tells clients not
-           to wait around for other DHCP servers.
-
-           Better logging of DHCPv6 options.
-
-           Add --host-record. Thanks to Rob Zwissler for the
-           suggestion.
-
-           Invoke the DHCP script with action "tftp" when a TFTP file
-           transfer completes. The size of the file, address to which
-           it was sent and complete pathname are supplied. Note that
-           version 2.60 introduced some script incompatibilties
-           associated with DHCPv6, and this is a further change. To
-           be safe, scripts should ignore unknown actions, and if
-           not IPv6-aware, should exit if the environment
-           variable DNSMASQ_IAID is set. The use-case for this is
-           to track netboot/install.  Suggestion from Shantanu
-           Gadgil.
-
-           Update contrib/port-forward/dnsmasq-portforward to reflect
-           the above.
-
-           Set the environment variable DNSMASQ_LOG_DHCP when running
-           the script id --log-dhcp is in effect, so that script can
-           taylor their logging verbosity. Suggestion from Malte
-           Forkel.
-           
-           Arrange that addresses specified with --listen-address
-           work even if there is no interface carrying the
-           address. This is chiefly useful for IPv4 loopback
-           addresses, where any address in 127.0.0.0/8 is a valid
-           loopback address, but normally only 127.0.0.1 appears on
-           the lo interface. Thanks to Mathieu Trudel-Lapierre for
-           the idea and initial patch. 
-
-           Fix crash, introduced in 2.60, when a DHCPINFORM is
-           received from a network which has no valid dhcp-range.
-           Thanks to Stephane Glondu for the bug report.
-
-           Add a new DHCP lease time keyword, "deprecated" for
-           --dhcp-range. This is only valid for IPv6, and sets the
-           preffered lease time for both DHCP and RA to zero. The
-           effect is that clients can continue to use the address 
-           for existing connections, but new connections will use
-            other addresses, if they exist. This makes hitless
-           renumbering at least possible.
-
-           Fix bug in address6_available() which caused DHCPv6 lease
-           aquisition to fail if more than one dhcp-range in use.
-
-           Provide RDNSS and DNSSL data in router advertisements,
-           using the settings provided for DHCP options
-           option6:domain-search and option6:dns-server.
-
-           Tweak logo/favicon.ico to add some transparency. Thanks to
-           SamLT for work on this.
-           
-           Don't cache data from non-recursive nameservers, since it
-           may erroneously look like a valid CNAME to a non-exitant
-           name. Thanks to Ben Winslow for finding this.
-
-           Call SO_BINDTODEVICE on the DHCP socket(s) when doing DHCP
-           on exactly one interface and --bind-interfaces is set. This 
-           makes the OpenStack use-case of one dnsmasq per virtual
-           interface work. This is only available on Linux; it's not
-           supported on other platforms. Thanks to Vishvananda Ishaya
-           and the OpenStack team for the suggestion.
-
-           Updated French translation. Thanks to Gildas Le Nadan.
-
-           Give correct from-cache answers to explict CNAME queries.
-           Thanks to Rob Zwissler for spotting this.
-           
-           Add --tftp-lowercase option. Thanks to Oliver Rath for the
-           patch. 
-
-           Ensure that the DBus DhcpLeaseUpdated events are generated
-           when a lease goes through INIT_REBOOT state, even if the
-           dhcp-script is not in use. Thanks to Antoaneta-Ecaterina
-           Ene for the patch.
-
-           Fix failure of TFTP over IPv4 on OpenBSD platform. Thanks
-           to Brad Smith for spotting this.
-           
+       Re-write interface discovery code on *BSD to use
+       getifaddrs. This is more portable, more straightforward,
+       and allows us to find the prefix length for IPv6
+       addresses.
+
+       Add ra-names, ra-stateless and slaac keywords for DHCPv6.
+       Dnsmasq can now synthesise AAAA records for dual-stack 
+       hosts which get IPv6 addresses via SLAAC. It is also now 
+       possible to use SLAAC and stateless DHCPv6, and to 
+       tell clients to use SLAAC addresses as well as DHCP ones.
+       Thanks to Dave Taht for help with this.
+
+       Add --dhcp-duid to allow DUID-EN uids to be used.
+
+       Explicitly send DHCPv6 replies to the correct port, instead
+       of relying on clients to send requests with the correct
+       source address, since at least one client in the wild gets
+       this wrong. Thanks to Conrad Kostecki for help tracking
+       this down.
+
+       Send a preference value of 255 in DHCPv6 replies when 
+       --dhcp-authoritative is in effect. This tells clients not
+       to wait around for other DHCP servers.
+
+       Better logging of DHCPv6 options.
+
+       Add --host-record. Thanks to Rob Zwissler for the
+       suggestion.
+
+       Invoke the DHCP script with action "tftp" when a TFTP file
+       transfer completes. The size of the file, address to which
+       it was sent and complete pathname are supplied. Note that
+       version 2.60 introduced some script incompatibilities
+       associated with DHCPv6, and this is a further change. To
+       be safe, scripts should ignore unknown actions, and if
+       not IPv6-aware, should exit if the environment
+       variable DNSMASQ_IAID is set. The use-case for this is
+       to track netboot/install.  Suggestion from Shantanu
+       Gadgil.
+
+       Update contrib/port-forward/dnsmasq-portforward to reflect
+       the above.
+
+       Set the environment variable DNSMASQ_LOG_DHCP when running
+       the script id --log-dhcp is in effect, so that script can
+       taylor their logging verbosity. Suggestion from Malte
+       Forkel.
+
+       Arrange that addresses specified with --listen-address
+       work even if there is no interface carrying the
+       address. This is chiefly useful for IPv4 loopback
+       addresses, where any address in 127.0.0.0/8 is a valid
+       loopback address, but normally only 127.0.0.1 appears on
+       the lo interface. Thanks to Mathieu Trudel-Lapierre for
+       the idea and initial patch. 
+
+       Fix crash, introduced in 2.60, when a DHCPINFORM is
+       received from a network which has no valid dhcp-range.
+       Thanks to Stephane Glondu for the bug report.
+
+       Add a new DHCP lease time keyword, "deprecated" for
+       --dhcp-range. This is only valid for IPv6, and sets the
+       preferred lease time for both DHCP and RA to zero. The
+       effect is that clients can continue to use the address 
+       for existing connections, but new connections will use
+       other addresses, if they exist. This makes hitless
+       renumbering at least possible.
+
+       Fix bug in address6_available() which caused DHCPv6 lease
+       acquisition to fail if more than one dhcp-range in use.
+
+       Provide RDNSS and DNSSL data in router advertisements,
+       using the settings provided for DHCP options
+       option6:domain-search and option6:dns-server.
+
+       Tweak logo/favicon.ico to add some transparency. Thanks to
+       SamLT for work on this.
+
+       Don't cache data from non-recursive nameservers, since it
+       may erroneously look like a valid CNAME to a non-existent
+       name. Thanks to Ben Winslow for finding this.
+
+       Call SO_BINDTODEVICE on the DHCP socket(s) when doing DHCP
+       on exactly one interface and --bind-interfaces is set. This 
+       makes the OpenStack use-case of one dnsmasq per virtual
+       interface work. This is only available on Linux; it's not
+       supported on other platforms. Thanks to Vishvananda Ishaya
+       and the OpenStack team for the suggestion.
+
+       Updated French translation. Thanks to Gildas Le Nadan.
+
+       Give correct from-cache answers to explicit CNAME queries.
+       Thanks to Rob Zwissler for spotting this.
+
+       Add --tftp-lowercase option. Thanks to Oliver Rath for the
+       patch. 
+
+       Ensure that the DBus DhcpLeaseUpdated events are generated
+       when a lease goes through INIT_REBOOT state, even if the
+       dhcp-script is not in use. Thanks to Antoaneta-Ecaterina
+       Ene for the patch.
+
+       Fix failure of TFTP over IPv4 on OpenBSD platform. Thanks
+       to Brad Smith for spotting this.
+
 
 version 2.60
-            Fix compilation problem in Mac OS X Lion. Thanks to Olaf
-            Flebbe for the patch.
-
-           Fix DHCP when using --listen-address with an IP address
-           which is not the primary address of an interface.
-
-           Add --dhcp-client-update option.
-
-           Add Lua integration. Dnsmasq can now execute a DHCP
-           lease-change script written in Lua. This needs to be
-           enabled at compile time by setting HAVE_LUASCRIPT in 
-           src/config.h or running "make COPTS=-DHAVE_LUASCRIPT"
-           Thanks to Jan-Piet Mens for the idea and proof-of-concept 
-           implementation.
-           
-           Tidied src/config.h to distinguish between
-           platform-dependent compile-time options which are selected
-           automatically, and builder-selectable compile time
-           options. Document the latter better, and describe how to
-           set them from the make command line.
-
-           Tidied up IPPROTO_IP/SOL_IP (and IPv6 equivalent)
-           confusion. IPPROTO_IP works everywhere now.
-           
-           Set TOS on DHCP sockets, this improves things on busy
-           wireless networks. Thanks to Dave Taht for the patch.
-
-           Determine VERSION automatically based on git magic:
-           release tags or hash values.
-
-           Improve start-up speed when reading large hosts files 
-           containing many distinct addresses.
-
-           Fix problem if dnsmasq is started without the stdin,
-           stdout and stderr file descriptors open. This can manifest
-           itself as 100% CPU use. Thanks to Chris Moore for finding
-           this.
-
-           Fix shell-scripting bug in bld/pkg-wrapper. Thanks to 
-           Mark Mitchell for the patch.
-
-           Allow the TFP server or boot server in --pxe-service, to
-           be a domain name instead of an IP address. This allows for
-           round-robin to multiple servers, in the same way as
-           --dhcp-boot. A good suggestion from Cristiano Cumer.
-
-           Support BUILDDIR variable in the Makefile. Allows builds 
-           for multiple archs from the same source tree with eg.
-           make BUILDDIR=linux             (relative to dnsmasq tree)
-           make BUILDDIR=/tmp/openbsd      (absolute path)
-           If BUILDDIR is not set, compilation happens in the src
-           directory, as before. Suggestion from Mark Mitchell.
-
-           Support DHCPv6. Support is there for the sort of things
-           the existing v4 server does, including tags, options, 
-           static addresses and relay support. Missing is prefix 
-           delegation, which is probably not required in the dnsmasq
-           niche, and an easy way to accept prefix delegations from
-           an upstream DHCPv6 server, which is. Future plans include
-           support for DHCPv6 router option and MAC address option
-           (to make selecting clients by MAC address work like IPv4).
-           These will be added as the standards mature.
-           This code has been tested, but this is the first release,
-           so don't bet the farm on it just yet. Many thanks to all 
-           testers who have got it this far.
-
-           Support IPv6 router advertisements. This is a
-           simple-minded implementation, aimed at providing the
-           vestigial RA needed to go alongside IPv6. Is picks up
-           configuration from the DHCPv6 conf, and should just need
-           enabling with --enable-ra.   
-
-           Fix long-standing wrinkle with --localise-queries that
-           could result in wrong answers when DNS packets arrive
-           via an interface other than the expected one. Thanks to 
-           Lorenzo Milesi and John Hanks for spotting this one.
-            Update French translation. Thanks to Gildas Le Nadan.
-
-           Update Polish translation. Thanks to Jan Psota.
+       Fix compilation problem in Mac OS X Lion. Thanks to Olaf
+       Flebbe for the patch.
+
+       Fix DHCP when using --listen-address with an IP address
+       which is not the primary address of an interface.
+
+       Add --dhcp-client-update option.
+
+       Add Lua integration. Dnsmasq can now execute a DHCP
+       lease-change script written in Lua. This needs to be
+       enabled at compile time by setting HAVE_LUASCRIPT in 
+       src/config.h or running "make COPTS=-DHAVE_LUASCRIPT"
+       Thanks to Jan-Piet Mens for the idea and proof-of-concept 
+       implementation.
+
+       Tidied src/config.h to distinguish between
+       platform-dependent compile-time options which are selected
+       automatically, and builder-selectable compile time
+       options. Document the latter better, and describe how to
+       set them from the make command line.
+
+       Tidied up IPPROTO_IP/SOL_IP (and IPv6 equivalent)
+       confusion. IPPROTO_IP works everywhere now.
+
+       Set TOS on DHCP sockets, this improves things on busy
+       wireless networks. Thanks to Dave Taht for the patch.
+
+       Determine VERSION automatically based on git magic:
+       release tags or hash values.
+
+       Improve start-up speed when reading large hosts files 
+       containing many distinct addresses.
+
+       Fix problem if dnsmasq is started without the stdin,
+       stdout and stderr file descriptors open. This can manifest
+       itself as 100% CPU use. Thanks to Chris Moore for finding
+       this.
+
+       Fix shell-scripting bug in bld/pkg-wrapper. Thanks to 
+       Mark Mitchell for the patch.
+
+       Allow the TFP server or boot server in --pxe-service, to
+       be a domain name instead of an IP address. This allows for
+       round-robin to multiple servers, in the same way as
+       --dhcp-boot. A good suggestion from Cristiano Cumer.
+
+       Support BUILDDIR variable in the Makefile. Allows builds 
+       for multiple archs from the same source tree with eg.
+       make BUILDDIR=linux             (relative to dnsmasq tree)
+       make BUILDDIR=/tmp/openbsd      (absolute path)
+       If BUILDDIR is not set, compilation happens in the src
+       directory, as before. Suggestion from Mark Mitchell.
+
+       Support DHCPv6. Support is there for the sort of things
+       the existing v4 server does, including tags, options, 
+       static addresses and relay support. Missing is prefix 
+       delegation, which is probably not required in the dnsmasq
+       niche, and an easy way to accept prefix delegations from
+       an upstream DHCPv6 server, which is. Future plans include
+       support for DHCPv6 router option and MAC address option
+       (to make selecting clients by MAC address work like IPv4).
+       These will be added as the standards mature.
+       This code has been tested, but this is the first release,
+       so don't bet the farm on it just yet. Many thanks to all 
+       testers who have got it this far.
+
+       Support IPv6 router advertisements. This is a
+       simple-minded implementation, aimed at providing the
+       vestigial RA needed to go alongside IPv6. Is picks up
+       configuration from the DHCPv6 conf, and should just need
+       enabling with --enable-ra.   
+
+       Fix long-standing wrinkle with --localise-queries that
+       could result in wrong answers when DNS packets arrive
+       via an interface other than the expected one. Thanks to 
+       Lorenzo Milesi and John Hanks for spotting this one.
+
+       Update French translation. Thanks to Gildas Le Nadan.
+
+       Update Polish translation. Thanks to Jan Psota.
 
 
 version 2.59
-            Fix regression in 2.58 which caused failure to start up
-            with some combinations of dnsmasq config and IPv6 kernel
-            network config. Thanks to Brielle Bruns for the bug
-            report.
-
-            Improve dnsmasq's behaviour when network interfaces are
-            still doing duplicate address detection (DAD). Previously,
-            dnsmasq would wait up to 20 seconds at start-up for the
-            DAD state to terminate. This is broken for bridge
-            interfaces on recent Linux kernels, which don't start DAD
-            until the bridge comes up, and so can take arbitrary
-            time. The new behaviour lets dnsmasq poll for an arbitrary
-            time whilst providing service on other interfaces. Thanks
-            to Stephen Hemminger for pointing out the problem.
+       Fix regression in 2.58 which caused failure to start up
+       with some combinations of dnsmasq config and IPv6 kernel
+       network config. Thanks to Brielle Bruns for the bug
+       report.
+
+       Improve dnsmasq's behaviour when network interfaces are
+       still doing duplicate address detection (DAD). Previously,
+       dnsmasq would wait up to 20 seconds at start-up for the
+       DAD state to terminate. This is broken for bridge
+       interfaces on recent Linux kernels, which don't start DAD
+       until the bridge comes up, and so can take arbitrary
+       time. The new behaviour lets dnsmasq poll for an arbitrary
+       time whilst providing service on other interfaces. Thanks
+       to Stephen Hemminger for pointing out the problem.
 
 
 version 2.58
-           Provide a definition of the SA_SIZE macro where it's 
-           missing. Fixes build failure on openBSD.
-
-           Don't include a zero terminator at the end of messages
-           sent to /dev/log when /dev/log is a datagram socket.
-           Thanks to Didier Rabound for spotting the problem.
-
-           Add --dhcp-sequential-ip flag, to force allocation of IP
-           addresses in ascending order. Note that the default
-           pseudo-random mode is in general better but some
-           server-deployment applications need this.
-
-           Fix problem where a server-id of 0.0.0.0 is sent to a
-           client when a dhcp-relay is in use if a client renews a
-           lease after dnsmasq restart and before any clients on the
-           subnet get a new lease. Thanks to Mike Ruiz for assistance
-           in chasing this one down. 
-
-           Don't return NXDOMAIN to an AAAA query if we have CNAME
-           which points to an A record only: NODATA is the correct
-           reply in this case. Thanks to Tom Fernandes for spotting
-           the problem.
-
-           Relax the need to supply a netmask in --dhcp-range for
-           networks which use a DHCP relay. Whilst this is still
-           desireable, in the absence of a netmask dnsmasq will use
-           a default based on the class (A, B, or C) of the address. 
-           This should at least remove a cause of mysterious failure 
-           for people using RFC1918 addresses and relays.
-
-           Add support for Linux conntrack connection marking. If 
-           enabled with --conntrack, the connection mark for incoming
-           DNS queries will be copied  to the outgoing connections
-           used to answer those queries. This allows clever firewall
-           and accounting stuff. Only available if dnsmasq is
-           compiled with HAVE_CONNTRACK and adds a dependency on 
-           libnetfilter-conntrack. Thanks to Ed Wildgoose for the
-           initial idea, testing and sponsorship of this function.
-
-           Provide a sane error message when someone attempts to 
-           match a tag in --dhcp-host.
-
-           Tweak the behaviour of --domain-needed, to avoid problems
-           with recursive nameservers downstream of dnsmasq. The new
-           behaviour only stops A and AAAA queries, and returns
-           NODATA rather than NXDOMAIN replies. 
-
-           Efficiency fix for very large DHCP configurations, thanks
-           to James Gartrell and Mike Ruiz for help with this. 
-
-           Allow the TFTP-server address in --dhcp-boot to be a
-           domain-name which is looked up in /etc/hosts. This can 
-           give multiple IP addresses which are used round-robin,
-           thus doing TFTP server load-balancing. Thanks to Sushil
-           Agrawal for the patch.
-
-           When two tagged dhcp-options for a particular option
-           number are both valid, use the one which is valid without
-           a tag from the dhcp-range. Allows overriding of the value
-           of a DHCP option for a particular host as well as
-           per-network values.  So 
-           --dhcp-range=set:interface1,......
-           --dhcp-host=set:myhost,.....  
-           --dhcp-option=tag:interface1,option:nis-domain,"domain1" 
-           --dhcp-option=tag:myhost,option:nis-domain,"domain2" 
-           will set the NIS-domain to domain1 for hosts in the range, but
-                   override that to domain2 for a particular host.
-
-           Fix bug which resulted in truncated files and timeouts for
-           some TFTP transfers. The bug only occurs with netascii
-           transfers and needs an unfortunate relationship between
-           file size, blocksize and the number of newlines in the
-           last block before it manifests itself. Many thanks to 
-           Alkis Georgopoulos for spotting the problem and providing
-           a comprehensive test-case. 
-
-           Fix regression in TFTP server on *BSD platforms introduced
-           in version 2.56, due to confusion with sockaddr
-           length. Many thanks to Loic Pefferkorn for finding this.
-
-           Support scope-ids in IPv6 addresses of nameservers from
-           /etc/resolv.conf and in --server options. Eg
-           nameserver fe80::202:a412:4512:7bbf%eth0 or
-           server=fe80::202:a412:4512:7bbf%eth0. Thanks to 
-           Michael Stapelberg for the suggestion.
-
-           Update Polish translation, thanks to Jan Psota.
-
-           Update French translation. Thanks to Gildas Le Nadan.
+       Provide a definition of the SA_SIZE macro where it's 
+       missing. Fixes build failure on openBSD.
+
+       Don't include a zero terminator at the end of messages
+       sent to /dev/log when /dev/log is a datagram socket.
+       Thanks to Didier Rabound for spotting the problem.
+
+       Add --dhcp-sequential-ip flag, to force allocation of IP
+       addresses in ascending order. Note that the default
+       pseudo-random mode is in general better but some
+       server-deployment applications need this.
+
+       Fix problem where a server-id of 0.0.0.0 is sent to a
+       client when a dhcp-relay is in use if a client renews a
+       lease after dnsmasq restart and before any clients on the
+       subnet get a new lease. Thanks to Mike Ruiz for assistance
+       in chasing this one down. 
+
+       Don't return NXDOMAIN to an AAAA query if we have CNAME
+       which points to an A record only: NODATA is the correct
+       reply in this case. Thanks to Tom Fernandes for spotting
+       the problem.
+
+       Relax the need to supply a netmask in --dhcp-range for
+       networks which use a DHCP relay. Whilst this is still
+       desirable, in the absence of a netmask dnsmasq will use
+       a default based on the class (A, B, or C) of the address. 
+       This should at least remove a cause of mysterious failure 
+       for people using RFC1918 addresses and relays.
+
+       Add support for Linux conntrack connection marking. If 
+       enabled with --conntrack, the connection mark for incoming
+       DNS queries will be copied  to the outgoing connections
+       used to answer those queries. This allows clever firewall
+       and accounting stuff. Only available if dnsmasq is
+       compiled with HAVE_CONNTRACK and adds a dependency on 
+       libnetfilter-conntrack. Thanks to Ed Wildgoose for the
+       initial idea, testing and sponsorship of this function.
+
+       Provide a sane error message when someone attempts to 
+       match a tag in --dhcp-host.
+
+       Tweak the behaviour of --domain-needed, to avoid problems
+       with recursive nameservers downstream of dnsmasq. The new
+       behaviour only stops A and AAAA queries, and returns
+       NODATA rather than NXDOMAIN replies. 
+
+       Efficiency fix for very large DHCP configurations, thanks
+       to James Gartrell and Mike Ruiz for help with this. 
+
+       Allow the TFTP-server address in --dhcp-boot to be a
+       domain-name which is looked up in /etc/hosts. This can 
+       give multiple IP addresses which are used round-robin,
+       thus doing TFTP server load-balancing. Thanks to Sushil
+       Agrawal for the patch.
+
+       When two tagged dhcp-options for a particular option
+       number are both valid, use the one which is valid without
+       a tag from the dhcp-range. Allows overriding of the value
+       of a DHCP option for a particular host as well as
+       per-network values.  So 
+       --dhcp-range=set:interface1,......
+       --dhcp-host=set:myhost,.....  
+       --dhcp-option=tag:interface1,option:nis-domain,"domain1" 
+       --dhcp-option=tag:myhost,option:nis-domain,"domain2" 
+       will set the NIS-domain to domain1 for hosts in the range, but
+       override that to domain2 for a particular host.
+
+       Fix bug which resulted in truncated files and timeouts for
+       some TFTP transfers. The bug only occurs with netascii
+       transfers and needs an unfortunate relationship between
+       file size, blocksize and the number of newlines in the
+       last block before it manifests itself. Many thanks to 
+       Alkis Georgopoulos for spotting the problem and providing
+       a comprehensive test-case. 
+
+       Fix regression in TFTP server on *BSD platforms introduced
+       in version 2.56, due to confusion with sockaddr
+       length. Many thanks to Loic Pefferkorn for finding this.
+
+       Support scope-ids in IPv6 addresses of nameservers from
+       /etc/resolv.conf and in --server options. Eg
+       nameserver fe80::202:a412:4512:7bbf%eth0 or
+       server=fe80::202:a412:4512:7bbf%eth0. Thanks to 
+       Michael Stapelberg for the suggestion.
+
+       Update Polish translation, thanks to Jan Psota.
+
+       Update French translation. Thanks to Gildas Le Nadan.
 
 
 version 2.57
-           Add patches to allow build under Android.
+       Add patches to allow build under Android.
 
-           Provide our own header for the DNS protocol, rather than
-           relying on arpa/nameser.h. This has proved more or less
-           defective over the years and the final straw is that it's
-           effectively empty on Android.
+       Provide our own header for the DNS protocol, rather than
+       relying on arpa/nameser.h. This has proved more or less
+       defective over the years and the final straw is that it's
+       effectively empty on Android.
 
-           Fix regression in 2.56 which caused hex constants in
-           configuration to be rejected if they contain the '*'
-           wildcard.
+       Fix regression in 2.56 which caused hex constants in
+       configuration to be rejected if they contain the '*'
+       wildcard.
 
-           Correct wrong casts of arguments to ctype.h functions,
-           isdigit(), isxdigit() etc. Thanks to Matthias Andree for
-           spotting this.
+       Correct wrong casts of arguments to ctype.h functions,
+       isdigit(), isxdigit() etc. Thanks to Matthias Andree for
+       spotting this.
 
-           Allow build with IDN support independently from i18n. 
-            IDN support continues to be included automatically 
-           when i18n is included. 
-            'make COPTS=-DHAVE_IDN' is the magic incantation. 
+       Allow build with IDN support independently from i18n. 
+       IDN support continues to be included automatically 
+       when i18n is included. 
+       'make COPTS=-DHAVE_IDN' is the magic incantation. 
 
-           Modify check on extraneous command line junk (added in
-           2.56) so that it doesn't complain about extra _empty_ 
-           arguments. Otherwise this breaks libvirt.
+       Modify check on extraneous command line junk (added in
+       2.56) so that it doesn't complain about extra _empty_ 
+       arguments. Otherwise this breaks libvirt.
 
 
 version 2.56
-            Add a patch to allow dnsmasq to get interface names right in a
-            Solaris zone. Thanks to Dj Padzensky for this.
-
-           Improve data-type parsing heuristics so that
-           --dhcp-option=option:domain-search,. 
-           treats the value as a string and not an IP address.
-           Thanks to Clemens Fischer for spotting that.
-
-           Add IPv6 support to the TFTP server. Many thanks to Jan 
-           'RedBully' Seiffert for the patches.
-           
-           Log DNS queries at level LOG_INFO, rather then
-           LOG_DEBUG. This makes things consistent with DHCP
-           logging. Thanks to Adam Pribyl for spotting the problem.
-
-            Ensure that dnsmasq terminates cleanly when using
-            --syslog-async even if it cannot make a connection to the
-            syslogd.
-
-           Add --add-mac option. This is to support currently 
-           experimental DNS filtering facilities. Thanks to Benjamin
-           Petrin for the orignal patch. 
-
-           Fix bug which meant that tags were ignored in dhcp-range
-           configuration specifying PXE-proxy service. Thanks to
-           Cristiano Cumer for spotting this.
-
-           Raise an error if there is extra junk, not part of an
-           option, on the command line.
-
-           Flag a couple of log messages in cache.c as coming from
-           the DHCP subsystem. Thanks to Olaf Westrik for the patch.
-
-           Omit timestamps from logs when a) logging to stderr and 
-           b) --keep-in-forground is set. The logging facility on the
-           other end of stderr can be assumned to supply them. Thanks
-           to John Hallam for the patch.
-
-           Don't complain about strings longer than 255 characters in
-           --txt-record, just split the long strings into 255
-           character chunks instead.
-
-           Fix crash on double-free. This bug can only happen when
-           dhcp-script is in use and then only in rare circumstances
-           triggered by high DHCP transaction rate and a slow
-           script. Thanks to Ferenc Wagner for finding the problem.
-
-           Only log that a file has been sent by TFTP after the
-           transfer has completed succesfully. 
-
-           A good suggestion from Ferenc Wagner: extend
-           the --domain option to allow this sort of thing:
-            --domain=thekelleys.org.uk,192.168.0.0/24,local
-           which automatically creates
-           --local=/thekelleys.org.uk/
-           --local=/0.168.192.in-addr.arpa/ 
-
-           Tighten up syntax checking of hex contants in the config
-           file.  Thanks to Fred Damen for spotting this.
-
-           Add dnsmasq logo/icon, contributed by Justin Swift. Many
-           thanks for that.
-
-           Never cache DNS replies which have the 'cd' bit set, or
-           which result from queries forwarded with the 'cd' bit
-           set. The 'cd' bit instructs a DNSSEC validating server
-           upstream to ignore signature failures and return replies
-           anyway. Without this change it's possible to pollute the
-           dnsmasq cache with bad data by making a query with the
-           'cd' bit set and subsequent queries would return this data
-           without its being marked as suspect. Thanks to Anders
-           Kaseorg for pointing out this problem.
-
-           Add --proxy-dnssec flag, for compliance with RFC
-           4035. Dnsmasq will now clear the 'ad' bit in answers returned
-           from upstream validating nameservers unless this option is
-           set.
-
-           Allow a filename of "-" for --conf-file to read
-           stdin. Suggestion from Timothy Redaelli.
-
-           Rotate the order of SRV records in replies, to provide
-           round-robin load balancing when all the priorities are
-           equal. Thanks to Peter McKinney for the suggestion. 
-
-           Edit
-           contrib/MacOSX-launchd/uk.org.thekelleys.dnsmasq.plist 
-           so that it doesn't log all queries to a file by
-           default. Thanks again to Peter McKinney.    
-
-           By default, setting an IPv4 address for a domain but not
-           an IPv6 address causes dnsmasq to return
-           an NODATA reply for IPv6 (or vice-versa). So
-           --address=/google.com/1.2.3.4 stops IPv6 queries for
-           *google.com from being forwarded. Make it possible to
-           override this behaviour by defining the sematics if the
-           same domain appears in  both --server and --address.
-           In that case, the --address has priority for the address
-           family in which is appears, but the --server has priority
-           of the address family which doesn't appear in --adddress  
-           So:
-           --address=/google.com/1.2.3.4
-           --server=/google.com/#
-           will return 1.2.3.4 for IPv4 queries for *.google.com but
-           forward IPv6 queries to the normal upstream nameserver.
-           Similarly when setting an IPv6 address
-           only this will allow forwarding of IPv4 queries. Thanks to
-           William for pointing out the need for this.
-
-           Allow more than one --dhcp-optsfile and --dhcp-hostsfile
-           and make them understand directories as arguments in the
-           same way as --addn-hosts. Suggestion from John Hanks. 
-
-           Ignore rebinding requests for leases we don't know
-           about. Rebind is broadcast, so we might get to overhear a
-           request meant for another DHCP server. NAKing this is
-           wrong. Thanks to Brad D'Hondt for assistance with this.
-
-            Fix cosmetic bug which produced strange output when
-            dumping cache statistics with some configurations. Thanks
-            to Fedor Kozhevnikov for spotting this.
+       Add a patch to allow dnsmasq to get interface names right in a
+       Solaris zone. Thanks to Dj Padzensky for this.
+
+       Improve data-type parsing heuristics so that
+       --dhcp-option=option:domain-search,. 
+       treats the value as a string and not an IP address.
+       Thanks to Clemens Fischer for spotting that.
+
+       Add IPv6 support to the TFTP server. Many thanks to Jan 
+       'RedBully' Seiffert for the patches.
+
+       Log DNS queries at level LOG_INFO, rather then
+       LOG_DEBUG. This makes things consistent with DHCP
+       logging. Thanks to Adam Pribyl for spotting the problem.
+
+       Ensure that dnsmasq terminates cleanly when using
+       --syslog-async even if it cannot make a connection to the
+       syslogd.
+
+       Add --add-mac option. This is to support currently 
+       experimental DNS filtering facilities. Thanks to Benjamin
+       Petrin for the original patch. 
+
+       Fix bug which meant that tags were ignored in dhcp-range
+       configuration specifying PXE-proxy service. Thanks to
+       Cristiano Cumer for spotting this.
+
+       Raise an error if there is extra junk, not part of an
+       option, on the command line.
+
+       Flag a couple of log messages in cache.c as coming from
+       the DHCP subsystem. Thanks to Olaf Westrik for the patch.
+
+       Omit timestamps from logs when a) logging to stderr and 
+       b) --keep-in-foreground is set. The logging facility on the
+       other end of stderr can be assumed to supply them. Thanks
+       to John Hallam for the patch.
+
+       Don't complain about strings longer than 255 characters in
+       --txt-record, just split the long strings into 255
+       character chunks instead.
+
+       Fix crash on double-free. This bug can only happen when
+       dhcp-script is in use and then only in rare circumstances
+       triggered by high DHCP transaction rate and a slow
+       script. Thanks to Ferenc Wagner for finding the problem.
+
+       Only log that a file has been sent by TFTP after the
+       transfer has completed successfully. 
+
+       A good suggestion from Ferenc Wagner: extend
+       the --domain option to allow this sort of thing:
+       --domain=thekelleys.org.uk,192.168.0.0/24,local
+       which automatically creates
+       --local=/thekelleys.org.uk/
+       --local=/0.168.192.in-addr.arpa/ 
+
+       Tighten up syntax checking of hex constants in the config
+       file.  Thanks to Fred Damen for spotting this.
+
+       Add dnsmasq logo/icon, contributed by Justin Swift. Many
+       thanks for that.
+
+       Never cache DNS replies which have the 'cd' bit set, or
+       which result from queries forwarded with the 'cd' bit
+       set. The 'cd' bit instructs a DNSSEC validating server
+       upstream to ignore signature failures and return replies
+       anyway. Without this change it's possible to pollute the
+       dnsmasq cache with bad data by making a query with the
+       'cd' bit set and subsequent queries would return this data
+       without its being marked as suspect. Thanks to Anders
+       Kaseorg for pointing out this problem.
+
+       Add --proxy-dnssec flag, for compliance with RFC
+       4035. Dnsmasq will now clear the 'ad' bit in answers returned
+       from upstream validating nameservers unless this option is
+       set.
+
+       Allow a filename of "-" for --conf-file to read
+       stdin. Suggestion from Timothy Redaelli.
+
+       Rotate the order of SRV records in replies, to provide
+       round-robin load balancing when all the priorities are
+       equal. Thanks to Peter McKinney for the suggestion. 
+
+       Edit
+       contrib/MacOSX-launchd/uk.org.thekelleys.dnsmasq.plist 
+       so that it doesn't log all queries to a file by
+       default. Thanks again to Peter McKinney.    
+
+       By default, setting an IPv4 address for a domain but not
+       an IPv6 address causes dnsmasq to return
+       a NODATA reply for IPv6 (or vice-versa). So
+       --address=/google.com/1.2.3.4 stops IPv6 queries for
+       *google.com from being forwarded. Make it possible to
+       override this behaviour by defining the semantics if the
+       same domain appears in  both --server and --address.
+       In that case, the --address has priority for the address
+       family in which is appears, but the --server has priority
+       of the address family which doesn't appear in --address  
+       So:
+       --address=/google.com/1.2.3.4
+       --server=/google.com/#
+       will return 1.2.3.4 for IPv4 queries for *.google.com but
+       forward IPv6 queries to the normal upstream nameserver.
+       Similarly when setting an IPv6 address
+       only this will allow forwarding of IPv4 queries. Thanks to
+       William for pointing out the need for this.
+
+       Allow more than one --dhcp-optsfile and --dhcp-hostsfile
+       and make them understand directories as arguments in the
+       same way as --addn-hosts. Suggestion from John Hanks. 
+
+       Ignore rebinding requests for leases we don't know
+       about. Rebind is broadcast, so we might get to overhear a
+       request meant for another DHCP server. NAKing this is
+       wrong. Thanks to Brad D'Hondt for assistance with this.
+
+       Fix cosmetic bug which produced strange output when
+       dumping cache statistics with some configurations. Thanks
+       to Fedor Kozhevnikov for spotting this.
 
 
 version 2.55
-            Fix crash when /etc/ethers is in use. Thanks to 
-           Gianluigi Tiesi for finding this.
+       Fix crash when /etc/ethers is in use. Thanks to 
+       Gianluigi Tiesi for finding this.
 
-           Fix crash in netlink_multicast(). Thanks to Arno Wald for
-           finding this one.
+       Fix crash in netlink_multicast(). Thanks to Arno Wald for
+       finding this one.
 
-           Allow the empty domain "." in dhcp domain-search (119)
-           options. 
+       Allow the empty domain "." in dhcp domain-search (119)
+       options. 
 
 
 version 2.54
-            There is no version 2.54 to avoid confusion with 2.53,
-            which incorrectly identifies itself as 2.54.
+       There is no version 2.54 to avoid confusion with 2.53,
+       which incorrectly identifies itself as 2.54.
 
 
 version 2.53
-            Fix failure to compile on Debian/kFreeBSD. Thanks to 
-           Axel Beckert and Petr Salinger.
-
-           Fix code to avoid scary strict-aliasing warnings
-           generated by gcc 4.4.
-           
-           Added FAQ entry warning about DHCP failures with Vista
-           when firewalls block 255.255.255.255.
-           
-           Fixed bug which caused bad things to happen if a 
-           resolv.conf file which exists is subsequently removed.
-           Thanks to Nikolai Saoukh for the patch.
-
-           Rationalised the DHCP tag system. Every configuration item
-           which can set a tag does so by adding "set:<tag>" and
-           every configuration item which is conditional on a tag is
-           made so by "tag:<tag>". The NOT operator changes to '!',
-           which is a bit more intuitive too. Dhcp-host directives
-           can set more than one tag now. The old '#' NOT, 
-           "net:" prefix and no-prefixes are still honoured, so 
-           no existing config file needs to be changed, but 
-           the documentation and new-style config files should be 
-           much less confusing. 
-
-           Added --tag-if to allow boolean operations on tags. 
-           This allows complicated logic to be clearer and more 
-           general. A great suggestion from Richard Voigt. 
-
-           Add broadcast/unicast information to DHCP logging.
-
-           Allow --dhcp-broadcast to be unconditional.
-
-           Fixed incorrect behaviour with NOT <tag> conditionals in
-           dhcp-options. Thanks to Max Turkewitz for assistance
-           finding this.
-
-           If we send vendor-class encapsulated options based on the
-           vendor-class supplied by the client, and no explicit 
-           vendor-class option is given, echo back the vendor-class
-           from the client.
-           Fix bug which stopped dnsmasq from matching both a
-           circuitid and a remoteid. Thanks to Ignacio Bravo for
-           finding this.
-
-           Add --dhcp-proxy, which makes it possible to configure
-           dnsmasq to use a DHCP relay agent as a full proxy, with
-           all DHCP messages passing through the proxy. This is
-           useful if the relay adds extra information to the packets
-           it forwards, but cannot be configured with the RFC 5107 
-           server-override option.
-
-           Added interface:<iface name> part to dhcp-range. The
-           semantics of this are very odd at first sight, but it
-           allows a single line  of the form
-               dhcp-range=interface:virt0,192.168.0.4,192.168.0.200
-           to be added to dnsmasq configuration which then supplies
-           DHCP and DNS services to that interface, without affecting
-           what services are supplied to other interfaces and 
-           irrespective of the existance or lack of 
-                interface=<interface> 
-            lines elsewhere in the dnsmasq configuration. The idea is
-           that such a line can be added automatically by libvirt
-           or equivalent systems, without disturbing any manual
-           configuration.
-
-           Similarly to the above, allow --enable-tftp=<interface>
-
-           Allow a TFTP root to be set separately for requests via
-           different interfaces, --tftp-root=<path>,<interface>             
-
-           Correctly handle and log clashes between CNAMES and 
-           DNS names being given to DHCP leases. This fixes a bug 
-           which caused nonsense IP addresses to be logged. Thanks to 
-            Sergei Zhirikov for finding and analysing the problem.
-
-           Tweak flush_log so as to avoid leaving the log
-           file in non-blocking mode. O_NONBLOCK is a property of the
-           file, not the process/descriptor.
-
-           Fix contrib/Solaris10/create_package
-           (/usr/man -> /usr/share/man) Thanks to Vita Batrla.
-
-           Fix a problem where, if a client got a lease, then went
-           to another subnet and got another lease, then moved back,
-           it couldn't resume the old lease, but would instead get 
-           a new address. Thanks to Leonardo Rodrigues for spotting
-           this and testing the fix.
-           
-           Fix weird bug which sometimes omitted certain characters
-           from the start of quoted strings in dhcp-options. Thanks
-           to Dayton Turner for spotting the problem.
-
-           Add facility to redirect some domains to the standard
-           upstream servers: this allows something like 
-           --server=/google.com/1.2.3.4 --server=/www.google.com/#
-           which will send queries for *.google.com to 1.2.3.4,
-           except *www.google.com which will be forwarded as usual.
-           Thanks to AJ Weber for prompting this addition.
-           Improve the hash-algorithm used to generate IP addresses
-           from MAC addresses during initial DHCP address
-           allocation. This improves performance when large numbers
-           of hosts with similar MAC addresses all try and get an IP
-           address at the same time. Thanks to Paul Smith for his
-           work on this.
-
-           Tweak DHCP code so that --bridge-interface can be used to
-           select which IP alias of an interface should be used for
-           DHCP purposes on Linux. If eth0 has an alias eth0:dhcp
-           then adding  --bridge-interface=eth0:dhcp,eth0 will use 
-           the address of eth0:dhcp to determine the correct subnet 
-           for DHCP address allocation. Thanks to Pawel Golaszewski 
-            for prompting this and Eric Cooper for further testing.
-
-           Add --dhcp-generate-names. Suggestion by Ferenc Wagner.
-
-           Tweak DNS server selection algorithm when there is more
-           than one server available for a domain, eg.
-            --server=/mydomain/1.1.1.1
-            --server=/mydomain/2.2.2.2
-           Thanks to Alberto Cuesta-Canada for spotting a weakness
-           here.
-
-           Add --max-ttl. Thanks to Fredrik Ringertz for the patch.
-
-           Allow --log-facility=- to force all logging to
-           stderr. Suggestion from Clemens Fischer.
-
-           Fix regression which caused configuration like
-           --address=/.domain.com/1.2.3.4 to be rejected. The dot to the 
-           left of the domain has been implied and not required for a
-           long time, but it should be accepted for backward
-           compatibility. Thanks to Andrew Burcin for spotting this.
-    
-            Add --rebind-domain-ok and --rebind-localhost-ok.
-           Suggestion from Clemens Fischer.
-
-           Log replies to queries of type TXT, when --log-queries 
-           is set.
-
-           Fix compiler warnings when compiled with -DNO_DHCP. Thanks
-           to Shantanu Gadgil for the patch.
-
-            Updated French translation. Thanks to Gildas Le Nadan.
-
-           Updated Polish translation. Thanks to Jan Psota.
-
-           Updated German translation. Thanks to Matthias Andree.
-
-           Added contrib/static-arp, thanks to Darren Hoo.
-           Fix corruption of the domain when a name from /etc/hosts
-           overrides one supplied by a DHCP client. Thanks to Fedor
-           Kozhevnikov for spotting the problem.
-
-            Updated Spanish translation. Thanks to Chris Chatham.
+       Fix failure to compile on Debian/kFreeBSD. Thanks to 
+       Axel Beckert and Petr Salinger.
+
+       Fix code to avoid scary strict-aliasing warnings
+       generated by gcc 4.4.
+       
+       Added FAQ entry warning about DHCP failures with Vista
+       when firewalls block 255.255.255.255.
+       
+       Fixed bug which caused bad things to happen if a 
+       resolv.conf file which exists is subsequently removed.
+       Thanks to Nikolai Saoukh for the patch.
+
+       Rationalised the DHCP tag system. Every configuration item
+       which can set a tag does so by adding "set:<tag>" and
+       every configuration item which is conditional on a tag is
+       made so by "tag:<tag>". The NOT operator changes to '!',
+       which is a bit more intuitive too. Dhcp-host directives
+       can set more than one tag now. The old '#' NOT, 
+       "net:" prefix and no-prefixes are still honoured, so 
+       no existing config file needs to be changed, but 
+       the documentation and new-style config files should be 
+       much less confusing. 
+
+       Added --tag-if to allow boolean operations on tags. 
+       This allows complicated logic to be clearer and more 
+       general. A great suggestion from Richard Voigt. 
+
+       Add broadcast/unicast information to DHCP logging.
+
+       Allow --dhcp-broadcast to be unconditional.
+
+       Fixed incorrect behaviour with NOT <tag> conditionals in
+       dhcp-options. Thanks to Max Turkewitz for assistance
+       finding this.
+
+       If we send vendor-class encapsulated options based on the
+       vendor-class supplied by the client, and no explicit 
+       vendor-class option is given, echo back the vendor-class
+       from the client.
+       
+       Fix bug which stopped dnsmasq from matching both a
+       circuitid and a remoteid. Thanks to Ignacio Bravo for
+       finding this.
+
+       Add --dhcp-proxy, which makes it possible to configure
+       dnsmasq to use a DHCP relay agent as a full proxy, with
+       all DHCP messages passing through the proxy. This is
+       useful if the relay adds extra information to the packets
+       it forwards, but cannot be configured with the RFC 5107 
+       server-override option.
+
+       Added interface:<iface name> part to dhcp-range. The
+       semantics of this are very odd at first sight, but it
+       allows a single line  of the form
+       dhcp-range=interface:virt0,192.168.0.4,192.168.0.200
+       to be added to dnsmasq configuration which then supplies
+       DHCP and DNS services to that interface, without affecting
+       what services are supplied to other interfaces and 
+       irrespective of the existence or lack of 
+       interface=<interface> 
+       lines elsewhere in the dnsmasq configuration. The idea is
+       that such a line can be added automatically by libvirt
+       or equivalent systems, without disturbing any manual
+       configuration.
+
+       Similarly to the above, allow --enable-tftp=<interface>
+
+       Allow a TFTP root to be set separately for requests via
+       different interfaces, --tftp-root=<path>,<interface>             
+
+       Correctly handle and log clashes between CNAMES and 
+       DNS names being given to DHCP leases. This fixes a bug 
+       which caused nonsense IP addresses to be logged. Thanks to 
+       Sergei Zhirikov for finding and analysing the problem.
+
+       Tweak flush_log so as to avoid leaving the log
+       file in non-blocking mode. O_NONBLOCK is a property of the
+       file, not the process/descriptor.
+
+       Fix contrib/Solaris10/create_package
+       (/usr/man -> /usr/share/man) Thanks to Vita Batrla.
+
+       Fix a problem where, if a client got a lease, then went
+       to another subnet and got another lease, then moved back,
+       it couldn't resume the old lease, but would instead get 
+       a new address. Thanks to Leonardo Rodrigues for spotting
+       this and testing the fix.
+
+       Fix weird bug which sometimes omitted certain characters
+       from the start of quoted strings in dhcp-options. Thanks
+       to Dayton Turner for spotting the problem.
+
+       Add facility to redirect some domains to the standard
+       upstream servers: this allows something like 
+       --server=/google.com/1.2.3.4 --server=/www.google.com/#
+       which will send queries for *.google.com to 1.2.3.4,
+       except *www.google.com which will be forwarded as usual.
+       Thanks to AJ Weber for prompting this addition.
+
+       Improve the hash-algorithm used to generate IP addresses
+       from MAC addresses during initial DHCP address
+       allocation. This improves performance when large numbers
+       of hosts with similar MAC addresses all try and get an IP
+       address at the same time. Thanks to Paul Smith for his
+       work on this.
+
+       Tweak DHCP code so that --bridge-interface can be used to
+       select which IP alias of an interface should be used for
+       DHCP purposes on Linux. If eth0 has an alias eth0:dhcp
+       then adding  --bridge-interface=eth0:dhcp,eth0 will use 
+       the address of eth0:dhcp to determine the correct subnet 
+       for DHCP address allocation. Thanks to Pawel Golaszewski 
+       for prompting this and Eric Cooper for further testing.
+
+       Add --dhcp-generate-names. Suggestion by Ferenc Wagner.
+
+       Tweak DNS server selection algorithm when there is more
+       than one server available for a domain, eg.
+       --server=/mydomain/1.1.1.1
+       --server=/mydomain/2.2.2.2
+       Thanks to Alberto Cuesta-Canada for spotting a weakness
+       here.
+
+       Add --max-ttl. Thanks to Fredrik Ringertz for the patch.
+
+       Allow --log-facility=- to force all logging to
+       stderr. Suggestion from Clemens Fischer.
+
+       Fix regression which caused configuration like
+       --address=/.domain.com/1.2.3.4 to be rejected. The dot to the 
+       left of the domain has been implied and not required for a
+       long time, but it should be accepted for backward
+       compatibility. Thanks to Andrew Burcin for spotting this.
+
+       Add --rebind-domain-ok and --rebind-localhost-ok.
+       Suggestion from Clemens Fischer.
+
+       Log replies to queries of type TXT, when --log-queries 
+       is set.
+
+       Fix compiler warnings when compiled with -DNO_DHCP. Thanks
+       to Shantanu Gadgil for the patch.
+
+       Updated French translation. Thanks to Gildas Le Nadan.
+
+       Updated Polish translation. Thanks to Jan Psota.
+
+       Updated German translation. Thanks to Matthias Andree.
+
+       Added contrib/static-arp, thanks to Darren Hoo.
+
+       Fix corruption of the domain when a name from /etc/hosts
+       overrides one supplied by a DHCP client. Thanks to Fedor
+       Kozhevnikov for spotting the problem.
+
+       Updated Spanish translation. Thanks to Chris Chatham.
 
 
 version 2.52
-            Work around a Linux kernel bug which insists that the 
-           length of the option passed to setsockopt must be at least
-            sizeof(int) bytes, even if we're calling SO_BINDTODEVICE
-            and the device name is "lo".  Note that this is fixed 
-           in kernel 2.6.31, but the workaround is harmless and 
-           allows earlier kernels to be used. Also fix dnsmasq 
-           bug which reported the wrong address when this failed. 
-           Thanks to Fedor for finding this.
-
-           The API for IPv6 PKTINFO changed around Linux kernel
-           2.6.14. Workaround the case where dnsmasq is compiled
-           against newer headers, but then run on an old kernel:
-           necessary for some *WRT distros.
-
-           Re-read the set of network interfaces when re-loading
-           /etc/resolv.conf if --bind-interfaces is not set. This
-           handles the case that loopback interfaces do not exist
-           when dnsmasq is first started.
-
-           Tweak the PXE code to support port 4011. This should
-           reduce broadcasts and make things more reliable when other
-           servers are around. It also improves inter-operability
-           with certain clients.
-
-           Make a pxe-service configuration with no filename or boot 
-           service type legal: this does a local boot. eg.
-           pxe-service=x86PC, "Local boot" 
-
-           Be more conservative in detecting "A for A"
-           queries. Dnsmasq checks if the name in a type=A query looks
-           like a dotted-quad IP address and answers the query itself
-           if so, rather than forwarding it. Previously dnsmasq
-           relied in the library function inet_addr() to convert
-           addresses, and that will accept some things which are
-           confusing in this context, like 1.2.3 or even just
-           1234. Now we only do A for A processing for four decimal
-           numbers delimited by dots.
-
-           A couple of tweaks to fix compilation on Solaris. Thanks
-           to Joel Macklow for help with this.
-
-           Another Solaris compilation tweak, needed for Solaris
-           2009.06. Thanks to Lee Essen for that.
-
-           Added extract packaging stuff from Lee Essen to 
-           contrib/Solaris10.
-          
-            Increased the default limit on number of leases to 1000
-            (from 150). This is mainly a defence against DoS attacks,
-            and for the average "one for two class C networks"
-            installation, IP address exhaustion does that just as
-            well. Making the limit greater than the number of IP
-            addresses available in such an installation removes a
-            surprise which otherwise can catch people out.
-
-           Removed extraneous trailing space in the value of the
-           DNSMASQ_TIME_REMAINING DNSMASQ_LEASE_LENGTH and
-           DNSMASQ_LEASE_EXPIRES environment variables. Thanks to
-           Gildas Le Nadan for spotting this.
-
-           Provide the network-id tags for a DHCP transaction to 
-           the lease-change script in the environment variable
-           DNSMASQ_TAGS. A good suggestion from Gildas Le Nadan.  
-
-           Add support for RFC3925 "Vendor-Identifying Vendor
-           Options". The syntax looks like this:  
-           --dhcp-option=vi-encap:<enterprise number>, .........
-
-           Add support to --dhcp-match to allow matching against
-           RFC3925 "Vendor-Identifying Vendor Classes". The syntax
-           looks like this:
-           --dhcp-match=tag,vi-encap<enterprise number>, <value>
-           
-           Add some application specific code to assist in
-           implementing the Broadband forum TR069 CPE-WAN
-           specification. The details are in contrib/CPE-WAN/README
-
-           Increase the default DNS packet size limit to 4096, as
-           recommended by RFC5625 section 4.4.3. This can be
-           reconfigured using --edns-packet-max if needed. Thanks to
-           Francis Dupont for pointing this out.
-
-           Rewrite query-ids even for TSIG signed packets, since
-           this is allowed by RFC5625 section 4.5.
-           
-           Use getopt_long by default on OS X. It has been supported
-           since version 10.3.0. Thanks to Arek Dreyer for spotting
-           this.
-
-           Added up-to-date startup configuration for MacOSX/launchd
-           in contrib/MacOSX-launchd. Thanks to Arek Dreyer for
-           providing this.
-
-           Fix link error when including Dbus but excluding DHCP. 
-           Thanks to Oschtan for the bug report.
-
-            Updated French translation. Thanks to Gildas Le Nadan.
-            Updated Polish translation. Thanks to Jan Psota.
-
-           Updated Spanish translation. Thanks to Chris Chatham.
-
-           Fixed confusion about domains, when looking up DHCP hosts
-           in /etc/hosts. This could cause spurious "Ignoring
-           domain..." messages. Thanks to Fedor Kozhevnikov for
-           finding and analysing the problem.
-
-           
+       Work around a Linux kernel bug which insists that the 
+       length of the option passed to setsockopt must be at least
+       sizeof(int) bytes, even if we're calling SO_BINDTODEVICE
+       and the device name is "lo".  Note that this is fixed 
+       in kernel 2.6.31, but the workaround is harmless and 
+       allows earlier kernels to be used. Also fix dnsmasq 
+       bug which reported the wrong address when this failed. 
+       Thanks to Fedor for finding this.
+
+       The API for IPv6 PKTINFO changed around Linux kernel
+       2.6.14. Workaround the case where dnsmasq is compiled
+       against newer headers, but then run on an old kernel:
+       necessary for some *WRT distros.
+
+       Re-read the set of network interfaces when re-loading
+       /etc/resolv.conf if --bind-interfaces is not set. This
+       handles the case that loopback interfaces do not exist
+       when dnsmasq is first started.
+
+       Tweak the PXE code to support port 4011. This should
+       reduce broadcasts and make things more reliable when other
+       servers are around. It also improves inter-operability
+       with certain clients.
+
+       Make a pxe-service configuration with no filename or boot 
+       service type legal: this does a local boot. eg.
+       pxe-service=x86PC, "Local boot" 
+
+       Be more conservative in detecting "A for A"
+       queries. Dnsmasq checks if the name in a type=A query looks
+       like a dotted-quad IP address and answers the query itself
+       if so, rather than forwarding it. Previously dnsmasq
+       relied in the library function inet_addr() to convert
+       addresses, and that will accept some things which are
+       confusing in this context, like 1.2.3 or even just
+       1234. Now we only do A for A processing for four decimal
+       numbers delimited by dots.
+
+       A couple of tweaks to fix compilation on Solaris. Thanks
+       to Joel Macklow for help with this.
+
+       Another Solaris compilation tweak, needed for Solaris
+       2009.06. Thanks to Lee Essen for that.
+
+       Added extract packaging stuff from Lee Essen to 
+       contrib/Solaris10.
+
+       Increased the default limit on number of leases to 1000
+       (from 150). This is mainly a defence against DoS attacks,
+       and for the average "one for two class C networks"
+       installation, IP address exhaustion does that just as
+       well. Making the limit greater than the number of IP
+       addresses available in such an installation removes a
+       surprise which otherwise can catch people out.
+
+       Removed extraneous trailing space in the value of the
+       DNSMASQ_TIME_REMAINING DNSMASQ_LEASE_LENGTH and
+       DNSMASQ_LEASE_EXPIRES environment variables. Thanks to
+       Gildas Le Nadan for spotting this.
+
+       Provide the network-id tags for a DHCP transaction to 
+       the lease-change script in the environment variable
+       DNSMASQ_TAGS. A good suggestion from Gildas Le Nadan.  
+
+       Add support for RFC3925 "Vendor-Identifying Vendor
+       Options". The syntax looks like this:  
+       --dhcp-option=vi-encap:<enterprise number>, .........
+
+       Add support to --dhcp-match to allow matching against
+       RFC3925 "Vendor-Identifying Vendor Classes". The syntax
+       looks like this:
+       --dhcp-match=tag,vi-encap<enterprise number>, <value>
+
+       Add some application specific code to assist in
+       implementing the Broadband forum TR069 CPE-WAN
+       specification. The details are in contrib/CPE-WAN/README
+
+       Increase the default DNS packet size limit to 4096, as
+       recommended by RFC5625 section 4.4.3. This can be
+       reconfigured using --edns-packet-max if needed. Thanks to
+       Francis Dupont for pointing this out.
+
+       Rewrite query-ids even for TSIG signed packets, since
+       this is allowed by RFC5625 section 4.5.
+
+       Use getopt_long by default on OS X. It has been supported
+       since version 10.3.0. Thanks to Arek Dreyer for spotting
+       this.
+
+       Added up-to-date startup configuration for MacOSX/launchd
+       in contrib/MacOSX-launchd. Thanks to Arek Dreyer for
+       providing this.
+
+       Fix link error when including Dbus but excluding DHCP. 
+       Thanks to Oschtan for the bug report.
+
+       Updated French translation. Thanks to Gildas Le Nadan.
+
+       Updated Polish translation. Thanks to Jan Psota.
+
+       Updated Spanish translation. Thanks to Chris Chatham.
+
+       Fixed confusion about domains, when looking up DHCP hosts
+       in /etc/hosts. This could cause spurious "Ignoring
+       domain..." messages. Thanks to Fedor Kozhevnikov for
+       finding and analysing the problem.
+
+
 version 2.51
-            Add support for internationalised DNS. Non-ASCII characters
-            in domain names found in /etc/hosts, /etc/ethers and 
-           /etc/dnsmasq.conf will be correctly handled by translation to
-            punycode, as specified in RFC3490. This function is only
-            available if dnsmasq is compiled with internationalisation
-            support, and adds a dependency on GNU libidn. Without i18n
-            support, dnsmasq continues to be compilable with just
-            standard tools. Thanks to Yves Dorfsman for the
-            suggestion. 
-
-            Add two more environment variables for lease-change scripts:
-           First, DNSMASQ_SUPPLIED_HOSTNAME; this is set to the hostname
-           supplied by a client, even if the actual hostname used is
-           over-ridden by dhcp-host or dhcp-ignore-names directives.
-           Also DNSMASQ_RELAY_ADDRESS which gives the address of 
-            a DHCP relay, if used.
-           Suggestions from Michael Rack.
-
-           Fix regression which broke echo of relay-agent
-           options. Thanks to Michael Rack for spotting this.
-          
-            Don't treat option 67 as being interchangeable with
-            dhcp-boot parameters if it's specified as
-            dhcp-option-force.
-
-           Make the code to call scripts on lease-change compile-time
-           optional. It can be switched off by editing src/config.h
-           or building with "make COPTS=-DNO_SCRIPT".
-           Make the TFTP server cope with filenames from Windows/DOS
-           which use '\' as pathname separator. Thanks to Ralf for
-           the patch.
-
-           Updated Polish translation. Thanks to Jan Psota.
-           Warn if an IP address is duplicated in /etc/ethers. Thanks
-           to Felix Schwarz for pointing this out.
-
-           Teach --conf-dir to take an option list of file suffices
-           which will be ignored when scanning the directory. Useful
-           for backup files etc. Thanks to Helmut Hullen for the
-           suggestion. 
-
-           Add new DHCP option named tftpserver-address, which
-           corresponds to the third argument of dhcp-boot. This
-           allows the complete functionality of dhcp-boot to be
-           replicated with dhcp-option. Useful when using 
-           dhcp-optsfile.
-
-           Test which upstream nameserver to use every 10 seconds
-            or 50 queries and not just when a query times out and 
-            is retried. This should improve performance when there
-            is a slow nameserver in the list. Thanks to Joe for the
-            suggestion. 
-
-           Don't do any PXE processing, even for clients with the 
-           correct vendorclass, unless at least one pxe-prompt or 
-            pxe-service option is given. This stops dnsmasq 
-            interfering with proxy PXE subsystems when it is just 
-            the DHCP server. Thanks to Spencer Clark for spotting this.
-
-           Limit the blocksize used for TFTP transfers to a value
-           which avoids packet fragmentation, based on the MTU of the
-           local interface. Many netboot ROMs can't cope with
-           fragmented packets.
-
-           Honour dhcp-ignore configuration for PXE and proxy-PXE 
-           requests. Thanks to Niels Basjes for the bug report.
-
-            Updated French translation. Thanks to Gildas Le Nadan.
+       Add support for internationalised DNS. Non-ASCII characters
+       in domain names found in /etc/hosts, /etc/ethers and 
+       /etc/dnsmasq.conf will be correctly handled by translation to
+       punycode, as specified in RFC3490. This function is only
+       available if dnsmasq is compiled with internationalisation
+       support, and adds a dependency on GNU libidn. Without i18n
+       support, dnsmasq continues to be compilable with just
+       standard tools. Thanks to Yves Dorfsman for the
+       suggestion. 
+
+       Add two more environment variables for lease-change scripts:
+       First, DNSMASQ_SUPPLIED_HOSTNAME; this is set to the hostname
+       supplied by a client, even if the actual hostname used is
+       over-ridden by dhcp-host or dhcp-ignore-names directives.
+       Also DNSMASQ_RELAY_ADDRESS which gives the address of 
+       a DHCP relay, if used.
+       Suggestions from Michael Rack.
+
+       Fix regression which broke echo of relay-agent
+       options. Thanks to Michael Rack for spotting this.
+
+       Don't treat option 67 as being interchangeable with
+       dhcp-boot parameters if it's specified as
+       dhcp-option-force.
+
+       Make the code to call scripts on lease-change compile-time
+       optional. It can be switched off by editing src/config.h
+       or building with "make COPTS=-DNO_SCRIPT".
+
+       Make the TFTP server cope with filenames from Windows/DOS
+       which use '\' as pathname separator. Thanks to Ralf for
+       the patch.
+
+       Updated Polish translation. Thanks to Jan Psota.
+
+       Warn if an IP address is duplicated in /etc/ethers. Thanks
+       to Felix Schwarz for pointing this out.
+
+       Teach --conf-dir to take an option list of file suffices
+       which will be ignored when scanning the directory. Useful
+       for backup files etc. Thanks to Helmut Hullen for the
+       suggestion. 
+
+       Add new DHCP option named tftpserver-address, which
+       corresponds to the third argument of dhcp-boot. This
+       allows the complete functionality of dhcp-boot to be
+       replicated with dhcp-option. Useful when using 
+       dhcp-optsfile.
+
+       Test which upstream nameserver to use every 10 seconds
+       or 50 queries and not just when a query times out and 
+       is retried. This should improve performance when there
+       is a slow nameserver in the list. Thanks to Joe for the
+       suggestion. 
+
+       Don't do any PXE processing, even for clients with the 
+       correct vendorclass, unless at least one pxe-prompt or 
+       pxe-service option is given. This stops dnsmasq 
+       interfering with proxy PXE subsystems when it is just 
+       the DHCP server. Thanks to Spencer Clark for spotting this.
+
+       Limit the blocksize used for TFTP transfers to a value
+       which avoids packet fragmentation, based on the MTU of the
+       local interface. Many netboot ROMs can't cope with
+       fragmented packets.
+
+       Honour dhcp-ignore configuration for PXE and proxy-PXE 
+       requests. Thanks to Niels Basjes for the bug report.
+
+       Updated French translation. Thanks to Gildas Le Nadan.
 
 
 version 2.50
-           Fix security problem which allowed any host permitted to 
-            do TFTP to possibly compromise dnsmasq by remote buffer 
-            overflow when TFTP enabled. Thanks to Core Security 
-           Technologies and Iván Arce, Pablo Hernán Jorge, Alejandro 
-           Pablo Rodriguez, Martín Coco, Alberto Soliño Testa and
-           Pablo Annetta. This problem has Bugtraq id: 36121 
-            and CVE: 2009-2957
+       Fix security problem which allowed any host permitted to 
+       do TFTP to possibly compromise dnsmasq by remote buffer 
+       overflow when TFTP enabled. Thanks to Core Security 
+       Technologies and Iván Arce, Pablo Hernán Jorge, Alejandro 
+       Pablo Rodriguez, Martín Coco, Alberto Soliño Testa and
+       Pablo Annetta. This problem has Bugtraq id: 36121 
+       and CVE: 2009-2957
 
-            Fix a problem which allowed a malicious TFTP client to 
-            crash dnsmasq. Thanks to Steve Grubb at Red Hat for 
-            spotting this. This problem has Bugtraq id: 36120 and 
-            CVE: 2009-2958
+       Fix a problem which allowed a malicious TFTP client to 
+       crash dnsmasq. Thanks to Steve Grubb at Red Hat for 
+       spotting this. This problem has Bugtraq id: 36120 and 
+       CVE: 2009-2958
 
 
 version 2.49
-            Fix regression in 2.48 which disables the lease-change
-            script. Thanks to Jose Luis Duran for spotting this.
+       Fix regression in 2.48 which disables the lease-change
+       script. Thanks to Jose Luis Duran for spotting this.
+
+       Log TFTP "file not found" errors. These were not logged,
+       since a normal PXELinux boot generates many of them, but
+       the lack of the messages seems to be more confusing than
+       routinely seeing them when there is no real error.
 
-           Log TFTP "file not found" errors. These were not logged,
-           since a normal PXELinux boot generates many of them, but
-           the lack of the messages seems to be more confusing than
-           routinely seeing them when there is no real error.
+       Update Spanish translation. Thanks to Chris Chatham.
 
-           Update Spanish translation. Thanks to Chris Chatham.
 
 version 2.48
-            Archived the extensive, backwards, changelog to
-            CHANGELOG.archive. The current changelog now runs from
-            version 2.43 and runs conventionally.
-
-           Fixed bug which broke binding of servers to physical
-           interfaces when interface names were longer than four
-           characters. Thanks to MURASE Katsunori for the patch.
-
-           Fixed netlink code to check that messages come from the
-           correct source, and not another userspace process. Thanks
-           to Steve Grubb for the patch.
-
-           Maintainability drive: removed bug and missing feature
-           workarounds for some old platforms. Solaris 9, OpenBSD
-           older than 4.1, Glibc older than 2.2, Linux 2.2.x and 
-            DBus older than 1.1.x are no longer supported. 
-
-           Don't read included configuration files more than once:
-           allows complex configuration structures without problems.
-
-           Mark log messages from the various subsystems in dnsmasq:
-           messages from the DHCP subsystem now have the ident string
-           "dnsmasq-dhcp" and messages from TFTP have ident
-           "dnsmasq-tftp". Thanks to Olaf Westrik for the patch.
-
-           Fix possible infinite DHCP protocol loop when an IP
-           address nailed to a hostname (not a MAC address)  and a 
-           host sometimes provides the name, sometimes not.
-
-           Allow --addn-hosts to take a directory: all the files 
-           in the directory are read. Thanks to Phil Cornelius for 
-           the suggestion. 
-
-           Support --bridge-interface on all platforms, not just BSD.
-            Added support for advanced PXE functions. It's now
-            possible to define a prompt and menu options which will
-            be displayed when a client PXE boots. It's also possible to
-            hand-off booting to other boot servers. Proxy-DHCP, where
-            dnsmasq just supplies the PXE information and another DHCP
-            server does address allocation, is also allowed. See the
-            --pxe-prompt and --pxe-service keywords. Thanks to 
-           Alkis Georgopoulos for the suggestion and Guilherme Moro
-            and Michael Brown for assistance.
-
-           Improvements to DHCP logging. Thanks to Tom Metro for
-           useful suggestions.
-           
-           Add ability to build dnsmasq without DHCP support. To do
-           this, edit src/config.h or build with
-           "make COPTS=-DNO_DHCP". Thanks to Mahavir Jain for the patch. 
-           
-           Added --test command-line switch - syntax check
-           configuration files only.
-            Updated French translation. Thanks to Gildas Le Nadan.
+       Archived the extensive, backwards, changelog to
+       CHANGELOG.archive. The current changelog now runs from
+       version 2.43 and runs conventionally.
+
+       Fixed bug which broke binding of servers to physical
+       interfaces when interface names were longer than four
+       characters. Thanks to MURASE Katsunori for the patch.
+
+       Fixed netlink code to check that messages come from the
+       correct source, and not another userspace process. Thanks
+       to Steve Grubb for the patch.
+
+       Maintainability drive: removed bug and missing feature
+       workarounds for some old platforms. Solaris 9, OpenBSD
+       older than 4.1, Glibc older than 2.2, Linux 2.2.x and 
+       DBus older than 1.1.x are no longer supported. 
+
+       Don't read included configuration files more than once:
+       allows complex configuration structures without problems.
+
+       Mark log messages from the various subsystems in dnsmasq:
+       messages from the DHCP subsystem now have the ident string
+       "dnsmasq-dhcp" and messages from TFTP have ident
+       "dnsmasq-tftp". Thanks to Olaf Westrik for the patch.
+
+       Fix possible infinite DHCP protocol loop when an IP
+       address nailed to a hostname (not a MAC address)  and a 
+       host sometimes provides the name, sometimes not.
+
+       Allow --addn-hosts to take a directory: all the files 
+       in the directory are read. Thanks to Phil Cornelius for 
+       the suggestion. 
+
+       Support --bridge-interface on all platforms, not just BSD.
+
+       Added support for advanced PXE functions. It's now
+       possible to define a prompt and menu options which will
+       be displayed when a client PXE boots. It's also possible to
+       hand-off booting to other boot servers. Proxy-DHCP, where
+       dnsmasq just supplies the PXE information and another DHCP
+       server does address allocation, is also allowed. See the
+       --pxe-prompt and --pxe-service keywords. Thanks to 
+       Alkis Georgopoulos for the suggestion and Guilherme Moro
+       and Michael Brown for assistance.
+
+       Improvements to DHCP logging. Thanks to Tom Metro for
+       useful suggestions.
+
+       Add ability to build dnsmasq without DHCP support. To do
+       this, edit src/config.h or build with
+       "make COPTS=-DNO_DHCP". Thanks to Mahavir Jain for the patch. 
+
+       Added --test command-line switch - syntax check
+       configuration files only.
+
+       Updated French translation. Thanks to Gildas Le Nadan.
 
 
 version 2.47
-           Updated French translation. Thanks to Gildas Le Nadan.
-
-           Fixed interface enumeration code to work on NetBSD
-           5.0. Thanks to Roy Marples for the patch. 
-
-           Updated config.h to use the same location for the lease
-           file on NetBSD as the other *BSD variants. Also allow
-           LEASEFILE and CONFFILE symbols to be overriden in CFLAGS.  
-
-            Handle duplicate address detection on IPv6 more
-            intelligently. In IPv6, an interface can have an address
-            which is not usable, because it is still undergoing DAD
-            (such addresses are marked "tentative"). Attempting to
-            bind to an address in this state returns an error,
-            EADDRNOTAVAIL. Previously, on getting such an error,
-            dnsmasq would silently abandon the address, and never
-            listen on it. Now, it retries once per second for 20
-            seconds before generating a fatal error. 20 seconds should
-            be long enough for any DAD process to complete, but can be
-            adjusted in src/config.h if necessary. Thanks to Martin
-            Krafft for the bug report.
-
-           Add DBus introspection. Patch from Jeremy Laine.
-
-           Update Dbus configuration file. Patch from Colin Walters.
-           Fix for this bug:
-            http://bugs.freedesktop.org/show_bug.cgi?id=18961
-
-           Support arbitrarily encapsulated DHCP options, suggestion
-           and initial patch from Samium Gromoff. This is useful for
-           (eg) gPXE, which expect all its private options to be
-           encapsulated inside a single option 175. So, eg, 
-
-            dhcp-option = encap:175, 190, "iscsi-client0"
-            dhcp-option = encap:175, 191, "iscsi-client0-secret"
-           
-           will provide iSCSI parameters to gPXE.
-
-           Enhance --dhcp-match to allow testing of the contents of a
-           client-sent option, as well as its presence. This
-           application in mind for this is RFC 4578
-           client-architecture specifiers, but it's generally useful.
-           Joey Korkames suggested the enhancement. 
-
-           Move from using the IP_XMIT_IF ioctl to IP_BOUND_IF on
-           OpenSolaris. Thanks to Bastian Machek for the heads-up.
-
-           No longer complain about blank lines in
-           /etc/ethers. Thanks to Jon Nelson for the patch.
-
-           Fix binding of servers to physical devices, eg
-           --server=/domain/1.2.3.4@eth0 which was broken from 2.43
-           onwards unless --query-port=0 set. Thanks to Peter Naulls
-           for the bug report.
-
-           Reply to DHCPINFORM requests even when the supplied ciaddr
-           doesn't fall in any dhcp-range. In this case it's not
-           possible to supply a complete configuration, but
-           individually-configured options (eg PAC) may be useful.
-
-           Allow the source address of an alias to be a range:
-           --alias=192.168.0.0,10.0.0.0,255.255.255.0 maps the whole
-           subnet 192.168.0.0->192.168.0.255 to 10.0.0.0->10.0.0.255,
-           as before.
-           --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
-           maps only the 192.168.0.10->192.168.0.40 region. Thanks to
-           Ib Uhrskov for the suggestion.
-
-           Don't dynamically allocate DHCP addresses which may break
-           Windows.  Addresses which end in .255 or .0 are broken in
-           Windows even when using supernetting.
-           --dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0 means 
-           192.168.0.255 is a valid IP address, but not for Windows. 
-           See Microsoft KB281579. We therefore no longer allocate 
-           these addresses to avoid hard-to-diagnose problems. 
-
-           Update Polish translation. Thanks to Jan Psota.
-
-           Delete the PID-file when dnsmasq shuts down. Note that by
-           this time, dnsmasq is normally not running as root, so
-           this will fail if the PID-file is stored in a root-owned
-           directory; such failure is silently ignored. To take
-           advantage of this feature, the PID-file must be stored in a
-           directory owned and write-able by the user running
-           dnsmasq.
+       Updated French translation. Thanks to Gildas Le Nadan.
+
+       Fixed interface enumeration code to work on NetBSD
+       5.0. Thanks to Roy Marples for the patch. 
+
+       Updated config.h to use the same location for the lease
+       file on NetBSD as the other *BSD variants. Also allow
+       LEASEFILE and CONFFILE symbols to be overridden in CFLAGS.  
+
+       Handle duplicate address detection on IPv6 more
+       intelligently. In IPv6, an interface can have an address
+       which is not usable, because it is still undergoing DAD
+       (such addresses are marked "tentative"). Attempting to
+       bind to an address in this state returns an error,
+       EADDRNOTAVAIL. Previously, on getting such an error,
+       dnsmasq would silently abandon the address, and never
+       listen on it. Now, it retries once per second for 20
+       seconds before generating a fatal error. 20 seconds should
+       be long enough for any DAD process to complete, but can be
+       adjusted in src/config.h if necessary. Thanks to Martin
+       Krafft for the bug report.
+
+       Add DBus introspection. Patch from Jeremy Laine.
+
+       Update Dbus configuration file. Patch from Colin Walters.
+       Fix for this bug:
+       http://bugs.freedesktop.org/show_bug.cgi?id=18961
+
+       Support arbitrarily encapsulated DHCP options, suggestion
+       and initial patch from Samium Gromoff. This is useful for
+       (eg) iPXE, which expect all its private options to be
+       encapsulated inside a single option 175. So, eg, 
+
+       dhcp-option = encap:175, 190, "iscsi-client0"
+       dhcp-option = encap:175, 191, "iscsi-client0-secret"
+
+       will provide iSCSI parameters to iPXE.
+
+       Enhance --dhcp-match to allow testing of the contents of a
+       client-sent option, as well as its presence. This
+       application in mind for this is RFC 4578
+       client-architecture specifiers, but it's generally useful.
+       Joey Korkames suggested the enhancement. 
+
+       Move from using the IP_XMIT_IF ioctl to IP_BOUND_IF on
+       OpenSolaris. Thanks to Bastian Machek for the heads-up.
+
+       No longer complain about blank lines in
+       /etc/ethers. Thanks to Jon Nelson for the patch.
+
+       Fix binding of servers to physical devices, eg
+       --server=/domain/1.2.3.4@eth0 which was broken from 2.43
+       onwards unless --query-port=0 set. Thanks to Peter Naulls
+       for the bug report.
+
+       Reply to DHCPINFORM requests even when the supplied ciaddr
+       doesn't fall in any dhcp-range. In this case it's not
+       possible to supply a complete configuration, but
+       individually-configured options (eg PAC) may be useful.
+
+       Allow the source address of an alias to be a range:
+       --alias=192.168.0.0,10.0.0.0,255.255.255.0 maps the whole
+       subnet 192.168.0.0->192.168.0.255 to 10.0.0.0->10.0.0.255,
+       as before.
+       --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
+       maps only the 192.168.0.10->192.168.0.40 region. Thanks to
+       Ib Uhrskov for the suggestion.
+
+       Don't dynamically allocate DHCP addresses which may break
+       Windows.  Addresses which end in .255 or .0 are broken in
+       Windows even when using supernetting.
+       --dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0 means 
+       192.168.0.255 is a valid IP address, but not for Windows. 
+       See Microsoft KB281579. We therefore no longer allocate 
+       these addresses to avoid hard-to-diagnose problems. 
+
+       Update Polish translation. Thanks to Jan Psota.
+
+       Delete the PID-file when dnsmasq shuts down. Note that by
+       this time, dnsmasq is normally not running as root, so
+       this will fail if the PID-file is stored in a root-owned
+       directory; such failure is silently ignored. To take
+       advantage of this feature, the PID-file must be stored in a
+       directory owned and write-able by the user running
+       dnsmasq.
 
 
 version 2.46
-           Allow --bootp-dynamic to take a netid tag, so that it may
-           be selectively enabled. Thanks to Olaf Westrik for the
-           suggestion. 
-
-           Remove ISC-leasefile reading code. This has been
-           deprecated for a long time, and last time I removed it, it
-           ended up going back by request of one user. This time,
-           it's gone for good; otherwise it would need to be
-           re-worked to support multiple domains (see below).
-
-           Support DHCP clients in multiple DNS domains. This is a
-           long-standing request. Clients are assigned to a domain
-           based in their IP address.  
-
-            Add --dhcp-fqdn flag, which changes behaviour if DNS names
-            assigned to DHCP clients. When this is set, there must be
-            a domain associated with each client, and only
-            fully-qualified domain names are added to the DNS. The
-            advantage is that the only the FQDN needs to be unique,
-            so that two or more DHCP clients can share a hostname, as
-            long as they are in different domains.
-
-           Set environment variable DNSMASQ_DOMAIN when invoking
-           lease-change script. This may be useful information to
-           have now that it's variable.
-
-           Tighten up data-checking code for DNS packet
-           handling. Thanks to Steve Dodd who found certain illegal
-           packets which could crash dnsmasq. No memory overwrite was
-           possible, so this is not a security issue beyond the DoS
-           potential.  
-
-           Update example config dhcp option 47, the previous
-           suggestion generated an illegal, zero-length,
-           option. Thanks to Matthias Andree for finding this.
-
-           Rewrite hosts-file reading code to remove the limit of
-           1024 characters per line. John C Meuser found this.
-
-           Create a net-id tag with the name of the interface on
-           which the DHCP request was received.
-
-           Fixed minor memory leak in DBus code, thanks to Jeremy
-           Laine for the patch.
-
-           Emit DBus signals as the DHCP lease database
-           changes. Thanks to Jeremy Laine for the patch.
-
-           Allow for more that one MAC address in a dhcp-host
-           line. This configuration tells dnsmasq that it's OK to
-           abandon a DHCP lease of the fixed address to one MAC
-           address, if another MAC address in the dhcp-host statement 
-           asks for an address. This is useful to give a fixed
-           address to a host which has two network interfaces
-           (say, a laptop with wired and wireless interfaces.) 
-            It's very important to ensure that only one interface 
-           at a time is up, since dnsmasq abandons the first lease 
-           and re-uses the address before the leased time has
-           elapsed. John Gray suggested this.
-
-           Tweak the response to a DHCP request packet with a wrong
-           server-id when --dhcp-authoritative is set; dnsmasq now
-           returns a DHCPNAK, rather than silently ignoring the
-           packet. Thanks to Chris Marget for spotting this
-           improvement.
-
-           Add --cname option. This provides a limited alias
-           function, usable for DHCP names. Thanks to AJ Weber for
-           suggestions on this.
-
-           Updated contrib/webmin with latest version from Neil
-           Fisher.
-
-           Updated Polish translation. Thanks to Jan Psota.
-           
-           Correct the text names for DHCP options 64 and 65 to be
-           "nis+-domain" and "nis+-servers".
-
-           Updated Spanish translation. Thanks to Chris Chatham.
-
-           Force re-reading of /etc/resolv.conf when an "interface
-           up" event occurs.
+       Allow --bootp-dynamic to take a netid tag, so that it may
+       be selectively enabled. Thanks to Olaf Westrik for the
+       suggestion. 
+
+       Remove ISC-leasefile reading code. This has been
+       deprecated for a long time, and last time I removed it, it
+       ended up going back by request of one user. This time,
+       it's gone for good; otherwise it would need to be
+       re-worked to support multiple domains (see below).
+
+       Support DHCP clients in multiple DNS domains. This is a
+       long-standing request. Clients are assigned to a domain
+       based in their IP address.  
+
+       Add --dhcp-fqdn flag, which changes behaviour if DNS names
+       assigned to DHCP clients. When this is set, there must be
+       a domain associated with each client, and only
+       fully-qualified domain names are added to the DNS. The
+       advantage is that the only the FQDN needs to be unique,
+       so that two or more DHCP clients can share a hostname, as
+       long as they are in different domains.
+
+       Set environment variable DNSMASQ_DOMAIN when invoking
+       lease-change script. This may be useful information to
+       have now that it's variable.
+
+       Tighten up data-checking code for DNS packet
+       handling. Thanks to Steve Dodd who found certain illegal
+       packets which could crash dnsmasq. No memory overwrite was
+       possible, so this is not a security issue beyond the DoS
+       potential.  
+
+       Update example config dhcp option 47, the previous
+       suggestion generated an illegal, zero-length,
+       option. Thanks to Matthias Andree for finding this.
+
+       Rewrite hosts-file reading code to remove the limit of
+       1024 characters per line. John C Meuser found this.
+
+       Create a net-id tag with the name of the interface on
+       which the DHCP request was received.
+
+       Fixed minor memory leak in DBus code, thanks to Jeremy
+       Laine for the patch.
+
+       Emit DBus signals as the DHCP lease database
+       changes. Thanks to Jeremy Laine for the patch.
+
+       Allow for more that one MAC address in a dhcp-host
+       line. This configuration tells dnsmasq that it's OK to
+       abandon a DHCP lease of the fixed address to one MAC
+       address, if another MAC address in the dhcp-host statement 
+       asks for an address. This is useful to give a fixed
+       address to a host which has two network interfaces
+       (say, a laptop with wired and wireless interfaces.) 
+       It's very important to ensure that only one interface 
+       at a time is up, since dnsmasq abandons the first lease 
+       and re-uses the address before the leased time has
+       elapsed. John Gray suggested this.
+
+       Tweak the response to a DHCP request packet with a wrong
+       server-id when --dhcp-authoritative is set; dnsmasq now
+       returns a DHCPNAK, rather than silently ignoring the
+       packet. Thanks to Chris Marget for spotting this
+       improvement.
+
+       Add --cname option. This provides a limited alias
+       function, usable for DHCP names. Thanks to AJ Weber for
+       suggestions on this.
+
+       Updated contrib/webmin with latest version from Neil
+       Fisher.
+
+       Updated Polish translation. Thanks to Jan Psota.
+
+       Correct the text names for DHCP options 64 and 65 to be
+       "nis+-domain" and "nis+-servers".
+
+       Updated Spanish translation. Thanks to Chris Chatham.
+
+       Force re-reading of /etc/resolv.conf when an "interface
+       up" event occurs.
 
 
 version 2.45
-            Fix total DNS failure in release 2.44 unless --min-port 
-            specified. Thanks to Steven Barth and Grant Coady for
-            bugreport. Also reject out-of-range port spec, which could
-            break things too: suggestion from Gilles Espinasse.
-           
+       Fix total DNS failure in release 2.44 unless --min-port 
+       specified. Thanks to Steven Barth and Grant Coady for
+       bugreport. Also reject out-of-range port spec, which could
+       break things too: suggestion from Gilles Espinasse.
+
 
 version 2.44
-            Fix  crash when unknown client attempts to renew a DHCP
-            lease, problem introduced in version 2.43. Thanks to
-            Carlos Carvalho for help chasing this down.
+       Fix  crash when unknown client attempts to renew a DHCP
+       lease, problem introduced in version 2.43. Thanks to
+       Carlos Carvalho for help chasing this down.
 
-           Fix potential crash when a host which doesn't have a lease
-           does DHCPINFORM. Again introduced in 2.43. This bug has
-           never been reported in the wild.
+       Fix potential crash when a host which doesn't have a lease
+       does DHCPINFORM. Again introduced in 2.43. This bug has
+       never been reported in the wild.
 
-            Fix crash in netlink code introduced in 2.43. Thanks to
-            Jean Wolter for finding this.
+       Fix crash in netlink code introduced in 2.43. Thanks to
+       Jean Wolter for finding this.
 
-           Change implementation of min_port to work even if min-port
-           is large.
+       Change implementation of min_port to work even if min-port
+       is large.
 
-           Patch to enable compilation of latest Mac OS X. Thanks to
-           David Gilman.
+       Patch to enable compilation of latest Mac OS X. Thanks to
+       David Gilman.
 
-           Update Spanish translation. Thanks to Christopher Chatham.
+       Update Spanish translation. Thanks to Christopher Chatham.
 
 
 version 2.43
-           Updated Polish translation. Thanks to Jan Psota.
-
-           Flag errors when configuration options are repeated
-           illegally.
-
-           Further tweaks for GNU/kFreeBSD
-
-           Add --no-wrap to msgmerge call - provides nicer .po file
-           format.
-
-           Honour lease-time spec in dhcp-host lines even for
-           BOOTP. The user is assumed to known what they are doing in
-           this case. (Hosts without the time spec still get infinite
-           leases for BOOTP, over-riding the default in the
-           dhcp-range.) Thanks to Peter Katzmann for uncovering this.
-
-           Fix problem matching relay-agent ids. Thanks to Michael
-           Rack for the bug report.
-
-           Add --naptr-record option. Suggestion from Johan
-           Bergquist.
-
-           Implement RFC 5107 server-id-override DHCP relay agent
-           option.
-
-           Apply patches from Stefan Kruger for compilation on
-           Solaris 10 under Sun studio.
-
-           Yet more tweaking of Linux capability code, to suppress
-           pointless wingeing from kernel 2.6.25 and above.
-
-           Improve error checking during startup. Previously, some
-           errors which occurred during startup would be worked
-           around, with dnsmasq still starting up. Some were logged,
-            some silent. Now, they all cause a fatal error and dnsmasq 
-            terminates with a non-zero exit code. The errors are those
-            associated with changing uid and gid, setting process 
-            capabilities and writing the pidfile. Thanks to Uwe
-           Gansert and the Suse security team for pointing out 
-           this improvement, and Bill Reimers for good implementation
-           suggestions.
-
-           Provide NO_LARGEFILE compile option to switch off largefile
-           support when compiling against versions of uclibc which
-           don't support it. Thanks to Stephane Billiart for the patch.
-  
-            Implement random source ports for interactions with
-            upstream nameservers. New spoofing attacks have been found
-            against nameservers which do not do this, though it is not
-            clear if dnsmasq is vulnerable, since to doesn't implement
-            recursion. By default dnsmasq will now use a different
-            source port (and socket) for each query it sends
-            upstream. This behaviour can suppressed using the
-            --query-port option, and the old default behaviour
-            restored using --query-port=0. Explicit source-port
-            specifications in --server configs are still honoured.
-
-           Replace the random number generator, for better
-           security. On most BSD systems, dnsmasq uses the
-           arc4random() RNG, which is secure, but on other platforms,
-           it relied on the C-library RNG, which may be
-           guessable and therefore allow spoofing. This release
-           replaces the libc RNG with the SURF RNG, from Daniel
-           J. Berstein's DJBDNS package.  
-
-           Don't attempt to change user or group or set capabilities
-           if dnsmasq is run as a non-root user. Without this, the
-           change from soft to hard errors when these fail causes
-           problems for non-root daemons listening on high
-           ports. Thanks to Patrick McLean for spotting this.
-
-           Updated French translation. Thanks to Gildas Le Nadan.
+       Updated Polish translation. Thanks to Jan Psota.
+
+       Flag errors when configuration options are repeated
+       illegally.
+
+       Further tweaks for GNU/kFreeBSD
+
+       Add --no-wrap to msgmerge call - provides nicer .po file
+       format.
+
+       Honour lease-time spec in dhcp-host lines even for
+       BOOTP. The user is assumed to known what they are doing in
+       this case. (Hosts without the time spec still get infinite
+       leases for BOOTP, over-riding the default in the
+       dhcp-range.) Thanks to Peter Katzmann for uncovering this.
+
+       Fix problem matching relay-agent ids. Thanks to Michael
+       Rack for the bug report.
+
+       Add --naptr-record option. Suggestion from Johan
+       Bergquist.
+
+       Implement RFC 5107 server-id-override DHCP relay agent
+       option.
+
+       Apply patches from Stefan Kruger for compilation on
+       Solaris 10 under Sun studio.
+
+       Yet more tweaking of Linux capability code, to suppress
+       pointless wingeing from kernel 2.6.25 and above.
+
+       Improve error checking during startup. Previously, some
+       errors which occurred during startup would be worked
+       around, with dnsmasq still starting up. Some were logged,
+       some silent. Now, they all cause a fatal error and dnsmasq 
+       terminates with a non-zero exit code. The errors are those
+       associated with changing uid and gid, setting process 
+       capabilities and writing the pidfile. Thanks to Uwe
+       Gansert and the Suse security team for pointing out 
+       this improvement, and Bill Reimers for good implementation
+       suggestions.
+
+       Provide NO_LARGEFILE compile option to switch off largefile
+       support when compiling against versions of uclibc which
+       don't support it. Thanks to Stephane Billiart for the patch.
+
+       Implement random source ports for interactions with
+       upstream nameservers. New spoofing attacks have been found
+       against nameservers which do not do this, though it is not
+       clear if dnsmasq is vulnerable, since to doesn't implement
+       recursion. By default dnsmasq will now use a different
+       source port (and socket) for each query it sends
+       upstream. This behaviour can suppressed using the
+       --query-port option, and the old default behaviour
+       restored using --query-port=0. Explicit source-port
+       specifications in --server configs are still honoured.
+
+       Replace the random number generator, for better
+       security. On most BSD systems, dnsmasq uses the
+       arc4random() RNG, which is secure, but on other platforms,
+       it relied on the C-library RNG, which may be
+       guessable and therefore allow spoofing. This release
+       replaces the libc RNG with the SURF RNG, from Daniel
+       J. Berstein's DJBDNS package.  
+
+       Don't attempt to change user or group or set capabilities
+       if dnsmasq is run as a non-root user. Without this, the
+       change from soft to hard errors when these fail causes
+       problems for non-root daemons listening on high
+       ports. Thanks to Patrick McLean for spotting this.
+
+       Updated French translation. Thanks to Gildas Le Nadan.
 
 
 version 2.42
-            The changelog for version 2.42 and earlier is 
-            available in CHANGELOG.archive.
+       The changelog for version 2.42 and earlier is 
+       available in CHANGELOG.archive.
index c9973cc..c74c5e3 100644 (file)
@@ -56,7 +56,7 @@ release 0.95  Major rewrite: remove calls to gethostbyname() and talk
               any more memory after start-up. The NAT-like forwarding was
               inspired by a suggestion from Eli Chen <eli@routefree.com>
 
-release 0.96  Fixed embarrasing thinko in cache linked-list code.
+release 0.96  Fixed embarrassing thinko in cache linked-list code.
                              
 release 0.98  Some enhancements and bug-fixes. 
               Thanks to "Denis Carre" <denis.carre@laposte.net> and Martin 
@@ -78,7 +78,7 @@ release 0.98  Some enhancements and bug-fixes.
                   ids, to thwart DNS spoofers.
               (7) Dnsmasq no longer forwards queries when the 
                  "recursion desired" bit is not set in the header.
-             (8) Fixed getopt code to work on compliers with unsigned char.
+             (8) Fixed getopt code to work on compilers with unsigned char.
               
 release 0.991 Added -b flag: when set causes dnsmasq to always answer
              reverse queries on the RFC 1918 private IP space itself and
@@ -88,7 +88,7 @@ release 0.991 Added -b flag: when set causes dnsmasq to always answer
               Fixed a bug which stopped dnsmasq working on a box with
               two or more interfaces with the same IP address. 
 
-              Fixed cacheing of CNAMEs. Previously, a CNAME which pointed
+              Fixed caching of CNAMEs. Previously, a CNAME which pointed
               to  a name with many A records would not have all the addresses
               returned when being answered from the cache.
 
@@ -191,7 +191,7 @@ release 1.1   Added --user argument to allow user to change to
 
 release 1.2   Added IPv6 DNS record support. AAAA records are cached
               and read from /etc/hosts. Reverse-lookups in the
-             ip6.int and ip6.arpa domains are suppored. Dnsmasq can
+             ip6.int and ip6.arpa domains are supported. Dnsmasq can
               talk to upstream servers via IPv6 if it finds IP6 addresses
               in /etc/resolv.conf and it offers DNS service automatically
               if IPv6 support is present in the kernel.
@@ -214,7 +214,7 @@ release 1.3   Some versions of the Linux kernel return EINVAL rather
               starting, rather than after the first query - principle 
               of least surprise applies here.     
 
-release 1.4   Fix a bug with DHPC lease parsing which broke in
+release 1.4   Fix a bug with DHCP lease parsing which broke in
               non-UTC timezones. Thanks to Mark Wormgoor for
               spotting and diagnosing this. Fixed versions in
               the .spec files this time. Fixed bug in Suse startup
@@ -258,7 +258,7 @@ release 1.7   Fix a problem with cache not clearing properly
               on receipt of SIGHUP. Bug spotted by Sat Deshpande.
 
               In group-id changing code:
-             1) Drop supplimentary groups.
+             1) Drop supplementary groups.
               2) Change gid before dropping root (patch from Soewono Effendi.)
               3) Change group to "dip" if it exists, to allow access
                  to /etc/ppp/resolv.conf (suggestion from Jorg Sommer.)
@@ -297,7 +297,7 @@ release 1.9   Fixes to rpm .spec files.
               required. The difference is not really visible with
               bloated libcs like glibc, but should dramatically reduce
               memory requirements when linked against ulibc for use on
-              embeded routers, and that's the point really. Thanks to
+              embedded routers, and that's the point really. Thanks to
               Matthew Natalier for prompting this.   
 
              Changed debug mode (-d) so that all logging appears on
@@ -319,12 +319,12 @@ release 1.9   Fixes to rpm .spec files.
               uClinux. Thanks to Matthew Natalier for uClinux stuff. 
 
 release 1.10  Log warnings if resolv.conf or dhcp.leases are not
-              accessable for any reason, as suggested by Hinrich Eilts.
+              accessible for any reason, as suggested by Hinrich Eilts.
 
              Fixed wrong address printing in error message about
              no interface with address.
 
-             Updated docs and split installation instuctions into setup.html.
+             Updated docs and split installation instructions into setup.html.
 
              Fix bug in CNAME chasing code: One CNAME pointing
              to many A records would lose A records after the 
@@ -346,7 +346,7 @@ release 1.10  Log warnings if resolv.conf or dhcp.leases are not
 
              Added -S option to directly specify upstream servers and
               added ability to direct queries for specific domains to
-              specfic servers. Suggested by Jens Vonderheide.
+              specific servers. Suggested by Jens Vonderheide.
 
              Upgraded random ID generation - patch from Rob Funk.            
 
@@ -386,13 +386,13 @@ release 1.11  Actually implement the -R flag promised in the 1.10 man page.
               names in /etc/hosts -suggestion from Phil Harman.
 
              Always return a zero time-to-live for names derived from 
-             DHCP which stops anthing else caching these
+             DHCP which stops anything else caching these
               names. Previously the TTL was derived from the lease
               time but that is incorrect since a lease can be given
               up early: dnsmasq would know this but anything with the
               name cached with long TTL would not be updated.
 
-             Extended HAVE_IPV6 config flag to allow compliation on
+             Extended HAVE_IPV6 config flag to allow compilation on
              old systems which don't have modern library routines
              like inet_ntop(). Thanks to Phil Harman for the patch.
 
@@ -471,7 +471,7 @@ release 1.14  Fixed man page description of -b option which confused
              /etc/resolv.conf.
              (Thanks to Klaas Teschauer)
              
-             Check that recieved queries have only rfc1035-legal characters
+             Check that received queries have only rfc1035-legal characters
              in them. This check is mainly to avoid bad strings being
              sent to syslog.
 
@@ -549,7 +549,7 @@ release 1.16  Allow "/" characters in domain names - this fixes
 
 release 1.17  Fixed crash with DHCP hostnames > 40 characters.
 
-              Fixed name-comparision routines to not depend on Locale,
+              Fixed name-comparison routines to not depend on Locale,
               in theory this versions since 1.15 could lock up or give
               wrong results when run with locale != 'C'.
 
@@ -574,7 +574,7 @@ release 1.18  Added round-robin DNS for names which have more than one
              forwarded because -D is in effect, return NXDOMAIN not
              an empty reply.
 
-             Add code to return the software version in repsonse to the
+             Add code to return the software version in response to the
              correct magic query in the same way as BIND. Use  
              "dig version.bind chaos txt" to make the query.
 
@@ -635,7 +635,7 @@ release 2.0
              dynamic allocation.
 
             Allow dhcp-host options for the same host with different
-            IP adresses where the correct one will be selected for
+            IP addresses where the correct one will be selected for
             the network the host appears on.
 
             Fix parsing of --dhcp-option to allow more than one
@@ -674,7 +674,7 @@ release 2.1
              
              Fix unaligned access warnings on BSD/Alpha.
 
-            Allow empty DHCP options, like so: dhpc-option=44
+            Allow empty DHCP options, like so: dhcp-option=44
  
              Allow single-byte DHCP options like so: dhcp-option=20,1
 
@@ -745,7 +745,7 @@ release 2.3
             around a bug in the DHCP client in HP Jetdirect printers.
             Thanks to Marko Stolle for finding this problem.
 
-            Return DHCP T1 and T2 times, with "fuzz" to desychronise lease
+            Return DHCP T1 and T2 times, with "fuzz" to desynchronise lease
             renewals, as specified in the RFC.
             
             Ensure that the END option is always present in DHCP
@@ -838,7 +838,7 @@ release 2.4
             by Chad Skeeters.
 
             Fixed bug in /etc/ethers parsing code triggered by tab
-            characters. Qudos to Dag Wieers for hepling to nail that
+            characters. Kudos to Dag Wieers for helping to nail that
             one.
             
             Added "bind-interfaces" option correctly.       
@@ -975,7 +975,7 @@ release 2.8
             configuration. Specifically: (1) options are matched on
             the netids from dhcp-range, dhcp-host, vendor class and
             user class(es). Multiple net-ids are allowed and options
-            are searched on them all. (2) matches agains vendor class
+            are searched on them all. (2) matches against vendor class
             and user class are now on a substring, if the given
             string is a substring of the vendor/user class, then a
             match occurs. Thanks again to Richard Musil for prompting
@@ -997,7 +997,7 @@ release 2.8
 
             Add checks against DHCP clients which return zero-length
             hostnames. This avoids the potential lease-loss problems
-            reffered to above. Also, if a client sends a hostname when
+            referred to above. Also, if a client sends a hostname when
             it creates a lease but subsequently sends no or a
             zero-length hostname whilst renewing, continue to use the
             existing hostname, don't wipe it out. 
@@ -1010,7 +1010,7 @@ release 2.9
             but to the address of another interface were ignored
             unless the loopback interface was explicitly configured.
             2) on OpenBSD failure to configure one interface now
-            causes a fatal error on startup rather than an huge
+            causes a fatal error on startup rather than a huge
             stream of log messages. Thanks to Erik Jan Tromp for 
             finding that bug.
 
@@ -1019,7 +1019,7 @@ release 2.9
             broken. The new algorithm is to pick as before for the
             first try, but if a query is retried, to send to all
             available servers in parallel. The first one to reply
-            then becomes prefered for the next query. This should 
+            then becomes preferred for the next query. This should 
             improve reliability without generating significant extra
             upstream load.
 
@@ -1027,7 +1027,7 @@ release 2.9
             unqualified domains introduced in version 2.8 
              
             Allow fallback to "bind-interfaces" at runtime: Some
-            verions of *BSD seem to have enough stuff in the header
+            versions of *BSD seem to have enough stuff in the header
             files to build but no kernel support. Also now log if
             "bind-interfaces" is forced on.
 
@@ -1049,7 +1049,7 @@ release 2.9
             first name found is now returned for reverse lookups,
             rather than all of them.
 
-            Add back fatal errors when nonexistant 
+            Add back fatal errors when nonexistent 
             interfaces or interface addresses are given but only in
             "bind-interfaces" mode. Principle of least surprise applies.
             
@@ -1193,7 +1193,7 @@ version 2.14
 
 version 2.15
             Fixed NXDOMAIN/NODATA confusion for locally known
-            names. We now return a NODATA reponse for names which are
+            names. We now return a NODATA response for names which are
             locally known. Now a query for (eg AAAA or MX) for a name
            with an IPv4 address in /etc/hosts which fails upstream
             will generate a NODATA response. Note that the query 
@@ -1229,7 +1229,7 @@ version 2.16
 
             Set NONBLOCK on all listening sockets to workaround non-POSIX
             compliance in Linux 2.4 and 2.6. This fixes rare hangs which
-            occured when corrupted packets were received. Thanks to
+            occurred when corrupted packets were received. Thanks to
            Joris van Rantwijk for chasing that down.
  
            Updated config.h for NetBSD. Thanks to Martin Lambers.
@@ -1297,7 +1297,7 @@ version 2.18
            interfaces with more than one IPv6 address. Thanks to
             Martin Pels for help with that.
 
-           Fix problems which occured when more than one dhcp-range
+           Fix problems which occurred when more than one dhcp-range
            was specified in the same subnet: sometimes parameters
            (lease time, network-id tag) from the wrong one would be
            used. Thanks to Rory Campbell-Lange for the bug report.
@@ -1314,7 +1314,7 @@ version 2.19
            Thanks to Richard Atterer for the bug report.
 
            Check for under-length option fields in DHCP packets, a
-           zero length client-id, in particluar, could seriously
+           zero length client-id, in particular, could seriously
            confuse dnsmasq 'till now. Thanks to Will Murname for help
            with that.
 
@@ -1389,7 +1389,7 @@ version 2.21
            recursive queries.
 
            Fix DHCP address allocation problem when netid tags are in
-           use. Thanks to Will Murnane for the bug report and
+           use. Thanks to Will Murname for the bug report and
            subsequent testing.
 
            Add an additional data section to the reply for MX and SRV
@@ -1505,7 +1505,7 @@ version 2.23
             from dnsmasq --version. Thanks to Dirk Schenkewitz for 
             the suggestion. 
 
-           Fix pathalogical behaviour when a broken client keeps sending
+           Fix pathological behaviour when a broken client keeps sending
             DHCPDISCOVER messages repeatedly and fast. Because dealing with
             each of these takes a few seconds, (because of the ping) then a 
            queue of DHCP packets could build up. Now, the results of a ping 
@@ -1593,7 +1593,7 @@ version 2.24
            than one dhcp-range is available. Thanks to Sorin Panca
            for help chasing this down.
 
-           Added more explict error mesages to the hosts file and
+           Added more explicit error messages to the hosts file and
            ethers file reading code. Markus Kaiserswerth suffered to
            make this happen.
 
@@ -1617,7 +1617,7 @@ version 2.25
 
             Fixed Suse spec file - thanks to Steven Springl.
 
-           Fixed DHCP bug when two distict subnets are on the same
+           Fixed DHCP bug when two distinct subnets are on the same
            physical interface. Thanks to Pawel Zawora for finding
            this and suggesting the fix.
 
@@ -1740,7 +1740,7 @@ version 2.28
            Fixed regression in netlink code under 2.2.x kernels which 
            occurred in 2.27. Erik Jan Tromp is the vintage kernel fan 
            who found this. P.S. It looks like this "netlink bind:
-           permission denied" problem occured in kernels at least as
+           permission denied" problem occurred in kernels at least as
            late a 2.4.18. Good information from Alain Richoux.
 
            Added a warning when it's impossible to give a host its
@@ -1761,7 +1761,7 @@ version 2.28
            Eric House and Eric Spakman for help in chasing this down.
 
            Tolerate configuration screwups which lead to the DHCP
-           server attemping to allocate its own address to a
+           server attempting to allocate its own address to a
            client; eg setting the whole subnet range as a DHCP
            range. Addresses in use by the server are now excluded
            from use by clients.
@@ -2067,7 +2067,7 @@ version 2.36
            kernel. Thanks to Philip Wall for the bug report.
 
            Added --dhcp-bridge option, but only to the FreeBSD
-           build. This fixes an oddity with a particular bridged
+           build. This fixes an oddity with a particular bridged
            network configuration on FreeBSD. Thanks to Luigi Rizzo
            for the patch.
 
@@ -2273,7 +2273,7 @@ version 2.40
            this.
 
            Use client-id as hash-seed for DHCP address allocation
-           with Firewire and Infiniband, as these don't supply an MAC
+           with Firewire and InfiniBand, as these don't supply a MAC
            address. 
 
            Tweaked TFTP file-open code to make it behave sensibly
@@ -2307,7 +2307,7 @@ version 2.40
            Continue to use unqualified hostnames provided by DHCP
            clients, even if the domain part is illegal. (The domain
            is  ignored, and an error logged.) Previously in this
-           situation, the whole name whould have been
+           situation, the whole name would have been
            rejected. Thanks to Jima for the patch.
            
            Handle EINTR returns from wait() correctly and reap
@@ -2319,7 +2319,7 @@ version 2.40
            leases file and passed to the lease-change
            script. Suggestion from Ben Voigt.
 
-           Re-run the lease chamge script with an "old" event for
+           Re-run the lease change script with an "old" event for
            each lease when dnsmasq receives a SIGHUP.
 
            Added more useful exit codes, including passing on a
@@ -2417,7 +2417,7 @@ version 2.41
            Changed behavior of DHCP server to always return total length of
            a new lease in DHCPOFFER, even if an existing lease
            exists. (It used to return the time remaining on the lease
-           whne one existed.) This fixes problems with the Sony Ericsson
+           when one existed.) This fixes problems with the Sony Ericsson
            K610i phone. Thanks to Hakon Stordahl for finding and
            fixing this.
 
@@ -2433,7 +2433,7 @@ version 2.41
 
            Add --dhcp-match flag, to check for arbitrary options in
            DHCP messages from clients. This enables use of dnsmasq
-           with gPXE. Thanks to Rance Hall for the suggestion.
+           with iPXE. Thanks to Rance Hall for the suggestion.
 
            Added --dhcp-broadcast, to force broadcast replies to DHCP
            clients which need them but are too dumb or too old to
@@ -2476,7 +2476,7 @@ version 2.42
 
            Fix OS detection logic to cope with GNU/FreeBSD.
 
-           Fix unitialised variable in DBus code - thanks to Roy
+           Fix uninitialised variable in DBus code - thanks to Roy
            Marples.
 
            Fix network enumeration code to work on later NetBSD -
diff --git a/FAQ b/FAQ
index ec71691..fa22833 100644 (file)
--- a/FAQ
+++ b/FAQ
@@ -9,7 +9,7 @@ A: The high ports that dnsmasq opens are for replies from the upstream
    from port 53 the replies would be _to_ port 53 and get blocked.
 
    This is not a security hole since dnsmasq will only accept replies to that
-   port: queries are  dropped. The replies must be to oustanding queries
+   port: queries are dropped. The replies must be to outstanding queries
    which dnsmasq has forwarded, otherwise they are dropped too.
  
    Addendum: dnsmasq now has the option "query-port" (-Q), which allows
@@ -59,7 +59,7 @@ A: Yes, there is explicit support for *BSD and MacOS X and Solaris.
  
 Q: My company's nameserver knows about some names which aren't in the
    public DNS. Even though I put it first in /etc/resolv.conf, it
-   dosen't work: dnsmasq seems not to use the nameservers in the order
+   doesn't work: dnsmasq seems not to use the nameservers in the order
    given. What am I doing wrong?
 
 A: By default, dnsmasq treats all the nameservers it knows about as
@@ -144,19 +144,19 @@ Q: Who are Verisign, what do they have to do with the bogus-nxdomain
    option in dnsmasq and why should I wory about it?
 
 A: [note: this was written in September 2003, things may well change.]
-   Versign run the .com and .net top-level-domains. They have just
+   Verisign run the .com and .net top-level-domains. They have just
    changed the configuration of their servers so that unknown .com and
    .net domains, instead of returning an error code NXDOMAIN, (no such
-   domain) return the address of a host at Versign which runs a web
+   domain) return the address of a host at Verisign which runs a web
    server showing a search page. Most right-thinking people regard
    this new behaviour as broken :-).  You can test to see if you are
-   suffering Versign brokeness by run a command like 
+   suffering Verisign brokenness by run a command like 
    
    host jlsdajkdalld.com
 
    If you get "jlsdajkdalld.com" does not exist, then all is fine, if
    host returns an IP address, then the DNS is broken. (Try a few
-   different unlikely domains, just in case you picked a wierd one
+   different unlikely domains, just in case you picked a weird one
    which really _is_ registered.)
 
    Assuming that your DNS is broken, and you want to fix it, simply
@@ -180,7 +180,7 @@ A: There are a couple of configuration gotchas which have been
    whilst the ISC one works.
 
    The first thing to check is the broadcast address set for the
-   ethernet interface. This is normally the adddress on the connected
+   ethernet interface. This is normally the address on the connected
    network with all ones in the host part. For instance if the 
    address of the ethernet interface is 192.168.55.7 and the netmask
    is 255.255.255.0 then the broadcast address should be
@@ -205,7 +205,7 @@ A: By default, none of the DHCP clients send the host-name when asking
    send with the "hostname" keyword in /etc/network/interfaces. (See
    "man interfaces" for details.) That doesn't work for dhclient, were
    you have to add something like "send host-name daisy" to
-   /etc/dhclient.conf [Update: the lastest dhcpcd packages _do_ send
+   /etc/dhclient.conf [Update: the latest dhcpcd packages _do_ send
    the hostname by default.
 
 Q: I'm network booting my machines, and trying to give them static
@@ -240,7 +240,7 @@ Q: What are these strange "bind-interface" and "bind-dynamic" options?
 
 A: Dnsmasq from v2.63 can operate in one of three different "networking
    modes". This is unfortunate as it requires users configuring dnsmasq
-   to take into account some rather bizzare contraints and select the
+   to take into account some rather bizarre constraints and select the
    mode which best fits the requirements of a particular installation.
    The origin of these are deficiencies in the Unix networking
    model and APIs and each mode has different advantages and
@@ -252,10 +252,10 @@ A: Dnsmasq from v2.63 can operate in one of three different "networking
    The three modes are "wildcard", "bind-interfaces" and "bind-dynamic".
 
    In "wildcard" mode, dnsmasq binds the wildcard IP address (0.0.0.0 or
-   ::). This allows it to recieve all the packets sent to the server on
+   ::). This allows it to receive all the packets sent to the server on
    the relevant port. Access control (--interface, --except-interface,
    --listen-address, etc) is implemented by dnsmasq: it queries the
-   kernel to determine the interface on which a packet was recieved and
+   kernel to determine the interface on which a packet was received and
    the address to which it was sent, and applies the configured
    rules. Wildcard mode is the default if neither of the other modes are
    specified. 
@@ -276,7 +276,7 @@ A: Dnsmasq from v2.63 can operate in one of three different "networking
    The mode chosen has four different effects: co-existence with other
    servers, semantics of --interface access control, effect of new
    interfaces, and legality of --interface specifications for
-   non-existent inferfaces. We will deal with these in order.
+   non-existent interfaces. We will deal with these in order.
 
    A dnsmasq instance running in wildcard mode precludes a machine from
    running a second instance of dnsmasq or any other DNS, TFTP or DHCP
@@ -297,7 +297,7 @@ A: Dnsmasq from v2.63 can operate in one of three different "networking
    by dnsmasq when in --bind-interfaces mode. In wildcard or bind-dynamic
    mode, such interfaces are handled normally.
 
-   A --interface specification for a non-existent interface is a fatal
+   An --interface specification for a non-existent interface is a fatal
    error at start-up when in --bind-interfaces mode, by just generates a
    warning in wildcard or bind-dynamic mode.
 
@@ -313,15 +313,25 @@ Q: Can I get email notification when a new version of dnsmasq is
    released?
 
 A: Yes, new releases of dnsmasq are always announced through
-   freshmeat.net, and they allow you to subcribe to email alerts when
+   freshmeat.net, and they allow you to subscribe to email alerts when
    new versions of particular projects are released. New releases are
    also announced in the dnsmasq-discuss mailing list, subscribe at 
    http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
 
 Q: What does the dhcp-authoritative option do? 
 
-A: See http://www.isc.org/files/auth.html - that's
-   for the ISC daemon, but the same applies to dnsmasq.
+A: The DHCP spec says that when a DHCP server receives a renewal request
+   from a client it has no knowledge of, it should just ignore it.
+   This is because it's supported to have more than one DHCP server
+   on a network, and another DHCP server may be dealing with the client.
+   This has the unfortunate effect that when _no_ DHCP replies to 
+   the client, it takes some time for the client to time-out and start 
+   to get a new lease. Setting this option makes dnsmasq violate the
+   standard to the extent that it will send a NAK reply to the client, 
+   causing it to immediately start to get a new lease. This improves 
+   behaviour when machines move networks, and in the case that the DHCP
+   lease database is lost. As long as there are not more tha one DHCP
+   server on the network, it's safe to enable the option.
 
 Q: Why does my Gentoo box pause for a minute before getting a new
    lease?
@@ -349,18 +359,64 @@ A: By default, the identity of a machine is determined by using the
    method for setting the client-id varies with DHCP client software,
    dhcpcd uses the "-I" flag. Windows uses a registry setting,
    see http://www.jsiinc.com/SUBF/TIP2800/rh2845.htm
+
 Addendum:
    From version 2.46, dnsmasq has a solution to this which doesn't
    involve setting client-IDs. It's possible to put more than one MAC
    address in a --dhcp-host configuration. This tells dnsmasq that it
    should use the specified IP for any of the specified MAC addresses,
-   and furthermore it gives dnsmasq permission to sumarily abandon a
+   and furthermore it gives dnsmasq permission to summarily abandon a
    lease to one of the MAC addresses if another one comes along. Note
    that this will work fine only as longer as only one interface is
    up at any time. There is no way for dnsmasq to enforce this
    constraint: if you configure multiple MAC addresses and violate 
    this rule, bad things will happen.
 
+Addendum-II: The link above is dead, the former contents of the link are:
+
+------------------------------------------------------------------------------
+How can I keep the same DHCP client reservation, if the MAC address changes?
+
+When you reserve an IP address for a DHCP client, you provide the
+MAC address of the client's NIC.
+
+It is possible to use a custom identifier, which is sent as 
+option 61 in the client's DHCP Discover and Request packet.
+
+The DhcpClientIdentifier is a REG_DWORD value that is located at:
+
+Windows NT 4.0 SP2+
+
+HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<Adapter Name>'X'\Parameters\Tcpip
+
+where <Adapter Name> is the NIC driver name and 'X' is the number of the NIC.
+
+Windows 2000
+
+HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TcpIp\Parameters\Interfaces\<NIC GUID>
+
+where <NIC GUID> is the GUID of the NIC.
+
+The valid range of data is 0x0 - 0xFFFFFFFF. The custom identifier is send as 4 bytes, 
+8 hexadecimal character, in groups of 2 hexadecimal characters, with the groups being 
+sent in reverse order. If the custom identifier is less than 8 hexadeciaml characters, 
+it is zero padded at the end. Examples:
+
+Custom Client                 Client Reservation
+Identifier                    on DHCP Server
+12345678                      78563412
+123456                        56341200
+1234                          34120000
+1234567                       67452301
+12345                         45230100
+123                           23010000
+A18F42                        428FA100
+CF432                         32F40C00
+C32D1BE                       BED1320C
+
+-------------------------------------------------------------------------------------------------------
+
+
 Q: Can dnsmasq do DHCP on IP-alias interfaces?
 
 A: Yes, from version-2.21. The support is only available running under
@@ -488,7 +544,7 @@ Q: DHCP doesn't work with windows 7 but everything else is fine.
 
 A: There seems to be a problem if Windows 7 doesn't get a value for
    DHCP option 252 in DHCP packets it gets from the server. The
-   symtoms have beeen variously reported as continual DHCPINFORM
+   symptoms have been variously reported as continual DHCPINFORM
    requests in an attempt to get an option-252, or even ignoring DHCP
    offers completely (and failing to get an IP address) if there is no
    option-252 supplied. DHCP option 252 is for WPAD, WWW Proxy 
index 4c87ea9..98ec760 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+# dnsmasq is Copyright (c) 2000-2016 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
@@ -55,10 +55,12 @@ dbus_cflags =   `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG)
 dbus_libs =     `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1` 
 idn_cflags =    `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn` 
 idn_libs =      `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn` 
+idn2_cflags =   `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --cflags libidn2`
+idn2_libs =     `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --libs libidn2`
 ct_cflags =     `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --cflags libnetfilter_conntrack`
 ct_libs =       `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --libs libnetfilter_conntrack`
-lua_cflags =    `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --cflags lua5.1
-lua_libs =      `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.1
+lua_cflags =    `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --cflags lua5.2
+lua_libs =      `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.2
 nettle_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --cflags nettle hogweed`
 nettle_libs =   `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --libs nettle hogweed`
 gmp_libs =      `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC NO_GMP --copy -lgmp`
@@ -73,7 +75,8 @@ 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 inotify.o poll.o
+       domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
+       poll.o rrfilter.o edns0.o arp.o crypto.o
 
 hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
        dns-protocol.h radv-protocol.h ip6addr.h
@@ -81,8 +84,8 @@ hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
 all : $(BUILDDIR)
        @cd $(BUILDDIR) && $(MAKE) \
  top="$(top)" \
- build_cflags="$(version) $(dbus_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
- build_libs="$(dbus_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
+ build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
+ build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
  -f $(top)/Makefile dnsmasq 
 
 mostly_clean :
@@ -105,8 +108,8 @@ all-i18n : $(BUILDDIR)
        @cd $(BUILDDIR) && $(MAKE) \
  top="$(top)" \
  i18n=-DLOCALEDIR=\'\"$(LOCALEDIR)\"\' \
- build_cflags="$(version) $(dbus_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) `$(PKG_CONFIG) --cflags libidn`" \
- build_libs="$(dbus_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) `$(PKG_CONFIG) --libs libidn`"  \
+ build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
+ build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)"  \
  -f $(top)/Makefile dnsmasq
        for f in `cd $(PO); echo *.po`; do \
                cd $(top) && cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile $${f%.po}.mo; \
@@ -122,7 +125,7 @@ merge :
                echo -n msgmerge $(PO)/$$f && $(MSGMERGE) --no-wrap -U $(PO)/$$f $(BUILDDIR)/dnsmasq.pot; \
        done
 
-# Cannonicalise .po file.
+# Canonicalise .po file.
 %.po : 
        @cd $(BUILDDIR) && $(MAKE) -f $(top)/Makefile dnsmasq.pot
        mv $(PO)/$*.po $(PO)/$*.po.orig && $(MSGMERGE) --no-wrap $(PO)/$*.po.orig $(BUILDDIR)/dnsmasq.pot >$(PO)/$*.po; 
@@ -141,7 +144,7 @@ bloatcheck : $(BUILDDIR)/dnsmasq_baseline mostly_clean all
            $(top)/bld/bloat-o-meter dnsmasq_baseline dnsmasq; \
            size dnsmasq_baseline dnsmasq
 
-# rules below are targets in recusive makes with cwd=$(BUILDDIR)
+# rules below are targets in recursive makes with cwd=$(BUILDDIR)
 
 $(copts_conf): $(hdrs)
        @rm -f *.o .copts_*
diff --git a/VERSION b/VERSION
index 4b5d0ac..5ec247c 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
- (HEAD, tag: v2.74, origin/master, origin/HEAD, master)
+ (HEAD -> master, tag: v2.79, origin/master, origin/HEAD)
index 5364ee7..80ec842 100644 (file)
@@ -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 inotify.c poll.c
+                   loop.c inotify.c poll.c rrfilter.c edns0.c arp.c crypto.c
 
 LOCAL_MODULE := dnsmasq
 
index 5372869..e472aab 100755 (executable)
 # If there is more than one v[0-9].* tag, sort them and use the
 # first. This favours, eg v2.63 over 2.63rc6.
 
+# Change directory to the toplevel source directory.
+if test -z "$1" || ! test -d "$1" || ! cd "$1"; then
+    echo "$0: First argument $1 must be toplevel dir." >&2
+    exit 1
+fi
+
 if which git >/dev/null 2>&1 && \
-    ([ -d $1/.git ] || grep '^gitdir:' $1/.git >/dev/null 2>&1); then 
-    cd $1; git describe | sed 's/^v//'
+    ([ -d .git ] || grep '^gitdir:' .git >/dev/null 2>&1) && \
+    git describe >/dev/null 2>&1; then 
+    git describe | sed 's/^v//'
 elif grep '\$Format:%d\$' $1/VERSION >/dev/null 2>&1; then
-# unsubstituted VERSION, but no git available.
+    # unsubstituted VERSION, but no git available.
     echo UNKNOWN
 else
      vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep ^v[0-9]`
index 4783221..cf245ff 100644 (file)
@@ -22,7 +22,7 @@ sudo chmod 644 /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
 
 Optionally, edit your dnsmasq configuration file to your liking.
 
-To start the launchd job, which starts dnsmaq, reboot or use the command:
+To start the launchd job, which starts dnsmasq, reboot or use the command:
 sudo launchctl load /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
 
 To stop the launchd job, which stops dnsmasq, use the command:
index 2f19ca6..0b94108 100644 (file)
@@ -1,9 +1,9 @@
 This is a patch against SuSEfirewall2-3.1-206 (SuSE 9.x and older)
-It fixes the depancy from the dns daemon name 'named'
+It fixes the dependency from the dns daemon name 'named'
 After appending the patch, the SuSEfirewall is again able to autodetect 
 the dnsmasq named service.
 This is a very old bug in the SuSEfirewall script.
-The SuSE people think the name of the dns server will allways 'named'
+The SuSE people think the name of the dns server will always 'named'
 
 
 --- /sbin/SuSEfirewall2.orig   2004-01-23 13:30:09.000000000 +0100
index c0d17aa..e883447 100644 (file)
@@ -13,10 +13,10 @@ connection comes out of the other side.  However, sometimes, we want to
 maintain that relationship through the proxy and continue the connection
 mark on packets upstream of our proxy
 
-DNSMasq includes such a feature enabled by the --conntrack
+Dnsmasq includes such a feature enabled by the --conntrack
 option. This allows, for example, using iptables to mark traffic from
 a particular IP, and that mark to be persisted to requests made *by*
-DNSMasq. Such a feature could be useful for bandwidth accounting,
+Dnsmasq. Such a feature could be useful for bandwidth accounting,
 captive portals and the like. Note a similar feature has been 
 implemented in Squid 2.2
 
@@ -40,7 +40,7 @@ on IP address. 3) Saves the firewall mark back to the connection mark
 (which will persist it across related packets)
 
 4) is applied to the OUTPUT table, which is where we first see packets
-generated locally. DNSMasq will have already copied the firewall mark
+generated locally. Dnsmasq will have already copied the firewall mark
 from the request, across to the new packet, and so all that remains is
 for iptables to copy it to the connection mark so it's persisted across
 packets.
index ad76e25..911ee7e 100644 (file)
@@ -55,7 +55,7 @@ Index: src/dnsmasq.c
            }     
  
 @@ -434,7 +433,7 @@
-         /* lose the setuid and setgid capbilities */
+         /* lose the setuid and setgid capabilities */
          if (capset(hdr, data) == -1)
            {
 -            send_event(err_pipe[1], EVENT_CAP_ERR, errno);
diff --git a/contrib/lease-tools/Makefile b/contrib/lease-tools/Makefile
new file mode 100644 (file)
index 0000000..f38f2ed
--- /dev/null
@@ -0,0 +1,6 @@
+CFLAGS?= -O2 -Wall -W
+
+all: dhcp_release dhcp_release6 dhcp_lease_time
+
+clean:
+       rm -f *~ *.o core dhcp_release dhcp_release6 dhcp_lease_time
similarity index 97%
rename from contrib/wrt/dhcp_lease_time.c
rename to contrib/lease-tools/dhcp_lease_time.c
index b438ef7..f9d7a85 100644 (file)
@@ -168,7 +168,7 @@ int main(int argc, char **argv)
   *(p++) = 1;
   *(p++) = DHCPINFORM;
 
-  /* Explicity request the lease time, it won't be sent otherwise:
+  /* Explicitly request the lease time, it won't be sent otherwise:
      this is a dnsmasq extension, not standard. */
   *(p++) = OPTION_REQUESTED_OPTIONS;
   *(p++) = 1;
@@ -206,13 +206,13 @@ int main(int argc, char **argv)
        {
          unsigned int x;
          if ((x = t/86400))
-           printf("%dd", x);
+           printf("%ud", x);
          if ((x = (t/3600)%24))
-           printf("%dh", x);
+           printf("%uh", x);
          if ((x = (t/60)%60))
-           printf("%dm", x);
+           printf("%um", x);
          if ((x = t%60))
-           printf("%ds", x);
+           printf("%us", x);
        }
       return 0;
     }
similarity index 98%
rename from contrib/wrt/dhcp_release.c
rename to contrib/lease-tools/dhcp_release.c
index a51f04b..201fcd3 100644 (file)
@@ -117,7 +117,7 @@ static ssize_t netlink_recv(int fd)
       msg.msg_flags = 0;
       while ((rc = recvmsg(fd, &msg, MSG_PEEK)) == -1 && errno == EINTR);
       
-      /* 2.2.x doesn't suport MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a 
+      /* 2.2.x doesn't support MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a 
          big buffer and pray in that case. */
       if (rc == -1 && errno == EOPNOTSUPP)
         {
diff --git a/contrib/lease-tools/dhcp_release6.1 b/contrib/lease-tools/dhcp_release6.1
new file mode 100644 (file)
index 0000000..763e01c
--- /dev/null
@@ -0,0 +1,38 @@
+.TH DHCP_RELEASE 1
+.SH NAME
+dhcp_release6 \- Release a DHCPv6 lease on a the local dnsmasq DHCP server.
+.SH SYNOPSIS
+.B dhcp_release6 --iface <interface> --client-id <client-id> --server-id
+server-id --iaid <iaid>  --ip <IP>  [--dry-run] [--help]
+.SH "DESCRIPTION"
+A utility which forces the DHCP server running on this machine to release a 
+DHCPv6 lease.
+.SS OPTIONS
+.IP "-a, --ip"
+IPv6 address to release.
+.IP "-c, --client-id"
+Colon-separated hex string representing DHCPv6 client id. Normally
+it can be found in leases file both on client and server.
+.IP "-d, --dry-run"
+Print hexadecimal representation of generated DHCPv6 release packet to standard
+output and exit.
+.IP "-h, --help"
+print usage information to standard output and exit.
+.IP "-i, --iaid"
+Decimal representation of DHCPv6 IAID. Normally it can be found in leases file
+both on client and server.
+.IP "-n, --iface"
+Network interface to send a DHCPv6 release packet from.
+.IP "-s, --server-id"
+Colon-separated hex string representing DHCPv6 server id. Normally
+it can be found in leases file both on client and server.
+.SH NOTES
+MUST be run as root - will fail otherwise.
+.SH LIMITATIONS
+Only usable on IPv6 DHCP leases.
+.SH SEE ALSO
+.BR dnsmasq (8)
+.SH AUTHOR
+This manual page was written by Simon Kelley <simon@thekelleys.org.uk>.
+
+
diff --git a/contrib/lease-tools/dhcp_release6.c b/contrib/lease-tools/dhcp_release6.c
new file mode 100644 (file)
index 0000000..7f79fa7
--- /dev/null
@@ -0,0 +1,496 @@
+/*
+ dhcp_release6 --iface <interface> --client-id <client-id> --server-id
+ server-id --iaid <iaid>  --ip <IP>  [--dry-run] [--help]
+ MUST be run as root - will fail otherwise
+ */
+
+/* Send a DHCPRELEASE message  to IPv6 multicast address  via the specified interface
+ to tell the local DHCP server to delete a particular lease.
+ The interface argument is the interface in which a DHCP
+ request _would_ be received if it was coming from the client,
+ rather than being faked up here.
+ The client-id argument is colon-separated hex string and mandatory. Normally
+ it can be found in leases file both on client and server
+
+ The server-id argument is colon-separated hex string and mandatory. Normally
+ it can be found in leases file both on client and server.
+ The iaid argument is numeric string and mandatory. Normally
+ it can be found in leases file both on client and server.
+ IP is an IPv6 address to release
+ If --dry-run is specified, dhcp_release6 just prints hexadecimal representation of
+ packet to send to stdout and exits.
+ If --help is specified, dhcp_release6 print usage information to stdout and exits
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <getopt.h>
+#include <errno.h>
+#include <unistd.h>
+
+#define NOT_REPLY_CODE 115
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+enum DHCP6_TYPES
+  {
+    SOLICIT = 1,
+    ADVERTISE = 2,
+    REQUEST = 3,
+    CONFIRM = 4,
+    RENEW = 5,
+    REBIND = 6,
+    REPLY = 7,
+    RELEASE = 8,
+    DECLINE = 9,
+    RECONFIGURE = 10,
+    INFORMATION_REQUEST = 11,
+    RELAY_FORW = 12,
+    RELAY_REPL = 13
+    
+  };
+
+enum DHCP6_OPTIONS
+  {
+    CLIENTID = 1,
+    SERVERID = 2,
+    IA_NA = 3,
+    IA_TA = 4,
+    IAADDR = 5,
+    ORO = 6,
+    PREFERENCE = 7,
+    ELAPSED_TIME = 8,
+    RELAY_MSG = 9,
+    AUTH = 11,
+    UNICAST = 12,
+    STATUS_CODE = 13,
+    RAPID_COMMIT = 14,
+    USER_CLASS = 15,
+    VENDOR_CLASS = 16,
+    VENDOR_OPTS = 17,
+    INTERFACE_ID = 18,
+    RECONF_MSG = 19,
+    RECONF_ACCEPT = 20,
+  };
+
+enum DHCP6_STATUSES
+  {
+    SUCCESS = 0,
+    UNSPEC_FAIL = 1,
+    NOADDR_AVAIL=2,
+    NO_BINDING  = 3,
+    NOT_ON_LINK = 4,
+    USE_MULTICAST =5
+  };
+
+static struct option longopts[] = {
+  {"ip", required_argument, 0, 'a' },
+  {"server-id", required_argument, 0, 's' },
+  {"client-id", required_argument, 0, 'c' },
+  {"iface", required_argument, 0, 'n' },
+  {"iaid", required_argument, 0, 'i' },
+  {"dry-run", no_argument, 0, 'd' },
+  {"help", no_argument, 0, 'h' },
+  {0,     0,           0,   0 }
+};
+
+const short DHCP6_CLIENT_PORT = 546;
+const short DHCP6_SERVER_PORT = 547;
+
+const char*  DHCP6_MULTICAST_ADDRESS = "ff02::1:2";
+
+struct dhcp6_option {
+  uint16_t type;
+  uint16_t len;
+  char  value[1024];
+};
+
+struct dhcp6_iaaddr_option {
+  uint16_t type;
+  uint16_t len;
+  struct in6_addr ip;
+  uint32_t preferred_lifetime;
+  uint32_t valid_lifetime;
+};
+
+struct dhcp6_iana_option {
+  uint16_t type;
+  uint16_t len;
+  uint32_t iaid;
+  uint32_t t1;
+  uint32_t t2;
+  char options[1024];
+};
+
+
+struct dhcp6_packet {
+  size_t len;
+  char buf[2048];  
+};
+
+size_t pack_duid(const char* str, char* dst)
+{
+  char* tmp = strdup(str);
+  char* tmp_to_free = tmp;
+  char *ptr;
+  uint8_t write_pos = 0;
+  while ((ptr = strtok (tmp, ":")))
+    {
+      dst[write_pos] = (uint8_t) strtol(ptr, NULL, 16);
+      write_pos += 1;
+      tmp = NULL;
+    }
+  
+  free(tmp_to_free);
+  return write_pos;
+}
+
+struct dhcp6_option create_client_id_option(const char* duid)
+{
+  struct dhcp6_option option;
+  option.type = htons(CLIENTID);
+  bzero(option.value, sizeof(option.value));
+  option.len  = htons(pack_duid(duid, option.value));
+  return option;
+}
+
+struct dhcp6_option create_server_id_option(const char* duid)
+{
+  struct dhcp6_option   option;
+  option.type = htons(SERVERID);
+  bzero(option.value, sizeof(option.value));
+  option.len  = htons(pack_duid(duid, option.value));
+  return option;
+}
+
+struct dhcp6_iaaddr_option create_iaadr_option(const char* ip)
+{
+  struct dhcp6_iaaddr_option result;
+  result.type =htons(IAADDR);
+  /* no suboptions needed here, so length is 24  */
+  result.len = htons(24);
+  result.preferred_lifetime = 0;
+  result.valid_lifetime = 0;
+  int s = inet_pton(AF_INET6, ip, &(result.ip));
+  if (s <= 0) {
+    if (s == 0)
+      fprintf(stderr, "Not in presentation format");
+    else
+      perror("inet_pton");
+    exit(EXIT_FAILURE);
+  }
+
+  return result;
+}
+
+struct dhcp6_iana_option  create_iana_option(const char * iaid, struct dhcp6_iaaddr_option  ia_addr)
+{
+  struct dhcp6_iana_option  result;
+  result.type = htons(IA_NA);
+  result.iaid = htonl(atoi(iaid));
+  result.t1 = 0;
+  result.t2 = 0;
+  result.len = htons(12 + ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
+  memcpy(result.options, &ia_addr, ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
+  return result;
+}
+
+struct dhcp6_packet create_release_packet(const char* iaid, const char* ip, const char* client_id, const char* server_id)
+{
+  struct dhcp6_packet result;
+  bzero(result.buf, sizeof(result.buf));
+  /* message_type */
+  result.buf[0] = RELEASE;
+  /* tx_id */
+  bzero(result.buf+1, 3);
+  
+  struct dhcp6_option client_option = create_client_id_option(client_id);
+  struct dhcp6_option server_option = create_server_id_option(server_id);
+  struct dhcp6_iaaddr_option iaaddr_option = create_iaadr_option(ip);
+  struct dhcp6_iana_option iana_option = create_iana_option(iaid, iaaddr_option);
+  int offset = 4;
+  memcpy(result.buf + offset, &client_option, ntohs(client_option.len) + 2*sizeof(uint16_t));
+  offset += (ntohs(client_option.len)+ 2 *sizeof(uint16_t) );
+  memcpy(result.buf + offset, &server_option, ntohs(server_option.len) + 2*sizeof(uint16_t) );
+  offset += (ntohs(server_option.len)+ 2* sizeof(uint16_t));
+  memcpy(result.buf + offset, &iana_option, ntohs(iana_option.len) + 2*sizeof(uint16_t) );
+  offset += (ntohs(iana_option.len)+ 2* sizeof(uint16_t));
+  result.len = offset;
+  return result;
+}
+
+uint16_t parse_iana_suboption(char* buf, size_t len)
+{
+  size_t current_pos = 0;
+  char option_value[1024];
+  while (current_pos < len)
+    {
+      uint16_t option_type, option_len;
+      memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
+      memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
+      option_type = ntohs(option_type);
+      option_len = ntohs(option_len);
+      current_pos += 2 * sizeof(uint16_t);
+      if (option_type == STATUS_CODE)
+       {
+         uint16_t status;
+         memcpy(&status, buf + current_pos, sizeof(uint16_t));
+         status = ntohs(status);
+         if (status != SUCCESS)
+           {
+             memcpy(option_value, buf + current_pos + sizeof(uint16_t) , option_len - sizeof(uint16_t));
+             option_value[option_len-sizeof(uint16_t)] ='\0';
+             fprintf(stderr, "Error: %s\n", option_value);
+            }
+         return status;
+        }
+    }
+
+  return -2;
+}
+
+int16_t parse_packet(char* buf, size_t len)
+{
+  int16_t ret = -1;
+  uint8_t type = buf[0];
+  /*skipping tx id. you need it, uncomment following line
+    uint16_t tx_id = ntohs((buf[1] <<16) + (buf[2] <<8) + buf[3]);
+  */
+  size_t current_pos = 4;
+  if (type != REPLY )
+    return NOT_REPLY_CODE;
+  
+  char option_value[1024];
+  while (current_pos < len)
+    {
+      uint16_t option_type, option_len;
+      memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
+      memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
+      option_type = ntohs(option_type);
+      option_len = ntohs(option_len);
+      current_pos += 2 * sizeof(uint16_t);
+      if (option_type == STATUS_CODE)
+       {
+         uint16_t status;
+         memcpy(&status, buf + current_pos, sizeof(uint16_t));
+         status = ntohs(status);
+         if (status != SUCCESS)
+           {
+             memcpy(option_value, buf + current_pos +sizeof(uint16_t) , option_len -sizeof(uint16_t));
+             fprintf(stderr, "Error: %d %s\n", status, option_value);
+             return status;
+           }
+
+         /* Got success status, return that if there's no specific error in an IA_NA. */
+         ret = SUCCESS;   
+        }
+
+      if (option_type == IA_NA )
+       {
+         uint16_t result = parse_iana_suboption(buf + current_pos +24, option_len -24);
+         if (result)
+           return result;
+       }
+      
+      current_pos += option_len;
+    }
+
+  return ret;
+}
+
+void usage(const char* arg, FILE* stream)
+{
+  const char* usage_string ="--ip IPv6 --iface IFACE --server-id SERVER_ID --client-id CLIENT_ID --iaid IAID [--dry-run] | --help";
+  fprintf (stream, "Usage: %s %s\n", arg, usage_string);   
+}
+
+int send_release_packet(const char* iface, struct dhcp6_packet* packet)
+{
+  struct sockaddr_in6 server_addr, client_addr;
+  char response[1400];
+  int sock = socket(PF_INET6, SOCK_DGRAM, 0);
+  int i = 0;
+  if (sock < 0)
+    {
+      perror("creating socket");
+      return -1;
+    }
+  
+    if (setsockopt(sock, SOL_SOCKET, 25, iface, strlen(iface)) == -1)
+      {
+        perror("SO_BINDTODEVICE");
+        close(sock);
+        return -1;
+      }
+    
+    memset(&server_addr, 0, sizeof(server_addr));
+    server_addr.sin6_family = AF_INET6;
+    client_addr.sin6_family = AF_INET6;
+    client_addr.sin6_port = htons(DHCP6_CLIENT_PORT);
+    client_addr.sin6_flowinfo = 0;
+    client_addr.sin6_scope_id =0;
+    inet_pton(AF_INET6, "::", &client_addr.sin6_addr);
+    bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6));
+    inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
+    server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
+    int16_t recv_size = 0;
+    for (i = 0; i < 5; i++)
+      {
+        if (sendto(sock, packet->buf, packet->len, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
+         {
+           perror("sendto failed");
+            exit(4);
+         }
+       
+        recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
+        if (recv_size == -1)
+         {
+            if (errno == EAGAIN)
+             {
+               sleep(1);
+               continue;
+             }
+           else
+             {
+                perror("recvfrom");
+             }
+         }
+       
+        int16_t result = parse_packet(response, recv_size);
+        if (result == NOT_REPLY_CODE)
+         {
+            sleep(1);
+            continue;
+         }
+        return result;
+      }
+    
+    fprintf(stderr, "Response timed out\n");
+    return -1;   
+}
+
+
+int main(int argc, char *  const argv[])
+{
+  const char* UNINITIALIZED = "";
+  const char* iface = UNINITIALIZED;
+  const char* ip = UNINITIALIZED;
+  const char* client_id = UNINITIALIZED;
+  const char* server_id = UNINITIALIZED;
+  const char* iaid = UNINITIALIZED;
+  int dry_run = 0;
+  while (1)
+    {
+      int option_index = 0;
+      int c = getopt_long(argc, argv, "a:s:c:n:i:hd", longopts, &option_index);
+      if (c == -1)
+       break;
+        
+      switch(c)
+       {
+       case 0:
+         if (longopts[option_index].flag !=0)
+           break;
+         
+         printf ("option %s", longopts[option_index].name);
+         if (optarg)
+           printf (" with arg %s", optarg);
+         printf ("\n");
+         break;
+
+       case 'i':
+         iaid = optarg;
+         break;
+       case 'n':
+         iface = optarg;
+         break;
+       case 'a':
+         ip = optarg;
+         break;
+       case 'c':
+         client_id = optarg;
+         break;
+       case 'd':
+         dry_run = 1;
+         break;
+       case 's':
+         server_id = optarg;
+         break;
+       case 'h':
+         usage(argv[0], stdout);
+         return 0;
+       case '?':
+         usage(argv[0], stderr);
+         return -1;
+       default:
+         abort();
+         
+        }
+    }
+  
+  if (iaid == UNINITIALIZED)
+    {
+      fprintf(stderr, "Missing required iaid parameter\n");
+      usage(argv[0], stderr);
+      return -1;
+    }
+  
+    if (server_id == UNINITIALIZED)
+      {
+        fprintf(stderr, "Missing required server-id parameter\n");
+        usage(argv[0], stderr);
+        return -1;
+      }
+    
+    if (client_id == UNINITIALIZED)
+      {
+        fprintf(stderr, "Missing required client-id parameter\n");
+        usage(argv[0], stderr);
+        return -1;
+      }
+    
+    if (ip == UNINITIALIZED)
+      {
+        fprintf(stderr, "Missing required ip parameter\n");
+        usage(argv[0], stderr);
+        return -1;
+      }
+    
+    if (iface == UNINITIALIZED)
+      {
+       fprintf(stderr, "Missing required iface parameter\n");
+        usage(argv[0], stderr);
+        return -1;
+      }
+
+    
+    
+    struct dhcp6_packet packet = create_release_packet(iaid, ip, client_id, server_id);
+
+    if (dry_run)
+      {
+        uint16_t i;
+
+        for(i=0; i<packet.len; i++)
+         printf("%hhx", packet.buf[i]);
+        
+        printf("\n");
+        return 0;
+      }
+
+    return send_release_packet(iface, &packet);
+}
index 44a4477..9712d09 100755 (executable)
@@ -3,7 +3,7 @@
 STATUS_FILE="/tmp/dnsmasq-ip-mac.status"
 
 # Script for dnsmasq lease-change hook.
-# Maintains the above file with a IP address/MAC address pairs,
+# Maintains the above file with an IP address/MAC address pairs,
 # one lease per line. Works with IPv4 and IPv6 leases, file is
 # atomically updated, so no races for users of the data.
 
index 1a97c3a..21fdca1 100644 (file)
@@ -3,7 +3,7 @@
 # first column of this file, then a DNAT port-forward will be set up 
 # to the address which has just been allocated by DHCP . The second field 
 # is port number(s). If there is only one, then the port-forward goes to 
-# the same port on the DHCP-client, if there are two seperated with a 
+# the same port on the DHCP-client, if there are two separated with a 
 # colon, then the second number is the port to which the connection 
 # is forwarded on the DHCP-client. By default, forwarding is set up 
 # for TCP, but it can done for UDP instead by prefixing the port to "u". 
index 2ec4df1..62af669 100644 (file)
@@ -1,18 +1,18 @@
-The script reads stdin and replaces all IP addresses with names before\r
-outputting it again. IPs from private networks are reverse looked  up\r
-via dns. Other IP adresses are searched for in the dnsmasq query log.\r
-This gives names (CNAMEs if I understand DNS correctly) that are closer\r
-to the name the client originally asked for then the names obtained by\r
-reverse lookup. Just run\r
-\r
-netstat -n -4 | ./reverse_replace.sh \r
-\r
-to see what it does. It needs \r
-\r
-log-queries\r
-log-facility=/var/log/dnsmasq.log\r
-\r
-in the dnsmasq configuration.\r
-\r
-The script runs on debian (with ash installed) and on busybox.\r
-\r
+The script reads stdin and replaces all IP addresses with names before
+outputting it again. IPs from private networks are reverse looked  up
+via dns. Other IP addresses are searched for in the dnsmasq query log.
+This gives names (CNAMEs if I understand DNS correctly) that are closer
+to the name the client originally asked for then the names obtained by
+reverse lookup. Just run
+
+netstat -n -4 | ./reverse_replace.sh 
+
+to see what it does. It needs 
+
+log-queries
+log-facility=/var/log/dnsmasq.log
+
+in the dnsmasq configuration.
+
+The script runs on debian (with ash installed) and on busybox.
+
index 5b4aebd..c6401fb 100644 (file)
@@ -5,10 +5,10 @@
 # Parses stdin for IP4 addresses and replaces them 
 # with names retrieved by parsing the dnsmasq log.
 # This currently only gives CNAMEs. But these 
-# usually tell ou more than the mones from reverse 
+# usually tell you more than the ones from reverse 
 # lookups. 
 #
-# This has been tested on debian and asuswrt. Plese
+# This has been tested on debian and asuswrt. Please
 # report successful tests on other platforms.
 #
 # Author: Joachim Zobel <jz-2014@heute-morgen.de>
index 38f0822..94a8820 100644 (file)
@@ -1,57 +1,57 @@
-To: dnsmasq-discuss@lists.thekelleys.org.uk\r
-From: Alex Elsayed <eternaleye+usenet@gmail.com>\r
-Date: Tue, 15 May 2012 01:53:54 -0700\r
-Subject: [Dnsmasq-discuss] [PATCH] Support dbus activation\r
-\r
-Introduce dbus service file and turn dbus on in the systemd\r
-unit.\r
-\r
-Note to packagers:\r
-To add support for dbus activation, you must install the dbus\r
-service file (dbus/uk.org.thekelleys.dnsmasq.service) into\r
-$DATADIR/dbus-1/system-services.\r
-\r
----\r
- contrib/systemd/dnsmasq.service        |    2 +-\r
- dbus/uk.org.thekelleys.dnsmasq.service |    7 +++++++\r
- 2 files changed, 8 insertions(+), 1 deletion(-)\r
- create mode 100644 dbus/uk.org.thekelleys.dnsmasq.service\r
-\r
-diff --git a/contrib/systemd/dnsmasq.service \r
-b/contrib/systemd/dnsmasq.service\r
-index a27fe6d..4a784d3 100644\r
---- a/contrib/systemd/dnsmasq.service\r
-+++ b/contrib/systemd/dnsmasq.service\r
-@@ -5,7 +5,7 @@ Description=A lightweight DHCP and caching DNS server\r
- Type=dbus\r
- BusName=uk.org.thekelleys.dnsmasq\r
- ExecStartPre=/usr/sbin/dnsmasq --test\r
--ExecStart=/usr/sbin/dnsmasq -k\r
-+ExecStart=/usr/sbin/dnsmasq -k -1\r
- ExecReload=/bin/kill -HUP $MAINPID\r
\r
- [Install]\r
-diff --git a/dbus/uk.org.thekelleys.dnsmasq.service \r
-b/dbus/uk.org.thekelleys.dnsmasq.service\r
-new file mode 100644\r
-index 0000000..f5fe98d\r
---- /dev/null\r
-+++ b/dbus/uk.org.thekelleys.dnsmasq.service\r
-@@ -0,0 +1,7 @@\r
-+[D-BUS Service]\r
-+Name=uk.org.thekelleys.dnsmasq\r
-+Exec=/usr/sbin/dnsmasq -k -1\r
-+User=root\r
-+SystemdService=dnsmasq.service\r
-+\r
-+\r
--- \r
-1.7.10.2\r
-\r
-\r
-\r
-_______________________________________________\r
-Dnsmasq-discuss mailing list\r
-Dnsmasq-discuss@lists.thekelleys.org.uk\r
-http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss\r
-\r
+To: dnsmasq-discuss@lists.thekelleys.org.uk
+From: Alex Elsayed <eternaleye+usenet@gmail.com>
+Date: Tue, 15 May 2012 01:53:54 -0700
+Subject: [Dnsmasq-discuss] [PATCH] Support dbus activation
+
+Introduce dbus service file and turn dbus on in the systemd
+unit.
+
+Note to packagers:
+To add support for dbus activation, you must install the dbus
+service file (dbus/uk.org.thekelleys.dnsmasq.service) into
+$DATADIR/dbus-1/system-services.
+
+---
+ contrib/systemd/dnsmasq.service        |    2 +-
+ dbus/uk.org.thekelleys.dnsmasq.service |    7 +++++++
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+ create mode 100644 dbus/uk.org.thekelleys.dnsmasq.service
+
+diff --git a/contrib/systemd/dnsmasq.service 
+b/contrib/systemd/dnsmasq.service
+index a27fe6d..4a784d3 100644
+--- a/contrib/systemd/dnsmasq.service
++++ b/contrib/systemd/dnsmasq.service
+@@ -5,7 +5,7 @@ Description=A lightweight DHCP and caching DNS server
+ Type=dbus
+ BusName=uk.org.thekelleys.dnsmasq
+ ExecStartPre=/usr/sbin/dnsmasq --test
+-ExecStart=/usr/sbin/dnsmasq -k
++ExecStart=/usr/sbin/dnsmasq -k -1
+ ExecReload=/bin/kill -HUP $MAINPID
+ [Install]
+diff --git a/dbus/uk.org.thekelleys.dnsmasq.service 
+b/dbus/uk.org.thekelleys.dnsmasq.service
+new file mode 100644
+index 0000000..f5fe98d
+--- /dev/null
++++ b/dbus/uk.org.thekelleys.dnsmasq.service
+@@ -0,0 +1,7 @@
++[D-BUS Service]
++Name=uk.org.thekelleys.dnsmasq
++Exec=/usr/sbin/dnsmasq -k -1
++User=root
++SystemdService=dnsmasq.service
++
++
+-- 
+1.7.10.2
+
+
+
+_______________________________________________
+Dnsmasq-discuss mailing list
+Dnsmasq-discuss@lists.thekelleys.org.uk
+http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
+
index 3ebec65..bfe4ec7 100644 (file)
@@ -2,7 +2,7 @@ A remake of patch Bob Carroll had posted to dnsmasq,
 now compatible with version 2.47. Hopefully he doesn't 
 mind (sending a copy of this mail to him too).
 
-Maybe the patch in question is not acceptible
+Maybe the patch in question is not acceptable
 as it doesn't add new switch, rather it binds itself to "strict-order".
 
 What it does is: if you have strict-order in the 
diff --git a/contrib/try-all-ns/README-2.78 b/contrib/try-all-ns/README-2.78
new file mode 100644 (file)
index 0000000..3dfd200
--- /dev/null
@@ -0,0 +1,10 @@
+Hi,
+I updated the try-all-ns patch to work with the latest version of git. Ended up implementing it on top of master, 2.78test2-7-g63437ff. As that specific if-clause has been changed in the last few commits, it's not compatible for 2.77, sadly.
+
+Find the patch attached.
+
+Regards,
+
+Rasmus Ahlberg
+Software Developer, R&D
+Electrolux Small Appliances
diff --git a/contrib/try-all-ns/dnsmasq-2.78xx-try-all-ns.patch b/contrib/try-all-ns/dnsmasq-2.78xx-try-all-ns.patch
new file mode 100644 (file)
index 0000000..700439e
--- /dev/null
@@ -0,0 +1,20 @@
+diff --git a/src/forward.c b/src/forward.c
+index e3fa94b..ecf3b98 100644
+--- a/src/forward.c
++++ b/src/forward.c
+@@ -789,9 +789,12 @@ void reply_query(int fd, int family, time_t now)
+   /* Note: if we send extra options in the EDNS0 header, we can't recreate
+      the query from the reply. */
+-  if (RCODE(header) == REFUSED &&
+-      forward->forwardall == 0 &&
+-      !(forward->flags & FREC_HAS_EXTRADATA))
++  if ((RCODE(header) == REFUSED &&
++        forward->forwardall == 0 &&
++       !(forward->flags & FREC_HAS_EXTRADATA)) ||
++      /* If strict-order is set, try next server on NXDOMAIN reply */
++      (RCODE(header) == NXDOMAIN && option_bool(OPT_ORDER) &&
++       server->next != NULL))
+     /* for broken servers, attempt to send to another one. */
+     {
+       unsigned char *pheader;
index 8a8f937..2278871 100644 (file)
@@ -1,5 +1,5 @@
 
-This is the README for the DNSmasq webmin module.
+This is the README for the Dnsmasq webmin module.
 
 Problems:
 
@@ -48,7 +48,7 @@ wade through the config file and man pages again.
 
 If you modify it, or add a language file, and you have a spare moment,
 please e-mail me - I won't be upset at all if you fix my poor coding!
-(rather the opposite - I'd be pleased someone found it usefull)
+(rather the opposite - I'd be pleased someone found it useful)
 
 Cheers,
        Neil Fisher <neil@magnecor.com.au>
diff --git a/contrib/wrt/Makefile b/contrib/wrt/Makefile
deleted file mode 100644 (file)
index 68e8d32..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-CFLAGS?= -O2 -Wall -W
-
-all: dhcp_release dhcp_lease_time
-
-clean:
-       rm -f *~ *.o core dhcp_release dhcp_lease_time
index 862046f..981db9f 100644 (file)
@@ -4,7 +4,7 @@ reboot, then it will eventually be restored as hosts renew their
 leases. Until a host renews (which may take hours/days) it will
 not exist in the DNS if dnsmasq's DDNS function is in use.
 
-*WRT systems remount all non-volatile fileystems read-only after boot,
+*WRT systems remount all non-volatile filesystems read-only after boot,
 so the normal leasefile will not work. They do, however have NV
 storage, accessed with the nvram command:
 
@@ -62,7 +62,7 @@ about 100 bytes, so restricting the number of leases to 50 will limit
 use to half that. (The default limit in the distributed source is 150)
 
 Any UI script which reads the dnsmasq leasefile will have to be
-ammended, probably by changing it to read the output of 
+amended, probably by changing it to read the output of 
 `lease_update init` instead.
  
 
index 590f217..574b053 100644 (file)
@@ -90,7 +90,7 @@
 # server=10.1.2.3@eth1
 
 # and this sets the source (ie local) address used to talk to
-# 10.1.2.3 to 192.168.1.1 port 55 (there must be a interface with that
+# 10.1.2.3 to 192.168.1.1 port 55 (there must be an interface with that
 # IP on the machine, obviously).
 # server=10.1.2.3@192.168.1.1#55
 
 # add names to the DNS for the IPv6 address of SLAAC-configured dual-stack 
 # hosts. Use the DHCPv4 lease to derive the name, network segment and 
 # MAC address and assume that the host will also have an
-# IPv6 address calculated using the SLAAC alogrithm.
+# IPv6 address calculated using the SLAAC algorithm.
 #dhcp-range=1234::, ra-names
 
 # Do Router Advertisements, BUT NOT DHCP for this subnet.
 #dhcp-range=1234::, ra-stateless, ra-names
 
 # Do router advertisements for all subnets where we're doing DHCPv6
-# Unless overriden by ra-stateless, ra-names, et al, the router 
+# Unless overridden by ra-stateless, ra-names, et al, the router 
 # advertisements will have the M and O bits set, so that the clients
 # get addresses and configuration from DHCPv6, and the A bit reset, so the 
 # clients don't use SLAAC addresses.
 # the IP address 192.168.0.60
 #dhcp-host=id:01:02:02:04,192.168.0.60
 
-# Always give the Infiniband interface with hardware address
+# Always give the InfiniBand interface with hardware address
 # 80:00:00:48:fe:80:00:00:00:00:00:00:f4:52:14:03:00:28:05:81 the
 # ip address 192.168.0.61. The client id is derived from the prefix
 # ff:00:00:00:00:00:02:00:00:02:c9:00 and the last 8 pairs of
 # Give a fixed IPv6 address and name to client with 
 # DUID 00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2
 # Note the MAC addresses CANNOT be used to identify DHCPv6 clients.
-# Note also the they [] around the IPv6 address are obilgatory.
+# Note also that the [] around the IPv6 address are obligatory.
 #dhcp-host=id:00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2, fred, [1234::5] 
 
 # Ignore any clients which are not specified in dhcp-host lines
 
 # Set option 58 client renewal time (T1). Defaults to half of the
 # lease time if not specified. (RFC2132)
-#dhcp-option=option:T1:1m
+#dhcp-option=option:T1,1m
 
 # Set option 59 rebinding time (T2). Defaults to 7/8 of the
 # lease time if not specified. (RFC2132)
-#dhcp-option=option:T2:2m
+#dhcp-option=option:T2,2m
 
 # Set the NTP time server address to be the same machine as
 # is running dnsmasq
 #dhcp-option-force=211,30i
 
 # Set the boot filename for netboot/PXE. You will only need
-# this is you want to boot machines over the network and you will need
-# a TFTP server; either dnsmasq's built in TFTP server or an
+# this if you want to boot machines over the network and you will need
+# a TFTP server; either dnsmasq's built-in TFTP server or an
 # external one. (See below for how to enable the TFTP server.)
 #dhcp-boot=pxelinux.0
 
 # The same as above, but use custom tftp-server instead machine running dnsmasq
 #dhcp-boot=pxelinux,server.name,192.168.1.100
 
-# Boot for Etherboot gPXE. The idea is to send two different
-# filenames, the first loads gPXE, and the second tells gPXE what to
-# load. The dhcp-match sets the gpxe tag for requests from gPXE.
-#dhcp-match=set:gpxe,175 # gPXE sends a 175 option.
-#dhcp-boot=tag:!gpxe,undionly.kpxe
-#dhcp-boot=mybootimage
+# Boot for iPXE. The idea is to send two different
+# filenames, the first loads iPXE, and the second tells iPXE what to
+# load. The dhcp-match sets the ipxe tag for requests from iPXE.
+#dhcp-boot=undionly.kpxe
+#dhcp-match=set:ipxe,175 # iPXE sends a 175 option.
+#dhcp-boot=tag:ipxe,http://boot.ipxe.org/demo/boot.php
 
-# Encapsulated options for Etherboot gPXE. All the options are
+# Encapsulated options for iPXE. All the options are
 # encapsulated within option 175
 #dhcp-option=encap:175, 1, 5b         # priority code
 #dhcp-option=encap:175, 176, 1b       # no-proxydhcp
 # (using /etc/hosts) then that name can be specified as the
 # tftp_servername (the third option to dhcp-boot) and in that
 # case dnsmasq resolves this name and returns the resultant IP
-# addresses in round robin fasion. This facility can be used to
+# addresses in round robin fashion. This facility can be used to
 # load balance the tftp load among a set of servers.
 #dhcp-boot=/var/ftpd/pxelinux.0,boothost,tftp_server_name
 
index 54f59bb..b167be7 100644 (file)
--- a/doc.html
+++ b/doc.html
@@ -18,7 +18,7 @@ Linux distributions and the ports systems of FreeBSD, OpenBSD and NetBSD. Dnsmas
 
 <P>
 The DNS subsystem provides a local DNS server for the network, with forwarding of all query types to upstream recursive DNS servers and
-cacheing of common record types (A, AAAA, CNAME and PTR, also DNSKEY and DS when DNSSEC is enabled). 
+caching of common record types (A, AAAA, CNAME and PTR, also DNSKEY and DS when DNSSEC is enabled). 
 <DIR>
 <LI>Local DNS names can be defined by reading /etc/hosts, by importing names from the DHCP subsystem, or by configuration of a wide range of useful record types.</LI>
 <LI>Upstream servers can be configured in a variety of convenient ways, including  dynamic configuration as these change on moving upstream network.
@@ -66,6 +66,10 @@ the repo, or get a copy using git protocol with the command
 
 <PRE><TT>git clone git://thekelleys.org.uk/dnsmasq.git </TT></PRE>
 
+or
+
+<PRE><TT>git clone http://thekelleys.org.uk/git/dnsmasq.git </TT></PRE>
+
 <H2>License.</H2>
 Dnsmasq is distributed under the GPL, version 2 or version 3 at your discretion. See the files COPYING and COPYING-v3 in the distribution 
 for details.
index c8913b5..bd99b48 100644 (file)
@@ -30,7 +30,7 @@ DHCPv4 server, and in addition, it includes router advertisements and
 a neat feature which allows nameing for clients which use DHCPv4 and
 stateless autoconfiguration only for IPv6 configuration. There is support for doing address allocation (both DHCPv6 and RA) from subnets which are dynamically delegated via DHCPv6 prefix delegation.
 .PP
-Dnsmasq is coded with small embedded systems in mind. It aims for the smallest possible memory footprint compatible with the supported functions,  and allows uneeded functions to be omitted from the compiled binary.  
+Dnsmasq is coded with small embedded systems in mind. It aims for the smallest possible memory footprint compatible with the supported functions,  and allows unneeded functions to be omitted from the compiled binary.  
 .SH OPTIONS
 Note that in general missing parameters are allowed and switch off
 functions, for instance "--pid-file" disables writing a PID file. On
@@ -42,6 +42,13 @@ the configuration file.
 Read and syntax check configuration file(s). Exit with code 0 if all
 is OK, or a non-zero code otherwise. Do not start up dnsmasq.
 .TP
+.B \-w, --help
+Display all command-line options. 
+.B --help dhcp 
+will display known DHCPv4 configuration options, and 
+.B --help dhcp6 
+will display DHCPv6 options.
+.TP
 .B \-h, --no-hosts
 Don't read the hostnames in /etc/hosts.
 .TP
@@ -60,7 +67,7 @@ in the same way as for DHCP-derived names. Note that this does not
 apply to domain names in cnames, PTR records, TXT records etc.
 .TP
 .B \-T, --local-ttl=<time>
-When replying with information from /etc/hosts or the DHCP leases
+When replying with information from /etc/hosts or configuration or the DHCP leases
 file dnsmasq by default sets the time-to-live field to zero, meaning
 that the requester should not itself cache the information. This is
 the correct thing to do in almost all situations. This option allows a
@@ -68,6 +75,9 @@ time-to-live (in seconds) to be given for these replies. This will
 reduce the load on the server at the expense of clients using stale
 data under some circumstances.
 .TP
+.B --dhcp-ttl=<time>
+As for --local-ttl, but affects only replies with information from DHCP leases. If both are given, --dhcp-ttl applies for DHCP information, and --local-ttl for others. Setting this to zero eliminates the effect of --local-ttl for DHCP.
+.TP
 .B --neg-ttl=<time>
 Negative replies from upstream servers normally contain time-to-live
 information in SOA records which dnsmasq uses for caching. If the
@@ -172,8 +182,16 @@ OS: this was the default behaviour in versions prior to 2.43.
 Do not use ports less than that given as source for outbound DNS
 queries. Dnsmasq picks random ports as source for outbound queries:
 when this option is given, the ports used will always to larger
-than that specified. Useful for systems behind firewalls. 
+than that specified. Useful for systems behind firewalls. If not specified,
+defaults to 1024.
+.TP
+.B --max-port=<port>
+Use ports lower than that given as source for outbound DNS queries.
+Dnsmasq picks random ports as source for outbound queries:
+when this option is given, the ports used will always be lower
+than that specified. Useful for systems behind firewalls.
 .TP
+
 .B \-i, --interface=<interface name>
 Listen only on the specified interface(s). Dnsmasq automatically adds
 the loopback (local) interface to the list of interfaces to use when
@@ -186,12 +204,17 @@ or
 options are given dnsmasq listens on all available interfaces except any
 given in
 .B \--except-interface
-options. IP alias interfaces (eg "eth1:0") cannot be used with
-.B --interface
+options. On Linux, when
+.B \--bind-interfaces
 or
-.B --except-interface
-options, use --listen-address instead. A simple wildcard, consisting
-of a trailing '*', can be used in 
+.B \--bind-dynamic
+are in effect, IP alias interface labels (eg "eth1:0") are checked, rather than
+interface names. In the degenerate case when an interface has one address, this amounts to the same thing but when an interface has multiple addresses it
+allows control over which of those addresses are accepted.
+The same effect is achievable in default mode by using
+.B \--listen-address.
+A simple wildcard, consisting of a trailing '*',
+can be used in
 .B \--interface 
 and
 .B \--except-interface
@@ -205,7 +228,9 @@ and
 .B --except-interface
 options does not matter and that 
 .B --except-interface
-options always override the others.
+options always override the others. The comments about interface labels for
+.B --listen-address
+apply here.
 .TP
 .B --auth-server=<domain>,<interface>|<ip-address>
 Enable DNS authoritative mode for queries arriving at an interface or address. Note that the interface or address
@@ -215,9 +240,9 @@ or
 .B --listen-address
 configuration, indeed
 .B --auth-server
-will overide these and provide a different DNS service on the
+will override these and provide a different DNS service on the
 specified interface. The <domain> is the "glue record". It should
-resolve in the global DNS to a A and/or AAAA record which points to
+resolve in the global DNS to an A and/or AAAA record which points to
 the address dnsmasq is listening on. When an interface is specified,
 it may be qualified with "/4" or "/6" to specify only the IPv4 or IPv6
 addresses associated with the interface.
@@ -225,7 +250,7 @@ addresses associated with the interface.
 .B --local-service
 Accept DNS queries only from hosts whose address is on a local subnet,
 ie a subnet for which an interface exists on the server. This option
-only has effect is there are no --interface --except-interface,
+only has effect if there are no --interface --except-interface,
 --listen-address or --auth-server options. It is intended to be set as
 a default on installation, to allow unconfigured installations to be
 useful but also safe from being used for DNS amplification attacks.
@@ -272,8 +297,8 @@ option requires non-standard networking APIs and it is only available
 under Linux. On other platforms it falls-back to --bind-interfaces mode.
 .TP
 .B \-y, --localise-queries
-Return answers to DNS queries from /etc/hosts which depend on the interface over which the query was
-received. If a name in /etc/hosts has more than one address associated with
+Return answers to DNS queries from /etc/hosts and --interface-name which depend on the interface over which the query was
+received. If a name has more than one address associated with
 it, and at least one of those addresses is on the same subnet as the
 interface to which the query was sent, then return only the
 address(es) on that subnet. This allows for a server  to have multiple
@@ -284,7 +309,8 @@ attached to. Currently this facility is limited to IPv4.
 .B \-b, --bogus-priv
 Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc)
 which are not found in /etc/hosts or the DHCP leases file are answered
-with "no such domain" rather than being forwarded upstream.
+with "no such domain" rather than being forwarded upstream. The 
+set of prefixes affected is the list given in RFC6303, for IPv4 and IPv6.
 .TP
 .B \-V, --alias=[<old-ip>]|[<start-ip>-<end-ip>],<new-ip>[,<mask>]
 Modify IPv4 addresses returned from upstream nameservers; old-ip is
@@ -307,7 +333,7 @@ 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>
+.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
@@ -405,7 +431,10 @@ xxx.internal.thekelleys.org.uk at 192.168.1.1 then giving  the flag
 .B -S /internal.thekelleys.org.uk/192.168.1.1 
 will send all queries for
 internal machines to that nameserver, everything else will go to the
-servers in /etc/resolv.conf. An empty domain specification,
+servers in /etc/resolv.conf. DNSSEC validation is turned off for such
+private nameservers, UNLESS a
+.B --trust-anchor
+is specified for the domain in question. An empty domain specification,
 .B // 
 has the special meaning of "unqualified names only" ie names without any
 dots in them. A non-standard port may be specified as 
@@ -414,7 +443,7 @@ address using a # character.
 More than one -S flag is allowed, with
 repeated domain or ipaddr parts as required.
 
-More specific domains take precendence over less specific domains, so:
+More specific domains take precedence over less specific domains, so:
 .B --server=/google.com/1.2.3.4
 .B --server=/www.google.com/2.3.4.5
 will send queries for *.google.com to 1.2.3.4, except *www.google.com,
@@ -436,17 +465,17 @@ is a synonym for
 .B server
 to make configuration files clearer in this case.
 
-IPv6 addresses may include a %interface scope-id, eg
+IPv6 addresses may include an %interface scope-id, eg
 fe80::202:a412:4512:7bbf%eth0.
 
-The optional string after the @ character tells
-dnsmasq how to set the source of the queries to this
-nameserver. It should be an ip-address, which should belong to the machine on which
-dnsmasq is running otherwise this server line will be logged and then
-ignored, or an interface name. If an interface name is given, then
-queries to the server will be forced via that interface; if an
-ip-address is given then the source address of the queries will be set
-to that address.
+The optional string after the @ character tells dnsmasq how to set the source of
+the queries to this nameserver. It can either be an ip-address, an interface
+name or both. The ip-address should belong to the machine on which dnsmasq is
+running, otherwise this server line will be logged and then ignored. If an
+interface name is given, then queries to the server will be forced via that
+interface; if an ip-address is given then the source address of the queries will
+be set to that address; and if both are given then a combination of ip-address
+and interface name will be used to steer requests to the server.
 The query-port flag is ignored for any servers which have a
 source address specified but the port may be specified directly as
 part of the source address. Forcing queries to an interface is not
@@ -460,28 +489,36 @@ but provides some syntactic sugar to make specifying address-to-name queries eas
 is exactly equivalent to 
 .B --server=/3.2.1.in-addr.arpa/192.168.0.1
 .TP
-.B \-A, --address=/<domain>/[domain/][<ipaddr>]
+.B \-A, --address=/<domain>[/<domain>...]/[<ipaddr>]
 Specify an IP address to return for any host in the given domains.
 Queries in the domains are never forwarded and always replied to
 with the specified IP address which may be IPv4 or IPv6. To give
-both IPv4 and IPv6 addresses for a domain, use repeated -A flags.
+both IPv4 and IPv6 addresses for a domain, use repeated \fB-A\fP flags.
+To include multiple IP addresses for a single query, use
+\fB--addn-hosts=<path>\fP instead.
 Note that /etc/hosts and DHCP leases override this for individual
 names. A common use of this is to redirect the entire doubleclick.net
 domain to some friendly local web server to avoid banner ads. The
-domain specification works in the same was as for --server, with the
-additional facility that /#/ matches any domain. Thus
---address=/#/1.2.3.4 will always return 1.2.3.4 for any query not
-answered from /etc/hosts or DHCP and not sent to an upstream
-nameserver by a more specific --server directive. As for --server,
-one or more domains with no address returns a no-such-domain answer, so
---address=/example.com/ is equivalent to --server=/example.com/ and returns 
-NXDOMAIN for example.com and all its subdomains.
-.TP
-.B --ipset=/<domain>/[domain/]<ipset>[,<ipset>]
-Places the resolved IP addresses of queries for the specified domains
-in the specified netfilter ip sets. Domains and subdomains are matched
-in the same way as --address. These ip sets must already exist. See
-ipset(8) for more details.
+domain specification works in the same was as for \fB--server\fP, with
+the additional facility that \fB/#/\fP matches any domain. Thus
+\fB--address=/#/1.2.3.4\fP will always return \fB1.2.3.4\fP for any
+query not answered from \fB/etc/hosts\fP or DHCP and not sent to an
+upstream nameserver by a more specific \fB--server\fP directive. As for
+\fB--server\fP, one or more domains with no address returns a
+no-such-domain answer, so \fB--address=/example.com/\fP is equivalent to
+\fB--server=/example.com/\fP and returns NXDOMAIN for example.com and
+all its subdomains.
+.TP
+.B --ipset=/<domain>[/<domain>...]/<ipset>[,<ipset>...]
+Places the resolved IP addresses of queries for one or more domains in
+the specified Netfilter IP set. If multiple setnames are given, then the
+addresses are placed in each of them, subject to the limitations of an
+IP set (IPv4 addresses cannot be stored in an IPv6 IP set and vice
+versa).  Domains and subdomains are matched in the same way as
+\fB--address\fP.
+These IP sets must already exist. See
+.BR ipset (8)
+for more details.
 .TP
 .B \-m, --mx-host=<mx name>[[,<hostname>],<preference>]
 Return an MX record named <mx name> pointing to the given hostname (if
@@ -519,7 +556,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>][,<TTL>]
 Add A, AAAA and PTR records to the DNS. This adds one or more names to
 the DNS with associated IPv4 (A) and IPv6 (AAAA) records. A name may
 appear in more than one 
@@ -536,6 +573,10 @@ is in effect. Short and long names may appear in the same
 .B host-record,
 eg. 
 .B --host-record=laptop,laptop.thekelleys.org,192.168.0.1,1234::100
+
+If the time-to-live is given, it overrides the default, which is zero
+or the value of --local-ttl. The value is a positive integer and gives 
+the time-to-live in seconds.
 .TP
 .B \-Y, --txt-record=<name>[[,<text>],<text>]
 Return a TXT DNS record. The value of TXT record is a set of strings,
@@ -549,7 +590,7 @@ Return a PTR DNS record.
 .B --naptr-record=<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<replacement>]
 Return an NAPTR DNS record, as specified in RFC3403.
 .TP
-.B --cname=<cname>,<target>
+.B --cname=<cname>,[<cname>,]<target>[,<TTL>]
 Return a CNAME record which indicates that <cname> is really
 <target>. There are significant limitations on the target; it must be a
 DNS name which is known to dnsmasq from /etc/hosts (or additional
@@ -557,7 +598,13 @@ hosts files), from DHCP, from --interface-name or from another
 .B --cname.
 If the target does not satisfy this
 criteria, the whole cname is ignored. The cname must be unique, but it
-is permissable to have more than one cname pointing to the same target.
+is permissible to have more than one cname pointing to the same target. Indeed
+it's possible to declare multiple cnames to a target in a single line, like so:
+.B --cname=cname1,cname2,target
+
+If the time-to-live is given, it overrides the default, which is zero
+or the value of -local-ttl. The value is a positive integer and gives 
+the time-to-live in seconds.
 .TP
 .B --dns-rr=<name>,<RR-number>,[<hex data>]
 Return an arbitrary DNS Resource Record. The number is the type of the
@@ -566,7 +613,7 @@ given by the hex data, which may be of the form 01:23:45 or 01 23 45 or
 012345 or any mixture of these.
 .TP
 .B --interface-name=<name>,<interface>[/4|/6]
-Return a DNS record associating the name with the primary address on
+Return DNS records associating the name with the address(es) of
 the given interface. This flag specifies an A or AAAA record for the given
 name in the same way as an /etc/hosts line, except that the address is
 not constant, but taken from the given interface. The interface may be
@@ -576,25 +623,31 @@ down, not configured or non-existent, an empty record is returned. The
 matching PTR record is also created, mapping the interface address to
 the name. More than one name may be associated with an interface
 address by repeating the flag; in that case the first instance is used
-for the reverse address-to-name mapping.
+for the reverse address-to-name mapping. Note that a name used in 
+--interface-name may not appear in /etc/hosts.
 .TP
-.B --synth-domain=<domain>,<address range>[,<prefix>]
+.B --synth-domain=<domain>,<address range>[,<prefix>[*]]
 Create artificial A/AAAA and PTR records for an address range. The
-records use the address, with periods (or colons for IPv6) replaced
-with dashes.
+records either seqential numbers or the address, with periods (or colons for IPv6) replaced with dashes.
 
-An example should make this clearer.
-.B --synth-domain=thekelleys.org.uk,192.168.0.0/24,internal-
+An examples should make this clearer. First sequential numbers.
+.B --synth-domain=thekelleys.org.uk,192.168.0.50,192.168.0.70,internal-*
+results in the name internal-0.thekelleys.org.uk. returning 192.168.0.50, internal-1.thekelleys.org.uk returning 192.168.0.51 and so on. (note the *) The same principle applies to IPv6 addresses (where the numbers may be very large). Reverse lookups from address to name behave as expected.
+
+Second, 
+.B --synth-domain=thekelleys.org.uk,192.168.0.0/24,internal- (no *)
 will result in a query for internal-192-168-0-56.thekelleys.org.uk returning
 192.168.0.56 and a reverse query vice versa. The same applies to IPv6,
 but IPv6 addresses may start with '::'
 but DNS labels may not start with '-' so in this case if no prefix is
 configured a zero is added in front of the label. ::1 becomes 0--1.
 
+V4 mapped IPv6 addresses, which have a representation like ::ffff:1.2.3.4 are handled specially, and become like 0--ffff-1-2-3-4
+
 The address range can be of the form
-<ip address>,<ip address> or <ip address>/<netmask>
+<ip address>,<ip address> or <ip address>/<netmask> in both forms of the option.
 .TP
-.B --add-mac
+.B --add-mac[=base64|text]
 Add the MAC address of the requestor to DNS queries which are
 forwarded upstream. This may be used to DNS filtering by the upstream
 server. The MAC address can only be added if the requestor is on the same
@@ -602,19 +655,34 @@ subnet as the dnsmasq server. Note that the mechanism used to achieve this (an E
 is not yet standardised, so this should be considered
 experimental. Also note that exposing MAC addresses in this way may
 have security and privacy implications. The warning about caching
-given for --add-subnet applies to --add-mac too.
+given for --add-subnet applies to --add-mac too. An alternative encoding of the 
+MAC, as base64, is enabled by adding the "base64" parameter and a human-readable encoding of hex-and-colons is enabled by added the "text" parameter.
+.TP
+.B --add-cpe-id=<string>
+Add an arbitrary identifying string to o DNS queries which are
+forwarded upstream.
 .TP 
-.B --add-subnet[[=<IPv4 prefix length>],<IPv6 prefix length>]
-Add the subnet address of the requestor to the DNS queries which are
-forwarded upstream. The amount of the address forwarded depends on the
-prefix length parameter: 32 (128 for IPv6) forwards the whole address,
-zero forwards none of it but still marks the request so that no
-upstream nameserver will add client address information either. The
-default is zero for both IPv4 and IPv6. Note that upstream nameservers
-may be configured to return different results based on this
-information, but the dnsmasq cache does not take account. If a dnsmasq
-instance is configured such that different results may be encountered,
-caching should be disabled.
+.B --add-subnet[[=[<IPv4 address>/]<IPv4 prefix length>][,[<IPv6 address>/]<IPv6 prefix length>]]
+Add a subnet address to the DNS queries which are forwarded
+upstream. If an address is specified in the flag, it will be used,
+otherwise, the address of the requestor will be used. The amount of
+the address forwarded depends on the prefix length parameter: 32 (128
+for IPv6) forwards the whole address, zero forwards none of it but
+still marks the request so that no upstream nameserver will add client
+address information either. The default is zero for both IPv4 and
+IPv6. Note that upstream nameservers may be configured to return
+different results based on this information, but the dnsmasq cache
+does not take account. If a dnsmasq instance is configured such that
+different results may be encountered, caching should be disabled.
+
+For example,
+.B --add-subnet=24,96
+will add the /24 and /96 subnets of the requestor for IPv4 and IPv6 requestors, respectively.
+.B --add-subnet=1.2.3.4/24
+will add 1.2.3.0/24 for IPv4 requestors and ::/0 for IPv6 requestors.
+.B --add-subnet=1.2.3.4/24,1.2.3.4/24
+will add 1.2.3.0/24 for both IPv4 and IPv6 requestors.
+
 .TP
 .B \-c, --cache-size=<cachesize>
 Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching.
@@ -644,15 +712,15 @@ permitted to reduce the cache size below the default when DNSSEC is
 enabled. The nameservers upstream of dnsmasq must be DNSSEC-capable,
 ie capable of returning DNSSEC records with data. If they are not,
 then dnsmasq will not be able to determine the trusted status of
-answers. In the default mode, this menas that all replies will be
+answers. In the default mode, this means that all replies will be
 marked as untrusted. If 
 .B --dnssec-check-unsigned
 is set and the upstream servers don't support DNSSEC, then DNS service will be entirely broken.
 .TP
 .B --trust-anchor=[<class>],<domain>,<key-tag>,<algorithm>,<digest-type>,<digest>
 Provide DS records to act a trust anchors for DNSSEC
-validation. Typically these will be the DS record(s) for Zone Signing
-key(s) of the root zone,
+validation. Typically these will be the DS record(s) for Key Signing
+key(s) (KSK) of the root zone,
 but trust anchors for limited domains are also possible. The current
 root-zone trust anchors may be downloaded from https://data.iana.org/root-anchors/root-anchors.xml 
 .TP
@@ -672,10 +740,14 @@ section on
 DNSSEC signatures are only valid for specified time windows, and should be rejected outside those windows. This generates an
 interesting chicken-and-egg problem for machines which don't have a hardware real time clock. For these machines to determine the correct 
 time typically requires use of NTP and therefore DNS, but validating DNS requires that the correct time is already known. Setting this flag
-removes the time-window checks (but not other DNSSEC validation.) only until the dnsmasq process receives SIGHUP. The intention is
+removes the time-window checks (but not other DNSSEC validation.) only until the dnsmasq process receives SIGINT. The intention is
 that dnsmasq should be started with this flag when the platform determines that reliable time is not currently available. As soon as 
-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.
+reliable time is established, a SIGINT should be sent to dnsmasq, which enables time checking, and purges the cache of DNS records
+which have not been thoroughly checked.
+
+Earlier versions of dnsmasq overloaded SIGHUP (which re-reads much configuration) to also enable time validation.
+
+If dnsmasq is run in debug mode (-d flag) then SIGINT retains its usual meaning of terminating the dnsmasq process.
 .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 
@@ -696,7 +768,7 @@ a return code of SERVFAIL. Note that
 setting this may affect DNS behaviour in bad ways, it is not an
 extra-logging flag and should not be set in production.
 .TP
-.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....]]
+.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....][,exclude:<subnet>[/<prefix length>]].....]
 Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain
 will be served. If subnet(s) are given, A and AAAA records must be in one of the
 specified subnets.
@@ -713,6 +785,10 @@ appear in the zone, but RFC1918 IPv4 addresses which should not.
 Interface-name and address-literal subnet specifications may be used
 freely in the same --auth-zone declaration.
 
+It's possible to exclude certain IP addresses from responses. It can be
+used, to make sure that answers contain only global routeable IP
+addresses (by excluding loopback, RFC1918 and ULA addresses).
+
 The subnet(s) are also used to define in-addr.arpa and
 ip6.arpa domains which are served for reverse-DNS queries. If not
 specified, the prefix length defaults to 24 for IPv4 and 64 for IPv6.
@@ -747,7 +823,7 @@ compiled in and the kernel must have conntrack support
 included and configured. This option cannot be combined with
 --query-port. 
 .TP
-.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-addr>[,<end-addr>][,<mode>][,<netmask>[,<broadcast>]][,<lease time>]
+.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-addr>[,<end-addr>|<mode>][,<netmask>[,<broadcast>]][,<lease time>]
 .TP
 .B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-IPv6addr>[,<end-IPv6addr>|constructor:<interface>][,<mode>][,<prefix-len>][,<lease time>]
 
@@ -779,7 +855,7 @@ For IPv6, the parameters are slightly different: instead of netmask
 and broadcast address, there is an optional prefix length which must
 be equal to or larger then the prefix length on the local interface. If not
 given, this defaults to 64. Unlike the IPv4 case, the prefix length is not
-automatically derived from the interface configuration. The mimimum
+automatically derived from the interface configuration. The minimum
 size of the prefix length is 64.
 
 IPv6 (only) supports another type of range. In this, the start address and optional end address contain only the network part (ie ::1) and they are followed by
@@ -901,7 +977,7 @@ subnets which don't need a pool of dynamically allocated addresses,
 use the "static" keyword in the dhcp-range declaration.
 
 It is allowed to use client identifiers (called client
-DUID in IPv6-land rather than
+DUID in IPv6-land) rather than
 hardware addresses to identify hosts by prefixing with 'id:'. Thus: 
 .B --dhcp-host=id:01:02:03:04,..... 
 refers to the host with client identifier 01:02:03:04. It is also
@@ -953,6 +1029,8 @@ dhcp-host directive (or one implied by /etc/ethers) then the special
 tag "known" is set. This allows dnsmasq to be configured to
 ignore requests from unknown machines using
 .B --dhcp-ignore=tag:!known
+If the host matches only a dhcp-host directive which cannot
+be used because it specifies an address on different subnet, the tag "known-othernet" is set.
 Ethernet addresses (but not client-ids) may have
 wildcard bytes, so for example 
 .B --dhcp-host=00:20:e0:3b:13:*,ignore 
@@ -994,22 +1072,21 @@ 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
+.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
+in a dhcp-optsfile.
 .TP
 .B --dhcp-hostsdir=<path>
 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 
+If a file is deleted or changed after it has been read by dnsmasq, then the
+host record it contained will remain until dnsmasq receives 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
-.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
-in a dhcp-optsfile.
 .TP 
 .B \-Z, --read-ethers
 Read /etc/ethers for information about hosts for the DHCP server. The
@@ -1246,7 +1323,7 @@ Perform boolean operations on tags. Any tag appearing as set:<tag> is set if
 all the tags which appear as tag:<tag> are set, (or unset when tag:!<tag> is used)
 If no tag:<tag> appears set:<tag> tags are set unconditionally.
 Any number of set: and tag: forms may appear, in any order. 
-Tag-if lines ares executed in order, so if the tag in tag:<tag> is a
+Tag-if lines are executed in order, so if the tag in tag:<tag> is a
 tag set by another
 .B tag-if,
 the line which sets the tag must precede the one which tests it.
@@ -1315,7 +1392,7 @@ functions when supported by a suitable DHCP server.
 This specifies a boot option which may appear in a PXE boot menu. <CSA> is
 client system type, only services of the correct type will appear in a
 menu. The known types are x86PC, PC98, IA64_EFI, Alpha, Arc_x86,
-Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI and X86-64_EFI; an
+Intel_Lean_Client, IA32_EFI,  X86-64_EFI, Xscale_EFI, BC_EFI, ARM32_EFI and ARM64_EFI; an
 integer may be used for other types. The
 parameter after the menu text may be a file name, in which case dnsmasq acts as a
 boot server and directs the PXE client to download the file by TFTP,
@@ -1324,8 +1401,9 @@ either from itself (
 must be set for this to work) or another TFTP server if the final server
 address/name is given.
 Note that the "layer"
-suffix (normally ".0") is supplied by PXE, and should not be added to
-the basename. If an integer boot service type, rather than a basename
+suffix (normally ".0") is supplied by PXE, and need not be added to
+the basename. Alternatively, the basename may be a filename, complete with suffix, in which case
+no layer suffix is added. If an integer boot service type, rather than a basename
 is given, then the PXE client will search for a
 suitable boot service for that type on the network. This search may be done
 by broadcast, or direct to a server if its IP address/name is provided.  
@@ -1416,7 +1494,7 @@ DUID automatically when it is first needed. When given, this option
 provides dnsmasq the data required to create a DUID-EN type DUID. Note
 that once set, the DUID is stored in the lease database, so to change between DUID-EN and
 automatically created DUIDs or vice-versa, the lease database must be
-re-intialised. The enterprise-id is assigned by IANA, and the uid is a
+re-initialised. The enterprise-id is assigned by IANA, and the uid is a
 string of hex octets unique to a particular device.
 .TP
 .B \-6 --dhcp-script=<path>
@@ -1484,6 +1562,8 @@ DHCP relay-agent added any of these options.
  
 If the client provides vendor-class, DNSMASQ_VENDOR_CLASS.
 
+DNSMASQ_REQUESTED_OPTIONS a string containing the decimal values in the Parameter Request List option, comma separated, if the parameter request list option is provided by the client.
+
 For IPv6 only:
 
 If the client provides vendor-class, DNSMASQ_VENDOR_CLASS_ID,
@@ -1507,8 +1587,8 @@ database.
 
 
 All file descriptors are
-closed except stdin, stdout and stderr which are open to /dev/null
-(except in debug mode).
+closed except stdin, which is open to /dev/null, and stdout and stderr which capture output for logging by dnsmasq. 
+(In debug mode, stdio, stdout and stderr file are left as those inherited from the invoker of dnsmasq).
 
 The script is not invoked concurrently: at most one instance
 of the script is ever running (dnsmasq waits for an instance of script to exit
@@ -1523,11 +1603,11 @@ At dnsmasq startup, the script will be invoked for
 all existing leases as they are read from the lease file. Expired
 leases will be called with "del" and others with "old". When dnsmasq
 receives a HUP signal, the script will be invoked for existing leases
-with an "old " event.
+with an "old" event.
 
 
-There are two further actions which may appear as the first argument
-to the script, "init" and "tftp". More may be added in the future, so
+There are four further actions which may appear as the first argument
+to the script, "init", "arp-add", "arp-del" and "tftp". More may be added in the future, so
 scripts should be written to ignore unknown actions. "init" is
 described below in 
 .B --leasefile-ro
@@ -1535,11 +1615,16 @@ The "tftp" action is invoked when a TFTP file transfer completes: the
 arguments are the file size in bytes, the address to which the file
 was sent, and the complete pathname of the file.
  
+The "arp-add" and "arp-del" actions are only called if enabled with
+.B --script-arp
+They are are supplied with a MAC address and IP address as arguments. "arp-add" indicates
+the arrival of a new entry in the ARP or neighbour table, and "arp-del" indicates the deletion of same.
+
 .TP
 .B --dhcp-luascript=<path>
 Specify a script written in Lua, to be run when leases are created,
 destroyed or changed. To use this option, dnsmasq must be compiled
-with the correct support. The Lua interpreter is intialised once, when
+with the correct support. The Lua interpreter is initialised once, when
 dnsmasq starts, so that global variables persist between lease
 events. The Lua code must define a
 .B lease
@@ -1581,10 +1666,24 @@ table holds the tags
 .B file_name
 and 
 .B file_size.
+
+The 
+.B arp
+and
+.B arp-old
+functions are called only when enabled with
+.B --script-arp
+and have a table which holds the tags
+.B mac_address
+and
+.B client_address.
 .TP
 .B --dhcp-scriptuser
 Specify the user as which to run the lease-change script or Lua script. This defaults to root, but can be changed to another user using this flag. 
-.TP 
+.TP
+.B --script-arp
+Enable the "arp" and "arp-old" functions in the dhcp-script and dhcp-luascript.
+.TP
 .B \-9, --leasefile-ro
 Completely suppress use of the lease database file. The file will not
 be created, read, or written. Change the way the lease-change
@@ -1600,13 +1699,17 @@ option also forces the leasechange script to be called on changes
 to the client-id and lease length and expiry time.
 .TP
 .B --bridge-interface=<interface>,<alias>[,<alias>]
-Treat DHCP (v4 and v6) request and IPv6 Router Solicit packets
+Treat DHCP (v4 and v6) requests and IPv6 Router Solicit packets
 arriving at any of the <alias> interfaces as if they had arrived at
 <interface>.  This option allows dnsmasq to provide DHCP and RA
 service over unaddressed and unbridged Ethernet interfaces, e.g. on an
 OpenStack compute host where each such interface is a TAP interface to
 a VM, or as in "old style bridging" on BSD platforms.  A trailing '*'
 wildcard can be used in each <alias>.
+
+It is permissible to add more than one alias using more than one --bridge-interface option since 
+--bridge-interface=int1,alias1,alias2 is exactly equivalent to
+--bridge-interface=int1,alias1 --bridge-interface=int1,alias2
 .TP
 .B \-s, --domain=<domain>[,<address range>[,local]]
 Specifies DNS domains for the DHCP server. Domains may be be given 
@@ -1677,17 +1780,17 @@ creation are handled by a different protocol. When DHCP is in use,
 only a subset of this is needed, and dnsmasq can handle it, using
 existing DHCP configuration to provide most data. When RA is enabled,
 dnsmasq will advertise a prefix for each dhcp-range, with default
-router and recursive DNS server as the relevant link-local address on 
-the machine running dnsmasq. By default, he "managed address" bits are set, and
+router  as the relevant link-local address on 
+the machine running dnsmasq. By default, the "managed address" bits are set, and
 the "use SLAAC" bit is reset. This can be changed for individual
 subnets with the mode keywords described in
 .B --dhcp-range.
 RFC6106 DNS parameters are included in the advertisements. By default,
 the relevant link-local address of the machine running dnsmasq is sent
 as recursive DNS server. If provided, the DHCPv6 options dns-server and
-domain-search are used for RDNSS and DNSSL.
+domain-search are used for the DNS server (RDNSS) and the domain search list (DNSSL).
 .TP
-.B --ra-param=<interface>,[high|low],[[<ra-interval>],<router lifetime>]
+.B --ra-param=<interface>,[mtu:<integer>|<interface>|off,][high,|low,]<ra-interval>[,<router lifetime>]
 Set non-default values for router advertisements sent via an
 interface. The priority field for the router may be altered from the
 default of medium with eg
@@ -1697,16 +1800,26 @@ The interval between router advertisements may be set (in seconds) with
 The lifetime of the route may be changed or set to zero, which allows
 a router to advertise prefixes but not a route via itself. 
 .B --ra-parm=eth0,0,0
-(A value of zero for the interval means the default value.) All three parameters may be set at once.
-.B --ra-param=low,60,1200
+(A value of zero for the interval means the default value.) All four parameters may be set at once.
+.B --ra-param=eth0,mtu:1280,low,60,1200
+
 The interface field may include a wildcard.
+
+The mtu: parameter may be an arbitrary interface name, in which case the MTU value for that interface is used. This is useful
+for (eg) advertising the MTU of a WAN interface on the other interfaces of a router.
+.TP
+.B --dhcp-reply-delay=[tag:<tag>,]<integer>
+Delays sending DHCPOFFER and proxydhcp replies for at least the specified number of seconds.
+This can be used as workaround for bugs in PXE boot firmware that does not function properly when
+receiving an instant reply.
+This option takes into account the time already spent waiting (e.g. performing ping check) if any.
 .TP
 .B --enable-tftp[=<interface>[,<interface>]]
 Enable the TFTP server function. This is deliberately limited to that
 needed to net-boot a client. Only reading is allowed; the tsize and
 blksize extensions are supported (tsize is only supported in octet
 mode). Without an argument, the TFTP service is provided to the same set of interfaces as DHCP service. 
-If the list of interfaces is provided, that defines which interfaces recieve TFTP service.
+If the list of interfaces is provided, that defines which interfaces receive TFTP service.
 .TP
 .B --tftp-root=<directory>[,<interface>]
 Look for files to transfer using TFTP relative to the given
@@ -1719,12 +1832,16 @@ directory is only used for TFTP requests via that interface.
 .B --tftp-no-fail
 Do not abort startup if specified tftp root directories are inaccessible.
 .TP
-.B --tftp-unique-root
-Add the IP address of the TFTP client as a path component on the end
-of the TFTP-root (in standard dotted-quad format). Only valid if a
-tftp-root is set and the directory exists. For instance, if tftp-root is "/tftp" and client 
-1.2.3.4 requests file "myfile" then the effective path will be
-"/tftp/1.2.3.4/myfile" if /tftp/1.2.3.4 exists or /tftp/myfile otherwise.
+.B --tftp-unique-root[=ip|mac]
+Add the IP or hardware address of the TFTP client as a path component on the end
+of the TFTP-root. Only valid if a tftp-root is set and the directory exists.
+Defaults to adding IP address (in standard dotted-quad format).
+For instance, if tftp-root is "/tftp" and client 1.2.3.4 requests file "myfile"
+then the effective path will be "/tftp/1.2.3.4/myfile" if /tftp/1.2.3.4 exists or /tftp/myfile otherwise.
+When "=mac" is specified it will append the MAC address instead, using lowercase zero padded digits
+separated by dashes, e.g.: 01-02-03-04-aa-bb
+Note that resolving MAC addresses is only possible if the client is in the local network or obtained
+a DHCP lease from us.
 .TP
 .B --tftp-secure
 Enable TFTP secure mode: without this, any file which is readable by
@@ -1755,6 +1872,10 @@ require about (2*n) + 10 descriptors. If
 .B --tftp-port-range
 is given, that can affect the number of concurrent connections.
 .TP
+.B --tftp-mtu=<mtu size>
+Use size as the ceiling of the MTU supported by the intervening network when 
+negotiating TFTP blocksize, overriding the MTU setting of the local interface  if it is larger.
+.TP
 .B --tftp-no-blocksize
 Stop the TFTP server from negotiating the "blocksize" option with a
 client. Some buggy clients request this option but then behave badly
@@ -1790,7 +1911,7 @@ A special case of
 .B --conf-file
 which differs in two respects. Firstly, only --server and --rev-server are allowed 
 in the configuration file included. Secondly, the file is re-read and the configuration
-therein is updated when dnsmasq recieves SIGHUP.
+therein is updated when dnsmasq receives SIGHUP.
 .SH CONFIG FILE
 At startup, dnsmasq reads
 .I /etc/dnsmasq.conf,
@@ -1870,7 +1991,7 @@ and
 
  
 .PP
-Dnsmasq is a DNS query forwarder: it it not capable of recursively
+Dnsmasq is a DNS query forwarder: it is not capable of recursively
 answering arbitrary queries starting from the root servers but
 forwards such queries to a fully recursive upstream DNS server which is
 typically provided by an ISP. By default, dnsmasq reads
@@ -1939,7 +2060,7 @@ include set:<tag>, including one from the
 .B dhcp-range
 used to allocate the address, one from any matching 
 .B dhcp-host
-(and "known" if a dhcp-host matches) 
+(and "known" or "known-othernet" if a dhcp-host matches) 
 The tag "bootp" is set for BOOTP requests, and a tag whose name is the 
 name of the interface on which the request arrived is also set.
 
@@ -2126,7 +2247,12 @@ following data is used to populate the authoritative zone.
 .B --cname
 as long as the record name is in  the authoritative domain. If the
 target of the CNAME is unqualified, then it  is qualified with the
-authoritative zone name.
+authoritative zone name. CNAME used in this way (only) may be wildcards, as in
+
+.nf
+.B cname=*.example.com,default.example.com
+.fi
+
 .PP
 IPv4 and IPv6 addresses from /etc/hosts (and 
 .B --addn-hosts
@@ -2139,7 +2265,7 @@ provided the address falls into one of the subnets specified in the
 .PP
 Addresses of DHCP leases, provided the address falls into one of the subnets specified in the
 .B --auth-zone.
-(If contructed DHCP ranges are is use, which depend on the address dynamically 
+(If constructed DHCP ranges are is use, which depend on the address dynamically 
 assigned to an interface, then the form of
 .B --auth-zone
 which defines subnets by the dynamic address of an interface should
index b4cc16d..80cef39 100644 (file)
@@ -1756,20 +1756,20 @@ dnsmasq est spécifiée comme DNS récursif. Si elles sont fournies, les
 options dns-server et domain-search sont utilisées respectivement pour RDNSS et
 DNSSL.
 .TP
-.B --ra-param=<interface>,[high|low],[[<intervalle d'annonce routeur>],<durée de vie route>]
+.B --ra-param=<interface>,[mtu:<valeur>|<interface>|off,][high,|low,]<intervalle d'annonce routeur>[,<durée de vie route>]
 Configure pour une interface donnée des valeurs pour les annonces routeurs
 différentes des valeurs par défaut. La valeur par défaut du champ priorité
 pour le routeur peut-être changée de "medium" (moyen) à "high" (haute) ou
 "low" (basse). Par exemple :
-.B --ra-param=eth0,high.
+.B --ra-param=eth0,high,0.
 Un intervalle (en secondes) entre les annonces routeur peut-être fourni par :
 .B --ra-param=eth0,60.
 La durée de vie de la route peut-être changée ou mise à zéro, auquel cas 
 le routeur peut annoncer les préfixes mais pas de route :
 .B --ra-parm=eth0,0,0
 (une valeur de zéro pour l'intervalle signifie qu'il garde la valeur par défaut).
-Ces trois paramètres peuvent-être configurés en une fois :
-.B --ra-param=low,60,1200
+Ces quatre paramètres peuvent-être configurés en une fois :
+.B --ra-param=eth0,mtu:1280,low,60,1200
 La valeur pour l'interface peut inclure un caractère joker.
 .TP
 .B --enable-tftp[=<interface>[,<interface>]]
index 69d5d35..a8a83e0 100644 (file)
--- 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.74\n"
+"Project-Id-Version: dnsmasq 2.77\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2009-06-18 12:24+0100\n"
-"PO-Revision-Date: 2015-07-22 23:07+0200\n"
+"PO-Revision-Date: 2017-07-17 18:30+0100\n"
 "Last-Translator: Conrad Kostecki <ck@conrad-kostecki.de>\n"
 "Language-Team: German <de@li.org>\n"
 "Language: de\n"
@@ -20,720 +20,747 @@ 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.8.3\n"
+"X-Generator: Poedit 2.0.1\n"
 "X-Poedit-SourceCharset: UTF-8\n"
 
-#: cache.c:523
+#: cache.c:518
 msgid "Internal error in cache."
 msgstr "Interner Fehler im Cache."
 
-#: cache.c:941
+#: cache.c:928
 #, c-format
 msgid "failed to load names from %s: %s"
 msgstr "Fehler beim Laden der Namen von %s: %s"
 
-#: cache.c:967 dhcp.c:828
+#: cache.c:954 dhcp.c:867
 #, c-format
 msgid "bad address at %s line %d"
 msgstr "Fehlerhafte Adresse in %s Zeile %d"
 
-#: cache.c:1018 dhcp.c:844
+#: cache.c:1007 dhcp.c:883
 #, c-format
 msgid "bad name at %s line %d"
 msgstr "Fehlerhafter Name in %s Zeile %d"
 
-#: cache.c:1027 dhcp.c:919
+#: cache.c:1016 dhcp.c:958
 #, c-format
 msgid "read %s - %d addresses"
 msgstr "%s gelesen - %d Adressen"
 
-#: cache.c:1135
+#: cache.c:1129
 msgid "cleared cache"
 msgstr "Cache geleert"
 
-#: cache.c:1164
+#: cache.c:1158
 #, c-format
 msgid "No IPv4 address found for %s"
 msgstr "Keine IPv4-Adresse für %s gefunden"
 
-#: cache.c:1242
+#: cache.c:1237
 #, c-format
 msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
 msgstr "%s ist ein CNAME, weise es der DHCP-Lease von %s nicht zu"
 
-#: cache.c:1266
+#: cache.c:1261
 #, c-format
 msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
 msgstr "Name %s wurde dem DHCP-Lease von %s nicht zugewiesen, da der Name in %s bereits mit Adresse %s existiert"
 
-#: cache.c:1421
+#: cache.c:1418
 #, c-format
 msgid "time %lu"
 msgstr "Zeit %lu"
 
-#: cache.c:1422
+#: cache.c:1419
 #, c-format
 msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
 msgstr "Cache Größe %d, %d/%d Cache-Einfügungen verwendeten nicht abgelaufene Cache-Einträge wieder."
 
-#: cache.c:1424
+#: cache.c:1421
 #, c-format
 msgid "queries forwarded %u, queries answered locally %u"
 msgstr "%u weitergeleitete Anfragen, %u lokal beantwortete Anfragen"
 
-#: cache.c:1427
+#: cache.c:1424
 #, c-format
 msgid "queries for authoritative zones %u"
 msgstr "Anfragen nach autoritativen Zonen %u"
 
-#: cache.c:1453
+#: cache.c:1450
 #, c-format
 msgid "server %s#%d: queries sent %u, retried or failed %u"
 msgstr "Server %s#%d: %u Anfragen gesendet, %u erneut versucht oder fehlgeschlagen"
 
-#: util.c:45
+#: util.c:47
 #, c-format
 msgid "failed to seed the random number generator: %s"
 msgstr "Konnte den Zufallszahlengenerator nicht initialisieren: %s"
 
-#: util.c:205
+#: util.c:224
 msgid "failed to allocate memory"
 msgstr "Konnte Speicher nicht belegen"
 
-#: util.c:250 option.c:601
+#: util.c:281 option.c:619
 msgid "could not get memory"
 msgstr "Speicher nicht verfügbar"
 
-#: util.c:260
+#: util.c:291
 #, c-format
 msgid "cannot create pipe: %s"
 msgstr "Konnte Pipe nicht erzeugen: %s"
 
-#: util.c:268
+#: util.c:299
 #, c-format
 msgid "failed to allocate %d bytes"
 msgstr "Konnte %d Bytes nicht belegen"
 
 # @Simon: not perfect but I cannot get nearer right now.
-#: util.c:437
+#: util.c:468
 #, c-format
 msgid "infinite"
 msgstr "unendlich"
 
-#: option.c:332
+#: option.c:344
 msgid "Specify local address(es) to listen on."
 msgstr "Lokale abzuhörende Adresse(n) angeben."
 
-#: option.c:333
+#: option.c:345
 msgid "Return ipaddr for all hosts in specified domains."
 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
-#: option.c:334
+#: option.c:346
 msgid "Fake reverse lookups for RFC1918 private address ranges."
 msgstr "Für private Adressbereiche nach RFC1918 \"keine solche Domain\" liefern."
 
-#: option.c:335
+#: option.c:347
 msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
 msgstr "Diese IP-Adresse als NXDOMAIN interpretieren (wehrt \"Suchhilfen\" ab)."
 
-#: option.c:336
+#: option.c:348
 #, c-format
 msgid "Specify the size of the cache in entries (defaults to %s)."
 msgstr "Größe des Caches (Zahl der Einträge) festlegen (Voreinstellung: %s)."
 
-#: option.c:337
+#: option.c:349
 #, c-format
 msgid "Specify configuration file (defaults to %s)."
 msgstr "Konfigurationsdatei festlegen (Voreinstellung: %s)."
 
-#: option.c:338
+#: option.c:350
 msgid "Do NOT fork into the background: run in debug mode."
 msgstr "NICHT in den Hintergrund gehen: Betrieb im Debug-Modus"
 
-#: option.c:339
+#: option.c:351
 msgid "Do NOT forward queries with no domain part."
 msgstr "Anfragen ohne Domänen-Teil NICHT weiterschicken."
 
-#: option.c:340
+#: option.c:352
 msgid "Return self-pointing MX records for local hosts."
 msgstr "Für lokale Einträge MX-Einträge liefern, die auf sich selbst zeigen."
 
-#: option.c:341
+#: option.c:353
 msgid "Expand simple names in /etc/hosts with domain-suffix."
 msgstr "Erweitere einfache Namen in /etc/hosts mit der Domänen-Endung."
 
-#: option.c:342
+#: option.c:354
 msgid "Don't forward spurious DNS requests from Windows hosts."
 msgstr "'unechte' DNS-Anfragen von Windows-Rechnern nicht weiterleiten"
 
 # @Simon: I'm a bit unsure about "spurious"
-#: option.c:343
+#: option.c:355
 msgid "Enable DHCP in the range given with lease duration."
 msgstr "DHCP für angegebenen Bereich und Dauer einschalten"
 
-#: option.c:344
+#: option.c:356
 #, c-format
 msgid "Change to this group after startup (defaults to %s)."
 msgstr "Nach dem Start in diese Benutzergruppe wechseln (Voreinstellung %s)."
 
-#: option.c:345
+#: option.c:357
 msgid "Set address or hostname for a specified machine."
 msgstr "Adresse oder Hostnamen für einen angegebenen Computer setzen."
 
-#: option.c:346
+#: option.c:358
 msgid "Read DHCP host specs from file."
 msgstr "DHCP-Host-Angaben aus Datei lesen."
 
-#: option.c:347
+#: option.c:359
 msgid "Read DHCP option specs from file."
 msgstr "DHCP-Optionen aus Datei lesen."
 
-#: option.c:348
+#: option.c:360
 msgid "Read DHCP host specs from a directory."
 msgstr "DHCP-Host-Angaben aus einem Verzeichnis lesen."
 
-#: option.c:349
+#: option.c:361
 msgid "Read DHCP options from a directory."
 msgstr "DHCP-Optionen aus einem Verzeichnis lesen."
 
-#: option.c:350
+#: option.c:362
 msgid "Evaluate conditional tag expression."
 msgstr "Auswertung eines Ausdrucks bedingter Marken."
 
-#: option.c:351
+#: option.c:363
 #, c-format
 msgid "Do NOT load %s file."
 msgstr "%s-Datei NICHT laden."
 
-#: option.c:352
+#: option.c:364
 #, c-format
 msgid "Specify a hosts file to be read in addition to %s."
 msgstr "Hosts-Datei festlegen, die zusätzlich zu %s gelesen wird."
 
-#: option.c:353
+#: option.c:365
 msgid "Read hosts files from a directory."
 msgstr "DHCP-Host-Dateien aus einem Verzeichnis lesen."
 
-#: option.c:354
+#: option.c:366
 msgid "Specify interface(s) to listen on."
 msgstr "Schnittstelle(n) zum Empfang festlegen."
 
-#: option.c:355
+#: option.c:367
 msgid "Specify interface(s) NOT to listen on."
 msgstr "Schnittstelle(n) festlegen, die NICHT empfangen sollen."
 
-#: option.c:356
+#: option.c:368
 msgid "Map DHCP user class to tag."
 msgstr "DHCP-Benutzerklasse auf Marke abbilden."
 
-#: option.c:357
+#: option.c:369
 msgid "Map RFC3046 circuit-id to tag."
 msgstr "RFC3046 \"circuit-id\" auf Marke abbilden."
 
-#: option.c:358
+#: option.c:370
 msgid "Map RFC3046 remote-id to tag."
 msgstr "RFC3046 \"remote-id\" auf Marke abbilden."
 
-#: option.c:359
+#: option.c:371
 msgid "Map RFC3993 subscriber-id to tag."
 msgstr "RFC3993 \"subscriber-id\" auf Marke abbilden."
 
-#: option.c:360
+#: option.c:372
 msgid "Don't do DHCP for hosts with tag set."
 msgstr "Kein DHCP für Hosts mit gesetzter Marke verwenden."
 
-#: option.c:361
+#: option.c:373
 msgid "Force broadcast replies for hosts with tag set."
 msgstr "Rundsendung für Hosts mit gesetzter Marke erzwingen."
 
-#: option.c:362
+#: option.c:374
 msgid "Do NOT fork into the background, do NOT run in debug mode."
 msgstr "NICHT in den Hintergrund wechseln, NICHT im Debug-Modus laufen."
 
-#: option.c:363
+#: option.c:375
 msgid "Assume we are the only DHCP server on the local network."
 msgstr "Voraussetzen, dass wir der einzige DHCP-Server im lokalen Netz sind."
 
-#: option.c:364
+#: option.c:376
 #, c-format
 msgid "Specify where to store DHCP leases (defaults to %s)."
 msgstr "Festlegen, wo DHCP-Leases gespeichert werden (Voreinstellung %s)."
 
-#: option.c:365
+#: option.c:377
 msgid "Return MX records for local hosts."
 msgstr "MX-Einträge für lokale Hosts liefern."
 
-#: option.c:366
+#: option.c:378
 msgid "Specify an MX record."
 msgstr "Einen MX-Eintrag festlegen."
 
-#: option.c:367
+#: option.c:379
 msgid "Specify BOOTP options to DHCP server."
 msgstr "BOOTP-Optionen für DHCP-Server festlegen."
 
-#: option.c:368
+#: option.c:380
 #, c-format
 msgid "Do NOT poll %s file, reload only on SIGHUP."
 msgstr "%s-Datei NICHT abfragen, nur bei SIGHUP neu laden."
 
-#: option.c:369
+#: option.c:381
 msgid "Do NOT cache failed search results."
 msgstr "Fehlerhafte Suchergebnisse NICHT zwischenspeichern."
 
-#: option.c:370
+#: option.c:382
 #, c-format
 msgid "Use nameservers strictly in the order given in %s."
 msgstr "Namensserver streng in der in %s angegebenen Reihenfolge verwenden."
 
-#: option.c:371
+#: option.c:383
 msgid "Specify options to be sent to DHCP clients."
 msgstr "Optionen festlegen, die an DHCP-Klienten gesendet werden."
 
-#: option.c:372
+#: option.c:384
 msgid "DHCP option sent even if the client does not request it."
 msgstr "DHCP-Option, die selbst ohne Klientenanfrage gesendet wird."
 
-#: option.c:373
+#: option.c:385
 msgid "Specify port to listen for DNS requests on (defaults to 53)."
 msgstr "Port zum Abhören der DNS-Anfragen festlegen (53 voreingestellt)."
 
-#: option.c:374
+#: option.c:386
 #, c-format
 msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
 msgstr "Maximale unterstützte UDP-Paketgröße für EDNS.0 (Voreinstellung %s)."
 
-#: option.c:375
+#: option.c:387
 msgid "Log DNS queries."
 msgstr "DNS-Anfragen protokollieren."
 
-#: option.c:376
+#: option.c:388
 msgid "Force the originating port for upstream DNS queries."
 msgstr "Ausgehenden Port erzwingen für DNS-Anfragen an vorgelagerte Server."
 
-#: option.c:377
+#: option.c:389
 msgid "Do NOT read resolv.conf."
 msgstr "resolv.conf NICHT lesen."
 
-#: option.c:378
+#: option.c:390
 #, c-format
 msgid "Specify path to resolv.conf (defaults to %s)."
 msgstr "Pfad zu resolv.conf festlegen (%s voreingestellt)."
 
-#: option.c:379
+#: option.c:391
 msgid "Specify path to file with server= options"
 msgstr " Dateipfad mit der Option server= angeben"
 
-#: option.c:380
+#: option.c:392
 msgid "Specify address(es) of upstream servers with optional domains."
 msgstr "Adresse(n) vorgelagerter Server festlegen, optional mit Domänen."
 
-#: option.c:381
+#: option.c:393
 msgid "Specify address of upstream servers for reverse address queries"
 msgstr "Adresse(n) vorgelagerter Server festlegen, für reverse Adressanfragen"
 
-#: option.c:382
+#: option.c:394
 msgid "Never forward queries to specified domains."
 msgstr "Anfragen für angegebene Domänen niemals weiterleiten."
 
-#: option.c:383
+#: option.c:395
 msgid "Specify the domain to be assigned in DHCP leases."
 msgstr "Domäne festlegen, die für DHCP-Leases zugewiesen wird."
 
-#: option.c:384
+#: option.c:396
 msgid "Specify default target in an MX record."
 msgstr "Voreingestelltes Ziel für MX-Einträge festlegen."
 
-#: option.c:385
+#: option.c:397
 msgid "Specify time-to-live in seconds for replies from /etc/hosts."
 msgstr "Gültigkeitsdauer für Antworten aus /etc/hosts festlegen."
 
-#: option.c:386
+#: option.c:398
 msgid "Specify time-to-live in seconds for negative caching."
 msgstr "Gültigkeitsdauer in Sekunden für Caching negativer Ergebnisse festlegen."
 
-#: option.c:387
+#: option.c:399
 msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
 msgstr "Gültigkeitsdauer in Sekunden für Caching negativer Ergebnisse festlegen."
 
-#: option.c:388
+#: option.c:400
 msgid "Specify time-to-live ceiling for cache."
 msgstr "Spezifiziere time-to-live ceiling für Cache."
 
-#: option.c:389
+#: option.c:401
 msgid "Specify time-to-live floor for cache."
 msgstr "Spezifiziere time-to-live floor für Cache."
 
-#: option.c:390
+#: option.c:402
 #, c-format
 msgid "Change to this user after startup. (defaults to %s)."
 msgstr "Nach dem Start diese Benutzerrechte annehmen (%s voreingestellt)."
 
-#: option.c:391
+#: option.c:403
 msgid "Map DHCP vendor class to tag."
 msgstr "DHCP-\"vendor class\" auf Marke abbilden."
 
-#: option.c:392
+#: option.c:404
 msgid "Display dnsmasq version and copyright information."
 msgstr "dnsmasq-Version und Urheberrecht anzeigen."
 
-#: option.c:393
+#: option.c:405
 msgid "Translate IPv4 addresses from upstream servers."
 msgstr "IPv4-Adressen von vorgelagerten Servern übersetzen."
 
-#: option.c:394
+#: option.c:406
 msgid "Specify a SRV record."
 msgstr "SRV-Eintrag festlegen."
 
-#: option.c:395
-msgid "Display this message. Use --help dhcp for known DHCP options."
-msgstr "Diese Hilfe anzeigen. Benutzen Sie --help dhcp für bekannte DHCP-Optionen."
+#: option.c:407
+msgid "Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."
+msgstr "Diese Hilfe anzeigen. Benutzen Sie --help dhcp oder --help dhcp6 für bekannte DHCP-Optionen."
 
-#: option.c:396
+#: option.c:408
 #, c-format
 msgid "Specify path of PID file (defaults to %s)."
 msgstr "Dateipfad für Prozesskennung (PID) festlegen (Voreinstellung: %s)."
 
-#: option.c:397
+#: option.c:409
 #, c-format
 msgid "Specify maximum number of DHCP leases (defaults to %s)."
 msgstr "Höchstzahl der DHCP-Leases festlegen (%s voreingestellt)."
 
-#: option.c:398
+#: option.c:410
 msgid "Answer DNS queries based on the interface a query was sent to."
 msgstr "DNS-Anfragen abhängig der Emfpangsschnittstelle beantworten."
 
-#: option.c:399
+#: option.c:411
 msgid "Specify TXT DNS record."
 msgstr "DNS-TXT-Eintrag festlegen."
 
-#: option.c:400
+#: option.c:412
 msgid "Specify PTR DNS record."
 msgstr "DNS-PTR-Eintrag festlegen."
 
-#: option.c:401
+#: option.c:413
 msgid "Give DNS name to IPv4 address of interface."
 msgstr "Schnittstellennamen zur IPv4-Adresse des Interfaces auflösen."
 
-#: option.c:402
+#: option.c:414
 msgid "Bind only to interfaces in use."
 msgstr "Nur an verwendete Schnittstellen binden."
 
-#: option.c:403
+#: option.c:415
 #, c-format
 msgid "Read DHCP static host information from %s."
 msgstr "Statische DHCP-Host-Information aus %s lesen."
 
-#: option.c:404
+#: option.c:416
 msgid "Enable the DBus interface for setting upstream servers, etc."
 msgstr "DBus-Schnittstelle zum Festlegen vorgelagerter Server usw. festlegen."
 
-#: option.c:405
+#: option.c:417
 msgid "Do not provide DHCP on this interface, only provide DNS."
 msgstr "Auf dieser Schnittstelle kein DHCP anbieten, sondern nur DNS."
 
-#: option.c:406
+#: option.c:418
 msgid "Enable dynamic address allocation for bootp."
 msgstr "Dynamische Adressbelegung für bootp einschalten."
 
-#: option.c:407
+#: option.c:419
 msgid "Map MAC address (with wildcards) to option set."
 msgstr "MAC-Adresse (mit Jokerzeichen) auf Netzmarke abbilden."
 
-#: option.c:408
+#: option.c:420
 msgid "Treat DHCP requests on aliases as arriving from interface."
 msgstr "DHCP-Anfragen von Alias-Schnittstellen für die Hauptschnittstelle beantworten."
 
-#: option.c:409
+#: option.c:421
 msgid "Disable ICMP echo address checking in the DHCP server."
 msgstr "ICMP-Echo-Adressprüfung im DHCP-Server abschalten."
 
-#: option.c:410
+#: option.c:422
 msgid "Shell script to run on DHCP lease creation and destruction."
 msgstr "Skript, das bei Erzeugung/Löschung einer DHCP-Lease laufen soll."
 
-#: option.c:411
+#: option.c:423
 msgid "Lua script to run on DHCP lease creation and destruction."
 msgstr "Lua-Skript, welches bei Erzeugung/Löschung eines DHCP-Leases laufen soll."
 
-#: option.c:412
+#: option.c:424
 msgid "Run lease-change scripts as this user."
 msgstr "Lease-Änderungs-Skript mit den Rechten dieses Nutzers ausführen."
 
-#: option.c:413
+#: option.c:425
+msgid "Call dhcp-script with changes to local ARP table."
+msgstr "Rufe dhcp-script mit Änderungen an der lokalen ARP-Tabelle auf."
+
+#: option.c:426
 msgid "Read configuration from all the files in this directory."
 msgstr "Konfiguration aus allen Dateien in diesem Verzeichnis lesen."
 
-#: option.c:414
+#: option.c:427
 msgid "Log to this syslog facility or file. (defaults to DAEMON)"
 msgstr "Für diese Syslog-Anlage oder in Datei loggen (Voreinstellung DAEMON)."
 
-#: option.c:415
+#: option.c:428
 msgid "Do not use leasefile."
 msgstr "Keine Lease-Datei benützen."
 
-#: option.c:416
+#: option.c:429
 #, c-format
 msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
 msgstr "Höchstzahl nebenläufiger DNS-Anfragen (%s voreingestellt)."
 
-#: option.c:417
+#: option.c:430
 #, c-format
 msgid "Clear DNS cache when reloading %s."
 msgstr "DNS-Cache beim Neuladen von %s löschen."
 
-#: option.c:418
+#: option.c:431
 msgid "Ignore hostnames provided by DHCP clients."
 msgstr "Von DHCP-Clients gelieferte Hostnamen ignorieren."
 
-#: option.c:419
+#: option.c:432
 msgid "Do NOT reuse filename and server fields for extra DHCP options."
 msgstr "Dateinamen und Server-Datenfehler für zusätzliche DHCP-Optionen NICHT wiederverwenden."
 
-#: option.c:420
+#: option.c:433
 msgid "Enable integrated read-only TFTP server."
 msgstr "Eingebauten Nur-Lese-TFTP-Server einschalten."
 
-#: option.c:421
+#: option.c:434
 msgid "Export files by TFTP only from the specified subtree."
 msgstr "Nur vom festgelegten Unterbaum Dateien per TFTP exportieren."
 
-#: option.c:422
-msgid "Add client IP address to tftp-root."
+#: option.c:435
+#, fuzzy
+msgid "Add client IP or hardware address to tftp-root."
 msgstr "IP-Adresse des Klienten an tftp-root anhängen."
 
-#: option.c:423
+#: option.c:436
 msgid "Allow access only to files owned by the user running dnsmasq."
 msgstr "Zugriff nur auf Dateien gestatten, die dem dnsmasq aufrufenden Benutzer gehören."
 
-#: option.c:424
+#: option.c:437
 msgid "Do not terminate the service if TFTP directories are inaccessible."
 msgstr "Der Dienst sollte nicht beendet werden, wenn die TFTP-Verzeichnisse nicht zugreifbar sind."
 
-#: option.c:425
-#, c-format
-msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+#: option.c:438
+#, fuzzy, c-format
+msgid "Maximum number of concurrent TFTP transfers (defaults to %s)."
 msgstr "Höchstzahl nebenläufiger TFTP-Übertragungen (%s voreingestellt)."
 
-#: option.c:426
+#: option.c:439
+msgid "Maximum MTU to use for TFTP transfers."
+msgstr "Maximale MTU für TFTP-Übertragungen erreicht."
+
+#: option.c:440
 msgid "Disable the TFTP blocksize extension."
 msgstr "TFTP-Blockgrößen-Erweiterung abschalten."
 
-#: option.c:427
+#: option.c:441
 msgid "Convert TFTP filenames to lowercase"
 msgstr "Konvertiere TFTP Dateinamen in Kleinschreibung"
 
-#: option.c:428
+#: option.c:442
 msgid "Ephemeral port range for use by TFTP transfers."
 msgstr "Bereich für vorübergehende Ports für TFTP-Übertragungen."
 
-#: option.c:429
+#: option.c:443
 msgid "Extra logging for DHCP."
 msgstr "Erweiterte DHCP-Protokollierung."
 
-#: option.c:430
+#: option.c:444
 msgid "Enable async. logging; optionally set queue length."
 msgstr "Asynchrone Protokollierung einschalten, opt. Warteschlangenlänge festlegen."
 
-#: option.c:431
+#: option.c:445
 msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
 msgstr "DNS-Rebinding unterbinden, private IP-Bereiche bei der Auflösung ausfiltern."
 
-#: option.c:432
+#: option.c:446
 msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
 msgstr "Auflösung zu 127.0.0.0/8 erlauben, für RBL-Server."
 
-#: option.c:433
+#: option.c:447
 msgid "Inhibit DNS-rebind protection on this domain."
 msgstr "DNS-Rebind-Schutz für diese Domäne sperren."
 
-#: option.c:434
+#: option.c:448
 msgid "Always perform DNS queries to all servers."
 msgstr "DNS-Anfragen immer an alle Server weiterleiten."
 
-#: option.c:435
+#: option.c:449
 msgid "Set tag if client includes matching option in request."
 msgstr "Marke setzen, wenn Klient eine entsprechende Option anfragt."
 
-#: option.c:436
+#: option.c:450
 msgid "Use alternative ports for DHCP."
 msgstr "Alternative Ports für DHCP verwenden."
 
-#: option.c:437
+#: option.c:451
 msgid "Specify NAPTR DNS record."
 msgstr "DNS-NAPTR-Eintrag festlegen."
 
-#: option.c:438
+#: option.c:452
 msgid "Specify lowest port available for DNS query transmission."
 msgstr "Niedrigsten verfügbaren Port für Übertragung von DNS-Anfragen festlegen."
 
-#: option.c:439
+#: option.c:453
+msgid "Specify highest port available for DNS query transmission."
+msgstr "Höchsten verfügbaren Port für Übertragung von DNS-Anfragen festlegen."
+
+#: option.c:454
 msgid "Use only fully qualified domain names for DHCP clients."
 msgstr "Für DHCP-Klienten nur vollständig bestimmte Domänennamen benutzen."
 
 # FIXME: probably typo in original message. -- MA
-#: option.c:440
+#: option.c:455
 msgid "Generate hostnames based on MAC address for nameless clients."
 msgstr "Generiere Hostnamen auf Basis der MAC-Adresse für namenlose Klienten."
 
-#: option.c:441
+#: option.c:456
 msgid "Use these DHCP relays as full proxies."
 msgstr "Diese DHCP-Relais als vollwertige Proxies verwenden."
 
-#: option.c:442
+#: option.c:457
 msgid "Relay DHCP requests to a remote server"
 msgstr "Leute DHCP Anfragen an entfernten Server weiter"
 
-#: option.c:443
+#: option.c:458
 msgid "Specify alias name for LOCAL DNS name."
 msgstr "Alias für LOKALEN DNS-Namen festlegen."
 
-#: option.c:444
+#: option.c:459
 msgid "Prompt to send to PXE clients."
 msgstr "Aufforderung, die an PXE-Klienten geschickt wird."
 
-#: option.c:445
+#: option.c:460
 msgid "Boot service for PXE menu."
 msgstr "Boot-Dienst für PXE-Menü."
 
-#: option.c:446
+#: option.c:461
 msgid "Check configuration syntax."
 msgstr "Konfigurationssyntax prüfen."
 
-#: option.c:447
+#: option.c:462
 msgid "Add requestor's MAC address to forwarded DNS queries."
-msgstr "Anfragende MAC-Adresse in die weiterleitende DNS-Anfrage einfügen"
+msgstr "Anfragende MAC-Adresse in die weiterleitende DNS-Anfrage einfügen."
 
-#: option.c:448
-msgid "Add requestor's IP subnet to forwarded DNS queries."
-msgstr "Füge das IP-Subnetz des Anfragenden in die weitergeleiteten DNS-Anfragen hinzu."
+#: option.c:463
+msgid "Add specified IP subnet to forwarded DNS queries."
+msgstr "Füge spezifiziertes IP-Subnetz an weitergeleiteten DNS-Anfragen hinzu."
 
-#: option.c:449
+#: option.c:464
+msgid "Add client identification to forwarded DNS queries."
+msgstr "Füge Klient Identifikationan weitergeleiteten DNS-Anfragen hinzu."
+
+#: option.c:465
 msgid "Proxy DNSSEC validation results from upstream nameservers."
 msgstr "Proxy-DNSSEC-Validierung-Ergebnisse von Upstream-Namensservern."
 
-#: option.c:450
+#: option.c:466
 msgid "Attempt to allocate sequential IP addresses to DHCP clients."
 msgstr "Versuche sequenzielle IP-Adressen an DHCP-Klienten zu vergeben."
 
-#: option.c:451
+#: option.c:467
 msgid "Copy connection-track mark from queries to upstream connections."
 msgstr "Kopiere \"connection-track mark\" von Anfragen nach Upstream-Verbindungen."
 
-#: option.c:452
+#: option.c:468
 msgid "Allow DHCP clients to do their own DDNS updates."
 msgstr "Erlaube DHCP-Klienten ihre eigenen DDNS-Updates durchzuführen."
 
-#: option.c:453
+#: option.c:469
 msgid "Send router-advertisements for interfaces doing DHCPv6"
 msgstr "Sende \"Router-Advertisments\" für Netzwerkschnittstellen, welche DHCPv6 nutzen"
 
-#: option.c:454
+#: option.c:470
 msgid "Specify DUID_EN-type DHCPv6 server DUID"
 msgstr "Spezifiziere DUID_EN-type DHCPv6 Server DUID"
 
-#: option.c:455
+#: option.c:471
 msgid "Specify host (A/AAAA and PTR) records"
 msgstr "Spezifiziere Host (A/AAAA und PTR) Einträge"
 
-#: option.c:456
+#: option.c:472
 msgid "Specify arbitrary DNS resource record"
 msgstr "Spezifiziere einen beliebiegen DNS Eintrag"
 
-#: option.c:457
+#: option.c:473
 msgid "Bind to interfaces in use - check for new interfaces"
 msgstr "Bindung zu Schnittstellen in Benutzung - prüfe auf neue Schnittstellen"
 
-#: option.c:458
+#: option.c:474
 msgid "Export local names to global DNS"
 msgstr "Exportiere lokale Namen in das globale DNS"
 
-#: option.c:459
+#: option.c:475
 msgid "Domain to export to global DNS"
 msgstr "Domain für das Exportieren des globalen DNS"
 
-#: option.c:460
+#: option.c:476
 msgid "Set TTL for authoritative replies"
 msgstr "Setzte TTL für autoritative Antworten"
 
-#: option.c:461
-msgid "Set authoritive zone information"
+#: option.c:477
+#, fuzzy
+msgid "Set authoritative zone information"
 msgstr "Setze autoritative Zoneninformationen"
 
-#: option.c:462
+#: option.c:478
 msgid "Secondary authoritative nameservers for forward domains"
 msgstr "Sekundärer autoritativer Nameserver für weitergeleitete Domains"
 
-#: option.c:463
+#: option.c:479
 msgid "Peers which are allowed to do zone transfer"
 msgstr "Peers welche einen Zonentransfer durchführen dürfen"
 
-#: option.c:464
+#: option.c:480
 msgid "Specify ipsets to which matching domains should be added"
 msgstr "Spezifiziere IPSets zu welcher passende Domains hinzugefügt werden sollen"
 
-#: option.c:465
+#: option.c:481
 msgid "Specify a domain and address range for synthesised names"
 msgstr "Spezifiziere eine Domain und Adressbereich für synthetisierte Namen"
 
-#: option.c:466
+#: option.c:482
 msgid "Activate DNSSEC validation"
 msgstr "Aktiviere DNSSEC-Validierung"
 
-#: option.c:467
+#: option.c:483
 msgid "Specify trust anchor key digest."
 msgstr "Spezifiziere Vertrauensursprung (Trust Anchor) der Schlüssel-Prüfdaten (Key Digest)."
 
-#: option.c:468
+#: option.c:484
 msgid "Disable upstream checking for DNSSEC debugging."
-msgstr "Deaktiviere die Überprüfung vorgelagerter Server für DNSSEC-Debugging"
+msgstr "Deaktiviere die Überprüfung vorgelagerter Server für DNSSEC-Debugging."
 
-#: option.c:469
+#: option.c:485
 msgid "Ensure answers without DNSSEC are in unsigned zones."
 msgstr "Stellt sicher, dass Antworten ohne DNSSEC sich in einer unsignierten Zone befinden."
 
-#: option.c:470
+#: option.c:486
 msgid "Don't check DNSSEC signature timestamps until first cache-reload"
 msgstr "DNSSEC Signatur-Zeitstempel nicht prüfen, bis erstmalig der Cache neugeladen wird"
 
-#: option.c:471
+#: option.c:487
 msgid "Timestamp file to verify system clock for DNSSEC"
 msgstr "Zeitstempel-Datei für die Verifizierung der Systemuhrzeit für DNSSEC"
 
-#: option.c:473
+#: option.c:489
 msgid "Specify DHCPv6 prefix class"
 msgstr "Spezifiziere DHCPv6 Prefix Klasse"
 
-#: option.c:475
-msgid "Set priority, resend-interval and router-lifetime"
+#: option.c:491
+#, fuzzy
+msgid "Set MTU, priority, resend-interval and router-lifetime"
 msgstr "Setze Priorität, Intervall des erneuten Sendens und Router Lebenszeit"
 
-#: option.c:476
+#: option.c:492
 msgid "Do not log routine DHCP."
 msgstr "Protokolliere kein DHCP."
 
-#: option.c:477
+#: option.c:493
 msgid "Do not log routine DHCPv6."
 msgstr "Protokolliere kein DHCPv6."
 
-#: option.c:478
+#: option.c:494
 msgid "Do not log RA."
 msgstr "RA nicht protokollieren."
 
-#: option.c:479
-msgid "Accept queries only from directly-connected networks"
-msgstr "Akzeptiere nur Anfragen von direkt verbundenen Netzwerken"
+#: option.c:495
+msgid "Accept queries only from directly-connected networks."
+msgstr "Akzeptiere nur Anfragen von direkt verbundenen Netzwerken."
 
-#: option.c:480
-msgid "Detect and remove DNS forwarding loops"
-msgstr "Erkennen und Entfernen von DNS-Weiterleitungsschleifen"
+#: option.c:496
+msgid "Detect and remove DNS forwarding loops."
+msgstr "Erkennen und Entfernen von DNS-Weiterleitungsschleifen."
 
-#: option.c:481
+#: option.c:497
 msgid "Ignore DNS responses containing ipaddr."
 msgstr "Ignoriere DNS-Antworten, welche ipaddr enthalten."
 
-#: option.c:683
+#: option.c:498
+msgid "Set TTL in DNS responses with DHCP-derived addresses."
+msgstr "Setzte TTL in DNS-Antworten mit DHCP-abgeleiteten Adressen."
+
+#: option.c:499
+msgid "Delay DHCP replies for at least number of seconds."
+msgstr ""
+
+#: option.c:703
 #, c-format
 msgid ""
 "Usage: dnsmasq [options]\n"
@@ -742,312 +769,320 @@ msgstr ""
 "Verwendung: dnsmasq [Optionen]\n"
 "\n"
 
-#: option.c:685
+#: option.c:705
 #, c-format
 msgid "Use short options only on the command line.\n"
 msgstr "Auf der Befehlszeile nur kurze Optionen verwenden!\n"
 
-#: option.c:687
+#: option.c:707
 #, c-format
 msgid "Valid options are:\n"
 msgstr "Gültige Optionen sind:\n"
 
-#: option.c:744 option.c:748
+#: option.c:754 option.c:868
+msgid "bad address"
+msgstr "Fehlerhafte Adresse."
+
+#: option.c:779 option.c:783
 msgid "bad port"
 msgstr "unzulässiger Port"
 
-#: option.c:775 option.c:807
+#: option.c:797 option.c:826 option.c:861
 msgid "interface binding not supported"
 msgstr "Schnittstellenbindung nicht unterstützt"
 
-#: option.c:784 option.c:3575
+#: option.c:821 option.c:856
+msgid "interface can only be specified once"
+msgstr ""
+
+#: option.c:835 option.c:3809
 msgid "bad interface name"
 msgstr "unzulässiger Schnittestellenname"
 
-#: option.c:814
-msgid "bad address"
-msgstr "Fehlerhafte Adresse"
-
-#: option.c:996
+#: option.c:1062
 msgid "unsupported encapsulation for IPv6 option"
 msgstr "Nicht unterstützte Verkapselung für eine IPv6-Option"
 
-#: option.c:1010
+#: option.c:1076
 msgid "bad dhcp-option"
 msgstr "Fehlerhafte DHCP-Option"
 
-#: option.c:1078
+#: option.c:1144
 msgid "bad IP address"
 msgstr "Fehlerhafte IP-Adresse"
 
-#: option.c:1081 option.c:1219 option.c:2893
+#: option.c:1147 option.c:1286 option.c:3079
 msgid "bad IPv6 address"
 msgstr "Fehlerhafte IPv6-Adresse"
 
-#: option.c:1246 option.c:1340
+#: option.c:1240
+msgid "bad IPv4 address"
+msgstr "Fehlerhafte IPv4-Adresse"
+
+#: option.c:1313 option.c:1407
 msgid "bad domain in dhcp-option"
 msgstr "Fehlerhafte Domäne in DHCP-Option"
 
-#: option.c:1378
+#: option.c:1445
 msgid "dhcp-option too long"
 msgstr "DHCP-Option zu lang"
 
-#: option.c:1385
+#: option.c:1452
 msgid "illegal dhcp-match"
 msgstr "Unzulässige dhcp-match-Option"
 
-#: option.c:1447
+#: option.c:1514
 msgid "illegal repeated flag"
 msgstr "unzulässig wiederholte Markierung"
 
-#: option.c:1455
+#: option.c:1522
 msgid "illegal repeated keyword"
 msgstr "unzulässig wiederholtes Schlüsselwort"
 
-#: option.c:1520 option.c:4191
+#: option.c:1593 option.c:4443
 #, c-format
 msgid "cannot access directory %s: %s"
 msgstr "Kann auf Verzeichnis %s nicht zugreifen: %s"
 
-#: option.c:1566 tftp.c:493
+#: option.c:1639 tftp.c:537
 #, c-format
 msgid "cannot access %s: %s"
 msgstr "Kann auf %s nicht zugreifen: %s"
 
-#: option.c:1618
+#: option.c:1727
 msgid "setting log facility is not possible under Android"
 msgstr "Die Einstellung Protokolliereinrichtung kann unter Android nicht gesetzt werden"
 
-#: option.c:1627
+#: option.c:1736
 msgid "bad log facility"
 msgstr "Falsche Protokolliereinrichtung"
 
-#: option.c:1680
+#: option.c:1789
 msgid "bad MX preference"
 msgstr "unzulässige MX-Präferenz-Angabe"
 
-#: option.c:1685
+#: option.c:1794
 msgid "bad MX name"
 msgstr "unzulässiger MX-Name"
 
-#: option.c:1699
+#: option.c:1808
 msgid "bad MX target"
 msgstr "unzulässiges MX-Ziel"
 
-#: option.c:1711
+#: option.c:1820
 msgid "cannot run scripts under uClinux"
 msgstr "unter uClinux ist die Skriptausführung nicht möglich"
 
-#: option.c:1713
+#: option.c:1822
 msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
 msgstr "Neuübersetzung mit HAVE_SCRIPT nötig, um Lease-Änderungs-Skripte auszuführen"
 
-#: option.c:1717
+#: option.c:1826
 msgid "recompile with HAVE_LUASCRIPT defined to enable Lua scripts"
-msgstr "Um Benutzerdefinierte Lua-Scripte zu ermöglichen, muss mit HAVE_LUASCRIPT neu kompiliert werden"
+msgstr "Um Benutzerdefinierte Lua-Skripte zu ermöglichen, muss mit HAVE_LUASCRIPT neu kompiliert werden"
 
-#: option.c:1973 option.c:2018 option.c:2074
+#: option.c:2095 option.c:2106 option.c:2143 option.c:2199 option.c:2482
 msgid "bad prefix"
 msgstr "unzulässiger Präfix"
 
-#: option.c:2355
+#: option.c:2504
 msgid "recompile with HAVE_IPSET defined to enable ipset directives"
 msgstr "Um IPSet-Direktiven zu aktivieren, muss mit HAVE_IPSET neu übersetzt werden"
 
-#: option.c:2548
+#: option.c:2713
 msgid "bad port range"
 msgstr "unzulässiger Portbereich"
 
-#: option.c:2564
+#: option.c:2739
 msgid "bad bridge-interface"
 msgstr "unzulässige Brücken-Schnittstelle"
 
-#: option.c:2624
+#: option.c:2807
 msgid "only one tag allowed"
 msgstr "nur eine Marke zulässig"
 
-#: option.c:2644 option.c:2656 option.c:2764 option.c:2805
+#: option.c:2827 option.c:2839 option.c:2948 option.c:2953 option.c:2992
 msgid "bad dhcp-range"
 msgstr "unzulässiger DHCP-Bereich"
 
-#: option.c:2671
+#: option.c:2854
 msgid "inconsistent DHCP range"
 msgstr "inkonsistenter DHCP-Bereich"
 
-#: option.c:2732
+#: option.c:2916
 msgid "prefix length must be exactly 64 for RA subnets"
 msgstr "Die Präfixlenge muss genau 64 für RA Subnetze sein"
 
-#: option.c:2734
+#: option.c:2918
 msgid "prefix length must be exactly 64 for subnet constructors"
 msgstr "Die Präfixlenge muss genau 64 für Subnet Konstruktoren sein"
 
-#: option.c:2738
+#: option.c:2922
 msgid "prefix length must be at least 64"
 msgstr "Die Präfixlänge muss mindestens 64 sein"
 
-#: option.c:2741
+#: option.c:2925
 msgid "inconsistent DHCPv6 range"
 msgstr "Inkonsistenter DHCPv6-Bereich"
 
-#: option.c:2752
+#: option.c:2936
 msgid "prefix must be zero with \"constructor:\" argument"
 msgstr "Prefix muss mit dem \"constructor:\" Argument Null sein"
 
-#: option.c:2863 option.c:2911
+#: option.c:3049 option.c:3097
 msgid "bad hex constant"
 msgstr "Falscher Hexwert"
 
-#: option.c:2885
+#: option.c:3071
 msgid "cannot match tags in --dhcp-host"
 msgstr "Kann die Tags in --dhcp-host nicht abgleichen"
 
-#: option.c:2933
+#: option.c:3119
 #, c-format
 msgid "duplicate dhcp-host IP address %s"
 msgstr "doppelte dhcp-host IP-Adresse %s"
 
-#: option.c:2991
+#: option.c:3177
 msgid "bad DHCP host name"
 msgstr "unzulässiger DHCP-Hostname"
 
-#: option.c:3073
+#: option.c:3259
 msgid "bad tag-if"
 msgstr "unzulässige bedingte Marke (tag-if)"
 
-#: option.c:3397 option.c:3791
+#: option.c:3616 option.c:4039
 msgid "invalid port number"
 msgstr "unzulässige Portnummer"
 
-#: option.c:3459
+#: option.c:3678
 msgid "bad dhcp-proxy address"
 msgstr "Fehlerhafte DHCP-Proxy-Adresse"
 
-#: option.c:3485
+#: option.c:3704
 msgid "Bad dhcp-relay"
 msgstr "unzulässiger dhcp-relay"
 
-#: option.c:3511
+#: option.c:3745
 msgid "bad RA-params"
 msgstr "unzulässige RA-Parameter"
 
-#: option.c:3520
+#: option.c:3754
 msgid "bad DUID"
 msgstr "unzulässige DUID"
 
-#: option.c:3562
+#: option.c:3796
 msgid "invalid alias range"
 msgstr "unzulässiger Alias-Bereich"
 
-#: option.c:3616
+#: option.c:3850 option.c:3862
 msgid "bad CNAME"
 msgstr "unzulässiger CNAME"
 
-#: option.c:3621
+#: option.c:3866
 msgid "duplicate CNAME"
 msgstr "doppelter CNAME"
 
-#: option.c:3641
+#: option.c:3889
 msgid "bad PTR record"
 msgstr "unzulässiger PTR-Eintrag"
 
-#: option.c:3672
+#: option.c:3920
 msgid "bad NAPTR record"
 msgstr "unzulässiger NAPTR-Eintrag"
 
-#: option.c:3706
+#: option.c:3954
 msgid "bad RR record"
 msgstr "unzulässiger RR-Eintrag"
 
-#: option.c:3736
+#: option.c:3984
 msgid "bad TXT record"
 msgstr "unzulässiger TXT-Eintrag"
 
-#: option.c:3777
+#: option.c:4025
 msgid "bad SRV record"
 msgstr "unzulässiger SRV-Eintrag"
 
-#: option.c:3784
+#: option.c:4032
 msgid "bad SRV target"
 msgstr "unzulässiges SRV-Ziel"
 
-#: option.c:3798
+#: option.c:4046
 msgid "invalid priority"
 msgstr "unzulässige Priorität"
 
-#: option.c:3805
+#: option.c:4049
 msgid "invalid weight"
 msgstr "unzulässige Wichtung"
 
-#: option.c:3829
+#: option.c:4073
 msgid "Bad host-record"
 msgstr "unzulässiger host-record"
 
-#: option.c:3846
+#: option.c:4097
 msgid "Bad name in host-record"
 msgstr "Unzulässiger Name in host-record"
 
-#: option.c:3911
+#: option.c:4162
 msgid "bad trust anchor"
 msgstr "unzulässiger Vertrauensursprung (Trust Anchor)"
 
-#: option.c:3925
+#: option.c:4176
 msgid "bad HEX in trust anchor"
 msgstr "unzulässiger Hexwert in Vertrauensursprung (Trust Anchor)"
 
-#: option.c:3935
+#: option.c:4186
 msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"
 msgstr "Nicht unterstützte Option (prüfen Sie, ob DNSMasq mit DHCP/TFTP/DNSSEC/DBus-Unterstützung übersetzt wurde)"
 
-#: option.c:3994
+#: option.c:4246
 msgid "missing \""
 msgstr "fehlende \\\""
 
-#: option.c:4051
+#: option.c:4303
 msgid "bad option"
 msgstr "unzulässige Option"
 
-#: option.c:4053
+#: option.c:4305
 msgid "extraneous parameter"
 msgstr "überschüssiger Parameter"
 
-#: option.c:4055
+#: option.c:4307
 msgid "missing parameter"
 msgstr "fehler Parameter"
 
-#: option.c:4057
+#: option.c:4309
 msgid "illegal option"
 msgstr "unzulässige Option"
 
-#: option.c:4064
+#: option.c:4316
 msgid "error"
 msgstr "Fehler"
 
-#: option.c:4066
+#: option.c:4318
 #, c-format
 msgid " at line %d of %s"
 msgstr " in Zeile %d von %s"
 
-#: option.c:4081 option.c:4328 option.c:4364
+#: option.c:4333 option.c:4580 option.c:4616
 #, c-format
 msgid "read %s"
 msgstr "%s gelesen"
 
-#: option.c:4144 option.c:4267 tftp.c:667
+#: option.c:4396 option.c:4519 tftp.c:715
 #, c-format
 msgid "cannot read %s: %s"
 msgstr "kann %s nicht lesen: %s"
 
-#: option.c:4430
+#: option.c:4688
 msgid "junk found in command line"
 msgstr "Mist in der Kommandozeile gefunden"
 
-#: option.c:4465
+#: option.c:4729
 #, c-format
 msgid "Dnsmasq version %s  %s\n"
 msgstr "Dnsmasq Version %s  %s\n"
 
-#: option.c:4466
+#: option.c:4730
 #, c-format
 msgid ""
 "Compile time options: %s\n"
@@ -1056,462 +1091,505 @@ msgstr ""
 "Kompilierungs-Optionen %s\n"
 "\n"
 
-#: option.c:4467
+#: option.c:4731
 #, c-format
 msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
 msgstr "Für diese Software wird ABSOLUT KEINE GARANTIE gewährt.\n"
 
 # FIXME: this must be one long string! -- MA
-#: option.c:4468
+#: option.c:4732
 #, c-format
 msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
 msgstr "Dnsmasq ist freie Software, und du bist willkommen es weiter zu verteilen\n"
 
-#: option.c:4469
+#: option.c:4733
 #, c-format
 msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
 msgstr "unter den Bedingungen der GNU General Public Lizenz, Version 2 oder 3.\n"
 
-#: option.c:4480
+#: option.c:4744
 msgid "try --help"
 msgstr "versuchen Sie --help"
 
-#: option.c:4482
+#: option.c:4746
 msgid "try -w"
 msgstr "versuchen Sie -w"
 
-#: option.c:4484
+#: option.c:4748
 #, c-format
 msgid "bad command line options: %s"
 msgstr "unzulässige Optionen auf der Befehlszeile: %s"
 
-#: option.c:4544
+#: option.c:4818
+#, c-format
+msgid "CNAME loop involving %s"
+msgstr ""
+
+#: option.c:4854
 #, c-format
 msgid "cannot get host-name: %s"
 msgstr "kann Hostnamen nicht ermitteln: %s"
 
-#: option.c:4572
+#: option.c:4882
 msgid "only one resolv.conf file allowed in no-poll mode."
 msgstr "mit -n/--no-poll ist nur eine resolv.conf-Datei zulässig."
 
-#: option.c:4582
+#: option.c:4892
 msgid "must have exactly one resolv.conf to read domain from."
 msgstr "Um die Domäne zu lesen, muss genau eine resolv.conf-Datei verwendet werden."
 
-#: option.c:4585 network.c:1507 dhcp.c:777
+#: option.c:4895 network.c:1623 dhcp.c:816
 #, c-format
 msgid "failed to read %s: %s"
 msgstr "konnte %s nicht lesen: %s"
 
-#: option.c:4602
+#: option.c:4912
 #, c-format
 msgid "no search directive found in %s"
 msgstr "keine \"search\"-Anweisung in %s gefunden"
 
-#: option.c:4623
+#: option.c:4933
 msgid "there must be a default domain when --dhcp-fqdn is set"
 msgstr "Es muss eine standard Domain gesetzt sein, wenn --dhcp-fqdn gesetzt ist"
 
-#: option.c:4632
+#: option.c:4942
 msgid "syntax check OK"
 msgstr "Syntaxprüfung OK"
 
-#: forward.c:111
+#: forward.c:102
 #, c-format
 msgid "failed to send packet: %s"
 msgstr "Fehlgeschlagen, folgendes Paket zu senden: %s"
 
-#: forward.c:591
+#: forward.c:598
 msgid "discarding DNS reply: subnet option mismatch"
 msgstr "Verwerfe DNS Antwort: Subnetoption stimmt nicht überrein"
 
-#: forward.c:614
+#: forward.c:652
 #, c-format
 msgid "nameserver %s refused to do a recursive query"
 msgstr "Namensserver %s hat eine rekursive Anfrage verweigert"
 
-#: forward.c:646
+#: forward.c:684
 #, c-format
 msgid "possible DNS-rebind attack detected: %s"
 msgstr "möglichen DNS-Rebind-Angriff entdeckt: %s"
 
-#: forward.c:1209 forward.c:1785
+#: forward.c:870
+#, c-format
+msgid "reducing DNS packet size for nameserver %s to %d"
+msgstr ""
+
+#: forward.c:1266 forward.c:1704
 msgid "Ignoring query from non-local network"
 msgstr "Ignoriere Anfragen vom nicht lokalen Netzwerk"
 
-#: forward.c:2256
+#: forward.c:2184
 #, c-format
 msgid "Maximum number of concurrent DNS queries reached (max: %d)"
 msgstr "Maximale Anzahl an nebenläufiger DNS-Anfragen erreicht (Max: %d)"
 
-#: network.c:715
+#: network.c:720
 #, c-format
 msgid "failed to create listening socket for %s: %s"
 msgstr "Konnte Empfangs-Socket für %s: %s nicht erzeugen"
 
-#: network.c:1021
+#: network.c:1031
 #, c-format
 msgid "LOUD WARNING: listening on %s may accept requests via interfaces other than %s"
 msgstr "LOUD WARNING: Das Abhören von %s kann die Anfragen auf der Schnittstelle akzeptieren anders als %s"
 
-#: network.c:1028
+#: network.c:1038
 msgid "LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"
 msgstr "LOUD WARNING: Es sollte --bind-dynamic anstatt --bind-interfaces benutzt werden, um DNS-Verstärkungsangriffe auf diesen Schnittstellen zu unterbinden"
 
-#: network.c:1037
+#: network.c:1047
+#, fuzzy, c-format
+msgid "warning: using interface %s instead"
+msgstr "Warnung: %s nicht zugreifbar"
+
+#: network.c:1056
 #, c-format
 msgid "warning: no addresses found for interface %s"
 msgstr "Warnung: Keine Adresse für die Schnittstelle %s gefunden"
 
-#: network.c:1095
+#: network.c:1114
 #, c-format
 msgid "interface %s failed to join DHCPv6 multicast group: %s"
 msgstr "Schnittstelle %s konnte DHCPv6-Multicast-Gruppe nicht beitreten: %s"
 
-#: network.c:1289
+#: network.c:1119
+msgid "try increasing /proc/sys/net/core/optmem_max"
+msgstr "Versuche /proc/sys/net/core/optmem_max zu erhöhen"
+
+#: network.c:1337
 #, c-format
 msgid "failed to bind server socket for %s: %s"
 msgstr "konnte nicht an Server-Socket für %s binden: %s"
 
-#: network.c:1445
+#: network.c:1528
 #, c-format
 msgid "ignoring nameserver %s - local interface"
 msgstr "ignoriere Namensserver %s - lokale Schnittstelle"
 
-#: network.c:1456
+#: network.c:1539
 #, c-format
 msgid "ignoring nameserver %s - cannot make/bind socket: %s"
 msgstr "ignoriere Namensserver %s - kann Socket nicht erzeugen/binden: %s"
 
+#: network.c:1559
+msgid "(no DNSSEC)"
+msgstr "(kein DNSSEC)"
+
 # FIXME: this isn't translatable - always provide full strings, do not assemble yourself! -- MA
-#: network.c:1469
+#: network.c:1562
 msgid "unqualified"
 msgstr "unqualifiziert"
 
-#: network.c:1469
+#: network.c:1562
 msgid "names"
 msgstr "Namen"
 
-#: network.c:1471
+#: network.c:1564
 msgid "default"
 msgstr "Standard"
 
-#: network.c:1473
+#: network.c:1566
 msgid "domain"
 msgstr "Domain"
 
-#: network.c:1476
+#: network.c:1572
 #, c-format
 msgid "using local addresses only for %s %s"
 msgstr "Benutze lokale Adressen nur für %s %s"
 
-#: network.c:1478
+#: network.c:1575
 #, c-format
 msgid "using standard nameservers for %s %s"
 msgstr "Benutze standard Namensserver für %s %s"
 
-#: network.c:1480
+#: network.c:1577
 #, c-format
-msgid "using nameserver %s#%d for %s %s"
-msgstr "Benutze Namensserver %s#%d für %s %s"
+msgid "using nameserver %s#%d for %s %s %s"
+msgstr "Benutze Namensserver %s#%d für %s %s %s"
 
-#: network.c:1484
+#: network.c:1581
 #, c-format
 msgid "NOT using nameserver %s#%d - query loop detected"
 msgstr "Benutze Namensserver %s#%d NICHT - Anfragenschleife festgetellt"
 
-#: network.c:1487
+#: network.c:1584
 #, c-format
 msgid "using nameserver %s#%d(via %s)"
 msgstr "Benutze Namensserver %s#%d(via %s)"
 
-#: network.c:1489
+#: network.c:1586
 #, c-format
 msgid "using nameserver %s#%d"
 msgstr "Benutze Namensserver %s#%d"
 
-#: dnsmasq.c:163
+#: network.c:1591
+#, fuzzy, c-format
+msgid "using %d more local addresses"
+msgstr "Benutze %d mehr Namensserver"
+
+#: network.c:1593
+#, c-format
+msgid "using %d more nameservers"
+msgstr "Benutze %d mehr Namensserver"
+
+#: dnsmasq.c:171
 msgid "dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"
 msgstr "dhcp-hostsdir, dhcp-optsdir und hostsdir sind auf dieser Plattform nicht unterstüzt"
 
-#: dnsmasq.c:170
-msgid "no trust anchors provided for DNSSEC"
-msgstr "Keine Vertrauensursprünge (Trust Anchor) für DNSSEC verfügbar"
+#: dnsmasq.c:186
+msgid "no root trust anchor provided for DNSSEC"
+msgstr "Keine Root-Vertrauensursprünge (Root Trust Anchor) für DNSSEC verfügbar"
 
-#: dnsmasq.c:173
+#: dnsmasq.c:189
 msgid "cannot reduce cache size from default when DNSSEC enabled"
 msgstr "Kann die Standard Cachegröße nicht verkleinern, wenn DNSSEC aktiviert ist"
 
-#: dnsmasq.c:175
+#: dnsmasq.c:191
 msgid "DNSSEC not available: set HAVE_DNSSEC in src/config.h"
 msgstr "DNSSEC nicht verfügbar: setzen Sie HAVE_DNSSEC in src/config.h"
 
-#: dnsmasq.c:181
+#: dnsmasq.c:197
 msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
 msgstr "TFTP-Server nicht verfügbar, setzen Sie HAVE_TFTP in src/config.h"
 
-#: dnsmasq.c:186
+#: dnsmasq.c:202
 msgid "cannot use --conntrack AND --query-port"
 msgstr "Kann nicht --conntrack UND --query-port einsetzen"
 
-#: dnsmasq.c:189
+#: dnsmasq.c:205
 msgid "conntrack support not available: set HAVE_CONNTRACK in src/config.h"
 msgstr "Conntrack-Unterstützung nicht verfügbar: Aktiviere HAVE_CONNTRACK in src/config.h"
 
-#: dnsmasq.c:194
-msgid "asychronous logging is not available under Solaris"
+#: dnsmasq.c:210
+msgid "asynchronous logging is not available under Solaris"
 msgstr "asynchrone Protokollierung unter Solaris nicht verfügbar"
 
-#: dnsmasq.c:199
-msgid "asychronous logging is not available under Android"
+#: dnsmasq.c:215
+msgid "asynchronous logging is not available under Android"
 msgstr "Asynchrone Protokollierung unter Android nicht verfügbar"
 
-#: dnsmasq.c:204
+#: dnsmasq.c:220
 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:209
+#: dnsmasq.c:225
 msgid "loop detection not available: set HAVE_LOOP in src/config.h"
 msgstr "Loop-Erkennung nicht verfügbar, Aktiviere HAVE_LOOP in src/config.h"
 
-#: dnsmasq.c:217
+#: dnsmasq.c:229
+msgid "max_port cannot be smaller than min_port"
+msgstr "max_port darf nicht kleiner als min_port sein"
+
+#: dnsmasq.c:236
 msgid "zone serial must be configured in --auth-soa"
 msgstr "Zonen Seriennummer muss mit --auth-soa konfiguriert werden"
 
-#: dnsmasq.c:235
+#: dnsmasq.c:254
 msgid "dhcp-range constructor not available on this platform"
 msgstr "dhcp-range Konstruktor ist auf dieser Plattform nicht verfübar"
 
-#: dnsmasq.c:278
+#: dnsmasq.c:300
 msgid "cannot set --bind-interfaces and --bind-dynamic"
 msgstr "Kann nicht --bind-interfaces und --bind-dynamic setzen"
 
-#: dnsmasq.c:281
+#: dnsmasq.c:303
 #, c-format
 msgid "failed to find list of interfaces: %s"
 msgstr "konnte Schnitstellenliste nicht beziehen: %s"
 
-#: dnsmasq.c:290
+#: dnsmasq.c:312
 #, c-format
 msgid "unknown interface %s"
 msgstr "unbekannte Schnittstelle %s"
 
-#: dnsmasq.c:354 dnsmasq.c:1037
+#: dnsmasq.c:377 dnsmasq.c:1054
 #, c-format
 msgid "DBus error: %s"
 msgstr "DBus-Fehler: %s"
 
-#: dnsmasq.c:357
+#: dnsmasq.c:380
 msgid "DBus not available: set HAVE_DBUS in src/config.h"
 msgstr "DBus nicht verfügbar: setzen Sie HAVE_DBUS in src/config.h"
 
-#: dnsmasq.c:385
+#: dnsmasq.c:410
 #, c-format
 msgid "unknown user or group: %s"
 msgstr "Unbekannter Benutzer oder Gruppe: %s"
 
-#: dnsmasq.c:440
+#: dnsmasq.c:465
 #, c-format
 msgid "cannot chdir to filesystem root: %s"
 msgstr "kann nicht ins Wurzelverzeichnis des Dateisystems wechseln: %s"
 
 # FIXME: this and the next would need commas after the version
-#: dnsmasq.c:692
+#: dnsmasq.c:730
 #, c-format
 msgid "started, version %s DNS disabled"
 msgstr "gestartet, Version %s, DNS abgeschaltet"
 
-#: dnsmasq.c:694
+#: dnsmasq.c:734
 #, c-format
 msgid "started, version %s cachesize %d"
 msgstr "gestartet, Version %s, Cachegröße %d"
 
-#: dnsmasq.c:696
+#: dnsmasq.c:736
 #, c-format
 msgid "started, version %s cache disabled"
 msgstr "Gestartet, Version %s Cache deaktiviert"
 
-#: dnsmasq.c:698
+#: dnsmasq.c:739
+msgid "DNS service limited to local subnets"
+msgstr "DNS-Dienst auf lokale Subnetze eingeschränkt"
+
+#: dnsmasq.c:742
 #, c-format
 msgid "compile time options: %s"
 msgstr "Übersetzungsoptionen: %s"
 
-#: dnsmasq.c:704
+#: dnsmasq.c:751
 msgid "DBus support enabled: connected to system bus"
 msgstr "DBus-Unterstützung eingeschaltet: mit Systembus verbunden"
 
-#: dnsmasq.c:706
+#: dnsmasq.c:753
 msgid "DBus support enabled: bus connection pending"
 msgstr "DBus-Unterstützung eingeschaltet: warte auf Systembus-Verbindung"
 
-#: dnsmasq.c:711
-msgid "DNS service limited to local subnets"
-msgstr "DNS-Dienst auf lokale Subnetze eingeschränkt"
-
-#: dnsmasq.c:727
+#: dnsmasq.c:771
 msgid "DNSSEC validation enabled"
 msgstr "DNSSEC-Validierung aktiviert"
 
-#: dnsmasq.c:730
-msgid "DNSSEC signature timestamps not checked until first cache reload"
+#: dnsmasq.c:775
+#, fuzzy
+msgid "DNSSEC signature timestamps not checked until receipt of SIGINT"
 msgstr "DNSSEC Signatur-Zeitstempel werden erst ab dem ersten Neuladen des Caches überprüft"
 
-#: dnsmasq.c:733
+#: dnsmasq.c:778
 msgid "DNSSEC signature timestamps not checked until system time valid"
 msgstr "DNSSEC Signatur-Zeitstempel werden erst überprüft, sobald die Systemuhrzeit gültig ist"
 
-#: dnsmasq.c:738
+#: dnsmasq.c:783
 #, c-format
 msgid "warning: failed to change owner of %s: %s"
 msgstr "Warnung: konnte den Besitzer von %s nicht ändern: %s"
 
-#: dnsmasq.c:742
+#: dnsmasq.c:787
 msgid "setting --bind-interfaces option because of OS limitations"
 msgstr "Aktiviere --bind-interfaces wegen Einschränkungen des Betriebssystems"
 
-#: dnsmasq.c:752
+#: dnsmasq.c:799
 #, c-format
 msgid "warning: interface %s does not currently exist"
 msgstr "Warnung: Schnittstelle %s existiert derzeit nicht"
 
-#: dnsmasq.c:757
+#: dnsmasq.c:804
 msgid "warning: ignoring resolv-file flag because no-resolv is set"
 msgstr "Warnung: Ignoriere \"resolv-file\", weil \"no-resolv\" aktiv ist"
 
-#: dnsmasq.c:760
+#: dnsmasq.c:807
 msgid "warning: no upstream servers configured"
 msgstr "Warnung: keine vorgelagerten (Upstream) Server konfiguriert"
 
-#: dnsmasq.c:764
+#: dnsmasq.c:811
 #, c-format
 msgid "asynchronous logging enabled, queue limit is %d messages"
 msgstr "asynchrone Protokollierung eingeschaltet, Warteschlange fasst %d Nachrichten"
 
-#: dnsmasq.c:785
+#: dnsmasq.c:832
 msgid "IPv6 router advertisement enabled"
 msgstr "IPv6-Router-Advertisement aktiviert"
 
-#: dnsmasq.c:790
+#: dnsmasq.c:837
 #, c-format
 msgid "DHCP, sockets bound exclusively to interface %s"
 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:808
+#: dnsmasq.c:851
 msgid "root is "
 msgstr "Wurzel ist "
 
-#: dnsmasq.c:808
+#: dnsmasq.c:851
 msgid "enabled"
 msgstr "Aktiviert"
 
-#: dnsmasq.c:810
+#: dnsmasq.c:853
 msgid "secure mode"
 msgstr "sicherer Modus"
 
-#: dnsmasq.c:813
+#: dnsmasq.c:856
 #, c-format
 msgid "warning: %s inaccessible"
 msgstr "Warnung: %s nicht zugreifbar"
 
-#: dnsmasq.c:817
+#: dnsmasq.c:860
 #, c-format
 msgid "warning: TFTP directory %s inaccessible"
 msgstr "Warnung: Das TFTP-Verzeichnis %s ist nicht zugreifbar"
 
-#: dnsmasq.c:843
+#: dnsmasq.c:886
 #, c-format
 msgid "restricting maximum simultaneous TFTP transfers to %d"
 msgstr "Begrenze gleichzeitige TFTP-Übertragungen auf maximal %d"
 
-#: dnsmasq.c:1039
+#: dnsmasq.c:1056
 msgid "connected to system DBus"
 msgstr "Mit System-DBus verbunden"
 
-#: dnsmasq.c:1189
+#: dnsmasq.c:1215
 #, c-format
 msgid "cannot fork into background: %s"
 msgstr "kann nicht in den Hintergrund abspalten: %s"
 
-#: dnsmasq.c:1192
+#: dnsmasq.c:1218
 #, c-format
 msgid "failed to create helper: %s"
 msgstr "kann Helfer nicht erzeugen: %s"
 
-#: dnsmasq.c:1195
+#: dnsmasq.c:1221
 #, c-format
 msgid "setting capabilities failed: %s"
 msgstr "kann \"capabilities\" nicht setzen: %s"
 
-#: dnsmasq.c:1198
+#: dnsmasq.c:1224
 #, c-format
 msgid "failed to change user-id to %s: %s"
 msgstr "Kann nicht Benutzerrechte %s annehmen: %s"
 
-#: dnsmasq.c:1201
+#: dnsmasq.c:1227
 #, c-format
 msgid "failed to change group-id to %s: %s"
 msgstr "Kann nicht Gruppenrechte %s annehmen: %s"
 
-#: dnsmasq.c:1204
+#: dnsmasq.c:1230
 #, c-format
 msgid "failed to open pidfile %s: %s"
 msgstr "kann die Prozessidentifikations-(PID)-Datei %s nicht öffnen: %s"
 
-#: dnsmasq.c:1207
+#: dnsmasq.c:1233
 #, c-format
 msgid "cannot open log %s: %s"
 msgstr "Kann Logdatei %s nicht öffnen: %s"
 
-#: dnsmasq.c:1210
+#: dnsmasq.c:1236
 #, c-format
 msgid "failed to load Lua script: %s"
 msgstr "Konnte Lua-Script nicht laden: %s"
 
-#: dnsmasq.c:1213
+#: dnsmasq.c:1239
 #, c-format
 msgid "TFTP directory %s inaccessible: %s"
 msgstr "Das TFTP-Verzeichnis %s ist nicht zugreifbar: %s"
 
-#: dnsmasq.c:1216
+#: dnsmasq.c:1242
 #, c-format
 msgid "cannot create timestamp file %s: %s"
 msgstr "Kann keine timestamp-Datei %s erzeugen: %s "
 
-#: dnsmasq.c:1237
-msgid "now checking DNSSEC signature timestamps"
-msgstr "Prüfe jetzt DNSSEC Signatur-Zeitstempel"
-
-#: dnsmasq.c:1304
+#: dnsmasq.c:1326
 #, c-format
 msgid "script process killed by signal %d"
 msgstr "Scriptprozess durch Signal %d getötet"
 
-#: dnsmasq.c:1308
+#: dnsmasq.c:1330
 #, c-format
 msgid "script process exited with status %d"
 msgstr "Scriptprozess hat sich mit Status %d beendet"
 
-#: dnsmasq.c:1312
+#: dnsmasq.c:1334
 #, c-format
 msgid "failed to execute %s: %s"
 msgstr "konnte %s nicht ausführen: %s"
 
-#: dnsmasq.c:1367
+#: dnsmasq.c:1374
+msgid "now checking DNSSEC signature timestamps"
+msgstr "Prüfe jetzt DNSSEC Signatur-Zeitstempel"
+
+#: dnsmasq.c:1409 dnssec.c:160 dnssec.c:206
+#, c-format
+msgid "failed to update mtime on %s: %s"
+msgstr "kann die mtime nicht auf %s aktualisieren: %s"
+
+#: dnsmasq.c:1416
 msgid "exiting on receipt of SIGTERM"
 msgstr "beende nach Empfang von SIGTERM"
 
-#: dnsmasq.c:1395
+#: dnsmasq.c:1444
 #, c-format
 msgid "failed to access %s: %s"
 msgstr "konnte auf %s nicht zugreifen: %s"
 
-#: dnsmasq.c:1425
+#: dnsmasq.c:1474
 #, c-format
 msgid "reading %s"
 msgstr "lese %s"
 
-#: dnsmasq.c:1436
+#: dnsmasq.c:1485
 #, c-format
 msgid "no servers found in %s, will retry"
 msgstr "keine Server in %s gefunden, werde es später neu versuchen"
@@ -1541,249 +1619,269 @@ msgstr "kann nicht an DHCP-Server-Socket binden: %s"
 msgid "cannot create ICMP raw socket: %s."
 msgstr "kann ICMP-Rohdaten-Socket nicht erzeugen: %s."
 
-#: dhcp.c:241 dhcp6.c:180
+#: dhcp.c:252 dhcp6.c:173
 #, c-format
 msgid "unknown interface %s in bridge-interface"
 msgstr "unbekannte Schnittstelle %s in bridge-interface"
 
-#: dhcp.c:281
+#: dhcp.c:293
 #, c-format
 msgid "DHCP packet received on %s which has no address"
 msgstr "DHCP-Paket ohne Adresse an Schnittstelle %s empfangen"
 
-#: dhcp.c:415
+#: dhcp.c:427
 #, c-format
 msgid "ARP-cache injection failed: %s"
 msgstr "APR-Cache Injektion fehlgeschlagen: %s"
 
-#: dhcp.c:514
+#: dhcp.c:470
+#, c-format
+msgid "Error sending DHCP packet to %s: %s"
+msgstr "Fehler beim Senden des DHCP-Pakets an %s: %s"
+
+#: dhcp.c:531
 #, c-format
 msgid "DHCP range %s -- %s is not consistent with netmask %s"
 msgstr "DHCP-Bereich %s - %s passt nicht zur Netzmaske %s"
 
-#: dhcp.c:815
+#: dhcp.c:854
 #, c-format
 msgid "bad line at %s line %d"
 msgstr "ungültige Zeile %2$d in Datei %1$s"
 
-#: dhcp.c:858
+#: dhcp.c:897
 #, c-format
 msgid "ignoring %s line %d, duplicate name or IP address"
 msgstr "ignoriere %s Zeile %d, doppelter Name oder doppelte IP-Adresse"
 
-#: dhcp.c:1002 rfc3315.c:2135
+#: dhcp.c:1041 rfc3315.c:2149
 #, c-format
 msgid "DHCP relay %s -> %s"
 msgstr "DHCP Weiterleitung %s -> %s"
 
-#: lease.c:61
+#: lease.c:98
+msgid "too many stored leases"
+msgstr "zu viele Leases gespeichert"
+
+#: lease.c:166
 #, c-format
 msgid "cannot open or create lease file %s: %s"
 msgstr "kann Lease-Datei %s nicht öffnen: %s"
 
-#: lease.c:134
-msgid "too many stored leases"
-msgstr "zu viele Leases gespeichert"
+#: lease.c:175
+#, c-format
+msgid "failed to parse lease database, invalid line: %s %s %s %s ..."
+msgstr ""
 
-#: lease.c:165
+#: lease.c:180
+#, fuzzy, c-format
+msgid "failed to read lease file %s: %s"
+msgstr "konnte %s nicht lesen: %s"
+
+#: lease.c:196
 #, c-format
 msgid "cannot run lease-init script %s: %s"
 msgstr "kann Lease-Start-Skript %s nicht ausführen: %s"
 
-#: lease.c:171
+#: lease.c:202
 #, c-format
 msgid "lease-init script returned exit code %s"
 msgstr "Lease-Start-Skript beendete sich mit Code %s"
 
 # FIXME: This should be %u s also in English according to NIST and SI rules. -- MA
-#: lease.c:342
+#: lease.c:373
 #, c-format
 msgid "failed to write %s: %s (retry in %us)"
 msgstr "Konnte %s nicht schreiben: %s (Neuversuch in %u s)"
 
-#: lease.c:906
+#: lease.c:937
 #, c-format
 msgid "Ignoring domain %s for DHCP host name %s"
 msgstr "Ignoriere Domäne %s für DHCP-Hostnamen %s"
 
 # FIXME: this and the next few are not translatable. Please provide full
 # strings, do not programmatically assemble them.
-#: rfc2131.c:344
+#: rfc2131.c:347
 #, c-format
 msgid "no address range available for DHCP request %s %s"
 msgstr "Kein verfügbarer DHCP-Bereich für Anfrage %s %s"
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "with subnet selector"
 msgstr "mit Subnetz-Wähler"
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "via"
 msgstr "via"
 
-#: rfc2131.c:357
+#: rfc2131.c:360
 #, c-format
 msgid "%u available DHCP subnet: %s/%s"
 msgstr "%u verfügbare(s) DHCP-Subnetz: %s/%s"
 
-#: rfc2131.c:360 rfc3315.c:300
+#: rfc2131.c:363 rfc3315.c:306
 #, c-format
 msgid "%u available DHCP range: %s -- %s"
 msgstr "%u verfügbare(r) DHCP-Bereich: %s - %s"
 
-#: rfc2131.c:471
+#: rfc2131.c:474
 #, c-format
 msgid "%u vendor class: %s"
 msgstr "%u \"Vendor class\": %s"
 
-#: rfc2131.c:473
+#: rfc2131.c:476
 #, c-format
 msgid "%u user class: %s"
 msgstr "%u Benutzerklasse: %s"
 
 # FIXME: do not programmatically assemble strings - untranslatable
-#: rfc2131.c:500
+#: rfc2131.c:510
 msgid "disabled"
 msgstr "deaktiviert"
 
-#: rfc2131.c:541 rfc2131.c:974 rfc2131.c:1380 rfc3315.c:603 rfc3315.c:856
-#: rfc3315.c:1135
+#: rfc2131.c:551 rfc2131.c:1006 rfc2131.c:1430 rfc3315.c:616 rfc3315.c:869
+#: rfc3315.c:1148
 msgid "ignored"
 msgstr "ignoriert"
 
-#: rfc2131.c:556 rfc2131.c:1207 rfc3315.c:906
+#: rfc2131.c:566 rfc2131.c:1239 rfc3315.c:919
 msgid "address in use"
 msgstr "Adresse in Nutzung"
 
-#: rfc2131.c:570 rfc2131.c:1028
+#: rfc2131.c:580 rfc2131.c:1060
 msgid "no address available"
 msgstr "Keine Adresse verfügbar"
 
-#: rfc2131.c:577 rfc2131.c:1170
+#: rfc2131.c:587 rfc2131.c:1202
 msgid "wrong network"
 msgstr "Falsches Netzwerk"
 
-#: rfc2131.c:592
+#: rfc2131.c:602
 msgid "no address configured"
 msgstr "Keine Adresse konfiguriert"
 
-#: rfc2131.c:598 rfc2131.c:1220
+#: rfc2131.c:608 rfc2131.c:1252
 msgid "no leases left"
 msgstr "Keine Leases übrig"
 
-#: rfc2131.c:693 rfc3315.c:476
+#: rfc2131.c:703 rfc3315.c:482
 #, c-format
 msgid "%u client provides name: %s"
 msgstr "%u Klient stellt Name bereit: %s"
 
-#: rfc2131.c:798
+#: rfc2131.c:808
 msgid "PXE BIS not supported"
 msgstr "PXE BIS nicht unterstützt"
 
-#: rfc2131.c:942 rfc3315.c:1229
+#: rfc2131.c:974 rfc3315.c:1242
 #, c-format
 msgid "disabling DHCP static address %s for %s"
 msgstr "schalte statische DHCP-Adresse %s für %s ab"
 
 # FIXME: do not assemble
-#: rfc2131.c:963
+#: rfc2131.c:995
 msgid "unknown lease"
 msgstr "Unbekannter Lease"
 
-#: rfc2131.c:997
+#: rfc2131.c:1029
 #, c-format
 msgid "not using configured address %s because it is leased to %s"
 msgstr "benutze konfigurierte Adresse %s nicht, weil sie an %s verleast ist"
 
-#: rfc2131.c:1007
+#: rfc2131.c:1039
 #, c-format
 msgid "not using configured address %s because it is in use by the server or relay"
 msgstr "benutze konfigurierte Adresse %s nicht, weil sie von Server/Relais verwendet wird"
 
-#: rfc2131.c:1010
+#: rfc2131.c:1042
 #, c-format
 msgid "not using configured address %s because it was previously declined"
 msgstr "benutze konfigurierte Adresse %s nicht, weil sie zuvor abgelehnt wurde"
 
 # FIXME: do not assemble
-#: rfc2131.c:1026 rfc2131.c:1213
+#: rfc2131.c:1058 rfc2131.c:1245
 msgid "no unique-id"
 msgstr "Keine eindeutige ID"
 
-#: rfc2131.c:1108
+#: rfc2131.c:1140
 msgid "wrong server-ID"
 msgstr "Falsche Server-ID"
 
-#: rfc2131.c:1127
+#: rfc2131.c:1159
 msgid "wrong address"
 msgstr "Falsche Adresse"
 
-#: rfc2131.c:1145 rfc3315.c:1002
+#: rfc2131.c:1177 rfc3315.c:1015
 msgid "lease not found"
 msgstr "Lease nicht gefunden"
 
-#: rfc2131.c:1178
+#: rfc2131.c:1210
 msgid "address not available"
 msgstr "Adresse nicht verfügbar"
 
-#: rfc2131.c:1189
+#: rfc2131.c:1221
 msgid "static lease available"
 msgstr "Statischer Lease verfügbar"
 
-#: rfc2131.c:1193
+#: rfc2131.c:1225
 msgid "address reserved"
 msgstr "Adresse reserviert"
 
-#: rfc2131.c:1201
+#: rfc2131.c:1233
 #, c-format
 msgid "abandoning lease to %s of %s"
 msgstr "Gebe Lease von %2$s an %1$s auf"
 
-#: rfc2131.c:1707
+#: rfc2131.c:1757
 #, c-format
 msgid "%u bootfile name: %s"
 msgstr "%u Name der Bootdatei: %s"
 
-#: rfc2131.c:1716
+#: rfc2131.c:1766
 #, c-format
 msgid "%u server name: %s"
 msgstr "%u Servername: %s"
 
-#: rfc2131.c:1724
+#: rfc2131.c:1774
 #, c-format
 msgid "%u next server: %s"
 msgstr "%u nächster Server: %s"
 
-#: rfc2131.c:1727
+#: rfc2131.c:1777
 #, c-format
 msgid "%u broadcast response"
 msgstr "%u Antwort per Rundsendung"
 
-#: rfc2131.c:1790
+#: rfc2131.c:1840
 #, c-format
 msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
 msgstr "kann DHCP/BOOTP-Opition %d nicht setzen: kein Platz mehr im Paket"
 
-#: rfc2131.c:2031
+#: rfc2131.c:2131
 msgid "PXE menu too large"
 msgstr "PXE-Menüeintrag zu groß"
 
-#: rfc2131.c:2170 rfc3315.c:1502
+#: rfc2131.c:2270 rfc3315.c:1515
 #, c-format
 msgid "%u requested options: %s"
 msgstr "%u angeforderte Optionen: %s"
 
-#: rfc2131.c:2487
+#: rfc2131.c:2587
 #, c-format
 msgid "cannot send RFC3925 option: too many options for enterprise number %d"
 msgstr "Kann RFC3925-Option nicht senden: zu viele Optionen für Unternehmen Nr. %d"
 
+#: rfc2131.c:2650
+#, c-format
+msgid "%u reply delay: %d"
+msgstr ""
+
 #: netlink.c:77
 #, c-format
 msgid "cannot create netlink socket: %s"
 msgstr "kann Netlink-Socket nicht erzeugen: %s"
 
-#: netlink.c:348
+#: netlink.c:355
 #, c-format
 msgid "netlink returns error: %s"
 msgstr "Netlink liefert Fehler %s"
@@ -1802,62 +1900,62 @@ msgstr "Aktiviere --%s Option von D-Bus"
 msgid "Disabling --%s option from D-Bus"
 msgstr "Deaktiviere --%s Option von D-Bus"
 
-#: dbus.c:691
+#: dbus.c:690
 msgid "setting upstream servers from DBus"
 msgstr "vorgelagerte Server von DBus gesetzt"
 
-#: dbus.c:738
+#: dbus.c:737
 msgid "could not register a DBus message handler"
 msgstr "konnte Steuerungsprogramm für DBus-Nachrichten nicht anmelden"
 
-#: bpf.c:263
+#: bpf.c:265
 #, c-format
 msgid "cannot create DHCP BPF socket: %s"
 msgstr "konnte DHCP-BPF-Socket nicht einrichten: %s"
 
-#: bpf.c:291
+#: bpf.c:293
 #, c-format
 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
+#: bpf.c:378
 #, c-format
 msgid "cannot create PF_ROUTE socket: %s"
 msgstr "Kann PF_ROUTE socket nicht erzeugen: %s"
 
-#: bpf.c:397
+#: bpf.c:399
 msgid "Unknown protocol version from route socket"
 msgstr "Unbekannte Protokollversion vom Route Socket"
 
-#: helper.c:153
+#: helper.c:154
 msgid "lease() function missing in Lua script"
 msgstr "Die Funktion lease() fehlt im Lua-Script"
 
-#: tftp.c:309
+#: tftp.c:319
 msgid "unable to get free port for TFTP"
 msgstr "konnte keinen freien Port für TFTP bekommen"
 
-#: tftp.c:325
+#: tftp.c:335
 #, c-format
 msgid "unsupported request from %s"
 msgstr "nicht unterstützte Anfrage von %s"
 
-#: tftp.c:439
+#: tftp.c:483
 #, c-format
 msgid "file %s not found"
 msgstr "Datei %s nicht gefunden"
 
-#: tftp.c:548
+#: tftp.c:592
 #, c-format
 msgid "error %d %s received from %s"
 msgstr "Fehler %d %s von %s empfangen"
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "failed sending %s to %s"
 msgstr "konnte %s nicht an %s senden"
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "sent %s to %s"
 msgstr "%s an %s verschickt"
@@ -1872,7 +1970,7 @@ msgstr "Überlauf: %d Protokolleinträge verloren"
 msgid "log failed: %s"
 msgstr "Protokollierung fehlgeschlagen: %s"
 
-#: log.c:472
+#: log.c:471
 msgid "FAILED to start up"
 msgstr "Start fehlgeschlagen"
 
@@ -1881,17 +1979,17 @@ msgstr "Start fehlgeschlagen"
 msgid "Conntrack connection mark retrieval failed: %s"
 msgstr "\"Conntrack connection mark\"-Abruf fehlgeschlagen: %s"
 
-#: dhcp6.c:59
+#: dhcp6.c:52
 #, c-format
 msgid "cannot create DHCPv6 socket: %s"
 msgstr "Kann DHCPv6-Socket nicht erzeugen: %s"
 
-#: dhcp6.c:80
+#: dhcp6.c:73
 #, c-format
 msgid "failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"
 msgstr "kann SO_REUSE{ADDR|PORT} für DHCPv6-Socket nicht aktivieren: %s"
 
-#: dhcp6.c:92
+#: dhcp6.c:85
 #, c-format
 msgid "failed to bind DHCPv6 server socket: %s"
 msgstr "Kann nicht an DHCPv6-Server-Socket binden: %s"
@@ -1906,68 +2004,68 @@ msgstr "Kein Adressbereich verfügbar für die DHCPv6-Anfrage vom Relay bei %s"
 msgid "no address range available for DHCPv6 request via %s"
 msgstr "Kein Adressbereich verfügbar für die DHCPv6-Anfrage via %s"
 
-#: rfc3315.c:297
+#: rfc3315.c:303
 #, c-format
 msgid "%u available DHCPv6 subnet: %s/%d"
 msgstr "%u verfügbare(s) DHCPv6-Subnetz: %s/%d"
 
-#: rfc3315.c:380
+#: rfc3315.c:386
 #, c-format
 msgid "%u vendor class: %u"
 msgstr "%u Herstellerklasse: %u"
 
-#: rfc3315.c:428
+#: rfc3315.c:434
 #, c-format
 msgid "%u client MAC address: %s"
 msgstr "%u Klient MAC-Adresse: %s"
 
 # FIXME: do not assemble
-#: rfc3315.c:660
+#: rfc3315.c:673
 #, c-format
 msgid "unknown prefix-class %d"
 msgstr "unbekannte Präfixklasse %d"
 
-#: rfc3315.c:803 rfc3315.c:898
+#: rfc3315.c:816 rfc3315.c:911
 msgid "address unavailable"
 msgstr "Adresse nicht verfügbar"
 
-#: rfc3315.c:815 rfc3315.c:946 rfc3315.c:1279
+#: rfc3315.c:828 rfc3315.c:959 rfc3315.c:1292
 msgid "success"
 msgstr "Erfolg"
 
-#: rfc3315.c:830 rfc3315.c:839 rfc3315.c:954 rfc3315.c:956
+#: rfc3315.c:843 rfc3315.c:852 rfc3315.c:967 rfc3315.c:969
 msgid "no addresses available"
 msgstr "Keine Adressen verfügbar"
 
-#: rfc3315.c:933
+#: rfc3315.c:946
 msgid "not on link"
 msgstr "nicht on link"
 
-#: rfc3315.c:1006 rfc3315.c:1191 rfc3315.c:1268
+#: rfc3315.c:1019 rfc3315.c:1204 rfc3315.c:1281
 msgid "no binding found"
 msgstr "Keine Bindung gefunden"
 
-#: rfc3315.c:1044
+#: rfc3315.c:1057
 msgid "deprecated"
 msgstr "veraltet"
 
-#: rfc3315.c:1049
+#: rfc3315.c:1062
 msgid "address invalid"
 msgstr "Adresse ungültig"
 
-#: rfc3315.c:1096
+#: rfc3315.c:1109
 msgid "confirm failed"
 msgstr "Bestätigung fehlgeschlagen"
 
-#: rfc3315.c:1112
+#: rfc3315.c:1125
 msgid "all addresses still on link"
 msgstr "Alle Adressen immer noch on link"
 
-#: rfc3315.c:1200
+#: rfc3315.c:1213
 msgid "release received"
 msgstr "Freigabe empfangen"
 
-#: rfc3315.c:2126
+#: rfc3315.c:2140
 msgid "Cannot multicast to DHCPv6 server without correct interface"
 msgstr "Kann nicht zum DHCPv6 Server multicasten ohne korrekte Schnittstelle"
 
@@ -1991,76 +2089,76 @@ msgstr "%s hat mehr als eine Adresse in hosts-Datei, benutze %s für DHCP"
 msgid "duplicate IP address %s (%s) in dhcp-config directive"
 msgstr "doppelte IP-Adresse %s (%s) in \"dhcp-config\"-Anweisung"
 
-#: dhcp-common.c:494
+#: dhcp-common.c:491
 #, c-format
 msgid "failed to set SO_BINDTODEVICE on DHCP socket: %s"
 msgstr "kann SO_BINDTODEVICE für DHCP-Socket nicht aktivieren: %s"
 
-#: dhcp-common.c:615
+#: dhcp-common.c:612
 #, c-format
 msgid "Known DHCP options:\n"
 msgstr "Bekannte DHCP-Optionen:\n"
 
-#: dhcp-common.c:626
+#: dhcp-common.c:623
 #, c-format
 msgid "Known DHCPv6 options:\n"
 msgstr "Bekannte DHCPv6-Optionen:\n"
 
-#: dhcp-common.c:823
+#: dhcp-common.c:820
 msgid ", prefix deprecated"
 msgstr ", Prefix veraltet"
 
-#: dhcp-common.c:826
+#: dhcp-common.c:823
 #, c-format
 msgid ", lease time "
 msgstr ", Lease Zeit"
 
-#: dhcp-common.c:868
+#: dhcp-common.c:865
 #, c-format
 msgid "%s stateless on %s%.0s%.0s%s"
 msgstr "%s stateless auf %s%.0s%.0s%s"
 
-#: dhcp-common.c:870
+#: dhcp-common.c:867
 #, c-format
 msgid "%s, static leases only on %.0s%s%s%.0s"
 msgstr "%s, nur statische Leases auf %.0s%s%s%.0s"
 
-#: dhcp-common.c:872
+#: dhcp-common.c:869
 #, c-format
 msgid "%s, proxy on subnet %.0s%s%.0s%.0s"
 msgstr "%s, Proxy im Subnetz %.0s%s%.0s%.0s"
 
-#: dhcp-common.c:873
+#: dhcp-common.c:870
 #, c-format
 msgid "%s, IP range %s -- %s%s%.0s"
 msgstr "%s, IP-Bereich %s -- %s%s%.0s"
 
-#: dhcp-common.c:886
+#: dhcp-common.c:883
 #, c-format
 msgid "DHCPv4-derived IPv6 names on %s%s"
 msgstr "DHCPv4-abgeleitete IPv6 Namen auf %s%s"
 
-#: dhcp-common.c:889
+#: dhcp-common.c:886
 #, c-format
 msgid "router advertisement on %s%s"
 msgstr "Router-Advertisment auf %s%s"
 
-#: dhcp-common.c:900
+#: dhcp-common.c:897
 #, c-format
 msgid "DHCP relay from %s to %s via %s"
 msgstr "DHCP Weiterleitung von %s nach %s über %s"
 
-#: dhcp-common.c:902
+#: dhcp-common.c:899
 #, c-format
 msgid "DHCP relay from %s to %s"
 msgstr "DHCP Weiterleitung von %s nach %s"
 
-#: radv.c:109
+#: radv.c:110
 #, c-format
 msgid "cannot create ICMPv6 socket: %s"
 msgstr "Kann ICMPv6-Socket nicht erzeugen: %s"
 
-#: auth.c:448
+#: auth.c:449
 #, c-format
 msgid "ignoring zone transfer request from %s"
 msgstr "ignoriere Zonentransfer-Anfrage von %s"
@@ -2075,89 +2173,107 @@ msgstr "konnte Kernelversion nicht finden: %s"
 msgid "failed to create IPset control socket: %s"
 msgstr "konnte IPset-Kontroll-Socket nicht erzeugen: %s"
 
-#: dnssec.c:449 dnssec.c:493
-#, c-format
-msgid "failed to update mtime on %s: %s"
+#: ipset.c:233
+#, fuzzy, c-format
+msgid "failed to update ipset %s: %s"
 msgstr "kann die mtime nicht auf %s aktualisieren: %s"
 
+#: dnssec.c:208
+#, fuzzy
+msgid "system time considered valid, now checking DNSSEC signature timestamps."
+msgstr "Prüfe jetzt DNSSEC Signatur-Zeitstempel"
+
 #: blockdata.c:58
 #, c-format
 msgid "DNSSEC memory in use %u, max %u, allocated %u"
 msgstr "DNSSEC Speicher in Benutzung %u, Max %u, zugewiesen %u"
 
-#: tables.c:80
-msgid "error: fill_addr missused"
-msgstr "Fehler: fill_addr falsch verwendet"
-
-#: tables.c:109
+#: tables.c:61
 #, c-format
 msgid "failed to access pf devices: %s"
 msgstr "konnte auf pf Geräte nicht zugreifen: %s"
 
-#: tables.c:123
+#: tables.c:74
 #, c-format
 msgid "warning: no opened pf devices %s"
 msgstr "Warnung: Keine geöffneten pf Geräte %s"
 
-#: tables.c:131
+#: tables.c:82
 #, c-format
 msgid "error: cannot use table name %s"
 msgstr "Fehler: Kann Tabellenname %s nicht benutzen"
 
-#: tables.c:139
+#: tables.c:90
 #, c-format
 msgid "error: cannot strlcpy table name %s"
 msgstr "Fehler: Kann den Tabellennamen %s nicht strlcpy"
 
-#: tables.c:145
-#, c-format
-msgid "warning: pfr_add_tables: %s(%d)"
-msgstr "Warnung: pfr_add_tables: %s(%d)"
+#: tables.c:101
+#, fuzzy, c-format
+msgid "IPset: error:%s"
+msgstr "DBus-Fehler: %s"
 
-#: tables.c:151
+#: tables.c:108
 msgid "info: table created"
 msgstr "Info: Tabelle erstellt"
 
-#: tables.c:162
+#: tables.c:134
 #, c-format
 msgid "warning: DIOCR%sADDRS: %s"
 msgstr "Warnung: DIOCR%sADDRS: %s"
 
-#: tables.c:166
+#: tables.c:138
 #, c-format
 msgid "%d addresses %s"
 msgstr "%d Adressen %s"
 
-#: inotify.c:46
+#: inotify.c:62
+#, c-format
+msgid "cannot access path %s: %s"
+msgstr "Kann auf Pfad %s nicht zugreifen: %s"
+
+#: inotify.c:95
 #, c-format
 msgid "failed to create inotify: %s"
 msgstr "Kann kein inotify erzeugen: %s"
 
-#: inotify.c:60
+#: inotify.c:111
 #, c-format
-msgid "cannot cannonicalise resolv-file %s: %s"
-msgstr "Kann die resolv-file %s nicht kanonisieren: %s"
+msgid "too many symlinks following %s"
+msgstr "Zu viele nachfolgende symbolische Links folgend %s"
 
-#: inotify.c:72
+#: inotify.c:127
 #, c-format
 msgid "directory %s for resolv-file is missing, cannot poll"
 msgstr "Verzeichnis %s für resolv-file fehlt, kann nicht pollen"
 
-#: inotify.c:75 inotify.c:112
+#: inotify.c:131 inotify.c:168
 #, c-format
 msgid "failed to create inotify for %s: %s"
 msgstr "Konnte inotify für %s: %s nicht erzeugen"
 
-#: inotify.c:97
+#: inotify.c:153
 #, c-format
 msgid "bad dynamic directory %s: %s"
 msgstr "fehlerhaftes dynamisches Verzeichnis %s: %s"
 
-#: inotify.c:197
+#: inotify.c:257
 #, c-format
 msgid "inotify, new or changed file %s"
 msgstr "inotify, neue oder geänderte Datei %s"
 
+#~ msgid "bad TTL"
+#~ msgstr "unzulässige TTL"
+
+#~ msgid "error: fill_addr missused"
+#~ msgstr "Fehler: fill_addr falsch verwendet"
+
+#~ msgid "warning: pfr_add_tables: %s(%d)"
+#~ msgstr "Warnung: pfr_add_tables: %s(%d)"
+
+#~ msgid "cannot cannonicalise resolv-file %s: %s"
+#~ msgstr "Kann die resolv-file %s nicht kanonisieren: %s"
+
 #~ msgid "no interface with address %s"
 #~ msgstr "keine Schnittstelle mit Adresse %s"
 
index 46d8e42..bcca828 100644 (file)
--- a/po/es.po
+++ b/po/es.po
@@ -7,7 +7,7 @@ msgstr ""
 "Project-Id-Version: dnsmasq 2.67\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2009-06-18 12:24+0100\n"
-"PO-Revision-Date: 2013-10-04 13:24+0100\n"
+"PO-Revision-Date: 2017-07-17 18:30+0100\n"
 "Last-Translator: Vicente Soriano <victek@gmail.com>\n"
 "Language-Team:\n"
 "Language: es\n"
@@ -16,746 +16,776 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cache.c:523
+#: cache.c:518
 msgid "Internal error in cache."
 msgstr ""
 
-#: cache.c:941
+#: cache.c:928
 #, fuzzy, c-format
 msgid "failed to load names from %s: %s"
 msgstr "no se pudo cargar nombres desde %s: %s"
 
-#: cache.c:967 dhcp.c:828
+#: cache.c:954 dhcp.c:867
 #, fuzzy, c-format
 msgid "bad address at %s line %d"
 msgstr "dirección errónea en %s línea %d"
 
-#: cache.c:1018 dhcp.c:844
+#: cache.c:1007 dhcp.c:883
 #, c-format
 msgid "bad name at %s line %d"
 msgstr "nombre erróneo en %s línea %d"
 
-#: cache.c:1027 dhcp.c:919
+#: cache.c:1016 dhcp.c:958
 #, c-format
 msgid "read %s - %d addresses"
 msgstr "direcciónes %s - %d leídas"
 
-#: cache.c:1135
+#: cache.c:1129
 msgid "cleared cache"
 msgstr "el caché fue liberado"
 
-#: cache.c:1164
+#: cache.c:1158
 #, c-format
 msgid "No IPv4 address found for %s"
 msgstr ""
 
-#: cache.c:1242
+#: cache.c:1237
 #, c-format
 msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
 msgstr "%s es un CNAME, no se le está dando concesión DHCP de %s"
 
-#: cache.c:1266
+#: cache.c:1261
 #, c-format
 msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
 msgstr "no otorgando nombre %s a concesión DHCP de %s porque el nombre existe en %s con dirección %s"
 
-#: cache.c:1421
+#: cache.c:1418
 #, c-format
 msgid "time %lu"
 msgstr "tiempo %lu"
 
-#: cache.c:1422
+#: cache.c:1419
 #, fuzzy, c-format
 msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
 msgstr "tamaño de caché %d, %d/%d inserciónes de caché reutilizaron objetos no vencidos."
 
-#: cache.c:1424
+#: cache.c:1421
 #, c-format
 msgid "queries forwarded %u, queries answered locally %u"
 msgstr "búsquedas reenviadas %u, búsquedas respondidas localmente %u"
 
-#: cache.c:1427
+#: cache.c:1424
 #, fuzzy, c-format
 msgid "queries for authoritative zones %u"
 msgstr "Fijar TTL para respuestas autoritarias"
 
-#: cache.c:1453
+#: cache.c:1450
 #, c-format
 msgid "server %s#%d: queries sent %u, retried or failed %u"
 msgstr "servidor %s#%d: búsquedas enviadas %u, reintentadas o fallidas %u"
 
-#: util.c:45
+#: util.c:47
 #, fuzzy, c-format
 msgid "failed to seed the random number generator: %s"
 msgstr "no se pudo crear valor semilla para el generador de números aleatorios: %s"
 
-#: util.c:205
+#: util.c:224
 #, fuzzy
 msgid "failed to allocate memory"
 msgstr "no se pudo asignar memoria"
 
-#: util.c:250 option.c:601
+#: util.c:281 option.c:619
 msgid "could not get memory"
 msgstr "no se pudo adquirir memoria"
 
-#: util.c:260
+#: util.c:291
 #, fuzzy, c-format
 msgid "cannot create pipe: %s"
 msgstr "no se puede crear pipe: %s"
 
-#: util.c:268
+#: util.c:299
 #, fuzzy, c-format
 msgid "failed to allocate %d bytes"
 msgstr "no se pudo asignar %d bytes"
 
-#: util.c:437
+#: util.c:468
 #, c-format
 msgid "infinite"
 msgstr "infinito"
 
-#: option.c:332
+#: option.c:344
 msgid "Specify local address(es) to listen on."
 msgstr "Especificar dirección(es) locales dónde escuchar."
 
-#: option.c:333
+#: option.c:345
 msgid "Return ipaddr for all hosts in specified domains."
 msgstr "Retornar ipaddr (dirección IP) para todos los hosts en los dominios especificados."
 
-#: option.c:334
+#: option.c:346
 msgid "Fake reverse lookups for RFC1918 private address ranges."
 msgstr "Falsificar búsquedas reversas para rangos de dirección privados RFC1918."
 
-#: option.c:335
+#: option.c:347
 msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
 msgstr "Tratar ipaddr (dirección IP) como NXDOMAIN (derrota comodín Verisign)."
 
-#: option.c:336
+#: option.c:348
 #, c-format
 msgid "Specify the size of the cache in entries (defaults to %s)."
 msgstr "Especificar tamaño de caché en cuanto a cantidad de objetos (%s por predeterminado)."
 
-#: option.c:337
+#: option.c:349
 #, c-format
 msgid "Specify configuration file (defaults to %s)."
 msgstr "Especificar archivo de configuración (%s por predeterminado)."
 
-#: option.c:338
+#: option.c:350
 msgid "Do NOT fork into the background: run in debug mode."
 msgstr "NO hacer un fork hacia el fondo: correr en modo debug."
 
-#: option.c:339
+#: option.c:351
 msgid "Do NOT forward queries with no domain part."
 msgstr "NO reenviar búsquedas sin parte de dominio."
 
-#: option.c:340
+#: option.c:352
 msgid "Return self-pointing MX records for local hosts."
 msgstr "Retornar expedientes MX auto-señaladores para hosts locales."
 
-#: option.c:341
+#: option.c:353
 msgid "Expand simple names in /etc/hosts with domain-suffix."
 msgstr "Expandir nombres simples en /etc/hosts con domain-suffix (sufijo de dominio)."
 
-#: option.c:342
+#: option.c:354
 msgid "Don't forward spurious DNS requests from Windows hosts."
 msgstr "No reenviar pedidos DNS falsos desde máquinas Windows."
 
-#: option.c:343
+#: option.c:355
 msgid "Enable DHCP in the range given with lease duration."
 msgstr "Habilitar DHCP dentro del rango brindado con duración de concesión."
 
-#: option.c:344
+#: option.c:356
 #, c-format
 msgid "Change to this group after startup (defaults to %s)."
 msgstr "Cambiar a este grupo después del inicio (%s por predeterminado)."
 
-#: option.c:345
+#: option.c:357
 msgid "Set address or hostname for a specified machine."
 msgstr "Fijar dirección o nombre de host para una máquina especificada."
 
-#: option.c:346
+#: option.c:358
 #, fuzzy
 msgid "Read DHCP host specs from file."
 msgstr "Leer especificaciones DHCP de host desde archivo"
 
-#: option.c:347
+#: option.c:359
 #, fuzzy
 msgid "Read DHCP option specs from file."
 msgstr "Leer opciones DHCP de host desde archivo"
 
-#: option.c:348
+#: option.c:360
 #, fuzzy
 msgid "Read DHCP host specs from a directory."
 msgstr "Leer especificaciones DHCP de host desde archivo"
 
-#: option.c:349
+#: option.c:361
 #, fuzzy
 msgid "Read DHCP options from a directory."
 msgstr "Leer opciones DHCP de host desde archivo"
 
-#: option.c:350
+#: option.c:362
 msgid "Evaluate conditional tag expression."
 msgstr "Evaluar expresión condicional de etiqueta."
 
-#: option.c:351
+#: option.c:363
 #, c-format
 msgid "Do NOT load %s file."
 msgstr "NO cargar archivo %s."
 
-#: option.c:352
+#: option.c:364
 #, c-format
 msgid "Specify a hosts file to be read in addition to %s."
 msgstr "Especificar un archivo de hosts para ser leído adicionalmente a %s."
 
-#: option.c:353
+#: option.c:365
 #, fuzzy
 msgid "Read hosts files from a directory."
 msgstr "Leer especificaciones DHCP de host desde archivo"
 
-#: option.c:354
+#: option.c:366
 msgid "Specify interface(s) to listen on."
 msgstr "Especificar interfase(s) donde escuchar."
 
-#: option.c:355
+#: option.c:367
 msgid "Specify interface(s) NOT to listen on."
 msgstr "Especificar interfase(s) donde NO escuchar."
 
-#: option.c:356
+#: option.c:368
 #, fuzzy
 msgid "Map DHCP user class to tag."
 msgstr "Trazar clase de usuario DHCP a etiqueta."
 
-#: option.c:357
+#: option.c:369
 msgid "Map RFC3046 circuit-id to tag."
 msgstr "Trazar circuit-id (identificación de circuito) RFC3046 a etiqueta."
 
-#: option.c:358
+#: option.c:370
 msgid "Map RFC3046 remote-id to tag."
 msgstr "Trazar remote-id (identificación remota) RFC3046 a etiqueta."
 
-#: option.c:359
+#: option.c:371
 msgid "Map RFC3993 subscriber-id to tag."
 msgstr "Trazar subscriber-id (identificación de suscritor) RFC3993 a etiqueta."
 
-#: option.c:360
+#: option.c:372
 #, fuzzy
 msgid "Don't do DHCP for hosts with tag set."
 msgstr "No hacer DHCP para hosts con etiqueta fijada."
 
-#: option.c:361
+#: option.c:373
 #, fuzzy
 msgid "Force broadcast replies for hosts with tag set."
 msgstr "Forzar respuestas broadcast para hosts con etiqueta fijada."
 
-#: option.c:362
+#: option.c:374
 msgid "Do NOT fork into the background, do NOT run in debug mode."
 msgstr "NO hacer un fork hacia el fondo, NO correr en modo debug."
 
-#: option.c:363
+#: option.c:375
 msgid "Assume we are the only DHCP server on the local network."
 msgstr "Asumir que somos el único servidor DHCP en la red local."
 
-#: option.c:364
+#: option.c:376
 #, c-format
 msgid "Specify where to store DHCP leases (defaults to %s)."
 msgstr "Especificar donde almacenar concesión DHCP (%s por predeterminado)."
 
-#: option.c:365
+#: option.c:377
 msgid "Return MX records for local hosts."
 msgstr "Retornar expedientes MX para hosts locales."
 
-#: option.c:366
+#: option.c:378
 msgid "Specify an MX record."
 msgstr "Especificar un expediente MX."
 
-#: option.c:367
+#: option.c:379
 msgid "Specify BOOTP options to DHCP server."
 msgstr "Especificar opciones BOOTP a servidor DHCP."
 
-#: option.c:368
+#: option.c:380
 #, c-format
 msgid "Do NOT poll %s file, reload only on SIGHUP."
 msgstr "NO revisar archivo %s periódicamente, recargar solo con SIGHUP."
 
-#: option.c:369
+#: option.c:381
 msgid "Do NOT cache failed search results."
 msgstr "NO almacenar en caché resultados de búsquedas fallidas."
 
-#: option.c:370
+#: option.c:382
 #, c-format
 msgid "Use nameservers strictly in the order given in %s."
 msgstr "Usar servidores DNS estrictamente en el órden brindado en %s."
 
-#: option.c:371
+#: option.c:383
 #, fuzzy
 msgid "Specify options to be sent to DHCP clients."
 msgstr "Especificar opciones para ser enviadas a clientes DHCP."
 
-#: option.c:372
+#: option.c:384
 msgid "DHCP option sent even if the client does not request it."
 msgstr "Opción DHCP enviada aún si el cliente no la pide."
 
-#: option.c:373
+#: option.c:385
 msgid "Specify port to listen for DNS requests on (defaults to 53)."
 msgstr "Especificar puerto donde escuchar por búsquedas DNS (53 por predeterminado)."
 
-#: option.c:374
+#: option.c:386
 #, c-format
 msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
 msgstr "Tamaño máximo de paquetes UDP soportado para EDNS.0 (%s por predeterminado)."
 
-#: option.c:375
+#: option.c:387
 #, fuzzy
 msgid "Log DNS queries."
 msgstr "Bitacorear búsquedas DNS."
 
-#: option.c:376
+#: option.c:388
 #, fuzzy
 msgid "Force the originating port for upstream DNS queries."
 msgstr "Enforzar el puerto original para búsquedas DNS subida."
 
-#: option.c:377
+#: option.c:389
 msgid "Do NOT read resolv.conf."
 msgstr "NO leer resolv.conf."
 
-#: option.c:378
+#: option.c:390
 #, c-format
 msgid "Specify path to resolv.conf (defaults to %s)."
 msgstr "Especificar el path hacia resolv.conf (%s por predeterminado)."
 
-#: option.c:379
+#: option.c:391
 #, fuzzy
 msgid "Specify path to file with server= options"
 msgstr "Especificar path de archivo PID (%s por predeterminado)."
 
-#: option.c:380
+#: option.c:392
 msgid "Specify address(es) of upstream servers with optional domains."
 msgstr "Especificar dirección(es) de servidores subida con dominios opcionales."
 
-#: option.c:381
+#: option.c:393
 #, fuzzy
 msgid "Specify address of upstream servers for reverse address queries"
 msgstr "Especificar dirección(es) de servidores subida con dominios opcionales."
 
-#: option.c:382
+#: option.c:394
 msgid "Never forward queries to specified domains."
 msgstr "Nunca reenviar búsquedas a dominios especificados."
 
-#: option.c:383
+#: option.c:395
 msgid "Specify the domain to be assigned in DHCP leases."
 msgstr "Especificar el dominio para ser asignado en concesión DHCP."
 
-#: option.c:384
+#: option.c:396
 msgid "Specify default target in an MX record."
 msgstr "Especificar destino predeterminado en un expediente MX."
 
-#: option.c:385
+#: option.c:397
 msgid "Specify time-to-live in seconds for replies from /etc/hosts."
 msgstr "Especificar tiempo de vida en segundos para respuestas desde /etc/hosts."
 
-#: option.c:386
+#: option.c:398
 #, fuzzy
 msgid "Specify time-to-live in seconds for negative caching."
 msgstr "Especificar tiempo de vida en segundos para caché negativo."
 
-#: option.c:387
+#: option.c:399
 #, fuzzy
 msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
 msgstr "Especificar tiempo de vida en segundos para respuestas desde /etc/hosts."
 
-#: option.c:388
+#: option.c:400
 #, fuzzy
 msgid "Specify time-to-live ceiling for cache."
 msgstr "Especificar tiempo de vida en segundos para caché negativo."
 
-#: option.c:389
+#: option.c:401
 #, fuzzy
 msgid "Specify time-to-live floor for cache."
 msgstr "Especificar tiempo de vida en segundos para caché negativo."
 
-#: option.c:390
+#: option.c:402
 #, c-format
 msgid "Change to this user after startup. (defaults to %s)."
 msgstr "Cambiar a este usuario despues del inicio (%s por predeterminado)."
 
-#: option.c:391
+#: option.c:403
 #, fuzzy
 msgid "Map DHCP vendor class to tag."
 msgstr "Trazar clase de vendedor DHCP a etiqueta."
 
-#: option.c:392
+#: option.c:404
 msgid "Display dnsmasq version and copyright information."
 msgstr "Mostrar información sobre la versión y copyright de dnsmasq."
 
-#: option.c:393
+#: option.c:405
 msgid "Translate IPv4 addresses from upstream servers."
 msgstr "Traducir direcciones IPv4 desde servidores subida."
 
-#: option.c:394
+#: option.c:406
 msgid "Specify a SRV record."
 msgstr "Especificar un expediente SRV."
 
-#: option.c:395
-msgid "Display this message. Use --help dhcp for known DHCP options."
+#: option.c:407
+#, fuzzy
+msgid "Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."
 msgstr "Mostrar este mensaje. Usar --help dhcp para opciones DHCP conocidas."
 
-#: option.c:396
+#: option.c:408
 #, fuzzy, c-format
 msgid "Specify path of PID file (defaults to %s)."
 msgstr "Especificar path de archivo PID (%s por predeterminado)."
 
-#: option.c:397
+#: option.c:409
 #, c-format
 msgid "Specify maximum number of DHCP leases (defaults to %s)."
 msgstr "Especificar número máximo de concesión DHCP (%s por predeterminado)."
 
-#: option.c:398
+#: option.c:410
 msgid "Answer DNS queries based on the interface a query was sent to."
 msgstr "Responder a búsquedas DNS en base a la interfase a la cuál fueron enviadas."
 
-#: option.c:399
+#: option.c:411
 msgid "Specify TXT DNS record."
 msgstr "Especificar expediente DNS TXT."
 
-#: option.c:400
+#: option.c:412
 #, fuzzy
 msgid "Specify PTR DNS record."
 msgstr "Especificar expediente DNS PTR."
 
-#: option.c:401
+#: option.c:413
 msgid "Give DNS name to IPv4 address of interface."
 msgstr "Otorgar nombre DNS a dirección IPv4 de interfase."
 
-#: option.c:402
+#: option.c:414
 msgid "Bind only to interfaces in use."
 msgstr "Acoplar solo a interfases en uso."
 
-#: option.c:403
+#: option.c:415
 #, c-format
 msgid "Read DHCP static host information from %s."
 msgstr "Leer información sobre hosts DHCP estáticos desde %s."
 
-#: option.c:404
+#: option.c:416
 msgid "Enable the DBus interface for setting upstream servers, etc."
 msgstr "Habilitar la interfase DBus para fijar servidores subida, etc."
 
-#: option.c:405
+#: option.c:417
 msgid "Do not provide DHCP on this interface, only provide DNS."
 msgstr "No proveer DHCP en esta interfase, sólo proveer DNS."
 
-#: option.c:406
+#: option.c:418
 msgid "Enable dynamic address allocation for bootp."
 msgstr "Habilitar alocación dinámica de direcciónes para BOOTP."
 
-#: option.c:407
+#: option.c:419
 #, fuzzy
 msgid "Map MAC address (with wildcards) to option set."
 msgstr "Trazar dirección MAC (con comodínes) a opción fijada."
 
-#: option.c:408
+#: option.c:420
 msgid "Treat DHCP requests on aliases as arriving from interface."
 msgstr "Tratar pedidos DHCP en alias como si llegaran de la interfase."
 
-#: option.c:409
+#: option.c:421
 msgid "Disable ICMP echo address checking in the DHCP server."
 msgstr "Deshabilitar verificación de direcciónes para echo ICMP en el servidor DHCP."
 
-#: option.c:410
+#: option.c:422
 #, fuzzy
 msgid "Shell script to run on DHCP lease creation and destruction."
 msgstr "Archivo guión para ejecutar cuando se crea o destruye una concesión DHCP."
 
-#: option.c:411
+#: option.c:423
 #, fuzzy
 msgid "Lua script to run on DHCP lease creation and destruction."
 msgstr "Archivo guión para ejecutar cuando se crea o destruye una concesión DHCP."
 
-#: option.c:412
+#: option.c:424
 #, fuzzy
 msgid "Run lease-change scripts as this user."
 msgstr "Correr archivo guión de cambio de concesión como este usuario."
 
-#: option.c:413
+#: option.c:425
+msgid "Call dhcp-script with changes to local ARP table."
+msgstr ""
+
+#: option.c:426
 msgid "Read configuration from all the files in this directory."
 msgstr "Leer configuración desde todos los archivos en este directorio."
 
-#: option.c:414
+#: option.c:427
 #, fuzzy
 msgid "Log to this syslog facility or file. (defaults to DAEMON)"
 msgstr "Bitacorear a esta facilidad syslog o archivo. (DAEMON por predeterminado)"
 
-#: option.c:415
+#: option.c:428
 msgid "Do not use leasefile."
 msgstr "No usar archivo de concesión."
 
-#: option.c:416
+#: option.c:429
 #, fuzzy, c-format
 msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
 msgstr "Número máximo de búsquedas DNS simultáneas. (%s por predeterminado)"
 
-#: option.c:417
+#: option.c:430
 #, c-format
 msgid "Clear DNS cache when reloading %s."
 msgstr "Liberar caché DNS al recargar %s."
 
-#: option.c:418
+#: option.c:431
 msgid "Ignore hostnames provided by DHCP clients."
 msgstr "Ignorar nombres de host brindados por clientes DHCP."
 
-#: option.c:419
+#: option.c:432
 msgid "Do NOT reuse filename and server fields for extra DHCP options."
 msgstr "NO reutilizar campos de nombre de archivo y servidor para opciones DHCP extra."
 
-#: option.c:420
+#: option.c:433
 msgid "Enable integrated read-only TFTP server."
 msgstr "Habilitar servidor integrado TFTP solo-lectura."
 
-#: option.c:421
+#: option.c:434
 msgid "Export files by TFTP only from the specified subtree."
 msgstr "Exportar archivos vía TFTP solo del sub-árbol especificado."
 
-#: option.c:422
-msgid "Add client IP address to tftp-root."
+#: option.c:435
+#, fuzzy
+msgid "Add client IP or hardware address to tftp-root."
 msgstr "Agregar IP de cliente a tftp-root."
 
-#: option.c:423
+#: option.c:436
 msgid "Allow access only to files owned by the user running dnsmasq."
 msgstr "Permitir acceso solo a archivos pertenecientes al usuario que corre dnsmasq."
 
-#: option.c:424
+#: option.c:437
 msgid "Do not terminate the service if TFTP directories are inaccessible."
 msgstr ""
 
-#: option.c:425
+#: option.c:438
 #, fuzzy, c-format
-msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgid "Maximum number of concurrent TFTP transfers (defaults to %s)."
 msgstr "Número máximo de transferencias TFTP simultáneas (%s por predeterminado)."
 
-#: option.c:426
+#: option.c:439
+#, fuzzy
+msgid "Maximum MTU to use for TFTP transfers."
+msgstr "Número máximo de transferencias TFTP simultáneas (%s por predeterminado)."
+
+#: option.c:440
 msgid "Disable the TFTP blocksize extension."
 msgstr "Deshabilitar la extensión TFTP blocksize (tamaño de bloque)."
 
-#: option.c:427
+#: option.c:441
 msgid "Convert TFTP filenames to lowercase"
 msgstr "Convertir a minúsculas los nombres de archivos TFTP"
 
-#: option.c:428
+#: option.c:442
 msgid "Ephemeral port range for use by TFTP transfers."
 msgstr "Rango de puertos efímeros para ser usados en transferencias TFTP."
 
-#: option.c:429
+#: option.c:443
 msgid "Extra logging for DHCP."
 msgstr "Log extra para DHCP."
 
-#: option.c:430
+#: option.c:444
 msgid "Enable async. logging; optionally set queue length."
 msgstr "Habilitar registro asíncrono; opcionalmente fijar tamaño de cola."
 
-#: option.c:431
+#: option.c:445
 msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
 msgstr "Detener revinculación DNS. Filtrar rangos de IP privados al resolver."
 
-#: option.c:432
+#: option.c:446
 msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
 msgstr "Permitir revinculación de 127.0.0.0/8, para servidores RBL."
 
-#: option.c:433
+#: option.c:447
 msgid "Inhibit DNS-rebind protection on this domain."
 msgstr "Inhibir protección de revinculación DNS en este dominio."
 
-#: option.c:434
+#: option.c:448
 msgid "Always perform DNS queries to all servers."
 msgstr "Siempre realizar búsquedas DNS a todos los servidores."
 
-#: option.c:435
+#: option.c:449
 #, fuzzy
 msgid "Set tag if client includes matching option in request."
 msgstr "Fijar etiqueta si cliente incluye opción coincidente en pedido."
 
-#: option.c:436
+#: option.c:450
 msgid "Use alternative ports for DHCP."
 msgstr "Usar puertos alternativos para DHCP."
 
-#: option.c:437
+#: option.c:451
 #, fuzzy
 msgid "Specify NAPTR DNS record."
 msgstr "Especificar expediente DNS NAPTR."
 
-#: option.c:438
+#: option.c:452
 msgid "Specify lowest port available for DNS query transmission."
 msgstr "Especificar puerto más bajo disponible para transmisión de búsquedas DNS."
 
-#: option.c:439
+#: option.c:453
+#, fuzzy
+msgid "Specify highest port available for DNS query transmission."
+msgstr "Especificar puerto más bajo disponible para transmisión de búsquedas DNS."
+
+#: option.c:454
 msgid "Use only fully qualified domain names for DHCP clients."
 msgstr "Usar solo nombres de dominio completamente calificados para clientes DHCP."
 
-#: option.c:440
+#: option.c:455
 msgid "Generate hostnames based on MAC address for nameless clients."
 msgstr "Generar hostnames basados en direcciones MAC para clientes sin nombre."
 
-#: option.c:441
+#: option.c:456
 msgid "Use these DHCP relays as full proxies."
 msgstr "Usar estos relays DHCP como proxies completos."
 
-#: option.c:442
+#: option.c:457
 msgid "Relay DHCP requests to a remote server"
 msgstr ""
 
-#: option.c:443
+#: option.c:458
 msgid "Specify alias name for LOCAL DNS name."
 msgstr "Especificar nombre alias para nombre DNS LOCAL."
 
-#: option.c:444
+#: option.c:459
 #, fuzzy
 msgid "Prompt to send to PXE clients."
 msgstr "Aviso a ser enviado a clientes PXE."
 
-#: option.c:445
+#: option.c:460
 msgid "Boot service for PXE menu."
 msgstr "Servicio de arranque para menú PXE."
 
-#: option.c:446
+#: option.c:461
 msgid "Check configuration syntax."
 msgstr "Revisar sintaxis de configuración."
 
-#: option.c:447
+#: option.c:462
 msgid "Add requestor's MAC address to forwarded DNS queries."
 msgstr "Añadir direcciones MAC de los peticionarios a los filtros DNS enviados"
 
-#: option.c:448
+#: option.c:463
 #, fuzzy
-msgid "Add requestor's IP subnet to forwarded DNS queries."
+msgid "Add specified IP subnet to forwarded DNS queries."
 msgstr "Añadir direcciones MAC de los peticionarios a los filtros DNS enviados"
 
-#: option.c:449
+#: option.c:464
+#, fuzzy
+msgid "Add client identification to forwarded DNS queries."
+msgstr "Añadir direcciones MAC de los peticionarios a los filtros DNS enviados"
+
+#: option.c:465
 #, fuzzy
 msgid "Proxy DNSSEC validation results from upstream nameservers."
 msgstr "Traducir direcciones IPv4 desde servidores subida."
 
-#: option.c:450
+#: option.c:466
 msgid "Attempt to allocate sequential IP addresses to DHCP clients."
 msgstr "Intento de instaurar direcciones IP secuenciales a cliente DHCP"
 
-#: option.c:451
+#: option.c:467
 msgid "Copy connection-track mark from queries to upstream connections."
 msgstr "Copiar la marca de connection-track desde los filtros a las conexiones salientes"
 
-#: option.c:452
+#: option.c:468
 msgid "Allow DHCP clients to do their own DDNS updates."
 msgstr "Permite a clientes DHCP realizar sus propias actualizaciones DDNS"
 
-#: option.c:453
+#: option.c:469
 msgid "Send router-advertisements for interfaces doing DHCPv6"
 msgstr "Enviar anuncios del router a los interfases realizando DHCPv6"
 
-#: option.c:454
+#: option.c:470
 msgid "Specify DUID_EN-type DHCPv6 server DUID"
 msgstr ""
 
-#: option.c:455
+#: option.c:471
 #, fuzzy
 msgid "Specify host (A/AAAA and PTR) records"
 msgstr "Especificar un expediente MX."
 
-#: option.c:456
+#: option.c:472
 #, fuzzy
 msgid "Specify arbitrary DNS resource record"
 msgstr "Especificar expediente DNS TXT."
 
-#: option.c:457
+#: option.c:473
 #, fuzzy
 msgid "Bind to interfaces in use - check for new interfaces"
 msgstr "interfase desconocida %s en bridge-interfase"
 
-#: option.c:458
+#: option.c:474
 msgid "Export local names to global DNS"
 msgstr "Exportar nombres DNS locales a globales"
 
-#: option.c:459
+#: option.c:475
 msgid "Domain to export to global DNS"
 msgstr "Dominio a exportar a DNS global"
 
-#: option.c:460
+#: option.c:476
 msgid "Set TTL for authoritative replies"
 msgstr "Fijar TTL para respuestas autoritarias"
 
-#: option.c:461
-msgid "Set authoritive zone information"
+#: option.c:477
+#, fuzzy
+msgid "Set authoritative zone information"
 msgstr "Fijar información de zona autoritaria"
 
-#: option.c:462
+#: option.c:478
 msgid "Secondary authoritative nameservers for forward domains"
 msgstr "Nombres de servidor secundario autoritatorios para dominios enviados"
 
-#: option.c:463
+#: option.c:479
 msgid "Peers which are allowed to do zone transfer"
 msgstr "Colegas autorizados a la zona de transferencia (transfer)"
 
-#: option.c:464
+#: option.c:480
 msgid "Specify ipsets to which matching domains should be added"
 msgstr "Especificar los ipsets coincidentes en dominio que debrían ser añadidos"
 
-#: option.c:465
+#: option.c:481
 #, fuzzy
 msgid "Specify a domain and address range for synthesised names"
 msgstr "Especificar dominio y rango de direcciones para los nombres acrónimos"
 
-#: option.c:466
+#: option.c:482
 msgid "Activate DNSSEC validation"
 msgstr ""
 
-#: option.c:467
+#: option.c:483
 msgid "Specify trust anchor key digest."
 msgstr ""
 
-#: option.c:468
+#: option.c:484
 msgid "Disable upstream checking for DNSSEC debugging."
 msgstr ""
 
-#: option.c:469
+#: option.c:485
 msgid "Ensure answers without DNSSEC are in unsigned zones."
 msgstr ""
 
-#: option.c:470
+#: option.c:486
 msgid "Don't check DNSSEC signature timestamps until first cache-reload"
 msgstr ""
 
-#: option.c:471
+#: option.c:487
 msgid "Timestamp file to verify system clock for DNSSEC"
 msgstr ""
 
-#: option.c:473
+#: option.c:489
 msgid "Specify DHCPv6 prefix class"
 msgstr "Especificar prefijo de clase DHCPv6"
 
-#: option.c:475
-msgid "Set priority, resend-interval and router-lifetime"
+#: option.c:491
+msgid "Set MTU, priority, resend-interval and router-lifetime"
 msgstr ""
 
-#: option.c:476
+#: option.c:492
 msgid "Do not log routine DHCP."
 msgstr ""
 
-#: option.c:477
+#: option.c:493
 msgid "Do not log routine DHCPv6."
 msgstr ""
 
-#: option.c:478
+#: option.c:494
 msgid "Do not log RA."
 msgstr ""
 
-#: option.c:479
-msgid "Accept queries only from directly-connected networks"
+#: option.c:495
+msgid "Accept queries only from directly-connected networks."
 msgstr ""
 
-#: option.c:480
-msgid "Detect and remove DNS forwarding loops"
+#: option.c:496
+msgid "Detect and remove DNS forwarding loops."
 msgstr ""
 
-#: option.c:481
+#: option.c:497
 msgid "Ignore DNS responses containing ipaddr."
 msgstr ""
 
-#: option.c:683
+#: option.c:498
+msgid "Set TTL in DNS responses with DHCP-derived addresses."
+msgstr ""
+
+#: option.c:499
+msgid "Delay DHCP replies for at least number of seconds."
+msgstr ""
+
+#: option.c:703
 #, c-format
 msgid ""
 "Usage: dnsmasq [options]\n"
@@ -764,335 +794,344 @@ msgstr ""
 "Modo de uso: dnsmasq [opciones]\n"
 "\n"
 
-#: option.c:685
+#: option.c:705
 #, c-format
 msgid "Use short options only on the command line.\n"
 msgstr "Usar opciones cortas solo en la línea de comandos.\n"
 
-#: option.c:687
+#: option.c:707
 #, fuzzy, c-format
 msgid "Valid options are:\n"
 msgstr "Opciones válidas son :\n"
 
-#: option.c:744 option.c:748
+#: option.c:754 option.c:868
+#, fuzzy
+msgid "bad address"
+msgstr "dirección IP errónea"
+
+#: option.c:779 option.c:783
 msgid "bad port"
 msgstr "puerto erróneo"
 
-#: option.c:775 option.c:807
+#: option.c:797 option.c:826 option.c:861
 msgid "interface binding not supported"
 msgstr "vinculación de interfase no está soportado"
 
-#: option.c:784 option.c:3575
+#: option.c:821 option.c:856
+msgid "interface can only be specified once"
+msgstr ""
+
+#: option.c:835 option.c:3809
 #, fuzzy
 msgid "bad interface name"
 msgstr "nombre de interfase erróneo"
 
-#: option.c:814
-#, fuzzy
-msgid "bad address"
-msgstr "dirección IP errónea"
-
-#: option.c:996
+#: option.c:1062
 msgid "unsupported encapsulation for IPv6 option"
 msgstr "Encapsulación no soportada para opción IPv6"
 
-#: option.c:1010
+#: option.c:1076
 msgid "bad dhcp-option"
 msgstr "opción dhcp-option errónea"
 
-#: option.c:1078
+#: option.c:1144
 #, fuzzy
 msgid "bad IP address"
 msgstr "dirección IP errónea"
 
-#: option.c:1081 option.c:1219 option.c:2893
+#: option.c:1147 option.c:1286 option.c:3079
 #, fuzzy
 msgid "bad IPv6 address"
 msgstr "dirección IP errónea"
 
-#: option.c:1246 option.c:1340
+#: option.c:1240
+#, fuzzy
+msgid "bad IPv4 address"
+msgstr "dirección IP errónea"
+
+#: option.c:1313 option.c:1407
 msgid "bad domain in dhcp-option"
 msgstr "dominio erróneo en dhcp-option"
 
-#: option.c:1378
+#: option.c:1445
 msgid "dhcp-option too long"
 msgstr "opción dhcp-option demasiado larga"
 
-#: option.c:1385
+#: option.c:1452
 msgid "illegal dhcp-match"
 msgstr "dhcp-match ilegal"
 
-#: option.c:1447
+#: option.c:1514
 msgid "illegal repeated flag"
 msgstr "opción repetida ilegal"
 
-#: option.c:1455
+#: option.c:1522
 msgid "illegal repeated keyword"
 msgstr "palabra clave repetida ilegal"
 
-#: option.c:1520 option.c:4191
+#: option.c:1593 option.c:4443
 #, fuzzy, c-format
 msgid "cannot access directory %s: %s"
 msgstr "no se puede acceder a directorio %s: %s"
 
-#: option.c:1566 tftp.c:493
+#: option.c:1639 tftp.c:537
 #, fuzzy, c-format
 msgid "cannot access %s: %s"
 msgstr "no se puede acceder %s: %s"
 
-#: option.c:1618
+#: option.c:1727
 msgid "setting log facility is not possible under Android"
 msgstr "la creación de un registro no es posible en Android"
 
-#: option.c:1627
+#: option.c:1736
 msgid "bad log facility"
 msgstr "ubicación del registro errónea"
 
-#: option.c:1680
+#: option.c:1789
 msgid "bad MX preference"
 msgstr "preferencia MX errónea"
 
-#: option.c:1685
+#: option.c:1794
 msgid "bad MX name"
 msgstr "nombre MX erróneo"
 
-#: option.c:1699
+#: option.c:1808
 msgid "bad MX target"
 msgstr "destino MX erróneo"
 
-#: option.c:1711
+#: option.c:1820
 msgid "cannot run scripts under uClinux"
 msgstr "no se pueden correr archivos 'script' bajo uClinux"
 
-#: option.c:1713
+#: option.c:1822
 msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
 msgstr "recompilar con HAVE_SCRIPT definido para habilitar guiónes de cambio de concesión"
 
-#: option.c:1717
+#: option.c:1826
 #, fuzzy
 msgid "recompile with HAVE_LUASCRIPT defined to enable Lua scripts"
 msgstr "recompilar con HAVE_SCRIPT definido para habilitar 'scripts' en Lua"
 
-#: option.c:1973 option.c:2018 option.c:2074
+#: option.c:2095 option.c:2106 option.c:2143 option.c:2199 option.c:2482
 #, fuzzy
 msgid "bad prefix"
 msgstr "prefijo erróneo"
 
-#: option.c:2355
+#: option.c:2504
 #, fuzzy
 msgid "recompile with HAVE_IPSET defined to enable ipset directives"
 msgstr "recompilar con HAVE_SCRIPT definido para habilitar directivas ipset"
 
-#: option.c:2548
+#: option.c:2713
 #, fuzzy
 msgid "bad port range"
 msgstr "rango de puertos erróneo"
 
-#: option.c:2564
+#: option.c:2739
 msgid "bad bridge-interface"
 msgstr "opción bridge-interface (interfase puente) errónea"
 
-#: option.c:2624
+#: option.c:2807
 msgid "only one tag allowed"
 msgstr "solo una etiqueta permitida"
 
-#: option.c:2644 option.c:2656 option.c:2764 option.c:2805
+#: option.c:2827 option.c:2839 option.c:2948 option.c:2953 option.c:2992
 msgid "bad dhcp-range"
 msgstr "opción dhcp-range (rango DHCP) errónea"
 
-#: option.c:2671
+#: option.c:2854
 msgid "inconsistent DHCP range"
 msgstr "rango DHCP inconsistente"
 
-#: option.c:2732
+#: option.c:2916
 msgid "prefix length must be exactly 64 for RA subnets"
 msgstr "la longitud del prefijo debe ser 64 exacto para subredes RA"
 
-#: option.c:2734
+#: option.c:2918
 msgid "prefix length must be exactly 64 for subnet constructors"
 msgstr "la longitud del prefijo debe ser 64 exacto para subredes constructoras"
 
-#: option.c:2738
+#: option.c:2922
 msgid "prefix length must be at least 64"
 msgstr "la longitud del prefijo debe ser al menos 64"
 
-#: option.c:2741
+#: option.c:2925
 #, fuzzy
 msgid "inconsistent DHCPv6 range"
 msgstr "rango DHCP inconsistente"
 
-#: option.c:2752
+#: option.c:2936
 msgid "prefix must be zero with \"constructor:\" argument"
 msgstr "prefijo debe ser cero con argumento \"constructor:\""
 
-#: option.c:2863 option.c:2911
+#: option.c:3049 option.c:3097
 #, fuzzy
 msgid "bad hex constant"
 msgstr "constante hexadecimal errónea"
 
-#: option.c:2885
+#: option.c:3071
 msgid "cannot match tags in --dhcp-host"
 msgstr "no coinciden etiquetas en --dhcp-host"
 
-#: option.c:2933
+#: option.c:3119
 #, fuzzy, c-format
 msgid "duplicate dhcp-host IP address %s"
 msgstr "dirección IP duplicada %s en %s."
 
-#: option.c:2991
+#: option.c:3177
 #, fuzzy
 msgid "bad DHCP host name"
 msgstr "nombre de host DHCP erróneo"
 
-#: option.c:3073
+#: option.c:3259
 #, fuzzy
 msgid "bad tag-if"
 msgstr "etiqueta tag-if errónea"
 
-#: option.c:3397 option.c:3791
+#: option.c:3616 option.c:4039
 msgid "invalid port number"
 msgstr "número de puerto inválido"
 
-#: option.c:3459
+#: option.c:3678
 #, fuzzy
 msgid "bad dhcp-proxy address"
 msgstr "dirección IP errónea"
 
-#: option.c:3485
+#: option.c:3704
 #, fuzzy
 msgid "Bad dhcp-relay"
 msgstr "opción dhcp-range (rango DHCP) errónea"
 
-#: option.c:3511
+#: option.c:3745
 msgid "bad RA-params"
 msgstr ""
 
-#: option.c:3520
+#: option.c:3754
 msgid "bad DUID"
 msgstr "DUID erróneo"
 
-#: option.c:3562
+#: option.c:3796
 #, fuzzy
 msgid "invalid alias range"
 msgstr "rango alias inválido"
 
-#: option.c:3616
+#: option.c:3850 option.c:3862
 msgid "bad CNAME"
 msgstr "CNAME erróneo"
 
-#: option.c:3621
+#: option.c:3866
 msgid "duplicate CNAME"
 msgstr "CNAME duplicado"
 
-#: option.c:3641
+#: option.c:3889
 #, fuzzy
 msgid "bad PTR record"
 msgstr "registro PTR erróneo"
 
-#: option.c:3672
+#: option.c:3920
 #, fuzzy
 msgid "bad NAPTR record"
 msgstr "registro NAPTR erróneo"
 
-#: option.c:3706
+#: option.c:3954
 #, fuzzy
 msgid "bad RR record"
 msgstr "registro PTR erróneo"
 
-#: option.c:3736
+#: option.c:3984
 msgid "bad TXT record"
 msgstr "registro TXT erróneo"
 
-#: option.c:3777
+#: option.c:4025
 msgid "bad SRV record"
 msgstr "registro SRV erróneo"
 
-#: option.c:3784
+#: option.c:4032
 msgid "bad SRV target"
 msgstr "destino SRV erróneo"
 
-#: option.c:3798
+#: option.c:4046
 msgid "invalid priority"
 msgstr "prioridad inválida"
 
-#: option.c:3805
+#: option.c:4049
 msgid "invalid weight"
 msgstr "peso inválido"
 
-#: option.c:3829
+#: option.c:4073
 #, fuzzy
 msgid "Bad host-record"
 msgstr "registro PTR erróneo"
 
-#: option.c:3846
+#: option.c:4097
 #, fuzzy
 msgid "Bad name in host-record"
 msgstr "nombre erróneo en %s"
 
-#: option.c:3911
+#: option.c:4162
 #, fuzzy
 msgid "bad trust anchor"
 msgstr "rango de puertos erróneo"
 
-#: option.c:3925
+#: option.c:4176
 msgid "bad HEX in trust anchor"
 msgstr ""
 
-#: option.c:3935
+#: option.c:4186
 #, fuzzy
 msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"
 msgstr "opción no soportada (verificar que dnsmasq fue compilado con soporte para DHCP/TFTP/DBus)"
 
-#: option.c:3994
+#: option.c:4246
 msgid "missing \""
 msgstr "falta \""
 
-#: option.c:4051
+#: option.c:4303
 msgid "bad option"
 msgstr "opción errónea"
 
-#: option.c:4053
+#: option.c:4305
 msgid "extraneous parameter"
 msgstr "parámetro extraño"
 
-#: option.c:4055
+#: option.c:4307
 msgid "missing parameter"
 msgstr "parámetro ausente"
 
-#: option.c:4057
+#: option.c:4309
 #, fuzzy
 msgid "illegal option"
 msgstr "opción errónea"
 
-#: option.c:4064
+#: option.c:4316
 msgid "error"
 msgstr "error"
 
-#: option.c:4066
+#: option.c:4318
 #, fuzzy, c-format
 msgid " at line %d of %s"
 msgstr "%s en línea %d de %%s"
 
-#: option.c:4081 option.c:4328 option.c:4364
+#: option.c:4333 option.c:4580 option.c:4616
 #, fuzzy, c-format
 msgid "read %s"
 msgstr "lee %s"
 
-#: option.c:4144 option.c:4267 tftp.c:667
+#: option.c:4396 option.c:4519 tftp.c:715
 #, c-format
 msgid "cannot read %s: %s"
 msgstr "no se puede leer %s: %s"
 
-#: option.c:4430
+#: option.c:4688
 msgid "junk found in command line"
 msgstr "basura encontrada en linea de comando"
 
-#: option.c:4465
+#: option.c:4729
 #, c-format
 msgid "Dnsmasq version %s  %s\n"
 msgstr "Versión dnsmasq %s  %s\n"
 
-#: option.c:4466
+#: option.c:4730
 #, fuzzy, c-format
 msgid ""
 "Compile time options: %s\n"
@@ -1101,469 +1140,511 @@ msgstr ""
 "Opciones de compilación %s\n"
 "\n"
 
-#: option.c:4467
+#: option.c:4731
 #, c-format
 msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
 msgstr "Este software viene SIN NINGUNA GARANTIA.\n"
 
-#: option.c:4468
+#: option.c:4732
 #, c-format
 msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
 msgstr "Dnsmasq es software libre, y usted está autorizado a redistribuirlo\n"
 
-#: option.c:4469
+#: option.c:4733
 #, fuzzy, c-format
 msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
 msgstr "bajo los términos de la GNU General Public License, versión 2 o 3.\n"
 
-#: option.c:4480
+#: option.c:4744
 msgid "try --help"
 msgstr "pruebe --help"
 
-#: option.c:4482
+#: option.c:4746
 msgid "try -w"
 msgstr "pruebe -w"
 
-#: option.c:4484
+#: option.c:4748
 #, fuzzy, c-format
 msgid "bad command line options: %s"
 msgstr "opciones de línea de comandos erróneas: %s"
 
-#: option.c:4541
+#: option.c:4818
+#, c-format
+msgid "CNAME loop involving %s"
+msgstr ""
+
+#: option.c:4854
 #, c-format
 msgid "cannot get host-name: %s"
 msgstr "no se puede obtener host-name (nombre de host): %s"
 
-#: option.c:4569
+#: option.c:4882
 msgid "only one resolv.conf file allowed in no-poll mode."
 msgstr "solo un archivo resolv.conf está permitido en modo no-poll."
 
-#: option.c:4579
+#: option.c:4892
 msgid "must have exactly one resolv.conf to read domain from."
 msgstr "debe haber exáctamente un resolv.conf desde donde leer dominio."
 
-#: option.c:4582 network.c:1507 dhcp.c:777
+#: option.c:4895 network.c:1623 dhcp.c:816
 #, fuzzy, c-format
 msgid "failed to read %s: %s"
 msgstr "no se pudo leer %s: %s"
 
-#: option.c:4599
+#: option.c:4912
 #, c-format
 msgid "no search directive found in %s"
 msgstr "ninguna directiva de búsqueda encontrada en %s"
 
-#: option.c:4620
+#: option.c:4933
 #, fuzzy
 msgid "there must be a default domain when --dhcp-fqdn is set"
 msgstr "debe haber un dominio predeterminado cuando --dhcp-fqdn está fijado"
 
-#: option.c:4629
+#: option.c:4942
 msgid "syntax check OK"
 msgstr "revisión de sintaxis OK"
 
-#: forward.c:111
+#: forward.c:102
 #, fuzzy, c-format
 msgid "failed to send packet: %s"
 msgstr "no se pudo escuchar en socket: %s"
 
-#: forward.c:591
+#: forward.c:598
 msgid "discarding DNS reply: subnet option mismatch"
 msgstr ""
 
-#: forward.c:614
+#: forward.c:652
 #, c-format
 msgid "nameserver %s refused to do a recursive query"
 msgstr "servidor DNS %s rechazó realizar una búsqueda recursiva"
 
-#: forward.c:646
+#: forward.c:684
 #, fuzzy, c-format
 msgid "possible DNS-rebind attack detected: %s"
 msgstr "posible ataque de revinculación DNS detectado"
 
-#: forward.c:1209 forward.c:1815
+#: forward.c:870
+#, c-format
+msgid "reducing DNS packet size for nameserver %s to %d"
+msgstr ""
+
+#: forward.c:1266 forward.c:1704
 msgid "Ignoring query from non-local network"
 msgstr ""
 
-#: forward.c:2286
+#: forward.c:2184
 #, fuzzy, c-format
 msgid "Maximum number of concurrent DNS queries reached (max: %d)"
 msgstr "Número máximo de búsquedas DNS simultáneas alcanzado. (%s por predeterminado)"
 
-#: network.c:715
+#: network.c:720
 #, fuzzy, c-format
 msgid "failed to create listening socket for %s: %s"
 msgstr "no se pudo crear un zócalo de escucha: %s"
 
-#: network.c:1021
+#: network.c:1031
 #, c-format
 msgid "LOUD WARNING: listening on %s may accept requests via interfaces other than %s"
 msgstr ""
 
-#: network.c:1028
+#: network.c:1038
 msgid "LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"
 msgstr ""
 
-#: network.c:1037
+#: network.c:1047
+#, fuzzy, c-format
+msgid "warning: using interface %s instead"
+msgstr "advertencia: interfase %s no existe actualmente"
+
+#: network.c:1056
 #, fuzzy, c-format
 msgid "warning: no addresses found for interface %s"
 msgstr "usando direcciones locales solo para %s %s"
 
-#: network.c:1095
+#: network.c:1114
 #, fuzzy, c-format
 msgid "interface %s failed to join DHCPv6 multicast group: %s"
 msgstr "el interfase % falló al unirse al grupo multicast DHCPv6: %s"
 
-#: network.c:1289
+#: network.c:1119
+msgid "try increasing /proc/sys/net/core/optmem_max"
+msgstr ""
+
+#: network.c:1337
 #, fuzzy, c-format
 msgid "failed to bind server socket for %s: %s"
 msgstr "no se pudo acoplar al zócalo del servidor para %s: %s"
 
-#: network.c:1445
+#: network.c:1528
 #, c-format
 msgid "ignoring nameserver %s - local interface"
 msgstr "ignorando servidor DNS %s - interfase local"
 
-#: network.c:1456
+#: network.c:1539
 #, fuzzy, c-format
 msgid "ignoring nameserver %s - cannot make/bind socket: %s"
 msgstr "ignorando servidor DNS %s - no se puede crear/acoplar zócalo: %s"
 
-#: network.c:1469
+#: network.c:1559
+msgid "(no DNSSEC)"
+msgstr ""
+
+#: network.c:1562
 msgid "unqualified"
 msgstr "no cualificado"
 
-#: network.c:1469
+#: network.c:1562
 msgid "names"
 msgstr "nombres"
 
-#: network.c:1471
+#: network.c:1564
 msgid "default"
 msgstr "predeterminado"
 
-#: network.c:1473
+#: network.c:1566
 msgid "domain"
 msgstr "dominio"
 
-#: network.c:1476
+#: network.c:1572
 #, c-format
 msgid "using local addresses only for %s %s"
 msgstr "usando direcciones locales solo para %s %s"
 
-#: network.c:1478
+#: network.c:1575
 #, fuzzy, c-format
 msgid "using standard nameservers for %s %s"
 msgstr "usando nombres estándar %s#%d para %s %s"
 
-#: network.c:1480
-#, c-format
-msgid "using nameserver %s#%d for %s %s"
+#: network.c:1577
+#, fuzzy, c-format
+msgid "using nameserver %s#%d for %s %s %s"
 msgstr "usando nombre de servidor %s#%d para %s %s"
 
-#: network.c:1484
+#: network.c:1581
 #, fuzzy, c-format
 msgid "NOT using nameserver %s#%d - query loop detected"
 msgstr "usando nombre de servidor %s#%d para %s %s"
 
-#: network.c:1487
+#: network.c:1584
 #, fuzzy, c-format
 msgid "using nameserver %s#%d(via %s)"
 msgstr "usando nombre de servidor %s#%d(vía %s)"
 
-#: network.c:1489
+#: network.c:1586
 #, c-format
 msgid "using nameserver %s#%d"
 msgstr "usando nombre de servidor %s#%d"
 
-#: dnsmasq.c:163
+#: network.c:1591
+#, fuzzy, c-format
+msgid "using %d more local addresses"
+msgstr "usando nombre de servidor %s#%d"
+
+#: network.c:1593
+#, fuzzy, c-format
+msgid "using %d more nameservers"
+msgstr "usando nombre de servidor %s#%d"
+
+#: dnsmasq.c:171
 msgid "dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"
 msgstr ""
 
-#: dnsmasq.c:170
-msgid "no trust anchors provided for DNSSEC"
+#: dnsmasq.c:186
+msgid "no root trust anchor provided for DNSSEC"
 msgstr ""
 
-#: dnsmasq.c:173
+#: dnsmasq.c:189
 msgid "cannot reduce cache size from default when DNSSEC enabled"
 msgstr ""
 
-#: dnsmasq.c:175
+#: dnsmasq.c:191
 #, fuzzy
 msgid "DNSSEC not available: set HAVE_DNSSEC in src/config.h"
 msgstr "DBus no disponible: fijar HAVE_DBUS en src/config.h"
 
-#: dnsmasq.c:181
+#: dnsmasq.c:197
 #, fuzzy
 msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
 msgstr "servidor TFTP no disponible: fijar HAVE_TFTP en src/config.h"
 
-#: dnsmasq.c:186
+#: dnsmasq.c:202
 #, fuzzy
 msgid "cannot use --conntrack AND --query-port"
 msgstr "No puede usar --conntrack AND --query-port"
 
-#: dnsmasq.c:189
+#: dnsmasq.c:205
 #, fuzzy
 msgid "conntrack support not available: set HAVE_CONNTRACK in src/config.h"
 msgstr "servidor TFTP no disponible: fijar HAVE_TFTP en src/config.h"
 
-#: dnsmasq.c:194
+#: dnsmasq.c:210
 #, fuzzy
-msgid "asychronous logging is not available under Solaris"
+msgid "asynchronous logging is not available under Solaris"
 msgstr "registro asíncrono no está disponible bajo Solaris"
 
-#: dnsmasq.c:199
+#: dnsmasq.c:215
 #, fuzzy
-msgid "asychronous logging is not available under Android"
+msgid "asynchronous logging is not available under Android"
 msgstr "registro asíncrono no está disponible bajo Solaris"
 
-#: dnsmasq.c:204
+#: dnsmasq.c:220
 #, fuzzy
 msgid "authoritative DNS not available: set HAVE_AUTH in src/config.h"
 msgstr "DBus no disponible: fijar HAVE_DBUS en src/config.h"
 
-#: dnsmasq.c:209
+#: dnsmasq.c:225
 #, fuzzy
 msgid "loop detection not available: set HAVE_LOOP in src/config.h"
 msgstr "servidor TFTP no disponible: fijar HAVE_TFTP en src/config.h"
 
-#: dnsmasq.c:217
+#: dnsmasq.c:229
+msgid "max_port cannot be smaller than min_port"
+msgstr ""
+
+#: dnsmasq.c:236
 msgid "zone serial must be configured in --auth-soa"
 msgstr "zona serie debe ser configurada en --auth-soa"
 
-#: dnsmasq.c:235
+#: dnsmasq.c:254
 msgid "dhcp-range constructor not available on this platform"
 msgstr "constructor rango dhcp no disponible en esta plataforma"
 
-#: dnsmasq.c:278
+#: dnsmasq.c:300
 msgid "cannot set --bind-interfaces and --bind-dynamic"
 msgstr "no puede usar --bind-interfases y --bind-dynamic"
 
-#: dnsmasq.c:281
+#: dnsmasq.c:303
 #, c-format
 msgid "failed to find list of interfaces: %s"
 msgstr "no se pudo encontrar lista de interfases: %s"
 
-#: dnsmasq.c:290
+#: dnsmasq.c:312
 #, c-format
 msgid "unknown interface %s"
 msgstr "interfase desconocida %s"
 
-#: dnsmasq.c:354 dnsmasq.c:997
+#: dnsmasq.c:377 dnsmasq.c:1054
 #, c-format
 msgid "DBus error: %s"
 msgstr "error DBus: %s"
 
-#: dnsmasq.c:357
+#: dnsmasq.c:380
 msgid "DBus not available: set HAVE_DBUS in src/config.h"
 msgstr "DBus no disponible: fijar HAVE_DBUS en src/config.h"
 
-#: dnsmasq.c:385
+#: dnsmasq.c:410
 #, c-format
 msgid "unknown user or group: %s"
 msgstr "usuario o grupo desconocido: %s"
 
-#: dnsmasq.c:440
+#: dnsmasq.c:465
 #, c-format
 msgid "cannot chdir to filesystem root: %s"
 msgstr "no se puede cambiar directorio a raíz de sistema de archivos: %s"
 
-#: dnsmasq.c:692
+#: dnsmasq.c:730
 #, fuzzy, c-format
 msgid "started, version %s DNS disabled"
 msgstr "iniciado, versión %s DNS deshabilitado"
 
-#: dnsmasq.c:694
+#: dnsmasq.c:734
 #, c-format
 msgid "started, version %s cachesize %d"
 msgstr "iniciado, versión %s tamaño de caché %d"
 
-#: dnsmasq.c:696
+#: dnsmasq.c:736
 #, c-format
 msgid "started, version %s cache disabled"
 msgstr "iniciado, versión %s caché deshabilitado"
 
-#: dnsmasq.c:698
+#: dnsmasq.c:739
+msgid "DNS service limited to local subnets"
+msgstr ""
+
+#: dnsmasq.c:742
 #, c-format
 msgid "compile time options: %s"
 msgstr "opciones de compilación: %s"
 
-#: dnsmasq.c:704
+#: dnsmasq.c:751
 msgid "DBus support enabled: connected to system bus"
 msgstr "soporte DBus habilitado: conectado a bus de sistema"
 
-#: dnsmasq.c:706
+#: dnsmasq.c:753
 msgid "DBus support enabled: bus connection pending"
 msgstr "soporte DBus habilitado: conexión a bus pendiente"
 
-#: dnsmasq.c:711
-msgid "DNS service limited to local subnets"
-msgstr ""
-
-#: dnsmasq.c:727
+#: dnsmasq.c:771
 msgid "DNSSEC validation enabled"
 msgstr ""
 
-#: dnsmasq.c:730
-msgid "DNSSEC signature timestamps not checked until first cache reload"
+#: dnsmasq.c:775
+msgid "DNSSEC signature timestamps not checked until receipt of SIGINT"
 msgstr ""
 
-#: dnsmasq.c:733
+#: dnsmasq.c:778
 msgid "DNSSEC signature timestamps not checked until system time valid"
 msgstr ""
 
-#: dnsmasq.c:738
+#: dnsmasq.c:783
 #, fuzzy, c-format
 msgid "warning: failed to change owner of %s: %s"
 msgstr "advertencia: no se pudo cambiar propietario de %s: %s"
 
-#: dnsmasq.c:742
+#: dnsmasq.c:787
 msgid "setting --bind-interfaces option because of OS limitations"
 msgstr "fijando opción --bind-interfases debido a limitaciones de sistema operativo"
 
-#: dnsmasq.c:752
+#: dnsmasq.c:799
 #, c-format
 msgid "warning: interface %s does not currently exist"
 msgstr "advertencia: interfase %s no existe actualmente"
 
-#: dnsmasq.c:757
+#: dnsmasq.c:804
 msgid "warning: ignoring resolv-file flag because no-resolv is set"
 msgstr "advertencia: ignorando opción resolv-file porque no-resolv está fijado"
 
-#: dnsmasq.c:760
+#: dnsmasq.c:807
 #, fuzzy
 msgid "warning: no upstream servers configured"
 msgstr "advertencia: ningún servidor de subida configurado"
 
-#: dnsmasq.c:764
+#: dnsmasq.c:811
 #, c-format
 msgid "asynchronous logging enabled, queue limit is %d messages"
 msgstr "registro asíncrono habilitado, el límite de la cola es %d mensajes"
 
-#: dnsmasq.c:785
+#: dnsmasq.c:832
 msgid "IPv6 router advertisement enabled"
 msgstr "Anuncio de router IPv6 habilitado"
 
-#: dnsmasq.c:790
+#: dnsmasq.c:837
 #, c-format
 msgid "DHCP, sockets bound exclusively to interface %s"
 msgstr ""
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "root is "
 msgstr "root está "
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 #, fuzzy
 msgid "enabled"
 msgstr "habilitado"
 
-#: dnsmasq.c:806
+#: dnsmasq.c:853
 msgid "secure mode"
 msgstr "modo seguro"
 
-#: dnsmasq.c:809
+#: dnsmasq.c:856
 #, c-format
 msgid "warning: %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:813
+#: dnsmasq.c:860
 #, fuzzy, c-format
 msgid "warning: TFTP directory %s inaccessible"
 msgstr "directorio TFTP % inaccesible: %s"
 
-#: dnsmasq.c:839
+#: dnsmasq.c:886
 #, c-format
 msgid "restricting maximum simultaneous TFTP transfers to %d"
 msgstr "limitando número máximo de transferencias TFTP simultáneas a %d"
 
-#: dnsmasq.c:999
+#: dnsmasq.c:1056
 msgid "connected to system DBus"
 msgstr "conectado a DBus de sistema"
 
-#: dnsmasq.c:1149
+#: dnsmasq.c:1215
 #, c-format
 msgid "cannot fork into background: %s"
 msgstr "no se puede hacer fork en background: %s"
 
-#: dnsmasq.c:1152
+#: dnsmasq.c:1218
 #, fuzzy, c-format
 msgid "failed to create helper: %s"
 msgstr "no se pudo crear ayudante: %s"
 
-#: dnsmasq.c:1155
+#: dnsmasq.c:1221
 #, fuzzy, c-format
 msgid "setting capabilities failed: %s"
 msgstr "configuración de capacidades ha fallado: %s"
 
-#: dnsmasq.c:1158
+#: dnsmasq.c:1224
 #, fuzzy, c-format
 msgid "failed to change user-id to %s: %s"
 msgstr "no se pudo cambiar user-id a %s: %s"
 
-#: dnsmasq.c:1161
+#: dnsmasq.c:1227
 #, fuzzy, c-format
 msgid "failed to change group-id to %s: %s"
 msgstr "no se pudo cambiar group-id a %s: %s"
 
-#: dnsmasq.c:1164
+#: dnsmasq.c:1230
 #, fuzzy, c-format
 msgid "failed to open pidfile %s: %s"
 msgstr "no se pudo abrir archivo PID %s: %s"
 
-#: dnsmasq.c:1167
+#: dnsmasq.c:1233
 #, fuzzy, c-format
 msgid "cannot open log %s: %s"
 msgstr "no se puede abrir registro %s: %s"
 
-#: dnsmasq.c:1170
+#: dnsmasq.c:1236
 #, fuzzy, c-format
 msgid "failed to load Lua script: %s"
 msgstr "no se pudo cargar script Lua %s: %s"
 
-#: dnsmasq.c:1173
+#: dnsmasq.c:1239
 #, c-format
 msgid "TFTP directory %s inaccessible: %s"
 msgstr "directorio TFTP % inaccesible: %s"
 
-#: dnsmasq.c:1176
+#: dnsmasq.c:1242
 #, fuzzy, c-format
 msgid "cannot create timestamp file %s: %s"
 msgstr "no se puede abrir o crear archivo de concesión %s: %s"
 
-#: dnsmasq.c:1197
-msgid "now checking DNSSEC signature timestamps"
-msgstr ""
-
-#: dnsmasq.c:1264
+#: dnsmasq.c:1326
 #, fuzzy, c-format
 msgid "script process killed by signal %d"
 msgstr "proceso script eliminado por señal %d"
 
-#: dnsmasq.c:1268
+#: dnsmasq.c:1330
 #, fuzzy, c-format
 msgid "script process exited with status %d"
 msgstr "proceso script salió con con estado %d"
 
-#: dnsmasq.c:1272
+#: dnsmasq.c:1334
 #, fuzzy, c-format
 msgid "failed to execute %s: %s"
 msgstr "no se pudo ejecutar %s: %s"
 
-#: dnsmasq.c:1327
+#: dnsmasq.c:1374
+msgid "now checking DNSSEC signature timestamps"
+msgstr ""
+
+#: dnsmasq.c:1409 dnssec.c:160 dnssec.c:206
+#, fuzzy, c-format
+msgid "failed to update mtime on %s: %s"
+msgstr "no se pudo abrir archivo PID %s: %s"
+
+#: dnsmasq.c:1416
 msgid "exiting on receipt of SIGTERM"
 msgstr "saliendo al recibir SIGTERM"
 
-#: dnsmasq.c:1355
+#: dnsmasq.c:1444
 #, fuzzy, c-format
 msgid "failed to access %s: %s"
 msgstr "no se pudo acceder %s: %s"
 
-#: dnsmasq.c:1385
+#: dnsmasq.c:1474
 #, c-format
 msgid "reading %s"
 msgstr "leyendo %s"
 
-#: dnsmasq.c:1396
+#: dnsmasq.c:1485
 #, fuzzy, c-format
 msgid "no servers found in %s, will retry"
 msgstr "ningún servidor encontrado en %s, se reintentará"
@@ -1593,243 +1674,263 @@ msgstr "no se pudo acoplar z
 msgid "cannot create ICMP raw socket: %s."
 msgstr "no se puede crear zócalo puro ICMP: %s."
 
-#: dhcp.c:241 dhcp6.c:180
+#: dhcp.c:252 dhcp6.c:173
 #, fuzzy, c-format
 msgid "unknown interface %s in bridge-interface"
 msgstr "interfase desconocida %s en bridge-interface"
 
-#: dhcp.c:281
+#: dhcp.c:293
 #, c-format
 msgid "DHCP packet received on %s which has no address"
 msgstr "Paquete DHCP recibido en %s que no tiene dirección"
 
-#: dhcp.c:415
+#: dhcp.c:427
 #, c-format
 msgid "ARP-cache injection failed: %s"
 msgstr ""
 
-#: dhcp.c:514
+#: dhcp.c:470
+#, c-format
+msgid "Error sending DHCP packet to %s: %s"
+msgstr ""
+
+#: dhcp.c:531
 #, c-format
 msgid "DHCP range %s -- %s is not consistent with netmask %s"
 msgstr "rango DHCP %s -- %s no coincide con máscara de subred %s"
 
-#: dhcp.c:815
+#: dhcp.c:854
 #, fuzzy, c-format
 msgid "bad line at %s line %d"
 msgstr "línea errónea en %s línea %d"
 
-#: dhcp.c:858
+#: dhcp.c:897
 #, c-format
 msgid "ignoring %s line %d, duplicate name or IP address"
 msgstr "ignorando %s línea %d, nombre o dirección IP duplicada"
 
-#: dhcp.c:1002 rfc3315.c:2135
+#: dhcp.c:1041 rfc3315.c:2149
 #, c-format
 msgid "DHCP relay %s -> %s"
 msgstr "DHCP relay %s -> %s"
 
-#: lease.c:61
+#: lease.c:98
+msgid "too many stored leases"
+msgstr "demasiadas concesiones almacenadas"
+
+#: lease.c:166
 #, fuzzy, c-format
 msgid "cannot open or create lease file %s: %s"
 msgstr "no se puede abrir o crear archivo de concesión %s: %s"
 
-#: lease.c:134
-msgid "too many stored leases"
-msgstr "demasiadas concesiones almacenadas"
+#: lease.c:175
+#, c-format
+msgid "failed to parse lease database, invalid line: %s %s %s %s ..."
+msgstr ""
+
+#: lease.c:180
+#, fuzzy, c-format
+msgid "failed to read lease file %s: %s"
+msgstr "no se pudo leer %s: %s"
 
-#: lease.c:165
+#: lease.c:196
 #, fuzzy, c-format
 msgid "cannot run lease-init script %s: %s"
 msgstr "no se puede ejecutar archivo script lease-init %s: %s"
 
-#: lease.c:171
+#: lease.c:202
 #, c-format
 msgid "lease-init script returned exit code %s"
 msgstr "archivo guión lease-init retornó código de salida %s"
 
-#: lease.c:342
+#: lease.c:373
 #, fuzzy, c-format
 msgid "failed to write %s: %s (retry in %us)"
 msgstr "error al escribir %s: %s (reintentar en %us)"
 
-#: lease.c:906
+#: lease.c:937
 #, c-format
 msgid "Ignoring domain %s for DHCP host name %s"
 msgstr "Ignorando dominio %s para nombre de host DHCP %s"
 
-#: rfc2131.c:344
+#: rfc2131.c:347
 #, c-format
 msgid "no address range available for DHCP request %s %s"
 msgstr "ningún rango de direcciónes disponible para pedido DHCP %s %s"
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "with subnet selector"
 msgstr "con selector de subred"
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "via"
 msgstr "vía"
 
-#: rfc2131.c:357
+#: rfc2131.c:360
 #, fuzzy, c-format
 msgid "%u available DHCP subnet: %s/%s"
 msgstr "%u Subred DHCP disponible: %s/%s"
 
-#: rfc2131.c:360 rfc3315.c:300
+#: rfc2131.c:363 rfc3315.c:306
 #, fuzzy, c-format
 msgid "%u available DHCP range: %s -- %s"
 msgstr "%u Rango DHCP disponible: %s -- %s"
 
-#: rfc2131.c:471
+#: rfc2131.c:474
 #, fuzzy, c-format
 msgid "%u vendor class: %s"
 msgstr "%u Clase de vendedor: %s"
 
-#: rfc2131.c:473
+#: rfc2131.c:476
 #, fuzzy, c-format
 msgid "%u user class: %s"
 msgstr "%u Clase de usuario: %s"
 
-#: rfc2131.c:500
+#: rfc2131.c:510
 msgid "disabled"
 msgstr "deshabilitado"
 
-#: rfc2131.c:541 rfc2131.c:974 rfc2131.c:1380 rfc3315.c:603 rfc3315.c:856
-#: rfc3315.c:1135
+#: rfc2131.c:551 rfc2131.c:1006 rfc2131.c:1430 rfc3315.c:616 rfc3315.c:869
+#: rfc3315.c:1148
 msgid "ignored"
 msgstr "ignorado"
 
-#: rfc2131.c:556 rfc2131.c:1207 rfc3315.c:906
+#: rfc2131.c:566 rfc2131.c:1239 rfc3315.c:919
 msgid "address in use"
 msgstr "dirección en uso"
 
-#: rfc2131.c:570 rfc2131.c:1028
+#: rfc2131.c:580 rfc2131.c:1060
 msgid "no address available"
 msgstr "ninguna dirección disponible"
 
-#: rfc2131.c:577 rfc2131.c:1170
+#: rfc2131.c:587 rfc2131.c:1202
 msgid "wrong network"
 msgstr "red equivocada"
 
-#: rfc2131.c:592
+#: rfc2131.c:602
 msgid "no address configured"
 msgstr "ninguna dirección configurada"
 
-#: rfc2131.c:598 rfc2131.c:1220
+#: rfc2131.c:608 rfc2131.c:1252
 msgid "no leases left"
 msgstr "no sobra ninguna concesión"
 
-#: rfc2131.c:693 rfc3315.c:476
+#: rfc2131.c:703 rfc3315.c:482
 #, fuzzy, c-format
 msgid "%u client provides name: %s"
 msgstr "%u cliente provee nombre: %s"
 
-#: rfc2131.c:798
+#: rfc2131.c:808
 msgid "PXE BIS not supported"
 msgstr "no hay soporte para BIS PXE"
 
-#: rfc2131.c:942 rfc3315.c:1229
+#: rfc2131.c:974 rfc3315.c:1242
 #, fuzzy, c-format
 msgid "disabling DHCP static address %s for %s"
 msgstr "deshabilitando dirección DHCP estática %s para %s"
 
-#: rfc2131.c:963
+#: rfc2131.c:995
 msgid "unknown lease"
 msgstr "concesión desconocida"
 
-#: rfc2131.c:997
+#: rfc2131.c:1029
 #, c-format
 msgid "not using configured address %s because it is leased to %s"
 msgstr "no usando dirección configurada %s porque está concedida a %s"
 
-#: rfc2131.c:1007
+#: rfc2131.c:1039
 #, fuzzy, c-format
 msgid "not using configured address %s because it is in use by the server or relay"
 msgstr "no usando dirección configurada %s porque está en uso por el servidor o relay"
 
-#: rfc2131.c:1010
+#: rfc2131.c:1042
 #, fuzzy, c-format
 msgid "not using configured address %s because it was previously declined"
 msgstr "no usando dirección configurada %s porque fué previamente denegada"
 
-#: rfc2131.c:1026 rfc2131.c:1213
+#: rfc2131.c:1058 rfc2131.c:1245
 msgid "no unique-id"
 msgstr "ningún unique-id (identificación única)"
 
-#: rfc2131.c:1108
+#: rfc2131.c:1140
 msgid "wrong server-ID"
 msgstr "ID de servidor equivocada"
 
-#: rfc2131.c:1127
+#: rfc2131.c:1159
 msgid "wrong address"
 msgstr "dirección equivocada"
 
-#: rfc2131.c:1145 rfc3315.c:1002
+#: rfc2131.c:1177 rfc3315.c:1015
 msgid "lease not found"
 msgstr "concesión no encontrada"
 
-#: rfc2131.c:1178
+#: rfc2131.c:1210
 msgid "address not available"
 msgstr "dirección no disponible"
 
-#: rfc2131.c:1189
+#: rfc2131.c:1221
 msgid "static lease available"
 msgstr "concesión estática disponible"
 
-#: rfc2131.c:1193
+#: rfc2131.c:1225
 msgid "address reserved"
 msgstr "dirección reservada"
 
-#: rfc2131.c:1201
+#: rfc2131.c:1233
 #, c-format
 msgid "abandoning lease to %s of %s"
 msgstr "abandonando concesión a %s de %s"
 
-#: rfc2131.c:1707
+#: rfc2131.c:1757
 #, c-format
 msgid "%u bootfile name: %s"
 msgstr "%u nombre de bootfile: %s"
 
-#: rfc2131.c:1716
+#: rfc2131.c:1766
 #, c-format
 msgid "%u server name: %s"
 msgstr "%u nombre de servidor: %s"
 
-#: rfc2131.c:1724
+#: rfc2131.c:1774
 #, fuzzy, c-format
 msgid "%u next server: %s"
 msgstr "%u siguiente servidor: %s"
 
-#: rfc2131.c:1727
+#: rfc2131.c:1777
 #, c-format
 msgid "%u broadcast response"
 msgstr "%u respuesta broadcast"
 
-#: rfc2131.c:1790
+#: rfc2131.c:1840
 #, fuzzy, c-format
 msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
 msgstr "no se puede enviar opción DHCP/BOOTP %d: no queda espacio en el paquete"
 
-#: rfc2131.c:2031
+#: rfc2131.c:2131
 msgid "PXE menu too large"
 msgstr "menú PXE demasiado largo"
 
-#: rfc2131.c:2170 rfc3315.c:1502
+#: rfc2131.c:2270 rfc3315.c:1515
 #, fuzzy, c-format
 msgid "%u requested options: %s"
 msgstr "%u opciones solicitadas: %s"
 
-#: rfc2131.c:2487
+#: rfc2131.c:2587
 #, c-format
 msgid "cannot send RFC3925 option: too many options for enterprise number %d"
 msgstr "no se puede enviar opción RFC3925: demasiadas opciones para número enterprise %d"
 
+#: rfc2131.c:2650
+#, c-format
+msgid "%u reply delay: %d"
+msgstr ""
+
 #: netlink.c:77
 #, fuzzy, c-format
 msgid "cannot create netlink socket: %s"
 msgstr "no se puede crear zócalo netlink: %s"
 
-#: netlink.c:348
+#: netlink.c:355
 #, fuzzy, c-format
 msgid "netlink returns error: %s"
 msgstr "netlink retorna error: %s"
@@ -1848,62 +1949,62 @@ msgstr ""
 msgid "Disabling --%s option from D-Bus"
 msgstr ""
 
-#: dbus.c:691
+#: dbus.c:690
 msgid "setting upstream servers from DBus"
 msgstr "fijando servidores subida desde DBus"
 
-#: dbus.c:738
+#: dbus.c:737
 msgid "could not register a DBus message handler"
 msgstr "no se pudo registrar un manejador de mensajes DBus"
 
-#: bpf.c:263
+#: bpf.c:265
 #, c-format
 msgid "cannot create DHCP BPF socket: %s"
 msgstr "no se puede crear zócalo BPF DHCP: %s"
 
-#: bpf.c:291
+#: bpf.c:293
 #, fuzzy, c-format
 msgid "DHCP request for unsupported hardware type (%d) received on %s"
 msgstr "pedido DHCP por tipo de hardware no-soportado (%d) recibido en %s"
 
-#: bpf.c:376
+#: bpf.c:378
 #, fuzzy, c-format
 msgid "cannot create PF_ROUTE socket: %s"
 msgstr "no se puede crear zócalo DHCP: %s"
 
-#: bpf.c:397
+#: bpf.c:399
 msgid "Unknown protocol version from route socket"
 msgstr ""
 
-#: helper.c:153
+#: helper.c:154
 msgid "lease() function missing in Lua script"
 msgstr "la función lease() no se encuentra en el script Lua"
 
-#: tftp.c:309
+#: tftp.c:319
 msgid "unable to get free port for TFTP"
 msgstr "incapaz de conseguir puerto libre para TFTP"
 
-#: tftp.c:325
+#: tftp.c:335
 #, c-format
 msgid "unsupported request from %s"
 msgstr "pedido no-soportado desde %s"
 
-#: tftp.c:439
+#: tftp.c:483
 #, fuzzy, c-format
 msgid "file %s not found"
 msgstr "archivo %s no encontrado"
 
-#: tftp.c:548
+#: tftp.c:592
 #, fuzzy, c-format
 msgid "error %d %s received from %s"
 msgstr "error TFTP %d %s recibido de %s"
 
-#: tftp.c:590
+#: tftp.c:634
 #, fuzzy, c-format
 msgid "failed sending %s to %s"
 msgstr "TFTP no pudo enviar %s a %s"
 
-#: tftp.c:590
+#: tftp.c:634
 #, fuzzy, c-format
 msgid "sent %s to %s"
 msgstr "TFTP envió %s a %s"
@@ -1918,7 +2019,7 @@ msgstr "desbordamiento: %d entradas de registro perdidas"
 msgid "log failed: %s"
 msgstr "registro falló: %s"
 
-#: log.c:469
+#: log.c:471
 msgid "FAILED to start up"
 msgstr "el inicio ha FALLADO"
 
@@ -1927,17 +2028,17 @@ msgstr "el inicio ha FALLADO"
 msgid "Conntrack connection mark retrieval failed: %s"
 msgstr "Conexión conntrack con marca recuperación falló"
 
-#: dhcp6.c:59
+#: dhcp6.c:52
 #, fuzzy, c-format
 msgid "cannot create DHCPv6 socket: %s"
 msgstr "no se puede crear zócalo DHCP: %s"
 
-#: dhcp6.c:80
+#: dhcp6.c:73
 #, fuzzy, c-format
 msgid "failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"
 msgstr "no se pudo fijar SO_REUSE{ADDR|PORT} en zócalo DHCP: %s"
 
-#: dhcp6.c:92
+#: dhcp6.c:85
 #, fuzzy, c-format
 msgid "failed to bind DHCPv6 server socket: %s"
 msgstr "no se pudo acoplar zócalo de servidor DHCP: %s"
@@ -1952,71 +2053,71 @@ msgstr "ning
 msgid "no address range available for DHCPv6 request via %s"
 msgstr "ningún rango de direcciónes disponible para pedido DHCP %s %s"
 
-#: rfc3315.c:297
+#: rfc3315.c:303
 #, fuzzy, c-format
 msgid "%u available DHCPv6 subnet: %s/%d"
 msgstr "%u Subred DHCP disponible: %s/%s"
 
-#: rfc3315.c:380
+#: rfc3315.c:386
 #, fuzzy, c-format
 msgid "%u vendor class: %u"
 msgstr "%u Clase de vendedor: %s"
 
-#: rfc3315.c:428
+#: rfc3315.c:434
 #, fuzzy, c-format
 msgid "%u client MAC address: %s"
 msgstr "%u cliente provee nombre: %s"
 
-#: rfc3315.c:660
+#: rfc3315.c:673
 #, fuzzy, c-format
 msgid "unknown prefix-class %d"
 msgstr "clase de prefijo desconocida"
 
-#: rfc3315.c:803 rfc3315.c:898
+#: rfc3315.c:816 rfc3315.c:911
 #, fuzzy
 msgid "address unavailable"
 msgstr "dirección no disponible"
 
-#: rfc3315.c:815 rfc3315.c:946 rfc3315.c:1279
+#: rfc3315.c:828 rfc3315.c:959 rfc3315.c:1292
 msgid "success"
 msgstr ""
 
-#: rfc3315.c:830 rfc3315.c:839 rfc3315.c:954 rfc3315.c:956
+#: rfc3315.c:843 rfc3315.c:852 rfc3315.c:967 rfc3315.c:969
 #, fuzzy
 msgid "no addresses available"
 msgstr "ninguna dirección disponible"
 
-#: rfc3315.c:933
+#: rfc3315.c:946
 msgid "not on link"
 msgstr "no en el enlace"
 
-#: rfc3315.c:1006 rfc3315.c:1191 rfc3315.c:1268
+#: rfc3315.c:1019 rfc3315.c:1204 rfc3315.c:1281
 msgid "no binding found"
 msgstr "uniones no encontradas"
 
-#: rfc3315.c:1044
+#: rfc3315.c:1057
 msgid "deprecated"
 msgstr "descartado"
 
-#: rfc3315.c:1049
+#: rfc3315.c:1062
 #, fuzzy
 msgid "address invalid"
 msgstr "dirección en uso"
 
-#: rfc3315.c:1096
+#: rfc3315.c:1109
 msgid "confirm failed"
 msgstr "confirmación falló"
 
-#: rfc3315.c:1112
+#: rfc3315.c:1125
 #, fuzzy
 msgid "all addresses still on link"
 msgstr "dirección errónea en %s línea %d"
 
-#: rfc3315.c:1200
+#: rfc3315.c:1213
 msgid "release received"
 msgstr "concesión recibida"
 
-#: rfc3315.c:2126
+#: rfc3315.c:2140
 msgid "Cannot multicast to DHCPv6 server without correct interface"
 msgstr "No puede hacer multicast DHCPv6 sin el interfase correcto"
 
@@ -2040,76 +2141,76 @@ msgstr "%s tiene m
 msgid "duplicate IP address %s (%s) in dhcp-config directive"
 msgstr "dirección IP duplicada %s (%s) en directiva dhcp-config"
 
-#: dhcp-common.c:494
+#: dhcp-common.c:491
 #, fuzzy, c-format
 msgid "failed to set SO_BINDTODEVICE on DHCP socket: %s"
 msgstr "no se pudo fijar SO_REUSE{ADDR|PORT} en socket DHCP: %s"
 
-#: dhcp-common.c:615
+#: dhcp-common.c:612
 #, c-format
 msgid "Known DHCP options:\n"
 msgstr "Opciones DHCP conocidas:\n"
 
-#: dhcp-common.c:626
+#: dhcp-common.c:623
 #, fuzzy, c-format
 msgid "Known DHCPv6 options:\n"
 msgstr "Opciones DHCP conocidas:\n"
 
-#: dhcp-common.c:823
+#: dhcp-common.c:820
 msgid ", prefix deprecated"
 msgstr ", prefijo descartado"
 
-#: dhcp-common.c:826
+#: dhcp-common.c:823
 #, c-format
 msgid ", lease time "
 msgstr ", tiempo de concesión"
 
-#: dhcp-common.c:868
+#: dhcp-common.c:865
 #, c-format
 msgid "%s stateless on %s%.0s%.0s%s"
 msgstr "%s apátrida en %s%.0s%.0s%s"
 
-#: dhcp-common.c:870
+#: dhcp-common.c:867
 #, fuzzy, c-format
 msgid "%s, static leases only on %.0s%s%s%.0s"
 msgstr "DHCP, concesión estática solo en %.0s%s, tiempo de concesión %s"
 
-#: dhcp-common.c:872
+#: dhcp-common.c:869
 #, fuzzy, c-format
 msgid "%s, proxy on subnet %.0s%s%.0s%.0s"
 msgstr "DHCP, proxy en subred %.0s%s%.0s"
 
-#: dhcp-common.c:873
+#: dhcp-common.c:870
 #, fuzzy, c-format
 msgid "%s, IP range %s -- %s%s%.0s"
 msgstr "DHCP, rango de IPs %s -- %s, tiempo de concesión %s"
 
-#: dhcp-common.c:886
+#: dhcp-common.c:883
 #, c-format
 msgid "DHCPv4-derived IPv6 names on %s%s"
 msgstr ""
 
-#: dhcp-common.c:889
+#: dhcp-common.c:886
 #, fuzzy, c-format
 msgid "router advertisement on %s%s"
 msgstr "DHCP, concesión estáticos solo en %.0s%s, tiempo de concesión %s"
 
-#: dhcp-common.c:900
+#: dhcp-common.c:897
 #, c-format
 msgid "DHCP relay from %s to %s via %s"
 msgstr ""
 
-#: dhcp-common.c:902
+#: dhcp-common.c:899
 #, c-format
 msgid "DHCP relay from %s to %s"
 msgstr ""
 
-#: radv.c:109
+#: radv.c:110
 #, fuzzy, c-format
 msgid "cannot create ICMPv6 socket: %s"
 msgstr "no se puede crear socket DHCP: %s"
 
-#: auth.c:448
+#: auth.c:449
 #, fuzzy, c-format
 msgid "ignoring zone transfer request from %s"
 msgstr "pedido no-soportado desde %s"
@@ -2124,90 +2225,90 @@ msgstr "no se pudo acoplar socket de servidor DHCP: %s"
 msgid "failed to create IPset control socket: %s"
 msgstr "no se pudo crear socket TFTP: %s"
 
-#: dnssec.c:449 dnssec.c:493
+#: ipset.c:233
 #, fuzzy, c-format
-msgid "failed to update mtime on %s: %s"
+msgid "failed to update ipset %s: %s"
 msgstr "no se pudo abrir archivo PID %s: %s"
 
+#: dnssec.c:208
+msgid "system time considered valid, now checking DNSSEC signature timestamps."
+msgstr ""
+
 #: blockdata.c:58
 #, c-format
 msgid "DNSSEC memory in use %u, max %u, allocated %u"
 msgstr ""
 
-#: tables.c:80
-msgid "error: fill_addr missused"
-msgstr ""
-
-#: tables.c:109
+#: tables.c:61
 #, fuzzy, c-format
 msgid "failed to access pf devices: %s"
 msgstr "no se pudo acceder %s: %s"
 
-#: tables.c:123
+#: tables.c:74
 #, fuzzy, c-format
 msgid "warning: no opened pf devices %s"
 msgstr "usando direcciones locales solo para %s %s"
 
-#: tables.c:131
+#: tables.c:82
 #, fuzzy, c-format
 msgid "error: cannot use table name %s"
 msgstr "no se puede obtener host-name (nombre de host): %s"
 
-#: tables.c:139
+#: tables.c:90
 #, c-format
 msgid "error: cannot strlcpy table name %s"
 msgstr ""
 
-#: tables.c:145
-#, c-format
-msgid "warning: pfr_add_tables: %s(%d)"
-msgstr ""
+#: tables.c:101
+#, fuzzy, c-format
+msgid "IPset: error:%s"
+msgstr "error DBus: %s"
 
-#: tables.c:151
+#: tables.c:108
 msgid "info: table created"
 msgstr ""
 
-#: tables.c:162
+#: tables.c:134
 #, c-format
 msgid "warning: DIOCR%sADDRS: %s"
 msgstr ""
 
-#: tables.c:166
+#: tables.c:138
 #, fuzzy, c-format
 msgid "%d addresses %s"
 msgstr "dirección IP errónea"
 
-#: inotify.c:59
+#: inotify.c:62
 #, fuzzy, c-format
 msgid "cannot access path %s: %s"
 msgstr "no se puede acceder %s: %s"
 
-#: inotify.c:92
+#: inotify.c:95
 #, fuzzy, c-format
 msgid "failed to create inotify: %s"
 msgstr "no se pudo crear ayudante: %s"
 
-#: inotify.c:105
+#: inotify.c:111
 #, c-format
 msgid "too many symlinks following %s"
 msgstr ""
 
-#: inotify.c:121
+#: inotify.c:127
 #, c-format
 msgid "directory %s for resolv-file is missing, cannot poll"
 msgstr ""
 
-#: inotify.c:125 inotify.c:162
+#: inotify.c:131 inotify.c:168
 #, fuzzy, c-format
 msgid "failed to create inotify for %s: %s"
 msgstr "no se pudo crear un zócalo de escucha: %s"
 
-#: inotify.c:147
+#: inotify.c:153
 #, fuzzy, c-format
 msgid "bad dynamic directory %s: %s"
 msgstr "no se puede acceder a directorio %s: %s"
 
-#: inotify.c:247
+#: inotify.c:257
 #, c-format
 msgid "inotify, new or changed file %s"
 msgstr ""
index cb4428a..d3c54d7 100644 (file)
--- a/po/fi.po
+++ b/po/fi.po
@@ -7,7 +7,7 @@ msgstr ""
 "Project-Id-Version: dnsmasq 2.24\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2009-06-18 12:24+0100\n"
-"PO-Revision-Date: 2005-11-28 22:05+0000\n"
+"PO-Revision-Date: 2017-07-17 18:30+0100\n"
 "Last-Translator: Simon Kelley <simon@thekelleys.org.uk>\n"
 "Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"
 "Language: fi\n"
@@ -16,1482 +16,1556 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cache.c:523
+#: cache.c:518
 msgid "Internal error in cache."
 msgstr ""
 
-#: cache.c:941
+#: cache.c:928
 #, c-format
 msgid "failed to load names from %s: %s"
 msgstr ""
 
-#: cache.c:967 dhcp.c:828
+#: cache.c:954 dhcp.c:867
 #, c-format
 msgid "bad address at %s line %d"
 msgstr ""
 
-#: cache.c:1018 dhcp.c:844
+#: cache.c:1007 dhcp.c:883
 #, c-format
 msgid "bad name at %s line %d"
 msgstr ""
 
-#: cache.c:1027 dhcp.c:919
+#: cache.c:1016 dhcp.c:958
 #, c-format
 msgid "read %s - %d addresses"
 msgstr ""
 
-#: cache.c:1135
+#: cache.c:1129
 msgid "cleared cache"
 msgstr ""
 
-#: cache.c:1164
+#: cache.c:1158
 #, c-format
 msgid "No IPv4 address found for %s"
 msgstr ""
 
-#: cache.c:1242
+#: cache.c:1237
 #, c-format
 msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
 msgstr ""
 
-#: cache.c:1266
+#: cache.c:1261
 #, c-format
 msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
 msgstr ""
 
-#: cache.c:1421
+#: cache.c:1418
 #, c-format
 msgid "time %lu"
 msgstr ""
 
-#: cache.c:1422
+#: cache.c:1419
 #, c-format
 msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
 msgstr ""
 
-#: cache.c:1424
+#: cache.c:1421
 #, c-format
 msgid "queries forwarded %u, queries answered locally %u"
 msgstr ""
 
-#: cache.c:1427
+#: cache.c:1424
 #, c-format
 msgid "queries for authoritative zones %u"
 msgstr ""
 
-#: cache.c:1453
+#: cache.c:1450
 #, c-format
 msgid "server %s#%d: queries sent %u, retried or failed %u"
 msgstr ""
 
-#: util.c:45
+#: util.c:47
 #, c-format
 msgid "failed to seed the random number generator: %s"
 msgstr ""
 
-#: util.c:205
+#: util.c:224
 msgid "failed to allocate memory"
 msgstr ""
 
-#: util.c:250 option.c:601
+#: util.c:281 option.c:619
 msgid "could not get memory"
 msgstr ""
 
-#: util.c:260
+#: util.c:291
 #, c-format
 msgid "cannot create pipe: %s"
 msgstr ""
 
-#: util.c:268
+#: util.c:299
 #, c-format
 msgid "failed to allocate %d bytes"
 msgstr ""
 
-#: util.c:437
+#: util.c:468
 #, c-format
 msgid "infinite"
 msgstr ""
 
-#: option.c:332
+#: option.c:344
 msgid "Specify local address(es) to listen on."
 msgstr ""
 
-#: option.c:333
+#: option.c:345
 msgid "Return ipaddr for all hosts in specified domains."
 msgstr ""
 
-#: option.c:334
+#: option.c:346
 msgid "Fake reverse lookups for RFC1918 private address ranges."
 msgstr ""
 
-#: option.c:335
+#: option.c:347
 msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
 msgstr ""
 
-#: option.c:336
+#: option.c:348
 #, c-format
 msgid "Specify the size of the cache in entries (defaults to %s)."
 msgstr ""
 
-#: option.c:337
+#: option.c:349
 #, c-format
 msgid "Specify configuration file (defaults to %s)."
 msgstr ""
 
-#: option.c:338
+#: option.c:350
 msgid "Do NOT fork into the background: run in debug mode."
 msgstr ""
 
-#: option.c:339
+#: option.c:351
 msgid "Do NOT forward queries with no domain part."
 msgstr ""
 
-#: option.c:340
+#: option.c:352
 msgid "Return self-pointing MX records for local hosts."
 msgstr ""
 
-#: option.c:341
+#: option.c:353
 msgid "Expand simple names in /etc/hosts with domain-suffix."
 msgstr ""
 
-#: option.c:342
+#: option.c:354
 msgid "Don't forward spurious DNS requests from Windows hosts."
 msgstr ""
 
-#: option.c:343
+#: option.c:355
 msgid "Enable DHCP in the range given with lease duration."
 msgstr ""
 
-#: option.c:344
+#: option.c:356
 #, c-format
 msgid "Change to this group after startup (defaults to %s)."
 msgstr ""
 
-#: option.c:345
+#: option.c:357
 msgid "Set address or hostname for a specified machine."
 msgstr ""
 
-#: option.c:346
+#: option.c:358
 msgid "Read DHCP host specs from file."
 msgstr ""
 
-#: option.c:347
+#: option.c:359
 msgid "Read DHCP option specs from file."
 msgstr ""
 
-#: option.c:348
+#: option.c:360
 msgid "Read DHCP host specs from a directory."
 msgstr ""
 
-#: option.c:349
+#: option.c:361
 msgid "Read DHCP options from a directory."
 msgstr ""
 
-#: option.c:350
+#: option.c:362
 msgid "Evaluate conditional tag expression."
 msgstr ""
 
-#: option.c:351
+#: option.c:363
 #, c-format
 msgid "Do NOT load %s file."
 msgstr ""
 
-#: option.c:352
+#: option.c:364
 #, c-format
 msgid "Specify a hosts file to be read in addition to %s."
 msgstr ""
 
-#: option.c:353
+#: option.c:365
 msgid "Read hosts files from a directory."
 msgstr ""
 
-#: option.c:354
+#: option.c:366
 msgid "Specify interface(s) to listen on."
 msgstr ""
 
-#: option.c:355
+#: option.c:367
 msgid "Specify interface(s) NOT to listen on."
 msgstr ""
 
-#: option.c:356
+#: option.c:368
 msgid "Map DHCP user class to tag."
 msgstr ""
 
-#: option.c:357
+#: option.c:369
 msgid "Map RFC3046 circuit-id to tag."
 msgstr ""
 
-#: option.c:358
+#: option.c:370
 msgid "Map RFC3046 remote-id to tag."
 msgstr ""
 
-#: option.c:359
+#: option.c:371
 msgid "Map RFC3993 subscriber-id to tag."
 msgstr ""
 
-#: option.c:360
+#: option.c:372
 msgid "Don't do DHCP for hosts with tag set."
 msgstr ""
 
-#: option.c:361
+#: option.c:373
 msgid "Force broadcast replies for hosts with tag set."
 msgstr ""
 
-#: option.c:362
+#: option.c:374
 msgid "Do NOT fork into the background, do NOT run in debug mode."
 msgstr ""
 
-#: option.c:363
+#: option.c:375
 msgid "Assume we are the only DHCP server on the local network."
 msgstr ""
 
-#: option.c:364
+#: option.c:376
 #, c-format
 msgid "Specify where to store DHCP leases (defaults to %s)."
 msgstr ""
 
-#: option.c:365
+#: option.c:377
 msgid "Return MX records for local hosts."
 msgstr ""
 
-#: option.c:366
+#: option.c:378
 msgid "Specify an MX record."
 msgstr ""
 
-#: option.c:367
+#: option.c:379
 msgid "Specify BOOTP options to DHCP server."
 msgstr ""
 
-#: option.c:368
+#: option.c:380
 #, c-format
 msgid "Do NOT poll %s file, reload only on SIGHUP."
 msgstr ""
 
-#: option.c:369
+#: option.c:381
 msgid "Do NOT cache failed search results."
 msgstr ""
 
-#: option.c:370
+#: option.c:382
 #, c-format
 msgid "Use nameservers strictly in the order given in %s."
 msgstr ""
 
-#: option.c:371
+#: option.c:383
 msgid "Specify options to be sent to DHCP clients."
 msgstr ""
 
-#: option.c:372
+#: option.c:384
 msgid "DHCP option sent even if the client does not request it."
 msgstr ""
 
-#: option.c:373
+#: option.c:385
 msgid "Specify port to listen for DNS requests on (defaults to 53)."
 msgstr ""
 
-#: option.c:374
+#: option.c:386
 #, c-format
 msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
 msgstr ""
 
-#: option.c:375
+#: option.c:387
 msgid "Log DNS queries."
 msgstr ""
 
-#: option.c:376
+#: option.c:388
 msgid "Force the originating port for upstream DNS queries."
 msgstr ""
 
-#: option.c:377
+#: option.c:389
 msgid "Do NOT read resolv.conf."
 msgstr ""
 
-#: option.c:378
+#: option.c:390
 #, c-format
 msgid "Specify path to resolv.conf (defaults to %s)."
 msgstr ""
 
-#: option.c:379
+#: option.c:391
 msgid "Specify path to file with server= options"
 msgstr ""
 
-#: option.c:380
+#: option.c:392
 msgid "Specify address(es) of upstream servers with optional domains."
 msgstr ""
 
-#: option.c:381
+#: option.c:393
 msgid "Specify address of upstream servers for reverse address queries"
 msgstr ""
 
-#: option.c:382
+#: option.c:394
 msgid "Never forward queries to specified domains."
 msgstr ""
 
-#: option.c:383
+#: option.c:395
 msgid "Specify the domain to be assigned in DHCP leases."
 msgstr ""
 
-#: option.c:384
+#: option.c:396
 msgid "Specify default target in an MX record."
 msgstr ""
 
-#: option.c:385
+#: option.c:397
 msgid "Specify time-to-live in seconds for replies from /etc/hosts."
 msgstr ""
 
-#: option.c:386
+#: option.c:398
 msgid "Specify time-to-live in seconds for negative caching."
 msgstr ""
 
-#: option.c:387
+#: option.c:399
 msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
 msgstr ""
 
-#: option.c:388
+#: option.c:400
 msgid "Specify time-to-live ceiling for cache."
 msgstr ""
 
-#: option.c:389
+#: option.c:401
 msgid "Specify time-to-live floor for cache."
 msgstr ""
 
-#: option.c:390
+#: option.c:402
 #, c-format
 msgid "Change to this user after startup. (defaults to %s)."
 msgstr ""
 
-#: option.c:391
+#: option.c:403
 msgid "Map DHCP vendor class to tag."
 msgstr ""
 
-#: option.c:392
+#: option.c:404
 msgid "Display dnsmasq version and copyright information."
 msgstr ""
 
-#: option.c:393
+#: option.c:405
 msgid "Translate IPv4 addresses from upstream servers."
 msgstr ""
 
-#: option.c:394
+#: option.c:406
 msgid "Specify a SRV record."
 msgstr ""
 
-#: option.c:395
-msgid "Display this message. Use --help dhcp for known DHCP options."
+#: option.c:407
+msgid "Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."
 msgstr ""
 
-#: option.c:396
+#: option.c:408
 #, c-format
 msgid "Specify path of PID file (defaults to %s)."
 msgstr ""
 
-#: option.c:397
+#: option.c:409
 #, c-format
 msgid "Specify maximum number of DHCP leases (defaults to %s)."
 msgstr ""
 
-#: option.c:398
+#: option.c:410
 msgid "Answer DNS queries based on the interface a query was sent to."
 msgstr ""
 
-#: option.c:399
+#: option.c:411
 msgid "Specify TXT DNS record."
 msgstr ""
 
-#: option.c:400
+#: option.c:412
 msgid "Specify PTR DNS record."
 msgstr ""
 
-#: option.c:401
+#: option.c:413
 msgid "Give DNS name to IPv4 address of interface."
 msgstr ""
 
-#: option.c:402
+#: option.c:414
 msgid "Bind only to interfaces in use."
 msgstr ""
 
-#: option.c:403
+#: option.c:415
 #, c-format
 msgid "Read DHCP static host information from %s."
 msgstr ""
 
-#: option.c:404
+#: option.c:416
 msgid "Enable the DBus interface for setting upstream servers, etc."
 msgstr ""
 
-#: option.c:405
+#: option.c:417
 msgid "Do not provide DHCP on this interface, only provide DNS."
 msgstr ""
 
-#: option.c:406
+#: option.c:418
 msgid "Enable dynamic address allocation for bootp."
 msgstr ""
 
-#: option.c:407
+#: option.c:419
 msgid "Map MAC address (with wildcards) to option set."
 msgstr ""
 
-#: option.c:408
+#: option.c:420
 msgid "Treat DHCP requests on aliases as arriving from interface."
 msgstr ""
 
-#: option.c:409
+#: option.c:421
 msgid "Disable ICMP echo address checking in the DHCP server."
 msgstr ""
 
-#: option.c:410
+#: option.c:422
 msgid "Shell script to run on DHCP lease creation and destruction."
 msgstr ""
 
-#: option.c:411
+#: option.c:423
 msgid "Lua script to run on DHCP lease creation and destruction."
 msgstr ""
 
-#: option.c:412
+#: option.c:424
 msgid "Run lease-change scripts as this user."
 msgstr ""
 
-#: option.c:413
+#: option.c:425
+msgid "Call dhcp-script with changes to local ARP table."
+msgstr ""
+
+#: option.c:426
 msgid "Read configuration from all the files in this directory."
 msgstr ""
 
-#: option.c:414
+#: option.c:427
 msgid "Log to this syslog facility or file. (defaults to DAEMON)"
 msgstr ""
 
-#: option.c:415
+#: option.c:428
 msgid "Do not use leasefile."
 msgstr ""
 
-#: option.c:416
+#: option.c:429
 #, c-format
 msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
 msgstr ""
 
-#: option.c:417
+#: option.c:430
 #, c-format
 msgid "Clear DNS cache when reloading %s."
 msgstr ""
 
-#: option.c:418
+#: option.c:431
 msgid "Ignore hostnames provided by DHCP clients."
 msgstr ""
 
-#: option.c:419
+#: option.c:432
 msgid "Do NOT reuse filename and server fields for extra DHCP options."
 msgstr ""
 
-#: option.c:420
+#: option.c:433
 msgid "Enable integrated read-only TFTP server."
 msgstr ""
 
-#: option.c:421
+#: option.c:434
 msgid "Export files by TFTP only from the specified subtree."
 msgstr ""
 
-#: option.c:422
-msgid "Add client IP address to tftp-root."
+#: option.c:435
+msgid "Add client IP or hardware address to tftp-root."
 msgstr ""
 
-#: option.c:423
+#: option.c:436
 msgid "Allow access only to files owned by the user running dnsmasq."
 msgstr ""
 
-#: option.c:424
+#: option.c:437
 msgid "Do not terminate the service if TFTP directories are inaccessible."
 msgstr ""
 
-#: option.c:425
+#: option.c:438
 #, c-format
-msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgid "Maximum number of concurrent TFTP transfers (defaults to %s)."
 msgstr ""
 
-#: option.c:426
+#: option.c:439
+msgid "Maximum MTU to use for TFTP transfers."
+msgstr ""
+
+#: option.c:440
 msgid "Disable the TFTP blocksize extension."
 msgstr ""
 
-#: option.c:427
+#: option.c:441
 msgid "Convert TFTP filenames to lowercase"
 msgstr ""
 
-#: option.c:428
+#: option.c:442
 msgid "Ephemeral port range for use by TFTP transfers."
 msgstr ""
 
-#: option.c:429
+#: option.c:443
 msgid "Extra logging for DHCP."
 msgstr ""
 
-#: option.c:430
+#: option.c:444
 msgid "Enable async. logging; optionally set queue length."
 msgstr ""
 
-#: option.c:431
+#: option.c:445
 msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
 msgstr ""
 
-#: option.c:432
+#: option.c:446
 msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
 msgstr ""
 
-#: option.c:433
+#: option.c:447
 msgid "Inhibit DNS-rebind protection on this domain."
 msgstr ""
 
-#: option.c:434
+#: option.c:448
 msgid "Always perform DNS queries to all servers."
 msgstr ""
 
-#: option.c:435
+#: option.c:449
 msgid "Set tag if client includes matching option in request."
 msgstr ""
 
-#: option.c:436
+#: option.c:450
 msgid "Use alternative ports for DHCP."
 msgstr ""
 
-#: option.c:437
+#: option.c:451
 msgid "Specify NAPTR DNS record."
 msgstr ""
 
-#: option.c:438
+#: option.c:452
 msgid "Specify lowest port available for DNS query transmission."
 msgstr ""
 
-#: option.c:439
+#: option.c:453
+msgid "Specify highest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:454
 msgid "Use only fully qualified domain names for DHCP clients."
 msgstr ""
 
-#: option.c:440
+#: option.c:455
 msgid "Generate hostnames based on MAC address for nameless clients."
 msgstr ""
 
-#: option.c:441
+#: option.c:456
 msgid "Use these DHCP relays as full proxies."
 msgstr ""
 
-#: option.c:442
+#: option.c:457
 msgid "Relay DHCP requests to a remote server"
 msgstr ""
 
-#: option.c:443
+#: option.c:458
 msgid "Specify alias name for LOCAL DNS name."
 msgstr ""
 
-#: option.c:444
+#: option.c:459
 msgid "Prompt to send to PXE clients."
 msgstr ""
 
-#: option.c:445
+#: option.c:460
 msgid "Boot service for PXE menu."
 msgstr ""
 
-#: option.c:446
+#: option.c:461
 msgid "Check configuration syntax."
 msgstr ""
 
-#: option.c:447
+#: option.c:462
 msgid "Add requestor's MAC address to forwarded DNS queries."
 msgstr ""
 
-#: option.c:448
-msgid "Add requestor's IP subnet to forwarded DNS queries."
+#: option.c:463
+msgid "Add specified IP subnet to forwarded DNS queries."
 msgstr ""
 
-#: option.c:449
+#: option.c:464
+msgid "Add client identification to forwarded DNS queries."
+msgstr ""
+
+#: option.c:465
 msgid "Proxy DNSSEC validation results from upstream nameservers."
 msgstr ""
 
-#: option.c:450
+#: option.c:466
 msgid "Attempt to allocate sequential IP addresses to DHCP clients."
 msgstr ""
 
-#: option.c:451
+#: option.c:467
 msgid "Copy connection-track mark from queries to upstream connections."
 msgstr ""
 
-#: option.c:452
+#: option.c:468
 msgid "Allow DHCP clients to do their own DDNS updates."
 msgstr ""
 
-#: option.c:453
+#: option.c:469
 msgid "Send router-advertisements for interfaces doing DHCPv6"
 msgstr ""
 
-#: option.c:454
+#: option.c:470
 msgid "Specify DUID_EN-type DHCPv6 server DUID"
 msgstr ""
 
-#: option.c:455
+#: option.c:471
 msgid "Specify host (A/AAAA and PTR) records"
 msgstr ""
 
-#: option.c:456
+#: option.c:472
 msgid "Specify arbitrary DNS resource record"
 msgstr ""
 
-#: option.c:457
+#: option.c:473
 msgid "Bind to interfaces in use - check for new interfaces"
 msgstr ""
 
-#: option.c:458
+#: option.c:474
 msgid "Export local names to global DNS"
 msgstr ""
 
-#: option.c:459
+#: option.c:475
 msgid "Domain to export to global DNS"
 msgstr ""
 
-#: option.c:460
+#: option.c:476
 msgid "Set TTL for authoritative replies"
 msgstr ""
 
-#: option.c:461
-msgid "Set authoritive zone information"
+#: option.c:477
+msgid "Set authoritative zone information"
 msgstr ""
 
-#: option.c:462
+#: option.c:478
 msgid "Secondary authoritative nameservers for forward domains"
 msgstr ""
 
-#: option.c:463
+#: option.c:479
 msgid "Peers which are allowed to do zone transfer"
 msgstr ""
 
-#: option.c:464
+#: option.c:480
 msgid "Specify ipsets to which matching domains should be added"
 msgstr ""
 
-#: option.c:465
+#: option.c:481
 msgid "Specify a domain and address range for synthesised names"
 msgstr ""
 
-#: option.c:466
+#: option.c:482
 msgid "Activate DNSSEC validation"
 msgstr ""
 
-#: option.c:467
+#: option.c:483
 msgid "Specify trust anchor key digest."
 msgstr ""
 
-#: option.c:468
+#: option.c:484
 msgid "Disable upstream checking for DNSSEC debugging."
 msgstr ""
 
-#: option.c:469
+#: option.c:485
 msgid "Ensure answers without DNSSEC are in unsigned zones."
 msgstr ""
 
-#: option.c:470
+#: option.c:486
 msgid "Don't check DNSSEC signature timestamps until first cache-reload"
 msgstr ""
 
-#: option.c:471
+#: option.c:487
 msgid "Timestamp file to verify system clock for DNSSEC"
 msgstr ""
 
-#: option.c:473
+#: option.c:489
 msgid "Specify DHCPv6 prefix class"
 msgstr ""
 
-#: option.c:475
-msgid "Set priority, resend-interval and router-lifetime"
+#: option.c:491
+msgid "Set MTU, priority, resend-interval and router-lifetime"
 msgstr ""
 
-#: option.c:476
+#: option.c:492
 msgid "Do not log routine DHCP."
 msgstr ""
 
-#: option.c:477
+#: option.c:493
 msgid "Do not log routine DHCPv6."
 msgstr ""
 
-#: option.c:478
+#: option.c:494
 msgid "Do not log RA."
 msgstr ""
 
-#: option.c:479
-msgid "Accept queries only from directly-connected networks"
+#: option.c:495
+msgid "Accept queries only from directly-connected networks."
 msgstr ""
 
-#: option.c:480
-msgid "Detect and remove DNS forwarding loops"
+#: option.c:496
+msgid "Detect and remove DNS forwarding loops."
 msgstr ""
 
-#: option.c:481
+#: option.c:497
 msgid "Ignore DNS responses containing ipaddr."
 msgstr ""
 
-#: option.c:683
+#: option.c:498
+msgid "Set TTL in DNS responses with DHCP-derived addresses."
+msgstr ""
+
+#: option.c:499
+msgid "Delay DHCP replies for at least number of seconds."
+msgstr ""
+
+#: option.c:703
 #, c-format
 msgid ""
 "Usage: dnsmasq [options]\n"
 "\n"
 msgstr ""
 
-#: option.c:685
+#: option.c:705
 #, c-format
 msgid "Use short options only on the command line.\n"
 msgstr ""
 
-#: option.c:687
+#: option.c:707
 #, c-format
 msgid "Valid options are:\n"
 msgstr ""
 
-#: option.c:744 option.c:748
+#: option.c:754 option.c:868
+msgid "bad address"
+msgstr ""
+
+#: option.c:779 option.c:783
 msgid "bad port"
 msgstr ""
 
-#: option.c:775 option.c:807
+#: option.c:797 option.c:826 option.c:861
 msgid "interface binding not supported"
 msgstr ""
 
-#: option.c:784 option.c:3575
-msgid "bad interface name"
+#: option.c:821 option.c:856
+msgid "interface can only be specified once"
 msgstr ""
 
-#: option.c:814
-msgid "bad address"
+#: option.c:835 option.c:3809
+msgid "bad interface name"
 msgstr ""
 
-#: option.c:996
+#: option.c:1062
 msgid "unsupported encapsulation for IPv6 option"
 msgstr ""
 
-#: option.c:1010
+#: option.c:1076
 msgid "bad dhcp-option"
 msgstr ""
 
-#: option.c:1078
+#: option.c:1144
 msgid "bad IP address"
 msgstr ""
 
-#: option.c:1081 option.c:1219 option.c:2893
+#: option.c:1147 option.c:1286 option.c:3079
 msgid "bad IPv6 address"
 msgstr ""
 
-#: option.c:1246 option.c:1340
+#: option.c:1240
+msgid "bad IPv4 address"
+msgstr ""
+
+#: option.c:1313 option.c:1407
 msgid "bad domain in dhcp-option"
 msgstr ""
 
-#: option.c:1378
+#: option.c:1445
 msgid "dhcp-option too long"
 msgstr ""
 
-#: option.c:1385
+#: option.c:1452
 msgid "illegal dhcp-match"
 msgstr ""
 
-#: option.c:1447
+#: option.c:1514
 msgid "illegal repeated flag"
 msgstr ""
 
-#: option.c:1455
+#: option.c:1522
 msgid "illegal repeated keyword"
 msgstr ""
 
-#: option.c:1520 option.c:4191
+#: option.c:1593 option.c:4443
 #, c-format
 msgid "cannot access directory %s: %s"
 msgstr ""
 
-#: option.c:1566 tftp.c:493
+#: option.c:1639 tftp.c:537
 #, c-format
 msgid "cannot access %s: %s"
 msgstr ""
 
-#: option.c:1618
+#: option.c:1727
 msgid "setting log facility is not possible under Android"
 msgstr ""
 
-#: option.c:1627
+#: option.c:1736
 msgid "bad log facility"
 msgstr ""
 
-#: option.c:1680
+#: option.c:1789
 msgid "bad MX preference"
 msgstr ""
 
-#: option.c:1685
+#: option.c:1794
 msgid "bad MX name"
 msgstr ""
 
-#: option.c:1699
+#: option.c:1808
 msgid "bad MX target"
 msgstr ""
 
-#: option.c:1711
+#: option.c:1820
 msgid "cannot run scripts under uClinux"
 msgstr ""
 
-#: option.c:1713
+#: option.c:1822
 msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
 msgstr ""
 
-#: option.c:1717
+#: option.c:1826
 msgid "recompile with HAVE_LUASCRIPT defined to enable Lua scripts"
 msgstr ""
 
-#: option.c:1973 option.c:2018 option.c:2074
+#: option.c:2095 option.c:2106 option.c:2143 option.c:2199 option.c:2482
 msgid "bad prefix"
 msgstr ""
 
-#: option.c:2355
+#: option.c:2504
 msgid "recompile with HAVE_IPSET defined to enable ipset directives"
 msgstr ""
 
-#: option.c:2548
+#: option.c:2713
 msgid "bad port range"
 msgstr ""
 
-#: option.c:2564
+#: option.c:2739
 msgid "bad bridge-interface"
 msgstr ""
 
-#: option.c:2624
+#: option.c:2807
 msgid "only one tag allowed"
 msgstr ""
 
-#: option.c:2644 option.c:2656 option.c:2764 option.c:2805
+#: option.c:2827 option.c:2839 option.c:2948 option.c:2953 option.c:2992
 msgid "bad dhcp-range"
 msgstr ""
 
-#: option.c:2671
+#: option.c:2854
 msgid "inconsistent DHCP range"
 msgstr ""
 
-#: option.c:2732
+#: option.c:2916
 msgid "prefix length must be exactly 64 for RA subnets"
 msgstr ""
 
-#: option.c:2734
+#: option.c:2918
 msgid "prefix length must be exactly 64 for subnet constructors"
 msgstr ""
 
-#: option.c:2738
+#: option.c:2922
 msgid "prefix length must be at least 64"
 msgstr ""
 
-#: option.c:2741
+#: option.c:2925
 msgid "inconsistent DHCPv6 range"
 msgstr ""
 
-#: option.c:2752
+#: option.c:2936
 msgid "prefix must be zero with \"constructor:\" argument"
 msgstr ""
 
-#: option.c:2863 option.c:2911
+#: option.c:3049 option.c:3097
 msgid "bad hex constant"
 msgstr ""
 
-#: option.c:2885
+#: option.c:3071
 msgid "cannot match tags in --dhcp-host"
 msgstr ""
 
-#: option.c:2933
+#: option.c:3119
 #, c-format
 msgid "duplicate dhcp-host IP address %s"
 msgstr ""
 
-#: option.c:2991
+#: option.c:3177
 msgid "bad DHCP host name"
 msgstr ""
 
-#: option.c:3073
+#: option.c:3259
 msgid "bad tag-if"
 msgstr ""
 
-#: option.c:3397 option.c:3791
+#: option.c:3616 option.c:4039
 msgid "invalid port number"
 msgstr ""
 
-#: option.c:3459
+#: option.c:3678
 msgid "bad dhcp-proxy address"
 msgstr ""
 
-#: option.c:3485
+#: option.c:3704
 msgid "Bad dhcp-relay"
 msgstr ""
 
-#: option.c:3511
+#: option.c:3745
 msgid "bad RA-params"
 msgstr ""
 
-#: option.c:3520
+#: option.c:3754
 msgid "bad DUID"
 msgstr ""
 
-#: option.c:3562
+#: option.c:3796
 msgid "invalid alias range"
 msgstr ""
 
-#: option.c:3616
+#: option.c:3850 option.c:3862
 msgid "bad CNAME"
 msgstr ""
 
-#: option.c:3621
+#: option.c:3866
 msgid "duplicate CNAME"
 msgstr ""
 
-#: option.c:3641
+#: option.c:3889
 msgid "bad PTR record"
 msgstr ""
 
-#: option.c:3672
+#: option.c:3920
 msgid "bad NAPTR record"
 msgstr ""
 
-#: option.c:3706
+#: option.c:3954
 msgid "bad RR record"
 msgstr ""
 
-#: option.c:3736
+#: option.c:3984
 msgid "bad TXT record"
 msgstr ""
 
-#: option.c:3777
+#: option.c:4025
 msgid "bad SRV record"
 msgstr ""
 
-#: option.c:3784
+#: option.c:4032
 msgid "bad SRV target"
 msgstr ""
 
-#: option.c:3798
+#: option.c:4046
 msgid "invalid priority"
 msgstr ""
 
-#: option.c:3805
+#: option.c:4049
 msgid "invalid weight"
 msgstr ""
 
-#: option.c:3829
+#: option.c:4073
 msgid "Bad host-record"
 msgstr ""
 
-#: option.c:3846
+#: option.c:4097
 msgid "Bad name in host-record"
 msgstr ""
 
-#: option.c:3911
+#: option.c:4162
 msgid "bad trust anchor"
 msgstr ""
 
-#: option.c:3925
+#: option.c:4176
 msgid "bad HEX in trust anchor"
 msgstr ""
 
-#: option.c:3935
+#: option.c:4186
 msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"
 msgstr ""
 
-#: option.c:3994
+#: option.c:4246
 msgid "missing \""
 msgstr ""
 
-#: option.c:4051
+#: option.c:4303
 msgid "bad option"
 msgstr ""
 
-#: option.c:4053
+#: option.c:4305
 msgid "extraneous parameter"
 msgstr ""
 
-#: option.c:4055
+#: option.c:4307
 msgid "missing parameter"
 msgstr ""
 
-#: option.c:4057
+#: option.c:4309
 msgid "illegal option"
 msgstr ""
 
-#: option.c:4064
+#: option.c:4316
 msgid "error"
 msgstr ""
 
-#: option.c:4066
+#: option.c:4318
 #, c-format
 msgid " at line %d of %s"
 msgstr ""
 
-#: option.c:4081 option.c:4328 option.c:4364
+#: option.c:4333 option.c:4580 option.c:4616
 #, c-format
 msgid "read %s"
 msgstr ""
 
-#: option.c:4144 option.c:4267 tftp.c:667
+#: option.c:4396 option.c:4519 tftp.c:715
 #, c-format
 msgid "cannot read %s: %s"
 msgstr ""
 
-#: option.c:4430
+#: option.c:4688
 msgid "junk found in command line"
 msgstr ""
 
-#: option.c:4465
+#: option.c:4729
 #, c-format
 msgid "Dnsmasq version %s  %s\n"
 msgstr ""
 
-#: option.c:4466
+#: option.c:4730
 #, c-format
 msgid ""
 "Compile time options: %s\n"
 "\n"
 msgstr ""
 
-#: option.c:4467
+#: option.c:4731
 #, c-format
 msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
 msgstr ""
 
-#: option.c:4468
+#: option.c:4732
 #, c-format
 msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
 msgstr ""
 
-#: option.c:4469
+#: option.c:4733
 #, c-format
 msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
 msgstr ""
 
-#: option.c:4480
+#: option.c:4744
 msgid "try --help"
 msgstr ""
 
-#: option.c:4482
+#: option.c:4746
 msgid "try -w"
 msgstr ""
 
-#: option.c:4484
+#: option.c:4748
 #, c-format
 msgid "bad command line options: %s"
 msgstr ""
 
-#: option.c:4541
+#: option.c:4818
+#, c-format
+msgid "CNAME loop involving %s"
+msgstr ""
+
+#: option.c:4854
 #, c-format
 msgid "cannot get host-name: %s"
 msgstr ""
 
-#: option.c:4569
+#: option.c:4882
 msgid "only one resolv.conf file allowed in no-poll mode."
 msgstr ""
 
-#: option.c:4579
+#: option.c:4892
 msgid "must have exactly one resolv.conf to read domain from."
 msgstr ""
 
-#: option.c:4582 network.c:1507 dhcp.c:777
+#: option.c:4895 network.c:1623 dhcp.c:816
 #, c-format
 msgid "failed to read %s: %s"
 msgstr ""
 
-#: option.c:4599
+#: option.c:4912
 #, c-format
 msgid "no search directive found in %s"
 msgstr ""
 
-#: option.c:4620
+#: option.c:4933
 msgid "there must be a default domain when --dhcp-fqdn is set"
 msgstr ""
 
-#: option.c:4629
+#: option.c:4942
 msgid "syntax check OK"
 msgstr ""
 
-#: forward.c:111
+#: forward.c:102
 #, c-format
 msgid "failed to send packet: %s"
 msgstr ""
 
-#: forward.c:591
+#: forward.c:598
 msgid "discarding DNS reply: subnet option mismatch"
 msgstr ""
 
-#: forward.c:614
+#: forward.c:652
 #, c-format
 msgid "nameserver %s refused to do a recursive query"
 msgstr ""
 
-#: forward.c:646
+#: forward.c:684
 #, c-format
 msgid "possible DNS-rebind attack detected: %s"
 msgstr ""
 
-#: forward.c:1209 forward.c:1815
+#: forward.c:870
+#, c-format
+msgid "reducing DNS packet size for nameserver %s to %d"
+msgstr ""
+
+#: forward.c:1266 forward.c:1704
 msgid "Ignoring query from non-local network"
 msgstr ""
 
-#: forward.c:2286
+#: forward.c:2184
 #, c-format
 msgid "Maximum number of concurrent DNS queries reached (max: %d)"
 msgstr ""
 
-#: network.c:715
+#: network.c:720
 #, c-format
 msgid "failed to create listening socket for %s: %s"
 msgstr ""
 
-#: network.c:1021
+#: network.c:1031
 #, c-format
 msgid "LOUD WARNING: listening on %s may accept requests via interfaces other than %s"
 msgstr ""
 
-#: network.c:1028
+#: network.c:1038
 msgid "LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"
 msgstr ""
 
-#: network.c:1037
+#: network.c:1047
+#, c-format
+msgid "warning: using interface %s instead"
+msgstr ""
+
+#: network.c:1056
 #, c-format
 msgid "warning: no addresses found for interface %s"
 msgstr ""
 
-#: network.c:1095
+#: network.c:1114
 #, c-format
 msgid "interface %s failed to join DHCPv6 multicast group: %s"
 msgstr ""
 
-#: network.c:1289
+#: network.c:1119
+msgid "try increasing /proc/sys/net/core/optmem_max"
+msgstr ""
+
+#: network.c:1337
 #, c-format
 msgid "failed to bind server socket for %s: %s"
 msgstr ""
 
-#: network.c:1445
+#: network.c:1528
 #, c-format
 msgid "ignoring nameserver %s - local interface"
 msgstr ""
 
-#: network.c:1456
+#: network.c:1539
 #, c-format
 msgid "ignoring nameserver %s - cannot make/bind socket: %s"
 msgstr ""
 
-#: network.c:1469
+#: network.c:1559
+msgid "(no DNSSEC)"
+msgstr ""
+
+#: network.c:1562
 msgid "unqualified"
 msgstr ""
 
-#: network.c:1469
+#: network.c:1562
 msgid "names"
 msgstr ""
 
-#: network.c:1471
+#: network.c:1564
 msgid "default"
 msgstr ""
 
-#: network.c:1473
+#: network.c:1566
 msgid "domain"
 msgstr ""
 
-#: network.c:1476
+#: network.c:1572
 #, c-format
 msgid "using local addresses only for %s %s"
 msgstr ""
 
-#: network.c:1478
+#: network.c:1575
 #, c-format
 msgid "using standard nameservers for %s %s"
 msgstr ""
 
-#: network.c:1480
+#: network.c:1577
 #, c-format
-msgid "using nameserver %s#%d for %s %s"
+msgid "using nameserver %s#%d for %s %s %s"
 msgstr ""
 
-#: network.c:1484
+#: network.c:1581
 #, c-format
 msgid "NOT using nameserver %s#%d - query loop detected"
 msgstr ""
 
-#: network.c:1487
+#: network.c:1584
 #, c-format
 msgid "using nameserver %s#%d(via %s)"
 msgstr ""
 
-#: network.c:1489
+#: network.c:1586
 #, c-format
 msgid "using nameserver %s#%d"
 msgstr ""
 
-#: dnsmasq.c:163
+#: network.c:1591
+#, c-format
+msgid "using %d more local addresses"
+msgstr ""
+
+#: network.c:1593
+#, c-format
+msgid "using %d more nameservers"
+msgstr ""
+
+#: dnsmasq.c:171
 msgid "dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"
 msgstr ""
 
-#: dnsmasq.c:170
-msgid "no trust anchors provided for DNSSEC"
+#: dnsmasq.c:186
+msgid "no root trust anchor provided for DNSSEC"
 msgstr ""
 
-#: dnsmasq.c:173
+#: dnsmasq.c:189
 msgid "cannot reduce cache size from default when DNSSEC enabled"
 msgstr ""
 
-#: dnsmasq.c:175
+#: dnsmasq.c:191
 msgid "DNSSEC not available: set HAVE_DNSSEC in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:181
+#: dnsmasq.c:197
 msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:186
+#: dnsmasq.c:202
 msgid "cannot use --conntrack AND --query-port"
 msgstr ""
 
-#: dnsmasq.c:189
+#: dnsmasq.c:205
 msgid "conntrack support not available: set HAVE_CONNTRACK in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:194
-msgid "asychronous logging is not available under Solaris"
+#: dnsmasq.c:210
+msgid "asynchronous logging is not available under Solaris"
 msgstr ""
 
-#: dnsmasq.c:199
-msgid "asychronous logging is not available under Android"
+#: dnsmasq.c:215
+msgid "asynchronous logging is not available under Android"
 msgstr ""
 
-#: dnsmasq.c:204
+#: dnsmasq.c:220
 msgid "authoritative DNS not available: set HAVE_AUTH in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:209
+#: dnsmasq.c:225
 msgid "loop detection not available: set HAVE_LOOP in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:217
+#: dnsmasq.c:229
+msgid "max_port cannot be smaller than min_port"
+msgstr ""
+
+#: dnsmasq.c:236
 msgid "zone serial must be configured in --auth-soa"
 msgstr ""
 
-#: dnsmasq.c:235
+#: dnsmasq.c:254
 msgid "dhcp-range constructor not available on this platform"
 msgstr ""
 
-#: dnsmasq.c:278
+#: dnsmasq.c:300
 msgid "cannot set --bind-interfaces and --bind-dynamic"
 msgstr ""
 
-#: dnsmasq.c:281
+#: dnsmasq.c:303
 #, c-format
 msgid "failed to find list of interfaces: %s"
 msgstr ""
 
-#: dnsmasq.c:290
+#: dnsmasq.c:312
 #, c-format
 msgid "unknown interface %s"
 msgstr ""
 
-#: dnsmasq.c:354 dnsmasq.c:997
+#: dnsmasq.c:377 dnsmasq.c:1054
 #, c-format
 msgid "DBus error: %s"
 msgstr ""
 
-#: dnsmasq.c:357
+#: dnsmasq.c:380
 msgid "DBus not available: set HAVE_DBUS in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:385
+#: dnsmasq.c:410
 #, c-format
 msgid "unknown user or group: %s"
 msgstr ""
 
-#: dnsmasq.c:440
+#: dnsmasq.c:465
 #, c-format
 msgid "cannot chdir to filesystem root: %s"
 msgstr ""
 
-#: dnsmasq.c:692
+#: dnsmasq.c:730
 #, c-format
 msgid "started, version %s DNS disabled"
 msgstr ""
 
-#: dnsmasq.c:694
+#: dnsmasq.c:734
 #, c-format
 msgid "started, version %s cachesize %d"
 msgstr ""
 
-#: dnsmasq.c:696
+#: dnsmasq.c:736
 #, c-format
 msgid "started, version %s cache disabled"
 msgstr ""
 
-#: dnsmasq.c:698
+#: dnsmasq.c:739
+msgid "DNS service limited to local subnets"
+msgstr ""
+
+#: dnsmasq.c:742
 #, c-format
 msgid "compile time options: %s"
 msgstr ""
 
-#: dnsmasq.c:704
+#: dnsmasq.c:751
 msgid "DBus support enabled: connected to system bus"
 msgstr ""
 
-#: dnsmasq.c:706
+#: dnsmasq.c:753
 msgid "DBus support enabled: bus connection pending"
 msgstr ""
 
-#: dnsmasq.c:711
-msgid "DNS service limited to local subnets"
-msgstr ""
-
-#: dnsmasq.c:727
+#: dnsmasq.c:771
 msgid "DNSSEC validation enabled"
 msgstr ""
 
-#: dnsmasq.c:730
-msgid "DNSSEC signature timestamps not checked until first cache reload"
+#: dnsmasq.c:775
+msgid "DNSSEC signature timestamps not checked until receipt of SIGINT"
 msgstr ""
 
-#: dnsmasq.c:733
+#: dnsmasq.c:778
 msgid "DNSSEC signature timestamps not checked until system time valid"
 msgstr ""
 
-#: dnsmasq.c:738
+#: dnsmasq.c:783
 #, c-format
 msgid "warning: failed to change owner of %s: %s"
 msgstr ""
 
-#: dnsmasq.c:742
+#: dnsmasq.c:787
 msgid "setting --bind-interfaces option because of OS limitations"
 msgstr ""
 
-#: dnsmasq.c:752
+#: dnsmasq.c:799
 #, c-format
 msgid "warning: interface %s does not currently exist"
 msgstr ""
 
-#: dnsmasq.c:757
+#: dnsmasq.c:804
 msgid "warning: ignoring resolv-file flag because no-resolv is set"
 msgstr ""
 
-#: dnsmasq.c:760
+#: dnsmasq.c:807
 msgid "warning: no upstream servers configured"
 msgstr ""
 
-#: dnsmasq.c:764
+#: dnsmasq.c:811
 #, c-format
 msgid "asynchronous logging enabled, queue limit is %d messages"
 msgstr ""
 
-#: dnsmasq.c:785
+#: dnsmasq.c:832
 msgid "IPv6 router advertisement enabled"
 msgstr ""
 
-#: dnsmasq.c:790
+#: dnsmasq.c:837
 #, c-format
 msgid "DHCP, sockets bound exclusively to interface %s"
 msgstr ""
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "root is "
 msgstr ""
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "enabled"
 msgstr ""
 
-#: dnsmasq.c:806
+#: dnsmasq.c:853
 msgid "secure mode"
 msgstr ""
 
-#: dnsmasq.c:809
+#: dnsmasq.c:856
 #, c-format
 msgid "warning: %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:813
+#: dnsmasq.c:860
 #, c-format
 msgid "warning: TFTP directory %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:839
+#: dnsmasq.c:886
 #, c-format
 msgid "restricting maximum simultaneous TFTP transfers to %d"
 msgstr ""
 
-#: dnsmasq.c:999
+#: dnsmasq.c:1056
 msgid "connected to system DBus"
 msgstr ""
 
-#: dnsmasq.c:1149
+#: dnsmasq.c:1215
 #, c-format
 msgid "cannot fork into background: %s"
 msgstr ""
 
-#: dnsmasq.c:1152
+#: dnsmasq.c:1218
 #, c-format
 msgid "failed to create helper: %s"
 msgstr ""
 
-#: dnsmasq.c:1155
+#: dnsmasq.c:1221
 #, c-format
 msgid "setting capabilities failed: %s"
 msgstr ""
 
-#: dnsmasq.c:1158
+#: dnsmasq.c:1224
 #, c-format
 msgid "failed to change user-id to %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1161
+#: dnsmasq.c:1227
 #, c-format
 msgid "failed to change group-id to %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1164
+#: dnsmasq.c:1230
 #, c-format
 msgid "failed to open pidfile %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1167
+#: dnsmasq.c:1233
 #, c-format
 msgid "cannot open log %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1170
+#: dnsmasq.c:1236
 #, c-format
 msgid "failed to load Lua script: %s"
 msgstr ""
 
-#: dnsmasq.c:1173
+#: dnsmasq.c:1239
 #, c-format
 msgid "TFTP directory %s inaccessible: %s"
 msgstr ""
 
-#: dnsmasq.c:1176
+#: dnsmasq.c:1242
 #, c-format
 msgid "cannot create timestamp file %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1197
-msgid "now checking DNSSEC signature timestamps"
-msgstr ""
-
-#: dnsmasq.c:1264
+#: dnsmasq.c:1326
 #, c-format
 msgid "script process killed by signal %d"
 msgstr ""
 
-#: dnsmasq.c:1268
+#: dnsmasq.c:1330
 #, c-format
 msgid "script process exited with status %d"
 msgstr ""
 
-#: dnsmasq.c:1272
+#: dnsmasq.c:1334
 #, c-format
 msgid "failed to execute %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1327
+#: dnsmasq.c:1374
+msgid "now checking DNSSEC signature timestamps"
+msgstr ""
+
+#: dnsmasq.c:1409 dnssec.c:160 dnssec.c:206
+#, c-format
+msgid "failed to update mtime on %s: %s"
+msgstr ""
+
+#: dnsmasq.c:1416
 msgid "exiting on receipt of SIGTERM"
 msgstr ""
 
-#: dnsmasq.c:1355
+#: dnsmasq.c:1444
 #, c-format
 msgid "failed to access %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1385
+#: dnsmasq.c:1474
 #, c-format
 msgid "reading %s"
 msgstr ""
 
-#: dnsmasq.c:1396
+#: dnsmasq.c:1485
 #, c-format
 msgid "no servers found in %s, will retry"
 msgstr ""
@@ -1521,243 +1595,263 @@ msgstr ""
 msgid "cannot create ICMP raw socket: %s."
 msgstr ""
 
-#: dhcp.c:241 dhcp6.c:180
+#: dhcp.c:252 dhcp6.c:173
 #, c-format
 msgid "unknown interface %s in bridge-interface"
 msgstr ""
 
-#: dhcp.c:281
+#: dhcp.c:293
 #, c-format
 msgid "DHCP packet received on %s which has no address"
 msgstr ""
 
-#: dhcp.c:415
+#: dhcp.c:427
 #, c-format
 msgid "ARP-cache injection failed: %s"
 msgstr ""
 
-#: dhcp.c:514
+#: dhcp.c:470
+#, c-format
+msgid "Error sending DHCP packet to %s: %s"
+msgstr ""
+
+#: dhcp.c:531
 #, c-format
 msgid "DHCP range %s -- %s is not consistent with netmask %s"
 msgstr ""
 
-#: dhcp.c:815
+#: dhcp.c:854
 #, c-format
 msgid "bad line at %s line %d"
 msgstr ""
 
-#: dhcp.c:858
+#: dhcp.c:897
 #, c-format
 msgid "ignoring %s line %d, duplicate name or IP address"
 msgstr ""
 
-#: dhcp.c:1002 rfc3315.c:2135
+#: dhcp.c:1041 rfc3315.c:2149
 #, c-format
 msgid "DHCP relay %s -> %s"
 msgstr ""
 
-#: lease.c:61
+#: lease.c:98
+msgid "too many stored leases"
+msgstr ""
+
+#: lease.c:166
 #, c-format
 msgid "cannot open or create lease file %s: %s"
 msgstr ""
 
-#: lease.c:134
-msgid "too many stored leases"
+#: lease.c:175
+#, c-format
+msgid "failed to parse lease database, invalid line: %s %s %s %s ..."
 msgstr ""
 
-#: lease.c:165
+#: lease.c:180
+#, c-format
+msgid "failed to read lease file %s: %s"
+msgstr ""
+
+#: lease.c:196
 #, c-format
 msgid "cannot run lease-init script %s: %s"
 msgstr ""
 
-#: lease.c:171
+#: lease.c:202
 #, c-format
 msgid "lease-init script returned exit code %s"
 msgstr ""
 
-#: lease.c:342
+#: lease.c:373
 #, c-format
 msgid "failed to write %s: %s (retry in %us)"
 msgstr ""
 
-#: lease.c:906
+#: lease.c:937
 #, c-format
 msgid "Ignoring domain %s for DHCP host name %s"
 msgstr ""
 
-#: rfc2131.c:344
+#: rfc2131.c:347
 #, c-format
 msgid "no address range available for DHCP request %s %s"
 msgstr ""
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "with subnet selector"
 msgstr ""
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "via"
 msgstr ""
 
-#: rfc2131.c:357
+#: rfc2131.c:360
 #, c-format
 msgid "%u available DHCP subnet: %s/%s"
 msgstr ""
 
-#: rfc2131.c:360 rfc3315.c:300
+#: rfc2131.c:363 rfc3315.c:306
 #, c-format
 msgid "%u available DHCP range: %s -- %s"
 msgstr ""
 
-#: rfc2131.c:471
+#: rfc2131.c:474
 #, c-format
 msgid "%u vendor class: %s"
 msgstr ""
 
-#: rfc2131.c:473
+#: rfc2131.c:476
 #, c-format
 msgid "%u user class: %s"
 msgstr ""
 
-#: rfc2131.c:500
+#: rfc2131.c:510
 msgid "disabled"
 msgstr ""
 
-#: rfc2131.c:541 rfc2131.c:974 rfc2131.c:1380 rfc3315.c:603 rfc3315.c:856
-#: rfc3315.c:1135
+#: rfc2131.c:551 rfc2131.c:1006 rfc2131.c:1430 rfc3315.c:616 rfc3315.c:869
+#: rfc3315.c:1148
 msgid "ignored"
 msgstr ""
 
-#: rfc2131.c:556 rfc2131.c:1207 rfc3315.c:906
+#: rfc2131.c:566 rfc2131.c:1239 rfc3315.c:919
 msgid "address in use"
 msgstr ""
 
-#: rfc2131.c:570 rfc2131.c:1028
+#: rfc2131.c:580 rfc2131.c:1060
 msgid "no address available"
 msgstr ""
 
-#: rfc2131.c:577 rfc2131.c:1170
+#: rfc2131.c:587 rfc2131.c:1202
 msgid "wrong network"
 msgstr ""
 
-#: rfc2131.c:592
+#: rfc2131.c:602
 msgid "no address configured"
 msgstr ""
 
-#: rfc2131.c:598 rfc2131.c:1220
+#: rfc2131.c:608 rfc2131.c:1252
 msgid "no leases left"
 msgstr ""
 
-#: rfc2131.c:693 rfc3315.c:476
+#: rfc2131.c:703 rfc3315.c:482
 #, c-format
 msgid "%u client provides name: %s"
 msgstr ""
 
-#: rfc2131.c:798
+#: rfc2131.c:808
 msgid "PXE BIS not supported"
 msgstr ""
 
-#: rfc2131.c:942 rfc3315.c:1229
+#: rfc2131.c:974 rfc3315.c:1242
 #, c-format
 msgid "disabling DHCP static address %s for %s"
 msgstr ""
 
-#: rfc2131.c:963
+#: rfc2131.c:995
 msgid "unknown lease"
 msgstr ""
 
-#: rfc2131.c:997
+#: rfc2131.c:1029
 #, c-format
 msgid "not using configured address %s because it is leased to %s"
 msgstr ""
 
-#: rfc2131.c:1007
+#: rfc2131.c:1039
 #, c-format
 msgid "not using configured address %s because it is in use by the server or relay"
 msgstr ""
 
-#: rfc2131.c:1010
+#: rfc2131.c:1042
 #, c-format
 msgid "not using configured address %s because it was previously declined"
 msgstr ""
 
-#: rfc2131.c:1026 rfc2131.c:1213
+#: rfc2131.c:1058 rfc2131.c:1245
 msgid "no unique-id"
 msgstr ""
 
-#: rfc2131.c:1108
+#: rfc2131.c:1140
 msgid "wrong server-ID"
 msgstr ""
 
-#: rfc2131.c:1127
+#: rfc2131.c:1159
 msgid "wrong address"
 msgstr ""
 
-#: rfc2131.c:1145 rfc3315.c:1002
+#: rfc2131.c:1177 rfc3315.c:1015
 msgid "lease not found"
 msgstr ""
 
-#: rfc2131.c:1178
+#: rfc2131.c:1210
 msgid "address not available"
 msgstr ""
 
-#: rfc2131.c:1189
+#: rfc2131.c:1221
 msgid "static lease available"
 msgstr ""
 
-#: rfc2131.c:1193
+#: rfc2131.c:1225
 msgid "address reserved"
 msgstr ""
 
-#: rfc2131.c:1201
+#: rfc2131.c:1233
 #, c-format
 msgid "abandoning lease to %s of %s"
 msgstr ""
 
-#: rfc2131.c:1707
+#: rfc2131.c:1757
 #, c-format
 msgid "%u bootfile name: %s"
 msgstr ""
 
-#: rfc2131.c:1716
+#: rfc2131.c:1766
 #, c-format
 msgid "%u server name: %s"
 msgstr ""
 
-#: rfc2131.c:1724
+#: rfc2131.c:1774
 #, c-format
 msgid "%u next server: %s"
 msgstr ""
 
-#: rfc2131.c:1727
+#: rfc2131.c:1777
 #, c-format
 msgid "%u broadcast response"
 msgstr ""
 
-#: rfc2131.c:1790
+#: rfc2131.c:1840
 #, c-format
 msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
 msgstr ""
 
-#: rfc2131.c:2031
+#: rfc2131.c:2131
 msgid "PXE menu too large"
 msgstr ""
 
-#: rfc2131.c:2170 rfc3315.c:1502
+#: rfc2131.c:2270 rfc3315.c:1515
 #, c-format
 msgid "%u requested options: %s"
 msgstr ""
 
-#: rfc2131.c:2487
+#: rfc2131.c:2587
 #, c-format
 msgid "cannot send RFC3925 option: too many options for enterprise number %d"
 msgstr ""
 
+#: rfc2131.c:2650
+#, c-format
+msgid "%u reply delay: %d"
+msgstr ""
+
 #: netlink.c:77
 #, c-format
 msgid "cannot create netlink socket: %s"
 msgstr ""
 
-#: netlink.c:348
+#: netlink.c:355
 #, c-format
 msgid "netlink returns error: %s"
 msgstr ""
@@ -1776,62 +1870,62 @@ msgstr ""
 msgid "Disabling --%s option from D-Bus"
 msgstr ""
 
-#: dbus.c:691
+#: dbus.c:690
 msgid "setting upstream servers from DBus"
 msgstr ""
 
-#: dbus.c:738
+#: dbus.c:737
 msgid "could not register a DBus message handler"
 msgstr ""
 
-#: bpf.c:263
+#: bpf.c:265
 #, c-format
 msgid "cannot create DHCP BPF socket: %s"
 msgstr ""
 
-#: bpf.c:291
+#: bpf.c:293
 #, c-format
 msgid "DHCP request for unsupported hardware type (%d) received on %s"
 msgstr ""
 
-#: bpf.c:376
+#: bpf.c:378
 #, c-format
 msgid "cannot create PF_ROUTE socket: %s"
 msgstr ""
 
-#: bpf.c:397
+#: bpf.c:399
 msgid "Unknown protocol version from route socket"
 msgstr ""
 
-#: helper.c:153
+#: helper.c:154
 msgid "lease() function missing in Lua script"
 msgstr ""
 
-#: tftp.c:309
+#: tftp.c:319
 msgid "unable to get free port for TFTP"
 msgstr ""
 
-#: tftp.c:325
+#: tftp.c:335
 #, c-format
 msgid "unsupported request from %s"
 msgstr ""
 
-#: tftp.c:439
+#: tftp.c:483
 #, c-format
 msgid "file %s not found"
 msgstr ""
 
-#: tftp.c:548
+#: tftp.c:592
 #, c-format
 msgid "error %d %s received from %s"
 msgstr ""
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "failed sending %s to %s"
 msgstr ""
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "sent %s to %s"
 msgstr ""
@@ -1846,7 +1940,7 @@ msgstr ""
 msgid "log failed: %s"
 msgstr ""
 
-#: log.c:469
+#: log.c:471
 msgid "FAILED to start up"
 msgstr ""
 
@@ -1855,17 +1949,17 @@ msgstr ""
 msgid "Conntrack connection mark retrieval failed: %s"
 msgstr ""
 
-#: dhcp6.c:59
+#: dhcp6.c:52
 #, c-format
 msgid "cannot create DHCPv6 socket: %s"
 msgstr ""
 
-#: dhcp6.c:80
+#: dhcp6.c:73
 #, c-format
 msgid "failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"
 msgstr ""
 
-#: dhcp6.c:92
+#: dhcp6.c:85
 #, c-format
 msgid "failed to bind DHCPv6 server socket: %s"
 msgstr ""
@@ -1880,67 +1974,67 @@ msgstr ""
 msgid "no address range available for DHCPv6 request via %s"
 msgstr ""
 
-#: rfc3315.c:297
+#: rfc3315.c:303
 #, c-format
 msgid "%u available DHCPv6 subnet: %s/%d"
 msgstr ""
 
-#: rfc3315.c:380
+#: rfc3315.c:386
 #, c-format
 msgid "%u vendor class: %u"
 msgstr ""
 
-#: rfc3315.c:428
+#: rfc3315.c:434
 #, c-format
 msgid "%u client MAC address: %s"
 msgstr ""
 
-#: rfc3315.c:660
+#: rfc3315.c:673
 #, c-format
 msgid "unknown prefix-class %d"
 msgstr ""
 
-#: rfc3315.c:803 rfc3315.c:898
+#: rfc3315.c:816 rfc3315.c:911
 msgid "address unavailable"
 msgstr ""
 
-#: rfc3315.c:815 rfc3315.c:946 rfc3315.c:1279
+#: rfc3315.c:828 rfc3315.c:959 rfc3315.c:1292
 msgid "success"
 msgstr ""
 
-#: rfc3315.c:830 rfc3315.c:839 rfc3315.c:954 rfc3315.c:956
+#: rfc3315.c:843 rfc3315.c:852 rfc3315.c:967 rfc3315.c:969
 msgid "no addresses available"
 msgstr ""
 
-#: rfc3315.c:933
+#: rfc3315.c:946
 msgid "not on link"
 msgstr ""
 
-#: rfc3315.c:1006 rfc3315.c:1191 rfc3315.c:1268
+#: rfc3315.c:1019 rfc3315.c:1204 rfc3315.c:1281
 msgid "no binding found"
 msgstr ""
 
-#: rfc3315.c:1044
+#: rfc3315.c:1057
 msgid "deprecated"
 msgstr ""
 
-#: rfc3315.c:1049
+#: rfc3315.c:1062
 msgid "address invalid"
 msgstr ""
 
-#: rfc3315.c:1096
+#: rfc3315.c:1109
 msgid "confirm failed"
 msgstr ""
 
-#: rfc3315.c:1112
+#: rfc3315.c:1125
 msgid "all addresses still on link"
 msgstr ""
 
-#: rfc3315.c:1200
+#: rfc3315.c:1213
 msgid "release received"
 msgstr ""
 
-#: rfc3315.c:2126
+#: rfc3315.c:2140
 msgid "Cannot multicast to DHCPv6 server without correct interface"
 msgstr ""
 
@@ -1964,76 +2058,76 @@ msgstr ""
 msgid "duplicate IP address %s (%s) in dhcp-config directive"
 msgstr ""
 
-#: dhcp-common.c:494
+#: dhcp-common.c:491
 #, c-format
 msgid "failed to set SO_BINDTODEVICE on DHCP socket: %s"
 msgstr ""
 
-#: dhcp-common.c:615
+#: dhcp-common.c:612
 #, c-format
 msgid "Known DHCP options:\n"
 msgstr ""
 
-#: dhcp-common.c:626
+#: dhcp-common.c:623
 #, c-format
 msgid "Known DHCPv6 options:\n"
 msgstr ""
 
-#: dhcp-common.c:823
+#: dhcp-common.c:820
 msgid ", prefix deprecated"
 msgstr ""
 
-#: dhcp-common.c:826
+#: dhcp-common.c:823
 #, c-format
 msgid ", lease time "
 msgstr ""
 
-#: dhcp-common.c:868
+#: dhcp-common.c:865
 #, c-format
 msgid "%s stateless on %s%.0s%.0s%s"
 msgstr ""
 
-#: dhcp-common.c:870
+#: dhcp-common.c:867
 #, c-format
 msgid "%s, static leases only on %.0s%s%s%.0s"
 msgstr ""
 
-#: dhcp-common.c:872
+#: dhcp-common.c:869
 #, c-format
 msgid "%s, proxy on subnet %.0s%s%.0s%.0s"
 msgstr ""
 
-#: dhcp-common.c:873
+#: dhcp-common.c:870
 #, c-format
 msgid "%s, IP range %s -- %s%s%.0s"
 msgstr ""
 
-#: dhcp-common.c:886
+#: dhcp-common.c:883
 #, c-format
 msgid "DHCPv4-derived IPv6 names on %s%s"
 msgstr ""
 
-#: dhcp-common.c:889
+#: dhcp-common.c:886
 #, c-format
 msgid "router advertisement on %s%s"
 msgstr ""
 
-#: dhcp-common.c:900
+#: dhcp-common.c:897
 #, c-format
 msgid "DHCP relay from %s to %s via %s"
 msgstr ""
 
-#: dhcp-common.c:902
+#: dhcp-common.c:899
 #, c-format
 msgid "DHCP relay from %s to %s"
 msgstr ""
 
-#: radv.c:109
+#: radv.c:110
 #, c-format
 msgid "cannot create ICMPv6 socket: %s"
 msgstr ""
 
-#: auth.c:448
+#: auth.c:449
 #, c-format
 msgid "ignoring zone transfer request from %s"
 msgstr ""
@@ -2048,9 +2142,13 @@ msgstr ""
 msgid "failed to create IPset control socket: %s"
 msgstr ""
 
-#: dnssec.c:449 dnssec.c:493
+#: ipset.c:233
 #, c-format
-msgid "failed to update mtime on %s: %s"
+msgid "failed to update ipset %s: %s"
+msgstr ""
+
+#: dnssec.c:208
+msgid "system time considered valid, now checking DNSSEC signature timestamps."
 msgstr ""
 
 #: blockdata.c:58
@@ -2058,80 +2156,76 @@ msgstr ""
 msgid "DNSSEC memory in use %u, max %u, allocated %u"
 msgstr ""
 
-#: tables.c:80
-msgid "error: fill_addr missused"
-msgstr ""
-
-#: tables.c:109
+#: tables.c:61
 #, c-format
 msgid "failed to access pf devices: %s"
 msgstr ""
 
-#: tables.c:123
+#: tables.c:74
 #, c-format
 msgid "warning: no opened pf devices %s"
 msgstr ""
 
-#: tables.c:131
+#: tables.c:82
 #, c-format
 msgid "error: cannot use table name %s"
 msgstr ""
 
-#: tables.c:139
+#: tables.c:90
 #, c-format
 msgid "error: cannot strlcpy table name %s"
 msgstr ""
 
-#: tables.c:145
+#: tables.c:101
 #, c-format
-msgid "warning: pfr_add_tables: %s(%d)"
+msgid "IPset: error:%s"
 msgstr ""
 
-#: tables.c:151
+#: tables.c:108
 msgid "info: table created"
 msgstr ""
 
-#: tables.c:162
+#: tables.c:134
 #, c-format
 msgid "warning: DIOCR%sADDRS: %s"
 msgstr ""
 
-#: tables.c:166
+#: tables.c:138
 #, c-format
 msgid "%d addresses %s"
 msgstr ""
 
-#: inotify.c:59
+#: inotify.c:62
 #, c-format
 msgid "cannot access path %s: %s"
 msgstr ""
 
-#: inotify.c:92
+#: inotify.c:95
 #, c-format
 msgid "failed to create inotify: %s"
 msgstr ""
 
-#: inotify.c:105
+#: inotify.c:111
 #, c-format
 msgid "too many symlinks following %s"
 msgstr ""
 
-#: inotify.c:121
+#: inotify.c:127
 #, c-format
 msgid "directory %s for resolv-file is missing, cannot poll"
 msgstr ""
 
-#: inotify.c:125 inotify.c:162
+#: inotify.c:131 inotify.c:168
 #, c-format
 msgid "failed to create inotify for %s: %s"
 msgstr ""
 
-#: inotify.c:147
+#: inotify.c:153
 #, c-format
 msgid "bad dynamic directory %s: %s"
 msgstr ""
 
-#: inotify.c:247
+#: inotify.c:257
 #, c-format
 msgid "inotify, new or changed file %s"
 msgstr ""
index 6ee92ec..b532d4f 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
@@ -7,744 +7,774 @@ msgstr ""
 "Project-Id-Version: dnsmasq 2.67\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2009-06-18 12:24+0100\n"
-"PO-Revision-Date: 2013-10-24 19:24+1100\n"
+"PO-Revision-Date: 2017-07-17 18:30+0100\n"
 "Last-Translator:  Gildas Le Nadan <3ntr0p13@gmail.com>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=ISO-8859-1\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: cache.c:523
+#: cache.c:518
 msgid "Internal error in cache."
 msgstr ""
 
-#: cache.c:941
+#: cache.c:928
 #, c-format
 msgid "failed to load names from %s: %s"
 msgstr "Impossible de charger les noms à partir de %s : %s"
 
-#: cache.c:967 dhcp.c:828
+#: cache.c:954 dhcp.c:867
 #, c-format
 msgid "bad address at %s line %d"
 msgstr "mauvaise adresse dans %s ligne %d"
 
-#: cache.c:1018 dhcp.c:844
+#: cache.c:1007 dhcp.c:883
 #, c-format
 msgid "bad name at %s line %d"
 msgstr "mauvais nom dans %s ligne %d"
 
-#: cache.c:1027 dhcp.c:919
+#: cache.c:1016 dhcp.c:958
 #, c-format
 msgid "read %s - %d addresses"
 msgstr "lecture %s - %d adresses"
 
-#: cache.c:1135
+#: cache.c:1129
 msgid "cleared cache"
 msgstr "cache vidé"
 
-#: cache.c:1164
+#: cache.c:1158
 #, c-format
 msgid "No IPv4 address found for %s"
 msgstr "Aucune adresse IPv4 trouvée pour %s"
 
-#: cache.c:1242
+#: cache.c:1237
 #, c-format
 msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
 msgstr "%s est un CNAME, il ne sera pas donné au bail DHCP de %s"
 
-#: cache.c:1266
+#: cache.c:1261
 #, c-format
 msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
 msgstr "ne donne pas de nom %s au bail DHCP de %s parce-que le nom existe dans %s avec l'adresse %s"
 
-#: cache.c:1421
+#: cache.c:1418
 #, c-format
 msgid "time %lu"
 msgstr "horodatage %lu"
 
-#: cache.c:1422
+#: cache.c:1419
 #, c-format
 msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
 msgstr "taille de cache %d, %d/%d insertions dans le cache entrées non-expirées réutilisées"
 
-#: cache.c:1424
+#: cache.c:1421
 #, c-format
 msgid "queries forwarded %u, queries answered locally %u"
 msgstr "requêtes transmises %u, requêtes résolues localement %u"
 
-#: cache.c:1427
+#: cache.c:1424
 #, fuzzy, c-format
 msgid "queries for authoritative zones %u"
 msgstr "Configure la durée de vie (Time To Live) pour les réponses faisant autorité"
 
-#: cache.c:1453
+#: cache.c:1450
 #, c-format
 msgid "server %s#%d: queries sent %u, retried or failed %u"
 msgstr "serveur %s#%d: requêtes envoyées %u, requêtes réessayées ou échouées %u"
 
-#: util.c:45
+#: util.c:47
 #, c-format
 msgid "failed to seed the random number generator: %s"
 msgstr "impossible d'initialiser le générateur de nombre aléatoire : %s"
 
-#: util.c:205
+#: util.c:224
 msgid "failed to allocate memory"
 msgstr "impossible d'allouer la mémoire"
 
-#: util.c:250 option.c:601
+#: util.c:281 option.c:619
 msgid "could not get memory"
 msgstr "impossible d'allouer de la mémoire"
 
-#: util.c:260
+#: util.c:291
 #, c-format
 msgid "cannot create pipe: %s"
 msgstr "Ne peut pas créer le tube %s : %s"
 
-#: util.c:268
+#: util.c:299
 #, c-format
 msgid "failed to allocate %d bytes"
 msgstr "impossible d'allouer %d octets"
 
-#: util.c:437
+#: util.c:468
 #, c-format
 msgid "infinite"
 msgstr "illimité(e)"
 
-#: option.c:332
+#: option.c:344
 msgid "Specify local address(es) to listen on."
 msgstr "Spécifie la ou les adresse(s) locales où le démon doit se mettre à l'écoute."
 
-#: option.c:333
+#: option.c:345
 msgid "Return ipaddr for all hosts in specified domains."
 msgstr "Retourne les adresses IP pour toutes les machines présentes dans les domaines spécifiés"
 
-#: option.c:334
+#: option.c:346
 msgid "Fake reverse lookups for RFC1918 private address ranges."
 msgstr "Traduction inverse truquée pour la plage d'adresse privée RFC1918"
 
-#: option.c:335
+#: option.c:347
 msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
 msgstr "Traite l'adresse IP comme un domaine inexistant NXDOMAIN (contourne le systeme de redirection de Verisign)"
 
-#: option.c:336
+#: option.c:348
 #, c-format
 msgid "Specify the size of the cache in entries (defaults to %s)."
 msgstr "Spécifie le nombre d'entrées que contiendra le cache (par défaut : %s)."
 
-#: option.c:337
+#: option.c:349
 #, c-format
 msgid "Specify configuration file (defaults to %s)."
 msgstr "Spécifie le nom du fichier de configuration (par défaut : %s)"
 
-#: option.c:338
+#: option.c:350
 msgid "Do NOT fork into the background: run in debug mode."
 msgstr "Ne passe pas en tâche de fond : démarre en mode debug"
 
-#: option.c:339
+#: option.c:351
 msgid "Do NOT forward queries with no domain part."
 msgstr "Ne retransmet pas les requêtes qui n'ont pas de domaine."
 
-#: option.c:340
+#: option.c:352
 msgid "Return self-pointing MX records for local hosts."
 msgstr "Retourne les champs MX pour les machines locales."
 
-#: option.c:341
+#: option.c:353
 msgid "Expand simple names in /etc/hosts with domain-suffix."
 msgstr "Etend les noms uniques des machines dans /etc/hosts avec le suffixe du domaine."
 
-#: option.c:342
+#: option.c:354
 msgid "Don't forward spurious DNS requests from Windows hosts."
 msgstr "Ne retransmet pas les fausses requêtes DNS en provenance des machines Windows."
 
-#: option.c:343
+#: option.c:355
 msgid "Enable DHCP in the range given with lease duration."
 msgstr "Autorise DHCP dans la plage d'adresses donnée sur la durée de validité du bail."
 
-#: option.c:344
+#: option.c:356
 #, c-format
 msgid "Change to this group after startup (defaults to %s)."
 msgstr "On change pour ce groupe après le démarrage (par défaut : %s)."
 
-#: option.c:345
+#: option.c:357
 msgid "Set address or hostname for a specified machine."
 msgstr "On assigne une adresse ou un nom pour une machine spécifiée."
 
-#: option.c:346
+#: option.c:358
 msgid "Read DHCP host specs from file."
 msgstr "Lecture des spécifications d'hôtes DHCP à partir du fichier"
 
-#: option.c:347
+#: option.c:359
 msgid "Read DHCP option specs from file."
 msgstr "Lecture des options DHCP à partir du fichier"
 
-#: option.c:348
+#: option.c:360
 #, fuzzy
 msgid "Read DHCP host specs from a directory."
 msgstr "Lecture des spécifications d'hôtes DHCP à partir du fichier"
 
-#: option.c:349
+#: option.c:361
 #, fuzzy
 msgid "Read DHCP options from a directory."
 msgstr "Lecture des options DHCP à partir du fichier"
 
-#: option.c:350
+#: option.c:362
 msgid "Evaluate conditional tag expression."
 msgstr "Expression d'évaluation conditionnelle d'étiquette"
 
-#: option.c:351
+#: option.c:363
 #, c-format
 msgid "Do NOT load %s file."
 msgstr "Ne charge PAS le fichier %s."
 
-#: option.c:352
+#: option.c:364
 #, c-format
 msgid "Specify a hosts file to be read in addition to %s."
 msgstr "Spécifie un nom de fichier hosts à lire en complément de %s"
 
-#: option.c:353
+#: option.c:365
 #, fuzzy
 msgid "Read hosts files from a directory."
 msgstr "Lecture des spécifications d'hôtes DHCP à partir du fichier"
 
-#: option.c:354
+#: option.c:366
 msgid "Specify interface(s) to listen on."
 msgstr "Spécifie la ou les interface(s) où le démon doit se mettre à l'écoute."
 
-#: option.c:355
+#: option.c:367
 msgid "Specify interface(s) NOT to listen on."
 msgstr "Spécifie la ou les interface(s) que le démon ne doit PAS traiter."
 
 #
-#: option.c:356
+#: option.c:368
 msgid "Map DHCP user class to tag."
 msgstr "Associe les classes d'utilisateurs ('user class') DHCP aux options."
 
-#: option.c:357
+#: option.c:369
 msgid "Map RFC3046 circuit-id to tag."
 msgstr "Associe les identifiants de circuits RFC3046 ('circuit-id') aux options"
 
-#: option.c:358
+#: option.c:370
 msgid "Map RFC3046 remote-id to tag."
 msgstr "Associe les identifiants distants RFC3046 ('remote-id') aux options"
 
-#: option.c:359
+#: option.c:371
 msgid "Map RFC3993 subscriber-id to tag."
 msgstr "Associe les identifiants de souscripteurs RFC3993 ('subscriber-id') aux options"
 
 #
-#: option.c:360
+#: option.c:372
 msgid "Don't do DHCP for hosts with tag set."
 msgstr "Ne pas autoriser DHCP pour les machines énumerées dans les options."
 
 #
-#: option.c:361
+#: option.c:373
 msgid "Force broadcast replies for hosts with tag set."
 msgstr "Forcer les réponses par 'broadcast' pour les machines énumerées dans les options."
 
-#: option.c:362
+#: option.c:374
 msgid "Do NOT fork into the background, do NOT run in debug mode."
 msgstr "Ne passe pas en tâche de fond, ne pas s'exécuter en mode debug."
 
-#: option.c:363
+#: option.c:375
 msgid "Assume we are the only DHCP server on the local network."
 msgstr "On considère que l'on est le seul serveur DHCP sur le réseau local."
 
-#: option.c:364
+#: option.c:376
 #, c-format
 msgid "Specify where to store DHCP leases (defaults to %s)."
 msgstr "Spécifie où il faut sauvegarder les baux DHCP (par défaut : %s)."
 
-#: option.c:365
+#: option.c:377
 msgid "Return MX records for local hosts."
 msgstr "Retourne les champs MX pour les machines locales."
 
-#: option.c:366
+#: option.c:378
 msgid "Specify an MX record."
 msgstr "Spécifie un champ MX."
 
-#: option.c:367
+#: option.c:379
 msgid "Specify BOOTP options to DHCP server."
 msgstr "Spécifie les options BOOTP pour le serveur DHCP."
 
-#: option.c:368
+#: option.c:380
 #, c-format
 msgid "Do NOT poll %s file, reload only on SIGHUP."
 msgstr "Ne pas scruter le fichier %s, ne recharger les modifications que sur réception du signal SIGHUP."
 
-#: option.c:369
+#: option.c:381
 msgid "Do NOT cache failed search results."
 msgstr "Ne place pas en cache le résultat des requêtes qui ont échouées."
 
-#: option.c:370
+#: option.c:382
 #, c-format
 msgid "Use nameservers strictly in the order given in %s."
 msgstr "Utilise les serveurs de noms dans l'ordre donné dans %s."
 
 #
-#: option.c:371
+#: option.c:383
 msgid "Specify options to be sent to DHCP clients."
 msgstr "Options supplémentaires à associer aux clients DHCP."
 
-#: option.c:372
+#: option.c:384
 msgid "DHCP option sent even if the client does not request it."
 msgstr "Option DHCP envoyée même si le client de la demande pas."
 
-#: option.c:373
+#: option.c:385
 msgid "Specify port to listen for DNS requests on (defaults to 53)."
 msgstr "Spécifie le port où il faut écouter les requêtes DNS (par défaut : 53)."
 
-#: option.c:374
+#: option.c:386
 #, c-format
 msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
 msgstr "Taille maximale des paquets UDP supportés pour EDNS.0 (par défaut : %s)."
 
 #
-#: option.c:375
+#: option.c:387
 msgid "Log DNS queries."
 msgstr "Enregistre les requêtes DNS dans un journal d'activité."
 
 #
-#: option.c:376
+#: option.c:388
 msgid "Force the originating port for upstream DNS queries."
 msgstr "Force le port d'origine pour les requêtes vers les serveurs amonts."
 
-#: option.c:377
+#: option.c:389
 msgid "Do NOT read resolv.conf."
 msgstr "Ne pas lire le fichier resolv.conf."
 
-#: option.c:378
+#: option.c:390
 #, c-format
 msgid "Specify path to resolv.conf (defaults to %s)."
 msgstr "Spécifie le chemin pour le fichier resolv.conf (par défaut : %s)."
 
-#: option.c:379
+#: option.c:391
 #, fuzzy
 msgid "Specify path to file with server= options"
 msgstr "Spécifie un chemin pour le fichier PID (par défaut : %s)."
 
-#: option.c:380
+#: option.c:392
 msgid "Specify address(es) of upstream servers with optional domains."
 msgstr "Spécifie la ou les adresses des serveurs amonts avec des domaines optionels."
 
-#: option.c:381
+#: option.c:393
 #, fuzzy
 msgid "Specify address of upstream servers for reverse address queries"
 msgstr "Spécifie la ou les adresses des serveurs amonts avec des domaines optionels."
 
-#: option.c:382
+#: option.c:394
 msgid "Never forward queries to specified domains."
 msgstr "Ne jamais retransmettre les requêtes pour les domaines spécifiés."
 
-#: option.c:383
+#: option.c:395
 msgid "Specify the domain to be assigned in DHCP leases."
 msgstr "Spécifie le domaine qui doit etre assigné aux baux DHCP."
 
-#: option.c:384
+#: option.c:396
 msgid "Specify default target in an MX record."
 msgstr "Spécifie la cible par défaut dans un champ MX."
 
-#: option.c:385
+#: option.c:397
 msgid "Specify time-to-live in seconds for replies from /etc/hosts."
 msgstr "Spécifie le TTL en secondes pour les réponses qui utilisent /etc/hosts."
 
 #
-#: option.c:386
+#: option.c:398
 msgid "Specify time-to-live in seconds for negative caching."
 msgstr "Spécifie le TTL en secondes pour les réponses qui utilisent /etc/hosts."
 
-#: option.c:387
+#: option.c:399
 msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
 msgstr "Spécifie, en secondes, la valeur maximum de TTL à renvoyer aux clients."
 
 #
-#: option.c:388
+#: option.c:400
 #, fuzzy
 msgid "Specify time-to-live ceiling for cache."
 msgstr "Spécifie le TTL en secondes pour les réponses qui utilisent /etc/hosts."
 
 #
-#: option.c:389
+#: option.c:401
 #, fuzzy
 msgid "Specify time-to-live floor for cache."
 msgstr "Spécifie le TTL en secondes pour les réponses qui utilisent /etc/hosts."
 
-#: option.c:390
+#: option.c:402
 #, c-format
 msgid "Change to this user after startup. (defaults to %s)."
 msgstr "Change pour cet utilisateur après le démarrage (par défaut : %s)."
 
 #
-#: option.c:391
+#: option.c:403
 msgid "Map DHCP vendor class to tag."
 msgstr "Associe les classes de fournisseurs ('vendor class') DHCP aux options."
 
-#: option.c:392
+#: option.c:404
 msgid "Display dnsmasq version and copyright information."
 msgstr "Affiche la version de Dnsmasq et les informations liées au copyright."
 
-#: option.c:393
+#: option.c:405
 msgid "Translate IPv4 addresses from upstream servers."
 msgstr "Traduit les adresses IPV4 des serveurs amonts."
 
-#: option.c:394
+#: option.c:406
 msgid "Specify a SRV record."
 msgstr "Spécifie un champ SRV."
 
-#: option.c:395
-msgid "Display this message. Use --help dhcp for known DHCP options."
+#: option.c:407
+#, fuzzy
+msgid "Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."
 msgstr "Afficher ce message. Utiliser --help dhcp pour obtenir la liste des options DHCP connues."
 
-#: option.c:396
+#: option.c:408
 #, c-format
 msgid "Specify path of PID file (defaults to %s)."
 msgstr "Spécifie un chemin pour le fichier PID (par défaut : %s)."
 
-#: option.c:397
+#: option.c:409
 #, c-format
 msgid "Specify maximum number of DHCP leases (defaults to %s)."
 msgstr "Spécifie le nombre maximum de baux DHCP (par défaut : %s)."
 
-#: option.c:398
+#: option.c:410
 msgid "Answer DNS queries based on the interface a query was sent to."
 msgstr "Repond aux requêtes DNS en se basant sur l'interface ou a été envoyée la requête."
 
-#: option.c:399
+#: option.c:411
 msgid "Specify TXT DNS record."
 msgstr "Spécifie un champ DNS TXT"
 
 #
-#: option.c:400
+#: option.c:412
 msgid "Specify PTR DNS record."
 msgstr "Spécifie un champ DNS PTR"
 
-#: option.c:401
+#: option.c:413
 msgid "Give DNS name to IPv4 address of interface."
 msgstr "Donne le nom DNS pour l'adresse IPv4 de l'interface."
 
-#: option.c:402
+#: option.c:414
 msgid "Bind only to interfaces in use."
 msgstr "Association uniquement aux interfaces réseau actuellement actives."
 
-#: option.c:403
+#: option.c:415
 #, c-format
 msgid "Read DHCP static host information from %s."
 msgstr "Lecture des informations de DHCP statique à partir de %s."
 
-#: option.c:404
+#: option.c:416
 msgid "Enable the DBus interface for setting upstream servers, etc."
 msgstr "Autorise l'interface DBus pour la configuration des serveurs amonts, etc."
 
-#: option.c:405
+#: option.c:417
 msgid "Do not provide DHCP on this interface, only provide DNS."
 msgstr "Ne pas assurer de fonction DHCP sur cette interface, mais seulement la fonction DNS."
 
-#: option.c:406
+#: option.c:418
 msgid "Enable dynamic address allocation for bootp."
 msgstr "Autorise l'allocation dynamique d'adresse pour bootp."
 
 #
-#: option.c:407
+#: option.c:419
 msgid "Map MAC address (with wildcards) to option set."
 msgstr "Associe l'adresse MAC (avec les jokers) aux options."
 
-#: option.c:408
+#: option.c:420
 msgid "Treat DHCP requests on aliases as arriving from interface."
 msgstr "Traiter les requêtes DHCP sur les alias comme arrivant de l'interface."
 
-#: option.c:409
+#: option.c:421
 msgid "Disable ICMP echo address checking in the DHCP server."
 msgstr "Supprime la vérification d'adresse sur le serveur au moyen de paquets ICMP echo"
 
-#: option.c:410
+#: option.c:422
 msgid "Shell script to run on DHCP lease creation and destruction."
 msgstr "Script shell à exécuter lors de la création ou destruction de bail DHCP."
 
-#: option.c:411
+#: option.c:423
 msgid "Lua script to run on DHCP lease creation and destruction."
 msgstr "Script Lua à exécuter lors de la création ou destruction de bail DHCP."
 
-#: option.c:412
+#: option.c:424
 msgid "Run lease-change scripts as this user."
 msgstr "Lancer le script 'lease-change' avec cet utilisateur."
 
-#: option.c:413
+#: option.c:425
+msgid "Call dhcp-script with changes to local ARP table."
+msgstr ""
+
+#: option.c:426
 msgid "Read configuration from all the files in this directory."
 msgstr "Lecture de la configuration dans tous les fichiers de ce répertoire."
 
 #
-#: option.c:414
+#: option.c:427
 msgid "Log to this syslog facility or file. (defaults to DAEMON)"
 msgstr "Enregistrer les journaux d'activité dans cette facilité syslog. (défaut : DAEMON)"
 
-#: option.c:415
+#: option.c:428
 msgid "Do not use leasefile."
 msgstr "Ne pas utiliser de fichier de baux."
 
-#: option.c:416
+#: option.c:429
 #, c-format
 msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
 msgstr "Spécifie le nombre maximum de requêtes DHCP concurrentes (par défaut : %s)."
 
-#: option.c:417
+#: option.c:430
 #, c-format
 msgid "Clear DNS cache when reloading %s."
 msgstr "Vider le cache DNS lors du rechargement de %s."
 
-#: option.c:418
+#: option.c:431
 msgid "Ignore hostnames provided by DHCP clients."
 msgstr "Ignorer les noms d'hôtes fournis par les clients DHCP"
 
-#: option.c:419
+#: option.c:432
 msgid "Do NOT reuse filename and server fields for extra DHCP options."
 msgstr "Ne pas réutiliser les champs nom de fichier et serveur dans les options DHCP supplémentaires."
 
-#: option.c:420
+#: option.c:433
 msgid "Enable integrated read-only TFTP server."
 msgstr "Activer le server TFTP intégré (fonctionnant en lecture seulement)"
 
-#: option.c:421
+#: option.c:434
 msgid "Export files by TFTP only from the specified subtree."
 msgstr "N'exporter par TFTP que les fichiers de l'arborescence de fichier spécifiée"
 
-#: option.c:422
-msgid "Add client IP address to tftp-root."
+#: option.c:435
+#, fuzzy
+msgid "Add client IP or hardware address to tftp-root."
 msgstr "Ajouter les adresses IP clientes à la racine tftp ('tftp-root')."
 
-#: option.c:423
+#: option.c:436
 msgid "Allow access only to files owned by the user running dnsmasq."
 msgstr "Accès aux seuls fichiers appartenants à l'utilisateur sous lequel tourne dnsmasq"
 
-#: option.c:424
+#: option.c:437
 msgid "Do not terminate the service if TFTP directories are inaccessible."
 msgstr ""
 
-#: option.c:425
-#, c-format
-msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+#: option.c:438
+#, fuzzy, c-format
+msgid "Maximum number of concurrent TFTP transfers (defaults to %s)."
 msgstr "Spécifie le nombre maximum de transfert TFTP concurrents (défaut : %s)."
 
-#: option.c:426
+#: option.c:439
+#, fuzzy
+msgid "Maximum MTU to use for TFTP transfers."
+msgstr "Spécifie le nombre maximum de transfert TFTP concurrents (défaut : %s)."
+
+#: option.c:440
 msgid "Disable the TFTP blocksize extension."
 msgstr "Désactivation de l'extension TFTP « taille de bloc »"
 
-#: option.c:427
+#: option.c:441
 msgid "Convert TFTP filenames to lowercase"
 msgstr "Convertis les noms de fichiers TFTP en minuscule"
 
-#: option.c:428
+#: option.c:442
 msgid "Ephemeral port range for use by TFTP transfers."
 msgstr "Gamme de ports dans laquelle seront choisis les ports temporaires utilisés dans les transferts TFTP."
 
-#: option.c:429
+#: option.c:443
 msgid "Extra logging for DHCP."
 msgstr "Traces supplémentaires pour le DHCP."
 
-#: option.c:430
+#: option.c:444
 msgid "Enable async. logging; optionally set queue length."
 msgstr "Active l'écriture de traces en mode asynchrone. Peut prendre en option la valeur de la longueur de la queue."
 
-#: option.c:431
+#: option.c:445
 msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
 msgstr "Stopper la réassociation DNS ('DNS rebinding'). Filtre les gammes d'adresses IP privées lors de la résolution."
 
-#: option.c:432
+#: option.c:446
 msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
 msgstr "Autorise la réassociation de 127.0.0/8, pour les serveurs RBL (Realtime Blackhole List)"
 
-#: option.c:433
+#: option.c:447
 msgid "Inhibit DNS-rebind protection on this domain."
 msgstr "Désactive la protection contre les réassociation DNS pour ce domaine"
 
-#: option.c:434
+#: option.c:448
 msgid "Always perform DNS queries to all servers."
 msgstr "Toujours effectuer les requêtes DNS à tous les serveurs."
 
 #
-#: option.c:435
+#: option.c:449
 msgid "Set tag if client includes matching option in request."
 msgstr "Spécifie le label si le client inclus l'option dans la requête."
 
-#: option.c:436
+#: option.c:450
 msgid "Use alternative ports for DHCP."
 msgstr "Utiliser des ports alternatifs pour le DHCP."
 
 #
-#: option.c:437
+#: option.c:451
 msgid "Specify NAPTR DNS record."
 msgstr "Spécifie un champ DNS NAPTR."
 
-#: option.c:438
+#: option.c:452
 msgid "Specify lowest port available for DNS query transmission."
 msgstr "Définie le plus petit port utilisé pour la transmission d'une requête DNS."
 
-#: option.c:439
+#: option.c:453
+#, fuzzy
+msgid "Specify highest port available for DNS query transmission."
+msgstr "Définie le plus petit port utilisé pour la transmission d'une requête DNS."
+
+#: option.c:454
 msgid "Use only fully qualified domain names for DHCP clients."
 msgstr "Utilise seulement les noms de domaine pleinement qualifiés pour les clients DHCP."
 
-#: option.c:440
+#: option.c:455
 msgid "Generate hostnames based on MAC address for nameless clients."
 msgstr "Génère les noms d'hôtes à partir de l'adresse MAC pour les clients sans nom."
 
-#: option.c:441
+#: option.c:456
 msgid "Use these DHCP relays as full proxies."
 msgstr "Utilise ces relais DHCP en temps que proxy complets."
 
-#: option.c:442
+#: option.c:457
 msgid "Relay DHCP requests to a remote server"
 msgstr "Requêtes de relais DHCP à un serveur distant"
 
-#: option.c:443
+#: option.c:458
 msgid "Specify alias name for LOCAL DNS name."
 msgstr "Spécifie un alias pour un nom DNS local."
 
 #
-#: option.c:444
+#: option.c:459
 msgid "Prompt to send to PXE clients."
 msgstr "Invite à envoyer aux clients PXE."
 
-#: option.c:445
+#: option.c:460
 msgid "Boot service for PXE menu."
 msgstr "Service de démarrage pour menu PXE."
 
-#: option.c:446
+#: option.c:461
 msgid "Check configuration syntax."
 msgstr "vérification de la syntaxe de la configuration."
 
-#: option.c:447
+#: option.c:462
 msgid "Add requestor's MAC address to forwarded DNS queries."
 msgstr "Ajoute l'adresse MAC du requêteur aux requêtes DNS transmises"
 
-#: option.c:448
+#: option.c:463
 #, fuzzy
-msgid "Add requestor's IP subnet to forwarded DNS queries."
+msgid "Add specified IP subnet to forwarded DNS queries."
 msgstr "Ajoute l'adresse MAC du requêteur aux requêtes DNS transmises"
 
-#: option.c:449
+#: option.c:464
+#, fuzzy
+msgid "Add client identification to forwarded DNS queries."
+msgstr "Ajoute l'adresse MAC du requêteur aux requêtes DNS transmises"
+
+#: option.c:465
 msgid "Proxy DNSSEC validation results from upstream nameservers."
 msgstr "Copie dans la réponse DNS le résultat de la validation DNSSEC effectuée par les serveurs DNS amonts."
 
-#: option.c:450
+#: option.c:466
 msgid "Attempt to allocate sequential IP addresses to DHCP clients."
 msgstr "Essaie d'allouer des adresses IP séquentielles aux clients DHCP."
 
-#: option.c:451
+#: option.c:467
 msgid "Copy connection-track mark from queries to upstream connections."
 msgstr "Copie les marques de suivi de connexion pour les requêtes amont."
 
-#: option.c:452
+#: option.c:468
 msgid "Allow DHCP clients to do their own DDNS updates."
 msgstr "Autoriser les clients DHCP à faire leurs propres mises à jour DDNS (Dynamic DNS)"
 
-#: option.c:453
+#: option.c:469
 msgid "Send router-advertisements for interfaces doing DHCPv6"
 msgstr "Envoyer des annonces de routeurs pour toutes les interfaces faisant du DHCPv6"
 
-#: option.c:454
+#: option.c:470
 msgid "Specify DUID_EN-type DHCPv6 server DUID"
 msgstr "Spécifie pour le serveur DHCPv6 un identifiant unique DHCP (DUID) basé sur un numéro unique de vendeur (DUID_EN)"
 
-#: option.c:455
+#: option.c:471
 msgid "Specify host (A/AAAA and PTR) records"
 msgstr "Spécifie les enregistrements (A/AAAA et PTR) d'un hôte."
 
-#: option.c:456
+#: option.c:472
 msgid "Specify arbitrary DNS resource record"
 msgstr "Définie une resource DNS d'un type spécifique"
 
-#: option.c:457
+#: option.c:473
 msgid "Bind to interfaces in use - check for new interfaces"
 msgstr "Se lie aux interfaces préexistantes - vérifie l'apparition de nouvelles interfaces"
 
-#: option.c:458
+#: option.c:474
 msgid "Export local names to global DNS"
 msgstr "Exporte les noms locaux dans le DNS global"
 
-#: option.c:459
+#: option.c:475
 msgid "Domain to export to global DNS"
 msgstr "Domaine à exporter dans le DNS global"
 
-#: option.c:460
+#: option.c:476
 msgid "Set TTL for authoritative replies"
 msgstr "Configure la durée de vie (Time To Live) pour les réponses faisant autorité"
 
-#: option.c:461
-msgid "Set authoritive zone information"
+#: option.c:477
+#, fuzzy
+msgid "Set authoritative zone information"
 msgstr "Configure les informations pour une zone de nom faisant autorité"
 
-#: option.c:462
+#: option.c:478
 msgid "Secondary authoritative nameservers for forward domains"
 msgstr "Serveurs de noms secondaires faisant autorité pour les domaines délégués"
 
-#: option.c:463
+#: option.c:479
 msgid "Peers which are allowed to do zone transfer"
 msgstr "Pairs autorisés à faire des transferts de zone"
 
-#: option.c:464
+#: option.c:480
 msgid "Specify ipsets to which matching domains should be added"
 msgstr "Spécifie les ipsets auxquels les domaines correspondants doivent-être ajoutés"
 
-#: option.c:465
+#: option.c:481
 #, fuzzy
 msgid "Specify a domain and address range for synthesised names"
 msgstr "Spécifie un domaine et une plage d'adresses pour les noms auto-générés"
 
-#: option.c:466
+#: option.c:482
 msgid "Activate DNSSEC validation"
 msgstr ""
 
-#: option.c:467
+#: option.c:483
 msgid "Specify trust anchor key digest."
 msgstr ""
 
-#: option.c:468
+#: option.c:484
 msgid "Disable upstream checking for DNSSEC debugging."
 msgstr ""
 
-#: option.c:469
+#: option.c:485
 msgid "Ensure answers without DNSSEC are in unsigned zones."
 msgstr ""
 
-#: option.c:470
+#: option.c:486
 msgid "Don't check DNSSEC signature timestamps until first cache-reload"
 msgstr ""
 
-#: option.c:471
+#: option.c:487
 msgid "Timestamp file to verify system clock for DNSSEC"
 msgstr ""
 
-#: option.c:473
+#: option.c:489
 msgid "Specify DHCPv6 prefix class"
 msgstr "Spécifie le préfixe de classe DHCPv6"
 
-#: option.c:475
-msgid "Set priority, resend-interval and router-lifetime"
+#: option.c:491
+msgid "Set MTU, priority, resend-interval and router-lifetime"
 msgstr ""
 
-#: option.c:476
+#: option.c:492
 msgid "Do not log routine DHCP."
 msgstr ""
 
-#: option.c:477
+#: option.c:493
 msgid "Do not log routine DHCPv6."
 msgstr ""
 
-#: option.c:478
+#: option.c:494
 msgid "Do not log RA."
 msgstr ""
 
-#: option.c:479
-msgid "Accept queries only from directly-connected networks"
+#: option.c:495
+msgid "Accept queries only from directly-connected networks."
 msgstr ""
 
-#: option.c:480
-msgid "Detect and remove DNS forwarding loops"
+#: option.c:496
+msgid "Detect and remove DNS forwarding loops."
 msgstr ""
 
-#: option.c:481
+#: option.c:497
 msgid "Ignore DNS responses containing ipaddr."
 msgstr ""
 
-#: option.c:683
+#: option.c:498
+msgid "Set TTL in DNS responses with DHCP-derived addresses."
+msgstr ""
+
+#: option.c:499
+msgid "Delay DHCP replies for at least number of seconds."
+msgstr ""
+
+#: option.c:703
 #, c-format
 msgid ""
 "Usage: dnsmasq [options]\n"
@@ -753,328 +783,338 @@ msgstr ""
 "Usage : dnsmasq [options]\n"
 "\n"
 
-#: option.c:685
+#: option.c:705
 #, c-format
 msgid "Use short options only on the command line.\n"
 msgstr "Utilisez les options courtes uniquement sur la ligne de commande.\n"
 
-#: option.c:687
+#: option.c:707
 #, c-format
 msgid "Valid options are:\n"
 msgstr "Les options valides sont :\n"
 
-#: option.c:744 option.c:748
+#
+#: option.c:754 option.c:868
+msgid "bad address"
+msgstr "mauvaise adresse"
+
+#: option.c:779 option.c:783
 msgid "bad port"
 msgstr "numéro de port incorrect"
 
-#: option.c:775 option.c:807
+#: option.c:797 option.c:826 option.c:861
 msgid "interface binding not supported"
 msgstr "association d'interface non supportée"
 
+#: option.c:821 option.c:856
+msgid "interface can only be specified once"
+msgstr ""
+
 #
-#: option.c:784 option.c:3575
+#: option.c:835 option.c:3809
 msgid "bad interface name"
 msgstr "nom d'interface invalide"
 
-#
-#: option.c:814
-msgid "bad address"
-msgstr "mauvaise adresse"
-
-#: option.c:996
+#: option.c:1062
 msgid "unsupported encapsulation for IPv6 option"
 msgstr "encapsulation d'option non supportée pour IPv6"
 
-#: option.c:1010
+#: option.c:1076
 msgid "bad dhcp-option"
 msgstr "mauvaise valeur de 'dhcp-option'"
 
 #
-#: option.c:1078
+#: option.c:1144
 msgid "bad IP address"
 msgstr "mauvaise adresse IP"
 
 #
-#: option.c:1081 option.c:1219 option.c:2893
+#: option.c:1147 option.c:1286 option.c:3079
 msgid "bad IPv6 address"
 msgstr "mauvaise adresse IPv6"
 
-#: option.c:1246 option.c:1340
+#
+#: option.c:1240
+#, fuzzy
+msgid "bad IPv4 address"
+msgstr "mauvaise adresse IPv6"
+
+#: option.c:1313 option.c:1407
 msgid "bad domain in dhcp-option"
 msgstr "mauvais domaine dans dhcp-option"
 
-#: option.c:1378
+#: option.c:1445
 msgid "dhcp-option too long"
 msgstr "dhcp-option trop long"
 
-#: option.c:1385
+#: option.c:1452
 msgid "illegal dhcp-match"
 msgstr "valeur illégale pour 'dhcp-match'"
 
-#: option.c:1447
+#: option.c:1514
 msgid "illegal repeated flag"
 msgstr "Une option ne pouvant être spécifié qu'une seule fois à été donnée plusieurs fois"
 
-#: option.c:1455
+#: option.c:1522
 msgid "illegal repeated keyword"
 msgstr "Mot-clef ne pouvant être répété"
 
-#: option.c:1520 option.c:4191
+#: option.c:1593 option.c:4443
 #, c-format
 msgid "cannot access directory %s: %s"
 msgstr "Ne peut pas lire le répertoire %s : %s"
 
-#: option.c:1566 tftp.c:493
+#: option.c:1639 tftp.c:537
 #, c-format
 msgid "cannot access %s: %s"
 msgstr "Ne peut pas lire %s : %s"
 
-#: option.c:1618
+#: option.c:1727
 msgid "setting log facility is not possible under Android"
 msgstr "Sous android, impossible de positionner la cible (facility) pour les traces (logs)."
 
-#: option.c:1627
+#: option.c:1736
 msgid "bad log facility"
 msgstr "Mauvaise cible (facility) pour les traces."
 
-#: option.c:1680
+#: option.c:1789
 msgid "bad MX preference"
 msgstr "préference MX incorrecte"
 
-#: option.c:1685
+#: option.c:1794
 msgid "bad MX name"
 msgstr "nom MX incorrect"
 
-#: option.c:1699
+#: option.c:1808
 msgid "bad MX target"
 msgstr "valeur MX cible incorrecte"
 
-#: option.c:1711
+#: option.c:1820
 msgid "cannot run scripts under uClinux"
 msgstr "ne peut exécuter de script sous uClinux"
 
-#: option.c:1713
+#: option.c:1822
 msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
 msgstr "recompiler en définissant HAVE_SCRIPT pour permettre l'exécution de scripts shell au changement de bail (lease-change)"
 
-#: option.c:1717
+#: option.c:1826
 msgid "recompile with HAVE_LUASCRIPT defined to enable Lua scripts"
 msgstr "recompiler en définissant HAVE_LUASCRIPT pour permettre l'exécution de scripts LUA au changement de bail (lease-change)"
 
-#: option.c:1973 option.c:2018 option.c:2074
+#: option.c:2095 option.c:2106 option.c:2143 option.c:2199 option.c:2482
 msgid "bad prefix"
 msgstr "mauvais préfixe"
 
-#: option.c:2355
+#: option.c:2504
 msgid "recompile with HAVE_IPSET defined to enable ipset directives"
 msgstr "recompiler en définissant HAVE_IPSET pour permettre l'utilisation de directives de groupes d'IP (IPset)"
 
 #
-#: option.c:2548
+#: option.c:2713
 msgid "bad port range"
 msgstr "gamme de ports incorrecte"
 
-#: option.c:2564
+#: option.c:2739
 msgid "bad bridge-interface"
 msgstr "interface-pont incorrecte"
 
-#: option.c:2624
+#: option.c:2807
 msgid "only one tag allowed"
 msgstr "une seule étiquette est autorisée"
 
-#: option.c:2644 option.c:2656 option.c:2764 option.c:2805
+#: option.c:2827 option.c:2839 option.c:2948 option.c:2953 option.c:2992
 msgid "bad dhcp-range"
 msgstr "plage d'adresses DHCP (dhcp-range) incorrecte"
 
-#: option.c:2671
+#: option.c:2854
 msgid "inconsistent DHCP range"
 msgstr "plage d'adresses DHCP incohérente"
 
-#: option.c:2732
+#: option.c:2916
 msgid "prefix length must be exactly 64 for RA subnets"
 msgstr "la taille du préfixe doit être exactement 64 pour les sous-réseaux d'annonces de routeurs (RA)"
 
-#: option.c:2734
+#: option.c:2918
 msgid "prefix length must be exactly 64 for subnet constructors"
 msgstr "la taille du préfixe doit être exactement 64 pour le constructeur de sous-réseaux"
 
-#: option.c:2738
+#: option.c:2922
 msgid "prefix length must be at least 64"
 msgstr "la taille de préfixe doit être au minimum 64"
 
-#: option.c:2741
+#: option.c:2925
 msgid "inconsistent DHCPv6 range"
 msgstr "plage d'adresses DHCPv6 incohérente"
 
-#: option.c:2752
+#: option.c:2936
 msgid "prefix must be zero with \"constructor:\" argument"
 msgstr "le préfixe doit avoir une taille de 0 lorsque l'argument \"constructor:\" est utilisé"
 
-#: option.c:2863 option.c:2911
+#: option.c:3049 option.c:3097
 msgid "bad hex constant"
 msgstr "mauvaise constante hexadecimale"
 
-#: option.c:2885
+#: option.c:3071
 msgid "cannot match tags in --dhcp-host"
 msgstr "L'utilisation de labels est prohibée dans --dhcp-host"
 
-#: option.c:2933
+#: option.c:3119
 #, c-format
 msgid "duplicate dhcp-host IP address %s"
 msgstr "adresse IP dhcp-host dupliquée dans %s."
 
 #
-#: option.c:2991
+#: option.c:3177
 msgid "bad DHCP host name"
 msgstr "nom d'hôte DHCP incorrect"
 
-#: option.c:3073
+#: option.c:3259
 msgid "bad tag-if"
 msgstr "mauvaise étiquette tag-if"
 
-#: option.c:3397 option.c:3791
+#: option.c:3616 option.c:4039
 msgid "invalid port number"
 msgstr "numéro de port invalide"
 
 #
-#: option.c:3459
+#: option.c:3678
 msgid "bad dhcp-proxy address"
 msgstr "adresse dhcp-proxy incorrecte"
 
-#: option.c:3485
+#: option.c:3704
 msgid "Bad dhcp-relay"
 msgstr "valeur incorrecte pour le relais DHCP (dhcp-relay)"
 
-#: option.c:3511
+#: option.c:3745
 msgid "bad RA-params"
 msgstr ""
 
-#: option.c:3520
+#: option.c:3754
 msgid "bad DUID"
 msgstr "mauvais identifiant unique DHCP (DUID)"
 
 #
-#: option.c:3562
+#: option.c:3796
 msgid "invalid alias range"
 msgstr "poids invalide"
 
-#: option.c:3616
+#: option.c:3850 option.c:3862
 msgid "bad CNAME"
 msgstr "mauvais CNAME"
 
-#: option.c:3621
+#: option.c:3866
 msgid "duplicate CNAME"
 msgstr "ce CNAME existe déja"
 
 #
-#: option.c:3641
+#: option.c:3889
 msgid "bad PTR record"
 msgstr "mauvais champ PTR"
 
 #
-#: option.c:3672
+#: option.c:3920
 msgid "bad NAPTR record"
 msgstr "mauvais champ NAPTR"
 
 #
-#: option.c:3706
+#: option.c:3954
 msgid "bad RR record"
 msgstr "mauvais enregistrement RR"
 
-#: option.c:3736
+#: option.c:3984
 msgid "bad TXT record"
 msgstr "champ TXT invalide"
 
-#: option.c:3777
+#: option.c:4025
 msgid "bad SRV record"
 msgstr "champ SRV invalide"
 
-#: option.c:3784
+#: option.c:4032
 msgid "bad SRV target"
 msgstr "cible SRV invalide"
 
-#: option.c:3798
+#: option.c:4046
 msgid "invalid priority"
 msgstr "priorité invalide"
 
-#: option.c:3805
+#: option.c:4049
 msgid "invalid weight"
 msgstr "poids invalide"
 
 #
-#: option.c:3829
+#: option.c:4073
 msgid "Bad host-record"
 msgstr "mauvais champ host-record"
 
-#: option.c:3846
+#: option.c:4097
 msgid "Bad name in host-record"
 msgstr "mauvais nom dans le champ host-record"
 
 #
-#: option.c:3911
+#: option.c:4162
 #, fuzzy
 msgid "bad trust anchor"
 msgstr "gamme de ports incorrecte"
 
-#: option.c:3925
+#: option.c:4176
 msgid "bad HEX in trust anchor"
 msgstr ""
 
-#: option.c:3935
+#: option.c:4186
 #, fuzzy
 msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"
 msgstr "option non supportée (vérifier que Dnsmasq a été compilé avec le support DHCP/TFTP/DBus)"
 
-#: option.c:3994
+#: option.c:4246
 msgid "missing \""
 msgstr "il manque \""
 
-#: option.c:4051
+#: option.c:4303
 msgid "bad option"
 msgstr "mauvaise option"
 
-#: option.c:4053
+#: option.c:4305
 msgid "extraneous parameter"
 msgstr "paramètre en trop"
 
-#: option.c:4055
+#: option.c:4307
 msgid "missing parameter"
 msgstr "paramètre manquant"
 
-#: option.c:4057
+#: option.c:4309
 #, fuzzy
 msgid "illegal option"
 msgstr "mauvaise option"
 
-#: option.c:4064
+#: option.c:4316
 msgid "error"
 msgstr "erreur"
 
-#: option.c:4066
+#: option.c:4318
 #, c-format
 msgid " at line %d of %s"
 msgstr "à la ligne %d de %s"
 
-#: option.c:4081 option.c:4328 option.c:4364
+#: option.c:4333 option.c:4580 option.c:4616
 #, c-format
 msgid "read %s"
 msgstr "Lecture de %s"
 
-#: option.c:4144 option.c:4267 tftp.c:667
+#: option.c:4396 option.c:4519 tftp.c:715
 #, c-format
 msgid "cannot read %s: %s"
 msgstr "Ne peut pas lire %s : %s"
 
-#: option.c:4430
+#: option.c:4688
 msgid "junk found in command line"
 msgstr "la ligne de commande contient des éléments indésirables ou incompréhensibles"
 
-#: option.c:4465
+#: option.c:4729
 #, c-format
 msgid "Dnsmasq version %s  %s\n"
 msgstr "Version de Dnsmasq %s  %s\n"
 
-#: option.c:4466
+#: option.c:4730
 #, c-format
 msgid ""
 "Compile time options: %s\n"
@@ -1083,468 +1123,510 @@ msgstr ""
 "Options à la compilation %s\n"
 "\n"
 
-#: option.c:4467
+#: option.c:4731
 #, c-format
 msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
 msgstr "Ce logiciel est fourni sans AUCUNE GARANTIE.\n"
 
-#: option.c:4468
+#: option.c:4732
 #, c-format
 msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
 msgstr "Dnsmasq est un logiciel libre, il vous est permis de le redistribuer\n"
 
-#: option.c:4469
+#: option.c:4733
 #, c-format
 msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
 msgstr "sous les termes de la licence GPL (GNU General Public License), version 2 ou 3.\n"
 
-#: option.c:4480
+#: option.c:4744
 msgid "try --help"
 msgstr "essayez avec --help"
 
-#: option.c:4482
+#: option.c:4746
 msgid "try -w"
 msgstr "essayez avec -w"
 
-#: option.c:4484
+#: option.c:4748
 #, c-format
 msgid "bad command line options: %s"
 msgstr "mauvaises options en ligne de commande : %s."
 
-#: option.c:4541
+#: option.c:4818
+#, c-format
+msgid "CNAME loop involving %s"
+msgstr ""
+
+#: option.c:4854
 #, c-format
 msgid "cannot get host-name: %s"
 msgstr "ne peut pas obtenir le nom de la machine : %s"
 
-#: option.c:4569
+#: option.c:4882
 msgid "only one resolv.conf file allowed in no-poll mode."
 msgstr "seul un fichier resolv.conf est autorisé dans le mode no-poll"
 
-#: option.c:4579
+#: option.c:4892
 msgid "must have exactly one resolv.conf to read domain from."
 msgstr "un fichier resolv.conf (et un seul) est nécessaire pour y récuperer le nom de domaine."
 
-#: option.c:4582 network.c:1507 dhcp.c:777
+#: option.c:4895 network.c:1623 dhcp.c:816
 #, c-format
 msgid "failed to read %s: %s"
 msgstr "impossible de lire %s : %s"
 
-#: option.c:4599
+#: option.c:4912
 #, c-format
 msgid "no search directive found in %s"
 msgstr "pas de directive de recherche trouvée dans %s"
 
-#: option.c:4620
+#: option.c:4933
 msgid "there must be a default domain when --dhcp-fqdn is set"
 msgstr "un domaine par défaut doit être spécifié lorsque l'option --dhcp-fqdn est utilisée"
 
-#: option.c:4629
+#: option.c:4942
 msgid "syntax check OK"
 msgstr "vérification de syntaxe OK"
 
-#: forward.c:111
+#: forward.c:102
 #, c-format
 msgid "failed to send packet: %s"
 msgstr "impossible d'envoyer le paquet : %s"
 
-#: forward.c:591
+#: forward.c:598
 msgid "discarding DNS reply: subnet option mismatch"
 msgstr ""
 
-#: forward.c:614
+#: forward.c:652
 #, c-format
 msgid "nameserver %s refused to do a recursive query"
 msgstr "le serveur de nom %s a refusé de faire une recherche récursive"
 
-#: forward.c:646
+#: forward.c:684
 #, c-format
 msgid "possible DNS-rebind attack detected: %s"
 msgstr "détection d'une possible attaque de type DNS-rebind: %s"
 
-#: forward.c:1209 forward.c:1815
+#: forward.c:870
+#, c-format
+msgid "reducing DNS packet size for nameserver %s to %d"
+msgstr ""
+
+#: forward.c:1266 forward.c:1704
 msgid "Ignoring query from non-local network"
 msgstr ""
 
-#: forward.c:2286
+#: forward.c:2184
 #, c-format
 msgid "Maximum number of concurrent DNS queries reached (max: %d)"
 msgstr "Nombre maximum de requêtes DNS concurrentes atteint (maximum : %d)."
 
-#: network.c:715
+#: network.c:720
 #, c-format
 msgid "failed to create listening socket for %s: %s"
 msgstr "impossible de créer une socket d'écoute pour %s : %s"
 
-#: network.c:1021
+#: network.c:1031
 #, c-format
 msgid "LOUD WARNING: listening on %s may accept requests via interfaces other than %s"
 msgstr ""
 
-#: network.c:1028
+#: network.c:1038
 msgid "LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"
 msgstr ""
 
-#: network.c:1037
+#: network.c:1047
+#, fuzzy, c-format
+msgid "warning: using interface %s instead"
+msgstr "attention : l'interface %s n'existe pas actuellement"
+
+#: network.c:1056
 #, fuzzy, c-format
 msgid "warning: no addresses found for interface %s"
 msgstr "utilise les adresses locales seulement pour %s %s"
 
-#: network.c:1095
+#: network.c:1114
 #, c-format
 msgid "interface %s failed to join DHCPv6 multicast group: %s"
 msgstr "impossible de faire rejoindre l'interface %s dans le groupe multicast DHCPv6 %s"
 
-#: network.c:1289
+#: network.c:1119
+msgid "try increasing /proc/sys/net/core/optmem_max"
+msgstr ""
+
+#: network.c:1337
 #, c-format
 msgid "failed to bind server socket for %s: %s"
 msgstr "impossible de lier la socket de serveur pour %s : %s"
 
-#: network.c:1445
+#: network.c:1528
 #, c-format
 msgid "ignoring nameserver %s - local interface"
 msgstr "ignore le serveur de nom %s - interface locale"
 
-#: network.c:1456
+#: network.c:1539
 #, c-format
 msgid "ignoring nameserver %s - cannot make/bind socket: %s"
 msgstr "ignore le serveur de nom %s - ne peut construire/lier la socket : %m"
 
-#: network.c:1469
+#: network.c:1559
+msgid "(no DNSSEC)"
+msgstr ""
+
+#: network.c:1562
 msgid "unqualified"
 msgstr "non-qualifié(e)"
 
-#: network.c:1469
+#: network.c:1562
 msgid "names"
 msgstr "noms"
 
-#: network.c:1471
+#: network.c:1564
 msgid "default"
 msgstr "défaut"
 
-#: network.c:1473
+#: network.c:1566
 msgid "domain"
 msgstr "domaine"
 
-#: network.c:1476
+#: network.c:1572
 #, c-format
 msgid "using local addresses only for %s %s"
 msgstr "utilise les adresses locales seulement pour %s %s"
 
-#: network.c:1478
+#: network.c:1575
 #, c-format
 msgid "using standard nameservers for %s %s"
 msgstr "utilisation des serveurs de nom standards pour %s %s"
 
-#: network.c:1480
-#, c-format
-msgid "using nameserver %s#%d for %s %s"
+#: network.c:1577
+#, fuzzy, c-format
+msgid "using nameserver %s#%d for %s %s %s"
 msgstr "utilise le serveur de nom %s#%d pour %s %s"
 
-#: network.c:1484
+#: network.c:1581
 #, fuzzy, c-format
 msgid "NOT using nameserver %s#%d - query loop detected"
 msgstr "utilise le serveur de nom %s#%d pour %s %s"
 
-#: network.c:1487
+#: network.c:1584
 #, c-format
 msgid "using nameserver %s#%d(via %s)"
 msgstr "utilise le serveur de nom %s#%d (via %s)"
 
-#: network.c:1489
+#: network.c:1586
 #, c-format
 msgid "using nameserver %s#%d"
 msgstr "utilise le serveur de nom %s#%d"
 
-#: dnsmasq.c:163
+#: network.c:1591
+#, fuzzy, c-format
+msgid "using %d more local addresses"
+msgstr "utilise le serveur de nom %s#%d"
+
+#: network.c:1593
+#, fuzzy, c-format
+msgid "using %d more nameservers"
+msgstr "utilise le serveur de nom %s#%d"
+
+#: dnsmasq.c:171
 msgid "dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"
 msgstr ""
 
-#: dnsmasq.c:170
-msgid "no trust anchors provided for DNSSEC"
+#: dnsmasq.c:186
+msgid "no root trust anchor provided for DNSSEC"
 msgstr ""
 
-#: dnsmasq.c:173
+#: dnsmasq.c:189
 msgid "cannot reduce cache size from default when DNSSEC enabled"
 msgstr ""
 
-#: dnsmasq.c:175
+#: dnsmasq.c:191
 #, fuzzy
 msgid "DNSSEC not available: set HAVE_DNSSEC in src/config.h"
 msgstr "DBus n'est pas disponible : activez HAVE_DBUS dans src/config.h"
 
 #
-#: dnsmasq.c:181
+#: dnsmasq.c:197
 msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
 msgstr "TFTP n'est pas disponible : activez HAVE_TFTP dans src/config.h"
 
-#: dnsmasq.c:186
+#: dnsmasq.c:202
 #, fuzzy
 msgid "cannot use --conntrack AND --query-port"
 msgstr "impossible d'utiliser conjointement --conntrack et --query-port"
 
 #
-#: dnsmasq.c:189
+#: dnsmasq.c:205
 #, fuzzy
 msgid "conntrack support not available: set HAVE_CONNTRACK in src/config.h"
 msgstr "Support de suivi de connexion non disponible : activez HAVE_CONNTRACK dans src/config.h"
 
-#: dnsmasq.c:194
-msgid "asychronous logging is not available under Solaris"
+#: dnsmasq.c:210
+msgid "asynchronous logging is not available under Solaris"
 msgstr "l'écriture de traces en mode asynchrone n'est pas disponible sous Solaris."
 
-#: dnsmasq.c:199
-msgid "asychronous logging is not available under Android"
+#: dnsmasq.c:215
+msgid "asynchronous logging is not available under Android"
 msgstr "l'écriture de traces en mode asynchrone n'est pas disponible sous Android."
 
-#: dnsmasq.c:204
+#: dnsmasq.c:220
 msgid "authoritative DNS not available: set HAVE_AUTH in src/config.h"
 msgstr "le mode « autorité DNS » n'est pas disponible : activez HAVE_AUTH dans src/config.h"
 
 #
-#: dnsmasq.c:209
+#: dnsmasq.c:225
 #, fuzzy
 msgid "loop detection not available: set HAVE_LOOP in src/config.h"
 msgstr "TFTP n'est pas disponible : activez HAVE_TFTP dans src/config.h"
 
-#: dnsmasq.c:217
+#: dnsmasq.c:229
+msgid "max_port cannot be smaller than min_port"
+msgstr ""
+
+#: dnsmasq.c:236
 msgid "zone serial must be configured in --auth-soa"
 msgstr "le numéro de série de la zone doit être configuré dans --auth-soa"
 
-#: dnsmasq.c:235
+#: dnsmasq.c:254
 msgid "dhcp-range constructor not available on this platform"
 msgstr "le constructeur de plage dhcp n'est pas disponible sur cette plate-forme"
 
-#: dnsmasq.c:278
+#: dnsmasq.c:300
 msgid "cannot set --bind-interfaces and --bind-dynamic"
 msgstr "--bind-interfaces et --bind-dynamic sont mutuellement exclusives"
 
-#: dnsmasq.c:281
+#: dnsmasq.c:303
 #, c-format
 msgid "failed to find list of interfaces: %s"
 msgstr "impossible de trouver la liste des interfaces : %s"
 
-#: dnsmasq.c:290
+#: dnsmasq.c:312
 #, c-format
 msgid "unknown interface %s"
 msgstr "interface %s inconnue"
 
-#: dnsmasq.c:354 dnsmasq.c:997
+#: dnsmasq.c:377 dnsmasq.c:1054
 #, c-format
 msgid "DBus error: %s"
 msgstr "Erreur DBus : %s"
 
-#: dnsmasq.c:357
+#: dnsmasq.c:380
 msgid "DBus not available: set HAVE_DBUS in src/config.h"
 msgstr "DBus n'est pas disponible : activez HAVE_DBUS dans src/config.h"
 
-#: dnsmasq.c:385
+#: dnsmasq.c:410
 #, c-format
 msgid "unknown user or group: %s"
 msgstr "utilisateur ou groupe inconnu : %s"
 
-#: dnsmasq.c:440
+#: dnsmasq.c:465
 #, c-format
 msgid "cannot chdir to filesystem root: %s"
 msgstr "Ne peut effectuer un 'chdir' à la racine du système de fichier : %s"
 
-#: dnsmasq.c:692
+#: dnsmasq.c:730
 #, c-format
 msgid "started, version %s DNS disabled"
 msgstr "démarrage avec le DNS désactivé (version %s)"
 
-#: dnsmasq.c:694
+#: dnsmasq.c:734
 #, c-format
 msgid "started, version %s cachesize %d"
 msgstr "demarré, version %s (taille de cache %d)"
 
-#: dnsmasq.c:696
+#: dnsmasq.c:736
 #, c-format
 msgid "started, version %s cache disabled"
 msgstr "démarrage avec le cache désactivé (version %s)"
 
-#: dnsmasq.c:698
+#: dnsmasq.c:739
+msgid "DNS service limited to local subnets"
+msgstr ""
+
+#: dnsmasq.c:742
 #, c-format
 msgid "compile time options: %s"
 msgstr "options à la compilation : %s"
 
-#: dnsmasq.c:704
+#: dnsmasq.c:751
 msgid "DBus support enabled: connected to system bus"
 msgstr "Support DBus autorisé : connecté au bus système"
 
-#: dnsmasq.c:706
+#: dnsmasq.c:753
 msgid "DBus support enabled: bus connection pending"
 msgstr "Support DBus autorisé : connexion au bus en attente"
 
-#: dnsmasq.c:711
-msgid "DNS service limited to local subnets"
-msgstr ""
-
-#: dnsmasq.c:727
+#: dnsmasq.c:771
 msgid "DNSSEC validation enabled"
 msgstr ""
 
-#: dnsmasq.c:730
-msgid "DNSSEC signature timestamps not checked until first cache reload"
+#: dnsmasq.c:775
+msgid "DNSSEC signature timestamps not checked until receipt of SIGINT"
 msgstr ""
 
-#: dnsmasq.c:733
+#: dnsmasq.c:778
 msgid "DNSSEC signature timestamps not checked until system time valid"
 msgstr ""
 
-#: dnsmasq.c:738
+#: dnsmasq.c:783
 #, c-format
 msgid "warning: failed to change owner of %s: %s"
 msgstr "Impossible de changer pour l'utilisateur %s : %s"
 
-#: dnsmasq.c:742
+#: dnsmasq.c:787
 msgid "setting --bind-interfaces option because of OS limitations"
 msgstr "active l'option --bind-interfaces à cause de limitations dans le système d'exploitation"
 
-#: dnsmasq.c:752
+#: dnsmasq.c:799
 #, c-format
 msgid "warning: interface %s does not currently exist"
 msgstr "attention : l'interface %s n'existe pas actuellement"
 
-#: dnsmasq.c:757
+#: dnsmasq.c:804
 msgid "warning: ignoring resolv-file flag because no-resolv is set"
 msgstr "attention : l'option « resolv-file » sera ignorée car « no-resolv » a été spécifié"
 
 #
-#: dnsmasq.c:760
+#: dnsmasq.c:807
 msgid "warning: no upstream servers configured"
 msgstr "attention : aucun serveur amont n'est configuré"
 
-#: dnsmasq.c:764
+#: dnsmasq.c:811
 #, c-format
 msgid "asynchronous logging enabled, queue limit is %d messages"
 msgstr "mode asynchrone d'écriture de traces, la taille maximum de la queue est de %d messages."
 
-#: dnsmasq.c:785
+#: dnsmasq.c:832
 msgid "IPv6 router advertisement enabled"
 msgstr "annonces de routeur IPv6 activées"
 
-#: dnsmasq.c:790
+#: dnsmasq.c:837
 #, c-format
 msgid "DHCP, sockets bound exclusively to interface %s"
 msgstr ""
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "root is "
 msgstr "root est"
 
 #
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "enabled"
 msgstr "activé"
 
-#: dnsmasq.c:806
+#: dnsmasq.c:853
 msgid "secure mode"
 msgstr "mode sécurisé"
 
-#: dnsmasq.c:809
+#: dnsmasq.c:856
 #, c-format
 msgid "warning: %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:813
+#: dnsmasq.c:860
 #, fuzzy, c-format
 msgid "warning: TFTP directory %s inaccessible"
 msgstr "répertoire TFTP %s inaccessible : %s"
 
-#: dnsmasq.c:839
+#: dnsmasq.c:886
 #, c-format
 msgid "restricting maximum simultaneous TFTP transfers to %d"
 msgstr "le nombre maximum de transferts TFTP simultanés sera restreint à %d"
 
-#: dnsmasq.c:999
+#: dnsmasq.c:1056
 msgid "connected to system DBus"
 msgstr "connecté au systeme DBus"
 
-#: dnsmasq.c:1149
+#: dnsmasq.c:1215
 #, c-format
 msgid "cannot fork into background: %s"
 msgstr "Ne peut se lancer en tâche de fond : %s"
 
-#: dnsmasq.c:1152
+#: dnsmasq.c:1218
 #, c-format
 msgid "failed to create helper: %s"
 msgstr "impossible de créer le 'helper' : %s"
 
-#: dnsmasq.c:1155
+#: dnsmasq.c:1221
 #, c-format
 msgid "setting capabilities failed: %s"
 msgstr "impossible de configurer la capacité %s"
 
-#: dnsmasq.c:1158
+#: dnsmasq.c:1224
 #, c-format
 msgid "failed to change user-id to %s: %s"
 msgstr "Impossible de changer l'identifiant utilisateur pour %s : %s"
 
-#: dnsmasq.c:1161
+#: dnsmasq.c:1227
 #, c-format
 msgid "failed to change group-id to %s: %s"
 msgstr "Impossible de changer l'identifiant de groupe pour %s : %s"
 
-#: dnsmasq.c:1164
+#: dnsmasq.c:1230
 #, c-format
 msgid "failed to open pidfile %s: %s"
 msgstr "impossible de lire le fichier de PID %s : %s"
 
-#: dnsmasq.c:1167
+#: dnsmasq.c:1233
 #, c-format
 msgid "cannot open log %s: %s"
 msgstr "Ne peut ouvrir le fichier de log %s : %s"
 
 #
-#: dnsmasq.c:1170
+#: dnsmasq.c:1236
 #, c-format
 msgid "failed to load Lua script: %s"
 msgstr "impossible de charger le script Lua : %s"
 
-#: dnsmasq.c:1173
+#: dnsmasq.c:1239
 #, c-format
 msgid "TFTP directory %s inaccessible: %s"
 msgstr "répertoire TFTP %s inaccessible : %s"
 
-#: dnsmasq.c:1176
+#: dnsmasq.c:1242
 #, fuzzy, c-format
 msgid "cannot create timestamp file %s: %s"
 msgstr "ne peut ouvrir ou créer le fichiers de baux %s : %s"
 
-#: dnsmasq.c:1197
-msgid "now checking DNSSEC signature timestamps"
-msgstr ""
-
-#: dnsmasq.c:1264
+#: dnsmasq.c:1326
 #, c-format
 msgid "script process killed by signal %d"
 msgstr "Le script a été terminé par le signal %d"
 
-#: dnsmasq.c:1268
+#: dnsmasq.c:1330
 #, c-format
 msgid "script process exited with status %d"
 msgstr "Le script s'est terminé avec le statut %d"
 
-#: dnsmasq.c:1272
+#: dnsmasq.c:1334
 #, c-format
 msgid "failed to execute %s: %s"
 msgstr "impossible d'exécuter à %s : %s"
 
-#: dnsmasq.c:1327
+#: dnsmasq.c:1374
+msgid "now checking DNSSEC signature timestamps"
+msgstr ""
+
+#: dnsmasq.c:1409 dnssec.c:160 dnssec.c:206
+#, fuzzy, c-format
+msgid "failed to update mtime on %s: %s"
+msgstr "impossible de lire le fichier de PID %s : %s"
+
+#: dnsmasq.c:1416
 msgid "exiting on receipt of SIGTERM"
 msgstr "sortie sur réception du signal SIGTERM"
 
-#: dnsmasq.c:1355
+#: dnsmasq.c:1444
 #, c-format
 msgid "failed to access %s: %s"
 msgstr "impossible d'accéder à %s : %s"
 
-#: dnsmasq.c:1385
+#: dnsmasq.c:1474
 #, c-format
 msgid "reading %s"
 msgstr "Lecture de %s"
 
-#: dnsmasq.c:1396
+#: dnsmasq.c:1485
 #, c-format
 msgid "no servers found in %s, will retry"
 msgstr "aucun serveur trouvé dans %s, va réessayer"
@@ -1574,243 +1656,263 @@ msgstr "impossible de lier la socket serveur DHCP : %s"
 msgid "cannot create ICMP raw socket: %s."
 msgstr "ne peut créer de socket en mode raw pour ICMP : %s."
 
-#: dhcp.c:241 dhcp6.c:180
+#: dhcp.c:252 dhcp6.c:173
 #, c-format
 msgid "unknown interface %s in bridge-interface"
 msgstr "interface %s inconnue spécifiée comme interface de pont"
 
-#: dhcp.c:281
+#: dhcp.c:293
 #, c-format
 msgid "DHCP packet received on %s which has no address"
 msgstr "Paquet DHCP reçu sur %s qui n'a pas d'adresse"
 
-#: dhcp.c:415
+#: dhcp.c:427
 #, c-format
 msgid "ARP-cache injection failed: %s"
 msgstr ""
 
-#: dhcp.c:514
+#: dhcp.c:470
+#, c-format
+msgid "Error sending DHCP packet to %s: %s"
+msgstr ""
+
+#: dhcp.c:531
 #, c-format
 msgid "DHCP range %s -- %s is not consistent with netmask %s"
 msgstr "La plage d'adresses DHCP %s -- %s n'est pas cohérente avec le masque de réseau %s"
 
-#: dhcp.c:815
+#: dhcp.c:854
 #, c-format
 msgid "bad line at %s line %d"
 msgstr "mauvaise ligne dans %s ligne %d"
 
-#: dhcp.c:858
+#: dhcp.c:897
 #, c-format
 msgid "ignoring %s line %d, duplicate name or IP address"
 msgstr "ignore %s à la ligne %d : duplication de nom ou d'adresse IP"
 
-#: dhcp.c:1002 rfc3315.c:2135
+#: dhcp.c:1041 rfc3315.c:2149
 #, c-format
 msgid "DHCP relay %s -> %s"
 msgstr "Relais DHCP %s -> %s"
 
-#: lease.c:61
+#: lease.c:98
+msgid "too many stored leases"
+msgstr "beaucoup trop de baux enregistrés"
+
+#: lease.c:166
 #, c-format
 msgid "cannot open or create lease file %s: %s"
 msgstr "ne peut ouvrir ou créer le fichiers de baux %s : %s"
 
-#: lease.c:134
-msgid "too many stored leases"
-msgstr "beaucoup trop de baux enregistrés"
+#: lease.c:175
+#, c-format
+msgid "failed to parse lease database, invalid line: %s %s %s %s ..."
+msgstr ""
+
+#: lease.c:180
+#, fuzzy, c-format
+msgid "failed to read lease file %s: %s"
+msgstr "impossible de lire %s : %s"
 
-#: lease.c:165
+#: lease.c:196
 #, c-format
 msgid "cannot run lease-init script %s: %s"
 msgstr "Ne peut pas exécuter le script lease-init %s : %s"
 
-#: lease.c:171
+#: lease.c:202
 #, c-format
 msgid "lease-init script returned exit code %s"
 msgstr "le script lease-init a retourné le code %s"
 
-#: lease.c:342
+#: lease.c:373
 #, c-format
 msgid "failed to write %s: %s (retry in %us)"
 msgstr "impossible de lire %s : %s (prochain essai dans %us)"
 
-#: lease.c:906
+#: lease.c:937
 #, c-format
 msgid "Ignoring domain %s for DHCP host name %s"
 msgstr "Le domaine %s est ignoré pour l'hôte DHCP %s"
 
-#: rfc2131.c:344
+#: rfc2131.c:347
 #, c-format
 msgid "no address range available for DHCP request %s %s"
 msgstr "pas de plage d'adresse disponible pour la requête DHCP %s %s"
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "with subnet selector"
 msgstr "avec sélecteur de sous-reseau"
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "via"
 msgstr "par l'intermédiaire de"
 
-#: rfc2131.c:357
+#: rfc2131.c:360
 #, c-format
 msgid "%u available DHCP subnet: %s/%s"
 msgstr "%u sous-réseaux DHCP disponibles : %s/%s"
 
-#: rfc2131.c:360 rfc3315.c:300
+#: rfc2131.c:363 rfc3315.c:306
 #, c-format
 msgid "%u available DHCP range: %s -- %s"
 msgstr "%u la gamme DHCP disponible est : %s -- %s"
 
-#: rfc2131.c:471
+#: rfc2131.c:474
 #, c-format
 msgid "%u vendor class: %s"
 msgstr "%u Classe de vendeur ('Vendor Class') : %s"
 
-#: rfc2131.c:473
+#: rfc2131.c:476
 #, c-format
 msgid "%u user class: %s"
 msgstr "%u Classe d'utilisateur : %s"
 
-#: rfc2131.c:500
+#: rfc2131.c:510
 msgid "disabled"
 msgstr "désactivé"
 
-#: rfc2131.c:541 rfc2131.c:974 rfc2131.c:1380 rfc3315.c:603 rfc3315.c:856
-#: rfc3315.c:1135
+#: rfc2131.c:551 rfc2131.c:1006 rfc2131.c:1430 rfc3315.c:616 rfc3315.c:869
+#: rfc3315.c:1148
 msgid "ignored"
 msgstr "ignoré"
 
-#: rfc2131.c:556 rfc2131.c:1207 rfc3315.c:906
+#: rfc2131.c:566 rfc2131.c:1239 rfc3315.c:919
 msgid "address in use"
 msgstr "adresse déjà utilisée"
 
-#: rfc2131.c:570 rfc2131.c:1028
+#: rfc2131.c:580 rfc2131.c:1060
 msgid "no address available"
 msgstr "pas d'adresse disponible"
 
-#: rfc2131.c:577 rfc2131.c:1170
+#: rfc2131.c:587 rfc2131.c:1202
 msgid "wrong network"
 msgstr "mauvais réseau"
 
-#: rfc2131.c:592
+#: rfc2131.c:602
 msgid "no address configured"
 msgstr "pas d'adresse configurée"
 
-#: rfc2131.c:598 rfc2131.c:1220
+#: rfc2131.c:608 rfc2131.c:1252
 msgid "no leases left"
 msgstr "plus aucun bail disponible"
 
-#: rfc2131.c:693 rfc3315.c:476
+#: rfc2131.c:703 rfc3315.c:482
 #, c-format
 msgid "%u client provides name: %s"
 msgstr "le client %u fourni le nom : %s"
 
-#: rfc2131.c:798
+#: rfc2131.c:808
 msgid "PXE BIS not supported"
 msgstr "Service PXE BIS (Boot Integrity Services) non supporté"
 
-#: rfc2131.c:942 rfc3315.c:1229
+#: rfc2131.c:974 rfc3315.c:1242
 #, c-format
 msgid "disabling DHCP static address %s for %s"
 msgstr "désactive l'adresse statique DHCP %s pour %s"
 
-#: rfc2131.c:963
+#: rfc2131.c:995
 msgid "unknown lease"
 msgstr "bail inconnu"
 
-#: rfc2131.c:997
+#: rfc2131.c:1029
 #, c-format
 msgid "not using configured address %s because it is leased to %s"
 msgstr "L'adresse statique %s ne sera pas utilisée car un bail est déjà attribué à %s"
 
-#: rfc2131.c:1007
+#: rfc2131.c:1039
 #, c-format
 msgid "not using configured address %s because it is in use by the server or relay"
 msgstr "L'adresse statique %s ne sera pas utilisée car elle est utilisée par le serveur ou un relai"
 
-#: rfc2131.c:1010
+#: rfc2131.c:1042
 #, c-format
 msgid "not using configured address %s because it was previously declined"
 msgstr "L'adresse statique %s ne sera pas utilisée car elle a préalablement été refusée"
 
-#: rfc2131.c:1026 rfc2131.c:1213
+#: rfc2131.c:1058 rfc2131.c:1245
 msgid "no unique-id"
 msgstr "pas d'identifiant unique"
 
-#: rfc2131.c:1108
+#: rfc2131.c:1140
 msgid "wrong server-ID"
 msgstr "mauvais identifiant de serveur"
 
-#: rfc2131.c:1127
+#: rfc2131.c:1159
 msgid "wrong address"
 msgstr "mauvaise adresse"
 
-#: rfc2131.c:1145 rfc3315.c:1002
+#: rfc2131.c:1177 rfc3315.c:1015
 msgid "lease not found"
 msgstr "bail non trouvé"
 
-#: rfc2131.c:1178
+#: rfc2131.c:1210
 msgid "address not available"
 msgstr "adresse non disponible"
 
-#: rfc2131.c:1189
+#: rfc2131.c:1221
 msgid "static lease available"
 msgstr "bail statique disponible"
 
-#: rfc2131.c:1193
+#: rfc2131.c:1225
 msgid "address reserved"
 msgstr "adresse reservée"
 
-#: rfc2131.c:1201
+#: rfc2131.c:1233
 #, c-format
 msgid "abandoning lease to %s of %s"
 msgstr "abandon du bail de %s pour %s"
 
-#: rfc2131.c:1707
+#: rfc2131.c:1757
 #, c-format
 msgid "%u bootfile name: %s"
 msgstr "%u nom de fichier 'bootfile' : %s"
 
-#: rfc2131.c:1716
+#: rfc2131.c:1766
 #, c-format
 msgid "%u server name: %s"
 msgstr "%u nom du serveur : %s"
 
-#: rfc2131.c:1724
+#: rfc2131.c:1774
 #, c-format
 msgid "%u next server: %s"
 msgstr "%u serveur suivant : %s"
 
-#: rfc2131.c:1727
+#: rfc2131.c:1777
 #, c-format
 msgid "%u broadcast response"
 msgstr "%u réponse broadcast"
 
-#: rfc2131.c:1790
+#: rfc2131.c:1840
 #, c-format
 msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
 msgstr "Impossible d'envoyer l'option DHCP/BOOTP %d : pas assez d'espace dans le paquet"
 
-#: rfc2131.c:2031
+#: rfc2131.c:2131
 msgid "PXE menu too large"
 msgstr "menu PXE trop grand"
 
-#: rfc2131.c:2170 rfc3315.c:1502
+#: rfc2131.c:2270 rfc3315.c:1515
 #, c-format
 msgid "%u requested options: %s"
 msgstr "%u options demandées : %s"
 
-#: rfc2131.c:2487
+#: rfc2131.c:2587
 #, c-format
 msgid "cannot send RFC3925 option: too many options for enterprise number %d"
 msgstr "ne peux envoyer l'option RFC3925 : trop d'options pour le numéro d'entreprise %d"
 
+#: rfc2131.c:2650
+#, c-format
+msgid "%u reply delay: %d"
+msgstr ""
+
 #: netlink.c:77
 #, c-format
 msgid "cannot create netlink socket: %s"
 msgstr "ne peux lier une socket netlink : %s"
 
-#: netlink.c:348
+#: netlink.c:355
 #, c-format
 msgid "netlink returns error: %s"
 msgstr "Erreur netlink : %s"
@@ -1829,62 +1931,62 @@ msgstr ""
 msgid "Disabling --%s option from D-Bus"
 msgstr ""
 
-#: dbus.c:691
+#: dbus.c:690
 msgid "setting upstream servers from DBus"
 msgstr "configuration des serveurs amonts à partir de DBus"
 
-#: dbus.c:738
+#: dbus.c:737
 msgid "could not register a DBus message handler"
 msgstr "ne peut enregistrer une routine de traitement des messages DBus"
 
-#: bpf.c:263
+#: bpf.c:265
 #, c-format
 msgid "cannot create DHCP BPF socket: %s"
 msgstr "impossible de créer une socket BPF pour DHCP : %s"
 
-#: bpf.c:291
+#: bpf.c:293
 #, c-format
 msgid "DHCP request for unsupported hardware type (%d) received on %s"
 msgstr "requête DHCP pour un type de matériel non supporté (%d) reçue sur %s"
 
-#: bpf.c:376
+#: bpf.c:378
 #, fuzzy, c-format
 msgid "cannot create PF_ROUTE socket: %s"
 msgstr "ne peut créer la socket DHCP: %s"
 
-#: bpf.c:397
+#: bpf.c:399
 msgid "Unknown protocol version from route socket"
 msgstr ""
 
-#: helper.c:153
+#: helper.c:154
 msgid "lease() function missing in Lua script"
 msgstr "la fonction lease() est absente du script Lua"
 
-#: tftp.c:309
+#: tftp.c:319
 msgid "unable to get free port for TFTP"
 msgstr "impossible d'obtenir un port libre pour TFTP"
 
-#: tftp.c:325
+#: tftp.c:335
 #, c-format
 msgid "unsupported request from %s"
 msgstr "requête de %s non supportée"
 
-#: tftp.c:439
+#: tftp.c:483
 #, c-format
 msgid "file %s not found"
 msgstr "fichier %s non trouvé"
 
-#: tftp.c:548
+#: tftp.c:592
 #, c-format
 msgid "error %d %s received from %s"
 msgstr "erreur %d %s reçu de %s"
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "failed sending %s to %s"
 msgstr "impossible d'envoyer %s à %s"
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "sent %s to %s"
 msgstr "envoyé %s à %s"
@@ -1899,7 +2001,7 @@ msgstr "d
 msgid "log failed: %s"
 msgstr "trace perdue : %s"
 
-#: log.c:469
+#: log.c:471
 msgid "FAILED to start up"
 msgstr "IMPOSSIBLE de démarrer"
 
@@ -1908,17 +2010,17 @@ msgstr "IMPOSSIBLE de d
 msgid "Conntrack connection mark retrieval failed: %s"
 msgstr "La récupération de la marque de suivi de connexion a échoué : %s"
 
-#: dhcp6.c:59
+#: dhcp6.c:52
 #, c-format
 msgid "cannot create DHCPv6 socket: %s"
 msgstr "ne peut créer la socket DHCPv6: %s"
 
-#: dhcp6.c:80
+#: dhcp6.c:73
 #, c-format
 msgid "failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"
 msgstr "impossible de déclarer SO_REUSE{ADDR|PORT} sur la socket DHCPv6 : %s"
 
-#: dhcp6.c:92
+#: dhcp6.c:85
 #, c-format
 msgid "failed to bind DHCPv6 server socket: %s"
 msgstr "impossible de lier la socket serveur DHCPv6 : %s"
@@ -1933,67 +2035,67 @@ msgstr "pas de plage d'adresse disponible pour la requ
 msgid "no address range available for DHCPv6 request via %s"
 msgstr "pas de plage d'adresse disponible pour la requête DHCPv6 via %s"
 
-#: rfc3315.c:297
+#: rfc3315.c:303
 #, c-format
 msgid "%u available DHCPv6 subnet: %s/%d"
 msgstr "%u sous-réseaux DHCPv6 disponibles : %s/%d"
 
-#: rfc3315.c:380
+#: rfc3315.c:386
 #, c-format
 msgid "%u vendor class: %u"
 msgstr "%u Classe de vendeur ('Vendor Class') : %u"
 
-#: rfc3315.c:428
+#: rfc3315.c:434
 #, c-format
 msgid "%u client MAC address: %s"
 msgstr "%u MAC adresse du client : %s"
 
-#: rfc3315.c:660
+#: rfc3315.c:673
 #, c-format
 msgid "unknown prefix-class %d"
 msgstr "préfixe de classe inconnu %d"
 
-#: rfc3315.c:803 rfc3315.c:898
+#: rfc3315.c:816 rfc3315.c:911
 msgid "address unavailable"
 msgstr "adresse non disponible"
 
-#: rfc3315.c:815 rfc3315.c:946 rfc3315.c:1279
+#: rfc3315.c:828 rfc3315.c:959 rfc3315.c:1292
 msgid "success"
 msgstr "réussi"
 
-#: rfc3315.c:830 rfc3315.c:839 rfc3315.c:954 rfc3315.c:956
+#: rfc3315.c:843 rfc3315.c:852 rfc3315.c:967 rfc3315.c:969
 msgid "no addresses available"
 msgstr "pas d'adresse disponible"
 
-#: rfc3315.c:933
+#: rfc3315.c:946
 msgid "not on link"
 msgstr "pas sur ce lien"
 
-#: rfc3315.c:1006 rfc3315.c:1191 rfc3315.c:1268
+#: rfc3315.c:1019 rfc3315.c:1204 rfc3315.c:1281
 msgid "no binding found"
 msgstr "aucune liaison trouvée"
 
-#: rfc3315.c:1044
+#: rfc3315.c:1057
 msgid "deprecated"
 msgstr "obsolète"
 
-#: rfc3315.c:1049
+#: rfc3315.c:1062
 msgid "address invalid"
 msgstr "adresse non valide"
 
-#: rfc3315.c:1096
+#: rfc3315.c:1109
 msgid "confirm failed"
 msgstr "confirmation d'échec"
 
-#: rfc3315.c:1112
+#: rfc3315.c:1125
 msgid "all addresses still on link"
 msgstr "toutes les adresses sont toujours sur le lien"
 
-#: rfc3315.c:1200
+#: rfc3315.c:1213
 msgid "release received"
 msgstr "libération reçue"
 
-#: rfc3315.c:2126
+#: rfc3315.c:2140
 msgid "Cannot multicast to DHCPv6 server without correct interface"
 msgstr "Impossible de faire du multicast au server DHCPv6 sans interface valide"
 
@@ -2017,76 +2119,76 @@ msgstr "%s a plus d'une adresse dans le fichier d'h
 msgid "duplicate IP address %s (%s) in dhcp-config directive"
 msgstr "adresse IP %s (%s) dupliquée dans la directive dhcp-config."
 
-#: dhcp-common.c:494
+#: dhcp-common.c:491
 #, c-format
 msgid "failed to set SO_BINDTODEVICE on DHCP socket: %s"
 msgstr "impossible de déclarer SO_BINDTODEVICE sur la socket DHCP : %s"
 
-#: dhcp-common.c:615
+#: dhcp-common.c:612
 #, c-format
 msgid "Known DHCP options:\n"
 msgstr "Options DHCP connues :\n"
 
-#: dhcp-common.c:626
+#: dhcp-common.c:623
 #, c-format
 msgid "Known DHCPv6 options:\n"
 msgstr "Options DHCPv6 connues :\n"
 
-#: dhcp-common.c:823
+#: dhcp-common.c:820
 msgid ", prefix deprecated"
 msgstr ", préfixe obsolète"
 
-#: dhcp-common.c:826
+#: dhcp-common.c:823
 #, c-format
 msgid ", lease time "
 msgstr ", durée de bail "
 
-#: dhcp-common.c:868
+#: dhcp-common.c:865
 #, c-format
 msgid "%s stateless on %s%.0s%.0s%s"
 msgstr "%s sans état (stateless) sur %s%.0s%.0s%s"
 
-#: dhcp-common.c:870
+#: dhcp-common.c:867
 #, c-format
 msgid "%s, static leases only on %.0s%s%s%.0s"
 msgstr "%s, baux statiques seulement sur %.0s%s%s%.0s"
 
-#: dhcp-common.c:872
+#: dhcp-common.c:869
 #, c-format
 msgid "%s, proxy on subnet %.0s%s%.0s%.0s"
 msgstr "%s, proxy sur le sous-réseau %.0s%s%.0s"
 
-#: dhcp-common.c:873
+#: dhcp-common.c:870
 #, c-format
 msgid "%s, IP range %s -- %s%s%.0s"
 msgstr "%s, plage d'adresses IP %s -- %s%s%.0s"
 
-#: dhcp-common.c:886
+#: dhcp-common.c:883
 #, c-format
 msgid "DHCPv4-derived IPv6 names on %s%s"
 msgstr "noms IPv6 dérivés de DHCPv4 sur %s%s"
 
-#: dhcp-common.c:889
+#: dhcp-common.c:886
 #, c-format
 msgid "router advertisement on %s%s"
 msgstr "annonces de routeurs sur %s%s"
 
-#: dhcp-common.c:900
+#: dhcp-common.c:897
 #, c-format
 msgid "DHCP relay from %s to %s via %s"
 msgstr "Relais DHCP de %s à %s via %s"
 
-#: dhcp-common.c:902
+#: dhcp-common.c:899
 #, c-format
 msgid "DHCP relay from %s to %s"
 msgstr "Relais DHCP de %s à %s"
 
-#: radv.c:109
+#: radv.c:110
 #, c-format
 msgid "cannot create ICMPv6 socket: %s"
 msgstr "ne peut créer la socket ICMPv6: %s"
 
-#: auth.c:448
+#: auth.c:449
 #, c-format
 msgid "ignoring zone transfer request from %s"
 msgstr "la requête de transfert de zone en provenance de %s est ignorée"
@@ -2101,91 +2203,91 @@ msgstr "impossible de trouver la version de noyau : %s"
 msgid "failed to create IPset control socket: %s"
 msgstr "impossible de créer une socket de contrôle IPset : %s"
 
-#: dnssec.c:449 dnssec.c:493
+#: ipset.c:233
 #, fuzzy, c-format
-msgid "failed to update mtime on %s: %s"
+msgid "failed to update ipset %s: %s"
 msgstr "impossible de lire le fichier de PID %s : %s"
 
+#: dnssec.c:208
+msgid "system time considered valid, now checking DNSSEC signature timestamps."
+msgstr ""
+
 #: blockdata.c:58
 #, c-format
 msgid "DNSSEC memory in use %u, max %u, allocated %u"
 msgstr ""
 
-#: tables.c:80
-msgid "error: fill_addr missused"
-msgstr ""
-
-#: tables.c:109
+#: tables.c:61
 #, fuzzy, c-format
 msgid "failed to access pf devices: %s"
 msgstr "impossible d'accéder à %s : %s"
 
-#: tables.c:123
+#: tables.c:74
 #, fuzzy, c-format
 msgid "warning: no opened pf devices %s"
 msgstr "utilise les adresses locales seulement pour %s %s"
 
-#: tables.c:131
+#: tables.c:82
 #, fuzzy, c-format
 msgid "error: cannot use table name %s"
 msgstr "ne peut pas obtenir le nom de la machine : %s"
 
-#: tables.c:139
+#: tables.c:90
 #, c-format
 msgid "error: cannot strlcpy table name %s"
 msgstr ""
 
-#: tables.c:145
-#, c-format
-msgid "warning: pfr_add_tables: %s(%d)"
-msgstr ""
+#: tables.c:101
+#, fuzzy, c-format
+msgid "IPset: error:%s"
+msgstr "Erreur DBus : %s"
 
-#: tables.c:151
+#: tables.c:108
 msgid "info: table created"
 msgstr ""
 
-#: tables.c:162
+#: tables.c:134
 #, c-format
 msgid "warning: DIOCR%sADDRS: %s"
 msgstr ""
 
 #
-#: tables.c:166
+#: tables.c:138
 #, fuzzy, c-format
 msgid "%d addresses %s"
 msgstr "mauvaise adresse"
 
-#: inotify.c:59
+#: inotify.c:62
 #, fuzzy, c-format
 msgid "cannot access path %s: %s"
 msgstr "Ne peut pas lire %s : %s"
 
-#: inotify.c:92
+#: inotify.c:95
 #, fuzzy, c-format
 msgid "failed to create inotify: %s"
 msgstr "impossible de créer le 'helper' : %s"
 
-#: inotify.c:105
+#: inotify.c:111
 #, c-format
 msgid "too many symlinks following %s"
 msgstr ""
 
-#: inotify.c:121
+#: inotify.c:127
 #, c-format
 msgid "directory %s for resolv-file is missing, cannot poll"
 msgstr ""
 
-#: inotify.c:125 inotify.c:162
+#: inotify.c:131 inotify.c:168
 #, fuzzy, c-format
 msgid "failed to create inotify for %s: %s"
 msgstr "impossible de créer une socket d'écoute pour %s : %s"
 
-#: inotify.c:147
+#: inotify.c:153
 #, fuzzy, c-format
 msgid "bad dynamic directory %s: %s"
 msgstr "Ne peut pas lire le répertoire %s : %s"
 
-#: inotify.c:247
+#: inotify.c:257
 #, c-format
 msgid "inotify, new or changed file %s"
 msgstr ""
index 5545aee..3634add 100644 (file)
--- a/po/id.po
+++ b/po/id.po
@@ -7,7 +7,7 @@ msgstr ""
 "Project-Id-Version: dnsmasq 2.24\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2009-06-18 12:24+0100\n"
-"PO-Revision-Date: 2005-10-07 11:45+0100\n"
+"PO-Revision-Date: 2017-07-17 18:30+0100\n"
 "Last-Translator: Salman AS <sas@salman.or.id>\n"
 "Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n"
 "Language: id\n"
@@ -15,829 +15,857 @@ msgstr ""
 "Content-Type: text/plain; charset=ASCII\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: cache.c:523
+#: cache.c:518
 msgid "Internal error in cache."
 msgstr ""
 
 # OK
-#: cache.c:941
+#: cache.c:928
 #, fuzzy, c-format
 msgid "failed to load names from %s: %s"
 msgstr "gagal memuat nama-nama dari %s: %s"
 
 # OK
-#: cache.c:967 dhcp.c:828
+#: cache.c:954 dhcp.c:867
 #, fuzzy, c-format
 msgid "bad address at %s line %d"
 msgstr "kesalahan nama pada %s baris %d"
 
 # OK
-#: cache.c:1018 dhcp.c:844
+#: cache.c:1007 dhcp.c:883
 #, c-format
 msgid "bad name at %s line %d"
 msgstr "kesalahan nama pada %s baris %d"
 
 # OK
-#: cache.c:1027 dhcp.c:919
+#: cache.c:1016 dhcp.c:958
 #, c-format
 msgid "read %s - %d addresses"
 msgstr "membaca %s - %d alamat"
 
 # OK
-#: cache.c:1135
+#: cache.c:1129
 msgid "cleared cache"
 msgstr "cache telah dihapus"
 
-#: cache.c:1164
+#: cache.c:1158
 #, c-format
 msgid "No IPv4 address found for %s"
 msgstr ""
 
-#: cache.c:1242
+#: cache.c:1237
 #, c-format
 msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
 msgstr ""
 
 # OK
-#: cache.c:1266
+#: cache.c:1261
 #, c-format
 msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
 msgstr "tidak memberikan nama %s kepada lease DHCP %s karena nama telah ada dalam %sdengan alamat %s"
 
-#: cache.c:1421
+#: cache.c:1418
 #, c-format
 msgid "time %lu"
 msgstr ""
 
 # OK
-#: cache.c:1422
+#: cache.c:1419
 #, fuzzy, c-format
 msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
 msgstr "ukuran cache %d, %d/%d penyisipan cache menimpa cache yang belum kadaluwarsa"
 
-#: cache.c:1424
+#: cache.c:1421
 #, c-format
 msgid "queries forwarded %u, queries answered locally %u"
 msgstr ""
 
-#: cache.c:1427
+#: cache.c:1424
 #, c-format
 msgid "queries for authoritative zones %u"
 msgstr ""
 
-#: cache.c:1453
+#: cache.c:1450
 #, c-format
 msgid "server %s#%d: queries sent %u, retried or failed %u"
 msgstr ""
 
 # OK
-#: util.c:45
+#: util.c:47
 #, fuzzy, c-format
 msgid "failed to seed the random number generator: %s"
 msgstr "gagal mendengarkan di socket: %s"
 
 # OK
-#: util.c:205
+#: util.c:224
 #, fuzzy
 msgid "failed to allocate memory"
 msgstr "gagal memuat %S: %m"
 
 # OK
-#: util.c:250 option.c:601
+#: util.c:281 option.c:619
 msgid "could not get memory"
 msgstr "tidak bisa mendapatkan memory"
 
 # OK
-#: util.c:260
+#: util.c:291
 #, fuzzy, c-format
 msgid "cannot create pipe: %s"
 msgstr "tidak bisa membaca %s: %s"
 
 # OK
-#: util.c:268
+#: util.c:299
 #, fuzzy, c-format
 msgid "failed to allocate %d bytes"
 msgstr "gagal memuat %S: %m"
 
 # OK
-#: util.c:437
+#: util.c:468
 #, c-format
 msgid "infinite"
 msgstr "tak terbatas"
 
 # OK
-#: option.c:332
+#: option.c:344
 msgid "Specify local address(es) to listen on."
 msgstr "Tentukan alamat lokal untuk mendengarkan."
 
 # OK
-#: option.c:333
+#: option.c:345
 msgid "Return ipaddr for all hosts in specified domains."
 msgstr "Menghasilkan ipaddr untuk semua host dalam domain yang dipilih."
 
 # OK
-#: option.c:334
+#: option.c:346
 msgid "Fake reverse lookups for RFC1918 private address ranges."
 msgstr "Fake pencarian balik untuk alamat private sesuai dengan RFC1918."
 
 # OK
-#: option.c:335
+#: option.c:347
 msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
 msgstr "Perlakukan ipaddr sebagai NXDOMAIN (mengalahkan wildcard Verisign)."
 
 # OK
-#: option.c:336
+#: option.c:348
 #, c-format
 msgid "Specify the size of the cache in entries (defaults to %s)."
 msgstr "Tentukan ukuran cache, dalam jumlah isian (default %s)."
 
 # OK
-#: option.c:337
+#: option.c:349
 #, c-format
 msgid "Specify configuration file (defaults to %s)."
 msgstr "Tentukan file konfigurasi (default %s)."
 
 # OK
-#: option.c:338
+#: option.c:350
 msgid "Do NOT fork into the background: run in debug mode."
 msgstr "JANGAN berjalan di background: berjalan dalam modus debug."
 
 # OK
-#: option.c:339
+#: option.c:351
 msgid "Do NOT forward queries with no domain part."
 msgstr "JANGAN teruskan permintaan tanpa bagian domain."
 
 # OK
-#: option.c:340
+#: option.c:352
 msgid "Return self-pointing MX records for local hosts."
 msgstr "Mengembalikan record MX untuk diri sendiri host-host lokal."
 
 # OK
-#: option.c:341
+#: option.c:353
 msgid "Expand simple names in /etc/hosts with domain-suffix."
 msgstr "Melengkapi nama-nama di /etc/hosts dengan akhiran domain."
 
 # OK
-#: option.c:342
+#: option.c:354
 msgid "Don't forward spurious DNS requests from Windows hosts."
 msgstr "Jangan meneruskan permintaan DNS spurious dari host-host Windows."
 
 # OK
-#: option.c:343
+#: option.c:355
 msgid "Enable DHCP in the range given with lease duration."
 msgstr "Bolehkan DHCP dalam jangkauan yang diberikan dengan durasi lease."
 
 # OK
-#: option.c:344
+#: option.c:356
 #, c-format
 msgid "Change to this group after startup (defaults to %s)."
 msgstr "Ubah ke group ini setelah mulai (default %s)."
 
 # OK
-#: option.c:345
+#: option.c:357
 msgid "Set address or hostname for a specified machine."
 msgstr "Setel alamat atau nama host untuk mesin yang disebutkan."
 
 # OK
-#: option.c:346
+#: option.c:358
 #, fuzzy
 msgid "Read DHCP host specs from file."
 msgstr "nama MX salah"
 
-#: option.c:347
+#: option.c:359
 msgid "Read DHCP option specs from file."
 msgstr ""
 
 # OK
-#: option.c:348
+#: option.c:360
 #, fuzzy
 msgid "Read DHCP host specs from a directory."
 msgstr "nama MX salah"
 
 # OK
-#: option.c:349
+#: option.c:361
 #, fuzzy
 msgid "Read DHCP options from a directory."
 msgstr "nama MX salah"
 
-#: option.c:350
+#: option.c:362
 msgid "Evaluate conditional tag expression."
 msgstr ""
 
 # OK
-#: option.c:351
+#: option.c:363
 #, c-format
 msgid "Do NOT load %s file."
 msgstr "JANGAN muat file %s."
 
 # OK
-#: option.c:352
+#: option.c:364
 #, c-format
 msgid "Specify a hosts file to be read in addition to %s."
 msgstr "Sebutkan sebuah file hosts yang harus dibaca sebagai tambahan untuk %s."
 
 # OK
-#: option.c:353
+#: option.c:365
 #, fuzzy
 msgid "Read hosts files from a directory."
 msgstr "nama MX salah"
 
 # OK
-#: option.c:354
+#: option.c:366
 msgid "Specify interface(s) to listen on."
 msgstr "Sebutkan antarmuka untuk mendengarkan."
 
 # OK
-#: option.c:355
+#: option.c:367
 msgid "Specify interface(s) NOT to listen on."
 msgstr "Sebutkan antarmuka untuk TIDAK mendengarkan."
 
 # OK
-#: option.c:356
+#: option.c:368
 #, fuzzy
 msgid "Map DHCP user class to tag."
 msgstr "Petakan kelas user DHCP ke setelan yang dipilih."
 
-#: option.c:357
+#: option.c:369
 msgid "Map RFC3046 circuit-id to tag."
 msgstr ""
 
-#: option.c:358
+#: option.c:370
 msgid "Map RFC3046 remote-id to tag."
 msgstr ""
 
-#: option.c:359
+#: option.c:371
 msgid "Map RFC3993 subscriber-id to tag."
 msgstr ""
 
 # OK
-#: option.c:360
+#: option.c:372
 #, fuzzy
 msgid "Don't do DHCP for hosts with tag set."
 msgstr "Jangan menggunakan DHCP untuk host-host yang dipilih."
 
 # OK
-#: option.c:361
+#: option.c:373
 #, fuzzy
 msgid "Force broadcast replies for hosts with tag set."
 msgstr "Jangan menggunakan DHCP untuk host-host yang dipilih."
 
 # OK
-#: option.c:362
+#: option.c:374
 msgid "Do NOT fork into the background, do NOT run in debug mode."
 msgstr "JANGAN berjalan di background, jangan berjalan dalam modus debug."
 
 # OK
-#: option.c:363
+#: option.c:375
 msgid "Assume we are the only DHCP server on the local network."
 msgstr "Berpikir bahwa kita satu-satunya DHCP server dalam jaringan."
 
 # OK
-#: option.c:364
+#: option.c:376
 #, c-format
 msgid "Specify where to store DHCP leases (defaults to %s)."
 msgstr "Sebutkan lokasi untuk menyimpan lease DHCP (default %s)."
 
 # OK
-#: option.c:365
+#: option.c:377
 msgid "Return MX records for local hosts."
 msgstr "Kembalikan rekord MX untuk host-host lokal."
 
 # OK
-#: option.c:366
+#: option.c:378
 msgid "Specify an MX record."
 msgstr "Sebutkan sebuah rekord MX."
 
 # OK
-#: option.c:367
+#: option.c:379
 msgid "Specify BOOTP options to DHCP server."
 msgstr "Sebutkan pilihan-pilihan BOOTP untuk DHCP server."
 
-#: option.c:368
+#: option.c:380
 #, c-format
 msgid "Do NOT poll %s file, reload only on SIGHUP."
 msgstr "Jangan kumpulkan file %s, muat kembali saat SIGHUP."
 
 # OK
-#: option.c:369
+#: option.c:381
 msgid "Do NOT cache failed search results."
 msgstr "JANGAN menyimpan hasil pencarian yang gagal."
 
 # OK
-#: option.c:370
+#: option.c:382
 #, c-format
 msgid "Use nameservers strictly in the order given in %s."
 msgstr "Gunakan secara ketat namaserver yang disebutkan sesuai urutan di %s."
 
 # OK
-#: option.c:371
+#: option.c:383
 #, fuzzy
 msgid "Specify options to be sent to DHCP clients."
 msgstr "Setel pilihan-pilihan tambahan yang akan disetel untuk klien-klien DHCP."
 
-#: option.c:372
+#: option.c:384
 msgid "DHCP option sent even if the client does not request it."
 msgstr ""
 
 # OK
-#: option.c:373
+#: option.c:385
 msgid "Specify port to listen for DNS requests on (defaults to 53)."
 msgstr "Sebutkan port untuk mendengarkan permintaan DNS (default port 53)."
 
 # OK
-#: option.c:374
+#: option.c:386
 #, c-format
 msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
 msgstr "Ukuran maksimum paket UDP yang didukung untuk EDNS.0 (default %s)."
 
 # OK
-#: option.c:375
+#: option.c:387
 #, fuzzy
 msgid "Log DNS queries."
 msgstr "Permintaan log."
 
 # OK
-#: option.c:376
+#: option.c:388
 #, fuzzy
 msgid "Force the originating port for upstream DNS queries."
 msgstr "Paksa port asal untuk permintaan ke atas."
 
 # OK
-#: option.c:377
+#: option.c:389
 msgid "Do NOT read resolv.conf."
 msgstr "JANGAN baca resolv.conf."
 
 # OK
-#: option.c:378
+#: option.c:390
 #, c-format
 msgid "Specify path to resolv.conf (defaults to %s)."
 msgstr "Sebutkan path ke resolv.conf (default %s)."
 
 # OK
-#: option.c:379
+#: option.c:391
 #, fuzzy
 msgid "Specify path to file with server= options"
 msgstr "Sebutkan path file PID. (default %s)."
 
 # OK
-#: option.c:380
+#: option.c:392
 msgid "Specify address(es) of upstream servers with optional domains."
 msgstr "Sebutkan alamat-alamat server di atas, boleh dilengkapi dengan nama domain."
 
 # OK
-#: option.c:381
+#: option.c:393
 #, fuzzy
 msgid "Specify address of upstream servers for reverse address queries"
 msgstr "Sebutkan alamat-alamat server di atas, boleh dilengkapi dengan nama domain."
 
 # OK
-#: option.c:382
+#: option.c:394
 msgid "Never forward queries to specified domains."
 msgstr "JANGAN pernah meneruskan permintaan ke domain yang disebutkan."
 
 # OK
-#: option.c:383
+#: option.c:395
 msgid "Specify the domain to be assigned in DHCP leases."
 msgstr "Sebutkan domain yang digunakan dalam lease DHCP."
 
 # OK
-#: option.c:384
+#: option.c:396
 msgid "Specify default target in an MX record."
 msgstr "Sebutkan tujuan default dalam rekord MX."
 
 # OK
-#: option.c:385
+#: option.c:397
 msgid "Specify time-to-live in seconds for replies from /etc/hosts."
 msgstr "Sebutkan time-to-live dalam detik untuk jawaban dari /etc/hosts."
 
 # OK
-#: option.c:386
+#: option.c:398
 #, fuzzy
 msgid "Specify time-to-live in seconds for negative caching."
 msgstr "Sebutkan time-to-live dalam detik untuk jawaban dari /etc/hosts."
 
 # OK
-#: option.c:387
+#: option.c:399
 #, fuzzy
 msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
 msgstr "Sebutkan time-to-live dalam detik untuk jawaban dari /etc/hosts."
 
 # OK
-#: option.c:388
+#: option.c:400
 #, fuzzy
 msgid "Specify time-to-live ceiling for cache."
 msgstr "Sebutkan time-to-live dalam detik untuk jawaban dari /etc/hosts."
 
 # OK
-#: option.c:389
+#: option.c:401
 #, fuzzy
 msgid "Specify time-to-live floor for cache."
 msgstr "Sebutkan time-to-live dalam detik untuk jawaban dari /etc/hosts."
 
 # OK
-#: option.c:390
+#: option.c:402
 #, c-format
 msgid "Change to this user after startup. (defaults to %s)."
 msgstr "Ubah ke user ini setelah mulai. (default %s)."
 
 # OK
-#: option.c:391
+#: option.c:403
 #, fuzzy
 msgid "Map DHCP vendor class to tag."
 msgstr "Memetakan kelas vendor DHCP ke daftar pilihan."
 
 # OK
-#: option.c:392
+#: option.c:404
 msgid "Display dnsmasq version and copyright information."
 msgstr "Menampilkan versi dan informasi hak cipta dnsmasq."
 
 # OK
-#: option.c:393
+#: option.c:405
 msgid "Translate IPv4 addresses from upstream servers."
 msgstr "Terjemahkan alamat-alamat IPv4 dari server-server di atas."
 
 # OK
-#: option.c:394
+#: option.c:406
 msgid "Specify a SRV record."
 msgstr "Sebutkan rekord SRV."
 
-#: option.c:395
-msgid "Display this message. Use --help dhcp for known DHCP options."
+#: option.c:407
+msgid "Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."
 msgstr ""
 
 # OK
-#: option.c:396
+#: option.c:408
 #, fuzzy, c-format
 msgid "Specify path of PID file (defaults to %s)."
 msgstr "Sebutkan path file PID. (default %s)."
 
 # OK
-#: option.c:397
+#: option.c:409
 #, c-format
 msgid "Specify maximum number of DHCP leases (defaults to %s)."
 msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)."
 
 # OK
-#: option.c:398
+#: option.c:410
 msgid "Answer DNS queries based on the interface a query was sent to."
 msgstr "Jawab permintaan DNS berdasarkan antarmuka dimana permintaan dikirimkan."
 
 # OK
-#: option.c:399
+#: option.c:411
 msgid "Specify TXT DNS record."
 msgstr "Sebutkan rekord TXT DNS."
 
 # OK
-#: option.c:400
+#: option.c:412
 #, fuzzy
 msgid "Specify PTR DNS record."
 msgstr "Sebutkan rekord TXT DNS."
 
-#: option.c:401
+#: option.c:413
 msgid "Give DNS name to IPv4 address of interface."
 msgstr ""
 
 # OK
-#: option.c:402
+#: option.c:414
 msgid "Bind only to interfaces in use."
 msgstr "Hanya kaitkan ke antarmuka yang sedang digunakan saja."
 
 # OK
-#: option.c:403
+#: option.c:415
 #, c-format
 msgid "Read DHCP static host information from %s."
 msgstr "Baca informasi statik host DHCP dari %s."
 
 # OK
-#: option.c:404
+#: option.c:416
 msgid "Enable the DBus interface for setting upstream servers, etc."
 msgstr "Mungkinkan antar muka DBus untuk menyetel server-server di atas, dsb."
 
 # OK
-#: option.c:405
+#: option.c:417
 msgid "Do not provide DHCP on this interface, only provide DNS."
 msgstr "JANGAN menyediakan DHCP pada antarmuka ini, hanya menyediakan DNS."
 
 # OK
-#: option.c:406
+#: option.c:418
 msgid "Enable dynamic address allocation for bootp."
 msgstr "Mungkinkan alokasi alamat dinamis untuk bootp."
 
 # OK
-#: option.c:407
+#: option.c:419
 #, fuzzy
 msgid "Map MAC address (with wildcards) to option set."
 msgstr "Memetakan kelas vendor DHCP ke daftar pilihan."
 
-#: option.c:408
+#: option.c:420
 msgid "Treat DHCP requests on aliases as arriving from interface."
 msgstr ""
 
-#: option.c:409
+#: option.c:421
 msgid "Disable ICMP echo address checking in the DHCP server."
 msgstr ""
 
-#: option.c:410
+#: option.c:422
 msgid "Shell script to run on DHCP lease creation and destruction."
 msgstr ""
 
-#: option.c:411
+#: option.c:423
 msgid "Lua script to run on DHCP lease creation and destruction."
 msgstr ""
 
-#: option.c:412
+#: option.c:424
 msgid "Run lease-change scripts as this user."
 msgstr ""
 
-#: option.c:413
+#: option.c:425
+msgid "Call dhcp-script with changes to local ARP table."
+msgstr ""
+
+#: option.c:426
 msgid "Read configuration from all the files in this directory."
 msgstr ""
 
 # OK
-#: option.c:414
+#: option.c:427
 #, fuzzy
 msgid "Log to this syslog facility or file. (defaults to DAEMON)"
 msgstr "Ubah ke user ini setelah mulai. (default %s)."
 
-#: option.c:415
+#: option.c:428
 msgid "Do not use leasefile."
 msgstr ""
 
 # OK
-#: option.c:416
+#: option.c:429
 #, fuzzy, c-format
 msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
 msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)."
 
-#: option.c:417
+#: option.c:430
 #, c-format
 msgid "Clear DNS cache when reloading %s."
 msgstr ""
 
-#: option.c:418
+#: option.c:431
 msgid "Ignore hostnames provided by DHCP clients."
 msgstr ""
 
-#: option.c:419
+#: option.c:432
 msgid "Do NOT reuse filename and server fields for extra DHCP options."
 msgstr ""
 
-#: option.c:420
+#: option.c:433
 msgid "Enable integrated read-only TFTP server."
 msgstr ""
 
-#: option.c:421
+#: option.c:434
 msgid "Export files by TFTP only from the specified subtree."
 msgstr ""
 
-#: option.c:422
-msgid "Add client IP address to tftp-root."
+#: option.c:435
+msgid "Add client IP or hardware address to tftp-root."
 msgstr ""
 
-#: option.c:423
+#: option.c:436
 msgid "Allow access only to files owned by the user running dnsmasq."
 msgstr ""
 
-#: option.c:424
+#: option.c:437
 msgid "Do not terminate the service if TFTP directories are inaccessible."
 msgstr ""
 
 # OK
-#: option.c:425
+#: option.c:438
 #, fuzzy, c-format
-msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgid "Maximum number of concurrent TFTP transfers (defaults to %s)."
 msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)."
 
-#: option.c:426
+# OK
+#: option.c:439
+#, fuzzy
+msgid "Maximum MTU to use for TFTP transfers."
+msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)."
+
+#: option.c:440
 msgid "Disable the TFTP blocksize extension."
 msgstr ""
 
-#: option.c:427
+#: option.c:441
 msgid "Convert TFTP filenames to lowercase"
 msgstr ""
 
-#: option.c:428
+#: option.c:442
 msgid "Ephemeral port range for use by TFTP transfers."
 msgstr ""
 
-#: option.c:429
+#: option.c:443
 msgid "Extra logging for DHCP."
 msgstr ""
 
-#: option.c:430
+#: option.c:444
 msgid "Enable async. logging; optionally set queue length."
 msgstr ""
 
-#: option.c:431
+#: option.c:445
 msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
 msgstr ""
 
-#: option.c:432
+#: option.c:446
 msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
 msgstr ""
 
-#: option.c:433
+#: option.c:447
 msgid "Inhibit DNS-rebind protection on this domain."
 msgstr ""
 
-#: option.c:434
+#: option.c:448
 msgid "Always perform DNS queries to all servers."
 msgstr ""
 
-#: option.c:435
+#: option.c:449
 msgid "Set tag if client includes matching option in request."
 msgstr ""
 
-#: option.c:436
+#: option.c:450
 msgid "Use alternative ports for DHCP."
 msgstr ""
 
 # OK
-#: option.c:437
+#: option.c:451
 #, fuzzy
 msgid "Specify NAPTR DNS record."
 msgstr "Sebutkan rekord TXT DNS."
 
-#: option.c:438
+#: option.c:452
 msgid "Specify lowest port available for DNS query transmission."
 msgstr ""
 
-#: option.c:439
+#: option.c:453
+msgid "Specify highest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:454
 msgid "Use only fully qualified domain names for DHCP clients."
 msgstr ""
 
-#: option.c:440
+#: option.c:455
 msgid "Generate hostnames based on MAC address for nameless clients."
 msgstr ""
 
-#: option.c:441
+#: option.c:456
 msgid "Use these DHCP relays as full proxies."
 msgstr ""
 
-#: option.c:442
+#: option.c:457
 msgid "Relay DHCP requests to a remote server"
 msgstr ""
 
-#: option.c:443
+#: option.c:458
 msgid "Specify alias name for LOCAL DNS name."
 msgstr ""
 
 # OK
-#: option.c:444
+#: option.c:459
 #, fuzzy
 msgid "Prompt to send to PXE clients."
 msgstr "Setel pilihan-pilihan tambahan yang akan disetel untuk klien-klien DHCP."
 
-#: option.c:445
+#: option.c:460
 msgid "Boot service for PXE menu."
 msgstr ""
 
-#: option.c:446
+#: option.c:461
 msgid "Check configuration syntax."
 msgstr ""
 
-#: option.c:447
+#: option.c:462
 msgid "Add requestor's MAC address to forwarded DNS queries."
 msgstr ""
 
-#: option.c:448
-msgid "Add requestor's IP subnet to forwarded DNS queries."
+#: option.c:463
+msgid "Add specified IP subnet to forwarded DNS queries."
 msgstr ""
 
 # OK
-#: option.c:449
+#: option.c:464
+#, fuzzy
+msgid "Add client identification to forwarded DNS queries."
+msgstr "Paksa port asal untuk permintaan ke atas."
+
+# OK
+#: option.c:465
 #, fuzzy
 msgid "Proxy DNSSEC validation results from upstream nameservers."
 msgstr "Terjemahkan alamat-alamat IPv4 dari server-server di atas."
 
-#: option.c:450
+#: option.c:466
 msgid "Attempt to allocate sequential IP addresses to DHCP clients."
 msgstr ""
 
-#: option.c:451
+#: option.c:467
 msgid "Copy connection-track mark from queries to upstream connections."
 msgstr ""
 
-#: option.c:452
+#: option.c:468
 msgid "Allow DHCP clients to do their own DDNS updates."
 msgstr ""
 
-#: option.c:453
+#: option.c:469
 msgid "Send router-advertisements for interfaces doing DHCPv6"
 msgstr ""
 
-#: option.c:454
+#: option.c:470
 msgid "Specify DUID_EN-type DHCPv6 server DUID"
 msgstr ""
 
 # OK
-#: option.c:455
+#: option.c:471
 #, fuzzy
 msgid "Specify host (A/AAAA and PTR) records"
 msgstr "Sebutkan sebuah rekord MX."
 
 # OK
-#: option.c:456
+#: option.c:472
 #, fuzzy
 msgid "Specify arbitrary DNS resource record"
 msgstr "Sebutkan rekord TXT DNS."
 
 # OK
-#: option.c:457
+#: option.c:473
 #, fuzzy
 msgid "Bind to interfaces in use - check for new interfaces"
 msgstr "antarmuka tidak dikenal %s"
 
-#: option.c:458
+#: option.c:474
 msgid "Export local names to global DNS"
 msgstr ""
 
-#: option.c:459
+#: option.c:475
 msgid "Domain to export to global DNS"
 msgstr ""
 
-#: option.c:460
+#: option.c:476
 msgid "Set TTL for authoritative replies"
 msgstr ""
 
-#: option.c:461
-msgid "Set authoritive zone information"
+#: option.c:477
+msgid "Set authoritative zone information"
 msgstr ""
 
-#: option.c:462
+#: option.c:478
 msgid "Secondary authoritative nameservers for forward domains"
 msgstr ""
 
-#: option.c:463
+#: option.c:479
 msgid "Peers which are allowed to do zone transfer"
 msgstr ""
 
-#: option.c:464
+#: option.c:480
 msgid "Specify ipsets to which matching domains should be added"
 msgstr ""
 
-#: option.c:465
+#: option.c:481
 msgid "Specify a domain and address range for synthesised names"
 msgstr ""
 
-#: option.c:466
+#: option.c:482
 msgid "Activate DNSSEC validation"
 msgstr ""
 
-#: option.c:467
+#: option.c:483
 msgid "Specify trust anchor key digest."
 msgstr ""
 
-#: option.c:468
+#: option.c:484
 msgid "Disable upstream checking for DNSSEC debugging."
 msgstr ""
 
-#: option.c:469
+#: option.c:485
 msgid "Ensure answers without DNSSEC are in unsigned zones."
 msgstr ""
 
-#: option.c:470
+#: option.c:486
 msgid "Don't check DNSSEC signature timestamps until first cache-reload"
 msgstr ""
 
-#: option.c:471
+#: option.c:487
 msgid "Timestamp file to verify system clock for DNSSEC"
 msgstr ""
 
-#: option.c:473
+#: option.c:489
 msgid "Specify DHCPv6 prefix class"
 msgstr ""
 
-#: option.c:475
-msgid "Set priority, resend-interval and router-lifetime"
+#: option.c:491
+msgid "Set MTU, priority, resend-interval and router-lifetime"
 msgstr ""
 
-#: option.c:476
+#: option.c:492
 msgid "Do not log routine DHCP."
 msgstr ""
 
-#: option.c:477
+#: option.c:493
 msgid "Do not log routine DHCPv6."
 msgstr ""
 
-#: option.c:478
+#: option.c:494
 msgid "Do not log RA."
 msgstr ""
 
-#: option.c:479
-msgid "Accept queries only from directly-connected networks"
+#: option.c:495
+msgid "Accept queries only from directly-connected networks."
 msgstr ""
 
-#: option.c:480
-msgid "Detect and remove DNS forwarding loops"
+#: option.c:496
+msgid "Detect and remove DNS forwarding loops."
 msgstr ""
 
-#: option.c:481
+#: option.c:497
 msgid "Ignore DNS responses containing ipaddr."
 msgstr ""
 
+#: option.c:498
+msgid "Set TTL in DNS responses with DHCP-derived addresses."
+msgstr ""
+
+#: option.c:499
+msgid "Delay DHCP replies for at least number of seconds."
+msgstr ""
+
 # OK
-#: option.c:683
+#: option.c:703
 #, c-format
 msgid ""
 "Usage: dnsmasq [options]\n"
@@ -847,381 +875,391 @@ msgstr ""
 "\n"
 
 # OK
-#: option.c:685
+#: option.c:705
 #, c-format
 msgid "Use short options only on the command line.\n"
 msgstr "Gunakan pilihan pendek saja pada perintah baris.\n"
 
 # OK
-#: option.c:687
+#: option.c:707
 #, fuzzy, c-format
 msgid "Valid options are:\n"
 msgstr "Pilihan yang boleh adalah:\n"
 
 # OK
-#: option.c:744 option.c:748
+#: option.c:754 option.c:868
+#, fuzzy
+msgid "bad address"
+msgstr "membaca %s - %d alamat"
+
+# OK
+#: option.c:779 option.c:783
 msgid "bad port"
 msgstr "port salah"
 
-#: option.c:775 option.c:807
+#: option.c:797 option.c:826 option.c:861
 msgid "interface binding not supported"
 msgstr ""
 
+#: option.c:821 option.c:856
+msgid "interface can only be specified once"
+msgstr ""
+
 # OK
-#: option.c:784 option.c:3575
+#: option.c:835 option.c:3809
 #, fuzzy
 msgid "bad interface name"
 msgstr "nama MX salah"
 
-# OK
-#: option.c:814
-#, fuzzy
-msgid "bad address"
-msgstr "membaca %s - %d alamat"
-
-#: option.c:996
+#: option.c:1062
 msgid "unsupported encapsulation for IPv6 option"
 msgstr ""
 
 # OK
-#: option.c:1010
+#: option.c:1076
 msgid "bad dhcp-option"
 msgstr "dhcp-option salah"
 
 # OK
-#: option.c:1078
+#: option.c:1144
 #, fuzzy
 msgid "bad IP address"
 msgstr "membaca %s - %d alamat"
 
 # OK
-#: option.c:1081 option.c:1219 option.c:2893
+#: option.c:1147 option.c:1286 option.c:3079
 #, fuzzy
 msgid "bad IPv6 address"
 msgstr "membaca %s - %d alamat"
 
 # OK
-#: option.c:1246 option.c:1340
+#: option.c:1240
+#, fuzzy
+msgid "bad IPv4 address"
+msgstr "membaca %s - %d alamat"
+
+# OK
+#: option.c:1313 option.c:1407
 msgid "bad domain in dhcp-option"
 msgstr "domain dalam dhcp-option salah"
 
 # OK
-#: option.c:1378
+#: option.c:1445
 msgid "dhcp-option too long"
 msgstr "dhcp-option terlalu panjang"
 
-#: option.c:1385
+#: option.c:1452
 msgid "illegal dhcp-match"
 msgstr ""
 
-#: option.c:1447
+#: option.c:1514
 msgid "illegal repeated flag"
 msgstr ""
 
-#: option.c:1455
+#: option.c:1522
 msgid "illegal repeated keyword"
 msgstr ""
 
 # OK
-#: option.c:1520 option.c:4191
+#: option.c:1593 option.c:4443
 #, fuzzy, c-format
 msgid "cannot access directory %s: %s"
 msgstr "tidak bisa membaca %s: %s"
 
 # OK
-#: option.c:1566 tftp.c:493
+#: option.c:1639 tftp.c:537
 #, fuzzy, c-format
 msgid "cannot access %s: %s"
 msgstr "tidak bisa membaca %s: %s"
 
-#: option.c:1618
+#: option.c:1727
 msgid "setting log facility is not possible under Android"
 msgstr ""
 
-#: option.c:1627
+#: option.c:1736
 msgid "bad log facility"
 msgstr ""
 
 # OK
-#: option.c:1680
+#: option.c:1789
 msgid "bad MX preference"
 msgstr "kesukaan MX salah"
 
 # OK
-#: option.c:1685
+#: option.c:1794
 msgid "bad MX name"
 msgstr "nama MX salah"
 
 # OK
-#: option.c:1699
+#: option.c:1808
 msgid "bad MX target"
 msgstr "target MX salah"
 
-#: option.c:1711
+#: option.c:1820
 msgid "cannot run scripts under uClinux"
 msgstr ""
 
-#: option.c:1713
+#: option.c:1822
 msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
 msgstr ""
 
-#: option.c:1717
+#: option.c:1826
 msgid "recompile with HAVE_LUASCRIPT defined to enable Lua scripts"
 msgstr ""
 
 # OK
-#: option.c:1973 option.c:2018 option.c:2074
+#: option.c:2095 option.c:2106 option.c:2143 option.c:2199 option.c:2482
 #, fuzzy
 msgid "bad prefix"
 msgstr "port salah"
 
-#: option.c:2355
+#: option.c:2504
 msgid "recompile with HAVE_IPSET defined to enable ipset directives"
 msgstr ""
 
 # OK
-#: option.c:2548
+#: option.c:2713
 #, fuzzy
 msgid "bad port range"
 msgstr "port salah"
 
-#: option.c:2564
+#: option.c:2739
 msgid "bad bridge-interface"
 msgstr ""
 
-#: option.c:2624
+#: option.c:2807
 msgid "only one tag allowed"
 msgstr ""
 
 # OK
-#: option.c:2644 option.c:2656 option.c:2764 option.c:2805
+#: option.c:2827 option.c:2839 option.c:2948 option.c:2953 option.c:2992
 msgid "bad dhcp-range"
 msgstr "dhcp-range salah"
 
 # OK
-#: option.c:2671
+#: option.c:2854
 msgid "inconsistent DHCP range"
 msgstr "jangkauan DHCP tidak konsisten"
 
-#: option.c:2732
+#: option.c:2916
 msgid "prefix length must be exactly 64 for RA subnets"
 msgstr ""
 
-#: option.c:2734
+#: option.c:2918
 msgid "prefix length must be exactly 64 for subnet constructors"
 msgstr ""
 
-#: option.c:2738
+#: option.c:2922
 msgid "prefix length must be at least 64"
 msgstr ""
 
 # OK
-#: option.c:2741
+#: option.c:2925
 #, fuzzy
 msgid "inconsistent DHCPv6 range"
 msgstr "jangkauan DHCP tidak konsisten"
 
-#: option.c:2752
+#: option.c:2936
 msgid "prefix must be zero with \"constructor:\" argument"
 msgstr ""
 
 # OK
-#: option.c:2863 option.c:2911
+#: option.c:3049 option.c:3097
 #, fuzzy
 msgid "bad hex constant"
 msgstr "dhcp-host salah"
 
-#: option.c:2885
+#: option.c:3071
 msgid "cannot match tags in --dhcp-host"
 msgstr ""
 
 # OK
-#: option.c:2933
+#: option.c:3119
 #, fuzzy, c-format
 msgid "duplicate dhcp-host IP address %s"
 msgstr "alamat IP kembar %s dalam direktif dhcp-config"
 
 # OK
-#: option.c:2991
+#: option.c:3177
 #, fuzzy
 msgid "bad DHCP host name"
 msgstr "nama MX salah"
 
 # OK
-#: option.c:3073
+#: option.c:3259
 #, fuzzy
 msgid "bad tag-if"
 msgstr "target MX salah"
 
 # OK
-#: option.c:3397 option.c:3791
+#: option.c:3616 option.c:4039
 msgid "invalid port number"
 msgstr "nomor port tidak benar"
 
 # OK
-#: option.c:3459
+#: option.c:3678
 #, fuzzy
 msgid "bad dhcp-proxy address"
 msgstr "membaca %s - %d alamat"
 
 # OK
-#: option.c:3485
+#: option.c:3704
 #, fuzzy
 msgid "Bad dhcp-relay"
 msgstr "dhcp-range salah"
 
-#: option.c:3511
+#: option.c:3745
 msgid "bad RA-params"
 msgstr ""
 
-#: option.c:3520
+#: option.c:3754
 msgid "bad DUID"
 msgstr ""
 
 # OK
-#: option.c:3562
+#: option.c:3796
 #, fuzzy
 msgid "invalid alias range"
 msgstr "weight tidak benar"
 
-#: option.c:3616
+#: option.c:3850 option.c:3862
 msgid "bad CNAME"
 msgstr ""
 
-#: option.c:3621
+#: option.c:3866
 msgid "duplicate CNAME"
 msgstr ""
 
 # OK
-#: option.c:3641
+#: option.c:3889
 #, fuzzy
 msgid "bad PTR record"
 msgstr "rekord SRV salah"
 
 # OK
-#: option.c:3672
+#: option.c:3920
 #, fuzzy
 msgid "bad NAPTR record"
 msgstr "rekord SRV salah"
 
 # OK
-#: option.c:3706
+#: option.c:3954
 #, fuzzy
 msgid "bad RR record"
 msgstr "rekord SRV salah"
 
 # OK
-#: option.c:3736
+#: option.c:3984
 msgid "bad TXT record"
 msgstr "rekord TXT salah"
 
 # OK
-#: option.c:3777
+#: option.c:4025
 msgid "bad SRV record"
 msgstr "rekord SRV salah"
 
 # OK
-#: option.c:3784
+#: option.c:4032
 msgid "bad SRV target"
 msgstr "target SRV salah"
 
 # OK
-#: option.c:3798
+#: option.c:4046
 msgid "invalid priority"
 msgstr "prioritas tidak benar"
 
 # OK
-#: option.c:3805
+#: option.c:4049
 msgid "invalid weight"
 msgstr "weight tidak benar"
 
 # OK
-#: option.c:3829
+#: option.c:4073
 #, fuzzy
 msgid "Bad host-record"
 msgstr "rekord SRV salah"
 
 # OK
-#: option.c:3846
+#: option.c:4097
 #, fuzzy
 msgid "Bad name in host-record"
 msgstr "kesalahan nama di %s"
 
 # OK
-#: option.c:3911
+#: option.c:4162
 #, fuzzy
 msgid "bad trust anchor"
 msgstr "port salah"
 
-#: option.c:3925
+#: option.c:4176
 msgid "bad HEX in trust anchor"
 msgstr ""
 
-#: option.c:3935
+#: option.c:4186
 msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"
 msgstr ""
 
 # OK
-#: option.c:3994
+#: option.c:4246
 msgid "missing \""
 msgstr "kurang \""
 
 # OK
-#: option.c:4051
+#: option.c:4303
 msgid "bad option"
 msgstr "pilihan salah"
 
 # OK
-#: option.c:4053
+#: option.c:4305
 msgid "extraneous parameter"
 msgstr "parameter berlebihan"
 
 # OK
-#: option.c:4055
+#: option.c:4307
 msgid "missing parameter"
 msgstr "parameter kurang"
 
 # OK
-#: option.c:4057
+#: option.c:4309
 #, fuzzy
 msgid "illegal option"
 msgstr "pilihan salah"
 
 # OK
-#: option.c:4064
+#: option.c:4316
 msgid "error"
 msgstr "kesalahan"
 
 # OK
-#: option.c:4066
+#: option.c:4318
 #, fuzzy, c-format
 msgid " at line %d of %s"
 msgstr "%s pada baris %d dari %%s"
 
 # OK
-#: option.c:4081 option.c:4328 option.c:4364
+#: option.c:4333 option.c:4580 option.c:4616
 #, fuzzy, c-format
 msgid "read %s"
 msgstr "membaca %s"
 
 # OK
-#: option.c:4144 option.c:4267 tftp.c:667
+#: option.c:4396 option.c:4519 tftp.c:715
 #, c-format
 msgid "cannot read %s: %s"
 msgstr "tidak bisa membaca %s: %s"
 
-#: option.c:4430
+#: option.c:4688
 msgid "junk found in command line"
 msgstr ""
 
 # OK
-#: option.c:4465
+#: option.c:4729
 #, c-format
 msgid "Dnsmasq version %s  %s\n"
 msgstr "Dnsmasq versi %s  %s\n"
 
 # OK
-#: option.c:4466
+#: option.c:4730
 #, fuzzy, c-format
 msgid ""
 "Compile time options: %s\n"
@@ -1231,521 +1269,567 @@ msgstr ""
 "\n"
 
 # OK
-#: option.c:4467
+#: option.c:4731
 #, c-format
 msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
 msgstr "Perangkat lunak ini tersedia TANPA JAMINAN SEDIKITPUN.\n"
 
 # OK
-#: option.c:4468
+#: option.c:4732
 #, c-format
 msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
 msgstr "Dnsdmasq adalah perangkat lunak bebas, dan Anda dipersilahkan untuk membagikannya\n"
 
 # OK
-#: option.c:4469
+#: option.c:4733
 #, fuzzy, c-format
 msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
 msgstr "dengan aturan GNU General Public License, versi 2.\n"
 
-#: option.c:4480
+#: option.c:4744
 msgid "try --help"
 msgstr ""
 
-#: option.c:4482
+#: option.c:4746
 msgid "try -w"
 msgstr ""
 
 # OK
-#: option.c:4484
+#: option.c:4748
 #, fuzzy, c-format
 msgid "bad command line options: %s"
 msgstr "pilihan baris perintah salah: %s."
 
+#: option.c:4818
+#, c-format
+msgid "CNAME loop involving %s"
+msgstr ""
+
 # OK
-#: option.c:4541
+#: option.c:4854
 #, c-format
 msgid "cannot get host-name: %s"
 msgstr "tidak bisa mendapatkan host-name: %s"
 
 # OK
-#: option.c:4569
+#: option.c:4882
 msgid "only one resolv.conf file allowed in no-poll mode."
 msgstr "hanya satu file resolv.conf yang diperbolehkan dalam modus no-poll."
 
 # OK
-#: option.c:4579
+#: option.c:4892
 msgid "must have exactly one resolv.conf to read domain from."
 msgstr "harus mempunyai tepat satu resolv.conf untuk mendapatkan nama domain."
 
 # OK
-#: option.c:4582 network.c:1507 dhcp.c:777
+#: option.c:4895 network.c:1623 dhcp.c:816
 #, fuzzy, c-format
 msgid "failed to read %s: %s"
 msgstr "gagal membaca %s: %s"
 
 # OK
-#: option.c:4599
+#: option.c:4912
 #, c-format
 msgid "no search directive found in %s"
 msgstr "tidak ditemukan direktif search di %s"
 
-#: option.c:4620
+#: option.c:4933
 msgid "there must be a default domain when --dhcp-fqdn is set"
 msgstr ""
 
-#: option.c:4629
+#: option.c:4942
 msgid "syntax check OK"
 msgstr ""
 
 # OK
-#: forward.c:111
+#: forward.c:102
 #, fuzzy, c-format
 msgid "failed to send packet: %s"
 msgstr "gagal mendengarkan di socket: %s"
 
-#: forward.c:591
+#: forward.c:598
 msgid "discarding DNS reply: subnet option mismatch"
 msgstr ""
 
 # OK
-#: forward.c:614
+#: forward.c:652
 #, c-format
 msgid "nameserver %s refused to do a recursive query"
 msgstr "nameserver %s menolak melakukan resolusi rekursif"
 
-#: forward.c:646
+#: forward.c:684
 #, c-format
 msgid "possible DNS-rebind attack detected: %s"
 msgstr ""
 
-#: forward.c:1209 forward.c:1815
+#: forward.c:870
+#, c-format
+msgid "reducing DNS packet size for nameserver %s to %d"
+msgstr ""
+
+#: forward.c:1266 forward.c:1704
 msgid "Ignoring query from non-local network"
 msgstr ""
 
 # OK
-#: forward.c:2286
+#: forward.c:2184
 #, fuzzy, c-format
 msgid "Maximum number of concurrent DNS queries reached (max: %d)"
 msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)."
 
 # OK
-#: network.c:715
+#: network.c:720
 #, fuzzy, c-format
 msgid "failed to create listening socket for %s: %s"
 msgstr "gagal membuat socket: %s "
 
-#: network.c:1021
+#: network.c:1031
 #, c-format
 msgid "LOUD WARNING: listening on %s may accept requests via interfaces other than %s"
 msgstr ""
 
-#: network.c:1028
+#: network.c:1038
 msgid "LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"
 msgstr ""
 
 # OK
-#: network.c:1037
+#: network.c:1047
+#, fuzzy, c-format
+msgid "warning: using interface %s instead"
+msgstr "peringatan: antarmuka %s tidak ada"
+
+# OK
+#: network.c:1056
 #, fuzzy, c-format
 msgid "warning: no addresses found for interface %s"
 msgstr "menggunakan alamat lokal saja untuk %s %s"
 
 # OK
-#: network.c:1095
+#: network.c:1114
 #, fuzzy, c-format
 msgid "interface %s failed to join DHCPv6 multicast group: %s"
 msgstr "gagal mem-bind socket server DHCP: %s"
 
-#: network.c:1289
+#: network.c:1119
+msgid "try increasing /proc/sys/net/core/optmem_max"
+msgstr ""
+
+#: network.c:1337
 #, fuzzy, c-format
 msgid "failed to bind server socket for %s: %s"
 msgstr "gagal mem-bind socket untuk mendengarkan %s: %s"
 
 # OK
-#: network.c:1445
+#: network.c:1528
 #, c-format
 msgid "ignoring nameserver %s - local interface"
 msgstr "mengabaikan nameserver %s - antarmuka lokal"
 
 # OK
-#: network.c:1456
+#: network.c:1539
 #, fuzzy, c-format
 msgid "ignoring nameserver %s - cannot make/bind socket: %s"
 msgstr "mengabaikan nameserver %s - tak dapat membuat/mem-bind socket: %s"
 
+#: network.c:1559
+msgid "(no DNSSEC)"
+msgstr ""
+
 # OK
-#: network.c:1469
+#: network.c:1562
 msgid "unqualified"
 msgstr "tidak memenuhi syarat"
 
-#: network.c:1469
+#: network.c:1562
 msgid "names"
 msgstr ""
 
-#: network.c:1471
+#: network.c:1564
 msgid "default"
 msgstr ""
 
 # OK
-#: network.c:1473
+#: network.c:1566
 msgid "domain"
 msgstr "domain"
 
 # OK
-#: network.c:1476
+#: network.c:1572
 #, c-format
 msgid "using local addresses only for %s %s"
 msgstr "menggunakan alamat lokal saja untuk %s %s"
 
 # OK
-#: network.c:1478
+#: network.c:1575
 #, fuzzy, c-format
 msgid "using standard nameservers for %s %s"
 msgstr "menggunakan nameserver %s#%d untuk %s %s"
 
 # OK
-#: network.c:1480
-#, c-format
-msgid "using nameserver %s#%d for %s %s"
+#: network.c:1577
+#, fuzzy, c-format
+msgid "using nameserver %s#%d for %s %s %s"
 msgstr "menggunakan nameserver %s#%d untuk %s %s"
 
 # OK
-#: network.c:1484
+#: network.c:1581
 #, fuzzy, c-format
 msgid "NOT using nameserver %s#%d - query loop detected"
 msgstr "menggunakan nameserver %s#%d untuk %s %s"
 
 # OK
-#: network.c:1487
+#: network.c:1584
 #, fuzzy, c-format
 msgid "using nameserver %s#%d(via %s)"
 msgstr "menggunakan nameserver %s#%d"
 
 # OK
-#: network.c:1489
+#: network.c:1586
 #, c-format
 msgid "using nameserver %s#%d"
 msgstr "menggunakan nameserver %s#%d"
 
-#: dnsmasq.c:163
+# OK
+#: network.c:1591
+#, fuzzy, c-format
+msgid "using %d more local addresses"
+msgstr "menggunakan nameserver %s#%d"
+
+# OK
+#: network.c:1593
+#, fuzzy, c-format
+msgid "using %d more nameservers"
+msgstr "menggunakan nameserver %s#%d"
+
+#: dnsmasq.c:171
 msgid "dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"
 msgstr ""
 
-#: dnsmasq.c:170
-msgid "no trust anchors provided for DNSSEC"
+#: dnsmasq.c:186
+msgid "no root trust anchor provided for DNSSEC"
 msgstr ""
 
-#: dnsmasq.c:173
+#: dnsmasq.c:189
 msgid "cannot reduce cache size from default when DNSSEC enabled"
 msgstr ""
 
 # OK
-#: dnsmasq.c:175
+#: dnsmasq.c:191
 #, fuzzy
 msgid "DNSSEC not available: set HAVE_DNSSEC in src/config.h"
 msgstr "DBus tidak tersedia: setel HAVE_DBUS dalam src/config.h"
 
 # OK
-#: dnsmasq.c:181
+#: dnsmasq.c:197
 #, fuzzy
 msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
 msgstr "DBus tidak tersedia: setel HAVE_DBUS dalam src/config.h"
 
-#: dnsmasq.c:186
+#: dnsmasq.c:202
 msgid "cannot use --conntrack AND --query-port"
 msgstr ""
 
 # OK
-#: dnsmasq.c:189
+#: dnsmasq.c:205
 #, fuzzy
 msgid "conntrack support not available: set HAVE_CONNTRACK in src/config.h"
 msgstr "DBus tidak tersedia: setel HAVE_DBUS dalam src/config.h"
 
-#: dnsmasq.c:194
-msgid "asychronous logging is not available under Solaris"
+#: dnsmasq.c:210
+msgid "asynchronous logging is not available under Solaris"
 msgstr ""
 
-#: dnsmasq.c:199
-msgid "asychronous logging is not available under Android"
+#: dnsmasq.c:215
+msgid "asynchronous logging is not available under Android"
 msgstr ""
 
 # OK
-#: dnsmasq.c:204
+#: dnsmasq.c:220
 #, fuzzy
 msgid "authoritative DNS not available: set HAVE_AUTH in src/config.h"
 msgstr "DBus tidak tersedia: setel HAVE_DBUS dalam src/config.h"
 
 # OK
-#: dnsmasq.c:209
+#: dnsmasq.c:225
 #, fuzzy
 msgid "loop detection not available: set HAVE_LOOP in src/config.h"
 msgstr "DBus tidak tersedia: setel HAVE_DBUS dalam src/config.h"
 
-#: dnsmasq.c:217
+#: dnsmasq.c:229
+msgid "max_port cannot be smaller than min_port"
+msgstr ""
+
+#: dnsmasq.c:236
 msgid "zone serial must be configured in --auth-soa"
 msgstr ""
 
-#: dnsmasq.c:235
+#: dnsmasq.c:254
 msgid "dhcp-range constructor not available on this platform"
 msgstr ""
 
-#: dnsmasq.c:278
+#: dnsmasq.c:300
 msgid "cannot set --bind-interfaces and --bind-dynamic"
 msgstr ""
 
 # OK
-#: dnsmasq.c:281
+#: dnsmasq.c:303
 #, c-format
 msgid "failed to find list of interfaces: %s"
 msgstr "gagal mendapatkan daftar antarmuka: %s"
 
 # OK
-#: dnsmasq.c:290
+#: dnsmasq.c:312
 #, c-format
 msgid "unknown interface %s"
 msgstr "antarmuka tidak dikenal %s"
 
 # OK
-#: dnsmasq.c:354 dnsmasq.c:997
+#: dnsmasq.c:377 dnsmasq.c:1054
 #, c-format
 msgid "DBus error: %s"
 msgstr "DBus error: %s"
 
 # OK
-#: dnsmasq.c:357
+#: dnsmasq.c:380
 msgid "DBus not available: set HAVE_DBUS in src/config.h"
 msgstr "DBus tidak tersedia: setel HAVE_DBUS dalam src/config.h"
 
-#: dnsmasq.c:385
+#: dnsmasq.c:410
 #, c-format
 msgid "unknown user or group: %s"
 msgstr ""
 
-#: dnsmasq.c:440
+#: dnsmasq.c:465
 #, c-format
 msgid "cannot chdir to filesystem root: %s"
 msgstr ""
 
 # OK
-#: dnsmasq.c:692
+#: dnsmasq.c:730
 #, fuzzy, c-format
 msgid "started, version %s DNS disabled"
 msgstr "dimulai, cache versi %s di disable"
 
 # OK
-#: dnsmasq.c:694
+#: dnsmasq.c:734
 #, c-format
 msgid "started, version %s cachesize %d"
 msgstr "dimulai, versi %s ukuran cache %d"
 
 # OK
-#: dnsmasq.c:696
+#: dnsmasq.c:736
 #, c-format
 msgid "started, version %s cache disabled"
 msgstr "dimulai, cache versi %s di disable"
 
+#: dnsmasq.c:739
+msgid "DNS service limited to local subnets"
+msgstr ""
+
 # OK
-#: dnsmasq.c:698
+#: dnsmasq.c:742
 #, c-format
 msgid "compile time options: %s"
 msgstr "pilihan-pilihan saat kompilasi: %s"
 
 # OK
-#: dnsmasq.c:704
+#: dnsmasq.c:751
 msgid "DBus support enabled: connected to system bus"
 msgstr "dukungan DBus dimungkinkan: terkoneksi pada bus sistem"
 
 # OK
-#: dnsmasq.c:706
+#: dnsmasq.c:753
 msgid "DBus support enabled: bus connection pending"
 msgstr "dukungan DBus dimungkinkan: koneksi bus ditunda"
 
-#: dnsmasq.c:711
-msgid "DNS service limited to local subnets"
-msgstr ""
-
-#: dnsmasq.c:727
+#: dnsmasq.c:771
 msgid "DNSSEC validation enabled"
 msgstr ""
 
-#: dnsmasq.c:730
-msgid "DNSSEC signature timestamps not checked until first cache reload"
+#: dnsmasq.c:775
+msgid "DNSSEC signature timestamps not checked until receipt of SIGINT"
 msgstr ""
 
-#: dnsmasq.c:733
+#: dnsmasq.c:778
 msgid "DNSSEC signature timestamps not checked until system time valid"
 msgstr ""
 
 # OK
-#: dnsmasq.c:738
+#: dnsmasq.c:783
 #, fuzzy, c-format
 msgid "warning: failed to change owner of %s: %s"
 msgstr "gagal memuat nama-nama dari %s: %s"
 
 # OK
-#: dnsmasq.c:742
+#: dnsmasq.c:787
 msgid "setting --bind-interfaces option because of OS limitations"
 msgstr "setelan opsi --bind-interfaces disebabkan keterbatasan OS"
 
 # OK
-#: dnsmasq.c:752
+#: dnsmasq.c:799
 #, c-format
 msgid "warning: interface %s does not currently exist"
 msgstr "peringatan: antarmuka %s tidak ada"
 
-#: dnsmasq.c:757
+#: dnsmasq.c:804
 msgid "warning: ignoring resolv-file flag because no-resolv is set"
 msgstr ""
 
 # OK
-#: dnsmasq.c:760
+#: dnsmasq.c:807
 #, fuzzy
 msgid "warning: no upstream servers configured"
 msgstr "menyetel server-server di atas dengan DBus"
 
-#: dnsmasq.c:764
+#: dnsmasq.c:811
 #, c-format
 msgid "asynchronous logging enabled, queue limit is %d messages"
 msgstr ""
 
-#: dnsmasq.c:785
+#: dnsmasq.c:832
 msgid "IPv6 router advertisement enabled"
 msgstr ""
 
-#: dnsmasq.c:790
+#: dnsmasq.c:837
 #, c-format
 msgid "DHCP, sockets bound exclusively to interface %s"
 msgstr ""
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "root is "
 msgstr ""
 
 # OK
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 #, fuzzy
 msgid "enabled"
 msgstr "di disable"
 
-#: dnsmasq.c:806
+#: dnsmasq.c:853
 msgid "secure mode"
 msgstr ""
 
-#: dnsmasq.c:809
+#: dnsmasq.c:856
 #, c-format
 msgid "warning: %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:813
+#: dnsmasq.c:860
 #, c-format
 msgid "warning: TFTP directory %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:839
+#: dnsmasq.c:886
 #, c-format
 msgid "restricting maximum simultaneous TFTP transfers to %d"
 msgstr ""
 
 # OK
-#: dnsmasq.c:999
+#: dnsmasq.c:1056
 msgid "connected to system DBus"
 msgstr "terhubung ke sistem DBus"
 
-#: dnsmasq.c:1149
+#: dnsmasq.c:1215
 #, c-format
 msgid "cannot fork into background: %s"
 msgstr ""
 
 # OK
-#: dnsmasq.c:1152
+#: dnsmasq.c:1218
 #, fuzzy, c-format
 msgid "failed to create helper: %s"
 msgstr "gagal membaca %s: %s"
 
-#: dnsmasq.c:1155
+#: dnsmasq.c:1221
 #, c-format
 msgid "setting capabilities failed: %s"
 msgstr ""
 
 # OK
-#: dnsmasq.c:1158
+#: dnsmasq.c:1224
 #, fuzzy, c-format
 msgid "failed to change user-id to %s: %s"
 msgstr "gagal memuat nama-nama dari %s: %s"
 
 # OK
-#: dnsmasq.c:1161
+#: dnsmasq.c:1227
 #, fuzzy, c-format
 msgid "failed to change group-id to %s: %s"
 msgstr "gagal memuat nama-nama dari %s: %s"
 
 # OK
-#: dnsmasq.c:1164
+#: dnsmasq.c:1230
 #, fuzzy, c-format
 msgid "failed to open pidfile %s: %s"
 msgstr "gagal membaca %s: %s"
 
 # OK
-#: dnsmasq.c:1167
+#: dnsmasq.c:1233
 #, fuzzy, c-format
 msgid "cannot open log %s: %s"
 msgstr "tidak bisa membuka %s:%s"
 
 # OK
-#: dnsmasq.c:1170
+#: dnsmasq.c:1236
 #, fuzzy, c-format
 msgid "failed to load Lua script: %s"
 msgstr "gagal memuat %S: %s"
 
-#: dnsmasq.c:1173
+#: dnsmasq.c:1239
 #, c-format
 msgid "TFTP directory %s inaccessible: %s"
 msgstr ""
 
 # OK
-#: dnsmasq.c:1176
+#: dnsmasq.c:1242
 #, fuzzy, c-format
 msgid "cannot create timestamp file %s: %s"
 msgstr "tidak dapat membuka atau membuat file lease: %s"
 
-#: dnsmasq.c:1197
-msgid "now checking DNSSEC signature timestamps"
-msgstr ""
-
-#: dnsmasq.c:1264
+#: dnsmasq.c:1326
 #, c-format
 msgid "script process killed by signal %d"
 msgstr ""
 
-#: dnsmasq.c:1268
+#: dnsmasq.c:1330
 #, c-format
 msgid "script process exited with status %d"
 msgstr ""
 
 # OK
-#: dnsmasq.c:1272
+#: dnsmasq.c:1334
 #, fuzzy, c-format
 msgid "failed to execute %s: %s"
 msgstr "gagal mengakses %s: %s"
 
-#: dnsmasq.c:1327
+#: dnsmasq.c:1374
+msgid "now checking DNSSEC signature timestamps"
+msgstr ""
+
+# OK
+#: dnsmasq.c:1409 dnssec.c:160 dnssec.c:206
+#, fuzzy, c-format
+msgid "failed to update mtime on %s: %s"
+msgstr "gagal membaca %s: %s"
+
+#: dnsmasq.c:1416
 msgid "exiting on receipt of SIGTERM"
 msgstr "keluar karena menerima SIGTERM"
 
 # OK
-#: dnsmasq.c:1355
+#: dnsmasq.c:1444
 #, fuzzy, c-format
 msgid "failed to access %s: %s"
 msgstr "gagal mengakses %s: %s"
 
 # OK
-#: dnsmasq.c:1385
+#: dnsmasq.c:1474
 #, c-format
 msgid "reading %s"
 msgstr "membaca %s"
 
 # OK
-#: dnsmasq.c:1396
+#: dnsmasq.c:1485
 #, fuzzy, c-format
 msgid "no servers found in %s, will retry"
 msgstr "tidak ditemukan direktif search di %s"
@@ -1781,266 +1865,287 @@ msgid "cannot create ICMP raw socket: %s."
 msgstr "tidak dapat membuat socket ICMP raw: %s"
 
 # OK
-#: dhcp.c:241 dhcp6.c:180
+#: dhcp.c:252 dhcp6.c:173
 #, fuzzy, c-format
 msgid "unknown interface %s in bridge-interface"
 msgstr "antarmuka tidak dikenal %s"
 
-#: dhcp.c:281
+#: dhcp.c:293
 #, c-format
 msgid "DHCP packet received on %s which has no address"
 msgstr ""
 
-#: dhcp.c:415
+#: dhcp.c:427
 #, c-format
 msgid "ARP-cache injection failed: %s"
 msgstr ""
 
+#: dhcp.c:470
+#, c-format
+msgid "Error sending DHCP packet to %s: %s"
+msgstr ""
+
 # OK
-#: dhcp.c:514
+#: dhcp.c:531
 #, c-format
 msgid "DHCP range %s -- %s is not consistent with netmask %s"
 msgstr "jangkauan DHCP %s -- %s tidak konsisten dengan netmask %s"
 
 # OK
-#: dhcp.c:815
+#: dhcp.c:854
 #, fuzzy, c-format
 msgid "bad line at %s line %d"
 msgstr "kesalahan nama pada %s baris %d"
 
-#: dhcp.c:858
+#: dhcp.c:897
 #, c-format
 msgid "ignoring %s line %d, duplicate name or IP address"
 msgstr ""
 
-#: dhcp.c:1002 rfc3315.c:2135
+#: dhcp.c:1041 rfc3315.c:2149
 #, c-format
 msgid "DHCP relay %s -> %s"
 msgstr ""
 
 # OK
-#: lease.c:61
+#: lease.c:98
+msgid "too many stored leases"
+msgstr "terlalu banyak lease yang disimpan"
+
+# OK
+#: lease.c:166
 #, fuzzy, c-format
 msgid "cannot open or create lease file %s: %s"
 msgstr "tidak dapat membuka atau membuat file lease: %s"
 
+#: lease.c:175
+#, c-format
+msgid "failed to parse lease database, invalid line: %s %s %s %s ..."
+msgstr ""
+
 # OK
-#: lease.c:134
-msgid "too many stored leases"
-msgstr "terlalu banyak lease yang disimpan"
+#: lease.c:180
+#, fuzzy, c-format
+msgid "failed to read lease file %s: %s"
+msgstr "gagal membaca %s: %s"
 
 # OK
-#: lease.c:165
+#: lease.c:196
 #, fuzzy, c-format
 msgid "cannot run lease-init script %s: %s"
 msgstr "tidak bisa membaca %s: %s"
 
-#: lease.c:171
+#: lease.c:202
 #, c-format
 msgid "lease-init script returned exit code %s"
 msgstr ""
 
 # OK
-#: lease.c:342
+#: lease.c:373
 #, fuzzy, c-format
 msgid "failed to write %s: %s (retry in %us)"
 msgstr "gagal membaca %s: %s"
 
-#: lease.c:906
+#: lease.c:937
 #, c-format
 msgid "Ignoring domain %s for DHCP host name %s"
 msgstr ""
 
 # OK
-#: rfc2131.c:344
+#: rfc2131.c:347
 #, c-format
 msgid "no address range available for DHCP request %s %s"
 msgstr "tidak ada alamat yang bisa dipakai untuk permintaan DHCP %s %s"
 
 # OK
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "with subnet selector"
 msgstr "dengan pemilih subnet"
 
 # OK
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "via"
 msgstr "lewat"
 
 # OK
-#: rfc2131.c:357
+#: rfc2131.c:360
 #, fuzzy, c-format
 msgid "%u available DHCP subnet: %s/%s"
 msgstr "tidak ada alamat yang bisa dipakai untuk permintaan DHCP %s %s"
 
-#: rfc2131.c:360 rfc3315.c:300
+#: rfc2131.c:363 rfc3315.c:306
 #, c-format
 msgid "%u available DHCP range: %s -- %s"
 msgstr ""
 
 # OK
-#: rfc2131.c:471
+#: rfc2131.c:474
 #, fuzzy, c-format
 msgid "%u vendor class: %s"
 msgstr "DBus error: %s"
 
 # OK
-#: rfc2131.c:473
+#: rfc2131.c:476
 #, fuzzy, c-format
 msgid "%u user class: %s"
 msgstr "DBus error: %s"
 
 # OK
-#: rfc2131.c:500
+#: rfc2131.c:510
 msgid "disabled"
 msgstr "di disable"
 
 # OK
-#: rfc2131.c:541 rfc2131.c:974 rfc2131.c:1380 rfc3315.c:603 rfc3315.c:856
-#: rfc3315.c:1135
+#: rfc2131.c:551 rfc2131.c:1006 rfc2131.c:1430 rfc3315.c:616 rfc3315.c:869
+#: rfc3315.c:1148
 msgid "ignored"
 msgstr "diabaikan"
 
 # OK
-#: rfc2131.c:556 rfc2131.c:1207 rfc3315.c:906
+#: rfc2131.c:566 rfc2131.c:1239 rfc3315.c:919
 msgid "address in use"
 msgstr "alamat telah digunakan"
 
 # OK
-#: rfc2131.c:570 rfc2131.c:1028
+#: rfc2131.c:580 rfc2131.c:1060
 msgid "no address available"
 msgstr "tak ada alamat yang tersedia"
 
 # OK
-#: rfc2131.c:577 rfc2131.c:1170
+#: rfc2131.c:587 rfc2131.c:1202
 msgid "wrong network"
 msgstr "jaringan yang salah"
 
 # OK
-#: rfc2131.c:592
+#: rfc2131.c:602
 msgid "no address configured"
 msgstr "tak ada alamat yang disetel"
 
 # OK
-#: rfc2131.c:598 rfc2131.c:1220
+#: rfc2131.c:608 rfc2131.c:1252
 msgid "no leases left"
 msgstr "tak ada lease yang tersisa"
 
-#: rfc2131.c:693 rfc3315.c:476
+#: rfc2131.c:703 rfc3315.c:482
 #, c-format
 msgid "%u client provides name: %s"
 msgstr ""
 
-#: rfc2131.c:798
+#: rfc2131.c:808
 msgid "PXE BIS not supported"
 msgstr ""
 
 # OK
-#: rfc2131.c:942 rfc3315.c:1229
+#: rfc2131.c:974 rfc3315.c:1242
 #, fuzzy, c-format
 msgid "disabling DHCP static address %s for %s"
 msgstr "men-disable alamat statik DHCP %s"
 
 # OK
-#: rfc2131.c:963
+#: rfc2131.c:995
 msgid "unknown lease"
 msgstr "lease tidak diketahui"
 
-#: rfc2131.c:997
+#: rfc2131.c:1029
 #, c-format
 msgid "not using configured address %s because it is leased to %s"
 msgstr ""
 
-#: rfc2131.c:1007
+#: rfc2131.c:1039
 #, c-format
 msgid "not using configured address %s because it is in use by the server or relay"
 msgstr ""
 
-#: rfc2131.c:1010
+#: rfc2131.c:1042
 #, c-format
 msgid "not using configured address %s because it was previously declined"
 msgstr ""
 
-#: rfc2131.c:1026 rfc2131.c:1213
+#: rfc2131.c:1058 rfc2131.c:1245
 msgid "no unique-id"
 msgstr ""
 
-#: rfc2131.c:1108
+#: rfc2131.c:1140
 msgid "wrong server-ID"
 msgstr ""
 
 # OK
-#: rfc2131.c:1127
+#: rfc2131.c:1159
 msgid "wrong address"
 msgstr "alamat salah"
 
 # OK
-#: rfc2131.c:1145 rfc3315.c:1002
+#: rfc2131.c:1177 rfc3315.c:1015
 msgid "lease not found"
 msgstr "lease tak ditemukan"
 
 # OK
-#: rfc2131.c:1178
+#: rfc2131.c:1210
 msgid "address not available"
 msgstr "alamat tak tersedia"
 
 # OK
-#: rfc2131.c:1189
+#: rfc2131.c:1221
 msgid "static lease available"
 msgstr "lease statik tak tersedia"
 
 # OK
-#: rfc2131.c:1193
+#: rfc2131.c:1225
 msgid "address reserved"
 msgstr "alamat telah dipesan"
 
-#: rfc2131.c:1201
+#: rfc2131.c:1233
 #, c-format
 msgid "abandoning lease to %s of %s"
 msgstr ""
 
-#: rfc2131.c:1707
+#: rfc2131.c:1757
 #, c-format
 msgid "%u bootfile name: %s"
 msgstr ""
 
 # OK
-#: rfc2131.c:1716
+#: rfc2131.c:1766
 #, fuzzy, c-format
 msgid "%u server name: %s"
 msgstr "DBus error: %s"
 
 # OK
-#: rfc2131.c:1724
+#: rfc2131.c:1774
 #, fuzzy, c-format
 msgid "%u next server: %s"
 msgstr "DBus error: %s"
 
-#: rfc2131.c:1727
+#: rfc2131.c:1777
 #, c-format
 msgid "%u broadcast response"
 msgstr ""
 
-#: rfc2131.c:1790
+#: rfc2131.c:1840
 #, c-format
 msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
 msgstr ""
 
-#: rfc2131.c:2031
+#: rfc2131.c:2131
 msgid "PXE menu too large"
 msgstr ""
 
 # OK
-#: rfc2131.c:2170 rfc3315.c:1502
+#: rfc2131.c:2270 rfc3315.c:1515
 #, fuzzy, c-format
 msgid "%u requested options: %s"
 msgstr "pilihan-pilihan saat kompilasi: %s"
 
-#: rfc2131.c:2487
+#: rfc2131.c:2587
 #, c-format
 msgid "cannot send RFC3925 option: too many options for enterprise number %d"
 msgstr ""
 
+#: rfc2131.c:2650
+#, c-format
+msgid "%u reply delay: %d"
+msgstr ""
+
 # OK
 #: netlink.c:77
 #, fuzzy, c-format
@@ -2048,7 +2153,7 @@ msgid "cannot create netlink socket: %s"
 msgstr "tidak bisa mem-bind netlink socket: %s"
 
 # OK
-#: netlink.c:348
+#: netlink.c:355
 #, fuzzy, c-format
 msgid "netlink returns error: %s"
 msgstr "DBus error: %s"
@@ -2069,68 +2174,68 @@ msgid "Disabling --%s option from D-Bus"
 msgstr ""
 
 # OK
-#: dbus.c:691
+#: dbus.c:690
 msgid "setting upstream servers from DBus"
 msgstr "menyetel server-server di atas dengan DBus"
 
 # OK
-#: dbus.c:738
+#: dbus.c:737
 msgid "could not register a DBus message handler"
 msgstr "tidak bisa mendaftar sebuah DBus message handler"
 
 # OK
-#: bpf.c:263
+#: bpf.c:265
 #, c-format
 msgid "cannot create DHCP BPF socket: %s"
 msgstr "tidak dapat membuat socket DHCP BPF: %s"
 
 # OK
-#: bpf.c:291
+#: bpf.c:293
 #, fuzzy, c-format
 msgid "DHCP request for unsupported hardware type (%d) received on %s"
 msgstr "permintaan DHCP untuk tipe hardware yang tidak didukung (%d) diterima pada %s"
 
 # OK
-#: bpf.c:376
+#: bpf.c:378
 #, fuzzy, c-format
 msgid "cannot create PF_ROUTE socket: %s"
 msgstr "tidak bisa membuat socket DHCP: %s"
 
-#: bpf.c:397
+#: bpf.c:399
 msgid "Unknown protocol version from route socket"
 msgstr ""
 
-#: helper.c:153
+#: helper.c:154
 msgid "lease() function missing in Lua script"
 msgstr ""
 
-#: tftp.c:309
+#: tftp.c:319
 msgid "unable to get free port for TFTP"
 msgstr ""
 
-#: tftp.c:325
+#: tftp.c:335
 #, c-format
 msgid "unsupported request from %s"
 msgstr ""
 
 # OK
-#: tftp.c:439
+#: tftp.c:483
 #, fuzzy, c-format
 msgid "file %s not found"
 msgstr "lease tak ditemukan"
 
-#: tftp.c:548
+#: tftp.c:592
 #, c-format
 msgid "error %d %s received from %s"
 msgstr ""
 
 # OK
-#: tftp.c:590
+#: tftp.c:634
 #, fuzzy, c-format
 msgid "failed sending %s to %s"
 msgstr "gagal membaca %s: %s"
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "sent %s to %s"
 msgstr ""
@@ -2146,7 +2251,7 @@ msgid "log failed: %s"
 msgstr ""
 
 # OK
-#: log.c:469
+#: log.c:471
 msgid "FAILED to start up"
 msgstr "GAGAL untuk memulai"
 
@@ -2156,19 +2261,19 @@ msgid "Conntrack connection mark retrieval failed: %s"
 msgstr ""
 
 # OK
-#: dhcp6.c:59
+#: dhcp6.c:52
 #, fuzzy, c-format
 msgid "cannot create DHCPv6 socket: %s"
 msgstr "tidak bisa membuat socket DHCP: %s"
 
 # OK
-#: dhcp6.c:80
+#: dhcp6.c:73
 #, fuzzy, c-format
 msgid "failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"
 msgstr "gagal menyetel SO_REUSEADDR pada socket DHCP: %s"
 
 # OK
-#: dhcp6.c:92
+#: dhcp6.c:85
 #, fuzzy, c-format
 msgid "failed to bind DHCPv6 server socket: %s"
 msgstr "gagal mem-bind socket server DHCP: %s"
@@ -2186,78 +2291,78 @@ msgid "no address range available for DHCPv6 request via %s"
 msgstr "tidak ada alamat yang bisa dipakai untuk permintaan DHCP %s %s"
 
 # OK
-#: rfc3315.c:297
+#: rfc3315.c:303
 #, fuzzy, c-format
 msgid "%u available DHCPv6 subnet: %s/%d"
 msgstr "tidak ada alamat yang bisa dipakai untuk permintaan DHCP %s %s"
 
 # OK
-#: rfc3315.c:380
+#: rfc3315.c:386
 #, fuzzy, c-format
 msgid "%u vendor class: %u"
 msgstr "DBus error: %s"
 
 # OK
-#: rfc3315.c:428
+#: rfc3315.c:434
 #, fuzzy, c-format
 msgid "%u client MAC address: %s"
 msgstr "tidak ada antarmuka dengan alamat %s"
 
 # OK
-#: rfc3315.c:660
+#: rfc3315.c:673
 #, fuzzy, c-format
 msgid "unknown prefix-class %d"
 msgstr "lease tidak diketahui"
 
 # OK
-#: rfc3315.c:803 rfc3315.c:898
+#: rfc3315.c:816 rfc3315.c:911
 #, fuzzy
 msgid "address unavailable"
 msgstr "alamat tak tersedia"
 
-#: rfc3315.c:815 rfc3315.c:946 rfc3315.c:1279
+#: rfc3315.c:828 rfc3315.c:959 rfc3315.c:1292
 msgid "success"
 msgstr ""
 
 # OK
-#: rfc3315.c:830 rfc3315.c:839 rfc3315.c:954 rfc3315.c:956
+#: rfc3315.c:843 rfc3315.c:852 rfc3315.c:967 rfc3315.c:969
 #, fuzzy
 msgid "no addresses available"
 msgstr "tak ada alamat yang tersedia"
 
-#: rfc3315.c:933
+#: rfc3315.c:946
 msgid "not on link"
 msgstr ""
 
-#: rfc3315.c:1006 rfc3315.c:1191 rfc3315.c:1268
+#: rfc3315.c:1019 rfc3315.c:1204 rfc3315.c:1281
 msgid "no binding found"
 msgstr ""
 
-#: rfc3315.c:1044
+#: rfc3315.c:1057
 msgid "deprecated"
 msgstr ""
 
 # OK
-#: rfc3315.c:1049
+#: rfc3315.c:1062
 #, fuzzy
 msgid "address invalid"
 msgstr "alamat telah digunakan"
 
-#: rfc3315.c:1096
+#: rfc3315.c:1109
 msgid "confirm failed"
 msgstr ""
 
 # OK
-#: rfc3315.c:1112
+#: rfc3315.c:1125
 #, fuzzy
 msgid "all addresses still on link"
 msgstr "kesalahan nama pada %s baris %d"
 
-#: rfc3315.c:1200
+#: rfc3315.c:1213
 msgid "release received"
 msgstr ""
 
-#: rfc3315.c:2126
+#: rfc3315.c:2140
 msgid "Cannot multicast to DHCPv6 server without correct interface"
 msgstr ""
 
@@ -2283,80 +2388,80 @@ msgid "duplicate IP address %s (%s) in dhcp-config directive"
 msgstr "alamat IP kembar %s (%s) dalam direktif dhcp-config"
 
 # OK
-#: dhcp-common.c:494
+#: dhcp-common.c:491
 #, fuzzy, c-format
 msgid "failed to set SO_BINDTODEVICE on DHCP socket: %s"
 msgstr "gagal menyetel SO_REUSEADDR pada socket DHCP: %s"
 
-#: dhcp-common.c:615
+#: dhcp-common.c:612
 #, c-format
 msgid "Known DHCP options:\n"
 msgstr ""
 
-#: dhcp-common.c:626
+#: dhcp-common.c:623
 #, c-format
 msgid "Known DHCPv6 options:\n"
 msgstr ""
 
-#: dhcp-common.c:823
+#: dhcp-common.c:820
 msgid ", prefix deprecated"
 msgstr ""
 
-#: dhcp-common.c:826
+#: dhcp-common.c:823
 #, c-format
 msgid ", lease time "
 msgstr ""
 
-#: dhcp-common.c:868
+#: dhcp-common.c:865
 #, c-format
 msgid "%s stateless on %s%.0s%.0s%s"
 msgstr ""
 
 # OK
-#: dhcp-common.c:870
+#: dhcp-common.c:867
 #, fuzzy, c-format
 msgid "%s, static leases only on %.0s%s%s%.0s"
 msgstr "DHCP, lease static pada %.0s%s, waktu lease %s"
 
-#: dhcp-common.c:872
+#: dhcp-common.c:869
 #, c-format
 msgid "%s, proxy on subnet %.0s%s%.0s%.0s"
 msgstr ""
 
 # OK
-#: dhcp-common.c:873
+#: dhcp-common.c:870
 #, fuzzy, c-format
 msgid "%s, IP range %s -- %s%s%.0s"
 msgstr "DHCP, jangkaun IP %s -- %s, waktu lease %s"
 
-#: dhcp-common.c:886
+#: dhcp-common.c:883
 #, c-format
 msgid "DHCPv4-derived IPv6 names on %s%s"
 msgstr ""
 
 # OK
-#: dhcp-common.c:889
+#: dhcp-common.c:886
 #, fuzzy, c-format
 msgid "router advertisement on %s%s"
 msgstr "DHCP, lease static pada %.0s%s, waktu lease %s"
 
-#: dhcp-common.c:900
+#: dhcp-common.c:897
 #, c-format
 msgid "DHCP relay from %s to %s via %s"
 msgstr ""
 
-#: dhcp-common.c:902
+#: dhcp-common.c:899
 #, c-format
 msgid "DHCP relay from %s to %s"
 msgstr ""
 
 # OK
-#: radv.c:109
+#: radv.c:110
 #, fuzzy, c-format
 msgid "cannot create ICMPv6 socket: %s"
 msgstr "tidak bisa membuat socket DHCP: %s"
 
-#: auth.c:448
+#: auth.c:449
 #, c-format
 msgid "ignoring zone transfer request from %s"
 msgstr ""
@@ -2374,98 +2479,99 @@ msgid "failed to create IPset control socket: %s"
 msgstr "gagal membuat socket: %s "
 
 # OK
-#: dnssec.c:449 dnssec.c:493
+#: ipset.c:233
 #, fuzzy, c-format
-msgid "failed to update mtime on %s: %s"
+msgid "failed to update ipset %s: %s"
 msgstr "gagal membaca %s: %s"
 
+#: dnssec.c:208
+msgid "system time considered valid, now checking DNSSEC signature timestamps."
+msgstr ""
+
 #: blockdata.c:58
 #, c-format
 msgid "DNSSEC memory in use %u, max %u, allocated %u"
 msgstr ""
 
-#: tables.c:80
-msgid "error: fill_addr missused"
-msgstr ""
-
 # OK
-#: tables.c:109
+#: tables.c:61
 #, fuzzy, c-format
 msgid "failed to access pf devices: %s"
 msgstr "gagal mengakses %s: %s"
 
 # OK
-#: tables.c:123
+#: tables.c:74
 #, fuzzy, c-format
 msgid "warning: no opened pf devices %s"
 msgstr "menggunakan alamat lokal saja untuk %s %s"
 
 # OK
-#: tables.c:131
+#: tables.c:82
 #, fuzzy, c-format
 msgid "error: cannot use table name %s"
 msgstr "tidak bisa mendapatkan host-name: %s"
 
-#: tables.c:139
+#: tables.c:90
 #, c-format
 msgid "error: cannot strlcpy table name %s"
 msgstr ""
 
-#: tables.c:145
-#, c-format
-msgid "warning: pfr_add_tables: %s(%d)"
-msgstr ""
+# OK
+#: tables.c:101
+#, fuzzy, c-format
+msgid "IPset: error:%s"
+msgstr "DBus error: %s"
 
-#: tables.c:151
+#: tables.c:108
 msgid "info: table created"
 msgstr ""
 
-#: tables.c:162
+#: tables.c:134
 #, c-format
 msgid "warning: DIOCR%sADDRS: %s"
 msgstr ""
 
 # OK
-#: tables.c:166
+#: tables.c:138
 #, fuzzy, c-format
 msgid "%d addresses %s"
 msgstr "membaca %s - %d alamat"
 
 # OK
-#: inotify.c:59
+#: inotify.c:62
 #, fuzzy, c-format
 msgid "cannot access path %s: %s"
 msgstr "tidak bisa membaca %s: %s"
 
 # OK
-#: inotify.c:92
+#: inotify.c:95
 #, fuzzy, c-format
 msgid "failed to create inotify: %s"
 msgstr "gagal membaca %s: %s"
 
-#: inotify.c:105
+#: inotify.c:111
 #, c-format
 msgid "too many symlinks following %s"
 msgstr ""
 
-#: inotify.c:121
+#: inotify.c:127
 #, c-format
 msgid "directory %s for resolv-file is missing, cannot poll"
 msgstr ""
 
 # OK
-#: inotify.c:125 inotify.c:162
+#: inotify.c:131 inotify.c:168
 #, fuzzy, c-format
 msgid "failed to create inotify for %s: %s"
 msgstr "gagal membuat socket: %s "
 
 # OK
-#: inotify.c:147
+#: inotify.c:153
 #, fuzzy, c-format
 msgid "bad dynamic directory %s: %s"
 msgstr "tidak bisa membaca %s: %s"
 
-#: inotify.c:247
+#: inotify.c:257
 #, c-format
 msgid "inotify, new or changed file %s"
 msgstr ""
index 172fbbe..aafc9b6 100644 (file)
--- a/po/it.po
+++ b/po/it.po
@@ -7,7 +7,7 @@ msgstr ""
 "Project-Id-Version: dnsmasq 2.32\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2009-06-18 12:24+0100\n"
-"PO-Revision-Date: 2006-05-22 11:09+0100\n"
+"PO-Revision-Date: 2017-07-17 18:30+0100\n"
 "Last-Translator: Simon Kelley <simon@thekelleys.org.uk>\n"
 "Language-Team: Italian <tp@lists.linux.it>\n"
 "Language: it\n"
@@ -16,1482 +16,1556 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cache.c:523
+#: cache.c:518
 msgid "Internal error in cache."
 msgstr ""
 
-#: cache.c:941
+#: cache.c:928
 #, c-format
 msgid "failed to load names from %s: %s"
 msgstr ""
 
-#: cache.c:967 dhcp.c:828
+#: cache.c:954 dhcp.c:867
 #, c-format
 msgid "bad address at %s line %d"
 msgstr ""
 
-#: cache.c:1018 dhcp.c:844
+#: cache.c:1007 dhcp.c:883
 #, c-format
 msgid "bad name at %s line %d"
 msgstr ""
 
-#: cache.c:1027 dhcp.c:919
+#: cache.c:1016 dhcp.c:958
 #, c-format
 msgid "read %s - %d addresses"
 msgstr ""
 
-#: cache.c:1135
+#: cache.c:1129
 msgid "cleared cache"
 msgstr ""
 
-#: cache.c:1164
+#: cache.c:1158
 #, c-format
 msgid "No IPv4 address found for %s"
 msgstr ""
 
-#: cache.c:1242
+#: cache.c:1237
 #, c-format
 msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
 msgstr ""
 
-#: cache.c:1266
+#: cache.c:1261
 #, c-format
 msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
 msgstr ""
 
-#: cache.c:1421
+#: cache.c:1418
 #, c-format
 msgid "time %lu"
 msgstr ""
 
-#: cache.c:1422
+#: cache.c:1419
 #, c-format
 msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
 msgstr ""
 
-#: cache.c:1424
+#: cache.c:1421
 #, c-format
 msgid "queries forwarded %u, queries answered locally %u"
 msgstr ""
 
-#: cache.c:1427
+#: cache.c:1424
 #, c-format
 msgid "queries for authoritative zones %u"
 msgstr ""
 
-#: cache.c:1453
+#: cache.c:1450
 #, c-format
 msgid "server %s#%d: queries sent %u, retried or failed %u"
 msgstr ""
 
-#: util.c:45
+#: util.c:47
 #, c-format
 msgid "failed to seed the random number generator: %s"
 msgstr ""
 
-#: util.c:205
+#: util.c:224
 msgid "failed to allocate memory"
 msgstr ""
 
-#: util.c:250 option.c:601
+#: util.c:281 option.c:619
 msgid "could not get memory"
 msgstr ""
 
-#: util.c:260
+#: util.c:291
 #, c-format
 msgid "cannot create pipe: %s"
 msgstr ""
 
-#: util.c:268
+#: util.c:299
 #, c-format
 msgid "failed to allocate %d bytes"
 msgstr ""
 
-#: util.c:437
+#: util.c:468
 #, c-format
 msgid "infinite"
 msgstr ""
 
-#: option.c:332
+#: option.c:344
 msgid "Specify local address(es) to listen on."
 msgstr ""
 
-#: option.c:333
+#: option.c:345
 msgid "Return ipaddr for all hosts in specified domains."
 msgstr ""
 
-#: option.c:334
+#: option.c:346
 msgid "Fake reverse lookups for RFC1918 private address ranges."
 msgstr ""
 
-#: option.c:335
+#: option.c:347
 msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
 msgstr ""
 
-#: option.c:336
+#: option.c:348
 #, c-format
 msgid "Specify the size of the cache in entries (defaults to %s)."
 msgstr ""
 
-#: option.c:337
+#: option.c:349
 #, c-format
 msgid "Specify configuration file (defaults to %s)."
 msgstr ""
 
-#: option.c:338
+#: option.c:350
 msgid "Do NOT fork into the background: run in debug mode."
 msgstr ""
 
-#: option.c:339
+#: option.c:351
 msgid "Do NOT forward queries with no domain part."
 msgstr ""
 
-#: option.c:340
+#: option.c:352
 msgid "Return self-pointing MX records for local hosts."
 msgstr ""
 
-#: option.c:341
+#: option.c:353
 msgid "Expand simple names in /etc/hosts with domain-suffix."
 msgstr ""
 
-#: option.c:342
+#: option.c:354
 msgid "Don't forward spurious DNS requests from Windows hosts."
 msgstr ""
 
-#: option.c:343
+#: option.c:355
 msgid "Enable DHCP in the range given with lease duration."
 msgstr ""
 
-#: option.c:344
+#: option.c:356
 #, c-format
 msgid "Change to this group after startup (defaults to %s)."
 msgstr ""
 
-#: option.c:345
+#: option.c:357
 msgid "Set address or hostname for a specified machine."
 msgstr ""
 
-#: option.c:346
+#: option.c:358
 msgid "Read DHCP host specs from file."
 msgstr ""
 
-#: option.c:347
+#: option.c:359
 msgid "Read DHCP option specs from file."
 msgstr ""
 
-#: option.c:348
+#: option.c:360
 msgid "Read DHCP host specs from a directory."
 msgstr ""
 
-#: option.c:349
+#: option.c:361
 msgid "Read DHCP options from a directory."
 msgstr ""
 
-#: option.c:350
+#: option.c:362
 msgid "Evaluate conditional tag expression."
 msgstr ""
 
-#: option.c:351
+#: option.c:363
 #, c-format
 msgid "Do NOT load %s file."
 msgstr ""
 
-#: option.c:352
+#: option.c:364
 #, c-format
 msgid "Specify a hosts file to be read in addition to %s."
 msgstr ""
 
-#: option.c:353
+#: option.c:365
 msgid "Read hosts files from a directory."
 msgstr ""
 
-#: option.c:354
+#: option.c:366
 msgid "Specify interface(s) to listen on."
 msgstr ""
 
-#: option.c:355
+#: option.c:367
 msgid "Specify interface(s) NOT to listen on."
 msgstr ""
 
-#: option.c:356
+#: option.c:368
 msgid "Map DHCP user class to tag."
 msgstr ""
 
-#: option.c:357
+#: option.c:369
 msgid "Map RFC3046 circuit-id to tag."
 msgstr ""
 
-#: option.c:358
+#: option.c:370
 msgid "Map RFC3046 remote-id to tag."
 msgstr ""
 
-#: option.c:359
+#: option.c:371
 msgid "Map RFC3993 subscriber-id to tag."
 msgstr ""
 
-#: option.c:360
+#: option.c:372
 msgid "Don't do DHCP for hosts with tag set."
 msgstr ""
 
-#: option.c:361
+#: option.c:373
 msgid "Force broadcast replies for hosts with tag set."
 msgstr ""
 
-#: option.c:362
+#: option.c:374
 msgid "Do NOT fork into the background, do NOT run in debug mode."
 msgstr ""
 
-#: option.c:363
+#: option.c:375
 msgid "Assume we are the only DHCP server on the local network."
 msgstr ""
 
-#: option.c:364
+#: option.c:376
 #, c-format
 msgid "Specify where to store DHCP leases (defaults to %s)."
 msgstr ""
 
-#: option.c:365
+#: option.c:377
 msgid "Return MX records for local hosts."
 msgstr ""
 
-#: option.c:366
+#: option.c:378
 msgid "Specify an MX record."
 msgstr ""
 
-#: option.c:367
+#: option.c:379
 msgid "Specify BOOTP options to DHCP server."
 msgstr ""
 
-#: option.c:368
+#: option.c:380
 #, c-format
 msgid "Do NOT poll %s file, reload only on SIGHUP."
 msgstr ""
 
-#: option.c:369
+#: option.c:381
 msgid "Do NOT cache failed search results."
 msgstr ""
 
-#: option.c:370
+#: option.c:382
 #, c-format
 msgid "Use nameservers strictly in the order given in %s."
 msgstr ""
 
-#: option.c:371
+#: option.c:383
 msgid "Specify options to be sent to DHCP clients."
 msgstr ""
 
-#: option.c:372
+#: option.c:384
 msgid "DHCP option sent even if the client does not request it."
 msgstr ""
 
-#: option.c:373
+#: option.c:385
 msgid "Specify port to listen for DNS requests on (defaults to 53)."
 msgstr ""
 
-#: option.c:374
+#: option.c:386
 #, c-format
 msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
 msgstr ""
 
-#: option.c:375
+#: option.c:387
 msgid "Log DNS queries."
 msgstr ""
 
-#: option.c:376
+#: option.c:388
 msgid "Force the originating port for upstream DNS queries."
 msgstr ""
 
-#: option.c:377
+#: option.c:389
 msgid "Do NOT read resolv.conf."
 msgstr ""
 
-#: option.c:378
+#: option.c:390
 #, c-format
 msgid "Specify path to resolv.conf (defaults to %s)."
 msgstr ""
 
-#: option.c:379
+#: option.c:391
 msgid "Specify path to file with server= options"
 msgstr ""
 
-#: option.c:380
+#: option.c:392
 msgid "Specify address(es) of upstream servers with optional domains."
 msgstr ""
 
-#: option.c:381
+#: option.c:393
 msgid "Specify address of upstream servers for reverse address queries"
 msgstr ""
 
-#: option.c:382
+#: option.c:394
 msgid "Never forward queries to specified domains."
 msgstr ""
 
-#: option.c:383
+#: option.c:395
 msgid "Specify the domain to be assigned in DHCP leases."
 msgstr ""
 
-#: option.c:384
+#: option.c:396
 msgid "Specify default target in an MX record."
 msgstr ""
 
-#: option.c:385
+#: option.c:397
 msgid "Specify time-to-live in seconds for replies from /etc/hosts."
 msgstr ""
 
-#: option.c:386
+#: option.c:398
 msgid "Specify time-to-live in seconds for negative caching."
 msgstr ""
 
-#: option.c:387
+#: option.c:399
 msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
 msgstr ""
 
-#: option.c:388
+#: option.c:400
 msgid "Specify time-to-live ceiling for cache."
 msgstr ""
 
-#: option.c:389
+#: option.c:401
 msgid "Specify time-to-live floor for cache."
 msgstr ""
 
-#: option.c:390
+#: option.c:402
 #, c-format
 msgid "Change to this user after startup. (defaults to %s)."
 msgstr ""
 
-#: option.c:391
+#: option.c:403
 msgid "Map DHCP vendor class to tag."
 msgstr ""
 
-#: option.c:392
+#: option.c:404
 msgid "Display dnsmasq version and copyright information."
 msgstr ""
 
-#: option.c:393
+#: option.c:405
 msgid "Translate IPv4 addresses from upstream servers."
 msgstr ""
 
-#: option.c:394
+#: option.c:406
 msgid "Specify a SRV record."
 msgstr ""
 
-#: option.c:395
-msgid "Display this message. Use --help dhcp for known DHCP options."
+#: option.c:407
+msgid "Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."
 msgstr ""
 
-#: option.c:396
+#: option.c:408
 #, c-format
 msgid "Specify path of PID file (defaults to %s)."
 msgstr ""
 
-#: option.c:397
+#: option.c:409
 #, c-format
 msgid "Specify maximum number of DHCP leases (defaults to %s)."
 msgstr ""
 
-#: option.c:398
+#: option.c:410
 msgid "Answer DNS queries based on the interface a query was sent to."
 msgstr ""
 
-#: option.c:399
+#: option.c:411
 msgid "Specify TXT DNS record."
 msgstr ""
 
-#: option.c:400
+#: option.c:412
 msgid "Specify PTR DNS record."
 msgstr ""
 
-#: option.c:401
+#: option.c:413
 msgid "Give DNS name to IPv4 address of interface."
 msgstr ""
 
-#: option.c:402
+#: option.c:414
 msgid "Bind only to interfaces in use."
 msgstr ""
 
-#: option.c:403
+#: option.c:415
 #, c-format
 msgid "Read DHCP static host information from %s."
 msgstr ""
 
-#: option.c:404
+#: option.c:416
 msgid "Enable the DBus interface for setting upstream servers, etc."
 msgstr ""
 
-#: option.c:405
+#: option.c:417
 msgid "Do not provide DHCP on this interface, only provide DNS."
 msgstr ""
 
-#: option.c:406
+#: option.c:418
 msgid "Enable dynamic address allocation for bootp."
 msgstr ""
 
-#: option.c:407
+#: option.c:419
 msgid "Map MAC address (with wildcards) to option set."
 msgstr ""
 
-#: option.c:408
+#: option.c:420
 msgid "Treat DHCP requests on aliases as arriving from interface."
 msgstr ""
 
-#: option.c:409
+#: option.c:421
 msgid "Disable ICMP echo address checking in the DHCP server."
 msgstr ""
 
-#: option.c:410
+#: option.c:422
 msgid "Shell script to run on DHCP lease creation and destruction."
 msgstr ""
 
-#: option.c:411
+#: option.c:423
 msgid "Lua script to run on DHCP lease creation and destruction."
 msgstr ""
 
-#: option.c:412
+#: option.c:424
 msgid "Run lease-change scripts as this user."
 msgstr ""
 
-#: option.c:413
+#: option.c:425
+msgid "Call dhcp-script with changes to local ARP table."
+msgstr ""
+
+#: option.c:426
 msgid "Read configuration from all the files in this directory."
 msgstr ""
 
-#: option.c:414
+#: option.c:427
 msgid "Log to this syslog facility or file. (defaults to DAEMON)"
 msgstr ""
 
-#: option.c:415
+#: option.c:428
 msgid "Do not use leasefile."
 msgstr ""
 
-#: option.c:416
+#: option.c:429
 #, c-format
 msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
 msgstr ""
 
-#: option.c:417
+#: option.c:430
 #, c-format
 msgid "Clear DNS cache when reloading %s."
 msgstr ""
 
-#: option.c:418
+#: option.c:431
 msgid "Ignore hostnames provided by DHCP clients."
 msgstr ""
 
-#: option.c:419
+#: option.c:432
 msgid "Do NOT reuse filename and server fields for extra DHCP options."
 msgstr ""
 
-#: option.c:420
+#: option.c:433
 msgid "Enable integrated read-only TFTP server."
 msgstr ""
 
-#: option.c:421
+#: option.c:434
 msgid "Export files by TFTP only from the specified subtree."
 msgstr ""
 
-#: option.c:422
-msgid "Add client IP address to tftp-root."
+#: option.c:435
+msgid "Add client IP or hardware address to tftp-root."
 msgstr ""
 
-#: option.c:423
+#: option.c:436
 msgid "Allow access only to files owned by the user running dnsmasq."
 msgstr ""
 
-#: option.c:424
+#: option.c:437
 msgid "Do not terminate the service if TFTP directories are inaccessible."
 msgstr ""
 
-#: option.c:425
+#: option.c:438
 #, c-format
-msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgid "Maximum number of concurrent TFTP transfers (defaults to %s)."
 msgstr ""
 
-#: option.c:426
+#: option.c:439
+msgid "Maximum MTU to use for TFTP transfers."
+msgstr ""
+
+#: option.c:440
 msgid "Disable the TFTP blocksize extension."
 msgstr ""
 
-#: option.c:427
+#: option.c:441
 msgid "Convert TFTP filenames to lowercase"
 msgstr ""
 
-#: option.c:428
+#: option.c:442
 msgid "Ephemeral port range for use by TFTP transfers."
 msgstr ""
 
-#: option.c:429
+#: option.c:443
 msgid "Extra logging for DHCP."
 msgstr ""
 
-#: option.c:430
+#: option.c:444
 msgid "Enable async. logging; optionally set queue length."
 msgstr ""
 
-#: option.c:431
+#: option.c:445
 msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
 msgstr ""
 
-#: option.c:432
+#: option.c:446
 msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
 msgstr ""
 
-#: option.c:433
+#: option.c:447
 msgid "Inhibit DNS-rebind protection on this domain."
 msgstr ""
 
-#: option.c:434
+#: option.c:448
 msgid "Always perform DNS queries to all servers."
 msgstr ""
 
-#: option.c:435
+#: option.c:449
 msgid "Set tag if client includes matching option in request."
 msgstr ""
 
-#: option.c:436
+#: option.c:450
 msgid "Use alternative ports for DHCP."
 msgstr ""
 
-#: option.c:437
+#: option.c:451
 msgid "Specify NAPTR DNS record."
 msgstr ""
 
-#: option.c:438
+#: option.c:452
 msgid "Specify lowest port available for DNS query transmission."
 msgstr ""
 
-#: option.c:439
+#: option.c:453
+msgid "Specify highest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:454
 msgid "Use only fully qualified domain names for DHCP clients."
 msgstr ""
 
-#: option.c:440
+#: option.c:455
 msgid "Generate hostnames based on MAC address for nameless clients."
 msgstr ""
 
-#: option.c:441
+#: option.c:456
 msgid "Use these DHCP relays as full proxies."
 msgstr ""
 
-#: option.c:442
+#: option.c:457
 msgid "Relay DHCP requests to a remote server"
 msgstr ""
 
-#: option.c:443
+#: option.c:458
 msgid "Specify alias name for LOCAL DNS name."
 msgstr ""
 
-#: option.c:444
+#: option.c:459
 msgid "Prompt to send to PXE clients."
 msgstr ""
 
-#: option.c:445
+#: option.c:460
 msgid "Boot service for PXE menu."
 msgstr ""
 
-#: option.c:446
+#: option.c:461
 msgid "Check configuration syntax."
 msgstr ""
 
-#: option.c:447
+#: option.c:462
 msgid "Add requestor's MAC address to forwarded DNS queries."
 msgstr ""
 
-#: option.c:448
-msgid "Add requestor's IP subnet to forwarded DNS queries."
+#: option.c:463
+msgid "Add specified IP subnet to forwarded DNS queries."
 msgstr ""
 
-#: option.c:449
+#: option.c:464
+msgid "Add client identification to forwarded DNS queries."
+msgstr ""
+
+#: option.c:465
 msgid "Proxy DNSSEC validation results from upstream nameservers."
 msgstr ""
 
-#: option.c:450
+#: option.c:466
 msgid "Attempt to allocate sequential IP addresses to DHCP clients."
 msgstr ""
 
-#: option.c:451
+#: option.c:467
 msgid "Copy connection-track mark from queries to upstream connections."
 msgstr ""
 
-#: option.c:452
+#: option.c:468
 msgid "Allow DHCP clients to do their own DDNS updates."
 msgstr ""
 
-#: option.c:453
+#: option.c:469
 msgid "Send router-advertisements for interfaces doing DHCPv6"
 msgstr ""
 
-#: option.c:454
+#: option.c:470
 msgid "Specify DUID_EN-type DHCPv6 server DUID"
 msgstr ""
 
-#: option.c:455
+#: option.c:471
 msgid "Specify host (A/AAAA and PTR) records"
 msgstr ""
 
-#: option.c:456
+#: option.c:472
 msgid "Specify arbitrary DNS resource record"
 msgstr ""
 
-#: option.c:457
+#: option.c:473
 msgid "Bind to interfaces in use - check for new interfaces"
 msgstr ""
 
-#: option.c:458
+#: option.c:474
 msgid "Export local names to global DNS"
 msgstr ""
 
-#: option.c:459
+#: option.c:475
 msgid "Domain to export to global DNS"
 msgstr ""
 
-#: option.c:460
+#: option.c:476
 msgid "Set TTL for authoritative replies"
 msgstr ""
 
-#: option.c:461
-msgid "Set authoritive zone information"
+#: option.c:477
+msgid "Set authoritative zone information"
 msgstr ""
 
-#: option.c:462
+#: option.c:478
 msgid "Secondary authoritative nameservers for forward domains"
 msgstr ""
 
-#: option.c:463
+#: option.c:479
 msgid "Peers which are allowed to do zone transfer"
 msgstr ""
 
-#: option.c:464
+#: option.c:480
 msgid "Specify ipsets to which matching domains should be added"
 msgstr ""
 
-#: option.c:465
+#: option.c:481
 msgid "Specify a domain and address range for synthesised names"
 msgstr ""
 
-#: option.c:466
+#: option.c:482
 msgid "Activate DNSSEC validation"
 msgstr ""
 
-#: option.c:467
+#: option.c:483
 msgid "Specify trust anchor key digest."
 msgstr ""
 
-#: option.c:468
+#: option.c:484
 msgid "Disable upstream checking for DNSSEC debugging."
 msgstr ""
 
-#: option.c:469
+#: option.c:485
 msgid "Ensure answers without DNSSEC are in unsigned zones."
 msgstr ""
 
-#: option.c:470
+#: option.c:486
 msgid "Don't check DNSSEC signature timestamps until first cache-reload"
 msgstr ""
 
-#: option.c:471
+#: option.c:487
 msgid "Timestamp file to verify system clock for DNSSEC"
 msgstr ""
 
-#: option.c:473
+#: option.c:489
 msgid "Specify DHCPv6 prefix class"
 msgstr ""
 
-#: option.c:475
-msgid "Set priority, resend-interval and router-lifetime"
+#: option.c:491
+msgid "Set MTU, priority, resend-interval and router-lifetime"
 msgstr ""
 
-#: option.c:476
+#: option.c:492
 msgid "Do not log routine DHCP."
 msgstr ""
 
-#: option.c:477
+#: option.c:493
 msgid "Do not log routine DHCPv6."
 msgstr ""
 
-#: option.c:478
+#: option.c:494
 msgid "Do not log RA."
 msgstr ""
 
-#: option.c:479
-msgid "Accept queries only from directly-connected networks"
+#: option.c:495
+msgid "Accept queries only from directly-connected networks."
 msgstr ""
 
-#: option.c:480
-msgid "Detect and remove DNS forwarding loops"
+#: option.c:496
+msgid "Detect and remove DNS forwarding loops."
 msgstr ""
 
-#: option.c:481
+#: option.c:497
 msgid "Ignore DNS responses containing ipaddr."
 msgstr ""
 
-#: option.c:683
+#: option.c:498
+msgid "Set TTL in DNS responses with DHCP-derived addresses."
+msgstr ""
+
+#: option.c:499
+msgid "Delay DHCP replies for at least number of seconds."
+msgstr ""
+
+#: option.c:703
 #, c-format
 msgid ""
 "Usage: dnsmasq [options]\n"
 "\n"
 msgstr ""
 
-#: option.c:685
+#: option.c:705
 #, c-format
 msgid "Use short options only on the command line.\n"
 msgstr ""
 
-#: option.c:687
+#: option.c:707
 #, c-format
 msgid "Valid options are:\n"
 msgstr ""
 
-#: option.c:744 option.c:748
+#: option.c:754 option.c:868
+msgid "bad address"
+msgstr ""
+
+#: option.c:779 option.c:783
 msgid "bad port"
 msgstr ""
 
-#: option.c:775 option.c:807
+#: option.c:797 option.c:826 option.c:861
 msgid "interface binding not supported"
 msgstr ""
 
-#: option.c:784 option.c:3575
-msgid "bad interface name"
+#: option.c:821 option.c:856
+msgid "interface can only be specified once"
 msgstr ""
 
-#: option.c:814
-msgid "bad address"
+#: option.c:835 option.c:3809
+msgid "bad interface name"
 msgstr ""
 
-#: option.c:996
+#: option.c:1062
 msgid "unsupported encapsulation for IPv6 option"
 msgstr ""
 
-#: option.c:1010
+#: option.c:1076
 msgid "bad dhcp-option"
 msgstr ""
 
-#: option.c:1078
+#: option.c:1144
 msgid "bad IP address"
 msgstr ""
 
-#: option.c:1081 option.c:1219 option.c:2893
+#: option.c:1147 option.c:1286 option.c:3079
 msgid "bad IPv6 address"
 msgstr ""
 
-#: option.c:1246 option.c:1340
+#: option.c:1240
+msgid "bad IPv4 address"
+msgstr ""
+
+#: option.c:1313 option.c:1407
 msgid "bad domain in dhcp-option"
 msgstr ""
 
-#: option.c:1378
+#: option.c:1445
 msgid "dhcp-option too long"
 msgstr ""
 
-#: option.c:1385
+#: option.c:1452
 msgid "illegal dhcp-match"
 msgstr ""
 
-#: option.c:1447
+#: option.c:1514
 msgid "illegal repeated flag"
 msgstr ""
 
-#: option.c:1455
+#: option.c:1522
 msgid "illegal repeated keyword"
 msgstr ""
 
-#: option.c:1520 option.c:4191
+#: option.c:1593 option.c:4443
 #, c-format
 msgid "cannot access directory %s: %s"
 msgstr ""
 
-#: option.c:1566 tftp.c:493
+#: option.c:1639 tftp.c:537
 #, c-format
 msgid "cannot access %s: %s"
 msgstr ""
 
-#: option.c:1618
+#: option.c:1727
 msgid "setting log facility is not possible under Android"
 msgstr ""
 
-#: option.c:1627
+#: option.c:1736
 msgid "bad log facility"
 msgstr ""
 
-#: option.c:1680
+#: option.c:1789
 msgid "bad MX preference"
 msgstr ""
 
-#: option.c:1685
+#: option.c:1794
 msgid "bad MX name"
 msgstr ""
 
-#: option.c:1699
+#: option.c:1808
 msgid "bad MX target"
 msgstr ""
 
-#: option.c:1711
+#: option.c:1820
 msgid "cannot run scripts under uClinux"
 msgstr ""
 
-#: option.c:1713
+#: option.c:1822
 msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
 msgstr ""
 
-#: option.c:1717
+#: option.c:1826
 msgid "recompile with HAVE_LUASCRIPT defined to enable Lua scripts"
 msgstr ""
 
-#: option.c:1973 option.c:2018 option.c:2074
+#: option.c:2095 option.c:2106 option.c:2143 option.c:2199 option.c:2482
 msgid "bad prefix"
 msgstr ""
 
-#: option.c:2355
+#: option.c:2504
 msgid "recompile with HAVE_IPSET defined to enable ipset directives"
 msgstr ""
 
-#: option.c:2548
+#: option.c:2713
 msgid "bad port range"
 msgstr ""
 
-#: option.c:2564
+#: option.c:2739
 msgid "bad bridge-interface"
 msgstr ""
 
-#: option.c:2624
+#: option.c:2807
 msgid "only one tag allowed"
 msgstr ""
 
-#: option.c:2644 option.c:2656 option.c:2764 option.c:2805
+#: option.c:2827 option.c:2839 option.c:2948 option.c:2953 option.c:2992
 msgid "bad dhcp-range"
 msgstr ""
 
-#: option.c:2671
+#: option.c:2854
 msgid "inconsistent DHCP range"
 msgstr ""
 
-#: option.c:2732
+#: option.c:2916
 msgid "prefix length must be exactly 64 for RA subnets"
 msgstr ""
 
-#: option.c:2734
+#: option.c:2918
 msgid "prefix length must be exactly 64 for subnet constructors"
 msgstr ""
 
-#: option.c:2738
+#: option.c:2922
 msgid "prefix length must be at least 64"
 msgstr ""
 
-#: option.c:2741
+#: option.c:2925
 msgid "inconsistent DHCPv6 range"
 msgstr ""
 
-#: option.c:2752
+#: option.c:2936
 msgid "prefix must be zero with \"constructor:\" argument"
 msgstr ""
 
-#: option.c:2863 option.c:2911
+#: option.c:3049 option.c:3097
 msgid "bad hex constant"
 msgstr ""
 
-#: option.c:2885
+#: option.c:3071
 msgid "cannot match tags in --dhcp-host"
 msgstr ""
 
-#: option.c:2933
+#: option.c:3119
 #, c-format
 msgid "duplicate dhcp-host IP address %s"
 msgstr ""
 
-#: option.c:2991
+#: option.c:3177
 msgid "bad DHCP host name"
 msgstr ""
 
-#: option.c:3073
+#: option.c:3259
 msgid "bad tag-if"
 msgstr ""
 
-#: option.c:3397 option.c:3791
+#: option.c:3616 option.c:4039
 msgid "invalid port number"
 msgstr ""
 
-#: option.c:3459
+#: option.c:3678
 msgid "bad dhcp-proxy address"
 msgstr ""
 
-#: option.c:3485
+#: option.c:3704
 msgid "Bad dhcp-relay"
 msgstr ""
 
-#: option.c:3511
+#: option.c:3745
 msgid "bad RA-params"
 msgstr ""
 
-#: option.c:3520
+#: option.c:3754
 msgid "bad DUID"
 msgstr ""
 
-#: option.c:3562
+#: option.c:3796
 msgid "invalid alias range"
 msgstr ""
 
-#: option.c:3616
+#: option.c:3850 option.c:3862
 msgid "bad CNAME"
 msgstr ""
 
-#: option.c:3621
+#: option.c:3866
 msgid "duplicate CNAME"
 msgstr ""
 
-#: option.c:3641
+#: option.c:3889
 msgid "bad PTR record"
 msgstr ""
 
-#: option.c:3672
+#: option.c:3920
 msgid "bad NAPTR record"
 msgstr ""
 
-#: option.c:3706
+#: option.c:3954
 msgid "bad RR record"
 msgstr ""
 
-#: option.c:3736
+#: option.c:3984
 msgid "bad TXT record"
 msgstr ""
 
-#: option.c:3777
+#: option.c:4025
 msgid "bad SRV record"
 msgstr ""
 
-#: option.c:3784
+#: option.c:4032
 msgid "bad SRV target"
 msgstr ""
 
-#: option.c:3798
+#: option.c:4046
 msgid "invalid priority"
 msgstr ""
 
-#: option.c:3805
+#: option.c:4049
 msgid "invalid weight"
 msgstr ""
 
-#: option.c:3829
+#: option.c:4073
 msgid "Bad host-record"
 msgstr ""
 
-#: option.c:3846
+#: option.c:4097
 msgid "Bad name in host-record"
 msgstr ""
 
-#: option.c:3911
+#: option.c:4162
 msgid "bad trust anchor"
 msgstr ""
 
-#: option.c:3925
+#: option.c:4176
 msgid "bad HEX in trust anchor"
 msgstr ""
 
-#: option.c:3935
+#: option.c:4186
 msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"
 msgstr ""
 
-#: option.c:3994
+#: option.c:4246
 msgid "missing \""
 msgstr ""
 
-#: option.c:4051
+#: option.c:4303
 msgid "bad option"
 msgstr ""
 
-#: option.c:4053
+#: option.c:4305
 msgid "extraneous parameter"
 msgstr ""
 
-#: option.c:4055
+#: option.c:4307
 msgid "missing parameter"
 msgstr ""
 
-#: option.c:4057
+#: option.c:4309
 msgid "illegal option"
 msgstr ""
 
-#: option.c:4064
+#: option.c:4316
 msgid "error"
 msgstr ""
 
-#: option.c:4066
+#: option.c:4318
 #, c-format
 msgid " at line %d of %s"
 msgstr ""
 
-#: option.c:4081 option.c:4328 option.c:4364
+#: option.c:4333 option.c:4580 option.c:4616
 #, c-format
 msgid "read %s"
 msgstr ""
 
-#: option.c:4144 option.c:4267 tftp.c:667
+#: option.c:4396 option.c:4519 tftp.c:715
 #, c-format
 msgid "cannot read %s: %s"
 msgstr ""
 
-#: option.c:4430
+#: option.c:4688
 msgid "junk found in command line"
 msgstr ""
 
-#: option.c:4465
+#: option.c:4729
 #, c-format
 msgid "Dnsmasq version %s  %s\n"
 msgstr ""
 
-#: option.c:4466
+#: option.c:4730
 #, c-format
 msgid ""
 "Compile time options: %s\n"
 "\n"
 msgstr ""
 
-#: option.c:4467
+#: option.c:4731
 #, c-format
 msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
 msgstr ""
 
-#: option.c:4468
+#: option.c:4732
 #, c-format
 msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
 msgstr ""
 
-#: option.c:4469
+#: option.c:4733
 #, c-format
 msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
 msgstr ""
 
-#: option.c:4480
+#: option.c:4744
 msgid "try --help"
 msgstr ""
 
-#: option.c:4482
+#: option.c:4746
 msgid "try -w"
 msgstr ""
 
-#: option.c:4484
+#: option.c:4748
 #, c-format
 msgid "bad command line options: %s"
 msgstr ""
 
-#: option.c:4541
+#: option.c:4818
+#, c-format
+msgid "CNAME loop involving %s"
+msgstr ""
+
+#: option.c:4854
 #, c-format
 msgid "cannot get host-name: %s"
 msgstr ""
 
-#: option.c:4569
+#: option.c:4882
 msgid "only one resolv.conf file allowed in no-poll mode."
 msgstr ""
 
-#: option.c:4579
+#: option.c:4892
 msgid "must have exactly one resolv.conf to read domain from."
 msgstr ""
 
-#: option.c:4582 network.c:1507 dhcp.c:777
+#: option.c:4895 network.c:1623 dhcp.c:816
 #, c-format
 msgid "failed to read %s: %s"
 msgstr ""
 
-#: option.c:4599
+#: option.c:4912
 #, c-format
 msgid "no search directive found in %s"
 msgstr ""
 
-#: option.c:4620
+#: option.c:4933
 msgid "there must be a default domain when --dhcp-fqdn is set"
 msgstr ""
 
-#: option.c:4629
+#: option.c:4942
 msgid "syntax check OK"
 msgstr ""
 
-#: forward.c:111
+#: forward.c:102
 #, c-format
 msgid "failed to send packet: %s"
 msgstr ""
 
-#: forward.c:591
+#: forward.c:598
 msgid "discarding DNS reply: subnet option mismatch"
 msgstr ""
 
-#: forward.c:614
+#: forward.c:652
 #, c-format
 msgid "nameserver %s refused to do a recursive query"
 msgstr ""
 
-#: forward.c:646
+#: forward.c:684
 #, c-format
 msgid "possible DNS-rebind attack detected: %s"
 msgstr ""
 
-#: forward.c:1209 forward.c:1815
+#: forward.c:870
+#, c-format
+msgid "reducing DNS packet size for nameserver %s to %d"
+msgstr ""
+
+#: forward.c:1266 forward.c:1704
 msgid "Ignoring query from non-local network"
 msgstr ""
 
-#: forward.c:2286
+#: forward.c:2184
 #, c-format
 msgid "Maximum number of concurrent DNS queries reached (max: %d)"
 msgstr ""
 
-#: network.c:715
+#: network.c:720
 #, c-format
 msgid "failed to create listening socket for %s: %s"
 msgstr ""
 
-#: network.c:1021
+#: network.c:1031
 #, c-format
 msgid "LOUD WARNING: listening on %s may accept requests via interfaces other than %s"
 msgstr ""
 
-#: network.c:1028
+#: network.c:1038
 msgid "LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"
 msgstr ""
 
-#: network.c:1037
+#: network.c:1047
+#, c-format
+msgid "warning: using interface %s instead"
+msgstr ""
+
+#: network.c:1056
 #, c-format
 msgid "warning: no addresses found for interface %s"
 msgstr ""
 
-#: network.c:1095
+#: network.c:1114
 #, c-format
 msgid "interface %s failed to join DHCPv6 multicast group: %s"
 msgstr ""
 
-#: network.c:1289
+#: network.c:1119
+msgid "try increasing /proc/sys/net/core/optmem_max"
+msgstr ""
+
+#: network.c:1337
 #, c-format
 msgid "failed to bind server socket for %s: %s"
 msgstr ""
 
-#: network.c:1445
+#: network.c:1528
 #, c-format
 msgid "ignoring nameserver %s - local interface"
 msgstr ""
 
-#: network.c:1456
+#: network.c:1539
 #, c-format
 msgid "ignoring nameserver %s - cannot make/bind socket: %s"
 msgstr ""
 
-#: network.c:1469
+#: network.c:1559
+msgid "(no DNSSEC)"
+msgstr ""
+
+#: network.c:1562
 msgid "unqualified"
 msgstr ""
 
-#: network.c:1469
+#: network.c:1562
 msgid "names"
 msgstr ""
 
-#: network.c:1471
+#: network.c:1564
 msgid "default"
 msgstr ""
 
-#: network.c:1473
+#: network.c:1566
 msgid "domain"
 msgstr ""
 
-#: network.c:1476
+#: network.c:1572
 #, c-format
 msgid "using local addresses only for %s %s"
 msgstr ""
 
-#: network.c:1478
+#: network.c:1575
 #, c-format
 msgid "using standard nameservers for %s %s"
 msgstr ""
 
-#: network.c:1480
+#: network.c:1577
 #, c-format
-msgid "using nameserver %s#%d for %s %s"
+msgid "using nameserver %s#%d for %s %s %s"
 msgstr ""
 
-#: network.c:1484
+#: network.c:1581
 #, c-format
 msgid "NOT using nameserver %s#%d - query loop detected"
 msgstr ""
 
-#: network.c:1487
+#: network.c:1584
 #, c-format
 msgid "using nameserver %s#%d(via %s)"
 msgstr ""
 
-#: network.c:1489
+#: network.c:1586
 #, c-format
 msgid "using nameserver %s#%d"
 msgstr ""
 
-#: dnsmasq.c:163
+#: network.c:1591
+#, c-format
+msgid "using %d more local addresses"
+msgstr ""
+
+#: network.c:1593
+#, c-format
+msgid "using %d more nameservers"
+msgstr ""
+
+#: dnsmasq.c:171
 msgid "dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"
 msgstr ""
 
-#: dnsmasq.c:170
-msgid "no trust anchors provided for DNSSEC"
+#: dnsmasq.c:186
+msgid "no root trust anchor provided for DNSSEC"
 msgstr ""
 
-#: dnsmasq.c:173
+#: dnsmasq.c:189
 msgid "cannot reduce cache size from default when DNSSEC enabled"
 msgstr ""
 
-#: dnsmasq.c:175
+#: dnsmasq.c:191
 msgid "DNSSEC not available: set HAVE_DNSSEC in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:181
+#: dnsmasq.c:197
 msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:186
+#: dnsmasq.c:202
 msgid "cannot use --conntrack AND --query-port"
 msgstr ""
 
-#: dnsmasq.c:189
+#: dnsmasq.c:205
 msgid "conntrack support not available: set HAVE_CONNTRACK in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:194
-msgid "asychronous logging is not available under Solaris"
+#: dnsmasq.c:210
+msgid "asynchronous logging is not available under Solaris"
 msgstr ""
 
-#: dnsmasq.c:199
-msgid "asychronous logging is not available under Android"
+#: dnsmasq.c:215
+msgid "asynchronous logging is not available under Android"
 msgstr ""
 
-#: dnsmasq.c:204
+#: dnsmasq.c:220
 msgid "authoritative DNS not available: set HAVE_AUTH in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:209
+#: dnsmasq.c:225
 msgid "loop detection not available: set HAVE_LOOP in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:217
+#: dnsmasq.c:229
+msgid "max_port cannot be smaller than min_port"
+msgstr ""
+
+#: dnsmasq.c:236
 msgid "zone serial must be configured in --auth-soa"
 msgstr ""
 
-#: dnsmasq.c:235
+#: dnsmasq.c:254
 msgid "dhcp-range constructor not available on this platform"
 msgstr ""
 
-#: dnsmasq.c:278
+#: dnsmasq.c:300
 msgid "cannot set --bind-interfaces and --bind-dynamic"
 msgstr ""
 
-#: dnsmasq.c:281
+#: dnsmasq.c:303
 #, c-format
 msgid "failed to find list of interfaces: %s"
 msgstr ""
 
-#: dnsmasq.c:290
+#: dnsmasq.c:312
 #, c-format
 msgid "unknown interface %s"
 msgstr ""
 
-#: dnsmasq.c:354 dnsmasq.c:997
+#: dnsmasq.c:377 dnsmasq.c:1054
 #, c-format
 msgid "DBus error: %s"
 msgstr ""
 
-#: dnsmasq.c:357
+#: dnsmasq.c:380
 msgid "DBus not available: set HAVE_DBUS in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:385
+#: dnsmasq.c:410
 #, c-format
 msgid "unknown user or group: %s"
 msgstr ""
 
-#: dnsmasq.c:440
+#: dnsmasq.c:465
 #, c-format
 msgid "cannot chdir to filesystem root: %s"
 msgstr ""
 
-#: dnsmasq.c:692
+#: dnsmasq.c:730
 #, c-format
 msgid "started, version %s DNS disabled"
 msgstr ""
 
-#: dnsmasq.c:694
+#: dnsmasq.c:734
 #, c-format
 msgid "started, version %s cachesize %d"
 msgstr ""
 
-#: dnsmasq.c:696
+#: dnsmasq.c:736
 #, c-format
 msgid "started, version %s cache disabled"
 msgstr ""
 
-#: dnsmasq.c:698
+#: dnsmasq.c:739
+msgid "DNS service limited to local subnets"
+msgstr ""
+
+#: dnsmasq.c:742
 #, c-format
 msgid "compile time options: %s"
 msgstr ""
 
-#: dnsmasq.c:704
+#: dnsmasq.c:751
 msgid "DBus support enabled: connected to system bus"
 msgstr ""
 
-#: dnsmasq.c:706
+#: dnsmasq.c:753
 msgid "DBus support enabled: bus connection pending"
 msgstr ""
 
-#: dnsmasq.c:711
-msgid "DNS service limited to local subnets"
-msgstr ""
-
-#: dnsmasq.c:727
+#: dnsmasq.c:771
 msgid "DNSSEC validation enabled"
 msgstr ""
 
-#: dnsmasq.c:730
-msgid "DNSSEC signature timestamps not checked until first cache reload"
+#: dnsmasq.c:775
+msgid "DNSSEC signature timestamps not checked until receipt of SIGINT"
 msgstr ""
 
-#: dnsmasq.c:733
+#: dnsmasq.c:778
 msgid "DNSSEC signature timestamps not checked until system time valid"
 msgstr ""
 
-#: dnsmasq.c:738
+#: dnsmasq.c:783
 #, c-format
 msgid "warning: failed to change owner of %s: %s"
 msgstr ""
 
-#: dnsmasq.c:742
+#: dnsmasq.c:787
 msgid "setting --bind-interfaces option because of OS limitations"
 msgstr ""
 
-#: dnsmasq.c:752
+#: dnsmasq.c:799
 #, c-format
 msgid "warning: interface %s does not currently exist"
 msgstr ""
 
-#: dnsmasq.c:757
+#: dnsmasq.c:804
 msgid "warning: ignoring resolv-file flag because no-resolv is set"
 msgstr ""
 
-#: dnsmasq.c:760
+#: dnsmasq.c:807
 msgid "warning: no upstream servers configured"
 msgstr ""
 
-#: dnsmasq.c:764
+#: dnsmasq.c:811
 #, c-format
 msgid "asynchronous logging enabled, queue limit is %d messages"
 msgstr ""
 
-#: dnsmasq.c:785
+#: dnsmasq.c:832
 msgid "IPv6 router advertisement enabled"
 msgstr ""
 
-#: dnsmasq.c:790
+#: dnsmasq.c:837
 #, c-format
 msgid "DHCP, sockets bound exclusively to interface %s"
 msgstr ""
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "root is "
 msgstr ""
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "enabled"
 msgstr ""
 
-#: dnsmasq.c:806
+#: dnsmasq.c:853
 msgid "secure mode"
 msgstr ""
 
-#: dnsmasq.c:809
+#: dnsmasq.c:856
 #, c-format
 msgid "warning: %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:813
+#: dnsmasq.c:860
 #, c-format
 msgid "warning: TFTP directory %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:839
+#: dnsmasq.c:886
 #, c-format
 msgid "restricting maximum simultaneous TFTP transfers to %d"
 msgstr ""
 
-#: dnsmasq.c:999
+#: dnsmasq.c:1056
 msgid "connected to system DBus"
 msgstr ""
 
-#: dnsmasq.c:1149
+#: dnsmasq.c:1215
 #, c-format
 msgid "cannot fork into background: %s"
 msgstr ""
 
-#: dnsmasq.c:1152
+#: dnsmasq.c:1218
 #, c-format
 msgid "failed to create helper: %s"
 msgstr ""
 
-#: dnsmasq.c:1155
+#: dnsmasq.c:1221
 #, c-format
 msgid "setting capabilities failed: %s"
 msgstr ""
 
-#: dnsmasq.c:1158
+#: dnsmasq.c:1224
 #, c-format
 msgid "failed to change user-id to %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1161
+#: dnsmasq.c:1227
 #, c-format
 msgid "failed to change group-id to %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1164
+#: dnsmasq.c:1230
 #, c-format
 msgid "failed to open pidfile %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1167
+#: dnsmasq.c:1233
 #, c-format
 msgid "cannot open log %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1170
+#: dnsmasq.c:1236
 #, c-format
 msgid "failed to load Lua script: %s"
 msgstr ""
 
-#: dnsmasq.c:1173
+#: dnsmasq.c:1239
 #, c-format
 msgid "TFTP directory %s inaccessible: %s"
 msgstr ""
 
-#: dnsmasq.c:1176
+#: dnsmasq.c:1242
 #, c-format
 msgid "cannot create timestamp file %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1197
-msgid "now checking DNSSEC signature timestamps"
-msgstr ""
-
-#: dnsmasq.c:1264
+#: dnsmasq.c:1326
 #, c-format
 msgid "script process killed by signal %d"
 msgstr ""
 
-#: dnsmasq.c:1268
+#: dnsmasq.c:1330
 #, c-format
 msgid "script process exited with status %d"
 msgstr ""
 
-#: dnsmasq.c:1272
+#: dnsmasq.c:1334
 #, c-format
 msgid "failed to execute %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1327
+#: dnsmasq.c:1374
+msgid "now checking DNSSEC signature timestamps"
+msgstr ""
+
+#: dnsmasq.c:1409 dnssec.c:160 dnssec.c:206
+#, c-format
+msgid "failed to update mtime on %s: %s"
+msgstr ""
+
+#: dnsmasq.c:1416
 msgid "exiting on receipt of SIGTERM"
 msgstr ""
 
-#: dnsmasq.c:1355
+#: dnsmasq.c:1444
 #, c-format
 msgid "failed to access %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1385
+#: dnsmasq.c:1474
 #, c-format
 msgid "reading %s"
 msgstr ""
 
-#: dnsmasq.c:1396
+#: dnsmasq.c:1485
 #, c-format
 msgid "no servers found in %s, will retry"
 msgstr ""
@@ -1521,243 +1595,263 @@ msgstr ""
 msgid "cannot create ICMP raw socket: %s."
 msgstr ""
 
-#: dhcp.c:241 dhcp6.c:180
+#: dhcp.c:252 dhcp6.c:173
 #, c-format
 msgid "unknown interface %s in bridge-interface"
 msgstr ""
 
-#: dhcp.c:281
+#: dhcp.c:293
 #, c-format
 msgid "DHCP packet received on %s which has no address"
 msgstr ""
 
-#: dhcp.c:415
+#: dhcp.c:427
 #, c-format
 msgid "ARP-cache injection failed: %s"
 msgstr ""
 
-#: dhcp.c:514
+#: dhcp.c:470
+#, c-format
+msgid "Error sending DHCP packet to %s: %s"
+msgstr ""
+
+#: dhcp.c:531
 #, c-format
 msgid "DHCP range %s -- %s is not consistent with netmask %s"
 msgstr ""
 
-#: dhcp.c:815
+#: dhcp.c:854
 #, c-format
 msgid "bad line at %s line %d"
 msgstr ""
 
-#: dhcp.c:858
+#: dhcp.c:897
 #, c-format
 msgid "ignoring %s line %d, duplicate name or IP address"
 msgstr ""
 
-#: dhcp.c:1002 rfc3315.c:2135
+#: dhcp.c:1041 rfc3315.c:2149
 #, c-format
 msgid "DHCP relay %s -> %s"
 msgstr ""
 
-#: lease.c:61
+#: lease.c:98
+msgid "too many stored leases"
+msgstr ""
+
+#: lease.c:166
 #, c-format
 msgid "cannot open or create lease file %s: %s"
 msgstr ""
 
-#: lease.c:134
-msgid "too many stored leases"
+#: lease.c:175
+#, c-format
+msgid "failed to parse lease database, invalid line: %s %s %s %s ..."
 msgstr ""
 
-#: lease.c:165
+#: lease.c:180
+#, c-format
+msgid "failed to read lease file %s: %s"
+msgstr ""
+
+#: lease.c:196
 #, c-format
 msgid "cannot run lease-init script %s: %s"
 msgstr ""
 
-#: lease.c:171
+#: lease.c:202
 #, c-format
 msgid "lease-init script returned exit code %s"
 msgstr ""
 
-#: lease.c:342
+#: lease.c:373
 #, c-format
 msgid "failed to write %s: %s (retry in %us)"
 msgstr ""
 
-#: lease.c:906
+#: lease.c:937
 #, c-format
 msgid "Ignoring domain %s for DHCP host name %s"
 msgstr ""
 
-#: rfc2131.c:344
+#: rfc2131.c:347
 #, c-format
 msgid "no address range available for DHCP request %s %s"
 msgstr ""
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "with subnet selector"
 msgstr ""
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "via"
 msgstr ""
 
-#: rfc2131.c:357
+#: rfc2131.c:360
 #, c-format
 msgid "%u available DHCP subnet: %s/%s"
 msgstr ""
 
-#: rfc2131.c:360 rfc3315.c:300
+#: rfc2131.c:363 rfc3315.c:306
 #, c-format
 msgid "%u available DHCP range: %s -- %s"
 msgstr ""
 
-#: rfc2131.c:471
+#: rfc2131.c:474
 #, c-format
 msgid "%u vendor class: %s"
 msgstr ""
 
-#: rfc2131.c:473
+#: rfc2131.c:476
 #, c-format
 msgid "%u user class: %s"
 msgstr ""
 
-#: rfc2131.c:500
+#: rfc2131.c:510
 msgid "disabled"
 msgstr ""
 
-#: rfc2131.c:541 rfc2131.c:974 rfc2131.c:1380 rfc3315.c:603 rfc3315.c:856
-#: rfc3315.c:1135
+#: rfc2131.c:551 rfc2131.c:1006 rfc2131.c:1430 rfc3315.c:616 rfc3315.c:869
+#: rfc3315.c:1148
 msgid "ignored"
 msgstr ""
 
-#: rfc2131.c:556 rfc2131.c:1207 rfc3315.c:906
+#: rfc2131.c:566 rfc2131.c:1239 rfc3315.c:919
 msgid "address in use"
 msgstr ""
 
-#: rfc2131.c:570 rfc2131.c:1028
+#: rfc2131.c:580 rfc2131.c:1060
 msgid "no address available"
 msgstr ""
 
-#: rfc2131.c:577 rfc2131.c:1170
+#: rfc2131.c:587 rfc2131.c:1202
 msgid "wrong network"
 msgstr ""
 
-#: rfc2131.c:592
+#: rfc2131.c:602
 msgid "no address configured"
 msgstr ""
 
-#: rfc2131.c:598 rfc2131.c:1220
+#: rfc2131.c:608 rfc2131.c:1252
 msgid "no leases left"
 msgstr ""
 
-#: rfc2131.c:693 rfc3315.c:476
+#: rfc2131.c:703 rfc3315.c:482
 #, c-format
 msgid "%u client provides name: %s"
 msgstr ""
 
-#: rfc2131.c:798
+#: rfc2131.c:808
 msgid "PXE BIS not supported"
 msgstr ""
 
-#: rfc2131.c:942 rfc3315.c:1229
+#: rfc2131.c:974 rfc3315.c:1242
 #, c-format
 msgid "disabling DHCP static address %s for %s"
 msgstr ""
 
-#: rfc2131.c:963
+#: rfc2131.c:995
 msgid "unknown lease"
 msgstr ""
 
-#: rfc2131.c:997
+#: rfc2131.c:1029
 #, c-format
 msgid "not using configured address %s because it is leased to %s"
 msgstr ""
 
-#: rfc2131.c:1007
+#: rfc2131.c:1039
 #, c-format
 msgid "not using configured address %s because it is in use by the server or relay"
 msgstr ""
 
-#: rfc2131.c:1010
+#: rfc2131.c:1042
 #, c-format
 msgid "not using configured address %s because it was previously declined"
 msgstr ""
 
-#: rfc2131.c:1026 rfc2131.c:1213
+#: rfc2131.c:1058 rfc2131.c:1245
 msgid "no unique-id"
 msgstr ""
 
-#: rfc2131.c:1108
+#: rfc2131.c:1140
 msgid "wrong server-ID"
 msgstr ""
 
-#: rfc2131.c:1127
+#: rfc2131.c:1159
 msgid "wrong address"
 msgstr ""
 
-#: rfc2131.c:1145 rfc3315.c:1002
+#: rfc2131.c:1177 rfc3315.c:1015
 msgid "lease not found"
 msgstr ""
 
-#: rfc2131.c:1178
+#: rfc2131.c:1210
 msgid "address not available"
 msgstr ""
 
-#: rfc2131.c:1189
+#: rfc2131.c:1221
 msgid "static lease available"
 msgstr ""
 
-#: rfc2131.c:1193
+#: rfc2131.c:1225
 msgid "address reserved"
 msgstr ""
 
-#: rfc2131.c:1201
+#: rfc2131.c:1233
 #, c-format
 msgid "abandoning lease to %s of %s"
 msgstr ""
 
-#: rfc2131.c:1707
+#: rfc2131.c:1757
 #, c-format
 msgid "%u bootfile name: %s"
 msgstr ""
 
-#: rfc2131.c:1716
+#: rfc2131.c:1766
 #, c-format
 msgid "%u server name: %s"
 msgstr ""
 
-#: rfc2131.c:1724
+#: rfc2131.c:1774
 #, c-format
 msgid "%u next server: %s"
 msgstr ""
 
-#: rfc2131.c:1727
+#: rfc2131.c:1777
 #, c-format
 msgid "%u broadcast response"
 msgstr ""
 
-#: rfc2131.c:1790
+#: rfc2131.c:1840
 #, c-format
 msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
 msgstr ""
 
-#: rfc2131.c:2031
+#: rfc2131.c:2131
 msgid "PXE menu too large"
 msgstr ""
 
-#: rfc2131.c:2170 rfc3315.c:1502
+#: rfc2131.c:2270 rfc3315.c:1515
 #, c-format
 msgid "%u requested options: %s"
 msgstr ""
 
-#: rfc2131.c:2487
+#: rfc2131.c:2587
 #, c-format
 msgid "cannot send RFC3925 option: too many options for enterprise number %d"
 msgstr ""
 
+#: rfc2131.c:2650
+#, c-format
+msgid "%u reply delay: %d"
+msgstr ""
+
 #: netlink.c:77
 #, c-format
 msgid "cannot create netlink socket: %s"
 msgstr ""
 
-#: netlink.c:348
+#: netlink.c:355
 #, c-format
 msgid "netlink returns error: %s"
 msgstr ""
@@ -1776,62 +1870,62 @@ msgstr ""
 msgid "Disabling --%s option from D-Bus"
 msgstr ""
 
-#: dbus.c:691
+#: dbus.c:690
 msgid "setting upstream servers from DBus"
 msgstr ""
 
-#: dbus.c:738
+#: dbus.c:737
 msgid "could not register a DBus message handler"
 msgstr ""
 
-#: bpf.c:263
+#: bpf.c:265
 #, c-format
 msgid "cannot create DHCP BPF socket: %s"
 msgstr ""
 
-#: bpf.c:291
+#: bpf.c:293
 #, c-format
 msgid "DHCP request for unsupported hardware type (%d) received on %s"
 msgstr ""
 
-#: bpf.c:376
+#: bpf.c:378
 #, c-format
 msgid "cannot create PF_ROUTE socket: %s"
 msgstr ""
 
-#: bpf.c:397
+#: bpf.c:399
 msgid "Unknown protocol version from route socket"
 msgstr ""
 
-#: helper.c:153
+#: helper.c:154
 msgid "lease() function missing in Lua script"
 msgstr ""
 
-#: tftp.c:309
+#: tftp.c:319
 msgid "unable to get free port for TFTP"
 msgstr ""
 
-#: tftp.c:325
+#: tftp.c:335
 #, c-format
 msgid "unsupported request from %s"
 msgstr ""
 
-#: tftp.c:439
+#: tftp.c:483
 #, c-format
 msgid "file %s not found"
 msgstr ""
 
-#: tftp.c:548
+#: tftp.c:592
 #, c-format
 msgid "error %d %s received from %s"
 msgstr ""
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "failed sending %s to %s"
 msgstr ""
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "sent %s to %s"
 msgstr ""
@@ -1846,7 +1940,7 @@ msgstr ""
 msgid "log failed: %s"
 msgstr ""
 
-#: log.c:469
+#: log.c:471
 msgid "FAILED to start up"
 msgstr ""
 
@@ -1855,17 +1949,17 @@ msgstr ""
 msgid "Conntrack connection mark retrieval failed: %s"
 msgstr ""
 
-#: dhcp6.c:59
+#: dhcp6.c:52
 #, c-format
 msgid "cannot create DHCPv6 socket: %s"
 msgstr ""
 
-#: dhcp6.c:80
+#: dhcp6.c:73
 #, c-format
 msgid "failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"
 msgstr ""
 
-#: dhcp6.c:92
+#: dhcp6.c:85
 #, c-format
 msgid "failed to bind DHCPv6 server socket: %s"
 msgstr ""
@@ -1880,67 +1974,67 @@ msgstr ""
 msgid "no address range available for DHCPv6 request via %s"
 msgstr ""
 
-#: rfc3315.c:297
+#: rfc3315.c:303
 #, c-format
 msgid "%u available DHCPv6 subnet: %s/%d"
 msgstr ""
 
-#: rfc3315.c:380
+#: rfc3315.c:386
 #, c-format
 msgid "%u vendor class: %u"
 msgstr ""
 
-#: rfc3315.c:428
+#: rfc3315.c:434
 #, c-format
 msgid "%u client MAC address: %s"
 msgstr ""
 
-#: rfc3315.c:660
+#: rfc3315.c:673
 #, c-format
 msgid "unknown prefix-class %d"
 msgstr ""
 
-#: rfc3315.c:803 rfc3315.c:898
+#: rfc3315.c:816 rfc3315.c:911
 msgid "address unavailable"
 msgstr ""
 
-#: rfc3315.c:815 rfc3315.c:946 rfc3315.c:1279
+#: rfc3315.c:828 rfc3315.c:959 rfc3315.c:1292
 msgid "success"
 msgstr ""
 
-#: rfc3315.c:830 rfc3315.c:839 rfc3315.c:954 rfc3315.c:956
+#: rfc3315.c:843 rfc3315.c:852 rfc3315.c:967 rfc3315.c:969
 msgid "no addresses available"
 msgstr ""
 
-#: rfc3315.c:933
+#: rfc3315.c:946
 msgid "not on link"
 msgstr ""
 
-#: rfc3315.c:1006 rfc3315.c:1191 rfc3315.c:1268
+#: rfc3315.c:1019 rfc3315.c:1204 rfc3315.c:1281
 msgid "no binding found"
 msgstr ""
 
-#: rfc3315.c:1044
+#: rfc3315.c:1057
 msgid "deprecated"
 msgstr ""
 
-#: rfc3315.c:1049
+#: rfc3315.c:1062
 msgid "address invalid"
 msgstr ""
 
-#: rfc3315.c:1096
+#: rfc3315.c:1109
 msgid "confirm failed"
 msgstr ""
 
-#: rfc3315.c:1112
+#: rfc3315.c:1125
 msgid "all addresses still on link"
 msgstr ""
 
-#: rfc3315.c:1200
+#: rfc3315.c:1213
 msgid "release received"
 msgstr ""
 
-#: rfc3315.c:2126
+#: rfc3315.c:2140
 msgid "Cannot multicast to DHCPv6 server without correct interface"
 msgstr ""
 
@@ -1964,76 +2058,76 @@ msgstr ""
 msgid "duplicate IP address %s (%s) in dhcp-config directive"
 msgstr ""
 
-#: dhcp-common.c:494
+#: dhcp-common.c:491
 #, c-format
 msgid "failed to set SO_BINDTODEVICE on DHCP socket: %s"
 msgstr ""
 
-#: dhcp-common.c:615
+#: dhcp-common.c:612
 #, c-format
 msgid "Known DHCP options:\n"
 msgstr ""
 
-#: dhcp-common.c:626
+#: dhcp-common.c:623
 #, c-format
 msgid "Known DHCPv6 options:\n"
 msgstr ""
 
-#: dhcp-common.c:823
+#: dhcp-common.c:820
 msgid ", prefix deprecated"
 msgstr ""
 
-#: dhcp-common.c:826
+#: dhcp-common.c:823
 #, c-format
 msgid ", lease time "
 msgstr ""
 
-#: dhcp-common.c:868
+#: dhcp-common.c:865
 #, c-format
 msgid "%s stateless on %s%.0s%.0s%s"
 msgstr ""
 
-#: dhcp-common.c:870
+#: dhcp-common.c:867
 #, c-format
 msgid "%s, static leases only on %.0s%s%s%.0s"
 msgstr ""
 
-#: dhcp-common.c:872
+#: dhcp-common.c:869
 #, c-format
 msgid "%s, proxy on subnet %.0s%s%.0s%.0s"
 msgstr ""
 
-#: dhcp-common.c:873
+#: dhcp-common.c:870
 #, c-format
 msgid "%s, IP range %s -- %s%s%.0s"
 msgstr ""
 
-#: dhcp-common.c:886
+#: dhcp-common.c:883
 #, c-format
 msgid "DHCPv4-derived IPv6 names on %s%s"
 msgstr ""
 
-#: dhcp-common.c:889
+#: dhcp-common.c:886
 #, c-format
 msgid "router advertisement on %s%s"
 msgstr ""
 
-#: dhcp-common.c:900
+#: dhcp-common.c:897
 #, c-format
 msgid "DHCP relay from %s to %s via %s"
 msgstr ""
 
-#: dhcp-common.c:902
+#: dhcp-common.c:899
 #, c-format
 msgid "DHCP relay from %s to %s"
 msgstr ""
 
-#: radv.c:109
+#: radv.c:110
 #, c-format
 msgid "cannot create ICMPv6 socket: %s"
 msgstr ""
 
-#: auth.c:448
+#: auth.c:449
 #, c-format
 msgid "ignoring zone transfer request from %s"
 msgstr ""
@@ -2048,9 +2142,13 @@ msgstr ""
 msgid "failed to create IPset control socket: %s"
 msgstr ""
 
-#: dnssec.c:449 dnssec.c:493
+#: ipset.c:233
 #, c-format
-msgid "failed to update mtime on %s: %s"
+msgid "failed to update ipset %s: %s"
+msgstr ""
+
+#: dnssec.c:208
+msgid "system time considered valid, now checking DNSSEC signature timestamps."
 msgstr ""
 
 #: blockdata.c:58
@@ -2058,80 +2156,76 @@ msgstr ""
 msgid "DNSSEC memory in use %u, max %u, allocated %u"
 msgstr ""
 
-#: tables.c:80
-msgid "error: fill_addr missused"
-msgstr ""
-
-#: tables.c:109
+#: tables.c:61
 #, c-format
 msgid "failed to access pf devices: %s"
 msgstr ""
 
-#: tables.c:123
+#: tables.c:74
 #, c-format
 msgid "warning: no opened pf devices %s"
 msgstr ""
 
-#: tables.c:131
+#: tables.c:82
 #, c-format
 msgid "error: cannot use table name %s"
 msgstr ""
 
-#: tables.c:139
+#: tables.c:90
 #, c-format
 msgid "error: cannot strlcpy table name %s"
 msgstr ""
 
-#: tables.c:145
+#: tables.c:101
 #, c-format
-msgid "warning: pfr_add_tables: %s(%d)"
+msgid "IPset: error:%s"
 msgstr ""
 
-#: tables.c:151
+#: tables.c:108
 msgid "info: table created"
 msgstr ""
 
-#: tables.c:162
+#: tables.c:134
 #, c-format
 msgid "warning: DIOCR%sADDRS: %s"
 msgstr ""
 
-#: tables.c:166
+#: tables.c:138
 #, c-format
 msgid "%d addresses %s"
 msgstr ""
 
-#: inotify.c:59
+#: inotify.c:62
 #, c-format
 msgid "cannot access path %s: %s"
 msgstr ""
 
-#: inotify.c:92
+#: inotify.c:95
 #, c-format
 msgid "failed to create inotify: %s"
 msgstr ""
 
-#: inotify.c:105
+#: inotify.c:111
 #, c-format
 msgid "too many symlinks following %s"
 msgstr ""
 
-#: inotify.c:121
+#: inotify.c:127
 #, c-format
 msgid "directory %s for resolv-file is missing, cannot poll"
 msgstr ""
 
-#: inotify.c:125 inotify.c:162
+#: inotify.c:131 inotify.c:168
 #, c-format
 msgid "failed to create inotify for %s: %s"
 msgstr ""
 
-#: inotify.c:147
+#: inotify.c:153
 #, c-format
 msgid "bad dynamic directory %s: %s"
 msgstr ""
 
-#: inotify.c:247
+#: inotify.c:257
 #, c-format
 msgid "inotify, new or changed file %s"
 msgstr ""
index 5cac04f..2718648 100644 (file)
--- a/po/no.po
+++ b/po/no.po
@@ -9,7 +9,7 @@ msgstr ""
 "Project-Id-Version: dnsmasq 2.25\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2009-06-18 12:24+0100\n"
-"PO-Revision-Date: 2006-01-11 17:39+0000\n"
+"PO-Revision-Date: 2017-07-17 18:30+0100\n"
 "Last-Translator: Jan Erik Askildt <jeaskildt@gmail.com>\n"
 "Language-Team: Norwegian <i18n-nb@lister.ping.uio.no>\n"
 "Language: no\n"
@@ -18,739 +18,765 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cache.c:523
+#: cache.c:518
 msgid "Internal error in cache."
 msgstr ""
 
-#: cache.c:941
+#: cache.c:928
 #, fuzzy, c-format
 msgid "failed to load names from %s: %s"
 msgstr "feilet å laste navn fra %s: %s"
 
-#: cache.c:967 dhcp.c:828
+#: cache.c:954 dhcp.c:867
 #, c-format
 msgid "bad address at %s line %d"
 msgstr "dårlig adresse ved %s linje %d"
 
-#: cache.c:1018 dhcp.c:844
+#: cache.c:1007 dhcp.c:883
 #, c-format
 msgid "bad name at %s line %d"
 msgstr "dårlig navn ved %s linje %d"
 
-#: cache.c:1027 dhcp.c:919
+#: cache.c:1016 dhcp.c:958
 #, c-format
 msgid "read %s - %d addresses"
 msgstr "les %s - %d adresser"
 
-#: cache.c:1135
+#: cache.c:1129
 msgid "cleared cache"
 msgstr "mellomlager tømt"
 
-#: cache.c:1164
+#: cache.c:1158
 #, c-format
 msgid "No IPv4 address found for %s"
 msgstr ""
 
-#: cache.c:1242
+#: cache.c:1237
 #, c-format
 msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
 msgstr ""
 
-#: cache.c:1266
+#: cache.c:1261
 #, c-format
 msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
 msgstr "gir ikke navnet %s til DHCP leien for %s fordi navnet eksisterer i %s med adressen %s"
 
-#: cache.c:1421
+#: cache.c:1418
 #, c-format
 msgid "time %lu"
 msgstr ""
 
-#: cache.c:1422
+#: cache.c:1419
 #, fuzzy, c-format
 msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
 msgstr "mellomlager størrelse %d, %d/%d mellomlager innsettinger re-bruker mellomlager plasser som ikke er utløpt"
 
-#: cache.c:1424
+#: cache.c:1421
 #, c-format
 msgid "queries forwarded %u, queries answered locally %u"
 msgstr ""
 
-#: cache.c:1427
+#: cache.c:1424
 #, c-format
 msgid "queries for authoritative zones %u"
 msgstr ""
 
-#: cache.c:1453
+#: cache.c:1450
 #, c-format
 msgid "server %s#%d: queries sent %u, retried or failed %u"
 msgstr ""
 
-#: util.c:45
+#: util.c:47
 #, fuzzy, c-format
 msgid "failed to seed the random number generator: %s"
 msgstr "feilet å lytte på socket: %s"
 
-#: util.c:205
+#: util.c:224
 #, fuzzy
 msgid "failed to allocate memory"
 msgstr "feilet å laste %d bytes"
 
-#: util.c:250 option.c:601
+#: util.c:281 option.c:619
 msgid "could not get memory"
 msgstr "kunne ikke få minne"
 
-#: util.c:260
+#: util.c:291
 #, fuzzy, c-format
 msgid "cannot create pipe: %s"
 msgstr "kan ikke lese %s: %s"
 
-#: util.c:268
+#: util.c:299
 #, fuzzy, c-format
 msgid "failed to allocate %d bytes"
 msgstr "feilet å laste %d bytes"
 
-#: util.c:437
+#: util.c:468
 #, c-format
 msgid "infinite"
 msgstr "uendelig"
 
-#: option.c:332
+#: option.c:344
 msgid "Specify local address(es) to listen on."
 msgstr "Spesifiser lokal(e) adresse(r) å lytte på."
 
-#: option.c:333
+#: option.c:345
 msgid "Return ipaddr for all hosts in specified domains."
 msgstr "Returner ipaddr for alle verter i det spesifiserte domenet."
 
-#: option.c:334
+#: option.c:346
 msgid "Fake reverse lookups for RFC1918 private address ranges."
 msgstr "Forfalsk revers oppslag for RFC1918 private adresse områder."
 
-#: option.c:335
+#: option.c:347
 msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
 msgstr "Behandle ipaddr som NXDOMAIN (omgår Verisign wildcard)."
 
-#: option.c:336
+#: option.c:348
 #, c-format
 msgid "Specify the size of the cache in entries (defaults to %s)."
 msgstr "Spesifiser størrelsen på mellomlager plassene (standard er %s)."
 
-#: option.c:337
+#: option.c:349
 #, c-format
 msgid "Specify configuration file (defaults to %s)."
 msgstr "Spesifiser konfigurasjonsfil (standard er %s)."
 
-#: option.c:338
+#: option.c:350
 msgid "Do NOT fork into the background: run in debug mode."
 msgstr "IKKE legg (fork) som bakgrunnsprosess: kjør i debug modus."
 
-#: option.c:339
+#: option.c:351
 msgid "Do NOT forward queries with no domain part."
 msgstr "IKKE videresend oppslag som mangler domene del."
 
-#: option.c:340
+#: option.c:352
 msgid "Return self-pointing MX records for local hosts."
 msgstr "Returner selv-pekende MX post for lokale verter."
 
-#: option.c:341
+#: option.c:353
 msgid "Expand simple names in /etc/hosts with domain-suffix."
 msgstr "Utvid enkle navn i /etc/hosts med domene-suffiks."
 
-#: option.c:342
+#: option.c:354
 msgid "Don't forward spurious DNS requests from Windows hosts."
 msgstr "Ikke videresend falske/uekte DNS forespørsler fra Windows verter."
 
-#: option.c:343
+#: option.c:355
 msgid "Enable DHCP in the range given with lease duration."
 msgstr "Aktiver DHCP i det gitte området med leie varighet"
 
-#: option.c:344
+#: option.c:356
 #, c-format
 msgid "Change to this group after startup (defaults to %s)."
 msgstr "Skift til denne gruppen etter oppstart (standard er %s)."
 
-#: option.c:345
+#: option.c:357
 msgid "Set address or hostname for a specified machine."
 msgstr "Sett adresse eller vertsnavn for en spesifikk maskin."
 
-#: option.c:346
+#: option.c:358
 #, fuzzy
 msgid "Read DHCP host specs from file."
 msgstr "dårlig MX navn"
 
-#: option.c:347
+#: option.c:359
 msgid "Read DHCP option specs from file."
 msgstr ""
 
-#: option.c:348
+#: option.c:360
 #, fuzzy
 msgid "Read DHCP host specs from a directory."
 msgstr "dårlig MX navn"
 
-#: option.c:349
+#: option.c:361
 #, fuzzy
 msgid "Read DHCP options from a directory."
 msgstr "dårlig MX navn"
 
-#: option.c:350
+#: option.c:362
 msgid "Evaluate conditional tag expression."
 msgstr ""
 
-#: option.c:351
+#: option.c:363
 #, c-format
 msgid "Do NOT load %s file."
 msgstr "IKKE last %s filen."
 
-#: option.c:352
+#: option.c:364
 #, c-format
 msgid "Specify a hosts file to be read in addition to %s."
 msgstr "Spesifiser en verts (hosts) fil som skal leses i tilleg til %s."
 
-#: option.c:353
+#: option.c:365
 #, fuzzy
 msgid "Read hosts files from a directory."
 msgstr "dårlig MX navn"
 
-#: option.c:354
+#: option.c:366
 msgid "Specify interface(s) to listen on."
 msgstr "Spesifiser nettverkskort det skal lyttes på."
 
-#: option.c:355
+#: option.c:367
 msgid "Specify interface(s) NOT to listen on."
 msgstr "Spesifiser nettverkskort det IKKE skal lyttes på."
 
-#: option.c:356
+#: option.c:368
 #, fuzzy
 msgid "Map DHCP user class to tag."
 msgstr "Map DHCP bruker klasse til opsjon sett."
 
-#: option.c:357
+#: option.c:369
 msgid "Map RFC3046 circuit-id to tag."
 msgstr ""
 
-#: option.c:358
+#: option.c:370
 msgid "Map RFC3046 remote-id to tag."
 msgstr ""
 
-#: option.c:359
+#: option.c:371
 msgid "Map RFC3993 subscriber-id to tag."
 msgstr ""
 
-#: option.c:360
+#: option.c:372
 #, fuzzy
 msgid "Don't do DHCP for hosts with tag set."
 msgstr "Ikke utfør DHCP for klienter i opsjon sett."
 
-#: option.c:361
+#: option.c:373
 #, fuzzy
 msgid "Force broadcast replies for hosts with tag set."
 msgstr "Ikke utfør DHCP for klienter i opsjon sett."
 
-#: option.c:362
+#: option.c:374
 msgid "Do NOT fork into the background, do NOT run in debug mode."
 msgstr "IKKE last (fork) som bakgrunnsprosess, IKKE kjør i debug modus."
 
-#: option.c:363
+#: option.c:375
 msgid "Assume we are the only DHCP server on the local network."
 msgstr "Anta at vi er den eneste DHCP tjeneren på det lokale nettverket."
 
-#: option.c:364
+#: option.c:376
 #, c-format
 msgid "Specify where to store DHCP leases (defaults to %s)."
 msgstr "Spesifiser hvor DHCP leiene skal lagres (standard er %s)."
 
-#: option.c:365
+#: option.c:377
 msgid "Return MX records for local hosts."
 msgstr "Returner MX records for lokale verter."
 
-#: option.c:366
+#: option.c:378
 msgid "Specify an MX record."
 msgstr "Spesifiser en MX post."
 
-#: option.c:367
+#: option.c:379
 msgid "Specify BOOTP options to DHCP server."
 msgstr "Spesifiser BOOTP opsjoner til DHCP tjener."
 
-#: option.c:368
+#: option.c:380
 #, c-format
 msgid "Do NOT poll %s file, reload only on SIGHUP."
 msgstr "IKKE spør (poll) %s fil, les på nytt kun ved SIGHUP"
 
-#: option.c:369
+#: option.c:381
 msgid "Do NOT cache failed search results."
 msgstr "IKKE mellomlagre søkeresultater som feiler."
 
-#: option.c:370
+#: option.c:382
 #, c-format
 msgid "Use nameservers strictly in the order given in %s."
 msgstr "Bruk navnetjenere kun som bestemt i rekkefølgen gitt i %s."
 
-#: option.c:371
+#: option.c:383
 #, fuzzy
 msgid "Specify options to be sent to DHCP clients."
 msgstr "Sett ekstra opsjoner som skal fordeles til DHCP klientene."
 
-#: option.c:372
+#: option.c:384
 msgid "DHCP option sent even if the client does not request it."
 msgstr ""
 
-#: option.c:373
+#: option.c:385
 msgid "Specify port to listen for DNS requests on (defaults to 53)."
 msgstr "Spesifiser lytteport for DNS oppslag (standard er 53)."
 
-#: option.c:374
+#: option.c:386
 #, c-format
 msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
 msgstr "Maksimal støttet UDP pakkestørrelse for EDNS.0 (standard er %s)."
 
-#: option.c:375
+#: option.c:387
 #, fuzzy
 msgid "Log DNS queries."
 msgstr "Logg oppslag."
 
-#: option.c:376
+#: option.c:388
 #, fuzzy
 msgid "Force the originating port for upstream DNS queries."
 msgstr "Tving bruk av opprinnelig port for oppstrøms oppslag."
 
-#: option.c:377
+#: option.c:389
 msgid "Do NOT read resolv.conf."
 msgstr "IKKE les resolv.conf."
 
-#: option.c:378
+#: option.c:390
 #, c-format
 msgid "Specify path to resolv.conf (defaults to %s)."
 msgstr "Spesifiser stien til resolv.conf (standard er %s)."
 
-#: option.c:379
+#: option.c:391
 #, fuzzy
 msgid "Specify path to file with server= options"
 msgstr "Spesifiser stien til PID fil. (standard er %s)."
 
-#: option.c:380
+#: option.c:392
 msgid "Specify address(es) of upstream servers with optional domains."
 msgstr "Spesifiser adressen(e) til oppstrøms tjenere med valgfrie domener."
 
-#: option.c:381
+#: option.c:393
 #, fuzzy
 msgid "Specify address of upstream servers for reverse address queries"
 msgstr "Spesifiser adressen(e) til oppstrøms tjenere med valgfrie domener."
 
-#: option.c:382
+#: option.c:394
 msgid "Never forward queries to specified domains."
 msgstr "Aldri videresend oppslag til spesifiserte domener."
 
-#: option.c:383
+#: option.c:395
 msgid "Specify the domain to be assigned in DHCP leases."
 msgstr "Spesifiser domenet som skal tildeles i DHCP leien."
 
-#: option.c:384
+#: option.c:396
 msgid "Specify default target in an MX record."
 msgstr "Spesifiser default mål i en MX post."
 
-#: option.c:385
+#: option.c:397
 msgid "Specify time-to-live in seconds for replies from /etc/hosts."
 msgstr "Spesifiser time-to-live i sekunder for svar fra /etc/hosts."
 
-#: option.c:386
+#: option.c:398
 #, fuzzy
 msgid "Specify time-to-live in seconds for negative caching."
 msgstr "Spesifiser time-to-live i sekunder for svar fra /etc/hosts."
 
-#: option.c:387
+#: option.c:399
 #, fuzzy
 msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
 msgstr "Spesifiser time-to-live i sekunder for svar fra /etc/hosts."
 
-#: option.c:388
+#: option.c:400
 #, fuzzy
 msgid "Specify time-to-live ceiling for cache."
 msgstr "Spesifiser time-to-live i sekunder for svar fra /etc/hosts."
 
-#: option.c:389
+#: option.c:401
 #, fuzzy
 msgid "Specify time-to-live floor for cache."
 msgstr "Spesifiser time-to-live i sekunder for svar fra /etc/hosts."
 
-#: option.c:390
+#: option.c:402
 #, c-format
 msgid "Change to this user after startup. (defaults to %s)."
 msgstr "Skift til denne bruker etter oppstart (standard er %s)."
 
-#: option.c:391
+#: option.c:403
 #, fuzzy
 msgid "Map DHCP vendor class to tag."
 msgstr "Map DHCP produsent klasse til opsjon sett."
 
-#: option.c:392
+#: option.c:404
 msgid "Display dnsmasq version and copyright information."
 msgstr "Vis dnsmasq versjon og copyright informasjon."
 
-#: option.c:393
+#: option.c:405
 msgid "Translate IPv4 addresses from upstream servers."
 msgstr "Oversett IPv4 adresser fra oppstrøms tjenere."
 
-#: option.c:394
+#: option.c:406
 msgid "Specify a SRV record."
 msgstr "Spesifiser en SRV post."
 
-#: option.c:395
-msgid "Display this message. Use --help dhcp for known DHCP options."
+#: option.c:407
+msgid "Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."
 msgstr ""
 
-#: option.c:396
+#: option.c:408
 #, fuzzy, c-format
 msgid "Specify path of PID file (defaults to %s)."
 msgstr "Spesifiser stien til PID fil. (standard er %s)."
 
-#: option.c:397
+#: option.c:409
 #, c-format
 msgid "Specify maximum number of DHCP leases (defaults to %s)."
 msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)"
 
-#: option.c:398
+#: option.c:410
 msgid "Answer DNS queries based on the interface a query was sent to."
 msgstr "Svar DNS oppslag basert på nettverkskortet oppslaget ble sendt til."
 
-#: option.c:399
+#: option.c:411
 msgid "Specify TXT DNS record."
 msgstr "Spesifiser TXT DNS post."
 
-#: option.c:400
+#: option.c:412
 #, fuzzy
 msgid "Specify PTR DNS record."
 msgstr "Spesifiser TXT DNS post."
 
-#: option.c:401
+#: option.c:413
 msgid "Give DNS name to IPv4 address of interface."
 msgstr ""
 
-#: option.c:402
+#: option.c:414
 msgid "Bind only to interfaces in use."
 msgstr "Bind kun til nettverkskort som er i bruk."
 
-#: option.c:403
+#: option.c:415
 #, c-format
 msgid "Read DHCP static host information from %s."
 msgstr "Les DHCP statisk vert informasjon fra %s."
 
-#: option.c:404
+#: option.c:416
 msgid "Enable the DBus interface for setting upstream servers, etc."
 msgstr "Aktiver DBus interface for å sette oppstrøms tjenere, osv."
 
-#: option.c:405
+#: option.c:417
 msgid "Do not provide DHCP on this interface, only provide DNS."
 msgstr "Ikke lever DHCP på dette nettverkskortet, kun lever DNS."
 
-#: option.c:406
+#: option.c:418
 msgid "Enable dynamic address allocation for bootp."
 msgstr "Aktiver dynamisk adresse allokering for bootp."
 
-#: option.c:407
+#: option.c:419
 #, fuzzy
 msgid "Map MAC address (with wildcards) to option set."
 msgstr "Map DHCP produsent klasse til opsjon sett."
 
-#: option.c:408
+#: option.c:420
 msgid "Treat DHCP requests on aliases as arriving from interface."
 msgstr ""
 
-#: option.c:409
+#: option.c:421
 msgid "Disable ICMP echo address checking in the DHCP server."
 msgstr ""
 
-#: option.c:410
+#: option.c:422
 msgid "Shell script to run on DHCP lease creation and destruction."
 msgstr ""
 
-#: option.c:411
+#: option.c:423
 msgid "Lua script to run on DHCP lease creation and destruction."
 msgstr ""
 
-#: option.c:412
+#: option.c:424
 msgid "Run lease-change scripts as this user."
 msgstr ""
 
-#: option.c:413
+#: option.c:425
+msgid "Call dhcp-script with changes to local ARP table."
+msgstr ""
+
+#: option.c:426
 msgid "Read configuration from all the files in this directory."
 msgstr ""
 
-#: option.c:414
+#: option.c:427
 #, fuzzy
 msgid "Log to this syslog facility or file. (defaults to DAEMON)"
 msgstr "Skift til denne bruker etter oppstart (standard er %s)."
 
-#: option.c:415
+#: option.c:428
 msgid "Do not use leasefile."
 msgstr ""
 
-#: option.c:416
+#: option.c:429
 #, fuzzy, c-format
 msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
 msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)"
 
-#: option.c:417
+#: option.c:430
 #, c-format
 msgid "Clear DNS cache when reloading %s."
 msgstr ""
 
-#: option.c:418
+#: option.c:431
 msgid "Ignore hostnames provided by DHCP clients."
 msgstr ""
 
-#: option.c:419
+#: option.c:432
 msgid "Do NOT reuse filename and server fields for extra DHCP options."
 msgstr ""
 
-#: option.c:420
+#: option.c:433
 msgid "Enable integrated read-only TFTP server."
 msgstr ""
 
-#: option.c:421
+#: option.c:434
 msgid "Export files by TFTP only from the specified subtree."
 msgstr ""
 
-#: option.c:422
-msgid "Add client IP address to tftp-root."
+#: option.c:435
+msgid "Add client IP or hardware address to tftp-root."
 msgstr ""
 
-#: option.c:423
+#: option.c:436
 msgid "Allow access only to files owned by the user running dnsmasq."
 msgstr ""
 
-#: option.c:424
+#: option.c:437
 msgid "Do not terminate the service if TFTP directories are inaccessible."
 msgstr ""
 
-#: option.c:425
+#: option.c:438
 #, fuzzy, c-format
-msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgid "Maximum number of concurrent TFTP transfers (defaults to %s)."
 msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)"
 
-#: option.c:426
+#: option.c:439
+#, fuzzy
+msgid "Maximum MTU to use for TFTP transfers."
+msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)"
+
+#: option.c:440
 msgid "Disable the TFTP blocksize extension."
 msgstr ""
 
-#: option.c:427
+#: option.c:441
 msgid "Convert TFTP filenames to lowercase"
 msgstr ""
 
-#: option.c:428
+#: option.c:442
 msgid "Ephemeral port range for use by TFTP transfers."
 msgstr ""
 
-#: option.c:429
+#: option.c:443
 msgid "Extra logging for DHCP."
 msgstr ""
 
-#: option.c:430
+#: option.c:444
 msgid "Enable async. logging; optionally set queue length."
 msgstr ""
 
-#: option.c:431
+#: option.c:445
 msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
 msgstr ""
 
-#: option.c:432
+#: option.c:446
 msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
 msgstr ""
 
-#: option.c:433
+#: option.c:447
 msgid "Inhibit DNS-rebind protection on this domain."
 msgstr ""
 
-#: option.c:434
+#: option.c:448
 msgid "Always perform DNS queries to all servers."
 msgstr ""
 
-#: option.c:435
+#: option.c:449
 msgid "Set tag if client includes matching option in request."
 msgstr ""
 
-#: option.c:436
+#: option.c:450
 msgid "Use alternative ports for DHCP."
 msgstr ""
 
-#: option.c:437
+#: option.c:451
 #, fuzzy
 msgid "Specify NAPTR DNS record."
 msgstr "Spesifiser TXT DNS post."
 
-#: option.c:438
+#: option.c:452
 msgid "Specify lowest port available for DNS query transmission."
 msgstr ""
 
-#: option.c:439
+#: option.c:453
+msgid "Specify highest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:454
 msgid "Use only fully qualified domain names for DHCP clients."
 msgstr ""
 
-#: option.c:440
+#: option.c:455
 msgid "Generate hostnames based on MAC address for nameless clients."
 msgstr ""
 
-#: option.c:441
+#: option.c:456
 msgid "Use these DHCP relays as full proxies."
 msgstr ""
 
-#: option.c:442
+#: option.c:457
 msgid "Relay DHCP requests to a remote server"
 msgstr ""
 
-#: option.c:443
+#: option.c:458
 msgid "Specify alias name for LOCAL DNS name."
 msgstr ""
 
-#: option.c:444
+#: option.c:459
 #, fuzzy
 msgid "Prompt to send to PXE clients."
 msgstr "Sett ekstra opsjoner som skal fordeles til DHCP klientene."
 
-#: option.c:445
+#: option.c:460
 msgid "Boot service for PXE menu."
 msgstr ""
 
-#: option.c:446
+#: option.c:461
 msgid "Check configuration syntax."
 msgstr ""
 
-#: option.c:447
+#: option.c:462
 msgid "Add requestor's MAC address to forwarded DNS queries."
 msgstr ""
 
-#: option.c:448
-msgid "Add requestor's IP subnet to forwarded DNS queries."
+#: option.c:463
+msgid "Add specified IP subnet to forwarded DNS queries."
 msgstr ""
 
-#: option.c:449
+#: option.c:464
+#, fuzzy
+msgid "Add client identification to forwarded DNS queries."
+msgstr "Tving bruk av opprinnelig port for oppstrøms oppslag."
+
+#: option.c:465
 #, fuzzy
 msgid "Proxy DNSSEC validation results from upstream nameservers."
 msgstr "Oversett IPv4 adresser fra oppstrøms tjenere."
 
-#: option.c:450
+#: option.c:466
 msgid "Attempt to allocate sequential IP addresses to DHCP clients."
 msgstr ""
 
-#: option.c:451
+#: option.c:467
 msgid "Copy connection-track mark from queries to upstream connections."
 msgstr ""
 
-#: option.c:452
+#: option.c:468
 msgid "Allow DHCP clients to do their own DDNS updates."
 msgstr ""
 
-#: option.c:453
+#: option.c:469
 msgid "Send router-advertisements for interfaces doing DHCPv6"
 msgstr ""
 
-#: option.c:454
+#: option.c:470
 msgid "Specify DUID_EN-type DHCPv6 server DUID"
 msgstr ""
 
-#: option.c:455
+#: option.c:471
 #, fuzzy
 msgid "Specify host (A/AAAA and PTR) records"
 msgstr "Spesifiser en MX post."
 
-#: option.c:456
+#: option.c:472
 #, fuzzy
 msgid "Specify arbitrary DNS resource record"
 msgstr "Spesifiser TXT DNS post."
 
-#: option.c:457
+#: option.c:473
 #, fuzzy
 msgid "Bind to interfaces in use - check for new interfaces"
 msgstr "ukjent tilknytning (interface) %s"
 
-#: option.c:458
+#: option.c:474
 msgid "Export local names to global DNS"
 msgstr ""
 
-#: option.c:459
+#: option.c:475
 msgid "Domain to export to global DNS"
 msgstr ""
 
-#: option.c:460
+#: option.c:476
 msgid "Set TTL for authoritative replies"
 msgstr ""
 
-#: option.c:461
-msgid "Set authoritive zone information"
+#: option.c:477
+msgid "Set authoritative zone information"
 msgstr ""
 
-#: option.c:462
+#: option.c:478
 msgid "Secondary authoritative nameservers for forward domains"
 msgstr ""
 
-#: option.c:463
+#: option.c:479
 msgid "Peers which are allowed to do zone transfer"
 msgstr ""
 
-#: option.c:464
+#: option.c:480
 msgid "Specify ipsets to which matching domains should be added"
 msgstr ""
 
-#: option.c:465
+#: option.c:481
 msgid "Specify a domain and address range for synthesised names"
 msgstr ""
 
-#: option.c:466
+#: option.c:482
 msgid "Activate DNSSEC validation"
 msgstr ""
 
-#: option.c:467
+#: option.c:483
 msgid "Specify trust anchor key digest."
 msgstr ""
 
-#: option.c:468
+#: option.c:484
 msgid "Disable upstream checking for DNSSEC debugging."
 msgstr ""
 
-#: option.c:469
+#: option.c:485
 msgid "Ensure answers without DNSSEC are in unsigned zones."
 msgstr ""
 
-#: option.c:470
+#: option.c:486
 msgid "Don't check DNSSEC signature timestamps until first cache-reload"
 msgstr ""
 
-#: option.c:471
+#: option.c:487
 msgid "Timestamp file to verify system clock for DNSSEC"
 msgstr ""
 
-#: option.c:473
+#: option.c:489
 msgid "Specify DHCPv6 prefix class"
 msgstr ""
 
-#: option.c:475
-msgid "Set priority, resend-interval and router-lifetime"
+#: option.c:491
+msgid "Set MTU, priority, resend-interval and router-lifetime"
 msgstr ""
 
-#: option.c:476
+#: option.c:492
 msgid "Do not log routine DHCP."
 msgstr ""
 
-#: option.c:477
+#: option.c:493
 msgid "Do not log routine DHCPv6."
 msgstr ""
 
-#: option.c:478
+#: option.c:494
 msgid "Do not log RA."
 msgstr ""
 
-#: option.c:479
-msgid "Accept queries only from directly-connected networks"
+#: option.c:495
+msgid "Accept queries only from directly-connected networks."
 msgstr ""
 
-#: option.c:480
-msgid "Detect and remove DNS forwarding loops"
+#: option.c:496
+msgid "Detect and remove DNS forwarding loops."
 msgstr ""
 
-#: option.c:481
+#: option.c:497
 msgid "Ignore DNS responses containing ipaddr."
 msgstr ""
 
-#: option.c:683
+#: option.c:498
+msgid "Set TTL in DNS responses with DHCP-derived addresses."
+msgstr ""
+
+#: option.c:499
+msgid "Delay DHCP replies for at least number of seconds."
+msgstr ""
+
+#: option.c:703
 #, c-format
 msgid ""
 "Usage: dnsmasq [options]\n"
@@ -759,332 +785,341 @@ msgstr ""
 "Bruk: dnsmasq [opsjoner]\n"
 "\n"
 
-#: option.c:685
+#: option.c:705
 #, c-format
 msgid "Use short options only on the command line.\n"
 msgstr "Bruk korte opsjoner kun på kommandolinjen.\n"
 
-#: option.c:687
+#: option.c:707
 #, fuzzy, c-format
 msgid "Valid options are:\n"
 msgstr "Gyldige opsjoner er :\n"
 
-#: option.c:744 option.c:748
+#: option.c:754 option.c:868
+#, fuzzy
+msgid "bad address"
+msgstr "les %s - %d adresser"
+
+#: option.c:779 option.c:783
 msgid "bad port"
 msgstr "dårlig port"
 
-#: option.c:775 option.c:807
+#: option.c:797 option.c:826 option.c:861
 msgid "interface binding not supported"
 msgstr ""
 
-#: option.c:784 option.c:3575
+#: option.c:821 option.c:856
+msgid "interface can only be specified once"
+msgstr ""
+
+#: option.c:835 option.c:3809
 #, fuzzy
 msgid "bad interface name"
 msgstr "dårlig MX navn"
 
-#: option.c:814
-#, fuzzy
-msgid "bad address"
-msgstr "les %s - %d adresser"
-
-#: option.c:996
+#: option.c:1062
 msgid "unsupported encapsulation for IPv6 option"
 msgstr ""
 
-#: option.c:1010
+#: option.c:1076
 msgid "bad dhcp-option"
 msgstr "dårlig dhcp-opsjon"
 
-#: option.c:1078
+#: option.c:1144
 #, fuzzy
 msgid "bad IP address"
 msgstr "les %s - %d adresser"
 
-#: option.c:1081 option.c:1219 option.c:2893
+#: option.c:1147 option.c:1286 option.c:3079
 #, fuzzy
 msgid "bad IPv6 address"
 msgstr "les %s - %d adresser"
 
-#: option.c:1246 option.c:1340
+#: option.c:1240
+#, fuzzy
+msgid "bad IPv4 address"
+msgstr "les %s - %d adresser"
+
+#: option.c:1313 option.c:1407
 msgid "bad domain in dhcp-option"
 msgstr "dårlig domene i dhcp-opsjon"
 
-#: option.c:1378
+#: option.c:1445
 msgid "dhcp-option too long"
 msgstr "dhcp-opsjon for lang"
 
-#: option.c:1385
+#: option.c:1452
 msgid "illegal dhcp-match"
 msgstr ""
 
-#: option.c:1447
+#: option.c:1514
 msgid "illegal repeated flag"
 msgstr ""
 
-#: option.c:1455
+#: option.c:1522
 msgid "illegal repeated keyword"
 msgstr ""
 
-#: option.c:1520 option.c:4191
+#: option.c:1593 option.c:4443
 #, fuzzy, c-format
 msgid "cannot access directory %s: %s"
 msgstr "kan ikke lese %s: %s"
 
-#: option.c:1566 tftp.c:493
+#: option.c:1639 tftp.c:537
 #, fuzzy, c-format
 msgid "cannot access %s: %s"
 msgstr "kan ikke lese %s: %s"
 
-#: option.c:1618
+#: option.c:1727
 msgid "setting log facility is not possible under Android"
 msgstr ""
 
-#: option.c:1627
+#: option.c:1736
 msgid "bad log facility"
 msgstr ""
 
-#: option.c:1680
+#: option.c:1789
 msgid "bad MX preference"
 msgstr "dårlig MX preferanse"
 
-#: option.c:1685
+#: option.c:1794
 msgid "bad MX name"
 msgstr "dårlig MX navn"
 
-#: option.c:1699
+#: option.c:1808
 msgid "bad MX target"
 msgstr "dårlig MX mål"
 
-#: option.c:1711
+#: option.c:1820
 msgid "cannot run scripts under uClinux"
 msgstr ""
 
-#: option.c:1713
+#: option.c:1822
 msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
 msgstr ""
 
-#: option.c:1717
+#: option.c:1826
 msgid "recompile with HAVE_LUASCRIPT defined to enable Lua scripts"
 msgstr ""
 
-#: option.c:1973 option.c:2018 option.c:2074
+#: option.c:2095 option.c:2106 option.c:2143 option.c:2199 option.c:2482
 #, fuzzy
 msgid "bad prefix"
 msgstr "dårlig port"
 
-#: option.c:2355
+#: option.c:2504
 msgid "recompile with HAVE_IPSET defined to enable ipset directives"
 msgstr ""
 
-#: option.c:2548
+#: option.c:2713
 #, fuzzy
 msgid "bad port range"
 msgstr "dårlig port"
 
-#: option.c:2564
+#: option.c:2739
 msgid "bad bridge-interface"
 msgstr ""
 
-#: option.c:2624
+#: option.c:2807
 msgid "only one tag allowed"
 msgstr ""
 
-#: option.c:2644 option.c:2656 option.c:2764 option.c:2805
+#: option.c:2827 option.c:2839 option.c:2948 option.c:2953 option.c:2992
 msgid "bad dhcp-range"
 msgstr "dårlig dhcp-område"
 
-#: option.c:2671
+#: option.c:2854
 msgid "inconsistent DHCP range"
 msgstr "ikke konsistent DHCP område"
 
-#: option.c:2732
+#: option.c:2916
 msgid "prefix length must be exactly 64 for RA subnets"
 msgstr ""
 
-#: option.c:2734
+#: option.c:2918
 msgid "prefix length must be exactly 64 for subnet constructors"
 msgstr ""
 
-#: option.c:2738
+#: option.c:2922
 msgid "prefix length must be at least 64"
 msgstr ""
 
-#: option.c:2741
+#: option.c:2925
 #, fuzzy
 msgid "inconsistent DHCPv6 range"
 msgstr "ikke konsistent DHCP område"
 
-#: option.c:2752
+#: option.c:2936
 msgid "prefix must be zero with \"constructor:\" argument"
 msgstr ""
 
-#: option.c:2863 option.c:2911
+#: option.c:3049 option.c:3097
 #, fuzzy
 msgid "bad hex constant"
 msgstr "dårlig dhcp-vert"
 
-#: option.c:2885
+#: option.c:3071
 msgid "cannot match tags in --dhcp-host"
 msgstr ""
 
-#: option.c:2933
+#: option.c:3119
 #, fuzzy, c-format
 msgid "duplicate dhcp-host IP address %s"
 msgstr "dubliserte IP adresser i %s dhcp-config direktiv."
 
-#: option.c:2991
+#: option.c:3177
 #, fuzzy
 msgid "bad DHCP host name"
 msgstr "dårlig MX navn"
 
-#: option.c:3073
+#: option.c:3259
 #, fuzzy
 msgid "bad tag-if"
 msgstr "dårlig MX mål"
 
-#: option.c:3397 option.c:3791
+#: option.c:3616 option.c:4039
 msgid "invalid port number"
 msgstr "ugyldig portnummer"
 
-#: option.c:3459
+#: option.c:3678
 #, fuzzy
 msgid "bad dhcp-proxy address"
 msgstr "les %s - %d adresser"
 
-#: option.c:3485
+#: option.c:3704
 #, fuzzy
 msgid "Bad dhcp-relay"
 msgstr "dårlig dhcp-område"
 
-#: option.c:3511
+#: option.c:3745
 msgid "bad RA-params"
 msgstr ""
 
-#: option.c:3520
+#: option.c:3754
 msgid "bad DUID"
 msgstr ""
 
-#: option.c:3562
+#: option.c:3796
 #, fuzzy
 msgid "invalid alias range"
 msgstr "ugyldig vekt"
 
-#: option.c:3616
+#: option.c:3850 option.c:3862
 msgid "bad CNAME"
 msgstr ""
 
-#: option.c:3621
+#: option.c:3866
 msgid "duplicate CNAME"
 msgstr ""
 
-#: option.c:3641
+#: option.c:3889
 #, fuzzy
 msgid "bad PTR record"
 msgstr "dårlig SRV post"
 
-#: option.c:3672
+#: option.c:3920
 #, fuzzy
 msgid "bad NAPTR record"
 msgstr "dårlig SRV post"
 
-#: option.c:3706
+#: option.c:3954
 #, fuzzy
 msgid "bad RR record"
 msgstr "dårlig SRV post"
 
-#: option.c:3736
+#: option.c:3984
 msgid "bad TXT record"
 msgstr "dårlig TXT post"
 
-#: option.c:3777
+#: option.c:4025
 msgid "bad SRV record"
 msgstr "dårlig SRV post"
 
-#: option.c:3784
+#: option.c:4032
 msgid "bad SRV target"
 msgstr "dårlig SRV mål"
 
-#: option.c:3798
+#: option.c:4046
 msgid "invalid priority"
 msgstr "ugyldig prioritet"
 
-#: option.c:3805
+#: option.c:4049
 msgid "invalid weight"
 msgstr "ugyldig vekt"
 
-#: option.c:3829
+#: option.c:4073
 #, fuzzy
 msgid "Bad host-record"
 msgstr "dårlig SRV post"
 
-#: option.c:3846
+#: option.c:4097
 #, fuzzy
 msgid "Bad name in host-record"
 msgstr "dårlig navn i %s"
 
-#: option.c:3911
+#: option.c:4162
 #, fuzzy
 msgid "bad trust anchor"
 msgstr "dårlig port"
 
-#: option.c:3925
+#: option.c:4176
 msgid "bad HEX in trust anchor"
 msgstr ""
 
-#: option.c:3935
+#: option.c:4186
 msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"
 msgstr ""
 
-#: option.c:3994
+#: option.c:4246
 msgid "missing \""
 msgstr "mangler \""
 
-#: option.c:4051
+#: option.c:4303
 msgid "bad option"
 msgstr "dårlig opsjon"
 
-#: option.c:4053
+#: option.c:4305
 msgid "extraneous parameter"
 msgstr "overflødig parameter"
 
-#: option.c:4055
+#: option.c:4307
 msgid "missing parameter"
 msgstr "mangler parameter"
 
-#: option.c:4057
+#: option.c:4309
 #, fuzzy
 msgid "illegal option"
 msgstr "dårlig opsjon"
 
-#: option.c:4064
+#: option.c:4316
 msgid "error"
 msgstr "feil"
 
-#: option.c:4066
+#: option.c:4318
 #, fuzzy, c-format
 msgid " at line %d of %s"
 msgstr "%s på linje %d av %%s"
 
-#: option.c:4081 option.c:4328 option.c:4364
+#: option.c:4333 option.c:4580 option.c:4616
 #, fuzzy, c-format
 msgid "read %s"
 msgstr "leser %s"
 
-#: option.c:4144 option.c:4267 tftp.c:667
+#: option.c:4396 option.c:4519 tftp.c:715
 #, c-format
 msgid "cannot read %s: %s"
 msgstr "kan ikke lese %s: %s"
 
-#: option.c:4430
+#: option.c:4688
 msgid "junk found in command line"
 msgstr ""
 
-#: option.c:4465
+#: option.c:4729
 #, c-format
 msgid "Dnsmasq version %s  %s\n"
 msgstr "Dnsmasq versjon %s %s\n"
 
-#: option.c:4466
+#: option.c:4730
 #, fuzzy, c-format
 msgid ""
 "Compile time options: %s\n"
@@ -1093,465 +1128,507 @@ msgstr ""
 "Kompileringsopsjoner %s\n"
 "\n"
 
-#: option.c:4467
+#: option.c:4731
 #, c-format
 msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
 msgstr "Denne programvaren kommer med ABSOLUTT INGEN GARANTI.\n"
 
-#: option.c:4468
+#: option.c:4732
 #, c-format
 msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
 msgstr "DNsmasq er fri programvare, du er velkommen til å redistribuere den\n"
 
-#: option.c:4469
+#: option.c:4733
 #, fuzzy, c-format
 msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
 msgstr "under vilkårene gitt i GNU General Public License, versjon 2.\n"
 
-#: option.c:4480
+#: option.c:4744
 msgid "try --help"
 msgstr ""
 
-#: option.c:4482
+#: option.c:4746
 msgid "try -w"
 msgstr ""
 
-#: option.c:4484
+#: option.c:4748
 #, fuzzy, c-format
 msgid "bad command line options: %s"
 msgstr "dårlige kommandlinje opsjoner: %s."
 
-#: option.c:4541
+#: option.c:4818
+#, c-format
+msgid "CNAME loop involving %s"
+msgstr ""
+
+#: option.c:4854
 #, c-format
 msgid "cannot get host-name: %s"
 msgstr "klarer ikke å få vertsnavn: %s"
 
-#: option.c:4569
+#: option.c:4882
 msgid "only one resolv.conf file allowed in no-poll mode."
 msgstr "kun en resolv.conf fil tillat i no-poll modus."
 
-#: option.c:4579
+#: option.c:4892
 msgid "must have exactly one resolv.conf to read domain from."
 msgstr "må ha nøyaktig en resolv.conf å lese domene fra."
 
-#: option.c:4582 network.c:1507 dhcp.c:777
+#: option.c:4895 network.c:1623 dhcp.c:816
 #, fuzzy, c-format
 msgid "failed to read %s: %s"
 msgstr "feilet å lese %s: %s"
 
-#: option.c:4599
+#: option.c:4912
 #, c-format
 msgid "no search directive found in %s"
 msgstr "intet søke direktiv funnet i %s"
 
-#: option.c:4620
+#: option.c:4933
 msgid "there must be a default domain when --dhcp-fqdn is set"
 msgstr ""
 
-#: option.c:4629
+#: option.c:4942
 msgid "syntax check OK"
 msgstr ""
 
-#: forward.c:111
+#: forward.c:102
 #, fuzzy, c-format
 msgid "failed to send packet: %s"
 msgstr "feilet å lytte på socket: %s"
 
-#: forward.c:591
+#: forward.c:598
 msgid "discarding DNS reply: subnet option mismatch"
 msgstr ""
 
-#: forward.c:614
+#: forward.c:652
 #, c-format
 msgid "nameserver %s refused to do a recursive query"
 msgstr "navnetjener %s nektet å gjøre et rekursivt oppslag"
 
-#: forward.c:646
+#: forward.c:684
 #, c-format
 msgid "possible DNS-rebind attack detected: %s"
 msgstr ""
 
-#: forward.c:1209 forward.c:1815
+#: forward.c:870
+#, c-format
+msgid "reducing DNS packet size for nameserver %s to %d"
+msgstr ""
+
+#: forward.c:1266 forward.c:1704
 msgid "Ignoring query from non-local network"
 msgstr ""
 
-#: forward.c:2286
+#: forward.c:2184
 #, fuzzy, c-format
 msgid "Maximum number of concurrent DNS queries reached (max: %d)"
 msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)"
 
-#: network.c:715
+#: network.c:720
 #, fuzzy, c-format
 msgid "failed to create listening socket for %s: %s"
 msgstr "feilet å lage lytte socket: %s"
 
-#: network.c:1021
+#: network.c:1031
 #, c-format
 msgid "LOUD WARNING: listening on %s may accept requests via interfaces other than %s"
 msgstr ""
 
-#: network.c:1028
+#: network.c:1038
 msgid "LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"
 msgstr ""
 
-#: network.c:1037
+#: network.c:1047
+#, fuzzy, c-format
+msgid "warning: using interface %s instead"
+msgstr "advarsel: nettverkskort %s eksisterer ikke for tiden"
+
+#: network.c:1056
 #, fuzzy, c-format
 msgid "warning: no addresses found for interface %s"
 msgstr "benytter lokale adresser kun for %s %s"
 
-#: network.c:1095
+#: network.c:1114
 #, fuzzy, c-format
 msgid "interface %s failed to join DHCPv6 multicast group: %s"
 msgstr "feilet å binde DHCP tjener socket: %s"
 
-#: network.c:1289
+#: network.c:1119
+msgid "try increasing /proc/sys/net/core/optmem_max"
+msgstr ""
+
+#: network.c:1337
 #, fuzzy, c-format
 msgid "failed to bind server socket for %s: %s"
 msgstr "feilet å binde lytte socket for %s: %s"
 
-#: network.c:1445
+#: network.c:1528
 #, c-format
 msgid "ignoring nameserver %s - local interface"
 msgstr "ignorerer navnetjener %s - lokal tilknytning"
 
-#: network.c:1456
+#: network.c:1539
 #, fuzzy, c-format
 msgid "ignoring nameserver %s - cannot make/bind socket: %s"
 msgstr "ignorerer navnetjener %s - kan ikke lage/dinde socket: %s"
 
-#: network.c:1469
+#: network.c:1559
+msgid "(no DNSSEC)"
+msgstr ""
+
+#: network.c:1562
 msgid "unqualified"
 msgstr "ikke kvalifisert"
 
-#: network.c:1469
+#: network.c:1562
 msgid "names"
 msgstr ""
 
-#: network.c:1471
+#: network.c:1564
 msgid "default"
 msgstr ""
 
-#: network.c:1473
+#: network.c:1566
 msgid "domain"
 msgstr "domene"
 
-#: network.c:1476
+#: network.c:1572
 #, c-format
 msgid "using local addresses only for %s %s"
 msgstr "benytter lokale adresser kun for %s %s"
 
-#: network.c:1478
+#: network.c:1575
 #, fuzzy, c-format
 msgid "using standard nameservers for %s %s"
 msgstr "benytter navnetjener %s#%d for %s %s"
 
-#: network.c:1480
-#, c-format
-msgid "using nameserver %s#%d for %s %s"
+#: network.c:1577
+#, fuzzy, c-format
+msgid "using nameserver %s#%d for %s %s %s"
 msgstr "benytter navnetjener %s#%d for %s %s"
 
-#: network.c:1484
+#: network.c:1581
 #, fuzzy, c-format
 msgid "NOT using nameserver %s#%d - query loop detected"
 msgstr "benytter navnetjener %s#%d for %s %s"
 
-#: network.c:1487
+#: network.c:1584
 #, fuzzy, c-format
 msgid "using nameserver %s#%d(via %s)"
 msgstr "benytter navnetjener %s#%d"
 
-#: network.c:1489
+#: network.c:1586
 #, c-format
 msgid "using nameserver %s#%d"
 msgstr "benytter navnetjener %s#%d"
 
-#: dnsmasq.c:163
+#: network.c:1591
+#, fuzzy, c-format
+msgid "using %d more local addresses"
+msgstr "benytter navnetjener %s#%d"
+
+#: network.c:1593
+#, fuzzy, c-format
+msgid "using %d more nameservers"
+msgstr "benytter navnetjener %s#%d"
+
+#: dnsmasq.c:171
 msgid "dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"
 msgstr ""
 
-#: dnsmasq.c:170
-msgid "no trust anchors provided for DNSSEC"
+#: dnsmasq.c:186
+msgid "no root trust anchor provided for DNSSEC"
 msgstr ""
 
-#: dnsmasq.c:173
+#: dnsmasq.c:189
 msgid "cannot reduce cache size from default when DNSSEC enabled"
 msgstr ""
 
-#: dnsmasq.c:175
+#: dnsmasq.c:191
 #, fuzzy
 msgid "DNSSEC not available: set HAVE_DNSSEC in src/config.h"
 msgstr "DBus ikke tilgjengelig: sett HAVE_DBUS i src/config.h"
 
-#: dnsmasq.c:181
+#: dnsmasq.c:197
 #, fuzzy
 msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
 msgstr "DBus ikke tilgjengelig: sett HAVE_DBUS i src/config.h"
 
-#: dnsmasq.c:186
+#: dnsmasq.c:202
 msgid "cannot use --conntrack AND --query-port"
 msgstr ""
 
-#: dnsmasq.c:189
+#: dnsmasq.c:205
 #, fuzzy
 msgid "conntrack support not available: set HAVE_CONNTRACK in src/config.h"
 msgstr "DBus ikke tilgjengelig: sett HAVE_DBUS i src/config.h"
 
-#: dnsmasq.c:194
-msgid "asychronous logging is not available under Solaris"
+#: dnsmasq.c:210
+msgid "asynchronous logging is not available under Solaris"
 msgstr ""
 
-#: dnsmasq.c:199
-msgid "asychronous logging is not available under Android"
+#: dnsmasq.c:215
+msgid "asynchronous logging is not available under Android"
 msgstr ""
 
-#: dnsmasq.c:204
+#: dnsmasq.c:220
 #, fuzzy
 msgid "authoritative DNS not available: set HAVE_AUTH in src/config.h"
 msgstr "DBus ikke tilgjengelig: sett HAVE_DBUS i src/config.h"
 
-#: dnsmasq.c:209
+#: dnsmasq.c:225
 #, fuzzy
 msgid "loop detection not available: set HAVE_LOOP in src/config.h"
 msgstr "DBus ikke tilgjengelig: sett HAVE_DBUS i src/config.h"
 
-#: dnsmasq.c:217
+#: dnsmasq.c:229
+msgid "max_port cannot be smaller than min_port"
+msgstr ""
+
+#: dnsmasq.c:236
 msgid "zone serial must be configured in --auth-soa"
 msgstr ""
 
-#: dnsmasq.c:235
+#: dnsmasq.c:254
 msgid "dhcp-range constructor not available on this platform"
 msgstr ""
 
-#: dnsmasq.c:278
+#: dnsmasq.c:300
 msgid "cannot set --bind-interfaces and --bind-dynamic"
 msgstr ""
 
-#: dnsmasq.c:281
+#: dnsmasq.c:303
 #, c-format
 msgid "failed to find list of interfaces: %s"
 msgstr "feilet å finne liste av tilknytninger (interfaces): %s"
 
-#: dnsmasq.c:290
+#: dnsmasq.c:312
 #, c-format
 msgid "unknown interface %s"
 msgstr "ukjent tilknytning (interface) %s"
 
-#: dnsmasq.c:354 dnsmasq.c:997
+#: dnsmasq.c:377 dnsmasq.c:1054
 #, c-format
 msgid "DBus error: %s"
 msgstr "DBus feil: %s"
 
-#: dnsmasq.c:357
+#: dnsmasq.c:380
 msgid "DBus not available: set HAVE_DBUS in src/config.h"
 msgstr "DBus ikke tilgjengelig: sett HAVE_DBUS i src/config.h"
 
-#: dnsmasq.c:385
+#: dnsmasq.c:410
 #, c-format
 msgid "unknown user or group: %s"
 msgstr ""
 
-#: dnsmasq.c:440
+#: dnsmasq.c:465
 #, c-format
 msgid "cannot chdir to filesystem root: %s"
 msgstr ""
 
-#: dnsmasq.c:692
+#: dnsmasq.c:730
 #, fuzzy, c-format
 msgid "started, version %s DNS disabled"
 msgstr "startet, versjon %s mellomlager deaktivert"
 
-#: dnsmasq.c:694
+#: dnsmasq.c:734
 #, c-format
 msgid "started, version %s cachesize %d"
 msgstr "startet, versjon %s mellomlager størrelse %d"
 
-#: dnsmasq.c:696
+#: dnsmasq.c:736
 #, c-format
 msgid "started, version %s cache disabled"
 msgstr "startet, versjon %s mellomlager deaktivert"
 
-#: dnsmasq.c:698
+#: dnsmasq.c:739
+msgid "DNS service limited to local subnets"
+msgstr ""
+
+#: dnsmasq.c:742
 #, c-format
 msgid "compile time options: %s"
 msgstr "kompilerings opsjoner: %s"
 
-#: dnsmasq.c:704
+#: dnsmasq.c:751
 msgid "DBus support enabled: connected to system bus"
 msgstr "DBus støtte aktivert: koblet til system buss"
 
-#: dnsmasq.c:706
+#: dnsmasq.c:753
 msgid "DBus support enabled: bus connection pending"
 msgstr "DBus støtte aktivert: avventer buss tilkobling"
 
-#: dnsmasq.c:711
-msgid "DNS service limited to local subnets"
-msgstr ""
-
-#: dnsmasq.c:727
+#: dnsmasq.c:771
 msgid "DNSSEC validation enabled"
 msgstr ""
 
-#: dnsmasq.c:730
-msgid "DNSSEC signature timestamps not checked until first cache reload"
+#: dnsmasq.c:775
+msgid "DNSSEC signature timestamps not checked until receipt of SIGINT"
 msgstr ""
 
-#: dnsmasq.c:733
+#: dnsmasq.c:778
 msgid "DNSSEC signature timestamps not checked until system time valid"
 msgstr ""
 
-#: dnsmasq.c:738
+#: dnsmasq.c:783
 #, fuzzy, c-format
 msgid "warning: failed to change owner of %s: %s"
 msgstr "feilet å laste navn fra %s: %s"
 
-#: dnsmasq.c:742
+#: dnsmasq.c:787
 msgid "setting --bind-interfaces option because of OS limitations"
 msgstr "setter --bind-interfaces opsjon på grunn av OS begrensninger"
 
-#: dnsmasq.c:752
+#: dnsmasq.c:799
 #, c-format
 msgid "warning: interface %s does not currently exist"
 msgstr "advarsel: nettverkskort %s eksisterer ikke for tiden"
 
-#: dnsmasq.c:757
+#: dnsmasq.c:804
 msgid "warning: ignoring resolv-file flag because no-resolv is set"
 msgstr ""
 
-#: dnsmasq.c:760
+#: dnsmasq.c:807
 #, fuzzy
 msgid "warning: no upstream servers configured"
 msgstr "setter oppstrøms tjener fra DBus"
 
-#: dnsmasq.c:764
+#: dnsmasq.c:811
 #, c-format
 msgid "asynchronous logging enabled, queue limit is %d messages"
 msgstr ""
 
-#: dnsmasq.c:785
+#: dnsmasq.c:832
 msgid "IPv6 router advertisement enabled"
 msgstr ""
 
-#: dnsmasq.c:790
+#: dnsmasq.c:837
 #, c-format
 msgid "DHCP, sockets bound exclusively to interface %s"
 msgstr ""
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "root is "
 msgstr ""
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 #, fuzzy
 msgid "enabled"
 msgstr "deaktivert"
 
-#: dnsmasq.c:806
+#: dnsmasq.c:853
 msgid "secure mode"
 msgstr ""
 
-#: dnsmasq.c:809
+#: dnsmasq.c:856
 #, c-format
 msgid "warning: %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:813
+#: dnsmasq.c:860
 #, c-format
 msgid "warning: TFTP directory %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:839
+#: dnsmasq.c:886
 #, c-format
 msgid "restricting maximum simultaneous TFTP transfers to %d"
 msgstr ""
 
-#: dnsmasq.c:999
+#: dnsmasq.c:1056
 msgid "connected to system DBus"
 msgstr "tilkoblet til system DBus"
 
-#: dnsmasq.c:1149
+#: dnsmasq.c:1215
 #, c-format
 msgid "cannot fork into background: %s"
 msgstr ""
 
-#: dnsmasq.c:1152
+#: dnsmasq.c:1218
 #, fuzzy, c-format
 msgid "failed to create helper: %s"
 msgstr "feilet å lese %s: %s"
 
-#: dnsmasq.c:1155
+#: dnsmasq.c:1221
 #, c-format
 msgid "setting capabilities failed: %s"
 msgstr ""
 
-#: dnsmasq.c:1158
+#: dnsmasq.c:1224
 #, fuzzy, c-format
 msgid "failed to change user-id to %s: %s"
 msgstr "feilet å laste navn fra %s: %s"
 
-#: dnsmasq.c:1161
+#: dnsmasq.c:1227
 #, fuzzy, c-format
 msgid "failed to change group-id to %s: %s"
 msgstr "feilet å laste navn fra %s: %s"
 
-#: dnsmasq.c:1164
+#: dnsmasq.c:1230
 #, fuzzy, c-format
 msgid "failed to open pidfile %s: %s"
 msgstr "feilet å lese %s: %s"
 
-#: dnsmasq.c:1167
+#: dnsmasq.c:1233
 #, fuzzy, c-format
 msgid "cannot open log %s: %s"
 msgstr "kan ikke åpne %s:%s"
 
-#: dnsmasq.c:1170
+#: dnsmasq.c:1236
 #, fuzzy, c-format
 msgid "failed to load Lua script: %s"
 msgstr "feilet å laste %s: %s"
 
-#: dnsmasq.c:1173
+#: dnsmasq.c:1239
 #, c-format
 msgid "TFTP directory %s inaccessible: %s"
 msgstr ""
 
-#: dnsmasq.c:1176
+#: dnsmasq.c:1242
 #, fuzzy, c-format
 msgid "cannot create timestamp file %s: %s"
 msgstr "kan ikke åpne eller lage leie fil: %s"
 
-#: dnsmasq.c:1197
-msgid "now checking DNSSEC signature timestamps"
-msgstr ""
-
-#: dnsmasq.c:1264
+#: dnsmasq.c:1326
 #, c-format
 msgid "script process killed by signal %d"
 msgstr ""
 
-#: dnsmasq.c:1268
+#: dnsmasq.c:1330
 #, c-format
 msgid "script process exited with status %d"
 msgstr ""
 
-#: dnsmasq.c:1272
+#: dnsmasq.c:1334
 #, fuzzy, c-format
 msgid "failed to execute %s: %s"
 msgstr "feilet å få tilgang til %s: %s"
 
-#: dnsmasq.c:1327
+#: dnsmasq.c:1374
+msgid "now checking DNSSEC signature timestamps"
+msgstr ""
+
+#: dnsmasq.c:1409 dnssec.c:160 dnssec.c:206
+#, fuzzy, c-format
+msgid "failed to update mtime on %s: %s"
+msgstr "feilet å lese %s: %s"
+
+#: dnsmasq.c:1416
 msgid "exiting on receipt of SIGTERM"
 msgstr "avslutter etter mottak av SIGTERM"
 
-#: dnsmasq.c:1355
+#: dnsmasq.c:1444
 #, fuzzy, c-format
 msgid "failed to access %s: %s"
 msgstr "feilet å få tilgang til %s: %s"
 
-#: dnsmasq.c:1385
+#: dnsmasq.c:1474
 #, c-format
 msgid "reading %s"
 msgstr "leser %s"
 
-#: dnsmasq.c:1396
+#: dnsmasq.c:1485
 #, fuzzy, c-format
 msgid "no servers found in %s, will retry"
 msgstr "intet søke direktiv funnet i %s"
@@ -1581,243 +1658,263 @@ msgstr "feilet 
 msgid "cannot create ICMP raw socket: %s."
 msgstr "kan ikke lage ICMP raw socket: %s"
 
-#: dhcp.c:241 dhcp6.c:180
+#: dhcp.c:252 dhcp6.c:173
 #, fuzzy, c-format
 msgid "unknown interface %s in bridge-interface"
 msgstr "ukjent tilknytning (interface) %s"
 
-#: dhcp.c:281
+#: dhcp.c:293
 #, c-format
 msgid "DHCP packet received on %s which has no address"
 msgstr ""
 
-#: dhcp.c:415
+#: dhcp.c:427
 #, c-format
 msgid "ARP-cache injection failed: %s"
 msgstr ""
 
-#: dhcp.c:514
+#: dhcp.c:470
+#, c-format
+msgid "Error sending DHCP packet to %s: %s"
+msgstr ""
+
+#: dhcp.c:531
 #, c-format
 msgid "DHCP range %s -- %s is not consistent with netmask %s"
 msgstr "DHCP område %s -- %s er ikke konsistent med nettmaske %s"
 
-#: dhcp.c:815
+#: dhcp.c:854
 #, c-format
 msgid "bad line at %s line %d"
 msgstr "dårlig linje ved %s linje %d"
 
-#: dhcp.c:858
+#: dhcp.c:897
 #, c-format
 msgid "ignoring %s line %d, duplicate name or IP address"
 msgstr ""
 
-#: dhcp.c:1002 rfc3315.c:2135
+#: dhcp.c:1041 rfc3315.c:2149
 #, c-format
 msgid "DHCP relay %s -> %s"
 msgstr ""
 
-#: lease.c:61
+#: lease.c:98
+msgid "too many stored leases"
+msgstr "for mange lagrede leier"
+
+#: lease.c:166
 #, fuzzy, c-format
 msgid "cannot open or create lease file %s: %s"
 msgstr "kan ikke åpne eller lage leie fil: %s"
 
-#: lease.c:134
-msgid "too many stored leases"
-msgstr "for mange lagrede leier"
+#: lease.c:175
+#, c-format
+msgid "failed to parse lease database, invalid line: %s %s %s %s ..."
+msgstr ""
+
+#: lease.c:180
+#, fuzzy, c-format
+msgid "failed to read lease file %s: %s"
+msgstr "feilet å lese %s: %s"
 
-#: lease.c:165
+#: lease.c:196
 #, fuzzy, c-format
 msgid "cannot run lease-init script %s: %s"
 msgstr "kan ikke lese %s: %s"
 
-#: lease.c:171
+#: lease.c:202
 #, c-format
 msgid "lease-init script returned exit code %s"
 msgstr ""
 
-#: lease.c:342
+#: lease.c:373
 #, fuzzy, c-format
 msgid "failed to write %s: %s (retry in %us)"
 msgstr "feilet å lese %s: %s"
 
-#: lease.c:906
+#: lease.c:937
 #, c-format
 msgid "Ignoring domain %s for DHCP host name %s"
 msgstr ""
 
-#: rfc2131.c:344
+#: rfc2131.c:347
 #, c-format
 msgid "no address range available for DHCP request %s %s"
 msgstr "ingen adresse område tilgjengelig for DHCP krav %s %s"
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "with subnet selector"
 msgstr "med subnet velger"
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "via"
 msgstr "via"
 
-#: rfc2131.c:357
+#: rfc2131.c:360
 #, fuzzy, c-format
 msgid "%u available DHCP subnet: %s/%s"
 msgstr "ingen adresse område tilgjengelig for DHCP krav %s %s"
 
-#: rfc2131.c:360 rfc3315.c:300
+#: rfc2131.c:363 rfc3315.c:306
 #, c-format
 msgid "%u available DHCP range: %s -- %s"
 msgstr ""
 
-#: rfc2131.c:471
+#: rfc2131.c:474
 #, fuzzy, c-format
 msgid "%u vendor class: %s"
 msgstr "DBus feil: %s"
 
-#: rfc2131.c:473
+#: rfc2131.c:476
 #, fuzzy, c-format
 msgid "%u user class: %s"
 msgstr "DBus feil: %s"
 
-#: rfc2131.c:500
+#: rfc2131.c:510
 msgid "disabled"
 msgstr "deaktivert"
 
-#: rfc2131.c:541 rfc2131.c:974 rfc2131.c:1380 rfc3315.c:603 rfc3315.c:856
-#: rfc3315.c:1135
+#: rfc2131.c:551 rfc2131.c:1006 rfc2131.c:1430 rfc3315.c:616 rfc3315.c:869
+#: rfc3315.c:1148
 msgid "ignored"
 msgstr "oversett"
 
-#: rfc2131.c:556 rfc2131.c:1207 rfc3315.c:906
+#: rfc2131.c:566 rfc2131.c:1239 rfc3315.c:919
 msgid "address in use"
 msgstr "adresse i bruk"
 
-#: rfc2131.c:570 rfc2131.c:1028
+#: rfc2131.c:580 rfc2131.c:1060
 msgid "no address available"
 msgstr "ingen adresse tilgjengelig"
 
-#: rfc2131.c:577 rfc2131.c:1170
+#: rfc2131.c:587 rfc2131.c:1202
 msgid "wrong network"
 msgstr "galt nettverk"
 
-#: rfc2131.c:592
+#: rfc2131.c:602
 msgid "no address configured"
 msgstr "ingen adresse konfigurert"
 
-#: rfc2131.c:598 rfc2131.c:1220
+#: rfc2131.c:608 rfc2131.c:1252
 msgid "no leases left"
 msgstr "ingen leier igjen"
 
-#: rfc2131.c:693 rfc3315.c:476
+#: rfc2131.c:703 rfc3315.c:482
 #, c-format
 msgid "%u client provides name: %s"
 msgstr ""
 
-#: rfc2131.c:798
+#: rfc2131.c:808
 msgid "PXE BIS not supported"
 msgstr ""
 
-#: rfc2131.c:942 rfc3315.c:1229
+#: rfc2131.c:974 rfc3315.c:1242
 #, fuzzy, c-format
 msgid "disabling DHCP static address %s for %s"
 msgstr "deaktiverer DHCP statisk adresse %s"
 
-#: rfc2131.c:963
+#: rfc2131.c:995
 msgid "unknown lease"
 msgstr "ukjent leie"
 
-#: rfc2131.c:997
+#: rfc2131.c:1029
 #, c-format
 msgid "not using configured address %s because it is leased to %s"
 msgstr ""
 
-#: rfc2131.c:1007
+#: rfc2131.c:1039
 #, c-format
 msgid "not using configured address %s because it is in use by the server or relay"
 msgstr ""
 
-#: rfc2131.c:1010
+#: rfc2131.c:1042
 #, c-format
 msgid "not using configured address %s because it was previously declined"
 msgstr ""
 
-#: rfc2131.c:1026 rfc2131.c:1213
+#: rfc2131.c:1058 rfc2131.c:1245
 msgid "no unique-id"
 msgstr ""
 
-#: rfc2131.c:1108
+#: rfc2131.c:1140
 msgid "wrong server-ID"
 msgstr ""
 
-#: rfc2131.c:1127
+#: rfc2131.c:1159
 msgid "wrong address"
 msgstr "gal adresse"
 
-#: rfc2131.c:1145 rfc3315.c:1002
+#: rfc2131.c:1177 rfc3315.c:1015
 msgid "lease not found"
 msgstr "leie ikke funnet"
 
-#: rfc2131.c:1178
+#: rfc2131.c:1210
 msgid "address not available"
 msgstr "adresse ikke tilgjengelig"
 
-#: rfc2131.c:1189
+#: rfc2131.c:1221
 msgid "static lease available"
 msgstr "statisk leie tilgjengelig"
 
-#: rfc2131.c:1193
+#: rfc2131.c:1225
 msgid "address reserved"
 msgstr "adresse reservert"
 
-#: rfc2131.c:1201
+#: rfc2131.c:1233
 #, c-format
 msgid "abandoning lease to %s of %s"
 msgstr ""
 
-#: rfc2131.c:1707
+#: rfc2131.c:1757
 #, c-format
 msgid "%u bootfile name: %s"
 msgstr ""
 
-#: rfc2131.c:1716
+#: rfc2131.c:1766
 #, fuzzy, c-format
 msgid "%u server name: %s"
 msgstr "DBus feil: %s"
 
-#: rfc2131.c:1724
+#: rfc2131.c:1774
 #, fuzzy, c-format
 msgid "%u next server: %s"
 msgstr "DBus feil: %s"
 
-#: rfc2131.c:1727
+#: rfc2131.c:1777
 #, c-format
 msgid "%u broadcast response"
 msgstr ""
 
-#: rfc2131.c:1790
+#: rfc2131.c:1840
 #, fuzzy, c-format
 msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
 msgstr "kan ikke sende DHCP opsjon %d: ikke mer plass i pakken"
 
-#: rfc2131.c:2031
+#: rfc2131.c:2131
 msgid "PXE menu too large"
 msgstr ""
 
-#: rfc2131.c:2170 rfc3315.c:1502
+#: rfc2131.c:2270 rfc3315.c:1515
 #, fuzzy, c-format
 msgid "%u requested options: %s"
 msgstr "kompilerings opsjoner: %s"
 
-#: rfc2131.c:2487
+#: rfc2131.c:2587
 #, c-format
 msgid "cannot send RFC3925 option: too many options for enterprise number %d"
 msgstr ""
 
+#: rfc2131.c:2650
+#, c-format
+msgid "%u reply delay: %d"
+msgstr ""
+
 #: netlink.c:77
 #, fuzzy, c-format
 msgid "cannot create netlink socket: %s"
 msgstr "kan ikke binde netlink socket: %s"
 
-#: netlink.c:348
+#: netlink.c:355
 #, fuzzy, c-format
 msgid "netlink returns error: %s"
 msgstr "DBus feil: %s"
@@ -1836,62 +1933,62 @@ msgstr ""
 msgid "Disabling --%s option from D-Bus"
 msgstr ""
 
-#: dbus.c:691
+#: dbus.c:690
 msgid "setting upstream servers from DBus"
 msgstr "setter oppstrøms tjener fra DBus"
 
-#: dbus.c:738
+#: dbus.c:737
 msgid "could not register a DBus message handler"
 msgstr "kunne ikke registrere en DBus meldingshåndterer"
 
-#: bpf.c:263
+#: bpf.c:265
 #, c-format
 msgid "cannot create DHCP BPF socket: %s"
 msgstr "kan ikke lage DHCP BPF socket: %s"
 
-#: bpf.c:291
+#: bpf.c:293
 #, fuzzy, c-format
 msgid "DHCP request for unsupported hardware type (%d) received on %s"
 msgstr "DHCP krav for ikke støttet maskinvare type (%d) mottatt på %s"
 
-#: bpf.c:376
+#: bpf.c:378
 #, fuzzy, c-format
 msgid "cannot create PF_ROUTE socket: %s"
 msgstr "kan ikke lage DHCP socket: %s"
 
-#: bpf.c:397
+#: bpf.c:399
 msgid "Unknown protocol version from route socket"
 msgstr ""
 
-#: helper.c:153
+#: helper.c:154
 msgid "lease() function missing in Lua script"
 msgstr ""
 
-#: tftp.c:309
+#: tftp.c:319
 msgid "unable to get free port for TFTP"
 msgstr ""
 
-#: tftp.c:325
+#: tftp.c:335
 #, c-format
 msgid "unsupported request from %s"
 msgstr ""
 
-#: tftp.c:439
+#: tftp.c:483
 #, fuzzy, c-format
 msgid "file %s not found"
 msgstr "leie ikke funnet"
 
-#: tftp.c:548
+#: tftp.c:592
 #, c-format
 msgid "error %d %s received from %s"
 msgstr ""
 
-#: tftp.c:590
+#: tftp.c:634
 #, fuzzy, c-format
 msgid "failed sending %s to %s"
 msgstr "feilet å lese %s: %s"
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "sent %s to %s"
 msgstr ""
@@ -1906,7 +2003,7 @@ msgstr ""
 msgid "log failed: %s"
 msgstr ""
 
-#: log.c:469
+#: log.c:471
 msgid "FAILED to start up"
 msgstr "FEILET å starte opp"
 
@@ -1915,17 +2012,17 @@ msgstr "FEILET 
 msgid "Conntrack connection mark retrieval failed: %s"
 msgstr ""
 
-#: dhcp6.c:59
+#: dhcp6.c:52
 #, fuzzy, c-format
 msgid "cannot create DHCPv6 socket: %s"
 msgstr "kan ikke lage DHCP socket: %s"
 
-#: dhcp6.c:80
+#: dhcp6.c:73
 #, fuzzy, c-format
 msgid "failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"
 msgstr "feilet å sette SO_REUSEADDR på DHCP socket: %s"
 
-#: dhcp6.c:92
+#: dhcp6.c:85
 #, fuzzy, c-format
 msgid "failed to bind DHCPv6 server socket: %s"
 msgstr "feilet å binde DHCP tjener socket: %s"
@@ -1940,71 +2037,71 @@ msgstr "ingen adresse omr
 msgid "no address range available for DHCPv6 request via %s"
 msgstr "ingen adresse område tilgjengelig for DHCP krav %s %s"
 
-#: rfc3315.c:297
+#: rfc3315.c:303
 #, fuzzy, c-format
 msgid "%u available DHCPv6 subnet: %s/%d"
 msgstr "ingen adresse område tilgjengelig for DHCP krav %s %s"
 
-#: rfc3315.c:380
+#: rfc3315.c:386
 #, fuzzy, c-format
 msgid "%u vendor class: %u"
 msgstr "DBus feil: %s"
 
-#: rfc3315.c:428
+#: rfc3315.c:434
 #, fuzzy, c-format
 msgid "%u client MAC address: %s"
 msgstr "ingen tilknytning (interface) med adresse %s"
 
-#: rfc3315.c:660
+#: rfc3315.c:673
 #, fuzzy, c-format
 msgid "unknown prefix-class %d"
 msgstr "ukjent leie"
 
-#: rfc3315.c:803 rfc3315.c:898
+#: rfc3315.c:816 rfc3315.c:911
 #, fuzzy
 msgid "address unavailable"
 msgstr "adresse ikke tilgjengelig"
 
-#: rfc3315.c:815 rfc3315.c:946 rfc3315.c:1279
+#: rfc3315.c:828 rfc3315.c:959 rfc3315.c:1292
 msgid "success"
 msgstr ""
 
-#: rfc3315.c:830 rfc3315.c:839 rfc3315.c:954 rfc3315.c:956
+#: rfc3315.c:843 rfc3315.c:852 rfc3315.c:967 rfc3315.c:969
 #, fuzzy
 msgid "no addresses available"
 msgstr "ingen adresse tilgjengelig"
 
-#: rfc3315.c:933
+#: rfc3315.c:946
 msgid "not on link"
 msgstr ""
 
-#: rfc3315.c:1006 rfc3315.c:1191 rfc3315.c:1268
+#: rfc3315.c:1019 rfc3315.c:1204 rfc3315.c:1281
 msgid "no binding found"
 msgstr ""
 
-#: rfc3315.c:1044
+#: rfc3315.c:1057
 msgid "deprecated"
 msgstr ""
 
-#: rfc3315.c:1049
+#: rfc3315.c:1062
 #, fuzzy
 msgid "address invalid"
 msgstr "adresse i bruk"
 
-#: rfc3315.c:1096
+#: rfc3315.c:1109
 msgid "confirm failed"
 msgstr ""
 
-#: rfc3315.c:1112
+#: rfc3315.c:1125
 #, fuzzy
 msgid "all addresses still on link"
 msgstr "dårlig adresse ved %s linje %d"
 
-#: rfc3315.c:1200
+#: rfc3315.c:1213
 msgid "release received"
 msgstr ""
 
-#: rfc3315.c:2126
+#: rfc3315.c:2140
 msgid "Cannot multicast to DHCPv6 server without correct interface"
 msgstr ""
 
@@ -2028,76 +2125,76 @@ msgstr ""
 msgid "duplicate IP address %s (%s) in dhcp-config directive"
 msgstr "dubliserte IP adresser i %s (%s) i dhcp-config direktiv"
 
-#: dhcp-common.c:494
+#: dhcp-common.c:491
 #, fuzzy, c-format
 msgid "failed to set SO_BINDTODEVICE on DHCP socket: %s"
 msgstr "feilet å sette SO_REUSEADDR på DHCP socket: %s"
 
-#: dhcp-common.c:615
+#: dhcp-common.c:612
 #, c-format
 msgid "Known DHCP options:\n"
 msgstr ""
 
-#: dhcp-common.c:626
+#: dhcp-common.c:623
 #, c-format
 msgid "Known DHCPv6 options:\n"
 msgstr ""
 
-#: dhcp-common.c:823
+#: dhcp-common.c:820
 msgid ", prefix deprecated"
 msgstr ""
 
-#: dhcp-common.c:826
+#: dhcp-common.c:823
 #, c-format
 msgid ", lease time "
 msgstr ""
 
-#: dhcp-common.c:868
+#: dhcp-common.c:865
 #, c-format
 msgid "%s stateless on %s%.0s%.0s%s"
 msgstr ""
 
-#: dhcp-common.c:870
+#: dhcp-common.c:867
 #, fuzzy, c-format
 msgid "%s, static leases only on %.0s%s%s%.0s"
 msgstr "DHCP, statisk leie kun på %.0s%s, leie tid %s"
 
-#: dhcp-common.c:872
+#: dhcp-common.c:869
 #, c-format
 msgid "%s, proxy on subnet %.0s%s%.0s%.0s"
 msgstr ""
 
-#: dhcp-common.c:873
+#: dhcp-common.c:870
 #, fuzzy, c-format
 msgid "%s, IP range %s -- %s%s%.0s"
 msgstr "DHCP, IP område %s -- %s, leie tid %s"
 
-#: dhcp-common.c:886
+#: dhcp-common.c:883
 #, c-format
 msgid "DHCPv4-derived IPv6 names on %s%s"
 msgstr ""
 
-#: dhcp-common.c:889
+#: dhcp-common.c:886
 #, fuzzy, c-format
 msgid "router advertisement on %s%s"
 msgstr "DHCP, statisk leie kun på %.0s%s, leie tid %s"
 
-#: dhcp-common.c:900
+#: dhcp-common.c:897
 #, c-format
 msgid "DHCP relay from %s to %s via %s"
 msgstr ""
 
-#: dhcp-common.c:902
+#: dhcp-common.c:899
 #, c-format
 msgid "DHCP relay from %s to %s"
 msgstr ""
 
-#: radv.c:109
+#: radv.c:110
 #, fuzzy, c-format
 msgid "cannot create ICMPv6 socket: %s"
 msgstr "kan ikke lage DHCP socket: %s"
 
-#: auth.c:448
+#: auth.c:449
 #, c-format
 msgid "ignoring zone transfer request from %s"
 msgstr ""
@@ -2112,90 +2209,90 @@ msgstr "feilet 
 msgid "failed to create IPset control socket: %s"
 msgstr "feilet å lage lytte socket: %s"
 
-#: dnssec.c:449 dnssec.c:493
+#: ipset.c:233
 #, fuzzy, c-format
-msgid "failed to update mtime on %s: %s"
+msgid "failed to update ipset %s: %s"
 msgstr "feilet å lese %s: %s"
 
+#: dnssec.c:208
+msgid "system time considered valid, now checking DNSSEC signature timestamps."
+msgstr ""
+
 #: blockdata.c:58
 #, c-format
 msgid "DNSSEC memory in use %u, max %u, allocated %u"
 msgstr ""
 
-#: tables.c:80
-msgid "error: fill_addr missused"
-msgstr ""
-
-#: tables.c:109
+#: tables.c:61
 #, fuzzy, c-format
 msgid "failed to access pf devices: %s"
 msgstr "feilet å få tilgang til %s: %s"
 
-#: tables.c:123
+#: tables.c:74
 #, fuzzy, c-format
 msgid "warning: no opened pf devices %s"
 msgstr "benytter lokale adresser kun for %s %s"
 
-#: tables.c:131
+#: tables.c:82
 #, fuzzy, c-format
 msgid "error: cannot use table name %s"
 msgstr "klarer ikke å få vertsnavn: %s"
 
-#: tables.c:139
+#: tables.c:90
 #, c-format
 msgid "error: cannot strlcpy table name %s"
 msgstr ""
 
-#: tables.c:145
-#, c-format
-msgid "warning: pfr_add_tables: %s(%d)"
-msgstr ""
+#: tables.c:101
+#, fuzzy, c-format
+msgid "IPset: error:%s"
+msgstr "DBus feil: %s"
 
-#: tables.c:151
+#: tables.c:108
 msgid "info: table created"
 msgstr ""
 
-#: tables.c:162
+#: tables.c:134
 #, c-format
 msgid "warning: DIOCR%sADDRS: %s"
 msgstr ""
 
-#: tables.c:166
+#: tables.c:138
 #, fuzzy, c-format
 msgid "%d addresses %s"
 msgstr "les %s - %d adresser"
 
-#: inotify.c:59
+#: inotify.c:62
 #, fuzzy, c-format
 msgid "cannot access path %s: %s"
 msgstr "kan ikke lese %s: %s"
 
-#: inotify.c:92
+#: inotify.c:95
 #, fuzzy, c-format
 msgid "failed to create inotify: %s"
 msgstr "feilet å lese %s: %s"
 
-#: inotify.c:105
+#: inotify.c:111
 #, c-format
 msgid "too many symlinks following %s"
 msgstr ""
 
-#: inotify.c:121
+#: inotify.c:127
 #, c-format
 msgid "directory %s for resolv-file is missing, cannot poll"
 msgstr ""
 
-#: inotify.c:125 inotify.c:162
+#: inotify.c:131 inotify.c:168
 #, fuzzy, c-format
 msgid "failed to create inotify for %s: %s"
 msgstr "feilet å lage lytte socket: %s"
 
-#: inotify.c:147
+#: inotify.c:153
 #, fuzzy, c-format
 msgid "bad dynamic directory %s: %s"
 msgstr "kan ikke lese %s: %s"
 
-#: inotify.c:247
+#: inotify.c:257
 #, c-format
 msgid "inotify, new or changed file %s"
 msgstr ""
index 8bcd85f..33f0d5a 100644 (file)
--- a/po/pl.po
+++ b/po/pl.po
@@ -10,7 +10,7 @@ msgstr ""
 "Project-Id-Version: pl\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2009-06-10 20:57+0100\n"
-"PO-Revision-Date: 2015-07-15 02:08+0100\n"
+"PO-Revision-Date: 2017-07-17 18:30+0100\n"
 "Last-Translator: Jan Psota <jasiupsota@gmail.com>\n"
 "Language-Team: polski <>\n"
 "Language: pl\n"
@@ -18,715 +18,742 @@ 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.5.5\n"
+"X-Generator: Poedit 1.8.7\n"
 "X-Language: pl_PL\n"
 
-#: cache.c:523
+#: cache.c:518
 msgid "Internal error in cache."
 msgstr "Wewnętrzny błąd w pamięci podręcznej."
 
-#: cache.c:941
+#: cache.c:928
 #, c-format
 msgid "failed to load names from %s: %s"
 msgstr "nie potrafię wczytać nazw z %s: %s"
 
-#: cache.c:967 dhcp.c:828
+#: cache.c:954 dhcp.c:867
 #, c-format
 msgid "bad address at %s line %d"
 msgstr "błędny adres w pliku %s, w linii %d"
 
-#: cache.c:1018 dhcp.c:844
+#: cache.c:1007 dhcp.c:883
 #, c-format
 msgid "bad name at %s line %d"
 msgstr "błędna nazwa w pliku %s, w linii %d"
 
-#: cache.c:1027 dhcp.c:919
+#: cache.c:1016 dhcp.c:958
 #, c-format
 msgid "read %s - %d addresses"
 msgstr "wczytałem %s - %d adresów"
 
-#: cache.c:1135
+#: cache.c:1129
 msgid "cleared cache"
 msgstr "wyczyszczono pamięć podręczną"
 
-#: cache.c:1164
+#: cache.c:1158
 #, c-format
 msgid "No IPv4 address found for %s"
 msgstr "Nie znalazłem adresu IPv4 komputera %s"
 
-#: cache.c:1242
+#: cache.c:1237
 #, c-format
 msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
 msgstr "%s to nazwa CNAME, nie przypisuję jej dzierżawie DHCP %s"
 
-#: cache.c:1266
+#: cache.c:1261
 #, c-format
 msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
 msgstr "nazwa %s nie została nadana dzierżawie DHCP %s, ponieważ nazwa istnieje w %s i ma już adres %s"
 
-#: cache.c:1421
+#: cache.c:1418
 #, c-format
 msgid "time %lu"
 msgstr "czas %lu"
 
-#: cache.c:1422
+#: cache.c:1419
 #, c-format
 msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
 msgstr "wielkość pamięci podręcznej: %d; %d z %d miejsc aktualnych wpisów użyto ponownie."
 
-#: cache.c:1424
+#: cache.c:1421
 #, c-format
 msgid "queries forwarded %u, queries answered locally %u"
 msgstr "%u zapytań przesłanych dalej, %u odpowiedzi udzielonych samodzielnie"
 
-#: cache.c:1427
+#: cache.c:1424
 #, c-format
 msgid "queries for authoritative zones %u"
 msgstr "zapytań do stref autorytatywnych %u"
 
-#: cache.c:1453
+#: cache.c:1450
 #, c-format
 msgid "server %s#%d: queries sent %u, retried or failed %u"
 msgstr "serwer %s#%d: %u zapytań wysłanych, %u ponowionych lub nieudanych"
 
-#: util.c:45
+#: util.c:47
 #, c-format
 msgid "failed to seed the random number generator: %s"
 msgstr "brak możliwości użycia generatora liczb losowych: %s"
 
-#: util.c:205
+#: util.c:224
 msgid "failed to allocate memory"
 msgstr "nie udało się przydzielić pamięci"
 
-#: util.c:250 option.c:601
+#: util.c:281 option.c:619
 msgid "could not get memory"
 msgstr "nie można dostać pamięci"
 
-#: util.c:260
+#: util.c:291
 #, c-format
 msgid "cannot create pipe: %s"
 msgstr "błąd podczas próby utworzenia potoku: %s"
 
-#: util.c:268
+#: util.c:299
 #, c-format
 msgid "failed to allocate %d bytes"
 msgstr "niemożliwość przydzielenia %d bajtów pamięci"
 
-#: util.c:437
+#: util.c:468
 #, c-format
 msgid "infinite"
 msgstr "nieskończona"
 
-#: option.c:332
+#: option.c:344
 msgid "Specify local address(es) to listen on."
 msgstr "Wskazanie adresów, na których należy nasłuchiwać."
 
-#: option.c:333
+#: option.c:345
 msgid "Return ipaddr for all hosts in specified domains."
 msgstr "Zwracanie adresu IP dla wszystkich hostów we wskazanych domenach."
 
-#: option.c:334
+#: option.c:346
 msgid "Fake reverse lookups for RFC1918 private address ranges."
 msgstr "Wyłączenie przekazywania zapytań odwrotnych dla prywatnych zakresów IP."
 
-#: option.c:335
+#: option.c:347
 msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
 msgstr "Traktowanie adresu IP jako NXDOMAIN (unieważnia ,,Verisign wildcard'')."
 
-#: option.c:336
+#: option.c:348
 #, c-format
 msgid "Specify the size of the cache in entries (defaults to %s)."
 msgstr "Wskazanie wielkości pamięci podręcznej (domyślnie: %s miejsc)."
 
-#: option.c:337
+#: option.c:349
 #, c-format
 msgid "Specify configuration file (defaults to %s)."
 msgstr "Wskazanie pliku konfiguracyjnego (domyślnie: %s)."
 
-#: option.c:338
+#: option.c:350
 msgid "Do NOT fork into the background: run in debug mode."
 msgstr "NIE twórz procesu potomnego w tle: działanie w trybie debugowania."
 
-#: option.c:339
+#: option.c:351
 msgid "Do NOT forward queries with no domain part."
 msgstr "Wyłączenie przekazywania zapytań bez podanej części domenowej."
 
-#: option.c:340
+#: option.c:352
 msgid "Return self-pointing MX records for local hosts."
 msgstr "Zwracanie samowskazującego rekordu MX dla lokalnych hostów."
 
-#: option.c:341
+#: option.c:353
 msgid "Expand simple names in /etc/hosts with domain-suffix."
 msgstr "Rozwijanie prostych nazw z /etc/hosts przyrostkiem domenowym."
 
-#: option.c:342
+#: option.c:354
 msgid "Don't forward spurious DNS requests from Windows hosts."
 msgstr "Wyłączenie przekazywania pozornych zapytań DNS z komputerów działających pod Windows."
 
-#: option.c:343
+#: option.c:355
 msgid "Enable DHCP in the range given with lease duration."
 msgstr "Włączenie serwera DHCP dla wskazanego zakresu adresów."
 
-#: option.c:344
+#: option.c:356
 #, c-format
 msgid "Change to this group after startup (defaults to %s)."
 msgstr "Po uruchomieniu zmiana grupy procesu na podaną (domyślnie: %s)."
 
-#: option.c:345
+#: option.c:357
 msgid "Set address or hostname for a specified machine."
 msgstr "Ustawienie adresu lub nazwy dla wskazanego komputera."
 
-#: option.c:346
+#: option.c:358
 msgid "Read DHCP host specs from file."
 msgstr "Wskazanie pliku z wartościami 'dhcp-host='."
 
-#: option.c:347
+#: option.c:359
 msgid "Read DHCP option specs from file."
 msgstr "Wskazanie pliku z wartościami 'dhcp-option='."
 
-#: option.c:348
+#: option.c:360
 msgid "Read DHCP host specs from a directory."
 msgstr "Odczyt specyfikacji hostów dla DHCP z katalogu."
 
-#: option.c:349
+#: option.c:361
 msgid "Read DHCP options from a directory."
 msgstr "Odczyt opcji DHCP z katalogu."
 
-#: option.c:350
+#: option.c:362
 msgid "Evaluate conditional tag expression."
 msgstr "Warunkowe ustawianie znaczników."
 
-#: option.c:351
+#: option.c:363
 #, c-format
 msgid "Do NOT load %s file."
 msgstr "NIE wczytywanie pliku %s."
 
-#: option.c:352
+#: option.c:364
 #, c-format
 msgid "Specify a hosts file to be read in addition to %s."
 msgstr "Wskazanie dodatkowego pliku 'hosts' oprócz %s."
 
-#: option.c:353
+#: option.c:365
 msgid "Read hosts files from a directory."
 msgstr "Odczyt pliku hostów z katalogu."
 
-#: option.c:354
+#: option.c:366
 msgid "Specify interface(s) to listen on."
 msgstr "Interfejsy, na których nasłuchiwać."
 
-#: option.c:355
+#: option.c:367
 msgid "Specify interface(s) NOT to listen on."
 msgstr "Interfejsy, na których NIE nasłuchiwać."
 
-#: option.c:356
+#: option.c:368
 msgid "Map DHCP user class to tag."
 msgstr "Przyporządkowanie znacznika w zależności od klasy użytkownika DHCP."
 
-#: option.c:357
+#: option.c:369
 msgid "Map RFC3046 circuit-id to tag."
 msgstr "Przyporządkowanie znacznika w zależności od numeru obwodu (w rozumieniu RFC3046)."
 
-#: option.c:358
+#: option.c:370
 msgid "Map RFC3046 remote-id to tag."
 msgstr "Przyporządkowanie znacznika w zależności od numeru agenta (w rozumieniu RFC3046)."
 
-#: option.c:359
+#: option.c:371
 msgid "Map RFC3993 subscriber-id to tag."
 msgstr "Przyporządkowanie znacznika w zależności od numeru subskrybenta (w rozumieniu RFC3993)."
 
-#: option.c:360
+#: option.c:372
 msgid "Don't do DHCP for hosts with tag set."
 msgstr "Wyłączenie DHCP dla hostów z określonym znacznikiem."
 
-#: option.c:361
+#: option.c:373
 msgid "Force broadcast replies for hosts with tag set."
 msgstr "Wymuszenie odpowiedzi w trybie rozgłoszeniowym dla hostów z określonym znacznikiem."
 
-#: option.c:362
+#: option.c:374
 msgid "Do NOT fork into the background, do NOT run in debug mode."
 msgstr "NIE twórz procesu potomnego w tle i NIE włączaj trybu debugowania."
 
-#: option.c:363
+#: option.c:375
 msgid "Assume we are the only DHCP server on the local network."
 msgstr "Zakładanie, że jesteśmy jedynym serwerem DHCP w sieci lokalnej."
 
-#: option.c:364
+#: option.c:376
 #, c-format
 msgid "Specify where to store DHCP leases (defaults to %s)."
 msgstr "Ścieżka przechowywania pliku dzierżaw DHCP (domyślnie: %s)."
 
-#: option.c:365
+#: option.c:377
 msgid "Return MX records for local hosts."
 msgstr "Włączenie zwracania rekordu MX dla hostów lokalnych."
 
-#: option.c:366
+#: option.c:378
 msgid "Specify an MX record."
 msgstr "Specyfikacja rekordu MX."
 
-#: option.c:367
+#: option.c:379
 msgid "Specify BOOTP options to DHCP server."
 msgstr "Określenie opcji BOOTP serwera DHCP."
 
-#: option.c:368
+#: option.c:380
 #, c-format
 msgid "Do NOT poll %s file, reload only on SIGHUP."
 msgstr "Wyłączenie obserwowania pliku %s; ponowne odczytywanie tylko po odebraniu sygnału SIGHUP."
 
-#: option.c:369
+#: option.c:381
 msgid "Do NOT cache failed search results."
 msgstr "Wyłączenie przechowywania w pamięci podręcznej wyników nieudanych wyszukiwań."
 
-#: option.c:370
+#: option.c:382
 #, c-format
 msgid "Use nameservers strictly in the order given in %s."
 msgstr "Odpytywanie serwerów nazw w kolejności ich wystąpienia w %s."
 
-#: option.c:371
+#: option.c:383
 msgid "Specify options to be sent to DHCP clients."
 msgstr "Specyfikacja opcji wysyłanej do klientów DHCP."
 
-#: option.c:372
+#: option.c:384
 msgid "DHCP option sent even if the client does not request it."
 msgstr "Opcja DHCP wysyłana nawet jeżeli klient o nią nie prosi."
 
-#: option.c:373
+#: option.c:385
 msgid "Specify port to listen for DNS requests on (defaults to 53)."
 msgstr "Wskazanie portu do nasłuchiwania zapytań DNS (domyślnie: 53)."
 
-#: option.c:374
+#: option.c:386
 #, c-format
 msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
 msgstr "Maksymalna obsługiwana wielkość pakietu EDNS.0 (domyślnie: %s)."
 
-#: option.c:375
+#: option.c:387
 msgid "Log DNS queries."
 msgstr "Włączenie spisywania zapytań DNS do logu."
 
-#: option.c:376
+#: option.c:388
 msgid "Force the originating port for upstream DNS queries."
 msgstr "Wymuszenie użycia wskazanego portu UDP do odpytywania nadrzędnych serwerów DNS i odbierania od nich odpowiedzi."
 
-#: option.c:377
+#: option.c:389
 msgid "Do NOT read resolv.conf."
 msgstr "Wyłączenie czytania pliku resolv.conf."
 
-#: option.c:378
+#: option.c:390
 #, c-format
 msgid "Specify path to resolv.conf (defaults to %s)."
 msgstr "Wskazanie położenia pliku resolv.conf (domyślnie: %s)."
 
-#: option.c:379
+#: option.c:391
 msgid "Specify path to file with server= options"
 msgstr "Wskazanie położenia pliku z opcjami server="
 
-#: option.c:380
+#: option.c:392
 msgid "Specify address(es) of upstream servers with optional domains."
 msgstr "Wskazywanie adresów serwerów nazw, opcjonalnie z przypisaniem do domeny."
 
-#: option.c:381
+#: option.c:393
 msgid "Specify address of upstream servers for reverse address queries"
 msgstr "Wskazanie serwerów nazw do odwrotnej translacji adresów."
 
-#: option.c:382
+#: option.c:394
 msgid "Never forward queries to specified domains."
 msgstr "Wyłączenie przekazywania zapytań do wskazanych domen."
 
-#: option.c:383
+#: option.c:395
 msgid "Specify the domain to be assigned in DHCP leases."
 msgstr "Wskazanie domeny dla serwera DHCP."
 
-#: option.c:384
+#: option.c:396
 msgid "Specify default target in an MX record."
 msgstr "Określenie domyślnego celu w rekordzie MX."
 
-#: option.c:385
+#: option.c:397
 msgid "Specify time-to-live in seconds for replies from /etc/hosts."
 msgstr "Określenie (w sekundach) czasu ważności odpowiedzi udzielonych na podstawie /etc/hosts (domyślnie 0)."
 
-#: option.c:386
+#: option.c:398
 msgid "Specify time-to-live in seconds for negative caching."
 msgstr "Określenie (w sekundach) czasu ważności negatywnych odpowiedzi."
 
-#: option.c:387
+#: option.c:399
 msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
 msgstr "Ograniczenie maksymalnego czasu ważności odpowiedzi (TTL) podawanego klientom [w sekundach]."
 
-#: option.c:388
+#: option.c:400
 msgid "Specify time-to-live ceiling for cache."
 msgstr "Określenie górnej granicy czasu ważności dla wpisów w pamięci podręcznej."
 
-#: option.c:389
+#: option.c:401
 msgid "Specify time-to-live floor for cache."
 msgstr "Określenie dolnej granicy czasu ważności dla wpisów w pamięci podręcznej."
 
-#: option.c:390
+#: option.c:402
 #, c-format
 msgid "Change to this user after startup. (defaults to %s)."
 msgstr "Zmiana użytkownika procesu na wskazanego (po uruchomieniu, domyślnie: %s)."
 
-#: option.c:391
+#: option.c:403
 msgid "Map DHCP vendor class to tag."
 msgstr "Przyporządkowanie znacznika w zależności od typu klienta DHCP."
 
-#: option.c:392
+#: option.c:404
 msgid "Display dnsmasq version and copyright information."
 msgstr "Wydrukowanie informacji o programie i ochronie praw autorskich."
 
-#: option.c:393
+#: option.c:405
 msgid "Translate IPv4 addresses from upstream servers."
 msgstr "Tłumaczenie adresów IPv4 z serwerów nadrzędnych."
 
-#: option.c:394
+#: option.c:406
 msgid "Specify a SRV record."
 msgstr "Określenie rekordu SRV."
 
-#: option.c:395
-msgid "Display this message. Use --help dhcp for known DHCP options."
-msgstr "Wyświetla ten komunikat. Użyj '--help dhcp' chcąc przejrzeć listę opcji DHCP (dhcp-option=xxx,...)."
+#: option.c:407
+msgid "Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."
+msgstr "Wyświetla ten komunikat. Chcąc przejrzeć listę dostępnych opcji DHCP użyj '--help dhcp' lub '--help dhcp6' ."
 
-#: option.c:396
+#: option.c:408
 #, c-format
 msgid "Specify path of PID file (defaults to %s)."
 msgstr "Określenie ścieżki do pliku PID (domyślnie: %s)."
 
-#: option.c:397
+#: option.c:409
 #, c-format
 msgid "Specify maximum number of DHCP leases (defaults to %s)."
 msgstr "Maksymalna liczba dzierżaw DHCP (domyślnie: %s)."
 
-#: option.c:398
+#: option.c:410
 msgid "Answer DNS queries based on the interface a query was sent to."
 msgstr "Uzależnienie odpowiedzi DNS od interfejsu, na którym odebrano zapytanie (wygodne dla serwerów kilku podsieci z różnymi adresami w /etc/hosts)."
 
-#: option.c:399
+#: option.c:411
 msgid "Specify TXT DNS record."
 msgstr "Specyfikacja rekordu DNS TXT."
 
-#: option.c:400
+#: option.c:412
 msgid "Specify PTR DNS record."
 msgstr "Specyfikacja rekordu DNS PTR."
 
-#: option.c:401
+#: option.c:413
 msgid "Give DNS name to IPv4 address of interface."
 msgstr "Zwraca nazwę domenową powiązaną z adresem interfejsu sieciowego."
 
-#: option.c:402
+#: option.c:414
 msgid "Bind only to interfaces in use."
 msgstr "Nasłuchiwanie tylko na wykorzystywanych interfejsach (umożliwia uruchomienie osobnych serwerów dla różnych kart)."
 
-#: option.c:403
+#: option.c:415
 #, c-format
 msgid "Read DHCP static host information from %s."
 msgstr "Wczytanie przyporządkowań adresów z %s."
 
-#: option.c:404
+#: option.c:416
 msgid "Enable the DBus interface for setting upstream servers, etc."
 msgstr "Włączenie używania interfejsu DBus do informowania o zmianach konfiguracji."
 
-#: option.c:405
+#: option.c:417
 msgid "Do not provide DHCP on this interface, only provide DNS."
 msgstr "Uruchomienie na wskazanym interfejsie tylko DNS-a, bez usług DHCP i TFTP."
 
-#: option.c:406
+#: option.c:418
 msgid "Enable dynamic address allocation for bootp."
 msgstr "Włączenie dynamicznego przydzielania adresów dla klientów BOOTP."
 
-#: option.c:407
+#: option.c:419
 msgid "Map MAC address (with wildcards) to option set."
 msgstr "Przyporządkowanie znacznika w zależności od adresu MAC (można używać uogólnień: *)."
 
-#: option.c:408
+#: option.c:420
 msgid "Treat DHCP requests on aliases as arriving from interface."
 msgstr "Traktowanie żądań DHCP odebranych na interfejsach alias, ..., jako odebranych na iface."
 
-#: option.c:409
+#: option.c:421
 msgid "Disable ICMP echo address checking in the DHCP server."
 msgstr "Pominięcie sprawdzania za pomocą ICMP niezajętości adresu przed jego wydzierżawieniem."
 
-#: option.c:410
+#: option.c:422
 msgid "Shell script to run on DHCP lease creation and destruction."
 msgstr "Skrypt powłoki uruchamiany po przyznaniu lub zwolnieniu adresu."
 
-#: option.c:411
+#: option.c:423
 msgid "Lua script to run on DHCP lease creation and destruction."
 msgstr "Skrypt Lua uruchamiany po przyznaniu lub zwolnieniu adresu."
 
-#: option.c:412
+#: option.c:424
 msgid "Run lease-change scripts as this user."
 msgstr "Wskazanie użytkownika z którego uprawnieniami będą uruchamiane skrypty."
 
-#: option.c:413
+#: option.c:425
+msgid "Call dhcp-script with changes to local ARP table."
+msgstr "Wywoływanie dhcp-script w reakcji na zmiany w tablicy ARP."
+
+#: option.c:426
 msgid "Read configuration from all the files in this directory."
 msgstr "Wczytanie wszystkich plików ze wskazanego katalogu jako konfiguracyjnych."
 
-#: option.c:414
+#: option.c:427
 msgid "Log to this syslog facility or file. (defaults to DAEMON)"
 msgstr "Wskazanie kanału syslog-a do którego mają trafiać komunikaty (domyślnie: DAEMON)"
 
-#: option.c:415
+#: option.c:428
 msgid "Do not use leasefile."
 msgstr "Nieużywanie bazy dzierżaw."
 
-#: option.c:416
+#: option.c:429
 #, c-format
 msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
 msgstr "Maksymalna liczba jednocześnie obsługiwanych zapytań DNS (domyślnie: %s)"
 
-#: option.c:417
+#: option.c:430
 #, c-format
 msgid "Clear DNS cache when reloading %s."
 msgstr "Czyszczenie pamięci podręcznej serwera nazw w przypadku ponownego odczytu %s."
 
-#: option.c:418
+#: option.c:431
 msgid "Ignore hostnames provided by DHCP clients."
 msgstr "Nie zwracanie uwagi na nazwę podawaną przez klienta w przypadku dopasowania wszystkich wymienionych znaczników."
 
-#: option.c:419
+#: option.c:432
 msgid "Do NOT reuse filename and server fields for extra DHCP options."
 msgstr "Wyłączenie oszczędzania miejsca w pakiecie DHCP przez przesuwanie pól servername i filename do opcji DHCP. Wymusza prostszy tryb budowy pakietu rozwiązując problemy z nieprzystosowanymi klientami DHCP."
 
-#: option.c:420
+#: option.c:433
 msgid "Enable integrated read-only TFTP server."
 msgstr "Włączenie wbudowanego serwera TFTP (tylko do wysyłania)."
 
-#: option.c:421
+#: option.c:434
 msgid "Export files by TFTP only from the specified subtree."
 msgstr "Ograniczenie działania serwera TFTP do wskazanego katalogu i podkatalogów. Nazwy z .. są odrzucane, / odnosi się do wskazanego katalogu."
 
-#: option.c:422
-msgid "Add client IP address to tftp-root."
+#: option.c:435
+#, fuzzy
+msgid "Add client IP or hardware address to tftp-root."
 msgstr "Doklejanie adresu IP klienta do głównego katalogu TFTP. Jeżeli wynikowy katalog nie istnieje, nadal wykorzystuje się tftp-root."
 
-#: option.c:423
+#: option.c:436
 msgid "Allow access only to files owned by the user running dnsmasq."
 msgstr "Ograniczenie dostępu do plików przez TFTP do tych, których właścicielem jest użytkownik uruchamiający dnsmasq-a."
 
-#: option.c:424
+#: option.c:437
 msgid "Do not terminate the service if TFTP directories are inaccessible."
 msgstr "Nieprzerywanie działania serwisu mimo braku dostępu do katalogów TFTP."
 
-#: option.c:425
-#, c-format
-msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+#: option.c:438
+#, fuzzy, c-format
+msgid "Maximum number of concurrent TFTP transfers (defaults to %s)."
 msgstr "Maksymalna liczba jednocześnie obsługiwanych połączeń TFTP (domyślnie %s)."
 
-#: option.c:426
+#: option.c:439
+msgid "Maximum MTU to use for TFTP transfers."
+msgstr "Ograniczenie MTU w komunikacji TFTP."
+
+#: option.c:440
 msgid "Disable the TFTP blocksize extension."
 msgstr "Wyłączenie możliwości negocjowania wielkości bloku dla przesyłów przez TFTP."
 
-#: option.c:427
+#: option.c:441
 msgid "Convert TFTP filenames to lowercase"
 msgstr "Konwertowanie nazw plików żądanych przez TFTP do małych liter"
 
-#: option.c:428
+#: option.c:442
 msgid "Ephemeral port range for use by TFTP transfers."
 msgstr "Wskazanie zakresu portów do użytku TFTP."
 
-#: option.c:429
+#: option.c:443
 msgid "Extra logging for DHCP."
 msgstr "Włączenie spisywania w logu operacji DHCP."
 
-#: option.c:430
+#: option.c:444
 msgid "Enable async. logging; optionally set queue length."
 msgstr "Włączenie asynchronicznego zapisywania do logu z ewentualnym wskazaniem długości kolejki."
 
-#: option.c:431
+#: option.c:445
 msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
 msgstr "Odfiltrowywanie adresów wskazujących na komputery w sieciach wewnętrznych spośród odpowiedzi od zewnętrznych serwerów DNS."
 
-#: option.c:432
+#: option.c:446
 msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
 msgstr "Zezwolenie na przekazywanie odpowiedzi w klasie 127.0.0.0/8. Dla serwerów RBL."
 
-#: option.c:433
+#: option.c:447
 msgid "Inhibit DNS-rebind protection on this domain."
 msgstr "Dezaktywacja zabezpieczenia przed atakami DNS-rebind dla wskazanych domen."
 
-#: option.c:434
+#: option.c:448
 msgid "Always perform DNS queries to all servers."
 msgstr "Jednoczesne odpytywanie wszystkich serwerów nadrzędnych; klientowi przekazywana jest pierwsza odpowiedź."
 
-#: option.c:435
+#: option.c:449
 msgid "Set tag if client includes matching option in request."
 msgstr "Ustawienie znacznika jeżeli w żądaniu DHCP pojawi się wskazana opcja, ewentualnie o konkretnej wartości."
 
-#: option.c:436
+#: option.c:450
 msgid "Use alternative ports for DHCP."
 msgstr "Użycie alternatywnych portów dla usługi DHCP."
 
-#: option.c:437
+#: option.c:451
 msgid "Specify NAPTR DNS record."
 msgstr "Specyfikacja rekordu DNS NAPTR."
 
-#: option.c:438
+#: option.c:452
 msgid "Specify lowest port available for DNS query transmission."
 msgstr "Ustawienie dolnej granicy numerów portów do przesyłania zapytań DNS."
 
-#: option.c:439
+#: option.c:453
+msgid "Specify highest port available for DNS query transmission."
+msgstr "Ograniczenie najwyższego numeru portu dla transmisji zapytań DNS."
+
+#: option.c:454
 msgid "Use only fully qualified domain names for DHCP clients."
 msgstr "Przechowywanie w serwerze DNS dnsmasq-a tylko w pełni kwalifikowanych nazw zgłaszanych przez klientów DHCP."
 
-#: option.c:440
+#: option.c:455
 msgid "Generate hostnames based on MAC address for nameless clients."
 msgstr "Generowanie nazw na podstawie MAC-adresów dla klientów bez nazwy."
 
-#: option.c:441
+#: option.c:456
 msgid "Use these DHCP relays as full proxies."
 msgstr "Traktowanie wskazanych serwerów pośredniczących DHCP jako działających w trybie \"pełnomocnika\" (full-proxy)."
 
-#: option.c:442
+#: option.c:457
 msgid "Relay DHCP requests to a remote server"
 msgstr "Przekazywanie żądań DHCP do zdalnego serwera"
 
-#: option.c:443
+#: option.c:458
 msgid "Specify alias name for LOCAL DNS name."
 msgstr "Wskazanie synonimu nazwy komputera lokalnego - znanego z /etc/hosts albo z DHCP."
 
-#: option.c:444
+#: option.c:459
 msgid "Prompt to send to PXE clients."
 msgstr "Zgłoszenie wysyłane klientom PXE."
 
-#: option.c:445
+#: option.c:460
 msgid "Boot service for PXE menu."
 msgstr "Składnik menu PXE (--> man)."
 
-#: option.c:446
+#: option.c:461
 msgid "Check configuration syntax."
 msgstr "Sprawdzenie składni."
 
-#: option.c:447
+#: option.c:462
 msgid "Add requestor's MAC address to forwarded DNS queries."
 msgstr "Przekazywanie MAC-adresu komputera pytającego w ruchu wychodzącym DNS."
 
-#: option.c:448
-msgid "Add requestor's IP subnet to forwarded DNS queries."
-msgstr "Zamieszczanie adresu IP pytającego w przekazywanych zapytaniach DNS."
+#: option.c:463
+msgid "Add specified IP subnet to forwarded DNS queries."
+msgstr "Zamieszczanie wskazanego adresu podsieci w przekazywanych zapytaniach DNS."
 
-#: option.c:449
+#: option.c:464
+msgid "Add client identification to forwarded DNS queries."
+msgstr "Zamieszczanie identyfikacji pytającego w przekazywanych zapytaniach DNS."
+
+#: option.c:465
 msgid "Proxy DNSSEC validation results from upstream nameservers."
 msgstr "Przekazywanie wyników weryfikacji DNSSEC z serwerów nadrzędnych."
 
-#: option.c:450
+#: option.c:466
 msgid "Attempt to allocate sequential IP addresses to DHCP clients."
 msgstr "Zmiana sposobu przydzielania adresów IP na sekwencyjny."
 
-#: option.c:451
+#: option.c:467
 msgid "Copy connection-track mark from queries to upstream connections."
 msgstr "Zachowanie znacznika połączenia z odebranego zapytania DNS w ruchu zewnętrznym."
 
-#: option.c:452
+#: option.c:468
 msgid "Allow DHCP clients to do their own DDNS updates."
 msgstr "Zezwolenie klientom DHCP na uaktualnianie DDNS-ów."
 
-#: option.c:453
+#: option.c:469
 msgid "Send router-advertisements for interfaces doing DHCPv6"
 msgstr "Załączenie anonsowania (RA) na interfejsach serwujących DHCPv6"
 
-#: option.c:454
+#: option.c:470
 msgid "Specify DUID_EN-type DHCPv6 server DUID"
 msgstr "Określenie DHCPv6 DUID"
 
-#: option.c:455
+#: option.c:471
 msgid "Specify host (A/AAAA and PTR) records"
 msgstr "Określenie rekordów A/AAAA i PTR"
 
-#: option.c:456
+#: option.c:472
 msgid "Specify arbitrary DNS resource record"
 msgstr "Określenie rekordu TXT"
 
-#: option.c:457
+#: option.c:473
 msgid "Bind to interfaces in use - check for new interfaces"
 msgstr "Dynamiczne podpinanie do interfejsów sieciowych"
 
-#: option.c:458
+#: option.c:474
 msgid "Export local names to global DNS"
 msgstr "Eksportowanie lokalnych nazw hostów do globalnego DNS-a"
 
-#: option.c:459
+#: option.c:475
 msgid "Domain to export to global DNS"
 msgstr "Domena pod którą będą eksportowane lokalne nazwy"
 
-#: option.c:460
+#: option.c:476
 msgid "Set TTL for authoritative replies"
 msgstr "Określenie TTL dla odpowiedzi autorytatywnych"
 
-#: option.c:461
-msgid "Set authoritive zone information"
+#: option.c:477
+#, fuzzy
+msgid "Set authoritative zone information"
 msgstr "Określenie danych strefy autorytatywnej (SOA)"
 
-#: option.c:462
+#: option.c:478
 msgid "Secondary authoritative nameservers for forward domains"
 msgstr "Pomocnicze serwery autorytatywne dla forwardowanych domen"
 
-#: option.c:463
+#: option.c:479
 msgid "Peers which are allowed to do zone transfer"
 msgstr "Wskazanie serwerów uprawnionych do transferu stref"
 
-#: option.c:464
+#: option.c:480
 msgid "Specify ipsets to which matching domains should be added"
 msgstr "Wyszczególnienie ipset-ów, do których będą dopisywane adresy IP leżące we wskazanych domenach"
 
-#: option.c:465
+#: option.c:481
 msgid "Specify a domain and address range for synthesised names"
 msgstr "Wskazanie domeny i zakresu adresów dla generowanych nazw"
 
-#: option.c:466
+#: option.c:482
 msgid "Activate DNSSEC validation"
 msgstr "Uaktywnienie walidacji DNSSEC"
 
-#: option.c:467
+#: option.c:483
 msgid "Specify trust anchor key digest."
 msgstr "Wskazanie punktu zaufania dla uwierzytelniania DNSSEC."
 
-#: option.c:468
+#: option.c:484
 msgid "Disable upstream checking for DNSSEC debugging."
 msgstr "Akceptowanie nieuwiarygodnionych odpowiedzi DNSSEC (ustawienie bitu CD w zapytaniach)."
 
-#: option.c:469
+#: option.c:485
 msgid "Ensure answers without DNSSEC are in unsigned zones."
 msgstr "Upewnianie się, że odpowiedzi bez DNSSEC pochodzą ze stref niepodpisanych."
 
-#: option.c:470
+#: option.c:486
 msgid "Don't check DNSSEC signature timestamps until first cache-reload"
 msgstr "Wyłączenie sprawdzania sygnatur czasowych DNSSEC do pierwszego przeładowania pamięci podręcznej."
 
-#: option.c:471
+#: option.c:487
 msgid "Timestamp file to verify system clock for DNSSEC"
 msgstr "Plik znacznika czasu do weryfikacji zegara systemowego dla potrzeb DNSSEC."
 
-#: option.c:473
+#: option.c:489
 msgid "Specify DHCPv6 prefix class"
 msgstr "Określenie prefiksu klasy DHCPv6"
 
-#: option.c:475
-msgid "Set priority, resend-interval and router-lifetime"
+#: option.c:491
+#, fuzzy
+msgid "Set MTU, priority, resend-interval and router-lifetime"
 msgstr "Ustawianie priorytetu, okresu rozsyłania oraz czasu życia rutera (RA)."
 
-#: option.c:476
+#: option.c:492
 msgid "Do not log routine DHCP."
 msgstr "Wyłączenie logowania zwyczajnego DHCP."
 
-#: option.c:477
+#: option.c:493
 msgid "Do not log routine DHCPv6."
 msgstr "Wyłączenie logowania zwyczajnego DHCPv6."
 
-#: option.c:478
+#: option.c:494
 msgid "Do not log RA."
 msgstr "Wyłączenie logowania RA."
 
-#: option.c:479
-msgid "Accept queries only from directly-connected networks"
+#: option.c:495
+msgid "Accept queries only from directly-connected networks."
 msgstr "Akceptowanie zapytań wyłącznie z sieci podpiętych bezpośrednio."
 
-#: option.c:480
-msgid "Detect and remove DNS forwarding loops"
+#: option.c:496
+msgid "Detect and remove DNS forwarding loops."
 msgstr "Wykrywanie i usuwanie pętli zapytań DNS."
 
-#: option.c:481
+#: option.c:497
 msgid "Ignore DNS responses containing ipaddr."
 msgstr "Ignorowanie odpowiedzi DNS zawierających ipaddr."
 
-#: option.c:683
+#: option.c:498
+msgid "Set TTL in DNS responses with DHCP-derived addresses."
+msgstr "Ustawienie TTL w odpowiedziach DNS dla adresów przydzielonych przez DHCP."
+
+#: option.c:499
+msgid "Delay DHCP replies for at least number of seconds."
+msgstr ""
+
+#: option.c:703
 #, c-format
 msgid ""
 "Usage: dnsmasq [options]\n"
@@ -735,312 +762,320 @@ msgstr ""
 "Użycie: dnsmasq [opcje]\n"
 "\n"
 
-#: option.c:685
+#: option.c:705
 #, c-format
 msgid "Use short options only on the command line.\n"
 msgstr "W tym systemie w linii poleceń można używać wyłącznie jednoliterowych opcji.\n"
 
-#: option.c:687
+#: option.c:707
 #, c-format
 msgid "Valid options are:\n"
 msgstr "Dostępne opcje:\n"
 
-#: option.c:744 option.c:748
+#: option.c:754 option.c:868
+msgid "bad address"
+msgstr "zły adres"
+
+#: option.c:779 option.c:783
 msgid "bad port"
 msgstr "nieprawidłowy numer portu"
 
-#: option.c:775 option.c:807
+#: option.c:797 option.c:826 option.c:861
 msgid "interface binding not supported"
 msgstr "nie ma możliwości dowiązywania do interfejsu"
 
-#: option.c:784 option.c:3575
+#: option.c:821 option.c:856
+msgid "interface can only be specified once"
+msgstr ""
+
+#: option.c:835 option.c:3809
 msgid "bad interface name"
 msgstr "nieprawidłowa nazwa interfejsu"
 
-#: option.c:814
-msgid "bad address"
-msgstr "zły adres"
-
-#: option.c:996
+#: option.c:1062
 msgid "unsupported encapsulation for IPv6 option"
 msgstr "nieobsługiwany rodzaj enkapsulacji opcji IPv6"
 
-#: option.c:1010
+#: option.c:1076
 msgid "bad dhcp-option"
 msgstr "błąd w dhcp-option"
 
-#: option.c:1078
+#: option.c:1144
 msgid "bad IP address"
 msgstr "zły adres IP"
 
-#: option.c:1081 option.c:1219 option.c:2893
+#: option.c:1147 option.c:1286 option.c:3079
 msgid "bad IPv6 address"
 msgstr "zły adres IPv6"
 
-#: option.c:1246 option.c:1340
+#: option.c:1240
+msgid "bad IPv4 address"
+msgstr "nieprawidłowy adres IPv4"
+
+#: option.c:1313 option.c:1407
 msgid "bad domain in dhcp-option"
 msgstr "nieprawidłowa nazwa domeny w dhcp-option"
 
-#: option.c:1378
+#: option.c:1445
 msgid "dhcp-option too long"
 msgstr "zbyt długa dhcp-option (>255 znaków)"
 
-#: option.c:1385
+#: option.c:1452
 msgid "illegal dhcp-match"
 msgstr "niedopuszczalne dhcp-match"
 
-#: option.c:1447
+#: option.c:1514
 msgid "illegal repeated flag"
 msgstr "wielokrotne użycie opcji niedozwolone (pojawiła się wcześniej w linii poleceń)"
 
-#: option.c:1455
+#: option.c:1522
 msgid "illegal repeated keyword"
 msgstr "wielokrotne użycie opcji niedozwolone (pojawiła się wsześniej w pliku konfiguracyjnym)"
 
-#: option.c:1520 option.c:4191
+#: option.c:1593 option.c:4443
 #, c-format
 msgid "cannot access directory %s: %s"
 msgstr "brak dostępu do katalogu %s: %s"
 
-#: option.c:1566 tftp.c:493
+#: option.c:1639 tftp.c:537
 #, c-format
 msgid "cannot access %s: %s"
 msgstr "brak dostępu do %s: %s"
 
-#: option.c:1618
+#: option.c:1727
 msgid "setting log facility is not possible under Android"
 msgstr "zmiana log-facility w systemie Android nie jest możliwa"
 
-#: option.c:1627
+#: option.c:1736
 msgid "bad log facility"
 msgstr "nierozpoznany znacznik logów"
 
-#: option.c:1680
+#: option.c:1789
 msgid "bad MX preference"
 msgstr "nieprawidłowa wartość preferencji MX"
 
-#: option.c:1685
+#: option.c:1794
 msgid "bad MX name"
 msgstr "nieprawidłowa nazwa MX"
 
-#: option.c:1699
+#: option.c:1808
 msgid "bad MX target"
 msgstr "nieprawidłowa wartość celu MX"
 
-#: option.c:1711
+#: option.c:1820
 msgid "cannot run scripts under uClinux"
 msgstr "w uClinuksie nie ma możliwości uruchamiania skryptów"
 
-#: option.c:1713
+#: option.c:1822
 msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
 msgstr "żeby mieć możliwość używania skryptów wywoływanych przy zmianie dzierżawy, przekompiluj dnsmasq-a z włączoną flagą HAVE_SCRIPT"
 
-#: option.c:1717
+#: option.c:1826
 msgid "recompile with HAVE_LUASCRIPT defined to enable Lua scripts"
 msgstr "używanie skryptów Lua, wymaga skompilowania dnsmasq-a z flagą HAVE_LUASCRIPT"
 
-#: option.c:1973 option.c:2018 option.c:2074
+#: option.c:2095 option.c:2106 option.c:2143 option.c:2199 option.c:2482
 msgid "bad prefix"
 msgstr "zła maska"
 
-#: option.c:2355
+#: option.c:2504
 msgid "recompile with HAVE_IPSET defined to enable ipset directives"
 msgstr "chcąc korzystać z ipsets przekompiluj dnsmasq-a z HAVE_IPSET"
 
-#: option.c:2548
+#: option.c:2713
 msgid "bad port range"
 msgstr "nieprawidłowy zakres numerów portów"
 
-#: option.c:2564
+#: option.c:2739
 msgid "bad bridge-interface"
 msgstr "nieprawidłowa nazwa urządzenia w bridge-interface"
 
-#: option.c:2624
+#: option.c:2807
 msgid "only one tag allowed"
 msgstr "można wskazać tylko jeden znacznik sieci"
 
-#: option.c:2644 option.c:2656 option.c:2764 option.c:2805
+#: option.c:2827 option.c:2839 option.c:2948 option.c:2953 option.c:2992
 msgid "bad dhcp-range"
 msgstr "nieprawidłowy zakres dhcp-range"
 
-#: option.c:2671
+#: option.c:2854
 msgid "inconsistent DHCP range"
 msgstr "niespójny zakres adresów DHCP"
 
-#: option.c:2732
+#: option.c:2916
 msgid "prefix length must be exactly 64 for RA subnets"
 msgstr "długość prefiksu musi wynosić dokładnie 64 dla podsieci RA"
 
-#: option.c:2734
+#: option.c:2918
 msgid "prefix length must be exactly 64 for subnet constructors"
 msgstr "długość prefiksu musi wynosić dokładnie 64 dla konstruktorów podsieci"
 
-#: option.c:2738
+#: option.c:2922
 msgid "prefix length must be at least 64"
 msgstr "długość prefiksu musi wynosić co najmniej 64"
 
-#: option.c:2741
+#: option.c:2925
 msgid "inconsistent DHCPv6 range"
 msgstr "niespójny zakres adresów DHCPv6"
 
-#: option.c:2752
+#: option.c:2936
 msgid "prefix must be zero with \"constructor:\" argument"
 msgstr "prefiks musi wynosić zero z argumentem \"constructor:\""
 
-#: option.c:2863 option.c:2911
+#: option.c:3049 option.c:3097
 msgid "bad hex constant"
 msgstr "zapis niezgodny z formatem szesnastkowym"
 
-#: option.c:2885
+#: option.c:3071
 msgid "cannot match tags in --dhcp-host"
 msgstr "--dhcp-host nie dopuszcza dopasowywania na podstawie znaczników"
 
-#: option.c:2933
+#: option.c:3119
 #, c-format
 msgid "duplicate dhcp-host IP address %s"
 msgstr "powtórzony adres IP %s w specyfikacji dhcp-host"
 
-#: option.c:2991
+#: option.c:3177
 msgid "bad DHCP host name"
 msgstr "niedopuszczalna nazwa komputera w dhcp-host"
 
-#: option.c:3073
+#: option.c:3259
 msgid "bad tag-if"
 msgstr "nieprawidłowa składnia 'tag-if'"
 
-#: option.c:3397 option.c:3791
+#: option.c:3616 option.c:4039
 msgid "invalid port number"
 msgstr "nieprawidłowy numer portu"
 
-#: option.c:3459
+#: option.c:3678
 msgid "bad dhcp-proxy address"
 msgstr "zły adres dhcp-proxy"
 
-#: option.c:3485
+#: option.c:3704
 msgid "Bad dhcp-relay"
 msgstr "zły dhcp-relay"
 
-#: option.c:3511
+#: option.c:3745
 msgid "bad RA-params"
 msgstr "nieprawidłowe argumenty RA"
 
-#: option.c:3520
+#: option.c:3754
 msgid "bad DUID"
 msgstr "zły DUID"
 
-#: option.c:3562
+#: option.c:3796
 msgid "invalid alias range"
 msgstr "nieprawidłowy zakres adresów w --alias"
 
-#: option.c:3616
+#: option.c:3850 option.c:3862
 msgid "bad CNAME"
 msgstr "zła CNAME"
 
-#: option.c:3621
+#: option.c:3866
 msgid "duplicate CNAME"
 msgstr "powtórzona CNAME"
 
-#: option.c:3641
+#: option.c:3889
 msgid "bad PTR record"
 msgstr "nieprawidłowy zapis rekordu PTR"
 
-#: option.c:3672
+#: option.c:3920
 msgid "bad NAPTR record"
 msgstr "nieprawidłowy zapis rekordu NAPTR"
 
-#: option.c:3706
+#: option.c:3954
 msgid "bad RR record"
 msgstr "nieprawidłowy zapis rekordu RR"
 
-#: option.c:3736
+#: option.c:3984
 msgid "bad TXT record"
 msgstr "nieprawidłowy zapis rekordu TXT"
 
-#: option.c:3777
+#: option.c:4025
 msgid "bad SRV record"
 msgstr "nieprawidłowy zapis rekordu SRV"
 
-#: option.c:3784
+#: option.c:4032
 msgid "bad SRV target"
 msgstr "nieprawidłowa wartość celu SRV"
 
-#: option.c:3798
+#: option.c:4046
 msgid "invalid priority"
 msgstr "nieprawidłowy priorytet"
 
-#: option.c:3805
+#: option.c:4049
 msgid "invalid weight"
 msgstr "nieprawidłowa waga"
 
-#: option.c:3829
+#: option.c:4073
 msgid "Bad host-record"
 msgstr "nieprawidłowy zapis host-record"
 
-#: option.c:3846
+#: option.c:4097
 msgid "Bad name in host-record"
 msgstr "niedopuszczalna nazwa w host-record"
 
-#: option.c:3911
+#: option.c:4162
 msgid "bad trust anchor"
 msgstr "nieprawidłowa specyfikacja punktu zaufania"
 
-#: option.c:3925
+#: option.c:4176
 msgid "bad HEX in trust anchor"
 msgstr "zły zapis szesnastkowy"
 
-#: option.c:3935
+#: option.c:4186
 msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"
 msgstr "nieobsługiwana opcja (sprawdź, czy obsługa DHCP/TFTP/DNSSEC/DBus została wkompilowana)"
 
-#: option.c:3994
+#: option.c:4246
 msgid "missing \""
 msgstr "brakuje \""
 
-#: option.c:4051
+#: option.c:4303
 msgid "bad option"
 msgstr "nieprawidłowa opcja"
 
-#: option.c:4053
+#: option.c:4305
 msgid "extraneous parameter"
 msgstr "nadwyżkowy parametr"
 
-#: option.c:4055
+#: option.c:4307
 msgid "missing parameter"
 msgstr "brak parametru"
 
-#: option.c:4057
+#: option.c:4309
 msgid "illegal option"
 msgstr "niedopuszczalna opcja"
 
-#: option.c:4064
+#: option.c:4316
 msgid "error"
 msgstr "błąd"
 
-#: option.c:4066
+#: option.c:4318
 #, c-format
 msgid " at line %d of %s"
 msgstr " w linii %d pliku %s"
 
-#: option.c:4081 option.c:4328 option.c:4364
+#: option.c:4333 option.c:4580 option.c:4616
 #, c-format
 msgid "read %s"
 msgstr "przeczytałem %s"
 
-#: option.c:4144 option.c:4267 tftp.c:667
+#: option.c:4396 option.c:4519 tftp.c:715
 #, c-format
 msgid "cannot read %s: %s"
 msgstr "błąd odczytu z pliku %s: %s"
 
-#: option.c:4430
+#: option.c:4688
 msgid "junk found in command line"
 msgstr "jakieś śmieci w linii poleceń"
 
-#: option.c:4465
+#: option.c:4729
 #, c-format
 msgid "Dnsmasq version %s  %s\n"
 msgstr "Dnsmasq, wersja %s  %s\n"
 
-#: option.c:4466
+#: option.c:4730
 #, c-format
 msgid ""
 "Compile time options: %s\n"
@@ -1049,458 +1084,501 @@ msgstr ""
 "Wkompilowane opcje %s\n"
 "\n"
 
-#: option.c:4467
+#: option.c:4731
 #, c-format
 msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
 msgstr "Autor nie daje ŻADNYCH GWARANCJI egzekwowalnych prawnie.\n"
 
-#: option.c:4468
+#: option.c:4732
 #, c-format
 msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
 msgstr "Dnsmasq jest wolnym oprogramowaniem, możesz go rozprowadzać\n"
 
-#: option.c:4469
+#: option.c:4733
 #, c-format
 msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
 msgstr "na warunkach określonych w GNU General Public Licence, w wersji 2 lub 3.\n"
 
-#: option.c:4480
+#: option.c:4744
 msgid "try --help"
 msgstr "spróbuj: --help"
 
-#: option.c:4482
+#: option.c:4746
 msgid "try -w"
 msgstr "spróbuj: -w"
 
-#: option.c:4484
+#: option.c:4748
 #, c-format
 msgid "bad command line options: %s"
 msgstr "nieprawidłowa opcja w linii poleceń %s"
 
-#: option.c:4541
+#: option.c:4818
+#, c-format
+msgid "CNAME loop involving %s"
+msgstr ""
+
+#: option.c:4854
 #, c-format
 msgid "cannot get host-name: %s"
 msgstr "nie można pobrać nazwy hosta: %s"
 
-#: option.c:4569
+#: option.c:4882
 msgid "only one resolv.conf file allowed in no-poll mode."
 msgstr "w trybie no-poll można wskazać najwyżej jeden plik resolv.conf."
 
-#: option.c:4579
+#: option.c:4892
 msgid "must have exactly one resolv.conf to read domain from."
 msgstr "musisz mieć dokładnie jeden plik resolv.conf do odczytu domen."
 
-#: option.c:4582 network.c:1507 dhcp.c:777
+#: option.c:4895 network.c:1623 dhcp.c:816
 #, c-format
 msgid "failed to read %s: %s"
 msgstr "nie udało się odczytać %s: %s"
 
-#: option.c:4599
+#: option.c:4912
 #, c-format
 msgid "no search directive found in %s"
 msgstr "brak wytycznych wyszukiwania w %s"
 
-#: option.c:4620
+#: option.c:4933
 msgid "there must be a default domain when --dhcp-fqdn is set"
 msgstr "w przypadku używania --dhcp-fqdn trzeba wskazać domyślną domenę"
 
-#: option.c:4629
+#: option.c:4942
 msgid "syntax check OK"
 msgstr "składnia sprawdzona, jest prawidłowa"
 
-#: forward.c:111
+#: forward.c:102
 #, c-format
 msgid "failed to send packet: %s"
 msgstr "wysyłanie pakietu nie powiodło się: %s"
 
-#: forward.c:591
+#: forward.c:598
 msgid "discarding DNS reply: subnet option mismatch"
 msgstr "odrzucam odpowiedź DNS: nie zgadza się specyfikacja podsieci"
 
-#: forward.c:614
+#: forward.c:652
 #, c-format
 msgid "nameserver %s refused to do a recursive query"
 msgstr "serwer nazw %s odmawia wykonania zapytania rekurencyjnego"
 
-#: forward.c:646
+#: forward.c:684
 #, c-format
 msgid "possible DNS-rebind attack detected: %s"
 msgstr "prawdopodobnie wykryto atak DNS-rebind: %s"
 
-#: forward.c:1209 forward.c:1815
+#: forward.c:870
+#, c-format
+msgid "reducing DNS packet size for nameserver %s to %d"
+msgstr ""
+
+#: forward.c:1266 forward.c:1704
 msgid "Ignoring query from non-local network"
 msgstr "Ignorowanie zapytań z sieci pozalokalnych."
 
-#: forward.c:2286
+#: forward.c:2184
 #, c-format
 msgid "Maximum number of concurrent DNS queries reached (max: %d)"
 msgstr "Osiągnięto graniczną ilość jednocześnie obsługiwanych zapytań DNS (maks: %d)"
 
-#: network.c:715
+#: network.c:720
 #, c-format
 msgid "failed to create listening socket for %s: %s"
 msgstr "nie udało się otworzyć gniazda %s: %s"
 
-#: network.c:1021
+#: network.c:1031
 #, c-format
 msgid "LOUD WARNING: listening on %s may accept requests via interfaces other than %s"
 msgstr "UWAGA: nasłuchiwanie na %s może przyjmować żądania przychodzące przez interfejsy inne niż %s"
 
-#: network.c:1028
+#: network.c:1038
 msgid "LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"
 msgstr "UWAGA: zastosowanie --bind-dynamic zamiast --bind-interfaces daje ochronę przed atakami wzmocnienia DNS"
 
-#: network.c:1037
+#: network.c:1047
+#, fuzzy, c-format
+msgid "warning: using interface %s instead"
+msgstr "uwaga: %s niedostępny"
+
+#: network.c:1056
 #, c-format
 msgid "warning: no addresses found for interface %s"
 msgstr "uwaga: nie znaleziono adresu interfejsu %s"
 
-#: network.c:1095
+#: network.c:1114
 #, c-format
 msgid "interface %s failed to join DHCPv6 multicast group: %s"
 msgstr "interfejs %s nie pozwolił się przyłączyć do grupy rozgłoszeniowej DHCPv6: %s"
 
-#: network.c:1289
+#: network.c:1119
+msgid "try increasing /proc/sys/net/core/optmem_max"
+msgstr "spróbuj podwyższyć /proc/sys/net/core/optmem_max"
+
+#: network.c:1337
 #, c-format
 msgid "failed to bind server socket for %s: %s"
 msgstr "błąd przy przyznawaniu nazwy gniazdu serwera %s: %s"
 
-#: network.c:1445
+#: network.c:1528
 #, c-format
 msgid "ignoring nameserver %s - local interface"
 msgstr "ignorowanie serwera nazw %s - interfejs lokalny"
 
-#: network.c:1456
+#: network.c:1539
 #, c-format
 msgid "ignoring nameserver %s - cannot make/bind socket: %s"
 msgstr "ignorowanie serwera nazw %s - nie można utworzyć/dowiązać gniazda: %s"
 
-#: network.c:1469
+#: network.c:1559
+msgid "(no DNSSEC)"
+msgstr "(brak obsługi DNSSEC)"
+
+#: network.c:1562
 msgid "unqualified"
 msgstr "niekwalifikowane(-a)"
 
-#: network.c:1469
+#: network.c:1562
 msgid "names"
 msgstr "nazwy"
 
-#: network.c:1471
+#: network.c:1564
 msgid "default"
 msgstr "domyślne"
 
-#: network.c:1473
+#: network.c:1566
 msgid "domain"
 msgstr "domeny"
 
-#: network.c:1476
+#: network.c:1572
 #, c-format
 msgid "using local addresses only for %s %s"
 msgstr "używam adresów lokalnych tylko dla %s %s"
 
-#: network.c:1478
+#: network.c:1575
 #, c-format
 msgid "using standard nameservers for %s %s"
 msgstr "używam standardowych serwerów nazw dla %s %s"
 
-#: network.c:1480
+#: network.c:1577
 #, c-format
-msgid "using nameserver %s#%d for %s %s"
-msgstr "używam serwera nazw %s#%d dla %s %s"
+msgid "using nameserver %s#%d for %s %s %s"
+msgstr "używam serwera nazw %s#%d dla %s %s %s"
 
-#: network.c:1484
+#: network.c:1581
 #, c-format
 msgid "NOT using nameserver %s#%d - query loop detected"
 msgstr "NIE używam serwera nazw %s#%d - wykryto pętlę zapytań"
 
-#: network.c:1487
+#: network.c:1584
 #, c-format
 msgid "using nameserver %s#%d(via %s)"
 msgstr "używam serwera nazw %s#%d (przez %s)"
 
-#: network.c:1489
+#: network.c:1586
 #, c-format
 msgid "using nameserver %s#%d"
 msgstr "używam serwera nazw %s#%d"
 
-#: dnsmasq.c:163
+#: network.c:1591
+#, fuzzy, c-format
+msgid "using %d more local addresses"
+msgstr "używam o %d serwerów nazw więcej"
+
+#: network.c:1593
+#, c-format
+msgid "using %d more nameservers"
+msgstr "używam o %d serwerów nazw więcej"
+
+#: dnsmasq.c:171
 msgid "dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"
 msgstr "dhcp-hostsdir, dhcp-optsdir i hostsdir nie znajdują zastosowania na tej platformie"
 
-#: dnsmasq.c:170
-msgid "no trust anchors provided for DNSSEC"
+#: dnsmasq.c:186
+msgid "no root trust anchor provided for DNSSEC"
 msgstr "nie wskazano punktów zaufania dla DNSSEC"
 
-#: dnsmasq.c:173
+#: dnsmasq.c:189
 msgid "cannot reduce cache size from default when DNSSEC enabled"
 msgstr "brak możliwości zmniejszenia pamięci podręcznej poniżej wielkości domyślnej w przypadku używania DNSSEC"
 
-#: dnsmasq.c:175
+#: dnsmasq.c:191
 msgid "DNSSEC not available: set HAVE_DNSSEC in src/config.h"
 msgstr "obsługa DNSSEC niedostępna - ustaw HAVE_DNSSEC w src/config.h"
 
-#: dnsmasq.c:181
+#: dnsmasq.c:197
 msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
 msgstr "Serwer TFTP nie został wkompilowany -- ustaw HAVE_TFTP w src/config.h"
 
-#: dnsmasq.c:186
+#: dnsmasq.c:202
 msgid "cannot use --conntrack AND --query-port"
 msgstr "--conntrack i --query-port wzajemnie się wykluczają"
 
-#: dnsmasq.c:189
+#: dnsmasq.c:205
 msgid "conntrack support not available: set HAVE_CONNTRACK in src/config.h"
 msgstr "wsparcie przekazywania znaczników połączeń (conntrack) nie zostało wkompilowane - ustaw HAVE_CONNTRACK w src/config.h"
 
-#: dnsmasq.c:194
-msgid "asychronous logging is not available under Solaris"
+#: dnsmasq.c:210
+msgid "asynchronous logging is not available under Solaris"
 msgstr "zapis do logów w trybie asynchronicznym nie jest dostępny w Solarisie"
 
-#: dnsmasq.c:199
-msgid "asychronous logging is not available under Android"
+#: dnsmasq.c:215
+msgid "asynchronous logging is not available under Android"
 msgstr "zapis do logów w trybie asynchronicznym nie jest dostępny w Androidzie"
 
-#: dnsmasq.c:204
+#: dnsmasq.c:220
 msgid "authoritative DNS not available: set HAVE_AUTH in src/config.h"
 msgstr "tryb autorytatywny DNS-a niedostępny - ustaw HAVE_AUTH w src/config.h"
 
-#: dnsmasq.c:209
+#: dnsmasq.c:225
 msgid "loop detection not available: set HAVE_LOOP in src/config.h"
 msgstr "wykrywanie pętli zapytań nie zostało wkompilowane - ustaw HAVE_LOOP w src/config.h"
 
-#: dnsmasq.c:217
+#: dnsmasq.c:229
+msgid "max_port cannot be smaller than min_port"
+msgstr "max_port nie może być niższy niż min_port"
+
+#: dnsmasq.c:236
 msgid "zone serial must be configured in --auth-soa"
 msgstr "za pomocą --auth-soa musi zostać ustawiony numer seryjny strefy"
 
-#: dnsmasq.c:235
+#: dnsmasq.c:254
 msgid "dhcp-range constructor not available on this platform"
 msgstr "konstrukcja dhcp-range nie jest dostępna w tym systemie"
 
-#: dnsmasq.c:278
+#: dnsmasq.c:300
 msgid "cannot set --bind-interfaces and --bind-dynamic"
 msgstr "--bind-interfaces i --bind-dynamic wzajemnie się wykluczają"
 
-#: dnsmasq.c:281
+#: dnsmasq.c:303
 #, c-format
 msgid "failed to find list of interfaces: %s"
 msgstr "błąd podczas tworzenia listy interfejsów sieciowych: %s"
 
-#: dnsmasq.c:290
+#: dnsmasq.c:312
 #, c-format
 msgid "unknown interface %s"
 msgstr "nieznany interfejs %s"
 
-#: dnsmasq.c:354 dnsmasq.c:997
+#: dnsmasq.c:377 dnsmasq.c:1054
 #, c-format
 msgid "DBus error: %s"
 msgstr "błąd DBus: %s"
 
-#: dnsmasq.c:357
+#: dnsmasq.c:380
 msgid "DBus not available: set HAVE_DBUS in src/config.h"
 msgstr "Obsługa DBus nie została wkompilowana -- ustaw HAVE_DBUS w src/config.h"
 
-#: dnsmasq.c:385
+#: dnsmasq.c:410
 #, c-format
 msgid "unknown user or group: %s"
 msgstr "nieznany użytkownik lub grupa: %s"
 
-#: dnsmasq.c:440
+#: dnsmasq.c:465
 #, c-format
 msgid "cannot chdir to filesystem root: %s"
 msgstr "nie potrafię wejść do głównego katalogu: %s"
 
-#: dnsmasq.c:692
+#: dnsmasq.c:730
 #, c-format
 msgid "started, version %s DNS disabled"
 msgstr "uruchomiony, wersja %s, DNS wyłączony"
 
-#: dnsmasq.c:694
+#: dnsmasq.c:734
 #, c-format
 msgid "started, version %s cachesize %d"
 msgstr "uruchomiony, wersja %s, %d miejsc w pamięci podręcznej"
 
-#: dnsmasq.c:696
+#: dnsmasq.c:736
 #, c-format
 msgid "started, version %s cache disabled"
 msgstr "uruchomiony, wersja %s, pamięć podręczna wyłączona"
 
-#: dnsmasq.c:698
+#: dnsmasq.c:739
+msgid "DNS service limited to local subnets"
+msgstr "usługa DNS ograniczona do lokalnych podsieci"
+
+#: dnsmasq.c:742
 #, c-format
 msgid "compile time options: %s"
 msgstr "opcje kompilacji: %s"
 
-#: dnsmasq.c:704
+#: dnsmasq.c:751
 msgid "DBus support enabled: connected to system bus"
 msgstr "obsługa DBus włączona, podłączono do serwera DBus"
 
-#: dnsmasq.c:706
+#: dnsmasq.c:753
 msgid "DBus support enabled: bus connection pending"
 msgstr "obsługa DBus włączona, trwa podłączanie do serwera DBus"
 
-#: dnsmasq.c:711
-msgid "DNS service limited to local subnets"
-msgstr "usługa DNS ograniczona do lokalnych podsieci"
-
-#: dnsmasq.c:727
+#: dnsmasq.c:771
 msgid "DNSSEC validation enabled"
 msgstr "walidacja DNSSEC włączona"
 
-#: dnsmasq.c:730
-msgid "DNSSEC signature timestamps not checked until first cache reload"
+#: dnsmasq.c:775
+#, fuzzy
+msgid "DNSSEC signature timestamps not checked until receipt of SIGINT"
 msgstr "sprawdzanie sygnatur czasowych DNSSEC wyłączone do czasu przeładowania pamięci podręcznej"
 
-#: dnsmasq.c:733
+#: dnsmasq.c:778
 msgid "DNSSEC signature timestamps not checked until system time valid"
 msgstr "sprawdzanie sygnatur czasowych DNSSEC wyłączone do czasu zsynchronizowania się zegara systemowego"
 
-#: dnsmasq.c:738
+#: dnsmasq.c:783
 #, c-format
 msgid "warning: failed to change owner of %s: %s"
 msgstr "uwaga: nie udało się zmienić użytkownika pliku %s: %s"
 
-#: dnsmasq.c:742
+#: dnsmasq.c:787
 msgid "setting --bind-interfaces option because of OS limitations"
 msgstr "ustawiam --bind-interfaces z powodu ograniczeń systemu operacyjnego"
 
-#: dnsmasq.c:752
+#: dnsmasq.c:799
 #, c-format
 msgid "warning: interface %s does not currently exist"
 msgstr "uwaga: interfejs %s nie jest włączony"
 
-#: dnsmasq.c:757
+#: dnsmasq.c:804
 msgid "warning: ignoring resolv-file flag because no-resolv is set"
 msgstr "uwaga: ignoruję opcję resolv-file, ponieważ wybrano tryb no-resolv"
 
-#: dnsmasq.c:760
+#: dnsmasq.c:807
 msgid "warning: no upstream servers configured"
 msgstr "uwaga: nie wskazano nadrzędnych serwerów DNS"
 
-#: dnsmasq.c:764
+#: dnsmasq.c:811
 #, c-format
 msgid "asynchronous logging enabled, queue limit is %d messages"
 msgstr "włączono asynchroniczny tryb zapisu do logów z kolejką na %d komunikatów"
 
-#: dnsmasq.c:785
+#: dnsmasq.c:832
 msgid "IPv6 router advertisement enabled"
 msgstr "anonsowanie rutera IPv6 włączone"
 
-#: dnsmasq.c:790
+#: dnsmasq.c:837
 #, c-format
 msgid "DHCP, sockets bound exclusively to interface %s"
 msgstr "DHCP, gniazda dowiązane na wyłączność interfejsowi %s"
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "root is "
 msgstr "z głównym katalogiem w "
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "enabled"
 msgstr "włączony"
 
-#: dnsmasq.c:806
+#: dnsmasq.c:853
 msgid "secure mode"
 msgstr "w trybie bezpiecznym"
 
-#: dnsmasq.c:809
+#: dnsmasq.c:856
 #, c-format
 msgid "warning: %s inaccessible"
 msgstr "uwaga: %s niedostępny"
 
-#: dnsmasq.c:813
+#: dnsmasq.c:860
 #, c-format
 msgid "warning: TFTP directory %s inaccessible"
 msgstr "uwaga: katalog TFTP %s nie jest dostępny"
 
-#: dnsmasq.c:839
+#: dnsmasq.c:886
 #, c-format
 msgid "restricting maximum simultaneous TFTP transfers to %d"
 msgstr "ograniczam ilość jednoczesnych przesłań TFTP do %d"
 
-#: dnsmasq.c:999
+#: dnsmasq.c:1056
 msgid "connected to system DBus"
 msgstr "podłączono do DBus-a"
 
-#: dnsmasq.c:1149
+#: dnsmasq.c:1215
 #, c-format
 msgid "cannot fork into background: %s"
 msgstr "nie potrafię przełączyć się do pracy w tle: %s"
 
-#: dnsmasq.c:1152
+#: dnsmasq.c:1218
 #, c-format
 msgid "failed to create helper: %s"
 msgstr "nie udało się utworzyć procesu pomocniczego: %s"
 
-#: dnsmasq.c:1155
+#: dnsmasq.c:1221
 #, c-format
 msgid "setting capabilities failed: %s"
 msgstr "nie powiodło się ustawianie ograniczeń (capabilities): %s"
 
-#: dnsmasq.c:1158
+#: dnsmasq.c:1224
 #, c-format
 msgid "failed to change user-id to %s: %s"
 msgstr "nie udało się zmienić użytkownika procesu na %s: %s"
 
-#: dnsmasq.c:1161
+#: dnsmasq.c:1227
 #, c-format
 msgid "failed to change group-id to %s: %s"
 msgstr "nie udało się zmienić grupy procesu na %s: %s"
 
-#: dnsmasq.c:1164
+#: dnsmasq.c:1230
 #, c-format
 msgid "failed to open pidfile %s: %s"
 msgstr "nie udało się otworzyć pliku z PID-em %s: %s"
 
-#: dnsmasq.c:1167
+#: dnsmasq.c:1233
 #, c-format
 msgid "cannot open log %s: %s"
 msgstr "nie udało się otworzyć logu %s: %s"
 
-#: dnsmasq.c:1170
+#: dnsmasq.c:1236
 #, c-format
 msgid "failed to load Lua script: %s"
 msgstr "nie udało się wczytać skryptu Lua: %s"
 
-#: dnsmasq.c:1173
+#: dnsmasq.c:1239
 #, c-format
 msgid "TFTP directory %s inaccessible: %s"
 msgstr "katalog TFTP %s nie jest dostępny: %s"
 
-#: dnsmasq.c:1176
+#: dnsmasq.c:1242
 #, c-format
 msgid "cannot create timestamp file %s: %s"
 msgstr "nie potrafię utworzyć pliku znacznika czasu %s: %s"
 
-#: dnsmasq.c:1197
-msgid "now checking DNSSEC signature timestamps"
-msgstr "trwa sprawdzanie sygnatur czasowych podpisów DNSSEC"
-
-#: dnsmasq.c:1264
+#: dnsmasq.c:1326
 #, c-format
 msgid "script process killed by signal %d"
 msgstr "skrypt został zabity sygnałem %d"
 
-#: dnsmasq.c:1268
+#: dnsmasq.c:1330
 #, c-format
 msgid "script process exited with status %d"
 msgstr "skrypt zakończył się z kodem powrotu %d"
 
-#: dnsmasq.c:1272
+#: dnsmasq.c:1334
 #, c-format
 msgid "failed to execute %s: %s"
 msgstr "nie udało się uruchomić %s: %s"
 
-#: dnsmasq.c:1327
+#: dnsmasq.c:1374
+msgid "now checking DNSSEC signature timestamps"
+msgstr "trwa sprawdzanie sygnatur czasowych podpisów DNSSEC"
+
+#: dnsmasq.c:1409 dnssec.c:160 dnssec.c:206
+#, c-format
+msgid "failed to update mtime on %s: %s"
+msgstr "nie udało się uaktualnić znacznika czasu pliku %s: %s"
+
+#: dnsmasq.c:1416
 msgid "exiting on receipt of SIGTERM"
 msgstr "zakończyłem działanie z powodu odebrania SIGTERM"
 
-#: dnsmasq.c:1355
+#: dnsmasq.c:1444
 #, c-format
 msgid "failed to access %s: %s"
 msgstr "brak dostępu do %s: %s"
 
-#: dnsmasq.c:1385
+#: dnsmasq.c:1474
 #, c-format
 msgid "reading %s"
 msgstr "czytanie %s"
 
-#: dnsmasq.c:1396
+#: dnsmasq.c:1485
 #, c-format
 msgid "no servers found in %s, will retry"
 msgstr "w %s nie znalazłem serwerów, spróbuję ponownie później"
@@ -1530,243 +1608,263 @@ msgstr "błąd przy przyznawaniu nazwy gniazdu serwera DHCP: %s"
 msgid "cannot create ICMP raw socket: %s."
 msgstr "nie udało się utworzyć surowego gniazda ICMP: %s."
 
-#: dhcp.c:241 dhcp6.c:180
+#: dhcp.c:252 dhcp6.c:173
 #, c-format
 msgid "unknown interface %s in bridge-interface"
 msgstr "nieznany interfejs %s w bridge-u"
 
-#: dhcp.c:281
+#: dhcp.c:293
 #, c-format
 msgid "DHCP packet received on %s which has no address"
 msgstr "żądanie DHCP odebrano na interfejsie %s, który nie ma adresu"
 
-#: dhcp.c:415
+#: dhcp.c:427
 #, c-format
 msgid "ARP-cache injection failed: %s"
 msgstr "uzupełnienie pamięci podręcznej ARP nie powiodło się: %s"
 
-#: dhcp.c:514
+#: dhcp.c:470
+#, c-format
+msgid "Error sending DHCP packet to %s: %s"
+msgstr "Błąd wysyłania pakietu DHCP do %s: %s"
+
+#: dhcp.c:531
 #, c-format
 msgid "DHCP range %s -- %s is not consistent with netmask %s"
 msgstr "zakres adresów DHCP %s -- %s jest niespójny z maską sieci %s"
 
-#: dhcp.c:815
+#: dhcp.c:854
 #, c-format
 msgid "bad line at %s line %d"
 msgstr "zła zawartość pliku %s, w linii %d"
 
-#: dhcp.c:858
+#: dhcp.c:897
 #, c-format
 msgid "ignoring %s line %d, duplicate name or IP address"
 msgstr "w %s pomijam linię %d -- powtórzona nazwa lub adres IP"
 
-#: dhcp.c:1002 rfc3315.c:2135
+#: dhcp.c:1041 rfc3315.c:2149
 #, c-format
 msgid "DHCP relay %s -> %s"
 msgstr "przekazywanie DHCP %s -> %s"
 
-#: lease.c:61
+#: lease.c:98
+msgid "too many stored leases"
+msgstr "zbyt duża ilość zapisanych dzierżaw"
+
+#: lease.c:166
 #, c-format
 msgid "cannot open or create lease file %s: %s"
 msgstr "nie potrafię otworzyć albo utworzyć pliku dzierżaw %s: %s"
 
-#: lease.c:134
-msgid "too many stored leases"
-msgstr "zbyt duża ilość zapisanych dzierżaw"
+#: lease.c:175
+#, c-format
+msgid "failed to parse lease database, invalid line: %s %s %s %s ..."
+msgstr ""
+
+#: lease.c:180
+#, fuzzy, c-format
+msgid "failed to read lease file %s: %s"
+msgstr "nie udało się odczytać %s: %s"
 
-#: lease.c:165
+#: lease.c:196
 #, c-format
 msgid "cannot run lease-init script %s: %s"
 msgstr "nie potrafię uruchomić skryptu %s: %s"
 
-#: lease.c:171
+#: lease.c:202
 #, c-format
 msgid "lease-init script returned exit code %s"
 msgstr "skrypt zakończył się z kodem powrotu %s"
 
-#: lease.c:342
+#: lease.c:373
 #, c-format
 msgid "failed to write %s: %s (retry in %us)"
 msgstr "błąd zapisu do %s: %s (spróbuję ponownie za %us)"
 
-#: lease.c:906
+#: lease.c:937
 #, c-format
 msgid "Ignoring domain %s for DHCP host name %s"
 msgstr "Nie uwzględniam części domenowej (%s) dla komputera %s"
 
-#: rfc2131.c:344
+#: rfc2131.c:347
 #, c-format
 msgid "no address range available for DHCP request %s %s"
 msgstr "nie zdefiniowano zakresu adresów odpowiedniego dla żądania %s %s"
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "with subnet selector"
 msgstr "z wyborem podsieci"
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "via"
 msgstr "przez"
 
-#: rfc2131.c:357
+#: rfc2131.c:360
 #, c-format
 msgid "%u available DHCP subnet: %s/%s"
 msgstr "%u dostępna podsieć DHCP: %s/%s"
 
-#: rfc2131.c:360 rfc3315.c:300
+#: rfc2131.c:363 rfc3315.c:306
 #, c-format
 msgid "%u available DHCP range: %s -- %s"
 msgstr "%u dostępny zakres adresów DHCP: %s -- %s"
 
-#: rfc2131.c:471
+#: rfc2131.c:474
 #, c-format
 msgid "%u vendor class: %s"
 msgstr "%u klasa dostawcy: %s"
 
-#: rfc2131.c:473
+#: rfc2131.c:476
 #, c-format
 msgid "%u user class: %s"
 msgstr "%u klasa użytkownika: %s"
 
-#: rfc2131.c:500
+#: rfc2131.c:510
 msgid "disabled"
 msgstr "wyłączony(a)"
 
-#: rfc2131.c:541 rfc2131.c:974 rfc2131.c:1380 rfc3315.c:603 rfc3315.c:856
-#: rfc3315.c:1135
+#: rfc2131.c:551 rfc2131.c:1006 rfc2131.c:1430 rfc3315.c:616 rfc3315.c:869
+#: rfc3315.c:1148
 msgid "ignored"
 msgstr "ignoruję"
 
-#: rfc2131.c:556 rfc2131.c:1207 rfc3315.c:906
+#: rfc2131.c:566 rfc2131.c:1239 rfc3315.c:919
 msgid "address in use"
 msgstr "adres jest w użyciu"
 
-#: rfc2131.c:570 rfc2131.c:1028
+#: rfc2131.c:580 rfc2131.c:1060
 msgid "no address available"
 msgstr "brak dostępnego adresu"
 
-#: rfc2131.c:577 rfc2131.c:1170
+#: rfc2131.c:587 rfc2131.c:1202
 msgid "wrong network"
 msgstr "nieprawidłowa sieć"
 
-#: rfc2131.c:592
+#: rfc2131.c:602
 msgid "no address configured"
 msgstr "brak skonfigurowanego adresu"
 
-#: rfc2131.c:598 rfc2131.c:1220
+#: rfc2131.c:608 rfc2131.c:1252
 msgid "no leases left"
 msgstr "brak wolnych dzierżaw"
 
-#: rfc2131.c:693 rfc3315.c:476
+#: rfc2131.c:703 rfc3315.c:482
 #, c-format
 msgid "%u client provides name: %s"
 msgstr "klient %u przedstawia się jako %s"
 
-#: rfc2131.c:798
+#: rfc2131.c:808
 msgid "PXE BIS not supported"
 msgstr "PXE BIS nie jest obsługiwane"
 
-#: rfc2131.c:942 rfc3315.c:1229
+#: rfc2131.c:974 rfc3315.c:1242
 #, c-format
 msgid "disabling DHCP static address %s for %s"
 msgstr "wyłączam statyczne przypisanie adresu %s dla %s"
 
-#: rfc2131.c:963
+#: rfc2131.c:995
 msgid "unknown lease"
 msgstr "nieznana dzierżawa"
 
-#: rfc2131.c:997
+#: rfc2131.c:1029
 #, c-format
 msgid "not using configured address %s because it is leased to %s"
 msgstr "nie proponuję zakładanego w konfiguracji adresu %s, bo jest on już wydzierżawiony komputerowi %s"
 
-#: rfc2131.c:1007
+#: rfc2131.c:1039
 #, c-format
 msgid "not using configured address %s because it is in use by the server or relay"
 msgstr "nie proponuję zakładanego w konfiguracji adresu %s, bo używa go któryś z serwerów"
 
-#: rfc2131.c:1010
+#: rfc2131.c:1042
 #, c-format
 msgid "not using configured address %s because it was previously declined"
 msgstr "nie proponuję zakładanego w konfiguracji adresu %s, bo już poprzednio został odrzucony"
 
-#: rfc2131.c:1026 rfc2131.c:1213
+#: rfc2131.c:1058 rfc2131.c:1245
 msgid "no unique-id"
 msgstr "brak unikalnego id"
 
-#: rfc2131.c:1108
+#: rfc2131.c:1140
 msgid "wrong server-ID"
 msgstr "nieprawidłowy identyfikator serwera (server-ID)"
 
-#: rfc2131.c:1127
+#: rfc2131.c:1159
 msgid "wrong address"
 msgstr "błędny adres"
 
-#: rfc2131.c:1145 rfc3315.c:1002
+#: rfc2131.c:1177 rfc3315.c:1015
 msgid "lease not found"
 msgstr "dzierżawa nieznaleziona"
 
-#: rfc2131.c:1178
+#: rfc2131.c:1210
 msgid "address not available"
 msgstr "adres niedostępny"
 
-#: rfc2131.c:1189
+#: rfc2131.c:1221
 msgid "static lease available"
 msgstr "dostępna statyczna dzierżawa"
 
-#: rfc2131.c:1193
+#: rfc2131.c:1225
 msgid "address reserved"
 msgstr "adres zarezerwowany"
 
-#: rfc2131.c:1201
+#: rfc2131.c:1233
 #, c-format
 msgid "abandoning lease to %s of %s"
 msgstr "porzucam przypisanie do %s nazwy %s"
 
-#: rfc2131.c:1707
+#: rfc2131.c:1757
 #, c-format
 msgid "%u bootfile name: %s"
 msgstr "%u nazwa pliku bootowania: %s"
 
-#: rfc2131.c:1716
+#: rfc2131.c:1766
 #, c-format
 msgid "%u server name: %s"
 msgstr "%u nazwa serwera: %s"
 
-#: rfc2131.c:1724
+#: rfc2131.c:1774
 #, c-format
 msgid "%u next server: %s"
 msgstr "%u następny serwer: %s"
 
-#: rfc2131.c:1727
+#: rfc2131.c:1777
 #, c-format
 msgid "%u broadcast response"
 msgstr "%u odpowiedź rozgłoszeniowa"
 
-#: rfc2131.c:1790
+#: rfc2131.c:1840
 #, c-format
 msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
 msgstr "nie mam możliwości wysłania opcji %d DHCP/BOOTP: niedostateczna ilość miejsca w pakiecie"
 
-#: rfc2131.c:2031
+#: rfc2131.c:2131
 msgid "PXE menu too large"
 msgstr "menu PXE zbyt duże"
 
-#: rfc2131.c:2170 rfc3315.c:1502
+#: rfc2131.c:2270 rfc3315.c:1515
 #, c-format
 msgid "%u requested options: %s"
 msgstr "%u zażądano: %s"
 
-#: rfc2131.c:2487
+#: rfc2131.c:2587
 #, c-format
 msgid "cannot send RFC3925 option: too many options for enterprise number %d"
 msgstr "nie mogę wysłać opcji RFC3925: za długi łańcuch opcji przy numerze %d"
 
+#: rfc2131.c:2650
+#, c-format
+msgid "%u reply delay: %d"
+msgstr ""
+
 #: netlink.c:77
 #, c-format
 msgid "cannot create netlink socket: %s"
 msgstr "nie potrafię utworzyć połączenia netlink %s"
 
-#: netlink.c:348
+#: netlink.c:355
 #, c-format
 msgid "netlink returns error: %s"
 msgstr "wystąpił błąd w połączeniu netlink %s"
@@ -1785,62 +1883,62 @@ msgstr "opcja --%s została właśnie aktywowana za pomocą D-Bus"
 msgid "Disabling --%s option from D-Bus"
 msgstr "opcja --%s została właśnie dezaktywowana za pomocą D-Bus"
 
-#: dbus.c:691
+#: dbus.c:690
 msgid "setting upstream servers from DBus"
 msgstr "ustawiam adresy serwerów nadrzędnych na podstawie informacji odebranych z DBus"
 
-#: dbus.c:738
+#: dbus.c:737
 msgid "could not register a DBus message handler"
 msgstr "nie można zarejestrować uchwytu DBus"
 
-#: bpf.c:263
+#: bpf.c:265
 #, c-format
 msgid "cannot create DHCP BPF socket: %s"
 msgstr "nie potrafię utworzyć gniazda DHCP BPF: %s"
 
-#: bpf.c:291
+#: bpf.c:293
 #, c-format
 msgid "DHCP request for unsupported hardware type (%d) received on %s"
 msgstr "żądanie DHCP od urządzenia nieobsługiwanego typu (%d) odebrano na %s"
 
-#: bpf.c:376
+#: bpf.c:378
 #, c-format
 msgid "cannot create PF_ROUTE socket: %s"
 msgstr "nie udało się utworzyć gniazda PF_ROUTE: %s"
 
-#: bpf.c:397
+#: bpf.c:399
 msgid "Unknown protocol version from route socket"
 msgstr "Nieznana wersja protokołu."
 
-#: helper.c:153
+#: helper.c:154
 msgid "lease() function missing in Lua script"
 msgstr "w skrypcie Lua brak funkcji lease()"
 
-#: tftp.c:309
+#: tftp.c:319
 msgid "unable to get free port for TFTP"
 msgstr "brak wolnego portu dla usługi TFTP"
 
-#: tftp.c:325
+#: tftp.c:335
 #, c-format
 msgid "unsupported request from %s"
 msgstr "nieobsługiwane żądanie od komputera %s"
 
-#: tftp.c:439
+#: tftp.c:483
 #, c-format
 msgid "file %s not found"
 msgstr "plik %s nie został znaleziony"
 
-#: tftp.c:548
+#: tftp.c:592
 #, c-format
 msgid "error %d %s received from %s"
 msgstr "błąd %d %s odebrano od %s"
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "failed sending %s to %s"
 msgstr "błąd wysyłania pliku %s do komputera %s"
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "sent %s to %s"
 msgstr "plik %s przesłano do %s"
@@ -1855,7 +1953,7 @@ msgstr "przepełnienie: stracono %d wpisów do logów"
 msgid "log failed: %s"
 msgstr "nie udało się zapisać komunikatów do %s"
 
-#: log.c:469
+#: log.c:471
 msgid "FAILED to start up"
 msgstr "BŁĄD: nie udało się uruchomić dnsmasq-a"
 
@@ -1864,17 +1962,17 @@ msgstr "BŁĄD: nie udało się uruchomić dnsmasq-a"
 msgid "Conntrack connection mark retrieval failed: %s"
 msgstr "Nie udało się odcztać znacznika połączenia (conntrack): %s"
 
-#: dhcp6.c:59
+#: dhcp6.c:52
 #, c-format
 msgid "cannot create DHCPv6 socket: %s"
 msgstr "nie udało się utworzyć gniazda dla DHCPv6: %s"
 
-#: dhcp6.c:80
+#: dhcp6.c:73
 #, c-format
 msgid "failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"
 msgstr "nie udało się ustawić SO_REUSE{ADDR|PORT} gniazda DHCPv6: %s"
 
-#: dhcp6.c:92
+#: dhcp6.c:85
 #, c-format
 msgid "failed to bind DHCPv6 server socket: %s"
 msgstr "dowiązywanie gniazda serwera DHCPv6 zakończone niepowodzeniem: %s"
@@ -1889,67 +1987,67 @@ msgstr "nie zdefiniowano zakresu adresów odpowiedniego dla żądania DHCPv6 prz
 msgid "no address range available for DHCPv6 request via %s"
 msgstr "nie zdefiniowano zakresu adresów odpowiedniego dla żądania DHCPv6 od %s"
 
-#: rfc3315.c:297
+#: rfc3315.c:303
 #, c-format
 msgid "%u available DHCPv6 subnet: %s/%d"
 msgstr "%u dostępna podsieć DHCPv6: %s/%d"
 
-#: rfc3315.c:380
+#: rfc3315.c:386
 #, c-format
 msgid "%u vendor class: %u"
 msgstr "%u klasa dostawcy: %u"
 
-#: rfc3315.c:428
+#: rfc3315.c:434
 #, c-format
 msgid "%u client MAC address: %s"
 msgstr "adres MAC klienta %u: %s"
 
-#: rfc3315.c:660
+#: rfc3315.c:673
 #, c-format
 msgid "unknown prefix-class %d"
 msgstr "nieznana klasa sieci %d"
 
-#: rfc3315.c:803 rfc3315.c:898
+#: rfc3315.c:816 rfc3315.c:911
 msgid "address unavailable"
 msgstr "adres niedostępny"
 
-#: rfc3315.c:815 rfc3315.c:946 rfc3315.c:1279
+#: rfc3315.c:828 rfc3315.c:959 rfc3315.c:1292
 msgid "success"
 msgstr "udane"
 
-#: rfc3315.c:830 rfc3315.c:839 rfc3315.c:954 rfc3315.c:956
+#: rfc3315.c:843 rfc3315.c:852 rfc3315.c:967 rfc3315.c:969
 msgid "no addresses available"
 msgstr "brak wolnych adresów"
 
-#: rfc3315.c:933
+#: rfc3315.c:946
 msgid "not on link"
 msgstr "poza zasięgiem"
 
-#: rfc3315.c:1006 rfc3315.c:1191 rfc3315.c:1268
+#: rfc3315.c:1019 rfc3315.c:1204 rfc3315.c:1281
 msgid "no binding found"
 msgstr "brak powiązania"
 
-#: rfc3315.c:1044
+#: rfc3315.c:1057
 msgid "deprecated"
 msgstr "przestarzały"
 
-#: rfc3315.c:1049
+#: rfc3315.c:1062
 msgid "address invalid"
 msgstr "niepoprawny adres"
 
-#: rfc3315.c:1096
+#: rfc3315.c:1109
 msgid "confirm failed"
 msgstr "brak potwierdzenia"
 
-#: rfc3315.c:1112
+#: rfc3315.c:1125
 msgid "all addresses still on link"
 msgstr "wszystkie adresy ciągle w użyciu"
 
-#: rfc3315.c:1200
+#: rfc3315.c:1213
 msgid "release received"
 msgstr "adres został zwolniony"
 
-#: rfc3315.c:2126
+#: rfc3315.c:2140
 msgid "Cannot multicast to DHCPv6 server without correct interface"
 msgstr "Nie mogę rozesłać do serwerów DHCPv6 nie mając prawidłowego interfejsu"
 
@@ -1973,76 +2071,76 @@ msgstr "do komputera o nazwie %s pasuje więcej niż jeden adres, w odpowiedzi D
 msgid "duplicate IP address %s (%s) in dhcp-config directive"
 msgstr "powtórzenie adresu IP %s (%s) w opcji dhcp-config"
 
-#: dhcp-common.c:494
+#: dhcp-common.c:491
 #, c-format
 msgid "failed to set SO_BINDTODEVICE on DHCP socket: %s"
 msgstr "nie udało się ustawić SO_BINDTODEVICE gniazda DHCP: %s"
 
-#: dhcp-common.c:615
+#: dhcp-common.c:612
 #, c-format
 msgid "Known DHCP options:\n"
 msgstr "Znane opcje DHCP:\n"
 
-#: dhcp-common.c:626
+#: dhcp-common.c:623
 #, c-format
 msgid "Known DHCPv6 options:\n"
 msgstr "Rozpoznawane opcje DHCPv6:\n"
 
-#: dhcp-common.c:823
+#: dhcp-common.c:820
 msgid ", prefix deprecated"
 msgstr ", przestarzały prefiks"
 
-#: dhcp-common.c:826
+#: dhcp-common.c:823
 #, c-format
 msgid ", lease time "
 msgstr ", czas dzierżawy "
 
-#: dhcp-common.c:868
+#: dhcp-common.c:865
 #, c-format
 msgid "%s stateless on %s%.0s%.0s%s"
 msgstr "%s bezstanowy na %s%.0s%.0s%s"
 
-#: dhcp-common.c:870
+#: dhcp-common.c:867
 #, c-format
 msgid "%s, static leases only on %.0s%s%s%.0s"
 msgstr "%s, wyłącznie statyczne dzierżawy na %.0s%s%s%.0s"
 
-#: dhcp-common.c:872
+#: dhcp-common.c:869
 #, c-format
 msgid "%s, proxy on subnet %.0s%s%.0s%.0s"
 msgstr "%s, wykryto pośrednika na podsieci %.0s%s%.0s%.0s"
 
-#: dhcp-common.c:873
+#: dhcp-common.c:870
 #, c-format
 msgid "%s, IP range %s -- %s%s%.0s"
 msgstr "%s, zakres IP %s -- %s%s%.0s"
 
-#: dhcp-common.c:886
+#: dhcp-common.c:883
 #, c-format
 msgid "DHCPv4-derived IPv6 names on %s%s"
 msgstr "pochodzące z DHCPv4 nazwy IPv6 na %s%s"
 
-#: dhcp-common.c:889
+#: dhcp-common.c:886
 #, c-format
 msgid "router advertisement on %s%s"
 msgstr "anonsowanie rutera na %s%s"
 
-#: dhcp-common.c:900
+#: dhcp-common.c:897
 #, c-format
 msgid "DHCP relay from %s to %s via %s"
 msgstr "przekazywanie DHCP z %s do %s za pomocą %s"
 
-#: dhcp-common.c:902
+#: dhcp-common.c:899
 #, c-format
 msgid "DHCP relay from %s to %s"
 msgstr "przekazywanie DHCP z %s do %s"
 
-#: radv.c:109
+#: radv.c:110
 #, c-format
 msgid "cannot create ICMPv6 socket: %s"
 msgstr "nie udało się utworzyć gniazda dla ICMPv6: %s"
 
-#: auth.c:448
+#: auth.c:449
 #, c-format
 msgid "ignoring zone transfer request from %s"
 msgstr "ignoruję żądanie transferu strefy od %s"
@@ -2057,94 +2155,104 @@ msgstr "niezgodna wersja jądra: %s"
 msgid "failed to create IPset control socket: %s"
 msgstr "nie powiodło się otwieranie gniazda sterującego IPset: %s"
 
-#: dnssec.c:449 dnssec.c:493
-#, c-format
-msgid "failed to update mtime on %s: %s"
+#: ipset.c:233
+#, fuzzy, c-format
+msgid "failed to update ipset %s: %s"
 msgstr "nie udało się uaktualnić znacznika czasu pliku %s: %s"
 
+#: dnssec.c:208
+#, fuzzy
+msgid "system time considered valid, now checking DNSSEC signature timestamps."
+msgstr "trwa sprawdzanie sygnatur czasowych podpisów DNSSEC"
+
 #: blockdata.c:58
 #, c-format
 msgid "DNSSEC memory in use %u, max %u, allocated %u"
 msgstr "DNSSEC: zużycie pamięci %u, maks. %u, przydzielona %u"
 
-#: tables.c:80
-msgid "error: fill_addr missused"
-msgstr "błąd: niepoprawnie użyty fill_addr"
-
-#: tables.c:109
+#: tables.c:61
 #, c-format
 msgid "failed to access pf devices: %s"
 msgstr "brak dostępu do /dev/pf (filtra pakietów): %s"
 
-#: tables.c:123
+#: tables.c:74
 #, c-format
 msgid "warning: no opened pf devices %s"
 msgstr "uwaga: brak otwartych filtrów pakietów %s"
 
-#: tables.c:131
+#: tables.c:82
 #, c-format
 msgid "error: cannot use table name %s"
 msgstr "błąd: nie potrafię użyć nazwy tablicy %s"
 
-#: tables.c:139
+#: tables.c:90
 #, c-format
 msgid "error: cannot strlcpy table name %s"
 msgstr "błąd: nie potrafię strlcpy nazwy tablicy %s"
 
-#: tables.c:145
-#, c-format
-msgid "warning: pfr_add_tables: %s(%d)"
-msgstr "uwaga: pfr_add_tables: %s(%d)"
+#: tables.c:101
+#, fuzzy, c-format
+msgid "IPset: error:%s"
+msgstr "błąd DBus: %s"
 
-#: tables.c:151
+#: tables.c:108
 msgid "info: table created"
 msgstr "info: tablica utworzona"
 
-#: tables.c:162
+#: tables.c:134
 #, c-format
 msgid "warning: DIOCR%sADDRS: %s"
 msgstr "uwaga: DIOCR%sADDRS: %s"
 
-#: tables.c:166
+#: tables.c:138
 #, c-format
 msgid "%d addresses %s"
 msgstr "%d adresów %s"
 
-#: inotify.c:59
+#: inotify.c:62
 #, c-format
 msgid "cannot access path %s: %s"
 msgstr "brak dostępu do katalogu %s: %s"
 
-#: inotify.c:92
+#: inotify.c:95
 #, c-format
 msgid "failed to create inotify: %s"
 msgstr "nie udało się uruchomić powiadamiania inotify: %s"
 
-#: inotify.c:105
+#: inotify.c:111
 #, c-format
 msgid "too many symlinks following %s"
 msgstr "zbyt wiele odniesień począwszy od %s"
 
-#: inotify.c:121
+#: inotify.c:127
 #, c-format
 msgid "directory %s for resolv-file is missing, cannot poll"
 msgstr "katalog %s z resolv-file nie istnieje - nie ma czego odpytywać"
 
-#: inotify.c:125 inotify.c:162
+#: inotify.c:131 inotify.c:168
 #, c-format
 msgid "failed to create inotify for %s: %s"
 msgstr "nie udało się utworzyć powiadamiania dla %s: %s"
 
-#: inotify.c:147
+#: inotify.c:153
 #, c-format
 msgid "bad dynamic directory %s: %s"
 msgstr "zły katalog dynamiczny %s: %s"
 
-#: inotify.c:247
+#: inotify.c:257
 #, c-format
 msgid "inotify, new or changed file %s"
 msgstr "inotify: pojawił się lub uległ zmianie plik %s"
 
+#~ msgid "bad TTL"
+#~ msgstr "zły TTL"
+
+#~ msgid "error: fill_addr missused"
+#~ msgstr "błąd: niepoprawnie użyty fill_addr"
+
+#~ msgid "warning: pfr_add_tables: %s(%d)"
+#~ msgstr "uwaga: pfr_add_tables: %s(%d)"
+
 #, fuzzy
 #~ msgid "cannot cannonicalise resolv-file %s: %s"
 #~ msgstr "nie potrafię otworzyć albo utworzyć pliku dzierżaw %s: %s"
index 74d9eda..cbaea31 100644 (file)
@@ -7,7 +7,7 @@ msgstr ""
 "Project-Id-Version: dnsmasq 2.26\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2009-06-18 12:24+0100\n"
-"PO-Revision-Date: 2006-01-16 20:42+0000\n"
+"PO-Revision-Date: 2017-07-17 18:30+0100\n"
 "Last-Translator: Simon Kelley <simon@thekelleys.org.uk>\n"
 "Language-Team: Portuguese <ldp-br@bazar.conectiva.com.br>\n"
 "Language: pt\n"
@@ -16,1482 +16,1556 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: cache.c:523
+#: cache.c:518
 msgid "Internal error in cache."
 msgstr ""
 
-#: cache.c:941
+#: cache.c:928
 #, c-format
 msgid "failed to load names from %s: %s"
 msgstr ""
 
-#: cache.c:967 dhcp.c:828
+#: cache.c:954 dhcp.c:867
 #, c-format
 msgid "bad address at %s line %d"
 msgstr ""
 
-#: cache.c:1018 dhcp.c:844
+#: cache.c:1007 dhcp.c:883
 #, c-format
 msgid "bad name at %s line %d"
 msgstr ""
 
-#: cache.c:1027 dhcp.c:919
+#: cache.c:1016 dhcp.c:958
 #, c-format
 msgid "read %s - %d addresses"
 msgstr ""
 
-#: cache.c:1135
+#: cache.c:1129
 msgid "cleared cache"
 msgstr ""
 
-#: cache.c:1164
+#: cache.c:1158
 #, c-format
 msgid "No IPv4 address found for %s"
 msgstr ""
 
-#: cache.c:1242
+#: cache.c:1237
 #, c-format
 msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
 msgstr ""
 
-#: cache.c:1266
+#: cache.c:1261
 #, c-format
 msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
 msgstr ""
 
-#: cache.c:1421
+#: cache.c:1418
 #, c-format
 msgid "time %lu"
 msgstr ""
 
-#: cache.c:1422
+#: cache.c:1419
 #, c-format
 msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
 msgstr ""
 
-#: cache.c:1424
+#: cache.c:1421
 #, c-format
 msgid "queries forwarded %u, queries answered locally %u"
 msgstr ""
 
-#: cache.c:1427
+#: cache.c:1424
 #, c-format
 msgid "queries for authoritative zones %u"
 msgstr ""
 
-#: cache.c:1453
+#: cache.c:1450
 #, c-format
 msgid "server %s#%d: queries sent %u, retried or failed %u"
 msgstr ""
 
-#: util.c:45
+#: util.c:47
 #, c-format
 msgid "failed to seed the random number generator: %s"
 msgstr ""
 
-#: util.c:205
+#: util.c:224
 msgid "failed to allocate memory"
 msgstr ""
 
-#: util.c:250 option.c:601
+#: util.c:281 option.c:619
 msgid "could not get memory"
 msgstr ""
 
-#: util.c:260
+#: util.c:291
 #, c-format
 msgid "cannot create pipe: %s"
 msgstr ""
 
-#: util.c:268
+#: util.c:299
 #, c-format
 msgid "failed to allocate %d bytes"
 msgstr ""
 
-#: util.c:437
+#: util.c:468
 #, c-format
 msgid "infinite"
 msgstr ""
 
-#: option.c:332
+#: option.c:344
 msgid "Specify local address(es) to listen on."
 msgstr ""
 
-#: option.c:333
+#: option.c:345
 msgid "Return ipaddr for all hosts in specified domains."
 msgstr ""
 
-#: option.c:334
+#: option.c:346
 msgid "Fake reverse lookups for RFC1918 private address ranges."
 msgstr ""
 
-#: option.c:335
+#: option.c:347
 msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
 msgstr ""
 
-#: option.c:336
+#: option.c:348
 #, c-format
 msgid "Specify the size of the cache in entries (defaults to %s)."
 msgstr ""
 
-#: option.c:337
+#: option.c:349
 #, c-format
 msgid "Specify configuration file (defaults to %s)."
 msgstr ""
 
-#: option.c:338
+#: option.c:350
 msgid "Do NOT fork into the background: run in debug mode."
 msgstr ""
 
-#: option.c:339
+#: option.c:351
 msgid "Do NOT forward queries with no domain part."
 msgstr ""
 
-#: option.c:340
+#: option.c:352
 msgid "Return self-pointing MX records for local hosts."
 msgstr ""
 
-#: option.c:341
+#: option.c:353
 msgid "Expand simple names in /etc/hosts with domain-suffix."
 msgstr ""
 
-#: option.c:342
+#: option.c:354
 msgid "Don't forward spurious DNS requests from Windows hosts."
 msgstr ""
 
-#: option.c:343
+#: option.c:355
 msgid "Enable DHCP in the range given with lease duration."
 msgstr ""
 
-#: option.c:344
+#: option.c:356
 #, c-format
 msgid "Change to this group after startup (defaults to %s)."
 msgstr ""
 
-#: option.c:345
+#: option.c:357
 msgid "Set address or hostname for a specified machine."
 msgstr ""
 
-#: option.c:346
+#: option.c:358
 msgid "Read DHCP host specs from file."
 msgstr ""
 
-#: option.c:347
+#: option.c:359
 msgid "Read DHCP option specs from file."
 msgstr ""
 
-#: option.c:348
+#: option.c:360
 msgid "Read DHCP host specs from a directory."
 msgstr ""
 
-#: option.c:349
+#: option.c:361
 msgid "Read DHCP options from a directory."
 msgstr ""
 
-#: option.c:350
+#: option.c:362
 msgid "Evaluate conditional tag expression."
 msgstr ""
 
-#: option.c:351
+#: option.c:363
 #, c-format
 msgid "Do NOT load %s file."
 msgstr ""
 
-#: option.c:352
+#: option.c:364
 #, c-format
 msgid "Specify a hosts file to be read in addition to %s."
 msgstr ""
 
-#: option.c:353
+#: option.c:365
 msgid "Read hosts files from a directory."
 msgstr ""
 
-#: option.c:354
+#: option.c:366
 msgid "Specify interface(s) to listen on."
 msgstr ""
 
-#: option.c:355
+#: option.c:367
 msgid "Specify interface(s) NOT to listen on."
 msgstr ""
 
-#: option.c:356
+#: option.c:368
 msgid "Map DHCP user class to tag."
 msgstr ""
 
-#: option.c:357
+#: option.c:369
 msgid "Map RFC3046 circuit-id to tag."
 msgstr ""
 
-#: option.c:358
+#: option.c:370
 msgid "Map RFC3046 remote-id to tag."
 msgstr ""
 
-#: option.c:359
+#: option.c:371
 msgid "Map RFC3993 subscriber-id to tag."
 msgstr ""
 
-#: option.c:360
+#: option.c:372
 msgid "Don't do DHCP for hosts with tag set."
 msgstr ""
 
-#: option.c:361
+#: option.c:373
 msgid "Force broadcast replies for hosts with tag set."
 msgstr ""
 
-#: option.c:362
+#: option.c:374
 msgid "Do NOT fork into the background, do NOT run in debug mode."
 msgstr ""
 
-#: option.c:363
+#: option.c:375
 msgid "Assume we are the only DHCP server on the local network."
 msgstr ""
 
-#: option.c:364
+#: option.c:376
 #, c-format
 msgid "Specify where to store DHCP leases (defaults to %s)."
 msgstr ""
 
-#: option.c:365
+#: option.c:377
 msgid "Return MX records for local hosts."
 msgstr ""
 
-#: option.c:366
+#: option.c:378
 msgid "Specify an MX record."
 msgstr ""
 
-#: option.c:367
+#: option.c:379
 msgid "Specify BOOTP options to DHCP server."
 msgstr ""
 
-#: option.c:368
+#: option.c:380
 #, c-format
 msgid "Do NOT poll %s file, reload only on SIGHUP."
 msgstr ""
 
-#: option.c:369
+#: option.c:381
 msgid "Do NOT cache failed search results."
 msgstr ""
 
-#: option.c:370
+#: option.c:382
 #, c-format
 msgid "Use nameservers strictly in the order given in %s."
 msgstr ""
 
-#: option.c:371
+#: option.c:383
 msgid "Specify options to be sent to DHCP clients."
 msgstr ""
 
-#: option.c:372
+#: option.c:384
 msgid "DHCP option sent even if the client does not request it."
 msgstr ""
 
-#: option.c:373
+#: option.c:385
 msgid "Specify port to listen for DNS requests on (defaults to 53)."
 msgstr ""
 
-#: option.c:374
+#: option.c:386
 #, c-format
 msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
 msgstr ""
 
-#: option.c:375
+#: option.c:387
 msgid "Log DNS queries."
 msgstr ""
 
-#: option.c:376
+#: option.c:388
 msgid "Force the originating port for upstream DNS queries."
 msgstr ""
 
-#: option.c:377
+#: option.c:389
 msgid "Do NOT read resolv.conf."
 msgstr ""
 
-#: option.c:378
+#: option.c:390
 #, c-format
 msgid "Specify path to resolv.conf (defaults to %s)."
 msgstr ""
 
-#: option.c:379
+#: option.c:391
 msgid "Specify path to file with server= options"
 msgstr ""
 
-#: option.c:380
+#: option.c:392
 msgid "Specify address(es) of upstream servers with optional domains."
 msgstr ""
 
-#: option.c:381
+#: option.c:393
 msgid "Specify address of upstream servers for reverse address queries"
 msgstr ""
 
-#: option.c:382
+#: option.c:394
 msgid "Never forward queries to specified domains."
 msgstr ""
 
-#: option.c:383
+#: option.c:395
 msgid "Specify the domain to be assigned in DHCP leases."
 msgstr ""
 
-#: option.c:384
+#: option.c:396
 msgid "Specify default target in an MX record."
 msgstr ""
 
-#: option.c:385
+#: option.c:397
 msgid "Specify time-to-live in seconds for replies from /etc/hosts."
 msgstr ""
 
-#: option.c:386
+#: option.c:398
 msgid "Specify time-to-live in seconds for negative caching."
 msgstr ""
 
-#: option.c:387
+#: option.c:399
 msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
 msgstr ""
 
-#: option.c:388
+#: option.c:400
 msgid "Specify time-to-live ceiling for cache."
 msgstr ""
 
-#: option.c:389
+#: option.c:401
 msgid "Specify time-to-live floor for cache."
 msgstr ""
 
-#: option.c:390
+#: option.c:402
 #, c-format
 msgid "Change to this user after startup. (defaults to %s)."
 msgstr ""
 
-#: option.c:391
+#: option.c:403
 msgid "Map DHCP vendor class to tag."
 msgstr ""
 
-#: option.c:392
+#: option.c:404
 msgid "Display dnsmasq version and copyright information."
 msgstr ""
 
-#: option.c:393
+#: option.c:405
 msgid "Translate IPv4 addresses from upstream servers."
 msgstr ""
 
-#: option.c:394
+#: option.c:406
 msgid "Specify a SRV record."
 msgstr ""
 
-#: option.c:395
-msgid "Display this message. Use --help dhcp for known DHCP options."
+#: option.c:407
+msgid "Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."
 msgstr ""
 
-#: option.c:396
+#: option.c:408
 #, c-format
 msgid "Specify path of PID file (defaults to %s)."
 msgstr ""
 
-#: option.c:397
+#: option.c:409
 #, c-format
 msgid "Specify maximum number of DHCP leases (defaults to %s)."
 msgstr ""
 
-#: option.c:398
+#: option.c:410
 msgid "Answer DNS queries based on the interface a query was sent to."
 msgstr ""
 
-#: option.c:399
+#: option.c:411
 msgid "Specify TXT DNS record."
 msgstr ""
 
-#: option.c:400
+#: option.c:412
 msgid "Specify PTR DNS record."
 msgstr ""
 
-#: option.c:401
+#: option.c:413
 msgid "Give DNS name to IPv4 address of interface."
 msgstr ""
 
-#: option.c:402
+#: option.c:414
 msgid "Bind only to interfaces in use."
 msgstr ""
 
-#: option.c:403
+#: option.c:415
 #, c-format
 msgid "Read DHCP static host information from %s."
 msgstr ""
 
-#: option.c:404
+#: option.c:416
 msgid "Enable the DBus interface for setting upstream servers, etc."
 msgstr ""
 
-#: option.c:405
+#: option.c:417
 msgid "Do not provide DHCP on this interface, only provide DNS."
 msgstr ""
 
-#: option.c:406
+#: option.c:418
 msgid "Enable dynamic address allocation for bootp."
 msgstr ""
 
-#: option.c:407
+#: option.c:419
 msgid "Map MAC address (with wildcards) to option set."
 msgstr ""
 
-#: option.c:408
+#: option.c:420
 msgid "Treat DHCP requests on aliases as arriving from interface."
 msgstr ""
 
-#: option.c:409
+#: option.c:421
 msgid "Disable ICMP echo address checking in the DHCP server."
 msgstr ""
 
-#: option.c:410
+#: option.c:422
 msgid "Shell script to run on DHCP lease creation and destruction."
 msgstr ""
 
-#: option.c:411
+#: option.c:423
 msgid "Lua script to run on DHCP lease creation and destruction."
 msgstr ""
 
-#: option.c:412
+#: option.c:424
 msgid "Run lease-change scripts as this user."
 msgstr ""
 
-#: option.c:413
+#: option.c:425
+msgid "Call dhcp-script with changes to local ARP table."
+msgstr ""
+
+#: option.c:426
 msgid "Read configuration from all the files in this directory."
 msgstr ""
 
-#: option.c:414
+#: option.c:427
 msgid "Log to this syslog facility or file. (defaults to DAEMON)"
 msgstr ""
 
-#: option.c:415
+#: option.c:428
 msgid "Do not use leasefile."
 msgstr ""
 
-#: option.c:416
+#: option.c:429
 #, c-format
 msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
 msgstr ""
 
-#: option.c:417
+#: option.c:430
 #, c-format
 msgid "Clear DNS cache when reloading %s."
 msgstr ""
 
-#: option.c:418
+#: option.c:431
 msgid "Ignore hostnames provided by DHCP clients."
 msgstr ""
 
-#: option.c:419
+#: option.c:432
 msgid "Do NOT reuse filename and server fields for extra DHCP options."
 msgstr ""
 
-#: option.c:420
+#: option.c:433
 msgid "Enable integrated read-only TFTP server."
 msgstr ""
 
-#: option.c:421
+#: option.c:434
 msgid "Export files by TFTP only from the specified subtree."
 msgstr ""
 
-#: option.c:422
-msgid "Add client IP address to tftp-root."
+#: option.c:435
+msgid "Add client IP or hardware address to tftp-root."
 msgstr ""
 
-#: option.c:423
+#: option.c:436
 msgid "Allow access only to files owned by the user running dnsmasq."
 msgstr ""
 
-#: option.c:424
+#: option.c:437
 msgid "Do not terminate the service if TFTP directories are inaccessible."
 msgstr ""
 
-#: option.c:425
+#: option.c:438
 #, c-format
-msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgid "Maximum number of concurrent TFTP transfers (defaults to %s)."
 msgstr ""
 
-#: option.c:426
+#: option.c:439
+msgid "Maximum MTU to use for TFTP transfers."
+msgstr ""
+
+#: option.c:440
 msgid "Disable the TFTP blocksize extension."
 msgstr ""
 
-#: option.c:427
+#: option.c:441
 msgid "Convert TFTP filenames to lowercase"
 msgstr ""
 
-#: option.c:428
+#: option.c:442
 msgid "Ephemeral port range for use by TFTP transfers."
 msgstr ""
 
-#: option.c:429
+#: option.c:443
 msgid "Extra logging for DHCP."
 msgstr ""
 
-#: option.c:430
+#: option.c:444
 msgid "Enable async. logging; optionally set queue length."
 msgstr ""
 
-#: option.c:431
+#: option.c:445
 msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
 msgstr ""
 
-#: option.c:432
+#: option.c:446
 msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
 msgstr ""
 
-#: option.c:433
+#: option.c:447
 msgid "Inhibit DNS-rebind protection on this domain."
 msgstr ""
 
-#: option.c:434
+#: option.c:448
 msgid "Always perform DNS queries to all servers."
 msgstr ""
 
-#: option.c:435
+#: option.c:449
 msgid "Set tag if client includes matching option in request."
 msgstr ""
 
-#: option.c:436
+#: option.c:450
 msgid "Use alternative ports for DHCP."
 msgstr ""
 
-#: option.c:437
+#: option.c:451
 msgid "Specify NAPTR DNS record."
 msgstr ""
 
-#: option.c:438
+#: option.c:452
 msgid "Specify lowest port available for DNS query transmission."
 msgstr ""
 
-#: option.c:439
+#: option.c:453
+msgid "Specify highest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:454
 msgid "Use only fully qualified domain names for DHCP clients."
 msgstr ""
 
-#: option.c:440
+#: option.c:455
 msgid "Generate hostnames based on MAC address for nameless clients."
 msgstr ""
 
-#: option.c:441
+#: option.c:456
 msgid "Use these DHCP relays as full proxies."
 msgstr ""
 
-#: option.c:442
+#: option.c:457
 msgid "Relay DHCP requests to a remote server"
 msgstr ""
 
-#: option.c:443
+#: option.c:458
 msgid "Specify alias name for LOCAL DNS name."
 msgstr ""
 
-#: option.c:444
+#: option.c:459
 msgid "Prompt to send to PXE clients."
 msgstr ""
 
-#: option.c:445
+#: option.c:460
 msgid "Boot service for PXE menu."
 msgstr ""
 
-#: option.c:446
+#: option.c:461
 msgid "Check configuration syntax."
 msgstr ""
 
-#: option.c:447
+#: option.c:462
 msgid "Add requestor's MAC address to forwarded DNS queries."
 msgstr ""
 
-#: option.c:448
-msgid "Add requestor's IP subnet to forwarded DNS queries."
+#: option.c:463
+msgid "Add specified IP subnet to forwarded DNS queries."
 msgstr ""
 
-#: option.c:449
+#: option.c:464
+msgid "Add client identification to forwarded DNS queries."
+msgstr ""
+
+#: option.c:465
 msgid "Proxy DNSSEC validation results from upstream nameservers."
 msgstr ""
 
-#: option.c:450
+#: option.c:466
 msgid "Attempt to allocate sequential IP addresses to DHCP clients."
 msgstr ""
 
-#: option.c:451
+#: option.c:467
 msgid "Copy connection-track mark from queries to upstream connections."
 msgstr ""
 
-#: option.c:452
+#: option.c:468
 msgid "Allow DHCP clients to do their own DDNS updates."
 msgstr ""
 
-#: option.c:453
+#: option.c:469
 msgid "Send router-advertisements for interfaces doing DHCPv6"
 msgstr ""
 
-#: option.c:454
+#: option.c:470
 msgid "Specify DUID_EN-type DHCPv6 server DUID"
 msgstr ""
 
-#: option.c:455
+#: option.c:471
 msgid "Specify host (A/AAAA and PTR) records"
 msgstr ""
 
-#: option.c:456
+#: option.c:472
 msgid "Specify arbitrary DNS resource record"
 msgstr ""
 
-#: option.c:457
+#: option.c:473
 msgid "Bind to interfaces in use - check for new interfaces"
 msgstr ""
 
-#: option.c:458
+#: option.c:474
 msgid "Export local names to global DNS"
 msgstr ""
 
-#: option.c:459
+#: option.c:475
 msgid "Domain to export to global DNS"
 msgstr ""
 
-#: option.c:460
+#: option.c:476
 msgid "Set TTL for authoritative replies"
 msgstr ""
 
-#: option.c:461
-msgid "Set authoritive zone information"
+#: option.c:477
+msgid "Set authoritative zone information"
 msgstr ""
 
-#: option.c:462
+#: option.c:478
 msgid "Secondary authoritative nameservers for forward domains"
 msgstr ""
 
-#: option.c:463
+#: option.c:479
 msgid "Peers which are allowed to do zone transfer"
 msgstr ""
 
-#: option.c:464
+#: option.c:480
 msgid "Specify ipsets to which matching domains should be added"
 msgstr ""
 
-#: option.c:465
+#: option.c:481
 msgid "Specify a domain and address range for synthesised names"
 msgstr ""
 
-#: option.c:466
+#: option.c:482
 msgid "Activate DNSSEC validation"
 msgstr ""
 
-#: option.c:467
+#: option.c:483
 msgid "Specify trust anchor key digest."
 msgstr ""
 
-#: option.c:468
+#: option.c:484
 msgid "Disable upstream checking for DNSSEC debugging."
 msgstr ""
 
-#: option.c:469
+#: option.c:485
 msgid "Ensure answers without DNSSEC are in unsigned zones."
 msgstr ""
 
-#: option.c:470
+#: option.c:486
 msgid "Don't check DNSSEC signature timestamps until first cache-reload"
 msgstr ""
 
-#: option.c:471
+#: option.c:487
 msgid "Timestamp file to verify system clock for DNSSEC"
 msgstr ""
 
-#: option.c:473
+#: option.c:489
 msgid "Specify DHCPv6 prefix class"
 msgstr ""
 
-#: option.c:475
-msgid "Set priority, resend-interval and router-lifetime"
+#: option.c:491
+msgid "Set MTU, priority, resend-interval and router-lifetime"
 msgstr ""
 
-#: option.c:476
+#: option.c:492
 msgid "Do not log routine DHCP."
 msgstr ""
 
-#: option.c:477
+#: option.c:493
 msgid "Do not log routine DHCPv6."
 msgstr ""
 
-#: option.c:478
+#: option.c:494
 msgid "Do not log RA."
 msgstr ""
 
-#: option.c:479
-msgid "Accept queries only from directly-connected networks"
+#: option.c:495
+msgid "Accept queries only from directly-connected networks."
 msgstr ""
 
-#: option.c:480
-msgid "Detect and remove DNS forwarding loops"
+#: option.c:496
+msgid "Detect and remove DNS forwarding loops."
 msgstr ""
 
-#: option.c:481
+#: option.c:497
 msgid "Ignore DNS responses containing ipaddr."
 msgstr ""
 
-#: option.c:683
+#: option.c:498
+msgid "Set TTL in DNS responses with DHCP-derived addresses."
+msgstr ""
+
+#: option.c:499
+msgid "Delay DHCP replies for at least number of seconds."
+msgstr ""
+
+#: option.c:703
 #, c-format
 msgid ""
 "Usage: dnsmasq [options]\n"
 "\n"
 msgstr ""
 
-#: option.c:685
+#: option.c:705
 #, c-format
 msgid "Use short options only on the command line.\n"
 msgstr ""
 
-#: option.c:687
+#: option.c:707
 #, c-format
 msgid "Valid options are:\n"
 msgstr ""
 
-#: option.c:744 option.c:748
+#: option.c:754 option.c:868
+msgid "bad address"
+msgstr ""
+
+#: option.c:779 option.c:783
 msgid "bad port"
 msgstr ""
 
-#: option.c:775 option.c:807
+#: option.c:797 option.c:826 option.c:861
 msgid "interface binding not supported"
 msgstr ""
 
-#: option.c:784 option.c:3575
-msgid "bad interface name"
+#: option.c:821 option.c:856
+msgid "interface can only be specified once"
 msgstr ""
 
-#: option.c:814
-msgid "bad address"
+#: option.c:835 option.c:3809
+msgid "bad interface name"
 msgstr ""
 
-#: option.c:996
+#: option.c:1062
 msgid "unsupported encapsulation for IPv6 option"
 msgstr ""
 
-#: option.c:1010
+#: option.c:1076
 msgid "bad dhcp-option"
 msgstr ""
 
-#: option.c:1078
+#: option.c:1144
 msgid "bad IP address"
 msgstr ""
 
-#: option.c:1081 option.c:1219 option.c:2893
+#: option.c:1147 option.c:1286 option.c:3079
 msgid "bad IPv6 address"
 msgstr ""
 
-#: option.c:1246 option.c:1340
+#: option.c:1240
+msgid "bad IPv4 address"
+msgstr ""
+
+#: option.c:1313 option.c:1407
 msgid "bad domain in dhcp-option"
 msgstr ""
 
-#: option.c:1378
+#: option.c:1445
 msgid "dhcp-option too long"
 msgstr ""
 
-#: option.c:1385
+#: option.c:1452
 msgid "illegal dhcp-match"
 msgstr ""
 
-#: option.c:1447
+#: option.c:1514
 msgid "illegal repeated flag"
 msgstr ""
 
-#: option.c:1455
+#: option.c:1522
 msgid "illegal repeated keyword"
 msgstr ""
 
-#: option.c:1520 option.c:4191
+#: option.c:1593 option.c:4443
 #, c-format
 msgid "cannot access directory %s: %s"
 msgstr ""
 
-#: option.c:1566 tftp.c:493
+#: option.c:1639 tftp.c:537
 #, c-format
 msgid "cannot access %s: %s"
 msgstr ""
 
-#: option.c:1618
+#: option.c:1727
 msgid "setting log facility is not possible under Android"
 msgstr ""
 
-#: option.c:1627
+#: option.c:1736
 msgid "bad log facility"
 msgstr ""
 
-#: option.c:1680
+#: option.c:1789
 msgid "bad MX preference"
 msgstr ""
 
-#: option.c:1685
+#: option.c:1794
 msgid "bad MX name"
 msgstr ""
 
-#: option.c:1699
+#: option.c:1808
 msgid "bad MX target"
 msgstr ""
 
-#: option.c:1711
+#: option.c:1820
 msgid "cannot run scripts under uClinux"
 msgstr ""
 
-#: option.c:1713
+#: option.c:1822
 msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
 msgstr ""
 
-#: option.c:1717
+#: option.c:1826
 msgid "recompile with HAVE_LUASCRIPT defined to enable Lua scripts"
 msgstr ""
 
-#: option.c:1973 option.c:2018 option.c:2074
+#: option.c:2095 option.c:2106 option.c:2143 option.c:2199 option.c:2482
 msgid "bad prefix"
 msgstr ""
 
-#: option.c:2355
+#: option.c:2504
 msgid "recompile with HAVE_IPSET defined to enable ipset directives"
 msgstr ""
 
-#: option.c:2548
+#: option.c:2713
 msgid "bad port range"
 msgstr ""
 
-#: option.c:2564
+#: option.c:2739
 msgid "bad bridge-interface"
 msgstr ""
 
-#: option.c:2624
+#: option.c:2807
 msgid "only one tag allowed"
 msgstr ""
 
-#: option.c:2644 option.c:2656 option.c:2764 option.c:2805
+#: option.c:2827 option.c:2839 option.c:2948 option.c:2953 option.c:2992
 msgid "bad dhcp-range"
 msgstr ""
 
-#: option.c:2671
+#: option.c:2854
 msgid "inconsistent DHCP range"
 msgstr ""
 
-#: option.c:2732
+#: option.c:2916
 msgid "prefix length must be exactly 64 for RA subnets"
 msgstr ""
 
-#: option.c:2734
+#: option.c:2918
 msgid "prefix length must be exactly 64 for subnet constructors"
 msgstr ""
 
-#: option.c:2738
+#: option.c:2922
 msgid "prefix length must be at least 64"
 msgstr ""
 
-#: option.c:2741
+#: option.c:2925
 msgid "inconsistent DHCPv6 range"
 msgstr ""
 
-#: option.c:2752
+#: option.c:2936
 msgid "prefix must be zero with \"constructor:\" argument"
 msgstr ""
 
-#: option.c:2863 option.c:2911
+#: option.c:3049 option.c:3097
 msgid "bad hex constant"
 msgstr ""
 
-#: option.c:2885
+#: option.c:3071
 msgid "cannot match tags in --dhcp-host"
 msgstr ""
 
-#: option.c:2933
+#: option.c:3119
 #, c-format
 msgid "duplicate dhcp-host IP address %s"
 msgstr ""
 
-#: option.c:2991
+#: option.c:3177
 msgid "bad DHCP host name"
 msgstr ""
 
-#: option.c:3073
+#: option.c:3259
 msgid "bad tag-if"
 msgstr ""
 
-#: option.c:3397 option.c:3791
+#: option.c:3616 option.c:4039
 msgid "invalid port number"
 msgstr ""
 
-#: option.c:3459
+#: option.c:3678
 msgid "bad dhcp-proxy address"
 msgstr ""
 
-#: option.c:3485
+#: option.c:3704
 msgid "Bad dhcp-relay"
 msgstr ""
 
-#: option.c:3511
+#: option.c:3745
 msgid "bad RA-params"
 msgstr ""
 
-#: option.c:3520
+#: option.c:3754
 msgid "bad DUID"
 msgstr ""
 
-#: option.c:3562
+#: option.c:3796
 msgid "invalid alias range"
 msgstr ""
 
-#: option.c:3616
+#: option.c:3850 option.c:3862
 msgid "bad CNAME"
 msgstr ""
 
-#: option.c:3621
+#: option.c:3866
 msgid "duplicate CNAME"
 msgstr ""
 
-#: option.c:3641
+#: option.c:3889
 msgid "bad PTR record"
 msgstr ""
 
-#: option.c:3672
+#: option.c:3920
 msgid "bad NAPTR record"
 msgstr ""
 
-#: option.c:3706
+#: option.c:3954
 msgid "bad RR record"
 msgstr ""
 
-#: option.c:3736
+#: option.c:3984
 msgid "bad TXT record"
 msgstr ""
 
-#: option.c:3777
+#: option.c:4025
 msgid "bad SRV record"
 msgstr ""
 
-#: option.c:3784
+#: option.c:4032
 msgid "bad SRV target"
 msgstr ""
 
-#: option.c:3798
+#: option.c:4046
 msgid "invalid priority"
 msgstr ""
 
-#: option.c:3805
+#: option.c:4049
 msgid "invalid weight"
 msgstr ""
 
-#: option.c:3829
+#: option.c:4073
 msgid "Bad host-record"
 msgstr ""
 
-#: option.c:3846
+#: option.c:4097
 msgid "Bad name in host-record"
 msgstr ""
 
-#: option.c:3911
+#: option.c:4162
 msgid "bad trust anchor"
 msgstr ""
 
-#: option.c:3925
+#: option.c:4176
 msgid "bad HEX in trust anchor"
 msgstr ""
 
-#: option.c:3935
+#: option.c:4186
 msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"
 msgstr ""
 
-#: option.c:3994
+#: option.c:4246
 msgid "missing \""
 msgstr ""
 
-#: option.c:4051
+#: option.c:4303
 msgid "bad option"
 msgstr ""
 
-#: option.c:4053
+#: option.c:4305
 msgid "extraneous parameter"
 msgstr ""
 
-#: option.c:4055
+#: option.c:4307
 msgid "missing parameter"
 msgstr ""
 
-#: option.c:4057
+#: option.c:4309
 msgid "illegal option"
 msgstr ""
 
-#: option.c:4064
+#: option.c:4316
 msgid "error"
 msgstr ""
 
-#: option.c:4066
+#: option.c:4318
 #, c-format
 msgid " at line %d of %s"
 msgstr ""
 
-#: option.c:4081 option.c:4328 option.c:4364
+#: option.c:4333 option.c:4580 option.c:4616
 #, c-format
 msgid "read %s"
 msgstr ""
 
-#: option.c:4144 option.c:4267 tftp.c:667
+#: option.c:4396 option.c:4519 tftp.c:715
 #, c-format
 msgid "cannot read %s: %s"
 msgstr ""
 
-#: option.c:4430
+#: option.c:4688
 msgid "junk found in command line"
 msgstr ""
 
-#: option.c:4465
+#: option.c:4729
 #, c-format
 msgid "Dnsmasq version %s  %s\n"
 msgstr ""
 
-#: option.c:4466
+#: option.c:4730
 #, c-format
 msgid ""
 "Compile time options: %s\n"
 "\n"
 msgstr ""
 
-#: option.c:4467
+#: option.c:4731
 #, c-format
 msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
 msgstr ""
 
-#: option.c:4468
+#: option.c:4732
 #, c-format
 msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
 msgstr ""
 
-#: option.c:4469
+#: option.c:4733
 #, c-format
 msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
 msgstr ""
 
-#: option.c:4480
+#: option.c:4744
 msgid "try --help"
 msgstr ""
 
-#: option.c:4482
+#: option.c:4746
 msgid "try -w"
 msgstr ""
 
-#: option.c:4484
+#: option.c:4748
 #, c-format
 msgid "bad command line options: %s"
 msgstr ""
 
-#: option.c:4541
+#: option.c:4818
+#, c-format
+msgid "CNAME loop involving %s"
+msgstr ""
+
+#: option.c:4854
 #, c-format
 msgid "cannot get host-name: %s"
 msgstr ""
 
-#: option.c:4569
+#: option.c:4882
 msgid "only one resolv.conf file allowed in no-poll mode."
 msgstr ""
 
-#: option.c:4579
+#: option.c:4892
 msgid "must have exactly one resolv.conf to read domain from."
 msgstr ""
 
-#: option.c:4582 network.c:1507 dhcp.c:777
+#: option.c:4895 network.c:1623 dhcp.c:816
 #, c-format
 msgid "failed to read %s: %s"
 msgstr ""
 
-#: option.c:4599
+#: option.c:4912
 #, c-format
 msgid "no search directive found in %s"
 msgstr ""
 
-#: option.c:4620
+#: option.c:4933
 msgid "there must be a default domain when --dhcp-fqdn is set"
 msgstr ""
 
-#: option.c:4629
+#: option.c:4942
 msgid "syntax check OK"
 msgstr ""
 
-#: forward.c:111
+#: forward.c:102
 #, c-format
 msgid "failed to send packet: %s"
 msgstr ""
 
-#: forward.c:591
+#: forward.c:598
 msgid "discarding DNS reply: subnet option mismatch"
 msgstr ""
 
-#: forward.c:614
+#: forward.c:652
 #, c-format
 msgid "nameserver %s refused to do a recursive query"
 msgstr ""
 
-#: forward.c:646
+#: forward.c:684
 #, c-format
 msgid "possible DNS-rebind attack detected: %s"
 msgstr ""
 
-#: forward.c:1209 forward.c:1815
+#: forward.c:870
+#, c-format
+msgid "reducing DNS packet size for nameserver %s to %d"
+msgstr ""
+
+#: forward.c:1266 forward.c:1704
 msgid "Ignoring query from non-local network"
 msgstr ""
 
-#: forward.c:2286
+#: forward.c:2184
 #, c-format
 msgid "Maximum number of concurrent DNS queries reached (max: %d)"
 msgstr ""
 
-#: network.c:715
+#: network.c:720
 #, c-format
 msgid "failed to create listening socket for %s: %s"
 msgstr ""
 
-#: network.c:1021
+#: network.c:1031
 #, c-format
 msgid "LOUD WARNING: listening on %s may accept requests via interfaces other than %s"
 msgstr ""
 
-#: network.c:1028
+#: network.c:1038
 msgid "LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"
 msgstr ""
 
-#: network.c:1037
+#: network.c:1047
+#, c-format
+msgid "warning: using interface %s instead"
+msgstr ""
+
+#: network.c:1056
 #, c-format
 msgid "warning: no addresses found for interface %s"
 msgstr ""
 
-#: network.c:1095
+#: network.c:1114
 #, c-format
 msgid "interface %s failed to join DHCPv6 multicast group: %s"
 msgstr ""
 
-#: network.c:1289
+#: network.c:1119
+msgid "try increasing /proc/sys/net/core/optmem_max"
+msgstr ""
+
+#: network.c:1337
 #, c-format
 msgid "failed to bind server socket for %s: %s"
 msgstr ""
 
-#: network.c:1445
+#: network.c:1528
 #, c-format
 msgid "ignoring nameserver %s - local interface"
 msgstr ""
 
-#: network.c:1456
+#: network.c:1539
 #, c-format
 msgid "ignoring nameserver %s - cannot make/bind socket: %s"
 msgstr ""
 
-#: network.c:1469
+#: network.c:1559
+msgid "(no DNSSEC)"
+msgstr ""
+
+#: network.c:1562
 msgid "unqualified"
 msgstr ""
 
-#: network.c:1469
+#: network.c:1562
 msgid "names"
 msgstr ""
 
-#: network.c:1471
+#: network.c:1564
 msgid "default"
 msgstr ""
 
-#: network.c:1473
+#: network.c:1566
 msgid "domain"
 msgstr ""
 
-#: network.c:1476
+#: network.c:1572
 #, c-format
 msgid "using local addresses only for %s %s"
 msgstr ""
 
-#: network.c:1478
+#: network.c:1575
 #, c-format
 msgid "using standard nameservers for %s %s"
 msgstr ""
 
-#: network.c:1480
+#: network.c:1577
 #, c-format
-msgid "using nameserver %s#%d for %s %s"
+msgid "using nameserver %s#%d for %s %s %s"
 msgstr ""
 
-#: network.c:1484
+#: network.c:1581
 #, c-format
 msgid "NOT using nameserver %s#%d - query loop detected"
 msgstr ""
 
-#: network.c:1487
+#: network.c:1584
 #, c-format
 msgid "using nameserver %s#%d(via %s)"
 msgstr ""
 
-#: network.c:1489
+#: network.c:1586
 #, c-format
 msgid "using nameserver %s#%d"
 msgstr ""
 
-#: dnsmasq.c:163
+#: network.c:1591
+#, c-format
+msgid "using %d more local addresses"
+msgstr ""
+
+#: network.c:1593
+#, c-format
+msgid "using %d more nameservers"
+msgstr ""
+
+#: dnsmasq.c:171
 msgid "dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"
 msgstr ""
 
-#: dnsmasq.c:170
-msgid "no trust anchors provided for DNSSEC"
+#: dnsmasq.c:186
+msgid "no root trust anchor provided for DNSSEC"
 msgstr ""
 
-#: dnsmasq.c:173
+#: dnsmasq.c:189
 msgid "cannot reduce cache size from default when DNSSEC enabled"
 msgstr ""
 
-#: dnsmasq.c:175
+#: dnsmasq.c:191
 msgid "DNSSEC not available: set HAVE_DNSSEC in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:181
+#: dnsmasq.c:197
 msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:186
+#: dnsmasq.c:202
 msgid "cannot use --conntrack AND --query-port"
 msgstr ""
 
-#: dnsmasq.c:189
+#: dnsmasq.c:205
 msgid "conntrack support not available: set HAVE_CONNTRACK in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:194
-msgid "asychronous logging is not available under Solaris"
+#: dnsmasq.c:210
+msgid "asynchronous logging is not available under Solaris"
 msgstr ""
 
-#: dnsmasq.c:199
-msgid "asychronous logging is not available under Android"
+#: dnsmasq.c:215
+msgid "asynchronous logging is not available under Android"
 msgstr ""
 
-#: dnsmasq.c:204
+#: dnsmasq.c:220
 msgid "authoritative DNS not available: set HAVE_AUTH in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:209
+#: dnsmasq.c:225
 msgid "loop detection not available: set HAVE_LOOP in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:217
+#: dnsmasq.c:229
+msgid "max_port cannot be smaller than min_port"
+msgstr ""
+
+#: dnsmasq.c:236
 msgid "zone serial must be configured in --auth-soa"
 msgstr ""
 
-#: dnsmasq.c:235
+#: dnsmasq.c:254
 msgid "dhcp-range constructor not available on this platform"
 msgstr ""
 
-#: dnsmasq.c:278
+#: dnsmasq.c:300
 msgid "cannot set --bind-interfaces and --bind-dynamic"
 msgstr ""
 
-#: dnsmasq.c:281
+#: dnsmasq.c:303
 #, c-format
 msgid "failed to find list of interfaces: %s"
 msgstr ""
 
-#: dnsmasq.c:290
+#: dnsmasq.c:312
 #, c-format
 msgid "unknown interface %s"
 msgstr ""
 
-#: dnsmasq.c:354 dnsmasq.c:997
+#: dnsmasq.c:377 dnsmasq.c:1054
 #, c-format
 msgid "DBus error: %s"
 msgstr ""
 
-#: dnsmasq.c:357
+#: dnsmasq.c:380
 msgid "DBus not available: set HAVE_DBUS in src/config.h"
 msgstr ""
 
-#: dnsmasq.c:385
+#: dnsmasq.c:410
 #, c-format
 msgid "unknown user or group: %s"
 msgstr ""
 
-#: dnsmasq.c:440
+#: dnsmasq.c:465
 #, c-format
 msgid "cannot chdir to filesystem root: %s"
 msgstr ""
 
-#: dnsmasq.c:692
+#: dnsmasq.c:730
 #, c-format
 msgid "started, version %s DNS disabled"
 msgstr ""
 
-#: dnsmasq.c:694
+#: dnsmasq.c:734
 #, c-format
 msgid "started, version %s cachesize %d"
 msgstr ""
 
-#: dnsmasq.c:696
+#: dnsmasq.c:736
 #, c-format
 msgid "started, version %s cache disabled"
 msgstr ""
 
-#: dnsmasq.c:698
+#: dnsmasq.c:739
+msgid "DNS service limited to local subnets"
+msgstr ""
+
+#: dnsmasq.c:742
 #, c-format
 msgid "compile time options: %s"
 msgstr ""
 
-#: dnsmasq.c:704
+#: dnsmasq.c:751
 msgid "DBus support enabled: connected to system bus"
 msgstr ""
 
-#: dnsmasq.c:706
+#: dnsmasq.c:753
 msgid "DBus support enabled: bus connection pending"
 msgstr ""
 
-#: dnsmasq.c:711
-msgid "DNS service limited to local subnets"
-msgstr ""
-
-#: dnsmasq.c:727
+#: dnsmasq.c:771
 msgid "DNSSEC validation enabled"
 msgstr ""
 
-#: dnsmasq.c:730
-msgid "DNSSEC signature timestamps not checked until first cache reload"
+#: dnsmasq.c:775
+msgid "DNSSEC signature timestamps not checked until receipt of SIGINT"
 msgstr ""
 
-#: dnsmasq.c:733
+#: dnsmasq.c:778
 msgid "DNSSEC signature timestamps not checked until system time valid"
 msgstr ""
 
-#: dnsmasq.c:738
+#: dnsmasq.c:783
 #, c-format
 msgid "warning: failed to change owner of %s: %s"
 msgstr ""
 
-#: dnsmasq.c:742
+#: dnsmasq.c:787
 msgid "setting --bind-interfaces option because of OS limitations"
 msgstr ""
 
-#: dnsmasq.c:752
+#: dnsmasq.c:799
 #, c-format
 msgid "warning: interface %s does not currently exist"
 msgstr ""
 
-#: dnsmasq.c:757
+#: dnsmasq.c:804
 msgid "warning: ignoring resolv-file flag because no-resolv is set"
 msgstr ""
 
-#: dnsmasq.c:760
+#: dnsmasq.c:807
 msgid "warning: no upstream servers configured"
 msgstr ""
 
-#: dnsmasq.c:764
+#: dnsmasq.c:811
 #, c-format
 msgid "asynchronous logging enabled, queue limit is %d messages"
 msgstr ""
 
-#: dnsmasq.c:785
+#: dnsmasq.c:832
 msgid "IPv6 router advertisement enabled"
 msgstr ""
 
-#: dnsmasq.c:790
+#: dnsmasq.c:837
 #, c-format
 msgid "DHCP, sockets bound exclusively to interface %s"
 msgstr ""
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "root is "
 msgstr ""
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "enabled"
 msgstr ""
 
-#: dnsmasq.c:806
+#: dnsmasq.c:853
 msgid "secure mode"
 msgstr ""
 
-#: dnsmasq.c:809
+#: dnsmasq.c:856
 #, c-format
 msgid "warning: %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:813
+#: dnsmasq.c:860
 #, c-format
 msgid "warning: TFTP directory %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:839
+#: dnsmasq.c:886
 #, c-format
 msgid "restricting maximum simultaneous TFTP transfers to %d"
 msgstr ""
 
-#: dnsmasq.c:999
+#: dnsmasq.c:1056
 msgid "connected to system DBus"
 msgstr ""
 
-#: dnsmasq.c:1149
+#: dnsmasq.c:1215
 #, c-format
 msgid "cannot fork into background: %s"
 msgstr ""
 
-#: dnsmasq.c:1152
+#: dnsmasq.c:1218
 #, c-format
 msgid "failed to create helper: %s"
 msgstr ""
 
-#: dnsmasq.c:1155
+#: dnsmasq.c:1221
 #, c-format
 msgid "setting capabilities failed: %s"
 msgstr ""
 
-#: dnsmasq.c:1158
+#: dnsmasq.c:1224
 #, c-format
 msgid "failed to change user-id to %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1161
+#: dnsmasq.c:1227
 #, c-format
 msgid "failed to change group-id to %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1164
+#: dnsmasq.c:1230
 #, c-format
 msgid "failed to open pidfile %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1167
+#: dnsmasq.c:1233
 #, c-format
 msgid "cannot open log %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1170
+#: dnsmasq.c:1236
 #, c-format
 msgid "failed to load Lua script: %s"
 msgstr ""
 
-#: dnsmasq.c:1173
+#: dnsmasq.c:1239
 #, c-format
 msgid "TFTP directory %s inaccessible: %s"
 msgstr ""
 
-#: dnsmasq.c:1176
+#: dnsmasq.c:1242
 #, c-format
 msgid "cannot create timestamp file %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1197
-msgid "now checking DNSSEC signature timestamps"
-msgstr ""
-
-#: dnsmasq.c:1264
+#: dnsmasq.c:1326
 #, c-format
 msgid "script process killed by signal %d"
 msgstr ""
 
-#: dnsmasq.c:1268
+#: dnsmasq.c:1330
 #, c-format
 msgid "script process exited with status %d"
 msgstr ""
 
-#: dnsmasq.c:1272
+#: dnsmasq.c:1334
 #, c-format
 msgid "failed to execute %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1327
+#: dnsmasq.c:1374
+msgid "now checking DNSSEC signature timestamps"
+msgstr ""
+
+#: dnsmasq.c:1409 dnssec.c:160 dnssec.c:206
+#, c-format
+msgid "failed to update mtime on %s: %s"
+msgstr ""
+
+#: dnsmasq.c:1416
 msgid "exiting on receipt of SIGTERM"
 msgstr ""
 
-#: dnsmasq.c:1355
+#: dnsmasq.c:1444
 #, c-format
 msgid "failed to access %s: %s"
 msgstr ""
 
-#: dnsmasq.c:1385
+#: dnsmasq.c:1474
 #, c-format
 msgid "reading %s"
 msgstr ""
 
-#: dnsmasq.c:1396
+#: dnsmasq.c:1485
 #, c-format
 msgid "no servers found in %s, will retry"
 msgstr ""
@@ -1521,243 +1595,263 @@ msgstr ""
 msgid "cannot create ICMP raw socket: %s."
 msgstr ""
 
-#: dhcp.c:241 dhcp6.c:180
+#: dhcp.c:252 dhcp6.c:173
 #, c-format
 msgid "unknown interface %s in bridge-interface"
 msgstr ""
 
-#: dhcp.c:281
+#: dhcp.c:293
 #, c-format
 msgid "DHCP packet received on %s which has no address"
 msgstr ""
 
-#: dhcp.c:415
+#: dhcp.c:427
 #, c-format
 msgid "ARP-cache injection failed: %s"
 msgstr ""
 
-#: dhcp.c:514
+#: dhcp.c:470
+#, c-format
+msgid "Error sending DHCP packet to %s: %s"
+msgstr ""
+
+#: dhcp.c:531
 #, c-format
 msgid "DHCP range %s -- %s is not consistent with netmask %s"
 msgstr ""
 
-#: dhcp.c:815
+#: dhcp.c:854
 #, c-format
 msgid "bad line at %s line %d"
 msgstr ""
 
-#: dhcp.c:858
+#: dhcp.c:897
 #, c-format
 msgid "ignoring %s line %d, duplicate name or IP address"
 msgstr ""
 
-#: dhcp.c:1002 rfc3315.c:2135
+#: dhcp.c:1041 rfc3315.c:2149
 #, c-format
 msgid "DHCP relay %s -> %s"
 msgstr ""
 
-#: lease.c:61
+#: lease.c:98
+msgid "too many stored leases"
+msgstr ""
+
+#: lease.c:166
 #, c-format
 msgid "cannot open or create lease file %s: %s"
 msgstr ""
 
-#: lease.c:134
-msgid "too many stored leases"
+#: lease.c:175
+#, c-format
+msgid "failed to parse lease database, invalid line: %s %s %s %s ..."
 msgstr ""
 
-#: lease.c:165
+#: lease.c:180
+#, c-format
+msgid "failed to read lease file %s: %s"
+msgstr ""
+
+#: lease.c:196
 #, c-format
 msgid "cannot run lease-init script %s: %s"
 msgstr ""
 
-#: lease.c:171
+#: lease.c:202
 #, c-format
 msgid "lease-init script returned exit code %s"
 msgstr ""
 
-#: lease.c:342
+#: lease.c:373
 #, c-format
 msgid "failed to write %s: %s (retry in %us)"
 msgstr ""
 
-#: lease.c:906
+#: lease.c:937
 #, c-format
 msgid "Ignoring domain %s for DHCP host name %s"
 msgstr ""
 
-#: rfc2131.c:344
+#: rfc2131.c:347
 #, c-format
 msgid "no address range available for DHCP request %s %s"
 msgstr ""
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "with subnet selector"
 msgstr ""
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "via"
 msgstr ""
 
-#: rfc2131.c:357
+#: rfc2131.c:360
 #, c-format
 msgid "%u available DHCP subnet: %s/%s"
 msgstr ""
 
-#: rfc2131.c:360 rfc3315.c:300
+#: rfc2131.c:363 rfc3315.c:306
 #, c-format
 msgid "%u available DHCP range: %s -- %s"
 msgstr ""
 
-#: rfc2131.c:471
+#: rfc2131.c:474
 #, c-format
 msgid "%u vendor class: %s"
 msgstr ""
 
-#: rfc2131.c:473
+#: rfc2131.c:476
 #, c-format
 msgid "%u user class: %s"
 msgstr ""
 
-#: rfc2131.c:500
+#: rfc2131.c:510
 msgid "disabled"
 msgstr ""
 
-#: rfc2131.c:541 rfc2131.c:974 rfc2131.c:1380 rfc3315.c:603 rfc3315.c:856
-#: rfc3315.c:1135
+#: rfc2131.c:551 rfc2131.c:1006 rfc2131.c:1430 rfc3315.c:616 rfc3315.c:869
+#: rfc3315.c:1148
 msgid "ignored"
 msgstr ""
 
-#: rfc2131.c:556 rfc2131.c:1207 rfc3315.c:906
+#: rfc2131.c:566 rfc2131.c:1239 rfc3315.c:919
 msgid "address in use"
 msgstr ""
 
-#: rfc2131.c:570 rfc2131.c:1028
+#: rfc2131.c:580 rfc2131.c:1060
 msgid "no address available"
 msgstr ""
 
-#: rfc2131.c:577 rfc2131.c:1170
+#: rfc2131.c:587 rfc2131.c:1202
 msgid "wrong network"
 msgstr ""
 
-#: rfc2131.c:592
+#: rfc2131.c:602
 msgid "no address configured"
 msgstr ""
 
-#: rfc2131.c:598 rfc2131.c:1220
+#: rfc2131.c:608 rfc2131.c:1252
 msgid "no leases left"
 msgstr ""
 
-#: rfc2131.c:693 rfc3315.c:476
+#: rfc2131.c:703 rfc3315.c:482
 #, c-format
 msgid "%u client provides name: %s"
 msgstr ""
 
-#: rfc2131.c:798
+#: rfc2131.c:808
 msgid "PXE BIS not supported"
 msgstr ""
 
-#: rfc2131.c:942 rfc3315.c:1229
+#: rfc2131.c:974 rfc3315.c:1242
 #, c-format
 msgid "disabling DHCP static address %s for %s"
 msgstr ""
 
-#: rfc2131.c:963
+#: rfc2131.c:995
 msgid "unknown lease"
 msgstr ""
 
-#: rfc2131.c:997
+#: rfc2131.c:1029
 #, c-format
 msgid "not using configured address %s because it is leased to %s"
 msgstr ""
 
-#: rfc2131.c:1007
+#: rfc2131.c:1039
 #, c-format
 msgid "not using configured address %s because it is in use by the server or relay"
 msgstr ""
 
-#: rfc2131.c:1010
+#: rfc2131.c:1042
 #, c-format
 msgid "not using configured address %s because it was previously declined"
 msgstr ""
 
-#: rfc2131.c:1026 rfc2131.c:1213
+#: rfc2131.c:1058 rfc2131.c:1245
 msgid "no unique-id"
 msgstr ""
 
-#: rfc2131.c:1108
+#: rfc2131.c:1140
 msgid "wrong server-ID"
 msgstr ""
 
-#: rfc2131.c:1127
+#: rfc2131.c:1159
 msgid "wrong address"
 msgstr ""
 
-#: rfc2131.c:1145 rfc3315.c:1002
+#: rfc2131.c:1177 rfc3315.c:1015
 msgid "lease not found"
 msgstr ""
 
-#: rfc2131.c:1178
+#: rfc2131.c:1210
 msgid "address not available"
 msgstr ""
 
-#: rfc2131.c:1189
+#: rfc2131.c:1221
 msgid "static lease available"
 msgstr ""
 
-#: rfc2131.c:1193
+#: rfc2131.c:1225
 msgid "address reserved"
 msgstr ""
 
-#: rfc2131.c:1201
+#: rfc2131.c:1233
 #, c-format
 msgid "abandoning lease to %s of %s"
 msgstr ""
 
-#: rfc2131.c:1707
+#: rfc2131.c:1757
 #, c-format
 msgid "%u bootfile name: %s"
 msgstr ""
 
-#: rfc2131.c:1716
+#: rfc2131.c:1766
 #, c-format
 msgid "%u server name: %s"
 msgstr ""
 
-#: rfc2131.c:1724
+#: rfc2131.c:1774
 #, c-format
 msgid "%u next server: %s"
 msgstr ""
 
-#: rfc2131.c:1727
+#: rfc2131.c:1777
 #, c-format
 msgid "%u broadcast response"
 msgstr ""
 
-#: rfc2131.c:1790
+#: rfc2131.c:1840
 #, c-format
 msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
 msgstr ""
 
-#: rfc2131.c:2031
+#: rfc2131.c:2131
 msgid "PXE menu too large"
 msgstr ""
 
-#: rfc2131.c:2170 rfc3315.c:1502
+#: rfc2131.c:2270 rfc3315.c:1515
 #, c-format
 msgid "%u requested options: %s"
 msgstr ""
 
-#: rfc2131.c:2487
+#: rfc2131.c:2587
 #, c-format
 msgid "cannot send RFC3925 option: too many options for enterprise number %d"
 msgstr ""
 
+#: rfc2131.c:2650
+#, c-format
+msgid "%u reply delay: %d"
+msgstr ""
+
 #: netlink.c:77
 #, c-format
 msgid "cannot create netlink socket: %s"
 msgstr ""
 
-#: netlink.c:348
+#: netlink.c:355
 #, c-format
 msgid "netlink returns error: %s"
 msgstr ""
@@ -1776,62 +1870,62 @@ msgstr ""
 msgid "Disabling --%s option from D-Bus"
 msgstr ""
 
-#: dbus.c:691
+#: dbus.c:690
 msgid "setting upstream servers from DBus"
 msgstr ""
 
-#: dbus.c:738
+#: dbus.c:737
 msgid "could not register a DBus message handler"
 msgstr ""
 
-#: bpf.c:263
+#: bpf.c:265
 #, c-format
 msgid "cannot create DHCP BPF socket: %s"
 msgstr ""
 
-#: bpf.c:291
+#: bpf.c:293
 #, c-format
 msgid "DHCP request for unsupported hardware type (%d) received on %s"
 msgstr ""
 
-#: bpf.c:376
+#: bpf.c:378
 #, c-format
 msgid "cannot create PF_ROUTE socket: %s"
 msgstr ""
 
-#: bpf.c:397
+#: bpf.c:399
 msgid "Unknown protocol version from route socket"
 msgstr ""
 
-#: helper.c:153
+#: helper.c:154
 msgid "lease() function missing in Lua script"
 msgstr ""
 
-#: tftp.c:309
+#: tftp.c:319
 msgid "unable to get free port for TFTP"
 msgstr ""
 
-#: tftp.c:325
+#: tftp.c:335
 #, c-format
 msgid "unsupported request from %s"
 msgstr ""
 
-#: tftp.c:439
+#: tftp.c:483
 #, c-format
 msgid "file %s not found"
 msgstr ""
 
-#: tftp.c:548
+#: tftp.c:592
 #, c-format
 msgid "error %d %s received from %s"
 msgstr ""
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "failed sending %s to %s"
 msgstr ""
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "sent %s to %s"
 msgstr ""
@@ -1846,7 +1940,7 @@ msgstr ""
 msgid "log failed: %s"
 msgstr ""
 
-#: log.c:469
+#: log.c:471
 msgid "FAILED to start up"
 msgstr ""
 
@@ -1855,17 +1949,17 @@ msgstr ""
 msgid "Conntrack connection mark retrieval failed: %s"
 msgstr ""
 
-#: dhcp6.c:59
+#: dhcp6.c:52
 #, c-format
 msgid "cannot create DHCPv6 socket: %s"
 msgstr ""
 
-#: dhcp6.c:80
+#: dhcp6.c:73
 #, c-format
 msgid "failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"
 msgstr ""
 
-#: dhcp6.c:92
+#: dhcp6.c:85
 #, c-format
 msgid "failed to bind DHCPv6 server socket: %s"
 msgstr ""
@@ -1880,67 +1974,67 @@ msgstr ""
 msgid "no address range available for DHCPv6 request via %s"
 msgstr ""
 
-#: rfc3315.c:297
+#: rfc3315.c:303
 #, c-format
 msgid "%u available DHCPv6 subnet: %s/%d"
 msgstr ""
 
-#: rfc3315.c:380
+#: rfc3315.c:386
 #, c-format
 msgid "%u vendor class: %u"
 msgstr ""
 
-#: rfc3315.c:428
+#: rfc3315.c:434
 #, c-format
 msgid "%u client MAC address: %s"
 msgstr ""
 
-#: rfc3315.c:660
+#: rfc3315.c:673
 #, c-format
 msgid "unknown prefix-class %d"
 msgstr ""
 
-#: rfc3315.c:803 rfc3315.c:898
+#: rfc3315.c:816 rfc3315.c:911
 msgid "address unavailable"
 msgstr ""
 
-#: rfc3315.c:815 rfc3315.c:946 rfc3315.c:1279
+#: rfc3315.c:828 rfc3315.c:959 rfc3315.c:1292
 msgid "success"
 msgstr ""
 
-#: rfc3315.c:830 rfc3315.c:839 rfc3315.c:954 rfc3315.c:956
+#: rfc3315.c:843 rfc3315.c:852 rfc3315.c:967 rfc3315.c:969
 msgid "no addresses available"
 msgstr ""
 
-#: rfc3315.c:933
+#: rfc3315.c:946
 msgid "not on link"
 msgstr ""
 
-#: rfc3315.c:1006 rfc3315.c:1191 rfc3315.c:1268
+#: rfc3315.c:1019 rfc3315.c:1204 rfc3315.c:1281
 msgid "no binding found"
 msgstr ""
 
-#: rfc3315.c:1044
+#: rfc3315.c:1057
 msgid "deprecated"
 msgstr ""
 
-#: rfc3315.c:1049
+#: rfc3315.c:1062
 msgid "address invalid"
 msgstr ""
 
-#: rfc3315.c:1096
+#: rfc3315.c:1109
 msgid "confirm failed"
 msgstr ""
 
-#: rfc3315.c:1112
+#: rfc3315.c:1125
 msgid "all addresses still on link"
 msgstr ""
 
-#: rfc3315.c:1200
+#: rfc3315.c:1213
 msgid "release received"
 msgstr ""
 
-#: rfc3315.c:2126
+#: rfc3315.c:2140
 msgid "Cannot multicast to DHCPv6 server without correct interface"
 msgstr ""
 
@@ -1964,76 +2058,76 @@ msgstr ""
 msgid "duplicate IP address %s (%s) in dhcp-config directive"
 msgstr ""
 
-#: dhcp-common.c:494
+#: dhcp-common.c:491
 #, c-format
 msgid "failed to set SO_BINDTODEVICE on DHCP socket: %s"
 msgstr ""
 
-#: dhcp-common.c:615
+#: dhcp-common.c:612
 #, c-format
 msgid "Known DHCP options:\n"
 msgstr ""
 
-#: dhcp-common.c:626
+#: dhcp-common.c:623
 #, c-format
 msgid "Known DHCPv6 options:\n"
 msgstr ""
 
-#: dhcp-common.c:823
+#: dhcp-common.c:820
 msgid ", prefix deprecated"
 msgstr ""
 
-#: dhcp-common.c:826
+#: dhcp-common.c:823
 #, c-format
 msgid ", lease time "
 msgstr ""
 
-#: dhcp-common.c:868
+#: dhcp-common.c:865
 #, c-format
 msgid "%s stateless on %s%.0s%.0s%s"
 msgstr ""
 
-#: dhcp-common.c:870
+#: dhcp-common.c:867
 #, c-format
 msgid "%s, static leases only on %.0s%s%s%.0s"
 msgstr ""
 
-#: dhcp-common.c:872
+#: dhcp-common.c:869
 #, c-format
 msgid "%s, proxy on subnet %.0s%s%.0s%.0s"
 msgstr ""
 
-#: dhcp-common.c:873
+#: dhcp-common.c:870
 #, c-format
 msgid "%s, IP range %s -- %s%s%.0s"
 msgstr ""
 
-#: dhcp-common.c:886
+#: dhcp-common.c:883
 #, c-format
 msgid "DHCPv4-derived IPv6 names on %s%s"
 msgstr ""
 
-#: dhcp-common.c:889
+#: dhcp-common.c:886
 #, c-format
 msgid "router advertisement on %s%s"
 msgstr ""
 
-#: dhcp-common.c:900
+#: dhcp-common.c:897
 #, c-format
 msgid "DHCP relay from %s to %s via %s"
 msgstr ""
 
-#: dhcp-common.c:902
+#: dhcp-common.c:899
 #, c-format
 msgid "DHCP relay from %s to %s"
 msgstr ""
 
-#: radv.c:109
+#: radv.c:110
 #, c-format
 msgid "cannot create ICMPv6 socket: %s"
 msgstr ""
 
-#: auth.c:448
+#: auth.c:449
 #, c-format
 msgid "ignoring zone transfer request from %s"
 msgstr ""
@@ -2048,9 +2142,13 @@ msgstr ""
 msgid "failed to create IPset control socket: %s"
 msgstr ""
 
-#: dnssec.c:449 dnssec.c:493
+#: ipset.c:233
 #, c-format
-msgid "failed to update mtime on %s: %s"
+msgid "failed to update ipset %s: %s"
+msgstr ""
+
+#: dnssec.c:208
+msgid "system time considered valid, now checking DNSSEC signature timestamps."
 msgstr ""
 
 #: blockdata.c:58
@@ -2058,80 +2156,76 @@ msgstr ""
 msgid "DNSSEC memory in use %u, max %u, allocated %u"
 msgstr ""
 
-#: tables.c:80
-msgid "error: fill_addr missused"
-msgstr ""
-
-#: tables.c:109
+#: tables.c:61
 #, c-format
 msgid "failed to access pf devices: %s"
 msgstr ""
 
-#: tables.c:123
+#: tables.c:74
 #, c-format
 msgid "warning: no opened pf devices %s"
 msgstr ""
 
-#: tables.c:131
+#: tables.c:82
 #, c-format
 msgid "error: cannot use table name %s"
 msgstr ""
 
-#: tables.c:139
+#: tables.c:90
 #, c-format
 msgid "error: cannot strlcpy table name %s"
 msgstr ""
 
-#: tables.c:145
+#: tables.c:101
 #, c-format
-msgid "warning: pfr_add_tables: %s(%d)"
+msgid "IPset: error:%s"
 msgstr ""
 
-#: tables.c:151
+#: tables.c:108
 msgid "info: table created"
 msgstr ""
 
-#: tables.c:162
+#: tables.c:134
 #, c-format
 msgid "warning: DIOCR%sADDRS: %s"
 msgstr ""
 
-#: tables.c:166
+#: tables.c:138
 #, c-format
 msgid "%d addresses %s"
 msgstr ""
 
-#: inotify.c:59
+#: inotify.c:62
 #, c-format
 msgid "cannot access path %s: %s"
 msgstr ""
 
-#: inotify.c:92
+#: inotify.c:95
 #, c-format
 msgid "failed to create inotify: %s"
 msgstr ""
 
-#: inotify.c:105
+#: inotify.c:111
 #, c-format
 msgid "too many symlinks following %s"
 msgstr ""
 
-#: inotify.c:121
+#: inotify.c:127
 #, c-format
 msgid "directory %s for resolv-file is missing, cannot poll"
 msgstr ""
 
-#: inotify.c:125 inotify.c:162
+#: inotify.c:131 inotify.c:168
 #, c-format
 msgid "failed to create inotify for %s: %s"
 msgstr ""
 
-#: inotify.c:147
+#: inotify.c:153
 #, c-format
 msgid "bad dynamic directory %s: %s"
 msgstr ""
 
-#: inotify.c:247
+#: inotify.c:257
 #, c-format
 msgid "inotify, new or changed file %s"
 msgstr ""
index 8d9ff71..f84d0bc 100644 (file)
--- a/po/ro.po
+++ b/po/ro.po
@@ -7,7 +7,7 @@ msgstr ""
 "Project-Id-Version: dnsmasq 2.24\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2009-06-18 12:24+0100\n"
-"PO-Revision-Date: 2005-11-22 16:46+0000\n"
+"PO-Revision-Date: 2017-07-17 18:30+0100\n"
 "Last-Translator: Simon Kelley <simon@thekelleys.org.uk>\n"
 "Language-Team: Romanian <translation-team-ro@lists.sourceforge.net>\n"
 "Language: ro\n"
@@ -15,740 +15,766 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: cache.c:523
+#: cache.c:518
 msgid "Internal error in cache."
 msgstr ""
 
 # for compatibility purposes the letters â, ă, ş, ţ and î can be written as their look-alike correspondent.
-#: cache.c:941
+#: cache.c:928
 #, fuzzy, c-format
 msgid "failed to load names from %s: %s"
 msgstr "încărcarea numelor din %s: %s a eşuat"
 
-#: cache.c:967 dhcp.c:828
+#: cache.c:954 dhcp.c:867
 #, c-format
 msgid "bad address at %s line %d"
 msgstr "adresă greşită în %s, linia %d"
 
-#: cache.c:1018 dhcp.c:844
+#: cache.c:1007 dhcp.c:883
 #, c-format
 msgid "bad name at %s line %d"
 msgstr "nume greşit în %s linia %d"
 
-#: cache.c:1027 dhcp.c:919
+#: cache.c:1016 dhcp.c:958
 #, c-format
 msgid "read %s - %d addresses"
 msgstr "citesc %s - %d adrese"
 
-#: cache.c:1135
+#: cache.c:1129
 msgid "cleared cache"
 msgstr "memoria temporară a fost ştearsă"
 
-#: cache.c:1164
+#: cache.c:1158
 #, c-format
 msgid "No IPv4 address found for %s"
 msgstr ""
 
-#: cache.c:1242
+#: cache.c:1237
 #, c-format
 msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
 msgstr ""
 
-#: cache.c:1266
+#: cache.c:1261
 #, c-format
 msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
 msgstr "nu pot da numele %s împrumutului de adresă DHCP a lui %s deoarece numeleexistă în %s cu adresa %s"
 
-#: cache.c:1421
+#: cache.c:1418
 #, c-format
 msgid "time %lu"
 msgstr ""
 
-#: cache.c:1422
+#: cache.c:1419
 #, fuzzy, c-format
 msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
 msgstr "cantitate de memorie temporară %d, %d/%d stocări temporare aureutilizat locaţii neexpirate."
 
-#: cache.c:1424
+#: cache.c:1421
 #, c-format
 msgid "queries forwarded %u, queries answered locally %u"
 msgstr ""
 
-#: cache.c:1427
+#: cache.c:1424
 #, c-format
 msgid "queries for authoritative zones %u"
 msgstr ""
 
-#: cache.c:1453
+#: cache.c:1450
 #, c-format
 msgid "server %s#%d: queries sent %u, retried or failed %u"
 msgstr ""
 
-#: util.c:45
+#: util.c:47
 #, fuzzy, c-format
 msgid "failed to seed the random number generator: %s"
 msgstr "ascultarea pe socket a eşuat: %s"
 
-#: util.c:205
+#: util.c:224
 #, fuzzy
 msgid "failed to allocate memory"
 msgstr "nu pot încărca %d bytes"
 
-#: util.c:250 option.c:601
+#: util.c:281 option.c:619
 msgid "could not get memory"
 msgstr "nu am putut aloca memorie"
 
-#: util.c:260
+#: util.c:291
 #, fuzzy, c-format
 msgid "cannot create pipe: %s"
 msgstr "nu pot citi %s: %s"
 
-#: util.c:268
+#: util.c:299
 #, fuzzy, c-format
 msgid "failed to allocate %d bytes"
 msgstr "nu pot încărca %d bytes"
 
-#: util.c:437
+#: util.c:468
 #, c-format
 msgid "infinite"
 msgstr "infinit"
 
-#: option.c:332
+#: option.c:344
 msgid "Specify local address(es) to listen on."
 msgstr "Specificaţi adresele locale deservite."
 
-#: option.c:333
+#: option.c:345
 msgid "Return ipaddr for all hosts in specified domains."
 msgstr "Afişează adresele IP ale maşinilor în domeniul dat."
 
-#: option.c:334
+#: option.c:346
 msgid "Fake reverse lookups for RFC1918 private address ranges."
 msgstr "Simulează căutări după adresă pentru domenii de adresă private (RFC1918)."
 
-#: option.c:335
+#: option.c:347
 msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
 msgstr "Interpretează adresa IP ca NXDOMAIN (împotriva manipulărilor Verisign)"
 
-#: option.c:336
+#: option.c:348
 #, c-format
 msgid "Specify the size of the cache in entries (defaults to %s)."
 msgstr "Specifică mărimea înregistrărilor temporare (implicit e %s)."
 
-#: option.c:337
+#: option.c:349
 #, c-format
 msgid "Specify configuration file (defaults to %s)."
 msgstr "Specifică fişier de configurare (implicit e %s)."
 
-#: option.c:338
+#: option.c:350
 msgid "Do NOT fork into the background: run in debug mode."
 msgstr "NU porneşte în fundal: rulează în modul depanare."
 
-#: option.c:339
+#: option.c:351
 msgid "Do NOT forward queries with no domain part."
 msgstr "NU înainta cererile ce nu conţin domeniu DNS."
 
-#: option.c:340
+#: option.c:352
 msgid "Return self-pointing MX records for local hosts."
 msgstr "Răspunde cu înregistrări MX spre el însuşi pentru maşini locale."
 
-#: option.c:341
+#: option.c:353
 msgid "Expand simple names in /etc/hosts with domain-suffix."
 msgstr "Adaugă numelor simple din /etc/hosts numele domeniului ca sufix."
 
-#: option.c:342
+#: option.c:354
 msgid "Don't forward spurious DNS requests from Windows hosts."
 msgstr "Nu inainta cereri DNS defecte provenite de la maşini Windows."
 
-#: option.c:343
+#: option.c:355
 msgid "Enable DHCP in the range given with lease duration."
 msgstr "Activează DHCP în domeniul dat cu durată limitată de împrumut."
 
-#: option.c:344
+#: option.c:356
 #, c-format
 msgid "Change to this group after startup (defaults to %s)."
 msgstr "Rulează sub acest grup după pornire (implicit e %s)."
 
-#: option.c:345
+#: option.c:357
 msgid "Set address or hostname for a specified machine."
 msgstr "Schimbă adresa sau numele maşinii specificate."
 
-#: option.c:346
+#: option.c:358
 #, fuzzy
 msgid "Read DHCP host specs from file."
 msgstr "nume MX invalid"
 
-#: option.c:347
+#: option.c:359
 msgid "Read DHCP option specs from file."
 msgstr ""
 
-#: option.c:348
+#: option.c:360
 #, fuzzy
 msgid "Read DHCP host specs from a directory."
 msgstr "nume MX invalid"
 
-#: option.c:349
+#: option.c:361
 #, fuzzy
 msgid "Read DHCP options from a directory."
 msgstr "nume MX invalid"
 
-#: option.c:350
+#: option.c:362
 msgid "Evaluate conditional tag expression."
 msgstr ""
 
-#: option.c:351
+#: option.c:363
 #, c-format
 msgid "Do NOT load %s file."
 msgstr "Nu încarcă fişierul %s."
 
-#: option.c:352
+#: option.c:364
 #, c-format
 msgid "Specify a hosts file to be read in addition to %s."
 msgstr "Specifică spre citire un fişier hosts adiţional la %s."
 
-#: option.c:353
+#: option.c:365
 #, fuzzy
 msgid "Read hosts files from a directory."
 msgstr "nume MX invalid"
 
-#: option.c:354
+#: option.c:366
 msgid "Specify interface(s) to listen on."
 msgstr "Specifică interfeţele deservite."
 
-#: option.c:355
+#: option.c:367
 msgid "Specify interface(s) NOT to listen on."
 msgstr "Specifică interfeţele NE-deservite."
 
-#: option.c:356
+#: option.c:368
 #, fuzzy
 msgid "Map DHCP user class to tag."
 msgstr "Leagă clasa de utilizator DHCP cu grup de opţiuni."
 
-#: option.c:357
+#: option.c:369
 msgid "Map RFC3046 circuit-id to tag."
 msgstr ""
 
-#: option.c:358
+#: option.c:370
 msgid "Map RFC3046 remote-id to tag."
 msgstr ""
 
-#: option.c:359
+#: option.c:371
 msgid "Map RFC3993 subscriber-id to tag."
 msgstr ""
 
-#: option.c:360
+#: option.c:372
 #, fuzzy
 msgid "Don't do DHCP for hosts with tag set."
 msgstr "Nu furniza DHCP maşinilor din grupul de opţiuni."
 
-#: option.c:361
+#: option.c:373
 #, fuzzy
 msgid "Force broadcast replies for hosts with tag set."
 msgstr "Nu furniza DHCP maşinilor din grupul de opţiuni."
 
-#: option.c:362
+#: option.c:374
 msgid "Do NOT fork into the background, do NOT run in debug mode."
 msgstr "NU porneşte în fundal, NU rulează în modul depanare."
 
-#: option.c:363
+#: option.c:375
 msgid "Assume we are the only DHCP server on the local network."
 msgstr "Presupune că suntem singurul server DHCP din reţeaua locală."
 
-#: option.c:364
+#: option.c:376
 #, c-format
 msgid "Specify where to store DHCP leases (defaults to %s)."
 msgstr "Specifică fişierul de stocare a împrumuturilor DHCP (implicit e %s)."
 
-#: option.c:365
+#: option.c:377
 msgid "Return MX records for local hosts."
 msgstr "Răspunde cu întregistrări MX pentru maşini locale."
 
-#: option.c:366
+#: option.c:378
 msgid "Specify an MX record."
 msgstr "Specifică o înregistrare MX."
 
-#: option.c:367
+#: option.c:379
 msgid "Specify BOOTP options to DHCP server."
 msgstr "Specifică opţiuni BOOTP serverului DHCP."
 
-#: option.c:368
+#: option.c:380
 #, c-format
 msgid "Do NOT poll %s file, reload only on SIGHUP."
 msgstr "Nu încărca fişierul %s, citeşte-l doar la SIGHUP."
 
-#: option.c:369
+#: option.c:381
 msgid "Do NOT cache failed search results."
 msgstr "NU memora rezultatele de căutare DNS eşuatată."
 
-#: option.c:370
+#: option.c:382
 #, c-format
 msgid "Use nameservers strictly in the order given in %s."
 msgstr "Foloseşte servere DNS strict în ordinea dată în %s."
 
-#: option.c:371
+#: option.c:383
 #, fuzzy
 msgid "Specify options to be sent to DHCP clients."
 msgstr "Configurează opţiuni în plusce trebuie trimise clienţilor DHCP."
 
-#: option.c:372
+#: option.c:384
 msgid "DHCP option sent even if the client does not request it."
 msgstr ""
 
-#: option.c:373
+#: option.c:385
 msgid "Specify port to listen for DNS requests on (defaults to 53)."
 msgstr "Specifică numărul portului pentru cereri DNS (implicit e 53)."
 
-#: option.c:374
+#: option.c:386
 #, c-format
 msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
 msgstr "Marimea maximă a pachetului UDP pentru EDNS.0 (implicit e %s)."
 
-#: option.c:375
+#: option.c:387
 #, fuzzy
 msgid "Log DNS queries."
 msgstr "Înregistrează tranzacţiile."
 
-#: option.c:376
+#: option.c:388
 #, fuzzy
 msgid "Force the originating port for upstream DNS queries."
 msgstr "Forţează acest port pentru datele ce pleacă."
 
-#: option.c:377
+#: option.c:389
 msgid "Do NOT read resolv.conf."
 msgstr "NU citi fişierul resolv.conf"
 
-#: option.c:378
+#: option.c:390
 #, c-format
 msgid "Specify path to resolv.conf (defaults to %s)."
 msgstr "Specifică calea către resolv.conf (implicit e %s)."
 
-#: option.c:379
+#: option.c:391
 #, fuzzy
 msgid "Specify path to file with server= options"
 msgstr "Specifică o cale pentru fişierul PID. (implicit %s)."
 
-#: option.c:380
+#: option.c:392
 msgid "Specify address(es) of upstream servers with optional domains."
 msgstr "Specifică adresele server(elor) superioare cu domenii opţionale."
 
-#: option.c:381
+#: option.c:393
 #, fuzzy
 msgid "Specify address of upstream servers for reverse address queries"
 msgstr "Specifică adresele server(elor) superioare cu domenii opţionale."
 
-#: option.c:382
+#: option.c:394
 msgid "Never forward queries to specified domains."
 msgstr "Nu înaintează cererile spre domeniile specificate."
 
-#: option.c:383
+#: option.c:395
 msgid "Specify the domain to be assigned in DHCP leases."
 msgstr "Specifică domeniul de transmis prin DHCP."
 
-#: option.c:384
+#: option.c:396
 msgid "Specify default target in an MX record."
 msgstr "Specifică o ţintă într-o înregistrare MX."
 
-#: option.c:385
+#: option.c:397
 msgid "Specify time-to-live in seconds for replies from /etc/hosts."
 msgstr "Specifică TTL în secunde pentru răspunsurile din /etc/hosts."
 
-#: option.c:386
+#: option.c:398
 #, fuzzy
 msgid "Specify time-to-live in seconds for negative caching."
 msgstr "Specifică TTL în secunde pentru răspunsurile din /etc/hosts."
 
-#: option.c:387
+#: option.c:399
 #, fuzzy
 msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
 msgstr "Specifică TTL în secunde pentru răspunsurile din /etc/hosts."
 
-#: option.c:388
+#: option.c:400
 #, fuzzy
 msgid "Specify time-to-live ceiling for cache."
 msgstr "Specifică TTL în secunde pentru răspunsurile din /etc/hosts."
 
-#: option.c:389
+#: option.c:401
 #, fuzzy
 msgid "Specify time-to-live floor for cache."
 msgstr "Specifică TTL în secunde pentru răspunsurile din /etc/hosts."
 
-#: option.c:390
+#: option.c:402
 #, c-format
 msgid "Change to this user after startup. (defaults to %s)."
 msgstr "Rulează sub acest utilizator după pornire. (implicit e %s)."
 
-#: option.c:391
+#: option.c:403
 #, fuzzy
 msgid "Map DHCP vendor class to tag."
 msgstr "Trimite opţiuni DHCP în funcţie de marca plăcii de reţea."
 
-#: option.c:392
+#: option.c:404
 msgid "Display dnsmasq version and copyright information."
 msgstr "Afişează versiunea dnsmasq şi drepturile de autor."
 
-#: option.c:393
+#: option.c:405
 msgid "Translate IPv4 addresses from upstream servers."
 msgstr "Traduce adresele IPv4 de la serverele DNS superioare."
 
-#: option.c:394
+#: option.c:406
 msgid "Specify a SRV record."
 msgstr "Specifică o înregistrare SRV."
 
-#: option.c:395
-msgid "Display this message. Use --help dhcp for known DHCP options."
+#: option.c:407
+msgid "Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."
 msgstr ""
 
-#: option.c:396
+#: option.c:408
 #, fuzzy, c-format
 msgid "Specify path of PID file (defaults to %s)."
 msgstr "Specifică o cale pentru fişierul PID. (implicit %s)."
 
-#: option.c:397
+#: option.c:409
 #, c-format
 msgid "Specify maximum number of DHCP leases (defaults to %s)."
 msgstr "Specifică numărul maxim de împrumuturi DHCP (implicit %s)."
 
-#: option.c:398
+#: option.c:410
 msgid "Answer DNS queries based on the interface a query was sent to."
 msgstr "Răspunde cererilor DNS în funcţie de interfaţa pe care a venit cererea."
 
-#: option.c:399
+#: option.c:411
 msgid "Specify TXT DNS record."
 msgstr "Specifică o înregistrare TXT."
 
-#: option.c:400
+#: option.c:412
 #, fuzzy
 msgid "Specify PTR DNS record."
 msgstr "Specifică o înregistrare TXT."
 
-#: option.c:401
+#: option.c:413
 msgid "Give DNS name to IPv4 address of interface."
 msgstr ""
 
-#: option.c:402
+#: option.c:414
 msgid "Bind only to interfaces in use."
 msgstr "Ascultă doar pe interfeţele active."
 
-#: option.c:403
+#: option.c:415
 #, c-format
 msgid "Read DHCP static host information from %s."
 msgstr "Citeşte informaţii DHCP statice despre maşină din %s."
 
-#: option.c:404
+#: option.c:416
 msgid "Enable the DBus interface for setting upstream servers, etc."
 msgstr "Activeaza interfaţa DBus pentru configurarea serverelor superioare."
 
-#: option.c:405
+#: option.c:417
 msgid "Do not provide DHCP on this interface, only provide DNS."
 msgstr "Nu activează DHCP ci doar DNS pe această interfaţă."
 
-#: option.c:406
+#: option.c:418
 msgid "Enable dynamic address allocation for bootp."
 msgstr "Activează alocarea dinamică a adreselor pentru BOOTP."
 
-#: option.c:407
+#: option.c:419
 #, fuzzy
 msgid "Map MAC address (with wildcards) to option set."
 msgstr "Trimite opţiuni DHCP în funcţie de marca plăcii de reţea."
 
-#: option.c:408
+#: option.c:420
 msgid "Treat DHCP requests on aliases as arriving from interface."
 msgstr ""
 
-#: option.c:409
+#: option.c:421
 msgid "Disable ICMP echo address checking in the DHCP server."
 msgstr ""
 
-#: option.c:410
+#: option.c:422
 msgid "Shell script to run on DHCP lease creation and destruction."
 msgstr ""
 
-#: option.c:411
+#: option.c:423
 msgid "Lua script to run on DHCP lease creation and destruction."
 msgstr ""
 
-#: option.c:412
+#: option.c:424
 msgid "Run lease-change scripts as this user."
 msgstr ""
 
-#: option.c:413
+#: option.c:425
+msgid "Call dhcp-script with changes to local ARP table."
+msgstr ""
+
+#: option.c:426
 msgid "Read configuration from all the files in this directory."
 msgstr ""
 
-#: option.c:414
+#: option.c:427
 #, fuzzy
 msgid "Log to this syslog facility or file. (defaults to DAEMON)"
 msgstr "Rulează sub acest utilizator după pornire. (implicit e %s)."
 
-#: option.c:415
+#: option.c:428
 msgid "Do not use leasefile."
 msgstr ""
 
-#: option.c:416
+#: option.c:429
 #, fuzzy, c-format
 msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
 msgstr "Specifică numărul maxim de împrumuturi DHCP (implicit %s)."
 
-#: option.c:417
+#: option.c:430
 #, c-format
 msgid "Clear DNS cache when reloading %s."
 msgstr ""
 
-#: option.c:418
+#: option.c:431
 msgid "Ignore hostnames provided by DHCP clients."
 msgstr ""
 
-#: option.c:419
+#: option.c:432
 msgid "Do NOT reuse filename and server fields for extra DHCP options."
 msgstr ""
 
-#: option.c:420
+#: option.c:433
 msgid "Enable integrated read-only TFTP server."
 msgstr ""
 
-#: option.c:421
+#: option.c:434
 msgid "Export files by TFTP only from the specified subtree."
 msgstr ""
 
-#: option.c:422
-msgid "Add client IP address to tftp-root."
+#: option.c:435
+msgid "Add client IP or hardware address to tftp-root."
 msgstr ""
 
-#: option.c:423
+#: option.c:436
 msgid "Allow access only to files owned by the user running dnsmasq."
 msgstr ""
 
-#: option.c:424
+#: option.c:437
 msgid "Do not terminate the service if TFTP directories are inaccessible."
 msgstr ""
 
-#: option.c:425
+#: option.c:438
 #, fuzzy, c-format
-msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgid "Maximum number of concurrent TFTP transfers (defaults to %s)."
 msgstr "Specifică numărul maxim de împrumuturi DHCP (implicit %s)."
 
-#: option.c:426
+#: option.c:439
+#, fuzzy
+msgid "Maximum MTU to use for TFTP transfers."
+msgstr "Specifică numărul maxim de împrumuturi DHCP (implicit %s)."
+
+#: option.c:440
 msgid "Disable the TFTP blocksize extension."
 msgstr ""
 
-#: option.c:427
+#: option.c:441
 msgid "Convert TFTP filenames to lowercase"
 msgstr ""
 
-#: option.c:428
+#: option.c:442
 msgid "Ephemeral port range for use by TFTP transfers."
 msgstr ""
 
-#: option.c:429
+#: option.c:443
 msgid "Extra logging for DHCP."
 msgstr ""
 
-#: option.c:430
+#: option.c:444
 msgid "Enable async. logging; optionally set queue length."
 msgstr ""
 
-#: option.c:431
+#: option.c:445
 msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
 msgstr ""
 
-#: option.c:432
+#: option.c:446
 msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
 msgstr ""
 
-#: option.c:433
+#: option.c:447
 msgid "Inhibit DNS-rebind protection on this domain."
 msgstr ""
 
-#: option.c:434
+#: option.c:448
 msgid "Always perform DNS queries to all servers."
 msgstr ""
 
-#: option.c:435
+#: option.c:449
 msgid "Set tag if client includes matching option in request."
 msgstr ""
 
-#: option.c:436
+#: option.c:450
 msgid "Use alternative ports for DHCP."
 msgstr ""
 
-#: option.c:437
+#: option.c:451
 #, fuzzy
 msgid "Specify NAPTR DNS record."
 msgstr "Specifică o înregistrare TXT."
 
-#: option.c:438
+#: option.c:452
 msgid "Specify lowest port available for DNS query transmission."
 msgstr ""
 
-#: option.c:439
+#: option.c:453
+msgid "Specify highest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:454
 msgid "Use only fully qualified domain names for DHCP clients."
 msgstr ""
 
-#: option.c:440
+#: option.c:455
 msgid "Generate hostnames based on MAC address for nameless clients."
 msgstr ""
 
-#: option.c:441
+#: option.c:456
 msgid "Use these DHCP relays as full proxies."
 msgstr ""
 
-#: option.c:442
+#: option.c:457
 msgid "Relay DHCP requests to a remote server"
 msgstr ""
 
-#: option.c:443
+#: option.c:458
 msgid "Specify alias name for LOCAL DNS name."
 msgstr ""
 
-#: option.c:444
+#: option.c:459
 #, fuzzy
 msgid "Prompt to send to PXE clients."
 msgstr "Configurează opţiuni în plusce trebuie trimise clienţilor DHCP."
 
-#: option.c:445
+#: option.c:460
 msgid "Boot service for PXE menu."
 msgstr ""
 
-#: option.c:446
+#: option.c:461
 msgid "Check configuration syntax."
 msgstr ""
 
-#: option.c:447
+#: option.c:462
 msgid "Add requestor's MAC address to forwarded DNS queries."
 msgstr ""
 
-#: option.c:448
-msgid "Add requestor's IP subnet to forwarded DNS queries."
+#: option.c:463
+msgid "Add specified IP subnet to forwarded DNS queries."
 msgstr ""
 
-#: option.c:449
+#: option.c:464
+#, fuzzy
+msgid "Add client identification to forwarded DNS queries."
+msgstr "Forţează acest port pentru datele ce pleacă."
+
+#: option.c:465
 #, fuzzy
 msgid "Proxy DNSSEC validation results from upstream nameservers."
 msgstr "Traduce adresele IPv4 de la serverele DNS superioare."
 
-#: option.c:450
+#: option.c:466
 msgid "Attempt to allocate sequential IP addresses to DHCP clients."
 msgstr ""
 
-#: option.c:451
+#: option.c:467
 msgid "Copy connection-track mark from queries to upstream connections."
 msgstr ""
 
-#: option.c:452
+#: option.c:468
 msgid "Allow DHCP clients to do their own DDNS updates."
 msgstr ""
 
-#: option.c:453
+#: option.c:469
 msgid "Send router-advertisements for interfaces doing DHCPv6"
 msgstr ""
 
-#: option.c:454
+#: option.c:470
 msgid "Specify DUID_EN-type DHCPv6 server DUID"
 msgstr ""
 
-#: option.c:455
+#: option.c:471
 #, fuzzy
 msgid "Specify host (A/AAAA and PTR) records"
 msgstr "Specifică o înregistrare MX."
 
-#: option.c:456
+#: option.c:472
 #, fuzzy
 msgid "Specify arbitrary DNS resource record"
 msgstr "Specifică o înregistrare TXT."
 
-#: option.c:457
+#: option.c:473
 #, fuzzy
 msgid "Bind to interfaces in use - check for new interfaces"
 msgstr "interfaţă necunoscută %s"
 
-#: option.c:458
+#: option.c:474
 msgid "Export local names to global DNS"
 msgstr ""
 
-#: option.c:459
+#: option.c:475
 msgid "Domain to export to global DNS"
 msgstr ""
 
-#: option.c:460
+#: option.c:476
 msgid "Set TTL for authoritative replies"
 msgstr ""
 
-#: option.c:461
-msgid "Set authoritive zone information"
+#: option.c:477
+msgid "Set authoritative zone information"
 msgstr ""
 
-#: option.c:462
+#: option.c:478
 msgid "Secondary authoritative nameservers for forward domains"
 msgstr ""
 
-#: option.c:463
+#: option.c:479
 msgid "Peers which are allowed to do zone transfer"
 msgstr ""
 
-#: option.c:464
+#: option.c:480
 msgid "Specify ipsets to which matching domains should be added"
 msgstr ""
 
-#: option.c:465
+#: option.c:481
 msgid "Specify a domain and address range for synthesised names"
 msgstr ""
 
-#: option.c:466
+#: option.c:482
 msgid "Activate DNSSEC validation"
 msgstr ""
 
-#: option.c:467
+#: option.c:483
 msgid "Specify trust anchor key digest."
 msgstr ""
 
-#: option.c:468
+#: option.c:484
 msgid "Disable upstream checking for DNSSEC debugging."
 msgstr ""
 
-#: option.c:469
+#: option.c:485
 msgid "Ensure answers without DNSSEC are in unsigned zones."
 msgstr ""
 
-#: option.c:470
+#: option.c:486
 msgid "Don't check DNSSEC signature timestamps until first cache-reload"
 msgstr ""
 
-#: option.c:471
+#: option.c:487
 msgid "Timestamp file to verify system clock for DNSSEC"
 msgstr ""
 
-#: option.c:473
+#: option.c:489
 msgid "Specify DHCPv6 prefix class"
 msgstr ""
 
-#: option.c:475
-msgid "Set priority, resend-interval and router-lifetime"
+#: option.c:491
+msgid "Set MTU, priority, resend-interval and router-lifetime"
 msgstr ""
 
-#: option.c:476
+#: option.c:492
 msgid "Do not log routine DHCP."
 msgstr ""
 
-#: option.c:477
+#: option.c:493
 msgid "Do not log routine DHCPv6."
 msgstr ""
 
-#: option.c:478
+#: option.c:494
 msgid "Do not log RA."
 msgstr ""
 
-#: option.c:479
-msgid "Accept queries only from directly-connected networks"
+#: option.c:495
+msgid "Accept queries only from directly-connected networks."
 msgstr ""
 
-#: option.c:480
-msgid "Detect and remove DNS forwarding loops"
+#: option.c:496
+msgid "Detect and remove DNS forwarding loops."
 msgstr ""
 
-#: option.c:481
+#: option.c:497
 msgid "Ignore DNS responses containing ipaddr."
 msgstr ""
 
-#: option.c:683
+#: option.c:498
+msgid "Set TTL in DNS responses with DHCP-derived addresses."
+msgstr ""
+
+#: option.c:499
+msgid "Delay DHCP replies for at least number of seconds."
+msgstr ""
+
+#: option.c:703
 #, c-format
 msgid ""
 "Usage: dnsmasq [options]\n"
@@ -757,332 +783,341 @@ msgstr ""
 "Utilizare: dnsmasq [opţiuni]\n"
 "\n"
 
-#: option.c:685
+#: option.c:705
 #, c-format
 msgid "Use short options only on the command line.\n"
 msgstr "Folosiţi opţiunile prescurtate doar în linie de comandă.\n"
 
-#: option.c:687
+#: option.c:707
 #, fuzzy, c-format
 msgid "Valid options are:\n"
 msgstr "Opţiunile valide sunt:\n"
 
-#: option.c:744 option.c:748
+#: option.c:754 option.c:868
+#, fuzzy
+msgid "bad address"
+msgstr "citesc %s - %d adrese"
+
+#: option.c:779 option.c:783
 msgid "bad port"
 msgstr "port invalid"
 
-#: option.c:775 option.c:807
+#: option.c:797 option.c:826 option.c:861
 msgid "interface binding not supported"
 msgstr ""
 
-#: option.c:784 option.c:3575
+#: option.c:821 option.c:856
+msgid "interface can only be specified once"
+msgstr ""
+
+#: option.c:835 option.c:3809
 #, fuzzy
 msgid "bad interface name"
 msgstr "nume MX invalid"
 
-#: option.c:814
-#, fuzzy
-msgid "bad address"
-msgstr "citesc %s - %d adrese"
-
-#: option.c:996
+#: option.c:1062
 msgid "unsupported encapsulation for IPv6 option"
 msgstr ""
 
-#: option.c:1010
+#: option.c:1076
 msgid "bad dhcp-option"
 msgstr "dhcp-option invalid"
 
-#: option.c:1078
+#: option.c:1144
 #, fuzzy
 msgid "bad IP address"
 msgstr "citesc %s - %d adrese"
 
-#: option.c:1081 option.c:1219 option.c:2893
+#: option.c:1147 option.c:1286 option.c:3079
 #, fuzzy
 msgid "bad IPv6 address"
 msgstr "citesc %s - %d adrese"
 
-#: option.c:1246 option.c:1340
+#: option.c:1240
+#, fuzzy
+msgid "bad IPv4 address"
+msgstr "citesc %s - %d adrese"
+
+#: option.c:1313 option.c:1407
 msgid "bad domain in dhcp-option"
 msgstr "domeniu DNS invalid în declaraţia dhcp-option"
 
-#: option.c:1378
+#: option.c:1445
 msgid "dhcp-option too long"
 msgstr "declararea dhcp-option este prea lungă"
 
-#: option.c:1385
+#: option.c:1452
 msgid "illegal dhcp-match"
 msgstr ""
 
-#: option.c:1447
+#: option.c:1514
 msgid "illegal repeated flag"
 msgstr ""
 
-#: option.c:1455
+#: option.c:1522
 msgid "illegal repeated keyword"
 msgstr ""
 
-#: option.c:1520 option.c:4191
+#: option.c:1593 option.c:4443
 #, fuzzy, c-format
 msgid "cannot access directory %s: %s"
 msgstr "nu pot citi %s: %s"
 
-#: option.c:1566 tftp.c:493
+#: option.c:1639 tftp.c:537
 #, fuzzy, c-format
 msgid "cannot access %s: %s"
 msgstr "nu pot citi %s: %s"
 
-#: option.c:1618
+#: option.c:1727
 msgid "setting log facility is not possible under Android"
 msgstr ""
 
-#: option.c:1627
+#: option.c:1736
 msgid "bad log facility"
 msgstr ""
 
-#: option.c:1680
+#: option.c:1789
 msgid "bad MX preference"
 msgstr "preferinţă MX invalidă"
 
-#: option.c:1685
+#: option.c:1794
 msgid "bad MX name"
 msgstr "nume MX invalid"
 
-#: option.c:1699
+#: option.c:1808
 msgid "bad MX target"
 msgstr "ţintă MX invalidă"
 
-#: option.c:1711
+#: option.c:1820
 msgid "cannot run scripts under uClinux"
 msgstr ""
 
-#: option.c:1713
+#: option.c:1822
 msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
 msgstr ""
 
-#: option.c:1717
+#: option.c:1826
 msgid "recompile with HAVE_LUASCRIPT defined to enable Lua scripts"
 msgstr ""
 
-#: option.c:1973 option.c:2018 option.c:2074
+#: option.c:2095 option.c:2106 option.c:2143 option.c:2199 option.c:2482
 #, fuzzy
 msgid "bad prefix"
 msgstr "port invalid"
 
-#: option.c:2355
+#: option.c:2504
 msgid "recompile with HAVE_IPSET defined to enable ipset directives"
 msgstr ""
 
-#: option.c:2548
+#: option.c:2713
 #, fuzzy
 msgid "bad port range"
 msgstr "port invalid"
 
-#: option.c:2564
+#: option.c:2739
 msgid "bad bridge-interface"
 msgstr ""
 
-#: option.c:2624
+#: option.c:2807
 msgid "only one tag allowed"
 msgstr ""
 
-#: option.c:2644 option.c:2656 option.c:2764 option.c:2805
+#: option.c:2827 option.c:2839 option.c:2948 option.c:2953 option.c:2992
 msgid "bad dhcp-range"
 msgstr "dhcp-range invalid"
 
-#: option.c:2671
+#: option.c:2854
 msgid "inconsistent DHCP range"
 msgstr "domeniu DHCP inconsistent"
 
-#: option.c:2732
+#: option.c:2916
 msgid "prefix length must be exactly 64 for RA subnets"
 msgstr ""
 
-#: option.c:2734
+#: option.c:2918
 msgid "prefix length must be exactly 64 for subnet constructors"
 msgstr ""
 
-#: option.c:2738
+#: option.c:2922
 msgid "prefix length must be at least 64"
 msgstr ""
 
-#: option.c:2741
+#: option.c:2925
 #, fuzzy
 msgid "inconsistent DHCPv6 range"
 msgstr "domeniu DHCP inconsistent"
 
-#: option.c:2752
+#: option.c:2936
 msgid "prefix must be zero with \"constructor:\" argument"
 msgstr ""
 
-#: option.c:2863 option.c:2911
+#: option.c:3049 option.c:3097
 #, fuzzy
 msgid "bad hex constant"
 msgstr "dhcp-host invalid"
 
-#: option.c:2885
+#: option.c:3071
 msgid "cannot match tags in --dhcp-host"
 msgstr ""
 
-#: option.c:2933
+#: option.c:3119
 #, fuzzy, c-format
 msgid "duplicate dhcp-host IP address %s"
 msgstr "adresă IP duplicat %s în declaraţia dhcp-config."
 
-#: option.c:2991
+#: option.c:3177
 #, fuzzy
 msgid "bad DHCP host name"
 msgstr "nume MX invalid"
 
-#: option.c:3073
+#: option.c:3259
 #, fuzzy
 msgid "bad tag-if"
 msgstr "ţintă MX invalidă"
 
-#: option.c:3397 option.c:3791
+#: option.c:3616 option.c:4039
 msgid "invalid port number"
 msgstr "număr de port invalid"
 
-#: option.c:3459
+#: option.c:3678
 #, fuzzy
 msgid "bad dhcp-proxy address"
 msgstr "citesc %s - %d adrese"
 
-#: option.c:3485
+#: option.c:3704
 #, fuzzy
 msgid "Bad dhcp-relay"
 msgstr "dhcp-range invalid"
 
-#: option.c:3511
+#: option.c:3745
 msgid "bad RA-params"
 msgstr ""
 
-#: option.c:3520
+#: option.c:3754
 msgid "bad DUID"
 msgstr ""
 
-#: option.c:3562
+#: option.c:3796
 #, fuzzy
 msgid "invalid alias range"
 msgstr "pondere invalidă"
 
-#: option.c:3616
+#: option.c:3850 option.c:3862
 msgid "bad CNAME"
 msgstr ""
 
-#: option.c:3621
+#: option.c:3866
 msgid "duplicate CNAME"
 msgstr ""
 
-#: option.c:3641
+#: option.c:3889
 #, fuzzy
 msgid "bad PTR record"
 msgstr "înregistrare SRV invalidă"
 
-#: option.c:3672
+#: option.c:3920
 #, fuzzy
 msgid "bad NAPTR record"
 msgstr "înregistrare SRV invalidă"
 
-#: option.c:3706
+#: option.c:3954
 #, fuzzy
 msgid "bad RR record"
 msgstr "înregistrare SRV invalidă"
 
-#: option.c:3736
+#: option.c:3984
 msgid "bad TXT record"
 msgstr "înregistrare TXT invalidă"
 
-#: option.c:3777
+#: option.c:4025
 msgid "bad SRV record"
 msgstr "înregistrare SRV invalidă"
 
-#: option.c:3784
+#: option.c:4032
 msgid "bad SRV target"
 msgstr "ţintă SRV invalidă"
 
-#: option.c:3798
+#: option.c:4046
 msgid "invalid priority"
 msgstr "prioritate invalidă"
 
-#: option.c:3805
+#: option.c:4049
 msgid "invalid weight"
 msgstr "pondere invalidă"
 
-#: option.c:3829
+#: option.c:4073
 #, fuzzy
 msgid "Bad host-record"
 msgstr "înregistrare SRV invalidă"
 
-#: option.c:3846
+#: option.c:4097
 #, fuzzy
 msgid "Bad name in host-record"
 msgstr "nume invalid în %s"
 
-#: option.c:3911
+#: option.c:4162
 #, fuzzy
 msgid "bad trust anchor"
 msgstr "port invalid"
 
-#: option.c:3925
+#: option.c:4176
 msgid "bad HEX in trust anchor"
 msgstr ""
 
-#: option.c:3935
+#: option.c:4186
 msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"
 msgstr ""
 
-#: option.c:3994
+#: option.c:4246
 msgid "missing \""
 msgstr "lipseşte \""
 
-#: option.c:4051
+#: option.c:4303
 msgid "bad option"
 msgstr "opţiune invalidă"
 
-#: option.c:4053
+#: option.c:4305
 msgid "extraneous parameter"
 msgstr "parametru nerecunoscut"
 
-#: option.c:4055
+#: option.c:4307
 msgid "missing parameter"
 msgstr "parametru lipsa"
 
-#: option.c:4057
+#: option.c:4309
 #, fuzzy
 msgid "illegal option"
 msgstr "opţiune invalidă"
 
-#: option.c:4064
+#: option.c:4316
 msgid "error"
 msgstr "eroare"
 
-#: option.c:4066
+#: option.c:4318
 #, fuzzy, c-format
 msgid " at line %d of %s"
 msgstr "%s la linia %d din %%s"
 
-#: option.c:4081 option.c:4328 option.c:4364
+#: option.c:4333 option.c:4580 option.c:4616
 #, fuzzy, c-format
 msgid "read %s"
 msgstr "citesc %s"
 
-#: option.c:4144 option.c:4267 tftp.c:667
+#: option.c:4396 option.c:4519 tftp.c:715
 #, c-format
 msgid "cannot read %s: %s"
 msgstr "nu pot citi %s: %s"
 
-#: option.c:4430
+#: option.c:4688
 msgid "junk found in command line"
 msgstr ""
 
-#: option.c:4465
+#: option.c:4729
 #, c-format
 msgid "Dnsmasq version %s  %s\n"
 msgstr "dnsmasq versiunea %s  %s\n"
 
-#: option.c:4466
+#: option.c:4730
 #, fuzzy, c-format
 msgid ""
 "Compile time options: %s\n"
@@ -1091,468 +1126,510 @@ msgstr ""
 "Opţiuni cu care a fost compilat %s\n"
 "\n"
 
-#: option.c:4467
+#: option.c:4731
 #, c-format
 msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
 msgstr "Acest program vine FĂRĂ NICI O GARANŢIE.\n"
 
-#: option.c:4468
+#: option.c:4732
 #, c-format
 msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
 msgstr "Dnsmasq este un program gratuit, sunteţi invitaţi să-l redistribuiţi\n"
 
-#: option.c:4469
+#: option.c:4733
 #, fuzzy, c-format
 msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
 msgstr "în termenii Licenţei publice generale GNU, versiunea 2.\n"
 
-#: option.c:4480
+#: option.c:4744
 msgid "try --help"
 msgstr ""
 
-#: option.c:4482
+#: option.c:4746
 msgid "try -w"
 msgstr ""
 
-#: option.c:4484
+#: option.c:4748
 #, fuzzy, c-format
 msgid "bad command line options: %s"
 msgstr "opţiuni în linie de comandă invalide: %s."
 
-#: option.c:4541
+#: option.c:4818
+#, c-format
+msgid "CNAME loop involving %s"
+msgstr ""
+
+#: option.c:4854
 #, c-format
 msgid "cannot get host-name: %s"
 msgstr "nu pot citi numele maşinii: %s"
 
-#: option.c:4569
+#: option.c:4882
 msgid "only one resolv.conf file allowed in no-poll mode."
 msgstr "se permite un singur fişier resolv.conf în modul no-poll"
 
-#: option.c:4579
+#: option.c:4892
 msgid "must have exactly one resolv.conf to read domain from."
 msgstr "am nevoie de un singur resolv.conf din care să citesc numele domeniului."
 
-#: option.c:4582 network.c:1507 dhcp.c:777
+#: option.c:4895 network.c:1623 dhcp.c:816
 #, fuzzy, c-format
 msgid "failed to read %s: %s"
 msgstr "nu pot citi %s: %s"
 
-#: option.c:4599
+#: option.c:4912
 #, c-format
 msgid "no search directive found in %s"
 msgstr "nu s-a găsit nici un criteriu de căutare în %s"
 
-#: option.c:4620
+#: option.c:4933
 msgid "there must be a default domain when --dhcp-fqdn is set"
 msgstr ""
 
-#: option.c:4629
+#: option.c:4942
 msgid "syntax check OK"
 msgstr ""
 
-#: forward.c:111
+#: forward.c:102
 #, fuzzy, c-format
 msgid "failed to send packet: %s"
 msgstr "ascultarea pe socket a eşuat: %s"
 
-#: forward.c:591
+#: forward.c:598
 msgid "discarding DNS reply: subnet option mismatch"
 msgstr ""
 
-#: forward.c:614
+#: forward.c:652
 #, c-format
 msgid "nameserver %s refused to do a recursive query"
 msgstr "serverul DNS %s refuză interogările recursive"
 
-#: forward.c:646
+#: forward.c:684
 #, c-format
 msgid "possible DNS-rebind attack detected: %s"
 msgstr ""
 
-#: forward.c:1209 forward.c:1815
+#: forward.c:870
+#, c-format
+msgid "reducing DNS packet size for nameserver %s to %d"
+msgstr ""
+
+#: forward.c:1266 forward.c:1704
 msgid "Ignoring query from non-local network"
 msgstr ""
 
-#: forward.c:2286
+#: forward.c:2184
 #, fuzzy, c-format
 msgid "Maximum number of concurrent DNS queries reached (max: %d)"
 msgstr "Specifică numărul maxim de împrumuturi DHCP (implicit %s)."
 
-#: network.c:715
+#: network.c:720
 #, fuzzy, c-format
 msgid "failed to create listening socket for %s: %s"
 msgstr "creearea socket-ului de ascultare a eşuat: %s"
 
-#: network.c:1021
+#: network.c:1031
 #, c-format
 msgid "LOUD WARNING: listening on %s may accept requests via interfaces other than %s"
 msgstr ""
 
-#: network.c:1028
+#: network.c:1038
 msgid "LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"
 msgstr ""
 
-#: network.c:1037
+#: network.c:1047
+#, fuzzy, c-format
+msgid "warning: using interface %s instead"
+msgstr "atenţie: interfaţa %s nu există momentan"
+
+#: network.c:1056
 #, fuzzy, c-format
 msgid "warning: no addresses found for interface %s"
 msgstr "folosim adresele locale doar pentru %S %s"
 
-#: network.c:1095
+#: network.c:1114
 #, fuzzy, c-format
 msgid "interface %s failed to join DHCPv6 multicast group: %s"
 msgstr "activarea socket-ului server-ului DHCP a eşuat: %s"
 
-#: network.c:1289
+#: network.c:1119
+msgid "try increasing /proc/sys/net/core/optmem_max"
+msgstr ""
+
+#: network.c:1337
 #, fuzzy, c-format
 msgid "failed to bind server socket for %s: %s"
 msgstr "activarea socket-ului de ascultare pentru %s a eşuat: %s"
 
-#: network.c:1445
+#: network.c:1528
 #, c-format
 msgid "ignoring nameserver %s - local interface"
 msgstr "ignorăm serverul DNS %s - interfaţă locală"
 
-#: network.c:1456
+#: network.c:1539
 #, fuzzy, c-format
 msgid "ignoring nameserver %s - cannot make/bind socket: %s"
 msgstr "ignorăm serverul DNS %s - nu pot creea/activa socket-ul: %s"
 
-#: network.c:1469
+#: network.c:1559
+msgid "(no DNSSEC)"
+msgstr ""
+
+#: network.c:1562
 msgid "unqualified"
 msgstr "invalid"
 
-#: network.c:1469
+#: network.c:1562
 msgid "names"
 msgstr ""
 
-#: network.c:1471
+#: network.c:1564
 msgid "default"
 msgstr ""
 
-#: network.c:1473
+#: network.c:1566
 msgid "domain"
 msgstr "domeniu"
 
-#: network.c:1476
+#: network.c:1572
 #, c-format
 msgid "using local addresses only for %s %s"
 msgstr "folosim adresele locale doar pentru %S %s"
 
-#: network.c:1478
+#: network.c:1575
 #, fuzzy, c-format
 msgid "using standard nameservers for %s %s"
 msgstr "folosim serverul DNS %s#%d pentru %s %s"
 
-#: network.c:1480
-#, c-format
-msgid "using nameserver %s#%d for %s %s"
+#: network.c:1577
+#, fuzzy, c-format
+msgid "using nameserver %s#%d for %s %s %s"
 msgstr "folosim serverul DNS %s#%d pentru %s %s"
 
-#: network.c:1484
+#: network.c:1581
 #, fuzzy, c-format
 msgid "NOT using nameserver %s#%d - query loop detected"
 msgstr "folosim serverul DNS %s#%d pentru %s %s"
 
-#: network.c:1487
+#: network.c:1584
 #, fuzzy, c-format
 msgid "using nameserver %s#%d(via %s)"
 msgstr "folosim serverul DNS %s#%d"
 
-#: network.c:1489
+#: network.c:1586
 #, c-format
 msgid "using nameserver %s#%d"
 msgstr "folosim serverul DNS %s#%d"
 
-#: dnsmasq.c:163
+#: network.c:1591
+#, fuzzy, c-format
+msgid "using %d more local addresses"
+msgstr "folosim serverul DNS %s#%d"
+
+#: network.c:1593
+#, fuzzy, c-format
+msgid "using %d more nameservers"
+msgstr "folosim serverul DNS %s#%d"
+
+#: dnsmasq.c:171
 msgid "dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"
 msgstr ""
 
-#: dnsmasq.c:170
-msgid "no trust anchors provided for DNSSEC"
+#: dnsmasq.c:186
+msgid "no root trust anchor provided for DNSSEC"
 msgstr ""
 
-#: dnsmasq.c:173
+#: dnsmasq.c:189
 msgid "cannot reduce cache size from default when DNSSEC enabled"
 msgstr ""
 
-#: dnsmasq.c:175
+#: dnsmasq.c:191
 #, fuzzy
 msgid "DNSSEC not available: set HAVE_DNSSEC in src/config.h"
 msgstr "DBus nu este disponibil: puneţi HAVE_DBUS in src/config.h"
 
-#: dnsmasq.c:181
+#: dnsmasq.c:197
 #, fuzzy
 msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
 msgstr "DBus nu este disponibil: puneţi HAVE_DBUS in src/config.h"
 
-#: dnsmasq.c:186
+#: dnsmasq.c:202
 msgid "cannot use --conntrack AND --query-port"
 msgstr ""
 
-#: dnsmasq.c:189
+#: dnsmasq.c:205
 #, fuzzy
 msgid "conntrack support not available: set HAVE_CONNTRACK in src/config.h"
 msgstr "DBus nu este disponibil: puneţi HAVE_DBUS in src/config.h"
 
-#: dnsmasq.c:194
-msgid "asychronous logging is not available under Solaris"
+#: dnsmasq.c:210
+msgid "asynchronous logging is not available under Solaris"
 msgstr ""
 
-#: dnsmasq.c:199
-msgid "asychronous logging is not available under Android"
+#: dnsmasq.c:215
+msgid "asynchronous logging is not available under Android"
 msgstr ""
 
-#: dnsmasq.c:204
+#: dnsmasq.c:220
 #, fuzzy
 msgid "authoritative DNS not available: set HAVE_AUTH in src/config.h"
 msgstr "DBus nu este disponibil: puneţi HAVE_DBUS in src/config.h"
 
-#: dnsmasq.c:209
+#: dnsmasq.c:225
 #, fuzzy
 msgid "loop detection not available: set HAVE_LOOP in src/config.h"
 msgstr "DBus nu este disponibil: puneţi HAVE_DBUS in src/config.h"
 
-#: dnsmasq.c:217
+#: dnsmasq.c:229
+msgid "max_port cannot be smaller than min_port"
+msgstr ""
+
+#: dnsmasq.c:236
 msgid "zone serial must be configured in --auth-soa"
 msgstr ""
 
-#: dnsmasq.c:235
+#: dnsmasq.c:254
 msgid "dhcp-range constructor not available on this platform"
 msgstr ""
 
-#: dnsmasq.c:278
+#: dnsmasq.c:300
 msgid "cannot set --bind-interfaces and --bind-dynamic"
 msgstr ""
 
-#: dnsmasq.c:281
+#: dnsmasq.c:303
 #, c-format
 msgid "failed to find list of interfaces: %s"
 msgstr "enumerarea interfeţelor a eşuat: %s"
 
-#: dnsmasq.c:290
+#: dnsmasq.c:312
 #, c-format
 msgid "unknown interface %s"
 msgstr "interfaţă necunoscută %s"
 
-#: dnsmasq.c:354 dnsmasq.c:997
+#: dnsmasq.c:377 dnsmasq.c:1054
 #, c-format
 msgid "DBus error: %s"
 msgstr "eroare DBus: %s"
 
-#: dnsmasq.c:357
+#: dnsmasq.c:380
 msgid "DBus not available: set HAVE_DBUS in src/config.h"
 msgstr "DBus nu este disponibil: puneţi HAVE_DBUS in src/config.h"
 
-#: dnsmasq.c:385
+#: dnsmasq.c:410
 #, c-format
 msgid "unknown user or group: %s"
 msgstr ""
 
-#: dnsmasq.c:440
+#: dnsmasq.c:465
 #, c-format
 msgid "cannot chdir to filesystem root: %s"
 msgstr ""
 
-#: dnsmasq.c:692
+#: dnsmasq.c:730
 #, fuzzy, c-format
 msgid "started, version %s DNS disabled"
 msgstr "am pornit, versiunea %s memorie temporară dezactivată"
 
-#: dnsmasq.c:694
+#: dnsmasq.c:734
 #, c-format
 msgid "started, version %s cachesize %d"
 msgstr "am ponit, versiunea %s memorie temporară %d"
 
-#: dnsmasq.c:696
+#: dnsmasq.c:736
 #, c-format
 msgid "started, version %s cache disabled"
 msgstr "am pornit, versiunea %s memorie temporară dezactivată"
 
-#: dnsmasq.c:698
+#: dnsmasq.c:739
+msgid "DNS service limited to local subnets"
+msgstr ""
+
+#: dnsmasq.c:742
 #, c-format
 msgid "compile time options: %s"
 msgstr "compilat cu opţiunile: %s"
 
-#: dnsmasq.c:704
+#: dnsmasq.c:751
 msgid "DBus support enabled: connected to system bus"
 msgstr "suportul DBus activ: sunt conectat la magistrala sistem"
 
-#: dnsmasq.c:706
+#: dnsmasq.c:753
 msgid "DBus support enabled: bus connection pending"
 msgstr "suportul DBus activ: aştept conexiunea la magistrală"
 
-#: dnsmasq.c:711
-msgid "DNS service limited to local subnets"
-msgstr ""
-
-#: dnsmasq.c:727
+#: dnsmasq.c:771
 msgid "DNSSEC validation enabled"
 msgstr ""
 
-#: dnsmasq.c:730
-msgid "DNSSEC signature timestamps not checked until first cache reload"
+#: dnsmasq.c:775
+msgid "DNSSEC signature timestamps not checked until receipt of SIGINT"
 msgstr ""
 
-#: dnsmasq.c:733
+#: dnsmasq.c:778
 msgid "DNSSEC signature timestamps not checked until system time valid"
 msgstr ""
 
 # for compatibility purposes the letters â, ă, ş, ţ and î can be written as their look-alike correspondent.
-#: dnsmasq.c:738
+#: dnsmasq.c:783
 #, fuzzy, c-format
 msgid "warning: failed to change owner of %s: %s"
 msgstr "încărcarea numelor din %s: %s a eşuat"
 
-#: dnsmasq.c:742
+#: dnsmasq.c:787
 msgid "setting --bind-interfaces option because of OS limitations"
 msgstr "specific opţiunea --bind-interfaces din cauza limitărilor SO"
 
-#: dnsmasq.c:752
+#: dnsmasq.c:799
 #, c-format
 msgid "warning: interface %s does not currently exist"
 msgstr "atenţie: interfaţa %s nu există momentan"
 
-#: dnsmasq.c:757
+#: dnsmasq.c:804
 msgid "warning: ignoring resolv-file flag because no-resolv is set"
 msgstr ""
 
-#: dnsmasq.c:760
+#: dnsmasq.c:807
 #, fuzzy
 msgid "warning: no upstream servers configured"
 msgstr "configurăm serverele superioare prin Dbus"
 
-#: dnsmasq.c:764
+#: dnsmasq.c:811
 #, c-format
 msgid "asynchronous logging enabled, queue limit is %d messages"
 msgstr ""
 
-#: dnsmasq.c:785
+#: dnsmasq.c:832
 msgid "IPv6 router advertisement enabled"
 msgstr ""
 
-#: dnsmasq.c:790
+#: dnsmasq.c:837
 #, c-format
 msgid "DHCP, sockets bound exclusively to interface %s"
 msgstr ""
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 msgid "root is "
 msgstr ""
 
-#: dnsmasq.c:804
+#: dnsmasq.c:851
 #, fuzzy
 msgid "enabled"
 msgstr "dezactivat"
 
-#: dnsmasq.c:806
+#: dnsmasq.c:853
 msgid "secure mode"
 msgstr ""
 
-#: dnsmasq.c:809
+#: dnsmasq.c:856
 #, c-format
 msgid "warning: %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:813
+#: dnsmasq.c:860
 #, c-format
 msgid "warning: TFTP directory %s inaccessible"
 msgstr ""
 
-#: dnsmasq.c:839
+#: dnsmasq.c:886
 #, c-format
 msgid "restricting maximum simultaneous TFTP transfers to %d"
 msgstr ""
 
-#: dnsmasq.c:999
+#: dnsmasq.c:1056
 msgid "connected to system DBus"
 msgstr "magistrala sistem Dbus conectată"
 
-#: dnsmasq.c:1149
+#: dnsmasq.c:1215
 #, c-format
 msgid "cannot fork into background: %s"
 msgstr ""
 
-#: dnsmasq.c:1152
+#: dnsmasq.c:1218
 #, fuzzy, c-format
 msgid "failed to create helper: %s"
 msgstr "nu pot citi %s: %s"
 
-#: dnsmasq.c:1155
+#: dnsmasq.c:1221
 #, c-format
 msgid "setting capabilities failed: %s"
 msgstr ""
 
 # for compatibility purposes the letters â, ă, ş, ţ and î can be written as their look-alike correspondent.
-#: dnsmasq.c:1158
+#: dnsmasq.c:1224
 #, fuzzy, c-format
 msgid "failed to change user-id to %s: %s"
 msgstr "încărcarea numelor din %s: %s a eşuat"
 
 # for compatibility purposes the letters â, ă, ş, ţ and î can be written as their look-alike correspondent.
-#: dnsmasq.c:1161
+#: dnsmasq.c:1227
 #, fuzzy, c-format
 msgid "failed to change group-id to %s: %s"
 msgstr "încărcarea numelor din %s: %s a eşuat"
 
-#: dnsmasq.c:1164
+#: dnsmasq.c:1230
 #, fuzzy, c-format
 msgid "failed to open pidfile %s: %s"
 msgstr "nu pot citi %s: %s"
 
-#: dnsmasq.c:1167
+#: dnsmasq.c:1233
 #, fuzzy, c-format
 msgid "cannot open log %s: %s"
 msgstr "nu pot deschide %s:%s"
 
-#: dnsmasq.c:1170
+#: dnsmasq.c:1236
 #, fuzzy, c-format
 msgid "failed to load Lua script: %s"
 msgstr "nu pot încărca %s: %s"
 
-#: dnsmasq.c:1173
+#: dnsmasq.c:1239
 #, c-format
 msgid "TFTP directory %s inaccessible: %s"
 msgstr ""
 
-#: dnsmasq.c:1176
+#: dnsmasq.c:1242
 #, fuzzy, c-format
 msgid "cannot create timestamp file %s: %s"
 msgstr "nu pot creea sau deschide fişierul cu împrumuturi: %s"
 
-#: dnsmasq.c:1197
-msgid "now checking DNSSEC signature timestamps"
-msgstr ""
-
-#: dnsmasq.c:1264
+#: dnsmasq.c:1326
 #, c-format
 msgid "script process killed by signal %d"
 msgstr ""
 
-#: dnsmasq.c:1268
+#: dnsmasq.c:1330
 #, c-format
 msgid "script process exited with status %d"
 msgstr ""
 
-#: dnsmasq.c:1272
+#: dnsmasq.c:1334
 #, fuzzy, c-format
 msgid "failed to execute %s: %s"
 msgstr "accesarea serverului %s a eşuat: %s"
 
-#: dnsmasq.c:1327
+#: dnsmasq.c:1374
+msgid "now checking DNSSEC signature timestamps"
+msgstr ""
+
+#: dnsmasq.c:1409 dnssec.c:160 dnssec.c:206
+#, fuzzy, c-format
+msgid "failed to update mtime on %s: %s"
+msgstr "nu pot citi %s: %s"
+
+#: dnsmasq.c:1416
 msgid "exiting on receipt of SIGTERM"
 msgstr "am primit SIGTERM, am terminat"
 
-#: dnsmasq.c:1355
+#: dnsmasq.c:1444
 #, fuzzy, c-format
 msgid "failed to access %s: %s"
 msgstr "accesarea serverului %s a eşuat: %s"
 
-#: dnsmasq.c:1385
+#: dnsmasq.c:1474
 #, c-format
 msgid "reading %s"
 msgstr "citesc %s"
 
-#: dnsmasq.c:1396
+#: dnsmasq.c:1485
 #, fuzzy, c-format
 msgid "no servers found in %s, will retry"
 msgstr "nu s-a găsit nici un criteriu de căutare în %s"
@@ -1582,243 +1659,263 @@ msgstr "activarea socket-ului server-ului DHCP a eşuat: %s"
 msgid "cannot create ICMP raw socket: %s."
 msgstr "nu pot creea socket ICMP raw: %s."
 
-#: dhcp.c:241 dhcp6.c:180
+#: dhcp.c:252 dhcp6.c:173
 #, fuzzy, c-format
 msgid "unknown interface %s in bridge-interface"
 msgstr "interfaţă necunoscută %s"
 
-#: dhcp.c:281
+#: dhcp.c:293
 #, c-format
 msgid "DHCP packet received on %s which has no address"
 msgstr ""
 
-#: dhcp.c:415
+#: dhcp.c:427
 #, c-format
 msgid "ARP-cache injection failed: %s"
 msgstr ""
 
-#: dhcp.c:514
+#: dhcp.c:470
+#, c-format
+msgid "Error sending DHCP packet to %s: %s"
+msgstr ""
+
+#: dhcp.c:531
 #, c-format
 msgid "DHCP range %s -- %s is not consistent with netmask %s"
 msgstr "domeniu DHCP %s -- %s nu este consistent cu masca de reţea %s"
 
-#: dhcp.c:815
+#: dhcp.c:854
 #, c-format
 msgid "bad line at %s line %d"
 msgstr "linie invalidă în %s rândul %d"
 
-#: dhcp.c:858
+#: dhcp.c:897
 #, c-format
 msgid "ignoring %s line %d, duplicate name or IP address"
 msgstr ""
 
-#: dhcp.c:1002 rfc3315.c:2135
+#: dhcp.c:1041 rfc3315.c:2149
 #, c-format
 msgid "DHCP relay %s -> %s"
 msgstr ""
 
-#: lease.c:61
+#: lease.c:98
+msgid "too many stored leases"
+msgstr "prea multe împrumuturi stocate"
+
+#: lease.c:166
 #, fuzzy, c-format
 msgid "cannot open or create lease file %s: %s"
 msgstr "nu pot creea sau deschide fişierul cu împrumuturi: %s"
 
-#: lease.c:134
-msgid "too many stored leases"
-msgstr "prea multe împrumuturi stocate"
+#: lease.c:175
+#, c-format
+msgid "failed to parse lease database, invalid line: %s %s %s %s ..."
+msgstr ""
+
+#: lease.c:180
+#, fuzzy, c-format
+msgid "failed to read lease file %s: %s"
+msgstr "nu pot citi %s: %s"
 
-#: lease.c:165
+#: lease.c:196
 #, fuzzy, c-format
 msgid "cannot run lease-init script %s: %s"
 msgstr "nu pot citi %s: %s"
 
-#: lease.c:171
+#: lease.c:202
 #, c-format
 msgid "lease-init script returned exit code %s"
 msgstr ""
 
-#: lease.c:342
+#: lease.c:373
 #, fuzzy, c-format
 msgid "failed to write %s: %s (retry in %us)"
 msgstr "nu pot citi %s: %s"
 
-#: lease.c:906
+#: lease.c:937
 #, c-format
 msgid "Ignoring domain %s for DHCP host name %s"
 msgstr ""
 
-#: rfc2131.c:344
+#: rfc2131.c:347
 #, c-format
 msgid "no address range available for DHCP request %s %s"
 msgstr "nici un domeniu de adrese disponibil pentru cererea DHCP %s %s"
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "with subnet selector"
 msgstr "cu selectorul de subreţea"
 
-#: rfc2131.c:345
+#: rfc2131.c:348
 msgid "via"
 msgstr "prin"
 
-#: rfc2131.c:357
+#: rfc2131.c:360
 #, fuzzy, c-format
 msgid "%u available DHCP subnet: %s/%s"
 msgstr "nici un domeniu de adrese disponibil pentru cererea DHCP %s %s"
 
-#: rfc2131.c:360 rfc3315.c:300
+#: rfc2131.c:363 rfc3315.c:306
 #, c-format
 msgid "%u available DHCP range: %s -- %s"
 msgstr ""
 
-#: rfc2131.c:471
+#: rfc2131.c:474
 #, fuzzy, c-format
 msgid "%u vendor class: %s"
 msgstr "eroare DBus: %s"
 
-#: rfc2131.c:473
+#: rfc2131.c:476
 #, fuzzy, c-format
 msgid "%u user class: %s"
 msgstr "eroare DBus: %s"
 
-#: rfc2131.c:500
+#: rfc2131.c:510
 msgid "disabled"
 msgstr "dezactivat"
 
-#: rfc2131.c:541 rfc2131.c:974 rfc2131.c:1380 rfc3315.c:603 rfc3315.c:856
-#: rfc3315.c:1135
+#: rfc2131.c:551 rfc2131.c:1006 rfc2131.c:1430 rfc3315.c:616 rfc3315.c:869
+#: rfc3315.c:1148
 msgid "ignored"
 msgstr "ignorat"
 
-#: rfc2131.c:556 rfc2131.c:1207 rfc3315.c:906
+#: rfc2131.c:566 rfc2131.c:1239 rfc3315.c:919
 msgid "address in use"
 msgstr "adresa este folosită"
 
-#: rfc2131.c:570 rfc2131.c:1028
+#: rfc2131.c:580 rfc2131.c:1060
 msgid "no address available"
 msgstr "nici o adresă disponibilă"
 
-#: rfc2131.c:577 rfc2131.c:1170
+#: rfc2131.c:587 rfc2131.c:1202
 msgid "wrong network"
 msgstr "reţea greşită"
 
-#: rfc2131.c:592
+#: rfc2131.c:602
 msgid "no address configured"
 msgstr "adresă lipsă"
 
-#: rfc2131.c:598 rfc2131.c:1220
+#: rfc2131.c:608 rfc2131.c:1252
 msgid "no leases left"
 msgstr "nu mai am de unde să împrumut"
 
-#: rfc2131.c:693 rfc3315.c:476
+#: rfc2131.c:703 rfc3315.c:482
 #, c-format
 msgid "%u client provides name: %s"
 msgstr ""
 
-#: rfc2131.c:798
+#: rfc2131.c:808
 msgid "PXE BIS not supported"
 msgstr ""
 
-#: rfc2131.c:942 rfc3315.c:1229
+#: rfc2131.c:974 rfc3315.c:1242
 #, fuzzy, c-format
 msgid "disabling DHCP static address %s for %s"
 msgstr "dezactivăm adresele DHCP statice %s"
 
-#: rfc2131.c:963
+#: rfc2131.c:995
 msgid "unknown lease"
 msgstr "împrumut necunoscut"
 
-#: rfc2131.c:997
+#: rfc2131.c:1029
 #, c-format
 msgid "not using configured address %s because it is leased to %s"
 msgstr ""
 
-#: rfc2131.c:1007
+#: rfc2131.c:1039
 #, c-format
 msgid "not using configured address %s because it is in use by the server or relay"
 msgstr ""
 
-#: rfc2131.c:1010
+#: rfc2131.c:1042
 #, c-format
 msgid "not using configured address %s because it was previously declined"
 msgstr ""
 
-#: rfc2131.c:1026 rfc2131.c:1213
+#: rfc2131.c:1058 rfc2131.c:1245
 msgid "no unique-id"
 msgstr ""
 
-#: rfc2131.c:1108
+#: rfc2131.c:1140
 msgid "wrong server-ID"
 msgstr ""
 
-#: rfc2131.c:1127
+#: rfc2131.c:1159
 msgid "wrong address"
 msgstr "adresă greşită"
 
-#: rfc2131.c:1145 rfc3315.c:1002
+#: rfc2131.c:1177 rfc3315.c:1015
 msgid "lease not found"
 msgstr "împrumutul nu a fost găsit"
 
-#: rfc2131.c:1178
+#: rfc2131.c:1210
 msgid "address not available"
 msgstr "adresă indisponibilă"
 
-#: rfc2131.c:1189
+#: rfc2131.c:1221
 msgid "static lease available"
 msgstr "împrumut static este disponibil"
 
-#: rfc2131.c:1193
+#: rfc2131.c:1225
 msgid "address reserved"
 msgstr "adresă rezervată"
 
-#: rfc2131.c:1201
+#: rfc2131.c:1233
 #, c-format
 msgid "abandoning lease to %s of %s"
 msgstr ""
 
-#: rfc2131.c:1707
+#: rfc2131.c:1757
 #, c-format
 msgid "%u bootfile name: %s"
 msgstr ""
 
-#: rfc2131.c:1716
+#: rfc2131.c:1766
 #, fuzzy, c-format
 msgid "%u server name: %s"
 msgstr "eroare DBus: %s"
 
-#: rfc2131.c:1724
+#: rfc2131.c:1774
 #, fuzzy, c-format
 msgid "%u next server: %s"
 msgstr "eroare DBus: %s"
 
-#: rfc2131.c:1727
+#: rfc2131.c:1777
 #, c-format
 msgid "%u broadcast response"
 msgstr ""
 
-#: rfc2131.c:1790
+#: rfc2131.c:1840
 #, fuzzy, c-format
 msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
 msgstr "nu pot trimite opţiunea DHCP %d: nu mai este loc în pachet"
 
-#: rfc2131.c:2031
+#: rfc2131.c:2131
 msgid "PXE menu too large"
 msgstr ""
 
-#: rfc2131.c:2170 rfc3315.c:1502
+#: rfc2131.c:2270 rfc3315.c:1515
 #, fuzzy, c-format
 msgid "%u requested options: %s"
 msgstr "compilat cu opţiunile: %s"
 
-#: rfc2131.c:2487
+#: rfc2131.c:2587
 #, c-format
 msgid "cannot send RFC3925 option: too many options for enterprise number %d"
 msgstr ""
 
+#: rfc2131.c:2650
+#, c-format
+msgid "%u reply delay: %d"
+msgstr ""
+
 #: netlink.c:77
 #, fuzzy, c-format
 msgid "cannot create netlink socket: %s"
 msgstr "nu pot să activez socket-ul netlink: %s"
 
-#: netlink.c:348
+#: netlink.c:355
 #, fuzzy, c-format
 msgid "netlink returns error: %s"
 msgstr "eroare DBus: %s"
@@ -1837,62 +1934,62 @@ msgstr ""
 msgid "Disabling --%s option from D-Bus"
 msgstr ""
 
-#: dbus.c:691
+#: dbus.c:690
 msgid "setting upstream servers from DBus"
 msgstr "configurăm serverele superioare prin Dbus"
 
-#: dbus.c:738
+#: dbus.c:737
 msgid "could not register a DBus message handler"
 msgstr "nu pot activa o interfaţă de mesaje DBus"
 
-#: bpf.c:263
+#: bpf.c:265
 #, c-format
 msgid "cannot create DHCP BPF socket: %s"
 msgstr "nu pot creea socket DHCP BPF: %s"
 
-#: bpf.c:291
+#: bpf.c:293
 #, fuzzy, c-format
 msgid "DHCP request for unsupported hardware type (%d) received on %s"
 msgstr "cerere DHCP pentru dispozitiv nesuportat (%d) recepţionată prin %s"
 
-#: bpf.c:376
+#: bpf.c:378
 #, fuzzy, c-format
 msgid "cannot create PF_ROUTE socket: %s"
 msgstr "nu pot creea socket DHCP: %s"
 
-#: bpf.c:397
+#: bpf.c:399
 msgid "Unknown protocol version from route socket"
 msgstr ""
 
-#: helper.c:153
+#: helper.c:154
 msgid "lease() function missing in Lua script"
 msgstr ""
 
-#: tftp.c:309
+#: tftp.c:319
 msgid "unable to get free port for TFTP"
 msgstr ""
 
-#: tftp.c:325
+#: tftp.c:335
 #, c-format
 msgid "unsupported request from %s"
 msgstr ""
 
-#: tftp.c:439
+#: tftp.c:483
 #, fuzzy, c-format
 msgid "file %s not found"
 msgstr "împrumutul nu a fost găsit"
 
-#: tftp.c:548
+#: tftp.c:592
 #, c-format
 msgid "error %d %s received from %s"
 msgstr ""
 
-#: tftp.c:590
+#: tftp.c:634
 #, fuzzy, c-format
 msgid "failed sending %s to %s"
 msgstr "nu pot citi %s: %s"
 
-#: tftp.c:590
+#: tftp.c:634
 #, c-format
 msgid "sent %s to %s"
 msgstr ""
@@ -1907,7 +2004,7 @@ msgstr ""
 msgid "log failed: %s"
 msgstr ""
 
-#: log.c:469
+#: log.c:471
 msgid "FAILED to start up"
 msgstr "pornirea A EŞUAT"
 
@@ -1916,17 +2013,17 @@ msgstr "pornirea A EŞUAT"
 msgid "Conntrack connection mark retrieval failed: %s"
 msgstr ""
 
-#: dhcp6.c:59
+#: dhcp6.c:52
 #, fuzzy, c-format
 msgid "cannot create DHCPv6 socket: %s"
 msgstr "nu pot creea socket DHCP: %s"
 
-#: dhcp6.c:80
+#: dhcp6.c:73
 #, fuzzy, c-format
 msgid "failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"
 msgstr "configurarea SO_REUSEADDR pe socket-ul DHCP a eşuat: %s"
 
-#: dhcp6.c:92
+#: dhcp6.c:85
 #, fuzzy, c-format
 msgid "failed to bind DHCPv6 server socket: %s"
 msgstr "activarea socket-ului server-ului DHCP a eşuat: %s"
@@ -1941,71 +2038,71 @@ msgstr "nici un domeniu de adrese disponibil pentru cererea DHCP %s %s"
 msgid "no address range available for DHCPv6 request via %s"
 msgstr "nici un domeniu de adrese disponibil pentru cererea DHCP %s %s"
 
-#: rfc3315.c:297
+#: rfc3315.c:303
 #, fuzzy, c-format
 msgid "%u available DHCPv6 subnet: %s/%d"
 msgstr "nici un domeniu de adrese disponibil pentru cererea DHCP %s %s"
 
-#: rfc3315.c:380
+#: rfc3315.c:386
 #, fuzzy, c-format
 msgid "%u vendor class: %u"
 msgstr "eroare DBus: %s"
 
-#: rfc3315.c:428
+#: rfc3315.c:434
 #, fuzzy, c-format
 msgid "%u client MAC address: %s"
 msgstr "nu exista interfaţă pentru adresa %s"
 
-#: rfc3315.c:660
+#: rfc3315.c:673
 #, fuzzy, c-format
 msgid "unknown prefix-class %d"
 msgstr "împrumut necunoscut"
 
-#: rfc3315.c:803 rfc3315.c:898
+#: rfc3315.c:816 rfc3315.c:911
 #, fuzzy
 msgid "address unavailable"
 msgstr "adresă indisponibilă"
 
-#: rfc3315.c:815 rfc3315.c:946 rfc3315.c:1279
+#: rfc3315.c:828 rfc3315.c:959 rfc3315.c:1292
 msgid "success"
 msgstr ""
 
-#: rfc3315.c:830 rfc3315.c:839 rfc3315.c:954 rfc3315.c:956
+#: rfc3315.c:843 rfc3315.c:852 rfc3315.c:967 rfc3315.c:969
 #, fuzzy
 msgid "no addresses available"
 msgstr "nici o adresă disponibilă"
 
-#: rfc3315.c:933
+#: rfc3315.c:946
 msgid "not on link"
 msgstr ""
 
-#: rfc3315.c:1006 rfc3315.c:1191 rfc3315.c:1268
+#: rfc3315.c:1019 rfc3315.c:1204 rfc3315.c:1281
 msgid "no binding found"
 msgstr ""
 
-#: rfc3315.c:1044
+#: rfc3315.c:1057
 msgid "deprecated"
 msgstr ""
 
-#: rfc3315.c:1049
+#: rfc3315.c:1062
 #, fuzzy
 msgid "address invalid"
 msgstr "adresa este folosită"
 
-#: rfc3315.c:1096
+#: rfc3315.c:1109
 msgid "confirm failed"
 msgstr ""
 
-#: rfc3315.c:1112
+#: rfc3315.c:1125
 #, fuzzy
 msgid "all addresses still on link"
 msgstr "adresă greşită în %s, linia %d"
 
-#: rfc3315.c:1200
+#: rfc3315.c:1213
 msgid "release received"
 msgstr ""
 
-#: rfc3315.c:2126
+#: rfc3315.c:2140
 msgid "Cannot multicast to DHCPv6 server without correct interface"
 msgstr ""
 
@@ -2029,76 +2126,76 @@ msgstr ""
 msgid "duplicate IP address %s (%s) in dhcp-config directive"
 msgstr "adresă IP duplicat %s (%s) în declaraţia dhcp-config."
 
-#: dhcp-common.c:494
+#: dhcp-common.c:491
 #, fuzzy, c-format
 msgid "failed to set SO_BINDTODEVICE on DHCP socket: %s"
 msgstr "configurarea SO_REUSEADDR pe socket-ul DHCP a eşuat: %s"
 
-#: dhcp-common.c:615
+#: dhcp-common.c:612
 #, c-format
 msgid "Known DHCP options:\n"
 msgstr ""
 
-#: dhcp-common.c:626
+#: dhcp-common.c:623
 #, c-format
 msgid "Known DHCPv6 options:\n"
 msgstr ""
 
-#: dhcp-common.c:823
+#: dhcp-common.c:820
 msgid ", prefix deprecated"
 msgstr ""
 
-#: dhcp-common.c:826
+#: dhcp-common.c:823
 #, c-format
 msgid ", lease time "
 msgstr ""
 
-#: dhcp-common.c:868
+#: dhcp-common.c:865
 #, c-format
 msgid "%s stateless on %s%.0s%.0s%s"
 msgstr ""
 
-#: dhcp-common.c:870
+#: dhcp-common.c:867
 #, fuzzy, c-format
 msgid "%s, static leases only on %.0s%s%s%.0s"
 msgstr "DHCP, împrumuturi statice doar către  %.0s%s, timpul reînoirii %s"
 
-#: dhcp-common.c:872
+#: dhcp-common.c:869
 #, c-format
 msgid "%s, proxy on subnet %.0s%s%.0s%.0s"
 msgstr ""
 
-#: dhcp-common.c:873
+#: dhcp-common.c:870
 #, fuzzy, c-format
 msgid "%s, IP range %s -- %s%s%.0s"
 msgstr "DHCP, domeniu IP %s -- %s, timpul reînoirii %s"
 
-#: dhcp-common.c:886
+#: dhcp-common.c:883
 #, c-format
 msgid "DHCPv4-derived IPv6 names on %s%s"
 msgstr ""
 
-#: dhcp-common.c:889
+#: dhcp-common.c:886
 #, fuzzy, c-format
 msgid "router advertisement on %s%s"
 msgstr "DHCP, împrumuturi statice doar către  %.0s%s, timpul reînoirii %s"
 
-#: dhcp-common.c:900
+#: dhcp-common.c:897
 #, c-format
 msgid "DHCP relay from %s to %s via %s"
 msgstr ""
 
-#: dhcp-common.c:902
+#: dhcp-common.c:899
 #, c-format
 msgid "DHCP relay from %s to %s"
 msgstr ""
 
-#: radv.c:109
+#: radv.c:110
 #, fuzzy, c-format
 msgid "cannot create ICMPv6 socket: %s"
 msgstr "nu pot creea socket DHCP: %s"
 
-#: auth.c:448
+#: auth.c:449
 #, c-format
 msgid "ignoring zone transfer request from %s"
 msgstr ""
@@ -2113,90 +2210,90 @@ msgstr "activarea socket-ului server-ului DHCP a eşuat: %s"
 msgid "failed to create IPset control socket: %s"
 msgstr "creearea socket-ului de ascultare a eşuat: %s"
 
-#: dnssec.c:449 dnssec.c:493
+#: ipset.c:233
 #, fuzzy, c-format
-msgid "failed to update mtime on %s: %s"
+msgid "failed to update ipset %s: %s"
 msgstr "nu pot citi %s: %s"
 
+#: dnssec.c:208
+msgid "system time considered valid, now checking DNSSEC signature timestamps."
+msgstr ""
+
 #: blockdata.c:58
 #, c-format
 msgid "DNSSEC memory in use %u, max %u, allocated %u"
 msgstr ""
 
-#: tables.c:80
-msgid "error: fill_addr missused"
-msgstr ""
-
-#: tables.c:109
+#: tables.c:61
 #, fuzzy, c-format
 msgid "failed to access pf devices: %s"
 msgstr "accesarea serverului %s a eşuat: %s"
 
-#: tables.c:123
+#: tables.c:74
 #, fuzzy, c-format
 msgid "warning: no opened pf devices %s"
 msgstr "folosim adresele locale doar pentru %S %s"
 
-#: tables.c:131
+#: tables.c:82
 #, fuzzy, c-format
 msgid "error: cannot use table name %s"
 msgstr "nu pot citi numele maşinii: %s"
 
-#: tables.c:139
+#: tables.c:90
 #, c-format
 msgid "error: cannot strlcpy table name %s"
 msgstr ""
 
-#: tables.c:145
-#, c-format
-msgid "warning: pfr_add_tables: %s(%d)"
-msgstr ""
+#: tables.c:101
+#, fuzzy, c-format
+msgid "IPset: error:%s"
+msgstr "eroare DBus: %s"
 
-#: tables.c:151
+#: tables.c:108
 msgid "info: table created"
 msgstr ""
 
-#: tables.c:162
+#: tables.c:134
 #, c-format
 msgid "warning: DIOCR%sADDRS: %s"
 msgstr ""
 
-#: tables.c:166
+#: tables.c:138
 #, fuzzy, c-format
 msgid "%d addresses %s"
 msgstr "citesc %s - %d adrese"
 
-#: inotify.c:59
+#: inotify.c:62
 #, fuzzy, c-format
 msgid "cannot access path %s: %s"
 msgstr "nu pot citi %s: %s"
 
-#: inotify.c:92
+#: inotify.c:95
 #, fuzzy, c-format
 msgid "failed to create inotify: %s"
 msgstr "nu pot citi %s: %s"
 
-#: inotify.c:105
+#: inotify.c:111
 #, c-format
 msgid "too many symlinks following %s"
 msgstr ""
 
-#: inotify.c:121
+#: inotify.c:127
 #, c-format
 msgid "directory %s for resolv-file is missing, cannot poll"
 msgstr ""
 
-#: inotify.c:125 inotify.c:162
+#: inotify.c:131 inotify.c:168
 #, fuzzy, c-format
 msgid "failed to create inotify for %s: %s"
 msgstr "creearea socket-ului de ascultare a eşuat: %s"
 
-#: inotify.c:147
+#: inotify.c:153
 #, fuzzy, c-format
 msgid "bad dynamic directory %s: %s"
 msgstr "nu pot citi %s: %s"
 
-#: inotify.c:247
+#: inotify.c:257
 #, c-format
 msgid "inotify, new or changed file %s"
 msgstr ""
index 482ff5d..fb80dab 100644 (file)
@@ -78,7 +78,7 @@ by modifying MODIFY_RESOLV_CONF_DYNAMICALLY="no" in <TT>/etc/sysconfig/network/c
  
 
 <h3>Automatic DNS server configuration with DHCP.</h3>
-You need to get your DHCP client to write the addresse(s) of the DNS
+You need to get your DHCP client to write the address(es) of the DNS
 servers to a file other than <TT>/etc/resolv.conf</TT>. For dhcpcd, the
 <TT>dhcpcd.exe</TT> script gets run with the addresses of the nameserver(s) in
 the shell variable <TT>$DNS</TT>. The following bit of shell script
@@ -86,8 +86,8 @@ uses that to write a file suitable for dnsmasq.
 <PRE>
 
 echo -n >|/etc/dhcpc/resolv.conf
-dnsservs=${DNS//,/ }
-for serv in $dnsservs; do
+dnsservers=${DNS//,/ }
+for serv in $dnsservers; do
     echo "nameserver $serv" >>/etc/dhcpc/resolv.conf
 done
 
@@ -125,7 +125,7 @@ address of its ethernet card. For the former to work, a machine needs to know it
 requests a DHCP lease. For dhcpcd, the -h option specifies this. The
 names may be anything as far as DHCP is concerned, but dnsmasq adds
 some limitations. By default the names must no have a domain part, ie
-they must just be a alphanumeric name, without any dots.  This is a
+they must just be alphanumeric names, without any dots.  This is a
 security feature to stop a machine on your network telling DHCP that
 its name is "www.microsoft.com" and thereby grabbing traffic which
 shouldn't go to it. A domain part is only allowed by dnsmasq in DHCP machine names
@@ -186,7 +186,7 @@ more than one nameserver just include as many
 
 <H2>Local domains.</H2>
 Sometimes people have local domains which they do not want forwarded
-to upstream servers. This is accomodated by using server options
+to upstream servers. This is accommodated by using server options
 without the server IP address. To make things clearer <TT>local</TT>
 is a synonym for <TT>server</TT>. For example the option
 <TT>local=/localnet/</TT> ensures that any domain name query which ends in
diff --git a/src/arp.c b/src/arp.c
new file mode 100644 (file)
index 0000000..8beaed4
--- /dev/null
+++ b/src/arp.c
@@ -0,0 +1,247 @@
+/* dnsmasq is Copyright (c) 2000-2018 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"
+
+/* Time between forced re-loads from kernel. */
+#define INTERVAL 90
+
+#define ARP_MARK  0
+#define ARP_FOUND 1  /* Confirmed */
+#define ARP_NEW   2  /* Newly created */
+#define ARP_EMPTY 3  /* No MAC addr */
+
+struct arp_record {
+  unsigned short hwlen, status;
+  int family;
+  unsigned char hwaddr[DHCP_CHADDR_MAX]; 
+  struct all_addr addr;
+  struct arp_record *next;
+};
+
+static struct arp_record *arps = NULL, *old = NULL, *freelist = NULL;
+static time_t last = 0;
+
+static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
+{
+  struct arp_record *arp;
+
+  (void)parmv;
+
+  if (maclen > DHCP_CHADDR_MAX)
+    return 1;
+
+#ifndef HAVE_IPV6
+  if (family != AF_INET)
+    return 1;
+#endif
+
+  /* Look for existing entry */
+  for (arp = arps; arp; arp = arp->next)
+    {
+      if (family != arp->family || arp->status == ARP_NEW)
+       continue;
+      
+      if (family == AF_INET)
+       {
+         if (arp->addr.addr.addr4.s_addr != ((struct in_addr *)addrp)->s_addr)
+           continue;
+       }
+#ifdef HAVE_IPV6
+      else
+       {
+         if (!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, (struct in6_addr *)addrp))
+           continue;
+       }
+#endif
+
+      if (arp->status == ARP_EMPTY)
+       {
+         /* existing address, was negative. */
+         arp->status = ARP_NEW;
+         arp->hwlen = maclen;
+         memcpy(arp->hwaddr, mac, maclen);
+       }
+      else if (arp->hwlen == maclen && memcmp(arp->hwaddr, mac, maclen) == 0)
+       /* Existing entry matches - confirm. */
+       arp->status = ARP_FOUND;
+      else
+       continue;
+      
+      break;
+    }
+
+  if (!arp)
+    {
+      /* New entry */
+      if (freelist)
+       {
+         arp = freelist;
+         freelist = freelist->next;
+       }
+      else if (!(arp = whine_malloc(sizeof(struct arp_record))))
+       return 1;
+      
+      arp->next = arps;
+      arps = arp;
+      arp->status = ARP_NEW;
+      arp->hwlen = maclen;
+      arp->family = family;
+      memcpy(arp->hwaddr, mac, maclen);
+      if (family == AF_INET)
+       arp->addr.addr.addr4.s_addr = ((struct in_addr *)addrp)->s_addr;
+#ifdef HAVE_IPV6
+      else
+       memcpy(&arp->addr.addr.addr6, addrp, IN6ADDRSZ);
+#endif
+    }
+  
+  return 1;
+}
+
+/* If in lazy mode, we cache absence of ARP entries. */
+int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now)
+{
+  struct arp_record *arp, *tmp, **up;
+  int updated = 0;
+
+ again:
+  
+  /* If the database is less then INTERVAL old, look in there */
+  if (difftime(now, last) < INTERVAL)
+    {
+      /* addr == NULL -> just make cache up-to-date */
+      if (!addr)
+       return 0;
+
+      for (arp = arps; arp; arp = arp->next)
+       {
+         if (addr->sa.sa_family != arp->family)
+           continue;
+           
+         if (arp->family == AF_INET &&
+             arp->addr.addr.addr4.s_addr != addr->in.sin_addr.s_addr)
+           continue;
+           
+#ifdef HAVE_IPV6
+         if (arp->family == AF_INET6 && 
+             !IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, &addr->in6.sin6_addr))
+           continue;
+#endif
+         
+         /* Only accept positive entries unless in lazy mode. */
+         if (arp->status != ARP_EMPTY || lazy || updated)
+           {
+             if (mac && arp->hwlen != 0)
+               memcpy(mac, arp->hwaddr, arp->hwlen);
+             return arp->hwlen;
+           }
+       }
+    }
+
+  /* Not found, try the kernel */
+  if (!updated)
+     {
+       updated = 1;
+       last = now;
+
+       /* Mark all non-negative entries */
+       for (arp = arps; arp; arp = arp->next)
+        if (arp->status != ARP_EMPTY)
+          arp->status = ARP_MARK;
+       
+       iface_enumerate(AF_UNSPEC, NULL, filter_mac);
+       
+       /* Remove all unconfirmed entries to old list. */
+       for (arp = arps, up = &arps; arp; arp = tmp)
+        {
+          tmp = arp->next;
+          
+          if (arp->status == ARP_MARK)
+            {
+              *up = arp->next;
+              arp->next = old;
+              old = arp;
+            }
+          else
+            up = &arp->next;
+        }
+
+       goto again;
+     }
+
+  /* record failure, so we don't consult the kernel each time
+     we're asked for this address */
+  if (freelist)
+    {
+      arp = freelist;
+      freelist = freelist->next;
+    }
+  else
+    arp = whine_malloc(sizeof(struct arp_record));
+  
+  if (arp)
+    {      
+      arp->next = arps;
+      arps = arp;
+      arp->status = ARP_EMPTY;
+      arp->family = addr->sa.sa_family;
+      arp->hwlen = 0;
+
+      if (addr->sa.sa_family == AF_INET)
+       arp->addr.addr.addr4.s_addr = addr->in.sin_addr.s_addr;
+#ifdef HAVE_IPV6
+      else
+       memcpy(&arp->addr.addr.addr6, &addr->in6.sin6_addr, IN6ADDRSZ);
+#endif
+    }
+         
+   return 0;
+}
+
+int do_arp_script_run(void)
+{
+  struct arp_record *arp;
+  
+  /* Notify any which went, then move to free list */
+  if (old)
+    {
+#ifdef HAVE_SCRIPT
+      if (option_bool(OPT_SCRIPT_ARP))
+       queue_arp(ACTION_ARP_DEL, old->hwaddr, old->hwlen, old->family, &old->addr);
+#endif
+      arp = old;
+      old = arp->next;
+      arp->next = freelist;
+      freelist = arp;
+      return 1;
+    }
+
+  for (arp = arps; arp; arp = arp->next)
+    if (arp->status == ARP_NEW)
+      {
+#ifdef HAVE_SCRIPT
+       if (option_bool(OPT_SCRIPT_ARP))
+         queue_arp(ACTION_ARP, arp->hwaddr, arp->hwlen, arp->family, &arp->addr);
+#endif
+       arp->status = ARP_FOUND;
+       return 1;
+      }
+
+  return 0;
+}
+
+
index 2b0b7d6..6ad051d 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
 
 #ifdef HAVE_AUTH
 
-static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u)
+static struct addrlist *find_addrlist(struct addrlist *list, int flag, struct all_addr *addr_u)
 {
-  struct addrlist *subnet;
-
-  for (subnet = zone->subnet; subnet; subnet = subnet->next)
-    {
-      if (!(subnet->flags & ADDRLIST_IPV6))
-       {
-         struct in_addr netmask, addr = addr_u->addr.addr4;
-
-         if (!(flag & F_IPV4))
-           continue;
-         
-         netmask.s_addr = htonl(~(in_addr_t)0 << (32 - subnet->prefixlen));
-         
-         if  (is_same_net(addr, subnet->addr.addr.addr4, netmask))
-           return subnet;
-       }
+  do {
+    if (!(list->flags & ADDRLIST_IPV6))
+      {
+       struct in_addr netmask, addr = addr_u->addr.addr4;
+       
+       if (!(flag & F_IPV4))
+         continue;
+       
+       netmask.s_addr = htonl(~(in_addr_t)0 << (32 - list->prefixlen));
+       
+       if  (is_same_net(addr, list->addr.addr.addr4, netmask))
+         return list;
+      }
 #ifdef HAVE_IPV6
-      else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr.addr.addr6, subnet->prefixlen))
-       return subnet;
+    else if (is_same_net6(&(addr_u->addr.addr6), &list->addr.addr.addr6, list->prefixlen))
+      return list;
 #endif
-
-    }
+    
+  } while ((list = list->next));
+  
   return NULL;
 }
 
+static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u)
+{
+  if (!zone->subnet)
+    return NULL;
+  
+  return find_addrlist(zone->subnet, flag, addr_u);
+}
+
+static struct addrlist *find_exclude(struct auth_zone *zone, int flag, struct all_addr *addr_u)
+{
+  if (!zone->exclude)
+    return NULL;
+  
+  return find_addrlist(zone->exclude, flag, addr_u);
+}
+
 static int filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
 {
-  /* No zones specified, no filter */
+  if (find_exclude(zone, flag, addr_u))
+    return 0;
+
+  /* No subnets specified, no filter */
   if (!zone->subnet)
     return 1;
   
@@ -81,7 +98,8 @@ int in_zone(struct auth_zone *zone, char *name, char **cut)
 }
 
 
-size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr, int local_query) 
+size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr, 
+                  int local_query, int do_bit, int have_pseudoheader) 
 {
   char *name = daemon->namebuff;
   unsigned char *p, *ansp;
@@ -98,7 +116,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
   struct interface_name *intr;
   struct naptr *na;
   struct all_addr addr;
-  struct cname *a;
+  struct cname *a, *candidate;
+  unsigned int wclen;
   
   if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
     return 0;
@@ -114,6 +133,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
     {
       unsigned short flag = 0;
       int found = 0;
+      int cname_wildcard = 0;
   
       /* save pointer to name for copying into answers */
       nameoffset = p - (unsigned char *)header;
@@ -388,25 +408,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
                   }
             }
        
-       for (a = daemon->cnames; a; a = a->next)
-        if (hostname_isequal(name, a->alias) )
-          {
-            log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
-            strcpy(name, a->target);
-            if (!strchr(name, '.'))
-              {
-                strcat(name, ".");
-                strcat(name, zone->domain);
-              }
-            found = 1;
-            if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
-                                    daemon->auth_ttl, &nameoffset,
-                                    T_CNAME, C_IN, "d", name))
-              anscount++;
-            
-            goto cname_restart;
-          }
-
       if (!cut)
        {
          nxdomain = 0;
@@ -512,8 +513,62 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
              } while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
        }
       
-      if (!found)
-       log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
+      /* Only supply CNAME if no record for any type is known. */
+      if (nxdomain)
+       {
+         /* Check for possible wildcard match against *.domain 
+            return length of match, to get longest.
+            Note that if return length of wildcard section, so
+            we match b.simon to _both_ *.simon and b.simon
+            but return a longer (better) match to b.simon.
+         */  
+         for (wclen = 0, candidate = NULL, a = daemon->cnames; a; a = a->next)
+           if (a->alias[0] == '*')
+             {
+               char *test = name;
+               
+               while ((test = strchr(test+1, '.')))
+                 {
+                   if (hostname_isequal(test, &(a->alias[1])))
+                     {
+                       if (strlen(test) > wclen && !cname_wildcard)
+                         {
+                           wclen = strlen(test);
+                           candidate = a;
+                           cname_wildcard = 1;
+                         }
+                       break;
+                     }
+                 }
+               
+             }
+           else if (hostname_isequal(a->alias, name) && strlen(a->alias) > wclen)
+             {
+               /* Simple case, no wildcard */
+               wclen = strlen(a->alias);
+               candidate = a;
+             }
+         
+         if (candidate)
+           {
+             log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
+             strcpy(name, candidate->target);
+             if (!strchr(name, '.'))
+               {
+                 strcat(name, ".");
+                 strcat(name, zone->domain);
+               }
+             found = 1;
+             if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
+                                     daemon->auth_ttl, &nameoffset,
+                                     T_CNAME, C_IN, "d", name))
+               anscount++;
+             
+             goto cname_restart;
+           }
+
+         log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
+       }
       
     }
   
@@ -537,12 +592,12 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
              char *p = name;
              
              if (subnet->prefixlen >= 24)
-               p += sprintf(p, "%d.", a & 0xff);
+               p += sprintf(p, "%u.", a & 0xff);
              a = a >> 8;
              if (subnet->prefixlen >= 16 )
-               p += sprintf(p, "%d.", a & 0xff);
+               p += sprintf(p, "%u.", a & 0xff);
              a = a >> 8;
-             p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
+             p += sprintf(p, "%u.in-addr.arpa", a & 0xff);
              
            }
 #ifdef HAVE_IPV6
@@ -805,7 +860,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
       header->hb4 &= ~HB4_RA;
     }
 
-  /* authoritive */
+  /* authoritative */
   if (auth)
     header->hb3 |= HB3_AA;
   
@@ -820,6 +875,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
   header->ancount = htons(anscount);
   header->nscount = htons(authcount);
   header->arcount = htons(0);
+
+  /* Advertise our packet size limit in our reply */
+  if (have_pseudoheader)
+    return add_pseudoheader(header,  ansp - (unsigned char *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
+
   return ansp - (unsigned char *)header;
 }
   
index c8f5eae..72f0575 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -25,7 +25,7 @@ static void blockdata_expand(int n)
 {
   struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
   
-  if (n > 0 && new)
+  if (new)
     {
       int i;
       
@@ -49,7 +49,7 @@ void blockdata_init(void)
 
   /* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */  
   if (option_bool(OPT_DNSSEC_VALID))
-    blockdata_expand((daemon->cachesize * 100) / sizeof(struct blockdata));
+    blockdata_expand(daemon->cachesize);
 }
 
 void blockdata_report(void)
@@ -100,6 +100,7 @@ struct blockdata *blockdata_alloc(char *data, size_t len)
   return ret;
 }
 
+
 void blockdata_free(struct blockdata *blocks)
 {
   struct blockdata *tmp;
index a066641..49a11bf 100644 (file)
--- a/src/bpf.c
+++ b/src/bpf.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -20,7 +20,9 @@
 #include <ifaddrs.h>
 
 #include <sys/param.h>
+#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
 #include <sys/sysctl.h>
+#endif
 #include <net/if.h>
 #include <net/route.h>
 #include <net/if_dl.h>
@@ -103,7 +105,7 @@ int arp_enumerate(void *parm, int (*callback)())
 int iface_enumerate(int family, void *parm, int (*callback)())
 {
   struct ifaddrs *head, *addrs;
-  int errsav, fd = -1, ret = 0;
+  int errsave, fd = -1, ret = 0;
 
   if (family == AF_UNSPEC)
 #if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
@@ -235,11 +237,11 @@ int iface_enumerate(int family, void *parm, int (*callback)())
   ret = 1;
 
  err:
-  errsav = errno;
+  errsave = errno;
   freeifaddrs(head); 
   if (fd != -1)
     close(fd);
-  errno = errsav;
+  errno = errsave;
 
   return ret;
 }
index 178d654..8b1b560 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -45,6 +45,7 @@ static const struct {
   { 24,  "SIG" },
   { 25,  "KEY" },
   { 28,  "AAAA" },
+  { 29,  "LOC" },
   { 33,  "SRV" },
   { 35,  "NAPTR" },
   { 36,  "KX" },
@@ -57,6 +58,10 @@ static const struct {
   { 47,  "NSEC" },
   { 48,  "DNSKEY" },
   { 50,  "NSEC3" },
+  { 51,  "NSEC3PARAM" },
+  { 52,  "TLSA" },
+  { 53,  "SMIMEA" },
+  { 55,  "HIP" },
   { 249, "TKEY" },
   { 250, "TSIG" },
   { 251, "IXFR" },
@@ -189,12 +194,7 @@ static void cache_hash(struct crec *crecp)
 static void cache_blockdata_free(struct crec *crecp)
 {
   if (crecp->flags & F_DNSKEY)
-    {
-      if (crecp->flags & F_DS)
-       blockdata_free(crecp->addr.sig.keydata);
-      else
-       blockdata_free(crecp->addr.key.keydata);
-    }
+    blockdata_free(crecp->addr.key.keydata);
   else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG))
     blockdata_free(crecp->addr.ds.keydata);
 }
@@ -369,13 +369,8 @@ static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t no
                }
              
 #ifdef HAVE_DNSSEC
-             /* Deletion has to be class-sensitive for DS, DNSKEY, RRSIG, also 
-                type-covered sensitive for  RRSIG */
-             if ((flags & (F_DNSKEY | F_DS)) &&
-                 (flags & (F_DNSKEY | F_DS)) == (crecp->flags & (F_DNSKEY | F_DS)) &&
-                 crecp->uid == addr->addr.dnssec.class &&
-                 (!((flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY)) || 
-                  crecp->addr.sig.type_covered == addr->addr.dnssec.type))
+             /* Deletion has to be class-sensitive for DS and DNSKEY */
+             if ((flags & crecp->flags & (F_DNSKEY | F_DS)) && crecp->uid == addr->addr.dnssec.class)
                {
                  if (crecp->flags & F_CONFIG)
                    return crecp;
@@ -481,7 +476,7 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
         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 | F_IPV6)) && (flags & F_FORWARD) && addr)
        {
          if ((flags & F_IPV4) && (new->flags & F_IPV4) &&
              new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr)
@@ -532,13 +527,9 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
            struct all_addr free_addr = new->addr.addr;;
 
 #ifdef HAVE_DNSSEC
-           /* For DNSSEC records, addr holds class and type_covered for RRSIG */
+           /* For DNSSEC records, addr holds class. */
            if (new->flags & (F_DS | F_DNSKEY))
-             {
-               free_addr.addr.dnssec.class = new->uid;
-               if ((new->flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY))
-                 free_addr.addr.dnssec.type = new->addr.sig.type_covered;
-             }
+             free_addr.addr.dnssec.class = new->uid;
 #endif
            
            free_avail = 1; /* Must be free space now. */
@@ -653,9 +644,6 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
          if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp))
            {
              if ((crecp->flags & F_FORWARD) && 
-#ifdef HAVE_DNSSEC
-                 (((crecp->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) || (prot & F_NSIGMATCH)) &&
-#endif
                  (crecp->flags & prot) &&
                  hostname_isequal(cache_get_name(crecp), name))
                {
@@ -713,9 +701,6 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
 
   if (ans && 
       (ans->flags & F_FORWARD) &&
-#ifdef HAVE_DNSSEC
-      (((ans->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) || (prot & F_NSIGMATCH)) &&
-#endif
       (ans->flags & prot) &&     
       hostname_isequal(cache_get_name(ans), name))
     return ans;
@@ -794,10 +779,12 @@ static void add_hosts_cname(struct crec *target)
   struct cname *a;
   
   for (a = daemon->cnames; a; a = a->next)
-    if (hostname_isequal(cache_get_name(target), a->target) &&
+    if (a->alias[1] != '*' &&
+       hostname_isequal(cache_get_name(target), a->target) &&
        (crec = whine_malloc(sizeof(struct crec))))
       {
        crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
+       crec->ttd = a->ttl;
        crec->name.namep = a->alias;
        crec->addr.cname.target.cache = target;
        crec->addr.cname.uid = target->uid;
@@ -939,7 +926,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
   if (!f)
     {
       my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
-      return 0;
+      return cache_size;
     }
   
   eatspace(f);
@@ -1001,6 +988,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
                  strcat(cache->name.sname, ".");
                  strcat(cache->name.sname, domain_suffix);
                  cache->flags = flags;
+                 cache->ttd = daemon->local_ttl;
                  add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
                  name_count++;
                }
@@ -1008,6 +996,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
                {
                  strcpy(cache->name.sname, canon);
                  cache->flags = flags;
+                 cache->ttd = daemon->local_ttl;
                  add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
                  name_count++;
                }
@@ -1073,10 +1062,12 @@ void cache_reload(void)
   /* Add CNAMEs to interface_names to the cache */
   for (a = daemon->cnames; a; a = a->next)
     for (intr = daemon->int_names; intr; intr = intr->next)
-      if (hostname_isequal(a->target, intr->name) &&
+      if (a->alias[1] != '*' &&
+         hostname_isequal(a->target, intr->name) &&
          ((cache = whine_malloc(sizeof(struct crec)))))
        {
          cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
+         cache->ttd = a->ttl;
          cache->name.namep = a->alias;
          cache->addr.cname.target.int_name = intr;
          cache->addr.cname.uid = SRC_INTERFACE;
@@ -1091,6 +1082,7 @@ void cache_reload(void)
        (cache->addr.ds.keydata = blockdata_alloc(ds->digest, ds->digestlen)))
       {
        cache->flags = F_FORWARD | F_IMMORTAL | F_DS | F_CONFIG | F_NAMEP;
+       cache->ttd = daemon->local_ttl;
        cache->name.namep = ds->name;
        cache->addr.ds.keylen = ds->digestlen;
        cache->addr.ds.algo = ds->algo;
@@ -1115,6 +1107,7 @@ void cache_reload(void)
            (cache = whine_malloc(sizeof(struct crec))))
          {
            cache->name.namep = nl->name;
+           cache->ttd = hr->ttl;
            cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG;
            add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
          }
@@ -1123,6 +1116,7 @@ void cache_reload(void)
            (cache = whine_malloc(sizeof(struct crec))))
          {
            cache->name.namep = nl->name;
+           cache->ttd = hr->ttl;
            cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG;
            add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
          }
@@ -1190,7 +1184,8 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
   struct cname *a;
   
   for (a = daemon->cnames; a; a = a->next)
-    if (hostname_isequal(cache_get_name(target), a->target))
+    if (a->alias[1] != '*' &&
+       hostname_isequal(cache_get_name(target), a->target))
       {
        if ((aliasc = dhcp_spare))
          dhcp_spare = dhcp_spare->next;
@@ -1303,6 +1298,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
 }
 #endif
 
+#ifndef NO_ID
 int cache_make_stat(struct txt_record *t)
 { 
   static char *buff = NULL;
@@ -1398,6 +1394,7 @@ int cache_make_stat(struct txt_record *t)
   *buff = len;
   return 1;
 }
+#endif
 
 /* There can be names in the cache containing control chars, don't 
    mess up logging or open security holes. */
@@ -1472,11 +1469,7 @@ void dump_cache(time_t now)
 #ifdef HAVE_DNSSEC
            else if (cache->flags & F_DS)
              {
-               if (cache->flags & F_DNSKEY)
-                 /* RRSIG */
-                 sprintf(a, "%5u %3u %s", cache->addr.sig.keytag,
-                         cache->addr.sig.algo, querystr("", cache->addr.sig.type_covered));
-               else if (!(cache->flags & F_NEG))
+               if (!(cache->flags & F_NEG))
                  sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
                          cache->addr.ds.algo, cache->addr.ds.digest);
              }
@@ -1502,8 +1495,6 @@ void dump_cache(time_t now)
            else if (cache->flags & F_CNAME)
              t = "C";
 #ifdef HAVE_DNSSEC
-           else if ((cache->flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY))
-             t = "G"; /* DNSKEY and DS set -> RRISG */
            else if (cache->flags & F_DS)
              t = "S";
            else if (cache->flags & F_DNSKEY)
@@ -1525,7 +1516,7 @@ void dump_cache(time_t now)
            /* ctime includes trailing \n - eat it */
            *(p-1) = 0;
 #endif
-           my_syslog(LOG_INFO, daemon->namebuff);
+           my_syslog(LOG_INFO, "%s", daemon->namebuff);
          }
     }
 }
@@ -1606,7 +1597,7 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
   if (addr)
     {
       if (flags & F_KEYTAG)
-       sprintf(daemon->addrbuff, arg, addr->addr.keytag);
+       sprintf(daemon->addrbuff, arg, addr->addr.log.keytag, addr->addr.log.algo, addr->addr.log.digest);
       else
        {
 #ifdef HAVE_IPV6
index f75fe9d..ecefb87 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
 #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 TCP_BACKLOG 32  /* kernel backlog limit for TCP connections */
 #define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
 #define SAFE_PKTSZ 1280 /* "go anywhere" UDP packet size */
-#define KEYBLOCK_LEN 40 /* choose to mininise fragmentation when storing DNSSEC keys */
+#define KEYBLOCK_LEN 40 /* choose to minimise fragmentation when storing DNSSEC keys */
 #define DNSSEC_WORK 50 /* Max number of queries to validate one question */
 #define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
 #define FORWARD_TEST 50 /* try all servers every 50 queries */
 #define FORWARD_TIME 20 /* or 20 seconds */
+#define UDP_TEST_TIME 60 /* How often to reset our idea of max packet size. */
+#define SERVERS_LOGGED 30 /* Only log this many servers when logging state */
+#define LOCALS_LOGGED 8 /* Only log this many local addresses when logging state */
 #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 */
@@ -91,13 +95,13 @@ HAVE_DBUS
    servers via DBus.
 
 HAVE_IDN
-   define this if you want international domain name support.
-   NOTE: for backwards compatibility, IDN support is automatically 
-         included when internationalisation support is built, using the 
-        *-i18n makefile targets, even if HAVE_IDN is not explicitly set.
+   define this if you want international domain name 2003 support.
+   
+HAVE_LIBIDN2
+   define this if you want international domain name 2008 support.
 
 HAVE_CONNTRACK
-   define this to include code which propogates conntrack marks from
+   define this to include code which propagates conntrack marks from
    incoming DNS queries to the corresponding upstream queries. This adds
    a build-dependency on libnetfilter_conntrack, but the resulting binary will
    still run happily on a kernel without conntrack support.
@@ -119,6 +123,8 @@ HAVE_LOOP
 HAVE_INOTIFY
    use the Linux inotify facility to efficiently re-read configuration files.
 
+NO_ID
+   Don't report *.bind CHAOS info to clients, forward such requests upstream instead.
 NO_IPV6
 NO_TFTP
 NO_DHCP
@@ -127,13 +133,10 @@ NO_SCRIPT
 NO_LARGEFILE
 NO_AUTH
 NO_INOTIFY
-   these are avilable to explictly disable compile time options which would 
+   these are available to explicitly 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
    with something like "make COPTS=-DNO_SCRIPT" will do the trick.
-
-NO_NETTLE_ECC
-   Don't include the ECDSA cypher in DNSSEC validation. Needed for older Nettle versions.
 NO_GMP
    Don't use and link against libgmp, Useful if nettle is built with --enable-mini-gmp.
 
@@ -172,6 +175,7 @@ RESOLVFILE
 /* #define HAVE_LUASCRIPT */
 /* #define HAVE_DBUS */
 /* #define HAVE_IDN */
+/* #define HAVE_LIBIDN2 */
 /* #define HAVE_CONNTRACK */
 /* #define HAVE_DNSSEC */
 
@@ -228,7 +232,7 @@ HAVE_SOCKADDR_SA_LEN
    defined if struct sockaddr has sa_len field (*BSD) 
 */
 
-/* Must preceed __linux__ since uClinux defines __linux__ too. */
+/* Must precede __linux__ since uClinux defines __linux__ too. */
 #if defined(__uClinux__)
 #define HAVE_LINUX_NETWORK
 #define HAVE_GETOPT_LONG
@@ -266,7 +270,7 @@ HAVE_SOCKADDR_SA_LEN
       defined(__DragonFly__) || \
       defined(__FreeBSD_kernel__)
 #define HAVE_BSD_NETWORK
-/* Later verions of FreeBSD have getopt_long() */
+/* Later versions of FreeBSD have getopt_long() */
 #if defined(optional_argument) && defined(required_argument)
 #   define HAVE_GETOPT_LONG
 #endif
@@ -337,7 +341,7 @@ HAVE_SOCKADDR_SA_LEN
 #define HAVE_DHCP
 #endif
 
-#if defined(NO_SCRIPT) || !defined(HAVE_DHCP) || defined(NO_FORK)
+#if defined(NO_SCRIPT) || defined(NO_FORK)
 #undef HAVE_SCRIPT
 #undef HAVE_LUASCRIPT
 #endif
@@ -364,7 +368,7 @@ HAVE_SOCKADDR_SA_LEN
 #endif
 
 /* Define a string indicating which options are in use.
-   DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */
+   DNSMASQ_COMPILE_OPTS is only defined in dnsmasq.c */
 
 #ifdef DNSMASQ_COMPILE_OPTS
 
@@ -391,10 +395,14 @@ static char *compile_opts =
 "no-"
 #endif
 "i18n "
-#if !defined(LOCALEDIR) && !defined(HAVE_IDN)
+#if defined(HAVE_LIBIDN2)
+"IDN2 "
+#else
+ #if !defined(HAVE_IDN)
 "no-"
-#endif 
-"IDN "
+ #endif 
+"IDN " 
+#endif
 #ifndef HAVE_DHCP
 "no-"
 #endif
@@ -404,14 +412,14 @@ static char *compile_opts =
      "no-"
 #  endif  
      "DHCPv6 "
-#  if !defined(HAVE_SCRIPT)
+#endif
+#if !defined(HAVE_SCRIPT)
      "no-scripts "
-#  else
-#    if !defined(HAVE_LUASCRIPT)
-       "no-"
-#    endif
-     "Lua "
+#else
+#  if !defined(HAVE_LUASCRIPT)
+     "no-"
 #  endif
+     "Lua "
 #endif
 #ifndef HAVE_TFTP
 "no-"
@@ -433,6 +441,9 @@ static char *compile_opts =
 "no-"
 #endif
 "DNSSEC "
+#ifdef NO_ID
+"no-ID "
+#endif
 #ifndef HAVE_LOOP
 "no-"
 #endif
index 0fa2da9..2929f8c 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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/crypto.c b/src/crypto.c
new file mode 100644 (file)
index 0000000..ebb871e
--- /dev/null
@@ -0,0 +1,460 @@
+/* dnsmasq is Copyright (c) 2000-2018 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"
+
+#ifdef HAVE_DNSSEC
+
+#include <nettle/rsa.h>
+#include <nettle/dsa.h>
+#include <nettle/ecdsa.h>
+#include <nettle/ecc-curve.h>
+#include <nettle/eddsa.h>
+#include <nettle/nettle-meta.h>
+#include <nettle/bignum.h>
+
+/* Implement a "hash-function" to the nettle API, which simply returns
+   the input data, concatenated into a single, statically maintained, buffer.
+
+   Used for the EdDSA sigs, which operate on the whole message, rather 
+   than a digest. */
+
+struct null_hash_digest
+{
+  uint8_t *buff;
+  size_t len;
+};
+
+struct null_hash_ctx
+{
+  size_t len;
+};
+
+static size_t null_hash_buff_sz = 0;
+static uint8_t *null_hash_buff = NULL;
+#define BUFF_INCR 128
+
+static void null_hash_init(void *ctx)
+{
+  ((struct null_hash_ctx *)ctx)->len = 0;
+}
+
+static void null_hash_update(void *ctxv, size_t length, const uint8_t *src)
+{
+  struct null_hash_ctx *ctx = ctxv;
+  size_t new_len = ctx->len + length;
+  
+  if (new_len > null_hash_buff_sz)
+    {
+      uint8_t *new;
+      
+      if (!(new = whine_malloc(new_len + BUFF_INCR)))
+       return;
+
+      if (null_hash_buff)
+       {
+         if (ctx->len != 0)
+           memcpy(new, null_hash_buff, ctx->len);
+         free(null_hash_buff);
+       }
+      
+      null_hash_buff_sz = new_len + BUFF_INCR;
+      null_hash_buff = new;
+    }
+
+  memcpy(null_hash_buff + ctx->len, src, length);
+  ctx->len += length;
+}
+
+static void null_hash_digest(void *ctx, size_t length, uint8_t *dst)
+{
+  (void)length;
+  
+  ((struct null_hash_digest *)dst)->buff = null_hash_buff;
+  ((struct null_hash_digest *)dst)->len = ((struct null_hash_ctx *)ctx)->len;
+}
+
+static struct nettle_hash null_hash = {
+  "null_hash",
+  sizeof(struct null_hash_ctx),
+  sizeof(struct null_hash_digest),
+  0,
+  (nettle_hash_init_func *) null_hash_init,
+  (nettle_hash_update_func *) null_hash_update,
+  (nettle_hash_digest_func *) null_hash_digest
+};
+
+/* Find pointer to correct hash function in nettle library */
+const struct nettle_hash *hash_find(char *name)
+{
+  if (!name)
+    return NULL;
+  
+  /* We provide a "null" hash which returns the input data as digest. */
+  if (strcmp(null_hash.name, name) == 0)
+    return &null_hash;
+
+  /* libnettle >= 3.4 provides nettle_lookup_hash() which avoids nasty ABI
+     incompatibilities if sizeof(nettle_hashes) changes between library
+     versions. It also #defines nettle_hashes, so use that to tell
+     if we have the new facilities. */
+  
+#ifdef nettle_hashes
+  return nettle_lookup_hash(name);
+#else
+  {
+    int i;
+
+    for (i = 0; nettle_hashes[i]; i++)
+      if (strcmp(nettle_hashes[i]->name, name) == 0)
+       return nettle_hashes[i];
+  }
+  
+  return NULL;
+#endif
+}
+
+/* expand ctx and digest memory allocations if necessary and init hash function */
+int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
+{
+  static void *ctx = NULL;
+  static unsigned char *digest = NULL;
+  static unsigned int ctx_sz = 0;
+  static unsigned int digest_sz = 0;
+
+  void *new;
+
+  if (ctx_sz < hash->context_size)
+    {
+      if (!(new = whine_malloc(hash->context_size)))
+       return 0;
+      if (ctx)
+       free(ctx);
+      ctx = new;
+      ctx_sz = hash->context_size;
+    }
+  
+  if (digest_sz < hash->digest_size)
+    {
+      if (!(new = whine_malloc(hash->digest_size)))
+       return 0;
+      if (digest)
+       free(digest);
+      digest = new;
+      digest_sz = hash->digest_size;
+    }
+
+  *ctxp = ctx;
+  *digestp = digest;
+
+  hash->init(ctx);
+
+  return 1;
+}
+  
+static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
+                             unsigned char *digest, size_t digest_len, int algo)
+{
+  unsigned char *p;
+  size_t exp_len;
+  
+  static struct rsa_public_key *key = NULL;
+  static mpz_t sig_mpz;
+
+  (void)digest_len;
+  
+  if (key == NULL)
+    {
+      if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
+       return 0;
+      
+      nettle_rsa_public_key_init(key);
+      mpz_init(sig_mpz);
+    }
+  
+  if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
+    return 0;
+  
+  key_len--;
+  if ((exp_len = *p++) == 0)
+    {
+      GETSHORT(exp_len, p);
+      key_len -= 2;
+    }
+  
+  if (exp_len >= key_len)
+    return 0;
+  
+  key->size =  key_len - exp_len;
+  mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
+  mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
+
+  mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
+  
+  switch (algo)
+    {
+    case 1:
+      return nettle_rsa_md5_verify_digest(key, digest, sig_mpz);
+    case 5: case 7:
+      return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
+    case 8:
+      return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
+    case 10:
+      return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
+    }
+
+  return 0;
+}  
+
+static int dnsmasq_dsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
+                             unsigned char *digest, size_t digest_len, int algo)
+{
+  unsigned char *p;
+  unsigned int t;
+
+  static mpz_t y;
+  static struct dsa_params *params = NULL;
+  static struct dsa_signature *sig_struct;
+  
+  (void)digest_len;
+
+  if (params == NULL)
+    {
+      if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) || 
+         !(params = whine_malloc(sizeof(struct dsa_params)))) 
+       return 0;
+      
+      mpz_init(y);
+      nettle_dsa_params_init(params);
+      nettle_dsa_signature_init(sig_struct);
+    }
+  
+  if ((sig_len < 41) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
+    return 0;
+  
+  t = *p++;
+  
+  if (key_len < (213 + (t * 24)))
+    return 0;
+  
+  mpz_import(params->q, 20, 1, 1, 0, 0, p); p += 20;
+  mpz_import(params->p, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
+  mpz_import(params->g, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
+  mpz_import(y, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
+  
+  mpz_import(sig_struct->r, 20, 1, 1, 0, 0, sig+1);
+  mpz_import(sig_struct->s, 20, 1, 1, 0, 0, sig+21);
+  
+  (void)algo;
+  
+  return nettle_dsa_verify(params, y, digest_len, digest, sig_struct);
+} 
+static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len, 
+                               unsigned char *sig, size_t sig_len,
+                               unsigned char *digest, size_t digest_len, int algo)
+{
+  unsigned char *p;
+  unsigned int t;
+  struct ecc_point *key;
+
+  static struct ecc_point *key_256 = NULL, *key_384 = NULL;
+  static mpz_t x, y;
+  static struct dsa_signature *sig_struct;
+  
+  if (!sig_struct)
+    {
+      if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
+       return 0;
+      
+      nettle_dsa_signature_init(sig_struct);
+      mpz_init(x);
+      mpz_init(y);
+    }
+  
+  switch (algo)
+    {
+    case 13:
+      if (!key_256)
+       {
+         if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
+           return 0;
+         
+         nettle_ecc_point_init(key_256, &nettle_secp_256r1);
+       }
+      
+      key = key_256;
+      t = 32;
+      break;
+      
+    case 14:
+      if (!key_384)
+       {
+         if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
+           return 0;
+         
+         nettle_ecc_point_init(key_384, &nettle_secp_384r1);
+       }
+      
+      key = key_384;
+      t = 48;
+      break;
+        
+    default:
+      return 0;
+    }
+  
+  if (sig_len != 2*t || key_len != 2*t ||
+      !(p = blockdata_retrieve(key_data, key_len, NULL)))
+    return 0;
+  
+  mpz_import(x, t , 1, 1, 0, 0, p);
+  mpz_import(y, t , 1, 1, 0, 0, p + t);
+
+  if (!ecc_point_set(key, x, y))
+    return 0;
+  
+  mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
+  mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
+  
+  return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
+}
+
+static int dnsmasq_eddsa_verify(struct blockdata *key_data, unsigned int key_len, 
+                               unsigned char *sig, size_t sig_len,
+                               unsigned char *digest, size_t digest_len, int algo)
+{
+  unsigned char *p;
+   
+  if (key_len != ED25519_KEY_SIZE ||
+      sig_len != ED25519_SIGNATURE_SIZE ||
+      digest_len != sizeof(struct null_hash_digest) ||
+      !(p = blockdata_retrieve(key_data, key_len, NULL)))
+    return 0;
+  
+  /* The "digest" returned by the null_hash function is simply a struct null_hash_digest
+     which has a pointer to the actual data and a length, because the buffer
+     may need to be extended during "hashing". */
+  
+  switch (algo)
+    {
+    case 15:
+      return ed25519_sha512_verify(p,
+                                  ((struct null_hash_digest *)digest)->len,
+                                  ((struct null_hash_digest *)digest)->buff,
+                                  sig);
+    case 16:
+      /* Ed448 when available */
+      return 0;
+    }
+
+  return 0;
+}
+
+static int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
+                            unsigned char *digest, size_t digest_len, int algo)
+{
+    
+  /* Enure at runtime that we have support for this digest */
+  if (!hash_find(algo_digest_name(algo)))
+    return NULL;
+  
+  /* This switch defines which sig algorithms we support, can't introspect Nettle for that. */
+  switch (algo)
+    {
+    case 1: case 5: case 7: case 8: case 10:
+      return dnsmasq_rsa_verify;
+      
+    case 3: case 6: 
+      return dnsmasq_dsa_verify;
+    
+    case 13: case 14:
+      return dnsmasq_ecdsa_verify;
+
+    case 15: case 16:
+      return dnsmasq_eddsa_verify;
+    }
+  
+  return NULL;
+}
+
+int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
+          unsigned char *digest, size_t digest_len, int algo)
+{
+
+  int (*func)(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
+             unsigned char *digest, size_t digest_len, int algo);
+  
+  func = verify_func(algo);
+  
+  if (!func)
+    return 0;
+
+  return (*func)(key_data, key_len, sig, sig_len, digest, digest_len, algo);
+}
+
+/* Note the ds_digest_name(), algo_digest_name() and nsec3_digest_name()
+   define which algo numbers we support. If algo_digest_name() returns
+   non-NULL for an algorithm number, we assume that algorithm is 
+   supported by verify(). */
+
+/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
+char *ds_digest_name(int digest)
+{
+  switch (digest)
+    {
+    case 1: return "sha1";
+    case 2: return "sha256";
+    case 3: return "gosthash94";
+    case 4: return "sha384";
+    default: return NULL;
+    }
+}
+/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
+char *algo_digest_name(int algo)
+{
+  switch (algo)
+    {
+    case 1: return NULL;          /* RSA/MD5 - Must Not Implement.  RFC 6944 para 2.3. */
+    case 2: return NULL;          /* Diffie-Hellman */
+    case 3: return "sha1";        /* DSA/SHA1 */ 
+    case 5: return "sha1";        /* RSA/SHA1 */
+    case 6: return "sha1";        /* DSA-NSEC3-SHA1 */
+    case 7: return "sha1";        /* RSASHA1-NSEC3-SHA1 */
+    case 8: return "sha256";      /* RSA/SHA-256 */
+    case 10: return "sha512";     /* RSA/SHA-512 */
+    case 12: return NULL;         /* ECC-GOST */
+    case 13: return "sha256";     /* ECDSAP256SHA256 */
+    case 14: return "sha384";     /* ECDSAP384SHA384 */        
+    case 15: return "null_hash";  /* ED25519 */
+    case 16: return NULL;         /* ED448 */
+    default: return NULL;
+    }
+}
+  
+/* http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
+char *nsec3_digest_name(int digest)
+{
+  switch (digest)
+    {
+    case 1: return "sha1";
+    default: return NULL;
+    }
+}
+
+#endif
index 3555f49..6a78b20 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -549,17 +549,16 @@ static DBusMessage *dbus_add_lease(DBusMessage* message)
     return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
                                         "Invalid IP address '%s'", ipaddr);
    
-  hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL,
-                    &hw_type);
+  hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
   if (hw_type == 0 && hw_len != 0)
     hw_type = ARPHRD_ETHER;
-
-    lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
+  
+  lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
                    clid_len, now, 0);
   lease_set_expires(lease, expires, now);
   if (hostname_len != 0)
     lease_set_hostname(lease, hostname, 0, get_domain(lease->addr), NULL);
-    
+  
   lease_update_file(now);
   lease_update_dns(0);
 
index bc48f41..d9719d1 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
 
 void dhcp_common_init(void)
 {
-    /* These each hold a DHCP option max size 255
-       and get a terminating zero added */
-  daemon->dhcp_buff = safe_malloc(256);
-  daemon->dhcp_buff2 = safe_malloc(256); 
-  daemon->dhcp_buff3 = safe_malloc(256);
+  /* These each hold a DHCP option max size 255
+     and get a terminating zero added */
+  daemon->dhcp_buff = safe_malloc(DHCP_BUFF_SZ);
+  daemon->dhcp_buff2 = safe_malloc(DHCP_BUFF_SZ); 
+  daemon->dhcp_buff3 = safe_malloc(DHCP_BUFF_SZ);
   
   /* dhcp_packet is used by v4 and v6, outpacket only by v6 
      sizeof(struct dhcp_packet) is as good an initial size as any,
@@ -485,11 +485,8 @@ char *whichdevice(void)
  
 void  bindtodevice(char *device, int fd)
 {
-  struct ifreq ifr;
-  
-  strcpy(ifr.ifr_name, device);
   /* only allowed by root. */
-  if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
+  if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, IFNAMSIZ) == -1 &&
       errno != EPERM)
     die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
 }
@@ -599,7 +596,7 @@ static const struct opttab_t opttab6[] = {
   { "sntp-server", 31,  OT_ADDR_LIST },
   { "information-refresh-time", 32, OT_TIME },
   { "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
-  { "ntp-server", 56,  OT_ADDR_LIST },
+  { "ntp-server", 56,  0 },
   { "bootfile-url", 59, OT_NAME },
   { "bootfile-param", 60, OT_CSTRING },
   { NULL, 0, 0 }
@@ -855,14 +852,14 @@ void log_context(int family, struct dhcp_context *context)
       if (context->flags & CONTEXT_RA_STATELESS)
        {
          if (context->flags & CONTEXT_TEMPLATE)
-           strncpy(daemon->dhcp_buff, context->template_interface, 256);
+           strncpy(daemon->dhcp_buff, context->template_interface, DHCP_BUFF_SZ);
          else
            strcpy(daemon->dhcp_buff, daemon->addrbuff);
        }
       else 
 #endif
-       inet_ntop(family, start, daemon->dhcp_buff, 256);
-      inet_ntop(family, end, daemon->dhcp_buff3, 256);
+       inet_ntop(family, start, daemon->dhcp_buff, DHCP_BUFF_SZ);
+      inet_ntop(family, end, daemon->dhcp_buff3, DHCP_BUFF_SZ);
       my_syslog(MS_DHCP | LOG_INFO, 
                (context->flags & CONTEXT_RA_STATELESS) ? 
                _("%s stateless on %s%.0s%.0s%s") :
index 701b6cb..a4a3535 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
 #define DHCP_CLIENT_ALTPORT 1068
 #define PXE_PORT 4011
 
+/* These each hold a DHCP option max size 255
+   and get a terminating zero added */
+#define DHCP_BUFF_SZ 256
+
 #define BOOTREQUEST              1
 #define BOOTREPLY                2
 #define DHCP_COOKIE              0x63825363
index e6fceb1..5a8daec 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -67,9 +67,9 @@ static int make_fd(int port)
       setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1)  
     die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET);
   
-  /* When bind-interfaces is set, there might be more than one dnmsasq
+  /* When bind-interfaces is set, there might be more than one dnsmasq
      instance binding port 67. That's OK if they serve different networks.
-     Need to set REUSEADDR|REUSEPORT to make this posible.
+     Need to set REUSEADDR|REUSEPORT to make this possible.
      Handle the case that REUSEPORT is defined, but the kernel doesn't 
      support it. This handles the introduction of REUSEPORT on Linux. */
   if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
@@ -145,11 +145,14 @@ void dhcp_packet(time_t now, int pxe_fd)
   struct cmsghdr *cmptr;
   struct iovec iov;
   ssize_t sz; 
-  int iface_index = 0, unicast_dest = 0, is_inform = 0;
+  int iface_index = 0, unicast_dest = 0, is_inform = 0, loopback = 0;
+  int rcvd_iface_index;
   struct in_addr iface_addr;
   struct iface_param parm;
+  time_t recvtime = now;
 #ifdef HAVE_LINUX_NETWORK
   struct arpreq arp_req;
+  struct timeval tv;
 #endif
   
   union {
@@ -176,6 +179,9 @@ void dhcp_packet(time_t now, int pxe_fd)
     return;
     
   #if defined (HAVE_LINUX_NETWORK)
+  if (ioctl(fd, SIOCGSTAMP, &tv) == 0)
+    recvtime = tv.tv_sec;
+
   if (msg.msg_controllen >= sizeof(struct cmsghdr))
     for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
       if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
@@ -217,9 +223,13 @@ void dhcp_packet(time_t now, int pxe_fd)
        }
 #endif
        
-  if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
+  if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name) ||
+      ioctl(daemon->dhcpfd, SIOCGIFFLAGS, &ifr) != 0)
     return;
-
+  
+  mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
+  loopback = !mess->giaddr.s_addr && (ifr.ifr_flags & IFF_LOOPBACK);
+  
 #ifdef HAVE_LINUX_NETWORK
   /* ARP fiddling uses original interface even if we pretend to use a different one. */
   strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
@@ -230,6 +240,7 @@ void dhcp_packet(time_t now, int pxe_fd)
      --bridge-interface option), change ifr.ifr_name so that we look
      for DHCP contexts associated with the aliased interface instead
      of with the aliasing one. */
+  rcvd_iface_index = iface_index;
   for (bridge = daemon->bridges; bridge; bridge = bridge->next)
     {
       for (alias = bridge->alias; alias; alias = alias->next)
@@ -262,8 +273,8 @@ void dhcp_packet(time_t now, int pxe_fd)
   if ((relay = relay_reply4((struct dhcp_packet *)daemon->dhcp_packet.iov_base, ifr.ifr_name)))
     {
       /* Reply from server, using us as relay. */
-      iface_index = relay->iface_index;
-      if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
+      rcvd_iface_index = relay->iface_index;
+      if (!indextoname(daemon->dhcpfd, rcvd_iface_index, ifr.ifr_name))
        return;
       is_relay_reply = 1; 
       iov.iov_len = sz;
@@ -278,7 +289,8 @@ void dhcp_packet(time_t now, int pxe_fd)
        iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
       else
        {
-         my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
+         if (iface_check(AF_INET, NULL, ifr.ifr_name, NULL))
+           my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
          return;
        }
       
@@ -323,7 +335,7 @@ void dhcp_packet(time_t now, int pxe_fd)
 
       /* We're relaying this request */
       if  (parm.relay_local.s_addr != 0 &&
-          relay_upstream4(parm.relay, (struct dhcp_packet *)daemon->dhcp_packet.iov_base, (size_t)sz, iface_index))
+          relay_upstream4(parm.relay, mess, (size_t)sz, iface_index))
        return;
 
       /* May have configured relay, but not DHCP server */
@@ -332,14 +344,14 @@ void dhcp_packet(time_t now, int pxe_fd)
 
       lease_prune(NULL, now); /* lose any expired leases */
       iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz, 
-                              now, unicast_dest, &is_inform, pxe_fd, iface_addr);
+                              now, unicast_dest, loopback, &is_inform, pxe_fd, iface_addr, recvtime);
       lease_update_file(now);
       lease_update_dns(0);
       
       if (iov.iov_len == 0)
        return;
     }
-  
+
   msg.msg_name = &dest;
   msg.msg_namelen = sizeof(dest);
   msg.msg_control = NULL;
@@ -387,7 +399,7 @@ void dhcp_packet(time_t now, int pxe_fd)
       msg.msg_controllen = sizeof(control_u);
       cmptr = CMSG_FIRSTHDR(&msg);
       pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
-      pkt->ipi_ifindex = iface_index;
+      pkt->ipi_ifindex = rcvd_iface_index;
       pkt->ipi_spec_dst.s_addr = 0;
       msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
       cmptr->cmsg_level = IPPROTO_IP;
@@ -452,8 +464,13 @@ void dhcp_packet(time_t now, int pxe_fd)
 #endif
   
   while(retry_send(sendmsg(fd, &msg, 0)));
+
+  /* This can fail when, eg, iptables DROPS destination 255.255.255.255 */
+  if (errno != 0)
+    my_syslog(MS_DHCP | LOG_WARNING, _("Error sending DHCP packet to %s: %s"),
+             inet_ntoa(dest.sin_addr), strerror(errno));
 }
+
 /* check against secondary interface addresses */
 static int check_listen_addrs(struct in_addr local, int if_index, char *label,
                              struct in_addr netmask, struct in_addr broadcast, void *vparam)
@@ -488,7 +505,7 @@ static int check_listen_addrs(struct in_addr local, int if_index, char *label,
    3) Fills in local (this host) and router (this host or relay) addresses.
    4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current.
 
-   Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
+   Note that the current chain may be superseded later for configured hosts or those coming via gateways. */
 
 static int complete_context(struct in_addr local, int if_index, char *label,
                            struct in_addr netmask, struct in_addr broadcast, void *vparam)
@@ -588,7 +605,7 @@ struct dhcp_context *narrow_context(struct dhcp_context *context,
 {
   /* We start of with a set of possible contexts, all on the current physical interface.
      These are chained on ->current.
-     Here we have an address, and return the actual context correponding to that
+     Here we have an address, and return the actual context corresponding to that
      address. Note that none may fit, if the address came a dhcp-host and is outside
      any dhcp-range. In that case we return a static range if possible, or failing that,
      any context on the correct subnet. (If there's more than one, this is a dodgy 
@@ -630,9 +647,69 @@ struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct i
   return NULL;
 }
 
+/* Check if and address is in use by sending ICMP ping.
+   This wrapper handles a cache and load-limiting.
+   Return is NULL is address in use, or a pointer to a cache entry
+   recording that it isn't. */
+struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, unsigned int hash, int loopback)
+{
+  static struct ping_result dummy;
+  struct ping_result *r, *victim = NULL;
+  int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
+                               ((float)PING_WAIT)));
+
+  /* check if we failed to ping addr sometime in the last
+     PING_CACHE_TIME seconds. If so, assume the same situation still exists.
+     This avoids problems when a stupid client bangs
+     on us repeatedly. As a final check, if we did more
+     than 60% of the possible ping checks in the last 
+     PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
+  for (count = 0, r = daemon->ping_results; r; r = r->next)
+    if (difftime(now, r->time) >  (float)PING_CACHE_TIME)
+      victim = r; /* old record */
+    else 
+      {
+       count++;
+       if (r->addr.s_addr == addr.s_addr)
+         return r;
+      }
+  
+  /* didn't find cached entry */
+  if ((count >= max) || option_bool(OPT_NO_PING) || loopback)
+    {
+      /* overloaded, or configured not to check, loopback interface, return "not in use" */
+      dummy.hash = 0;
+      return &dummy;
+    }
+  else if (icmp_ping(addr))
+    return NULL; /* address in use. */
+  else
+    {
+      /* at this point victim may hold an expired record */
+      if (!victim)
+       {
+         if ((victim = whine_malloc(sizeof(struct ping_result))))
+           {
+             victim->next = daemon->ping_results;
+             daemon->ping_results = victim;
+           }
+       }
+      
+      /* record that this address is OK for 30s 
+        without more ping checks */
+      if (victim)
+       {
+         victim->addr = addr;
+         victim->time = now;
+         victim->hash = hash;
+       }
+      return victim;
+    }
+}
+
 int address_allocate(struct dhcp_context *context,
                     struct in_addr *addrp, unsigned char *hwaddr, int hw_len, 
-                    struct dhcp_netid *netids, time_t now)   
+                    struct dhcp_netid *netids, time_t now, int loopback)   
 {
   /* Find a free address: exclude anything in use and anything allocated to
      a particular hwaddr/clientid/hostname in our configuration.
@@ -646,7 +723,11 @@ int address_allocate(struct dhcp_context *context,
   /* hash hwaddr: use the SDBM hashing algorithm.  Seems to give good
      dispersal even with similarly-valued "strings". */ 
   for (j = 0, i = 0; i < hw_len; i++)
-    j += hwaddr[i] + (j << 6) + (j << 16) - j;
+    j = hwaddr[i] + (j << 6) + (j << 16) - j;
+
+  /* j == 0 is marker */
+  if (j == 0)
+    j = 1;
   
   for (pass = 0; pass <= 1; pass++)
     for (c = context; c; c = c->current)
@@ -684,69 +765,27 @@ int address_allocate(struct dhcp_context *context,
                (!IN_CLASSC(ntohl(addr.s_addr)) || 
                 ((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
              {
-               struct ping_result *r, *victim = NULL;
-               int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
-                                             ((float)PING_WAIT)));
+               struct ping_result *r;
                
-               *addrp = addr;
-
-               /* check if we failed to ping addr sometime in the last
-                  PING_CACHE_TIME seconds. If so, assume the same situation still exists.
-                  This avoids problems when a stupid client bangs
-                  on us repeatedly. As a final check, if we did more
-                  than 60% of the possible ping checks in the last 
-                  PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
-               for (count = 0, r = daemon->ping_results; r; r = r->next)
-                 if (difftime(now, r->time) >  (float)PING_CACHE_TIME)
-                   victim = r; /* old record */
-                 else 
-                   {
-                     count++;
-                     if (r->addr.s_addr == addr.s_addr)
-                       {
-                         /* consec-ip mode: we offered this address for another client
-                            (different hash) recently, don't offer it to this one. */
-                         if (option_bool(OPT_CONSEC_ADDR) && r->hash != j)
-                           break;
-                         
-                         return 1;
-                       }
-                   }
-
-               if (!r) 
-                 {
-                   if ((count < max) && !option_bool(OPT_NO_PING) && icmp_ping(addr))
-                     {
-                       /* address in use: perturb address selection so that we are
-                          less likely to try this address again. */
-                       if (!option_bool(OPT_CONSEC_ADDR))
-                         c->addr_epoch++;
-                     }
-                   else
+               if ((r = do_icmp_ping(now, addr, j, loopback)))
+                 {
+                   /* consec-ip mode: we offered this address for another client
+                      (different hash) recently, don't offer it to this one. */
+                   if (!option_bool(OPT_CONSEC_ADDR) || r->hash == j)
                      {
-                       /* at this point victim may hold an expired record */
-                       if (!victim)
-                         {
-                           if ((victim = whine_malloc(sizeof(struct ping_result))))
-                             {
-                               victim->next = daemon->ping_results;
-                               daemon->ping_results = victim;
-                             }
-                         }
-                       
-                       /* record that this address is OK for 30s 
-                          without more ping checks */
-                       if (victim)
-                         {
-                           victim->addr = addr;
-                           victim->time = now;
-                           victim->hash = j;
-                         }
+                       *addrp = addr;
                        return 1;
                      }
                  }
+               else
+                 {
+                   /* address in use: perturb address selection so that we are
+                      less likely to try this address again. */
+                   if (!option_bool(OPT_CONSEC_ADDR))
+                     c->addr_epoch++;
+                 }
              }
-
+           
            addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
            
            if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1))
index 928a2fa..fee5d28 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
index 8286ff4..0853664 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -27,17 +27,10 @@ struct iface_param {
   int ind, addr_match;
 };
 
-struct mac_param {
-  struct in6_addr *target;
-  unsigned char *mac;
-  unsigned int maclen;
-};
-
 
 static int complete_context6(struct in6_addr *local,  int prefix,
                             int scope, int if_index, int flags, 
                             unsigned int preferred, unsigned int valid, void *vparam);
-static int find_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv);
 static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm); 
 
 void dhcp6_init(void)
@@ -58,9 +51,9 @@ void dhcp6_init(void)
       !set_ipv6pktinfo(fd))
     die (_("cannot create DHCPv6 socket: %s"), NULL, EC_BADNET);
   
- /* When bind-interfaces is set, there might be more than one dnmsasq
+ /* When bind-interfaces is set, there might be more than one dnsmasq
      instance binding port 547. That's OK if they serve different networks.
-     Need to set REUSEADDR|REUSEPORT to make this posible.
+     Need to set REUSEADDR|REUSEPORT to make this possible.
      Handle the case that REUSEPORT is defined, but the kernel doesn't 
      support it. This handles the introduction of REUSEPORT on Linux. */
   if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
@@ -227,7 +220,7 @@ void dhcp6_packet(time_t now)
          inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
          
          if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
-           relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id);
+           relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id, now);
          return;
        }
       
@@ -257,16 +250,15 @@ void dhcp6_packet(time_t now)
     }
 }
 
-void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned int *maclenp, unsigned int *mactypep)
+void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned int *maclenp, unsigned int *mactypep, time_t now)
 {
-  /* Recieving a packet from a host does not populate the neighbour
+  /* Receiving a packet from a host does not populate the neighbour
      cache, so we send a neighbour discovery request if we can't 
      find the sender. Repeat a few times in case of packet loss. */
   
   struct neigh_packet neigh;
-  struct sockaddr_in6 addr;
-  struct mac_param mac_param;
-  int i;
+  union mysockaddr addr;
+  int i, maclen;
 
   neigh.type = ND_NEIGHBOR_SOLICIT;
   neigh.code = 0;
@@ -277,55 +269,31 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsi
    
   memset(&addr, 0, sizeof(addr));
 #ifdef HAVE_SOCKADDR_SA_LEN
-  addr.sin6_len = sizeof(struct sockaddr_in6);
+  addr.in6.sin6_len = sizeof(struct sockaddr_in6);
 #endif
-  addr.sin6_family = AF_INET6;
-  addr.sin6_port = htons(IPPROTO_ICMPV6);
-  addr.sin6_addr = *client;
-  addr.sin6_scope_id = iface;
-  
-  mac_param.target = client;
-  mac_param.maclen = 0;
-  mac_param.mac = mac;
+  addr.in6.sin6_family = AF_INET6;
+  addr.in6.sin6_port = htons(IPPROTO_ICMPV6);
+  addr.in6.sin6_addr = *client;
+  addr.in6.sin6_scope_id = iface;
   
   for (i = 0; i < 5; i++)
     {
       struct timespec ts;
       
-      iface_enumerate(AF_UNSPEC, &mac_param, find_mac);
-      
-      if (mac_param.maclen != 0)
+      if ((maclen = find_mac(&addr, mac, 0, now)) != 0)
        break;
-      
-      sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, (struct sockaddr *)&addr, sizeof(addr));
+         
+      sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr));
       
       ts.tv_sec = 0;
       ts.tv_nsec = 100000000; /* 100ms */
       nanosleep(&ts, NULL);
     }
 
-  *maclenp = mac_param.maclen;
+  *maclenp = maclen;
   *mactypep = ARPHRD_ETHER;
 }
     
-static int find_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
-{
-  struct mac_param *parm = parmv;
-  
-  if (family == AF_INET6 && IN6_ARE_ADDR_EQUAL(parm->target, (struct in6_addr *)addrp))
-    {
-      if (maclen <= DHCP_CHADDR_MAX)
-       {
-         parm->maclen = maclen;
-         memcpy(parm->mac, mac, maclen);
-       }
-      
-      return 0; /* found, abort */
-    }
-  
-  return 1;
-}
-
 static int complete_context6(struct in6_addr *local,  int prefix,
                             int scope, int if_index, int flags, unsigned int preferred, 
                             unsigned int valid, void *vparam)
@@ -376,7 +344,7 @@ static int complete_context6(struct in6_addr *local,  int prefix,
                    {
                      struct dhcp_context *tmp, **up;
                      
-                     /* use interface values only for contructed contexts */
+                     /* use interface values only for constructed contexts */
                      if (!(context->flags & CONTEXT_CONSTRUCTED))
                        preferred = valid = 0xffffffff;
                      else if (flags & IFACE_DEPRECATED)
@@ -452,7 +420,7 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context,  unsigned c
     j = rand64();
   else
     for (j = iaid, i = 0; i < clid_len; i++)
-      j += clid[i] + (j << 6) + (j << 16) - j;
+      j = clid[i] + (j << 6) + (j << 16) - j;
   
   for (pass = 0; pass <= plain_range ? 1 : 0; pass++)
     for (c = context; c; c = c->current)
@@ -466,7 +434,16 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context,  unsigned c
            /* seed is largest extant lease addr in this context */
            start = lease_find_max_addr6(c) + serial;
          else
-           start = addr6part(&c->start6) + ((j + c->addr_epoch) % (1 + addr6part(&c->end6) - addr6part(&c->start6)));
+           {
+             u64 range = 1 + addr6part(&c->end6) - addr6part(&c->start6);
+             u64 offset = j + c->addr_epoch;
+
+             /* don't divide by zero if range is whole 2^64 */
+             if (range != 0)
+               offset = offset % range;
+
+             start = addr6part(&c->start6) + offset;
+           }
 
          /* iterate until we find a free address. */
          addr = start;
@@ -695,7 +672,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
                  /* address went, now it's back */
                  log_context(AF_INET6, context); 
                  /* fast RAs for a while */
-                 ra_start_unsolicted(param->now, context);
+                 ra_start_unsolicited(param->now, context);
                  param->newone = 1; 
                  /* Add address to name again */
                  if (context->flags & CONTEXT_RA_NAME)
@@ -718,7 +695,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
            context->next = daemon->dhcp6;
            daemon->dhcp6 = context;
 
-           ra_start_unsolicted(param->now, context);
+           ra_start_unsolicited(param->now, context);
            /* we created a new one, need to call
               lease_update_file to get periodic functions called */
            param->newone = 1; 
@@ -766,7 +743,7 @@ void dhcp_construct_contexts(time_t now)
              /* maximum time is 2 hours, from RFC */
              if (context->saved_valid > 7200) /* 2 hours */
                context->saved_valid = 7200;
-             ra_start_unsolicted(now, context);
+             ra_start_unsolicited(now, context);
              param.newone = 1; /* include deletion */ 
              
              if (context->flags & CONTEXT_RA_NAME)
index 6cf5158..4958830 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -16,6 +16,8 @@
 
 #define NAMESERVER_PORT 53
 #define TFTP_PORT       69
+#define MIN_PORT        1024           /* first non-reserved port */
+#define MAX_PORT        65535u
 
 #define IN6ADDRSZ       16
 #define INADDRSZ        4
@@ -77,6 +79,8 @@
 
 #define EDNS0_OPTION_MAC            65001 /* dyndns.org temporary assignment */
 #define EDNS0_OPTION_CLIENT_SUBNET  8     /* IANA */
+#define EDNS0_OPTION_NOMDEVICEID    65073 /* Nominum temporary assignment */
+#define EDNS0_OPTION_NOMCPEID       65074 /* Nominum temporary assignment */
 
 struct dns_header {
   u16 id;
index 04d5758..ce44809 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -48,6 +48,7 @@ int main (int argc, char **argv)
   long i, max_fd = sysconf(_SC_OPEN_MAX);
   char *baduser = NULL;
   int log_err;
+  int chown_warn = 0;
 #if defined(HAVE_LINUX_NETWORK)
   cap_user_header_t hdr = NULL;
   cap_user_data_t data = NULL;
@@ -77,7 +78,8 @@ int main (int argc, char **argv)
   sigaction(SIGTERM, &sigact, NULL);
   sigaction(SIGALRM, &sigact, NULL);
   sigaction(SIGCHLD, &sigact, NULL);
-
+  sigaction(SIGINT, &sigact, NULL);
+  
   /* ignore SIGPIPE */
   sigact.sa_handler = SIG_IGN;
   sigaction(SIGPIPE, &sigact, NULL);
@@ -91,8 +93,11 @@ int main (int argc, char **argv)
   if (daemon->edns_pktsz < PACKETSZ)
     daemon->edns_pktsz = PACKETSZ;
 
-  daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ? 
-    daemon->edns_pktsz : DNSMASQ_PACKETSZ;
+  /* Min buffer size: we check after adding each record, so there must be 
+     memory for the largest packet, and the largest record so the
+     min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
+     This might be increased is EDNS packet size if greater than the minimum. */ 
+  daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
   daemon->packet = safe_malloc(daemon->packet_buff_sz);
   
   daemon->addrbuff = safe_malloc(ADDRSTRLEN);
@@ -115,6 +120,9 @@ int main (int argc, char **argv)
       daemon->namebuff = safe_malloc(MAXDNAME * 2);
       daemon->keyname = safe_malloc(MAXDNAME * 2);
       daemon->workspacename = safe_malloc(MAXDNAME * 2);
+      /* one char flag per possible RR in answer section (may get extended). */
+      daemon->rr_status_sz = 64;
+      daemon->rr_status = safe_malloc(daemon->rr_status_sz);
     }
 #endif
 
@@ -166,8 +174,16 @@ int main (int argc, char **argv)
   if (option_bool(OPT_DNSSEC_VALID))
     {
 #ifdef HAVE_DNSSEC
-      if (!daemon->ds)
-       die(_("no trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
+      struct ds_config *ds;
+
+      /* Must have at least a root trust anchor, or the DNSSEC code
+        can loop forever. */
+      for (ds = daemon->ds; ds; ds = ds->next)
+       if (ds->name[0] == 0)
+         break;
+
+      if (!ds)
+       die(_("no root trust anchor provided for DNSSEC"), NULL, EC_BADCONF);
       
       if (daemon->cachesize < CACHESIZ)
        die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
@@ -191,12 +207,12 @@ int main (int argc, char **argv)
 
 #ifdef HAVE_SOLARIS_NETWORK
   if (daemon->max_logs != 0)
-    die(_("asychronous logging is not available under Solaris"), NULL, EC_BADCONF);
+    die(_("asynchronous logging is not available under Solaris"), NULL, EC_BADCONF);
 #endif
   
 #ifdef __ANDROID__
   if (daemon->max_logs != 0)
-    die(_("asychronous logging is not available under Android"), NULL, EC_BADCONF);
+    die(_("asynchronous logging is not available under Android"), NULL, EC_BADCONF);
 #endif
 
 #ifndef HAVE_AUTH
@@ -208,7 +224,10 @@ int main (int argc, char **argv)
   if (option_bool(OPT_LOOP_DETECT))
     die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
 #endif
-  
+
+  if (daemon->max_port < daemon->min_port)
+    die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
+
   now = dnsmasq_time();
 
   /* Create a serial at startup if not configured. */
@@ -242,8 +261,11 @@ int main (int argc, char **argv)
   /* Note that order matters here, we must call lease_init before
      creating any file descriptors which shouldn't be leaked
      to the lease-script init process. We need to call common_init
-     before lease_init to allocate buffers it uses.*/
-  if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 || daemon->relay6)
+     before lease_init to allocate buffers it uses.
+     The script subsystem relies on DHCP buffers, hence the last two
+     conditions below. */  
+  if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 || 
+      daemon->relay6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP))
     {
       dhcp_common_init();
       if (daemon->dhcp || daemon->doing_dhcp6)
@@ -338,7 +360,8 @@ int main (int argc, char **argv)
     }
 
 #ifdef HAVE_INOTIFY
-  if (daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
+  if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
+      && (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
     inotify_dnsmasq_init();
   else
     daemon->inotifyfd = -1;
@@ -366,10 +389,12 @@ int main (int argc, char **argv)
       daemon->scriptuser && 
       (daemon->lease_change_command || daemon->luascript))
     {
-      if ((ent_pw = getpwnam(daemon->scriptuser)))
+      struct passwd *scr_pw;
+      
+      if ((scr_pw = getpwnam(daemon->scriptuser)))
        {
-         script_uid = ent_pw->pw_uid;
-         script_gid = ent_pw->pw_gid;
+         script_uid = scr_pw->pw_uid;
+         script_gid = scr_pw->pw_gid;
         }
       else
        baduser = daemon->scriptuser;
@@ -494,7 +519,7 @@ int main (int argc, char **argv)
             extent that an attacker running as the unprivileged  user could replace the pidfile with a 
             symlink, and have the target of that symlink overwritten as root next time dnsmasq starts. 
 
-            The folowing code first deletes any existing file, and then opens it with the O_EXCL flag,
+            The following code first deletes any existing file, and then opens it with the O_EXCL flag,
             ensuring that the open() fails should there be any existing file (because the unlink() failed, 
             or an attacker exploited the race between unlink() and open()). This ensures that no symlink
             attack can succeed. 
@@ -517,9 +542,18 @@ int main (int argc, char **argv)
            }
          else
            {
+             /* We're still running as root here. Change the ownership of the PID file
+                to the user we will be running as. Note that this is not to allow
+                us to delete the file, since that depends on the permissions 
+                of the directory containing the file. That directory will
+                need to by owned by the dnsmasq user, and the ownership of the
+                file has to match, to keep systemd >273 happy. */
+             if (getuid() == 0 && ent_pw && ent_pw->pw_uid != 0 && fchown(fd, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
+               chown_warn = errno;
+
              if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
                err = 1;
-             else 
+             else
                {
                  while (retry_send(close(fd)));
                  if (errno != 0)
@@ -541,17 +575,21 @@ int main (int argc, char **argv)
      {       
        /* open  stdout etc to /dev/null */
        int nullfd = open("/dev/null", O_RDWR);
-       dup2(nullfd, STDOUT_FILENO);
-       dup2(nullfd, STDERR_FILENO);
-       dup2(nullfd, STDIN_FILENO);
-       close(nullfd);
+       if (nullfd != -1)
+        {
+          dup2(nullfd, STDOUT_FILENO);
+          dup2(nullfd, STDERR_FILENO);
+          dup2(nullfd, STDIN_FILENO);
+          close(nullfd);
+        }
      }
    
    /* if we are to run scripts, we need to fork a helper before dropping root. */
   daemon->helperfd = -1;
 #ifdef HAVE_SCRIPT 
-  if ((daemon->dhcp || daemon->dhcp6) && (daemon->lease_change_command || daemon->luascript))
-    daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
+  if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) && 
+      (daemon->lease_change_command || daemon->luascript))
+      daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
 #endif
 
   if (!option_bool(OPT_DEBUG) && getuid() == 0)   
@@ -559,7 +597,7 @@ int main (int argc, char **argv)
       int bad_capabilities = 0;
       gid_t dummy;
       
-      /* remove all supplimentary groups */
+      /* remove all supplementary groups */
       if (gp && 
          (setgroups(0, &dummy) == -1 ||
           setgid(gp->gr_gid) == -1))
@@ -631,7 +669,7 @@ int main (int argc, char **argv)
             (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
          data->inheritable = 0;
          
-         /* lose the setuid and setgid capbilities */
+         /* lose the setuid and setgid capabilities */
          if (capset(hdr, data) == -1)
            {
              send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
@@ -690,12 +728,21 @@ int main (int argc, char **argv)
 
   if (daemon->port == 0)
     my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
-  else if (daemon->cachesize != 0)
-    my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
-  else
-    my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
+  else 
+    {
+      if (daemon->cachesize != 0)
+       my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
+      else
+       my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
+
+      if (option_bool(OPT_LOCAL_SERVICE))
+       my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
+    }
   
   my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
+
+  if (chown_warn != 0)
+    my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
   
 #ifdef HAVE_DBUS
   if (option_bool(OPT_DBUS))
@@ -707,9 +754,6 @@ int main (int argc, char **argv)
     }
 #endif
 
-  if (option_bool(OPT_LOCAL_SERVICE))
-    my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
-  
 #ifdef HAVE_DNSSEC
   if (option_bool(OPT_DNSSEC_VALID))
     {
@@ -726,8 +770,9 @@ 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"));
+      daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
+      if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
+       my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
       
       if (rc == 1)
        my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
@@ -743,6 +788,8 @@ int main (int argc, char **argv)
 
   if (option_bool(OPT_NOWILD))
     warn_bound_listeners();
+  else if (!option_bool(OPT_CLEVERBIND))
+    warn_wild_labels();
 
   warn_int_names();
   
@@ -790,7 +837,7 @@ int main (int argc, char **argv)
     my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
 #  endif
 
-  /* after dhcp_contruct_contexts */
+  /* after dhcp_construct_contexts */
   if (daemon->dhcp || daemon->doing_dhcp6)
     lease_find_interfaces(now);
 #endif
@@ -911,9 +958,15 @@ int main (int argc, char **argv)
       
       poll_listen(piperead, POLLIN);
 
-#ifdef HAVE_DHCP
-#  ifdef HAVE_SCRIPT
-      while (helper_buf_empty() && do_script_run(now));
+#ifdef HAVE_SCRIPT
+#    ifdef HAVE_DHCP
+      while (helper_buf_empty() && do_script_run(now)); 
+#    endif
+
+      /* Refresh cache */
+      if (option_bool(OPT_SCRIPT_ARP))
+       find_mac(NULL, NULL, 0, now);
+      while (helper_buf_empty() && do_arp_script_run());
 
 #    ifdef HAVE_TFTP
       while (helper_buf_empty() && do_tftp_script_run());
@@ -921,16 +974,20 @@ int main (int argc, char **argv)
 
       if (!helper_buf_empty())
        poll_listen(daemon->helperfd, POLLOUT);
-#  else
+#else
       /* need this for other side-effects */
+#    ifdef HAVE_DHCP
       while (do_script_run(now));
+#    endif
+
+      while (do_arp_script_run());
 
 #    ifdef HAVE_TFTP 
       while (do_tftp_script_run());
 #    endif
 
-#  endif
 #endif
+
    
       /* must do this just before select(), when we know no
         more calls to my_syslog() can occur */
@@ -1025,7 +1082,7 @@ int main (int argc, char **argv)
 #endif
 
 #  ifdef HAVE_SCRIPT
-      if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLIN))
+      if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
        helper_write();
 #  endif
 #endif
@@ -1039,7 +1096,7 @@ static void sig_handler(int sig)
     {
       /* ignore anything other than TERM during startup
         and in helper proc. (helper ignore TERM too) */
-      if (sig == SIGTERM)
+      if (sig == SIGTERM || sig == SIGINT)
        exit(EC_MISC);
     }
   else if (pid != getpid())
@@ -1065,6 +1122,15 @@ static void sig_handler(int sig)
        event = EVENT_DUMP;
       else if (sig == SIGUSR2)
        event = EVENT_REOPEN;
+      else if (sig == SIGINT)
+       {
+         /* Handle SIGINT normally in debug mode, so
+            ctrl-c continues to operate. */
+         if (option_bool(OPT_DEBUG))
+           exit(EC_MISC);
+         else
+           event = EVENT_TIME;
+       }
       else
        return;
 
@@ -1147,31 +1213,40 @@ static void fatal_event(struct event_desc *ev, char *msg)
 
     case EVENT_FORK_ERR:
       die(_("cannot fork into background: %s"), NULL, EC_MISC);
-  
+
+      /* fall through */
     case EVENT_PIPE_ERR:
       die(_("failed to create helper: %s"), NULL, EC_MISC);
-  
+
+      /* fall through */
     case EVENT_CAP_ERR:
       die(_("setting capabilities failed: %s"), NULL, EC_MISC);
 
+      /* fall through */
     case EVENT_USER_ERR:
       die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
 
+      /* fall through */
     case EVENT_GROUP_ERR:
       die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
-      
+
+      /* fall through */
     case EVENT_PIDFILE:
       die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
 
+      /* fall through */
     case EVENT_LOG_ERR:
       die(_("cannot open log %s: %s"), msg, EC_FILE);
-    
+
+      /* fall through */
     case EVENT_LUA_ERR:
       die(_("failed to load Lua script: %s"), msg, EC_MISC);
 
+      /* fall through */
     case EVENT_TFTP_ERR:
       die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
-    
+
+      /* fall through */
     case EVENT_TIME_ERR:
       die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
     }
@@ -1191,13 +1266,8 @@ static void async_event(int pipe, time_t now)
     switch (ev.event)
       {
       case EVENT_RELOAD:
-#ifdef HAVE_DNSSEC
-       if (option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
-         {
-           my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
-           reset_option_bool(OPT_DNSSEC_TIME);
-         } 
-#endif
+       daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
+       
        /* fall through */
        
       case EVENT_INIT:
@@ -1260,6 +1330,7 @@ static void async_event(int pipe, time_t now)
                daemon->tcp_pids[i] = 0;
        break;
        
+#if defined(HAVE_SCRIPT)       
       case EVENT_KILLED:
        my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
        break;
@@ -1273,12 +1344,19 @@ static void async_event(int pipe, time_t now)
                  daemon->lease_change_command, strerror(ev.data));
        break;
 
+      case EVENT_SCRIPT_LOG:
+       my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
+        free(msg);
+       msg = NULL;
+       break;
+
        /* necessary for fatal errors in helper */
       case EVENT_USER_ERR:
       case EVENT_DIE:
       case EVENT_LUA_ERR:
        fatal_event(&ev, msg);
        break;
+#endif
 
       case EVENT_REOPEN:
        /* Note: this may leave TCP-handling processes with the old file still open.
@@ -1298,13 +1376,24 @@ static void async_event(int pipe, time_t now)
        poll_resolv(0, 1, now);
        break;
 
+      case EVENT_TIME:
+#ifdef HAVE_DNSSEC
+       if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
+         {
+           my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
+           daemon->dnssec_no_time_check = 0;
+           clear_cache_and_reload(now);
+         }
+#endif
+       break;
+       
       case EVENT_TERM:
        /* Knock all our children on the head. */
        for (i = 0; i < MAX_PROCS; i++)
          if (daemon->tcp_pids[i] != 0)
            kill(daemon->tcp_pids[i], SIGALRM);
        
-#if defined(HAVE_SCRIPT)
+#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
        /* handle pending lease transitions */
        if (daemon->helperfd != -1)
          {
@@ -1325,7 +1414,7 @@ static void async_event(int pipe, time_t now)
        /* update timestamp file on TERM if time is considered valid */
        if (daemon->back_to_the_future)
          {
-            if (utime(daemon->timestamp_file, NULL) == -1)
+            if (utimes(daemon->timestamp_file, NULL) == -1)
                my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
          }
 #endif
@@ -1422,9 +1511,6 @@ void clear_cache_and_reload(time_t now)
       if (option_bool(OPT_ETHERS))
        dhcp_read_ethers();
       reread_dhcp();
-#ifdef HAVE_INOTIFY
-      set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0);
-#endif
       dhcp_update_configs(daemon->dhcp_conf);
       lease_update_from_configs(); 
       lease_update_file(now); 
@@ -1640,7 +1726,7 @@ static void check_dns_listeners(time_t now)
                }
 
 #ifndef NO_FORK
-             /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
+             /* Arrange for SIGALRM after CHILD_LIFETIME seconds to
                 terminate the process. */
              if (!option_bool(OPT_DEBUG))
                alarm(CHILD_LIFETIME);
@@ -1705,29 +1791,15 @@ int icmp_ping(struct in_addr addr)
 {
   /* Try and get an ICMP echo from a machine. */
 
-  /* Note that whilst in the three second wait, we check for 
-     (and service) events on the DNS and TFTP  sockets, (so doing that
-     better not use any resources our caller has in use...)
-     but we remain deaf to signals or further DHCP packets. */
-
-  /* There can be a problem using dnsmasq_time() to end the loop, since
-     it's not monotonic, and can go backwards if the system clock is
-     tweaked, leading to the code getting stuck in this loop and
-     ignoring DHCP requests. To fix this, we check to see if select returned
-     as a result of a timeout rather than a socket becoming available. We
-     only allow this to happen as many times as it takes to get to the wait time
-     in quarter-second chunks. This provides a fallback way to end loop. */ 
-
-  int fd, rc;
+  int fd;
   struct sockaddr_in saddr;
   struct { 
     struct ip ip;
     struct icmp icmp;
   } packet;
   unsigned short id = rand16();
-  unsigned int i, j, timeout_count;
+  unsigned int i, j;
   int gotreply = 0;
-  time_t start, now;
 
 #if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
   if ((fd = make_icmp_sock()) == -1)
@@ -1757,14 +1829,46 @@ int icmp_ping(struct in_addr addr)
   while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0, 
                           (struct sockaddr *)&saddr, sizeof(saddr))));
   
-  for (now = start = dnsmasq_time(), timeout_count = 0; 
-       (difftime(now, start) < (float)PING_WAIT) && (timeout_count < PING_WAIT * 4);)
+  gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
+
+#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
+  while (retry_send(close(fd)));
+#else
+  opt = 1;
+  setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
+#endif
+
+  return gotreply;
+}
+
+int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
+{
+  /* Delay processing DHCP packets for "sec" seconds counting from "start".
+     If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
+     from "addr" with ICMP ID "id" and return 1 */
+
+  /* Note that whilst waiting, we check for
+     (and service) events on the DNS and TFTP  sockets, (so doing that
+     better not use any resources our caller has in use...)
+     but we remain deaf to signals or further DHCP packets. */
+
+  /* There can be a problem using dnsmasq_time() to end the loop, since
+     it's not monotonic, and can go backwards if the system clock is
+     tweaked, leading to the code getting stuck in this loop and
+     ignoring DHCP requests. To fix this, we check to see if select returned
+     as a result of a timeout rather than a socket becoming available. We
+     only allow this to happen as many times as it takes to get to the wait time
+     in quarter-second chunks. This provides a fallback way to end loop. */
+
+  int rc, timeout_count;
+  time_t now;
+
+  for (now = dnsmasq_time(), timeout_count = 0;
+       (difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
     {
-      struct sockaddr_in faddr;
-      socklen_t len = sizeof(faddr);
-      
       poll_reset();
-      poll_listen(fd, POLLIN);
+      if (fd != -1)
+        poll_listen(fd, POLLIN);
       set_dns_listeners(now);
       set_log_writer();
       
@@ -1781,10 +1885,10 @@ int icmp_ping(struct in_addr addr)
        timeout_count++;
 
       now = dnsmasq_time();
-
+      
       check_log_writer(0);
       check_dns_listeners(now);
-
+      
 #ifdef HAVE_DHCP6
       if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
        icmp6_packet(now);
@@ -1794,27 +1898,26 @@ int icmp_ping(struct in_addr addr)
       check_tftp_listeners(now);
 #endif
 
-      if (poll_check(fd, POLLIN) &&
-         recvfrom(fd, &packet, sizeof(packet), 0,
-                  (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
-         saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
-         packet.icmp.icmp_type == ICMP_ECHOREPLY &&
-         packet.icmp.icmp_seq == 0 &&
-         packet.icmp.icmp_id == id)
-       {
-         gotreply = 1;
-         break;
+      if (fd != -1)
+        {
+          struct {
+            struct ip ip;
+            struct icmp icmp;
+          } packet;
+          struct sockaddr_in faddr;
+          socklen_t len = sizeof(faddr);
+         
+          if (poll_check(fd, POLLIN) &&
+             recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
+             addr == faddr.sin_addr.s_addr &&
+             packet.icmp.icmp_type == ICMP_ECHOREPLY &&
+             packet.icmp.icmp_seq == 0 &&
+             packet.icmp.icmp_id == id)
+           return 1;
        }
     }
-  
-#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
-  while (retry_send(close(fd)));
-#else
-  opt = 1;
-  setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
-#endif
 
-  return gotreply;
+  return 0;
 }
 #endif
 
index cf1a782..6773b69 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#define COPYRIGHT "Copyright (c) 2000-2015 Simon Kelley" 
+#define COPYRIGHT "Copyright (c) 2000-2018 Simon Kelley"
+
+/* We do defines that influence behavior of stdio.h, so complain
+   if included too early. */
+#ifdef _STDIO_H
+#  error "Header file stdio.h included too early!"
+#endif 
 
 #ifndef NO_LARGEFILE
 /* Ensure we can use files >2GB (log files may grow this big) */
@@ -117,7 +123,6 @@ typedef unsigned long long u64;
 #include <sys/uio.h>
 #include <syslog.h>
 #include <dirent.h>
-#include <utime.h>
 #ifndef HAVE_LINUX_NETWORK
 #  include <net/if_dl.h>
 #endif
@@ -125,7 +130,7 @@ typedef unsigned long long u64;
 #if defined(HAVE_LINUX_NETWORK)
 #include <linux/capability.h>
 /* There doesn't seem to be a universally-available 
-   userpace header for these. */
+   userspace header for these. */
 extern int capset(cap_user_header_t header, cap_user_data_t data);
 extern int capget(cap_user_header_t header, cap_user_data_t data);
 #define LINUX_CAPABILITY_VERSION_1  0x19980330
@@ -137,6 +142,10 @@ extern int capget(cap_user_header_t header, cap_user_data_t data);
 #include <priv.h>
 #endif
 
+#ifdef HAVE_DNSSEC
+#  include <nettle/nettle-meta.h>
+#endif
+
 /* daemon is function in the C library.... */
 #define daemon dnsmasq_daemon
 
@@ -145,30 +154,32 @@ struct event_desc {
   int event, data, msg_sz;
 };
 
-#define EVENT_RELOAD    1
-#define EVENT_DUMP      2
-#define EVENT_ALARM     3
-#define EVENT_TERM      4
-#define EVENT_CHILD     5
-#define EVENT_REOPEN    6
-#define EVENT_EXITED    7
-#define EVENT_KILLED    8
-#define EVENT_EXEC_ERR  9
-#define EVENT_PIPE_ERR  10
-#define EVENT_USER_ERR  11
-#define EVENT_CAP_ERR   12
-#define EVENT_PIDFILE   13
-#define EVENT_HUSER_ERR 14
-#define EVENT_GROUP_ERR 15
-#define EVENT_DIE       16
-#define EVENT_LOG_ERR   17
-#define EVENT_FORK_ERR  18
-#define EVENT_LUA_ERR   19
-#define EVENT_TFTP_ERR  20
-#define EVENT_INIT      21
-#define EVENT_NEWADDR   22
-#define EVENT_NEWROUTE  23
-#define EVENT_TIME_ERR  24
+#define EVENT_RELOAD     1
+#define EVENT_DUMP       2
+#define EVENT_ALARM      3
+#define EVENT_TERM       4
+#define EVENT_CHILD      5
+#define EVENT_REOPEN     6
+#define EVENT_EXITED     7
+#define EVENT_KILLED     8
+#define EVENT_EXEC_ERR   9
+#define EVENT_PIPE_ERR   10
+#define EVENT_USER_ERR   11
+#define EVENT_CAP_ERR    12
+#define EVENT_PIDFILE    13
+#define EVENT_HUSER_ERR  14
+#define EVENT_GROUP_ERR  15
+#define EVENT_DIE        16
+#define EVENT_LOG_ERR    17
+#define EVENT_FORK_ERR   18
+#define EVENT_LUA_ERR    19
+#define EVENT_TFTP_ERR   20
+#define EVENT_INIT       21
+#define EVENT_NEWADDR    22
+#define EVENT_NEWROUTE   23
+#define EVENT_TIME_ERR   24
+#define EVENT_SCRIPT_LOG 25
+#define EVENT_TIME       26
 
 /* Exit codes. */
 #define EC_GOOD        0
@@ -179,13 +190,6 @@ struct event_desc {
 #define EC_MISC        5
 #define EC_INIT_OFFSET 10
 
-/* Min buffer size: we check after adding each record, so there must be 
-   memory for the largest packet, and the largest record so the
-   min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
-   This might be increased is EDNS packet size if greater than the minimum.
-*/
-#define DNSMASQ_PACKETSZ PACKETSZ+MAXDNAME+RRFIXEDSZ
-
 /* Trust the compiler dead-code eliminator.... */
 #define option_bool(x) (((x) < 32) ? daemon->options & (1u << (x)) : daemon->options2 & (1u << ((x) - 32)))
 
@@ -218,7 +222,7 @@ struct event_desc {
 #define OPT_TFTP_SECURE    26
 #define OPT_TFTP_NOBLOCK   27
 #define OPT_LOG_OPTS       28
-#define OPT_TFTP_APREF     29
+#define OPT_TFTP_APREF_IP  29
 #define OPT_NO_OVERRIDE    30
 #define OPT_NO_REBIND      31
 #define OPT_ADD_MAC        32
@@ -242,12 +246,17 @@ struct event_desc {
 #define OPT_LOOP_DETECT    50
 #define OPT_EXTRALOG       51
 #define OPT_TFTP_NO_FAIL   52
-#define OPT_LAST           53
+#define OPT_SCRIPT_ARP     53
+#define OPT_MAC_B64        54
+#define OPT_MAC_HEX        55
+#define OPT_TFTP_APREF_MAC 56
+#define OPT_LAST           57
 
 /* 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. */
-#define MS_TFTP LOG_USER
-#define MS_DHCP LOG_DAEMON 
+#define MS_TFTP   LOG_USER
+#define MS_DHCP   LOG_DAEMON
+#define MS_SCRIPT LOG_MAIL
 
 struct all_addr {
   union {
@@ -256,8 +265,10 @@ struct all_addr {
     struct in6_addr addr6;
 #endif
     /* for log_query */
-    unsigned int keytag;
-    /* for cache_insert if RRSIG, DNSKEY, DS */
+    struct {
+      unsigned short keytag, algo, digest;
+    } log; 
+    /* for cache_insert of DNSKEY, DS */
     struct {
       unsigned short class, type;
     } dnssec;      
@@ -288,6 +299,7 @@ struct naptr {
   struct naptr *next;
 };
 
+#ifndef NO_ID
 #define TXT_STAT_CACHESIZE     1
 #define TXT_STAT_INSERTS       2
 #define TXT_STAT_EVICTIONS     3
@@ -295,6 +307,7 @@ struct naptr {
 #define TXT_STAT_HITS          5
 #define TXT_STAT_AUTH          6
 #define TXT_STAT_SERVERS       7
+#endif
 
 struct txt_record {
   char *name;
@@ -310,8 +323,9 @@ struct ptr_record {
 };
 
 struct cname {
+  int ttl, flag;
   char *alias, *target;
-  struct cname *next;
+  struct cname *next, *targetp;
 }; 
 
 struct ds_config {
@@ -341,11 +355,13 @@ struct auth_zone {
     struct auth_name_list *next;
   } *interface_names;
   struct addrlist *subnet;
+  struct addrlist *exclude;
   struct auth_zone *next;
 };
 
 
 struct host_record {
+  int ttl;
   struct name_list {
     char *name;
     struct name_list *next;
@@ -398,14 +414,9 @@ struct crec {
       unsigned char algo;
       unsigned char digest; 
     } ds; 
-    struct {
-      struct blockdata *keydata;
-      unsigned short keylen, type_covered, keytag;
-      char algo;
-    } sig;
   } addr;
   time_t ttd; /* time to die */
-  /* used as class if DNSKEY/DS/RRSIG, index to source for F_HOSTS */
+  /* used as class if DNSKEY/DS, index to source for F_HOSTS */
   unsigned int uid; 
   unsigned short flags;
   union {
@@ -445,8 +456,8 @@ struct crec {
 #define F_SECSTAT   (1u<<24)
 #define F_NO_RR     (1u<<25)
 #define F_IPSET     (1u<<26)
-#define F_NSIGMATCH (1u<<27)
-#define F_NOEXTRA   (1u<<28)
+#define F_NOEXTRA   (1u<<27)
+#define F_SERVFAIL  (1u<<28)
 
 /* Values of uid in crecs with F_CONFIG bit set. */
 #define SRC_INTERFACE 0
@@ -487,11 +498,14 @@ union mysockaddr {
 #define SERV_NO_REBIND      2048  /* inhibit dns-rebind protection */
 #define SERV_FROM_FILE      4096  /* read from --servers-file */
 #define SERV_LOOP           8192  /* server causes forwarding loop */
+#define SERV_DO_DNSSEC     16384  /* Validate DNSSEC when using this server */
+#define SERV_GOT_TCP       32768  /* Got some data from the TCP connection */
 
 struct serverfd {
   int fd;
   union mysockaddr source_addr;
   char interface[IF_NAMESIZE+1];
+  unsigned int ifindex, used;
   struct serverfd *next;
 };
 
@@ -506,6 +520,7 @@ struct server {
   struct serverfd *sfd; 
   char *domain; /* set if this server only handles a domain. */ 
   int flags, tcpfd, edns_pktsz;
+  time_t pktsz_reduced;
   unsigned int queries, failed_queries;
 #ifdef HAVE_LOOP
   u32 uid;
@@ -522,7 +537,7 @@ struct ipsets {
 struct irec {
   union mysockaddr addr;
   struct in_addr netmask; /* only valid for IPv4 */
-  int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found;
+  int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found, label;
   char *name; 
   struct irec *next;
 };
@@ -541,6 +556,13 @@ struct iname {
   struct iname *next;
 };
 
+/* subnet parameters from command line */
+struct mysubnet {
+  union mysockaddr addr;
+  int addr_used;
+  int mask;
+};
+
 /* resolv-file parms from command-line */
 struct resolvc {
   struct resolvc *next;
@@ -579,12 +601,8 @@ struct hostsfile {
 #define STAT_NEED_KEY           5
 #define STAT_TRUNCATED          6
 #define STAT_SECURE_WILDCARD    7
-#define STAT_NO_SIG             8
-#define STAT_NO_DS              9
-#define STAT_NO_NS             10
-#define STAT_NEED_DS_NEG       11
-#define STAT_CHASE_CNAME       12
-#define STAT_INSECURE_DS       13
+#define STAT_OK                 8
+#define STAT_ABANDONED          9
 
 #define FREC_NOREBIND           1
 #define FREC_CHECKING_DISABLED  2
@@ -594,8 +612,8 @@ struct hostsfile {
 #define FREC_AD_QUESTION       32
 #define FREC_DO_QUESTION       64
 #define FREC_ADDED_PHEADER    128
-#define FREC_CHECK_NOSIGN     256
-#define FREC_TEST_PKTSZ       512
+#define FREC_TEST_PKTSZ       256
+#define FREC_HAS_EXTRADATA    512        
 
 #ifdef HAVE_DNSSEC
 #define HASH_SIZE 20 /* SHA-1 digest size */
@@ -619,9 +637,7 @@ struct frec {
 #ifdef HAVE_DNSSEC 
   int class, work_counter;
   struct blockdata *stash; /* Saved reply, whilst we validate */
-  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;
+  size_t stash_len;
   struct frec *dependent; /* Query awaiting internally-generated DNSKEY or DS query */
   struct frec *blocking_query; /* Query which is blocking us. */
 #endif
@@ -643,6 +659,8 @@ struct frec {
 #define ACTION_OLD           3
 #define ACTION_ADD           4
 #define ACTION_TFTP          5
+#define ACTION_ARP           6
+#define ACTION_ARP_DEL       7
 
 #define LEASE_NEW            1  /* newly created */
 #define LEASE_CHANGED        2  /* modified */
@@ -701,6 +719,12 @@ struct tag_if {
   struct tag_if *next;
 };
 
+struct delay_config {
+  int delay;
+  struct dhcp_netid *netid;
+  struct delay_config *next;
+};
+
 struct hwaddr_config {
   int hwaddr_len, hwaddr_type;
   unsigned char hwaddr[DHCP_CHADDR_MAX];
@@ -787,7 +811,7 @@ struct pxe_service {
 #define MATCH_REMOTE     4
 #define MATCH_SUBSCRIBER 5
 
-/* vendorclass, userclass, remote-id or cicuit-id */
+/* vendorclass, userclass, remote-id or circuit-id */
 struct dhcp_vendor {
   int len, match_type;
   unsigned int enterprise;
@@ -815,7 +839,7 @@ struct cond_domain {
 #ifdef HAVE_IPV6
   struct in6_addr start6, end6;
 #endif
-  int is6;
+  int is6, indexed;
   struct cond_domain *next;
 }; 
 
@@ -829,7 +853,8 @@ struct prefix_class {
 
 struct ra_interface {
   char *name;
-  int interval, lifetime, prio;
+  char *mtu_name;
+  int interval, lifetime, prio, mtu;
   struct ra_interface *next;
 };
 
@@ -935,9 +960,9 @@ extern struct daemon {
   struct auth_zone *auth_zones;
   struct interface_name *int_names;
   char *mxtarget;
-  int addr4_netmask;
-  int addr6_netmask;
-  char *lease_file; 
+  struct mysubnet *add_subnet4;
+  struct mysubnet *add_subnet6;
+  char *lease_file;
   char *username, *groupname, *scriptuser;
   char *luascript;
   char *authserver, *hostmaster;
@@ -956,8 +981,9 @@ extern struct daemon {
   char *log_file; /* optional log file */
   int max_logs;  /* queue limit */
   int cachesize, ftabsize;
-  int port, query_port, min_port;
-  unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl;
+  int port, query_port, min_port, max_port;
+  unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl, dhcp_ttl, use_dhcp_ttl;
+  char *dns_client_id;
   struct hostsfile *addn_hosts;
   struct dhcp_context *dhcp, *dhcp6;
   struct ra_interface *ra_interfaces;
@@ -970,13 +996,14 @@ extern struct daemon {
   struct tag_if *tag_if; 
   struct addr_list *override_relays;
   struct dhcp_relay *relay4, *relay6;
+  struct delay_config *delay_conf;
   int override;
   int enable_pxe;
   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, *dynamic_dirs;
-  int dhcp_max, tftp_max;
+  int dhcp_max, tftp_max, tftp_mtu;
   int dhcp_server_port, dhcp_client_port;
   int start_tftp_port, end_tftp_port; 
   unsigned int min_leasetime;
@@ -993,6 +1020,7 @@ extern struct daemon {
 #endif
 #ifdef HAVE_DNSSEC
   struct ds_config *ds;
+  int dnssec_no_time_check;
   int back_to_the_future;
   char *timestamp_file;
 #endif
@@ -1004,6 +1032,8 @@ extern struct daemon {
 #ifdef HAVE_DNSSEC
   char *keyname; /* MAXDNAME size buffer */
   char *workspacename; /* ditto */
+  char *rr_status; /* flags for individual RRs */
+  int rr_status_sz;
 #endif
   unsigned int local_answer, queries_forwarded, auth_answer;
   struct frec *frec_list;
@@ -1079,7 +1109,9 @@ void cache_add_dhcp_entry(char *host_name, int prot, struct all_addr *host_addre
 struct in_addr a_record_from_hosts(char *name, time_t now);
 void cache_unhash_dhcp(void);
 void dump_cache(time_t now);
+#ifndef NO_ID
 int cache_make_stat(struct txt_record *t);
+#endif
 char *cache_get_name(struct crec *crecp);
 char *cache_get_cname_target(struct crec *crecp);
 struct crec *cache_enumerate(int init);
@@ -1113,28 +1145,20 @@ unsigned int extract_request(struct dns_header *header, size_t qlen,
                               char *name, unsigned short *typep);
 size_t setup_reply(struct dns_header *header, size_t  qlen,
                   struct all_addr *addrp, unsigned int flags,
-                  unsigned long local_ttl);
-int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff, 
-                     time_t now, char **ipsets, int is_sign, int checkrebind,
-                     int no_cache, int secure, int *doctored);
+                  unsigned long ttl);
+int extract_addresses(struct dns_header *header, size_t qlen, char *name,
+                     time_t now, char **ipsets, int is_sign, int check_rebind,
+                     int no_cache_dnssec, int secure, int *doctored);
 size_t answer_request(struct dns_header *header, char *limit, size_t qlen,  
                      struct in_addr local_addr, struct in_addr local_netmask, 
-                     time_t now, int *ad_reqd, int *do_bit);
+                     time_t now, int ad_reqd, int do_bit, int have_pseudoheader);
 int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, 
-                            struct bogus_addr *addr, time_t now);
+                            struct bogus_addr *baddr, 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);
-unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
+unsigned int questions_crc(struct dns_header *header, size_t plen, char *name);
 size_t resize_packet(struct dns_header *header, size_t plen, 
                  unsigned char *pheader, size_t hlen);
-size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
-size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, union mysockaddr *source);
-#ifdef HAVE_DNSSEC
-size_t add_do_bit(struct dns_header *header, size_t plen, char *limit);
-#endif
-int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer);
 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, ...);
@@ -1147,29 +1171,39 @@ int private_net(struct in_addr addr, int ban_localhost);
 /* auth.c */
 #ifdef HAVE_AUTH
 size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, 
-                  time_t now, union mysockaddr *peer_addr, int local_query);
+                  time_t now, union mysockaddr *peer_addr, int local_query,
+                  int do_bit, int have_pseudoheader);
 int in_zone(struct auth_zone *zone, char *name, char **cut);
 #endif
 
 /* dnssec.c */
-size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
-int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, char *name, char *keyname, int class);
+size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
+int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
 int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
-int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int *neganswer, int *nons);
-int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname);
-int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
+int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class,
+                         int check_unsigned, int *neganswer, int *nons);
+int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen);
 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(void);
 
+/* crypto.c */
+const struct nettle_hash *hash_find(char *name);
+int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp);
+int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
+          unsigned char *digest, size_t digest_len, int algo);
+char *ds_digest_name(int digest);
+char *algo_digest_name(int algo);
+char *nsec3_digest_name(int digest);
+
 /* util.c */
 void rand_init(void);
 unsigned short rand16(void);
 u32 rand32(void);
 u64 rand64(void);
-int legal_hostname(char *c);
-char *canonicalise(char *s, int *nomem);
-unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
+int legal_hostname(char *name);
+char *canonicalise(char *in, int *nomem);
+unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
 void *safe_malloc(size_t size);
 void safe_pipe(int *fd, int read_noblock);
 void *whine_malloc(size_t size);
@@ -1202,7 +1236,9 @@ int wildcard_matchn(const char* wildcard, const char* match, int num);
 void die(char *message, char *arg1, int exit_code);
 int log_start(struct passwd *ent_pw, int errfd);
 int log_reopen(char *log_file);
+
 void my_syslog(int priority, const char *format, ...);
+
 void set_log_writer(void);
 void check_log_writer(int force);
 void flush_log(void);
@@ -1230,13 +1266,13 @@ struct frec *get_new_frec(time_t now, int *wait, int force);
 int send_from(int fd, int nowild, char *packet, size_t len, 
               union mysockaddr *to, struct all_addr *source,
               unsigned int iface);
-void resend_query();
+void resend_query(void);
 struct randfd *allocate_rfd(int family);
 void free_rfd(struct randfd *rfd);
 
 /* network.c */
 int indextoname(int fd, int index, char *name);
-int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp);
+int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp);
 int random_sock(int family);
 void pre_allocate_sfds(void);
 int reload_servers(char *fname);
@@ -1250,11 +1286,12 @@ void add_update_server(int flags,
 void check_servers(void);
 int enumerate_interfaces(int reset);
 void create_wildcard_listeners(void);
-void create_bound_listeners(int die);
+void create_bound_listeners(int dienow);
 void warn_bound_listeners(void);
+void warn_wild_labels(void);
 void warn_int_names(void);
 int is_dad_listeners(void);
-int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
+int iface_check(int family, struct all_addr *addr, char *name, int *auth);
 int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
 int label_exception(int index, int family, struct all_addr *addr);
 int fix_fd(int fd);
@@ -1275,14 +1312,16 @@ void newaddress(time_t now);
 void dhcp_init(void);
 void dhcp_packet(time_t now, int pxe_fd);
 struct dhcp_context *address_available(struct dhcp_context *context, 
-                                      struct in_addr addr,
+                                      struct in_addr taddr,
                                       struct dhcp_netid *netids);
 struct dhcp_context *narrow_context(struct dhcp_context *context, 
                                    struct in_addr taddr,
                                    struct dhcp_netid *netids);
+struct ping_result *do_icmp_ping(time_t now, struct in_addr addr,
+                                unsigned int hash, int loopback);
 int address_allocate(struct dhcp_context *context,
                     struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
-                    struct dhcp_netid *netids, time_t now);
+                    struct dhcp_netid *netids, time_t now, int loopback);
 void dhcp_read_ethers(void);
 struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr);
 char *host_from_dns(struct in_addr addr);
@@ -1331,7 +1370,8 @@ void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data,
 /* rfc2131.c */
 #ifdef HAVE_DHCP
 size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
-                 size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe_fd, struct in_addr fallback);
+                 size_t sz, time_t now, int unicast_dest, int loopback,
+                 int *is_inform, int pxe, struct in_addr fallback, time_t recvtime);
 unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr, 
                               int clid_len, unsigned char *clid, int *len_out);
 #endif
@@ -1340,6 +1380,7 @@ unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
 #ifdef HAVE_DHCP
 int make_icmp_sock(void);
 int icmp_ping(struct in_addr addr);
+int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id);
 #endif
 void queue_event(int event);
 void send_alarm(time_t event, time_t now);
@@ -1389,6 +1430,8 @@ void queue_script(int action, struct dhcp_lease *lease,
 #ifdef HAVE_TFTP
 void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer);
 #endif
+void queue_arp(int action, unsigned char *mac, int maclen,
+              int family, struct all_addr *addr);
 int helper_buf_empty(void);
 #endif
 
@@ -1425,7 +1468,7 @@ struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct
 void make_duid(time_t now);
 void dhcp_construct_contexts(time_t now);
 void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, 
-                   unsigned int *maclenp, unsigned int *mactypep);
+                   unsigned int *maclenp, unsigned int *mactypep, time_t now);
 #endif
   
 /* rfc3315.c */
@@ -1433,7 +1476,8 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac,
 unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name,  
                           struct in6_addr *fallback, struct in6_addr *ll_addr, struct in6_addr *ula_addr,
                           size_t sz, struct in6_addr *client_addr, time_t now);
-void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, u32 scope_id);
+void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, 
+                    u32 scope_id, time_t now);
 
 unsigned short relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface);
 #endif
@@ -1442,10 +1486,10 @@ unsigned short relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arriva
 #ifdef HAVE_DHCP
 void dhcp_common_init(void);
 ssize_t recv_dhcp_packet(int fd, struct msghdr *msg);
-struct dhcp_netid *run_tag_if(struct dhcp_netid *input);
+struct dhcp_netid *run_tag_if(struct dhcp_netid *tags);
 struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *context_tags,
                                 struct dhcp_opt *opts);
-int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);
+int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded);
 char *strip_hostname(char *hostname);
 void log_tags(struct dhcp_netid *netid, u32 xid);
 int match_bytes(struct dhcp_opt *o, unsigned char *p, int len);
@@ -1475,6 +1519,7 @@ void log_relay(int family, struct dhcp_relay *relay);
 /* outpacket.c */
 #ifdef HAVE_DHCP6
 void end_opt6(int container);
+void reset_counter(void);
 int save_counter(int newval);
 void *expand(size_t headroom);
 int new_opt6(int opt);
@@ -1490,7 +1535,7 @@ void put_opt6_string(char *s);
 void ra_init(time_t now);
 void icmp6_packet(time_t now);
 time_t periodic_ra(time_t now);
-void ra_start_unsolicted(time_t now, struct dhcp_context *context);
+void ra_start_unsolicited(time_t now, struct dhcp_context *context);
 #endif
 
 /* slaac.c */ 
@@ -1502,13 +1547,13 @@ void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
 
 /* loop.c */
 #ifdef HAVE_LOOP
-void loop_send_probes();
+void loop_send_probes(void);
 int detect_loop(char *query, int type);
 #endif
 
 /* inotify.c */
 #ifdef HAVE_INOTIFY
-void inotify_dnsmasq_init();
+void inotify_dnsmasq_init(void);
 int inotify_check(time_t now);
 void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz);
 #endif
@@ -1519,3 +1564,21 @@ int poll_check(int fd, short event);
 void poll_listen(int fd, short event);
 int do_poll(int timeout);
 
+/* rrfilter.c */
+size_t rrfilter(struct dns_header *header, size_t plen, int mode);
+u16 *rrfilter_desc(int type);
+int expand_workspace(unsigned char ***wkspc, int *szp, int new);
+
+/* edns0.c */
+unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
+                                  size_t *len, unsigned char **p, int *is_sign, int *is_last);
+size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit, 
+                       unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace);
+size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char *limit);
+size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit, 
+                       union mysockaddr *source, time_t now, int *check_subnet);
+int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer);
+
+/* arp.c */
+int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now);
+int do_arp_script_run(void);
index 4deda24..8143185 100644 (file)
@@ -1,5 +1,5 @@
 /* dnssec.c is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
-           and Copyright (c) 2012-2015 Simon Kelley
+           and Copyright (c) 2012-2018 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
 
 #ifdef HAVE_DNSSEC
 
-#include <nettle/rsa.h>
-#include <nettle/dsa.h>
-#ifndef NO_NETTLE_ECC
-#  include <nettle/ecdsa.h>
-#  include <nettle/ecc-curve.h>
-#endif
-#include <nettle/nettle-meta.h>
-#include <nettle/bignum.h>
-
-/* Nettle-3.0 moved to a new API for DSA. We use a name that's defined in the new API
-   to detect Nettle-3, and invoke the backwards compatibility mode. */
-#ifdef dsa_params_init
-#include <nettle/dsa-compat.h>
-#endif
-
 #define SERIAL_UNDEF  -100
 #define SERIAL_EQ        0
 #define SERIAL_LT       -1
 #define SERIAL_GT        1
 
-/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
-static char *ds_digest_name(int digest)
-{
-  switch (digest)
-    {
-    case 1: return "sha1";
-    case 2: return "sha256";
-    case 3: return "gosthash94";
-    case 4: return "sha384";
-    default: return NULL;
-    }
-}
-/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
-static char *algo_digest_name(int algo)
-{
-  switch (algo)
-    {
-    case 1: return "md5";
-    case 3: return "sha1";
-    case 5: return "sha1";
-    case 6: return "sha1";
-    case 7: return "sha1";
-    case 8: return "sha256";
-    case 10: return "sha512";
-    case 12: return "gosthash94";
-    case 13: return "sha256";
-    case 14: return "sha384";
-    default: return NULL;
-    }
-}
-      
-/* Find pointer to correct hash function in nettle library */
-static const struct nettle_hash *hash_find(char *name)
-{
-  int i;
-  
-  if (!name)
-    return NULL;
-  
-  for (i = 0; nettle_hashes[i]; i++)
-    {
-      if (strcmp(nettle_hashes[i]->name, name) == 0)
-       return nettle_hashes[i];
-    }
-
-  return NULL;
-}
-
-/* expand ctx and digest memory allocations if necessary and init hash function */
-static int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
-{
-  static void *ctx = NULL;
-  static unsigned char *digest = NULL;
-  static unsigned int ctx_sz = 0;
-  static unsigned int digest_sz = 0;
-
-  void *new;
-
-  if (ctx_sz < hash->context_size)
-    {
-      if (!(new = whine_malloc(hash->context_size)))
-       return 0;
-      if (ctx)
-       free(ctx);
-      ctx = new;
-      ctx_sz = hash->context_size;
-    }
-  
-  if (digest_sz < hash->digest_size)
-    {
-      if (!(new = whine_malloc(hash->digest_size)))
-       return 0;
-      if (digest)
-       free(digest);
-      digest = new;
-      digest_sz = hash->digest_size;
-    }
-
-  *ctxp = ctx;
-  *digestp = digest;
-
-  hash->init(ctx);
-
-  return 1;
-}
-  
-static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
-                             unsigned char *digest, int algo)
-{
-  unsigned char *p;
-  size_t exp_len;
-  
-  static struct rsa_public_key *key = NULL;
-  static mpz_t sig_mpz;
-  
-  if (key == NULL)
-    {
-      if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
-       return 0;
-      
-      nettle_rsa_public_key_init(key);
-      mpz_init(sig_mpz);
-    }
-  
-  if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
-    return 0;
-  
-  key_len--;
-  if ((exp_len = *p++) == 0)
-    {
-      GETSHORT(exp_len, p);
-      key_len -= 2;
-    }
-  
-  if (exp_len >= key_len)
-    return 0;
-  
-  key->size =  key_len - exp_len;
-  mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
-  mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
-
-  mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
-  
-  switch (algo)
-    {
-    case 1:
-      return nettle_rsa_md5_verify_digest(key, digest, sig_mpz);
-    case 5: case 7:
-      return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
-    case 8:
-      return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
-    case 10:
-      return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
-    }
-
-  return 0;
-}  
-
-static int dnsmasq_dsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
-                             unsigned char *digest, int algo)
-{
-  unsigned char *p;
-  unsigned int t;
-  
-  static struct dsa_public_key *key = NULL;
-  static struct dsa_signature *sig_struct;
-  
-  if (key == NULL)
-    {
-      if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) || 
-         !(key = whine_malloc(sizeof(struct dsa_public_key)))) 
-       return 0;
-      
-      nettle_dsa_public_key_init(key);
-      nettle_dsa_signature_init(sig_struct);
-    }
-  
-  if ((sig_len < 41) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
-    return 0;
-  
-  t = *p++;
-  
-  if (key_len < (213 + (t * 24)))
-    return 0;
-  
-  mpz_import(key->q, 20, 1, 1, 0, 0, p); p += 20;
-  mpz_import(key->p, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
-  mpz_import(key->g, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
-  mpz_import(key->y, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
-  
-  mpz_import(sig_struct->r, 20, 1, 1, 0, 0, sig+1);
-  mpz_import(sig_struct->s, 20, 1, 1, 0, 0, sig+21);
-  
-  (void)algo;
-  
-  return nettle_dsa_sha1_verify_digest(key, digest, sig_struct);
-} 
-#ifndef NO_NETTLE_ECC
-static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len, 
-                               unsigned char *sig, size_t sig_len,
-                               unsigned char *digest, size_t digest_len, int algo)
-{
-  unsigned char *p;
-  unsigned int t;
-  struct ecc_point *key;
-
-  static struct ecc_point *key_256 = NULL, *key_384 = NULL;
-  static mpz_t x, y;
-  static struct dsa_signature *sig_struct;
-  
-  if (!sig_struct)
-    {
-      if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
-       return 0;
-      
-      nettle_dsa_signature_init(sig_struct);
-      mpz_init(x);
-      mpz_init(y);
-    }
-  
-  switch (algo)
-    {
-    case 13:
-      if (!key_256)
-       {
-         if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
-           return 0;
-         
-         nettle_ecc_point_init(key_256, &nettle_secp_256r1);
-       }
-      
-      key = key_256;
-      t = 32;
-      break;
-      
-    case 14:
-      if (!key_384)
-       {
-         if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
-           return 0;
-         
-         nettle_ecc_point_init(key_384, &nettle_secp_384r1);
-       }
-      
-      key = key_384;
-      t = 48;
-      break;
-        
-    default:
-      return 0;
-    }
-  
-  if (sig_len != 2*t || key_len != 2*t ||
-      !(p = blockdata_retrieve(key_data, key_len, NULL)))
-    return 0;
-  
-  mpz_import(x, t , 1, 1, 0, 0, p);
-  mpz_import(y, t , 1, 1, 0, 0, p + t);
-
-  if (!ecc_point_set(key, x, y))
-    return 0;
-  
-  mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
-  mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
-  
-  return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
-} 
-#endif 
-
-static int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
-                 unsigned char *digest, size_t digest_len, int algo)
-{
-  (void)digest_len;
-
-  switch (algo)
-    {
-    case 1: case 5: case 7: case 8: case 10:
-      return dnsmasq_rsa_verify(key_data, key_len, sig, sig_len, digest, algo);
-      
-    case 3: case 6: 
-      return dnsmasq_dsa_verify(key_data, key_len, sig, sig_len, digest, algo);
-#ifndef NO_NETTLE_ECC   
-    case 13: case 14:
-      return dnsmasq_ecdsa_verify(key_data, key_len, sig, sig_len, digest, digest_len, algo);
-#endif
-    }
-  
-  return 0;
-}
-
 /* Convert from presentation format to wire format, in place.
    Also map UC -> LC.
    Note that using extract_name to get presentation format
@@ -325,7 +37,7 @@ static int verify(struct blockdata *key_data, unsigned int key_len, unsigned cha
    character. In theory, if all the characters in a name were /000 or
    '.' or NAME_ESCAPE then all would have to be escaped, so the 
    presentation format would be twice as long as the spec (1024). 
-   The buffers are all delcared as 2049 (allowing for the trailing zero) 
+   The buffers are all declared as 2049 (allowing for the trailing zero) 
    for this reason.
 */
 static int to_wire(char *name)
@@ -391,19 +103,21 @@ static void from_wire(char *name)
 static int count_labels(char *name)
 {
   int i;
-
+  char *p;
+  
   if (*name == 0)
     return 0;
 
-  for (i = 0; *name; name++)
-    if (*name == '.')
+  for (p = name, i = 0; *p; p++)
+    if (*p == '.')
       i++;
 
-  return i+1;
+  /* Don't count empty first label. */
+  return *name == '.' ? i : i+1;
 }
 
 /* Implement RFC1982 wrapped compare for 32-bit numbers */
-static int serial_compare_32(unsigned long s1, unsigned long s2)
+static int serial_compare_32(u32 s1, u32 s2)
 {
   if (s1 == s2)
     return SERIAL_EQ;
@@ -442,7 +156,7 @@ int setup_timestamp(void)
       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)
+         if (utimes(daemon->timestamp_file, NULL) == -1)
            my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
          daemon->back_to_the_future = 1;
          return 0;
@@ -456,12 +170,14 @@ int setup_timestamp(void)
       int fd = open(daemon->timestamp_file, O_WRONLY | O_CREAT | O_NONBLOCK | O_EXCL, 0666);
       if (fd != -1)
        {
-         struct utimbuf timbuf;
+         struct timeval tv[2];
 
          close(fd);
          
-         timestamp_time = timbuf.actime = timbuf.modtime = 1420070400; /* 1-1-2015 */
-         if (utime(daemon->timestamp_file, &timbuf) == 0)
+         timestamp_time = 1420070400; /* 1-1-2015 */
+         tv[0].tv_sec = tv[1].tv_sec = timestamp_time;
+         tv[0].tv_usec = tv[1].tv_usec = 0;
+         if (utimes(daemon->timestamp_file, tv) == 0)
            goto check_and_exit;
        }
     }
@@ -470,7 +186,7 @@ int setup_timestamp(void)
 }
 
 /* Check whether today/now is between date_start and date_end */
-static int check_date_range(unsigned long date_start, unsigned long date_end)
+static int check_date_range(u32 date_start, u32 date_end)
 {
   unsigned long curtime = time(0);
  
@@ -486,18 +202,19 @@ static int check_date_range(unsigned long date_start, unsigned long date_end)
     {
       if (daemon->back_to_the_future == 0 && difftime(timestamp_time, curtime) <= 0)
        {
-         if (utime(daemon->timestamp_file, NULL) != 0)
+         if (utimes(daemon->timestamp_file, NULL) != 0)
            my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
          
+         my_syslog(LOG_INFO, _("system time considered valid, now checking DNSSEC signature timestamps."));
          daemon->back_to_the_future = 1;
-         set_option_bool(OPT_DNSSEC_TIME);
+         daemon->dnssec_no_time_check = 0;
          queue_event(EVENT_RELOAD); /* purge cache */
        } 
 
       if (daemon->back_to_the_future == 0)
        return 1;
     }
-  else if (option_bool(OPT_DNSSEC_TIME))
+  else if (daemon->dnssec_no_time_check)
     return 1;
   
   /* We must explicitly check against wanted values, because of SERIAL_UNDEF */
@@ -505,50 +222,6 @@ static int check_date_range(unsigned long date_start, unsigned long date_end)
     && serial_compare_32(curtime, date_end) == SERIAL_LT;
 }
 
-static u16 *get_desc(int type)
-{
-  /* List of RRtypes which include domains in the data.
-     0 -> domain
-     integer -> no of plain bytes
-     -1 -> end
-
-     zero is not a valid RRtype, so the final entry is returned for
-     anything which needs no mangling.
-  */
-  
-  static u16 rr_desc[] = 
-    { 
-      T_NS, 0, -1, 
-      T_MD, 0, -1,
-      T_MF, 0, -1,
-      T_CNAME, 0, -1,
-      T_SOA, 0, 0, -1,
-      T_MB, 0, -1,
-      T_MG, 0, -1,
-      T_MR, 0, -1,
-      T_PTR, 0, -1,
-      T_MINFO, 0, 0, -1,
-      T_MX, 2, 0, -1,
-      T_RP, 0, 0, -1,
-      T_AFSDB, 2, 0, -1,
-      T_RT, 2, 0, -1,
-      T_SIG, 18, 0, -1,
-      T_PX, 2, 0, 0, -1,
-      T_NXT, 0, -1,
-      T_KX, 2, 0, -1,
-      T_SRV, 6, 0, -1,
-      T_DNAME, 0, -1,
-      0, -1 /* wildcard/catchall */
-    }; 
-  
-  u16 *p = rr_desc;
-  
-  while (*p != type && *p != 0)
-    while (*p++ != (u16)-1);
-
-  return p+1;
-}
-
 /* 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, int bufflen,
@@ -592,34 +265,6 @@ static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end,
     }
 }
 
-static int expand_workspace(unsigned char ***wkspc, int *sz, int new)
-{
-  unsigned char **p;
-  int new_sz = *sz;
-  
-  if (new_sz > new)
-    return 1;
-
-  if (new >= 100)
-    return 0;
-
-  new_sz += 5;
-  
-  if (!(p = whine_malloc((new_sz) * sizeof(unsigned char **))))
-    return 0;  
-  
-  if (*wkspc)
-    {
-      memcpy(p, *wkspc, *sz * sizeof(unsigned char **));
-      free(*wkspc);
-    }
-  
-  *wkspc = p;
-  *sz = new_sz;
-
-  return 1;
-}
-
 /* Bubble sort the RRset into the canonical order. 
    Note that the byte-streams from two RRs may get unsynced: consider 
    RRs which have two domain-names at the start and then other data.
@@ -634,10 +279,10 @@ static int expand_workspace(unsigned char ***wkspc, int *sz, int new)
    leaving the following bytes as deciding the order. Hence the nasty left1 and left2 variables.
 */
 
-static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int rrsetidx, 
-                      unsigned char **rrset, char *buff1, char *buff2)
+static int sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int rrsetidx, 
+                     unsigned char **rrset, char *buff1, char *buff2)
 {
-  int swap, quit, i;
+  int swap, quit, i, j;
   
   do
     {
@@ -699,54 +344,44 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
                  rrset[i] = tmp;
                  swap = quit = 1;
                }
+             else if (rc == 0 && quit && len1 == len2)
+               {
+                 /* Two RRs are equal, remove one copy. RFC 4034, para 6.3 */
+                 for (j = i+1; j < rrsetidx-1; j++)
+                   rrset[j] = rrset[j+1];
+                 rrsetidx--;
+                 i--;
+               }
              else if (rc < 0)
                quit = 1;
            }
        }
     } while (swap);
-}
 
-/* Validate a single RRset (class, type, name) in the supplied DNS reply 
-   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.
-   STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname)
+  return rrsetidx;
+}
 
-   if key is non-NULL, use that key, which has the algo and tag given in the params of those names,
-   otherwise find the key in the cache.
+static unsigned char **rrset = NULL, **sigs = NULL;
 
-   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, char **wildcard_out, struct blockdata *key, int keylen, int algo_in, int keytag_in)
+/* Get pointers to RRset members and signature(s) for same.
+   Check signatures, and return keyname associated in keyname. */
+static int explore_rrset(struct dns_header *header, size_t plen, int class, int type, 
+                        char *name, char *keyname, int *sigcnt, int *rrcnt)
 {
-  static unsigned char **rrset = NULL, **sigs = NULL;
-  static int rrset_sz = 0, sig_sz = 0;
-  
+  static int rrset_sz = 0, sig_sz = 0; 
   unsigned char *p;
-  int rrsetidx, sigidx, res, rdlen, j, name_labels;
-  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;
-  
+  int rrsetidx, sigidx, j, rdlen, res;
+  int gotkey = 0;
+
   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. */
+   /* look for RRSIGs for this RRset and get pointers to each RR in the set. */
   for (rrsetidx = 0, sigidx = 0, j = ntohs(header->ancount) + ntohs(header->nscount); 
        j != 0; j--) 
     {
       unsigned char *pstart, *pdata;
-      int stype, sclass;
+      int stype, sclass, type_covered;
 
       pstart = p;
       
@@ -762,14 +397,14 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
       GETSHORT(rdlen, p);
       
       if (!CHECK_LEN(header, p, plen, rdlen))
-       return STAT_BOGUS
+       return 0
       
       if (res == 1 && sclass == class)
        {
          if (stype == type)
            {
              if (!expand_workspace(&rrset, &rrset_sz, rrsetidx))
-               return STAT_BOGUS
+               return 0
              
              rrset[rrsetidx++] = pstart;
            }
@@ -777,14 +412,46 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
          if (stype == T_RRSIG)
            {
              if (rdlen < 18)
-               return STAT_BOGUS; /* bad packet */ 
+               return 0; /* bad packet */ 
              
              GETSHORT(type_covered, p);
+             p += 16; /* algo, labels, orig_ttl, sig_expiration, sig_inception, key_tag */
+             
+             if (gotkey)
+               {
+                 /* If there's more than one SIG, ensure they all have same keyname */
+                 if (extract_name(header, plen, &p, keyname, 0, 0) != 1)
+                   return 0;
+               }
+             else
+               {
+                 gotkey = 1;
+                 
+                 if (!extract_name(header, plen, &p, keyname, 1, 0))
+                   return 0;
+                 
+                 /* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
+                    the name of the zone containing the RRset. We can't tell that
+                    for certain, but we can check that  the RRset name is equal to
+                    or encloses the signers name, which should be enough to stop 
+                    an attacker using signatures made with the key of an unrelated 
+                    zone he controls. Note that the root key is always allowed. */
+                 if (*keyname != 0)
+                   {
+                     char *name_start;
+                     for (name_start = name; !hostname_isequal(name_start, keyname); )
+                       if ((name_start = strchr(name_start, '.')))
+                         name_start++; /* chop a label off and try again */
+                       else
+                         return 0;
+                   }
+               }
+                 
              
              if (type_covered == type)
                {
                  if (!expand_workspace(&sigs, &sig_sz, sigidx))
-                   return STAT_BOGUS
+                   return 0
                  
                  sigs[sigidx++] = pdata;
                } 
@@ -794,21 +461,49 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
        }
       
       if (!ADD_RDLEN(header, p, plen, rdlen))
-       return STAT_BOGUS;
+       return 0;
     }
   
-  /* RRset empty */
-  if (rrsetidx == 0)
-    return STAT_INSECURE; 
+  *sigcnt = sigidx;
+  *rrcnt = rrsetidx;
+
+  return 1;
+}
+
+/* Validate a single RRset (class, type, name) in the supplied DNS reply 
+   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_BOGUS    signature is wrong, bad packet.
+   STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname)
+   STAT_NEED_DS  need DS to complete validation (name is returned in keyname)
+
+   If key is non-NULL, use that key, which has the algo and tag given in the params of those names,
+   otherwise find the key in the cache.
+
+   Name is unchanged on exit. keyname is used as workspace and trashed.
 
-  /* no RRSIGs */
-  if (sigidx == 0)
-    return STAT_NO_SIG; 
+   Call explore_rrset first to find and count RRs and sigs.
+*/
+static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class, int type, int sigidx, int rrsetidx, 
+                         char *name, char *keyname, char **wildcard_out, struct blockdata *key, int keylen, int algo_in, int keytag_in)
+{
+  unsigned char *p;
+  int rdlen, j, name_labels, algo, labels, orig_ttl, key_tag;
+  struct crec *crecp = NULL;
+  u16 *rr_desc = rrfilter_desc(type);
+  u32 sig_expiration, sig_inception
+;
+  if (wildcard_out)
+    *wildcard_out = NULL;
   
+  name_labels = count_labels(name); /* For 4035 5.3.2 check */
+
   /* Sort RRset records into canonical order. 
      Note that at this point keyname and daemon->workspacename buffs are
      unused, and used as workspace by the sort. */
-  sort_rrset(header, plen, rr_desc, rrsetidx, rrset, daemon->workspacename, keyname);
+  rrsetidx = sort_rrset(header, plen, rr_desc, rrsetidx, rrset, daemon->workspacename, keyname);
          
   /* Now try all the sigs to try and find one which validates */
   for (j = 0; j <sigidx; j++)
@@ -835,37 +530,12 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
       if (!extract_name(header, plen, &p, keyname, 1, 0))
        return STAT_BOGUS;
 
-      /* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
-        the name of the zone containing the RRset. We can't tell that
-        for certain, but we can check that  the RRset name is equal to
-        or encloses the signers name, which should be enough to stop 
-        an attacker using signatures made with the key of an unrelated 
-        zone he controls. Note that the root key is always allowed. */
-      if (*keyname != 0)
-       {
-         int failed = 0;
-         
-         for (name_start = name; !hostname_isequal(name_start, keyname); )
-           if ((name_start = strchr(name_start, '.')))
-             name_start++; /* chop a label off and try again */
-           else
-             {
-               failed = 1;
-               break;
-             }
-
-         /* Bad sig, try another */
-         if (failed)
-           continue;
-       }
-      
-      /* Other 5.3.1 checks */
       if (!check_date_range(sig_inception, sig_expiration) ||
          labels > name_labels ||
          !(hash = hash_find(algo_digest_name(algo))) ||
          !hash_init(hash, &ctx, &digest))
        continue;
-       
+      
       /* OK, we have the signature record, see if the relevant DNSKEY is in the cache. */
       if (!key && !(crecp = cache_find_by_name(NULL, keyname, now, F_DNSKEY)))
        return STAT_NEED_KEY;
@@ -887,6 +557,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
          u16 len, *dp;
          
          p = rrset[i];
+                 
          if (!extract_name(header, plen, &p, name, 1, 10)) 
            return STAT_BOGUS;
 
@@ -968,19 +639,21 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
   return STAT_BOGUS;
 }
  
+
 /* 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_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 
+         STAT_OK        Done, key(s) 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 
+        STAT_NEED_KEY  DNSKEY records to validate a key not found, name in keyname 
 */
 int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
 {
   unsigned char *psave, *p = (unsigned char *)(header+1);
   struct crec *crecp, *recp1;
-  int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, keytag, type_covered;
+  int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, keytag;
   struct blockdata *key;
   struct all_addr a;
 
@@ -1001,10 +674,6 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
       return STAT_NEED_DS;
     }
   
-  /* If we've cached that DS provably doesn't exist, result must be INSECURE */
-  if (crecp->flags & F_NEG)
-    return STAT_INSECURE_DS;
-  
   /* NOTE, we need to find ONE DNSKEY which matches the DS */
   for (valid = 0, j = ntohs(header->ancount); j != 0 && !valid; j--) 
     {
@@ -1057,7 +726,8 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
          void *ctx;
          unsigned char *digest, *ds_digest;
          const struct nettle_hash *hash;
-         
+         int sigcnt, rrcnt;
+
          if (recp1->addr.ds.algo == algo && 
              recp1->addr.ds.keytag == keytag &&
              recp1->uid == (unsigned int)class &&
@@ -1075,10 +745,14 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
              
              from_wire(name);
              
-             if (recp1->addr.ds.keylen == (int)hash->digest_size &&
+             if (!(recp1->flags & F_NEG) &&
+                 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, NULL, key, rdlen - 4, algo, keytag) == STAT_SECURE)
+                 explore_rrset(header, plen, class, T_DNSKEY, name, keyname, &sigcnt, &rrcnt) &&
+                 sigcnt != 0 && rrcnt != 0 &&
+                 validate_rrset(now, header, plen, class, T_DNSKEY, sigcnt, rrcnt, name, keyname, 
+                                NULL, key, rdlen - 4, algo, keytag) == STAT_SECURE)
                {
                  valid = 1;
                  break;
@@ -1090,7 +764,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
 
   if (valid)
     {
-      /* DNSKEY RRset determined to be OK, now cache it and the RRsigs that sign it. */
+      /* DNSKEY RRset determined to be OK, now cache it. */
       cache_start_insert();
       
       p = skip_questions(header, plen);
@@ -1099,7 +773,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
        {
          /* Ensure we have type, class  TTL and length */
          if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
-           return STAT_INSECURE; /* bad packet */
+           return STAT_BOGUS; /* bad packet */
          
          GETSHORT(qtype, p); 
          GETSHORT(qclass, p);
@@ -1130,11 +804,18 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
                  if ((key = blockdata_alloc((char*)p, rdlen - 4)))
                    {
                      if (!(recp1 = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DNSSECOK)))
-                       blockdata_free(key);
+                       {
+                         blockdata_free(key);
+                         return STAT_BOGUS;
+                       }
                      else
                        {
-                         a.addr.keytag = keytag;
-                         log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u");
+                         a.addr.log.keytag = keytag;
+                         a.addr.log.algo = algo;
+                         if (algo_digest_name(algo))
+                           log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %hu, algo %hu");
+                         else
+                           log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %hu, algo %hu (not supported)");
                          
                          recp1->addr.key.keylen = rdlen - 4;
                          recp1->addr.key.keydata = key;
@@ -1144,38 +825,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
                        }
                    }
                }
-             else if (qtype == T_RRSIG)
-               {
-                 /* RRSIG, cache if covers DNSKEY RRset */
-                 if (rdlen < 18)
-                   return STAT_BOGUS; /* bad packet */
-                 
-                 GETSHORT(type_covered, p);
-                 
-                 if (type_covered == T_DNSKEY)
-                   {
-                     a.addr.dnssec.class = class;
-                     a.addr.dnssec.type = type_covered;
-                     
-                     algo = *p++;
-                     p += 13; /* labels, orig_ttl, expiration, inception */
-                     GETSHORT(keytag, p);      
-                     if ((key = blockdata_alloc((char*)psave, rdlen)))
-                       {
-                         if (!(crecp = cache_insert(name, &a, now, ttl,  F_FORWARD | F_DNSKEY | F_DS)))
-                           blockdata_free(key);
-                         else
-                           {
-                             crecp->addr.sig.keydata = key;
-                             crecp->addr.sig.keylen = rdlen;
-                             crecp->addr.sig.keytag = keytag;
-                             crecp->addr.sig.type_covered = type_covered;
-                             crecp->addr.sig.algo = algo;
-                           }
-                       }
-                   }
-               }
-             
+                     
              p = psave;
            }
 
@@ -1185,7 +835,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
       
       /* commit cache insert. */
       cache_end_insert();
-      return STAT_SECURE;
+      return STAT_OK;
     }
 
   log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DNSKEY");
@@ -1194,18 +844,23 @@ 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.
+   Also handles replies which prove that there's no DS at this location, 
+   either because the zone is unsigned or this isn't a zone cut. These are
+   cached too.
    return codes:
-   STAT_SECURE      At least one valid DS found and in cache.
-   STAT_NO_DS       It's proved there's no DS here.
-   STAT_NO_NS       It's proved there's no DS _or_ NS here.
+   STAT_OK          At least one valid DS found and in cache.
    STAT_BOGUS       no DS in reply or not signed, fails validation, bad packet.
    STAT_NEED_KEY    DNSKEY records to validate a DS not found, name in keyname
+   STAT_NEED_DS     DS record needed.
 */
 
 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, nons;
+  int qtype, qclass, rc, i, neganswer, nons;
+  int aclass, atype, rdlen;
+  unsigned long ttl;
+  struct all_addr a;
 
   if (ntohs(header->qdcount) != 1 ||
       !(p = skip_name(p, header, plen, 4)))
@@ -1215,50 +870,111 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
   GETSHORT(qclass, p);
 
   if (qtype != T_DS || qclass != class)
-    val = STAT_BOGUS;
+    rc = STAT_BOGUS;
   else
-    val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, &neganswer, &nons);
-  /* Note dnssec_validate_reply() will have cached positive answers */
+    rc = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons);
   
-  if (val == STAT_INSECURE)
-    val = STAT_BOGUS;
-
+  if (rc == STAT_INSECURE)
+    rc = 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)))
-    val = STAT_BOGUS;
-   
-  /* If we return STAT_NO_SIG, name contains the name of the DS query */
-  if (val == STAT_NO_SIG)
-    {
-      *keyname = 0;
-      return val;
-    }  
-
   /* If the key needed to validate the DS is on the same domain as the DS, we'll
      loop getting nowhere. Stop that now. This can happen of the DS answer comes
      from the DS's zone, and not the parent zone. */
-  if (val == STAT_BOGUS ||  (val == STAT_NEED_KEY && hostname_isequal(name, keyname)))
+  if (rc == STAT_BOGUS || (rc == STAT_NEED_KEY && hostname_isequal(name, keyname)))
     {
       log_query(F_NOEXTRA | 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)
+  
+  if (rc != STAT_SECURE)
+    return rc;
+   
+  if (!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;
+      cache_start_insert();
       
-      /* We only cache validated DS records, DNSSECOK flag hijacked 
-        to store presence/absence of NS. */
-      if (nons)
+      for (i = 0; i < ntohs(header->ancount); i++)
+       {
+         if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
+           return STAT_BOGUS; /* bad packet */
+         
+         GETSHORT(atype, p);
+         GETSHORT(aclass, p);
+         GETLONG(ttl, p);
+         GETSHORT(rdlen, p);
+         
+         if (!CHECK_LEN(header, p, plen, rdlen))
+           return STAT_BOGUS; /* bad packet */
+         
+         if (aclass == class && atype == T_DS && rc == 1)
+           { 
+             int algo, digest, keytag;
+             unsigned char *psave = p;
+             struct blockdata *key;
+             struct crec *crecp;
+
+             if (rdlen < 4)
+               return STAT_BOGUS; /* bad packet */
+             
+             GETSHORT(keytag, p);
+             algo = *p++;
+             digest = *p++;
+             
+             /* Cache needs to known class for DNSSEC stuff */
+             a.addr.dnssec.class = class;
+             
+             if ((key = blockdata_alloc((char*)p, rdlen - 4)))
+               {
+                 if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
+                   {
+                     blockdata_free(key);
+                     return STAT_BOGUS;
+                   }
+                 else
+                   {
+                     a.addr.log.keytag = keytag;
+                     a.addr.log.algo = algo;
+                     a.addr.log.digest = digest;
+                     if (ds_digest_name(digest) && algo_digest_name(algo))
+                       log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu");
+                     else
+                       log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu (not supported)");
+                     
+                     crecp->addr.ds.digest = digest;
+                     crecp->addr.ds.keydata = key;
+                     crecp->addr.ds.algo = algo;
+                     crecp->addr.ds.keytag = keytag;
+                     crecp->addr.ds.keylen = rdlen - 4; 
+                   } 
+               }
+             
+             p = psave;
+           }
+         if (!ADD_RDLEN(header, p, plen, rdlen))
+           return STAT_BOGUS; /* bad packet */
+       }
+
+      cache_end_insert();
+
+    }
+  else
+    {
+      int flags = F_FORWARD | F_DS | F_NEG | F_DNSSECOK;
+      unsigned long minttl = ULONG_MAX;
+      
+      if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
+       return STAT_BOGUS;
+      
+      if (RCODE(header) == NXDOMAIN)
+       flags |= F_NXDOMAIN;
+      
+      /* 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--)
@@ -1266,20 +982,20 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
          if (!(p = skip_name(p, header, plen, 0)))
            return STAT_BOGUS;
          
-         GETSHORT(qtype, p); 
-         GETSHORT(qclass, p);
+         GETSHORT(atype, p); 
+         GETSHORT(aclass, p);
          GETLONG(ttl, p);
          GETSHORT(rdlen, p);
-
+         
          if (!CHECK_LEN(header, p, plen, rdlen))
            return STAT_BOGUS; /* bad packet */
-           
-         if (qclass != class || qtype != T_SOA)
+         
+         if (aclass != class || atype != T_SOA)
            {
              p += rdlen;
              continue;
            }
-           
+         
          if (ttl < minttl)
            minttl = ttl;
          
@@ -1303,19 +1019,19 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
          cache_start_insert();
          
          a.addr.dnssec.class = class;
-         cache_insert(name, &a, now, ttl, flags);
+         if (!cache_insert(name, &a, now, ttl, flags))
+           return STAT_BOGUS;
          
          cache_end_insert();  
          
-         log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no delegation" : "no DS");
+         log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "no DS");
        }
-
-      return nons ? STAT_NO_NS : STAT_NO_DS; 
     }
-
-  return val;
+      
+  return STAT_OK;
 }
 
+
 /* 4034 6.1 */
 static int hostname_cmp(const char *a, const char *b)
 {
@@ -1375,66 +1091,13 @@ static int hostname_cmp(const char *a, const char *b)
       if (sb == b)
        return 1;
       
-      ea = sa--;
-      eb = sb--;
-    }
-}
-
-/* Find all the NSEC or NSEC3 records in a reply.
-   return an array of pointers to them. */
-static int find_nsec_records(struct dns_header *header, size_t plen, unsigned char ***nsecsetp, int *nsecsetl, int class_reqd)
-{
-  static unsigned char **nsecset = NULL;
-  static int nsecset_sz = 0;
-  
-  int type_found = 0;
-  unsigned char *p = skip_questions(header, plen);
-  int type, class, rdlen, i, nsecs_found;
-
-  /* Move to NS section */
-  if (!p || !(p = skip_section(p, ntohs(header->ancount), header, plen)))
-    return 0;
-  
-  for (nsecs_found = 0, i = ntohs(header->nscount); i != 0; i--)
-    {
-      unsigned char *pstart = p;
-      
-      if (!(p = skip_name(p, header, plen, 10)))
-       return 0;
-      
-      GETSHORT(type, p); 
-      GETSHORT(class, p);
-      p += 4; /* TTL */
-      GETSHORT(rdlen, p);
-
-      if (class == class_reqd && (type == T_NSEC || type == T_NSEC3))
-       {
-         /* No mixed NSECing 'round here, thankyouverymuch */
-         if (type_found == T_NSEC && type == T_NSEC3)
-           return 0;
-         if (type_found == T_NSEC3 && type == T_NSEC)
-           return 0;
-
-         type_found = type;
-
-         if (!expand_workspace(&nsecset, &nsecset_sz, nsecs_found))
-           return 0; 
-         
-         nsecset[nsecs_found++] = pstart;
-       }
-      
-      if (!ADD_RDLEN(header, p, plen, rdlen))
-       return 0;
+      ea = --sa;
+      eb = --sb;
     }
-  
-  *nsecsetp = nsecset;
-  *nsecsetl = nsecs_found;
-  
-  return type_found;
 }
 
-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, int *nons)
+static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, unsigned char **labels, int nsec_count,
+                                   char *workspace1_in, char *workspace2, char *name, int type, int *nons)
 {
   int i, rc, rdlen;
   unsigned char *p, *psave;
@@ -1442,27 +1105,50 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
   int mask = 0x80 >> (type & 0x07);
 
   if (nons)
-    *nons = 0;
+    *nons = 1;
   
   /* Find NSEC record that proves name doesn't exist */
   for (i = 0; i < nsec_count; i++)
     {
+      char *workspace1 = workspace1_in;
+      int sig_labels, name_labels;
+
       p = nsecs[i];
       if (!extract_name(header, plen, &p, workspace1, 1, 10))
-       return STAT_BOGUS;
+       return 0;
       p += 8; /* class, type, TTL */
       GETSHORT(rdlen, p);
       psave = p;
       if (!extract_name(header, plen, &p, workspace2, 1, 10))
-       return STAT_BOGUS;
-      
+       return 0;
+
+      /* If NSEC comes from wildcard expansion, use original wildcard
+        as name for computation. */
+      sig_labels = *labels[i];
+      name_labels = count_labels(workspace1);
+
+      if (sig_labels < name_labels)
+       {
+         int k;
+         for (k = name_labels - sig_labels; k != 0; k--)
+           {
+             while (*workspace1 != '.' && *workspace1 != 0)
+               workspace1++;
+             if (k != 1 && *workspace1 == '.')
+               workspace1++;
+           }
+         
+         workspace1--;
+         *workspace1 = '*';
+       }
+         
       rc = hostname_cmp(workspace1, name);
       
       if (rc == 0)
        {
          /* 4035 para 5.4. Last sentence */
          if (type == T_NSEC || type == T_RRSIG)
-           return STAT_SECURE;
+           return 1;
 
          /* NSEC with the same name as the RR we're testing, check
             that the type in question doesn't appear in the type map */
@@ -1470,45 +1156,59 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
          /* 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;
+         if (nons && rdlen >= 2 && p[0] == 0 && (p[2] & (0x80 >> T_NS)) != 0)
+           *nons = 0;
          
+         if (rdlen >= 2 && p[0] == 0)
+           {
+             /* A CNAME answer would also be valid, so if there's a CNAME is should 
+                have been returned. */
+             if ((p[2] & (0x80 >> T_CNAME)) != 0)
+               return 0;
+             
+             /* If the SOA bit is set for a DS record, then we have the
+                DS from the wrong side of the delegation. For the root DS, 
+                this is expected. */
+             if (name_labels != 0 && type == T_DS && (p[2] & (0x80 >> T_SOA)) != 0)
+               return 0;
+           }
+
          while (rdlen >= 2)
            {
              if (!CHECK_LEN(header, p, plen, rdlen))
-               return STAT_BOGUS;
+               return 0;
              
              if (p[0] == type >> 8)
                {
                  /* Does the NSEC say our type exists? */
                  if (offset < p[1] && (p[offset+2] & mask) != 0)
-                   return STAT_BOGUS;
+                   return 0;
                  
-                 break; /* finshed checking */
+                 break; /* finished checking */
                }
              
              rdlen -= p[1];
              p +=  p[1];
            }
          
-         return STAT_SECURE;
+         return 1;
        }
       else if (rc == -1)
        {
          /* Normal case, name falls between NSEC name and next domain name,
             wrap around case, name falls between NSEC name (rc == -1) and end */
          if (hostname_cmp(workspace2, name) >= 0 || hostname_cmp(workspace1, workspace2) >= 0)
-           return STAT_SECURE;
+           return 1;
        }
       else 
        {
          /* wrap around case, name falls between start and next domain name */
          if (hostname_cmp(workspace1, workspace2) >= 0 && hostname_cmp(workspace2, name) >=0 )
-           return STAT_SECURE;
+           return 1;
        }
     }
   
-  return STAT_BOGUS;
+  return 0;
 }
 
 /* return digest length, or zero on error */
@@ -1574,9 +1274,9 @@ 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, int *nons)
+                               char *workspace1, char *workspace2, unsigned char **nsecs, int nsec_count, int *nons, int name_labels)
 {
-  int i, hash_len, salt_len, base32_len, rdlen;
+  int i, hash_len, salt_len, base32_len, rdlen, flags;
   unsigned char *p, *psave;
 
   for (i = 0; i < nsec_count; i++)
@@ -1589,7 +1289,9 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
        p += 8; /* class, type, TTL */
        GETSHORT(rdlen, p);
        psave = p;
-       p += 4; /* algo, flags, iterations */
+       p++; /* algo */
+       flags = *p++; /* flags */
+       p += 2; /* iterations */
        salt_len = *p++; /* salt_len */
        p += salt_len; /* salt */
        hash_len = *p++; /* p now points to next hashed name */
@@ -1615,25 +1317,39 @@ 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;
+               if (rdlen >= 2 && p[0] == 0)
+                 {
+                   /* If we can prove that there's no NS record, return that information. */
+                   if (nons && (p[2] & (0x80 >> T_NS)) != 0)
+                     *nons = 0;
                
+                   /* A CNAME answer would also be valid, so if there's a CNAME is should 
+                      have been returned. */
+                   if ((p[2] & (0x80 >> T_CNAME)) != 0)
+                     return 0;
+                   
+                   /* If the SOA bit is set for a DS record, then we have the
+                      DS from the wrong side of the delegation. For the root DS, 
+                      this is expected.  */
+                   if (name_labels != 0 && type == T_DS && (p[2] & (0x80 >> T_SOA)) != 0)
+                     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;
+                         return 0;
                        
-                       break; /* finshed checking */
+                       break; /* finished checking */
                      }
                    
                    rdlen -= p[1];
                    p +=  p[1];
                  }
-
+               
                return 1;
              }
            else if (rc < 0)
@@ -1641,16 +1357,27 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
                /* 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;
+                 {
+                   if ((flags & 0x01) && nons) /* opt out */
+                     *nons = 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;
+                 {
+                   if ((flags & 0x01) && nons) /* opt out */
+                     *nons = 0;
+
+                   return 1;
+                 }
              }
          }
       }
+
   return 0;
 }
 
@@ -1663,10 +1390,10 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
   char *closest_encloser, *next_closest, *wildcard;
   
   if (nons)
-    *nons = 0;
+    *nons = 1;
   
   /* Look though the NSEC3 records to find the first one with 
-     an algorithm we support (currently only algo == 1).
+     an algorithm we support.
 
      Take the algo, iterations, and salt of that record
      as the ones we're going to use, and prune any 
@@ -1675,44 +1402,56 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
   for (i = 0; i < nsec_count; i++)
     {
       if (!(p = skip_name(nsecs[i], header, plen, 15)))
-       return STAT_BOGUS; /* bad packet */
+       return 0; /* bad packet */
       
       p += 10; /* type, class, TTL, rdlen */
       algo = *p++;
       
-      if (algo == 1)
+      if ((hash = hash_find(nsec3_digest_name(algo))))
        break; /* known algo */
     }
 
   /* No usable NSEC3s */
   if (i == nsec_count)
-    return STAT_BOGUS;
+    return 0;
 
   p++; /* flags */
+
   GETSHORT (iterations, p);
+  /* Upper-bound iterations, to avoid DoS.
+     Strictly, there are lower bounds for small keys, but
+     since we don't have key size info here, at least limit
+     to the largest bound, for 4096-bit keys. RFC 5155 10.3 */
+  if (iterations > 2500)
+    return 0;
+  
   salt_len = *p++;
   salt = p;
   if (!CHECK_LEN(header, salt, plen, salt_len))
-    return STAT_BOGUS; /* bad packet */
+    return 0; /* bad packet */
     
   /* Now prune so we only have NSEC3 records with same iterations, salt and algo */
   for (i = 0; i < nsec_count; i++)
     {
       unsigned char *nsec3p = nsecs[i];
-      int this_iter;
+      int this_iter, flags;
 
       nsecs[i] = NULL; /* Speculative, will be restored if OK. */
       
       if (!(p = skip_name(nsec3p, header, plen, 15)))
-       return STAT_BOGUS; /* bad packet */
+       return 0; /* bad packet */
       
       p += 10; /* type, class, TTL, rdlen */
       
       if (*p++ != algo)
        continue;
  
-      p++; /* flags */
+      flags = *p++; /* flags */
       
+      /* 5155 8.2 */
+      if (flags != 0 && flags != 1)
+       continue;
+
       GETSHORT(this_iter, p);
       if (this_iter != iterations)
        continue;
@@ -1721,7 +1460,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
        continue;
       
       if (!CHECK_LEN(header, p, plen, salt_len))
-       return STAT_BOGUS; /* bad packet */
+       return 0; /* bad packet */
 
       if (memcmp(p, salt, salt_len) != 0)
        continue;
@@ -1730,15 +1469,11 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
       nsecs[i] = nsec3p;
     }
 
-  /* Algo is checked as 1 above */
-  if (!(hash = hash_find("sha1")))
-    return STAT_BOGUS;
-
   if ((digest_len = hash_name(name, &digest, hash, salt, salt_len, iterations)) == 0)
-    return STAT_BOGUS;
+    return 0;
   
-  if (check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, nons))
-    return STAT_SECURE;
+  if (check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, nons, count_labels(name)))
+    return 1;
 
   /* Can't find an NSEC3 which covers the name directly, we need the "closest encloser NSEC3" 
      or an answer inferred from a wildcard record. */
@@ -1754,14 +1489,14 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
        break;
 
       if ((digest_len = hash_name(closest_encloser, &digest, hash, salt, salt_len, iterations)) == 0)
-       return STAT_BOGUS;
+       return 0;
       
       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;
+             return 0;
          
            if (digest_len == base32_len &&
                memcmp(digest, workspace2, digest_len) == 0)
@@ -1775,441 +1510,493 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
     }
   while ((closest_encloser = strchr(closest_encloser, '.')));
   
-  if (!closest_encloser)
-    return STAT_BOGUS;
+  if (!closest_encloser || !next_closest)
+    return 0;
   
   /* 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;
+    return 0;
 
-  if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, NULL))
-    return STAT_BOGUS;
+  if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, NULL, 1))
+    return 0;
   
   /* Finally, check that there's no seat of wildcard synthesis */
   if (!wildname)
     {
       if (!(wildcard = strchr(next_closest, '.')) || wildcard == next_closest)
-       return STAT_BOGUS;
+       return 0;
       
       wildcard--;
       *wildcard = '*';
       
       if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0)
-       return STAT_BOGUS;
+       return 0;
       
-      if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, NULL))
-       return STAT_BOGUS;
+      if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, NULL, 1))
+       return 0;
     }
   
-  return STAT_SECURE;
+  return 1;
 }
-    
-/* 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 *nons)
-{
-  unsigned char *ans_start, *qname, *p1, *p2, **nsecs;
-  int type1, class1, rdlen1, type2, class2, rdlen2, qclass, qtype;
-  int i, j, rc, nsec_count, cname_count = CNAME_CHAIN;
-  int nsec_type = 0, have_answer = 0;
 
-  if (neganswer)
-    *neganswer = 0;
+static int prove_non_existence(struct dns_header *header, size_t plen, char *keyname, char *name, int qtype, int qclass, char *wildname, int *nons)
+{
+  static unsigned char **nsecset = NULL, **rrsig_labels = NULL;
+  static int nsecset_sz = 0, rrsig_labels_sz = 0;
   
-  if (RCODE(header) == SERVFAIL || ntohs(header->qdcount) != 1)
-    return STAT_BOGUS;
+  int type_found = 0;
+  unsigned char *auth_start, *p = skip_questions(header, plen);
+  int type, class, rdlen, i, nsecs_found;
   
-  if (RCODE(header) != NXDOMAIN && RCODE(header) != NOERROR)
-    return STAT_INSECURE;
+  /* Move to NS section */
+  if (!p || !(p = skip_section(p, ntohs(header->ancount), header, plen)))
+    return 0;
 
-  qname = p1 = (unsigned char *)(header+1);
+  auth_start = p;
   
-  if (!extract_name(header, plen, &p1, name, 1, 4))
-    return STAT_BOGUS;
-
-  GETSHORT(qtype, p1);
-  GETSHORT(qclass, p1);
-  ans_start = p1;
-
-  if (qtype == T_ANY)
-    have_answer = 1;
-  /* Can't validate an RRISG query */
-  if (qtype == T_RRSIG)
-    return STAT_INSECURE;
- cname_loop:
-  for (j = ntohs(header->ancount); j != 0; j--) 
+  for (nsecs_found = 0, i = ntohs(header->nscount); i != 0; i--)
     {
-      /* leave pointer to missing name in qname */
-           
-      if (!(rc = extract_name(header, plen, &p1, name, 0, 10)))
-       return STAT_BOGUS; /* bad packet */
+      unsigned char *pstart = p;
       
-      GETSHORT(type2, p1); 
-      GETSHORT(class2, p1);
-      p1 += 4; /* TTL */
-      GETSHORT(rdlen2, p1);
+      if (!extract_name(header, plen, &p, daemon->workspacename, 1, 10))
+       return 0;
+         
+      GETSHORT(type, p); 
+      GETSHORT(class, p);
+      p += 4; /* TTL */
+      GETSHORT(rdlen, p);
 
-      if (rc == 1 && qclass == class2)
+      if (class == qclass && (type == T_NSEC || type == T_NSEC3))
        {
-         /* Do we have an answer for the question? */
-         if (type2 == qtype)
-           {
-             have_answer = 1;
-             break;
-           }
-         else if (type2 == T_CNAME)
+         /* No mixed NSECing 'round here, thankyouverymuch */
+         if (type_found != 0 && type_found != type)
+           return 0;
+
+         type_found = type;
+
+         if (!expand_workspace(&nsecset, &nsecset_sz, nsecs_found))
+           return 0; 
+         
+         if (type == T_NSEC)
            {
-             qname = p1;
+             /* If we're looking for NSECs, find the corresponding SIGs, to 
+                extract the labels value, which we need in case the NSECs
+                are the result of wildcard expansion.
+                Note that the NSEC may not have been validated yet
+                so if there are multiple SIGs, make sure the label value
+                is the same in all, to avoid be duped by a rogue one.
+                If there are no SIGs, that's an error */
+             unsigned char *p1 = auth_start;
+             int res, j, rdlen1, type1, class1;
              
-             /* looped CNAMES */
-             if (!cname_count-- || !extract_name(header, plen, &p1, name, 1, 0))
-               return STAT_BOGUS;
-              
-             p1 = ans_start;
-             goto cname_loop;
+             if (!expand_workspace(&rrsig_labels, &rrsig_labels_sz, nsecs_found))
+               return 0;
+             
+             rrsig_labels[nsecs_found] = NULL;
+             
+             for (j = ntohs(header->nscount); j != 0; j--)
+               {
+                 if (!(res = extract_name(header, plen, &p1, daemon->workspacename, 0, 10)))
+                   return 0;
+
+                  GETSHORT(type1, p1); 
+                  GETSHORT(class1, p1);
+                  p1 += 4; /* TTL */
+                  GETSHORT(rdlen1, p1);
+
+                  if (!CHECK_LEN(header, p1, plen, rdlen1))
+                    return 0;
+                  
+                  if (res == 1 && class1 == qclass && type1 == T_RRSIG)
+                    {
+                      int type_covered;
+                      unsigned char *psav = p1;
+                      
+                      if (rdlen1 < 18)
+                        return 0; /* bad packet */
+
+                      GETSHORT(type_covered, p1);
+
+                      if (type_covered == T_NSEC)
+                        {
+                          p1++; /* algo */
+                          
+                          /* labels field must be the same in every SIG we find. */
+                          if (!rrsig_labels[nsecs_found])
+                            rrsig_labels[nsecs_found] = p1;
+                          else if (*rrsig_labels[nsecs_found] != *p1) /* algo */
+                            return 0;
+                          }
+                      p1 = psav;
+                    }
+                  
+                  if (!ADD_RDLEN(header, p1, plen, rdlen1))
+                    return 0;
+               }
+
+             /* Must have found at least one sig. */
+             if (!rrsig_labels[nsecs_found])
+               return 0;
            }
-       } 
 
-      if (!ADD_RDLEN(header, p1, plen, rdlen2))
-       return STAT_BOGUS;
+         nsecset[nsecs_found++] = pstart;   
+       }
+      
+      if (!ADD_RDLEN(header, p, plen, rdlen))
+       return 0;
     }
-   
-  if (neganswer && !have_answer)
-    *neganswer = 1;
   
-  /* No data, therefore no sigs */
-  if (ntohs(header->ancount) + ntohs(header->nscount) == 0)
+  if (type_found == T_NSEC)
+    return prove_non_existence_nsec(header, plen, nsecset, rrsig_labels, nsecs_found, daemon->workspacename, keyname, name, qtype, nons);
+  else if (type_found == T_NSEC3)
+    return prove_non_existence_nsec3(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, wildname, nons);
+  else
+    return 0;
+}
+
+/* Check signing status of name.
+   returns:
+   STAT_SECURE   zone is signed.
+   STAT_INSECURE zone proved unsigned.
+   STAT_NEED_DS  require DS record of name returned in keyname.
+   STAT_NEED_KEY require DNSKEY record of name returned in keyname.
+   name returned unaltered.
+*/
+static int zone_status(char *name, int class, char *keyname, time_t now)
+{
+  int name_start = strlen(name); /* for when TA is root */
+  struct crec *crecp;
+  char *p;
+
+  /* First, work towards the root, looking for a trust anchor.
+     This can either be one configured, or one previously cached.
+     We can assume, if we don't find one first, that there is
+     a trust anchor at the root. */
+  for (p = name; p; p = strchr(p, '.'))
     {
-      *keyname = 0;
-      return STAT_NO_SIG;
+      if (*p == '.')
+       p++;
+
+      if (cache_find_by_name(NULL, p, now, F_DS))
+       {
+         name_start = p - name;
+         break;
+       }
     }
 
-  for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
+  /* Now work away from the trust anchor */
+  while (1)
     {
-      if (!extract_name(header, plen, &p1, name, 1, 10))
-       return STAT_BOGUS; /* bad packet */
+      strcpy(keyname, &name[name_start]);
       
-      GETSHORT(type1, p1);
-      GETSHORT(class1, p1);
-      p1 += 4; /* TTL */
-      GETSHORT(rdlen1, p1);
+      if (!(crecp = cache_find_by_name(NULL, keyname, now, F_DS)))
+       return STAT_NEED_DS;
       
-      /* Don't try and validate RRSIGs! */
-      if (type1 != T_RRSIG)
+       /* F_DNSSECOK misused in DS cache records to non-existence of NS record.
+         F_NEG && !F_DNSSECOK implies that we've proved there's no DS record here,
+         but that's because there's no NS record either, ie this isn't the start
+         of a zone. We only prove that the DNS tree below a node is unsigned when
+         we prove that we're at a zone cut AND there's no DS record. */
+      if (crecp->flags & F_NEG)
+       {
+         if (crecp->flags & F_DNSSECOK)
+           return STAT_INSECURE; /* proved no DS here */
+       }
+      else
        {
-         /* Check if we've done this RRset already */
-         for (p2 = ans_start, j = 0; j < i; j++)
+         /* If all the DS records have digest and/or sig algos we don't support,
+            then the zone is insecure. Note that if an algo
+            appears in the DS, then RRSIGs for that algo MUST
+            exist for each RRset: 4035 para 2.2  So if we find
+            a DS here with digest and sig we can do, we're entitled
+            to assume we can validate the zone and if we can't later,
+            because an RRSIG is missing we return BOGUS.
+         */
+         do 
            {
-             if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
-               return STAT_BOGUS; /* bad packet */
-             
-             GETSHORT(type2, p2);
-             GETSHORT(class2, p2);
-             p2 += 4; /* TTL */
-             GETSHORT(rdlen2, p2);
-             
-             if (type2 == type1 && class2 == class1 && rc == 1)
-               break; /* Done it before: name, type, class all match. */
-             
-             if (!ADD_RDLEN(header, p2, plen, rdlen2))
-               return STAT_BOGUS;
+             if (crecp->uid == (unsigned int)class &&
+                 ds_digest_name(crecp->addr.ds.digest) &&
+                 algo_digest_name(crecp->addr.ds.algo))
+               break;
            }
-         
-         /* Not done, validate now */
-         if (j == i)
-           {
-             int ttl, keytag, algo, digest, type_covered;
-             unsigned char *psave;
-             struct all_addr a;
-             struct blockdata *key;
-             struct crec *crecp;
-             char *wildname;
-             int have_wildcard = 0;
+         while ((crecp = cache_find_by_name(crecp, keyname, now, F_DS)));
 
-             rc = validate_rrset(now, header, plen, class1, type1, name, keyname, &wildname, NULL, 0, 0, 0);
-             
-             if (rc == STAT_SECURE_WILDCARD)
-               {
-                 have_wildcard = 1;
+         if (!crecp)
+           return STAT_INSECURE;
+       }
 
-                 /* 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
-                    the gennuine record doesn't exist. Check that here. */
-                 if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, class1)))
-                   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, NULL);
-                 else
-                   rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, 
-                                                  keyname, name, type1, wildname, NULL);
-                 
-                 if (rc != STAT_SECURE)
-                   return rc;
-               } 
-             else if (rc != STAT_SECURE)
-               {
-                 if (class)
-                   *class = class1; /* Class for DS or DNSKEY */
+      if (name_start == 0)
+       break;
 
-                 if (rc == STAT_NO_SIG)
-                   {
-                     /* If we dropped off the end of a CNAME chain, return
-                        STAT_NO_SIG and the last name is keyname. This is used for proving non-existence
-                        if DS records in CNAME chains. */
-                     if (cname_count == CNAME_CHAIN || i < ntohs(header->ancount)) 
-                       /* No CNAME chain, or no sig in answer section, return empty name. */
-                       *keyname = 0;
-                     else if (!extract_name(header, plen, &qname, keyname, 1, 0))
-                       return STAT_BOGUS;
-                   }
-                 return rc;
-               }
-             
-             /* Cache RRsigs in answer section, and if we just validated a DS RRset, cache it */
-             cache_start_insert();
-             
-             for (p2 = ans_start, j = 0; j < ntohs(header->ancount); j++)
-               {
-                 if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
-                   return STAT_BOGUS; /* bad packet */
-                     
-                 GETSHORT(type2, p2);
-                 GETSHORT(class2, p2);
-                 GETLONG(ttl, p2);
-                 GETSHORT(rdlen2, p2);
-                      
-                 if (!CHECK_LEN(header, p2, plen, rdlen2))
-                   return STAT_BOGUS; /* bad packet */
-                 
-                 if (class2 == class1 && rc == 1)
-                   { 
-                     psave = p2;
+      for (p = &name[name_start-2]; (*p != '.') && (p != name); p--);
+      
+      if (p != name)
+        p++;
+      
+      name_start = p - name;
+    } 
 
-                     if (type1 == T_DS && type2 == T_DS)
-                       {
-                         if (rdlen2 < 4)
-                           return STAT_BOGUS; /* bad packet */
-                         
-                         GETSHORT(keytag, p2);
-                         algo = *p2++;
-                         digest = *p2++;
-                         
-                         /* Cache needs to known class for DNSSEC stuff */
-                         a.addr.dnssec.class = class2;
-                         
-                         if ((key = blockdata_alloc((char*)p2, rdlen2 - 4)))
-                           {
-                             if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
-                               blockdata_free(key);
-                             else
-                               {
-                                 a.addr.keytag = keytag;
-                                 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;
-                                 crecp->addr.ds.keytag = keytag;
-                                 crecp->addr.ds.keylen = rdlen2 - 4; 
-                               } 
-                           }
-                       }
-                     else if (type2 == T_RRSIG)
-                       {
-                         if (rdlen2 < 18)
-                           return STAT_BOGUS; /* bad packet */
-                         
-                         GETSHORT(type_covered, p2);
-
-                         if (type_covered == type1 && 
-                             (type_covered == T_A || type_covered == T_AAAA ||
-                              type_covered == T_CNAME || type_covered == T_DS || 
-                              type_covered == T_DNSKEY || type_covered == T_PTR)) 
-                           {
-                             a.addr.dnssec.type = type_covered;
-                             a.addr.dnssec.class = class1;
-                             
-                             algo = *p2++;
-                             p2 += 13; /* labels, orig_ttl, expiration, inception */
-                             GETSHORT(keytag, p2);
-                             
-                             /* 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);
-                                 else
-                                   {
-                                     crecp->addr.sig.keydata = key;
-                                     crecp->addr.sig.keylen = rdlen2;
-                                     crecp->addr.sig.keytag = keytag;
-                                     crecp->addr.sig.type_covered = type_covered;
-                                     crecp->addr.sig.algo = algo;
-                                   }
-                               }
-                           }
-                       }
-                     
-                     p2 = psave;
-                   }
-                 
-                 if (!ADD_RDLEN(header, p2, plen, rdlen2))
-                   return STAT_BOGUS; /* bad packet */
-               }
-                 
-             cache_end_insert();
-           }
-       }
+  return STAT_SECURE;
+}
+       
+/* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3) 
+   Return code:
+   STAT_SECURE   if it validates.
+   STAT_INSECURE at least one RRset not validated, because in unsigned zone.
+   STAT_BOGUS    signature is wrong, bad packet, no validation where there should be.
+   STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname, class in *class)
+   STAT_NEED_DS  need DS to complete validation (name is returned in keyname)
 
-      if (!ADD_RDLEN(header, p1, plen, rdlen1))
-       return STAT_BOGUS;
-    }
+   daemon->rr_status points to a char array which corressponds to the RRs in the 
+   answer section (only). This is set to 1 for each RR which is validated, and 0 for any which aren't.
+*/
+int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, 
+                         int *class, int check_unsigned, int *neganswer, int *nons)
+{
+  static unsigned char **targets = NULL;
+  static int target_sz = 0;
 
-  /* OK, all the RRsets validate, now see if we have a NODATA or NXDOMAIN reply */
-  if (have_answer)
-    return STAT_SECURE;
-     
-  /* NXDOMAIN or NODATA reply, prove that (name, class1, type1) can't exist */
-  /* First marshall the NSEC records, if we've not done it previously */
-  if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, qclass)))
+  unsigned char *ans_start, *p1, *p2;
+  int type1, class1, rdlen1 = 0, type2, class2, rdlen2, qclass, qtype, targetidx;
+  int i, j, rc;
+  int secure = STAT_SECURE;
+
+  /* extend rr_status if necessary */
+  if (daemon->rr_status_sz < ntohs(header->ancount))
     {
-      /* No NSEC records. If we dropped off the end of a CNAME chain, return
-        STAT_NO_SIG and the last name is keyname. This is used for proving non-existence
-        if DS records in CNAME chains. */
-      if (cname_count == CNAME_CHAIN) /* No CNAME chain, return empty name. */
-       *keyname = 0;
-      else if (!extract_name(header, plen, &qname, keyname, 1, 0))
+      char *new = whine_malloc(ntohs(header->ancount) + 64);
+
+      if (!new)
        return STAT_BOGUS;
-      return STAT_NO_SIG; /* No NSECs, this is probably a dangling CNAME pointing into
-                            an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
+
+      free(daemon->rr_status);
+      daemon->rr_status = new;
+      daemon->rr_status_sz = ntohs(header->ancount) + 64;
     }
-   
-  /* Get name of missing answer */
-  if (!extract_name(header, plen, &qname, name, 1, 0))
+  
+  memset(daemon->rr_status, 0, ntohs(header->ancount));
+  
+  if (neganswer)
+    *neganswer = 0;
+  
+  if (RCODE(header) == SERVFAIL || ntohs(header->qdcount) != 1)
     return STAT_BOGUS;
   
-  if (nsec_type == T_NSEC)
-    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, nons);
-}
+  if (RCODE(header) != NXDOMAIN && RCODE(header) != NOERROR)
+    return STAT_INSECURE;
 
-/* Chase the CNAME chain in the packet until the first record which _doesn't validate.
-   Needed for proving answer in unsigned space.
-   Return STAT_NEED_* 
-          STAT_BOGUS - error
-          STAT_INSECURE - name of first non-secure record in name 
-*/
-int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname)
-{
-  unsigned char *p = (unsigned char *)(header+1);
-  int type, class, qclass, rdlen, j, rc;
-  int cname_count = CNAME_CHAIN;
-  char *wildname;
+  p1 = (unsigned char *)(header+1);
+  
+   /* Find all the targets we're looking for answers to.
+     The zeroth array element is for the query, subsequent ones
+     for CNAME targets, unless the query is for a CNAME. */
 
-  /* Get question */
-  if (!extract_name(header, plen, &p, name, 1, 4))
+  if (!expand_workspace(&targets, &target_sz, 0))
     return STAT_BOGUS;
   
-  p +=2; /* type */
-  GETSHORT(qclass, p);
-
-  while (1)
+  targets[0] = p1;
+  targetidx = 1;
+   
+  if (!extract_name(header, plen, &p1, name, 1, 4))
+    return STAT_BOGUS;
+  
+  GETSHORT(qtype, p1);
+  GETSHORT(qclass, p1);
+  ans_start = p1;
+  /* Can't validate an RRSIG query */
+  if (qtype == T_RRSIG)
+    return STAT_INSECURE;
+  
+  if (qtype != T_CNAME)
+    for (j = ntohs(header->ancount); j != 0; j--) 
+      {
+       if (!(p1 = skip_name(p1, header, plen, 10)))
+         return STAT_BOGUS; /* bad packet */
+       
+       GETSHORT(type2, p1); 
+       p1 += 6; /* class, TTL */
+       GETSHORT(rdlen2, p1);  
+       
+       if (type2 == T_CNAME)
+         {
+           if (!expand_workspace(&targets, &target_sz, targetidx))
+             return STAT_BOGUS;
+           
+           targets[targetidx++] = p1; /* pointer to target name */
+         }
+       
+       if (!ADD_RDLEN(header, p1, plen, rdlen2))
+         return STAT_BOGUS;
+      }
+  
+  for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
     {
-      for (j = ntohs(header->ancount); j != 0; j--) 
+       if (i != 0 && !ADD_RDLEN(header, p1, plen, rdlen1))
+        return STAT_BOGUS;
+
+       if (!extract_name(header, plen, &p1, name, 1, 10))
+       return STAT_BOGUS; /* bad packet */
+      
+      GETSHORT(type1, p1);
+      GETSHORT(class1, p1);
+      p1 += 4; /* TTL */
+      GETSHORT(rdlen1, p1);
+      
+      /* Don't try and validate RRSIGs! */
+      if (type1 == T_RRSIG)
+       continue;
+      
+      /* Check if we've done this RRset already */
+      for (p2 = ans_start, j = 0; j < i; j++)
        {
-         if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
+         if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
            return STAT_BOGUS; /* bad packet */
          
-         GETSHORT(type, p); 
-         GETSHORT(class, p);
-         p += 4; /* TTL */
-         GETSHORT(rdlen, p);
-
-         /* Not target, loop */
-         if (rc == 2 || qclass != class)
-           {
-             if (!ADD_RDLEN(header, p, plen, rdlen))
-               return STAT_BOGUS;
-             continue;
-           }
+         GETSHORT(type2, p2);
+         GETSHORT(class2, p2);
+         p2 += 4; /* TTL */
+         GETSHORT(rdlen2, p2);
          
-         /* Got to end of CNAME chain. */
-         if (type != T_CNAME)
-           return STAT_INSECURE;
+         if (type2 == type1 && class2 == class1 && rc == 1)
+           break; /* Done it before: name, type, class all match. */
+         
+         if (!ADD_RDLEN(header, p2, plen, rdlen2))
+           return STAT_BOGUS;
+       }
+      
+      if (j != i)
+       {
+         /* Done already: copy the validation status */
+         if (i < ntohs(header->ancount))
+           daemon->rr_status[i] = daemon->rr_status[j];
+       }
+      else
+       {
+         /* Not done, validate now */
+         int sigcnt, rrcnt;
+         char *wildname;
+         
+         if (!explore_rrset(header, plen, class1, type1, name, keyname, &sigcnt, &rrcnt))
+           return STAT_BOGUS;
          
-         /* validate CNAME chain, return if insecure or need more data */
-         rc = validate_rrset(now, header, plen, class, type, name, keyname, &wildname, NULL, 0, 0, 0);
-          
-         if (rc == STAT_SECURE_WILDCARD)
+         /* No signatures for RRset. We can be configured to assume this is OK and return an INSECURE result. */
+         if (sigcnt == 0)
            {
-             int nsec_type, nsec_count, i;
-             unsigned char **nsecs;
-
-             /* An attacker can replay a wildcard answer with a different
-                answer and overlay a genuine RR. To prove this
-                hasn't happened, the answer must prove that
-                the genuine record doesn't exist. Check that here. */
-             if (!(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, class)))
-               return STAT_BOGUS; /* No NSECs or bad packet */
-             
-             /* Note that we're called here because something didn't validate in validate_reply,
-                so we can't assume that any NSEC records have been validated. We do them by steam here */
-
-             for (i = 0; i < nsec_count; i++)
+             if (check_unsigned)
                {
-                 unsigned char *p1 = nsecs[i];
-                 
-                 if (!extract_name(header, plen, &p1, daemon->workspacename, 1, 0))
-                   return STAT_BOGUS;
-
-                 rc = validate_rrset(now, header, plen, class, nsec_type, daemon->workspacename, keyname, NULL, NULL, 0, 0, 0);
-
-                 /* NSECs can't be wildcards. */
-                 if (rc == STAT_SECURE_WILDCARD)
+                 rc = zone_status(name, class1, keyname, now);
+                 if (rc == STAT_SECURE)
                    rc = STAT_BOGUS;
-
-                 if (rc != STAT_SECURE)
-                   return rc;
+                 if (class)
+                   *class = class1; /* Class for NEED_DS or NEED_KEY */
                }
-
-             if (nsec_type == T_NSEC)
-               rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type, NULL);
-             else
-               rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, 
-                                              keyname, name, type, wildname, NULL);
+             else 
+               rc = STAT_INSECURE; 
              
-             if (rc != STAT_SECURE)
+             if (rc != STAT_INSECURE)
                return rc;
            }
-         
-         if (rc != STAT_SECURE)
+         else
            {
-             if (rc == STAT_NO_SIG)
-               rc = STAT_INSECURE;
-             return rc;
-           }
+             /* explore_rrset() gives us key name from sigs in keyname.
+                Can't overwrite name here. */
+             strcpy(daemon->workspacename, keyname);
+             rc = zone_status(daemon->workspacename, class1, keyname, now);
+             
+             if (rc == STAT_BOGUS || rc == STAT_NEED_KEY || rc == STAT_NEED_DS)
+               {
+                 /* Zone is insecure, don't need to validate RRset */
+                 if (class)
+                   *class = class1; /* Class for NEED_DS or NEED_KEY */
+                 return rc;
+               }
+             
+             /* Zone is insecure, don't need to validate RRset */
+             if (rc == STAT_SECURE)
+               {
+                 rc = validate_rrset(now, header, plen, class1, type1, sigcnt,
+                                     rrcnt, name, keyname, &wildname, NULL, 0, 0, 0);
+                 
+                 if (rc == STAT_BOGUS || rc == STAT_NEED_KEY || rc == STAT_NEED_DS)
+                   {
+                     if (class)
+                       *class = class1; /* Class for DS or DNSKEY */
+                     return rc;
+                   } 
+                 
+                 /* rc is now STAT_SECURE or STAT_SECURE_WILDCARD */
+                 
+                 /* Note that RR is validated */
+                  if (i < ntohs(header->ancount))
+                    daemon->rr_status[i] = 1;
+                  
+                 /* Note if we've validated either the answer to the question
+                    or the target of a CNAME. Any not noted will need NSEC or
+                    to be in unsigned space. */
+                 for (j = 0; j <targetidx; j++)
+                   if ((p2 = targets[j]))
+                     {
+                       int rc1;
+                       if (!(rc1 = extract_name(header, plen, &p2, name, 0, 10)))
+                         return STAT_BOGUS; /* bad packet */
+                       
+                       if (class1 == qclass && rc1 == 1 && (type1 == T_CNAME || type1 == qtype || qtype == T_ANY ))
+                         targets[j] = NULL;
+                     }
+                 
+                 /* 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
+                    the genuine record doesn't exist. Check that here. 
+                    Note that we may not yet have validated the NSEC/NSEC3 RRsets. 
+                    That's not a problem since if the RRsets later fail
+                    we'll return BOGUS then. */
+                 if (rc == STAT_SECURE_WILDCARD &&
+                     !prove_non_existence(header, plen, keyname, name, type1, class1, wildname, NULL))
+                   return STAT_BOGUS;
 
-         /* Loop down CNAME chain/ */
-         if (!cname_count-- || 
-             !extract_name(header, plen, &p, name, 1, 0) ||
-             !(p = skip_questions(header, plen)))
-           return STAT_BOGUS;
-         
-         break;
+                 rc = STAT_SECURE;
+               }
+           }
        }
 
-      /* End of CNAME chain */
-      return STAT_INSECURE;    
+      if (rc == STAT_INSECURE)
+       secure = STAT_INSECURE;
     }
+
+  /* OK, all the RRsets validate, now see if we have a missing answer or CNAME target. */
+  for (j = 0; j <targetidx; j++)
+    if ((p2 = targets[j]))
+      {
+       if (neganswer)
+         *neganswer = 1;
+
+       if (!extract_name(header, plen, &p2, name, 1, 10))
+         return STAT_BOGUS; /* bad packet */
+           
+       /* NXDOMAIN or NODATA reply, unanswered question is (name, qclass, qtype) */
+
+       /* For anything other than a DS record, this situation is OK if either
+          the answer is in an unsigned zone, or there's a NSEC records. */
+       if (!prove_non_existence(header, plen, keyname, name, qtype, qclass, NULL, nons))
+         {
+           /* Empty DS without NSECS */
+           if (qtype == T_DS)
+             return STAT_BOGUS;
+           
+           if ((rc = zone_status(name, qclass, keyname, now)) != STAT_SECURE)
+             {
+               if (class)
+                 *class = qclass; /* Class for NEED_DS or NEED_KEY */
+               return rc;
+             } 
+           
+           return STAT_BOGUS; /* signed zone, no NSECs */
+         }
+      }
+  
+  return secure;
 }
 
 
@@ -2235,7 +2022,7 @@ int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen)
     }
 }
 
-size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, 
+size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, 
                             int type, union mysockaddr *addr, int edns_pktsz)
 {
   unsigned char *p;
@@ -2264,252 +2051,19 @@ size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, i
 
   p = (unsigned char *)(header+1);
        
-  p = do_rfc1035_name(p, name);
+  p = do_rfc1035_name(p, name, NULL);
   *p++ = 0;
   PUTSHORT(type, p);
   PUTSHORT(class, p);
 
   ret = add_do_bit(header, p - (unsigned char *)header, end);
 
-  if (find_pseudoheader(header, ret, NULL, &p, NULL))
+  if (find_pseudoheader(header, ret, NULL, &p, NULL, NULL))
     PUTSHORT(edns_pktsz, p);
 
   return ret;
 }
 
-/* Go through a domain name, find "pointers" and fix them up based on how many bytes
-   we've chopped out of the packet, or check they don't point into an elided part.  */
-static int check_name(unsigned char **namep, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
-{
-  unsigned char *ansp = *namep;
-
-  while(1)
-    {
-      unsigned int label_type;
-      
-      if (!CHECK_LEN(header, ansp, plen, 1))
-       return 0;
-      
-      label_type = (*ansp) & 0xc0;
-
-      if (label_type == 0xc0)
-       {
-         /* pointer for compression. */
-         unsigned int offset;
-         int i;
-         unsigned char *p;
-         
-         if (!CHECK_LEN(header, ansp, plen, 2))
-           return 0;
-
-         offset = ((*ansp++) & 0x3f) << 8;
-         offset |= *ansp++;
-
-         p = offset + (unsigned char *)header;
-         
-         for (i = 0; i < rr_count; i++)
-           if (p < rrs[i])
-             break;
-           else
-             if (i & 1)
-               offset -= rrs[i] - rrs[i-1];
-
-         /* does the pointer end up in an elided RR? */
-         if (i & 1)
-           return 0;
-
-         /* No, scale the pointer */
-         if (fixup)
-           {
-             ansp -= 2;
-             *ansp++ = (offset >> 8) | 0xc0;
-             *ansp++ = offset & 0xff;
-           }
-         break;
-       }
-      else if (label_type == 0x80)
-       return 0; /* reserved */
-      else if (label_type == 0x40)
-       {
-         /* Extended label type */
-         unsigned int count;
-         
-         if (!CHECK_LEN(header, ansp, plen, 2))
-           return 0;
-         
-         if (((*ansp++) & 0x3f) != 1)
-           return 0; /* we only understand bitstrings */
-         
-         count = *(ansp++); /* Bits in bitstring */
-         
-         if (count == 0) /* count == 0 means 256 bits */
-           ansp += 32;
-         else
-           ansp += ((count-1)>>3)+1;
-       }
-      else
-       { /* label type == 0 Bottom six bits is length */
-         unsigned int len = (*ansp++) & 0x3f;
-         
-         if (!ADD_RDLEN(header, ansp, plen, len))
-           return 0;
-
-         if (len == 0)
-           break; /* zero length label marks the end. */
-       }
-    }
-
-  *namep = ansp;
-
-  return 1;
-}
-
-/* Go through RRs and check or fixup the domain names contained within */
-static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
-{
-  int i, type, class, rdlen;
-  unsigned char *pp;
-  
-  for (i = 0; i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount); i++)
-    {
-      pp = p;
-
-      if (!(p = skip_name(p, header, plen, 10)))
-       return 0;
-      
-      GETSHORT(type, p); 
-      GETSHORT(class, p);
-      p += 4; /* TTL */
-      GETSHORT(rdlen, p);
-
-      if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
-       {
-         /* fixup name of RR */
-         if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
-           return 0;
-         
-         if (class == C_IN)
-           {
-             u16 *d;
-             for (pp = p, d = get_desc(type); *d != (u16)-1; d++)
-               {
-                 if (*d != 0)
-                   pp += *d;
-                 else if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
-                   return 0;
-               }
-           }
-       }
-      
-      if (!ADD_RDLEN(header, p, plen, rdlen))
-       return 0;
-    }
-  
-  return 1;
-}
-       
-
-size_t filter_rrsigs(struct dns_header *header, size_t plen)
-{
-  static unsigned char **rrs;
-  static int rr_sz = 0;
-  
-  unsigned char *p = (unsigned char *)(header+1);
-  int i, rdlen, qtype, qclass, rr_found, chop_an, chop_ns, chop_ar;
-
-  if (ntohs(header->qdcount) != 1 ||
-      !(p = skip_name(p, header, plen, 4)))
-    return plen;
-  
-  GETSHORT(qtype, p);
-  GETSHORT(qclass, p);
-
-  /* First pass, find pointers to start and end of all the records we wish to elide:
-     records added for DNSSEC, unless explicity queried for */
-  for (rr_found = 0, chop_ns = 0, chop_an = 0, chop_ar = 0, i = 0; 
-       i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount);
-       i++)
-    {
-      unsigned char *pstart = p;
-      int type, class;
-
-      if (!(p = skip_name(p, header, plen, 10)))
-       return plen;
-      
-      GETSHORT(type, p); 
-      GETSHORT(class, p);
-      p += 4; /* TTL */
-      GETSHORT(rdlen, p);
-      
-      if ((type == T_NSEC || type == T_NSEC3 || type == T_RRSIG) && 
-         (type != qtype || class != qclass))
-       {
-         if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
-           return plen; 
-         
-         rrs[rr_found++] = pstart;
-
-         if (!ADD_RDLEN(header, p, plen, rdlen))
-           return plen;
-         
-         rrs[rr_found++] = p;
-         
-         if (i < ntohs(header->ancount))
-           chop_an++;
-         else if (i < (ntohs(header->nscount) + ntohs(header->ancount)))
-           chop_ns++;
-         else
-           chop_ar++;
-       }
-      else if (!ADD_RDLEN(header, p, plen, rdlen))
-       return plen;
-    }
-  
-  /* Nothing to do. */
-  if (rr_found == 0)
-    return plen;
-
-  /* Second pass, look for pointers in names in the records we're keeping and make sure they don't
-     point to records we're going to elide. This is theoretically possible, but unlikely. If
-     it happens, we give up and leave the answer unchanged. */
-  p = (unsigned char *)(header+1);
-  
-  /* question first */
-  if (!check_name(&p, header, plen, 0, rrs, rr_found))
-    return plen;
-  p += 4; /* qclass, qtype */
-  
-  /* Now answers and NS */
-  if (!check_rrs(p, header, plen, 0, rrs, rr_found))
-    return plen;
-  
-  /* Third pass, elide records */
-  for (p = rrs[0], i = 1; i < rr_found; i += 2)
-    {
-      unsigned char *start = rrs[i];
-      unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)(header+1)) + plen;
-      
-      memmove(p, start, end-start);
-      p += end-start;
-    }
-     
-  plen = p - (unsigned char *)header;
-  header->ancount = htons(ntohs(header->ancount) - chop_an);
-  header->nscount = htons(ntohs(header->nscount) - chop_ns);
-  header->arcount = htons(ntohs(header->arcount) - chop_ar);
-
-  /* Fourth pass, fix up pointers in the remaining records */
-  p = (unsigned char *)(header+1);
-  
-  check_name(&p, header, plen, 1, rrs, rr_found);
-  p += 4; /* qclass, qtype */
-  
-  check_rrs(p, header, plen, 1, rrs, rr_found);
-  
-  return plen;
-}
-
 unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name)
 {
   int q;
index 278698c..04d7cf8 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -55,70 +55,133 @@ int is_name_synthetic(int flags, char *name, struct all_addr *addr)
       
       if (pref && *pref != 0)
        continue; /* prefix match fail */
-      
-      /* NB, must not alter name if we return zero */
-      for (p = tail; *p; p++)
+
+      if (c->indexed)
        {
-         char c = *p;
+         for (p = tail; *p; p++)
+           {
+             char c = *p;
+             
+             if (c < '0' || c > '9')
+               break;
+           }
          
-         if ((c >='0' && c <= '9') || c == '-')
+         if (*p != '.')
            continue;
          
-#ifdef HAVE_IPV6
-         if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f'))) 
-           continue;
-#endif
+         *p = 0;
          
-         break;
-       }
-      
-      if (*p != '.')
-       continue;
-      
-      *p = 0;  
-      
-      /* swap . or : for - */
-      for (p = tail; *p; p++)
-       if (*p == '-')
-         {
-           if (prot == AF_INET)
-             *p = '.';
-#ifdef HAVE_IPV6
-           else
-             *p = ':';
+         if (hostname_isequal(c->domain, p+1))
+           {
+             if (prot == AF_INET)
+               {
+                 unsigned int index = atoi(tail);
+
+                  if (!c->is6 &&
+                     index <= ntohl(c->end.s_addr) - ntohl(c->start.s_addr))
+                   {
+                     addr->addr.addr4.s_addr = htonl(ntohl(c->start.s_addr) + index);
+                     found = 1;
+                   }
+               }
+#ifdef HAVE_IPV6 
+             else
+               {
+                 u64 index = atoll(tail);
+                 
+                 if (c->is6 &&
+                     index <= addr6part(&c->end6) - addr6part(&c->start6))
+                   {
+                     u64 start = addr6part(&c->start6);
+                     addr->addr.addr6 = c->start6;
+                     setaddr6part(&addr->addr.addr6, start + index);
+                     found = 1;
+                   }
+               }
 #endif
-         }
-      
-      if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
+           }
+       }
+      else
        {
-         if (prot == AF_INET)
+         /* NB, must not alter name if we return zero */
+         for (p = tail; *p; p++)
            {
-             if (!c->is6 &&
-                 ntohl(addr->addr.addr4.s_addr) >= ntohl(c->start.s_addr) &&
-                 ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr))
-               found = 1;
+             char c = *p;
+             
+             if ((c >='0' && c <= '9') || c == '-')
+               continue;
+             
+#ifdef HAVE_IPV6
+             if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f'))) 
+               continue;
+#endif
+             
+             break;
            }
+         
+         if (*p != '.')
+           continue;
+         
+         *p = 0;       
+         
 #ifdef HAVE_IPV6
+         if (prot == AF_INET6 && strstr(tail, "--ffff-") == tail)
+           {
+             /* special hack for v4-mapped. */
+             memcpy(tail, "::ffff:", 7);
+             for (p = tail + 7; *p; p++)
+               if (*p == '-')
+                 *p = '.';
+           }
          else
+#endif
            {
-             u64 addrpart = addr6part(&addr->addr.addr6);
-             
-             if (c->is6 &&
-                 is_same_net6(&addr->addr.addr6, &c->start6, 64) &&
-                 addrpart >= addr6part(&c->start6) &&
-                 addrpart <= addr6part(&c->end6))
-               found = 1;
+             /* swap . or : for - */
+             for (p = tail; *p; p++)
+               if (*p == '-')
+                 {
+                   if (prot == AF_INET)
+                     *p = '.';
+#ifdef HAVE_IPV6
+                   else
+                     *p = ':';
+#endif
+                 }
            }
+         
+         if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
+           {
+             if (prot == AF_INET)
+               {
+                 if (!c->is6 &&
+                     ntohl(addr->addr.addr4.s_addr) >= ntohl(c->start.s_addr) &&
+                     ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr))
+                   found = 1;
+               }
+#ifdef HAVE_IPV6
+             else
+               {
+                 u64 addrpart = addr6part(&addr->addr.addr6);
+                 
+                 if (c->is6 &&
+                     is_same_net6(&addr->addr.addr6, &c->start6, 64) &&
+                     addrpart >= addr6part(&c->start6) &&
+                     addrpart <= addr6part(&c->end6))
+                   found = 1;
+               }
 #endif
+           }
+
        }
-      
+
       /* restore name */
       for (p = tail; *p; p++)
        if (*p == '.' || *p == ':')
          *p = '-';
       
       *p = '.';
-
+      
+      
       if (found)
        return 1;
     }
@@ -136,14 +199,22 @@ int is_rev_synth(int flag, struct all_addr *addr, char *name)
        char *p;
        
        *name = 0;
-       if (c->prefix)
-        strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
+       if (c->indexed)
+        {
+          unsigned int index = ntohl(addr->addr.addr4.s_addr) - ntohl(c->start.s_addr);
+          snprintf(name, MAXDNAME, "%s%u", c->prefix ? c->prefix : "", index);
+        }
+       else
+        {
+          if (c->prefix)
+            strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
+       
+                  inet_ntop(AF_INET, &addr->addr.addr4, name + strlen(name), ADDRSTRLEN);
+          for (p = name; *p; p++)
+            if (*p == '.')
+              *p = '-';
+        }
        
-       inet_ntop(AF_INET, &addr->addr.addr4, name + strlen(name), ADDRSTRLEN);
-       for (p = name; *p; p++)
-        if (*p == '.')
-          *p = '-';
-
        strncat(name, ".", MAXDNAME);
        strncat(name, c->domain, MAXDNAME);
 
@@ -156,22 +227,32 @@ int is_rev_synth(int flag, struct all_addr *addr, char *name)
        char *p;
        
        *name = 0;
-       if (c->prefix)
-        strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
-       
-       inet_ntop(AF_INET6, &addr->addr.addr6, name + strlen(name), ADDRSTRLEN);
-
-       /* IPv6 presentation address can start with ":", but valid domain names
-         cannot start with "-" so prepend a zero in that case. */
-       if (!c->prefix && *name == ':')
+       if (c->indexed)
         {
-          *name = '0';
-          inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
+          u64 index = addr6part(&addr->addr.addr6) - addr6part(&c->start6);
+          snprintf(name, MAXDNAME, "%s%llu", c->prefix ? c->prefix : "", index);
         }
+       else
+        {
+          if (c->prefix)
+            strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
+       
+          inet_ntop(AF_INET6, &addr->addr.addr6, name + strlen(name), ADDRSTRLEN);
 
-       for (p = name; *p; p++)
-        if (*p == ':')
-          *p = '-';
+          /* IPv6 presentation address can start with ":", but valid domain names
+             cannot start with "-" so prepend a zero in that case. */
+          if (!c->prefix && *name == ':')
+            {
+              *name = '0';
+              inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
+            }
+          
+          /* V4-mapped have periods.... */
+          for (p = name; *p; p++)
+            if (*p == ':' || *p == '.')
+              *p = '-';
+          
+        }
 
        strncat(name, ".", MAXDNAME);
        strncat(name, c->domain, MAXDNAME);
diff --git a/src/edns0.c b/src/edns0.c
new file mode 100644 (file)
index 0000000..af33877
--- /dev/null
@@ -0,0 +1,449 @@
+/* dnsmasq is Copyright (c) 2000-2018 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"
+
+unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t  *len, unsigned char **p, int *is_sign, int *is_last)
+{
+  /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it. 
+     also return length of pseudoheader in *len and pointer to the UDP size in *p
+     Finally, check to see if a packet is signed. If it is we cannot change a single bit before
+     forwarding. We look for TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
+  
+  int i, arcount = ntohs(header->arcount);
+  unsigned char *ansp = (unsigned char *)(header+1);
+  unsigned short rdlen, type, class;
+  unsigned char *ret = NULL;
+
+  if (is_sign)
+    {
+      *is_sign = 0;
+
+      if (OPCODE(header) == QUERY)
+       {
+         for (i = ntohs(header->qdcount); i != 0; i--)
+           {
+             if (!(ansp = skip_name(ansp, header, plen, 4)))
+               return NULL;
+             
+             GETSHORT(type, ansp); 
+             GETSHORT(class, ansp);
+             
+             if (class == C_IN && type == T_TKEY)
+               *is_sign = 1;
+           }
+       }
+    }
+  else
+    {
+      if (!(ansp = skip_questions(header, plen)))
+       return NULL;
+    }
+    
+  if (arcount == 0)
+    return NULL;
+  
+  if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount), header, plen)))
+    return NULL; 
+  
+  for (i = 0; i < arcount; i++)
+    {
+      unsigned char *save, *start = ansp;
+      if (!(ansp = skip_name(ansp, header, plen, 10)))
+       return NULL; 
+
+      GETSHORT(type, ansp);
+      save = ansp;
+      GETSHORT(class, ansp);
+      ansp += 4; /* TTL */
+      GETSHORT(rdlen, ansp);
+      if (!ADD_RDLEN(header, ansp, plen, rdlen))
+       return NULL;
+      if (type == T_OPT)
+       {
+         if (len)
+           *len = ansp - start;
+
+         if (p)
+           *p = save;
+         
+         if (is_last)
+           *is_last = (i == arcount-1);
+
+         ret = start;
+       }
+      else if (is_sign && 
+              i == arcount - 1 && 
+              class == C_ANY && 
+              type == T_TSIG)
+       *is_sign = 1;
+    }
+  
+  return ret;
+}
+
+/* replace == 2 ->delete existing option only. */
+size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit, 
+                       unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace)
+{ 
+  unsigned char *lenp, *datap, *p, *udp_len, *buff = NULL;
+  int rdlen = 0, is_sign, is_last;
+  unsigned short flags = set_do ? 0x8000 : 0, rcode = 0;
+
+  p = find_pseudoheader(header, plen, NULL, &udp_len, &is_sign, &is_last);
+  
+  if (is_sign)
+    return plen;
+
+  if (p)
+    {
+      /* Existing header */
+      int i;
+      unsigned short code, len;
+
+      p = udp_len;
+      GETSHORT(udp_sz, p);
+      GETSHORT(rcode, p);
+      GETSHORT(flags, p);
+
+      if (set_do)
+       {
+         p -= 2;
+         flags |= 0x8000;
+         PUTSHORT(flags, p);
+       }
+
+      lenp = p;
+      GETSHORT(rdlen, p);
+      if (!CHECK_LEN(header, p, plen, rdlen))
+       return plen; /* bad packet */
+      datap = p;
+
+       /* no option to add */
+      if (optno == 0)
+       return plen;
+         
+      /* check if option already there */
+      for (i = 0; i + 4 < rdlen;)
+       {
+         GETSHORT(code, p);
+         GETSHORT(len, p);
+         
+         /* malformed option, delete the whole OPT RR and start again. */
+         if (i + 4 + len > rdlen)
+           {
+             rdlen = 0;
+             is_last = 0;
+             break;
+           }
+         
+         if (code == optno)
+           {
+             if (replace == 0)
+               return plen;
+
+             /* delete option if we're to replace it. */
+             p -= 4;
+             rdlen -= len + 4;
+             memmove(p, p+len+4, rdlen - i);
+             PUTSHORT(rdlen, lenp);
+             lenp -= 2;
+           }
+         else
+           {
+             p += len;
+             i += len + 4;
+           }
+       }
+
+      /* If we're going to extend the RR, it has to be the last RR in the packet */
+      if (!is_last)
+       {
+         /* First, take a copy of the options. */
+         if (rdlen != 0 && (buff = whine_malloc(rdlen)))
+           memcpy(buff, datap, rdlen);       
+         
+         /* now, delete OPT RR */
+         plen = rrfilter(header, plen, 0);
+         
+         /* Now, force addition of a new one */
+         p = NULL;       
+       }
+    }
+  
+  if (!p)
+    {
+      /* We are (re)adding the pseudoheader */
+      if (!(p = skip_questions(header, plen)) ||
+         !(p = skip_section(p, 
+                            ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount), 
+                            header, plen)))
+      {
+       free(buff);
+       return plen;
+      }
+      if (p + 11 > limit)
+      {
+        free(buff);
+        return plen; /* Too big */
+      }
+      *p++ = 0; /* empty name */
+      PUTSHORT(T_OPT, p);
+      PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
+      PUTSHORT(rcode, p);    /* extended RCODE and version */
+      PUTSHORT(flags, p); /* DO flag */
+      lenp = p;
+      PUTSHORT(rdlen, p);    /* RDLEN */
+      datap = p;
+      /* Copy back any options */
+      if (buff)
+       {
+          if (p + rdlen > limit)
+          {
+            free(buff);
+            return plen; /* Too big */
+          }
+         memcpy(p, buff, rdlen);
+         free(buff);
+         p += rdlen;
+       }
+      
+      /* Only bump arcount if RR is going to fit */ 
+      if (((ssize_t)optlen) <= (limit - (p + 4)))
+       header->arcount = htons(ntohs(header->arcount) + 1);
+    }
+  
+  if (((ssize_t)optlen) > (limit - (p + 4)))
+    return plen; /* Too big */
+  
+  /* Add new option */
+  if (optno != 0 && replace != 2)
+    {
+      if (p + 4 > limit)
+       return plen; /* Too big */
+      PUTSHORT(optno, p);
+      PUTSHORT(optlen, p);
+      if (p + optlen > limit)
+       return plen; /* Too big */
+      memcpy(p, opt, optlen);
+      p += optlen;  
+      PUTSHORT(p - datap, lenp);
+    }
+  return p - (unsigned char *)header;
+}
+
+size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char *limit)
+{
+  return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, 0, NULL, 0, 1, 0);
+}
+
+static unsigned char char64(unsigned char c)
+{
+  return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c & 0x3f];
+}
+
+static void encoder(unsigned char *in, char *out)
+{
+  out[0] = char64(in[0]>>2);
+  out[1] = char64((in[0]<<4) | (in[1]>>4));
+  out[2] = char64((in[1]<<2) | (in[2]>>6));
+  out[3] = char64(in[2]);
+}
+
+static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *l3, time_t now)
+{
+  int maclen, replace = 2; /* can't get mac address, just delete any incoming. */
+  unsigned char mac[DHCP_CHADDR_MAX];
+  char encode[18]; /* handle 6 byte MACs */
+
+  if ((maclen = find_mac(l3, mac, 1, now)) == 6)
+    {
+      replace = 1;
+
+      if (option_bool(OPT_MAC_HEX))
+       print_mac(encode, mac, maclen);
+      else
+       {
+         encoder(mac, encode);
+         encoder(mac+3, encode+4);
+         encode[8] = 0;
+       }
+    }
+
+  return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace); 
+}
+
+
+static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *l3, time_t now)
+{
+  int maclen;
+  unsigned char mac[DHCP_CHADDR_MAX];
+
+  if ((maclen = find_mac(l3, mac, 1, now)) != 0)
+    plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, 0); 
+    
+  return plen; 
+}
+
+struct subnet_opt {
+  u16 family;
+  u8 source_netmask, scope_netmask;
+#ifdef HAVE_IPV6 
+  u8 addr[IN6ADDRSZ];
+#else
+  u8 addr[INADDRSZ];
+#endif
+};
+
+static void *get_addrp(union mysockaddr *addr, const short family) 
+{
+#ifdef HAVE_IPV6
+  if (family == AF_INET6)
+    return &addr->in6.sin6_addr;
+#endif
+
+  return &addr->in.sin_addr;
+}
+
+static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
+{
+  /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
+  
+  int len;
+  void *addrp = NULL;
+  int sa_family = source->sa.sa_family;
+
+  opt->source_netmask = 0;
+  opt->scope_netmask = 0;
+
+#ifdef HAVE_IPV6
+  if (source->sa.sa_family == AF_INET6 && daemon->add_subnet6)
+    {
+      opt->source_netmask = daemon->add_subnet6->mask;
+      if (daemon->add_subnet6->addr_used) 
+       {
+         sa_family = daemon->add_subnet6->addr.sa.sa_family;
+         addrp = get_addrp(&daemon->add_subnet6->addr, sa_family);
+       } 
+      else 
+       addrp = &source->in6.sin6_addr;
+    }
+#endif
+
+  if (source->sa.sa_family == AF_INET && daemon->add_subnet4)
+    {
+      opt->source_netmask = daemon->add_subnet4->mask;
+      if (daemon->add_subnet4->addr_used)
+       {
+         sa_family = daemon->add_subnet4->addr.sa.sa_family;
+         addrp = get_addrp(&daemon->add_subnet4->addr, sa_family);
+       } 
+       else 
+         addrp = &source->in.sin_addr;
+    }
+  
+#ifdef HAVE_IPV6
+  opt->family = htons(sa_family == AF_INET6 ? 2 : 1);
+#else
+  opt->family = htons(1);
+#endif
+  
+  len = 0;
+  
+  if (addrp && opt->source_netmask != 0)
+    {
+      len = ((opt->source_netmask - 1) >> 3) + 1;
+      memcpy(opt->addr, addrp, len);
+      if (opt->source_netmask & 7)
+       opt->addr[len-1] &= 0xff << (8 - (opt->source_netmask & 7));
+    }
+  
+  return len + 4;
+}
+static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *source)
+{
+  /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
+  
+  int len;
+  struct subnet_opt opt;
+  
+  len = calc_subnet_opt(&opt, source);
+  return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, 0);
+}
+
+int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)
+{
+  /* Section 9.2, Check that subnet option in reply matches. */
+  
+  int len, calc_len;
+  struct subnet_opt opt;
+  unsigned char *p;
+  int code, i, rdlen;
+  
+   calc_len = calc_subnet_opt(&opt, peer);
+   
+   if (!(p = skip_name(pseudoheader, header, plen, 10)))
+     return 1;
+   
+   p += 8; /* skip UDP length and RCODE */
+   
+   GETSHORT(rdlen, p);
+   if (!CHECK_LEN(header, p, plen, rdlen))
+     return 1; /* bad packet */
+   
+   /* check if option there */
+   for (i = 0; i + 4 < rdlen; i += len + 4)
+     {
+       GETSHORT(code, p);
+       GETSHORT(len, p);
+       if (code == EDNS0_OPTION_CLIENT_SUBNET)
+        {
+          /* make sure this doesn't mismatch. */
+          opt.scope_netmask = p[3];
+          if (len != calc_len || memcmp(p, &opt, len) != 0)
+            return 0;
+        }
+       p += len;
+     }
+   
+   return 1;
+}
+
+size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit, 
+                       union mysockaddr *source, time_t now, int *check_subnet)    
+{
+  *check_subnet = 0;
+
+  if (option_bool(OPT_ADD_MAC))
+    plen  = add_mac(header, plen, limit, source, now);
+  
+  if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX))
+    plen = add_dns_client(header, plen, limit, source, now);
+
+  if (daemon->dns_client_id)
+    plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID, 
+                           (unsigned char *)daemon->dns_client_id, strlen(daemon->dns_client_id), 0, 1);
+  
+  if (option_bool(OPT_CLIENT_SUBNET))
+    {
+      plen = add_source_addr(header, plen, limit, source); 
+      *check_subnet = 1;
+    }
+         
+  return plen;
+}
index 2731b90..cdd11d3 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -23,15 +23,6 @@ static struct frec *lookup_frec_by_sender(unsigned short id,
 static unsigned short get_id(void);
 static void free_frec(struct frec *f);
 
-#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(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
-
-
 /* Send a UDP packet with its source address set as "source" 
    unless nowild is true, when we just send it with the kernel default */
 int send_from(int fd, int nowild, char *packet, size_t len, 
@@ -115,8 +106,8 @@ int send_from(int fd, int nowild, char *packet, size_t len,
   return 1;
 }
           
-static unsigned int search_servers(time_t now, struct all_addr **addrpp, 
-                                    unsigned int qtype, char *qdomain, int *type, char **domain, int *norebind)
+static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigned int qtype,
+                                  char *qdomain, int *type, char **domain, int *norebind)
                              
 {
   /* If the query ends in the domain in one of our servers, set
@@ -129,8 +120,10 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp,
   unsigned int flags = 0;
   
   for (serv = daemon->servers; serv; serv=serv->next)
+    if (qtype == F_DNSSECOK && !(serv->flags & SERV_DO_DNSSEC))
+      continue;
     /* domain matches take priority over NODOTS matches */
-    if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
+    else if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
       {
        unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6; 
        *type = SERV_FOR_NODOTS;
@@ -160,7 +153,7 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp,
            hostname_isequal(matchstart, serv->domain) &&
            (domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
          {
-           if (serv->flags & SERV_NO_REBIND)   
+           if ((serv->flags & SERV_NO_REBIND) && norebind)     
              *norebind = 1;
            else
              {
@@ -184,7 +177,7 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp,
                
                if (domainlen >= matchlen)
                  {
-                   *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND);
+                   *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_DO_DNSSEC);
                    *domain = serv->domain;
                    matchlen = domainlen;
                    if (serv->flags & SERV_NO_ADDR)
@@ -211,7 +204,7 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp,
          }
       }
   
-  if (flags == 0 && !(qtype & F_QUERY) && 
+  if (flags == 0 && !(qtype & (F_QUERY | F_DNSSECOK)) && 
       option_bool(OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
     /* don't forward A or AAAA queries for simple names, except the empty name */
     flags = F_NOERR;
@@ -242,25 +235,23 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
                         struct frec *forward, int ad_reqd, int do_bit)
 {
   char *domain = NULL;
-  int type = 0, norebind = 0;
+  int type = SERV_DO_DNSSEC, norebind = 0;
   struct all_addr *addrp = NULL;
   unsigned int flags = 0;
   struct server *start = NULL;
 #ifdef HAVE_DNSSEC
   void *hash = hash_questions(header, plen, daemon->namebuff);
+  int do_dnssec = 0;
 #else
   unsigned int crc = questions_crc(header, plen, daemon->namebuff);
   void *hash = &crc;
 #endif
  unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
- unsigned char *pheader;
 
  (void)do_bit;
 
   /* may be no servers available. */
-  if (!daemon->servers)
-    forward = NULL;
-  else if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
+  if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
     {
       /* If we didn't get an answer advertising a maximal packet in EDNS,
         fall back to 1280, which should work everywhere on IPv6.
@@ -273,21 +264,21 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
         there's no point retrying the query, retry the key query instead...... */
       if (forward->blocking_query)
        {
-         int fd;
+         int fd, is_sign;
+         unsigned char *pheader;
          
          forward->flags &= ~FREC_TEST_PKTSZ;
          
          while (forward->blocking_query)
            forward = forward->blocking_query;
           
-         forward->flags |= FREC_TEST_PKTSZ;
-         
          blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
          plen = forward->stash_len;
          
-         if (find_pseudoheader(header, plen, NULL, &pheader, NULL))
-           PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? SAFE_PKTSZ : forward->sentto->edns_pktsz, pheader);
-
+         forward->flags |= FREC_TEST_PKTSZ;
+         if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
+           PUTSHORT(SAFE_PKTSZ, pheader);
+         
          if (forward->sentto->addr.sa.sa_family == AF_INET) 
            log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
 #ifdef HAVE_IPV6
@@ -324,6 +315,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
          daemon->last_server = NULL;
        }
       type = forward->sentto->flags & SERV_TYPE;
+#ifdef HAVE_DNSSEC
+      do_dnssec = forward->sentto->flags & SERV_DO_DNSSEC;
+#endif
+
       if (!(start = forward->sentto->next))
        start = daemon->servers; /* at end of list, recycle */
       header->id = htons(forward->new_id);
@@ -333,9 +328,14 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
       if (gotname)
        flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
       
-      if (!flags && !(forward = get_new_frec(now, NULL, 0)))
-       /* table full - server failure. */
-       flags = F_NEG;
+#ifdef HAVE_DNSSEC
+      do_dnssec = type & SERV_DO_DNSSEC;
+#endif
+      type &= ~SERV_DO_DNSSEC;      
+
+      if (daemon->servers && !flags)
+       forward = get_new_frec(now, NULL, 0);
+      /* table full - flags == 0, return REFUSED */
       
       if (forward)
        {
@@ -397,40 +397,46 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
   if (!flags && forward)
     {
       struct server *firstsentto = start;
-      int forwarded = 0;
+      int subnet, forwarded = 0;
+      size_t edns0_len;
+      unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
+      unsigned char *pheader;
       
       /* 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);
+      plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->source, now, &subnet);
+      
+      if (subnet)
+       forward->flags |= FREC_HAS_SUBNET;
       
-      if (option_bool(OPT_CLIENT_SUBNET))
-       {
-         size_t new = add_source_addr(header, plen, ((char *) header) + daemon->packet_buff_sz, &forward->source); 
-         if (new != plen)
-           {
-             plen = new;
-             forward->flags |= FREC_HAS_SUBNET;
-           }
-       }
-
 #ifdef HAVE_DNSSEC
-      if (option_bool(OPT_DNSSEC_VALID))
+      if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
        {
-         size_t new_plen = add_do_bit(header, plen, ((char *) header) + daemon->packet_buff_sz);
-        
+         plen = add_do_bit(header, plen, ((unsigned char *) header) + PACKETSZ);
+                     
          /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
             this allows it to select auth servers when one is returning bad data. */
          if (option_bool(OPT_DNSSEC_DEBUG))
            header->hb4 |= HB4_CD;
 
-         if (new_plen != plen)
+       }
+#endif
+
+      if (find_pseudoheader(header, plen, &edns0_len, &pheader, NULL, NULL))
+       {
+         /* If there wasn't a PH before, and there is now, we added it. */
+         if (!oph)
            forward->flags |= FREC_ADDED_PHEADER;
 
-         plen = new_plen;
+         /* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */
+         if (edns0_len > 11)
+           forward->flags |= FREC_HAS_EXTRADATA;
+
+         /* Reduce udp size on retransmits. */
+         if (forward->flags & FREC_TEST_PKTSZ)
+           PUTSHORT(SAFE_PKTSZ, pheader);
        }
-#endif
       
       while (1)
        { 
@@ -478,10 +484,23 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
                    }
 #endif
                }
-
-             if (find_pseudoheader(header, plen, NULL, &pheader, NULL))
-               PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? SAFE_PKTSZ : start->edns_pktsz, pheader);
              
+#ifdef HAVE_DNSSEC
+             if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER))
+               {
+                 /* Difficult one here. If our client didn't send EDNS0, we will have set the UDP
+                    packet size to 512. But that won't provide space for the RRSIGS in many cases.
+                    The RRSIGS will be stripped out before the answer goes back, so the packet should
+                    shrink again. So, if we added a do-bit, bump the udp packet size to the value
+                    known to be OK for this server. We check returned size after stripping and set
+                    the truncated bit if it's still too big. */                  
+                 unsigned char *pheader;
+                 int is_sign;
+                 if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
+                   PUTSHORT(start->edns_pktsz, pheader);
+               }
+#endif
+
              if (retry_send(sendto(fd, (char *)header, plen, 0,
                                    &start->addr.sa,
                                    sa_len(&start->addr))))
@@ -545,7 +564,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
   char **sets = 0;
   int munged = 0, is_sign;
   size_t plen; 
-
+  
   (void)ad_reqd;
   (void)do_bit;
   (void)bogusanswer;
@@ -572,30 +591,49 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
     }
 #endif
   
-  /* If upstream is advertising a larger UDP packet size
-     than we allow, trim it so that we don't get overlarge
-     requests for the client. We can't do this for signed packets. */
-
-  if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)))
+  if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
     {
-      unsigned short udpsz;
-      unsigned char *psave = sizep;
-      
-      GETSHORT(udpsz, sizep);
-
-      if (!is_sign && udpsz > daemon->edns_pktsz)
-       PUTSHORT(daemon->edns_pktsz, psave);
-      
       if (check_subnet && !check_source(header, plen, pheader, query_source))
        {
          my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
          return 0;
        }
       
-      if (added_pheader)
+      if (!is_sign)
        {
-         pheader = 0; 
-         header->arcount = htons(0);
+         if (added_pheader)
+           {
+             /* client didn't send EDNS0, we added one, strip it off before returning answer. */
+             n = rrfilter(header, n, 0);
+             pheader = NULL;
+           }
+         else
+           {
+             unsigned short udpsz;
+
+             /* If upstream is advertising a larger UDP packet size
+                than we allow, trim it so that we don't get overlarge
+                requests for the client. We can't do this for signed packets. */
+             GETSHORT(udpsz, sizep);
+             if (udpsz > daemon->edns_pktsz)
+               {
+                 sizep -= 2;
+                 PUTSHORT(daemon->edns_pktsz, sizep);
+               }
+
+#ifdef HAVE_DNSSEC
+             /* If the client didn't set the do bit, but we did, reset it. */
+             if (option_bool(OPT_DNSSEC_VALID) && !do_bit)
+               {
+                 unsigned short flags;
+                 sizep += 2; /* skip RCODE */
+                 GETSHORT(flags, sizep);
+                 flags &= ~0x8000;
+                 sizep -= 2;
+                 PUTSHORT(flags, sizep);
+               }
+#endif
+           }
        }
     }
   
@@ -607,7 +645,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
     return resize_packet(header, n, pheader, plen);
   
   /* Complain loudly if the upstream server is non-recursive. */
-  if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR && ntohs(header->ancount) == 0 &&
+  if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR &&
       server && !(server->flags & SERV_WARNED_RECURSIVE))
     {
       prettyprint_addr(&server->addr, daemon->namebuff);
@@ -653,25 +691,24 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
     }
   
 #ifdef HAVE_DNSSEC
-  if (bogusanswer && !(header->hb4 & HB4_CD)
+  if (bogusanswer && !(header->hb4 & HB4_CD) && !option_bool(OPT_DNSSEC_DEBUG))
     {
-      if (!option_bool(OPT_DNSSEC_DEBUG))
-       {
-         /* Bogus reply, turn into SERVFAIL */
-         SET_RCODE(header, SERVFAIL);
-         munged = 1;
-       }
+      /* Bogus reply, turn into SERVFAIL */
+      SET_RCODE(header, SERVFAIL);
+      munged = 1;
     }
 
   if (option_bool(OPT_DNSSEC_VALID))
-    header->hb4 &= ~HB4_AD;
-  
-  if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
-    header->hb4 |= HB4_AD;
-
-  /* If the requestor didn't set the DO bit, don't return DNSSEC info. */
-  if (!do_bit)
-    n = filter_rrsigs(header, n);
+    {
+      header->hb4 &= ~HB4_AD;
+      
+      if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
+       header->hb4 |= HB4_AD;
+      
+      /* If the requestor didn't set the DO bit, don't return DNSSEC info. */
+      if (!do_bit)
+       n = rrfilter(header, n, 1);
+    }
 #endif
 
   /* do this after extract_addresses. Ensure NODATA reply and remove
@@ -731,7 +768,11 @@ void reply_query(int fd, int family, time_t now)
   
   if (!server)
     return;
-  
+
+  /* If sufficient time has elapsed, try and expand UDP buffer size again. */
+  if (difftime(now, server->pktsz_reduced) > UDP_TEST_TIME)
+    server->edns_pktsz = daemon->edns_pktsz;
+
 #ifdef HAVE_DNSSEC
   hash = hash_questions(header, n, daemon->namebuff);
 #else
@@ -751,18 +792,30 @@ void reply_query(int fd, int family, time_t now)
       check_for_ignored_address(header, n, daemon->ignore_addr))
     return;
 
+  /* Note: if we send extra options in the EDNS0 header, we can't recreate
+     the query from the reply. */
   if (RCODE(header) == REFUSED &&
-      !option_bool(OPT_ORDER) &&
-      forward->forwardall == 0)
+      forward->forwardall == 0 &&
+      !(forward->flags & FREC_HAS_EXTRADATA))
     /* for broken servers, attempt to send to another one. */
     {
       unsigned char *pheader;
       size_t plen;
       int is_sign;
-      
+
+      /* In strict order mode, there must be a server later in the chain
+        left to send to, otherwise without the forwardall mechanism,
+        code further on will cycle around the list forwever if they
+        all return REFUSED. Note that server is always non-NULL before 
+        this executes. */
+      if (option_bool(OPT_ORDER))
+       for (server = forward->sentto->next; server; server = server->next)
+         if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP)))
+           break;
+
       /* recreate query from reply */
-      pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign);
-      if (!is_sign)
+      pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
+      if (!is_sign && server)
        {
          header->ancount = htons(0);
          header->nscount = htons(0);
@@ -770,8 +823,14 @@ void reply_query(int fd, int family, time_t now)
          if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
            {
              header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC);
-             header->hb4 &= ~(HB4_RA | HB4_RCODE);
-             forward_query(-1, NULL, NULL, 0, header, nn, now, forward, 0, 0);
+             header->hb4 &= ~(HB4_RA | HB4_RCODE | HB4_CD | HB4_AD);
+             if (forward->flags & FREC_CHECKING_DISABLED)
+               header->hb4 |= HB4_CD;
+             if (forward->flags & FREC_AD_QUESTION)
+               header->hb4 |= HB4_AD;
+             if (forward->flags & FREC_DO_QUESTION)
+               add_do_bit(header, nn,  (unsigned char *)pheader + plen);
+             forward_query(-1, NULL, NULL, 0, header, nn, now, forward, forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION);
              return;
            }
        }
@@ -800,20 +859,27 @@ void reply_query(int fd, int family, time_t now)
     }
  
   /* We tried resending to this server with a smaller maximum size and got an answer.
-     Make that permanent. To avoid reduxing the packet size for an single dropped packet,
+     Make that permanent. To avoid reduxing the packet size for a single dropped packet,
      only do this when we get a truncated answer, or one larger than the safe size. */
-  if (server && (forward->flags & FREC_TEST_PKTSZ) && 
+  if (server && server->edns_pktsz > SAFE_PKTSZ && (forward->flags & FREC_TEST_PKTSZ) && 
       ((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
-    server->edns_pktsz = SAFE_PKTSZ;
-  
+    {
+      server->edns_pktsz = SAFE_PKTSZ;
+      server->pktsz_reduced = now;
+      prettyprint_addr(&server->addr, daemon->addrbuff);
+      my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ);
+    }
+
+    
   /* If the answer is an error, keep the forward record in place in case
      we get a good reply from another server. Kill it when we've
      had replies from all to avoid filling the forwarding table when
      everything is broken */
-  if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != SERVFAIL)
+  if (forward->forwardall == 0 || --forward->forwardall == 1 ||
+      (RCODE(header) != REFUSED && RCODE(header) != SERVFAIL))
     {
       int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
-
+      
       if (option_bool(OPT_NO_REBIND))
        check_rebind = !(forward->flags & FREC_NOREBIND);
       
@@ -823,238 +889,189 @@ void reply_query(int fd, int family, time_t now)
        no_cache_dnssec = 1;
       
 #ifdef HAVE_DNSSEC
-      if (server && option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
+      if (server && (server->flags & SERV_DO_DNSSEC) && 
+         option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
        {
-         int status;
+         int status = 0;
 
          /* We've had a reply already, which we're validating. Ignore this duplicate */
          if (forward->blocking_query)
            return;
-
+         
+          /* Truncated answer can't be validated.
+             If this is an answer to a DNSSEC-generated query, we still
+             need to get the client to retry over TCP, so return
+             an answer with the TC bit set, even if the actual answer fits.
+          */
          if (header->hb3 & HB3_TC)
+           status = STAT_TRUNCATED;
+         
+         while (1)
            {
-             /* Truncated answer can't be validated.
-                If this is an answer to a DNSSEC-generated query, we still
-                need to get the client to retry over TCP, so return
-                an answer with the TC bit set, even if the actual answer fits.
-             */
-             status = STAT_TRUNCATED;
-           }
-         else if (forward->flags & FREC_DNSKEY_QUERY)
-           status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
-         else if (forward->flags & FREC_DS_QUERY)
-           {
-             status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
-             /* Provably no DS, everything below is insecure, even if signatures are offered */
-             if (status == STAT_NO_DS)
-               /* We only cache sigs when we've validated a reply.
-                  Avoid caching a reply with sigs if there's a vaildated break in the 
-                  DS chain, so we don't return replies from cache missing sigs. */
-               status = STAT_INSECURE_DS;
-             else if (status == STAT_NO_SIG)
-                {
-                  if (option_bool(OPT_DNSSEC_NO_SIGN))
-                    {
-                     status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname);
-                     if (status == STAT_INSECURE)
-                       status = STAT_INSECURE_DS;
-                   }
-                 else
-                   status = STAT_INSECURE_DS;
-               }
-              else if (status == STAT_NO_NS)
-               status = STAT_BOGUS;
-           }
-         else if (forward->flags & FREC_CHECK_NOSIGN)
-           {
-             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, NULL);
-             if (status == STAT_NO_SIG)
+             /* As soon as anything returns BOGUS, we stop and unwind, to do otherwise
+                would invite infinite loops, since the answers to DNSKEY and DS queries
+                will not be cached, so they'll be repeated. */
+             if (status != STAT_BOGUS && status != STAT_TRUNCATED && status != STAT_ABANDONED)
                {
-                 if (option_bool(OPT_DNSSEC_NO_SIGN))
-                   status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname);
+                 if (forward->flags & FREC_DNSKEY_QUERY)
+                   status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
+                 else if (forward->flags & FREC_DS_QUERY)
+                   status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
                  else
-                   status = STAT_INSECURE;
+                   status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, 
+                                                  option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC),
+                                                  NULL, NULL);
                }
-           }
-         /* Can't validate, as we're missing key data. Put this
-            answer aside, whilst we get that. */     
-         if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG || status == STAT_NEED_KEY)
-           {
-             struct frec *new, *orig;
-             
-             /* Free any saved query */
-             if (forward->stash)
-               blockdata_free(forward->stash);
-             
-             /* Now save reply pending receipt of key data */
-             if (!(forward->stash = blockdata_alloc((char *)header, n)))
-               return;
-             forward->stash_len = n;
              
-           anotherkey:       
-             /* Find the original query that started it all.... */
-             for (orig = forward; orig->dependent; orig = orig->dependent);
-
-             if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, 1)))
-               status = STAT_INSECURE;
-             else
+             /* Can't validate, as we're missing key data. Put this
+                answer aside, whilst we get that. */     
+             if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
                {
-                 int fd;
-                 struct frec *next = new->next;
-                 *new = *forward; /* copy everything, then overwrite */
-                 new->next = next;
-                 new->blocking_query = NULL;
-                 new->sentto = server;
-                 new->rfd4 = NULL;
-                 new->orig_domain = NULL;
-#ifdef HAVE_IPV6
-                 new->rfd6 = NULL;
-#endif
-                 new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_CHECK_NOSIGN);
+                 struct frec *new, *orig;
                  
-                 new->dependent = forward; /* to find query awaiting new one. */
-                 forward->blocking_query = new; /* for garbage cleaning */
-                 /* validate routines leave name of required record in daemon->keyname */
-                 if (status == STAT_NEED_KEY)
-                   {
-                     new->flags |= FREC_DNSKEY_QUERY; 
-                     nn = dnssec_generate_query(header, ((char *) header) + daemon->packet_buff_sz,
-                                                daemon->keyname, forward->class, T_DNSKEY, &server->addr, server->edns_pktsz);
-                   }
-                 else 
-                   {
-                     if (status == STAT_NEED_DS_NEG)
-                       new->flags |= FREC_CHECK_NOSIGN;
-                     else
-                       new->flags |= FREC_DS_QUERY;
-                     nn = dnssec_generate_query(header,((char *) header) + daemon->packet_buff_sz,
-                                                daemon->keyname, forward->class, T_DS, &server->addr, server->edns_pktsz);
-                   }
-                 if ((hash = hash_questions(header, nn, daemon->namebuff)))
-                   memcpy(new->hash, hash, HASH_SIZE);
-                 new->new_id = get_id();
-                 header->id = htons(new->new_id);
-                 /* Save query for retransmission */
-                 if (!(new->stash = blockdata_alloc((char *)header, nn)))
+                 /* Free any saved query */
+                 if (forward->stash)
+                   blockdata_free(forward->stash);
+                 
+                 /* Now save reply pending receipt of key data */
+                 if (!(forward->stash = blockdata_alloc((char *)header, n)))
                    return;
-                     
-                 new->stash_len = nn;
+                 forward->stash_len = n;
                  
-                 /* Don't resend this. */
-                 daemon->srv_save = NULL;
+                 /* Find the original query that started it all.... */
+                 for (orig = forward; orig->dependent; orig = orig->dependent);
                  
-                 if (server->sfd)
-                   fd = server->sfd->fd;
+                 if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, 1)))
+                   status = STAT_ABANDONED;
                  else
                    {
-                     fd = -1;
+                     int fd, type = SERV_DO_DNSSEC;
+                     struct frec *next = new->next;
+                     char *domain;
+                     
+                     *new = *forward; /* copy everything, then overwrite */
+                     new->next = next;
+                     new->blocking_query = NULL;
+
+                     /* Find server to forward to. This will normally be the 
+                        same as for the original query, but may be another if
+                        servers for domains are involved. */                 
+                     if (search_servers(now, NULL, F_DNSSECOK, daemon->keyname, &type, &domain, NULL) == 0)
+                       {
+                         struct server *start = server, *new_server = NULL;
+                         
+                         while (1)
+                           {
+                             if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
+                                 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
+                                 !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
+                               {
+                                 new_server = start;
+                                 if (server == start)
+                                   {
+                                     new_server = NULL;
+                                     break;
+                                   }
+                               }
+                             
+                             if (!(start = start->next))
+                               start = daemon->servers;
+                             if (start == server)
+                               break;
+                           }
+                         
+                         if (new_server)
+                           server = new_server;
+                       }
+                     
+                     new->sentto = server;
+                     new->rfd4 = NULL;
 #ifdef HAVE_IPV6
-                     if (server->addr.sa.sa_family == AF_INET6)
+                     new->rfd6 = NULL;
+#endif
+                     new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
+                     
+                     new->dependent = forward; /* to find query awaiting new one. */
+                     forward->blocking_query = new; /* for garbage cleaning */
+                     /* validate routines leave name of required record in daemon->keyname */
+                     if (status == STAT_NEED_KEY)
+                       {
+                         new->flags |= FREC_DNSKEY_QUERY; 
+                         nn = dnssec_generate_query(header, ((unsigned char *) header) + server->edns_pktsz,
+                                                    daemon->keyname, forward->class, T_DNSKEY, &server->addr, server->edns_pktsz);
+                       }
+                     else 
                        {
-                         if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6)))
-                           fd = new->rfd6->fd;
+                         new->flags |= FREC_DS_QUERY;
+                         nn = dnssec_generate_query(header,((unsigned char *) header) + server->edns_pktsz,
+                                                    daemon->keyname, forward->class, T_DS, &server->addr, server->edns_pktsz);
                        }
+                     if ((hash = hash_questions(header, nn, daemon->namebuff)))
+                       memcpy(new->hash, hash, HASH_SIZE);
+                     new->new_id = get_id();
+                     header->id = htons(new->new_id);
+                     /* Save query for retransmission */
+                     new->stash = blockdata_alloc((char *)header, nn);
+                     new->stash_len = nn;
+                     
+                     /* Don't resend this. */
+                     daemon->srv_save = NULL;
+                     
+                     if (server->sfd)
+                       fd = server->sfd->fd;
                      else
+                       {
+                         fd = -1;
+#ifdef HAVE_IPV6
+                         if (server->addr.sa.sa_family == AF_INET6)
+                           {
+                             if (new->rfd6 || (new->rfd6 = allocate_rfd(AF_INET6)))
+                               fd = new->rfd6->fd;
+                           }
+                         else
 #endif
+                           {
+                             if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET)))
+                               fd = new->rfd4->fd;
+                           }
+                       }
+                     
+                     if (fd != -1)
                        {
-                         if (new->rfd4 || (new->rfd4 = allocate_rfd(AF_INET)))
-                           fd = new->rfd4->fd;
+#ifdef HAVE_CONNTRACK
+                         /* Copy connection mark of incoming query to outgoing connection. */
+                         if (option_bool(OPT_CONNTRACK))
+                           {
+                             unsigned int mark;
+                             if (get_incoming_mark(&orig->source, &orig->dest, 0, &mark))
+                               setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
+                           }
+#endif
+                         while (retry_send(sendto(fd, (char *)header, nn, 0, 
+                                                  &server->addr.sa, 
+                                                  sa_len(&server->addr)))); 
+                         server->queries++;
                        }
-                   }
-                 
-                 if (fd != -1)
-                   {
-                     while (retry_send(sendto(fd, (char *)header, nn, 0, 
-                                              &server->addr.sa, 
-                                              sa_len(&server->addr)))); 
-                     server->queries++;
-                   }
-                 
+                   }             
                  return;
                }
-           }
          
-         /* Ok, we reached far enough up the chain-of-trust that we can validate something.
-            Now wind back down, pulling back answers which wouldn't previously validate
-            and validate them with the new data. Note that if an answer needs multiple
-            keys to validate, we may find another key is needed, in which case we set off
-            down another branch of the tree. Once we get to the original answer 
-            (FREC_DNSSEC_QUERY not set) and it validates, return it to the original requestor. */
-         while (forward->dependent)
-           {
+             /* Validated original answer, all done. */
+             if (!forward->dependent)
+               break;
+             
+             /* validated subsidiary query, (and cached result)
+                pop that and return to the previous query we were working on. */
              struct frec *prev = forward->dependent;
              free_frec(forward);
              forward = prev;
              forward->blocking_query = NULL; /* already gone */
              blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
              n = forward->stash_len;
-             
-             if (status == STAT_SECURE)
-               {
-                 if (forward->flags & FREC_DNSKEY_QUERY)
-                   status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
-                 else if (forward->flags & FREC_DS_QUERY)
-                   {
-                     status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
-                      /* Provably no DS, everything below is insecure, even if signatures are offered */
-                     if (status == STAT_NO_DS)
-                       /* We only cache sigs when we've validated a reply.
-                          Avoid caching a reply with sigs if there's a vaildated break in the 
-                          DS chain, so we don't return replies from cache missing sigs. */
-                       status = STAT_INSECURE_DS;
-                      else if (status == STAT_NO_SIG)
-                        {
-                          if (option_bool(OPT_DNSSEC_NO_SIGN))
-                            {
-                              status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname); 
-                              if (status == STAT_INSECURE)
-                                status = STAT_INSECURE_DS;
-                            }
-                          else
-                            status = STAT_INSECURE_DS;
-                        }
-                      else if (status == STAT_NO_NS)
-                        status = STAT_BOGUS;
-                   }
-                 else if (forward->flags & FREC_CHECK_NOSIGN)
-                   {
-                     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, NULL);   
-                     if (status == STAT_NO_SIG)
-                       {
-                         if (option_bool(OPT_DNSSEC_NO_SIGN))
-                           status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname);
-                         else
-                           status = STAT_INSECURE;
-                       }
-                   }
-              
-                 if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG || status == STAT_NEED_KEY)
-                   goto anotherkey;
-               }
            }
+       
          
          no_cache_dnssec = 0;
-
-         if (status == STAT_INSECURE_DS)
-           {
-             /* We only cache sigs when we've validated a reply.
-                Avoid caching a reply with sigs if there's a vaildated break in the 
-                DS chain, so we don't return replies from cache missing sigs. */
-             status = STAT_INSECURE;
-             no_cache_dnssec = 1;
-           }
          
          if (status == STAT_TRUNCATED)
            header->hb3 |= HB3_TC;
@@ -1062,7 +1079,7 @@ void reply_query(int fd, int family, time_t now)
            {
              char *result, *domain = "result";
              
-             if (forward->work_counter == 0)
+             if (status == STAT_ABANDONED)
                {
                  result = "ABANDONED";
                  status = STAT_BOGUS;
@@ -1072,7 +1089,7 @@ void reply_query(int fd, int family, time_t now)
              
              if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
                domain = daemon->namebuff;
-
+             
              log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
            }
          
@@ -1092,12 +1109,25 @@ void reply_query(int fd, int family, time_t now)
       else
        header->hb4 &= ~HB4_CD;
       
-      if ((nn = process_reply(header, now, server, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer, 
+      if ((nn = process_reply(header, now, forward->sentto, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer, 
                              forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION, 
                              forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->source)))
        {
          header->id = htons(forward->orig_id);
          header->hb4 |= HB4_RA; /* recursion if available */
+#ifdef HAVE_DNSSEC
+         /* We added an EDNSO header for the purpose of getting DNSSEC RRs, and set the value of the UDP payload size
+            greater than the no-EDNS0-implied 512 to have space for the RRSIGS. If, having stripped them and the EDNS0
+             header, the answer is still bigger than 512, truncate it and mark it so. The client then retries with TCP. */
+         if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER) && (nn > PACKETSZ))
+           {
+             header->ancount = htons(0);
+             header->nscount = htons(0);
+             header->arcount = htons(0);
+             header->hb3 |= HB3_TC;
+             nn = resize_packet(header, nn, NULL, 0);
+           }
+#endif
          send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn, 
                    &forward->source, &forward->dest, forward->iface);
        }
@@ -1110,12 +1140,13 @@ void receive_query(struct listener *listen, time_t now)
 {
   struct dns_header *header = (struct dns_header *)daemon->packet;
   union mysockaddr source_addr;
-  unsigned short type;
+  unsigned char *pheader;
+  unsigned short type, udp_size = PACKETSZ; /* default if no EDNS0 */
   struct all_addr dst_addr;
   struct in_addr netmask, dst_addr_4;
   size_t m;
   ssize_t n;
-  int if_index = 0, auth_dns = 0;
+  int if_index = 0, auth_dns = 0, do_bit = 0, have_pseudoheader = 0;
 #ifdef HAVE_AUTH
   int local_auth = 0;
 #endif
@@ -1179,6 +1210,10 @@ void receive_query(struct listener *listen, time_t now)
       (msg.msg_flags & MSG_TRUNC) ||
       (header->hb3 & HB3_QR))
     return;
+
+  /* Clear buffer beyond request to avoid risk of
+     information disclosure. */
+  memset(daemon->packet + n, 0, daemon->edns_pktsz - n);
   
   source_addr.sa.sa_family = listen->family;
   
@@ -1317,8 +1352,8 @@ void receive_query(struct listener *listen, time_t now)
        {
          struct irec *iface;
          
-         /* get the netmask of the interface whch has the address we were sent to.
-            This is no neccessarily the interface we arrived on. */
+         /* get the netmask of the interface which has the address we were sent to.
+            This is no necessarily the interface we arrived on. */
          
          for (iface = daemon->interfaces; iface; iface = iface->next)
            if (iface->addr.sa.sa_family == AF_INET &&
@@ -1365,7 +1400,7 @@ void receive_query(struct listener *listen, time_t now)
 
 #ifdef HAVE_AUTH
       /* find queries for zones we're authoritative for, and answer them directly */
-      if (!auth_dns)
+      if (!auth_dns && !option_bool(OPT_LOCALISE))
        for (zone = daemon->auth_zones; zone; zone = zone->next)
          if (in_zone(zone, daemon->namebuff, NULL))
            {
@@ -1382,10 +1417,32 @@ void receive_query(struct listener *listen, time_t now)
 #endif
     }
   
+  if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL, NULL))
+    { 
+      unsigned short flags;
+      
+      have_pseudoheader = 1;
+      GETSHORT(udp_size, pheader);
+      pheader += 2; /* ext_rcode */
+      GETSHORT(flags, pheader);
+      
+      if (flags & 0x8000)
+       do_bit = 1;/* do bit */ 
+       
+      /* If the client provides an EDNS0 UDP size, use that to limit our reply.
+        (bounded by the maximum configured). If no EDNS0, then it
+        defaults to 512 */
+      if (udp_size > daemon->edns_pktsz)
+       udp_size = daemon->edns_pktsz;
+      else if (udp_size < PACKETSZ)
+       udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */
+    }
+
 #ifdef HAVE_AUTH
   if (auth_dns)
     {
-      m = answer_auth(header, ((char *) header) + daemon->packet_buff_sz, (size_t)n, now, &source_addr, local_auth);
+      m = answer_auth(header, ((char *) header) + udp_size, (size_t)n, now, &source_addr, 
+                     local_auth, do_bit, have_pseudoheader);
       if (m >= 1)
        {
          send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
@@ -1396,9 +1453,13 @@ void receive_query(struct listener *listen, time_t now)
   else
 #endif
     {
-      int ad_reqd, do_bit;
-      m = answer_request(header, ((char *) header) + daemon->packet_buff_sz, (size_t)n, 
-                        dst_addr_4, netmask, now, &ad_reqd, &do_bit);
+      int ad_reqd = do_bit;
+       /* RFC 6840 5.7 */
+      if (header->hb4 & HB4_AD)
+       ad_reqd = 1;
+
+      m = answer_request(header, ((char *) header) + udp_size, (size_t)n, 
+                        dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
       
       if (m >= 1)
        {
@@ -1415,390 +1476,152 @@ void receive_query(struct listener *listen, time_t now)
 }
 
 #ifdef HAVE_DNSSEC
-
-/* 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(struct frec *forward, time_t now, struct dns_header *header, size_t plen, 
-                          char *name, char *keyname)
+/* Recurse up the key hierarchy */
+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 have_mark, unsigned int mark, int *keycount)
 {
-  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);
-}
+  int new_status;
+  unsigned char *packet = NULL;
+  unsigned char *payload = NULL;
+  struct dns_header *new_header = NULL;
+  u16 *length = NULL;
  
-/* 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->orig_domain)
-    forward = forward->dependent;
-
-  blockdata_retrieve(forward->orig_domain, forward->name_len, name);
-  
   while (1)
     {
-      char *p; 
+      int type = SERV_DO_DNSSEC;
+      char *domain;
+      size_t m; 
+      unsigned char c1, c2;
+      struct server *firstsendto = NULL;
+      
+      /* limit the amount of work we do, to avoid cycling forever on loops in the DNS */
+      if (--(*keycount) == 0)
+       new_status = STAT_ABANDONED;
+      else if (status == STAT_NEED_KEY)
+       new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
+      else if (status == STAT_NEED_DS)
+       new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
+      else 
+       new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
+                                          option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC),
+                                          NULL, NULL);
+      
+      if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
+       break;
 
-      if (status == 0)
+      /* Can't validate because we need a key/DS whose name now in keyname.
+        Make query for same, and recurse to validate */
+      if (!packet)
        {
-         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;
+         packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
+         payload = &packet[2];
+         new_header = (struct dns_header *)payload;
+         length = (u16 *)packet;
        }
       
-      /* Have entered non-signed part of DNS tree. */ 
-      if (status == STAT_NO_DS)
-       return forward->dependent ? STAT_INSECURE_DS : STAT_INSECURE;
-
-      if (status == STAT_BOGUS)
-       return STAT_BOGUS;
-
-      if (status == STAT_NO_SIG && *keyname != 0)
+      if (!packet)
        {
-         /* There is a validated CNAME chain that doesn't end in a DS record. Start 
-            the search again in that domain. */
-         blockdata_free(forward->orig_domain);
-         forward->name_start = strlen(keyname);
-         forward->name_len = forward->name_start + 1;
-         if (!(forward->orig_domain = blockdata_alloc(keyname, forward->name_len)))
-           return STAT_BOGUS;
-         
-         strcpy(name, keyname);
-         status = 0; /* force to cache when we iterate. */
-         continue;
+         new_status = STAT_ABANDONED;
+         break;
        }
+        
+      m = dnssec_generate_query(new_header, ((unsigned char *) new_header) + 65536, keyname, class, 
+                               new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr, server->edns_pktsz);
       
-      /* 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 */
-
-      if (forward->name_start == 0)
-       return STAT_BOGUS;
-      
-      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. */
-    }
-}
-
-/* Move down from the root, until we find a signed non-existance of a DS, in which case
-   an unsigned answer is OK, or we find a signed DS, in which case there should be 
-   a signature, and the answer is BOGUS */
-static int  tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, size_t plen, int class, char *name, 
-                                       char *keyname, struct server *server, int *keycount)
-{
-  size_t m;
-  unsigned char *packet, *payload;
-  u16 *length;
-  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);
-  if (status == STAT_BOGUS)
-    return STAT_BOGUS;
-  
-  if (!(packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16))))
-    return STAT_BOGUS;
-  
-  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 c1, c2;
-      struct crec *crecp;
+      *length = htons(m);
 
-      if (--(*keycount) == 0)
+      /* Find server to forward to. This will normally be the 
+        same as for the original query, but may be another if
+        servers for domains are involved. */                 
+      if (search_servers(now, NULL, F_DNSSECOK, keyname, &type, &domain, NULL) != 0)
        {
-         free(packet);
-         blockdata_free(block);
-         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++;
+         new_status = STAT_ABANDONED;
+         break;
        }
-      
-      /* 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, server->edns_pktsz);
-      
-      *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))
+       
+      while (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 (status == STAT_NO_DS)
+         if (!firstsendto)
+           firstsendto = server;
+         else
            {
-             /* Found a secure denial of DS - delegation is indeed insecure */
-             free(packet);
-             blockdata_free(block);
-             return STAT_INSECURE;
+             if (!(server = server->next))
+               server = daemon->servers;
+             if (server == firstsendto)
+               {
+                 /* can't find server to accept our query. */
+                 new_status = STAT_ABANDONED;
+                 break;
+               }
            }
          
-         if (status == STAT_NO_SIG && *keyname != 0)
-           {
-             /* There is a validated CNAME chain that doesn't end in a DS record. Start 
-                the search again in that domain. */
-             blockdata_free(block);
-             name_len = strlen(keyname) + 1;
-             name_start = name + name_len - 1;
-             
-             if (!(block = blockdata_alloc(keyname, name_len)))
-               return STAT_BOGUS;
-             
-             strcpy(name, keyname);
-             continue;
-           }
+         if (type != (server->flags & (SERV_TYPE | SERV_DO_DNSSEC)) ||
+             (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, server->domain)) ||
+             (server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
+           continue;
+           
+         retry:
+           /* may need to make new connection. */
+           if (server->tcpfd == -1)
+             {
+               if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
+                 continue; /* No good, next server */
+               
+#ifdef HAVE_CONNTRACK
+               /* Copy connection mark of incoming query to outgoing connection. */
+               if (have_mark)
+                 setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
+#endif 
+               
+               if (!local_bind(server->tcpfd,  &server->source_addr, server->interface, 0, 1) ||
+                   connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
+                 {
+                   close(server->tcpfd);
+                   server->tcpfd = -1;
+                   continue; /* No good, next server */
+                 }
+               
+               server->flags &= ~SERV_GOT_TCP;
+             }
          
-         if (status == STAT_BOGUS)
+         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))
            {
-             free(packet);
-             blockdata_free(block);
-             return STAT_BOGUS;
+             close(server->tcpfd);
+             server->tcpfd = -1;
+             /* We get data then EOF, reopen connection to same server,
+                else try next. This avoids DoS from a server which accepts
+                connections and then closes them. */
+             if (server->flags & SERV_GOT_TCP)
+               goto retry;
+             else
+               continue;
            }
          
-         /* Here, either there's a secure DS, or no NS and no DS, and therefore no delegation.
-            Add another label and continue. */
+         server->flags |= SERV_GOT_TCP;
          
-         /* 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 */
-       }
-    }
-}
-
-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)
-{
-  /* Recurse up the key heirarchy */
-  int new_status;
-
-  /* limit the amount of work we do, to avoid cycling forever on loops in the DNS */
-  if (--(*keycount) == 0)
-    return STAT_INSECURE;
-  
-  if (status == STAT_NEED_KEY)
-    new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
-  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)
-       {
-         if (new_status == STAT_NO_DS)
-           new_status = STAT_INSECURE_DS;
-         if (new_status == STAT_NO_SIG)
-          {
-            if (option_bool(OPT_DNSSEC_NO_SIGN))
-              {
-                new_status = tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, server, keycount);
-                if (new_status == STAT_INSECURE)
-                  new_status = STAT_INSECURE_DS;
-              }
-            else
-              new_status = STAT_INSECURE_DS;
-          }
-         else if (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, NULL);
-      
-      if (new_status == STAT_NO_SIG)
-       {
-         if (option_bool(OPT_DNSSEC_NO_SIGN))
-           new_status = tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, server, keycount);
-         else
-           new_status = STAT_INSECURE;
-       }
-    }
-
-  /* Can't validate because we need a key/DS whose name now in keyname.
-     Make query for same, and recurse to validate */
-  if (new_status == STAT_NEED_DS || new_status == STAT_NEED_KEY)
-    {
-      size_t m; 
-      unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
-      unsigned char *payload = &packet[2];
-      struct dns_header *new_header = (struct dns_header *)payload;
-      u16 *length = (u16 *)packet;
-      unsigned char c1, c2;
-       
-      if (!packet)
-       return STAT_INSECURE;
-
-    another_tcp_key:
-      m = dnssec_generate_query(new_header, ((char *) new_header) + 65536, keyname, class, 
-                               new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr, server->edns_pktsz);
-      
-      *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))
-       new_status = STAT_INSECURE;
-      else
-       {
          m = (c1 << 8) | c2;
-         
-         new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, keycount);
-         
-         if (new_status == STAT_SECURE)
-           {
-             /* Reached a validated record, now try again at this level.
-                Note that we may get ANOTHER NEED_* if an answer needs more than one key.
-                If so, go round again. */
-             
-             if (status == STAT_NEED_KEY)
-               new_status = dnssec_validate_by_ds(now, header, n, name, keyname, class);
-             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)
-                   {
-                     if (new_status == STAT_NO_DS)
-                       new_status = STAT_INSECURE_DS;
-                     else if (new_status == STAT_NO_SIG)
-                       {
-                         if (option_bool(OPT_DNSSEC_NO_SIGN))
-                           {
-                             new_status = tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, server, keycount); 
-                             if (new_status == STAT_INSECURE)
-                               new_status = STAT_INSECURE_DS;
-                           }
-                         else
-                           new_status = STAT_INSECURE_DS;
-                       }
-                     else if (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, NULL);
-                 
-                 if (new_status == STAT_NO_SIG)
-                   {
-                     if (option_bool(OPT_DNSSEC_NO_SIGN))
-                       new_status = tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, server, keycount);
-                     else
-                       new_status = STAT_INSECURE;
-                   }
-               }
-             
-             if (new_status == STAT_NEED_DS || new_status == STAT_NEED_KEY)
-               goto another_tcp_key;
-           }
+         new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
+         break;
        }
       
-      free(packet);
+      if (new_status != STAT_OK)
+       break;
     }
+    
+  if (packet)
+    free(packet);
+    
   return new_status;
 }
 #endif
 
 
 /* The daemon forks before calling this: it should deal with one connection,
-   blocking as neccessary, and then return. Note, need to be a bit careful
+   blocking as necessary, and then return. Note, need to be a bit careful
    about resources for debug mode, when the fork is suppressed: that's
    done by the caller. */
 unsigned char *tcp_request(int confd, time_t now,
@@ -1809,7 +1632,7 @@ unsigned char *tcp_request(int confd, time_t now,
 #ifdef HAVE_AUTH
   int local_auth = 0;
 #endif
-  int checking_disabled, ad_question, do_bit, added_pheader = 0;
+  int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
   int check_subnet, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
   size_t m;
   unsigned short qtype;
@@ -1826,10 +1649,32 @@ unsigned char *tcp_request(int confd, time_t now,
   union mysockaddr peer_addr;
   socklen_t peer_len = sizeof(union mysockaddr);
   int query_count = 0;
+  unsigned char *pheader;
+  unsigned int mark = 0;
+  int have_mark = 0;
+
+  (void)mark;
+  (void)have_mark;
 
   if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
     return packet;
-  
+
+#ifdef HAVE_CONNTRACK
+  /* Get connection mark of incoming query to set on outgoing connections. */
+  if (option_bool(OPT_CONNTRACK))
+    {
+      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;
+      
+      have_mark = get_incoming_mark(&peer_addr, &local, 1, &mark);
+    }
+#endif 
+
   /* We can be configured to only accept queries from at-most-one-hop-away addresses. */
   if (option_bool(OPT_LOCAL_SERVICE))
     {
@@ -1872,6 +1717,10 @@ unsigned char *tcp_request(int confd, time_t now,
   
       if (size < (int)sizeof(struct dns_header))
        continue;
+
+      /* Clear buffer beyond request to avoid risk of
+        information disclosure. */
+      memset(payload + size, 0, 65536 - size);
       
       query_count++;
 
@@ -1880,8 +1729,6 @@ unsigned char *tcp_request(int confd, time_t now,
       daemon->log_display_id = ++daemon->log_id;
       daemon->log_source_addr = &peer_addr;
       
-      check_subnet = 0;
-
       /* save state of "cd" flag in query */
       if ((checking_disabled = header->hb4 & HB4_CD))
        no_cache_dnssec = 1;
@@ -1904,7 +1751,7 @@ unsigned char *tcp_request(int confd, time_t now,
          
 #ifdef HAVE_AUTH
          /* find queries for zones we're authoritative for, and answer them directly */
-         if (!auth_dns)
+         if (!auth_dns && !option_bool(OPT_LOCALISE))
            for (zone = daemon->auth_zones; zone; zone = zone->next)
              if (in_zone(zone, daemon->namebuff, NULL))
                {
@@ -1920,15 +1767,35 @@ unsigned char *tcp_request(int confd, time_t now,
       else
        dst_addr_4.s_addr = 0;
       
+      do_bit = 0;
+
+      if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
+       { 
+         unsigned short flags;
+         
+         have_pseudoheader = 1;
+         pheader += 4; /* udp_size, ext_rcode */
+         GETSHORT(flags, pheader);
+      
+         if (flags & 0x8000)
+           do_bit = 1; /* do bit */ 
+       }
+
 #ifdef HAVE_AUTH
       if (auth_dns)
-       m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr, local_auth);
+       m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr, 
+                       local_auth, do_bit, have_pseudoheader);
       else
 #endif
        {
-         /* m > 0 if answered from cache */
-         m = answer_request(header, ((char *) header) + 65536, (size_t)size, 
-                            dst_addr_4, netmask, now, &ad_question, &do_bit);
+          int ad_reqd = do_bit;
+          /* RFC 6840 5.7 */
+          if (header->hb4 & HB4_AD)
+            ad_reqd = 1;
+          
+          /* m > 0 if answered from cache */
+          m = answer_request(header, ((char *) header) + 65536, (size_t)size, 
+                             dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader);
          
          /* Do this by steam now we're not in the select() loop */
          check_log_writer(1); 
@@ -1937,24 +1804,33 @@ unsigned char *tcp_request(int confd, time_t now,
            {
              unsigned int flags = 0;
              struct all_addr *addrp = NULL;
-             int type = 0;
+             int type = SERV_DO_DNSSEC;
              char *domain = NULL;
-             
-             if (option_bool(OPT_ADD_MAC))
-               size = add_mac(header, size, ((char *) header) + 65536, &peer_addr);
-               
-             if (option_bool(OPT_CLIENT_SUBNET))
-               {
-                 size_t new = add_source_addr(header, size, ((char *) header) + 65536, &peer_addr);
-                 if (size != new)
-                   {
-                     size = new;
-                     check_subnet = 1;
-                   }
-               }
+             unsigned char *oph = find_pseudoheader(header, size, NULL, NULL, NULL, NULL);
+
+             size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet);
 
              if (gotname)
                flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
+
+#ifdef HAVE_DNSSEC
+             if (option_bool(OPT_DNSSEC_VALID) && (type & SERV_DO_DNSSEC))
+               {
+                 size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
+                 
+                 /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
+                    this allows it to select auth servers when one is returning bad data. */
+                 if (option_bool(OPT_DNSSEC_DEBUG))
+                   header->hb4 |= HB4_CD;
+               }
+#endif
+
+             /* Check if we added a pheader on forwarding - may need to
+                strip it from the reply. */
+             if (!oph && find_pseudoheader(header, size, NULL, NULL, NULL, NULL))
+               added_pheader = 1;
+
+             type &= ~SERV_DO_DNSSEC;
              
              if (type != 0  || option_bool(OPT_ORDER) || !daemon->last_server)
                last_server = daemon->servers;
@@ -1974,7 +1850,7 @@ unsigned char *tcp_request(int confd, time_t now,
                  unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
 #endif           
                  /* Loop round available servers until we succeed in connecting to one.
-                    Note that this code subtley ensures that consecutive queries on this connection
+                    Note that this code subtly ensures that consecutive queries on this connection
                     which can go to the same server, do so. */
                  while (1) 
                    {
@@ -1994,7 +1870,8 @@ unsigned char *tcp_request(int confd, time_t now,
                          (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)) ||
                          (last_server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
                        continue;
-                     
+
+                   retry:
                      if (last_server->tcpfd == -1)
                        {
                          if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
@@ -2002,23 +1879,11 @@ unsigned char *tcp_request(int confd, time_t now,
                          
 #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));
-                           }
+                         if (have_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) ||
+                         if ((!local_bind(last_server->tcpfd,  &last_server->source_addr, last_server->interface, 0, 1) ||
                               connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
                            {
                              close(last_server->tcpfd);
@@ -2026,22 +1891,7 @@ unsigned char *tcp_request(int confd, time_t now,
                              continue;
                            }
                          
-#ifdef HAVE_DNSSEC
-                         if (option_bool(OPT_DNSSEC_VALID))
-                           {
-                             size_t new_size = add_do_bit(header, size, ((char *) header) + 65536);
-                             
-                             /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
-                                this allows it to select auth servers when one is returning bad data. */
-                             if (option_bool(OPT_DNSSEC_DEBUG))
-                               header->hb4 |= HB4_CD;
-                             
-                             if (size != new_size)
-                               added_pheader = 1;
-                             
-                             size = new_size;
-                           }
-#endif
+                         last_server->flags &= ~SERV_GOT_TCP;
                        }
                      
                      *length = htons(size);
@@ -2057,9 +1907,17 @@ unsigned char *tcp_request(int confd, time_t now,
                        {
                          close(last_server->tcpfd);
                          last_server->tcpfd = -1;
-                         continue;
-                       } 
+                         /* We get data then EOF, reopen connection to same server,
+                            else try next. This avoids DoS from a server which accepts
+                            connections and then closes them. */
+                         if (last_server->flags & SERV_GOT_TCP)
+                           goto retry;
+                         else
+                           continue;
+                       }
                      
+                     last_server->flags |= SERV_GOT_TCP;
+
                      m = (c1 << 8) | c2;
                      
                      if (last_server->addr.sa.sa_family == AF_INET)
@@ -2072,22 +1930,14 @@ unsigned char *tcp_request(int confd, time_t now,
 #endif 
 
 #ifdef HAVE_DNSSEC
-                     if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled)
+                     if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC))
                        {
                          int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
-                         int status = tcp_key_recurse(now, STAT_TRUNCATED, header, m, 0, daemon->namebuff, daemon->keyname, last_server, &keycount);
+                         int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname, 
+                                                      last_server, have_mark, mark, &keycount);
                          char *result, *domain = "result";
-
-                         if (status == STAT_INSECURE_DS)
-                           {
-                             /* We only cache sigs when we've validated a reply.
-                                Avoid caching a reply with sigs if there's a vaildated break in the 
-                                DS chain, so we don't return replies from cache missing sigs. */
-                             status = STAT_INSECURE;
-                             no_cache_dnssec = 1;
-                           }
                          
-                         if (keycount == 0)
+                         if (status == STAT_ABANDONED)
                            {
                              result = "ABANDONED";
                              status = STAT_BOGUS;
@@ -2140,7 +1990,7 @@ unsigned char *tcp_request(int confd, time_t now,
 
                      m = process_reply(header, now, last_server, (unsigned int)m, 
                                        option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
-                                       ad_question, do_bit, added_pheader, check_subnet, &peer_addr); 
+                                       ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr); 
                      
                      break;
                    }
@@ -2179,7 +2029,6 @@ 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;
     }
@@ -2248,12 +2097,6 @@ 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);
@@ -2262,6 +2105,8 @@ static void free_frec(struct frec *f)
 #endif
 }
 
+
+
 /* if wait==NULL return a free or older than TIMEOUT record.
    else return *wait zero if one available, or *wait is delay to
    when the oldest in-use record will expire. Impose an absolute
@@ -2281,14 +2126,23 @@ struct frec *get_new_frec(time_t now, int *wait, int force)
       target = f;
     else 
       {
-       if (difftime(now, f->time) >= 4*TIMEOUT)
-         {
-           free_frec(f);
-           target = f;
-         }
-       
-       if (!oldest || difftime(f->time, oldest->time) <= 0)
-         oldest = f;
+#ifdef HAVE_DNSSEC
+           /* Don't free DNSSEC sub-queries here, as we may end up with
+              dangling references to them. They'll go when their "real" query 
+              is freed. */
+           if (!f->dependent)
+#endif
+             {
+               if (difftime(now, f->time) >= 4*TIMEOUT)
+                 {
+                   free_frec(f);
+                   target = f;
+                 }
+            
+           
+               if (!oldest || difftime(f->time, oldest->time) <= 0)
+                 oldest = f;
+             }
       }
 
   if (target)
@@ -2299,7 +2153,7 @@ struct frec *get_new_frec(time_t now, int *wait, int force)
   
   /* can't find empty one, use oldest if there is one
      and it's older than timeout */
-  if (oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
+  if (!force && oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
     { 
       /* keep stuff for twice timeout if we can by allocating a new
         record instead */
@@ -2339,7 +2193,7 @@ struct frec *get_new_frec(time_t now, int *wait, int force)
 
   return f; /* OK if malloc fails and this is NULL */
 }
+
 /* crc is all-ones if not known. */
 static struct frec *lookup_frec(unsigned short id, void *hash)
 {
index 1fee72d..c134071 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -18,7 +18,7 @@
 
 #ifdef HAVE_SCRIPT
 
-/* This file has code to fork a helper process which recieves data via a pipe 
+/* This file has code to fork a helper process which receives data via a pipe 
    shared with the main process and which is responsible for calling a script when
    DHCP leases change.
 
@@ -97,13 +97,14 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
       return pipefd[1];
     }
 
-  /* ignore SIGTERM, so that we can clean up when the main process gets hit
+  /* ignore SIGTERM and SIGINT, so that we can clean up when the main process gets hit
      and SIGALRM so that we can use sleep() */
   sigact.sa_handler = SIG_IGN;
   sigact.sa_flags = 0;
   sigemptyset(&sigact.sa_mask);
   sigaction(SIGTERM, &sigact, NULL);
   sigaction(SIGALRM, &sigact, NULL);
+  sigaction(SIGINT, &sigact, NULL);
 
   if (!option_bool(OPT_DEBUG) && uid != 0)
     {
@@ -135,7 +136,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
        max_fd != STDIN_FILENO && max_fd != pipefd[0] && 
        max_fd != event_fd && max_fd != err_fd)
       close(max_fd);
-  
+
 #ifdef HAVE_LUASCRIPT
   if (daemon->luascript)
     {
@@ -189,6 +190,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
       unsigned char *buf = (unsigned char *)daemon->namebuff;
       unsigned char *end, *extradata, *alloc_buff = NULL;
       int is6, err = 0;
+      int pipeout[2];
 
       free(alloc_buff);
       
@@ -219,7 +221,18 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
          action_str = "tftp";
          is6 = (data.flags != AF_INET);
        }
-      else
+      else if (data.action == ACTION_ARP)
+       {
+         action_str = "arp-add";
+         is6 = (data.flags != AF_INET);
+       }
+       else if (data.action == ACTION_ARP_DEL)
+       {
+         action_str = "arp-del";
+         is6 = (data.flags != AF_INET);
+         data.action = ACTION_ARP;
+       }
+       else 
        continue;
 
        
@@ -289,7 +302,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
     
       if (!is6)
        inet_ntop(AF_INET, &data.addr, daemon->addrbuff, ADDRSTRLEN);
-#ifdef HAVE_DHCP6
+#ifdef HAVE_IPV6
       else
        inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN);
 #endif
@@ -321,6 +334,22 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
                  lua_call(lua, 2, 0);  /* pass 2 values, expect 0 */
                }
            }
+         else if (data.action == ACTION_ARP)
+           {
+             lua_getglobal(lua, "arp"); 
+             if (lua_type(lua, -1) != LUA_TFUNCTION)
+               lua_pop(lua, 1); /* arp function optional */
+             else
+               {
+                 lua_pushstring(lua, action_str); /* arg1 - action */
+                 lua_newtable(lua);               /* arg2 - data table */
+                 lua_pushstring(lua, daemon->addrbuff);
+                 lua_setfield(lua, -2, "client_address");
+                 lua_pushstring(lua, daemon->dhcp_buff);
+                 lua_setfield(lua, -2, "mac_address");
+                 lua_call(lua, 2, 0);  /* pass 2 values, expect 0 */
+               }
+           }
          else
            {
              lua_getglobal(lua, "lease");     /* function to call */
@@ -445,16 +474,54 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
       if (!daemon->lease_change_command)
        continue;
 
+      /* Pipe to capture stdout and stderr from script */
+      if (!option_bool(OPT_DEBUG) && pipe(pipeout) == -1)
+       continue;
+      
       /* possible fork errors are all temporary resource problems */
       while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM))
        sleep(2);
 
       if (pid == -1)
-       continue;
+        {
+         if (!option_bool(OPT_DEBUG))
+           {
+             close(pipeout[0]);
+             close(pipeout[1]);
+           }
+         continue;
+        }
       
       /* wait for child to complete */
       if (pid != 0)
        {
+         if (!option_bool(OPT_DEBUG))
+           {
+             FILE *fp;
+         
+             close(pipeout[1]);
+             
+             /* Read lines sent to stdout/err by the script and pass them back to be logged */
+             if (!(fp = fdopen(pipeout[0], "r")))
+               close(pipeout[0]);
+             else
+               {
+                 while (fgets(daemon->packet, daemon->packet_buff_sz, fp))
+                   {
+                     /* do not include new lines, log will append them */
+                     size_t len = strlen(daemon->packet);
+                     if (len > 0)
+                       {
+                         --len;
+                         if (daemon->packet[len] == '\n')
+                           daemon->packet[len] = 0;
+                       }
+                     send_event(event_fd, EVENT_SCRIPT_LOG, 0, daemon->packet);
+                   }
+                 fclose(fp);
+               }
+           }
+         
          /* reap our children's children, if necessary */
          while (1)
            {
@@ -477,8 +544,17 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
          
          continue;
        }
+
+      if (!option_bool(OPT_DEBUG))
+       {
+         /* map stdout/stderr of script to pipeout */
+         close(pipeout[0]);
+         dup2(pipeout[1], STDOUT_FILENO);
+         dup2(pipeout[1], STDERR_FILENO);
+         close(pipeout[1]);
+       }
       
-      if (data.action != ACTION_TFTP)
+      if (data.action != ACTION_TFTP && data.action != ACTION_ARP)
        {
 #ifdef HAVE_DHCP6
          my_setenv("DNSMASQ_IAID", is6 ? daemon->dhcp_buff3 : NULL, &err);
@@ -529,6 +605,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
              buf = grab_extradata(buf, end, "DNSMASQ_CIRCUIT_ID", &err);
              buf = grab_extradata(buf, end, "DNSMASQ_SUBSCRIBER_ID", &err);
              buf = grab_extradata(buf, end, "DNSMASQ_REMOTE_ID", &err);
+             buf = grab_extradata(buf, end, "DNSMASQ_REQUESTED_OPTIONS", &err);
            }
          
          buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err);
@@ -550,9 +627,9 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
          my_setenv("DNSMASQ_OLD_HOSTNAME", data.action == ACTION_OLD_HOSTNAME ? hostname : NULL, &err);
          if (data.action == ACTION_OLD_HOSTNAME)
            hostname = NULL;
+         
+         my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err);
        }
-
-      my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err);
       
       /* we need to have the event_fd around if exec fails */
       if ((i = fcntl(event_fd, F_GETFD)) != -1)
@@ -563,8 +640,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
       if (err == 0)
        {
          execl(daemon->lease_change_command, 
-               p ? p+1 : daemon->lease_change_command,
-               action_str, is6 ? daemon->packet : daemon->dhcp_buff, 
+               p ? p+1 : daemon->lease_change_command, action_str, 
+               (is6 && data.action != ACTION_ARP) ? daemon->packet : daemon->dhcp_buff, 
                daemon->addrbuff, hostname, (char*)NULL);
          err = errno;
        }
@@ -760,6 +837,30 @@ void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)
 }
 #endif
 
+void queue_arp(int action, unsigned char *mac, int maclen, int family, struct all_addr *addr)
+{
+  /* no script */
+  if (daemon->helperfd == -1)
+    return;
+  
+  buff_alloc(sizeof(struct script_data));
+  memset(buf, 0, sizeof(struct script_data));
+
+  buf->action = action;
+  buf->hwaddr_len = maclen;
+  buf->hwaddr_type =  ARPHRD_ETHER; 
+  if ((buf->flags = family) == AF_INET)
+    buf->addr = addr->addr.addr4;
+#ifdef HAVE_IPV6
+  else
+    buf->addr6 = addr->addr.addr6;
+#endif
+  
+  memcpy(buf->hwaddr, mac, maclen);
+  
+  bytes_in_buf = sizeof(struct script_data);
+}
+
 int helper_buf_empty(void)
 {
   return bytes_in_buf == 0;
index 52d412f..7107833 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -20,7 +20,7 @@
 #include <sys/inotify.h>
 #include <sys/param.h> /* For MAXSYMLINKS */
 
-/* the strategy is to set a inotify on the directories containing
+/* the strategy is to set an inotify on the directories containing
    resolv files, for any files in the directory which are close-write 
    or moved into the directory.
    
@@ -54,7 +54,10 @@ static char *my_readlink(char *path)
        {
          /* Not link or doesn't exist. */
          if (errno == EINVAL || errno == ENOENT)
-           return NULL;
+           {
+             free(buf);
+             return NULL;
+           }
          else
            die(_("cannot access path %s: %s"), path, EC_MISC);
        }
@@ -90,6 +93,9 @@ void inotify_dnsmasq_init()
   
   if (daemon->inotifyfd == -1)
     die(_("failed to create inotify: %s"), NULL, EC_MISC);
+
+  if (option_bool(OPT_NO_RESOLV))
+    return;
   
   for (res = daemon->resolv_files; res; res = res->next)
     {
@@ -98,7 +104,7 @@ void inotify_dnsmasq_init()
 
       strcpy(path, res->name);
 
-      /* Follow symlinks until we reach a non-symlink, or a non-existant file. */
+      /* Follow symlinks until we reach a non-symlink, or a non-existent file. */
       while ((new_path = my_readlink(path)))
        {
          if (links-- == 0)
@@ -197,6 +203,8 @@ void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revh
               free(path);
             }
         }
+
+       closedir(dir_stream);
     }
 }
 
@@ -219,19 +227,21 @@ int inotify_check(time_t now)
       
       for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len) 
        {
+         size_t namelen;
+
          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] == '#') ||
+         if (in->len == 0 || (namelen = strlen(in->name)) == 0 ||
+             in->name[namelen - 1] == '~' ||
+             (in->name[0] == '#' && in->name[namelen - 1] == '#') ||
              in->name[0] == '.')
            continue;
-         
+
+         for (res = daemon->resolv_files; res; res = res->next)
+           if (res->wd == in->wd && strcmp(res->file, in->name) == 0)
+             hit = 1;
+
          for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
            if (ah->wd == in->wd)
              {
@@ -252,7 +262,7 @@ int inotify_check(time_t now)
 #ifdef HAVE_DHCP
                        if (daemon->dhcp || daemon->doing_dhcp6) 
                          {
-                           /* Propogate the consequences of loading a new dhcp-host */
+                           /* Propagate the consequences of loading a new dhcp-host */
                            dhcp_update_configs(daemon->dhcp_conf);
                            lease_update_from_configs(); 
                            lease_update_file(now); 
@@ -265,7 +275,7 @@ int inotify_check(time_t now)
                      {
                        if (option_read_dynfile(path, AH_DHCP_HST))
                          {
-                           /* Propogate the consequences of loading a new dhcp-host */
+                           /* Propagate the consequences of loading a new dhcp-host */
                            dhcp_update_configs(daemon->dhcp_conf);
                            lease_update_from_configs(); 
                            lease_update_file(now); 
index f0b7e82..6f6dff7 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
index a315e86..3a5ecc5 100644 (file)
@@ -211,7 +211,7 @@ static int old_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
 
 int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags, int remove)
 {
-  int af = AF_INET;
+  int ret = 0, af = AF_INET;
 
 #ifdef HAVE_IPV6
   if (flags & F_IPV6)
@@ -219,11 +219,20 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags,
       af = AF_INET6;
       /* old method only supports IPv4 */
       if (old_kernel)
-       return -1;
+       {
+         errno = EAFNOSUPPORT ;
+         ret = -1;
+       }
     }
 #endif
   
-  return old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);
+  if (ret != -1) 
+    ret = old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);
+
+  if (ret == -1)
+     my_syslog(LOG_ERR, _("failed to update ipset %s: %s"), setname, strerror(errno));
+
+  return ret;
 }
 
 #endif
index 8adb605..5c33df7 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
 static struct dhcp_lease *leases = NULL, *old_leases = NULL;
 static int dns_dirty, file_dirty, leases_left;
 
-void lease_init(time_t now)
+static int read_leases(time_t now, FILE *leasestream)
 {
   unsigned long ei;
   struct all_addr addr;
   struct dhcp_lease *lease;
   int clid_len, hw_len, hw_type;
-  FILE *leasestream;
-  
-  leases_left = daemon->dhcp_max;
-  
-  if (option_bool(OPT_LEASE_RO))
-    {
-      /* run "<lease_change_script> init" once to get the
-        initial state of the database. If leasefile-ro is
-        set without a script, we just do without any 
-        lease database. */
-#ifdef HAVE_SCRIPT
-      if (daemon->lease_change_command)
-       {
-         strcpy(daemon->dhcp_buff, daemon->lease_change_command);
-         strcat(daemon->dhcp_buff, " init");
-         leasestream = popen(daemon->dhcp_buff, "r");
-       }
-      else
+  int items;
+  char *domain = NULL;
+
+  *daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
+
+  /* client-id max length is 255 which is 255*2 digits + 254 colons
+     borrow DNS packet buffer which is always larger than 1000 bytes
+
+     Check various buffers are big enough for the code below */
+
+#if (DHCP_BUFF_SZ < 255) || (MAXDNAME < 64) || (PACKETSZ+MAXDNAME+RRFIXEDSZ  < 764)
+# error Buffer size breakage in leasefile parsing.
 #endif
-       {
-          file_dirty = dns_dirty = 0;
-          return;
-        }
 
-    }
-  else
-    {
-      /* NOTE: need a+ mode to create file if it doesn't exist */
-      leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
-      
-      if (!leasestream)
-       die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
-      
-      /* a+ mode leaves pointer at end. */
-      rewind(leasestream);
-    }
-  
-  /* client-id max length is 255 which is 255*2 digits + 254 colons 
-     borrow DNS packet buffer which is always larger than 1000 bytes */
-  if (leasestream)
-    while (fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2) == 2)
+    while ((items=fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2)) == 2)
       {
+       *daemon->namebuff = *daemon->dhcp_buff = *daemon->packet = '\0';
+       hw_len = hw_type = clid_len = 0;
+       
 #ifdef HAVE_DHCP6
        if (strcmp(daemon->dhcp_buff3, "duid") == 0)
          {
            daemon->duid_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, 130, NULL, NULL);
+           if (daemon->duid_len < 0)
+             return 0;
            daemon->duid = safe_malloc(daemon->duid_len);
            memcpy(daemon->duid, daemon->dhcp_buff2, daemon->duid_len);
            continue;
          }
 #endif
-
-       ei = atol(daemon->dhcp_buff3);
        
        if (fscanf(leasestream, " %64s %255s %764s",
                   daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3)
-         break;
+         return 0;
        
-       clid_len = 0;
-       if (strcmp(daemon->packet, "*") != 0)
-         clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
-       
-       if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4) &&
-           (lease = lease4_allocate(addr.addr.addr4)))
+       if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4))
          {
+           if ((lease = lease4_allocate(addr.addr.addr4)))
+             domain = get_domain(lease->addr);
+           
            hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
-           /* For backwards compatibility, no explict MAC address type means ether. */
+           /* For backwards compatibility, no explicit MAC address type means ether. */
            if (hw_type == 0 && hw_len != 0)
              hw_type = ARPHRD_ETHER; 
-
-           lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, 
-                            hw_len, hw_type, clid_len, now, 0);
-           
-           if (strcmp(daemon->dhcp_buff, "*") !=  0)
-             lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain(lease->addr), NULL);
          }
 #ifdef HAVE_DHCP6
        else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6))
          {
            char *s = daemon->dhcp_buff2;
            int lease_type = LEASE_NA;
-           int iaid;
 
            if (s[0] == 'T')
              {
@@ -116,23 +84,30 @@ void lease_init(time_t now)
                s++;
              }
            
-           iaid = strtoul(s, NULL, 10);
-           
            if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
              {
-               lease_set_hwaddr(lease, NULL, (unsigned char *)daemon->packet, 0, 0, clid_len, now, 0);
-               lease_set_iaid(lease, iaid);
-               if (strcmp(daemon->dhcp_buff, "*") !=  0)
-                 lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain6((struct in6_addr *)lease->hwaddr), NULL);
+               lease_set_iaid(lease, strtoul(s, NULL, 10));
+               domain = get_domain6((struct in6_addr *)lease->hwaddr);
              }
          }
 #endif
        else
-         break;
+         return 0;
 
        if (!lease)
          die (_("too many stored leases"), NULL, EC_MISC);
-               
+
+       if (strcmp(daemon->packet, "*") != 0)
+         clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
+       
+       lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, 
+                        hw_len, hw_type, clid_len, now, 0);
+       
+       if (strcmp(daemon->dhcp_buff, "*") !=  0)
+         lease_set_hostname(lease, daemon->dhcp_buff, 0, domain, NULL);
+
+       ei = atol(daemon->dhcp_buff3);
+
 #ifdef HAVE_BROKEN_RTC
        if (ei != 0)
          lease->expires = (time_t)ei + now;
@@ -148,7 +123,62 @@ void lease_init(time_t now)
        /* set these correctly: the "old" events are generated later from
           the startup synthesised SIGHUP. */
        lease->flags &= ~(LEASE_NEW | LEASE_CHANGED);
+       
+       *daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
       }
+    
+    return (items == 0 || items == EOF);
+}
+
+void lease_init(time_t now)
+{
+  FILE *leasestream;
+
+  leases_left = daemon->dhcp_max;
+
+  if (option_bool(OPT_LEASE_RO))
+    {
+      /* run "<lease_change_script> init" once to get the
+        initial state of the database. If leasefile-ro is
+        set without a script, we just do without any
+        lease database. */
+#ifdef HAVE_SCRIPT
+      if (daemon->lease_change_command)
+       {
+         strcpy(daemon->dhcp_buff, daemon->lease_change_command);
+         strcat(daemon->dhcp_buff, " init");
+         leasestream = popen(daemon->dhcp_buff, "r");
+       }
+      else
+#endif
+       {
+          file_dirty = dns_dirty = 0;
+          return;
+        }
+
+    }
+  else
+    {
+      /* NOTE: need a+ mode to create file if it doesn't exist */
+      leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
+
+      if (!leasestream)
+       die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
+
+      /* a+ mode leaves pointer at end. */
+      rewind(leasestream);
+    }
+
+  if (leasestream)
+    {
+      if (!read_leases(now, leasestream))
+       my_syslog(MS_DHCP | LOG_ERR, _("failed to parse lease database, invalid line: %s %s %s %s ..."),
+                 daemon->dhcp_buff3, daemon->dhcp_buff2,
+                 daemon->namebuff, daemon->dhcp_buff);
+
+      if (ferror(leasestream))
+       die(_("failed to read lease file %s: %s"), daemon->lease_file, EC_FILE);
+    }
   
 #ifdef HAVE_SCRIPT
   if (!daemon->lease_stream)
@@ -162,6 +192,7 @@ void lease_init(time_t now)
            errno = ENOENT;
          else if (WEXITSTATUS(rc) == 126)
            errno = EACCES;
+
          die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE);
        }
       
@@ -198,7 +229,7 @@ void lease_update_from_configs(void)
     else if ((name = host_from_dns(lease->addr)))
       lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */
 }
+
 static void ourprintf(int *errp, char *format, ...)
 {
   va_list ap;
@@ -406,7 +437,7 @@ void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
 
 void lease_update_slaac(time_t now)
 {
-  /* Called when we contruct a new RA-names context, to add putative
+  /* Called when we construct a new RA-names context, to add putative
      new SLAAC addresses to existing leases. */
 
   struct dhcp_lease *lease;
@@ -776,7 +807,7 @@ void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now)
     {
       exp = now + (time_t)len;
       /* Check for 2038 overflow. Make the lease
-        inifinite in that case, as the least disruptive
+        infinite in that case, as the least disruptive
         thing we can do. */
       if (difftime(exp, now) <= 0.0)
        exp = 0;
@@ -1110,18 +1141,22 @@ int do_script_run(time_t now)
 }
 
 #ifdef HAVE_SCRIPT
+/* delim == -1 -> delim = 0, but embedded 0s, creating extra records, are OK. */
 void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data, unsigned int len, int delim)
 {
   unsigned int i;
   
-  /* check for embeded NULLs */
-  for (i = 0; i < len; i++)
-    if (data[i] == 0)
-      {
-       len = i;
-       break;
-      }
-
+  if (delim == -1)
+    delim = 0;
+  else
+    /* check for embedded NULLs */
+    for (i = 0; i < len; i++)
+      if (data[i] == 0)
+       {
+         len = i;
+         break;
+       }
+  
   if ((lease->extradata_size - lease->extradata_len) < (len + 1))
     {
       size_t newsz = lease->extradata_len + len + 100;
index 27b2e59..dae8a75 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -154,7 +154,7 @@ static void log_write(void)
    
   while (entries)
     {
-      /* The data in the payoad is written with a terminating zero character 
+      /* The data in the payload is written with a terminating zero character 
         and the length reflects this. For a stream connection we need to 
         send the zero as a record terminator, but this isn't done for a 
         datagram connection, so treat the length as one less than reality 
@@ -288,7 +288,9 @@ void my_syslog(int priority, const char *format, ...)
     func = "-tftp";
   else if ((LOG_FACMASK & priority) == MS_DHCP)
     func = "-dhcp";
-      
+  else if ((LOG_FACMASK & priority) == MS_SCRIPT)
+    func = "-script";
+           
 #ifdef LOG_PRI
   priority = LOG_PRI(priority);
 #else
@@ -436,7 +438,7 @@ void check_log_writer(int force)
 void flush_log(void)
 {
   /* write until queue empty, but don't loop forever if there's
-   no connection to the syslog in existance */
+   no connection to the syslog in existence */
   while (log_fd != -1)
     {
       struct timespec waiter;
index c9ed075..0b47a2f 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
index 753784d..05153f5 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -73,7 +73,7 @@ void netlink_init(void)
     }
   
   if (daemon->netlinkfd == -1 || 
-      getsockname(daemon->netlinkfd, (struct sockaddr *)&addr, &slen) == 1)
+      getsockname(daemon->netlinkfd, (struct sockaddr *)&addr, &slen) == -1)
     die(_("cannot create netlink socket: %s"), NULL, EC_MISC);
    
   /* save pid assigned by bind() and retrieved by getsockname() */ 
@@ -188,11 +188,17 @@ int iface_enumerate(int family, void *parm, int (*callback)())
        }
 
       for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
-       if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
+       if (h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
          {
            /* May be multicast arriving async */
            nl_async(h);
          }
+       else if (h->nlmsg_seq != seq)
+         {
+           /* May be part of incomplete response to previous request after
+              ENOBUFS. Drop it. */
+           continue;
+         }
        else if (h->nlmsg_type == NLMSG_DONE)
          return callback_ok;
        else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
@@ -288,7 +294,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
                rta = RTA_NEXT(rta, len1);
              }
 
-           if (inaddr && mac && callback_ok)
+           if (!(neigh->ndm_state & (NUD_NOARP | NUD_INCOMPLETE | NUD_FAILED)) &&
+               inaddr && mac && callback_ok)
              if (!((*callback)(neigh->ndm_family, inaddr, mac, maclen, parm)))
                callback_ok = 0;
          }
index a1d90c8..0381513 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -178,7 +178,7 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth)
 }
 
 
-/* Fix for problem that the kernel sometimes reports the loopback inerface as the
+/* Fix for problem that the kernel sometimes reports the loopback interface as the
    arrival interface when a packet originates locally, even when sent to address of 
    an interface other than the loopback. Accept packet if it arrived via a loopback 
    interface, even when we're not accepting packets that way, as long as the destination
@@ -244,6 +244,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
   int tftp_ok = !!option_bool(OPT_TFTP);
   int dhcp_ok = 1;
   int auth_dns = 0;
+  int is_label = 0;
 #if defined(HAVE_DHCP) || defined(HAVE_TFTP)
   struct iname *tmp;
 #endif
@@ -264,6 +265,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
   
   if (!label)
     label = ifr.ifr_name;
+  else
+    is_label = strcmp(label, ifr.ifr_name);
  
   /* maintain a list of all addresses on all interfaces for --local-service option */
   if (option_bool(OPT_LOCAL_SERVICE))
@@ -482,6 +485,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
       iface->found = 1;
       iface->done = iface->multicast_done = iface->warned = 0;
       iface->index = if_index;
+      iface->label = is_label;
       if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
        {
          strcpy(iface->name, ifr.ifr_name);
@@ -532,13 +536,14 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
 {
   union mysockaddr addr;
   int prefix, bit;
+  (void)broadcast; /* warning */
 
   memset(&addr, 0, sizeof(addr));
 #ifdef HAVE_SOCKADDR_SA_LEN
   addr.in.sin_len = sizeof(addr.in);
 #endif
   addr.in.sin_family = AF_INET;
-  addr.in.sin_addr = broadcast; /* warning */
   addr.in.sin_addr = local;
   addr.in.sin_port = htons(daemon->port);
 
@@ -643,7 +648,7 @@ int enumerate_interfaces(int reset)
       /* Garbage-collect listeners listening on addresses that no longer exist.
         Does nothing when not binding interfaces or for listeners on localhost, 
         since the ->iface field is NULL. Note that this needs the protections
-        against re-entrancy, hence it's here.  It also means there's a possibility,
+        against reentrancy, hence it's here.  It also means there's a possibility,
         in OPT_CLEVERBIND mode, that at listener will just disappear after
         a call to enumerate_interfaces, this is checked OK on all calls. */
       struct listener *l, *tmp, **up;
@@ -698,7 +703,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
   
   if ((fd = socket(family, type, 0)) == -1)
     {
-      int port, errsav;
+      int port, errsave;
       char *s;
 
       /* No error if the kernel just doesn't support this IP flavour */
@@ -708,7 +713,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
        return -1;
       
     err:
-      errsav = errno;
+      errsave = errno;
       port = prettyprint_addr(addr, daemon->addrbuff);
       if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
        sprintf(daemon->addrbuff, "port %d", port);
@@ -717,7 +722,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
       if (fd != -1)
        close (fd);
        
-      errno = errsav;
+      errno = errsave;
 
       if (dienow)
        {
@@ -745,7 +750,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
   
   if (type == SOCK_STREAM)
     {
-      if (listen(fd, 5) == -1)
+      if (listen(fd, TCP_BACKLOG) == -1)
        goto err;
     }
   else if (family == AF_INET)
@@ -809,10 +814,11 @@ int tcp_interface(int fd, int af)
   int opt = 1;
   struct cmsghdr *cmptr;
   struct msghdr msg;
+  socklen_t len;
   
-  /* use mshdr do that the CMSDG_* macros are available */
+  /* use mshdr so that the CMSDG_* macros are available */
   msg.msg_control = daemon->packet;
-  msg.msg_controllen = daemon->packet_buff_sz;
+  msg.msg_controllen = len = daemon->packet_buff_sz;
   
   /* we overwrote the buffer... */
   daemon->srv_save = NULL;
@@ -820,18 +826,21 @@ int tcp_interface(int fd, int af)
   if (af == AF_INET)
     {
       if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
-         getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
-       for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
-         if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
-            {
-              union {
-                unsigned char *c;
-                struct in_pktinfo *p;
-              } p;
-             
-             p.c = CMSG_DATA(cmptr);
-             if_index = p.p->ipi_ifindex;
-           }
+         getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
+       {
+         msg.msg_controllen = len;
+         for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+           if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
+             {
+               union {
+                 unsigned char *c;
+                 struct in_pktinfo *p;
+               } p;
+               
+               p.c = CMSG_DATA(cmptr);
+               if_index = p.p->ipi_ifindex;
+             }
+       }
     }
 #ifdef HAVE_IPV6
   else
@@ -849,9 +858,10 @@ int tcp_interface(int fd, int af)
 #endif
 
       if (set_ipv6pktinfo(fd) &&
-         getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
+         getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, &len) != -1)
        {
-          for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+          msg.msg_controllen = len;
+         for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
             if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
               {
                 union {
@@ -1028,6 +1038,15 @@ void warn_bound_listeners(void)
     my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)")); 
 }
 
+void warn_wild_labels(void)
+{
+  struct irec *iface;
+
+  for (iface = daemon->interfaces; iface; iface = iface->next)
+    if (iface->found && iface->name && iface->label)
+      my_syslog(LOG_WARNING, _("warning: using interface %s instead"), iface->name);
+}
+
 void warn_int_names(void)
 {
   struct interface_name *intname;
@@ -1076,23 +1095,30 @@ void join_multicast(int dienow)
            
            if ((daemon->doing_dhcp6 || daemon->relay6) &&
                setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
-             err = 1;
+             err = errno;
            
            inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
            
            if (daemon->doing_dhcp6 && 
                setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
-             err = 1;
+             err = errno;
            
            inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
            
            if (daemon->doing_ra &&
                setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
-             err = 1;
+             err = errno;
            
            if (err)
              {
                char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
+               errno = err;
+
+#ifdef HAVE_LINUX_NETWORK
+               if (errno == ENOMEM)
+                 my_syslog(LOG_ERR, _("try increasing /proc/sys/net/core/optmem_max"));
+#endif
+
                if (dienow)
                  die(s, iface->name, EC_BADNET);
                else
@@ -1112,7 +1138,7 @@ int random_sock(int family)
   if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
     {
       union mysockaddr addr;
-      unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
+      unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
       int tries = ports_avail < 30 ? 3 * ports_avail : 100;
 
       memset(&addr, 0, sizeof(addr));
@@ -1123,10 +1149,7 @@ int random_sock(int family)
       if (fix_fd(fd))
        while(tries--)
          {
-           unsigned short port = rand16();
-           
-           if (daemon->min_port != 0)
-             port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
+           unsigned short port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
            
            if (family == AF_INET) 
              {
@@ -1161,7 +1184,7 @@ int random_sock(int family)
 }
   
 
-int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
+int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp)
 {
   union mysockaddr addr_copy = *addr;
 
@@ -1178,7 +1201,25 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
   
   if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
     return 0;
-    
+
+  if (!is_tcp && ifindex > 0)
+    {
+#if defined(IP_UNICAST_IF)
+      if (addr_copy.sa.sa_family == AF_INET)
+        {
+          uint32_t ifindex_opt = htonl(ifindex);
+          return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
+        }
+#endif
+#if defined(HAVE_IPV6) && defined (IPV6_UNICAST_IF)
+      if (addr_copy.sa.sa_family == AF_INET6)
+        {
+          uint32_t ifindex_opt = htonl(ifindex);
+          return setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
+        }
+#endif
+    }
+
 #if defined(SO_BINDTODEVICE)
   if (intname[0] != 0 &&
       setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
@@ -1191,6 +1232,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
 static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
 {
   struct serverfd *sfd;
+  unsigned int ifindex = 0;
   int errsave;
 
   /* when using random ports, servers which would otherwise use
@@ -1211,11 +1253,15 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
        return NULL;
 #endif
     }
+
+  if (intname && strlen(intname) != 0)
+    ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
       
   /* may have a suitable one already */
   for (sfd = daemon->sfds; sfd; sfd = sfd->next )
     if (sockaddr_isequal(&sfd->source_addr, addr) &&
-       strcmp(intname, sfd->interface) == 0)
+       strcmp(intname, sfd->interface) == 0 &&
+       ifindex == sfd->ifindex) 
       return sfd;
   
   /* need to make a new one. */
@@ -1229,7 +1275,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
       return NULL;
     }
   
-  if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
+  if (!local_bind(sfd->fd, addr, intname, ifindex, 0) || !fix_fd(sfd->fd))
     { 
       errsave = errno; /* save error from bind. */
       close(sfd->fd);
@@ -1237,11 +1283,13 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
       errno = errsave;
       return NULL;
     }
-    
+
   strcpy(sfd->interface, intname); 
   sfd->source_addr = *addr;
   sfd->next = daemon->sfds;
+  sfd->ifindex = ifindex;
   daemon->sfds = sfd;
+
   return sfd; 
 }
 
@@ -1396,7 +1444,6 @@ void add_update_server(int flags,
       serv->domain = domain_str;
       serv->next = next;
       serv->queries = serv->failed_queries = 0;
-      serv->edns_pktsz = daemon->edns_pktsz;
 #ifdef HAVE_LOOP
       serv->uid = rand32();
 #endif      
@@ -1417,18 +1464,54 @@ void check_servers(void)
 {
   struct irec *iface;
   struct server *serv;
-  int port = 0;
+  struct serverfd *sfd, *tmp, **up;
+  int port = 0, count;
+  int locals = 0;
 
   /* interface may be new since startup */
   if (!option_bool(OPT_NOWILD))
     enumerate_interfaces(0);
   
-  for (serv = daemon->servers; serv; serv = serv->next)
+  for (sfd = daemon->sfds; sfd; sfd = sfd->next)
+    sfd->used = 0;
+
+  for (count = 0, serv = daemon->servers; serv; serv = serv->next)
     {
-       if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
+      if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
        {
-         port = prettyprint_addr(&serv->addr, daemon->namebuff);
+         /* Init edns_pktsz for newly created server records. */
+         if (serv->edns_pktsz == 0)
+           serv->edns_pktsz = daemon->edns_pktsz;
+         
+#ifdef HAVE_DNSSEC
+         if (option_bool(OPT_DNSSEC_VALID))
+           { 
+             if (!(serv->flags & SERV_FOR_NODOTS))
+               serv->flags |= SERV_DO_DNSSEC;
+             
+             /* Disable DNSSEC validation when using server=/domain/.... servers
+                unless there's a configured trust anchor. */
+             if (serv->flags & SERV_HAS_DOMAIN)
+               {
+                 struct ds_config *ds;
+                 char *domain = serv->domain;
+                 
+                 /* .example.com is valid */
+                 while (*domain == '.')
+                   domain++;
+                 
+                 for (ds = daemon->ds; ds; ds = ds->next)
+                   if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
+                     break;
+                 
+                 if (!ds)
+                   serv->flags &= ~SERV_DO_DNSSEC;
+               }
+           }
+#endif
 
+         port = prettyprint_addr(&serv->addr, daemon->namebuff);
+         
          /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
          if (serv->addr.sa.sa_family == AF_INET &&
              serv->addr.in.sin_addr.s_addr == 0)
@@ -1458,13 +1541,23 @@ void check_servers(void)
              serv->flags |= SERV_MARK;
              continue;
            }
+         
+         if (serv->sfd)
+           serv->sfd->used = 1;
        }
       
       if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
        {
+         if (++count > SERVERS_LOGGED)
+           continue;
+         
          if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
            {
-             char *s1, *s2;
+             char *s1, *s2, *s3 = "";
+#ifdef HAVE_DNSSEC
+             if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
+               s3 = _("(no DNSSEC)");
+#endif
              if (!(serv->flags & SERV_HAS_DOMAIN))
                s1 = _("unqualified"), s2 = _("names");
              else if (strlen(serv->domain) == 0)
@@ -1473,11 +1566,15 @@ void check_servers(void)
                s1 = _("domain"), s2 = serv->domain;
              
              if (serv->flags & SERV_NO_ADDR)
-               my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
+               {
+                 count--;
+                 if (++locals <= LOCALS_LOGGED)
+                       my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
+               }
              else if (serv->flags & SERV_USE_RESOLV)
                my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
              else 
-               my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
+               my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s %s"), daemon->namebuff, port, s1, s2, s3);
            }
 #ifdef HAVE_LOOP
          else if (serv->flags & SERV_LOOP)
@@ -1489,7 +1586,26 @@ void check_servers(void)
            my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port); 
        }
     }
+  
+  if (locals > LOCALS_LOGGED)
+    my_syslog(LOG_INFO, _("using %d more local addresses"), locals - LOCALS_LOGGED);
+  if (count - 1 > SERVERS_LOGGED)
+    my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
 
+  /* Remove unused sfds */
+  for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
+    {
+       tmp = sfd->next;
+       if (!sfd->used) 
+       {
+         *up = sfd->next;
+         close(sfd->fd);
+         free(sfd);
+       } 
+      else
+       up = &sfd->next;
+    }
+  
   cleanup_servers();
 }
 
index ecc2619..d358d99 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -154,7 +154,13 @@ struct myoption {
 #define LOPT_HOST_INOTIFY  342
 #define LOPT_DNSSEC_STAMP  343
 #define LOPT_TFTP_NO_FAIL  344
-
+#define LOPT_MAXPORT       345
+#define LOPT_CPE_ID        346
+#define LOPT_SCRIPT_ARP    347
+#define LOPT_DHCPTTL       348
+#define LOPT_TFTP_MTU      349
+#define LOPT_REPLY_DELAY   350
 #ifdef HAVE_GETOPT_LONG
 static const struct option opts[] =  
 #else
@@ -237,9 +243,10 @@ static const struct myoption opts[] =
     { "enable-tftp", 2, 0, LOPT_TFTP },
     { "tftp-secure", 0, 0, LOPT_SECURE },
     { "tftp-no-fail", 0, 0, LOPT_TFTP_NO_FAIL },
-    { "tftp-unique-root", 0, 0, LOPT_APREF },
+    { "tftp-unique-root", 2, 0, LOPT_APREF },
     { "tftp-root", 1, 0, LOPT_PREFIX },
     { "tftp-max", 1, 0, LOPT_TFTP_MAX },
+    { "tftp-mtu", 1, 0, LOPT_TFTP_MTU },
     { "tftp-lowercase", 0, 0, LOPT_TFTP_LC },
     { "ptr-record", 1, 0, LOPT_PTR },
     { "naptr-record", 1, 0, LOPT_NAPTR },
@@ -270,6 +277,7 @@ static const struct myoption opts[] =
     { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
     { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
     { "min-port", 1, 0, LOPT_MINPORT },
+    { "max-port", 1, 0, LOPT_MAXPORT },
     { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
     { "cname", 1, 0, LOPT_CNAME },
     { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
@@ -279,8 +287,9 @@ static const struct myoption opts[] =
     { "dhcp-proxy", 2, 0, LOPT_PROXY },
     { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
     { "rebind-localhost-ok", 0, 0,  LOPT_LOC_REBND },
-    { "add-mac", 0, 0, LOPT_ADD_MAC },
+    { "add-mac", 2, 0, LOPT_ADD_MAC },
     { "add-subnet", 2, 0, LOPT_ADD_SBNET },
+    { "add-cpe-id", 1, 0 , LOPT_CPE_ID },
     { "proxy-dnssec", 0, 0, LOPT_DNSSEC },
     { "dhcp-sequential-ip", 0, 0,  LOPT_INCR_ADDR },
     { "conntrack", 0, 0, LOPT_CONNTRACK },
@@ -313,6 +322,9 @@ static const struct myoption opts[] =
     { "quiet-dhcp6", 0, 0, LOPT_QUIET_DHCP6 },
     { "quiet-ra", 0, 0, LOPT_QUIET_RA },
     { "dns-loop-detect", 0, 0, LOPT_LOOP_DETECT },
+    { "script-arp", 0, 0, LOPT_SCRIPT_ARP },
+    { "dhcp-ttl", 1, 0 , LOPT_DHCPTTL },
+    { "dhcp-reply-delay", 1, 0, LOPT_REPLY_DELAY },
     { NULL, 0, 0, 0 }
   };
 
@@ -392,7 +404,7 @@ static struct {
   { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
   { 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
   { 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },
-  { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
+  { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."), NULL },
   { 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
   { 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
   { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
@@ -410,8 +422,9 @@ static struct {
   { '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
   { LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
   { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
+  { LOPT_SCRIPT_ARP, OPT_SCRIPT_ARP, NULL, gettext_noop("Call dhcp-script with changes to local ARP table."), NULL },
   { '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
-  { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
+  { '8', ARG_ONE, "<facility>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
   { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
   { '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" }, 
   { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
@@ -419,10 +432,11 @@ static struct {
   { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
   { LOPT_TFTP, ARG_DUP, "[=<intr>[,<intr>]]", gettext_noop("Enable integrated read-only TFTP server."), NULL },
   { LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
-  { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
+  { LOPT_APREF, ARG_DUP, "[=ip|mac]", gettext_noop("Add client IP or hardware address to tftp-root."), NULL },
   { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
   { LOPT_TFTP_NO_FAIL, OPT_TFTP_NO_FAIL, NULL, gettext_noop("Do not terminate the service if TFTP directories are inaccessible."), NULL },
-  { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
+  { LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent TFTP transfers (defaults to %s)."), "#" },
+  { LOPT_TFTP_MTU, ARG_ONE, "<integer>", gettext_noop("Maximum MTU to use for TFTP transfers."), NULL },
   { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
   { LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },
   { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
@@ -436,32 +450,34 @@ static struct {
   { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
   { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
   { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
+  { LOPT_MAXPORT, ARG_ONE, "<port>", gettext_noop("Specify highest port available for DNS query transmission."), NULL },
   { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
   { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
   { LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
-  { LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<interface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL},
-  { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
+  { LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<iface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL},
+  { LOPT_CNAME, ARG_DUP, "<alias>,<target>[,<ttl>]", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
   { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
   { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
   { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
-  { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
-  { LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add requestor's IP subnet to forwarded DNS queries."), NULL },
+  { LOPT_ADD_MAC, ARG_DUP, "[=base64|text]", gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
+  { LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add specified IP subnet to forwarded DNS queries."), NULL },
+  { LOPT_CPE_ID, ARG_ONE, "<text>", gettext_noop("Add client identification to forwarded DNS queries."), NULL },
   { LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },
   { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },
   { LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
   { LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
   { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
   { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
-  { LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
+  { LOPT_HOST_REC, ARG_DUP, "<name>,<address>[,<ttl>]", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
   { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
   { LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
   { LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
   { LOPT_AUTHZONE, ARG_DUP, "<domain>,[<subnet>...]", gettext_noop("Domain to export to global DNS"), NULL },
   { LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
-  { LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
+  { LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritative zone information"), NULL },
   { LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
   { LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
-  { LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
+  { LOPT_IPSET, ARG_DUP, "/<domain>[/<domain>...]/<ipset>...", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
   { LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
   { LOPT_SEC_VALID, OPT_DNSSEC_VALID, NULL, gettext_noop("Activate DNSSEC validation"), NULL },
   { LOPT_TRUST_ANCHOR, ARG_DUP, "<domain>,[<class>],...", gettext_noop("Specify trust anchor key digest."), NULL },
@@ -472,17 +488,19 @@ static struct {
 #ifdef OPTION6_PREFIX_CLASS 
   { LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
 #endif
-  { LOPT_RA_PARAM, ARG_DUP, "<interface>,[high,|low,]<interval>[,<lifetime>]", gettext_noop("Set priority, resend-interval and router-lifetime"), NULL },
+  { LOPT_RA_PARAM, ARG_DUP, "<iface>,[mtu:<value>|<interface>|off,][<prio>,]<intval>[,<lifetime>]", gettext_noop("Set MTU, priority, resend-interval and router-lifetime"), NULL },
   { LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log routine DHCP."), NULL },
   { LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log routine DHCPv6."), NULL },
   { 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_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 }, 
+  { LOPT_DHCPTTL, ARG_ONE, "<ttl>", gettext_noop("Set TTL in DNS responses with DHCP-derived addresses."), NULL }, 
+  { LOPT_REPLY_DELAY, ARG_ONE, "<integer>", gettext_noop("Delay DHCP replies for at least number of seconds."), NULL },
   { 0, 0, NULL, NULL, NULL }
 }; 
 
-/* We hide metacharaters in quoted strings by mapping them into the ASCII control
+/* We hide metacharacters in quoted strings by mapping them into the ASCII control
    character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
    following sequence so that they map to themselves: it is therefore possible to call
    unhide_metas repeatedly on string without breaking things.
@@ -642,7 +660,8 @@ static int atoi_check8(char *a, int *res)
   return 1;
 }
 #endif
-       
+
+#ifndef NO_ID
 static void add_txt(char *name, char *txt, int stat)
 {
   struct txt_record *r = opt_malloc(sizeof(struct txt_record));
@@ -655,13 +674,14 @@ static void add_txt(char *name, char *txt, int stat)
       *(r->txt) = len;
       memcpy((r->txt)+1, txt, len);
     }
-  
+
   r->stat = stat;
   r->name = opt_string_alloc(name);
   r->next = daemon->txt;
   daemon->txt = r;
   r->class = C_CHAOS;
 }
+#endif
 
 static void do_usage(void)
 {
@@ -706,7 +726,7 @@ static void do_usage(void)
        sprintf(buff, "    ");
       
       sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
-      printf("%-40.40s", buff);
+      printf("%-55.55s", buff);
             
       if (usage[i].arg)
        {
@@ -722,10 +742,25 @@ static void do_usage(void)
 
 #define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
 
+static char *parse_mysockaddr(char *arg, union mysockaddr *addr) 
+{
+  if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
+    addr->sa.sa_family = AF_INET;
+#ifdef HAVE_IPV6
+  else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
+    addr->sa.sa_family = AF_INET6;
+#endif
+  else
+    return _("bad address");
+   
+  return NULL;
+}
+
 char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
 {
   int source_port = 0, serv_port = NAMESERVER_PORT;
   char *portno, *source;
+  char *interface_opt = NULL;
 #ifdef HAVE_IPV6
   int scope_index = 0;
   char *scope_id;
@@ -751,6 +786,19 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
   scope_id = split_chr(arg, '%');
 #endif
   
+  if (source) {
+    interface_opt = split_chr(source, '@');
+
+    if (interface_opt)
+      {
+#if defined(SO_BINDTODEVICE)
+       strncpy(interface, interface_opt, IF_NAMESIZE - 1);
+#else
+       return _("interface binding not supported");
+#endif
+      }
+  }
+
   if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
     {
       addr->in.sin_port = htons(serv_port);    
@@ -769,6 +817,9 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
          if (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
            {
 #if defined(SO_BINDTODEVICE)
+             if (interface_opt)
+               return _("interface can only be specified once");
+             
              source_addr->in.sin_addr.s_addr = INADDR_ANY;
              strncpy(interface, source, IF_NAMESIZE - 1);
 #else
@@ -801,7 +852,10 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
          if (inet_pton(AF_INET6, source, &source_addr->in6.sin6_addr) == 0)
            {
 #if defined(SO_BINDTODEVICE)
-             source_addr->in6.sin6_addr = in6addr_any; 
+             if (interface_opt)
+               return _("interface can only be specified once");
+             
+             source_addr->in6.sin6_addr = in6addr_any;
              strncpy(interface, source, IF_NAMESIZE - 1);
 #else
              return _("interface binding not supported");
@@ -819,19 +873,31 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
 static struct server *add_rev4(struct in_addr addr, int msize)
 {
   struct server *serv = opt_malloc(sizeof(struct server));
-  in_addr_t  a = ntohl(addr.s_addr) >> 8;
+  in_addr_t  a = ntohl(addr.s_addr);
   char *p;
 
   memset(serv, 0, sizeof(struct server));
-  p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
-  
-  if (msize == 24)
-    p += sprintf(p, "%d.", a & 0xff);
-  a = a >> 8;
-  if (msize != 8)
-    p += sprintf(p, "%d.", a & 0xff);
-  a = a >> 8;
-  p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
+  p = serv->domain = opt_malloc(29); /* strlen("xxx.yyy.zzz.ttt.in-addr.arpa")+1 */
+
+  switch (msize)
+    {
+    case 32:
+      p += sprintf(p, "%u.", a & 0xff);
+      /* fall through */
+    case 24:
+      p += sprintf(p, "%d.", (a >> 8) & 0xff);
+      /* fall through */
+    case 16:
+      p += sprintf(p, "%d.", (a >> 16) & 0xff);
+      /* fall through */
+    case 8:
+      p += sprintf(p, "%d.", (a >> 24) & 0xff);
+      break;
+    default:
+      return NULL;
+    }
+
+  p += sprintf(p, "in-addr.arpa");
   
   serv->flags = SERV_HAS_DOMAIN;
   serv->next = daemon->servers;
@@ -1097,7 +1163,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
            case 'd':
            case 'D':
              fac *= 24;
-             /* fall though */
+             /* fall through */
            case 'h':
            case 'H':
              fac *= 60;
@@ -1170,7 +1236,8 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
              cp = comma;
              comma = split(cp);
              slash = split_chr(cp, '/');
-             inet_pton(AF_INET, cp, &in);
+             if (!inet_pton(AF_INET, cp, &in))
+               ret_err(_("bad IPv4 address"));
              if (!slash)
                {
                  memcpy(op, &in, INADDRSZ);
@@ -1348,7 +1415,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
                    }
                  
                  p = newp;
-                 end = do_rfc1035_name(p + len, dom);
+                 end = do_rfc1035_name(p + len, dom, NULL);
                  *end++ = 0;
                  len = end - p;
                  free(dom);
@@ -1501,10 +1568,16 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
                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);
+                   /* "*" with no suffix is a no-op */
+                   if (arg[1] == 0)
+                     free(li);
+                   else
+                     {
+                       li->next = match_suffix;
+                       match_suffix = li;
+                       /* Have to copy: buffer is overwritten */
+                       li->suffix = opt_string_alloc(arg+1);
+                     }
                  }
                else
                  {
@@ -1585,7 +1658,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
            li = match_suffix->next;
            free(match_suffix->suffix);
            free(match_suffix);
-         }    
+         }
        break;
       }
 
@@ -1593,10 +1666,46 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
       set_option_bool(OPT_CLIENT_SUBNET);
       if (arg)
        {
+          char *err, *end;
          comma = split(arg);
-         if (!atoi_check(arg, &daemon->addr4_netmask) || 
-             (comma && !atoi_check(comma, &daemon->addr6_netmask)))
-            ret_err(gen_err);
+
+          struct mysubnet* new = opt_malloc(sizeof(struct mysubnet));
+          if ((end = split_chr(arg, '/')))
+           {
+             /* has subnet+len */
+             err = parse_mysockaddr(arg, &new->addr);
+             if (err)
+               ret_err(err);
+             if (!atoi_check(end, &new->mask))
+               ret_err(gen_err);
+             new->addr_used = 1;
+           } 
+         else if (!atoi_check(arg, &new->mask))
+           ret_err(gen_err);
+           
+          daemon->add_subnet4 = new;
+
+          if (comma)
+            {
+             new = opt_malloc(sizeof(struct mysubnet));
+             if ((end = split_chr(comma, '/')))
+               {
+                 /* has subnet+len */
+                  err = parse_mysockaddr(comma, &new->addr);
+                  if (err)
+                    ret_err(err);
+                  if (!atoi_check(end, &new->mask))
+                    ret_err(gen_err);
+                  new->addr_used = 1;
+                }
+              else
+                {
+                  if (!atoi_check(comma, &new->mask))
+                    ret_err(gen_err);
+                }
+          
+             daemon->add_subnet6 = new;
+           }
        }
       break;
 
@@ -1834,6 +1943,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
        new = opt_malloc(sizeof(struct auth_zone));
        new->domain = opt_string_alloc(arg);
        new->subnet = NULL;
+       new->exclude = NULL;
        new->interface_names = NULL;
        new->next = daemon->auth_zones;
        daemon->auth_zones = new;
@@ -1841,6 +1951,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
        while ((arg = comma))
          {
            int prefixlen = 0;
+           int is_exclude = 0;
            char *prefix;
            struct addrlist *subnet =  NULL;
            struct all_addr addr;
@@ -1851,6 +1962,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
            if (prefix && !atoi_check(prefix, &prefixlen))
              ret_err(gen_err);
            
+           if (strstr(arg, "exclude:") == arg)
+             {
+                   is_exclude = 1;
+                   arg = arg+8;
+             }
+
            if (inet_pton(AF_INET, arg, &addr.addr.addr4))
              {
                subnet = opt_malloc(sizeof(struct addrlist));
@@ -1888,8 +2005,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
            if (subnet)
              {
                subnet->addr = addr;
-               subnet->next = new->subnet;
-               new->subnet = subnet;
+
+               if (is_exclude)
+                 {
+                   subnet->next = new->exclude;
+                   new->exclude = subnet;
+                 }
+               else
+                 {
+                   subnet->next = new->subnet;
+                   new->subnet = subnet;
+                 }
              }
          }
        break;
@@ -1919,11 +2045,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
                  comma = split(arg); 
                  daemon->soa_retry = (u32)atoi(arg);
                  if (comma)
-                   {
-                     arg = comma;
-                     comma = split(arg); 
-                     daemon->soa_expiry = (u32)atoi(arg);
-                   }
+                   daemon->soa_expiry = (u32)atoi(comma);
                }
            }
        }
@@ -1949,7 +2071,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
                  char *netpart;
                  
                  new->prefix = NULL;
-
+                 new->indexed = 0;
+                 
                  unhide_metas(comma);
                  if ((netpart = split_chr(comma, '/')))
                    {
@@ -1980,6 +2103,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
                                   /* generate the equivalent of
                                      local=/xxx.yyy.zzz.in-addr.arpa/ */
                                  struct server *serv = add_rev4(new->start, msize);
+                                 if (!serv)
+                                   ret_err(_("bad prefix"));
+
                                  serv->flags |= SERV_NO_ADDR;
 
                                  /* local=/<domain>/ */
@@ -2083,8 +2209,14 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
                    }
                  else
                    {
+                     char *star;
                      new->next = daemon->synth_domains;
                      daemon->synth_domains = new;
+                     if ((star = strrchr(new->prefix, '*')) && *(star+1) == 0)
+                       {
+                         *star = 0;
+                         new->indexed = 1;
+                       }
                    }
                }
              else if (option == 's')
@@ -2095,6 +2227,26 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
        }
       break;
       
+    case LOPT_CPE_ID: /* --add-dns-client */
+      if (arg)
+       daemon->dns_client_id = opt_string_alloc(arg);
+      break;
+
+    case LOPT_ADD_MAC: /* --add-mac */
+      if (!arg)
+       set_option_bool(OPT_ADD_MAC);
+      else
+       {
+         unhide_metas(arg);
+         if (strcmp(arg, "base64") == 0)
+           set_option_bool(OPT_MAC_B64);
+         else if (strcmp(arg, "text") == 0)
+           set_option_bool(OPT_MAC_HEX);
+         else
+           ret_err(gen_err);
+       }
+      break;
+
     case 'u':  /* --user */
       daemon->username = opt_string_alloc(arg);
       break;
@@ -2331,7 +2483,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
          ret_err(gen_err);
 
        if (inet_pton(AF_INET, arg, &addr4))
-         serv = add_rev4(addr4, size);
+         {
+           serv = add_rev4(addr4, size);
+           if (!serv)
+             ret_err(_("bad prefix"));
+         }
 #ifdef HAVE_IPV6
        else if (inet_pton(AF_INET6, arg, &addr6))
          serv = add_rev6(&addr6, size);
@@ -2448,6 +2604,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
        ret_err(gen_err);
       break;
 
+    case LOPT_MAXPORT:  /* --max-port */
+      if (!atoi_check16(arg, &daemon->max_port))
+       ret_err(gen_err);
+      break;
+
     case '0':  /* --dns-forward-max */
       if (!atoi_check(arg, &daemon->ftabsize))
        ret_err(gen_err);
@@ -2491,6 +2652,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
     case LOPT_MINCTTL: /* --min-cache-ttl */
     case LOPT_MAXCTTL: /* --max-cache-ttl */
     case LOPT_AUTHTTL: /* --auth-ttl */
+    case LOPT_DHCPTTL: /* --dhcp-ttl */
       {
        int ttl;
        if (!atoi_check(arg, &ttl))
@@ -2509,6 +2671,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
          daemon->max_cache_ttl = (unsigned long)ttl;
        else if (option == LOPT_AUTHTTL)
          daemon->auth_ttl = (unsigned long)ttl;
+       else if (option == LOPT_DHCPTTL)
+         {
+           daemon->dhcp_ttl = (unsigned long)ttl;
+           daemon->use_dhcp_ttl = 1;
+         }
        else
          daemon->local_ttl = (unsigned long)ttl;
        break;
@@ -2527,6 +2694,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
        ret_err(gen_err);
       break;  
 
+    case LOPT_TFTP_MTU:  /*  --tftp-mtu */
+      if (!atoi_check(arg, &daemon->tftp_mtu))
+       ret_err(gen_err);
+      break;
+
     case LOPT_PREFIX: /* --tftp-prefix */
       comma = split(arg);
       if (comma)
@@ -2555,19 +2727,37 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
        } 
       
       break;
+
+    case LOPT_APREF: /* --tftp-unique-root */
+      if (!arg || strcasecmp(arg, "ip") == 0)
+        set_option_bool(OPT_TFTP_APREF_IP);
+      else if (strcasecmp(arg, "mac") == 0)
+        set_option_bool(OPT_TFTP_APREF_MAC);
+      else
+        ret_err(gen_err);
+      break;
 #endif
              
     case LOPT_BRIDGE:   /* --bridge-interface */
       {
-       struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
+       struct dhcp_bridge *new;
+
        if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
          ret_err(_("bad bridge-interface"));
-       
-       strcpy(new->iface, arg);
-       new->alias = NULL;
-       new->next = daemon->bridges;
-       daemon->bridges = new;
 
+       for (new = daemon->bridges; new; new = new->next)
+         if (strcmp(new->iface, arg) == 0)
+           break;
+
+       if (!new)
+         {
+            new = opt_malloc(sizeof(struct dhcp_bridge));
+            strcpy(new->iface, arg);
+            new->alias = NULL;
+            new->next = daemon->bridges;
+            daemon->bridges = new;
+         }
+       
        do {
          arg = comma;
          comma = split(arg);
@@ -2669,13 +2859,14 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
                leasepos = 3;
                if (!is_same_net(new->start, new->end, new->netmask))
                  ret_err(_("inconsistent DHCP range"));
-             }
+               
            
-           if (k >= 4 && strchr(a[3], '.') &&  
-               (inet_pton(AF_INET, a[3], &new->broadcast) > 0))
-             {
-               new->flags |= CONTEXT_BRDCAST;
-               leasepos = 4;
+               if (k >= 4 && strchr(a[3], '.') &&  
+                   (inet_pton(AF_INET, a[3], &new->broadcast) > 0))
+                 {
+                   new->flags |= CONTEXT_BRDCAST;
+                   leasepos = 4;
+                 }
              }
          }
 #ifdef HAVE_DHCP6
@@ -2765,6 +2956,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
        
        if (leasepos < k)
          {
+           if (leasepos != k-1)
+             ret_err(_("bad dhcp-range"));
+           
            if (strcmp(a[leasepos], "infinite") == 0)
              new->lease_time = 0xffffffff;
            else if (strcmp(a[leasepos], "deprecated") == 0)
@@ -2783,7 +2977,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
                      case 'd':
                      case 'D':
                        fac *= 24;
-                       /* fall though */
+                       /* fall through */
                      case 'h':
                      case 'H':
                        fac *= 60;
@@ -2859,7 +3053,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
                        }
 
                      if (len == -1)
-
                        ret_err(_("bad hex constant"));
                      else if ((new->clid = opt_malloc(len)))
                        {
@@ -3143,11 +3336,43 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
        break;
       }
 
+    case LOPT_REPLY_DELAY: /* --dhcp-reply-delay */
+      {
+       struct dhcp_netid *id = NULL;
+       while (is_tag_prefix(arg))
+         {
+           struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
+           newid->next = id;
+           id = newid;
+           comma = split(arg);
+           newid->net = opt_string_alloc(arg+4);
+           arg = comma;
+         };
+       
+       if (!arg)
+         ret_err(gen_err);
+       else
+         {
+           struct delay_config *new;
+           int delay;
+           if (!atoi_check(arg, &delay))
+              ret_err(gen_err);
+           
+           new = opt_malloc(sizeof(struct delay_config));
+           new->delay = delay;
+           new->netid = id;
+            new->next = daemon->delay_conf;
+            daemon->delay_conf = new;
+         }
+       
+       break;
+      }
+      
     case LOPT_PXE_PROMT:  /* --pxe-prompt */
        {
         struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
         int timeout;
-
+        
         new->netid = NULL;
         new->opt = 10; /* PXE_MENU_PROMPT */
 
@@ -3191,7 +3416,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
        {
         struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
         char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
-                        "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };  
+                        "IA32_EFI", "x86-64_EFI", "Xscale_EFI", "BC_EFI",
+                        "ARM32_EFI", "ARM64_EFI", NULL };  
         static int boottype = 32768;
         
         new->netid = NULL;
@@ -3496,7 +3722,21 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
          struct ra_interface *new = opt_malloc(sizeof(struct ra_interface));
          new->lifetime = -1;
          new->prio = 0;
+         new->mtu = 0;
+         new->mtu_name = NULL;
          new->name = opt_string_alloc(arg);
+         if (strcasestr(comma, "mtu:") == comma)
+           {
+             arg = comma + 4;
+             if (!(comma = split(comma)))
+               goto err;
+             if (!strcasecmp(arg, "off"))
+               new->mtu = -1;
+             else if (!atoi_check(arg, &new->mtu))
+               new->mtu_name = opt_string_alloc(arg);
+             else if (new->mtu < 1280)
+               goto err;
+           }
          if (strcasestr(comma, "high") == comma || strcasestr(comma, "low") == comma)
            {
              if (*comma == 'l' || *comma == 'L')
@@ -3508,6 +3748,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
           arg = split(comma);
           if (!atoi_check(comma, &new->interval) || 
              (arg && !atoi_check(arg, &new->lifetime)))
+err:
            ret_err(_("bad RA-params"));
          
          new->next = daemon->ra_interfaces;
@@ -3552,8 +3793,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
            (!(inet_pton(AF_INET, a[1], &new->out) > 0)))
          option = '?';
        
-       if (k == 3)
-         inet_pton(AF_INET, a[2], &new->mask);
+       if (k == 3 && !inet_pton(AF_INET, a[2], &new->mask))
+         option = '?';
        
        if (dash && 
            (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
@@ -3603,27 +3844,42 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
     case LOPT_CNAME: /* --cname */
       {
        struct cname *new;
-       char *alias;
-       char *target;
+       char *alias, *target, *last, *pen;
+       int ttl = -1;
 
-       if (!(comma = split(arg)))
-         ret_err(gen_err);
-       
-       alias = canonicalise_opt(arg);
-       target = canonicalise_opt(comma);
-           
-       if (!alias || !target)
+       for (last = pen = NULL, comma = arg; comma; comma = split(comma))
+         {
+           pen = last;
+           last = comma;
+         }
+
+       if (!pen)
          ret_err(_("bad CNAME"));
-       else
+       
+       if (pen != arg && atoi_check(last, &ttl))
+         last = pen;
+               
+       target = canonicalise_opt(last);
+
+       while (arg != last)
          {
+           int arglen = strlen(arg);
+           alias = canonicalise_opt(arg);
+
+           if (!alias || !target)
+             ret_err(_("bad CNAME"));
+           
            for (new = daemon->cnames; new; new = new->next)
-             if (hostname_isequal(new->alias, arg))
+             if (hostname_isequal(new->alias, alias))
                ret_err(_("duplicate CNAME"));
            new = opt_malloc(sizeof(struct cname));
            new->next = daemon->cnames;
            daemon->cnames = new;
            new->alias = alias;
            new->target = target;
+           new->ttl = ttl;
+
+           for (arg += arglen+1; *arg && isspace(*arg); arg++);
          }
       
        break;
@@ -3689,7 +3945,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
     case LOPT_RR: /* dns-rr */
       {
                struct txt_record *new;
-       size_t len = len;
+       size_t len = 0;
        char *data;
        int val;
 
@@ -3797,13 +4053,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
                    if (!atoi_check16(arg, &priority))
                      ret_err(_("invalid priority"));
                        
-                   if (comma)
-                     {
-                       arg = comma;
-                       comma = split(arg);
-                       if (!atoi_check16(arg, &weight))
-                         ret_err(_("invalid weight"));
-                     }
+                   if (comma && !atoi_check16(comma, &weight))
+                     ret_err(_("invalid weight"));
                  }
              }
          }
@@ -3824,14 +4075,22 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
       {
        struct host_record *new = opt_malloc(sizeof(struct host_record));
        memset(new, 0, sizeof(struct host_record));
-       
+       new->ttl = -1;
+
        if (!arg || !(comma = split(arg)))
          ret_err(_("Bad host-record"));
        
        while (arg)
          {
            struct all_addr addr;
-           if (inet_pton(AF_INET, arg, &addr))
+           char *dig;
+
+           for (dig = arg; *dig != 0; dig++)
+             if (*dig < '0' || *dig > '9')
+               break;
+           if (*dig == 0)
+             new->ttl = atoi(arg);
+           else if (inet_pton(AF_INET, arg, &addr))
              new->addr = addr.addr.addr4;
 #ifdef HAVE_IPV6
            else if (inet_pton(AF_INET6, arg, &addr))
@@ -3948,7 +4207,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
     {
       int white, i;
       volatile int option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
-      char *errmess, *p, *arg = NULL, *start;
+      char *errmess, *p, *arg, *start;
       size_t len;
 
       /* Memory allocation failure longjmps here if mem_recover == 1 */ 
@@ -3959,6 +4218,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
          mem_recover = 1;
        }
       
+      arg = NULL;
       lineno++;
       errmess = NULL;
       
@@ -4075,7 +4335,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
   fclose(f);
 }
 
-#ifdef HAVE_DHCP
+#if defined(HAVE_DHCP) && defined(HAVE_INOTIFY)
 int option_read_dynfile(char *file, int flags)
 {
   my_syslog(MS_DHCP | LOG_INFO, _("read %s"), file);
@@ -4276,86 +4536,99 @@ void read_servers_file(void)
  
 
 #ifdef HAVE_DHCP
-void reread_dhcp(void)
+static void clear_dynamic_conf(void)
 {
-  struct hostsfile *hf;
-
-  if (daemon->dhcp_hosts_file)
-    {
-      struct dhcp_config *configs, *cp, **up;
+  struct dhcp_config *configs, *cp, **up;
   
-      /* remove existing... */
-      for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
+  /* remove existing... */
+  for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
+    {
+      cp = configs->next;
+      
+      if (configs->flags & CONFIG_BANK)
        {
-         cp = configs->next;
+         struct hwaddr_config *mac, *tmp;
+         struct dhcp_netid_list *list, *tmplist;
          
-         if (configs->flags & CONFIG_BANK)
+         for (mac = configs->hwaddr; mac; mac = tmp)
            {
-             struct hwaddr_config *mac, *tmp;
-             struct dhcp_netid_list *list, *tmplist;
-             
-             for (mac = configs->hwaddr; mac; mac = tmp)
-               {
-                 tmp = mac->next;
-                 free(mac);
-               }
+             tmp = mac->next;
+             free(mac);
+           }
+         
+         if (configs->flags & CONFIG_CLID)
+           free(configs->clid);
+         
+         for (list = configs->netid; list; list = tmplist)
+           {
+             free(list->list);
+             tmplist = list->next;
+             free(list);
+           }
+         
+         if (configs->flags & CONFIG_NAME)
+           free(configs->hostname);
+         
+         *up = configs->next;
+         free(configs);
+       }
+      else
+       up = &configs->next;
+    }
+}
 
-             if (configs->flags & CONFIG_CLID)
-               free(configs->clid);
+static void clear_dynamic_opt(void)
+{
+  struct dhcp_opt *opts, *cp, **up;
+  struct dhcp_netid *id, *next;
 
-             for (list = configs->netid; list; list = tmplist)
-               {
-                 free(list->list);
-                 tmplist = list->next;
-                 free(list);
-               }
-             
-             if (configs->flags & CONFIG_NAME)
-               free(configs->hostname);
-             
-             *up = configs->next;
-             free(configs);
+  for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
+    {
+      cp = opts->next;
+      
+      if (opts->flags & DHOPT_BANK)
+       {
+         if ((opts->flags & DHOPT_VENDOR))
+           free(opts->u.vendor_class);
+         free(opts->val);
+         for (id = opts->netid; id; id = next)
+           {
+             next = id->next;
+             free(id->net);
+             free(id);
            }
-         else
-           up = &configs->next;
+         *up = opts->next;
+         free(opts);
        }
-      
+      else
+       up = &opts->next;
+    }
+}
+
+void reread_dhcp(void)
+{
+   struct hostsfile *hf;
+
+   /* Do these even if there is no daemon->dhcp_hosts_file or
+      daemon->dhcp_opts_file since entries may have been created by the
+      inotify dynamic file reading system. */
+   
+   clear_dynamic_conf();
+   clear_dynamic_opt();
+
+   if (daemon->dhcp_hosts_file)
+    {
       daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
       for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
-        if (!(hf->flags & AH_INACTIVE))
-          {
-            if (one_file(hf->fname, LOPT_BANK))  
-              my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
-          }
+       if (!(hf->flags & AH_INACTIVE))
+         {
+           if (one_file(hf->fname, LOPT_BANK))  
+             my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
+         }
     }
 
   if (daemon->dhcp_opts_file)
     {
-      struct dhcp_opt *opts, *cp, **up;
-      struct dhcp_netid *id, *next;
-
-      for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
-       {
-         cp = opts->next;
-         
-         if (opts->flags & DHOPT_BANK)
-           {
-             if ((opts->flags & DHOPT_VENDOR))
-               free(opts->u.vendor_class);
-             free(opts->val);
-             for (id = opts->netid; id; id = next)
-               {
-                 next = id->next;
-                 free(id->net);
-                 free(id);
-               }
-             *up = opts->next;
-             free(opts);
-           }
-         else
-           up = &opts->next;
-       }
-      
       daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
       for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
        if (!(hf->flags & AH_INACTIVE))
@@ -4364,11 +4637,18 @@ void reread_dhcp(void)
              my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
          }
     }
+
+#  ifdef HAVE_INOTIFY
+  /* Setup notify and read pre-existing files. */
+  set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0);
+#  endif
 }
 #endif
-    
+
 void read_opts(int argc, char **argv, char *compile_opts)
 {
+  size_t argbuf_size = MAXDNAME;
+  char *argbuf = opt_malloc(argbuf_size);
   char *buff = opt_malloc(MAXDNAME);
   int option, conffile_opt = '7', testmode = 0;
   char *arg, *conffile = CONFFILE;
@@ -4398,7 +4678,10 @@ void read_opts(int argc, char **argv, char *compile_opts)
   daemon->soa_refresh = SOA_REFRESH;
   daemon->soa_retry = SOA_RETRY;
   daemon->soa_expiry = SOA_EXPIRY;
+  daemon->max_port = MAX_PORT;
+  daemon->min_port = MIN_PORT;
 
+#ifndef NO_ID
   add_txt("version.bind", "dnsmasq-" VERSION, 0 );
   add_txt("authors.bind", "Simon Kelley", 0);
   add_txt("copyright.bind", COPYRIGHT, 0);
@@ -4411,6 +4694,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
   add_txt("auth.bind", NULL, TXT_STAT_AUTH);
 #endif
   add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
+#endif
 
   while (1) 
     {
@@ -4435,9 +4719,15 @@ void read_opts(int argc, char **argv, char *compile_opts)
       /* Copy optarg so that argv doesn't get changed */
       if (optarg)
        {
-         strncpy(buff, optarg, MAXDNAME);
-         buff[MAXDNAME-1] = 0;
-         arg = buff;
+         if (strlen(optarg) >= argbuf_size)
+           {
+             free(argbuf);
+             argbuf_size = strlen(optarg) + 1;
+             argbuf = opt_malloc(argbuf_size);
+           }
+         strncpy(argbuf, optarg, argbuf_size);
+         argbuf[argbuf_size-1] = 0;
+         arg = argbuf;
        }
       else
        arg = NULL;
@@ -4485,6 +4775,8 @@ void read_opts(int argc, char **argv, char *compile_opts)
        }
     }
 
+  free(argbuf);
+
   if (conffile)
     {
       one_file(conffile, conffile_opt);
@@ -4497,21 +4789,68 @@ void read_opts(int argc, char **argv, char *compile_opts)
     {
       struct server *tmp;
       for (tmp = daemon->servers; tmp; tmp = tmp->next)
-       {
-         tmp->edns_pktsz = daemon->edns_pktsz;
-        
-         if (!(tmp->flags & SERV_HAS_SOURCE))
-           {
-             if (tmp->source_addr.sa.sa_family == AF_INET)
-               tmp->source_addr.in.sin_port = htons(daemon->query_port);
+       if (!(tmp->flags & SERV_HAS_SOURCE))
+         {
+           if (tmp->source_addr.sa.sa_family == AF_INET)
+             tmp->source_addr.in.sin_port = htons(daemon->query_port);
 #ifdef HAVE_IPV6
-             else if (tmp->source_addr.sa.sa_family == AF_INET6)
-               tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
+           else if (tmp->source_addr.sa.sa_family == AF_INET6)
+             tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
 #endif 
+         }
+    } 
+  
+  if (daemon->host_records)
+    {
+      struct host_record *hr;
+      
+      for (hr = daemon->host_records; hr; hr = hr->next)
+       if (hr->ttl == -1)
+         hr->ttl = daemon->local_ttl;
+    }
+
+  if (daemon->cnames)
+    {
+      struct cname *cn, *cn2, *cn3;
+
+#define NOLOOP 1
+#define TESTLOOP 2      
+
+      /* Fill in TTL for CNAMES noe we have local_ttl.
+        Also prepare to do loop detection. */
+      for (cn = daemon->cnames; cn; cn = cn->next)
+       {
+         if (cn->ttl == -1)
+           cn->ttl = daemon->local_ttl;
+         cn->flag = 0;
+         cn->targetp = NULL;
+         for (cn2 = daemon->cnames; cn2; cn2 = cn2->next)
+           if (hostname_isequal(cn->target, cn2->alias))
+             {
+               cn->targetp = cn2;
+               break;
+             }
+       }
+      
+      /* Find any CNAME loops.*/
+      for (cn = daemon->cnames; cn; cn = cn->next)
+       {
+         for (cn2 = cn->targetp; cn2; cn2 = cn2->targetp)
+           {
+             if (cn2->flag == NOLOOP)
+               break;
+             
+             if (cn2->flag == TESTLOOP)
+               die(_("CNAME loop involving %s"), cn->alias, EC_BADCONF);
+             
+             cn2->flag = TESTLOOP;
            }
-       } 
+         
+         for (cn3 = cn->targetp; cn3 != cn2; cn3 = cn3->targetp)
+           cn3->flag = NOLOOP;
+       }
     }
-  
+
   if (daemon->if_addrs)
     {  
       struct iname *tmp;
index 5b1ff93..d20bd33 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -29,9 +29,19 @@ void end_opt6(int container)
    PUTSHORT(len, p);
 }
 
+void reset_counter(void)
+{
+  /* Clear out buffer when starting from beginning */
+  if (daemon->outpacket.iov_base)
+    memset(daemon->outpacket.iov_base, 0, daemon->outpacket.iov_len);
+  save_counter(0);
+}
+
 int save_counter(int newval)
 {
   int ret = outpacket_counter;
+  
   if (newval != -1)
     outpacket_counter = newval;
 
index d71b1b9..0d8382f 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
index 4cc1ea4..2ca9ec7 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
index 39f1e92..4f31457 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
 
 struct ra_param {
   time_t now;
-  int ind, managed, other, found_context, first, adv_router;
+  int ind, managed, other, first, adv_router;
   char *if_name;
   struct dhcp_netid *tags;
   struct in6_addr link_local, link_global, ula;
   unsigned int glob_pref_time, link_pref_time, ula_pref_time, adv_interval, prio;
+  struct dhcp_context *found_context;
 };
 
 struct search_param {
@@ -81,7 +82,7 @@ void ra_init(time_t now)
   /* ensure this is around even if we're not doing DHCPv6 */
   expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));
  
-  /* See if we're guessing SLAAC addresses, if so we need to recieve ping replies */
+  /* See if we're guessing SLAAC addresses, if so we need to receive ping replies */
   for (context = daemon->dhcp6; context; context = context->next)
     if ((context->flags & CONTEXT_RA_NAME))
       break;
@@ -111,10 +112,10 @@ void ra_init(time_t now)
    daemon->icmp6fd = fd;
    
    if (daemon->doing_ra)
-     ra_start_unsolicted(now, NULL);
+     ra_start_unsolicited(now, NULL);
 }
 
-void ra_start_unsolicted(time_t now, struct dhcp_context *context)
+void ra_start_unsolicited(time_t now, struct dhcp_context *context)
 {   
    /* init timers so that we do ra's for some/all soon. some ra_times will end up zeroed
      if it's not appropriate to advertise those contexts.
@@ -197,6 +198,9 @@ void icmp6_packet(time_t now)
       /* look for link-layer address option for logging */
       if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
        {
+         if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) {
+           return;
+         }
          print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
          mac = daemon->namebuff;
        }
@@ -242,7 +246,7 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
   struct dhcp_netid iface_id;
   struct dhcp_opt *opt_cfg;
   struct ra_interface *ra_param = find_iface_param(iface_name);
-  int done_dns = 0, old_prefix = 0;
+  int done_dns = 0, old_prefix = 0, mtu = 0;
   unsigned int min_pref_time;
 #ifdef HAVE_LINUX_NETWORK
   FILE *f;
@@ -251,7 +255,7 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
   parm.ind = iface;
   parm.managed = 0;
   parm.other = 0;
-  parm.found_context = 0;
+  parm.found_context = NULL;
   parm.adv_router = 0;
   parm.if_name = iface_name;
   parm.first = 1;
@@ -260,8 +264,10 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
   parm.adv_interval = calc_interval(ra_param);
   parm.prio = calc_prio(ra_param);
   
-  save_counter(0);
-  ra = expand(sizeof(struct ra_packet));
+  reset_counter();
+  
+  if (!(ra = expand(sizeof(struct ra_packet))))
+    return;
   
   ra->type = ND_ROUTER_ADVERT;
   ra->code = 0;
@@ -308,8 +314,14 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
          unsigned int old = difftime(now, context->address_lost_time);
          
          if (old > context->saved_valid)
-           {
+           { 
              /* We've advertised this enough, time to go */
+            
+             /* If this context held the timeout, and there's another context in use
+                transfer the timeout there. */
+             if (context->ra_time != 0 && parm.found_context && parm.found_context->ra_time == 0)
+               new_timeout(parm.found_context, iface_name, now);
+             
              *up = context->next;
              free(context);
            }
@@ -390,22 +402,32 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
       put_opt6_long(1000 * calc_interval(find_iface_param(iface_name)));
     }
 
+  /* Set the MTU from ra_param if any, an MTU of 0 mean automatic for linux, */
+  /* an MTU of -1 prevents the option from being sent. */
+  if (ra_param)
+    mtu = ra_param->mtu;
 #ifdef HAVE_LINUX_NETWORK
-  /* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU
+  /* Note that IPv6 MTU is not necessarily the same as the IPv4 MTU
      available from SIOCGIFMTU */
-  sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", iface_name);
-  if ((f = fopen(daemon->namebuff, "r")))
+  if (mtu == 0)
     {
-      if (fgets(daemon->namebuff, MAXDNAME, f))
-       {
-         put_opt6_char(ICMP6_OPT_MTU);
-         put_opt6_char(1);
-         put_opt6_short(0);
-         put_opt6_long(atoi(daemon->namebuff));
-       }
-      fclose(f);
+      char *mtu_name = ra_param ? ra_param->mtu_name : NULL;
+      sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", mtu_name ? : iface_name);
+      if ((f = fopen(daemon->namebuff, "r")))
+        {
+          if (fgets(daemon->namebuff, MAXDNAME, f))
+            mtu = atoi(daemon->namebuff);
+          fclose(f);
+        }
     }
 #endif
+  if (mtu > 0)
+    {
+      put_opt6_char(ICMP6_OPT_MTU);
+      put_opt6_char(1);
+      put_opt6_short(0);
+      put_opt6_long(mtu);
+    }
      
   iface_enumerate(AF_LOCAL, &send_iface, add_lla);
  
@@ -519,7 +541,7 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
     }
   
   while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base, 
-                          save_counter(0), 0, (struct sockaddr *)&addr, 
+                          save_counter(-1), 0, (struct sockaddr *)&addr, 
                           sizeof(addr))));
   
 }
@@ -636,8 +658,10 @@ static int add_prefixes(struct in6_addr *local,  int prefix,
                     off_link = (context->flags & CONTEXT_RA_OFF_LINK);
                  }
 
-               param->first = 0;       
-               param->found_context = 1;
+               param->first = 0;
+               /* found_context is the _last_ one we found, so if there's 
+                  more than one, it's not the first. */
+               param->found_context = context;
              }
 
          /* configured time is ceiling */
@@ -769,7 +793,7 @@ time_t periodic_ra(time_t now)
           associated with it, because it's for a subnet we dont 
           have an interface on. Probably we're doing DHCP on
           a remote subnet via a relay. Zero the timer, since we won't
-          ever be able to send ra's and satistfy it. */
+          ever be able to send ra's and satisfy it. */
        context->ra_time = 0;
       
       if (param.iface != 0 &&
index 56647b0..b078b59 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -36,8 +36,8 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
       if ((l = *p++) == 0) 
        /* end marker */
        {
-         /* check that there are the correct no of bytes after the name */
-         if (!CHECK_LEN(header, p, plen, extrabytes))
+         /* check that there are the correct no. of bytes after the name */
+         if (!CHECK_LEN(header, p1 ? p1 : p, plen, extrabytes))
            return 0;
          
          if (isExtract)
@@ -156,7 +156,7 @@ int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
   memset(addrp, 0, sizeof(struct all_addr));
 
   /* turn name into a series of asciiz strings */
-  /* j counts no of labels */
+  /* j counts no. of labels */
   for(j = 1,cp1 = name; *namein; cp1++, namein++)
     if (*namein == '.')
       {
@@ -176,7 +176,7 @@ int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
   if (hostname_isequal(lastchunk, "arpa") && hostname_isequal(penchunk, "in-addr"))
     {
       /* IP v4 */
-      /* address arives as a name of the form
+      /* address arrives as a name of the form
         www.xxx.yyy.zzz.in-addr.arpa
         some of the low order address octets might be missing
         and should be set to zero. */
@@ -206,7 +206,7 @@ int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
          Address arrives as 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.[int|arpa]
         or \[xfedcba9876543210fedcba9876543210/128].ip6.[int|arpa]
       
-        Note that most of these the various reprentations are obsolete and 
+        Note that most of these the various representations are obsolete and 
         left-over from the many DNS-for-IPv6 wars. We support all the formats
         that we can since there is no reason not to.
       */
@@ -336,7 +336,7 @@ unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *h
 }
 
 /* CRC the question section. This is used to safely detect query 
-   retransmision and to detect answers to questions we didn't ask, which 
+   retransmission and to detect answers to questions we didn't ask, which 
    might be poisoning attacks. Note that we decode the name rather 
    than CRC the raw bytes, since replies might be compressed differently. 
    We ignore case in the names for the same reason. Return all-ones
@@ -408,333 +408,37 @@ size_t resize_packet(struct dns_header *header, size_t plen, unsigned char *phea
   return ansp - (unsigned char *)header;
 }
 
-unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t  *len, unsigned char **p, int *is_sign)
-{
-  /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it. 
-     also return length of pseudoheader in *len and pointer to the UDP size in *p
-     Finally, check to see if a packet is signed. If it is we cannot change a single bit before
-     forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
-  
-  int i, arcount = ntohs(header->arcount);
-  unsigned char *ansp = (unsigned char *)(header+1);
-  unsigned short rdlen, type, class;
-  unsigned char *ret = NULL;
-
-  if (is_sign)
-    {
-      *is_sign = 0;
-
-      if (OPCODE(header) == QUERY)
-       {
-         for (i = ntohs(header->qdcount); i != 0; i--)
-           {
-             if (!(ansp = skip_name(ansp, header, plen, 4)))
-               return NULL;
-             
-             GETSHORT(type, ansp); 
-             GETSHORT(class, ansp);
-             
-             if (class == C_IN && type == T_TKEY)
-               *is_sign = 1;
-           }
-       }
-    }
-  else
-    {
-      if (!(ansp = skip_questions(header, plen)))
-       return NULL;
-    }
-    
-  if (arcount == 0)
-    return NULL;
-  
-  if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount), header, plen)))
-    return NULL; 
-  
-  for (i = 0; i < arcount; i++)
-    {
-      unsigned char *save, *start = ansp;
-      if (!(ansp = skip_name(ansp, header, plen, 10)))
-       return NULL; 
-
-      GETSHORT(type, ansp);
-      save = ansp;
-      GETSHORT(class, ansp);
-      ansp += 4; /* TTL */
-      GETSHORT(rdlen, ansp);
-      if (!ADD_RDLEN(header, ansp, plen, rdlen))
-       return NULL;
-      if (type == T_OPT)
-       {
-         if (len)
-           *len = ansp - start;
-         if (p)
-           *p = save;
-         ret = start;
-       }
-      else if (is_sign && 
-              i == arcount - 1 && 
-              class == C_ANY && 
-              type == T_TSIG)
-       *is_sign = 1;
-    }
-  
-  return ret;
-}
-
-struct macparm {
-  unsigned char *limit;
-  struct dns_header *header;
-  size_t plen;
-  union mysockaddr *l3;
-};
-static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit, 
-                              int optno, unsigned char *opt, size_t optlen, int set_do)
-{ 
-  unsigned char *lenp, *datap, *p;
-  int rdlen, is_sign;
-  
-  if (!(p = find_pseudoheader(header, plen, NULL, NULL, &is_sign)))
-    {
-      if (is_sign)
-       return plen;
-
-      /* We are adding the pseudoheader */
-      if (!(p = skip_questions(header, plen)) ||
-         !(p = skip_section(p, 
-                            ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount), 
-                            header, plen)))
-       return plen;
-      *p++ = 0; /* empty name */
-      PUTSHORT(T_OPT, p);
-      PUTSHORT(SAFE_PKTSZ, p); /* max packet length, this will be overwritten */
-      PUTSHORT(0, p);    /* extended RCODE and version */
-      PUTSHORT(set_do ? 0x8000 : 0, p); /* DO flag */
-      lenp = p;
-      PUTSHORT(0, p);    /* RDLEN */
-      rdlen = 0;
-      if (((ssize_t)optlen) > (limit - (p + 4)))
-       return plen; /* Too big */
-      header->arcount = htons(ntohs(header->arcount) + 1);
-      datap = p;
-    }
-  else
-    {
-      int i;
-      unsigned short code, len, flags;
-      
-      /* Must be at the end, if exists */
-      if (ntohs(header->arcount) != 1 ||
-         is_sign ||
-         (!(p = skip_name(p, header, plen, 10))))
-       return plen;
-      
-      p += 6; /* skip UDP length and RCODE */
-      GETSHORT(flags, p);
-      if (set_do)
-       {
-         p -=2;
-         PUTSHORT(flags | 0x8000, p);
-       }
-
-      lenp = p;
-      GETSHORT(rdlen, p);
-      if (!CHECK_LEN(header, p, plen, rdlen))
-       return plen; /* bad packet */
-      datap = p;
-
-       /* no option to add */
-      if (optno == 0)
-       return plen;
-         
-      /* check if option already there */
-      for (i = 0; i + 4 < rdlen; i += len + 4)
-       {
-         GETSHORT(code, p);
-         GETSHORT(len, p);
-         if (code == optno)
-           return plen;
-         p += len;
-       }
-      
-      if (((ssize_t)optlen) > (limit - (p + 4)))
-       return plen; /* Too big */
-    }
-  
-  if (optno != 0)
-    {
-      PUTSHORT(optno, p);
-      PUTSHORT(optlen, p);
-      memcpy(p, opt, optlen);
-      p += optlen;  
-    }
-
-  PUTSHORT(p - datap, lenp);
-  return p - (unsigned char *)header;
-  
-}
-
-static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
-{
-  struct macparm *parm = parmv;
-  int match = 0;
-    
-  if (family == parm->l3->sa.sa_family)
-    {
-      if (family == AF_INET && memcmp(&parm->l3->in.sin_addr, addrp, INADDRSZ) == 0)
-       match = 1;
-#ifdef HAVE_IPV6
-      else
-       if (family == AF_INET6 && memcmp(&parm->l3->in6.sin6_addr, addrp, IN6ADDRSZ) == 0)
-         match = 1;
-#endif
-    }
-  if (!match)
-    return 1; /* continue */
-
-  parm->plen = add_pseudoheader(parm->header, parm->plen, parm->limit,  EDNS0_OPTION_MAC, (unsigned char *)mac, maclen, 0);
-  
-  return 0; /* done */
-}            
-     
-size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3)
-{
-  struct macparm parm;
-     
-/* Must have an existing pseudoheader as the only ar-record, 
-   or have no ar-records. Must also not be signed */
-   
-  if (ntohs(header->arcount) > 1)
-    return plen;
-
-  parm.header = header;
-  parm.limit = (unsigned char *)limit;
-  parm.plen = plen;
-  parm.l3 = l3;
-
-  iface_enumerate(AF_UNSPEC, &parm, filter_mac);
-  
-  return parm.plen; 
-}
-
-struct subnet_opt {
-  u16 family;
-  u8 source_netmask, scope_netmask;
-#ifdef HAVE_IPV6 
-  u8 addr[IN6ADDRSZ];
-#else
-  u8 addr[INADDRSZ];
-#endif
-};
-
-static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
-{
-  /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
-  
-  int len;
-  void *addrp;
-
-#ifdef HAVE_IPV6
-  if (source->sa.sa_family == AF_INET6)
-    {
-      opt->family = htons(2);
-      opt->source_netmask = daemon->addr6_netmask;
-      addrp = &source->in6.sin6_addr;
-    }
-  else
-#endif
-    {
-      opt->family = htons(1);
-      opt->source_netmask = daemon->addr4_netmask;
-      addrp = &source->in.sin_addr;
-    }
-  
-  opt->scope_netmask = 0;
-  len = 0;
-  
-  if (opt->source_netmask != 0)
-    {
-      len = ((opt->source_netmask - 1) >> 3) + 1;
-      memcpy(opt->addr, addrp, len);
-      if (opt->source_netmask & 7)
-       opt->addr[len-1] &= 0xff << (8 - (opt->source_netmask & 7));
-    }
-
-  return len + 4;
-}
-size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, union mysockaddr *source)
-{
-  /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
-  
-  int len;
-  struct subnet_opt opt;
-  
-  len = calc_subnet_opt(&opt, source);
-  return add_pseudoheader(header, plen, (unsigned char *)limit, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0);
-}
-
-#ifdef HAVE_DNSSEC
-size_t add_do_bit(struct dns_header *header, size_t plen, char *limit)
-{
-  return add_pseudoheader(header, plen, (unsigned char *)limit, 0, NULL, 0, 1);
-}
-#endif
-
-int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)
-{
-  /* Section 9.2, Check that subnet option in reply matches. */
-
-
- int len, calc_len;
-  struct subnet_opt opt;
-  unsigned char *p;
-  int code, i, rdlen;
-  
-   calc_len = calc_subnet_opt(&opt, peer);
-   
-   if (!(p = skip_name(pseudoheader, header, plen, 10)))
-     return 1;
-   
-   p += 8; /* skip UDP length and RCODE */
-   
-   GETSHORT(rdlen, p);
-   if (!CHECK_LEN(header, p, plen, rdlen))
-     return 1; /* bad packet */
-   
-   /* check if option there */
-   for (i = 0; i + 4 < rdlen; i += len + 4)
-     {
-       GETSHORT(code, p);
-       GETSHORT(len, p);
-       if (code == EDNS0_OPTION_CLIENT_SUBNET)
-        {
-          /* make sure this doesn't mismatch. */
-          opt.scope_netmask = p[3];
-          if (len != calc_len || memcmp(p, &opt, len) != 0)
-            return 0;
-        }
-       p += len;
-     }
-   
-   return 1;
-}
-
 /* is addr in the non-globally-routed IP space? */ 
 int private_net(struct in_addr addr, int ban_localhost) 
 {
   in_addr_t ip_addr = ntohl(addr.s_addr);
 
   return
-    (((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost)  /* 127.0.0.0/8    (loopback) */ || 
-    ((ip_addr & 0xFFFF0000) == 0xC0A80000)  /* 192.168.0.0/16 (private)  */ ||
+    (((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost)  /* 127.0.0.0/8    (loopback) */ ||
+    ((ip_addr & 0xFF000000) == 0x00000000)  /* RFC 5735 section 3. "here" network */ ||
     ((ip_addr & 0xFF000000) == 0x0A000000)  /* 10.0.0.0/8     (private)  */ ||
     ((ip_addr & 0xFFF00000) == 0xAC100000)  /* 172.16.0.0/12  (private)  */ ||
-    ((ip_addr & 0xFFFF0000) == 0xA9FE0000)  /* 169.254.0.0/16 (zeroconf) */ ;
+    ((ip_addr & 0xFFFF0000) == 0xC0A80000)  /* 192.168.0.0/16 (private)  */ ||
+    ((ip_addr & 0xFFFF0000) == 0xA9FE0000)  /* 169.254.0.0/16 (zeroconf) */ ||
+    ((ip_addr & 0xFFFFFF00) == 0xC0000200)  /* 192.0.2.0/24   (test-net) */ ||
+    ((ip_addr & 0xFFFFFF00) == 0xC6336400)  /* 198.51.100.0/24(test-net) */ ||
+    ((ip_addr & 0xFFFFFF00) == 0xCB007100)  /* 203.0.113.0/24 (test-net) */ ||
+    ((ip_addr & 0xFFFFFFFF) == 0xFFFFFFFF)  /* 255.255.255.255/32 (broadcast)*/ ;
 }
 
+#ifdef HAVE_IPV6
+static int private_net6(struct in6_addr *a)
+{
+  return 
+    IN6_IS_ADDR_UNSPECIFIED(a) || /* RFC 6303 4.3 */
+    IN6_IS_ADDR_LOOPBACK(a) ||    /* RFC 6303 4.3 */
+    IN6_IS_ADDR_LINKLOCAL(a) ||   /* RFC 6303 4.5 */
+    ((unsigned char *)a)[0] == 0xfd ||   /* RFC 6303 4.4 */
+    ((u32 *)a)[0] == htonl(0x20010db8); /* RFC 6303 4.6 */
+}
+#endif
+
+
 static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, char *name, int *doctored)
 {
   int i, qtype, qclass, rdlen;
@@ -794,6 +498,8 @@ static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *
            {
              unsigned int i, len = *p1;
              unsigned char *p2 = p1;
+             if ((p1 + len - p) >= rdlen)
+               return 0; /* bad packet */
              /* make counted string zero-term  and sanitise */
              for (i = 0; i < len; i++)
                {
@@ -878,7 +584,8 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name, int *doc
    expired and cleaned out that way. 
    Return 1 if we reject an address because it look like part of dns-rebinding attack. */
 int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now, 
-                     char **ipsets, int is_sign, int check_rebind, int no_cache_dnssec, int secure, int *doctored)
+                     char **ipsets, int is_sign, int check_rebind, int no_cache_dnssec,
+                     int secure, int *doctored)
 {
   unsigned char *p, *p1, *endrr, *namep;
   int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
@@ -889,6 +596,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
 #else
   (void)ipsets; /* unused */
 #endif
+
   
   cache_start_insert();
 
@@ -897,10 +605,18 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
     {
       searched_soa = 1;
       ttl = find_soa(header, qlen, name, doctored);
+
+      if (*doctored)
+       {
+         if (secure)
+           return 0;
 #ifdef HAVE_DNSSEC
-      if (*doctored && secure)
-       return 0;
+         if (option_bool(OPT_DNSSEC_VALID))
+           for (i = 0; i < ntohs(header->ancount); i++)
+             if (daemon->rr_status[i])
+               return 0;
 #endif
+       }
     }
   
   /* go through the questions. */
@@ -911,7 +627,9 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
       int found = 0, cname_count = CNAME_CHAIN;
       struct crec *cpp = NULL;
       int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
-      int secflag = secure ?  F_DNSSECOK : 0;
+#ifdef HAVE_DNSSEC
+      int cname_short = 0;
+#endif
       unsigned long cttl = ULONG_MAX, attl;
 
       namep = p;
@@ -939,8 +657,9 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
              if (!(p1 = skip_questions(header, qlen)))
                return 0;
              
-             for (j = ntohs(header->ancount); j != 0; j--
+             for (j = 0; j < ntohs(header->ancount); j++
                {
+                 int secflag = 0;
                  unsigned char *tmp = namep;
                  /* the loop body overwrites the original name, so get it back here. */
                  if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
@@ -966,11 +685,24 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
                    {
                      if (!extract_name(header, qlen, &p1, name, 1, 0))
                        return 0;
-                     
+#ifdef HAVE_DNSSEC
+                     if (option_bool(OPT_DNSSEC_VALID) && daemon->rr_status[j])
+                       {
+                         /* validated RR anywhere in CNAME chain, don't cache. */
+                         if (cname_short || aqtype == T_CNAME)
+                           return 0;
+
+                         secflag = F_DNSSECOK;
+                       }
+#endif
+
                      if (aqtype == T_CNAME)
                        {
-                         if (!cname_count-- || secure)
-                           return 0; /* looped CNAMES, or DNSSEC, which we can't cache. */
+                         if (!cname_count--)
+                           return 0; /* looped CNAMES, we can't cache. */
+#ifdef HAVE_DNSSEC
+                         cname_short = 1;
+#endif
                          goto cname_loop;
                        }
                      
@@ -992,7 +724,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
                  ttl = find_soa(header, qlen, NULL, doctored);
                }
              if (ttl)
-               cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | secflag);       
+               cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | (secure ?  F_DNSSECOK : 0));    
            }
        }
       else
@@ -1020,8 +752,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
          if (!(p1 = skip_questions(header, qlen)))
            return 0;
          
-         for (j = ntohs(header->ancount); j != 0; j--
+         for (j = 0; j < ntohs(header->ancount); j++
            {
+             int secflag = 0;
+             
              if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
                return 0; /* bad packet */
              
@@ -1038,6 +772,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
              
              if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype))
                {
+#ifdef HAVE_DNSSEC
+                 if (option_bool(OPT_DNSSEC_VALID) && daemon->rr_status[j])
+                     secflag = F_DNSSECOK;
+#endif           
                  if (aqtype == T_CNAME)
                    {
                      if (!cname_count--)
@@ -1129,7 +867,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
                 pointing at this, inherit its TTL */
              if (ttl || cpp)
                {
-                 newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags | secflag);  
+                 newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));        
                  if (newc && cpp)
                    {
                      cpp->addr.cname.target.cache = newc;
@@ -1205,12 +943,12 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
   header->nscount = htons(0);
   header->arcount = htons(0);
   header->ancount = htons(0); /* no answers unless changed below */
-  if (flags == F_NEG)
-    SET_RCODE(header, SERVFAIL); /* couldn't get memory */
-  else if (flags == F_NOERR)
+  if (flags == F_NOERR)
     SET_RCODE(header, NOERROR); /* empty domain */
   else if (flags == F_NXDOMAIN)
     SET_RCODE(header, NXDOMAIN);
+  else if (flags == F_SERVFAIL)
+    SET_RCODE(header, SERVFAIL);
   else if (flags == F_IPV4)
     { /* we know the address */
       SET_RCODE(header, NOERROR);
@@ -1244,11 +982,9 @@ int check_for_local_domain(char *name, time_t now)
   struct naptr *naptr;
 
   /* Note: the call to cache_find_by_name is intended to find any record which matches
-     ie A, AAAA, CNAME, DS. Because RRSIG records are marked by setting both F_DS and F_DNSKEY,
-     cache_find_by name ordinarily only returns records with an exact match on those bits (ie
-     for the call below, only DS records). The F_NSIGMATCH bit changes this behaviour */
+     ie A, AAAA, CNAME. */
 
-  if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_DS | F_NO_RR | F_NSIGMATCH)) &&
+  if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_NO_RR)) &&
       (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
     return 1;
   
@@ -1362,6 +1098,7 @@ int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bog
   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, ...)
 {
@@ -1371,29 +1108,41 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
   unsigned short usval;
   long lval;
   char *sval;
+  
+#define CHECK_LIMIT(size) \
+  if (limit && p + (size) > (unsigned char*)limit) goto truncated;
 
-  if (truncp && *truncp)
-    return 0;
   va_start(ap, format);   /* make ap point to 1st unamed argument */
   
+  if (truncp && *truncp)
+    goto truncated;
+  
   if (nameoffset > 0)
     {
+      CHECK_LIMIT(2);
       PUTSHORT(nameoffset | 0xc000, p);
     }
   else
     {
       char *name = va_arg(ap, char *);
-      if (name)
-       p = do_rfc1035_name(p, name);
+      if (name && !(p = do_rfc1035_name(p, name, limit)))
+       goto truncated;
+      
       if (nameoffset < 0)
        {
+         CHECK_LIMIT(2);
          PUTSHORT(-nameoffset | 0xc000, p);
        }
       else
-       *p++ = 0;
+       {
+         CHECK_LIMIT(1);
+         *p++ = 0;
+       }
     }
 
+  /* type (2) + class (2) + ttl (4) + rdlen (2) */
+  CHECK_LIMIT(10);
+  
   PUTSHORT(type, p);
   PUTSHORT(class, p);
   PUTLONG(ttl, p);      /* TTL */
@@ -1406,6 +1155,7 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
       {
 #ifdef HAVE_IPV6
       case '6':
+        CHECK_LIMIT(IN6ADDRSZ);
        sval = va_arg(ap, char *); 
        memcpy(p, sval, IN6ADDRSZ);
        p += IN6ADDRSZ;
@@ -1413,36 +1163,43 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
 #endif
        
       case '4':
+        CHECK_LIMIT(INADDRSZ);
        sval = va_arg(ap, char *); 
        memcpy(p, sval, INADDRSZ);
        p += INADDRSZ;
        break;
        
       case 'b':
+        CHECK_LIMIT(1);
        usval = va_arg(ap, int);
        *p++ = usval;
        break;
        
       case 's':
+        CHECK_LIMIT(2);
        usval = va_arg(ap, int);
        PUTSHORT(usval, p);
        break;
        
       case 'l':
+        CHECK_LIMIT(4);
        lval = va_arg(ap, long);
        PUTLONG(lval, p);
        break;
        
       case 'd':
-       /* get domain-name answer arg and store it in RDATA field */
-       if (offset)
-         *offset = p - (unsigned char *)header;
-       p = do_rfc1035_name(p, va_arg(ap, char *));
-       *p++ = 0;
+        /* get domain-name answer arg and store it in RDATA field */
+        if (offset)
+          *offset = p - (unsigned char *)header;
+        if (!(p = do_rfc1035_name(p, va_arg(ap, char *), limit)))
+         goto truncated;
+       CHECK_LIMIT(1);
+        *p++ = 0;
        break;
        
       case 't':
        usval = va_arg(ap, int);
+        CHECK_LIMIT(usval);
        sval = va_arg(ap, char *);
        if (usval != 0)
          memcpy(p, sval, usval);
@@ -1454,6 +1211,7 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
        usval = sval ? strlen(sval) : 0;
        if (usval > 255)
          usval = 255;
+        CHECK_LIMIT(usval + 1);
        *p++ = (unsigned char)usval;
        memcpy(p, sval, usval);
        p += usval;
@@ -1462,30 +1220,43 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
 
   va_end(ap);  /* clean up variable argument pointer */
   
+  /* Now, store real RDLength. sav already checked against limit. */
   j = p - sav - 2;
-  PUTSHORT(j, sav);     /* Now, store real RDLength */
-  
-  /* check for overflow of buffer */
-  if (limit && ((unsigned char *)limit - p) < 0)
-    {
-      if (truncp)
-       *truncp = 1;
-      return 0;
-    }
+  PUTSHORT(j, sav);
   
   *pp = p;
   return 1;
+  
+ truncated:
+  va_end(ap);
+  if (truncp)
+    *truncp = 1;
+  return 0;
+
+#undef CHECK_LIMIT
 }
 
 static unsigned long crec_ttl(struct crec *crecp, time_t now)
 {
   /* Return 0 ttl for DHCP entries, which might change
-     before the lease expires. */
+     before the lease expires, unless configured otherwise. */
 
-  if  (crecp->flags & (F_IMMORTAL | F_DHCP))
-    return daemon->local_ttl;
+  if (crecp->flags & F_DHCP)
+    {
+      int conf_ttl = daemon->use_dhcp_ttl ? daemon->dhcp_ttl : daemon->local_ttl;
+      
+      /* Apply ceiling of actual lease length to configured TTL. */
+      if (!(crecp->flags & F_IMMORTAL) && (crecp->ttd - now) < conf_ttl)
+       return crecp->ttd - now;
+      
+      return conf_ttl;
+    }    
   
-  /* Return the Max TTL value if it is lower then the actual TTL */
+  /* Immortal entries other than DHCP are local, and hold TTL in TTD field. */
+  if (crecp->flags & F_IMMORTAL)
+    return crecp->ttd;
+
+  /* Return the Max TTL value if it is lower than the actual TTL */
   if (daemon->max_ttl == 0 || ((unsigned)(crecp->ttd - now) < daemon->max_ttl))
     return crecp->ttd - now;
   else
@@ -1496,54 +1267,41 @@ static unsigned long crec_ttl(struct crec *crecp, time_t now)
 /* return zero if we can't answer from cache, or packet size if we can */
 size_t answer_request(struct dns_header *header, char *limit, size_t qlen,  
                      struct in_addr local_addr, struct in_addr local_netmask, 
-                     time_t now, int *ad_reqd, int *do_bit
+                     time_t now, int ad_reqd, int do_bit, int have_pseudoheader
 {
   char *name = daemon->namebuff;
-  unsigned char *p, *ansp, *pheader;
+  unsigned char *p, *ansp;
   unsigned int qtype, qclass;
   struct all_addr addr;
   int nameoffset;
   unsigned short flag;
   int q, ans, anscount = 0, addncount = 0;
-  int dryrun = 0, sec_reqd = 0, have_pseudoheader = 0;
+  int dryrun = 0;
   struct crec *crecp;
   int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
   struct mx_srv_record *rec;
   size_t len;
+
+  if (ntohs(header->ancount) != 0 ||
+      ntohs(header->nscount) != 0 ||
+      ntohs(header->qdcount) == 0 || 
+      OPCODE(header) != QUERY )
+    return 0;
+
+  /* always servfail queries with RD unset, to avoid cache snooping. */
+  if (!(header->hb3 & HB3_RD))
+    return setup_reply(header, qlen, NULL, F_SERVFAIL, 0);
+  
   /* Don't return AD set if checking disabled. */
   if (header->hb4 & HB4_CD)
     sec_data = 0;
   
-  /* RFC 6840 5.7 */
-  *ad_reqd = header->hb4 & HB4_AD;
-  *do_bit = 0;
-
-  /* If there is an RFC2671 pseudoheader then it will be overwritten by
+  /* If there is an  additional data section then it will be overwritten by
      partial replies, so we have to do a dry run to see if we can answer
-     the query. We check to see if the do bit is set, if so we always
-     forward rather than answering from the cache, which doesn't include
-     security information, unless we're in DNSSEC validation mode. */
-
-  if (find_pseudoheader(header, qlen, NULL, &pheader, NULL))
-    { 
-      unsigned short flags;
-      
-      have_pseudoheader = 1;
-
-      pheader += 4; /* udp size, ext_rcode */
-      GETSHORT(flags, pheader);
-      
-      if ((sec_reqd = flags & 0x8000))
-       *do_bit = 1;/* do bit */ 
-
-      *ad_reqd = 1;
-      dryrun = 1;
-    }
+     the query. */
+  if (ntohs(header->arcount) != 0)
+    dryrun = 1;
 
-  if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
-    return 0;
-  
   for (rec = daemon->mxnames; rec; rec = rec->next)
     rec->offset = 0;
   
@@ -1567,11 +1325,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
       GETSHORT(qtype, p); 
       GETSHORT(qclass, p);
 
-      /* Don't filter RRSIGS from answers to ANY queries, even if do-bit
-        not set. */
-      if (qtype == T_ANY)
-       *do_bit = 1;
-
       ans = 0; /* have we answered this question */
       
       if (qtype == T_TXT || qtype == T_ANY)
@@ -1587,6 +1340,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                      unsigned long ttl = daemon->local_ttl;
                      int ok = 1;
                      log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
+#ifndef NO_ID
                      /* Dynamically generate stat record */
                      if (t->stat != 0)
                        {
@@ -1594,7 +1348,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                          if (!cache_make_stat(t))
                            ok = 0;
                        }
-                     
+#endif
                      if (ok && add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                                                    ttl, NULL,
                                                    T_TXT, t->class, "t", t->len, t->txt))
@@ -1605,98 +1359,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
            }
        }
 
-#ifdef HAVE_DNSSEC
-      if (option_bool(OPT_DNSSEC_VALID) && (qtype == T_DNSKEY || qtype == T_DS))
-       {
-         int gotone = 0;
-         struct blockdata *keydata;
-
-         /* Do we have RRSIG? Can't do DS or DNSKEY otherwise. */
-         if (sec_reqd)
-           {
-             crecp = NULL;
-             while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
-               if (crecp->uid == qclass && crecp->addr.sig.type_covered == qtype)
-                 break;
-           }
-         
-         if (!sec_reqd || crecp)
-           {
-             if (qtype == T_DS)
-               {
-                 crecp = NULL;
-                 while ((crecp = cache_find_by_name(crecp, name, now, F_DS)))
-                   if (crecp->uid == qclass)
-                     {
-                       gotone = 1; 
-                       if (!dryrun)
-                         {
-                           if (crecp->flags & F_NEG)
-                             {
-                               if (crecp->flags & F_NXDOMAIN)
-                                 nxdomain = 1;
-                               log_query(F_UPSTREAM, name, NULL, "no DS");     
-                             }
-                           else if ((keydata = blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, NULL)))
-                             {                                               
-                               struct all_addr a;
-                               a.addr.keytag =  crecp->addr.ds.keytag;
-                               log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DS keytag %u");
-                               if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
-                                                       crec_ttl(crecp, now), &nameoffset,
-                                                       T_DS, qclass, "sbbt", 
-                                                       crecp->addr.ds.keytag, crecp->addr.ds.algo, 
-                                                       crecp->addr.ds.digest, crecp->addr.ds.keylen, keydata))
-                                 anscount++;
-                               
-                             } 
-                         }
-                     }
-               }
-             else /* DNSKEY */
-               {
-                 crecp = NULL;
-                 while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY)))
-                   if (crecp->uid == qclass)
-                     {
-                       gotone = 1;
-                       if (!dryrun && (keydata = blockdata_retrieve(crecp->addr.key.keydata, crecp->addr.key.keylen, NULL)))
-                         {                                                   
-                           struct all_addr a;
-                           a.addr.keytag =  crecp->addr.key.keytag;
-                           log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DNSKEY keytag %u");
-                           if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
-                                                   crec_ttl(crecp, now), &nameoffset,
-                                                   T_DNSKEY, qclass, "sbbt", 
-                                                   crecp->addr.key.flags, 3, crecp->addr.key.algo, crecp->addr.key.keylen, keydata))
-                             anscount++;
-                         }
-                     }
-               }
-           }
-         
-         /* Now do RRSIGs */
-         if (gotone)
-           {
-             ans = 1;
-             auth = 0;
-             if (!dryrun && sec_reqd)
-               {
-                 crecp = NULL;
-                 while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
-                   if (crecp->uid == qclass && crecp->addr.sig.type_covered == qtype &&
-                       (keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)))
-                     {
-                       add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
-                                           crec_ttl(crecp, now), &nameoffset,
-                                           T_RRSIG, qclass, "t", crecp->addr.sig.keylen, keydata);
-                       anscount++;
-                     }
-               }
-           }
-       }
-#endif      
-      
       if (qclass == C_IN)
        {
          struct txt_record *t;
@@ -1705,6 +1367,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
            if ((t->class == qtype || qtype == T_ANY) && hostname_isequal(name, t->name))
              {
                ans = 1;
+               sec_data = 0;
                if (!dryrun)
                  {
                    log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
@@ -1761,6 +1424,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
              
              if (intr)
                {
+                 sec_data = 0;
                  ans = 1;
                  if (!dryrun)
                    {
@@ -1774,6 +1438,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
              else if (ptr)
                {
                  ans = 1;
+                 sec_data = 0;
                  if (!dryrun)
                    {
                      log_query(F_CONFIG | F_RRNAME, name, NULL, "<PTR>");
@@ -1788,38 +1453,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                }
              else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
                {
-                 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && sec_reqd)
-                   {
-                     if (!option_bool(OPT_DNSSEC_VALID) || ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK)))
-                       crecp = NULL;
-#ifdef HAVE_DNSSEC
-                     else if (crecp->flags & F_DNSSECOK)
-                       {
-                         int gotsig = 0;
-                         struct crec *rr_crec = NULL;
-
-                         while ((rr_crec = cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY)))
-                           {
-                             if (rr_crec->addr.sig.type_covered == T_PTR && rr_crec->uid == C_IN)
-                               {
-                                 char *sigdata = blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec->addr.sig.keylen, NULL);
-                                 gotsig = 1;
-                                 
-                                 if (!dryrun && 
-                                     add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
-                                                         rr_crec->ttd - now, &nameoffset,
-                                                         T_RRSIG, C_IN, "t", crecp->addr.sig.keylen, sigdata))
-                                   anscount++;
-                               }
-                           } 
-                         
-                         if (!gotsig)
-                           crecp = NULL;
-                       }
-#endif
-                   }
-
-                 if (crecp)
+                 /* Don't use cache when DNSSEC data required, unless we know that
+                    the zone is unsigned, which implies that we're doing
+                    validation. */
+                 if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || 
+                     !do_bit || 
+                     (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
                    {
                      do 
                        { 
@@ -1829,19 +1468,19 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                          
                          if (!(crecp->flags & F_DNSSECOK))
                            sec_data = 0;
-                         
+                          
+                         ans = 1;
+                          
                          if (crecp->flags & F_NEG)
                            {
-                             ans = 1;
                              auth = 0;
                              if (crecp->flags & F_NXDOMAIN)
                                nxdomain = 1;
                              if (!dryrun)
                                log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL);
                            }
-                         else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd || option_bool(OPT_DNSSEC_VALID))
+                         else
                            {
-                             ans = 1;
                              if (!(crecp->flags & (F_HOSTS | F_DHCP)))
                                auth = 0;
                              if (!dryrun)
@@ -1861,6 +1500,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
              else if (is_rev_synth(is_arpa, &addr, name))
                {
                  ans = 1;
+                 sec_data = 0;
                  if (!dryrun)
                    {
                      log_query(F_CONFIG | F_REVERSE | is_arpa, name, &addr, NULL); 
@@ -1871,19 +1511,48 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                              anscount++;
                    }
                }
-             else if (is_arpa == F_IPV4 && 
-                      option_bool(OPT_BOGUSPRIV) && 
-                      private_net(addr.addr.addr4, 1))
+             else if (option_bool(OPT_BOGUSPRIV) && (
+#ifdef HAVE_IPV6
+                      (is_arpa == F_IPV6 && private_net6(&addr.addr.addr6)) ||
+#endif
+                      (is_arpa == F_IPV4 && private_net(addr.addr.addr4, 1))))
                {
-                 /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
-                 ans = 1;
-                 nxdomain = 1;
-                 if (!dryrun)
-                   log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN, 
-                             name, &addr, NULL);
+                 struct server *serv;
+                 unsigned int namelen = strlen(name);
+                 char *nameend = name + namelen;
+
+                 /* see if have rev-server set */
+                 for (serv = daemon->servers; serv; serv = serv->next)
+                   {
+                     unsigned int domainlen;
+                     char *matchstart;
+
+                     if ((serv->flags & (SERV_HAS_DOMAIN | SERV_NO_ADDR)) != SERV_HAS_DOMAIN)
+                       continue;
+
+                     domainlen = strlen(serv->domain);
+                     if (domainlen == 0 || domainlen > namelen)
+                       continue;
+
+                     matchstart = nameend - domainlen;
+                     if (hostname_isequal(matchstart, serv->domain) &&
+                         (namelen == domainlen || *(matchstart-1) == '.' ))
+                       break;
+                   }
+
+                 /* if no configured server, not in cache, enabled and private IPV4 address, return NXDOMAIN */
+                 if (!serv)
+                   {
+                     ans = 1;
+                     sec_data = 0;
+                     nxdomain = 1;
+                     if (!dryrun)
+                       log_query(F_CONFIG | F_REVERSE | is_arpa | F_NEG | F_NXDOMAIN,
+                                 name, &addr, NULL);
+                   }
                }
            }
-           
+         
          for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0)
            {
              unsigned short type = T_A;
@@ -1899,43 +1568,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
              if (qtype != type && qtype != T_ANY)
                continue;
              
-             /* Check for "A for A"  queries; be rather conservative 
-                about what looks like dotted-quad.  */
-             if (qtype == T_A)
-               {
-                 char *cp;
-                 unsigned int i, a;
-                 int x;
-
-                 for (cp = name, i = 0, a = 0; *cp; i++)
-                   {
-                     if (!isdigit((unsigned char)*cp) || (x = strtol(cp, &cp, 10)) > 255) 
-                       {
-                         i = 5;
-                         break;
-                       }
-                     
-                     a = (a << 8) + x;
-                     
-                     if (*cp == '.') 
-                       cp++;
-                   }
-                 
-                 if (i == 4)
-                   {
-                     ans = 1;
-                     if (!dryrun)
-                       {
-                         addr.addr.addr4.s_addr = htonl(a);
-                         log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
-                         if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
-                                                 daemon->local_ttl, NULL, type, C_IN, "4", &addr))
-                           anscount++;
-                       }
-                     continue;
-                   }
-               }
-
              /* interface name stuff */
            intname_restart:
              for (intr = daemon->int_names; intr; intr = intr->next)
@@ -1945,9 +1577,24 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
              if (intr)
                {
                  struct addrlist *addrlist;
-                 int gotit = 0;
+                 int gotit = 0, localise = 0;
 
                  enumerate_interfaces(0);
+                   
+                 /* See if a putative address is on the network from which we received
+                    the query, is so we'll filter other answers. */
+                 if (local_addr.s_addr != 0 && option_bool(OPT_LOCALISE) && type == T_A)
+                   for (intr = daemon->int_names; intr; intr = intr->next)
+                     if (hostname_isequal(name, intr->name))
+                       for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
+#ifdef HAVE_IPV6
+                         if (!(addrlist->flags & ADDRLIST_IPV6))
+#endif
+                           if (is_same_net(*((struct in_addr *)&addrlist->addr), local_addr, local_netmask))
+                             {
+                               localise = 1;
+                               break;
+                             }
                  
                  for (intr = daemon->int_names; intr; intr = intr->next)
                    if (hostname_isequal(name, intr->name))
@@ -1957,11 +1604,16 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                          if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type)
 #endif
                            {
+                             if (localise && 
+                                 !is_same_net(*((struct in_addr *)&addrlist->addr), local_addr, local_netmask))
+                               continue;
+
 #ifdef HAVE_IPV6
                              if (addrlist->flags & ADDRLIST_REVONLY)
                                continue;
 #endif 
                              ans = 1;  
+                             sec_data = 0;
                              if (!dryrun)
                                {
                                  gotit = 1;
@@ -1985,7 +1637,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                {
                  int localise = 0;
                  
-                 /* See if a putative address is on the network from which we recieved
+                 /* See if a putative address is on the network from which we received
                     the query, is so we'll filter other answers. */
                  if (local_addr.s_addr != 0 && option_bool(OPT_LOCALISE) && flag == F_IPV4)
                    {
@@ -2001,48 +1653,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                      crecp = save;
                    }
 
-                 /* If the client asked for DNSSEC and we can't provide RRSIGs, either
-                    because we've not doing DNSSEC or the cached answer is signed by negative,
-                    don't answer from the cache, forward instead. */
-                 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && sec_reqd)
-                   {
-                     if (!option_bool(OPT_DNSSEC_VALID) || ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK)))
-                       crecp = NULL;
-#ifdef HAVE_DNSSEC
-                     else if (crecp->flags & F_DNSSECOK)
-                       {
-                         /* We're returning validated data, need to return the RRSIG too. */
-                         struct crec *rr_crec = NULL;
-                         int sigtype = type;
-                         /* The signature may have expired even though the data is still in cache, 
-                            forward instead of answering from cache if so. */
-                         int gotsig = 0;
-                         
-                         if (crecp->flags & F_CNAME)
-                           sigtype = T_CNAME;
-                         
-                         while ((rr_crec = cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY)))
-                           {
-                             if (rr_crec->addr.sig.type_covered == sigtype && rr_crec->uid == C_IN)
-                               {
-                                 char *sigdata = blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec->addr.sig.keylen, NULL);
-                                 gotsig = 1;
-                                 
-                                 if (!dryrun && 
-                                     add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
-                                                         rr_crec->ttd - now, &nameoffset,
-                                                         T_RRSIG, C_IN, "t", rr_crec->addr.sig.keylen, sigdata))
-                                   anscount++;
-                               }
-                           }
-                         
-                         if (!gotsig)
-                           crecp = NULL;
-                       }
-#endif
-                   }            
-
-                 if (crecp)
+                 /* If the client asked for DNSSEC  don't use cached data. */
+                 if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))
                    do
                      { 
                        /* don't answer wildcard queries with data not from /etc/hosts
@@ -2076,17 +1688,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                        
                        if (crecp->flags & F_NEG)
                          {
-                           /* We don't cache NSEC records, so if a DNSSEC-validated negative answer
-                              is cached and the client wants DNSSEC, forward rather than answering from the cache */
-                           if (!sec_reqd || !(crecp->flags & F_DNSSECOK))
-                             {
-                               ans = 1;
-                               auth = 0;
-                               if (crecp->flags & F_NXDOMAIN)
-                                 nxdomain = 1;
-                               if (!dryrun)
-                                 log_query(crecp->flags, name, NULL, NULL);
-                             }
+                           ans = 1;
+                           auth = 0;
+                           if (crecp->flags & F_NXDOMAIN)
+                             nxdomain = 1;
+                           if (!dryrun)
+                             log_query(crecp->flags, name, NULL, NULL);
                          }
                        else 
                          {
@@ -2129,8 +1736,9 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
 
          if (qtype == T_CNAME || qtype == T_ANY)
            {
-             if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)) &&
-                 (qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG  | (dryrun ? F_NO_RR : 0)))))
+             if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | (dryrun ? F_NO_RR : 0))) &&
+                 (qtype == T_CNAME || (crecp->flags & F_CONFIG)) &&
+                 ((crecp->flags & F_CONFIG) || !do_bit || !(crecp->flags & F_DNSSECOK)))
                {
                  if (!(crecp->flags & F_DNSSECOK))
                    sec_data = 0;
@@ -2306,7 +1914,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
   /* set RA flag */
   header->hb4 |= HB4_RA;
    
-  /* authoritive - only hosts and DHCP derived names. */
+  /* authoritative - only hosts and DHCP derived names. */
   if (auth)
     header->hb3 |= HB3_AA;
   
@@ -2324,14 +1932,14 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
 
   len = ansp - (unsigned char *)header;
   
+  /* Advertise our packet size limit in our reply */
   if (have_pseudoheader)
-    len = add_pseudoheader(header, len, (unsigned char *)limit, 0, NULL, 0, sec_reqd);
+    len = add_pseudoheader(header, len, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
   
-  if (*ad_reqd && sec_data)
+  if (ad_reqd && sec_data)
     header->hb4 |= HB4_AD;
   else
     header->hb4 &= ~HB4_AD;
   
   return len;
 }
-
index 9f69ed5..c08a8ab 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -32,7 +32,7 @@ static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, in
 static void option_put_string(struct dhcp_packet *mess, unsigned char *end, 
                              int opt, char *string, int null_term);
 static struct in_addr option_addr(unsigned char *opt);
-static unsigned int option_uint(unsigned char *opt, int i, int size);
+static unsigned int option_uint(unsigned char *opt, int offset, int size);
 static void log_packet(char *type, void *addr, unsigned char *ext_mac, 
                       int mac_len, char *interface, char *string, char *err, u32 xid);
 static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
@@ -42,14 +42,14 @@ static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
 static int in_list(unsigned char *list, int opt);
 static void do_options(struct dhcp_context *context,
                       struct dhcp_packet *mess,
-                      unsigned char *real_end, 
+                      unsigned char *end,
                       unsigned char *req_options,
                       char *hostname, 
-                      char *config_domain,
+                      char *domain,
                       struct dhcp_netid *netid,
                       struct in_addr subnet_addr, 
                       unsigned char fqdn_flags,
-                      int null_term, int pxearch,
+                      int null_term, int pxe_arch,
                       unsigned char *uuid,
                       int vendor_class_len,
                       time_t now,
@@ -58,15 +58,17 @@ static void do_options(struct dhcp_context *context,
 
 
 static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt); 
-static int do_encap_opts(struct dhcp_opt *opts, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
+static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
 static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid);
 static int prune_vendor_opts(struct dhcp_netid *netid);
 static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now);
 struct dhcp_boot *find_boot(struct dhcp_netid *netid);
+static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dhcp_packet *mess, struct in_addr local, time_t now, int pxe);
+static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid);
 
-  
 size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
-                 size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe, struct in_addr fallback)
+                 size_t sz, time_t now, int unicast_dest, int loopback,
+                 int *is_inform, int pxe, struct in_addr fallback, time_t recvtime)
 {
   unsigned char *opt, *clid = NULL;
   struct dhcp_lease *ltmp, *lease = NULL;
@@ -155,7 +157,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
          for (offset = 0; offset < (len - 5); offset += elen + 5)
            {
              elen = option_uint(opt, offset + 4 , 1);
-             if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA)
+             if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA && offset + elen + 5 <= len)
                {
                  unsigned char *x = option_ptr(opt, offset + 5);
                  unsigned char *y = option_ptr(opt, offset + elen + 5);
@@ -186,7 +188,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
             be enough free space at the end of the packet to copy the option. */
          unsigned char *sopt;
          unsigned int total = option_len(opt) + 2;
-         unsigned char *last_opt = option_find(mess, sz, OPTION_END, 0);
+         unsigned char *last_opt = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + sz,
+                                                OPTION_END, 0);
          if (last_opt && last_opt < end - total)
            {
              end -= total;
@@ -364,7 +367,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
   
   /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
      Otherwise assume the option is an array, and look for a matching element. 
-     If no data given, existance of the option is enough. This code handles 
+     If no data given, existence of the option is enough. This code handles 
      rfc3925 V-I classes too. */
   for (o = daemon->dhcp_match; o; o = o->next)
     {
@@ -380,7 +383,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
            {
              len = option_uint(opt, offset + 4 , 1);
              /* Need to take care that bad data can't run us off the end of the packet */
-             if ((offset + len + 5 <= (option_len(opt))) &&
+             if ((offset + len + 5 <= (unsigned)(option_len(opt))) &&
                  (option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
                for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
                  { 
@@ -485,6 +488,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
       known_id.next = netid;
       netid = &known_id;
     }
+  else if (find_config(daemon->dhcp_conf, NULL, clid, clid_len, 
+                      mess->chaddr, mess->hlen, mess->htype, NULL))
+    {
+      known_id.net = "known-othernet";
+      known_id.next = netid;
+      netid = &known_id;
+    }
   
   if (mess_type == 0 && !pxe)
     {
@@ -566,7 +576,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
                       lease_prune(lease, now);
                       lease = NULL;
                     }
-                  if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now))
+                  if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now, loopback))
                     message = _("no address available");
                }
              else
@@ -824,7 +834,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
          else
            mess->siaddr = context->local; 
          
-         snprintf((char *)mess->file, sizeof(mess->file), "%s.%d", service->basename, layer);
+         if (strchr(service->basename, '.'))
+           snprintf((char *)mess->file, sizeof(mess->file),
+               "%s", service->basename);
+         else
+           snprintf((char *)mess->file, sizeof(mess->file),
+               "%s.%d", service->basename, layer);
+         
          option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
          option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
          pxe_misc(mess, end, uuid);
@@ -851,6 +867,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
          if ((mess_type == DHCPDISCOVER || (pxe && mess_type == DHCPREQUEST)))
            {
              struct dhcp_context *tmp;
+             int workaround = 0;
              
              for (tmp = context; tmp; tmp = tmp->current)
                if ((tmp->flags & CONTEXT_PROXY) &&
@@ -860,7 +877,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
              if (tmp)
                {
                  struct dhcp_boot *boot;
-                 
+                 int redirect4011 = 0;
+
                  if (tmp->netid.net)
                    {
                      tmp->netid.next = netid;
@@ -878,10 +896,21 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
                  
                  clear_packet(mess, end);
                  
-                 /* Provide the bootfile here, for gPXE, and in case we have no menu items
-                    and set discovery_control = 8 */
-                 if (boot)
+                 /* Redirect EFI clients to port 4011 */
+                 if (pxearch >= 6)
+                   {
+                     redirect4011 = 1;
+                     mess->siaddr = tmp->local;
+                   }
+                 
+                 /* Returns true if only one matching service is available. On port 4011, 
+                    it also inserts the boot file and server name. */
+                 workaround = pxe_uefi_workaround(pxearch, tagif_netid, mess, tmp->local, now, pxe);
+                 
+                 if (!workaround && boot)
                    {
+                     /* Provide the bootfile here, for iPXE, and in case we have no menu items
+                        and set discovery_control = 8 */
                      if (boot->next_server.s_addr) 
                        mess->siaddr = boot->next_server;
                      else if (boot->tftp_sname) 
@@ -896,10 +925,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
                  option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(tmp->local.s_addr));
                  pxe_misc(mess, end, uuid);
                  prune_vendor_opts(tagif_netid);
-                 do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
-                 
+                 if ((pxe && !workaround) || !redirect4011)
+                   do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
+           
                  log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
                  log_tags(tagif_netid, ntohl(mess->xid));
+                 if (!ignore)
+                   apply_delay(mess->xid, recvtime, tagif_netid);
                  return ignore ? 0 : dhcp_packet_size(mess, agent_id, real_end);         
                }
            }
@@ -1020,11 +1052,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
                   !config_find_by_address(daemon->dhcp_conf, lease->addr))
            mess->yiaddr = lease->addr;
          else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) && 
-                  !config_find_by_address(daemon->dhcp_conf, addr))
+                  !config_find_by_address(daemon->dhcp_conf, addr) && do_icmp_ping(now, addr, 0, loopback))
            mess->yiaddr = addr;
          else if (emac_len == 0)
            message = _("no unique-id");
-         else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now))
+         else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now, loopback))
            message = _("no address available");      
        }
       
@@ -1040,7 +1072,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
        }
 
       log_tags(tagif_netid, ntohl(mess->xid));
-      
+      apply_delay(mess->xid, recvtime, tagif_netid);
       log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
       
       time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
@@ -1286,6 +1318,24 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
                      add_extradata_opt(lease, NULL);
                    }
 
+                 /* DNSMASQ_REQUESTED_OPTIONS */
+                 if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 1)))
+                   {
+                     int len = option_len(opt);
+                     unsigned char *rop = option_ptr(opt, 0);
+                     char *q = daemon->namebuff;
+                     int i;
+                     for (i = 0; i < len; i++)
+                       {
+                         q += snprintf(q, MAXDNAME - (q - daemon->namebuff), "%d%s", rop[i], i + 1 == len ? "" : ",");
+                       }
+                     lease_add_extradata(lease, (unsigned char *)daemon->namebuff, (q - daemon->namebuff), 0); 
+                   }
+                 else
+                   {
+                     add_extradata_opt(lease, NULL);
+                   }
+
                  /* space-concat tag set */
                  if (!tagif_netid)
                    add_extradata_opt(lease, NULL);
@@ -1308,7 +1358,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
                      /* If the user-class option started as counted strings, the first byte will be zero. */
                      if (len != 0 && ucp[0] == 0)
                        ucp++, len--;
-                     lease_add_extradata(lease, ucp, len, 0);
+                     lease_add_extradata(lease, ucp, len, -1);
                    }
                }
 #endif
@@ -1589,7 +1639,7 @@ static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt
 {
   while (1) 
     {
-      if (p > end)
+      if (p >= end)
        return NULL;
       else if (*p == OPTION_END)
        return opt == OPTION_END ? p : NULL;
@@ -1975,6 +2025,56 @@ static int prune_vendor_opts(struct dhcp_netid *netid)
   return force;
 }
 
+
+/* Many UEFI PXE implementations have badly broken menu code.
+   If there's exactly one relevant menu item, we abandon the menu system,
+   and jamb the data direct into the DHCP file, siaddr and sname fields.
+   Note that in this case, we have to assume that layer zero would be requested
+   by the client PXE stack. */
+static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dhcp_packet *mess, struct in_addr local, time_t now, int pxe)
+{
+  struct pxe_service *service, *found;
+
+  /* Only workaround UEFI archs. */
+  if (pxe_arch < 6)
+    return 0;
+  
+  for (found = NULL, service = daemon->pxe_services; service; service = service->next)
+    if (pxe_arch == service->CSA && service->basename && match_netid(service->netid, netid, 1))
+      {
+       if (found)
+         return 0; /* More than one relevant menu item */
+         
+       found = service;
+      }
+
+  if (!found)
+    return 0; /* No relevant menu items. */
+  
+  if (!pxe)
+     return 1;
+  
+  if (found->sname)
+    {
+      mess->siaddr = a_record_from_hosts(found->sname, now);
+      snprintf((char *)mess->sname, sizeof(mess->sname), "%s", found->sname);
+    }
+  else 
+    {
+      if (found->server.s_addr != 0)
+       mess->siaddr = found->server; 
+      else
+       mess->siaddr = local;
+  
+      inet_ntop(AF_INET, &mess->siaddr, (char *)mess->sname, INET_ADDRSTRLEN);
+    }
+  
+  snprintf((char *)mess->file, sizeof(mess->file), 
+          strchr(found->basename, '.') ? "%s" : "%s.0", found->basename);
+  
+  return 1;
+}
+
 static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now)
 {
 #define NUM_OPTS 4  
@@ -2184,7 +2284,7 @@ static void do_options(struct dhcp_context *context,
   /* See if we can send the boot stuff as options.
      To do this we need a requested option list, BOOTP
      and very old DHCP clients won't have this, we also 
-     provide an manual option to disable it.
+     provide a manual option to disable it.
      Some PXE ROMs have bugs (surprise!) and need zero-terminated 
      names, so we always send those.  */
   if ((boot = find_boot(tagif)))
@@ -2352,10 +2452,10 @@ static void do_options(struct dhcp_context *context,
 
              if (fqdn_flags & 0x04)
                {
-                 p = do_rfc1035_name(p, hostname);
+                 p = do_rfc1035_name(p, hostname, NULL);
                  if (domain)
                    {
-                     p = do_rfc1035_name(p, domain);
+                     p = do_rfc1035_name(p, domain, NULL);
                      *p++ = 0;
                    }
                }
@@ -2509,7 +2609,8 @@ static void do_options(struct dhcp_context *context,
   if (context && pxe_arch != -1)
     {
       pxe_misc(mess, end, uuid);
-      config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
+      if (!pxe_uefi_workaround(pxe_arch, tagif, mess, context->local, now, 0))
+       config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
     }
 
   if ((force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT)) &&
@@ -2528,6 +2629,29 @@ static void do_options(struct dhcp_context *context,
     }
 }
 
+static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid)
+{
+  struct delay_config *delay_conf;
+  
+  /* Decide which delay_config option we're using */
+  for (delay_conf = daemon->delay_conf; delay_conf; delay_conf = delay_conf->next)
+    if (match_netid(delay_conf->netid, netid, 0))
+      break;
+  
+  if (!delay_conf)
+    /* No match, look for one without a netid */
+    for (delay_conf = daemon->delay_conf; delay_conf; delay_conf = delay_conf->next)
+      if (match_netid(delay_conf->netid, netid, 1))
+        break;
+
+  if (delay_conf)
+    {
+      if (!option_bool(OPT_QUIET_DHCP))
+       my_syslog(MS_DHCP | LOG_INFO, _("%u reply delay: %d"), ntohl(xid), delay_conf->delay);
+      delay_dhcp(recvtime, delay_conf->delay, -1, 0, 0);
+    }
+}
+
 #endif
   
 
index 2665d0d..21fcd9b 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -89,7 +89,7 @@ unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *if
   for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
     vendor->netid.next = &vendor->netid;
   
-  save_counter(0);
+  reset_counter();
   state.context = context;
   state.interface = interface;
   state.iface_name = iface_name;
@@ -118,7 +118,7 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
   void *opt;
   struct dhcp_vendor *vendor;
 
-  /* if not an encaplsulated relayed message, just do the stuff */
+  /* if not an encapsulated relayed message, just do the stuff */
   if (msg_type != DHCP6RELAYFORW)
     {
       /* if link_address != NULL if points to the link address field of the 
@@ -130,7 +130,7 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
       MAC address from the local ND cache. */
       
       if (!state->link_address)
-       get_client_mac(client_addr, state->interface, state->mac, &state->mac_len, &state->mac_type);
+       get_client_mac(client_addr, state->interface, state->mac, &state->mac_len, &state->mac_type, now);
       else
        {
          struct dhcp_context *c;
@@ -206,6 +206,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
   /* RFC-6939 */
   if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3)))
     {
+      if (opt6_len(opt) - 2 > DHCP_CHADDR_MAX) {
+        return 0;
+      }
       state->mac_type = opt6_uint(opt, 0, 2);
       state->mac_len = opt6_len(opt) - 2;
       memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);
@@ -213,6 +216,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
   
   for (opt = opts; opt; opt = opt6_next(opt, end))
     {
+      if (opt6_ptr(opt, 0) + opt6_len(opt) > end) 
+        return 0;
+     
       int o = new_opt6(opt6_type(opt));
       if (opt6_type(opt) == OPTION6_RELAY_MSG)
        {
@@ -262,7 +268,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
   state->hostname_auth = 0;
   state->hostname = NULL;
   state->client_hostname = NULL;
-  state->fqdn_flags = 0x01; /* default to send if we recieve no FQDN option */
+  state->fqdn_flags = 0x01; /* default to send if we receive no FQDN option */
 #ifdef OPTION6_PREFIX_CLASS
   state->send_prefix_class = NULL;
 #endif
@@ -381,7 +387,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
   
   /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
      Otherwise assume the option is an array, and look for a matching element. 
-     If no data given, existance of the option is enough. This code handles 
+     If no data given, existence of the option is enough. This code handles 
      V-I opts too. */
   for (opt_cfg = daemon->dhcp_match6; opt_cfg; opt_cfg = opt_cfg->next)
     {
@@ -526,7 +532,14 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
       if (have_config(config, CONFIG_DISABLE))
        ignore = 1;
     }
-
+  else if (state->clid &&
+          find_config(daemon->dhcp_conf, NULL, state->clid, state->clid_len, state->mac, state->mac_len, state->mac_type, NULL))
+    {
+      known_id.net = "known-othernet";
+      known_id.next = state->tags;
+      state->tags = &known_id;
+    }
+  
 #ifdef OPTION6_PREFIX_CLASS
   /* OPTION_PREFIX_CLASS in ORO, send addresses in all prefix classes */
   if (daemon->prefix_classes && (msg_type == DHCP6SOLICIT || msg_type == DHCP6REQUEST))
@@ -869,7 +882,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
 
             if (!ia_option)
               {
-                /* If we get a request with a IA_*A without addresses, treat it exactly like
+                /* If we get a request with an IA_*A without addresses, treat it exactly like
                    a SOLICT with rapid commit set. */
                 save_counter(start);
                 goto request_no_address; 
@@ -1273,7 +1286,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
            
          }
 
-       /* We must anwser with 'success' in global section anyway */
+       /* We must answer with 'success' in global section anyway */
        o1 = new_opt6(OPTION6_STATUS_CODE);
        put_opt6_short(DHCP6SUCCESS);
        put_opt6_string(_("success"));
@@ -1320,15 +1333,15 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
       
       if (opt_cfg->opt == OPTION6_REFRESH_TIME)
        done_refresh = 1;
+       
+      if (opt_cfg->opt == OPTION6_DNS_SERVER)
+       done_dns = 1;
       
       if (opt_cfg->flags & DHOPT_ADDR6)
        {
          int len, j;
          struct in6_addr *a;
          
-         if (opt_cfg->opt == OPTION6_DNS_SERVER)
-           done_dns = 1;
-         
          for (a = (struct in6_addr *)opt_cfg->val, len = opt_cfg->len, j = 0; 
               j < opt_cfg->len; j += IN6ADDRSZ, a++)
            if ((IN6_IS_ADDR_ULA_ZERO(a) && IN6_IS_ADDR_UNSPECIFIED(state->ula_addr)) ||
@@ -1387,7 +1400,7 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
       unsigned int lease_time = 0xffffffff;
       
       /* Find the smallest lease tie of all contexts,
-        subjext to the RFC-4242 stipulation that this must not 
+        subject to the RFC-4242 stipulation that this must not 
         be less than 600. */
       for (c = state->context; c; c = c->next)
        if (c->lease_time < lease_time)
@@ -1472,10 +1485,10 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
       if ((p = expand(len + 2)))
        {
          *(p++) = state->fqdn_flags;
-         p = do_rfc1035_name(p, state->hostname);
+         p = do_rfc1035_name(p, state->hostname, NULL);
          if (state->send_domain)
            {
-             p = do_rfc1035_name(p, state->send_domain);
+             p = do_rfc1035_name(p, state->send_domain, NULL);
              *p = 0;
            }
        }
@@ -1612,7 +1625,7 @@ static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz)
 {
   if (t1cntr != 0)
     {
-      /* go back an fill in fields in IA_NA option */
+      /* go back and fill in fields in IA_NA option */
       int sav = save_counter(t1cntr);
       unsigned int t1, t2, fuzz = 0;
 
@@ -1975,7 +1988,7 @@ static void log6_packet(struct state *state, char *type, struct in6_addr *addr,
 
   if (addr)
     {
-      inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, 255);
+      inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, DHCP_BUFF_SZ - 1);
       strcat(daemon->dhcp_buff2, " ");
     }
   else
@@ -2054,7 +2067,8 @@ static unsigned int opt6_uint(unsigned char *opt, int offset, int size)
   return ret;
 } 
 
-void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, u32 scope_id)
+void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, 
+                    struct in6_addr *peer_address, u32 scope_id, time_t now)
 {
   /* ->local is same value for all relays on ->current chain */
   
@@ -2068,7 +2082,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer
   unsigned char mac[DHCP_CHADDR_MAX];
 
   inet_pton(AF_INET6, ALL_SERVERS, &multicast);
-  get_client_mac(peer_address, scope_id, mac, &maclen, &mactype);
+  get_client_mac(peer_address, scope_id, mac, &maclen, &mactype, now);
 
   /* source address == relay address */
   from.addr.addr6 = relay->local.addr.addr6;
@@ -2083,7 +2097,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer
   if (hopcount > 32)
     return;
 
-  save_counter(0);
+  reset_counter();
 
   if ((header = put_opt6(NULL, 34)))
     {
@@ -2126,7 +2140,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer
                my_syslog(MS_DHCP | LOG_ERR, _("Cannot multicast to DHCPv6 server without correct interface"));
            }
                
-         send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(0), &to, &from, 0);
+         send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(-1), &to, &from, 0);
          
          if (option_bool(OPT_LOG_OPTS))
            {
@@ -2160,7 +2174,7 @@ unsigned short relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival
        (!relay->interface || wildcard_match(relay->interface, arrival_interface)))
       break;
       
-  save_counter(0);
+  reset_counter();
 
   if (relay)
     {
diff --git a/src/rrfilter.c b/src/rrfilter.c
new file mode 100644 (file)
index 0000000..f5b9c61
--- /dev/null
@@ -0,0 +1,339 @@
+/* dnsmasq is Copyright (c) 2000-2018 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/>.
+*/
+
+/* Code to safely remove RRs from a DNS answer */ 
+
+#include "dnsmasq.h"
+
+/* Go through a domain name, find "pointers" and fix them up based on how many bytes
+   we've chopped out of the packet, or check they don't point into an elided part.  */
+static int check_name(unsigned char **namep, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
+{
+  unsigned char *ansp = *namep;
+
+  while(1)
+    {
+      unsigned int label_type;
+      
+      if (!CHECK_LEN(header, ansp, plen, 1))
+       return 0;
+      
+      label_type = (*ansp) & 0xc0;
+
+      if (label_type == 0xc0)
+       {
+         /* pointer for compression. */
+         unsigned int offset;
+         int i;
+         unsigned char *p;
+         
+         if (!CHECK_LEN(header, ansp, plen, 2))
+           return 0;
+
+         offset = ((*ansp++) & 0x3f) << 8;
+         offset |= *ansp++;
+
+         p = offset + (unsigned char *)header;
+         
+         for (i = 0; i < rr_count; i++)
+           if (p < rrs[i])
+             break;
+           else
+             if (i & 1)
+               offset -= rrs[i] - rrs[i-1];
+
+         /* does the pointer end up in an elided RR? */
+         if (i & 1)
+           return 0;
+
+         /* No, scale the pointer */
+         if (fixup)
+           {
+             ansp -= 2;
+             *ansp++ = (offset >> 8) | 0xc0;
+             *ansp++ = offset & 0xff;
+           }
+         break;
+       }
+      else if (label_type == 0x80)
+       return 0; /* reserved */
+      else if (label_type == 0x40)
+       {
+         /* Extended label type */
+         unsigned int count;
+         
+         if (!CHECK_LEN(header, ansp, plen, 2))
+           return 0;
+         
+         if (((*ansp++) & 0x3f) != 1)
+           return 0; /* we only understand bitstrings */
+         
+         count = *(ansp++); /* Bits in bitstring */
+         
+         if (count == 0) /* count == 0 means 256 bits */
+           ansp += 32;
+         else
+           ansp += ((count-1)>>3)+1;
+       }
+      else
+       { /* label type == 0 Bottom six bits is length */
+         unsigned int len = (*ansp++) & 0x3f;
+         
+         if (!ADD_RDLEN(header, ansp, plen, len))
+           return 0;
+
+         if (len == 0)
+           break; /* zero length label marks the end. */
+       }
+    }
+
+  *namep = ansp;
+
+  return 1;
+}
+
+/* Go through RRs and check or fixup the domain names contained within */
+static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
+{
+  int i, j, type, class, rdlen;
+  unsigned char *pp;
+  
+  for (i = 0; i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount); i++)
+    {
+      pp = p;
+
+      if (!(p = skip_name(p, header, plen, 10)))
+       return 0;
+      
+      GETSHORT(type, p); 
+      GETSHORT(class, p);
+      p += 4; /* TTL */
+      GETSHORT(rdlen, p);
+
+      /* If this RR is to be elided, don't fix up its contents */
+      for (j = 0; j < rr_count; j += 2)
+       if (rrs[j] == pp)
+         break;
+
+      if (j >= rr_count)
+       {
+         /* fixup name of RR */
+         if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
+           return 0;
+         
+         if (class == C_IN)
+           {
+             u16 *d;
+             for (pp = p, d = rrfilter_desc(type); *d != (u16)-1; d++)
+               {
+                 if (*d != 0)
+                   pp += *d;
+                 else if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
+                   return 0;
+               }
+           }
+       }
+      
+      if (!ADD_RDLEN(header, p, plen, rdlen))
+       return 0;
+    }
+  
+  return 1;
+}
+       
+
+/* mode is 0 to remove EDNS0, 1 to filter DNSSEC RRs */
+size_t rrfilter(struct dns_header *header, size_t plen, int mode)
+{
+  static unsigned char **rrs;
+  static int rr_sz = 0;
+
+  unsigned char *p = (unsigned char *)(header+1);
+  int i, rdlen, qtype, qclass, rr_found, chop_an, chop_ns, chop_ar;
+
+  if (ntohs(header->qdcount) != 1 ||
+      !(p = skip_name(p, header, plen, 4)))
+    return plen;
+  
+  GETSHORT(qtype, p);
+  GETSHORT(qclass, p);
+
+  /* First pass, find pointers to start and end of all the records we wish to elide:
+     records added for DNSSEC, unless explicitly queried for */
+  for (rr_found = 0, chop_ns = 0, chop_an = 0, chop_ar = 0, i = 0; 
+       i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount);
+       i++)
+    {
+      unsigned char *pstart = p;
+      int type, class;
+
+      if (!(p = skip_name(p, header, plen, 10)))
+       return plen;
+      
+      GETSHORT(type, p); 
+      GETSHORT(class, p);
+      p += 4; /* TTL */
+      GETSHORT(rdlen, p);
+        
+      if (!ADD_RDLEN(header, p, plen, rdlen))
+       return plen;
+
+      /* Don't remove the answer. */
+      if (i < ntohs(header->ancount) && type == qtype && class == qclass)
+       continue;
+      
+      if (mode == 0) /* EDNS */
+       {
+         /* EDNS mode, remove T_OPT from additional section only */
+         if (i < (ntohs(header->nscount) + ntohs(header->ancount)) || type != T_OPT)
+           continue;
+       }
+      else if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
+       /* DNSSEC mode, remove SIGs and NSECs from all three sections. */
+       continue;
+      
+      
+      if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
+       return plen; 
+      
+      rrs[rr_found++] = pstart;
+      rrs[rr_found++] = p;
+      
+      if (i < ntohs(header->ancount))
+       chop_an++;
+      else if (i < (ntohs(header->nscount) + ntohs(header->ancount)))
+       chop_ns++;
+      else
+       chop_ar++;
+    }
+  
+  /* Nothing to do. */
+  if (rr_found == 0)
+    return plen;
+
+  /* Second pass, look for pointers in names in the records we're keeping and make sure they don't
+     point to records we're going to elide. This is theoretically possible, but unlikely. If
+     it happens, we give up and leave the answer unchanged. */
+  p = (unsigned char *)(header+1);
+  
+  /* question first */
+  if (!check_name(&p, header, plen, 0, rrs, rr_found))
+    return plen;
+  p += 4; /* qclass, qtype */
+  
+  /* Now answers and NS */
+  if (!check_rrs(p, header, plen, 0, rrs, rr_found))
+    return plen;
+  
+  /* Third pass, actually fix up pointers in the records */
+  p = (unsigned char *)(header+1);
+  
+  check_name(&p, header, plen, 1, rrs, rr_found);
+  p += 4; /* qclass, qtype */
+  
+  check_rrs(p, header, plen, 1, rrs, rr_found);
+
+  /* Fourth pass, elide records */
+  for (p = rrs[0], i = 1; i < rr_found; i += 2)
+    {
+      unsigned char *start = rrs[i];
+      unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)header) + plen;
+      
+      memmove(p, start, end-start);
+      p += end-start;
+    }
+     
+  plen = p - (unsigned char *)header;
+  header->ancount = htons(ntohs(header->ancount) - chop_an);
+  header->nscount = htons(ntohs(header->nscount) - chop_ns);
+  header->arcount = htons(ntohs(header->arcount) - chop_ar);
+
+  return plen;
+}
+
+/* This is used in the DNSSEC code too, hence it's exported */
+u16 *rrfilter_desc(int type)
+{
+  /* List of RRtypes which include domains in the data.
+     0 -> domain
+     integer -> no. of plain bytes
+     -1 -> end
+
+     zero is not a valid RRtype, so the final entry is returned for
+     anything which needs no mangling.
+  */
+  
+  static u16 rr_desc[] = 
+    { 
+      T_NS, 0, -1, 
+      T_MD, 0, -1,
+      T_MF, 0, -1,
+      T_CNAME, 0, -1,
+      T_SOA, 0, 0, -1,
+      T_MB, 0, -1,
+      T_MG, 0, -1,
+      T_MR, 0, -1,
+      T_PTR, 0, -1,
+      T_MINFO, 0, 0, -1,
+      T_MX, 2, 0, -1,
+      T_RP, 0, 0, -1,
+      T_AFSDB, 2, 0, -1,
+      T_RT, 2, 0, -1,
+      T_SIG, 18, 0, -1,
+      T_PX, 2, 0, 0, -1,
+      T_NXT, 0, -1,
+      T_KX, 2, 0, -1,
+      T_SRV, 6, 0, -1,
+      T_DNAME, 0, -1,
+      0, -1 /* wildcard/catchall */
+    }; 
+  
+  u16 *p = rr_desc;
+  
+  while (*p != type && *p != 0)
+    while (*p++ != (u16)-1);
+
+  return p+1;
+}
+
+int expand_workspace(unsigned char ***wkspc, int *szp, int new)
+{
+  unsigned char **p;
+  int old = *szp;
+
+  if (old >= new+1)
+    return 1;
+
+  if (new >= 100)
+    return 0;
+
+  new += 5;
+  
+  if (!(p = whine_malloc(new * sizeof(unsigned char *))))
+    return 0;  
+  
+  if (old != 0 && *wkspc)
+    {
+      memcpy(p, *wkspc, old * sizeof(unsigned char *));
+      free(*wkspc);
+    }
+  
+  *wkspc = p;
+  *szp = new;
+
+  return 1;
+}
index abaad53..13317d8 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -94,7 +94,7 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
            slaac->backoff = 1;
            slaac->addr = addr;
            /* Do RA's to prod it */
-           ra_start_unsolicted(now, context);
+           ra_start_unsolicited(now, context);
          }
        
        if (slaac)
@@ -146,8 +146,11 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
            struct ping_packet *ping;
            struct sockaddr_in6 addr;
  
-           save_counter(0);
-           ping = expand(sizeof(struct ping_packet));
+           reset_counter();
+
+           if (!(ping = expand(sizeof(struct ping_packet))))
+             continue;
+
            ping->type = ICMP6_ECHO_REQUEST;
            ping->code = 0;
            ping->identifier = ping_id;
@@ -161,7 +164,7 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
            addr.sin6_port = htons(IPPROTO_ICMPV6);
            addr.sin6_addr = slaac->addr;
            
-           if (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0,
+           if (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(-1), 0,
                       (struct sockaddr *)&addr,  sizeof(addr)) == -1 &&
                errno == EHOSTUNREACH)
              slaac->ping_time = 0; /* Give up */ 
index aae1252..a3382ce 100644 (file)
@@ -20,9 +20,7 @@
 
 #if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK)
 
-#ifndef __FreeBSD__
 #include <string.h>
-#endif
 
 #include <sys/types.h>
 #include <sys/ioctl.h>
@@ -53,52 +51,6 @@ static char *pfr_strerror(int errnum)
     }
 }
 
-static int pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
-{
-  struct pfioc_table io;
-  
-  if (size < 0 || (size && tbl == NULL)) 
-    {
-      errno = EINVAL;
-      return (-1);
-    }
-  bzero(&io, sizeof io);
-  io.pfrio_flags = flags;
-  io.pfrio_buffer = tbl;
-  io.pfrio_esize = sizeof(*tbl);
-  io.pfrio_size = size;
-  if (ioctl(dev, DIOCRADDTABLES, &io))
-    return (-1);
-  if (nadd != NULL)
-    *nadd = io.pfrio_nadd;
-  return (0);
-}
-
-static int fill_addr(const struct all_addr *ipaddr, int flags, struct pfr_addr* addr) {
-  if ( !addr || !ipaddr)
-    {
-      my_syslog(LOG_ERR, _("error: fill_addr missused"));
-      return -1;
-    }
-  bzero(addr, sizeof(*addr));
-#ifdef HAVE_IPV6
-  if (flags & F_IPV6) 
-    {
-      addr->pfra_af = AF_INET6;
-      addr->pfra_net = 0x80;
-      memcpy(&(addr->pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
-    } 
-  else 
-#endif
-    {
-      addr->pfra_af = AF_INET;
-      addr->pfra_net = 0x20;
-      addr->pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
-    }
-  return 1;
-}
-
-/*****************************************************************************/
 
 void ipset_init(void) 
 {
@@ -111,14 +63,13 @@ void ipset_init(void)
 }
 
 int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
-                     int flags, int remove)
+                int flags, int remove)
 {
   struct pfr_addr addr;
   struct pfioc_table io;
   struct pfr_table table;
-  int n = 0, rc = 0;
 
-  if ( dev == -1 
+  if (dev == -1
     {
       my_syslog(LOG_ERR, _("warning: no opened pf devices %s"), pf_device);
       return -1;
@@ -126,31 +77,52 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
 
   bzero(&table, sizeof(struct pfr_table));
   table.pfrt_flags |= PFR_TFLAG_PERSIST;
-  if ( strlen(setname) >= PF_TABLE_NAME_SIZE )
+  if (strlen(setname) >= PF_TABLE_NAME_SIZE)
     {
       my_syslog(LOG_ERR, _("error: cannot use table name %s"), setname);
       errno = ENAMETOOLONG;
       return -1;
     }
   
-  if ( strlcpy(table.pfrt_name, setname,
-               sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name)) 
+  if (strlcpy(table.pfrt_name, setname,
+             sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name)) 
     {
       my_syslog(LOG_ERR, _("error: cannot strlcpy table name %s"), setname);
       return -1;
     }
   
-  if ((rc = pfr_add_tables(&table, 1, &n, 0))) 
+  bzero(&io, sizeof io);
+  io.pfrio_flags = 0;
+  io.pfrio_buffer = &table;
+  io.pfrio_esize = sizeof(table);
+  io.pfrio_size = 1;
+  if (ioctl(dev, DIOCRADDTABLES, &io))
     {
-      my_syslog(LOG_WARNING, _("warning: pfr_add_tables: %s(%d)"),
-               pfr_strerror(errno),rc);
+      my_syslog(LOG_WARNING, _("IPset: error:%s"), pfr_strerror(errno));
+      
       return -1;
     }
+  
   table.pfrt_flags &= ~PFR_TFLAG_PERSIST;
-  if (n)
+  if (io.pfrio_nadd)
     my_syslog(LOG_INFO, _("info: table created"));
-  
-  fill_addr(ipaddr,flags,&addr);
+  bzero(&addr, sizeof(addr));
+#ifdef HAVE_IPV6
+  if (flags & F_IPV6) 
+    {
+      addr.pfra_af = AF_INET6;
+      addr.pfra_net = 0x80;
+      memcpy(&(addr.pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
+    } 
+  else 
+#endif
+    {
+      addr.pfra_af = AF_INET;
+      addr.pfra_net = 0x20;
+      addr.pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
+    }
+
   bzero(&io, sizeof(io));
   io.pfrio_flags = 0;
   io.pfrio_table = table;
index 350a587..bccca69 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -20,7 +20,7 @@
 
 static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
 static void free_transfer(struct tftp_transfer *transfer);
-static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
+static ssize_t tftp_err(int err, char *packet, char *message, char *file);
 static ssize_t tftp_err_oops(char *packet, char *file);
 static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
 static char *next(char **p, char *end);
@@ -103,8 +103,10 @@ void tftp_request(struct listener *listen, time_t now)
       if (listen->iface)
        {
          addr = listen->iface->addr;
-         mtu = listen->iface->mtu;
          name = listen->iface->name;
+         mtu = listen->iface->mtu;
+         if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu)
+           mtu = daemon->tftp_mtu;
        }
       else
        {
@@ -234,9 +236,17 @@ void tftp_request(struct listener *listen, time_t now)
 
       strncpy(ifr.ifr_name, name, IF_NAMESIZE);
       if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
-       mtu = ifr.ifr_mtu;      
+       {
+         mtu = ifr.ifr_mtu;  
+         if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu)
+           mtu = daemon->tftp_mtu;    
+       }
     }
 
+  /* Failed to get interface mtu - can use configured value. */
+  if (mtu == 0)
+    mtu = daemon->tftp_mtu;
+
   if (name)
     {
       /* check for per-interface prefix */ 
@@ -336,14 +346,15 @@ void tftp_request(struct listener *listen, time_t now)
            {
              if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
                {
+                 /* 32 bytes for IP, UDP and TFTP headers, 52 bytes for IPv6 */
+                 int overhead = (listen->family == AF_INET) ? 32 : 52;
                  transfer->blocksize = atoi(opt);
                  if (transfer->blocksize < 1)
                    transfer->blocksize = 1;
                  if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
                    transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
-                 /* 32 bytes for IP, UDP and TFTP headers */
-                 if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32)
-                   transfer->blocksize = (unsigned)mtu - 32;
+                 if (mtu != 0 && transfer->blocksize > (unsigned)mtu - overhead)
+                   transfer->blocksize = (unsigned)mtu - overhead;
                  transfer->opt_blocksize = 1;
                  transfer->block = 0;
                }
@@ -371,7 +382,7 @@ void tftp_request(struct listener *listen, time_t now)
          if (prefix[strlen(prefix)-1] != '/')
            strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
 
-         if (option_bool(OPT_TFTP_APREF))
+         if (option_bool(OPT_TFTP_APREF_IP))
            {
              size_t oldlen = strlen(daemon->namebuff);
              struct stat statbuf;
@@ -383,7 +394,40 @@ void tftp_request(struct listener *listen, time_t now)
              if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
                daemon->namebuff[oldlen] = 0;
            }
-               
+         
+         if (option_bool(OPT_TFTP_APREF_MAC))
+           {
+             unsigned char *macaddr = NULL;
+             unsigned char macbuf[DHCP_CHADDR_MAX];
+             
+#ifdef HAVE_DHCP
+             if (daemon->dhcp && peer.sa.sa_family == AF_INET)
+               {
+                 /* Check if the client IP is in our lease database */
+                 struct dhcp_lease *lease = lease_find_by_addr(peer.in.sin_addr);
+                 if (lease && lease->hwaddr_type == ARPHRD_ETHER && lease->hwaddr_len == ETHER_ADDR_LEN)
+                   macaddr = lease->hwaddr;
+               }
+#endif
+             
+             /* If no luck, try to find in ARP table. This only works if client is in same (V)LAN */
+             if (!macaddr && find_mac(&peer, macbuf, 1, now) > 0)
+               macaddr = macbuf;
+             
+             if (macaddr)
+               {
+                 size_t oldlen = strlen(daemon->namebuff);
+                 struct stat statbuf;
+
+                 snprintf(daemon->namebuff + oldlen, (MAXDNAME-1) - oldlen, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x/",
+                          macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
+                 
+                 /* remove unique-directory if it doesn't exist */
+                 if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
+                   daemon->namebuff[oldlen] = 0;
+               }
+           }
+         
          /* Absolute pathnames OK if they match prefix */
          if (filename[0] == '/')
            {
@@ -396,7 +440,7 @@ void tftp_request(struct listener *listen, time_t now)
       else if (filename[0] == '/')
        daemon->namebuff[0] = 0;
       strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
-
+      
       /* check permissions and open file */
       if ((transfer->file = check_tftp_fileperm(&len, prefix)))
        {
@@ -459,7 +503,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
   else if (option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid)
     goto perm;
       
-  /* If we're doing many tranfers from the same file, only 
+  /* If we're doing many transfers from the same file, only 
      open it once this saves lots of file descriptors 
      when mass-booting a big cluster, for instance. 
      Be conservative and only share when inode and name match
@@ -641,20 +685,24 @@ static void sanitise(char *buf)
 
 }
 
+#define MAXMESSAGE 500 /* limit to make packet < 512 bytes and definitely smaller than buffer */ 
 static ssize_t tftp_err(int err, char *packet, char *message, char *file)
 {
   struct errmess {
     unsigned short op, err;
     char message[];
   } *mess = (struct errmess *)packet;
-  ssize_t ret = 4;
+  ssize_t len, ret = 4;
   char *errstr = strerror(errno);
   
+  memset(packet, 0, daemon->packet_buff_sz);
   sanitise(file);
-
+  
   mess->op = htons(OP_ERR);
   mess->err = htons(err);
-  ret += (snprintf(mess->message, 500,  message, file, errstr) + 1);
+  len = snprintf(mess->message, MAXMESSAGE,  message, file, errstr);
+  ret += (len < MAXMESSAGE) ? len + 1 : MAXMESSAGE; /* include terminating zero */
+  
   my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message);
   
   return  ret;
@@ -670,6 +718,8 @@ static ssize_t tftp_err_oops(char *packet, char *file)
 /* return -1 for error, zero for done. */
 static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
 {
+  memset(packet, 0, daemon->packet_buff_sz);
+  
   if (transfer->block == 0)
     {
       /* send OACK */
@@ -684,7 +734,7 @@ static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
       if (transfer->opt_blocksize)
        {
          p += (sprintf(p, "blksize") + 1);
-         p += (sprintf(p, "%d", transfer->blocksize) + 1);
+         p += (sprintf(p, "%u", transfer->blocksize) + 1);
        }
       if (transfer->opt_transize)
        {
index 469eaed..532bc16 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2018 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
@@ -24,7 +24,9 @@
 #include <sys/times.h>
 #endif
 
-#if defined(LOCALEDIR) || defined(HAVE_IDN)
+#if defined(HAVE_LIBIDN2)
+#include <idn2.h>
+#elif defined(HAVE_IDN)
 #include <idna.h>
 #endif
 
@@ -109,6 +111,7 @@ u64 rand64(void)
   return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
 }
 
+/* returns 2 if names is OK but contains one or more underscores */
 static int check_name(char *in)
 {
   /* remove trailing . 
@@ -116,6 +119,7 @@ static int check_name(char *in)
   size_t dotgap = 0, l = strlen(in);
   char c;
   int nowhite = 0;
+  int hasuscore = 0;
   
   if (l == 0 || l > MAXDNAME) return 0;
   
@@ -134,18 +138,22 @@ static int check_name(char *in)
       else if (isascii((unsigned char)c) && iscntrl((unsigned char)c)) 
        /* iscntrl only gives expected results for ascii */
        return 0;
-#if !defined(LOCALEDIR) && !defined(HAVE_IDN)
+#if !defined(HAVE_IDN) && !defined(HAVE_LIBIDN2)
       else if (!isascii((unsigned char)c))
        return 0;
 #endif
       else if (c != ' ')
-       nowhite = 1;
+       {
+         nowhite = 1;
+         if (c == '_')
+           hasuscore = 1;
+       }
     }
 
   if (!nowhite)
     return 0;
 
-  return 1;
+  return hasuscore ? 2 : 1;
 }
 
 /* Hostnames have a more limited valid charset than domain names
@@ -184,49 +192,70 @@ int legal_hostname(char *name)
 char *canonicalise(char *in, int *nomem)
 {
   char *ret = NULL;
-#if defined(LOCALEDIR) || defined(HAVE_IDN)
   int rc;
-#endif
-
+  
   if (nomem)
     *nomem = 0;
   
-  if (!check_name(in))
+  if (!(rc = check_name(in)))
     return NULL;
   
-#if defined(LOCALEDIR) || defined(HAVE_IDN)
-  if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS)
+#if defined(HAVE_LIBIDN2) && (!defined(IDN2_VERSION_NUMBER) || IDN2_VERSION_NUMBER < 0x02000003)
+  /* older libidn2 strips underscores, so don't do IDN processing
+     if the name has an underscore (check_name() returned 2) */
+  if (rc != 2)
+#endif
+#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2)
     {
-      if (ret)
-       free(ret);
-
-      if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
+#  ifdef HAVE_LIBIDN2
+      rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
+      if (rc == IDN2_DISALLOWED)
+       rc = idn2_to_ascii_lz(in, &ret, IDN2_TRANSITIONAL);
+#  else
+      rc = idna_to_ascii_lz(in, &ret, 0);
+#  endif
+      if (rc != IDNA_SUCCESS)
        {
-         my_syslog(LOG_ERR, _("failed to allocate memory"));
-         *nomem = 1;
+         if (ret)
+           free(ret);
+         
+         if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
+           {
+             my_syslog(LOG_ERR, _("failed to allocate memory"));
+             *nomem = 1;
+           }
+         
+         return NULL;
        }
-    
-      return NULL;
+      
+      return ret;
     }
-#else
+#endif
+  
   if ((ret = whine_malloc(strlen(in)+1)))
     strcpy(ret, in);
   else if (nomem)
     *nomem = 1;    
-#endif
 
   return ret;
 }
 
-unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
+unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
 {
   int j;
   
   while (sval && *sval)
     {
       unsigned char *cp = p++;
+
+      if (limit && p > (unsigned char*)limit)
+        return NULL;
+
       for (j = 0; *sval && (*sval != '.'); sval++, j++)
        {
+          if (limit && p + 1 > (unsigned char*)limit)
+            return NULL;
+
 #ifdef HAVE_DNSSEC
          if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
            *p++ = (*(++sval))-1;
@@ -234,21 +263,23 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
 #endif         
            *p++ = *sval;
        }
+      
       *cp  = j;
       if (*sval)
        sval++;
     }
+  
   return p;
 }
 
 /* for use during startup */
 void *safe_malloc(size_t size)
 {
-  void *ret = malloc(size);
+  void *ret = calloc(1, size);
   
   if (!ret)
     die(_("could not get memory"), NULL, EC_NOMEM);
-     
+      
   return ret;
 }    
 
@@ -262,11 +293,11 @@ void safe_pipe(int *fd, int read_noblock)
 
 void *whine_malloc(size_t size)
 {
-  void *ret = malloc(size);
+  void *ret = calloc(1, size);
 
   if (!ret)
     my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);
-
+  
   return ret;
 }
 
@@ -323,7 +354,7 @@ int hostname_isequal(const char *a, const char *b)
   
   return 1;
 }
-    
+
 time_t dnsmasq_time(void)
 {
 #ifdef HAVE_BROKEN_RTC
@@ -373,7 +404,7 @@ int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)
   return 0;
 }
 
-/* return least signigicant 64 bits if IPv6 address */
+/* return least significant 64 bits if IPv6 address */
 u64 addr6part(struct in6_addr *addr)
 {
   int i;
@@ -439,13 +470,13 @@ void prettyprint_time(char *buf, unsigned int t)
     {
       unsigned int x, p = 0;
        if ((x = t/86400))
-       p += sprintf(&buf[p], "%dd", x);
+       p += sprintf(&buf[p], "%ud", x);
        if ((x = (t/3600)%24))
-       p += sprintf(&buf[p], "%dh", x);
+       p += sprintf(&buf[p], "%uh", x);
       if ((x = (t/60)%60))
-       p += sprintf(&buf[p], "%dm", x);
+       p += sprintf(&buf[p], "%um", x);
       if ((x = t%60))
-       p += sprintf(&buf[p], "%ds", x);
+       p += sprintf(&buf[p], "%us", x);
     }
 }
 
@@ -497,9 +528,14 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
                          sav = in[(j+1)*2];
                          in[(j+1)*2] = 0;
                        }
+                     /* checks above allow mix of hexdigit and *, which
+                        is illegal. */
+                     if (strchr(&in[j*2], '*'))
+                       return -1;
                      out[i] = strtol(&in[j*2], NULL, 16);
                      mask = mask << 1;
-                     i++;
+                     if (++i == maxlen)
+                       break; 
                      if (j < bytes - 1)
                        in[(j+1)*2] = sav;
                    }
index afda518..6f807cf 100644 (file)
@@ -1,9 +1,10 @@
-# The root DNSSEC trust anchor, valid as at 30/01/2014
+# The root DNSSEC trust anchor, valid as at 10/02/2017
 
 # Note that this is a DS record (ie a hash of the root Zone Signing Key) 
 # If was downloaded from https://data.iana.org/root-anchors/root-anchors.xml
 
 trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
+trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D