Compare commits

...
21 Commits
Author SHA1 Message Date
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
15 changed files with 496 additions and 243 deletions

No files matched your search

+49 -3
View File
@@ -1,3 +1,12 @@
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 +37,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 +65,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
@@ -80,6 +119,13 @@ version 2.69
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
+12 -4
View File
@@ -1,11 +1,19 @@
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
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
+1 -1
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
+8
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,
+55 -75
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>
+23 -4
View File
@@ -636,6 +636,15 @@ 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
@@ -666,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
@@ -1753,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
@@ -2014,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.
+2 -2
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
+4 -2
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;
}
+102
View File
@@ -1262,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)
{
@@ -1514,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";
+17 -3
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;
@@ -667,7 +667,11 @@ int main (int argc, char **argv)
#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)
@@ -1130,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))
+13 -1
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,7 +231,7 @@ 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_DNSSEC_NO_SIGN 48
#define OPT_LOCAL_SERVICE 49
@@ -280,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;
};
@@ -426,6 +436,7 @@ 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
@@ -1027,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);
+7 -1
View File
@@ -390,7 +390,13 @@ static int serial_compare_32(unsigned long s1, unsigned long s2)
/* Check whether today/now is between date_start and date_end */
static int check_date_range(unsigned long date_start, unsigned long date_end)
{
unsigned long curtime = time(0);
unsigned long curtime;
/* Checking timestamps may be temporarily disabled */
if (option_bool(OPT_DNSSEC_TIME))
return 1;
curtime = time(0);
/* We must explicitly check against wanted values, because of SERIAL_UNDEF */
return serial_compare_32(curtime, date_start) == SERIAL_GT
+80 -55
View File
@@ -535,20 +535,23 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
(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
@@ -698,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
@@ -713,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)
@@ -747,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
{
@@ -770,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;
@@ -784,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;
@@ -850,6 +856,7 @@ 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;
@@ -1325,6 +1332,10 @@ static int send_check_sign(time_t now, struct dns_header *header, size_t plen, c
continue;
}
/* Reached the root */
if (!name_start)
return STAT_BOGUS;
strcpy(keyname, name_start);
return STAT_NEED_DS_NEG;
}
@@ -1390,8 +1401,11 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s
struct crec *crecp = cache_find_by_name(NULL, name_start, now, F_DS);
if (--(*keycount) == 0)
return STAT_BOGUS;
{
free(packet);
return STAT_BOGUS;
}
if (crecp && (crecp->flags & F_DNSSECOK))
{
free(packet);
@@ -1406,46 +1420,55 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s
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;
memcpy(hash, newhash, HASH_SIZE);
*length = htons(m);
newhash = hash_questions(header, (unsigned int)m, name);
if (newhash && memcmp(hash, newhash, HASH_SIZE) == 0)
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))
{
/* 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;
}
m = (c1 << 8) | c2;
/* No DS, not got to DNSSEC-land yet, go up. */
if (status == STAT_INSECURE)
newhash = hash_questions(header, (unsigned int)m, name);
if (newhash && memcmp(hash, newhash, HASH_SIZE) == 0)
{
p = (unsigned char *)(header+1);
/* Note this trashes all three name workspaces */
status = tcp_key_recurse(now, STAT_NEED_DS_NEG, header, m, class, name, keyname, server, keycount);
if (extract_name(header, plen, &p, name, 1, 4) &&
(name_start = strchr(name, '.')))
/* 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)
{
name_start++; /* chop a label off and try again */
continue;
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;
}
}
}
}
@@ -1722,8 +1745,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
+106 -88
View File
@@ -64,87 +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_DNSSEC_CHECK 334
#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[] =
@@ -287,6 +288,7 @@ static const struct myoption opts[] =
{ "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
@@ -443,6 +445,7 @@ static struct {
{ 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
@@ -615,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)
@@ -3609,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"));
@@ -4258,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)
{
+17 -4
View File
@@ -1102,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
@@ -1547,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++;
}