mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-06 15:51:41 +00:00
Compare commits
33
Commits
v2.69test11
...
v2.69
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
198d940af6 | ||
|
|
1d7e0a36e3 | ||
|
|
10068600f8 | ||
|
|
b7639d5815 | ||
|
|
49752b90d5 | ||
|
|
e98bd52e25 | ||
|
|
8a8bbad0cf | ||
|
|
fec216df32 | ||
|
|
4e1fe44428 | ||
|
|
51967f9807 | ||
|
|
b37f8b99ae | ||
|
|
fc2833f172 | ||
|
|
490f90758d | ||
|
|
56618c31f6 | ||
|
|
604f7598c2 | ||
|
|
2a7a2b84ec | ||
|
|
3e21a1a6fa | ||
|
|
2b29191e7c | ||
|
|
03431d6373 | ||
|
|
cc1a29e250 | ||
|
|
e62e9b6187 | ||
|
|
19c51cfa49 | ||
|
|
d5082158ee | ||
|
|
3f7483e816 | ||
|
|
0c8584eabc | ||
|
|
f00690f93e | ||
|
|
89b12ed35b | ||
|
|
1a9a3489ec | ||
|
|
c8a80487cd | ||
|
|
4ea8e80dd9 | ||
|
|
c07d30dcb1 | ||
|
|
d588ab54d4 | ||
|
|
f8b422a7b6 |
No files matched your search
@@ -28,9 +28,9 @@ version 2.69
|
|||||||
|
|
||||||
make dnsmasq COPTS='-DHAVE_DNSSEC -DHAVE_DNSSEC_STATIC'
|
make dnsmasq COPTS='-DHAVE_DNSSEC -DHAVE_DNSSEC_STATIC'
|
||||||
|
|
||||||
which bloats the dnsmasq binary to over a megabyte, but
|
which bloats the dnsmasq binary, but saves the size of
|
||||||
saves the size of the shared libraries which are five
|
the shared libraries which are much bigger.
|
||||||
times that size.
|
|
||||||
To enable, DNSSEC, you will need a set of
|
To enable, DNSSEC, you will need a set of
|
||||||
trust-anchors. Now that the TLDs are signed, this can be
|
trust-anchors. Now that the TLDs are signed, this can be
|
||||||
the keys for the root zone, and for convenience they are
|
the keys for the root zone, and for convenience they are
|
||||||
@@ -56,6 +56,36 @@ version 2.69
|
|||||||
downstream validators. Setting --log-queries will show
|
downstream validators. Setting --log-queries will show
|
||||||
DNSSEC in action.
|
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
|
The development of DNSSEC in dnsmasq was started by
|
||||||
Giovanni Bajo, to whom huge thanks are owed. It has been
|
Giovanni Bajo, to whom huge thanks are owed. It has been
|
||||||
supported by Comcast, whose techfund grant has allowed for
|
supported by Comcast, whose techfund grant has allowed for
|
||||||
@@ -67,7 +97,27 @@ version 2.69
|
|||||||
Add --servers-file. Allows dynamic update of upstream servers
|
Add --servers-file. Allows dynamic update of upstream servers
|
||||||
full access to configuration.
|
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
|
version 2.68
|
||||||
Use random addresses for DHCPv6 temporary address
|
Use random addresses for DHCPv6 temporary address
|
||||||
allocations, instead of algorithmically determined stable
|
allocations, instead of algorithmically determined stable
|
||||||
|
|||||||
+4
-1
@@ -14,8 +14,11 @@ if grep "^\#[[:space:]]*define[[:space:]]*$search" config.h >/dev/null 2>&1 || \
|
|||||||
|
|
||||||
if [ $op = "--copy" ]; then
|
if [ $op = "--copy" ]; then
|
||||||
pkg="$*"
|
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
|
else
|
||||||
pkg=`$pkg $op $*`
|
pkg=`$pkg $op $*`
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
|
if grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
|
||||||
|
|||||||
Vendored
+6
@@ -1,6 +1,12 @@
|
|||||||
dnsmasq (2.69-1) unstable; urgency=low
|
dnsmasq (2.69-1) unstable; urgency=low
|
||||||
|
|
||||||
* New upstream.
|
* 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
|
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 4 Feb 2014 16:28:12 +0000
|
||||||
|
|
||||||
|
|||||||
Vendored
+8
@@ -90,6 +90,14 @@ if [ ! "$DNSMASQ_USER" ]; then
|
|||||||
DNSMASQ_USER="dnsmasq"
|
DNSMASQ_USER="dnsmasq"
|
||||||
fi
|
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()
|
start()
|
||||||
{
|
{
|
||||||
# Return
|
# Return
|
||||||
|
|||||||
@@ -25,6 +25,14 @@
|
|||||||
#conf-file=%%PREFIX%%/share/dnsmasq/trust-anchors.conf
|
#conf-file=%%PREFIX%%/share/dnsmasq/trust-anchors.conf
|
||||||
#dnssec
|
#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
|
# Uncomment this to filter useless windows-originated DNS requests
|
||||||
# which can trigger dial-on-demand links needlessly.
|
# which can trigger dial-on-demand links needlessly.
|
||||||
# Note that (amongst other things) this blocks all SRV requests,
|
# Note that (amongst other things) this blocks all SRV requests,
|
||||||
|
|||||||
+46
-8
@@ -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,
|
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
|
it may be qualified with "/4" or "/6" to specify only the IPv4 or IPv6
|
||||||
addresses associated with the interface.
|
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
|
.TP
|
||||||
.B \-2, --no-dhcp-interface=<interface name>
|
.B \-2, --no-dhcp-interface=<interface name>
|
||||||
Do not provide DHCP or TFTP on the specified interface, but do provide DNS service.
|
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
|
the dnsmasq server and the client is trusted. Dnsmasq must be compiled with HAVE_DNSSEC enabled, and DNSSEC
|
||||||
trust anchors provided, see
|
trust anchors provided, see
|
||||||
.B --trust-anchor.
|
.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
|
.TP
|
||||||
.B --trust-anchor=[<class>],<domain>,<key-tag>,<algorithm>,<digest-type>,<digest>
|
.B --trust-anchor=[<class>],<domain>,<key-tag>,<algorithm>,<digest-type>,<digest>
|
||||||
Provide DS records to act a trust anchors for DNSSEC
|
Provide DS records to act a trust anchors for DNSSEC
|
||||||
@@ -615,7 +631,19 @@ legitimate: they are assumed to be valid and passed on (without the
|
|||||||
attacker forging unsigned replies for signed DNS zones, but it is
|
attacker forging unsigned replies for signed DNS zones, but it is
|
||||||
fast. If this flag is set, dnsmasq will check the zones of unsigned
|
fast. If this flag is set, dnsmasq will check the zones of unsigned
|
||||||
replies, to ensure that unsigned replies are allowed in those
|
replies, to ensure that unsigned replies are allowed in those
|
||||||
zones. The cost of this is more upstream queries and slower performance.
|
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
|
.TP
|
||||||
.B --proxy-dnssec
|
.B --proxy-dnssec
|
||||||
Copy the DNSSEC Authenticated Data bit from upstream servers to downstream clients and cache it. This is an
|
Copy the DNSSEC Authenticated Data bit from upstream servers to downstream clients and cache it. This is an
|
||||||
@@ -647,7 +675,7 @@ Interface-name and address-literal subnet specifications may be used
|
|||||||
freely in the same --auth-zone declaration.
|
freely in the same --auth-zone declaration.
|
||||||
|
|
||||||
The subnet(s) are also used to define in-addr.arpa and
|
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.
|
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
|
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
|
unless you are familiar with RFC 2317 and have arranged the
|
||||||
@@ -754,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
|
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
|
Information-request packets on a subnet which is provided with
|
||||||
stateless DHCPv6, ie
|
stateless DHCPv6, ie
|
||||||
.B --dhcp=range=::,static
|
.B --dhcp-range=::,static
|
||||||
|
|
||||||
For IPv4, the <mode> may be
|
For IPv4, the <mode> may be
|
||||||
.B proxy
|
.B proxy
|
||||||
@@ -1734,12 +1762,22 @@ When it receives a SIGUSR1,
|
|||||||
writes statistics to the system log. It writes the cache size,
|
writes statistics to the system log. It writes the cache size,
|
||||||
the number of names which have had to removed from the cache before
|
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
|
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
|
server it gives the number of queries sent, and the number which
|
||||||
resulted in an error. In
|
resulted in an error. In
|
||||||
.B --no-daemon
|
.B --no-daemon
|
||||||
mode or when full logging is enabled (-q), a complete dump of the
|
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
|
.PP
|
||||||
When it receives SIGUSR2 and it is logging direct to a file (see
|
When it receives SIGUSR2 and it is logging direct to a file (see
|
||||||
.B --log-facility
|
.B --log-facility
|
||||||
@@ -1843,7 +1881,7 @@ which has tags will be used in preference to an untagged
|
|||||||
.B dhcp-option,
|
.B dhcp-option,
|
||||||
provided that _all_ the tags match somewhere in the
|
provided that _all_ the tags match somewhere in the
|
||||||
set collected as described above. The prefix '!' on a tag means 'not'
|
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
|
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 !,
|
command line rather than a configuration file, be sure to escape !,
|
||||||
which is a shell metacharacter)
|
which is a shell metacharacter)
|
||||||
@@ -1995,7 +2033,7 @@ to particular hosts then
|
|||||||
will do so.
|
will do so.
|
||||||
|
|
||||||
Dnsmasq acts as an authoritative server for in-addr.arpa and
|
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
|
declarations, so reverse (address to name) lookups can be simply
|
||||||
configured with a suitable NS record, for instance in this example,
|
configured with a suitable NS record, for instance in this example,
|
||||||
where we allow 1.2.3.0/24 addresses.
|
where we allow 1.2.3.0/24 addresses.
|
||||||
|
|||||||
+2
-2
@@ -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
|
(ce comportement peut-être désactivé par
|
||||||
.B constructor-noauth:
|
.B constructor-noauth:
|
||||||
). Le ou les sous-réseaux sont également utilisé(s) pour définir les domaines
|
). 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
|
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
|
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
|
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
|
.fi
|
||||||
|
|
||||||
Dnsmasq joue le rôle de serveur faisant autorité pour les domaines in-addr.arpa
|
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
|
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
|
le nom) peuvent-simplement être configurées avec un enregistrement NS
|
||||||
adéquat. Par exemple, comme nous définissons plus haut les adresses
|
adéquat. Par exemple, comme nous définissons plus haut les adresses
|
||||||
|
|||||||
+4
-2
@@ -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)));
|
} while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
|
||||||
|
|
||||||
if (!found)
|
if (found)
|
||||||
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | F_AUTH, NULL, &addr, NULL);
|
nxdomain = 0;
|
||||||
|
else
|
||||||
|
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
+133
-17
@@ -24,7 +24,6 @@ static struct crec *new_chain = NULL;
|
|||||||
static int cache_inserted = 0, cache_live_freed = 0, insert_error;
|
static int cache_inserted = 0, cache_live_freed = 0, insert_error;
|
||||||
static union bigname *big_free = NULL;
|
static union bigname *big_free = NULL;
|
||||||
static int bignames_left, hash_size;
|
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. */
|
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
|
||||||
static const struct {
|
static const struct {
|
||||||
@@ -73,6 +72,19 @@ static void cache_link(struct crec *crecp);
|
|||||||
static void rehash(int size);
|
static void rehash(int size);
|
||||||
static void cache_hash(struct crec *crecp);
|
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)
|
void cache_init(void)
|
||||||
{
|
{
|
||||||
struct crec *crecp;
|
struct crec *crecp;
|
||||||
@@ -88,7 +100,7 @@ void cache_init(void)
|
|||||||
{
|
{
|
||||||
cache_link(crecp);
|
cache_link(crecp);
|
||||||
crecp->flags = 0;
|
crecp->flags = 0;
|
||||||
crecp->uid = uid++;
|
crecp->uid = next_uid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,10 +204,7 @@ static void cache_free(struct crec *crecp)
|
|||||||
{
|
{
|
||||||
crecp->flags &= ~F_FORWARD;
|
crecp->flags &= ~F_FORWARD;
|
||||||
crecp->flags &= ~F_REVERSE;
|
crecp->flags &= ~F_REVERSE;
|
||||||
crecp->uid = uid++; /* invalidate CNAMES pointing to this. */
|
crecp->uid = next_uid(); /* invalidate CNAMES pointing to this. */
|
||||||
|
|
||||||
if (uid == -1)
|
|
||||||
uid++;
|
|
||||||
|
|
||||||
if (cache_tail)
|
if (cache_tail)
|
||||||
cache_tail->next = crecp;
|
cache_tail->next = crecp;
|
||||||
@@ -256,7 +265,7 @@ char *cache_get_name(struct crec *crecp)
|
|||||||
|
|
||||||
char *cache_get_cname_target(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 cache_get_name(crecp->addr.cname.target.cache);
|
||||||
|
|
||||||
return crecp->addr.cname.target.int_name->name;
|
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)
|
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;
|
return 0;
|
||||||
|
|
||||||
/* NB. record may be reused as DS or DNSKEY, where uid is
|
/* NB. record may be reused as DS or DNSKEY, where uid is
|
||||||
@@ -774,13 +783,14 @@ static void add_hosts_cname(struct crec *target)
|
|||||||
crec->name.namep = a->alias;
|
crec->name.namep = a->alias;
|
||||||
crec->addr.cname.target.cache = target;
|
crec->addr.cname.target.cache = target;
|
||||||
crec->addr.cname.uid = target->uid;
|
crec->addr.cname.uid = target->uid;
|
||||||
|
crec->uid = next_uid();
|
||||||
cache_hash(crec);
|
cache_hash(crec);
|
||||||
add_hosts_cname(crec); /* handle chains */
|
add_hosts_cname(crec); /* handle chains */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
|
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));
|
struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6));
|
||||||
int i, nameexists = 0;
|
int i, nameexists = 0;
|
||||||
@@ -884,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");
|
FILE *f = fopen(filename, "r");
|
||||||
char *token = daemon->namebuff, *domain_suffix = NULL;
|
char *token = daemon->namebuff, *domain_suffix = NULL;
|
||||||
@@ -1034,7 +1044,8 @@ void cache_reload(void)
|
|||||||
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
|
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
|
||||||
cache->name.namep = a->alias;
|
cache->name.namep = a->alias;
|
||||||
cache->addr.cname.target.int_name = intr;
|
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);
|
cache_hash(cache);
|
||||||
add_hosts_cname(cache); /* handle chains */
|
add_hosts_cname(cache); /* handle chains */
|
||||||
}
|
}
|
||||||
@@ -1070,7 +1081,7 @@ void cache_reload(void)
|
|||||||
{
|
{
|
||||||
cache->name.namep = nl->name;
|
cache->name.namep = nl->name;
|
||||||
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG;
|
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
|
#ifdef HAVE_IPV6
|
||||||
if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) &&
|
if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) &&
|
||||||
@@ -1078,7 +1089,7 @@ void cache_reload(void)
|
|||||||
{
|
{
|
||||||
cache->name.namep = nl->name;
|
cache->name.namep = nl->name;
|
||||||
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG;
|
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
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1091,7 +1102,7 @@ void cache_reload(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!option_bool(OPT_NO_HOSTS))
|
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);
|
daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
|
||||||
for (ah = daemon->addn_hosts; ah; ah = ah->next)
|
for (ah = daemon->addn_hosts; ah; ah = ah->next)
|
||||||
@@ -1155,6 +1166,7 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
|
|||||||
aliasc->name.namep = a->alias;
|
aliasc->name.namep = a->alias;
|
||||||
aliasc->addr.cname.target.cache = target;
|
aliasc->addr.cname.target.cache = target;
|
||||||
aliasc->addr.cname.uid = target->uid;
|
aliasc->addr.cname.uid = target->uid;
|
||||||
|
aliasc->uid = next_uid();
|
||||||
cache_hash(aliasc);
|
cache_hash(aliasc);
|
||||||
add_dhcp_cname(aliasc, ttd);
|
add_dhcp_cname(aliasc, ttd);
|
||||||
}
|
}
|
||||||
@@ -1242,7 +1254,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
|||||||
crec->ttd = ttd;
|
crec->ttd = ttd;
|
||||||
crec->addr.addr = *host_address;
|
crec->addr.addr = *host_address;
|
||||||
crec->name.namep = host_name;
|
crec->name.namep = host_name;
|
||||||
crec->uid = uid++;
|
crec->uid = next_uid();
|
||||||
cache_hash(crec);
|
cache_hash(crec);
|
||||||
|
|
||||||
add_dhcp_cname(crec, ttd);
|
add_dhcp_cname(crec, ttd);
|
||||||
@@ -1250,6 +1262,101 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
|||||||
}
|
}
|
||||||
#endif
|
#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)
|
void dump_cache(time_t now)
|
||||||
{
|
{
|
||||||
@@ -1368,11 +1475,13 @@ void dump_cache(time_t now)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *record_source(int index)
|
char *record_source(unsigned int index)
|
||||||
{
|
{
|
||||||
struct hostsfile *ah;
|
struct hostsfile *ah;
|
||||||
|
|
||||||
if (index == 0)
|
if (index == SRC_CONFIG)
|
||||||
|
return "config";
|
||||||
|
else if (index == SRC_HOSTS)
|
||||||
return HOSTSFILE;
|
return HOSTSFILE;
|
||||||
|
|
||||||
for (ah = daemon->addn_hosts; ah; ah = ah->next)
|
for (ah = daemon->addn_hosts; ah; ah = ah->next)
|
||||||
@@ -1500,6 +1609,13 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
|
|||||||
source = arg;
|
source = arg;
|
||||||
verb = "to";
|
verb = "to";
|
||||||
}
|
}
|
||||||
|
else if (flags & F_IPSET)
|
||||||
|
{
|
||||||
|
source = "ipset add";
|
||||||
|
dest = name;
|
||||||
|
name = arg;
|
||||||
|
verb = daemon->addrbuff;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
source = "cached";
|
source = "cached";
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||||
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
|
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
|
||||||
#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
|
#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 DNSSEC_WORK 50 /* Max number of queries to validate one question */
|
||||||
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
||||||
#define FORWARD_TEST 50 /* try all servers every 50 queries */
|
#define FORWARD_TEST 50 /* try all servers every 50 queries */
|
||||||
|
|||||||
+20
-3
@@ -397,7 +397,7 @@ int main (int argc, char **argv)
|
|||||||
piperead = pipefd[0];
|
piperead = pipefd[0];
|
||||||
pipewrite = pipefd[1];
|
pipewrite = pipefd[1];
|
||||||
/* prime the pipe to load stuff first time. */
|
/* 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;
|
err_pipe[1] = -1;
|
||||||
|
|
||||||
@@ -661,10 +661,17 @@ int main (int argc, char **argv)
|
|||||||
my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
|
my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (option_bool(OPT_LOCAL_SERVICE))
|
||||||
|
my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
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
|
#endif
|
||||||
|
|
||||||
if (log_err != 0)
|
if (log_err != 0)
|
||||||
@@ -1127,8 +1134,18 @@ static void async_event(int pipe, time_t now)
|
|||||||
switch (ev.event)
|
switch (ev.event)
|
||||||
{
|
{
|
||||||
case EVENT_RELOAD:
|
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);
|
clear_cache_and_reload(now);
|
||||||
|
|
||||||
if (daemon->port != 0)
|
if (daemon->port != 0)
|
||||||
{
|
{
|
||||||
if (daemon->resolv_files && option_bool(OPT_NO_POLL))
|
if (daemon->resolv_files && option_bool(OPT_NO_POLL))
|
||||||
|
|||||||
+26
-6
@@ -164,6 +164,7 @@ struct event_desc {
|
|||||||
#define EVENT_FORK_ERR 18
|
#define EVENT_FORK_ERR 18
|
||||||
#define EVENT_LUA_ERR 19
|
#define EVENT_LUA_ERR 19
|
||||||
#define EVENT_TFTP_ERR 20
|
#define EVENT_TFTP_ERR 20
|
||||||
|
#define EVENT_INIT 21
|
||||||
|
|
||||||
/* Exit codes. */
|
/* Exit codes. */
|
||||||
#define EC_GOOD 0
|
#define EC_GOOD 0
|
||||||
@@ -230,10 +231,11 @@ struct event_desc {
|
|||||||
#define OPT_QUIET_DHCP6 43
|
#define OPT_QUIET_DHCP6 43
|
||||||
#define OPT_QUIET_RA 44
|
#define OPT_QUIET_RA 44
|
||||||
#define OPT_DNSSEC_VALID 45
|
#define OPT_DNSSEC_VALID 45
|
||||||
#define OPT_DNSSEC_PERMISS 46
|
#define OPT_DNSSEC_TIME 46
|
||||||
#define OPT_DNSSEC_DEBUG 47
|
#define OPT_DNSSEC_DEBUG 47
|
||||||
#define OPT_DNSSEC_NO_SIGN 48
|
#define OPT_DNSSEC_NO_SIGN 48
|
||||||
#define OPT_LAST 49
|
#define OPT_LOCAL_SERVICE 49
|
||||||
|
#define OPT_LAST 50
|
||||||
|
|
||||||
/* extra flags for my_syslog, we use a couple of facilities since they are known
|
/* 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. */
|
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
|
||||||
@@ -279,10 +281,19 @@ struct naptr {
|
|||||||
struct naptr *next;
|
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 {
|
struct txt_record {
|
||||||
char *name;
|
char *name;
|
||||||
unsigned char *txt;
|
unsigned char *txt;
|
||||||
unsigned short class, len;
|
unsigned short class, len;
|
||||||
|
int stat;
|
||||||
struct txt_record *next;
|
struct txt_record *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -366,7 +377,7 @@ struct crec {
|
|||||||
struct crec *cache;
|
struct crec *cache;
|
||||||
struct interface_name *int_name;
|
struct interface_name *int_name;
|
||||||
} target;
|
} target;
|
||||||
int uid; /* -1 if union is interface-name */
|
unsigned int uid; /* 0 if union is interface-name */
|
||||||
} cname;
|
} cname;
|
||||||
struct {
|
struct {
|
||||||
struct blockdata *keydata;
|
struct blockdata *keydata;
|
||||||
@@ -387,7 +398,7 @@ struct crec {
|
|||||||
} addr;
|
} addr;
|
||||||
time_t ttd; /* time to die */
|
time_t ttd; /* time to die */
|
||||||
/* used as class if DNSKEY/DS/RRSIG, index to source for F_HOSTS */
|
/* used as class if DNSKEY/DS/RRSIG, index to source for F_HOSTS */
|
||||||
int uid;
|
unsigned int uid;
|
||||||
unsigned short flags;
|
unsigned short flags;
|
||||||
union {
|
union {
|
||||||
char sname[SMALLDNAME];
|
char sname[SMALLDNAME];
|
||||||
@@ -425,6 +436,13 @@ struct crec {
|
|||||||
#define F_KEYTAG (1u<<23)
|
#define F_KEYTAG (1u<<23)
|
||||||
#define F_SECSTAT (1u<<24)
|
#define F_SECSTAT (1u<<24)
|
||||||
#define F_NO_RR (1u<<25)
|
#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,
|
/* struct sockaddr is not large enough to hold any address,
|
||||||
@@ -524,7 +542,7 @@ struct hostsfile {
|
|||||||
struct hostsfile *next;
|
struct hostsfile *next;
|
||||||
int flags;
|
int flags;
|
||||||
char *fname;
|
char *fname;
|
||||||
int index; /* matches to cache entries for logging */
|
unsigned int index; /* matches to cache entries for logging */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -966,6 +984,7 @@ extern struct daemon {
|
|||||||
pid_t tcp_pids[MAX_PROCS];
|
pid_t tcp_pids[MAX_PROCS];
|
||||||
struct randfd randomsocks[RANDOM_SOCKS];
|
struct randfd randomsocks[RANDOM_SOCKS];
|
||||||
int v6pktinfo;
|
int v6pktinfo;
|
||||||
|
struct addrlist *interface_addrs; /* list of all addresses/prefix lengths associated with all local interfaces */
|
||||||
|
|
||||||
/* DHCP state */
|
/* DHCP state */
|
||||||
int dhcpfd, helperfd, pxefd;
|
int dhcpfd, helperfd, pxefd;
|
||||||
@@ -1003,7 +1022,7 @@ extern struct daemon {
|
|||||||
/* cache.c */
|
/* cache.c */
|
||||||
void cache_init(void);
|
void cache_init(void);
|
||||||
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
|
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);
|
char *querystr(char *desc, unsigned short type);
|
||||||
struct crec *cache_find_by_addr(struct crec *crecp,
|
struct crec *cache_find_by_addr(struct crec *crecp,
|
||||||
struct all_addr *addr, time_t now,
|
struct all_addr *addr, time_t now,
|
||||||
@@ -1019,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);
|
struct in_addr a_record_from_hosts(char *name, time_t now);
|
||||||
void cache_unhash_dhcp(void);
|
void cache_unhash_dhcp(void);
|
||||||
void dump_cache(time_t now);
|
void dump_cache(time_t now);
|
||||||
|
int cache_make_stat(struct txt_record *t);
|
||||||
char *cache_get_name(struct crec *crecp);
|
char *cache_get_name(struct crec *crecp);
|
||||||
char *cache_get_cname_target(struct crec *crecp);
|
char *cache_get_cname_target(struct crec *crecp);
|
||||||
struct crec *cache_enumerate(int init);
|
struct crec *cache_enumerate(int init);
|
||||||
|
|||||||
+11
-5
@@ -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 */
|
/* Check whether today/now is between date_start and date_end */
|
||||||
static int check_date_range(unsigned long date_start, unsigned long date_end)
|
static int check_date_range(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 */
|
/* We must explicitly check against wanted values, because of SERIAL_UNDEF */
|
||||||
return serial_compare_32(curtime, date_start) == SERIAL_GT
|
return serial_compare_32(curtime, date_start) == SERIAL_GT
|
||||||
@@ -827,7 +833,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
|
|||||||
for (; crecp; crecp = cache_find_by_name(crecp, keyname, now, F_DNSKEY))
|
for (; crecp; crecp = cache_find_by_name(crecp, keyname, now, F_DNSKEY))
|
||||||
if (crecp->addr.key.algo == algo &&
|
if (crecp->addr.key.algo == algo &&
|
||||||
crecp->addr.key.keytag == key_tag &&
|
crecp->addr.key.keytag == key_tag &&
|
||||||
crecp->uid == class &&
|
crecp->uid == (unsigned int)class &&
|
||||||
verify(crecp->addr.key.keydata, crecp->addr.key.keylen, sig, sig_len, digest, hash->digest_size, algo))
|
verify(crecp->addr.key.keydata, crecp->addr.key.keylen, sig, sig_len, digest, hash->digest_size, algo))
|
||||||
return (labels < name_labels) ? STAT_SECURE_WILDCARD : STAT_SECURE;
|
return (labels < name_labels) ? STAT_SECURE_WILDCARD : STAT_SECURE;
|
||||||
}
|
}
|
||||||
@@ -932,7 +938,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
|
|
||||||
if (recp1->addr.ds.algo == algo &&
|
if (recp1->addr.ds.algo == algo &&
|
||||||
recp1->addr.ds.keytag == keytag &&
|
recp1->addr.ds.keytag == keytag &&
|
||||||
recp1->uid == class &&
|
recp1->uid == (unsigned int)class &&
|
||||||
(hash = hash_find(ds_digest_name(recp1->addr.ds.digest))) &&
|
(hash = hash_find(ds_digest_name(recp1->addr.ds.digest))) &&
|
||||||
hash_init(hash, &ctx, &digest))
|
hash_init(hash, &ctx, &digest))
|
||||||
|
|
||||||
@@ -1918,14 +1924,14 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname)
|
int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname)
|
||||||
{
|
{
|
||||||
unsigned char *p = (unsigned char *)(header+1);
|
unsigned char *p = (unsigned char *)(header+1);
|
||||||
int type, class, qtype, qclass, rdlen, j, rc;
|
int type, class, qclass, rdlen, j, rc;
|
||||||
int cname_count = CNAME_CHAIN;
|
int cname_count = CNAME_CHAIN;
|
||||||
|
|
||||||
/* Get question */
|
/* Get question */
|
||||||
if (!extract_name(header, plen, &p, name, 1, 4))
|
if (!extract_name(header, plen, &p, name, 1, 4))
|
||||||
return STAT_BOGUS;
|
return STAT_BOGUS;
|
||||||
|
|
||||||
GETSHORT(qtype, p);
|
p +=2; /* type */
|
||||||
GETSHORT(qclass, p);
|
GETSHORT(qclass, p);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
|
|||||||
+149
-47
@@ -278,7 +278,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
|
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
|
||||||
plen = forward->stash_len;
|
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");
|
log_query(F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else
|
else
|
||||||
@@ -299,7 +299,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
|
|
||||||
while (sendto(fd, (char *)header, plen, 0,
|
while (sendto(fd, (char *)header, plen, 0,
|
||||||
&forward->sentto->addr.sa,
|
&forward->sentto->addr.sa,
|
||||||
sa_len(&forward->sentto->addr)) == -1 && retry_send());
|
sa_len(&forward->sentto->addr)) == -1 && retry_send());
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -698,14 +698,20 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
serveraddr.in6.sin6_flowinfo = 0;
|
serveraddr.in6.sin6_flowinfo = 0;
|
||||||
#endif
|
#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, */
|
/* spoof check: answer must come from known server, */
|
||||||
for (server = daemon->servers; server; server = server->next)
|
for (server = daemon->servers; server; server = server->next)
|
||||||
if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
|
if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
|
||||||
sockaddr_isequal(&server->addr, &serveraddr))
|
sockaddr_isequal(&server->addr, &serveraddr))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
header = (struct dns_header *)daemon->packet;
|
if (!server)
|
||||||
|
return;
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
hash = hash_questions(header, n, daemon->namebuff);
|
hash = hash_questions(header, n, daemon->namebuff);
|
||||||
#else
|
#else
|
||||||
@@ -713,11 +719,9 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
crc = questions_crc(header, n, daemon->namebuff);
|
crc = questions_crc(header, n, daemon->namebuff);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!server ||
|
if (!(forward = lookup_frec(ntohs(header->id), hash)))
|
||||||
n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR) ||
|
|
||||||
!(forward = lookup_frec(ntohs(header->id), hash)))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
|
if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
|
||||||
!option_bool(OPT_ORDER) &&
|
!option_bool(OPT_ORDER) &&
|
||||||
forward->forwardall == 0)
|
forward->forwardall == 0)
|
||||||
@@ -747,7 +751,7 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
|
|
||||||
if ((forward->sentto->flags & SERV_TYPE) == 0)
|
if ((forward->sentto->flags & SERV_TYPE) == 0)
|
||||||
{
|
{
|
||||||
if (RCODE(header) == SERVFAIL || RCODE(header) == REFUSED)
|
if (RCODE(header) == REFUSED)
|
||||||
server = NULL;
|
server = NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -770,8 +774,7 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
we get a good reply from another server. Kill it when we've
|
we get a good reply from another server. Kill it when we've
|
||||||
had replies from all to avoid filling the forwarding table when
|
had replies from all to avoid filling the forwarding table when
|
||||||
everything is broken */
|
everything is broken */
|
||||||
if (forward->forwardall == 0 || --forward->forwardall == 1 ||
|
if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != SERVFAIL)
|
||||||
(RCODE(header) != REFUSED && RCODE(header) != SERVFAIL))
|
|
||||||
{
|
{
|
||||||
int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0;
|
int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0;
|
||||||
|
|
||||||
@@ -784,7 +787,7 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
no_cache_dnssec = 1;
|
no_cache_dnssec = 1;
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#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;
|
int status;
|
||||||
|
|
||||||
@@ -850,6 +853,7 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
*new = *forward; /* copy everything, then overwrite */
|
*new = *forward; /* copy everything, then overwrite */
|
||||||
new->next = next;
|
new->next = next;
|
||||||
new->blocking_query = NULL;
|
new->blocking_query = NULL;
|
||||||
|
new->sentto = server;
|
||||||
new->rfd4 = NULL;
|
new->rfd4 = NULL;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
new->rfd6 = NULL;
|
new->rfd6 = NULL;
|
||||||
@@ -1076,11 +1080,60 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
source_addr.sa.sa_family = listen->family;
|
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
|
#ifdef HAVE_IPV6
|
||||||
if (listen->family == AF_INET6)
|
else
|
||||||
source_addr.in6.sin6_flowinfo = 0;
|
{
|
||||||
|
/* 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
|
#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)
|
if (check_dst)
|
||||||
{
|
{
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
@@ -1276,6 +1329,10 @@ static int send_check_sign(time_t now, struct dns_header *header, size_t plen, c
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reached the root */
|
||||||
|
if (!name_start)
|
||||||
|
return STAT_BOGUS;
|
||||||
|
|
||||||
strcpy(keyname, name_start);
|
strcpy(keyname, name_start);
|
||||||
return STAT_NEED_DS_NEG;
|
return STAT_NEED_DS_NEG;
|
||||||
}
|
}
|
||||||
@@ -1341,8 +1398,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);
|
struct crec *crecp = cache_find_by_name(NULL, name_start, now, F_DS);
|
||||||
|
|
||||||
if (--(*keycount) == 0)
|
if (--(*keycount) == 0)
|
||||||
return STAT_BOGUS;
|
{
|
||||||
|
free(packet);
|
||||||
|
return STAT_BOGUS;
|
||||||
|
}
|
||||||
|
|
||||||
if (crecp && (crecp->flags & F_DNSSECOK))
|
if (crecp && (crecp->flags & F_DNSSECOK))
|
||||||
{
|
{
|
||||||
free(packet);
|
free(packet);
|
||||||
@@ -1357,46 +1417,55 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s
|
|||||||
continue;
|
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);
|
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. */
|
/* We rely on the question section coming back unchanged, ensure it is with the hash. */
|
||||||
if ((newhash = hash_questions(header, (unsigned int)m, name)))
|
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 (read_write(server->tcpfd, packet, m + sizeof(u16), 0) &&
|
||||||
if (newhash && memcmp(hash, newhash, HASH_SIZE) == 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 */
|
m = (c1 << 8) | c2;
|
||||||
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. */
|
newhash = hash_questions(header, (unsigned int)m, name);
|
||||||
if (status == STAT_INSECURE)
|
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) &&
|
/* We've found a DS which proves the bit of the DNS where the
|
||||||
(name_start = strchr(name, '.')))
|
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 */
|
free(packet);
|
||||||
continue;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1544,6 +1613,37 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
|
|
||||||
if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
|
if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
|
||||||
return packet;
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
@@ -1644,6 +1744,8 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
unsigned char *newhash, hash[HASH_SIZE];
|
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->keyname)))
|
||||||
memcpy(hash, newhash, HASH_SIZE);
|
memcpy(hash, newhash, HASH_SIZE);
|
||||||
|
else
|
||||||
|
memset(hash, 0, HASH_SIZE);
|
||||||
#else
|
#else
|
||||||
unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
|
unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+44
-1
@@ -268,7 +268,40 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||||||
|
|
||||||
if (!label)
|
if (!label)
|
||||||
label = ifr.ifr_name;
|
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
|
#ifdef HAVE_IPV6
|
||||||
if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
|
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;
|
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
|
#ifdef HAVE_AUTH
|
||||||
/* remove addresses stored against auth_zone subnets, but not
|
/* remove addresses stored against auth_zone subnets, but not
|
||||||
ones configured as address literals */
|
ones configured as address literals */
|
||||||
@@ -1528,7 +1570,8 @@ void newaddress(time_t now)
|
|||||||
{
|
{
|
||||||
(void)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);
|
enumerate_interfaces(0);
|
||||||
|
|
||||||
if (option_bool(OPT_CLEVERBIND))
|
if (option_bool(OPT_CLEVERBIND))
|
||||||
|
|||||||
+118
-91
@@ -64,86 +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:"
|
#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 */
|
/* options which don't have a one-char version */
|
||||||
#define LOPT_RELOAD 256
|
#define LOPT_RELOAD 256
|
||||||
#define LOPT_NO_NAMES 257
|
#define LOPT_NO_NAMES 257
|
||||||
#define LOPT_TFTP 258
|
#define LOPT_TFTP 258
|
||||||
#define LOPT_SECURE 259
|
#define LOPT_SECURE 259
|
||||||
#define LOPT_PREFIX 260
|
#define LOPT_PREFIX 260
|
||||||
#define LOPT_PTR 261
|
#define LOPT_PTR 261
|
||||||
#define LOPT_BRIDGE 262
|
#define LOPT_BRIDGE 262
|
||||||
#define LOPT_TFTP_MAX 263
|
#define LOPT_TFTP_MAX 263
|
||||||
#define LOPT_FORCE 264
|
#define LOPT_FORCE 264
|
||||||
#define LOPT_NOBLOCK 265
|
#define LOPT_NOBLOCK 265
|
||||||
#define LOPT_LOG_OPTS 266
|
#define LOPT_LOG_OPTS 266
|
||||||
#define LOPT_MAX_LOGS 267
|
#define LOPT_MAX_LOGS 267
|
||||||
#define LOPT_CIRCUIT 268
|
#define LOPT_CIRCUIT 268
|
||||||
#define LOPT_REMOTE 269
|
#define LOPT_REMOTE 269
|
||||||
#define LOPT_SUBSCR 270
|
#define LOPT_SUBSCR 270
|
||||||
#define LOPT_INTNAME 271
|
#define LOPT_INTNAME 271
|
||||||
#define LOPT_BANK 272
|
#define LOPT_BANK 272
|
||||||
#define LOPT_DHCP_HOST 273
|
#define LOPT_DHCP_HOST 273
|
||||||
#define LOPT_APREF 274
|
#define LOPT_APREF 274
|
||||||
#define LOPT_OVERRIDE 275
|
#define LOPT_OVERRIDE 275
|
||||||
#define LOPT_TFTPPORTS 276
|
#define LOPT_TFTPPORTS 276
|
||||||
#define LOPT_REBIND 277
|
#define LOPT_REBIND 277
|
||||||
#define LOPT_NOLAST 278
|
#define LOPT_NOLAST 278
|
||||||
#define LOPT_OPTS 279
|
#define LOPT_OPTS 279
|
||||||
#define LOPT_DHCP_OPTS 280
|
#define LOPT_DHCP_OPTS 280
|
||||||
#define LOPT_MATCH 281
|
#define LOPT_MATCH 281
|
||||||
#define LOPT_BROADCAST 282
|
#define LOPT_BROADCAST 282
|
||||||
#define LOPT_NEGTTL 283
|
#define LOPT_NEGTTL 283
|
||||||
#define LOPT_ALTPORT 284
|
#define LOPT_ALTPORT 284
|
||||||
#define LOPT_SCRIPTUSR 285
|
#define LOPT_SCRIPTUSR 285
|
||||||
#define LOPT_LOCAL 286
|
#define LOPT_LOCAL 286
|
||||||
#define LOPT_NAPTR 287
|
#define LOPT_NAPTR 287
|
||||||
#define LOPT_MINPORT 288
|
#define LOPT_MINPORT 288
|
||||||
#define LOPT_DHCP_FQDN 289
|
#define LOPT_DHCP_FQDN 289
|
||||||
#define LOPT_CNAME 290
|
#define LOPT_CNAME 290
|
||||||
#define LOPT_PXE_PROMT 291
|
#define LOPT_PXE_PROMT 291
|
||||||
#define LOPT_PXE_SERV 292
|
#define LOPT_PXE_SERV 292
|
||||||
#define LOPT_TEST 293
|
#define LOPT_TEST 293
|
||||||
#define LOPT_TAG_IF 294
|
#define LOPT_TAG_IF 294
|
||||||
#define LOPT_PROXY 295
|
#define LOPT_PROXY 295
|
||||||
#define LOPT_GEN_NAMES 296
|
#define LOPT_GEN_NAMES 296
|
||||||
#define LOPT_MAXTTL 297
|
#define LOPT_MAXTTL 297
|
||||||
#define LOPT_NO_REBIND 298
|
#define LOPT_NO_REBIND 298
|
||||||
#define LOPT_LOC_REBND 299
|
#define LOPT_LOC_REBND 299
|
||||||
#define LOPT_ADD_MAC 300
|
#define LOPT_ADD_MAC 300
|
||||||
#define LOPT_DNSSEC 301
|
#define LOPT_DNSSEC 301
|
||||||
#define LOPT_INCR_ADDR 302
|
#define LOPT_INCR_ADDR 302
|
||||||
#define LOPT_CONNTRACK 303
|
#define LOPT_CONNTRACK 303
|
||||||
#define LOPT_FQDN 304
|
#define LOPT_FQDN 304
|
||||||
#define LOPT_LUASCRIPT 305
|
#define LOPT_LUASCRIPT 305
|
||||||
#define LOPT_RA 306
|
#define LOPT_RA 306
|
||||||
#define LOPT_DUID 307
|
#define LOPT_DUID 307
|
||||||
#define LOPT_HOST_REC 308
|
#define LOPT_HOST_REC 308
|
||||||
#define LOPT_TFTP_LC 309
|
#define LOPT_TFTP_LC 309
|
||||||
#define LOPT_RR 310
|
#define LOPT_RR 310
|
||||||
#define LOPT_CLVERBIND 311
|
#define LOPT_CLVERBIND 311
|
||||||
#define LOPT_MAXCTTL 312
|
#define LOPT_MAXCTTL 312
|
||||||
#define LOPT_AUTHZONE 313
|
#define LOPT_AUTHZONE 313
|
||||||
#define LOPT_AUTHSERV 314
|
#define LOPT_AUTHSERV 314
|
||||||
#define LOPT_AUTHTTL 315
|
#define LOPT_AUTHTTL 315
|
||||||
#define LOPT_AUTHSOA 316
|
#define LOPT_AUTHSOA 316
|
||||||
#define LOPT_AUTHSFS 317
|
#define LOPT_AUTHSFS 317
|
||||||
#define LOPT_AUTHPEER 318
|
#define LOPT_AUTHPEER 318
|
||||||
#define LOPT_IPSET 319
|
#define LOPT_IPSET 319
|
||||||
#define LOPT_SYNTH 320
|
#define LOPT_SYNTH 320
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
#ifdef OPTION6_PREFIX_CLASS
|
||||||
#define LOPT_PREF_CLSS 321
|
#define LOPT_PREF_CLSS 321
|
||||||
#endif
|
#endif
|
||||||
#define LOPT_RELAY 323
|
#define LOPT_RELAY 323
|
||||||
#define LOPT_RA_PARAM 324
|
#define LOPT_RA_PARAM 324
|
||||||
#define LOPT_ADD_SBNET 325
|
#define LOPT_ADD_SBNET 325
|
||||||
#define LOPT_QUIET_DHCP 326
|
#define LOPT_QUIET_DHCP 326
|
||||||
#define LOPT_QUIET_DHCP6 327
|
#define LOPT_QUIET_DHCP6 327
|
||||||
#define LOPT_QUIET_RA 328
|
#define LOPT_QUIET_RA 328
|
||||||
#define LOPT_SEC_VALID 329
|
#define LOPT_SEC_VALID 329
|
||||||
#define LOPT_TRUST_ANCHOR 330
|
#define LOPT_TRUST_ANCHOR 330
|
||||||
#define LOPT_DNSSEC_DEBUG 331
|
#define LOPT_DNSSEC_DEBUG 331
|
||||||
#define LOPT_REV_SERV 332
|
#define LOPT_REV_SERV 332
|
||||||
#define LOPT_SERVERS_FILE 333
|
#define LOPT_SERVERS_FILE 333
|
||||||
#define LOPT_DNSSEC_CHECK 334
|
#define LOPT_DNSSEC_CHECK 334
|
||||||
|
#define LOPT_LOCAL_SERVICE 335
|
||||||
|
#define LOPT_DNSSEC_TIME 336
|
||||||
|
|
||||||
#ifdef HAVE_GETOPT_LONG
|
#ifdef HAVE_GETOPT_LONG
|
||||||
static const struct option opts[] =
|
static const struct option opts[] =
|
||||||
@@ -175,6 +177,7 @@ static const struct myoption opts[] =
|
|||||||
{ "domain-suffix", 1, 0, 's' },
|
{ "domain-suffix", 1, 0, 's' },
|
||||||
{ "interface", 1, 0, 'i' },
|
{ "interface", 1, 0, 'i' },
|
||||||
{ "listen-address", 1, 0, 'a' },
|
{ "listen-address", 1, 0, 'a' },
|
||||||
|
{ "local-service", 0, 0, LOPT_LOCAL_SERVICE },
|
||||||
{ "bogus-priv", 0, 0, 'b' },
|
{ "bogus-priv", 0, 0, 'b' },
|
||||||
{ "bogus-nxdomain", 1, 0, 'B' },
|
{ "bogus-nxdomain", 1, 0, 'B' },
|
||||||
{ "selfmx", 0, 0, 'e' },
|
{ "selfmx", 0, 0, 'e' },
|
||||||
@@ -285,6 +288,7 @@ static const struct myoption opts[] =
|
|||||||
{ "trust-anchor", 1, 0, LOPT_TRUST_ANCHOR },
|
{ "trust-anchor", 1, 0, LOPT_TRUST_ANCHOR },
|
||||||
{ "dnssec-debug", 0, 0, LOPT_DNSSEC_DEBUG },
|
{ "dnssec-debug", 0, 0, LOPT_DNSSEC_DEBUG },
|
||||||
{ "dnssec-check-unsigned", 0, 0, LOPT_DNSSEC_CHECK },
|
{ "dnssec-check-unsigned", 0, 0, LOPT_DNSSEC_CHECK },
|
||||||
|
{ "dnssec-no-timecheck", 0, 0, LOPT_DNSSEC_TIME },
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
#ifdef OPTION6_PREFIX_CLASS
|
||||||
{ "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
|
{ "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
|
||||||
#endif
|
#endif
|
||||||
@@ -441,6 +445,7 @@ static struct {
|
|||||||
{ LOPT_TRUST_ANCHOR, ARG_DUP, "<domain>,[<class>],...", gettext_noop("Specify trust anchor key digest."), 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_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_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
|
#ifdef OPTION6_PREFIX_CLASS
|
||||||
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
|
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
|
||||||
#endif
|
#endif
|
||||||
@@ -448,6 +453,7 @@ static struct {
|
|||||||
{ LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log routine DHCP."), NULL },
|
{ LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log routine DHCP."), NULL },
|
||||||
{ LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log routine DHCPv6."), NULL },
|
{ LOPT_QUIET_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_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 }
|
{ 0, 0, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -612,19 +618,24 @@ static int atoi_check8(char *a, int *res)
|
|||||||
}
|
}
|
||||||
#endif
|
#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));
|
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->name = opt_string_alloc(name);
|
||||||
r->next = daemon->txt;
|
r->next = daemon->txt;
|
||||||
daemon->txt = r;
|
daemon->txt = r;
|
||||||
r->class = C_CHAOS;
|
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)
|
static void do_usage(void)
|
||||||
@@ -1661,7 +1672,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
case 'H': /* --addn-hosts */
|
case 'H': /* --addn-hosts */
|
||||||
{
|
{
|
||||||
struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
|
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->fname = opt_string_alloc(arg);
|
||||||
new->index = hosts_index++;
|
new->index = hosts_index++;
|
||||||
new->flags = 0;
|
new->flags = 0;
|
||||||
@@ -3606,7 +3617,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
new->next = daemon->txt;
|
new->next = daemon->txt;
|
||||||
daemon->txt = new;
|
daemon->txt = new;
|
||||||
new->class = C_IN;
|
new->class = C_IN;
|
||||||
|
new->stat = 0;
|
||||||
|
|
||||||
if (!(new->name = canonicalise_opt(arg)))
|
if (!(new->name = canonicalise_opt(arg)))
|
||||||
ret_err(_("bad TXT record"));
|
ret_err(_("bad TXT record"));
|
||||||
|
|
||||||
@@ -4017,10 +4029,11 @@ static int one_file(char *file, int hard_opt)
|
|||||||
/* expand any name which is a directory */
|
/* expand any name which is a directory */
|
||||||
struct hostsfile *expand_filelist(struct hostsfile *list)
|
struct hostsfile *expand_filelist(struct hostsfile *list)
|
||||||
{
|
{
|
||||||
int i;
|
unsigned int i;
|
||||||
struct hostsfile *ah;
|
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)
|
if (i <= ah->index)
|
||||||
i = ah->index + 1;
|
i = ah->index + 1;
|
||||||
@@ -4254,9 +4267,18 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||||||
daemon->soa_refresh = SOA_REFRESH;
|
daemon->soa_refresh = SOA_REFRESH;
|
||||||
daemon->soa_retry = SOA_RETRY;
|
daemon->soa_retry = SOA_RETRY;
|
||||||
daemon->soa_expiry = SOA_EXPIRY;
|
daemon->soa_expiry = SOA_EXPIRY;
|
||||||
add_txt("version.bind", "dnsmasq-" VERSION );
|
add_txt("version.bind", "dnsmasq-" VERSION, 0 );
|
||||||
add_txt("authors.bind", "Simon Kelley");
|
add_txt("authors.bind", "Simon Kelley", 0);
|
||||||
add_txt("copyright.bind", COPYRIGHT);
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
@@ -4457,6 +4479,11 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||||||
else if (option_bool(OPT_DHCP_FQDN))
|
else if (option_bool(OPT_DHCP_FQDN))
|
||||||
die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
|
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)
|
if (testmode)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
|
fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
|
||||||
|
|||||||
+21
-6
@@ -1065,6 +1065,8 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
if (newc)
|
if (newc)
|
||||||
{
|
{
|
||||||
newc->addr.cname.target.cache = NULL;
|
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)
|
if (cpp)
|
||||||
{
|
{
|
||||||
cpp->addr.cname.target.cache = newc;
|
cpp->addr.cname.target.cache = newc;
|
||||||
@@ -1100,7 +1102,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
{
|
{
|
||||||
ipsets_cur = ipsets;
|
ipsets_cur = ipsets;
|
||||||
while (*ipsets_cur)
|
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
|
#endif
|
||||||
|
|
||||||
@@ -1456,7 +1461,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
{
|
{
|
||||||
char *name = daemon->namebuff;
|
char *name = daemon->namebuff;
|
||||||
unsigned char *p, *ansp, *pheader;
|
unsigned char *p, *ansp, *pheader;
|
||||||
int qtype, qclass;
|
unsigned int qtype, qclass;
|
||||||
struct all_addr addr;
|
struct all_addr addr;
|
||||||
int nameoffset;
|
int nameoffset;
|
||||||
unsigned short flag;
|
unsigned short flag;
|
||||||
@@ -1545,10 +1550,20 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
ans = 1;
|
ans = 1;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
|
unsigned long ttl = daemon->local_ttl;
|
||||||
|
int ok = 1;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
/* Dynamically generate stat record */
|
||||||
daemon->local_ttl, NULL,
|
if (t->stat != 0)
|
||||||
T_TXT, t->class, "t", t->len, t->txt))
|
{
|
||||||
|
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++;
|
anscount++;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2016,7 +2031,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
|
|
||||||
strcpy(name, cname_target);
|
strcpy(name, cname_target);
|
||||||
/* check if target interface_name */
|
/* check if target interface_name */
|
||||||
if (crecp->addr.cname.uid == -1)
|
if (crecp->addr.cname.uid == SRC_INTERFACE)
|
||||||
goto intname_restart;
|
goto intname_restart;
|
||||||
else
|
else
|
||||||
goto cname_restart;
|
goto cname_restart;
|
||||||
|
|||||||
@@ -962,6 +962,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
case DHCPDISCOVER:
|
case DHCPDISCOVER:
|
||||||
if (ignore || have_config(config, CONFIG_DISABLE))
|
if (ignore || have_config(config, CONFIG_DISABLE))
|
||||||
{
|
{
|
||||||
|
if (option_bool(OPT_QUIET_DHCP))
|
||||||
|
return 0;
|
||||||
message = _("ignored");
|
message = _("ignored");
|
||||||
opt = NULL;
|
opt = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user