Compare commits

...

62 Commits

Author SHA1 Message Date
Simon Kelley
b692f23466 Fix DNS failure of cachesize set to zero. 2014-05-09 10:29:43 +01:00
Simon Kelley
8aa999ef69 Debian packaging fixes. 2014-05-04 21:45:26 +01:00
Conrad Kostecki
20b215f293 Update German translation. 2014-05-04 20:43:49 +01:00
Simon Kelley
e6096e643a Another filter_rrsigs fix. 2014-05-01 18:19:12 +01:00
Simon Kelley
8938ae05ac Get packet size right when removing pseudoheader. 2014-05-01 17:46:25 +01:00
Simon Kelley
9d1b22aac2 Fix DNSSEC validation of ANY queries. 2014-04-29 13:02:41 +01:00
Simon Kelley
1fc02680af Do SERVFAIL, therefore continue when searching for DS in TCP path too. 2014-04-29 12:30:18 +01:00
Simon Kelley
4872aa747b Handle SERVFAIL replies when looking for proven-nonexistence of DS. 2014-04-26 22:13:31 +01:00
Simon Kelley
50f86ce8e4 Need to fixup records in the additional section when removing DNSSEC stuff. 2014-04-24 17:59:58 +01:00
Simon Kelley
7e22cf28f8 Update doc.html - was positively antediluvian. 2014-04-24 12:05:33 +01:00
Simon Kelley
3b1b3e9d50 CHANGELOG update for 2.70 release. 2014-04-23 15:46:05 +01:00
Simon Kelley
ab72091de2 Bump Debian version. 2014-04-23 15:14:48 +01:00
Matt Comben
66f57867d8 Typo. 2014-04-23 12:28:04 +01:00
Simon Kelley
6375838445 Fix crash on TCP DNS request when DNSSEC not enabled. 2014-04-16 22:20:55 +01:00
Simon Kelley
82a14af5e7 Ensure request name in buffer for ipset lookup. 2014-04-13 20:48:57 +01:00
Simon Kelley
97dce08ed7 Add donate button to doc.html. 2014-04-11 19:05:54 +01:00
Simon Kelley
198d940af6 Update CHANGELOG/release-notes. 2014-04-09 20:36:53 +01:00
Lutz Preßler
1d7e0a36e3 ipv6.arpa -> ip6.arpa 2014-04-07 22:06:23 +01:00
Simon Kelley
10068600f8 Fix NXDOMAIN RCODE in auth PTR replies. 2014-04-03 21:16:40 +01:00
Simon Kelley
b7639d5815 Fix ipsets logging patch. 2014-03-29 09:20:07 +00:00
Wang Jian
49752b90d5 Log IPSET actions. 2014-03-28 20:52:47 +00:00
Simon Kelley
e98bd52e25 Add --dnssec-no-timecheck 2014-03-28 20:41:23 +00:00
Simon Kelley
8a8bbad0cf Ensure ->sentto is valid for DNSSEC forwards. Otherwise retries SEGV. 2014-03-27 22:02:17 +00:00
Simon Kelley
fec216df32 Cache stats availble in CHAOS .bind domain. 2014-03-27 20:54:34 +00:00
Simon Kelley
4e1fe44428 Terminate DS-search when reaching the root via cache entries. 2014-03-26 12:24:19 +00:00
Simon Kelley
51967f9807 SERVFAIL is an expected error return, don't try all servers. 2014-03-25 21:07:00 +00:00
Tomas Hozza
b37f8b99ae Handle failure of hash_questions() 2014-03-25 20:52:28 +00:00
Tomas Hozza
fc2833f172 Memory leak in error path. 2014-03-25 20:43:21 +00:00
Simon Kelley
490f90758d Reorder sanity checks on UDP packet reception, to cope with failed recvfrom() 2014-03-24 22:04:42 +00:00
Simon Kelley
56618c31f6 Add dnssec-check-unsigned to example config file. 2014-03-24 21:13:49 +00:00
Simon Kelley
604f7598c2 CHANGELOG update. 2014-03-22 19:33:43 +00:00
Simon Kelley
2a7a2b84ec Ignore DNS queries from port 0: http://www.ietf.org/mail-archive/web/dnsop/current/msg11441.html 2014-03-22 19:18:06 +00:00
Andy
3e21a1a6fa Tidy uid defines. 2014-03-22 19:10:07 +00:00
Simon Kelley
2b29191e7c Fix DNSSEC crash retrying to IPv6 server. 2014-03-21 11:13:55 +00:00
Simon Kelley
03431d6373 Initialise uid when creating CNAME cache record. 2014-03-20 16:25:43 +00:00
Simon Kelley
cc1a29e250 Make --quiet-dhcp apply to DHCPDISCOVER when client ignored. 2014-03-20 15:47:18 +00:00
Moritz Warning
e62e9b6187 Manpage typos. 2014-03-20 15:32:22 +00:00
Simon Kelley
19c51cfa49 Tidy and fix cache->uid handling.
Some CNAMES left the value of ->uid undefined.

Since there are now special values if this, for CNAMES
to interface names, that could cause a crash
if the undefined value hit the special value.

Also ensure that the special value can't arise
when the uid is encoding the source of an F_CONFIG
record, in case there's a CNAME to it.
2014-03-18 22:38:30 +00:00
Andy
d5082158ee Ensure next_uid() can never return 0. 2014-03-17 19:50:29 +00:00
Simon Kelley
3f7483e816 Handle integer overflow in uid counter. Fixes rare crashes in cache code. 2014-03-16 22:56:58 +00:00
Simon Kelley
0c8584eabc Warn about non-local queries once only for UDP. 2014-03-12 20:12:56 +00:00
Simon Kelley
f00690f93e Typo 2014-03-12 20:07:12 +00:00
Simon Kelley
89b12ed35b OPT_LOCAL_SERVICE needs up-to-date interface list too. 2014-03-06 13:27:57 +00:00
Simon Kelley
1a9a3489ec Set --local-service in Debian package startup. 2014-03-05 15:01:08 +00:00
Simon Kelley
c8a80487cd --local-service. Default protection from DNS amplification attacks. 2014-03-05 14:29:54 +00:00
Simon Kelley
4ea8e80dd9 Add --static to pkg-config command when appropriate. 2014-03-05 11:01:23 +00:00
Simon Kelley
c07d30dcb1 Compiler warning. 2014-03-03 14:19:19 +00:00
Simon Kelley
d588ab54d4 Man page updates for DNSSEC. 2014-03-02 14:30:05 +00:00
Simon Kelley
f8b422a7b6 KEYBLOCK LEN better as a multiple of 8. 2014-03-02 12:46:51 +00:00
Simon Kelley
29fe922b14 Can have local DS records (trust anchors). 2014-03-01 22:53:57 +00:00
Simon Kelley
8707019237 Mass edit of INSECURE->BOGUS returns for server failure/bad input. 2014-03-01 20:48:24 +00:00
Simon Kelley
d1fbb77e0f Don't cache secure replies which we've messsed with. 2014-03-01 20:08:58 +00:00
Simon Kelley
1fbe4d2f5f Tweak tuning params. 2014-03-01 20:03:47 +00:00
Simon Kelley
0575610fa1 Handle replies with no answers and no NS in validate_reply. 2014-03-01 18:07:57 +00:00
Simon Kelley
e3f1455850 Don't free blockdata for negative DS cache entries. 2014-03-01 17:58:28 +00:00
Simon Kelley
bd9b3cf55b Fix off-by-one overwrite. 2014-03-01 16:12:28 +00:00
Simon Kelley
14db4212ab Tidy. 2014-03-01 15:35:50 +00:00
Simon Kelley
00a5b5d477 Check that unsigned replies come from unsigned zones if --dnssec-check-unsigned set. 2014-02-28 18:10:55 +00:00
Simon Kelley
b8eac19177 Negative caching for DS records. 2014-02-27 14:30:03 +00:00
Simon Kelley
b47b04c846 Return INSECURE when validation fails with proved non-existent DS. 2014-02-25 23:13:28 +00:00
Simon Kelley
613ad15d02 Strip DNSSEC RRs when query doesn't have DO bit set. 2014-02-25 23:02:28 +00:00
Simon Kelley
24187530fb Speeling. 2014-02-24 21:46:44 +00:00
22 changed files with 1917 additions and 710 deletions

View File

@@ -1,3 +1,30 @@
version 2.71
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.
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.
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 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
@@ -28,9 +55,9 @@ version 2.69
make dnsmasq COPTS='-DHAVE_DNSSEC -DHAVE_DNSSEC_STATIC'
which bloats the dnsmasq binary to over a megabyte, but
saves the size of the shared libraries which are five
times that size.
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
@@ -56,6 +83,36 @@ version 2.69
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
@@ -67,7 +124,27 @@ version 2.69
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

View File

@@ -14,8 +14,11 @@ if grep "^\#[[:space:]]*define[[:space:]]*$search" config.h >/dev/null 2>&1 || \
if [ $op = "--copy" ]; then
pkg="$*"
elif grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
pkg=`$pkg --static $op $*`
else
pkg=`$pkg $op $*`
pkg=`$pkg $op $*`
fi
if grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \

22
debian/changelog vendored
View File

@@ -1,6 +1,28 @@
dnsmasq (2.70-2) unstable; urgency=low
* Ensure daemon not stared if dnsmasq package has been removed,
even if dnsmasq-base is still installed. (closes: #746941)
* Tidy cruft in initscript. (closes: #746940)
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 04 May 2014 21:34:11 +0000
dnsmasq (2.70-1) unstable; urgency=low
* New upstream.
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 23 Apr 2014 15:14:42 +0000
dnsmasq (2.69-1) unstable; urgency=low
* New upstream.
* Set --local-service. (closes: #732610)
This tells dnsmasq to ignore DNS requests that don't come
from a local network. It's automatically ignored if
--interface --except-interface, --listen-address or
--auth-server exist in the configuration, so for most
installations, it will have no effect, but for
otherwise-unconfigured installations, it stops dnsmasq
from being vulnerable to DNS-reflection attacks.
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 4 Feb 2014 16:28:12 +0000

2
debian/default vendored
View File

@@ -27,7 +27,7 @@ CONFIG_DIR=/etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new
# If the resolvconf package is installed, dnsmasq will use its output
# rather than the contents of /etc/resolv.conf to find upstream
# nameservers. Uncommenting this line inhibits this behaviour.
# Not that including a "resolv-file=<filename>" line in
# Note that including a "resolv-file=<filename>" line in
# /etc/dnsmasq.conf is not enough to override resolvconf if it is
# installed: the line below must be uncommented.
#IGNORE_RESOLVCONF=yes

17
debian/init vendored
View File

@@ -29,6 +29,12 @@ if [ -r /etc/default/locale ]; then
export LANG
fi
# /etc/dnsmasq.d/README is a non-conffile installed by the dnsmasq package.
# Should the dnsmasq package be removed, the following test ensures that
# the daemon is no longer started, even if the dnsmasq-base package is
# still in place.
test -e /etc/dnsmasq.d/README || exit 0
test -x $DAEMON || exit 0
# Provide skeleton LSB log functions for backports which don't have LSB functions.
@@ -90,6 +96,14 @@ if [ ! "$DNSMASQ_USER" ]; then
DNSMASQ_USER="dnsmasq"
fi
# This tells dnsmasq to ignore DNS requests that don't come from a local network.
# It's automatically ignored if --interface --except-interface, --listen-address
# or --auth-server exist in the configuration, so for most installations, it will
# have no effect, but for otherwise-unconfigured installations, it stops dnsmasq
# from being vulnerable to DNS-reflection attacks.
DNSMASQ_OPTS="$DNSMASQ_OPTS --local-service"
start()
{
# Return
@@ -144,9 +158,6 @@ stop()
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile /var/run/dnsmasq/$NAME.pid --name $NAME
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
return "$RETVAL"
}
stop_resolvconf()

View File

@@ -25,6 +25,14 @@
#conf-file=%%PREFIX%%/share/dnsmasq/trust-anchors.conf
#dnssec
# Replies which are not DNSSEC signed may be legitimate, because the domain
# is unsigned, or may be forgeries. Setting this option tells dnsmasq to
# check that an unsigned reply is OK, by finding a secure proof that a DS
# record somewhere between the root and the domain does not exist.
# The cost of setting this is that even queries in unsigned domains will need
# one or more extra DNS queries to verify.
#dnssec-check-unsigned
# Uncomment this to filter useless windows-originated DNS requests
# which can trigger dial-on-demand links needlessly.
# Note that (amongst other things) this blocks all SRV requests,

130
doc.html
View File

@@ -1,6 +1,6 @@
<HTML>
<HEAD>
<TITLE> Dnsmasq - a DNS forwarder for NAT firewalls.</TITLE>
<TITLE> Dnsmasq - network services for small networks.</TITLE>
<link rel="icon"
href="http://www.thekelleys.org.uk/dnsmasq/images/favicon.ico">
</HEAD>
@@ -11,82 +11,48 @@
<td align="middle" valign="middle"><h1>Dnsmasq</h1></td>
<td align="right" valign="middle"><img border="0" src="http://www.thekelleys.org.uk/dnsmasq/images/icon.png" /></td></tr>
</table>
Dnsmasq provides network infrastructure for small networks: DNS, DHCP, router advertisement and network boot. It is designed to be
lightweight and have a small footprint, suitable for resource constrained routers and firewalls. It has also been widely used
for tethering on smartphones and portable hotspots, and to support virtual networking in virtualisation frameworks.
Supported platforms include Linux (with glibc and uclibc), Android, *BSD, and Mac OS X. Dnsmasq is included in most
Linux distributions and the ports systems of FreeBSD, OpenBSD and NetBSD. Dnsmasq provides full IPv6 support.
Dnsmasq is a lightweight, easy to configure DNS forwarder and DHCP
server. It is designed to provide DNS and, optionally, DHCP, to a
small network. It can serve the names of local machines which are
not in the global DNS. The DHCP server integrates with the DNS
server and allows machines with DHCP-allocated addresses
to appear in the DNS with names configured either in each host or
in a central configuration file. Dnsmasq supports static and dynamic
DHCP leases and BOOTP/TFTP/PXE for network booting of diskless machines.
<P>
Dnsmasq is targeted at home networks using NAT and
connected to the internet via a modem, cable-modem or ADSL
connection but would be a good choice for any smallish network (up to
1000 clients is known to work) where low
resource use and ease of configuration are important.
<P>
Supported platforms include Linux (with glibc and uclibc), Android, *BSD,
Solaris and Mac OS X.
Dnsmasq is included in at least the following Linux distributions:
Gentoo, Debian, Slackware, Suse, Fedora,
Smoothwall, IP-Cop, floppyfw, Firebox, LEAF, Freesco, fli4l,
CoyoteLinux, Endian Firewall and
Clarkconnect. It is also available as FreeBSD, OpenBSD and NetBSD ports and is used in
Linksys wireless routers (dd-wrt, openwrt and the stock firmware) and the m0n0wall project.
<P>
Dnsmasq provides the following features:
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).
<DIR>
<LI>
The DNS configuration of machines behind the firewall is simple and
doesn't depend on the details of the ISP's dns servers
<LI>
Clients which try to do DNS lookups while a modem link to the
internet is down will time out immediately.
</LI>
<LI>
Dnsmasq will serve names from the /etc/hosts file on the firewall
machine: If the names of local machines are there, then they can all
be addressed without having to maintain /etc/hosts on each machine.
</LI>
<LI>
The integrated DHCP server supports static and dynamic DHCP leases and
multiple networks and IP ranges. It works across BOOTP relays and
supports DHCP options including RFC3397 DNS search lists.
Machines which are configured by DHCP have their names automatically
included in the DNS and the names can specified by each machine or
centrally by associating a name with a MAC address in the dnsmasq
config file.
</LI>
<LI>
Dnsmasq caches internet addresses (A records and AAAA records) and address-to-name
mappings (PTR records), reducing the load on upstream servers and
improving performance (especially on modem connections).
</LI>
<LI>
Dnsmasq can be configured to automatically pick up the addresses of
its upstream nameservers from ppp or dhcp configuration. It will
automatically reload this information if it changes. This facility
will be of particular interest to maintainers of Linux firewall
distributions since it allows dns configuration to be made automatic.
</LI>
<LI>
On IPv6-enabled boxes, dnsmasq can both talk to upstream servers via IPv6
and offer DNS service via IPv6. On dual-stack (IPv4 and IPv6) boxes it talks
both protocols and can even act as IPv6-to-IPv4 or IPv4-to-IPv6 forwarder.
</LI>
<LI>
Dnsmasq can be configured to send queries for certain domains to
upstream servers handling only those domains. This makes integration
with private DNS systems easy.
</LI>
<LI>
Dnsmasq supports MX and SRV records and can be configured to return MX records
for any or all local machines.
</LI>
<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.
<LI>Authoritative DNS mode allows local DNS names may be exported to zone in the global DNS. Dnsmasq acts as authoritative server for this zone, and also provides
zone transfer to secondaries for the zone, if required.</LI>
<LI>DNSSEC validation may be performed on DNS replies from upstream nameservers, providing security against spoofing and cache poisoning.</LI>
<LI>Specified sub-domains can be directed to their own upstream DNS servers, making VPN configuration easy.</LI>
<LI>Internationalised domain names are supported.
</DIR>
<P>
The DHCP subsystem supports DHCPv4, DHCPv6, BOOTP and PXE.
<DIR>
<LI> Both static and dynamic DHCP leases are supported, along with stateless mode in DHCPv6.</LI>
<LI> The PXE system is a full PXE server, supporting netboot menus and multiple architecture support. It
includes proxy-mode, where the PXE system co-operates with another DHCP server.</LI>
<LI> There is a built in read-only TFTP server to support netboot.</LI>
<LI> Machines which are configured by DHCP have their names automatically
included in the DNS and the names can specified by each machine or
centrally by associating a name with a MAC address or UID in the dnsmasq
configuration file.</LI>
</DIR>
<P>
The Router Advertisement subsystem provides basic autoconfiguration for IPv6 hosts. It can be used stand-alone or in conjunction with DHCPv6.
<DIR>
<LI> The M and O bits are configurable, to control hosts' use of DHCPv6.</LI>
<LI> Router advertisements can include the RDNSS option.</LI>
<LI> There is a mode which uses name information from DHCPv4 configuration to provide DNS entries
for autoconfigured IPv6 addresses which would otherwise be anonymous.</LI>
</DIR>
<P>
For extra compactness, unused features may be omitted at compile time.
<H2>Get code.</H2>
@@ -102,7 +68,7 @@ the repo, or get a copy using git protocol with the command
<PRE><TT>git clone git://thekelleys.org.uk/dnsmasq.git </TT></PRE>
<H2>License.</H2>
Dnsmasq is distributed under the GPL. See the file COPYING in the distribution
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.
<H2>Contact.</H2>
@@ -110,7 +76,21 @@ There is a dnsmasq mailing list at <A
HREF="http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss">
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss</A> which should be the
first location for queries, bugreports, suggestions etc.
Dnsmasq was written by Simon Kelley. You can contact me at <A
You can contact me at <A
HREF="mailto:simon@thekelleys.org.uk">simon@thekelleys.org.uk</A>.
<H2>Donations.</H2>
Dnsmasq is mainly written and maintained by Simon Kelley. For most of its life, dnsmasq has been a spare-time project.
These days I'm working on it as my main activity.
I don't have an employer or anyone who pays me regularly to work on dnsmasq. If you'd like to make
a contribution towards my expenses, please use the donation button below.
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="V3X9GVW5GX6DA">
<input type="image" src="https://www.paypalobjects.com/en_US/GB/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal The safer, easier way to pay online.">
<img alt="" border="0" src="https://www.paypalobjects.com/en_GB/i/scr/pixel.gif" width="1" height="1">
</form>
</BODY>

View File

@@ -208,6 +208,14 @@ resolve in the global DNS to a 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.
.TP
.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,
--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.
.TP
.B \-2, --no-dhcp-interface=<interface name>
Do not provide DHCP or TFTP on the specified interface, but do provide DNS service.
@@ -599,7 +607,15 @@ clients unable to do validation, use of the AD bit set by dnsmasq is useful, pro
the dnsmasq server and the client is trusted. Dnsmasq must be compiled with HAVE_DNSSEC enabled, and DNSSEC
trust anchors provided, see
.B --trust-anchor.
Because the DNSSEC validation process uses the cache, it is not permitted to reduce the cache size below the default when DNSSEC is enabled.
Because the DNSSEC validation process uses the cache, it is not
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
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
@@ -608,6 +624,27 @@ key(s) of the root zone,
but trust anchors for limited domains are also possible. The current
root-zone trust anchors may be donwloaded from https://data.iana.org/root-anchors/root-anchors.xml
.TP
.B --dnssec-check-unsigned
As a default, dnsmasq does not check that unsigned DNS replies are
legitimate: they are assumed to be valid and passed on (without the
"authentic data" bit set, of course). This does not protect against an
attacker forging unsigned replies for signed DNS zones, but it is
fast. If this flag is set, dnsmasq will check the zones of unsigned
replies, to ensure that unsigned replies are allowed in those
zones. The cost of this is more upstream queries and slower
performance. See also the warning about upstream servers in the
section on
.B --dnssec
.TP
.B --dnssec-no-timecheck
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
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.
.TP
.B --proxy-dnssec
Copy the DNSSEC Authenticated Data bit from upstream servers to downstream clients and cache it. This is an
alternative to having dnsmasq validate DNSSEC, but it depends on the security of the network between
@@ -638,7 +675,7 @@ Interface-name and address-literal subnet specifications may be used
freely in the same --auth-zone declaration.
The subnet(s) are also used to define in-addr.arpa and
ipv6.arpa domains which are served for reverse-DNS queries. If not
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.
For IPv4 subnets, the prefix length should be have the value 8, 16 or 24
unless you are familiar with RFC 2317 and have arranged the
@@ -745,7 +782,7 @@ or from /etc/ethers will be served. A static-only subnet with address
all zeros may be used as a "catch-all" address to enable replies to all
Information-request packets on a subnet which is provided with
stateless DHCPv6, ie
.B --dhcp=range=::,static
.B --dhcp-range=::,static
For IPv4, the <mode> may be
.B proxy
@@ -1725,12 +1762,22 @@ When it receives a SIGUSR1,
writes statistics to the system log. It writes the cache size,
the number of names which have had to removed from the cache before
they expired in order to make room for new names and the total number
of names that have been inserted into the cache. For each upstream
of names that have been inserted into the cache. The number of cache hits and
misses and the number of authoritative queries answered are also given. For each upstream
server it gives the number of queries sent, and the number which
resulted in an error. In
.B --no-daemon
mode or when full logging is enabled (-q), a complete dump of the
contents of the cache is made.
contents of the cache is made.
The cache statistics are also available in the DNS as answers to
queries of class CHAOS and type TXT in domain bind. The domain names are cachesize.bind, insertions.bind, evictions.bind,
misses.bind, hits.bind, auth.bind and servers.bind. An example command to query this, using the
.B dig
utility would be
dig +short chaos txt cachesize.bind
.PP
When it receives SIGUSR2 and it is logging direct to a file (see
.B --log-facility
@@ -1834,7 +1881,7 @@ which has tags will be used in preference to an untagged
.B dhcp-option,
provided that _all_ the tags match somewhere in the
set collected as described above. The prefix '!' on a tag means 'not'
so --dhcp=option=tag:!purple,3,1.2.3.4 sends the option when the
so --dhcp-option=tag:!purple,3,1.2.3.4 sends the option when the
tag purple is not in the set of valid tags. (If using this in a
command line rather than a configuration file, be sure to escape !,
which is a shell metacharacter)
@@ -1986,7 +2033,7 @@ to particular hosts then
will do so.
Dnsmasq acts as an authoritative server for in-addr.arpa and
ipv6.arpa domains associated with the subnets given in auth-zone
ip6.arpa domains associated with the subnets given in auth-zone
declarations, so reverse (address to name) lookups can be simply
configured with a suitable NS record, for instance in this example,
where we allow 1.2.3.0/24 addresses.

View File

@@ -706,7 +706,7 @@ l'un des sous-réseaux définis, ou dans un réseau correspondant à une plage D
(ce comportement peut-être désactivé par
.B constructor-noauth:
). Le ou les sous-réseaux sont également utilisé(s) pour définir les domaines
in-addr.arpa et ipv6.arpa servant à l'interrogation DNS inverse. Si la longueur
in-addr.arpa et ip6.arpa servant à l'interrogation DNS inverse. Si la longueur
de préfixe n'est pas spécifiée, elle sera par défaut de 24 pour IPv4 et 64 pour
IPv6. Dans le cas d'IPv4, la longueur du masque de réseau devrait-être de 8, 16
ou 24, sauf si en cas de mise en place d'une délégation de la zone in-addr.arpa
@@ -2186,7 +2186,7 @@ spécifiques, vous pouvez le faire via :
.fi
Dnsmasq joue le rôle de serveur faisant autorité pour les domaines in-addr.arpa
et ipv6.arpa associés aux sous-réseaux définis dans la déclaration de zone
et ip6.arpa associés aux sous-réseaux définis dans la déclaration de zone
auth-zone, ce qui fait que les requêtes DNS inversées (de l'adresse vers
le nom) peuvent-simplement être configurées avec un enregistrement NS
adéquat. Par exemple, comme nous définissons plus haut les adresses

337
po/de.po
View File

@@ -9,17 +9,19 @@
# Simon Kelley <simon@thekelleys.org.uk>, 2005.
msgid ""
msgstr ""
"Project-Id-Version: dnsmasq 2.53rc1\n"
"Project-Id-Version: dnsmasq 2.70\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-06-18 12:24+0100\n"
"PO-Revision-Date: 2012-04-05 17:54+0100\n"
"Last-Translator: Conrad Kostecki <ConiKost@gmx.de>\n"
"PO-Revision-Date: 2014-05-01 22:51+0100\n"
"Last-Translator: Conrad Kostecki <ck@conrad-kostecki.de>\n"
"Language-Team: German <de@li.org>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.6.5\n"
"X-Poedit-SourceCharset: UTF-8\n"
#: cache.c:821
#, c-format
@@ -57,8 +59,12 @@ msgstr "%s ist ein CNAME, weise es der DHCP-Lease von %s nicht zu"
#: cache.c:1114
#, 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"
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:1159
#, c-format
@@ -68,7 +74,9 @@ msgstr "Zeit %lu"
#: cache.c:1160
#, 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."
msgstr ""
"Cache Größe %d, %d/%d Cache-Einfügungen verwendeten nicht abgelaufene Cache-"
"Einträge wieder."
#: cache.c:1162
#, c-format
@@ -78,12 +86,13 @@ msgstr "%u weitergeleitete Anfragen, %u lokal beantwortete Anfragen"
#: cache.c:1165
#, c-format
msgid "queries for authoritative zones %u"
msgstr ""
msgstr "Anfragen nach autoritativen Zonen %u"
#: cache.c:1188
#, 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"
msgstr ""
"Server %s#%d: %u Anfragen gesendet, %u erneut versucht oder fehlgeschlagen"
#: util.c:67
#, c-format
@@ -126,11 +135,13 @@ msgstr "IP-Adresse für alle Hosts in angebenen Domänen festlegen."
# from the manpage instead. -- MA
#: option.c:303
msgid "Fake reverse lookups for RFC1918 private address ranges."
msgstr "Für private Adressbereiche nach RFC1918 \"keine solche Domain\" liefern."
msgstr ""
"Für private Adressbereiche nach RFC1918 \"keine solche Domain\" liefern."
#: option.c:304
msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
msgstr "Diese IP-Adresse als NXDOMAIN interpretieren (wehrt \"Suchhilfen\" ab)."
msgstr ""
"Diese IP-Adresse als NXDOMAIN interpretieren (wehrt \"Suchhilfen\" ab)."
#: option.c:305
#, c-format
@@ -325,11 +336,13 @@ msgstr "Gültigkeitsdauer für Antworten aus /etc/hosts festlegen."
#: option.c:350
msgid "Specify time-to-live in seconds for negative caching."
msgstr "Gültigkeitsdauer in Sekunden für Caching negativer Ergebnisse festlegen."
msgstr ""
"Gültigkeitsdauer in Sekunden für Caching negativer Ergebnisse festlegen."
#: option.c:351
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."
msgstr ""
"Gültigkeitsdauer in Sekunden für Caching negativer Ergebnisse festlegen."
#: option.c:352
#, c-format
@@ -354,7 +367,8 @@ msgstr "SRV-Eintrag festlegen."
#: option.c:357
msgid "Display this message. Use --help dhcp for known DHCP options."
msgstr "Diese Hilfe anzeigen. Benutzen Sie --help dhcp für bekannte DHCP-Optionen."
msgstr ""
"Diese Hilfe anzeigen. Benutzen Sie --help dhcp für bekannte DHCP-Optionen."
#: option.c:358
#, c-format
@@ -409,7 +423,9 @@ msgstr "MAC-Adresse (mit Jokerzeichen) auf Netzmarke abbilden."
#: option.c:370
msgid "Treat DHCP requests on aliases as arriving from interface."
msgstr "DHCP-Anfragen von Alias-Schnittstellen für die Hauptschnittstelle beantworten."
msgstr ""
"DHCP-Anfragen von Alias-Schnittstellen für die Hauptschnittstelle "
"beantworten."
#: option.c:371
msgid "Disable ICMP echo address checking in the DHCP server."
@@ -421,7 +437,8 @@ msgstr "Skript, das bei Erzeugung/Löschung einer DHCP-Lease laufen soll."
#: option.c:373
msgid "Lua script to run on DHCP lease creation and destruction."
msgstr "Lua-Skript, welches bei Erzeugung/Löschung eines DHCP-Leases laufen soll."
msgstr ""
"Lua-Skript, welches bei Erzeugung/Löschung eines DHCP-Leases laufen soll."
#: option.c:374
msgid "Run lease-change scripts as this user."
@@ -455,7 +472,9 @@ msgstr "Von DHCP-Clients gelieferte Hostnamen ignorieren."
#: option.c:381
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."
msgstr ""
"Dateinamen und Server-Datenfehler für zusätzliche DHCP-Optionen NICHT "
"wiederverwenden."
#: option.c:382
msgid "Enable integrated read-only TFTP server."
@@ -471,7 +490,9 @@ msgstr "IP-Adresse des Klienten an tftp-root anhängen."
#: option.c:385
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."
msgstr ""
"Zugriff nur auf Dateien gestatten, die dem dnsmasq aufrufenden Benutzer "
"gehören."
#: option.c:386
#, c-format
@@ -484,7 +505,7 @@ msgstr "TFTP-Blockgrößen-Erweiterung abschalten."
#: option.c:388
msgid "Convert TFTP filenames to lowercase"
msgstr ""
msgstr "Konvertiere TFTP Dateinamen in Kleinschreibung"
#: option.c:389
msgid "Ephemeral port range for use by TFTP transfers."
@@ -496,11 +517,13 @@ msgstr "Erweiterte DHCP-Protokollierung."
#: option.c:391
msgid "Enable async. logging; optionally set queue length."
msgstr "Asynchrone Protokollierung einschalten, opt. Warteschlangenlänge festlegen."
msgstr ""
"Asynchrone Protokollierung einschalten, opt. Warteschlangenlänge festlegen."
#: option.c:392
msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
msgstr "DNS-Rebinding unterbinden, private IP-Bereiche bei der Auflösung ausfiltern."
msgstr ""
"DNS-Rebinding unterbinden, private IP-Bereiche bei der Auflösung ausfiltern."
#: option.c:393
msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
@@ -528,7 +551,8 @@ msgstr "DNS-NAPTR-Eintrag festlegen."
#: option.c:399
msgid "Specify lowest port available for DNS query transmission."
msgstr "Niedrigsten verfügbaren Port für Übertragung von DNS-Anfragen festlegen."
msgstr ""
"Niedrigsten verfügbaren Port für Übertragung von DNS-Anfragen festlegen."
#: option.c:400
msgid "Use only fully qualified domain names for DHCP clients."
@@ -545,7 +569,7 @@ msgstr "Diese DHCP-Relais als vollwertige Proxies verwenden."
#: option.c:403
msgid "Relay DHCP requests to a remote server"
msgstr ""
msgstr "Leute DHCP Anfragen an entfernten Server weiter"
#: option.c:404
msgid "Specify alias name for LOCAL DNS name."
@@ -568,9 +592,10 @@ msgid "Add requestor's MAC address to forwarded DNS queries."
msgstr "Anfragende MAC-Adresse in die weiterleitende DNS-Anfrage einfügen"
#: option.c:409
#, fuzzy
msgid "Add requestor's IP subnet to forwarded DNS queries."
msgstr "Anfragende MAC-Adresse in die weiterleitende DNS-Anfrage einfügen"
msgstr ""
"Füge das IP-Subnetz des Anfragenden in die weitergeleiteten DNS-Anfragen "
"hinzu."
#: option.c:410
msgid "Proxy DNSSEC validation results from upstream nameservers."
@@ -582,7 +607,8 @@ msgstr "Versuche sequenzielle IP-Adressen an DHCP-Klienten zu vergeben."
#: option.c:412
msgid "Copy connection-track mark from queries to upstream connections."
msgstr "Kopiere \"connection-track mark\" von Anfragen nach Upstream-Verbindungen."
msgstr ""
"Kopiere \"connection-track mark\" von Anfragen nach Upstream-Verbindungen."
#: option.c:413
msgid "Allow DHCP clients to do their own DDNS updates."
@@ -590,78 +616,78 @@ msgstr "Erlaube DHCP-Klienten ihre eigenen DDNS-Updates durchzuführen."
#: option.c:414
msgid "Send router-advertisements for interfaces doing DHCPv6"
msgstr "Sende \"Router-Advertisments\" für Netzwerkschnittstellen, welche DHCPv6 nutzen"
msgstr ""
"Sende \"Router-Advertisments\" für Netzwerkschnittstellen, welche DHCPv6 "
"nutzen"
#: option.c:415
msgid "Specify DUID_EN-type DHCPv6 server DUID"
msgstr ""
msgstr "Spezifiziere DUID_EN-type DHCPv6 Server DUID"
#: option.c:416
#, fuzzy
msgid "Specify host (A/AAAA and PTR) records"
msgstr "Einen MX-Eintrag festlegen."
msgstr "Spezifiziere Host (A/AAAA und PTR) Einträge"
#: option.c:417
#, fuzzy
msgid "Specify arbitrary DNS resource record"
msgstr "DNS-TXT-Eintrag festlegen."
msgstr "Spezifiziere einen beliebiegen DNS Eintrag"
#: option.c:418
#, fuzzy
msgid "Bind to interfaces in use - check for new interfaces"
msgstr "unbekannte Schnittstelle %s in bridge-interface"
msgstr "Bindung zu Schnittstellen in Benutzung - prüfe auf neue Schnittstellen"
#: option.c:419
msgid "Export local names to global DNS"
msgstr ""
msgstr "Exportiere lokale Namen in das globale DNS"
#: option.c:420
msgid "Domain to export to global DNS"
msgstr ""
msgstr "Domain für das Exportieren des globalen DNS"
#: option.c:421
msgid "Set TTL for authoritative replies"
msgstr ""
msgstr "Setzte TTL für autoritative Antworten"
#: option.c:422
msgid "Set authoritive zone information"
msgstr ""
msgstr "Setze autoritative Zoneninformationen"
#: option.c:423
msgid "Secondary authoritative nameservers for forward domains"
msgstr ""
msgstr "Sekundärer autoritativer Nameserver für weitergeleitete Domains"
#: option.c:424
msgid "Peers which are allowed to do zone transfer"
msgstr ""
msgstr "Peers welche einen Zonentransfer durchführen dürfen"
#: option.c:425
msgid "Specify ipsets to which matching domains should be added"
msgstr ""
"Spezifiziere IPSets zu welcher passende Domains hinzugefügt werden sollen"
#: option.c:426
msgid "Specify a domain and address range for synthesised names"
msgstr ""
msgstr "Spezifiziere eine Domain und Adressbereich für synthetisierte Namen"
#: option.c:428
msgid "Specify DHCPv6 prefix class"
msgstr ""
msgstr "Spezifiziere DHCPv6 Prefix Klasse"
#: option.c:430
msgid "Set priority, resend-interval and router-lifetime"
msgstr ""
msgstr "Setze Priorität, Intervall des erneuten Sendens und Router Lebenszeit"
#: option.c:431
msgid "Do not log routine DHCP."
msgstr ""
msgstr "Protokolliere kein DHCP."
#: option.c:432
msgid "Do not log routine DHCPv6."
msgstr ""
msgstr "Protokolliere kein DHCPv6."
#: option.c:433
msgid "Do not log RA."
msgstr ""
msgstr "RA nicht protokollieren."
#: option.c:618
#, c-format
@@ -695,9 +721,8 @@ msgid "bad interface name"
msgstr "unzulässiger Schnittestellenname"
#: option.c:742
#, fuzzy
msgid "bad address"
msgstr "Fehlerhafte IP-Adresse"
msgstr "Fehlerhafte Adresse"
#: option.c:876
msgid "unsupported encapsulation for IPv6 option"
@@ -747,7 +772,9 @@ msgstr "Kann auf %s nicht zugreifen: %s"
#: option.c:1466
msgid "setting log facility is not possible under Android"
msgstr "Die Einstellung Protokolliereinrichtung kann unter Android nicht gesetzt werden"
msgstr ""
"Die Einstellung Protokolliereinrichtung kann unter Android nicht gesetzt "
"werden"
#: option.c:1475
msgid "bad log facility"
@@ -771,21 +798,23 @@ msgstr "unter uClinux ist die Skriptausführung nicht möglich"
#: option.c:1557
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"
msgstr ""
"Neuübersetzung mit HAVE_SCRIPT nötig, um Lease-Änderungs-Skripte auszuführen"
#: option.c:1561
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-Scripte zu ermöglichen, muss mit HAVE_LUASCRIPT "
"neu kompiliert werden"
#: option.c:1802 option.c:1863 option.c:1933
#, fuzzy
msgid "bad prefix"
msgstr "unzulässiger Port"
msgstr "unzulässiger Präfix"
#: option.c:2167
#, fuzzy
msgid "recompile with HAVE_IPSET defined to enable ipset directives"
msgstr "Um Benutzerdefinierte Lua-Scripte zu ermöglichen, muss mit HAVE_LUASCRIPT neu kompiliert werden"
msgstr ""
"Um IPSet-Direktiven zu aktivieren, muss mit HAVE_IPSET neu übersetzt werden"
#: option.c:2347
msgid "bad port range"
@@ -808,19 +837,16 @@ msgid "inconsistent DHCP range"
msgstr "inkonsistenter DHCP-Bereich"
#: option.c:2527
#, fuzzy
msgid "prefix length must be exactly 64 for RA subnets"
msgstr "Der Prefix muss mindestens 64 sein"
msgstr "Die Präfixlenge muss genau 64 für RA Subnetze sein"
#: option.c:2529
#, fuzzy
msgid "prefix length must be exactly 64 for subnet constructors"
msgstr "Der Prefix muss mindestens 64 sein"
msgstr "Die Präfixlenge muss genau 64 für Subnet Konstruktoren sein"
#: option.c:2533
#, fuzzy
msgid "prefix length must be at least 64"
msgstr "Der Prefix muss mindestens 64 sein"
msgstr "Die Präfixlänge muss mindestens 64 sein"
#: option.c:2536
msgid "inconsistent DHCPv6 range"
@@ -828,7 +854,7 @@ msgstr "Inkonsistenter DHCPv6-Bereich"
#: option.c:2547
msgid "prefix must be zero with \"constructor:\" argument"
msgstr ""
msgstr "Prefix muss mit dem \"constructor:\" Argument Null sein"
#: option.c:2658 option.c:2706
msgid "bad hex constant"
@@ -839,9 +865,9 @@ msgid "cannot match tags in --dhcp-host"
msgstr "Kann die Tags in --dhcp-host nicht abgleichen"
#: option.c:2728
#, fuzzy, c-format
#, c-format
msgid "duplicate dhcp-host IP address %s"
msgstr "doppelte IP-Adresse %s in %s."
msgstr "doppelte dhcp-host IP-Adresse %s"
#: option.c:2784
msgid "bad DHCP host name"
@@ -860,17 +886,16 @@ msgid "bad dhcp-proxy address"
msgstr "Fehlerhafte DHCP-Proxy-Adresse"
#: option.c:3278
#, fuzzy
msgid "Bad dhcp-relay"
msgstr "unzulässiger DHCP-Bereich"
msgstr "unzulässiger dhcp-relay"
#: option.c:3304
msgid "bad RA-params"
msgstr ""
msgstr "unzulässige RA-Parameter"
#: option.c:3313
msgid "bad DUID"
msgstr ""
msgstr "unzulässige DUID"
#: option.c:3355
msgid "invalid alias range"
@@ -893,9 +918,8 @@ msgid "bad NAPTR record"
msgstr "unzulässiger NAPTR-Eintrag"
#: option.c:3499
#, fuzzy
msgid "bad RR record"
msgstr "unzulässiger PTR-Eintrag"
msgstr "unzulässiger RR-Eintrag"
#: option.c:3528
msgid "bad TXT record"
@@ -918,17 +942,20 @@ msgid "invalid weight"
msgstr "unzulässige Wichtung"
#: option.c:3621
#, fuzzy
msgid "Bad host-record"
msgstr "unzulässiger PTR-Eintrag"
msgstr "unzulässiger host-record"
#: option.c:3638
msgid "Bad name in host-record"
msgstr ""
msgstr "Unzulässiger Name in host-record"
#: option.c:3668
msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
msgstr "unzulässige Option (prüfen Sie, ob dnsmasq mit DHCP/TFTP/DBus-Unterstützt übersetzt wurde)"
msgid ""
"unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus "
"support)"
msgstr ""
"unzulässige Option (prüfen Sie, ob dnsmasq mit DHCP/TFTP/DBus-Unterstützt "
"übersetzt wurde)"
#: option.c:3726
msgid "missing \""
@@ -951,9 +978,9 @@ msgid "error"
msgstr "Fehler"
#: option.c:3796
#, fuzzy, c-format
#, c-format
msgid " at line %d of %s"
msgstr "%s in Zeile %d von %%s"
msgstr " in Zeile %d von %s"
#: option.c:3860 tftp.c:661
#, c-format
@@ -992,12 +1019,14 @@ msgstr "Für diese Software wird ABSOLUT KEINE GARANTIE gewährt.\n"
#: option.c:4157
#, 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"
msgstr ""
"Dnsmasq ist freie Software, und du bist willkommen es weiter zu verteilen\n"
#: option.c:4158
#, 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"
msgstr ""
"unter den Bedingungen der GNU General Public Lizenz, Version 2 oder 3.\n"
#: option.c:4169
msgid "try --help"
@@ -1023,7 +1052,8 @@ msgstr "mit -n/--no-poll ist nur eine resolv.conf-Datei zulässig."
#: option.c:4260
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."
msgstr ""
"Um die Domäne zu lesen, muss genau eine resolv.conf-Datei verwendet werden."
#: option.c:4263 network.c:1316 dhcp.c:768
#, c-format
@@ -1037,7 +1067,8 @@ msgstr "keine \"search\"-Anweisung in %s gefunden"
#: option.c:4301
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"
msgstr ""
"Es muss eine standard Domain gesetzt sein, wenn --dhcp-fqdn gesetzt ist"
#: option.c:4305
msgid "syntax check OK"
@@ -1050,7 +1081,7 @@ msgstr "Fehlgeschlagen, folgendes Paket zu senden: %s"
#: forward.c:493
msgid "discarding DNS reply: subnet option mismatch"
msgstr ""
msgstr "Verwerfe DNS Antwort: Subnetoption stimmt nicht überrein"
#: forward.c:511
#, c-format
@@ -1063,9 +1094,9 @@ msgid "possible DNS-rebind attack detected: %s"
msgstr "möglichen DNS-Rebind-Angriff entdeckt: %s"
#: forward.c:1284
#, fuzzy, c-format
#, c-format
msgid "Maximum number of concurrent DNS queries reached (max: %d)"
msgstr "Höchstzahl nebenläufiger DNS-Anfragen (%s voreingestellt)."
msgstr "Maximale Anzahl an nebenläufiger DNS-Anfragen erreicht (Max: %d)"
#: network.c:627
#, c-format
@@ -1074,22 +1105,30 @@ msgstr "Konnte Empfangs-Socket für %s: %s nicht erzeugen"
#: network.c:947
#, c-format
msgid "LOUD WARNING: listening on %s may accept requests via interfaces other than %s"
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:953
msgid "LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"
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:962
#, fuzzy, c-format
#, c-format
msgid "warning: no addresses found for interface %s"
msgstr "Benutze lokale Adressen nur für %s %s"
msgstr "Warnung: Keine Adresse für die Schnittstelle %s gefunden"
#: network.c:1020
#, fuzzy, c-format
#, c-format
msgid "interface %s failed to join DHCPv6 multicast group: %s"
msgstr "Konnte DHCPv6-Multicast-Gruppe nicht beitreten: %s"
msgstr "Schnittstelle %s konnte DHCPv6-Multicast-Gruppe nicht beitreten: %s"
#: network.c:1214
#, c-format
@@ -1158,7 +1197,8 @@ msgstr "Kann nicht --conntrack UND --query-port einsetzen"
#: dnsmasq.c:144
msgid "Conntrack support not available: set HAVE_CONNTRACK in src/config.h"
msgstr "Conntrack-Unterstützung nicht verfügbar: setze HAVE_CONNTRACK in src/config.h"
msgstr ""
"Conntrack-Unterstützung nicht verfügbar: setze HAVE_CONNTRACK in src/config.h"
#: dnsmasq.c:149
msgid "asychronous logging is not available under Solaris"
@@ -1169,21 +1209,22 @@ msgid "asychronous logging is not available under Android"
msgstr "Asynchrone Protokollierung unter Android nicht verfügbar"
#: dnsmasq.c:159
#, fuzzy
msgid "authoritative DNS not available: set HAVE_AUTH in src/config.h"
msgstr "DBus nicht verfügbar: setzen Sie HAVE_DBUS in src/config.h"
msgstr ""
"Authoritatives DNS nicht verfügbar: Es muss HAVE_AUTH in src/config.h "
"gesetzt sein"
#: dnsmasq.c:169
msgid "zone serial must be configured in --auth-soa"
msgstr ""
msgstr "Zonen Seriennummer muss mit --auth-soa konfiguriert werden"
#: dnsmasq.c:187
msgid "dhcp-range constructor not available on this platform"
msgstr ""
msgstr "dhcp-range Konstruktor ist auf dieser Plattform nicht verfübar"
#: dnsmasq.c:227
msgid "cannot set --bind-interfaces and --bind-dynamic"
msgstr ""
msgstr "Kann nicht --bind-interfaces und --bind-dynamic setzen"
#: dnsmasq.c:231
#, c-format
@@ -1268,7 +1309,8 @@ msgstr "Warnung: keine vorgelagerten (Upstream) Server konfiguriert"
#: dnsmasq.c:659
#, c-format
msgid "asynchronous logging enabled, queue limit is %d messages"
msgstr "asynchrone Protokollierung eingeschaltet, Warteschlange fasst %d Nachrichten"
msgstr ""
"asynchrone Protokollierung eingeschaltet, Warteschlange fasst %d Nachrichten"
#: dnsmasq.c:680
msgid "IPv6 router advertisement enabled"
@@ -1277,7 +1319,7 @@ msgstr "IPv6-Router-Advertisement aktiviert"
#: dnsmasq.c:685
#, c-format
msgid "DHCP, sockets bound exclusively to interface %s"
msgstr ""
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:702
@@ -1344,7 +1386,7 @@ msgstr "Konnte Lua-Script nicht laden: %s"
#: dnsmasq.c:1068
#, c-format
msgid "TFTP directory %s inaccessible: %s"
msgstr ""
msgstr "Das TFTP-Verzeichnis %s ist nicht zugreifbar: %s"
#: dnsmasq.c:1132
#, c-format
@@ -1433,7 +1475,7 @@ msgstr "ignoriere %s Zeile %d, doppelter Name oder doppelte IP-Adresse"
#: dhcp.c:993 rfc3315.c:2063
#, c-format
msgid "DHCP relay %s -> %s"
msgstr ""
msgstr "DHCP Weiterleitung %s -> %s"
#: lease.c:61
#, c-format
@@ -1556,8 +1598,11 @@ msgstr "benutze konfigurierte Adresse %s nicht, weil sie an %s verleast ist"
#: rfc2131.c:994
#, 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"
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:997
#, c-format
@@ -1635,7 +1680,8 @@ msgstr "%u angeforderte Optionen: %s"
#: rfc2131.c:2447
#, 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"
msgstr ""
"Kann RFC3925-Option nicht senden: zu viele Optionen für Unternehmen Nr. %d"
#: netlink.c:78
#, c-format
@@ -1649,7 +1695,8 @@ msgstr "Netlink liefert Fehler %s"
#: dbus.c:259
msgid "attempt to set an IPv6 server address via DBus - no IPv6 support"
msgstr "Versuch, via DBus eine IPv6-Serveradresse zu setzen: keine IPv6-Unterstützung"
msgstr ""
"Versuch, via DBus eine IPv6-Serveradresse zu setzen: keine IPv6-Unterstützung"
#: dbus.c:523
msgid "setting upstream servers from DBus"
@@ -1727,9 +1774,9 @@ msgid "cannot create DHCPv6 socket: %s"
msgstr "Kann DHCPv6-Socket nicht erzeugen: %s"
#: dhcp6.c:80
#, fuzzy, c-format
#, c-format
msgid "failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"
msgstr "kann SO_REUSE{ADDR|PORT} für DHCP-Socket nicht aktivieren: %s"
msgstr "kann SO_REUSE{ADDR|PORT} für DHCPv6-Socket nicht aktivieren: %s"
#: dhcp6.c:92
#, c-format
@@ -1752,68 +1799,64 @@ msgid "%u available DHCPv6 subnet: %s/%d"
msgstr "%u verfügbare(s) DHCPv6-Subnetz: %s/%d"
#: rfc3315.c:376
#, fuzzy, c-format
#, c-format
msgid "%u vendor class: %u"
msgstr "%u \"Vendor class\": %s"
msgstr "%u Herstellerklasse: %u"
#: rfc3315.c:424
#, fuzzy, c-format
#, c-format
msgid "%u client MAC address: %s"
msgstr "%u Klient stellt Name bereit: %s"
msgstr "%u Klient MAC-Adresse: %s"
# FIXME: do not assemble
#: rfc3315.c:656
#, fuzzy, c-format
#, c-format
msgid "unknown prefix-class %d"
msgstr "Unbekannter Lease"
msgstr "unbekannte Präfixklasse %d"
#: rfc3315.c:788 rfc3315.c:910
msgid "success"
msgstr ""
msgstr "Erfolg"
#: rfc3315.c:803 rfc3315.c:805 rfc3315.c:918 rfc3315.c:920
#, fuzzy
msgid "no addresses available"
msgstr "Keine Adresse verfügbar"
msgstr "Keine Adressen verfügbar"
#: rfc3315.c:862
#, fuzzy
msgid "address unavailable"
msgstr "Adresse nicht verfügbar"
#: rfc3315.c:897
msgid "not on link"
msgstr ""
msgstr "nicht on link"
#: rfc3315.c:970 rfc3315.c:1148 rfc3315.c:1225
msgid "no binding found"
msgstr ""
msgstr "Keine Bindung gefunden"
#: rfc3315.c:1008
msgid "deprecated"
msgstr ""
msgstr "veraltet"
#: rfc3315.c:1013
#, fuzzy
msgid "address invalid"
msgstr "Adresse in Nutzung"
msgstr "Adresse ungültig"
#: rfc3315.c:1058
msgid "confirm failed"
msgstr ""
msgstr "Bestätigung fehlgeschlagen"
#: rfc3315.c:1069
#, fuzzy
msgid "all addresses still on link"
msgstr "Fehlerhafte Adresse in %s Zeile %d"
msgstr "Alle Adressen immer noch on link"
#: rfc3315.c:1157
msgid "release received"
msgstr ""
msgstr "Freigabe empfangen"
#: rfc3315.c:2054
msgid "Cannot multicast to DHCPv6 server without correct interface"
msgstr ""
msgstr "Kann nicht zum DHCPv6 Server multicasten ohne korrekte Schnittstelle"
#: dhcp-common.c:145
#, c-format
@@ -1836,9 +1879,9 @@ msgid "duplicate IP address %s (%s) in dhcp-config directive"
msgstr "doppelte IP-Adresse %s (%s) in \"dhcp-config\"-Anweisung"
#: dhcp-common.c:494
#, fuzzy, c-format
#, c-format
msgid "failed to set SO_BINDTODEVICE on DHCP socket: %s"
msgstr "kann SO_REUSE{ADDR|PORT} für DHCP-Socket nicht aktivieren: %s"
msgstr "kann SO_BINDTODEVICE für DHCP-Socket nicht aktivieren: %s"
#: dhcp-common.c:615
#, c-format
@@ -1852,52 +1895,52 @@ msgstr "Bekannte DHCPv6-Optionen:\n"
#: dhcp-common.c:823
msgid ", prefix deprecated"
msgstr ""
msgstr ", Prefix veraltet"
#: dhcp-common.c:826
#, c-format
msgid ", lease time "
msgstr ""
msgstr ", Lease Zeit"
#: dhcp-common.c:868
#, c-format
msgid "%s stateless on %s%.0s%.0s%s"
msgstr ""
msgstr "%s stateless auf %s%.0s%.0s%s"
#: dhcp-common.c:870
#, fuzzy, c-format
#, c-format
msgid "%s, static leases only on %.0s%s%s%.0s"
msgstr "DHCP, nur statische Leases auf %.0s%s, Lease-Zeit %s"
msgstr "%s, nur statische Leases auf %.0s%s%s%.0s"
#: dhcp-common.c:872
#, fuzzy, c-format
#, c-format
msgid "%s, proxy on subnet %.0s%s%.0s%.0s"
msgstr "DHCP, Proxy im Subnetz %.0s%s%.0s"
msgstr "%s, Proxy im Subnetz %.0s%s%.0s%.0s"
#: dhcp-common.c:873
#, fuzzy, c-format
#, c-format
msgid "%s, IP range %s -- %s%s%.0s"
msgstr "DHCP, IP-Bereich %s - %s, Lease-Zeit %s "
msgstr "%s, IP-Bereich %s -- %s%s%.0s"
#: dhcp-common.c:886
#, c-format
msgid "DHCPv4-derived IPv6 names on %s%s"
msgstr ""
msgstr "DHCPv4-abgeleitete IPv6 Namen auf %s%s"
#: dhcp-common.c:889
#, fuzzy, c-format
#, c-format
msgid "router advertisement on %s%s"
msgstr "Router-Advertisment nur auf %.0s%s, Lebenszeit %s"
msgstr "Router-Advertisment auf %s%s"
#: dhcp-common.c:900
#, c-format
msgid "DHCP relay from %s to %s via %s"
msgstr ""
msgstr "DHCP Weiterleitung von %s nach %s über %s"
#: dhcp-common.c:902
#, c-format
msgid "DHCP relay from %s to %s"
msgstr ""
msgstr "DHCP Weiterleitung von %s nach %s"
#: radv.c:98
#, c-format
@@ -1905,19 +1948,19 @@ msgid "cannot create ICMPv6 socket: %s"
msgstr "Kann ICMPv6-Socket nicht erzeugen: %s"
#: auth.c:427
#, fuzzy, c-format
#, c-format
msgid "ignoring zone transfer request from %s"
msgstr "nicht unterstützte Anfrage von %s"
msgstr "ignoriere Zonentransfer-Anfrage von %s"
#: ipset.c:95
#, fuzzy, c-format
#, c-format
msgid "failed to find kernel version: %s"
msgstr "kann nicht an DHCP-Server-Socket binden: %s"
msgstr "konnte Kernelversion nicht finden: %s"
#: ipset.c:114
#, fuzzy, c-format
#, c-format
msgid "failed to create IPset control socket: %s"
msgstr "konnte TFTP-Socket nicht erzeugen: %s"
msgstr "konnte IPset-Kontroll-Socket nicht erzeugen: %s"
#~ msgid "no interface with address %s"
#~ msgstr "keine Schnittstelle mit Adresse %s"

View File

@@ -231,8 +231,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
} while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
if (!found)
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | F_AUTH, NULL, &addr, NULL);
if (found)
nxdomain = 0;
else
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL);
continue;
}

View File

@@ -25,7 +25,7 @@ static void blockdata_expand(int n)
{
struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
if (new)
if (n > 0 && new)
{
int i;
@@ -46,14 +46,19 @@ void blockdata_init(void)
blockdata_alloced = 0;
blockdata_count = 0;
blockdata_hwm = 0;
blockdata_expand((daemon->cachesize * 100) / sizeof(struct blockdata));
/* 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));
}
void blockdata_report(void)
{
my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u, allocated %u"),
blockdata_count * sizeof(struct blockdata), blockdata_hwm * sizeof(struct blockdata), blockdata_alloced * sizeof(struct blockdata));
if (option_bool(OPT_DNSSEC_VALID))
my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u, allocated %u"),
blockdata_count * sizeof(struct blockdata),
blockdata_hwm * sizeof(struct blockdata),
blockdata_alloced * sizeof(struct blockdata));
}
struct blockdata *blockdata_alloc(char *data, size_t len)

View File

@@ -24,7 +24,6 @@ static struct crec *new_chain = NULL;
static int cache_inserted = 0, cache_live_freed = 0, insert_error;
static union bigname *big_free = NULL;
static int bignames_left, hash_size;
static int uid = 1;
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
static const struct {
@@ -73,6 +72,19 @@ static void cache_link(struct crec *crecp);
static void rehash(int size);
static void cache_hash(struct crec *crecp);
static unsigned int next_uid(void)
{
static unsigned int uid = 0;
uid++;
/* uid == 0 used to indicate CNAME to interface name. */
if (uid == SRC_INTERFACE)
uid++;
return uid;
}
void cache_init(void)
{
struct crec *crecp;
@@ -88,7 +100,7 @@ void cache_init(void)
{
cache_link(crecp);
crecp->flags = 0;
crecp->uid = uid++;
crecp->uid = next_uid();
}
}
@@ -183,7 +195,7 @@ static void cache_blockdata_free(struct crec *crecp)
else
blockdata_free(crecp->addr.key.keydata);
}
else if (crecp->flags & F_DS)
else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG))
blockdata_free(crecp->addr.ds.keydata);
}
#endif
@@ -192,10 +204,7 @@ static void cache_free(struct crec *crecp)
{
crecp->flags &= ~F_FORWARD;
crecp->flags &= ~F_REVERSE;
crecp->uid = uid++; /* invalidate CNAMES pointing to this. */
if (uid == -1)
uid++;
crecp->uid = next_uid(); /* invalidate CNAMES pointing to this. */
if (cache_tail)
cache_tail->next = crecp;
@@ -256,7 +265,7 @@ char *cache_get_name(struct crec *crecp)
char *cache_get_cname_target(struct crec *crecp)
{
if (crecp->addr.cname.uid != -1)
if (crecp->addr.cname.uid != SRC_INTERFACE)
return cache_get_name(crecp->addr.cname.target.cache);
return crecp->addr.cname.target.int_name->name;
@@ -289,7 +298,7 @@ struct crec *cache_enumerate(int init)
static int is_outdated_cname_pointer(struct crec *crecp)
{
if (!(crecp->flags & F_CNAME) || crecp->addr.cname.uid == -1)
if (!(crecp->flags & F_CNAME) || crecp->addr.cname.uid == SRC_INTERFACE)
return 0;
/* NB. record may be reused as DS or DNSKEY, where uid is
@@ -564,7 +573,14 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
*cache_get_name(new) = 0;
if (addr)
new->addr.addr = *addr;
{
#ifdef HAVE_DNSSEC
if (flags & (F_DS | F_DNSKEY))
new->uid = addr->addr.dnssec.class;
else
#endif
new->addr.addr = *addr;
}
new->ttd = now + (time_t)ttl;
new->next = new_chain;
@@ -767,13 +783,14 @@ static void add_hosts_cname(struct crec *target)
crec->name.namep = a->alias;
crec->addr.cname.target.cache = target;
crec->addr.cname.uid = target->uid;
crec->uid = next_uid();
cache_hash(crec);
add_hosts_cname(crec); /* handle chains */
}
}
static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
int index, struct crec **rhash, int hashsz)
unsigned int index, struct crec **rhash, int hashsz)
{
struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6));
int i, nameexists = 0;
@@ -877,7 +894,7 @@ static int gettok(FILE *f, char *token)
}
}
static int read_hostsfile(char *filename, int index, int cache_size, struct crec **rhash, int hashsz)
static int read_hostsfile(char *filename, unsigned int index, int cache_size, struct crec **rhash, int hashsz)
{
FILE *f = fopen(filename, "r");
char *token = daemon->namebuff, *domain_suffix = NULL;
@@ -1027,7 +1044,8 @@ void cache_reload(void)
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
cache->name.namep = a->alias;
cache->addr.cname.target.int_name = intr;
cache->addr.cname.uid = -1;
cache->addr.cname.uid = SRC_INTERFACE;
cache->uid = next_uid();
cache_hash(cache);
add_hosts_cname(cache); /* handle chains */
}
@@ -1063,7 +1081,7 @@ void cache_reload(void)
{
cache->name.namep = nl->name;
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, 0, (struct crec **)daemon->packet, revhashsz);
add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
}
#ifdef HAVE_IPV6
if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) &&
@@ -1071,7 +1089,7 @@ void cache_reload(void)
{
cache->name.namep = nl->name;
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, 0, (struct crec **)daemon->packet, revhashsz);
add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
}
#endif
}
@@ -1084,7 +1102,7 @@ void cache_reload(void)
}
if (!option_bool(OPT_NO_HOSTS))
total_size = read_hostsfile(HOSTSFILE, 0, total_size, (struct crec **)daemon->packet, revhashsz);
total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
for (ah = daemon->addn_hosts; ah; ah = ah->next)
@@ -1148,6 +1166,7 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
aliasc->name.namep = a->alias;
aliasc->addr.cname.target.cache = target;
aliasc->addr.cname.uid = target->uid;
aliasc->uid = next_uid();
cache_hash(aliasc);
add_dhcp_cname(aliasc, ttd);
}
@@ -1235,7 +1254,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
crec->ttd = ttd;
crec->addr.addr = *host_address;
crec->name.namep = host_name;
crec->uid = uid++;
crec->uid = next_uid();
cache_hash(crec);
add_dhcp_cname(crec, ttd);
@@ -1243,6 +1262,101 @@ void cache_add_dhcp_entry(char *host_name, int prot,
}
#endif
int cache_make_stat(struct txt_record *t)
{
static char *buff = NULL;
static int bufflen = 60;
int len;
struct server *serv, *serv1;
char *p;
if (!buff && !(buff = whine_malloc(60)))
return 0;
p = buff;
switch (t->stat)
{
case TXT_STAT_CACHESIZE:
sprintf(buff+1, "%d", daemon->cachesize);
break;
case TXT_STAT_INSERTS:
sprintf(buff+1, "%d", cache_inserted);
break;
case TXT_STAT_EVICTIONS:
sprintf(buff+1, "%d", cache_live_freed);
break;
case TXT_STAT_MISSES:
sprintf(buff+1, "%u", daemon->queries_forwarded);
break;
case TXT_STAT_HITS:
sprintf(buff+1, "%u", daemon->local_answer);
break;
#ifdef HAVE_AUTH
case TXT_STAT_AUTH:
sprintf(buff+1, "%u", daemon->auth_answer);
break;
#endif
case TXT_STAT_SERVERS:
/* sum counts from different records for same server */
for (serv = daemon->servers; serv; serv = serv->next)
serv->flags &= ~SERV_COUNTED;
for (serv = daemon->servers; serv; serv = serv->next)
if (!(serv->flags &
(SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
{
char *new, *lenp;
int port, newlen, bytes_avail, bytes_needed;
unsigned int queries = 0, failed_queries = 0;
for (serv1 = serv; serv1; serv1 = serv1->next)
if (!(serv1->flags &
(SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
sockaddr_isequal(&serv->addr, &serv1->addr))
{
serv1->flags |= SERV_COUNTED;
queries += serv1->queries;
failed_queries += serv1->failed_queries;
}
port = prettyprint_addr(&serv->addr, daemon->addrbuff);
lenp = p++; /* length */
bytes_avail = (p - buff) + bufflen;
bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
if (bytes_needed >= bytes_avail)
{
/* expand buffer if necessary */
newlen = bytes_needed + 1 + bufflen - bytes_avail;
if (!(new = whine_malloc(newlen)))
return 0;
memcpy(new, buff, bufflen);
free(buff);
p = new + (p - buff);
lenp = p - 1;
buff = new;
bufflen = newlen;
bytes_avail = (p - buff) + bufflen;
bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
}
*lenp = bytes_needed;
p += bytes_needed;
}
t->txt = (unsigned char *)buff;
t->len = p - buff;
return 1;
}
len = strlen(buff+1);
t->txt = (unsigned char *)buff;
t->len = len + 1;
*buff = len;
return 1;
}
void dump_cache(time_t now)
{
@@ -1304,25 +1418,16 @@ void dump_cache(time_t now)
else if (cache->flags & F_DS)
{
if (cache->flags & F_DNSKEY)
{
/* RRSIG */
a = daemon->addrbuff;
sprintf(a, "%5u %3u %s", cache->addr.sig.keytag,
cache->addr.sig.algo, querystr("", cache->addr.sig.type_covered));
}
else
{
a = daemon->addrbuff;
sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
cache->addr.ds.algo, cache->addr.ds.digest);
}
/* 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))
sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
cache->addr.ds.algo, cache->addr.ds.digest);
}
else if (cache->flags & F_DNSKEY)
{
a = daemon->addrbuff;
sprintf(a, "%5u %3u %3u", cache->addr.key.keytag,
cache->addr.key.algo, cache->addr.key.flags);
}
sprintf(a, "%5u %3u %3u", cache->addr.key.keytag,
cache->addr.key.algo, cache->addr.key.flags);
#endif
else if (!(cache->flags & F_NEG) || !(cache->flags & F_FORWARD))
{
@@ -1370,11 +1475,13 @@ void dump_cache(time_t now)
}
}
char *record_source(int index)
char *record_source(unsigned int index)
{
struct hostsfile *ah;
if (index == 0)
if (index == SRC_CONFIG)
return "config";
else if (index == SRC_HOSTS)
return HOSTSFILE;
for (ah = daemon->addn_hosts; ah; ah = ah->next)
@@ -1502,6 +1609,13 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
source = arg;
verb = "to";
}
else if (flags & F_IPSET)
{
source = "ipset add";
dest = name;
name = arg;
verb = daemon->addrbuff;
}
else
source = "cached";

View File

@@ -18,7 +18,7 @@
#define MAX_PROCS 20 /* max no children for TCP requests */
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
#define KEYBLOCK_LEN 35 /* choose to mininise fragmentation when storing DNSSEC keys */
#define KEYBLOCK_LEN 40 /* choose to mininise 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 */
@@ -31,7 +31,8 @@
#define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */
#define DECLINE_BACKOFF 600 /* disable DECLINEd static addresses for this long */
#define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */
#define SMALLDNAME 40 /* most domain names are smaller than this */
#define SMALLDNAME 50 /* most domain names are smaller than this */
#define CNAME_CHAIN 10 /* chains longer than this atr dropped for loop protection */
#define HOSTSFILE "/etc/hosts"
#define ETHERSFILE "/etc/ethers"
#define DEFLEASE 3600 /* default lease time, 1 hour */

View File

@@ -397,7 +397,7 @@ int main (int argc, char **argv)
piperead = pipefd[0];
pipewrite = pipefd[1];
/* prime the pipe to load stuff first time. */
send_event(pipewrite, EVENT_RELOAD, 0, NULL);
send_event(pipewrite, EVENT_INIT, 0, NULL);
err_pipe[1] = -1;
@@ -661,10 +661,17 @@ int main (int argc, char **argv)
my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
}
#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))
my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
{
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"));
}
#endif
if (log_err != 0)
@@ -1127,8 +1134,18 @@ 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
/* fall through */
case EVENT_INIT:
clear_cache_and_reload(now);
if (daemon->port != 0)
{
if (daemon->resolv_files && option_bool(OPT_NO_POLL))

View File

@@ -164,6 +164,7 @@ struct event_desc {
#define EVENT_FORK_ERR 18
#define EVENT_LUA_ERR 19
#define EVENT_TFTP_ERR 20
#define EVENT_INIT 21
/* Exit codes. */
#define EC_GOOD 0
@@ -230,9 +231,11 @@ struct event_desc {
#define OPT_QUIET_DHCP6 43
#define OPT_QUIET_RA 44
#define OPT_DNSSEC_VALID 45
#define OPT_DNSSEC_PERMISS 46
#define OPT_DNSSEC_TIME 46
#define OPT_DNSSEC_DEBUG 47
#define OPT_LAST 48
#define OPT_DNSSEC_NO_SIGN 48
#define OPT_LOCAL_SERVICE 49
#define OPT_LAST 50
/* 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. */
@@ -278,10 +281,19 @@ struct naptr {
struct naptr *next;
};
#define TXT_STAT_CACHESIZE 1
#define TXT_STAT_INSERTS 2
#define TXT_STAT_EVICTIONS 3
#define TXT_STAT_MISSES 4
#define TXT_STAT_HITS 5
#define TXT_STAT_AUTH 6
#define TXT_STAT_SERVERS 7
struct txt_record {
char *name;
unsigned char *txt;
unsigned short class, len;
int stat;
struct txt_record *next;
};
@@ -365,7 +377,7 @@ struct crec {
struct crec *cache;
struct interface_name *int_name;
} target;
int uid; /* -1 if union is interface-name */
unsigned int uid; /* 0 if union is interface-name */
} cname;
struct {
struct blockdata *keydata;
@@ -386,7 +398,7 @@ struct crec {
} addr;
time_t ttd; /* time to die */
/* used as class if DNSKEY/DS/RRSIG, index to source for F_HOSTS */
int uid;
unsigned int uid;
unsigned short flags;
union {
char sname[SMALLDNAME];
@@ -424,6 +436,13 @@ struct crec {
#define F_KEYTAG (1u<<23)
#define F_SECSTAT (1u<<24)
#define F_NO_RR (1u<<25)
#define F_IPSET (1u<<26)
/* Values of uid in crecs with F_CONFIG bit set. */
#define SRC_INTERFACE 0
#define SRC_CONFIG 1
#define SRC_HOSTS 2
#define SRC_AH 3
/* struct sockaddr is not large enough to hold any address,
@@ -523,7 +542,7 @@ struct hostsfile {
struct hostsfile *next;
int flags;
char *fname;
int index; /* matches to cache entries for logging */
unsigned int index; /* matches to cache entries for logging */
};
@@ -535,6 +554,10 @@ 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_NEED_DS_NEG 10
#define STAT_CHASE_CNAME 11
#define FREC_NOREBIND 1
#define FREC_CHECKING_DISABLED 2
@@ -542,6 +565,9 @@ struct hostsfile {
#define FREC_DNSKEY_QUERY 8
#define FREC_DS_QUERY 16
#define FREC_AD_QUESTION 32
#define FREC_DO_QUESTION 64
#define FREC_ADDED_PHEADER 128
#define FREC_CHECK_NOSIGN 256
#ifdef HAVE_DNSSEC
#define HASH_SIZE 20 /* SHA-1 digest size */
@@ -958,6 +984,7 @@ extern struct daemon {
pid_t tcp_pids[MAX_PROCS];
struct randfd randomsocks[RANDOM_SOCKS];
int v6pktinfo;
struct addrlist *interface_addrs; /* list of all addresses/prefix lengths associated with all local interfaces */
/* DHCP state */
int dhcpfd, helperfd, pxefd;
@@ -995,7 +1022,7 @@ extern struct daemon {
/* cache.c */
void cache_init(void);
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
char *record_source(int index);
char *record_source(unsigned int index);
char *querystr(char *desc, unsigned short type);
struct crec *cache_find_by_addr(struct crec *crecp,
struct all_addr *addr, time_t now,
@@ -1011,6 +1038,7 @@ 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);
int cache_make_stat(struct txt_record *t);
char *cache_get_name(struct crec *crecp);
char *cache_get_cname_target(struct crec *crecp);
struct crec *cache_enumerate(int init);
@@ -1048,7 +1076,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff,
int no_cache, 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);
time_t now, int *ad_reqd, int *do_bit);
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
struct bogus_addr *addr, time_t now);
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
@@ -1083,8 +1111,10 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr);
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, char *name, char *keyname, int class);
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class);
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int *neganswer);
int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname);
int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
size_t filter_rrsigs(struct dns_header *header, size_t plen);
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
/* util.c */

File diff suppressed because it is too large Load Diff

View File

@@ -24,6 +24,14 @@ static unsigned short get_id(void);
static void free_frec(struct frec *f);
static struct randfd *allocate_rfd(int family);
#ifdef HAVE_DNSSEC
static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n,
int class, char *name, char *keyname, struct server *server, int *keycount);
static int do_check_sign(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
static int send_check_sign(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname);
#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,
@@ -235,7 +243,7 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp,
static int forward_query(int udpfd, union mysockaddr *udpaddr,
struct all_addr *dst_addr, unsigned int dst_iface,
struct dns_header *header, size_t plen, time_t now,
struct frec *forward, int ad_reqd)
struct frec *forward, int ad_reqd, int do_bit)
{
char *domain = NULL;
int type = 0, norebind = 0;
@@ -250,6 +258,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
#endif
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
(void)do_bit;
/* may be no servers available. */
if (!daemon->servers)
forward = NULL;
@@ -268,7 +278,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
plen = forward->stash_len;
if (forward->sentto->addr.sa.sa_family)
if (forward->sentto->addr.sa.sa_family == AF_INET)
log_query(F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
#ifdef HAVE_IPV6
else
@@ -289,7 +299,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
while (sendto(fd, (char *)header, plen, 0,
&forward->sentto->addr.sa,
sa_len(&forward->sentto->addr)) == -1 && retry_send());
sa_len(&forward->sentto->addr)) == -1 && retry_send());
return 1;
}
@@ -336,8 +346,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
forward->flags |= FREC_AD_QUESTION;
#ifdef HAVE_DNSSEC
forward->work_counter = DNSSEC_WORK;
if (do_bit)
forward->flags |= FREC_DO_QUESTION;
#endif
header->id = htons(forward->new_id);
/* In strict_order mode, always try servers in the order
@@ -393,11 +405,17 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
{
plen = add_do_bit(header, plen, ((char *) header) + daemon->packet_buff_sz);
size_t new_plen = add_do_bit(header, plen, ((char *) header) + daemon->packet_buff_sz);
/* 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)
forward->flags |= FREC_ADDED_PHEADER;
plen = new_plen;
}
#endif
@@ -506,7 +524,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
}
static size_t process_reply(struct dns_header *header, time_t now, struct server *server, size_t n, int check_rebind,
int no_cache, int cache_secure, int ad_reqd, int check_subnet, union mysockaddr *query_source)
int no_cache, int cache_secure, int ad_reqd, int do_bit, int added_pheader, int check_subnet, union mysockaddr *query_source)
{
unsigned char *pheader, *sizep;
char **sets = 0;
@@ -514,22 +532,26 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
size_t plen;
(void)ad_reqd;
(void) do_bit;
#ifdef HAVE_IPSET
/* Similar algorithm to search_servers. */
struct ipsets *ipset_pos;
unsigned int namelen = strlen(daemon->namebuff);
unsigned int matchlen = 0;
for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next)
if (daemon->ipsets && extract_request(header, n, daemon->namebuff, NULL))
{
unsigned int domainlen = strlen(ipset_pos->domain);
char *matchstart = daemon->namebuff + namelen - domainlen;
if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
(domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
domainlen >= matchlen)
/* Similar algorithm to search_servers. */
struct ipsets *ipset_pos;
unsigned int namelen = strlen(daemon->namebuff);
unsigned int matchlen = 0;
for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next)
{
matchlen = domainlen;
sets = ipset_pos->sets;
unsigned int domainlen = strlen(ipset_pos->domain);
char *matchstart = daemon->namebuff + namelen - domainlen;
if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
(domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
domainlen >= matchlen)
{
matchlen = domainlen;
sets = ipset_pos->sets;
}
}
}
#endif
@@ -553,6 +575,12 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
return 0;
}
if (added_pheader)
{
pheader = 0;
header->arcount = htons(0);
}
}
/* RFC 4035 sect 4.6 para 3 */
@@ -560,7 +588,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
header->hb4 &= ~HB4_AD;
if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
return n;
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 &&
@@ -624,6 +652,10 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
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);
#endif
/* do this after extract_addresses. Ensure NODATA reply and remove
@@ -669,14 +701,20 @@ void reply_query(int fd, int family, time_t now)
serveraddr.in6.sin6_flowinfo = 0;
#endif
header = (struct dns_header *)daemon->packet;
if (n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR))
return;
/* spoof check: answer must come from known server, */
for (server = daemon->servers; server; server = server->next)
if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
sockaddr_isequal(&server->addr, &serveraddr))
break;
header = (struct dns_header *)daemon->packet;
if (!server)
return;
#ifdef HAVE_DNSSEC
hash = hash_questions(header, n, daemon->namebuff);
#else
@@ -684,11 +722,9 @@ void reply_query(int fd, int family, time_t now)
crc = questions_crc(header, n, daemon->namebuff);
#endif
if (!server ||
n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR) ||
!(forward = lookup_frec(ntohs(header->id), hash)))
if (!(forward = lookup_frec(ntohs(header->id), hash)))
return;
if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
!option_bool(OPT_ORDER) &&
forward->forwardall == 0)
@@ -708,7 +744,7 @@ 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_TC);
forward_query(-1, NULL, NULL, 0, header, nn, now, forward, 0);
forward_query(-1, NULL, NULL, 0, header, nn, now, forward, 0, 0);
return;
}
}
@@ -718,7 +754,7 @@ void reply_query(int fd, int family, time_t now)
if ((forward->sentto->flags & SERV_TYPE) == 0)
{
if (RCODE(header) == SERVFAIL || RCODE(header) == REFUSED)
if (RCODE(header) == REFUSED)
server = NULL;
else
{
@@ -741,8 +777,7 @@ void reply_query(int fd, int family, time_t now)
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) != REFUSED && RCODE(header) != SERVFAIL))
if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != SERVFAIL)
{
int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0;
@@ -755,7 +790,7 @@ void reply_query(int fd, int family, time_t now)
no_cache_dnssec = 1;
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
if (server && option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
{
int status;
@@ -775,13 +810,27 @@ void reply_query(int fd, int family, time_t now)
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);
{
status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
if (status == STAT_NO_DS)
status = STAT_INSECURE;
}
else if (forward->flags & FREC_CHECK_NOSIGN)
status = do_check_sign(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
else
status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class);
{
status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, NULL);
if (status == STAT_NO_SIG)
{
if (option_bool(OPT_DNSSEC_NO_SIGN))
status = send_check_sign(now, header, n, daemon->namebuff, daemon->keyname);
else
status = STAT_INSECURE;
}
}
/* 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)
if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG || status == STAT_NEED_KEY)
{
struct frec *new, *orig;
@@ -807,11 +856,12 @@ void reply_query(int fd, int family, time_t now)
*new = *forward; /* copy everything, then overwrite */
new->next = next;
new->blocking_query = NULL;
new->sentto = server;
new->rfd4 = NULL;
#ifdef HAVE_IPV6
new->rfd6 = NULL;
#endif
new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_CHECK_NOSIGN);
new->dependent = forward; /* to find query awaiting new one. */
forward->blocking_query = new; /* for garbage cleaning */
@@ -824,7 +874,10 @@ void reply_query(int fd, int family, time_t now)
}
else
{
new->flags |= FREC_DS_QUERY;
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);
}
@@ -888,11 +941,26 @@ void reply_query(int fd, int family, time_t now)
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);
{
status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
if (status == STAT_NO_DS)
status = STAT_INSECURE;
}
else if (forward->flags & FREC_CHECK_NOSIGN)
status = do_check_sign(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
else
status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class);
if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
{
status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, NULL);
if (status == STAT_NO_SIG)
{
if (option_bool(OPT_DNSSEC_NO_SIGN))
status = send_check_sign(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;
}
}
@@ -927,7 +995,8 @@ void reply_query(int fd, int family, time_t now)
header->hb4 &= ~HB4_CD;
if ((nn = process_reply(header, now, server, (size_t)n, check_rebind, no_cache_dnssec, cache_secure,
forward->flags & FREC_AD_QUESTION, forward->flags & FREC_HAS_SUBNET, &forward->source)))
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 */
@@ -1014,11 +1083,60 @@ void receive_query(struct listener *listen, time_t now)
return;
source_addr.sa.sa_family = listen->family;
if (listen->family == AF_INET)
{
/* Source-port == 0 is an error, we can't send back to that.
http://www.ietf.org/mail-archive/web/dnsop/current/msg11441.html */
if (source_addr.in.sin_port == 0)
return;
}
#ifdef HAVE_IPV6
if (listen->family == AF_INET6)
source_addr.in6.sin6_flowinfo = 0;
else
{
/* Source-port == 0 is an error, we can't send back to that. */
if (source_addr.in6.sin6_port == 0)
return;
source_addr.in6.sin6_flowinfo = 0;
}
#endif
/* We can be configured to only accept queries from at-most-one-hop-away addresses. */
if (option_bool(OPT_LOCAL_SERVICE))
{
struct addrlist *addr;
#ifdef HAVE_IPV6
if (listen->family == AF_INET6)
{
for (addr = daemon->interface_addrs; addr; addr = addr->next)
if ((addr->flags & ADDRLIST_IPV6) &&
is_same_net6(&addr->addr.addr.addr6, &source_addr.in6.sin6_addr, addr->prefixlen))
break;
}
else
#endif
{
struct in_addr netmask;
for (addr = daemon->interface_addrs; addr; addr = addr->next)
{
netmask.s_addr = 0xffffffff << (32 - addr->prefixlen);
if (!(addr->flags & ADDRLIST_IPV6) &&
is_same_net(addr->addr.addr.addr4, source_addr.in.sin_addr, netmask))
break;
}
}
if (!addr)
{
static int warned = 0;
if (!warned)
{
my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
warned = 1;
}
return;
}
}
if (check_dst)
{
struct ifreq ifr;
@@ -1169,9 +1287,9 @@ void receive_query(struct listener *listen, time_t now)
else
#endif
{
int ad_reqd;
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);
dst_addr_4, netmask, now, &ad_reqd, &do_bit);
if (m >= 1)
{
@@ -1180,7 +1298,7 @@ void receive_query(struct listener *listen, time_t now)
daemon->local_answer++;
}
else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
header, (size_t)n, now, NULL, ad_reqd))
header, (size_t)n, now, NULL, ad_reqd, do_bit))
daemon->queries_forwarded++;
else
daemon->local_answer++;
@@ -1188,6 +1306,192 @@ 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(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname)
{
struct crec *crecp;
char *name_start = name;
int status = dnssec_chase_cname(now, header, plen, name, keyname);
if (status != STAT_INSECURE)
return status;
while (1)
{
crecp = cache_find_by_name(NULL, name_start, now, F_DS);
if (crecp && (crecp->flags & F_DNSSECOK))
return (crecp->flags & F_NEG) ? STAT_INSECURE : STAT_BOGUS;
if (crecp && (crecp->flags & F_NEG) && (name_start = strchr(name_start, '.')))
{
name_start++; /* chop a label off and try again */
continue;
}
/* Reached the root */
if (!name_start)
return STAT_BOGUS;
strcpy(keyname, name_start);
return STAT_NEED_DS_NEG;
}
}
/* Got answer to DS query from send_check_sign, check for proven non-existence, or make the next DS query to try. */
static int do_check_sign(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
{
char *name_start;
unsigned char *p;
int status;
/* In this case only, a SERVFAIL reply allows us to continue up the tree, looking for a
suitable NSEC reply to DS queries. */
if (RCODE(header) != SERVFAIL)
{
status = dnssec_validate_ds(now, header, plen, name, keyname, class);
if (status != STAT_INSECURE)
{
if (status == STAT_NO_DS)
status = STAT_INSECURE;
return status;
}
}
p = (unsigned char *)(header+1);
if (extract_name(header, plen, &p, name, 1, 4) &&
(name_start = strchr(name, '.')))
{
name_start++; /* chop a label off and try again */
strcpy(keyname, name_start);
return STAT_NEED_DS_NEG;
}
return STAT_BOGUS;
}
/* Move toward 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;
unsigned char *p = (unsigned char *)(header+1);
int status;
char *name_start = name;
/* 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;
while (1)
{
unsigned char *newhash, hash[HASH_SIZE];
unsigned char c1, c2;
struct crec *crecp = cache_find_by_name(NULL, name_start, now, F_DS);
if (--(*keycount) == 0)
{
free(packet);
return STAT_BOGUS;
}
if (crecp && (crecp->flags & F_DNSSECOK))
{
free(packet);
return (crecp->flags & F_NEG) ? STAT_INSECURE : STAT_BOGUS;
}
/* If we have cached insecurely that a DS doesn't exist,
ise that is a hit for where to start looking for the secure one */
if (crecp && (crecp->flags & F_NEG) && (name_start = strchr(name_start, '.')))
{
name_start++; /* chop a label off and try again */
continue;
}
/* reached the root */
if (!name_start)
{
free(packet);
return STAT_BOGUS;
}
m = dnssec_generate_query(header, ((char *) header) + 65536, name_start, class, T_DS, &server->addr);
/* We rely on the question section coming back unchanged, ensure it is with the hash. */
if ((newhash = hash_questions(header, (unsigned int)m, name)))
{
memcpy(hash, newhash, HASH_SIZE);
*length = htons(m);
if (read_write(server->tcpfd, packet, m + sizeof(u16), 0) &&
read_write(server->tcpfd, &c1, 1, 1) &&
read_write(server->tcpfd, &c2, 1, 1) &&
read_write(server->tcpfd, payload, (c1 << 8) | c2, 1))
{
m = (c1 << 8) | c2;
newhash = hash_questions(header, (unsigned int)m, name);
if (newhash && memcmp(hash, newhash, HASH_SIZE) == 0)
{
/* In this case only, a SERVFAIL reply allows us to continue up the tree, looking for a
suitable NSEC reply to DS queries. */
if (RCODE(header) == SERVFAIL)
status = STAT_INSECURE;
else
/* Note this trashes all three name workspaces */
status = tcp_key_recurse(now, STAT_NEED_DS_NEG, header, m, class, name, keyname, server, keycount);
/* We've found a DS which proves the bit of the DNS where the
original query is, is unsigned, so the answer is OK,
if unvalidated. */
if (status == STAT_NO_DS)
{
free(packet);
return STAT_INSECURE;
}
/* No DS, not got to DNSSEC-land yet, go up. */
if (status == STAT_INSECURE)
{
p = (unsigned char *)(header+1);
if (extract_name(header, plen, &p, name, 1, 4) &&
(name_start = strchr(name, '.')))
{
name_start++; /* chop a label off and try again */
continue;
}
}
}
}
}
free(packet);
return STAT_BOGUS;
}
}
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)
{
@@ -1200,11 +1504,27 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
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);
else if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG)
{
new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
if (status == STAT_NEED_DS && new_status == STAT_NO_DS)
new_status = STAT_INSECURE;
}
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);
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)
@@ -1234,7 +1554,9 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
{
m = (c1 << 8) | c2;
if (tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, keycount) == STAT_SECURE)
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.
@@ -1242,11 +1564,27 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
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);
else if (status == STAT_NEED_DS || status == STAT_NEED_DS_NEG)
{
new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
if (status == STAT_NEED_DS && new_status == STAT_NO_DS)
new_status = STAT_INSECURE; /* Validated no DS */
}
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);
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;
}
@@ -1254,7 +1592,6 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
free(packet);
}
return new_status;
}
#endif
@@ -1272,7 +1609,8 @@ unsigned char *tcp_request(int confd, time_t now,
#ifdef HAVE_AUTH
int local_auth = 0;
#endif
int checking_disabled, ad_question, check_subnet, no_cache_dnssec = 0, cache_secure = 0;
int checking_disabled, ad_question, do_bit, added_pheader = 0;
int check_subnet, no_cache_dnssec = 0, cache_secure = 0;
size_t m;
unsigned short qtype;
unsigned int gotname;
@@ -1290,6 +1628,37 @@ unsigned char *tcp_request(int confd, time_t now,
if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
return packet;
/* We can be configured to only accept queries from at-most-one-hop-away addresses. */
if (option_bool(OPT_LOCAL_SERVICE))
{
struct addrlist *addr;
#ifdef HAVE_IPV6
if (peer_addr.sa.sa_family == AF_INET6)
{
for (addr = daemon->interface_addrs; addr; addr = addr->next)
if ((addr->flags & ADDRLIST_IPV6) &&
is_same_net6(&addr->addr.addr.addr6, &peer_addr.in6.sin6_addr, addr->prefixlen))
break;
}
else
#endif
{
struct in_addr netmask;
for (addr = daemon->interface_addrs; addr; addr = addr->next)
{
netmask.s_addr = 0xffffffff << (32 - addr->prefixlen);
if (!(addr->flags & ADDRLIST_IPV6) &&
is_same_net(addr->addr.addr.addr4, peer_addr.in.sin_addr, netmask))
break;
}
}
if (!addr)
{
my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
return packet;
}
}
while (1)
{
@@ -1350,7 +1719,7 @@ unsigned char *tcp_request(int confd, time_t now,
{
/* m > 0 if answered from cache */
m = answer_request(header, ((char *) header) + 65536, (size_t)size,
dst_addr_4, netmask, now, &ad_question);
dst_addr_4, netmask, now, &ad_question, &do_bit);
/* Do this by steam now we're not in the select() loop */
check_log_writer(NULL);
@@ -1388,8 +1757,10 @@ unsigned char *tcp_request(int confd, time_t now,
struct server *firstsendto = NULL;
#ifdef HAVE_DNSSEC
unsigned char *newhash, hash[HASH_SIZE];
if ((newhash = hash_questions(header, (unsigned int)size, daemon->keyname)))
if ((newhash = hash_questions(header, (unsigned int)size, daemon->namebuff)))
memcpy(hash, newhash, HASH_SIZE);
else
memset(hash, 0, HASH_SIZE);
#else
unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
#endif
@@ -1430,11 +1801,17 @@ unsigned char *tcp_request(int confd, time_t now,
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
{
size = add_do_bit(header, size, ((char *) header) + 65536);
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
@@ -1458,6 +1835,10 @@ unsigned char *tcp_request(int confd, time_t now,
}
*length = htons(size);
/* get query name again for logging - may have been overwritten */
if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
strcpy(daemon->namebuff, "query");
if (!read_write(last_server->tcpfd, packet, size + sizeof(u16), 0) ||
!read_write(last_server->tcpfd, &c1, 1, 1) ||
@@ -1471,8 +1852,6 @@ unsigned char *tcp_request(int confd, time_t now,
m = (c1 << 8) | c2;
if (!gotname)
strcpy(daemon->namebuff, "query");
if (last_server->addr.sa.sa_family == AF_INET)
log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
(struct all_addr *)&last_server->addr.in.sin_addr, NULL);
@@ -1533,7 +1912,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, ad_question, check_subnet, &peer_addr);
cache_secure, ad_question, do_bit, added_pheader, check_subnet, &peer_addr);
break;
}

View File

@@ -268,7 +268,40 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
if (!label)
label = ifr.ifr_name;
/* maintain a list of all addresses on all interfaces for --local-service option */
if (option_bool(OPT_LOCAL_SERVICE))
{
struct addrlist *al;
if (param->spare)
{
al = param->spare;
param->spare = al->next;
}
else
al = whine_malloc(sizeof(struct addrlist));
if (al)
{
al->next = daemon->interface_addrs;
daemon->interface_addrs = al;
al->prefixlen = prefixlen;
if (addr->sa.sa_family == AF_INET)
{
al->addr.addr.addr4 = addr->in.sin_addr;
al->flags = 0;
}
#ifdef HAVE_IPV6
else
{
al->addr.addr.addr6 = addr->in6.sin6_addr;
al->flags = ADDRLIST_IPV6;
}
#endif
}
}
#ifdef HAVE_IPV6
if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
@@ -565,6 +598,15 @@ int enumerate_interfaces(int reset)
intname->addr = NULL;
}
/* Remove list of addresses of local interfaces */
for (addr = daemon->interface_addrs; addr; addr = tmp)
{
tmp = addr->next;
addr->next = spare;
spare = addr;
}
daemon->interface_addrs = NULL;
#ifdef HAVE_AUTH
/* remove addresses stored against auth_zone subnets, but not
ones configured as address literals */
@@ -1528,7 +1570,8 @@ void newaddress(time_t now)
{
(void)now;
if (option_bool(OPT_CLEVERBIND) || daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
enumerate_interfaces(0);
if (option_bool(OPT_CLEVERBIND))

View File

@@ -64,85 +64,88 @@ struct myoption {
#define OPTSTRING "951yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:7:8:0:3:"
/* options which don't have a one-char version */
#define LOPT_RELOAD 256
#define LOPT_NO_NAMES 257
#define LOPT_TFTP 258
#define LOPT_SECURE 259
#define LOPT_PREFIX 260
#define LOPT_PTR 261
#define LOPT_BRIDGE 262
#define LOPT_TFTP_MAX 263
#define LOPT_FORCE 264
#define LOPT_NOBLOCK 265
#define LOPT_LOG_OPTS 266
#define LOPT_MAX_LOGS 267
#define LOPT_CIRCUIT 268
#define LOPT_REMOTE 269
#define LOPT_SUBSCR 270
#define LOPT_INTNAME 271
#define LOPT_BANK 272
#define LOPT_DHCP_HOST 273
#define LOPT_APREF 274
#define LOPT_OVERRIDE 275
#define LOPT_TFTPPORTS 276
#define LOPT_REBIND 277
#define LOPT_NOLAST 278
#define LOPT_OPTS 279
#define LOPT_DHCP_OPTS 280
#define LOPT_MATCH 281
#define LOPT_BROADCAST 282
#define LOPT_NEGTTL 283
#define LOPT_ALTPORT 284
#define LOPT_SCRIPTUSR 285
#define LOPT_LOCAL 286
#define LOPT_NAPTR 287
#define LOPT_MINPORT 288
#define LOPT_DHCP_FQDN 289
#define LOPT_CNAME 290
#define LOPT_PXE_PROMT 291
#define LOPT_PXE_SERV 292
#define LOPT_TEST 293
#define LOPT_TAG_IF 294
#define LOPT_PROXY 295
#define LOPT_GEN_NAMES 296
#define LOPT_MAXTTL 297
#define LOPT_NO_REBIND 298
#define LOPT_LOC_REBND 299
#define LOPT_ADD_MAC 300
#define LOPT_DNSSEC 301
#define LOPT_INCR_ADDR 302
#define LOPT_CONNTRACK 303
#define LOPT_FQDN 304
#define LOPT_LUASCRIPT 305
#define LOPT_RA 306
#define LOPT_DUID 307
#define LOPT_HOST_REC 308
#define LOPT_TFTP_LC 309
#define LOPT_RR 310
#define LOPT_CLVERBIND 311
#define LOPT_MAXCTTL 312
#define LOPT_AUTHZONE 313
#define LOPT_AUTHSERV 314
#define LOPT_AUTHTTL 315
#define LOPT_AUTHSOA 316
#define LOPT_AUTHSFS 317
#define LOPT_AUTHPEER 318
#define LOPT_IPSET 319
#define LOPT_SYNTH 320
#define LOPT_RELOAD 256
#define LOPT_NO_NAMES 257
#define LOPT_TFTP 258
#define LOPT_SECURE 259
#define LOPT_PREFIX 260
#define LOPT_PTR 261
#define LOPT_BRIDGE 262
#define LOPT_TFTP_MAX 263
#define LOPT_FORCE 264
#define LOPT_NOBLOCK 265
#define LOPT_LOG_OPTS 266
#define LOPT_MAX_LOGS 267
#define LOPT_CIRCUIT 268
#define LOPT_REMOTE 269
#define LOPT_SUBSCR 270
#define LOPT_INTNAME 271
#define LOPT_BANK 272
#define LOPT_DHCP_HOST 273
#define LOPT_APREF 274
#define LOPT_OVERRIDE 275
#define LOPT_TFTPPORTS 276
#define LOPT_REBIND 277
#define LOPT_NOLAST 278
#define LOPT_OPTS 279
#define LOPT_DHCP_OPTS 280
#define LOPT_MATCH 281
#define LOPT_BROADCAST 282
#define LOPT_NEGTTL 283
#define LOPT_ALTPORT 284
#define LOPT_SCRIPTUSR 285
#define LOPT_LOCAL 286
#define LOPT_NAPTR 287
#define LOPT_MINPORT 288
#define LOPT_DHCP_FQDN 289
#define LOPT_CNAME 290
#define LOPT_PXE_PROMT 291
#define LOPT_PXE_SERV 292
#define LOPT_TEST 293
#define LOPT_TAG_IF 294
#define LOPT_PROXY 295
#define LOPT_GEN_NAMES 296
#define LOPT_MAXTTL 297
#define LOPT_NO_REBIND 298
#define LOPT_LOC_REBND 299
#define LOPT_ADD_MAC 300
#define LOPT_DNSSEC 301
#define LOPT_INCR_ADDR 302
#define LOPT_CONNTRACK 303
#define LOPT_FQDN 304
#define LOPT_LUASCRIPT 305
#define LOPT_RA 306
#define LOPT_DUID 307
#define LOPT_HOST_REC 308
#define LOPT_TFTP_LC 309
#define LOPT_RR 310
#define LOPT_CLVERBIND 311
#define LOPT_MAXCTTL 312
#define LOPT_AUTHZONE 313
#define LOPT_AUTHSERV 314
#define LOPT_AUTHTTL 315
#define LOPT_AUTHSOA 316
#define LOPT_AUTHSFS 317
#define LOPT_AUTHPEER 318
#define LOPT_IPSET 319
#define LOPT_SYNTH 320
#ifdef OPTION6_PREFIX_CLASS
#define LOPT_PREF_CLSS 321
#define LOPT_PREF_CLSS 321
#endif
#define LOPT_RELAY 323
#define LOPT_RA_PARAM 324
#define LOPT_ADD_SBNET 325
#define LOPT_QUIET_DHCP 326
#define LOPT_QUIET_DHCP6 327
#define LOPT_QUIET_RA 328
#define LOPT_SEC_VALID 329
#define LOPT_TRUST_ANCHOR 330
#define LOPT_DNSSEC_DEBUG 331
#define LOPT_REV_SERV 332
#define LOPT_SERVERS_FILE 333
#define LOPT_RELAY 323
#define LOPT_RA_PARAM 324
#define LOPT_ADD_SBNET 325
#define LOPT_QUIET_DHCP 326
#define LOPT_QUIET_DHCP6 327
#define LOPT_QUIET_RA 328
#define LOPT_SEC_VALID 329
#define LOPT_TRUST_ANCHOR 330
#define LOPT_DNSSEC_DEBUG 331
#define LOPT_REV_SERV 332
#define LOPT_SERVERS_FILE 333
#define LOPT_DNSSEC_CHECK 334
#define LOPT_LOCAL_SERVICE 335
#define LOPT_DNSSEC_TIME 336
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -174,6 +177,7 @@ static const struct myoption opts[] =
{ "domain-suffix", 1, 0, 's' },
{ "interface", 1, 0, 'i' },
{ "listen-address", 1, 0, 'a' },
{ "local-service", 0, 0, LOPT_LOCAL_SERVICE },
{ "bogus-priv", 0, 0, 'b' },
{ "bogus-nxdomain", 1, 0, 'B' },
{ "selfmx", 0, 0, 'e' },
@@ -283,6 +287,8 @@ static const struct myoption opts[] =
{ "dnssec", 0, 0, LOPT_SEC_VALID },
{ "trust-anchor", 1, 0, LOPT_TRUST_ANCHOR },
{ "dnssec-debug", 0, 0, LOPT_DNSSEC_DEBUG },
{ "dnssec-check-unsigned", 0, 0, LOPT_DNSSEC_CHECK },
{ "dnssec-no-timecheck", 0, 0, LOPT_DNSSEC_TIME },
#ifdef OPTION6_PREFIX_CLASS
{ "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
#endif
@@ -438,6 +444,8 @@ static struct {
{ 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 },
{ LOPT_DNSSEC_DEBUG, OPT_DNSSEC_DEBUG, NULL, gettext_noop("Disable upstream checking for DNSSEC debugging."), NULL },
{ LOPT_DNSSEC_CHECK, OPT_DNSSEC_NO_SIGN, NULL, gettext_noop("Ensure answers without DNSSEC are in unsigned zones."), NULL },
{ LOPT_DNSSEC_TIME, OPT_DNSSEC_TIME, NULL, gettext_noop("Don't check DNSSEC signature timestamps until first cache-reload"), NULL },
#ifdef OPTION6_PREFIX_CLASS
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
#endif
@@ -445,6 +453,7 @@ static struct {
{ 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 },
{ 0, 0, NULL, NULL, NULL }
};
@@ -609,19 +618,24 @@ static int atoi_check8(char *a, int *res)
}
#endif
static void add_txt(char *name, char *txt)
static void add_txt(char *name, char *txt, int stat)
{
size_t len = strlen(txt);
struct txt_record *r = opt_malloc(sizeof(struct txt_record));
if (txt)
{
size_t len = strlen(txt);
r->txt = opt_malloc(len+1);
r->len = len+1;
*(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;
r->txt = opt_malloc(len+1);
r->len = len+1;
*(r->txt) = len;
memcpy((r->txt)+1, txt, len);
}
static void do_usage(void)
@@ -1658,7 +1672,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case 'H': /* --addn-hosts */
{
struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
static int hosts_index = 1;
static unsigned int hosts_index = SRC_AH;
new->fname = opt_string_alloc(arg);
new->index = hosts_index++;
new->flags = 0;
@@ -3603,7 +3617,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->next = daemon->txt;
daemon->txt = new;
new->class = C_IN;
new->stat = 0;
if (!(new->name = canonicalise_opt(arg)))
ret_err(_("bad TXT record"));
@@ -4014,10 +4029,11 @@ static int one_file(char *file, int hard_opt)
/* expand any name which is a directory */
struct hostsfile *expand_filelist(struct hostsfile *list)
{
int i;
unsigned int i;
struct hostsfile *ah;
for (i = 0, ah = list; ah; ah = ah->next)
/* find largest used index */
for (i = SRC_AH, ah = list; ah; ah = ah->next)
{
if (i <= ah->index)
i = ah->index + 1;
@@ -4251,9 +4267,18 @@ 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;
add_txt("version.bind", "dnsmasq-" VERSION );
add_txt("authors.bind", "Simon Kelley");
add_txt("copyright.bind", COPYRIGHT);
add_txt("version.bind", "dnsmasq-" VERSION, 0 );
add_txt("authors.bind", "Simon Kelley", 0);
add_txt("copyright.bind", COPYRIGHT, 0);
add_txt("cachesize.bind", NULL, TXT_STAT_CACHESIZE);
add_txt("insertions.bind", NULL, TXT_STAT_INSERTS);
add_txt("evictions.bind", NULL, TXT_STAT_EVICTIONS);
add_txt("misses.bind", NULL, TXT_STAT_MISSES);
add_txt("hits.bind", NULL, TXT_STAT_HITS);
#ifdef HAVE_AUTH
add_txt("auth.bind", NULL, TXT_STAT_AUTH);
#endif
add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
while (1)
{
@@ -4454,6 +4479,11 @@ void read_opts(int argc, char **argv, char *compile_opts)
else if (option_bool(OPT_DHCP_FQDN))
die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
/* If there's access-control config, then ignore --local-service, it's intended
as a system default to keep otherwise unconfigured installations safe. */
if (daemon->if_names || daemon->if_except || daemon->if_addrs || daemon->authserver)
reset_option_bool(OPT_LOCAL_SERVICE);
if (testmode)
{
fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));

View File

@@ -601,11 +601,11 @@ static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *p
if (family == parm->l3->sa.sa_family)
{
if (family == AF_INET && memcmp (&parm->l3->in.sin_addr, addrp, INADDRSZ) == 0)
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)
if (family == AF_INET6 && memcmp(&parm->l3->in6.sin6_addr, addrp, IN6ADDRSZ) == 0)
match = 1;
#endif
}
@@ -917,8 +917,8 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
searched_soa = 1;
ttl = find_soa(header, qlen, name, doctored);
#ifdef HAVE_DNSSEC
if (*doctored)
secure = 0;
if (*doctored && secure)
return 0;
#endif
}
@@ -927,7 +927,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
for (i = ntohs(header->qdcount); i != 0; i--)
{
int found = 0, cname_count = 5;
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;
@@ -988,9 +988,8 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
if (aqtype == T_CNAME)
{
if (!cname_count--)
return 0; /* looped CNAMES */
secflag = 0; /* no longer DNSSEC */
if (!cname_count-- || secure)
return 0; /* looped CNAMES, or DNSSEC, which we can't cache. */
goto cname_loop;
}
@@ -1066,6 +1065,8 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
if (newc)
{
newc->addr.cname.target.cache = NULL;
/* anything other than zero, to avoid being mistaken for CNAME to interface-name */
newc->addr.cname.uid = 1;
if (cpp)
{
cpp->addr.cname.target.cache = newc;
@@ -1101,7 +1102,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
{
ipsets_cur = ipsets;
while (*ipsets_cur)
add_to_ipset(*ipsets_cur++, &addr, flags, 0);
{
log_query((flags & (F_IPV4 | F_IPV6)) | F_IPSET, name, &addr, *ipsets_cur);
add_to_ipset(*ipsets_cur++, &addr, flags, 0);
}
}
#endif
@@ -1242,7 +1246,7 @@ int check_for_local_domain(char *name, time_t now)
struct ptr_record *ptr;
struct naptr *naptr;
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_NO_RR)) &&
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_DS | F_NO_RR)) &&
(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
return 1;
@@ -1453,11 +1457,11 @@ 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)
time_t now, int *ad_reqd, int *do_bit)
{
char *name = daemon->namebuff;
unsigned char *p, *ansp, *pheader;
int qtype, qclass;
unsigned int qtype, qclass;
struct all_addr addr;
int nameoffset;
unsigned short flag;
@@ -1475,7 +1479,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
/* 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
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
@@ -1493,7 +1498,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
pheader += 2; /* ext_rcode */
GETSHORT(flags, pheader);
sec_reqd = flags & 0x8000; /* do bit */
if ((sec_reqd = flags & 0x8000))
*do_bit = 1;/* do bit */
*ad_reqd = 1;
/* If our client is advertising a larger UDP packet size
@@ -1544,10 +1550,20 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
ans = 1;
if (!dryrun)
{
unsigned long ttl = daemon->local_ttl;
int ok = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->local_ttl, NULL,
T_TXT, t->class, "t", t->len, t->txt))
/* Dynamically generate stat record */
if (t->stat != 0)
{
ttl = 0;
if (!cache_make_stat(t))
ok = 0;
}
if (ok && add_resource_record(header, limit, &trunc, nameoffset, &ansp,
ttl, NULL,
T_TXT, t->class, "t", t->len, t->txt))
anscount++;
}
@@ -1578,19 +1594,29 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
while ((crecp = cache_find_by_name(crecp, name, now, F_DS)))
if (crecp->uid == qclass)
{
gotone = 1;
if (!dryrun && (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++;
}
gotone = 1;
if (!dryrun)
{
if (crecp->flags & F_NEG)
{
if (crecp->flags & F_NXDOMAIN)
nxdomain = 1;
log_query(F_UPSTREAM, name, NULL, "secure 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 */
@@ -2005,7 +2031,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
strcpy(name, cname_target);
/* check if target interface_name */
if (crecp->addr.cname.uid == -1)
if (crecp->addr.cname.uid == SRC_INTERFACE)
goto intname_restart;
else
goto cname_restart;

View File

@@ -962,6 +962,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
case DHCPDISCOVER:
if (ignore || have_config(config, CONFIG_DISABLE))
{
if (option_bool(OPT_QUIET_DHCP))
return 0;
message = _("ignored");
opt = NULL;
}