Compare commits

...

58 Commits

Author SHA1 Message Date
Simon Kelley
c5db8f93ec Tidy 7f876b64c22b2b18412e2e3d8506ee33e42db7c 2018-08-23 23:06:00 +01:00
Simon Kelley
974a6d087a Add --caa-record 2018-08-23 23:01:16 +01:00
Simon Kelley
b758b67c37 Improve logging of RRs from --dns-rr. 2018-08-23 21:41:23 +01:00
Simon Kelley
9bafdc62b7 Tidy up file parsing code. 2018-08-21 22:53:38 +01:00
Simon Kelley
97f876b64c Properly deal with unaligned addresses in DHCPv6 packets.
Thanks to Vladislav Grishenko for spotting this.
2018-08-21 22:06:36 +01:00
Simon Kelley
cbfbd173c4 Fix broken DNSSEC records in previous. 2018-08-21 18:25:18 +01:00
Simon Kelley
b6f926fbef Don't return NXDOMAIN to empty non-terminals.
When a record is defined locally, eg an A record for one.two.example then
we already know that if we forward, eg an AAAA query for one.two.example,
and get back NXDOMAIN, then we need to alter that to NODATA. This is handled
by  check_for_local_domain(). But, if we forward two.example, because
one.two.example exists, then the answer to two.example should also be
a NODATA.

For most local records this is easy, just to substring matching.
for A, AAAA and CNAME records that are in the cache, it's more difficult.
The cache has no efficient way to find such records. The fix is to
insert empty (none of F_IPV4, F_IPV6 F_CNAME set) records for each
non-terminal.

The same considerations apply in auth mode, and the same basic mechanism
is used there too.
2018-08-21 17:46:52 +01:00
Simon Kelley
c822620967 Add --dhcp-name-match 2018-08-08 23:46:03 +01:00
Simon Kelley
397c0502e2 Handle case of --auth-zone but no --auth-server. 2018-08-04 21:04:59 +01:00
Simon Kelley
1682d15a74 Add missing EDNS0 section.
EDNS0 section missing in replies to EDNS0-containing queries where
answer generated from --local=/<domain>/
2018-08-03 20:38:18 +01:00
Simon Kelley
dd33e98da0 Fix crash parsing a --synth-domain with no prefix.
Problem introduced in 2.79/6b2b564ac34cb3c862f168e6b1457f9f0b9ca69c
2018-07-30 14:55:39 +01:00
Simon Kelley
c16d966ad3 Add copyright to src/metrics.h 2018-07-29 22:31:02 +01:00
Simon Kelley
1dfed16071 Remove C99 only code. 2018-07-29 22:16:41 +01:00
Simon Kelley
6f835ed6c8 Format fixes - ubus.c 2018-07-29 22:15:36 +01:00
Kevin Darbyshire-Bryant
9d6fd1727e dnsmasq.c fix OPT_UBUS option usage
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
2018-07-29 22:11:12 +01:00
Simon Kelley
8c1b6a5fd7 New metrics and ubus files. 2018-07-21 22:12:32 +01:00
Julian Kornberger
8dcdb33be9 Add --enable-ubus option. 2018-07-21 22:11:08 +01:00
Julian Kornberger
aba8bbb6e3 Add collection of metrics
Data can be retreived via D-Bus und U-Bus
2018-07-21 21:55:08 +01:00
Julian Kornberger
caf4d571e6 Add OpenWRT ubus patch
Originally written by John Crispin <john@phrozen.org>
2018-07-21 21:45:03 +01:00
Simon Kelley
3b6eb197a8 Log DNSSEC trust anchors at startup. 2018-07-20 21:23:56 +01:00
Simon Kelley
f3e57877ed Trivial comment change. 2018-07-20 21:10:48 +01:00
Simon Kelley
c851c695db Log failure to confirm an address in DHCPv6. 2018-07-20 17:35:24 +01:00
Simon Kelley
a3bd7e73d3 Fix missing fatal errors when parsing some command-line/config options. 2018-07-19 22:00:08 +01:00
Olivier Gayot
ab5ceaf74a Document the --help option in the french manual
The option was already described in the original manual page but was not
replicated in the french translation.

Reviewed-By: Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
2018-07-19 21:17:06 +01:00
Olivier Gayot
1f2f69d4f6 Fix recurrent minor spelling mistake in french manual
The use of "peut-être" should be spelled "peut être" (without the
hyphen) unless it can be replaced by "sans doute".

It is roughly the same difference between "maybe" and "may be".

As for "doit-être", it should always be spelled "doit être".

Reviewed-By: Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
2018-07-19 21:16:41 +01:00
Olivier Gayot
f361b39dea Fix some mistakes in french translation of the manual
Various typos were present along with spelling mistakes and grammar
errors. Some sentences were missing a few words to be easily
understandable.

Many of them probably remain though.

Reviewed-By: Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
2018-07-19 21:16:04 +01:00
Simon Kelley
eb1fe15ca8 When replacing cache entries, preserve CNAMES which target them.
When inserting new cache records, we first delete existing records
of the same name/type, to maintain consistency. This has the side effect
of deleting any CNAMES which have the records as target. So

cname1.example CNAME record.example
cname2.example CNAME record.example

looking up cname2.example will push it into the cache, and also
push record.example. Doing that deletes any cache of cname1.example.

This changeset avoids that problem by making sure that when
deleting record.example, and re-insterting it (with the same name -important),
it uses the same struct crec, with the same uid. This preserves the existing cnames.
2018-07-18 20:59:52 +01:00
Simon Kelley
45d8a2435e Introduce UID_NONE value, for cache records which are not the target of a CNAME. 2018-07-17 21:01:14 +01:00
Simon Kelley
706d84fd10 Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2018-07-16 18:07:15 +01:00
Simon Kelley
a997ca0da0 Fix sometimes missing DNSSEC RRs when DNSSEC validation not enabled.
Dnsmasq does pass on the do-bit, and return DNSSEC RRs, irrespective
of of having DNSSEC validation compiled in or enabled.

The thing to understand here is that the cache does not store all the
DNSSEC RRs, and dnsmasq doesn't have the (very complex) logic required
to determine the set of DNSSEC RRs required in an answer. Therefore if
the client wants the DNSSEC RRs, the query can not be answered from
the cache. When DNSSEC validation is enabled, any query with the
do-bit set is never answered from the cache, unless the domain is
known not to be signed: the query is always forwarded. This ensures
that the DNSEC RRs are included.

The same thing should be true when DNSSEC validation is not enabled,
but there's a bug in the logic.

line 1666 of src/rfc1035.c looks like this

 if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))

{ ...answer from cache ... }

So local stuff (hosts, DHCP, ) get answered. If the do_bit is not set
then the query is answered, and if the domain is known not to be
signed, the query is answered.

Unfortunately, if DNSSEC validation is not turned on then the
F_DNSSECOK bit is not valid, and it's always zero, so the question
always gets answered from the cache, even when the do-bit is set.

This code should look like that at line 1468, dealing with PTR queries

  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
      !do_bit ||
      (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))

where the F_DNSSECOK bit is only used when validation is enabled.
2018-06-29 14:39:41 +01:00
Peter Pöschl
9268b5d677 Man page: uniform formatting style for options.
* Always use the long option form, except when options are introduced.
* Render options in bold, with '--' prefix.
2018-06-12 17:04:54 +01:00
Paul Maddock
51e4eeeb04 Fix address-dependent domains for IPv6.
Thanks to Paul Maddock for spotting this.
It seems to have been broken forever.
2018-06-12 16:37:40 +01:00
Simon Kelley
05ff659a3c Fix stupid infinite loop introduced by preceding commit. 2018-06-12 16:03:09 +01:00
Simon Kelley
db0f488ea8 Handle some corner cases in RA contructed interfaces with addresses changing interface.
Thanks to Vladislav Grishenko for work on this.
2018-06-07 21:37:02 +01:00
Geert Stappers
7dcca6c622 Warn about the impact of cache-size on performance. 2018-06-02 18:54:04 +01:00
Simon Kelley
090856c7e6 Allow zone transfer in authoritative mode whenever auth-peer is specified. 2018-06-02 18:37:07 +01:00
Simon Kelley
cc5cc8f1e0 Sane error message when pcap file header is wrong. 2018-06-02 14:45:17 +01:00
Simon Kelley
c488b68e75 Handle standard and contructed dhcp-ranges on the same interface. 2018-06-02 13:06:00 +01:00
Simon Kelley
1f1873aadd Log warning on very large cachesize config, instead of truncating it. 2018-05-11 23:38:23 +01:00
Maarten de Vries
0a496f059c Do unsolicited RAs for interfaces which appear after dnsmasq startup.
I noticed that dnsmasq often wasn't sending any unsolicited RAs for me.

This turned out to happen when the interface (a bridge interface) wasn't
created yet at the time dnsmasq started. When dnsmasq is started after
the interface is created, it sends RAs as expected. I assume this also
extends to other types of virtual interfaces that are created after
dnsmasq starts.

Digging into the source, it seems to be caused by a missing call to
ra_start_unsolicited for non-template contexts in construct_worker from
src/dhcp6.c. The attached patch adds that call, but only if the
interface index or address changed to prevent doing fast RAs for no reason.

I tested it on my own server and it appears to work as expected. When
the interface is created and configured, dnsmasq does fast RAs for a
while and then settles into slow RAs.
2018-05-11 23:20:58 +01:00
Simon Kelley
e27825b0ef Fix logging in previous. 2018-05-11 17:20:47 +01:00
Simon Kelley
1f60a18ea1 Retry SERVFAIL DNSSEC queries to a different server, if possible. 2018-05-11 16:44:16 +01:00
Simon Kelley
a0088e8364 Handle query retry on REFUSED or SERVFAIL for DNSSEC-generated queries. 2018-05-10 21:43:14 +01:00
Simon Kelley
34e26e14c5 Retry query to other servers on receipt of SERVFAIL rcode. 2018-05-10 20:54:57 +01:00
Simon Kelley
6b17335209 Add packet-dump debugging facility. 2018-05-08 18:32:14 +01:00
Simon Kelley
07ed585c38 Add logging for DNS error returns from upstream and local configuration. 2018-05-04 21:52:22 +01:00
Simon Kelley
0669ee7a69 Fix DHCP broken-ness when --no-ping AND --dhcp-sequential-ip are set. 2018-05-04 16:46:24 +01:00
Simon Kelley
f84e674d8a Be persistent with broken-upstream-DNSSEC warnings. 2018-05-04 16:29:57 +01:00
Simon Kelley
7f0084316a Handle DNSSEC-unaware upstream servers better. 2018-04-15 20:01:49 +01:00
Simon Kelley
a6918530ce Change default for dnssec-check-unsigned. 2018-04-15 16:20:52 +01:00
Simon Kelley
4e72fec660 Fix DNSSEC without dnssec-check-unsigned.
An oversight meant that non-existance checking was being done
anyway.

(Should probably alter the default for this.)
2018-04-11 22:49:31 +01:00
Simon Kelley
4441cf762c Fix DNS server fd garbage collection.
If we're talking to upstream servers from a fixed port, specified by query-port
we create the fds to do this once, before dropping root, so that ports <1024 can be used.

But we call check_servers() before reading /etc/resolv.conf, so if the only servers
are in resolv.conf, at that point there will be no servers, and the fds get garbage
collected away, only to be recreated (but without root) after we read /etc/resolv.conf

Make pre-allocated server fds immortal, to avoid this problem.
2018-04-10 21:39:54 +01:00
Simon Kelley
e83915d10d Set V6ONLY on DNS upstream socket.
If query-port is set, we create sockets bound to the wildcard address and the query port for
IPv4 and IPv6, but the IPv6 one fails, because is covers IPv4 as well, and an IPv4 socket
already exists (it gets created first). Set V6ONLY to avoid this.
2018-04-10 21:27:26 +01:00
Kevin Darbyshire-Bryant
6d37924b86 Makefile: Stop creating '-d' directory
Install-common section was creating superfluous '-d' directory in build
location.

Split the directory creation into individual install commands to cope
with cross platform differences of interpreting subsequent '-d'
arguments.  e.g. GNU appears to be fine.  Apple creates the stray
directory.

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
2018-04-07 23:00:56 +01:00
Simon Kelley
f3d7974e86 Fixed bug number in changelog s/833596/883596/ 2018-03-26 13:23:59 +01:00
Simon Kelley
734d53176f Add RFC4039 rapid commit support. 2018-03-23 23:09:53 +00:00
Simon Kelley
9a7be47614 Add lintian override in Debian package. 2018-03-23 20:45:53 +00:00
Simon Kelley
26e27d0015 Symbolic link for /usr/share/doc/dnsmasq-base-lua in Debian package. 2018-03-18 17:29:12 +00:00
35 changed files with 1816 additions and 627 deletions

View File

@@ -1,3 +1,59 @@
version 2.80
Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method
for the initial patch and motivation.
Alter the default for dnssec-check-unsigned. Versions of
dnsmasq prior to 2.80 defaulted to not checking unsigned
replies, and used --dnssec-check-unsigned to switch
this on. Such configurations will continue to work as before,
but those which used the default of no checking will need to be
altered to explicitly select no checking. The new default is
because switching off checking for unsigned replies is
inherently dangerous. Not only does it open the possiblity of forged
replies, but it allows everything to appear to be working even
when the upstream namesevers do not support DNSSEC, and in this
case no DNSSEC validation at all is occuring.
Fix DHCP broken-ness when --no-ping AND --dhcp-sequential-ip
are set. Thanks to Daniel Miess for help with this.
Add a facilty to store DNS packets sent/recieved in a
pcap-format file for later debugging. The file location
is given by the --dumpfile option, and a bitmap controlling
which packets should be dumped is given by the --dumpmask
option.
Handle the case of both standard and constructed dhcp-ranges on the
same interface better. We don't now contruct a dhcp-range if there's
already one specified. This allows the specified interface to
have different parameters and avoids advertising the same
prefix twice. Thanks to Luis Marsano for spotting this case.
Allow zone transfer in authoritative mode if auth-peer is specified,
even if auth-sec-servers is not. Thanks to Raphaël Halimi for
the suggestion.
Fix bug which sometimes caused dnsmasq to wrongly return answers
without DNSSEC RRs to queries with the do-bit set, but only when
DNSSEC validation was not enabled.
Thanks to Petr Menšík for spotting this.
Fix missing fatal errors with some malformed options
(server, local, address, rebind-domain-ok, ipset, alias).
Thanks to Eugene Lozovoy for spotting the problem.
Fix crash on startup with a --synth-domain which has no prefix.
Introduced in 2.79. Thanks to Andreas Engel for the bug report.
Fix missing EDNS0 section in some replies generated by local
DNS configuration which confused systemd-resolvd. Thanks to
Steve Dodd for characterising the problem.
Add --dhcp-name-match config option.
Add --caa-record config option.
version 2.79
Fix parsing of CNAME arguments, which are confused by extra spaces.
Thanks to Diego Aguirre for spotting the bug.

View File

@@ -53,6 +53,7 @@ top?=$(CURDIR)
dbus_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --cflags dbus-1`
dbus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1`
ubus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_UBUS $(PKG_CONFIG) --copy -lubox -lubus`
idn_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn`
idn_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn`
idn2_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --cflags libidn2`
@@ -76,16 +77,16 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
poll.o rrfilter.o edns0.o arp.o crypto.o
poll.o rrfilter.o edns0.o arp.o crypto.o dump.o ubus.o metrics.o
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
dns-protocol.h radv-protocol.h ip6addr.h
dns-protocol.h radv-protocol.h ip6addr.h metrics.h
all : $(BUILDDIR)
@cd $(BUILDDIR) && $(MAKE) \
top="$(top)" \
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs)" \
-f $(top)/Makefile dnsmasq
mostly_clean :
@@ -100,7 +101,8 @@ clean : mostly_clean
install : all install-common
install-common :
$(INSTALL) -d $(DESTDIR)$(BINDIR) -d $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -d $(DESTDIR)$(BINDIR)
$(INSTALL) -d $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -m 644 $(MAN)/dnsmasq.8 $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -m 755 $(BUILDDIR)/dnsmasq $(DESTDIR)$(BINDIR)

View File

@@ -10,7 +10,8 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
radv.c slaac.c auth.c ipset.c domain.c \
dnssec.c dnssec-openssl.c blockdata.c tables.c \
loop.c inotify.c poll.c rrfilter.c edns0.c arp.c crypto.c
loop.c inotify.c poll.c rrfilter.c edns0.c arp.c \
crypto.c dump.c ubus.c
LOCAL_MODULE := dnsmasq

View File

@@ -243,6 +243,10 @@ IPv4 or IPv6 address of the lease to remove.
Note that this function will trigger the DhcpLeaseRemoved signal and the
configured DHCP lease script will be run with the "del" action.
GetMetrics
----------
Returns an array with various metrics for DNS and DHCP.
2. SIGNALS

2
debian/changelog vendored
View File

@@ -2,7 +2,7 @@ dnsmasq (2.79-1) unstable; urgency=low
* New upstream. (closes: #888200)
* Fix trust-anchor regex in init script. (closes: #884347)
* Fix exit code for dhcp_release6 (closes: #833596)
* Fix exit code for dhcp_release6 (closes: #883596)
* Add project homepage to control file. (closes: #887764)
* New binary package dnsmasq-base-lua, includes Lua support.
* Remove hardwired shlibs dependency for libnettle 3.3 and

3
debian/lintian-override vendored Normal file
View File

@@ -0,0 +1,3 @@
# dnsmasq-base and dnsmasq-base-lua are mutually exclusive and both
# provide /usr/share/doc/dnsmasq-base
dnsmasq-base-lua binary: usr-share-doc-symlink-without-dependency dnsmasq-base

3
debian/rules vendored
View File

@@ -217,9 +217,12 @@ else
rm -rf debian/trees/lua-base/usr/share/man
endif
$(call add_files,debian/trees/lua-base)
install -m 755 -d debian/trees/lua-base/usr/share/lintian/overrides
install -m 644 debian/lintian-override debian/trees/lua-base/usr/share/lintian/overrides/dnsmasq-base-lua
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/lua-base/usr/sbin/dnsmasq
endif
ln -s $(package) debian/trees/lua-base/usr/share/doc/dnsmasq-base-lua
cd debian/trees/lua-base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
dpkg-shlibdeps --warnings=1 debian/trees/lua-base/usr/sbin/dnsmasq
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base-lua -Pdebian/trees/lua-base

View File

@@ -547,6 +547,14 @@
# http://www.isc.org/files/auth.html
#dhcp-authoritative
# Set the DHCP server to enable DHCPv4 Rapid Commit Option per RFC 4039.
# In this mode it will respond to a DHCPDISCOVER message including a Rapid Commit
# option with a DHCPACK including a Rapid Commit option and fully committed address
# and configuration information. This must only be enabled if either the server is
# the only server for the subnet, or multiple servers are present and they each
# commit a binding for all clients.
#dhcp-rapid-commit
# Run an executable when a DHCP lease is created or destroyed.
# The arguments sent to the script are "add" or "del",
# then the MAC address, the IP address and finally the hostname

View File

@@ -53,13 +53,13 @@ will display DHCPv6 options.
Don't read the hostnames in /etc/hosts.
.TP
.B \-H, --addn-hosts=<file>
Additional hosts file. Read the specified file as well as /etc/hosts. If -h is given, read
Additional hosts file. Read the specified file as well as /etc/hosts. If \fB--no-hosts\fP is given, read
only the specified file. This option may be repeated for more than one
additional hosts file. If a directory is given, then read all the files contained in that directory.
.TP
.B --hostsdir=<path>
Read all the hosts files contained in the directory. New or changed files
are read automatically. See --dhcp-hostsdir for details.
are read automatically. See \fB--dhcp-hostsdir\fP for details.
.TP
.B \-E, --expand-hosts
Add the domain to simple names (without a period) in /etc/hosts
@@ -76,7 +76,7 @@ reduce the load on the server at the expense of clients using stale
data under some circumstances.
.TP
.B --dhcp-ttl=<time>
As for --local-ttl, but affects only replies with information from DHCP leases. If both are given, --dhcp-ttl applies for DHCP information, and --local-ttl for others. Setting this to zero eliminates the effect of --local-ttl for DHCP.
As for \fB--local-ttl\fP, but affects only replies with information from DHCP leases. If both are given, \fB--dhcp-ttl\fP applies for DHCP information, and \fB--local-ttl\fP for others. Setting this to zero eliminates the effect of \fB--local-ttl\fP for DHCP.
.TP
.B --neg-ttl=<time>
Negative replies from upstream servers normally contain time-to-live
@@ -115,7 +115,7 @@ don't change user id, generate a complete cache dump on receipt on
SIGUSR1, log to stderr as well as syslog, don't fork new processes
to handle TCP queries. Note that this option is for use in debugging
only, to stop dnsmasq daemonising in production, use
.B -k.
.B --keep-in-foreground.
.TP
.B \-q, --log-queries
Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1. If the argument "extra" is supplied, ie
@@ -191,7 +191,6 @@ Dnsmasq picks random ports as source for outbound queries:
when this option is given, the ports used will always be lower
than that specified. Useful for systems behind firewalls.
.TP
.B \-i, --interface=<interface name>
Listen only on the specified interface(s). Dnsmasq automatically adds
the loopback (local) interface to the list of interfaces to use when
@@ -250,8 +249,8 @@ addresses associated with the interface.
.B --local-service
Accept DNS queries only from hosts whose address is on a local subnet,
ie a subnet for which an interface exists on the server. This option
only has effect if there are no --interface --except-interface,
--listen-address or --auth-server options. It is intended to be set as
only has effect if there are no \fB--interface\fP, \fB--except-interface\fP,
\fB--listen-address\fP or \fB--auth-server\fP 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
@@ -294,10 +293,10 @@ addresses appear, it automatically listens on those (subject to any
access-control configuration). This makes dynamically created
interfaces work in the same way as the default. Implementing this
option requires non-standard networking APIs and it is only available
under Linux. On other platforms it falls-back to --bind-interfaces mode.
under Linux. On other platforms it falls-back to \fB--bind-interfaces\fP mode.
.TP
.B \-y, --localise-queries
Return answers to DNS queries from /etc/hosts and --interface-name which depend on the interface over which the query was
Return answers to DNS queries from /etc/hosts and \fB--interface-name\fP which depend on the interface over which the query was
received. If a name has more than one address associated with
it, and at least one of those addresses is on the same subnet as the
interface to which the query was sent, then return only the
@@ -367,6 +366,11 @@ been built with DBus support. If the service name is given, dnsmasq
provides service at that name, rather than the default which is
.B uk.org.thekelleys.dnsmasq
.TP
.B --enable-ubus
Enable dnsmasq UBus interface. It sends notifications via UBus on
DHCPACK and DHCPRELEASE events. Furthermore it offers metrics.
Requires that dnsmasq has been built with UBus support.
.TP
.B \-o, --strict-order
By default, dnsmasq will send queries to any of the upstream servers
it knows about and tries to favour servers that are known to
@@ -402,7 +406,7 @@ these services.
.B --rebind-domain-ok=[<domain>]|[[/<domain>/[<domain>/]
Do not detect and block dns-rebind on queries to these domains. The
argument may be either a single domain, or multiple domains surrounded
by '/', like the --server syntax, eg.
by '/', like the \fB--server\fP syntax, eg.
.B --rebind-domain-ok=/domain1/domain2/domain3/
.TP
.B \-n, --no-poll
@@ -421,14 +425,13 @@ from /etc/hosts or DHCP then a "not found" answer is returned.
.TP
.B \-S, --local, --server=[/[<domain>]/[domain/]][<ipaddr>[#<port>][@<source-ip>|<interface>[#<port>]]
Specify IP address of upstream servers directly. Setting this flag does
not suppress reading of /etc/resolv.conf, use -R to do that. If one or
more
not suppress reading of /etc/resolv.conf, use \fB--no-resolv\fP to do that. If one or more
optional domains are given, that server is used only for those domains
and they are queried only using the specified server. This is
intended for private nameservers: if you have a nameserver on your
network which deals with names of the form
xxx.internal.thekelleys.org.uk at 192.168.1.1 then giving the flag
.B -S /internal.thekelleys.org.uk/192.168.1.1
.B --server=/internal.thekelleys.org.uk/192.168.1.1
will send all queries for
internal machines to that nameserver, everything else will go to the
servers in /etc/resolv.conf. DNSSEC validation is turned off for such
@@ -440,7 +443,7 @@ has the special meaning of "unqualified names only" ie names without any
dots in them. A non-standard port may be specified as
part of the IP
address using a # character.
More than one -S flag is allowed, with
More than one \fB--server\fP flag is allowed, with
repeated domain or ipaddr parts as required.
More specific domains take precedence over less specific domains, so:
@@ -460,9 +463,9 @@ flag which gives a domain but no IP address; this tells dnsmasq that
a domain is local and it may answer queries from /etc/hosts or DHCP
but should never forward queries on that domain to any upstream
servers.
.B local
.B --local
is a synonym for
.B server
.B --server
to make configuration files clearer in this case.
IPv6 addresses may include an %interface scope-id, eg
@@ -493,7 +496,7 @@ is exactly equivalent to
Specify an IP address to return for any host in the given domains.
Queries in the domains are never forwarded and always replied to
with the specified IP address which may be IPv4 or IPv6. To give
both IPv4 and IPv6 addresses for a domain, use repeated \fB-A\fP flags.
both IPv4 and IPv6 addresses for a domain, use repeated \fB--address\fP flags.
To include multiple IP addresses for a single query, use
\fB--addn-hosts=<path>\fP instead.
Note that /etc/hosts and DHCP leases override this for individual
@@ -523,7 +526,7 @@ for more details.
.B \-m, --mx-host=<mx name>[[,<hostname>],<preference>]
Return an MX record named <mx name> pointing to the given hostname (if
given), or
the host specified in the --mx-target switch
the host specified in the \fB--mx-target\fP switch
or, if that switch is not given, the host on which dnsmasq
is running. The default is useful for directing mail from systems on a LAN
to a central server. The preference value is optional, and defaults to
@@ -531,7 +534,7 @@ to a central server. The preference value is optional, and defaults to
.TP
.B \-t, --mx-target=<hostname>
Specify the default target for the MX record returned by dnsmasq. See
--mx-host. If --mx-target is given, but not --mx-host, then dnsmasq
\fB--mx-host\fP. If \fB--mx-target\fP is given, but not \fB--mx-host\fP, then dnsmasq
returns a MX record containing the MX target for MX queries on the
hostname of the machine on which dnsmasq is running.
.TP
@@ -540,7 +543,7 @@ Return an MX record pointing to itself for each local
machine. Local machines are those in /etc/hosts or with DHCP leases.
.TP
.B \-L, --localmx
Return an MX record pointing to the host given by mx-target (or the
Return an MX record pointing to the host given by \fB--mx-target\fP (or the
machine on which dnsmasq is running) for each
local machine. Local machines are those in /etc/hosts or with DHCP
leases.
@@ -560,22 +563,22 @@ all that match are returned.
Add A, AAAA and PTR records to the DNS. This adds one or more names to
the DNS with associated IPv4 (A) and IPv6 (AAAA) records. A name may
appear in more than one
.B host-record
.B --host-record
and therefore be assigned more than one address. Only the first
address creates a PTR record linking the address to the name. This is
the same rule as is used reading hosts-files.
.B host-record
.B --host-record
options are considered to be read before host-files, so a name
appearing there inhibits PTR-record creation if it appears in
hosts-file also. Unlike hosts-files, names are not expanded, even when
.B expand-hosts
.B --expand-hosts
is in effect. Short and long names may appear in the same
.B host-record,
.B --host-record,
eg.
.B --host-record=laptop,laptop.thekelleys.org,192.168.0.1,1234::100
If the time-to-live is given, it overrides the default, which is zero
or the value of --local-ttl. The value is a positive integer and gives
or the value of \fB--local-ttl\fP. The value is a positive integer and gives
the time-to-live in seconds.
.TP
.B \-Y, --txt-record=<name>[[,<text>],<text>]
@@ -590,11 +593,14 @@ Return a PTR DNS record.
.B --naptr-record=<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<replacement>]
Return an NAPTR DNS record, as specified in RFC3403.
.TP
.B --caa-record=<name>,<flags>,<tag>,<value>
Return a CAA DNS record, as specified in RFC6844.
.TP
.B --cname=<cname>,[<cname>,]<target>[,<TTL>]
Return a CNAME record which indicates that <cname> is really
<target>. There are significant limitations on the target; it must be a
DNS name which is known to dnsmasq from /etc/hosts (or additional
hosts files), from DHCP, from --interface-name or from another
hosts files), from DHCP, from \fB--interface-name\fP or from another
.B --cname.
If the target does not satisfy this
criteria, the whole cname is ignored. The cname must be unique, but it
@@ -603,7 +609,7 @@ it's possible to declare multiple cnames to a target in a single line, like so:
.B --cname=cname1,cname2,target
If the time-to-live is given, it overrides the default, which is zero
or the value of -local-ttl. The value is a positive integer and gives
or the value of \fB--local-ttl\fP. The value is a positive integer and gives
the time-to-live in seconds.
.TP
.B --dns-rr=<name>,<RR-number>,[<hex data>]
@@ -624,7 +630,7 @@ matching PTR record is also created, mapping the interface address to
the name. More than one name may be associated with an interface
address by repeating the flag; in that case the first instance is used
for the reverse address-to-name mapping. Note that a name used in
--interface-name may not appear in /etc/hosts.
\fB--interface-name\fP may not appear in /etc/hosts.
.TP
.B --synth-domain=<domain>,<address range>[,<prefix>[*]]
Create artificial A/AAAA and PTR records for an address range. The
@@ -647,6 +653,13 @@ V4 mapped IPv6 addresses, which have a representation like ::ffff:1.2.3.4 are ha
The address range can be of the form
<ip address>,<ip address> or <ip address>/<netmask> in both forms of the option.
.TP
.B --dumpfile=<path/to/file>
Specify the location of a pcap-format file which dnsmasq uses to dump copies of network packets for debugging purposes. If the file exists when dnsmasq starts, it is not deleted; new packets are added to the end.
.TP
.B --dumpmask=<mask>
Specify which types of packets should be added to the dumpfile. The argument should be the OR of the bitmasks for each type of packet to be dumped: it can be specified in hex by preceding the number with 0x in the normal way. Each time a packet is written to the dumpfile, dnsmasq logs the packet sequence and the mask
representing its type. The current types are: 0x0001 - DNS queries from clients 0x0002 DNS replies to clients 0x0004 - DNS queries to upstream 0x0008 - DNS replies from upstream 0x0010 - queries send upstream for DNSSEC validation 0x0020 - replies to queries for DNSSEC validation 0x0040 - replies to client queries which fail DNSSEC validation 0x0080 replies to queries for DNSSEC validation which fail validation.
.TP
.B --add-mac[=base64|text]
Add the MAC address of the requestor to DNS queries which are
forwarded upstream. This may be used to DNS filtering by the upstream
@@ -655,7 +668,7 @@ subnet as the dnsmasq server. Note that the mechanism used to achieve this (an E
is not yet standardised, so this should be considered
experimental. Also note that exposing MAC addresses in this way may
have security and privacy implications. The warning about caching
given for --add-subnet applies to --add-mac too. An alternative encoding of the
given for \fB--add-subnet\fP applies to \fB--add-mac\fP too. An alternative encoding of the
MAC, as base64, is enabled by adding the "base64" parameter and a human-readable encoding of hex-and-colons is enabled by added the "text" parameter.
.TP
.B --add-cpe-id=<string>
@@ -685,7 +698,7 @@ will add 1.2.3.0/24 for both IPv4 and IPv6 requestors.
.TP
.B \-c, --cache-size=<cachesize>
Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching.
Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching. Note: huge cache size impacts performance.
.TP
.B \-N, --no-negcache
Disable negative caching. Negative caching allows dnsmasq to remember
@@ -712,10 +725,7 @@ 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 means that all replies will be
marked as untrusted. If
.B --dnssec-check-unsigned
is set and the upstream servers don't support DNSSEC, then DNS service will be entirely broken.
answers and this means that DNS service will be entirely broken.
.TP
.B --trust-anchor=[<class>],<domain>,<key-tag>,<algorithm>,<digest-type>,<digest>
Provide DS records to act a trust anchors for DNSSEC
@@ -724,17 +734,19 @@ key(s) (KSK) of the root zone,
but trust anchors for limited domains are also possible. The current
root-zone trust anchors may be downloaded from https://data.iana.org/root-anchors/root-anchors.xml
.TP
.B --dnssec-check-unsigned
As a default, dnsmasq does not check that unsigned DNS replies are
legitimate: they are assumed to be valid and passed on (without the
.B --dnssec-check-unsigned[=no]
As a default, dnsmasq checks that unsigned DNS replies are
legitimate: this entails possible extra queries even for the majority of DNS
zones which are not, at the moment, signed. If
.B --dnssec-check-unsigned=no
appears in the configuration, then such replies they are assumed to be valid and passed on (without the
"authentic data" bit set, of course). This does not protect against an
attacker forging unsigned replies for signed DNS zones, but it is
fast. If this flag is set, dnsmasq will check the zones of unsigned
replies, to ensure that unsigned replies are allowed in those
zones. The cost of this is more upstream queries and slower
performance. See also the warning about upstream servers in the
section on
.B --dnssec
fast.
Versions of dnsmasq prior to 2.80 defaulted to not checking unsigned replies, and used
.B --dnssec-check-unsigned
to switch this on. Such configurations will continue to work as before, but those which used the default of no checking will need to be altered to explicitly select no checking. The new default is because switching off checking for unsigned replies is inherently dangerous. Not only does it open the possiblity of forged replies, but it allows everything to appear to be working even when the upstream namesevers do not support DNSSEC, and in this case no DNSSEC validation at all is occuring.
.TP
.B --dnssec-no-timecheck
DNSSEC signatures are only valid for specified time windows, and should be rejected outside those windows. This generates an
@@ -747,10 +759,10 @@ which have not been thoroughly checked.
Earlier versions of dnsmasq overloaded SIGHUP (which re-reads much configuration) to also enable time validation.
If dnsmasq is run in debug mode (-d flag) then SIGINT retains its usual meaning of terminating the dnsmasq process.
If dnsmasq is run in debug mode (\fB--no-daemon\fP flag) then SIGINT retains its usual meaning of terminating the dnsmasq process.
.TP
.B --dnssec-timestamp=<path>
Enables an alternative way of checking the validity of the system time for DNSSEC (see --dnssec-no-timecheck). In this case, the
Enables an alternative way of checking the validity of the system time for DNSSEC (see \fB--dnssec-no-timecheck\fP). In this case, the
system time is considered to be valid once it becomes later than the timestamp on the specified file. The file is created and
its timestamp set automatically by dnsmasq. The file must be stored on a persistent filesystem, so that it and its mtime are carried
over system restarts. The timestamp file is created after dnsmasq has dropped root, so it must be in a location writable by the
@@ -783,7 +795,7 @@ interface addresses may be confined to only IPv6 addresses using
an interface has dynamically determined global IPv6 addresses which should
appear in the zone, but RFC1918 IPv4 addresses which should not.
Interface-name and address-literal subnet specifications may be used
freely in the same --auth-zone declaration.
freely in the same \fB--auth-zone\fP declaration.
It's possible to exclude certain IP addresses from responses. It can be
used, to make sure that answers contain only global routeable IP
@@ -811,7 +823,11 @@ authoritative zones as dnsmasq.
Specify the addresses of secondary servers which are allowed to
initiate zone transfer (AXFR) requests for zones for which dnsmasq is
authoritative. If this option is not given, then AXFR requests will be
accepted from any secondary.
accepted from any secondary. Specifying
.B --auth-peer
without
.B --auth-sec-servers
enables zone transfer but does not advertise the secondary in NS records returned by dnsmasq.
.TP
.B --conntrack
Read the Linux connection track mark associated with incoming DNS
@@ -821,7 +837,7 @@ associated with the queries which cause it, useful for bandwidth
accounting and firewalling. Dnsmasq must have conntrack support
compiled in and the kernel must have conntrack support
included and configured. This option cannot be combined with
--query-port.
.B --query-port.
.TP
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-addr>[,<end-addr>|<mode>][,<netmask>[,<broadcast>]][,<lease time>]
.TP
@@ -830,7 +846,7 @@ included and configured. This option cannot be combined with
Enable the DHCP server. Addresses will be given out from the range
<start-addr> to <end-addr> and from statically defined addresses given
in
.B dhcp-host
.B --dhcp-host
options. If the lease time is given, then leases
will be given for that length of time. The lease time is in seconds,
or minutes (eg 45m) or hours (eg 1h) or "infinite". If not given,
@@ -849,7 +865,7 @@ agent, dnsmasq cannot determine the netmask itself, so it should be
specified, otherwise dnsmasq will have to guess, based on the class (A, B or
C) of the network address. The broadcast address is
always optional. It is always
allowed to have more than one dhcp-range in a single subnet.
allowed to have more than one \fB--dhcp-range\fP in a single subnet.
For IPv6, the parameters are slightly different: instead of netmask
and broadcast address, there is an optional prefix length which must
@@ -873,7 +889,7 @@ then deleted. The interface name may have a final "*" wildcard. Note
that just any address on eth0 will not do: it must not be an
autoconfigured or privacy address, or be deprecated.
If a dhcp-range is only being used for stateless DHCP and/or SLAAC,
If a \fB--dhcp-range\fP is only being used for stateless DHCP and/or SLAAC,
then the address can be simply ::
.B --dhcp-range=::,constructor:eth0
@@ -892,7 +908,7 @@ The optional <mode> keyword may be
which tells dnsmasq to enable DHCP for the network specified, but not
to dynamically allocate IP addresses: only hosts which have static
addresses given via
.B dhcp-host
.B --dhcp-host
or from /etc/ethers will be served. A static-only subnet with address
all zeros may be used as a "catch-all" address to enable replies to all
Information-request packets on a subnet which is provided with
@@ -903,9 +919,9 @@ For IPv4, the <mode> may be
.B proxy
in which case dnsmasq will provide proxy-DHCP on the specified
subnet. (See
.B pxe-prompt
.B --pxe-prompt
and
.B pxe-service
.B --pxe-service
for details.)
For IPv6, the mode may be some combination of
@@ -971,10 +987,10 @@ dnsmasq to always allocate the machine lap the IP address
192.168.0.199.
Addresses allocated like this are not constrained to be
in the range given by the --dhcp-range option, but they must be in
in the range given by the \fB--dhcp-range\fP option, but they must be in
the same subnet as some valid dhcp-range. For
subnets which don't need a pool of dynamically allocated addresses,
use the "static" keyword in the dhcp-range declaration.
use the "static" keyword in the \fB--dhcp-range\fP declaration.
It is allowed to use client identifiers (called client
DUID in IPv6-land) rather than
@@ -985,7 +1001,7 @@ allowed to specify the client ID as text, like this:
.B --dhcp-host=id:clientidastext,.....
A single
.B dhcp-host
.B --dhcp-host
may contain an IPv4 address or an IPv6 address, or both. IPv6 addresses must be bracketed by square brackets thus:
.B --dhcp-host=laptop,[1234::56]
IPv6 addresses may contain only the host-identifier part:
@@ -1006,7 +1022,7 @@ allocated to a DHCP lease, but only if a
.B --dhcp-host
option specifying the name also exists. Only one hostname can be
given in a
.B dhcp-host
.B --dhcp-host
option, but aliases are possible by using CNAMEs. (See
.B --cname
).
@@ -1021,15 +1037,15 @@ useful when there is another DHCP server on the network which should
be used by some machines.
The set:<tag> construct sets the tag
whenever this dhcp-host directive is in use. This can be used to
whenever this \fB--dhcp-host\fP directive is in use. This can be used to
selectively send DHCP options just for this host. More than one tag
can be set in a dhcp-host directive (but not in other places where
can be set in a \fB--dhcp-host\fP directive (but not in other places where
"set:<tag>" is allowed). When a host matches any
dhcp-host directive (or one implied by /etc/ethers) then the special
\fB--dhcp-host\fP directive (or one implied by /etc/ethers) then the special
tag "known" is set. This allows dnsmasq to be configured to
ignore requests from unknown machines using
.B --dhcp-ignore=tag:!known
If the host matches only a dhcp-host directive which cannot
If the host matches only a \fB--dhcp-host\fP directive which cannot
be used because it specifies an address on different subnet, the tag "known-othernet" is set.
Ethernet addresses (but not client-ids) may have
wildcard bytes, so for example
@@ -1062,23 +1078,23 @@ has both wired and wireless interfaces.
Read DHCP host information from the specified file. If a directory
is given, then read all the files contained in that directory. The file contains
information about one host per line. The format of a line is the same
as text to the right of '=' in --dhcp-host. The advantage of storing DHCP host information
as text to the right of '=' in \fB--dhcp-host\fP. The advantage of storing DHCP host information
in this file is that it can be changed without re-starting dnsmasq:
the file will be re-read when dnsmasq receives SIGHUP.
.TP
.B --dhcp-optsfile=<path>
Read DHCP option information from the specified file. If a directory
is given, then read all the files contained in that directory. The advantage of
using this option is the same as for --dhcp-hostsfile: the
dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that
using this option is the same as for \fB--dhcp-hostsfile\fP: the
\fB--dhcp-optsfile\fP will be re-read when dnsmasq receives SIGHUP. Note that
it is possible to encode the information in a
.B --dhcp-boot
flag as DHCP options, using the options names bootfile-name,
server-ip-address and tftp-server. This allows these to be included
in a dhcp-optsfile.
in a \fB--dhcp-optsfile\fP.
.TP
.B --dhcp-hostsdir=<path>
This is equivalent to dhcp-hostsfile, except for the following. The path MUST be a
This is equivalent to \fB--dhcp-hostsfile\fP, except for the following. The path MUST be a
directory, and not an individual file. Changed or new files within
the directory are read automatically, without the need to send SIGHUP.
If a file is deleted or changed after it has been read by dnsmasq, then the
@@ -1086,7 +1102,7 @@ host record it contained will remain until dnsmasq receives a SIGHUP, or
is restarted; ie host records are only added dynamically.
.TP
.B --dhcp-optsdir=<path>
This is equivalent to dhcp-optsfile, with the differences noted for --dhcp-hostsdir.
This is equivalent to \fB--dhcp-optsfile\fP, with the differences noted for \fB--dhcp-hostsdir\fP.
.TP
.B \-Z, --read-ethers
Read /etc/ethers for information about hosts for the DHCP server. The
@@ -1157,12 +1173,12 @@ a literal IP address as TFTP server name, it is necessary to do
.B --dhcp-option=66,"1.2.3.4"
Encapsulated Vendor-class options may also be specified (IPv4 only) using
--dhcp-option: for instance
\fB--dhcp-option\fP: for instance
.B --dhcp-option=vendor:PXEClient,1,0.0.0.0
sends the encapsulated vendor
class-specific option "mftp-address=0.0.0.0" to any client whose
vendor-class matches "PXEClient". The vendor-class matching is
substring based (see --dhcp-vendorclass for details). If a
substring based (see \fB--dhcp-vendorclass\fP for details). If a
vendor-class option (number 60) is sent by dnsmasq, then that is used
for selecting encapsulated options in preference to any sent by the
client. It is
@@ -1175,7 +1191,7 @@ Options may be encapsulated (IPv4 only) within other options: for instance
will send option 175, within which is the option 190. If multiple
options are given which are encapsulated with the same option number
then they will be correctly combined into one encapsulated option.
encap: and vendor: are may not both be set in the same dhcp-option.
encap: and vendor: are may not both be set in the same \fB--dhcp-option\fP.
The final variant on encapsulated options is "Vendor-Identifying
Vendor Options" as specified by RFC3925. These are denoted like this:
@@ -1197,7 +1213,7 @@ needed, for example when sending options to PXELinux.
.B --dhcp-no-override
(IPv4 only) Disable re-use of the DHCP servername and filename fields as extra
option space. If it can, dnsmasq moves the boot server and filename
information (from dhcp-boot) out of their dedicated fields into
information (from \fB--dhcp-boot\fP) out of their dedicated fields into
DHCP options. This make extra space available in the DHCP packet for
options but can, rarely, confuse old or broken clients. This flag
forces "simple and safe" behaviour to avoid problems in such a case.
@@ -1207,7 +1223,7 @@ Configure dnsmasq to do DHCP relay. The local address is an address
allocated to an interface on the host running dnsmasq. All DHCP
requests arriving on that interface will we relayed to a remote DHCP
server at the server address. It is possible to relay from a single local
address to multiple remote servers by using multiple dhcp-relay
address to multiple remote servers by using multiple \fB--dhcp-relay\fP
configs with the same local address and different server
addresses. A server address must be an IP literal address, not a
domain name. In the case of DHCPv6, the server address may be the
@@ -1216,8 +1232,8 @@ must be given, not be wildcard, and is used to direct the multicast to the
correct interface to reach the DHCP server.
Access control for DHCP clients has the same rules as for the DHCP
server, see --interface, --except-interface, etc. The optional
interface name in the dhcp-relay config has a different function: it
server, see \fB--interface\fP, \fB--except-interface\fP, etc. The optional
interface name in the \fB--dhcp-relay\fP config has a different function: it
controls on which interface DHCP replies from the server will be
accepted. This is intended for configurations which have three
interfaces: one being relayed from, a second connecting the DHCP
@@ -1239,7 +1255,7 @@ Map from a vendor-class string to a tag. Most DHCP clients provide a
"vendor class" which represents, in some sense, the type of host. This option
maps vendor classes to tags, so that DHCP options may be selectively delivered
to different classes of hosts. For example
.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect
.B --dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect
will allow options to be set only for HP printers like so:
.B --dhcp-option=tag:printers,3,192.168.4.4
The vendor-class string is
@@ -1274,8 +1290,8 @@ normally given as colon-separated hex, but is also allowed to be a
simple string. If an exact match is achieved between the circuit or
agent ID and one provided by a relay agent, the tag is set.
.B dhcp-remoteid
(but not dhcp-circuitid) is supported in IPv6.
.B --dhcp-remoteid
(but not \fB--dhcp-circuitid\fP) is supported in IPv6.
.TP
.B --dhcp-subscrid=set:<tag>,<subscriber-id>
(IPv4 and IPv6) Map from RFC3993 subscriber-id relay agent options to tags.
@@ -1286,9 +1302,9 @@ a DHCP interaction to the DHCP server. Once a client is configured, it
communicates directly with the server. This is undesirable if the
relay agent is adding extra information to the DHCP packets, such as
that used by
.B dhcp-circuitid
.B --dhcp-circuitid
and
.B dhcp-remoteid.
.B --dhcp-remoteid.
A full relay implementation can use the RFC 5107 serverid-override
option to force the DHCP server to use the relay as a full proxy, with all
packets passing through it. This flag provides an alternative method
@@ -1304,12 +1320,10 @@ the option is sent and matches the value. The value may be of the form
"01:ff:*:02" in which case the value must match (apart from wildcards)
but the option sent may have unmatched data past the end of the
value. The value may also be of the same form as in
.B dhcp-option
.B --dhcp-option
in which case the option sent is treated as an array, and one element
must match, so
--dhcp-match=set:efi-ia32,option:client-arch,6
.B --dhcp-match=set:efi-ia32,option:client-arch,6
will set the tag "efi-ia32" if the the number 6 appears in the list of
architectures sent by the client in option 93. (See RFC 4578 for
details.) If the value is a string, substring matching is used.
@@ -1318,14 +1332,17 @@ The special form with vi-encap:<enterprise number> matches against
vendor-identifying vendor classes for the specified enterprise. Please
see RFC 3925 for more details of these rare and interesting beasts.
.TP
.B --dhcp-name-match=set:<tag>,<name>[*]
Set the tag if the given name is supplied by a dhcp client. There may be a single trailing wildcard *, which has the usual meaning. Combined with dhcp-ignore or dhcp-ignore-names this gives the ability to ignore certain clients by name, or disallow certain hostnames from being claimed by a client.
.TP
.B --tag-if=set:<tag>[,set:<tag>[,tag:<tag>[,tag:<tag>]]]
Perform boolean operations on tags. Any tag appearing as set:<tag> is set if
all the tags which appear as tag:<tag> are set, (or unset when tag:!<tag> is used)
If no tag:<tag> appears set:<tag> tags are set unconditionally.
Any number of set: and tag: forms may appear, in any order.
Tag-if lines are executed in order, so if the tag in tag:<tag> is a
\fB--tag-if\fP lines are executed in order, so if the tag in tag:<tag> is a
tag set by another
.B tag-if,
.B --tag-if,
the line which sets the tag must precede the one which tests it.
.TP
.B \-J, --dhcp-ignore=tag:<tag>[,tag:<tag>]
@@ -1334,10 +1351,10 @@ not allocate it a DHCP lease.
.TP
.B --dhcp-ignore-names[=tag:<tag>[,tag:<tag>]]
When all the given tags appear in the tag set, ignore any hostname
provided by the host. Note that, unlike dhcp-ignore, it is permissible
provided by the host. Note that, unlike \fB--dhcp-ignore\fP, it is permissible
to supply no tags, in which case DHCP-client supplied hostnames
are always ignored, and DHCP hosts are added to the DNS using only
dhcp-host configuration in dnsmasq and the contents of /etc/hosts and
\fB--dhcp-host\fP configuration in dnsmasq and the contents of /etc/hosts and
/etc/ethers.
.TP
.B --dhcp-generate-names=tag:<tag>[,tag:<tag>]
@@ -1385,7 +1402,7 @@ likely to move IP address; for this reason it should not be generally used.
.B --pxe-service=[tag:<tag>,]<CSA>,<menu text>[,<basename>|<bootservicetype>][,<server address>|<server_name>]
Most uses of PXE boot-ROMS simply allow the PXE
system to obtain an IP address and then download the file specified by
.B dhcp-boot
.B --dhcp-boot
and execute it. However the PXE system is capable of more complex
functions when supported by a suitable DHCP server.
@@ -1397,7 +1414,7 @@ integer may be used for other types. The
parameter after the menu text may be a file name, in which case dnsmasq acts as a
boot server and directs the PXE client to download the file by TFTP,
either from itself (
.B enable-tftp
.B --enable-tftp
must be set for this to work) or another TFTP server if the final server
address/name is given.
Note that the "layer"
@@ -1419,23 +1436,23 @@ timeout is given then after the
timeout has elapsed with no keyboard input, the first available menu
option will be automatically executed. If the timeout is zero then the first available menu
item will be executed immediately. If
.B pxe-prompt
.B --pxe-prompt
is omitted the system will wait for user input if there are multiple
items in the menu, but boot immediately if
there is only one. See
.B pxe-service
.B --pxe-service
for details of menu items.
Dnsmasq supports PXE "proxy-DHCP", in this case another DHCP server on
the network is responsible for allocating IP addresses, and dnsmasq
simply provides the information given in
.B pxe-prompt
.B --pxe-prompt
and
.B pxe-service
.B --pxe-service
to allow netbooting. This mode is enabled using the
.B proxy
keyword in
.B dhcp-range.
.B --dhcp-range.
.TP
.B \-X, --dhcp-lease-max=<number>
Limits dnsmasq to the specified maximum number of DHCP leases. The
@@ -1452,6 +1469,13 @@ allows dnsmasq to rebuild its lease database without each client needing to
reacquire a lease, if the database is lost. For DHCPv6 it sets the
priority in replies to 255 (the maximum) instead of 0 (the minimum).
.TP
.B --dhcp-rapid-commit
Enable DHCPv4 Rapid Commit Option specified in RFC 4039. When enabled, dnsmasq
will respond to a DHCPDISCOVER message including a Rapid Commit
option with a DHCPACK including a Rapid Commit option and fully committed
address and configuration information. Should only be enabled if either the
server is the only server for the subnet, or multiple servers are present and they each commit a binding for all clients.
.TP
.B --dhcp-alternate-port[=<server port>[,<client port>]]
(IPv4 only) Change the ports used for DHCP from the default. If this option is
given alone, without arguments, it changes the ports used for DHCP
@@ -1481,8 +1505,8 @@ the tags used to determine them.
.TP
.B --quiet-dhcp, --quiet-dhcp6, --quiet-ra
Suppress logging of the routine operation of these protocols. Errors and
problems will still be logged. --quiet-dhcp and quiet-dhcp6 are
over-ridden by --log-dhcp.
problems will still be logged. \fB--quiet-dhcp\fP and quiet-dhcp6 are
over-ridden by \fB--log-dhcp\fP.
.TP
.B \-l, --dhcp-leasefile=<path>
Use the specified file to store DHCP lease information.
@@ -1508,7 +1532,7 @@ address of the host (or DUID for IPv6) , the IP address, and the hostname,
if known. "add" means a lease has been created, "del" means it has
been destroyed, "old" is a notification of an existing lease when
dnsmasq starts or a change to MAC address or hostname of an existing
lease (also, lease length or expiry and client-id, if leasefile-ro is set).
lease (also, lease length or expiry and client-id, if \fB--leasefile-ro\fP is set).
If the MAC address is from a network type other than ethernet,
it will have the network type prepended, eg "06-01:23:45:67:89:ab" for
token ring. The process is run as root (assuming that dnsmasq was originally run as
@@ -1682,7 +1706,7 @@ and
Specify the user as which to run the lease-change script or Lua script. This defaults to root, but can be changed to another user using this flag.
.TP
.B --script-arp
Enable the "arp" and "arp-old" functions in the dhcp-script and dhcp-luascript.
Enable the "arp" and "arp-old" functions in the \fB--dhcp-script\fP and \fB--dhcp-luascript\fP.
.TP
.B \-9, --leasefile-ro
Completely suppress use of the lease database file. The file will not
@@ -1707,9 +1731,9 @@ OpenStack compute host where each such interface is a TAP interface to
a VM, or as in "old style bridging" on BSD platforms. A trailing '*'
wildcard can be used in each <alias>.
It is permissible to add more than one alias using more than one --bridge-interface option since
--bridge-interface=int1,alias1,alias2 is exactly equivalent to
--bridge-interface=int1,alias1 --bridge-interface=int1,alias2
It is permissible to add more than one alias using more than one \fB--bridge-interface\fP option since
\fB--bridge-interface=int1,alias1,alias2\fP is exactly equivalent to
\fB--bridge-interface=int1,alias1 --bridge-interface=int1,alias2\fP
.TP
.B \-s, --domain=<domain>[,<address range>[,local]]
Specifies DNS domains for the DHCP server. Domains may be be given
@@ -1740,11 +1764,11 @@ which can change the behaviour of dnsmasq with domains.
If the address range is given as ip-address/network-size, then a
additional flag "local" may be supplied which has the effect of adding
--local declarations for forward and reverse DNS queries. Eg.
\fB--local\fP declarations for forward and reverse DNS queries. Eg.
.B --domain=thekelleys.org.uk,192.168.0.0/24,local
is identical to
.B --domain=thekelleys.org.uk,192.168.0.0/24
--local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
.B --local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
The network size must be 8, 16 or 24 for this to be legal.
.TP
.B --dhcp-fqdn
@@ -1779,7 +1803,7 @@ discovery and (possibly) prefix discovery for autonomous address
creation are handled by a different protocol. When DHCP is in use,
only a subset of this is needed, and dnsmasq can handle it, using
existing DHCP configuration to provide most data. When RA is enabled,
dnsmasq will advertise a prefix for each dhcp-range, with default
dnsmasq will advertise a prefix for each \fB--dhcp-range\fP, with default
router as the relevant link-local address on
the machine running dnsmasq. By default, the "managed address" bits are set, and
the "use SLAAC" bit is reset. This can be changed for individual
@@ -1834,9 +1858,9 @@ Do not abort startup if specified tftp root directories are inaccessible.
.TP
.B --tftp-unique-root[=ip|mac]
Add the IP or hardware address of the TFTP client as a path component on the end
of the TFTP-root. Only valid if a tftp-root is set and the directory exists.
of the TFTP-root. Only valid if a \fB--tftp-root\fP is set and the directory exists.
Defaults to adding IP address (in standard dotted-quad format).
For instance, if tftp-root is "/tftp" and client 1.2.3.4 requests file "myfile"
For instance, if \fB--tftp-root\fP is "/tftp" and client 1.2.3.4 requests file "myfile"
then the effective path will be "/tftp/1.2.3.4/myfile" if /tftp/1.2.3.4 exists or /tftp/myfile otherwise.
When "=mac" is specified it will append the MAC address instead, using lowercase zero padded digits
separated by dashes, e.g.: 01-02-03-04-aa-bb
@@ -1846,12 +1870,12 @@ a DHCP lease from us.
.B --tftp-secure
Enable TFTP secure mode: without this, any file which is readable by
the dnsmasq process under normal unix access-control rules is
available via TFTP. When the --tftp-secure flag is given, only files
available via TFTP. When the \fB--tftp-secure\fP flag is given, only files
owned by the user running the dnsmasq process are accessible. If
dnsmasq is being run as root, different rules apply: --tftp-secure
dnsmasq is being run as root, different rules apply: \fB--tftp-secure\fP
has no effect, but only files which have the world-readable bit set
are accessible. It is not recommended to run dnsmasq as root with TFTP
enabled, and certainly not without specifying --tftp-root. Doing so
enabled, and certainly not without specifying \fB--tftp-root\fP. Doing so
can expose any world-readable file on the server to any host on the net.
.TP
.B --tftp-lowercase
@@ -1891,7 +1915,7 @@ cannot be lower than 1025 unless dnsmasq is running as root. The number
of concurrent TFTP connections is limited by the size of the port range.
.TP
.B \-C, --conf-file=<file>
Specify a different configuration file. The conf-file option is also allowed in
Specify a different configuration file. The \fB--conf-file\fP option is also allowed in
configuration files, to include multiple configuration files. A
filename of "-" causes dnsmasq to read configuration from stdin.
.TP
@@ -1909,7 +1933,7 @@ escape * characters.
.B --servers-file=<file>
A special case of
.B --conf-file
which differs in two respects. Firstly, only --server and --rev-server are allowed
which differs in two respects. Firstly, only \fB--server\fP and \fB--rev-server\fP are allowed
in the configuration file included. Secondly, the file is re-read and the configuration
therein is updated when dnsmasq receives SIGHUP.
.SH CONFIG FILE
@@ -1919,9 +1943,9 @@ if it exists. (On
FreeBSD, the file is
.I /usr/local/etc/dnsmasq.conf
) (but see the
.B \-C
.B \--conf-file
and
.B \-7
.B \--conf-dir
options.) The format of this
file consists of one option per line, exactly as the long options detailed
in the OPTIONS section but without the leading "--". Lines starting with # are comments and ignored. For
@@ -1937,8 +1961,8 @@ clears its cache and then re-loads
.I /etc/hosts
and
.I /etc/ethers
and any file given by --dhcp-hostsfile, --dhcp-hostsdir, --dhcp-optsfile,
--dhcp-optsdir, --addn-hosts or --hostsdir.
and any file given by \fB--dhcp-hostsfile\fP, \fB--dhcp-hostsdir\fP, \fB--dhcp-optsfile\fP,
\fB--dhcp-optsdir\fP, \fB--addn-hosts\fP or \fB--hostsdir\fP.
The dhcp lease change script is called for all
existing DHCP leases. If
.B
@@ -1958,7 +1982,7 @@ misses and the number of authoritative queries answered are also given. For each
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
mode or when full logging is enabled (\fB--log-queries\fP), a complete dump of the
contents of the cache is made.
The cache statistics are also available in the DNS as answers to
@@ -2039,7 +2063,7 @@ using
options or put their addresses real in another file, say
.I /etc/resolv.dnsmasq
and run dnsmasq with the
.B \-r /etc/resolv.dnsmasq
.B \--resolv-file /etc/resolv.dnsmasq
option. This second technique allows for dynamic update of the server
addresses by PPP or DHCP.
.PP
@@ -2057,60 +2081,60 @@ the CNAME is shadowed too.
The tag system works as follows: For each DHCP request, dnsmasq
collects a set of valid tags from active configuration lines which
include set:<tag>, including one from the
.B dhcp-range
.B --dhcp-range
used to allocate the address, one from any matching
.B dhcp-host
(and "known" or "known-othernet" if a dhcp-host matches)
.B --dhcp-host
(and "known" or "known-othernet" if a \fB--dhcp-host\fP matches)
The tag "bootp" is set for BOOTP requests, and a tag whose name is the
name of the interface on which the request arrived is also set.
Any configuration lines which include one or more tag:<tag> constructs
will only be valid if all that tags are matched in the set derived
above. Typically this is dhcp-option.
.B dhcp-option
above. Typically this is \fB--dhcp-option\fP.
.B --dhcp-option
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
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 \fB--dhcp-option=tag:!purple,3,1.2.3.4\fP sends the option when the
tag purple is not in the set of valid tags. (If using this in a
command line rather than a configuration file, be sure to escape !,
which is a shell metacharacter)
When selecting dhcp-options, a tag from dhcp-range is second class
When selecting \fB--dhcp-options\fP, a tag from \fB--dhcp-range\fP is second class
relative to other tags, to make it easy to override options for
individual hosts, so
.B dhcp-range=set:interface1,......
.B dhcp-host=set:myhost,.....
.B dhcp-option=tag:interface1,option:nis-domain,"domain1"
.B dhcp-option=tag:myhost,option:nis-domain,"domain2"
.B --dhcp-range=set:interface1,......
.B --dhcp-host=set:myhost,.....
.B --dhcp-option=tag:interface1,option:nis-domain,"domain1"
.B --dhcp-option=tag:myhost,option:nis-domain,"domain2"
will set the NIS-domain to domain1 for hosts in the range, but
override that to domain2 for a particular host.
.PP
Note that for
.B dhcp-range
.B --dhcp-range
both tag:<tag> and set:<tag> are allowed, to both select the range in
use based on (eg) dhcp-host, and to affect the options sent, based on
use based on (eg) \fB--dhcp-host\fP, and to affect the options sent, based on
the range selected.
This system evolved from an earlier, more limited one and for backward
compatibility "net:" may be used instead of "tag:" and "set:" may be
omitted. (Except in
.B dhcp-host,
.B --dhcp-host,
where "net:" may be used instead of "set:".) For the same reason, '#'
may be used instead of '!' to indicate NOT.
.PP
The DHCP server in dnsmasq will function as a BOOTP server also,
provided that the MAC address and IP address for clients are given,
either using
.B dhcp-host
.B --dhcp-host
configurations or in
.I /etc/ethers
, and a
.B dhcp-range
.B --dhcp-range
configuration option is present to activate the DHCP server
on a particular network. (Setting --bootp-dynamic removes the need for
on a particular network. (Setting \fB--bootp-dynamic\fP removes the need for
static address mappings.) The filename
parameter in a BOOTP request is used as a tag,
as is the tag "bootp", allowing some control over the options returned to
@@ -2131,8 +2155,8 @@ for which dnsmasq is authoritative our.zone.com.
The simplest configuration consists of two lines of dnsmasq configuration; something like
.nf
.B auth-server=server.example.com,eth0
.B auth-zone=our.zone.com,1.2.3.0/24
.B --auth-server=server.example.com,eth0
.B --auth-zone=our.zone.com,1.2.3.0/24
.fi
and two records in the external DNS
@@ -2155,8 +2179,8 @@ authoritative zone which dnsmasq is serving, typically at the root. Now
we have
.nf
.B auth-server=our.zone.com,eth0
.B auth-zone=our.zone.com,1.2.3.0/24
.B --auth-server=our.zone.com,eth0
.B --auth-zone=our.zone.com,1.2.3.0/24
.fi
.nf
@@ -2175,25 +2199,25 @@ entry or
.B --host-record.
.nf
.B auth-server=our.zone.com,eth0
.B host-record=our.zone.com,1.2.3.4
.B auth-zone=our.zone.com,1.2.3.0/24
.B --auth-server=our.zone.com,eth0
.B --host-record=our.zone.com,1.2.3.4
.B --auth-zone=our.zone.com,1.2.3.0/24
.fi
If the external address is dynamic, the address
associated with our.zone.com must be derived from the address of the
relevant interface. This is done using
.B interface-name
.B --interface-name
Something like:
.nf
.B auth-server=our.zone.com,eth0
.B interface-name=our.zone.com,eth0
.B auth-zone=our.zone.com,1.2.3.0/24,eth0
.B --auth-server=our.zone.com,eth0
.B --interface-name=our.zone.com,eth0
.B --auth-zone=our.zone.com,1.2.3.0/24,eth0
.fi
(The "eth0" argument in auth-zone adds the subnet containing eth0's
dynamic address to the zone, so that the interface-name returns the
(The "eth0" argument in \fB--auth-zone\fP adds the subnet containing eth0's
dynamic address to the zone, so that the \fB--interface-name\fP returns the
address in outside queries.)
Our final configuration builds on that above, but also adds a
@@ -2204,7 +2228,7 @@ secondary is beyond the scope of this man-page, but the extra
configuration of dnsmasq is simple:
.nf
.B auth-sec-servers=secondary.myisp.com
.B --auth-sec-servers=secondary.myisp.com
.fi
and
@@ -2218,13 +2242,13 @@ secondary to collect the DNS data. If you wish to restrict this data
to particular hosts then
.nf
.B auth-peer=<IP address of secondary>
.B --auth-peer=<IP address of secondary>
.fi
will do so.
Dnsmasq acts as an authoritative server for in-addr.arpa and
ip6.arpa domains associated with the subnets given in auth-zone
ip6.arpa domains associated with the subnets given in \fB--auth-zone\fP
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.
@@ -2241,8 +2265,8 @@ secondary servers for reverse lookups.
When dnsmasq is configured to act as an authoritative server, the
following data is used to populate the authoritative zone.
.PP
.B --mx-host, --srv-host, --dns-rr, --txt-record, --naptr-record
, as long as the record names are in the authoritative domain.
.B --mx-host, --srv-host, --dns-rr, --txt-record, --naptr-record, --caa-record,
as long as the record names are in the authoritative domain.
.PP
.B --cname
as long as the record name is in the authoritative domain. If the
@@ -2250,7 +2274,7 @@ target of the CNAME is unqualified, then it is qualified with the
authoritative zone name. CNAME used in this way (only) may be wildcards, as in
.nf
.B cname=*.example.com,default.example.com
.B --cname=*.example.com,default.example.com
.fi
.PP

View File

@@ -478,7 +478,8 @@ la traza reversa direcci
.TP
.B \-c, --cache-size=<tamaño de caché>
Fijar el tamaño del caché de dnsmasq. El predeterminado es 150 nombres.
Fijar el tamaño a cero deshabilita el caché.
Fijar el tamaño a cero deshabilita el caché. Nota: el gran tamaño de
caché afecta el rendimiento.
.TP
.B \-N, --no-negcache
Deshabilitar caché negativo. El caché negativo le permite a dnsmasq

View File

@@ -10,7 +10,7 @@ est un serveur à faible empreinte mémoire faisant DNS, TFTP, PXE, annonces de
routeurs et DHCP. Il offre à la fois les services DNS et DHCP pour un réseau
local (LAN).
.PP
Dnsmasq accepte les requêtes DNS et y réponds soit en utilisant un petit cache
Dnsmasq accepte les requêtes DNS et y répond soit en utilisant un petit cache
local, soit en effectuant une requête à un serveur DNS récursif externe (par
exemple celui de votre fournisseur d'accès internet). Il charge le contenu du
fichier /etc/hosts afin que les noms locaux n'apparaissant pas dans les DNS
@@ -19,25 +19,25 @@ pour les hôtes présents dans le service DHCP. Il peut aussi agir en temps que
serveur DNS faisant autorité pour un ou plusieurs domaines, permettant à des
noms locaux d'apparaitre dans le DNS global.
.PP
Le serveur DHCP Dnsmasq DHCP supporte les définitions d'adresses statiques et les
Le serveur DHCP de Dnsmasq supporte les définitions d'adresses statiques et les
réseaux multiples. Il fournit par défaut un jeu raisonnable de paramètres DHCP,
et peut être configuré pour fournir n'importe quelle option DHCP.
Il inclut un serveur TFTP sécurisé en lecture seule permettant le démarrage via
le réseau/PXE de clients DHCP et supporte également le protocole BOOTP. Le
support PXE est complet, et comprend un mode proxy permettant de fournir des
informations PXE aux clients alors que l'allocation DHCP est effectuée par un
autre serveur.
informations PXE aux clients alors que l'allocation d'adresse via DHCP est
effectuée par un autre serveur.
.PP
Le serveur DHCPv6 de dnsmasq possède non seulement les mêmes fonctionalités
Le serveur DHCPv6 de dnsmasq possède non seulement les mêmes fonctionnalités
que le serveur DHCPv4, mais aussi le support des annonces de routeurs ainsi
qu'une fonctionalité permettant l'addition de ressources AAAA pour des
qu'une fonctionnalité permettant l'addition de ressources AAAA pour des
clients utilisant DHCPv4 et la configuration IPv6 sans état (stateless
autoconfiguration).
Il inclut le support d'allocations d'adresses (à la fois en DHCPv6 et en
annonces de routeurs - RA) pour des sous-réseaux dynamiquement délégués via
une délégation de préfixe DHCPv6.
.PP
Dnsmasq est developpé pour de petits systèmes embarqués. It tends à avoir
Dnsmasq est développé pour de petits systèmes embarqués. Il tend à avoir
l'empreinte mémoire la plus faible possible pour les fonctions supportées,
et permet d'exclure les fonctions inutiles du binaire compilé.
.SH OPTIONS
@@ -46,16 +46,23 @@ Dans ce cas, la fonction correspondante sera désactivée. Par exemple
.B --pid-file=
(sans paramètre après le =) désactive l'écriture du fichier PID.
Sur BSD, à moins que le logiciel ne soit compilé avec la bibliothèque GNU
getopt, la forme longue des options ne fonctionne pas en ligne de commande; Elle
getopt, la forme longue des options ne fonctionne pas en ligne de commande; elle
est toujours supportée dans le fichier de configuration.
.TP
.B --test
Vérifie la syntaxe du ou des fichiers de configurations. Se termine avec le
Vérifie la syntaxe du ou des fichiers de configuration. Se termine avec le
code de retour 0 si tout est OK, ou un code différent de 0 dans le cas
contraire. Ne démarre pas Dnsmasq.
.TP
.B \-w, --help
Affiche toutes les options de ligne de commande.
.B --help dhcp
affiche les options de configuration connues pour DHCPv4, et
.B --help dhcp6
affiche les options de configuration connues pour DHCPv6.
.TP
.B \-h, --no-hosts
Ne pas charger les noms du fichier /etc/hosts.
Ne pas charger les noms d'hôtes du fichier /etc/hosts.
.TP
.B \-H, --addn-hosts=<fichier>
Fichiers d'hôtes additionnels. Lire le fichier spécifié en plus de /etc/hosts.
@@ -68,7 +75,7 @@ fichiers contenus dans ce répertoire.
.B \-E, --expand-hosts
Ajoute le nom de domaine aux noms simples (ne contenant pas de point dans le
nom) contenus dans le fichier /etc/hosts, de la même façon que pour le service
DHCP. Notez que cela ne s'applique pas au nom de domaine dans les CNAME, les
DHCP. Notez que cela ne s'applique pas aux noms de domaine dans les CNAME, les
enregistrements PTR, TXT, etc...
.TP
.B \-T, --local-ttl=<durée>
@@ -86,7 +93,7 @@ Les réponses négatives provenant des serveurs amonts contiennent normalement
une information de durée de vie (time-to-live) dans les enregistrements SOA,
information dont dnsmasq se sert pour mettre la réponse en cache. Si la réponse
du serveur amont omet cette information, dnsmasq ne cache pas la réponse. Cette
option permet de doner une valeur de durée de vie par défaut (en secondes) que
option permet de donner une valeur de durée de vie par défaut (en secondes) que
dnsmasq utilise pour mettre les réponses négatives dans son cache, même en
l'absence d'enregistrement SOA.
.TP
@@ -194,7 +201,7 @@ au dessus de la valeur spécifiée. Utile pour des systèmes derrière des dispo
garde-barrières ("firewalls").
.TP
.B \-i, --interface=<nom d'interface>
N'écouter que sur l'interface réseau spécifiée. Dnsmasq aujoute automatiquement
N'écouter que sur l'interface réseau spécifiée. Dnsmasq ajoute automatiquement
l'interface locale ("loopback") à la liste des interfaces lorsque l'option
.B --interface
est utilisée.
@@ -205,13 +212,13 @@ ou
n'est donnée, Dnsmasq écoutera sur toutes les interfaces disponibles sauf
celle(s) spécifiée(s) par l'option
.B --except-interface.
Les alias d'interfaces IP (e-g "eth1:0") ne peuvent être utilisés ni avec
Les alias d'interfaces IP (par exemple "eth1:0") ne peuvent être utilisés ni avec
.B --interface
ni
.B \--except-interface.
Utiliser l'option
.B --listen-address
à la place. Un simple joker, consistant d'un '*' final, peut-être utilisé dans
à la place. Un simple joker, consistant en un '*' final, peut être utilisé dans
les options
.B \--interface
et
@@ -229,10 +236,10 @@ sont fournies n'importe pas, et que l'option
.B --except-interface
l'emporte toujours sur les autres.
.TP
.B --auth-server=<domaine>,<interface>|<addresse IP>
.B --auth-server=<domaine>,<interface>|<adresse IP>
Active le mode DNS faisant autorité pour les requêtes arrivant sur cette
interface ou sur cette adresse. Noter que l'interface ou l'adresse n'ont
pas besoin d'être mentionées ni dans
pas besoin d'être mentionnées ni dans
.B --interface
ni dans
.B --listen-address
@@ -253,7 +260,7 @@ Ecouter sur la ou les adresse(s) IP spécifiée(s). Les options
.B \--interface
et
.B \--listen-address
peuvent-être spécifiées simultanément, auquel cas un jeu d'interfaces et
peuvent être spécifiées simultanément, auquel cas un jeu d'interfaces et
d'adresses seront utilisées. Notez que si
aucune option
.B \--interface
@@ -265,7 +272,7 @@ nécessaire de fournir explicitement son adresse IP, 127.0.0.1 via l'option
.B \--listen-address.
.TP
.B \-z, --bind-interfaces
Sur les systèmes qui le supporte, Dnsmasq s'associe avec l'interface joker
Sur les systèmes qui le supportent, Dnsmasq s'associe avec l'interface joker
("wildcard"), même lorsqu'il ne doit écouter que sur certaines interfaces. Par
la suite, il rejette les requêtes auxquelles il ne doit pas répondre. Cette
situation présente l'avantage de fonctionner même lorsque les interfaces vont
@@ -302,7 +309,7 @@ le réseau auquel ils sont attachés). Cette possibilité est actuellement limit
.TP
.B \-b, --bogus-priv
Fausse résolution inverse pour les réseaux privés. Toutes les requêtes DNS
inverses pour des adresses IP privées (ie 192.168.x.x, etc...) qui ne sont pas
inverses pour des adresses IP privées (192.168.x.x, etc...) qui ne sont pas
trouvées dans /etc/hosts ou dans le fichier de baux DHCP se voient retournées
une réponse "pas de tel domaine" ("no such domain") au lieu d'être transmises
aux serveurs de nom amont ("upstream server").
@@ -317,7 +324,7 @@ modifiera 1.2.3.56 en 6.7.8.56 et 1.2.3.67 en 6.7.8.67.
Cette fonctionnalité correspond à ce que les routeurs Cisco PIX appellent
"bidouillage DNS" ("DNS doctoring"). Si l'ancienne IP est donnée sous la forme
d'une gamme d'adresses, alors seules les adresses dans cette gamme seront
ecrites, et non le sous-réseau dans son ensemble. Ainsi,
écrites, et non le sous-réseau dans son ensemble. Ainsi,
.B --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
fait correspondre 192.168.0.10->192.168.0.40 à 10.0.0.10->10.0.0.40
.TP
@@ -380,7 +387,7 @@ effectuer ses requêtes à tous les serveurs disponibles. Le résultat renvoyé
au client sera celui fournit par le premier serveur ayant répondu.
.TP
.B --stop-dns-rebind
Rejete (et enregistre dans le journal d'activité) les adresses dans la gamme
Rejette (et enregistre dans le journal d'activité) les adresses dans la gamme
d'adresses IP privée (au sens RFC1918) qui pourraient être renvoyées par les
serveurs amonts suite à une résolution de nom. Cela bloque les attaques cherchant
à détourner de leur usage les logiciels de navigation web ('browser') en s'en
@@ -389,13 +396,13 @@ servant pour découvrir les machines situées sur le réseau local.
.B --rebind-localhost-ok
Exclue 127.0.0/8 des vérifications de réassociation DNS. Cette gamme d'adresses
est retournée par les serveurs Realtime Blackhole (RBL, utilisés dans la
lutte contre le spam), la bloquer peut entraîner des disfonctionnements de ces
lutte contre le spam), la bloquer peut entraîner des dysfonctionnements de ces
services.
.TP
.B --rebind-domain-ok=[<domaine>]|[[/<domaine>/[<domaine>/]
Ne pas détecter ni bloquer les actions de type dns-rebind pour ces domaines.
Cette option peut prendre comme valeur soit un nom de domaine soit plusieurs
noms de domains entourés par des '/', selon une syntaxe similaire à l'option
noms de domaine entourés par des '/', selon une syntaxe similaire à l'option
--server, c-à-d :
.B --rebind-domain-ok=/domaine1/domaine2/domaine3/
.TP
@@ -474,7 +481,7 @@ serveur de nom. Il doit s'agir d'une des adresses IP appartenant à la machine s
laquelle tourne Dnsmasq ou sinon la ligne sera ignorée et une erreur sera
consignée dans le journal des événements, ou alors d'un nom d'interface. Si un nom
d'interface est donné, alors les requêtes vers le serveur de nom seront envoyées
depuis cette interface; si une adresse ip est donnée, alors l'adresse source de
depuis cette interface; si une adresse IP est donnée, alors l'adresse source de
la requête sera l'adresse en question. L'option query-port est ignorée pour tous
les serveurs ayant une adresse source spécifiée, mais il est possible de la donner
directement dans la spécification de l'adresse source. Forcer les requêtes à être
@@ -510,7 +517,7 @@ d'IP netfilter (ipset) indiqués. Domaines et sous-domaines sont résolus de la
même façon que pour --address. Ces groupes d'IP doivent déjà exister. Voir
ipset(8) pour plus de détails.
.TP
.B \-m, --mx-host=<nom de l'hôte>[[,<nom du MX>],<préference>]
.B \-m, --mx-host=<nom de l'hôte>[[,<nom du MX>],<préférence>]
Spécifie un enregistrement de type MX pour <nom de l'hôte> retournant le nom
donné dans <nom du MX> (s'il est présent), ou sinon le nom spécifié dans
l'option
@@ -612,7 +619,7 @@ l'enregistrement est donnée dans les données hexadécimales, qui peuvent
être de la forme 01:23:45, 01 23 45,+012345 ou n'importe quelle combinaison.
.TP
.B --interface-name=<nom>,<interface>
Définit un entregistrement DNS associant le nom avec l'adresse primaire sur
Définit un enregistrement DNS associant le nom avec l'adresse primaire sur
l'interface donnée en argument. Cette option spécifie un enregistrement de type
A pour le nom donné en argument de la même façon que s'il était défini par une
ligne de /etc/hosts, sauf que l'adresse n'est pas constante mais dépendante de
@@ -638,7 +645,7 @@ IPv6 pouvant commencer par '::', mais les noms DNS ne pouvant pas commencer
par '-', si aucun préfixe n'est donné, un zéro est ajouté en début de nom.
Ainsi, ::1 devient 0--1.
La plage d'adresses peut-être de la forme
La plage d'adresses peut être de la forme
<adresse IP>,<adresse IP> ou <adresse IP>/<masque réseau>
.TP
.B --add-mac
@@ -647,7 +654,7 @@ amonts. Cela peut être utilisé dans un but de filtrage DNS par les serveurs
amonts. L'adresse MAC peut uniquement être ajoutée si le requêteur est sur le
même sous-réseau que le serveur dnsmasq. Veuillez noter que le mécanisme
utilisé pour effectuer cela (une option EDNS0) n'est pas encore standardisée,
aussi cette fonctionalité doit être considérée comme expérimentale. Notez
aussi cette fonctionnalité doit être considérée comme expérimentale. Notez
également qu'exposer les adresses MAC de la sorte peut avoir des implications
en termes de sécurité et de vie privée. L'avertissement donné pour --add-subnet
s'applique également ici.
@@ -659,19 +666,20 @@ longueur du préfixe : 32 (ou 128 dans le cas d'IPv6) transmet la totalité
de l'adresse, 0 n'en transmet aucun mais marque néanmoins la requête ce qui
fait qu'aucun serveur amont ne rajoutera d'adresse client. La valeur par
défaut est zéro et pour IPv4 et pour IPv6. A noter que les serveurs amonts
peuvent-être configurés pour retourner des valeurs différentes en fonction
peuvent être configurés pour retourner des valeurs différentes en fonction
de cette information mais que le cache de dnsmasq n'en tient pas compte.
Si une instance de dnsmasq est configurée de telle maniêre que des valeurs
différentes pourraient-être rencontrés, alors le cache devrait être désactivé.
Si une instance de dnsmasq est configurée de telle manière que des valeurs
différentes pourraient être rencontrées, alors le cache devrait être désactivé.
.TP
.B \-c, --cache-size=<taille>
Définit la taille du cache de Dnsmasq. La valeur par défaut est de 150 noms.
Définir une valeur de zéro désactive le cache.
Définir une valeur de zéro désactive le cache. Remarque: la taille importante
du cache a un impact sur les performances.
.TP
.B \-N, --no-negcache
Désactive le "cache négatif". Le "cache négatif" permet à Dnsmasq de se souvenir
des réponses de type "no such domain" fournies par les serveurs DNS en amont et
de fournir les réponses sans avoir à re-transmettre les requêtes aux serveurs
de fournir les réponses sans avoir à retransmettre les requêtes aux serveurs
amont.
.TP
.B \-0, --dns-forward-max=<nombre de requêtes>
@@ -683,17 +691,17 @@ son journal des requêtes, ce qui peut générer un nombre important de requête
simultanées.
.TP
.B --proxy-dnssec
Un resolveur sur une machine cliente peut effectuer la validation DNSSEC de
Un résolveur sur une machine cliente peut effectuer la validation DNSSEC de
deux façons : il peut effectuer lui-même les opérations de chiffrements sur
la réponse reçue, ou il peut laisser le serveur récursif amont faire la
validation et positionner un drapeau dans la réponse au cas où celle-ci est
correcte. Dnsmasq n'est pas un validateur DNSSEC, aussi il ne peut effectuer
la validation comme un serveur de nom récursif, cependant il peut retransmettre
les résultats de validation de ses serveurs amonts. Cette option permet
l'activation de cette fonctionalité. Vous ne devriez utiliser cela que si vous
l'activation de cette fonctionnalité. Vous ne devriez utiliser cela que si vous
faites confiance aux serveurs amonts
.I ainsi que le réseau entre vous et eux.
Si vous utilisez le premier mode DNSSEC, la validation par le resolveur des
Si vous utilisez le premier mode DNSSEC, la validation par le résolveur des
clients, cette option n'est pas requise. Dnsmasq retourne toujours toutes les
données nécessaires par un client pour effectuer la validation lui-même.
.TP
@@ -703,12 +711,12 @@ Définie une zone DNS pour laquelle dnsmasq agit en temps que serveur faisant
autorité. Les enregistrements DNS définis localement et correspondant à ce
domaine seront fournis. Les enregistrements A et AAAA doivent se situer dans
l'un des sous-réseaux définis, ou dans un réseau correspondant à une plage DHCP
(ce comportement peut-être désactivé par
(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 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
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
conforme au RFC 2317.
.TP
@@ -719,7 +727,7 @@ optionnel, les valeurs par défaut devant convenir à la majorité des cas.
.TP
.B --auth-sec-servers=<domaine>[,<domaine>[,<domaine>...]]
Spécifie un ou plusieurs serveur de nom secondaires pour une zone pour
laquelle dnsmasq fait autorité. Ces serveurs doivent-être configurés pour
laquelle dnsmasq fait autorité. Ces serveurs doivent être configurés pour
récupérer auprès de dnsmasq les informations liées à la zone au travers d'un
transfert de zone, et répondre aux requêtes pour toutes les zones pour
lesquelles dnsmasq fait autorité.
@@ -733,7 +741,7 @@ seront acceptées pour tous les serveurs secondaires.
.B --conntrack
Lis le marquage de suivi de connexion Linux associé aux requêtes DNS entrantes
et positionne la même marque au trafic amont utilisé pour répondre à ces
requétes. Cela permet au trafic généré par Dnsmasq d'étre associé aux requêtes
requêtes. Cela permet au trafic généré par Dnsmasq d'être associé aux requêtes
l'ayant déclenché, ce qui est pratique pour la gestion de la bande passante
(accounting) et le filtrage (firewall). Dnsmasq doit pour cela être compilé
avec le support conntrack, le noyau doit également inclure conntrack et être
@@ -742,7 +750,7 @@ configuré pour cela. Cette option ne peut pas être combinée avec
.TP
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<adresse de début>[,<adresse de fin>][,<mode>][,<masque de réseau>[,<broadcast>]][,<durée de bail>]
.TP
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<addresse IPv6 de début>[,<adresse IPv6 de fin>|constructor:<interface>][,<mode>][,<longueur de préfixe>][,<durée de bail>]
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<adresse IPv6 de début>[,<adresse IPv6 de fin>|constructor:<interface>][,<mode>][,<longueur de préfixe>][,<durée de bail>]
Active le serveur DHCP. Les adresses seront données dans la plage comprise entre
<adresse de début> et <adresse de fin> et à partir des adresses définies
@@ -755,7 +763,7 @@ durée indéterminée. Si aucune valeur n'est donnée, une durée de bail par d
de une heure est appliquée. La valeur minimum pour un bail DHCP est de 2
minutes.
Pour les plages IPv6, la durée de bail peut-être égale au mot-clef "deprecated"
Pour les plages IPv6, la durée de bail peut être égale au mot-clef "deprecated"
(obsolète); Cela positionne la durée de vie préférée envoyée dans les baux DHCP
ou les annonces routeurs à zéro, ce qui incite les clients à utiliser d'autres
adresses autant que possible, pour toute nouvelle connexion, en préalable à
@@ -795,7 +803,7 @@ adresses assignées à l'interface. Par exemple
provoque la recherche d'adresses de la forme <réseau>::1 sur eth0 et crée une
plage allant de <réseau>::1 à <réseau>:400. Si une interface est assignée à
plus d'un réseau, les plages correspondantes seront automatiquement créées,
rendues obsolètes puis supprimées lorsque l'adress est rendue obsolète puis
rendues obsolètes puis supprimées lorsque l'adresse est rendue obsolète puis
supprimée. Le nom de l'interface peut être spécifié avec un caractère joker '*'
final.
@@ -809,7 +817,7 @@ obsolètes ne conviennent pas.
Si une plage dhcp-range est uniquement utilisée pour du DHCP sans-état
("stateless") ou de l'autoconfiguration sans état ("SLAAC"), alors l'adresse
peut-être indiquée sous la forme '::'
peut être indiquée sous la forme '::'
.B --dhcp-range=::,constructor:eth0
@@ -851,7 +859,7 @@ et
.B pxe-service
pour plus de détails).
Pour IPv6, le mode peut-être une combinaison des valeurs
Pour IPv6, le mode peut être une combinaison des valeurs
.B ra-only, slaac, ra-names, ra-stateless, off-link.
.B ra-only
@@ -883,7 +891,7 @@ connectés (et non ceux pour lesquels DHCP se fait via relai), et ne
fonctionnera pas si un hôte utilise les "extensions de vie privée"
("privacy extensions").
.B ra-names
peut-être combiné avec
peut être combiné avec
.B ra-stateless
et
.B slaac.
@@ -914,7 +922,7 @@ sous-réseau qu'une plage dhcp-range valide. Pour les sous-réseaux qui n'ont pa
besoin d'adresses dynamiquement allouées, utiliser le mot-clef "static" dans la
déclaration de plage d'adresses dhcp-range.
Il est possible d'utiliser des identifiants clients (appellé "DUID client" dans
Il est possible d'utiliser des identifiants clients (appelés "DUID client" dans
le monde IPv6) plutôt que des adresses matérielles pour identifier les hôtes,
en préfixant ceux-ci par 'id:'. Ainsi,
.B --dhcp-host=id:01:02:03:04,.....
@@ -926,7 +934,7 @@ ceci :
Un seul
.B dhcp-host
peut contenir une adresse IPv4, une adresse IPv6, ou les deux en même temps.
Les adresses IPv6 doivent-être mises entre crochets comme suit :
Les adresses IPv6 doivent être mises entre crochets comme suit :
.B --dhcp-host=laptop,[1234::56]
Les adresses IPv6 peuvent ne contenir que la partie identifiant de client :
.B --dhcp-host=laptop,[::56]
@@ -945,7 +953,7 @@ identifiant client mais pas les autres.
Si un nom apparaît dans /etc/hosts, l'adresse associée peut être allouée à un
bail DHCP mais seulement si une option
.B --dhcp-host
spécifiant le nom existe par ailleurs. Seul un nom d'hôte peut-être donné dans
spécifiant le nom existe par ailleurs. Seul un nom d'hôte peut être donné dans
une option
.B dhcp-host
, mais les alias sont possibles au travers de l'utilisation des CNAMEs. (Voir
@@ -973,7 +981,7 @@ Les adresses ethernet (mais pas les identifiants clients) peuvent être définie
avec des octets joker, ainsi par exemple
.B --dhcp-host=00:20:e0:3b:13:*,ignore
demande à Dnsmasq d'ignorer une gamme d'adresses matérielles. Il est à noter
que "*" doit-être précédé d'un caractère d'échappement ou mis entre guillemets
que "*" doit être précédé d'un caractère d'échappement ou mis entre guillemets
lorsque spécifié en option de ligne de commande, mais pas dans le fichier de
configuration.
@@ -1059,14 +1067,14 @@ qu'aux réseaux dont tous les labels coïncident avec ceux de la requête.
Un traitement spécial est effectué sur les chaînes de caractères fournies pour
l'option 119, conformément à la RFC 3397. Les chaînes de caractères ou les
adresses IP sous forme de 4 chiffres séparés par des points donnés en arguments
de l'option 120 sont traités conforméments à la RFC 3361. Les adresses IP sous
de l'option 120 sont traités conformément à la RFC 3361. Les adresses IP sous
forme de 4 chiffres séparés par des points suivies par une barre montante "/",
puis une taille de masque sont encodés conforméments à la RFC 3442.
puis une taille de masque sont encodés conformément à la RFC 3442.
Les options IPv6 sont fournies en utilisant le mot-clef
.B option6:
suivi par le numéro d'option ou le nom d'option. L'espace de nommage des options
IPv6 est disjint de l'espace de nommage des options IPv4. Les adresses IPv6
IPv6 est disjoint de l'espace de nommage des options IPv4. Les adresses IPv6
en option doivent être entourées de crochets, comme par exemple :
.B --dhcp-option=option6:ntp-server,[1234::56]
@@ -1075,7 +1083,7 @@ adéquat sont envoyées pour un numéro d'option donné, il est tout à fait pos
de persuader Dnsmasq de générer des paquets DHCP illégaux par une utilisation
incorrecte de cette option. Lorsque la valeur est un nombre décimal, Dnsmasq
doit déterminer la taille des données. Cela est fait en examinant le numéro de
l'option et/ou la valeur, mais peut-être évité en rajoutant un suffixe d'une
l'option et/ou la valeur, mais peut être évité en rajoutant un suffixe d'une
lettre comme suit :
b = un octet, s = 2 octets, i = 4 octets. Cela sert essentiellement pour des
options encapsulées de classes de vendeurs (voir plus bas), pour lesquelles
@@ -1088,7 +1096,7 @@ d'une chaîne de caractères comme nom de serveur TFTP, il est nécessaire de fa
comme suit :
.B --dhcp-option=66,"1.2.3.4"
Les options encapsulées de classes de vendeurs peuvent-être aussi spécifiées
Les options encapsulées de classes de vendeurs peuvent être aussi spécifiées
(pour IPv4 seulement) en utilisant
.B --dhcp-option
: par exemple
@@ -1105,7 +1113,7 @@ par le client. Il est possible d'omettre complètement une classe de vendeur :
.B --dhcp-option=vendor:,1,0.0.0.0
Dans ce cas l'option encapsulée est toujours envoyée.
En IPv4, les options peuvent-être encapsulées au sein d'autres options :
En IPv4, les options peuvent être encapsulées au sein d'autres options :
par exemple
.B --dhcp-option=encap:175, 190, "iscsi-client0"
enverra l'option 175, au sein de laquelle se trouve l'option 190.
@@ -1128,7 +1136,7 @@ une option encapsulée.
Cela fonctionne exactement de la même façon que
.B --dhcp-option
sauf que cette option sera toujours envoyée, même si le client ne la demande pas
dans la liste de paramêtres requis. Cela est parfois nécessaire, par exemple lors
dans la liste de paramètres requis. Cela est parfois nécessaire, par exemple lors
de la fourniture d'options à PXELinux.
.TP
.B --dhcp-no-override
@@ -1149,10 +1157,10 @@ Toutes les requêtes DHCP arrivant sur cette interface seront relayées au
serveur DHCP distant correspondant à l'adresse de serveur indiquée. Il est
possible de relayer depuis une unique adresse locale vers différents serveurs
distant en spécifiant plusieurs fois l'option dhcp-relay avec la même adresse
locale et différentes adresses de serveur. L'adresse de serveur doit-être
sous forme numérique. Dans le cas de DHCPv6, l'adresse de serveur peut-être
locale et différentes adresses de serveur. L'adresse de serveur doit être
sous forme numérique. Dans le cas de DHCPv6, l'adresse de serveur peut être
l'adresse de multicast ff05::1:3 correspondant à tous les serveurs DHCP. Dans
ce cas, l'interface doittre spécifiée et ne peut comporter de caractère
ce cas, l'interface doit être spécifiée et ne peut comporter de caractère
joker. Elle sera utilisée pour indiquer l'interface à partir de laquelle le
multicast pourra atteindre le serveur DHCP.
@@ -1181,14 +1189,14 @@ vice-versa.
Associe une chaîne de classe de vendeur à un label. La plupart
des clients DHCP fournissent une "classe de vendeur" ("vendor class") qui
représente, d'une certaine façon, le type d'hôte. Cette option associe des
classes de vendeur à des labels, de telle sorte que des options DHCP peuvent-être
fournie de manière sélective aux différentes classes d'hôtes. Par exemple,
classes de vendeur à des labels, de telle sorte que des options DHCP peuvent être
fournies de manière sélective aux différentes classes d'hôtes. Par exemple,
.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect
ou
.B dhcp-vendorclass=printers,Hewlett-Packard JetDirect
permet de n'allouer des options qu'aux imprimantes HP de la manière suivante :
.B --dhcp-option=tag:printers,3,192.168.4.4
La chaîne de caractères de la classe de vendeur founie en argument est cherchée
La chaîne de caractères de la classe de vendeur fournie en argument est cherchée
en temps que sous-chaîne de caractères au sein de la classe de vendeur fournie
par le client, de façon à permettre la recherche d'un sous-ensemble de la chaîne
de caractères ("fuzzy matching"). Le préfixe set: est optionnel mais autorisé
@@ -1218,7 +1226,7 @@ matérielle coïncide avec les critères définis.
.TP
.B --dhcp-circuitid=set:<label>,<identifiant de circuit>, --dhcp-remoteid=set:<label>,<identifiant distant>
Associe des options de relais DHCP issus de la RFC3046 à des labels.
Cette information peut-être fournie par des relais DHCP. L'identifiant
Cette information peut être fournie par des relais DHCP. L'identifiant
de circuit ou l'identifiant distant est normalement fourni sous la forme d'une
chaîne de valeurs hexadécimales séparées par des ":", mais il est également
possible qu'elle le soit sous la forme d'une simple chaîne de caractères. Si
@@ -1231,7 +1239,7 @@ est supporté en IPv6 (mais non dhcp-circuitid).
(IPv4 et IPv6) Associe des options de relais DHCP issues de la RFC3993 à des
labels.
.TP
.B --dhcp-proxy[=<adresse ip>]......
.B --dhcp-proxy[=<adresse IP>]......
(IPv4 seulement) Un agent relai DHCP normal est uniquement utilisé pour faire
suivre les éléments initiaux de l'interaction avec le serveur DHCP. Une fois
que le client est configuré, il communique directement avec le serveur. Cela
@@ -1252,7 +1260,7 @@ interactions avec les relais dont l'adresse est dans la liste seront affectées.
Si aucune valeur n'est spécifiée, associe le label si le client
envoie une option DHCP avec le numéro ou le nom spécifié. Lorsqu'une valeur est
fournie, positionne le label seulement dans le cas où l'option est fournie et
correspond à la valeur. La valeur peut-être de la forme "01:ff:*:02", auquel
correspond à la valeur. La valeur peut être de la forme "01:ff:*:02", auquel
cas le début de l'option doit correspondre (en respectant les jokers). La
valeur peut aussi être de la même forme que dans
.B dhcp-option
@@ -1262,14 +1270,14 @@ valeur peut aussi être de la même forme que dans
--dhcp-match=set:efi-ia32,option:client-arch,6
spécifie le label "efi-ia32" si le numéro 6 apparaît dnas la liste
d'architectures envoyé par le client au sein de l'option 93. (se réferer
d'architectures envoyé par le client au sein de l'option 93. (se référer
au RFC 4578 pour plus de détails). Si la valeur est un chaine de caractères,
celle-ci est recherchée (correspondance en temps que sous-chaîne).
Pour la forme particulière vi-encap:<numéro d'entreprise>, la comparaison se
fait avec les classes de vendeur "identifiant de vendeur" ("vendor-identifying
vendor classes") pour l'entreprise dont le numéro est fourni en option.
Veuillez vous réferer à la RFC 3925 pour plus de détail.
Veuillez vous référer à la RFC 3925 pour plus de détails.
.TP
.B --tag-if=set:<label>[,set:<label>[,tag:<label>[,tag:<label>]]]
Effectue une opération booléenne sur les labels. Si tous les labels
@@ -1280,7 +1288,7 @@ Si aucun tag:<label> n'est spécifié, alors tous les labels fournis par
set:<label> sont positionnés.
N'importe quel nombre de set: ou tag: peuvent être fournis, et l'ordre est sans
importance.
Les lignes tag-if sont executées dans l'ordre, ce qui fait que si un label dans
Les lignes tag-if sont exécutées dans l'ordre, ce qui fait que si un label dans
tag:<label> est un label positionné par une rêgle
.B tag-if,
la ligne qui positionne le label doit précéder celle qui le teste.
@@ -1320,17 +1328,17 @@ le cas de certains vieux clients BOOTP.
(IPv4 seulement) Spécifie les options BOOTP devant être retournées par le
serveur DHCP. Le nom de serveur ainsi que l'adresse sont optionnels : s'ils
ne sont pas fournis, le nom est laissé vide et l'adresse fournie est celle de
la machine sur laquelle s'exécute Dnsmasq. Si Dnsmasq founit un service TFTP (voir
la machine sur laquelle s'exécute Dnsmasq. Si Dnsmasq fournit un service TFTP (voir
.B --enable-tftp
), alors seul un nom de fichier est requis ici pour permettre un démarrage par
le réseau.
Si d'éventuels labels sont fournis, ils doivent coïncider avec
ceux du client pour que cet élement de configuration lui soit envoyé.
ceux du client pour que cet élément de configuration lui soit envoyé.
Une adresse de serveur TFTP peut être spécifiée à la place de l'adresse IP,
sous la forme d'un nom de domaine qui sera cherché dans le fichier /etc/hosts.
Ce nom peut être associé dans /etc/hosts avec plusieurs adresses IP, auquel cas
celles-ci seront utilisées tour à tour (algorithme round-robin).
Cela peut-être utiliser pour équilibrer la charge tftp sur plusieurs serveurs.
Cela peut être utilisé pour équilibrer la charge tftp sur plusieurs serveurs.
.TP
.B --dhcp-sequential-ip
Dnsmasq est conçu pour choisir l'adresse IP des clients DHCP en utilisant
@@ -1357,7 +1365,7 @@ Ceci spécifie l'option de démarrage qui apparaitra dans un menu de démarrage
PXE. <CSA> est le type du système client. Seuls des types de services valides
apparaitront dans un menu. Les types connus sont x86PC, PC98, IA64_EFI, Alpha,
Arc_x86, Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI et X86-64_EFI;
D'autres types peuvent-être spécifiés sous la forme d'une valeur entière. Le
D'autres types peuvent être spécifiés sous la forme d'une valeur entière. Le
paramètre après le texte correspondant à l'entrée dans le menu peut être un nom
de fichier, auquel cas Dnsmasq agit comme un serveur de démarrage et indique au
client PXE qu'il faut télécharger ce fichier via TFTP, soit depuis ce serveur
@@ -1376,7 +1384,7 @@ démarrage n'est fournie (ou qu'une valeur de 0 est donnée pour le type de
service), alors l'entrée de menu provoque l'interruption du démarrage par
le réseau et la poursuite du démarrage sur un média local. L'adresse de serveur
peut être donnée sous la forme de nom de domaine qui est recherché dans
/etc/hosts. Ce nom peut-être associé à plusieurs adresses IP, qui dans ce cas
/etc/hosts. Ce nom peut être associé à plusieurs adresses IP, qui dans ce cas
sont utilisées à tour de rôle (en "round-robin").
.TP
.B --pxe-prompt=[tag:<label>,]<invite>[,<délai>]
@@ -1435,7 +1443,7 @@ Utiliser cette option avec précaution, une adresse allouée à un client BOOTP
étant perpétuelle, et de fait n'est plus disponibles pour d'autres hôtes. Si
aucun argument n'est donné, alors cette option permet une allocation dynamique
dans tous les cas. Si des arguments sont spécifiés, alors l'allocation ne se
fait que lorsque tous les identifiants coïncident. Il est possible de répeter
fait que lorsque tous les identifiants coïncident. Il est possible de répéter
cette option avec plusieurs jeux d'arguments.
.TP
.B \-5, --no-ping
@@ -1560,7 +1568,7 @@ Tous les descripteurs de fichiers sont fermés, sauf stdin, stdout et stderr qui
sont ouverts sur /dev/null (sauf en mode déverminage).
Le script n'est pas lancé de manière concurrente : au plus une instance du
script est executée à la fois (dnsmasq attends qu'une instance de script se
script est exécutée à la fois (dnsmasq attend qu'une instance de script se
termine avant de lancer la suivante). Les changements dans la base des baux
nécessitant le lancement du script sont placé en attente dans une queue jusqu'à
terminaison d'une instance du script en cours. Si cette mise en queue fait que
@@ -1575,7 +1583,7 @@ le script sera invoqué avec une action "old" pour tous les baux existants.
Il existe deux autres actions pouvant apparaître comme argument au script :
"init" et "tftp". D'autres sont susceptibles d'être rajoutées dans le futur,
aussi les scripts devraient-être écrits de sorte à ignorer les actions
aussi les scripts devraient être écrits de sorte à ignorer les actions
inconnues. "init" est décrite ci-dessous dans
.B --leasefile-ro.
L'action "tftp" est invoquée lorsqu'un transfert de fichier TFTP s'est
@@ -1588,7 +1596,7 @@ Spécifie un script écrit en Lua, devant être exécuté lorsque des baux sont
créés, détruits ou modifiés. Pour utiliser cette option, dnsmasq doit être
compilé avec avec le support de Lua. L'interpréteur Lua est initialisé une
seule fois, lorsque dnsmasq démarre, ce qui fait que les variables globales
persistent entre les évênements liés aux baux. Le code Lua doit définir une
persistent entre les événements liés aux baux. Le code Lua doit définir une
fonction
.B lease
et peut fournir des fonctions
@@ -1637,7 +1645,7 @@ et
.B --dhcp-scriptuser
Spécifie l'utilisateur sous lequel le script shell lease-change ou le script
doivent être exécutés. La valeur par défaut correspond à l'utilisateur root
mais peut-être changée par le biais de cette option.
mais peut être changée par le biais de cette option.
.TP
.B \-9, --leasefile-ro
Supprimer complètement l'usage du fichier servant de base de donnée pour les
@@ -1649,8 +1657,8 @@ biais de l'option
être complètement gérée par le script sur un stockage externe. En addition aux
actions décrites dans
.B --dhcp-script,
le script de changement d'état de bail est appellé une fois, au lancement de
Dnsmasq, avec pour seul argument "init". Lorsqu'appellé de la sorte, le script
le script de changement d'état de bail est appelé une fois, au lancement de
Dnsmasq, avec pour seul argument "init". Lorsqu'appelé de la sorte, le script
doit fournir l'état de la base de baux, dans le format de fichier de baux de
Dnsmasq, sur sa sortie standard (stdout) et retourner un code de retour de 0.
Positionner cette option provoque également une invocation du script de
@@ -1692,20 +1700,20 @@ positionné à la première valeur de la directive "search" du fichier
/etc/resolv.conf (ou équivalent).
La gamme d'adresses peut être de la forme
<adresse ip>,<adresse ip> ou <adresse ip>/<masque de réseau> voire une simple
<adresse ip>. Voir
<adresse IP>,<adresse IP> ou <adresse IP>/<masque de réseau> voire une simple
<adresse IP>. Voir
.B --dhcp-fqdn
qui peut changer le comportement de dnsmasq relatif aux domaines.
Si la gamme d'adresse est fournie sous la forme
<adresse ip>/<taille de réseau>, alors le drapeau "local" peut-être rajouté
qui a pour effect d'ajouter --local-declarations aux requêtes DNS directes et
<adresse IP>/<taille de réseau>, alors le drapeau "local" peut être rajouté
qui a pour effet d'ajouter --local-declarations aux requêtes DNS directes et
inverses. C-à-d
.B --domain=thekelleys.org.uk,192.168.0.0/24,local
est identique à
.B --domain=thekelleys.org.uk,192.168.0.0/24
--local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
La taille de réseau doit-être de 8, 16 ou 24 pour être valide.
La taille de réseau doit être de 8, 16 ou 24 pour être valide.
.TP
.B --dhcp-fqdn
Dans le mode par défaut, dnsmasq insère les noms non-qualifiés des clients
@@ -1717,8 +1725,8 @@ ce nom est transféré au nouveau client. Si
est spécifié, ce comportement change : les noms non qualifiés ne sont plus
rajoutés dans le DNS, seuls les noms qualifiés le sont. Deux clients DHCP
avec le même nom peuvent tous les deux garder le nom, pour peu que la partie
relative au domaine soit différente (c-à-d que les noms pleinements qualifiés
diffèrent). Pour d'assurer que tous les noms ont une partie domaine, il doit-y
relative au domaine soit différente (c-à-d que les noms pleinement qualifiés
diffèrent). Pour s'assurer que tous les noms ont une partie domaine, il doit y
avoir au moins un
.B --domain
sans gamme d'adresses de spécifié lorsque l'option
@@ -1735,7 +1743,7 @@ Windows de la mise à jour de serveurs Active Directory. Voir la RFC 4702 pour
plus de détails.
.TP
.B --enable-ra
Active la fonctionalité d'annonces routeurs IPv6 ("IPv6 Router Advertisement").
Active la fonctionnalité d'annonces routeurs IPv6 ("IPv6 Router Advertisement").
DHCPv6 ne gère pas la configuration complète du réseau de la même façon que
DHCPv4. La découverte de routeurs et la découverte (éventuelle) de préfixes pour
la création autonome d'adresse sont gérées par un protocole différent.
@@ -1747,7 +1755,7 @@ dhcp-range et, par défaut, fournir comme valeur de routeur et de DNS récursif
la valeur d'adresse link-local appropriée parmi celles de la machine sur
laquelle tourne dnsmasq.
Par défaut, les bits "managed address" sont positionnés, et le bit "use SLAAC"
("utiliser SLAAC") est réinitialisé. Cela peut-être changé pour des
("utiliser SLAAC") est réinitialisé. Cela peut être changé pour des
sous-réseaux donnés par le biais du mot clef de mode décris dans
.B --dhcp-range.
Les paramètres DNS du RFC6106 sont inclus dans les annonces. Par défaut,
@@ -1759,16 +1767,16 @@ DNSSL.
.B --ra-param=<interface>,[mtu:<valeur>|<interface>|off,][high,|low,]<intervalle d'annonce routeur>[,<durée de vie route>]
Configure pour une interface donnée des valeurs pour les annonces routeurs
différentes des valeurs par défaut. La valeur par défaut du champ priorité
pour le routeur peut-être changée de "medium" (moyen) à "high" (haute) ou
pour le routeur peut être changée de "medium" (moyen) à "high" (haute) ou
"low" (basse). Par exemple :
.B --ra-param=eth0,high,0.
Un intervalle (en secondes) entre les annonces routeur peut-être fourni par :
Un intervalle (en secondes) entre les annonces routeur peut être fourni par :
.B --ra-param=eth0,60.
La durée de vie de la route peut-être changée ou mise à zéro, auquel cas
La durée de vie de la route peut être changée ou mise à zéro, auquel cas
le routeur peut annoncer les préfixes mais pas de route :
.B --ra-parm=eth0,0,0
(une valeur de zéro pour l'intervalle signifie qu'il garde la valeur par défaut).
Ces quatre paramètres peuvent-être configurés en une fois :
Ces quatre paramètres peuvent être configurés en une fois :
.B --ra-param=eth0,mtu:1280,low,60,1200
La valeur pour l'interface peut inclure un caractère joker.
.TP
@@ -1776,7 +1784,7 @@ La valeur pour l'interface peut inclure un caractère joker.
Active la fonction serveur TFTP. Celui-ci est de manière délibérée limité aux
fonctions nécessaires au démarrage par le réseau ("net-boot") d'un client. Seul
un accès en lecture est possible; les extensions tsize et blksize sont supportées
(tsize est seulement supporté en mode octet). Sans argument optionel, le service
(tsize est seulement supportée en mode octet). Sans argument optionnel, le service
TFTP est fourni sur les mêmes interfaces que le service DHCP. Si une liste
d'interfaces est fournie, cela définit les interfaces sur lesquelles le
service TFTP sera activé.
@@ -1847,9 +1855,9 @@ Un serveur TFTP écoute sur le port prédéfini 69 ("well-known port") pour
l'initiation de la connexion, mais utilise également un port dynamiquement
alloué pour chaque connexion. Normalement, ces ports sont alloués par
le système d'exploitation, mais cette option permet de spécifier une gamme
de ports à utiliser pour les transferts TFTP. Cela peut-être utile si
de ports à utiliser pour les transferts TFTP. Cela peut être utile si
TFTP doit traverser un dispositif garde-barrière ("firewall"). La valeur
de début pour la plage de port ne peut-être inférieure à 1025 sauf si
de début pour la plage de port ne peut être inférieure à 1025 sauf si
dnsmasq tourne en temps que super-utilisateur ("root"). Le nombre de
connexions TFTP concurrentes est limitée par la taille de la gamme de
ports ainsi spécifiée.
@@ -1859,8 +1867,8 @@ Un serveur TFTP écoute sur un numéro de port bien connu (69) pour l'initiation
de la connexion, et alloue dynamiquement un port pour chaque connexion. Ces
numéros de ports sont en principe alloués par le système d'exploitation, mais
cette option permet de spécifier une gamme de ports à utiliser pour les
transferts TFTP. Cela peut-être utile lorsque ceux-ci doivent traverser un
dispositif garde-barrière ("firewall"). Le début de la plage ne peut-être
transferts TFTP. Cela peut être utile lorsque ceux-ci doivent traverser un
dispositif garde-barrière ("firewall"). Le début de la plage ne peut être
inférieur à 1024 à moins que Dnsmasq ne fonctionne en temps que
super-utilisateur ("root"). Le nombre maximal de connexions TFTP concurrentes
est limitée par la taille de la plage de ports ainsi définie.
@@ -1895,7 +1903,7 @@ par "--". Les lignes commençant par # sont des commentaires et sont ignorées.
Pour les options qui ne peuvent-être spécifiées qu'une seule fois, celle du
fichier de configuration prends le pas sur celle fournie en ligne de commande.
Il est possible d'utiliser des guillemets afin d'éviter que les ",",":","." et
"#" ne soit interprêtés, et il est possible d'utiliser les séquences
"#" ne soient interprétés, et il est possible d'utiliser les séquences
d'échappement suivantes : \\\\ \\" \\t \\e \\b \\r et \\n. Elles correspondent
respectivement à la barre oblique descendante ("anti-slash"), guillemets doubles,
tabulation, caractère d'échappement ("escape"), suppression ("backspace"), retour ("return") et
@@ -1940,8 +1948,8 @@ traces dans un fichier (voir
.B --log-facility
), alors
.B Dnsmasq
ferme et re-rouvre le fichier de traces. Il faut noter que pendant cette
opération Dnsmasq ne s'exécute pas en temps que "root". Lorsqu'il créé un
ferme et rouvre le fichier de traces. Il faut noter que pendant cette
opération Dnsmasq ne s'exécute pas en tant que "root". Lorsqu'il créé un
fichier de traces pour la première fois, Dnsmasq change le propriétaire du
fichier afin de le faire appartenir à l'utilisateur non "root" sous lequel
Dnsmasq s'exécute. Le logiciel de rotation de fichiers de trace logrotate doit
@@ -1983,7 +1991,7 @@ qu'une connexion PPP ne soit établie. Dans ce cas, Dnsmasq vérifie régulière
pour voir si un fichier
.I /etc/resolv.conf
est créé. Dnsmasq peut être configuré pour lire plus d'un fichier resolv.conf.
Cela est utile sur un ordinateur portable où PPP et DHCP peuvent-être utilisés :
Cela est utile sur un ordinateur portable où PPP et DHCP peuvent être utilisés :
Dnsmasq peut alors être configuré pour lire à la fois
.I /etc/ppp/resolv.conf
et
@@ -2007,7 +2015,7 @@ ou alors en mettant leurs adresses dans un autre fichier, par exemple
.I /etc/resolv.dnsmasq
et en lançant Dnsmasq avec l'option
.B \-r /etc/resolv.dnsmasq.
Cette deuxième technique permet la mise-à-jour dynamique des addresses de
Cette deuxième technique permet la mise-à-jour dynamique des adresses de
serveurs DNS amont par le biais de PPP ou DHCP.
.PP
Les adresses dans /etc/hosts prennent le dessus sur celles fournies par le
@@ -2067,10 +2075,10 @@ et pour affecter l'option envoyée, sur la base de la plage sélectionnée.
Ce système a évolué d'un système plus ancien et aux possibilités plus limitées,
et pour des raisons de compatibilité "net:" peut être utilisé à la place de
"tag:" et "set:" peut-être omis (à l'exception de
"tag:" et "set:" peut être omis (à l'exception de
.B dhcp-host,
où "net:" peut-être utilisé à la place de "set:"). Pour les mêmes raisons, '#'
peut-être utilisé à la place de '!' pour indiquer la négation.
où "net:" peut être utilisé à la place de "set:"). Pour les mêmes raisons, '#'
peut être utilisé à la place de '!' pour indiquer la négation.
.PP
Le serveur DHCP intégré dans Dnsmasq fonctionne également en temps que serveur
BOOTP, pour peu que l'adresse MAC et l'adresse IP des clients soient fournies,
@@ -2097,7 +2105,7 @@ scénarios de complexité croissante. Le pré-requis pour chacun de ces scénari
est l'existence d'une adresse IP globalement disponible, d'un enregistrement de
type A ou AAAA pointant vers cette adresse, ainsi que d'un serveur DNS externe
capable d'effectuer la délégation de la zone en question. Pour la première
partie de ces explications, nous allons appeller serveur.exemple.com
partie de ces explications, nous allons appeler serveur.exemple.com
l'enregistrement A (ou AAAA) de l'adresse globalement accessible, et
notre.zone.com la zone pour laquelle dnsmasq fait autorité.
@@ -2138,11 +2146,11 @@ notre.zone.com NS our.zone.com
.fi
L'enregistrement A pour notre.zone.com est dorénavant un enregistrement "colle"
qui résoud le problème de poule et d'oeuf consistant à trouver l'adresse IP
qui résout le problème de poule et d'oeuf consistant à trouver l'adresse IP
du serveur de nom pour notre.zone.com lorsque l'enregistrement se trouve dans
la zone en question. Il s'agit du seul rôle de cet enregistrement : comme dnsmasq
fait désormais autorité pour notre.zone.com, il doit également fournir cet
enregistrement. Si l'adresse externe est statique, cela peut-être réalisé par
enregistrement. Si l'adresse externe est statique, cela peut être réalisé par
le biais d'une entrée dans
.B /etc/hosts
ou via un
@@ -2194,7 +2202,7 @@ spécifiques, vous pouvez le faire via :
Dnsmasq joue le rôle de serveur faisant autorité pour les domaines in-addr.arpa
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
le nom) peuvent simplement être configurées avec un enregistrement NS
adéquat. Par exemple, comme nous définissons plus haut les adresses
1.2.3.0/24 :
.nf
@@ -2243,7 +2251,7 @@ celui fourni par
.B --domain.
Si l'option
.B --dhcp-fqdn
est fournie, alors les noms pleinemenet qualifiés associés aux baux DHCP
est fournie, alors les noms pleinement qualifiés associés aux baux DHCP
sont utilisés, dès lors qu'ils correspondent au nom de domaine associé
à la zone.
@@ -2282,7 +2290,7 @@ Dnsmasq est capable de gérer le DNS et DHCP pour au moins un millier de clients
Pour cela, la durée des bail ne doit pas être très courte (moins d'une heure).
La valeur de
.B --dns-forward-max
peut-être augmentée : commencer par la rendre égale au nombre de clients et
peut être augmentée : commencer par la rendre égale au nombre de clients et
l'augmenter si le DNS semble lent. Noter que la performance du DNS dépends
également de la performance des serveurs amonts. La taille du cache DNS peut-
être augmentée : la limite en dur est de 10000 entrées et la valeur par défaut
@@ -2306,7 +2314,7 @@ Il est possible d'utiliser Dnsmasq pour bloquer la publicité sur la toile
en associant des serveurs de publicité bien connus à l'adresse 127.0.0.1 ou
0.0.0.0 par le biais du fichier
.B /etc/hosts
ou d'un fichier d'hôte additionnel. Cette liste peut-être très longue, Dnsmasq
ou d'un fichier d'hôte additionnel. Cette liste peut être très longue, Dnsmasq
ayant été testé avec succès avec un million de noms. Cette taille de fichier
nécessite un processeur à 1 Ghz et environ 60 Mo de RAM.

View File

@@ -103,7 +103,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
{
char *name = daemon->namebuff;
unsigned char *p, *ansp;
int qtype, qclass;
int qtype, qclass, rc;
int nameoffset, axfroffset = 0;
int q, anscount = 0, authcount = 0;
struct crec *crecp;
@@ -283,11 +283,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (rec = daemon->mxnames; rec; rec = rec->next)
if (!rec->issrv && hostname_isequal(name, rec->name))
if (!rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
{
nxdomain = 0;
if (qtype == T_MX)
if (rc == 2 && qtype == T_MX)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
@@ -298,11 +298,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (move = NULL, up = &daemon->mxnames, rec = daemon->mxnames; rec; rec = rec->next)
if (rec->issrv && hostname_isequal(name, rec->name))
if (rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
{
nxdomain = 0;
if (qtype == T_SRV)
if (rc == 2 && qtype == T_SRV)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
@@ -333,13 +333,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (txt = daemon->rr; txt; txt = txt->next)
if (hostname_isequal(name, txt->name))
if ((rc = hostname_issubdomain(name, txt->name)))
{
nxdomain = 0;
if (txt->class == qtype)
if (rc == 2 && txt->class == qtype)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
log_query(F_CONFIG | F_RRNAME, name, NULL, querystr(NULL, txt->class));
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
NULL, txt->class, C_IN, "t", txt->len, txt->txt))
anscount++;
@@ -347,10 +347,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (txt = daemon->txt; txt; txt = txt->next)
if (txt->class == C_IN && hostname_isequal(name, txt->name))
if (txt->class == C_IN && (rc = hostname_issubdomain(name, txt->name)))
{
nxdomain = 0;
if (qtype == T_TXT)
if (rc == 2 && qtype == T_TXT)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
@@ -361,10 +361,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (na = daemon->naptr; na; na = na->next)
if (hostname_isequal(name, na->name))
if ((rc = hostname_issubdomain(name, na->name)))
{
nxdomain = 0;
if (qtype == T_NAPTR)
if (rc == 2 && qtype == T_NAPTR)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
@@ -384,13 +384,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
#endif
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(name, intr->name))
if ((rc = hostname_issubdomain(name, intr->name)))
{
struct addrlist *addrlist;
nxdomain = 0;
if (flag)
if (rc == 2 && flag)
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype &&
(local_query || filter_zone(zone, flag, &addrlist->addr)))
@@ -436,8 +436,9 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (sockaddr_isequal(peer_addr, &peers->addr))
break;
/* Refuse all AXFR unless --auth-sec-servers is set */
if ((!peers && daemon->auth_peers) || !daemon->secondary_forward_server)
/* Refuse all AXFR unless --auth-sec-servers or auth-peers is set */
if ((!daemon->secondary_forward_server && !daemon->auth_peers) ||
(daemon->auth_peers && !peers))
{
if (peer_addr->sa.sa_family == AF_INET)
inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
@@ -566,6 +567,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
goto cname_restart;
}
else if (cache_find_non_terminal(name, now))
nxdomain = 0;
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
}

View File

@@ -21,10 +21,12 @@ static struct crec *cache_head = NULL, *cache_tail = NULL, **hash_table = NULL;
static struct crec *dhcp_spare = NULL;
#endif
static struct crec *new_chain = NULL;
static int cache_inserted = 0, cache_live_freed = 0, insert_error;
static int insert_error;
static union bigname *big_free = NULL;
static int bignames_left, hash_size;
static void make_non_terminals(struct crec *source);
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
static const struct {
unsigned int type;
@@ -68,7 +70,8 @@ static const struct {
{ 252, "AXFR" },
{ 253, "MAILB" },
{ 254, "MAILA" },
{ 255, "ANY" }
{ 255, "ANY" },
{ 257, "CAA" }
};
static void cache_free(struct crec *crecp);
@@ -77,17 +80,20 @@ static void cache_link(struct crec *crecp);
static void rehash(int size);
static void cache_hash(struct crec *crecp);
static unsigned int next_uid(void)
void next_uid(struct crec *crecp)
{
static unsigned int uid = 0;
uid++;
if (crecp->uid == UID_NONE)
{
uid++;
/* uid == 0 used to indicate CNAME to interface name. */
if (uid == SRC_INTERFACE)
uid++;
return uid;
/* uid == 0 used to indicate CNAME to interface name. */
if (uid == UID_NONE)
uid++;
crecp->uid = uid;
}
}
void cache_init(void)
@@ -105,7 +111,7 @@ void cache_init(void)
{
cache_link(crecp);
crecp->flags = 0;
crecp->uid = next_uid();
crecp->uid = UID_NONE;
}
}
@@ -204,7 +210,7 @@ static void cache_free(struct crec *crecp)
{
crecp->flags &= ~F_FORWARD;
crecp->flags &= ~F_REVERSE;
crecp->uid = next_uid(); /* invalidate CNAMES pointing to this. */
crecp->uid = UID_NONE; /* invalidate CNAMES pointing to this. */
if (cache_tail)
cache_tail->next = crecp;
@@ -322,7 +328,8 @@ static int is_expired(time_t now, struct crec *crecp)
return 1;
}
static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags)
static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags,
struct crec **target_crec, unsigned int *target_uid)
{
/* Scan and remove old entries.
If (flags & F_FORWARD) then remove any forward entries for name and any expired
@@ -335,7 +342,10 @@ static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t no
to a cache entry if the name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
so that when we hit an entry which isn't reverse and is immortal, we're done. */
so that when we hit an entry which isn't reverse and is immortal, we're done.
If we free a crec which is a CNAME target, return the entry and uid in target_crec and target_uid.
This entry will get re-used with the same name, to preserve CNAMEs. */
struct crec *crecp, **up;
@@ -343,17 +353,6 @@ static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t no
{
for (up = hash_bucket(name), crecp = *up; crecp; crecp = crecp->hash_next)
{
if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp))
{
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
}
continue;
}
if ((crecp->flags & F_FORWARD) && hostname_isequal(cache_get_name(crecp), name))
{
/* Don't delete DNSSEC in favour of a CNAME, they can co-exist */
@@ -363,6 +362,16 @@ static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t no
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
return crecp;
*up = crecp->hash_next;
/* If this record is for the name we're inserting and is the target
of a CNAME record. Make the new record for the same name, in the same
crec, with the same uid to avoid breaking the existing CNAME. */
if (crecp->uid != UID_NONE)
{
if (target_crec)
*target_crec = crecp;
if (target_uid)
*target_uid = crecp->uid;
}
cache_unlink(crecp);
cache_free(crecp);
continue;
@@ -381,6 +390,18 @@ static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t no
}
#endif
}
if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp))
{
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
}
continue;
}
up = &crecp->hash_next;
}
}
@@ -447,11 +468,12 @@ void cache_start_insert(void)
struct crec *cache_insert(char *name, struct all_addr *addr,
time_t now, unsigned long ttl, unsigned short flags)
{
struct crec *new;
struct crec *new, *target_crec = NULL;
union bigname *big_name = NULL;
int freed_all = flags & F_REVERSE;
int free_avail = 0;
unsigned int target_uid;
/* Don't log DNSSEC records here, done elsewhere */
if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
{
@@ -469,7 +491,7 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
/* First remove any expired entries and entries for the name/address we
are currently inserting. */
if ((new = cache_scan_free(name, addr, now, flags)))
if ((new = cache_scan_free(name, addr, now, flags, &target_crec, &target_uid)))
{
/* We're trying to insert a record over one from
/etc/hosts or DHCP, or other config. If the
@@ -493,81 +515,89 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
}
/* Now get a cache entry from the end of the LRU list */
while (1) {
if (!(new = cache_tail)) /* no entries left - cache is too small, bail */
{
insert_error = 1;
return NULL;
}
/* End of LRU list is still in use: if we didn't scan all the hash
chains for expired entries do that now. If we already tried that
then it's time to start spilling things. */
if (new->flags & (F_FORWARD | F_REVERSE))
{
/* If free_avail set, we believe that an entry has been freed.
Bugs have been known to make this not true, resulting in
a tight loop here. If that happens, abandon the
insert. Once in this state, all inserts will probably fail. */
if (free_avail)
{
static int warned = 0;
if (!warned)
{
my_syslog(LOG_ERR, _("Internal error in cache."));
warned = 1;
}
insert_error = 1;
return NULL;
}
if (freed_all)
{
struct all_addr free_addr = new->addr.addr;;
if (!target_crec)
while (1) {
if (!(new = cache_tail)) /* no entries left - cache is too small, bail */
{
insert_error = 1;
return NULL;
}
/* Free entry at end of LRU list, use it. */
if (!(new->flags & (F_FORWARD | F_REVERSE)))
break;
/* End of LRU list is still in use: if we didn't scan all the hash
chains for expired entries do that now. If we already tried that
then it's time to start spilling things. */
/* If free_avail set, we believe that an entry has been freed.
Bugs have been known to make this not true, resulting in
a tight loop here. If that happens, abandon the
insert. Once in this state, all inserts will probably fail. */
if (free_avail)
{
static int warned = 0;
if (!warned)
{
my_syslog(LOG_ERR, _("Internal error in cache."));
warned = 1;
}
insert_error = 1;
return NULL;
}
if (freed_all)
{
struct all_addr free_addr = new->addr.addr;;
#ifdef HAVE_DNSSEC
/* For DNSSEC records, addr holds class. */
if (new->flags & (F_DS | F_DNSKEY))
free_addr.addr.dnssec.class = new->uid;
/* For DNSSEC records, addr holds class. */
if (new->flags & (F_DS | F_DNSKEY))
free_addr.addr.dnssec.class = new->uid;
#endif
free_avail = 1; /* Must be free space now. */
cache_scan_free(cache_get_name(new), &free_addr, now, new->flags);
cache_live_freed++;
}
else
{
cache_scan_free(NULL, NULL, now, 0);
freed_all = 1;
}
continue;
}
/* Check if we need to and can allocate extra memory for a long name.
If that fails, give up now, always succeed for DNSSEC records. */
if (name && (strlen(name) > SMALLDNAME-1))
{
if (big_free)
{
big_name = big_free;
big_free = big_free->next;
}
else if ((bignames_left == 0 && !(flags & (F_DS | F_DNSKEY))) ||
!(big_name = (union bigname *)whine_malloc(sizeof(union bigname))))
{
insert_error = 1;
return NULL;
}
else if (bignames_left != 0)
bignames_left--;
}
free_avail = 1; /* Must be free space now. */
cache_scan_free(cache_get_name(new), &free_addr, now, new->flags, NULL, NULL);
daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]++;
}
else
{
cache_scan_free(NULL, NULL, now, 0, NULL, NULL);
freed_all = 1;
}
}
/* Check if we need to and can allocate extra memory for a long name.
If that fails, give up now, always succeed for DNSSEC records. */
if (name && (strlen(name) > SMALLDNAME-1))
{
if (big_free)
{
big_name = big_free;
big_free = big_free->next;
}
else if ((bignames_left == 0 && !(flags & (F_DS | F_DNSKEY))) ||
!(big_name = (union bigname *)whine_malloc(sizeof(union bigname))))
{
insert_error = 1;
return NULL;
}
else if (bignames_left != 0)
bignames_left--;
}
/* Got the rest: finally grab entry. */
cache_unlink(new);
break;
}
/* If we freed a cache entry for our name which was a CNAME target, use that.
and preserve the uid, so that existing CNAMES are not broken. */
if (target_crec)
{
new = target_crec;
new->uid = target_uid;
}
/* Got the rest: finally grab entry. */
cache_unlink(new);
new->flags = flags;
if (big_name)
@@ -614,13 +644,27 @@ void cache_end_insert(void)
{
cache_hash(new_chain);
cache_link(new_chain);
cache_inserted++;
daemon->metrics[METRIC_DNS_CACHE_INSERTED]++;
}
new_chain = tmp;
}
new_chain = NULL;
}
int cache_find_non_terminal(char *name, time_t now)
{
struct crec *crecp;
for (crecp = *hash_bucket(name); crecp; crecp = crecp->hash_next)
if (!is_outdated_cname_pointer(crecp) &&
!is_expired(now, crecp) &&
(crecp->flags & F_FORWARD) &&
hostname_isequal(name, cache_get_name(crecp)))
return 1;
return 0;
}
struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned int prot)
{
struct crec *ans;
@@ -787,9 +831,12 @@ static void add_hosts_cname(struct crec *target)
crec->ttd = a->ttl;
crec->name.namep = a->alias;
crec->addr.cname.target.cache = target;
next_uid(target);
crec->addr.cname.uid = target->uid;
crec->uid = next_uid();
crec->uid = UID_NONE;
cache_hash(crec);
make_non_terminals(crec);
add_hosts_cname(crec); /* handle chains */
}
}
@@ -861,6 +908,7 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
cache->uid = index;
memcpy(&cache->addr.addr, addr, addrlen);
cache_hash(cache);
make_non_terminals(cache);
/* don't need to do alias stuff for second and subsequent addresses. */
if (!nameexists)
@@ -1031,7 +1079,8 @@ void cache_reload(void)
struct ds_config *ds;
#endif
cache_inserted = cache_live_freed = 0;
daemon->metrics[METRIC_DNS_CACHE_INSERTED] = 0;
daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED] = 0;
for (i=0; i<hash_size; i++)
for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
@@ -1071,8 +1120,9 @@ void cache_reload(void)
cache->name.namep = a->alias;
cache->addr.cname.target.int_name = intr;
cache->addr.cname.uid = SRC_INTERFACE;
cache->uid = next_uid();
cache->uid = UID_NONE;
cache_hash(cache);
make_non_terminals(cache);
add_hosts_cname(cache); /* handle chains */
}
@@ -1090,6 +1140,7 @@ void cache_reload(void)
cache->addr.ds.digest = ds->digest_type;
cache->uid = ds->class;
cache_hash(cache);
make_non_terminals(cache);
}
#endif
@@ -1201,9 +1252,11 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
aliasc->ttd = ttd;
aliasc->name.namep = a->alias;
aliasc->addr.cname.target.cache = target;
next_uid(target);
aliasc->addr.cname.uid = target->uid;
aliasc->uid = next_uid();
aliasc->uid = UID_NONE;
cache_hash(aliasc);
make_non_terminals(aliasc);
add_dhcp_cname(aliasc, ttd);
}
}
@@ -1243,7 +1296,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
}
else if (!(crec->flags & F_DHCP))
{
cache_scan_free(host_name, NULL, 0, crec->flags & (flags | F_CNAME | F_FORWARD));
cache_scan_free(host_name, NULL, 0, crec->flags & (flags | F_CNAME | F_FORWARD), NULL, NULL);
/* scan_free deletes all addresses associated with name */
break;
}
@@ -1270,7 +1323,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
if (crec->flags & F_NEG)
{
flags |= F_REVERSE;
cache_scan_free(NULL, (struct all_addr *)host_address, 0, flags);
cache_scan_free(NULL, (struct all_addr *)host_address, 0, flags, NULL, NULL);
}
}
else
@@ -1290,14 +1343,106 @@ void cache_add_dhcp_entry(char *host_name, int prot,
crec->ttd = ttd;
crec->addr.addr = *host_address;
crec->name.namep = host_name;
crec->uid = next_uid();
crec->uid = UID_NONE;
cache_hash(crec);
make_non_terminals(crec);
add_dhcp_cname(crec, ttd);
}
}
#endif
/* Called when we put a local or DHCP name into the cache.
Creates empty cache entries for subnames (ie,
for three.two.one, for two.one and one), without
F_IPV4 or F_IPV6 or F_CNAME set. These convert
NXDOMAIN answers to NoData ones. */
static void make_non_terminals(struct crec *source)
{
char *name = cache_get_name(source);
struct crec* crecp, *tmp, **up;
int type = F_HOSTS | F_CONFIG;
#ifdef HAVE_DHCP
if (source->flags & F_DHCP)
type = F_DHCP;
#endif
/* First delete any empty entries for our new real name. Note that
we only delete empty entries deriving from DHCP for a new DHCP-derived
entry and vice-versa for HOSTS and CONFIG. This ensures that
non-terminals from DHCP go when we reload DHCP and
for HOSTS/CONFIG when we re-read. */
for (up = hash_bucket(name), crecp = *up; crecp; crecp = tmp)
{
tmp = crecp->hash_next;
if (!is_outdated_cname_pointer(crecp) &&
(crecp->flags & F_FORWARD) &&
(crecp->flags & type) &&
!(crecp->flags & (F_IPV4 | F_IPV6 | F_CNAME | F_DNSKEY | F_DS)) &&
hostname_isequal(name, cache_get_name(crecp)))
{
*up = crecp->hash_next;
#ifdef HAVE_DHCP
if (type & F_DHCP)
{
crecp->next = dhcp_spare;
dhcp_spare = crecp;
}
else
#endif
free(crecp);
break;
}
else
up = &crecp->hash_next;
}
while ((name = strchr(name, '.')))
{
name++;
/* Look for one existing, don't need another */
for (crecp = *hash_bucket(name); crecp; crecp = crecp->hash_next)
if (!is_outdated_cname_pointer(crecp) &&
(crecp->flags & F_FORWARD) &&
(crecp->flags & type) &&
hostname_isequal(name, cache_get_name(crecp)))
break;
if (crecp)
{
/* If the new name expires later, transfer that time to
empty non-terminal entry. */
if (!(crecp->flags & F_IMMORTAL))
{
if (source->flags & F_IMMORTAL)
crecp->flags |= F_IMMORTAL;
else if (difftime(crecp->ttd, source->ttd) < 0)
crecp->ttd = source->ttd;
}
continue;
}
#ifdef HAVE_DHCP
if ((source->flags & F_DHCP) && dhcp_spare)
{
crecp = dhcp_spare;
dhcp_spare = dhcp_spare->next;
}
else
#endif
crecp = whine_malloc(sizeof(struct crec));
*crecp = *source;
crecp->flags &= ~(F_IPV4 | F_IPV6 | F_CNAME | F_DNSKEY | F_DS | F_REVERSE);
crecp->flags |= F_NAMEP;
crecp->name.namep = name;
cache_hash(crecp);
}
}
#ifndef NO_ID
int cache_make_stat(struct txt_record *t)
{
@@ -1319,24 +1464,24 @@ int cache_make_stat(struct txt_record *t)
break;
case TXT_STAT_INSERTS:
sprintf(buff+1, "%d", cache_inserted);
sprintf(buff+1, "%d", daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
break;
case TXT_STAT_EVICTIONS:
sprintf(buff+1, "%d", cache_live_freed);
sprintf(buff+1, "%d", daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]);
break;
case TXT_STAT_MISSES:
sprintf(buff+1, "%u", daemon->queries_forwarded);
sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]);
break;
case TXT_STAT_HITS:
sprintf(buff+1, "%u", daemon->local_answer);
sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
break;
#ifdef HAVE_AUTH
case TXT_STAT_AUTH:
sprintf(buff+1, "%u", daemon->auth_answer);
sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
break;
#endif
@@ -1413,15 +1558,14 @@ static char *sanitise(char *name)
void dump_cache(time_t now)
{
struct server *serv, *serv1;
char *t = "";
my_syslog(LOG_INFO, _("time %lu"), (unsigned long)now);
my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
daemon->cachesize, cache_live_freed, cache_inserted);
daemon->cachesize, daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED], daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
daemon->queries_forwarded, daemon->local_answer);
daemon->metrics[METRIC_DNS_QUERIES_FORWARDED], daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
#ifdef HAVE_AUTH
my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->auth_answer);
my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
#endif
#ifdef HAVE_DNSSEC
blockdata_report();
@@ -1459,6 +1603,7 @@ void dump_cache(time_t now)
for (i=0; i<hash_size; i++)
for (cache = hash_table[i]; cache; cache = cache->hash_next)
{
char *t = " ";
char *a = daemon->addrbuff, *p = daemon->namebuff, *n = cache_get_name(cache);
*a = 0;
if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
@@ -1559,9 +1704,13 @@ char *querystr(char *desc, unsigned short type)
break;
}
len += 3; /* braces, terminator */
len += strlen(desc);
if (desc)
{
len += 2; /* braces */
len += strlen(desc);
}
len++; /* terminator */
if (!buff || bufflen < len)
{
if (buff)
@@ -1575,12 +1724,22 @@ char *querystr(char *desc, unsigned short type)
if (buff)
{
if (types)
sprintf(buff, "%s[%s]", desc, types);
if (desc)
{
if (types)
sprintf(buff, "%s[%s]", desc, types);
else
sprintf(buff, "%s[type=%d]", desc, type);
}
else
sprintf(buff, "%s[type=%d]", desc, type);
{
if (types)
sprintf(buff, "<%s>", types);
else
sprintf(buff, "type=%d", type);
}
}
return buff ? buff : "";
}
@@ -1598,6 +1757,19 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
{
if (flags & F_KEYTAG)
sprintf(daemon->addrbuff, arg, addr->addr.log.keytag, addr->addr.log.algo, addr->addr.log.digest);
else if (flags & F_RCODE)
{
unsigned int rcode = addr->addr.rcode.rcode;
if (rcode == SERVFAIL)
dest = "SERVFAIL";
else if (rcode == REFUSED)
dest = "REFUSED";
else if (rcode == NOTIMP)
dest = "not implemented";
else
sprintf(daemon->addrbuff, "%u", rcode);
}
else
{
#ifdef HAVE_IPV6

View File

@@ -94,6 +94,9 @@ HAVE_DBUS
support some methods to allow (re)configuration of the upstream DNS
servers via DBus.
HAVE_UBUS
define this if you want to link against libubus
HAVE_IDN
define this if you want international domain name 2003 support.
@@ -117,6 +120,9 @@ HAVE_AUTH
HAVE_DNSSEC
include DNSSEC validator.
HAVE_DUMPFILE
include code to dump packets to a libpcap-format file for debugging.
HAVE_LOOP
include functionality to probe for and remove DNS forwarding loops.
@@ -132,6 +138,7 @@ NO_DHCP6
NO_SCRIPT
NO_LARGEFILE
NO_AUTH
NO_DUMPFILE
NO_INOTIFY
these are available to explicitly disable compile time options which would
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
@@ -164,6 +171,7 @@ RESOLVFILE
#define HAVE_AUTH
#define HAVE_IPSET
#define HAVE_LOOP
#define HAVE_DUMPFILE
/* Build options which require external libraries.
@@ -363,6 +371,10 @@ HAVE_SOCKADDR_SA_LEN
#undef HAVE_LOOP
#endif
#ifdef NO_DUMPFILE
#undef HAVE_DUMPFILE
#endif
#if defined (HAVE_LINUX_NETWORK) && !defined(NO_INOTIFY)
#define HAVE_INOTIFY
#endif
@@ -451,8 +463,11 @@ static char *compile_opts =
#ifndef HAVE_INOTIFY
"no-"
#endif
"inotify";
"inotify "
#ifndef HAVE_DUMPFILE
"no-"
#endif
"dumpfile";
#endif

View File

@@ -85,6 +85,9 @@ const char* introspection_xml_template =
" <arg name=\"success\" type=\"b\" direction=\"out\"/>\n"
" </method>\n"
#endif
" <method name=\"GetMetrics\">\n"
" <arg name=\"metrics\" direction=\"out\" type=\"a{su}\"/>\n"
" </method>\n"
" </interface>\n"
"</node>\n";
@@ -613,6 +616,30 @@ static DBusMessage *dbus_del_lease(DBusMessage* message)
}
#endif
static DBusMessage *dbus_get_metrics(DBusMessage* message)
{
DBusMessage *reply = dbus_message_new_method_return(message);
DBusMessageIter array, dict, iter;
int i;
dbus_message_iter_init_append(reply, &iter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{su}", &array);
for (i = 0; i < __METRIC_MAX; i++) {
const char *key = get_metric_name(i);
dbus_uint32_t value = daemon->metrics[i];
dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
dbus_message_iter_append_basic(&dict, DBUS_TYPE_UINT32, &value);
dbus_message_iter_close_container(&array, &dict);
}
dbus_message_iter_close_container(&iter, &array);
return reply;
}
DBusHandlerResult message_handler(DBusConnection *connection,
DBusMessage *message,
void *user_data)
@@ -680,6 +707,10 @@ DBusHandlerResult message_handler(DBusConnection *connection,
reply = dbus_del_lease(message);
}
#endif
else if (strcmp(method, "GetMetrics") == 0)
{
reply = dbus_get_metrics(message);
}
else if (strcmp(method, "ClearCache") == 0)
clear_cache = 1;
else

View File

@@ -556,6 +556,7 @@ static const struct opttab_t {
{ "nntp-server", 71, OT_ADDR_LIST },
{ "irc-server", 74, OT_ADDR_LIST },
{ "user-class", 77, 0 },
{ "rapid-commit", 80, 0 },
{ "FQDN", 81, OT_INTERNAL },
{ "agent-id", 82, OT_INTERNAL },
{ "client-arch", 93, 2 | OT_DEC },

View File

@@ -54,6 +54,7 @@
#define OPTION_SNAME 66
#define OPTION_FILENAME 67
#define OPTION_USER_CLASS 77
#define OPTION_RAPID_COMMIT 80
#define OPTION_CLIENT_FQDN 81
#define OPTION_AGENT_ID 82
#define OPTION_ARCH 93

View File

@@ -678,7 +678,7 @@ struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, unsigned int h
if ((count >= max) || option_bool(OPT_NO_PING) || loopback)
{
/* overloaded, or configured not to check, loopback interface, return "not in use" */
dummy.hash = 0;
dummy.hash = hash;
return &dummy;
}
else if (icmp_ping(addr))

View File

@@ -640,13 +640,20 @@ static int construct_worker(struct in6_addr *local, int prefix,
return 0;
for (template = daemon->dhcp6; template; template = template->next)
if (!(template->flags & CONTEXT_TEMPLATE))
if (!(template->flags & (CONTEXT_TEMPLATE | CONTEXT_CONSTRUCTED)))
{
/* non-template entries, just fill in interface and local addresses */
if (prefix <= template->prefix &&
is_same_net6(local, &template->start6, template->prefix) &&
is_same_net6(local, &template->end6, template->prefix))
{
/* First time found, do fast RA. */
if (template->if_index != if_index || !IN6_ARE_ADDR_EQUAL(&template->local6, local))
{
ra_start_unsolicited(param->now, template);
param->newone = 1;
}
template->if_index = if_index;
template->local6 = *local;
}
@@ -661,24 +668,33 @@ static int construct_worker(struct in6_addr *local, int prefix,
setaddr6part(&end6, addr6part(&template->end6));
for (context = daemon->dhcp6; context; context = context->next)
if ((context->flags & CONTEXT_CONSTRUCTED) &&
if (!(context->flags & CONTEXT_TEMPLATE) &&
IN6_ARE_ADDR_EQUAL(&start6, &context->start6) &&
IN6_ARE_ADDR_EQUAL(&end6, &context->end6))
{
int flags = context->flags;
context->flags &= ~(CONTEXT_GC | CONTEXT_OLD);
if (flags & CONTEXT_OLD)
/* If there's an absolute address context covering this address
then don't construct one as well. */
if (!(context->flags & CONTEXT_CONSTRUCTED))
break;
if (context->if_index == if_index)
{
/* address went, now it's back */
log_context(AF_INET6, context);
/* fast RAs for a while */
ra_start_unsolicited(param->now, context);
param->newone = 1;
/* Add address to name again */
if (context->flags & CONTEXT_RA_NAME)
param->newname = 1;
int cflags = context->flags;
context->flags &= ~(CONTEXT_GC | CONTEXT_OLD);
if (cflags & CONTEXT_OLD)
{
/* address went, now it's back, and on the same interface */
log_context(AF_INET6, context);
/* fast RAs for a while */
ra_start_unsolicited(param->now, context);
param->newone = 1;
/* Add address to name again */
if (context->flags & CONTEXT_RA_NAME)
param->newname = 1;
}
break;
}
break;
}
if (!context && (context = whine_malloc(sizeof (struct dhcp_context))))

View File

@@ -76,6 +76,7 @@
#define T_AXFR 252
#define T_MAILB 253
#define T_ANY 255
#define T_CAA 257
#define EDNS0_OPTION_MAC 65001 /* dyndns.org temporary assignment */
#define EDNS0_OPTION_CLIENT_SUBNET 8 /* IANA */

View File

@@ -216,7 +216,7 @@ int main (int argc, char **argv)
#endif
#ifndef HAVE_AUTH
if (daemon->authserver)
if (daemon->authserver || daemon->auth_zones)
die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
#endif
@@ -225,13 +225,18 @@ int main (int argc, char **argv)
die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
#endif
#ifndef HAVE_UBUS
if (option_bool(OPT_UBUS))
die(_("Ubus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
#endif
if (daemon->max_port < daemon->min_port)
die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
now = dnsmasq_time();
/* Create a serial at startup if not configured. */
if (daemon->authinterface && daemon->soa_sn == 0)
if (daemon->auth_zones && daemon->soa_sn == 0)
#ifdef HAVE_BROKEN_RTC
die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
#else
@@ -366,7 +371,16 @@ int main (int argc, char **argv)
else
daemon->inotifyfd = -1;
#endif
if (daemon->dump_file)
#ifdef HAVE_DUMPFILE
dump_init();
else
daemon->dumpfd = -1;
#else
die(_("Packet dumps not available: set HAVE_DUMP in src/config.h"), NULL, EC_BADCONF);
#endif
if (option_bool(OPT_DBUS))
#ifdef HAVE_DBUS
{
@@ -731,7 +745,11 @@ int main (int argc, char **argv)
else
{
if (daemon->cachesize != 0)
my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
{
my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
if (daemon->cachesize > 10000)
my_syslog(LOG_WARNING, _("cache size greater than 10000 may cause performance issues, and is unlikely to be useful."));
}
else
my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
@@ -758,7 +776,8 @@ int main (int argc, char **argv)
if (option_bool(OPT_DNSSEC_VALID))
{
int rc;
struct ds_config *ds;
/* Delay creating the timestamp file until here, after we've changed user, so that
it has the correct owner to allow updating the mtime later.
This means we have to report fatal errors via the pipe. */
@@ -768,7 +787,10 @@ int main (int argc, char **argv)
_exit(0);
}
my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
if (option_bool(OPT_DNSSEC_IGN_NS))
my_syslog(LOG_INFO, _("DNSSEC validation enabled but all unsigned answers are trusted"));
else
my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
@@ -776,6 +798,10 @@ int main (int argc, char **argv)
if (rc == 1)
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
for (ds = daemon->ds; ds; ds = ds->next)
my_syslog(LOG_INFO, _("configured with trust anchor for %s keytag %u"),
ds->name[0] == 0 ? "<root>" : ds->name, ds->keytag);
}
#endif
@@ -926,8 +952,13 @@ int main (int argc, char **argv)
#ifdef HAVE_DBUS
set_dbus_listeners();
#endif
#endif
#ifdef HAVE_UBUS
if (option_bool(OPT_UBUS))
set_ubus_listeners();
#endif
#ifdef HAVE_DHCP
if (daemon->dhcp || daemon->relay4)
{
@@ -1057,7 +1088,12 @@ int main (int argc, char **argv)
}
check_dbus_listeners();
#endif
#ifdef HAVE_UBUS
if (option_bool(OPT_UBUS))
check_ubus_listeners();
#endif
check_dns_listeners(now);
#ifdef HAVE_TFTP
@@ -1421,6 +1457,11 @@ static void async_event(int pipe, time_t now)
if (daemon->runfile)
unlink(daemon->runfile);
#ifdef HAVE_DUMPFILE
if (daemon->dumpfd != -1)
close(daemon->dumpfd);
#endif
my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
flush_log();

View File

@@ -57,6 +57,7 @@
#include "config.h"
#include "ip6addr.h"
#include "metrics.h"
typedef unsigned char u8;
typedef unsigned short u16;
@@ -119,6 +120,9 @@ typedef unsigned long long u64;
#include <net/if_arp.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#ifdef HAVE_IPV6
#include <netinet/ip6.h>
#endif
#include <netinet/ip_icmp.h>
#include <sys/uio.h>
#include <syslog.h>
@@ -241,7 +245,7 @@ struct event_desc {
#define OPT_DNSSEC_VALID 45
#define OPT_DNSSEC_TIME 46
#define OPT_DNSSEC_DEBUG 47
#define OPT_DNSSEC_NO_SIGN 48
#define OPT_DNSSEC_IGN_NS 48
#define OPT_LOCAL_SERVICE 49
#define OPT_LOOP_DETECT 50
#define OPT_EXTRALOG 51
@@ -250,7 +254,9 @@ struct event_desc {
#define OPT_MAC_B64 54
#define OPT_MAC_HEX 55
#define OPT_TFTP_APREF_MAC 56
#define OPT_LAST 57
#define OPT_RAPID_COMMIT 57
#define OPT_UBUS 58
#define OPT_LAST 59
/* 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. */
@@ -267,7 +273,11 @@ struct all_addr {
/* for log_query */
struct {
unsigned short keytag, algo, digest;
} log;
} log;
/* for log_query */
struct {
unsigned int rcode;
} rcode;
/* for cache_insert of DNSKEY, DS */
struct {
unsigned short class, type;
@@ -458,9 +468,14 @@ struct crec {
#define F_IPSET (1u<<26)
#define F_NOEXTRA (1u<<27)
#define F_SERVFAIL (1u<<28)
#define F_RCODE (1u<<29)
#define UID_NONE 0
/* Values of uid in crecs with F_CONFIG bit set. */
#define SRC_INTERFACE 0
/* cname to uid SRC_INTERFACE are to interface names,
so use UID_NONE for that to eliminate clashes with
any other uid */
#define SRC_INTERFACE UID_NONE
#define SRC_CONFIG 1
#define SRC_HOSTS 2
#define SRC_AH 3
@@ -505,7 +520,7 @@ struct serverfd {
int fd;
union mysockaddr source_addr;
char interface[IF_NAMESIZE+1];
unsigned int ifindex, used;
unsigned int ifindex, used, preallocated;
struct serverfd *next;
};
@@ -592,6 +607,16 @@ struct hostsfile {
unsigned int index; /* matches to cache entries for logging */
};
/* packet-dump flags */
#define DUMP_QUERY 0x0001
#define DUMP_REPLY 0x0002
#define DUMP_UP_QUERY 0x0004
#define DUMP_UP_REPLY 0x0008
#define DUMP_SEC_QUERY 0x0010
#define DUMP_SEC_REPLY 0x0020
#define DUMP_BOGUS 0x0040
#define DUMP_SEC_BOGUS 0x0080
/* DNSSEC status values. */
#define STAT_SECURE 1
@@ -797,6 +822,13 @@ struct dhcp_boot {
struct dhcp_boot *next;
};
struct dhcp_match_name {
char *name;
int wildcard;
struct dhcp_netid *netid;
struct dhcp_match_name *next;
};
struct pxe_service {
unsigned short CSA, type;
char *menu, *basename, *sname;
@@ -989,6 +1021,7 @@ extern struct daemon {
struct ra_interface *ra_interfaces;
struct dhcp_config *dhcp_conf;
struct dhcp_opt *dhcp_opts, *dhcp_match, *dhcp_opts6, *dhcp_match6;
struct dhcp_match_name *dhcp_name_match;
struct dhcp_vendor *dhcp_vendors;
struct dhcp_mac *dhcp_macs;
struct dhcp_boot *boot_config;
@@ -1014,14 +1047,15 @@ extern struct daemon {
unsigned int duid_enterprise, duid_config_len;
unsigned char *duid_config;
char *dbus_name;
char *dump_file;
int dump_mask;
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
u32 metrics[__METRIC_MAX];
#ifdef OPTION6_PREFIX_CLASS
struct prefix_class *prefix_classes;
#endif
#ifdef HAVE_DNSSEC
struct ds_config *ds;
int dnssec_no_time_check;
int back_to_the_future;
char *timestamp_file;
#endif
@@ -1034,8 +1068,9 @@ extern struct daemon {
char *workspacename; /* ditto */
char *rr_status; /* flags for individual RRs */
int rr_status_sz;
int dnssec_no_time_check;
int back_to_the_future;
#endif
unsigned int local_answer, queries_forwarded, auth_answer;
struct frec *frec_list;
struct serverfd *sfds;
struct irec *interfaces;
@@ -1088,13 +1123,19 @@ extern struct daemon {
char *addrbuff;
char *addrbuff2; /* only allocated when OPT_EXTRALOG */
#ifdef HAVE_DUMPFILE
/* file for packet dumps. */
int dumpfd;
#endif
} *daemon;
/* cache.c */
void cache_init(void);
void next_uid(struct crec *crecp);
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
char *record_source(unsigned int index);
char *querystr(char *desc, unsigned short type);
int cache_find_non_terminal(char *name, time_t now);
struct crec *cache_find_by_addr(struct crec *crecp,
struct all_addr *addr, time_t now,
unsigned int prot);
@@ -1210,6 +1251,7 @@ void *whine_malloc(size_t size);
int sa_len(union mysockaddr *addr);
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
int hostname_isequal(const char *a, const char *b);
int hostname_issubdomain(char *a, char *b);
time_t dnsmasq_time(void);
int netmask_length(struct in_addr mask);
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
@@ -1415,6 +1457,13 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
# endif
#endif
/* ubus.c */
#ifdef HAVE_UBUS
void set_ubus_listeners(void);
void check_ubus_listeners(void);
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface);
#endif
/* ipset.c */
#ifdef HAVE_IPSET
void ipset_init(void);
@@ -1582,3 +1631,9 @@ int check_source(struct dns_header *header, size_t plen, unsigned char *pseudohe
/* arp.c */
int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now);
int do_arp_script_run(void);
/* dump.c */
#ifdef HAVE_DUMPFILE
void dump_init(void);
void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst);
#endif

View File

@@ -875,8 +875,11 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
rc = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons);
if (rc == STAT_INSECURE)
rc = STAT_BOGUS;
{
my_syslog(LOG_WARNING, _("Insecure DS reply received, do upstream DNS servers support DNSSEC?"));
rc = STAT_BOGUS;
}
p = (unsigned char *)(header+1);
extract_name(header, plen, &p, name, 1, 4);
p += 4; /* qtype, qclass */
@@ -1906,7 +1909,6 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
if (rc == STAT_BOGUS || rc == STAT_NEED_KEY || rc == STAT_NEED_DS)
{
/* Zone is insecure, don't need to validate RRset */
if (class)
*class = class1; /* Class for NEED_DS or NEED_KEY */
return rc;
@@ -1966,35 +1968,36 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
}
/* OK, all the RRsets validate, now see if we have a missing answer or CNAME target. */
for (j = 0; j <targetidx; j++)
if ((p2 = targets[j]))
{
if (neganswer)
*neganswer = 1;
if (!extract_name(header, plen, &p2, name, 1, 10))
return STAT_BOGUS; /* bad packet */
/* NXDOMAIN or NODATA reply, unanswered question is (name, qclass, qtype) */
/* For anything other than a DS record, this situation is OK if either
the answer is in an unsigned zone, or there's a NSEC records. */
if (!prove_non_existence(header, plen, keyname, name, qtype, qclass, NULL, nons))
{
/* Empty DS without NSECS */
if (qtype == T_DS)
return STAT_BOGUS;
if ((rc = zone_status(name, qclass, keyname, now)) != STAT_SECURE)
{
if (class)
*class = qclass; /* Class for NEED_DS or NEED_KEY */
return rc;
}
return STAT_BOGUS; /* signed zone, no NSECs */
}
}
if (secure == STAT_SECURE)
for (j = 0; j <targetidx; j++)
if ((p2 = targets[j]))
{
if (neganswer)
*neganswer = 1;
if (!extract_name(header, plen, &p2, name, 1, 10))
return STAT_BOGUS; /* bad packet */
/* NXDOMAIN or NODATA reply, unanswered question is (name, qclass, qtype) */
/* For anything other than a DS record, this situation is OK if either
the answer is in an unsigned zone, or there's a NSEC records. */
if (!prove_non_existence(header, plen, keyname, name, qtype, qclass, NULL, nons))
{
/* Empty DS without NSECS */
if (qtype == T_DS)
return STAT_BOGUS;
if ((rc = zone_status(name, qclass, keyname, now)) != STAT_SECURE)
{
if (class)
*class = qclass; /* Class for NEED_DS or NEED_KEY */
return rc;
}
return STAT_BOGUS; /* signed zone, no NSECs */
}
}
return secure;
}

211
src/dump.c Normal file
View File

@@ -0,0 +1,211 @@
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
#ifdef HAVE_DUMPFILE
static u32 packet_count;
/* https://wiki.wireshark.org/Development/LibpcapFileFormat */
struct pcap_hdr_s {
u32 magic_number; /* magic number */
u16 version_major; /* major version number */
u16 version_minor; /* minor version number */
u32 thiszone; /* GMT to local correction */
u32 sigfigs; /* accuracy of timestamps */
u32 snaplen; /* max length of captured packets, in octets */
u32 network; /* data link type */
};
struct pcaprec_hdr_s {
u32 ts_sec; /* timestamp seconds */
u32 ts_usec; /* timestamp microseconds */
u32 incl_len; /* number of octets of packet saved in file */
u32 orig_len; /* actual length of packet */
};
void dump_init(void)
{
struct stat buf;
struct pcap_hdr_s header;
struct pcaprec_hdr_s pcap_header;
packet_count = 0;
if (stat(daemon->dump_file, &buf) == -1)
{
/* doesn't exist, create and add header */
header.magic_number = 0xa1b2c3d4;
header.version_major = 2;
header.version_minor = 4;
header.thiszone = 0;
header.sigfigs = 0;
header.snaplen = daemon->edns_pktsz + 200; /* slop for IP/UDP headers */
header.network = 101; /* DLT_RAW http://www.tcpdump.org/linktypes.html */
if (errno != ENOENT ||
(daemon->dumpfd = creat(daemon->dump_file, S_IRUSR | S_IWUSR)) == -1 ||
!read_write(daemon->dumpfd, (void *)&header, sizeof(header), 0))
die(_("cannot create %s: %s"), daemon->dump_file, EC_FILE);
}
else if ((daemon->dumpfd = open(daemon->dump_file, O_APPEND | O_RDWR)) == -1 ||
!read_write(daemon->dumpfd, (void *)&header, sizeof(header), 1))
die(_("cannot access %s: %s"), daemon->dump_file, EC_FILE);
else if (header.magic_number != 0xa1b2c3d4)
die(_("bad header in %s"), daemon->dump_file, EC_FILE);
else
{
/* count existing records */
while (read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 1))
{
lseek(daemon->dumpfd, pcap_header.incl_len, SEEK_CUR);
packet_count++;
}
}
}
void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst)
{
struct ip ip;
#ifdef HAVE_IPV6
struct ip6_hdr ip6;
int family;
#endif
struct udphdr {
u16 uh_sport; /* source port */
u16 uh_dport; /* destination port */
u16 uh_ulen; /* udp length */
u16 uh_sum; /* udp checksum */
} udp;
struct pcaprec_hdr_s pcap_header;
struct timeval time;
u32 i, sum;
void *iphdr;
size_t ipsz;
int rc;
if (daemon->dumpfd == -1 || !(mask & daemon->dump_mask))
return;
/* So wireshark can Id the packet. */
udp.uh_sport = udp.uh_dport = htons(NAMESERVER_PORT);
#ifdef HAVE_IPV6
if (src)
family = src->sa.sa_family;
else
family = dst->sa.sa_family;
if (family == AF_INET6)
{
iphdr = &ip6;
ipsz = sizeof(ip6);
memset(&ip6, 0, sizeof(ip6));
ip6.ip6_vfc = 6 << 4;
ip6.ip6_plen = htons(sizeof(struct udphdr) + len);
ip6.ip6_nxt = IPPROTO_UDP;
ip6.ip6_hops = 64;
if (src)
{
memcpy(&ip6.ip6_src, &src->in6.sin6_addr, IN6ADDRSZ);
udp.uh_sport = src->in6.sin6_port;
}
if (dst)
{
memcpy(&ip6.ip6_dst, &dst->in6.sin6_addr, IN6ADDRSZ);
udp.uh_dport = dst->in6.sin6_port;
}
/* start UDP checksum */
for (sum = 0, i = 0; i < IN6ADDRSZ; i++)
sum += ((u16 *)&ip6.ip6_src)[i];
}
else
#endif
{
iphdr = &ip;
ipsz = sizeof(ip);
memset(&ip, 0, sizeof(ip));
ip.ip_v = IPVERSION;
ip.ip_hl = sizeof(struct ip) / 4;
ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len);
ip.ip_ttl = IPDEFTTL;
ip.ip_p = IPPROTO_UDP;
if (src)
{
ip.ip_src = src->in.sin_addr;
udp.uh_sport = src->in.sin_port;
}
if (dst)
{
ip.ip_dst = dst->in.sin_addr;
udp.uh_dport = dst->in.sin_port;
}
ip.ip_sum = 0;
for (sum = 0, i = 0; i < sizeof(struct ip) / 2; i++)
sum += ((u16 *)&ip)[i];
while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
/* start UDP checksum */
sum = ip.ip_src.s_addr & 0xffff;
sum += (ip.ip_src.s_addr >> 16) & 0xffff;
sum += ip.ip_dst.s_addr & 0xffff;
sum += (ip.ip_dst.s_addr >> 16) & 0xffff;
}
if (len & 1)
((unsigned char *)packet)[len] = 0; /* for checksum, in case length is odd. */
udp.uh_sum = 0;
udp.uh_ulen = htons(sizeof(struct udphdr) + len);
sum += htons(IPPROTO_UDP);
sum += htons(sizeof(struct udphdr) + len);
for (i = 0; i < sizeof(struct udphdr)/2; i++)
sum += ((u16 *)&udp)[i];
for (i = 0; i < (len + 1) / 2; i++)
sum += ((u16 *)packet)[i];
while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
udp.uh_sum = (sum == 0xffff) ? sum : ~sum;
rc = gettimeofday(&time, NULL);
pcap_header.ts_sec = time.tv_sec;
pcap_header.ts_usec = time.tv_usec;
pcap_header.incl_len = pcap_header.orig_len = ipsz + sizeof(udp) + len;
if (rc == -1 ||
!read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 0) ||
!read_write(daemon->dumpfd, iphdr, ipsz, 0) ||
!read_write(daemon->dumpfd, (void *)&udp, sizeof(udp), 0) ||
!read_write(daemon->dumpfd, (void *)packet, len, 0))
my_syslog(LOG_ERR, _("failed to write packet dump"));
else
my_syslog(LOG_INFO, _("dumping UDP packet %u mask 0x%04x"), ++packet_count, mask);
}
#endif

View File

@@ -246,9 +246,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
unsigned int crc = questions_crc(header, plen, daemon->namebuff);
void *hash = &crc;
#endif
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
(void)do_bit;
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
(void)do_bit;
/* may be no servers available. */
if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
@@ -298,9 +298,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
fd = forward->rfd4->fd;
}
while (retry_send( sendto(fd, (char *)header, plen, 0,
&forward->sentto->addr.sa,
sa_len(&forward->sentto->addr))));
while (retry_send(sendto(fd, (char *)header, plen, 0,
&forward->sentto->addr.sa,
sa_len(&forward->sentto->addr))));
return 1;
}
@@ -399,7 +399,6 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
struct server *firstsentto = start;
int subnet, forwarded = 0;
size_t edns0_len;
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
unsigned char *pheader;
/* If a query is retried, use the log_id for the retry when logging the answer. */
@@ -508,6 +507,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (errno == 0)
{
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_UP_QUERY, (void *)header, plen, NULL, &start->addr);
#endif
/* Keep info in case we want to re-send this packet */
daemon->srv_save = start;
daemon->packet_len = plen;
@@ -550,6 +553,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (udpfd != -1)
{
plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
if (oph)
plen = add_pseudoheader(header, plen, ((unsigned char *) header) + PACKETSZ, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
send_from(udpfd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND), (char *)header, plen, udpaddr, dst_addr, dst_iface);
}
@@ -563,6 +568,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
unsigned char *pheader, *sizep;
char **sets = 0;
int munged = 0, is_sign;
unsigned int rcode = RCODE(header);
size_t plen;
(void)ad_reqd;
@@ -593,6 +599,9 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
{
/* Get extended RCODE. */
rcode |= sizep[2] << 4;
if (check_subnet && !check_source(header, plen, pheader, query_source))
{
my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
@@ -641,11 +650,20 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
header->hb4 &= ~HB4_AD;
if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
if (OPCODE(header) != QUERY)
return resize_packet(header, n, pheader, plen);
if (rcode != NOERROR && rcode != NXDOMAIN)
{
struct all_addr a;
a.addr.rcode.rcode = rcode;
log_query(F_UPSTREAM | F_RCODE, "error", &a, NULL);
return resize_packet(header, n, pheader, plen);
}
/* Complain loudly if the upstream server is non-recursive. */
if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR &&
if (!(header->hb4 & HB4_RA) && rcode == NOERROR &&
server && !(server->flags & SERV_WARNED_RECURSIVE))
{
prettyprint_addr(&server->addr, daemon->namebuff);
@@ -654,7 +672,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
server->flags |= SERV_WARNED_RECURSIVE;
}
if (daemon->bogus_addr && RCODE(header) != NXDOMAIN &&
if (daemon->bogus_addr && rcode != NXDOMAIN &&
check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
{
munged = 1;
@@ -666,7 +684,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
{
int doctored = 0;
if (RCODE(header) == NXDOMAIN &&
if (rcode == NXDOMAIN &&
extract_request(header, n, daemon->namebuff, NULL) &&
check_for_local_domain(daemon->namebuff, now))
{
@@ -756,7 +774,7 @@ void reply_query(int fd, int family, time_t now)
#endif
header = (struct dns_header *)daemon->packet;
if (n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR))
return;
@@ -783,6 +801,11 @@ void reply_query(int fd, int family, time_t now)
if (!(forward = lookup_frec(ntohs(header->id), hash)))
return;
#ifdef HAVE_DUMPFILE
dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY,
(void *)header, n, &serveraddr, NULL);
#endif
/* log_query gets called indirectly all over the place, so
pass these in global variables - sorry. */
daemon->log_display_id = forward->log_id;
@@ -794,7 +817,7 @@ void reply_query(int fd, int family, time_t now)
/* Note: if we send extra options in the EDNS0 header, we can't recreate
the query from the reply. */
if (RCODE(header) == REFUSED &&
if ((RCODE(header) == REFUSED || RCODE(header) == SERVFAIL) &&
forward->forwardall == 0 &&
!(forward->flags & FREC_HAS_EXTRADATA))
/* for broken servers, attempt to send to another one. */
@@ -803,6 +826,70 @@ void reply_query(int fd, int family, time_t now)
size_t plen;
int is_sign;
#ifdef HAVE_DNSSEC
/* For DNSSEC originated queries, just retry the query to the same server. */
if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
{
struct server *start;
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
plen = forward->stash_len;
forward->forwardall = 2; /* only retry once */
start = forward->sentto;
/* for non-domain specific servers, see if we can find another to try. */
if ((forward->sentto->flags & SERV_TYPE) == 0)
while (1)
{
if (!(start = start->next))
start = daemon->servers;
if (start == forward->sentto)
break;
if ((start->flags & SERV_TYPE) == 0 &&
(start->flags & SERV_DO_DNSSEC))
break;
}
if (start->sfd)
fd = start->sfd->fd;
else
{
#ifdef HAVE_IPV6
if (start->addr.sa.sa_family == AF_INET6)
{
/* may have changed family */
if (!forward->rfd6)
forward->rfd6 = allocate_rfd(AF_INET6);
fd = forward->rfd6->fd;
}
else
#endif
{
/* may have changed family */
if (!forward->rfd4)
forward->rfd4 = allocate_rfd(AF_INET);
fd = forward->rfd4->fd;
}
}
while (retry_send(sendto(fd, (char *)header, plen, 0,
&start->addr.sa,
sa_len(&start->addr))));
if (start->addr.sa.sa_family == AF_INET)
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&start->addr.in.sin_addr, "dnssec");
#ifdef HAVE_IPV6
else
log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&start->addr.in6.sin6_addr, "dnssec");
#endif
return;
}
#endif
/* In strict order mode, there must be a server later in the chain
left to send to, otherwise without the forwardall mechanism,
code further on will cycle around the list forwever if they
@@ -919,8 +1006,13 @@ void reply_query(int fd, int family, time_t now)
status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
else
status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC),
!option_bool(OPT_DNSSEC_IGN_NS) && (server->flags & SERV_DO_DNSSEC),
NULL, NULL);
#ifdef HAVE_DUMPFILE
if (status == STAT_BOGUS)
dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_BOGUS : DUMP_BOGUS,
header, (size_t)n, &serveraddr, NULL);
#endif
}
/* Can't validate, as we're missing key data. Put this
@@ -963,7 +1055,7 @@ void reply_query(int fd, int family, time_t now)
while (1)
{
if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
(type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
((type & SERV_TYPE) != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
!(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
{
new_server = start;
@@ -989,7 +1081,8 @@ void reply_query(int fd, int family, time_t now)
#ifdef HAVE_IPV6
new->rfd6 = NULL;
#endif
new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA);
new->forwardall = 0;
new->dependent = forward; /* to find query awaiting new one. */
forward->blocking_query = new; /* for garbage cleaning */
@@ -1047,6 +1140,11 @@ void reply_query(int fd, int family, time_t now)
setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
}
#endif
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)nn, NULL, &server->addr);
#endif
while (retry_send(sendto(fd, (char *)header, nn, 0,
&server->addr.sa,
sa_len(&server->addr))));
@@ -1090,7 +1188,7 @@ void reply_query(int fd, int family, time_t now)
if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
domain = daemon->namebuff;
log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
log_query(F_SECSTAT, domain, NULL, result);
}
if (status == STAT_SECURE)
@@ -1101,8 +1199,8 @@ void reply_query(int fd, int family, time_t now)
bogusanswer = 1;
}
}
#endif
#endif
/* restore CD bit to the value in the query */
if (forward->flags & FREC_CHECKING_DISABLED)
header->hb4 |= HB4_CD;
@@ -1128,6 +1226,11 @@ void reply_query(int fd, int family, time_t now)
nn = resize_packet(header, nn, NULL, 0);
}
#endif
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &forward->source);
#endif
send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
&forward->source, &forward->dest, forward->iface);
}
@@ -1381,7 +1484,11 @@ void receive_query(struct listener *listen, time_t now)
pass these in global variables - sorry. */
daemon->log_display_id = ++daemon->log_id;
daemon->log_source_addr = &source_addr;
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_QUERY, daemon->packet, (size_t)n, &source_addr, NULL);
#endif
if (extract_request(header, (size_t)n, daemon->namebuff, &type))
{
#ifdef HAVE_AUTH
@@ -1447,7 +1554,7 @@ void receive_query(struct listener *listen, time_t now)
{
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
(char *)header, m, &source_addr, &dst_addr, if_index);
daemon->auth_answer++;
daemon->metrics[METRIC_DNS_AUTH_ANSWERED]++;
}
}
else
@@ -1465,13 +1572,13 @@ void receive_query(struct listener *listen, time_t now)
{
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
(char *)header, m, &source_addr, &dst_addr, if_index);
daemon->local_answer++;
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
}
else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
header, (size_t)n, now, NULL, ad_reqd, do_bit))
daemon->queries_forwarded++;
daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++;
else
daemon->local_answer++;
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
}
}
@@ -1504,7 +1611,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
else
new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC),
!option_bool(OPT_DNSSEC_IGN_NS) && (server->flags & SERV_DO_DNSSEC),
NULL, NULL);
if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
@@ -1948,7 +2055,7 @@ unsigned char *tcp_request(int confd, time_t now,
if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
domain = daemon->namebuff;
log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
log_query(F_SECSTAT, domain, NULL, result);
if (status == STAT_BOGUS)
{
@@ -1998,7 +2105,11 @@ unsigned char *tcp_request(int confd, time_t now,
/* In case of local answer or no connections made. */
if (m == 0)
m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
{
m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
if (have_pseudoheader)
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
}
}
}

View File

@@ -87,7 +87,7 @@ static int read_leases(time_t now, FILE *leasestream)
if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
{
lease_set_iaid(lease, strtoul(s, NULL, 10));
domain = get_domain6((struct in6_addr *)lease->hwaddr);
domain = get_domain6(&lease->addr6);
}
}
#endif
@@ -555,7 +555,9 @@ void lease_prune(struct dhcp_lease *target, time_t now)
file_dirty = 1;
if (lease->hostname)
dns_dirty = 1;
daemon->metrics[lease->addr.s_addr ? METRIC_LEASES_PRUNED_4 : METRIC_LEASES_PRUNED_6]++;
*up = lease->next; /* unlink */
/* Put on old_leases list 'till we
@@ -773,7 +775,10 @@ struct dhcp_lease *lease4_allocate(struct in_addr addr)
{
struct dhcp_lease *lease = lease_allocate();
if (lease)
lease->addr = addr;
{
lease->addr = addr;
daemon->metrics[METRIC_LEASES_ALLOCATED_4]++;
}
return lease;
}
@@ -788,6 +793,8 @@ struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type)
lease->addr6 = *addrp;
lease->flags |= lease_type;
lease->iaid = 0;
daemon->metrics[METRIC_LEASES_ALLOCATED_6]++;
}
return lease;

44
src/metrics.c Normal file
View File

@@ -0,0 +1,44 @@
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
const char * metric_names[] = {
"dns_cache_inserted",
"dns_cache_live_freed",
"dns_queries_forwarded",
"dns_auth_answered",
"dns_local_answered",
"bootp",
"pxe",
"dhcp_ack",
"dhcp_decline",
"dhcp_discover",
"dhcp_inform",
"dhcp_nak",
"dhcp_offer",
"dhcp_release",
"dhcp_request",
"noanswer",
"leases_allocated_4",
"leases_pruned_4",
"leases_allocated_6",
"leases_pruned_6",
};
const char* get_metric_name(int i) {
return metric_names[i];
}

43
src/metrics.h Normal file
View File

@@ -0,0 +1,43 @@
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* If you modify this list, please keep the labels in metrics.c in sync. */
enum {
METRIC_DNS_CACHE_INSERTED,
METRIC_DNS_CACHE_LIVE_FREED,
METRIC_DNS_QUERIES_FORWARDED,
METRIC_DNS_AUTH_ANSWERED,
METRIC_DNS_LOCAL_ANSWERED,
METRIC_BOOTP,
METRIC_PXE,
METRIC_DHCPACK,
METRIC_DHCPDECLINE,
METRIC_DHCPDISCOVER,
METRIC_DHCPINFORM,
METRIC_DHCPNAK,
METRIC_DHCPOFFER,
METRIC_DHCPRELEASE,
METRIC_DHCPREQUEST,
METRIC_NOANSWER,
METRIC_LEASES_ALLOCATED_4,
METRIC_LEASES_PRUNED_4,
METRIC_LEASES_ALLOCATED_6,
METRIC_LEASES_PRUNED_6,
__METRIC_MAX,
};
const char* get_metric_name(int);

View File

@@ -1234,7 +1234,8 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
struct serverfd *sfd;
unsigned int ifindex = 0;
int errsave;
int opt = 1;
/* when using random ports, servers which would otherwise use
the INADDR_ANY/port0 socket have sfd set to NULL */
if (!daemon->osport && intname[0] == 0)
@@ -1274,10 +1275,11 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
free(sfd);
return NULL;
}
if (!local_bind(sfd->fd, addr, intname, ifindex, 0) || !fix_fd(sfd->fd))
if ((addr->sa.sa_family == AF_INET6 && setsockopt(sfd->fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) ||
!local_bind(sfd->fd, addr, intname, ifindex, 0) || !fix_fd(sfd->fd))
{
errsave = errno; /* save error from bind. */
errsave = errno; /* save error from bind/setsockopt. */
close(sfd->fd);
free(sfd);
errno = errsave;
@@ -1288,6 +1290,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
sfd->source_addr = *addr;
sfd->next = daemon->sfds;
sfd->ifindex = ifindex;
sfd->preallocated = 0;
daemon->sfds = sfd;
return sfd;
@@ -1298,6 +1301,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
void pre_allocate_sfds(void)
{
struct server *srv;
struct serverfd *sfd;
if (daemon->query_port != 0)
{
@@ -1309,7 +1313,8 @@ void pre_allocate_sfds(void)
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in.sin_len = sizeof(struct sockaddr_in);
#endif
allocate_sfd(&addr, "");
if ((sfd = allocate_sfd(&addr, "")))
sfd->preallocated = 1;
#ifdef HAVE_IPV6
memset(&addr, 0, sizeof(addr));
addr.in6.sin6_family = AF_INET6;
@@ -1318,7 +1323,8 @@ void pre_allocate_sfds(void)
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif
allocate_sfd(&addr, "");
if ((sfd = allocate_sfd(&addr, "")))
sfd->preallocated = 1;
#endif
}
@@ -1471,9 +1477,10 @@ void check_servers(void)
/* interface may be new since startup */
if (!option_bool(OPT_NOWILD))
enumerate_interfaces(0);
/* don't garbage collect pre-allocated sfds. */
for (sfd = daemon->sfds; sfd; sfd = sfd->next)
sfd->used = 0;
sfd->used = sfd->preallocated;
for (count = 0, serv = daemon->servers; serv; serv = serv->next)
{

View File

@@ -160,6 +160,12 @@ struct myoption {
#define LOPT_DHCPTTL 348
#define LOPT_TFTP_MTU 349
#define LOPT_REPLY_DELAY 350
#define LOPT_RAPID_COMMIT 351
#define LOPT_DUMPFILE 352
#define LOPT_DUMPMASK 353
#define LOPT_UBUS 354
#define LOPT_NAME_MATCH 355
#define LOPT_CAA 356
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -228,8 +234,10 @@ static const struct myoption opts[] =
{ "srv-host", 1, 0, 'W' },
{ "localise-queries", 0, 0, 'y' },
{ "txt-record", 1, 0, 'Y' },
{ "caa-record", 1, 0 , LOPT_CAA },
{ "dns-rr", 1, 0, LOPT_RR },
{ "enable-dbus", 2, 0, '1' },
{ "enable-ubus", 0, 0, LOPT_UBUS },
{ "bootp-dynamic", 2, 0, '3' },
{ "dhcp-mac", 1, 0, '4' },
{ "no-ping", 0, 0, '5' },
@@ -268,7 +276,8 @@ static const struct myoption opts[] =
{ "stop-dns-rebind", 0, 0, LOPT_REBIND },
{ "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
{ "all-servers", 0, 0, LOPT_NOLAST },
{ "dhcp-match", 1, 0, LOPT_MATCH },
{ "dhcp-match", 1, 0, LOPT_MATCH },
{ "dhcp-name-match", 1, 0, LOPT_NAME_MATCH },
{ "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
{ "neg-ttl", 1, 0, LOPT_NEGTTL },
{ "max-ttl", 1, 0, LOPT_MAXTTL },
@@ -310,7 +319,7 @@ static const struct myoption opts[] =
{ "dnssec", 0, 0, LOPT_SEC_VALID },
{ "trust-anchor", 1, 0, LOPT_TRUST_ANCHOR },
{ "dnssec-debug", 0, 0, LOPT_DNSSEC_DEBUG },
{ "dnssec-check-unsigned", 0, 0, LOPT_DNSSEC_CHECK },
{ "dnssec-check-unsigned", 2, 0, LOPT_DNSSEC_CHECK },
{ "dnssec-no-timecheck", 0, 0, LOPT_DNSSEC_TIME },
{ "dnssec-timestamp", 1, 0, LOPT_DNSSEC_STAMP },
#ifdef OPTION6_PREFIX_CLASS
@@ -325,6 +334,9 @@ static const struct myoption opts[] =
{ "script-arp", 0, 0, LOPT_SCRIPT_ARP },
{ "dhcp-ttl", 1, 0 , LOPT_DHCPTTL },
{ "dhcp-reply-delay", 1, 0, LOPT_REPLY_DELAY },
{ "dhcp-rapid-commit", 0, 0, LOPT_RAPID_COMMIT },
{ "dumpfile", 1, 0, LOPT_DUMPFILE },
{ "dumpmask", 1, 0, LOPT_DUMPMASK },
{ NULL, 0, 0, 0 }
};
@@ -414,6 +426,7 @@ static struct {
{ 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
{ 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
{ '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
{ LOPT_UBUS, OPT_UBUS, NULL, gettext_noop("Enable the UBus interface."), NULL },
{ '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
{ '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
{ '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
@@ -447,6 +460,7 @@ static struct {
{ LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
{ LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
{ LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
{ LOPT_NAME_MATCH, ARG_DUP, "set:<tag>,<string>[*]", gettext_noop("Set tag if client provides given name."), NULL },
{ LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
{ LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
{ LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
@@ -469,6 +483,7 @@ static struct {
{ LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
{ LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
{ LOPT_HOST_REC, ARG_DUP, "<name>,<address>[,<ttl>]", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
{ LOPT_CAA, ARG_DUP, "<name>,<flags>,<tag>,<value>", gettext_noop("Specify certification authority authorization record"), NULL },
{ LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
{ LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
{ LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
@@ -482,7 +497,7 @@ static struct {
{ LOPT_SEC_VALID, OPT_DNSSEC_VALID, NULL, gettext_noop("Activate DNSSEC validation"), NULL },
{ LOPT_TRUST_ANCHOR, ARG_DUP, "<domain>,[<class>],...", gettext_noop("Specify trust anchor key digest."), NULL },
{ LOPT_DNSSEC_DEBUG, OPT_DNSSEC_DEBUG, NULL, gettext_noop("Disable upstream checking for DNSSEC debugging."), NULL },
{ LOPT_DNSSEC_CHECK, OPT_DNSSEC_NO_SIGN, NULL, gettext_noop("Ensure answers without DNSSEC are in unsigned zones."), NULL },
{ LOPT_DNSSEC_CHECK, ARG_DUP, NULL, gettext_noop("Ensure answers without DNSSEC are in unsigned zones."), NULL },
{ LOPT_DNSSEC_TIME, OPT_DNSSEC_TIME, NULL, gettext_noop("Don't check DNSSEC signature timestamps until first cache-reload"), NULL },
{ LOPT_DNSSEC_STAMP, ARG_ONE, "<path>", gettext_noop("Timestamp file to verify system clock for DNSSEC"), NULL },
#ifdef OPTION6_PREFIX_CLASS
@@ -497,6 +512,9 @@ static struct {
{ LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>", gettext_noop("Ignore DNS responses containing ipaddr."), NULL },
{ LOPT_DHCPTTL, ARG_ONE, "<ttl>", gettext_noop("Set TTL in DNS responses with DHCP-derived addresses."), NULL },
{ LOPT_REPLY_DELAY, ARG_ONE, "<integer>", gettext_noop("Delay DHCP replies for at least number of seconds."), NULL },
{ LOPT_RAPID_COMMIT, OPT_RAPID_COMMIT, NULL, gettext_noop("Enables DHCPv4 Rapid Commit option."), NULL },
{ LOPT_DUMPFILE, ARG_ONE, "<path>", gettext_noop("Path to debug packet dump file"), NULL },
{ LOPT_DUMPMASK, ARG_ONE, "<hex>", gettext_noop("Mask which packets to dump"), NULL },
{ 0, 0, NULL, NULL, NULL }
};
@@ -1737,7 +1755,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
#endif
}
break;
case 'x': /* --pid-file */
daemon->runfile = opt_string_alloc(arg);
break;
@@ -1808,6 +1826,14 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
ret_err(_("bad MX target"));
break;
case LOPT_DUMPFILE: /* --dumpfile */
daemon->dump_file = opt_string_alloc(arg);
break;
case LOPT_DUMPMASK: /* --dumpmask */
daemon->dump_mask = strtol(arg, NULL, 0);
break;
#ifdef HAVE_DHCP
case 'l': /* --dhcp-leasefile */
daemon->lease_file = opt_string_alloc(arg);
@@ -1875,8 +1901,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
break;
}
#ifdef HAVE_AUTH
case LOPT_AUTHSERV: /* --auth-server */
if (!(comma = split(arg)))
ret_err(gen_err);
@@ -2051,7 +2075,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
break;
#endif
case 's': /* --domain */
case LOPT_SYNTH: /* --synth-domain */
@@ -2212,7 +2235,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
char *star;
new->next = daemon->synth_domains;
daemon->synth_domains = new;
if ((star = strrchr(new->prefix, '*')) && *(star+1) == 0)
if (new->prefix &&
(star = strrchr(new->prefix, '*'))
&& *(star+1) == 0)
{
*star = 0;
new->indexed = 1;
@@ -2400,7 +2425,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (strcmp(arg, "#") == 0)
domain = "";
else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
option = '?';
ret_err(gen_err);
serv = opt_malloc(sizeof(struct server));
memset(serv, 0, sizeof(struct server));
serv->next = newlist;
@@ -2532,7 +2557,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (strcmp(arg, "#") == 0 || !*arg)
domain = "";
else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
option = '?';
ret_err(gen_err);
ipsets->next = opt_malloc(sizeof(struct ipsets));
ipsets = ipsets->next;
memset(ipsets, 0, sizeof(struct ipsets));
@@ -2547,13 +2572,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
memset(ipsets, 0, sizeof(struct ipsets));
ipsets->domain = "";
}
if (!arg || !*arg)
{
option = '?';
break;
}
size = 2;
for (end = arg; *end; ++end)
ret_err(gen_err);
for (size = 2, end = arg; *end; ++end)
if (*end == ',')
++size;
@@ -2586,8 +2609,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (size < 0)
size = 0;
else if (size > 10000)
size = 10000;
daemon->cachesize = size;
}
@@ -2783,12 +2804,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
memset (new, 0, sizeof(*new));
new->lease_time = DEFLEASE;
if (!arg)
{
option = '?';
break;
}
while(1)
{
for (cp = arg; *cp; cp++)
@@ -3277,7 +3292,33 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
option == LOPT_FORCE ? DHOPT_FORCE :
(option == LOPT_MATCH ? DHOPT_MATCH :
(option == LOPT_OPTS ? DHOPT_BANK : 0)));
case LOPT_NAME_MATCH: /* --dhcp-name-match */
{
struct dhcp_match_name *new = opt_malloc(sizeof(struct dhcp_match_name));
struct dhcp_netid *id = opt_malloc(sizeof(struct dhcp_netid));
ssize_t len;
if (!(comma = split(arg)) || (len = strlen(comma)) == 0)
ret_err(gen_err);
new->wildcard = 0;
new->netid = id;
id->net = opt_string_alloc(set_prefix(arg));
if (comma[len-1] == '*')
{
comma[len-1] = 0;
new->wildcard = 1;
}
new->name = opt_string_alloc(comma);
new->next = daemon->dhcp_name_match;
daemon->dhcp_name_match = new;
break;
}
case 'M': /* --dhcp-boot */
{
struct dhcp_netid *id = NULL;
@@ -3790,11 +3831,9 @@ err:
if ((k < 2) ||
(!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
(!(inet_pton(AF_INET, a[1], &new->out) > 0)))
option = '?';
if (k == 3 && !inet_pton(AF_INET, a[2], &new->mask))
option = '?';
(!(inet_pton(AF_INET, a[1], &new->out) > 0)) ||
(k == 3 && !inet_pton(AF_INET, a[2], &new->mask)))
ret_err(_("missing address in alias"));
if (dash &&
(!(inet_pton(AF_INET, dash, &new->end) > 0) ||
@@ -3966,7 +4005,7 @@ err:
if (data)
{
new->txt=opt_malloc(len);
new->txt = opt_malloc(len);
new->len = len;
memcpy(new->txt, data, len);
}
@@ -3974,6 +4013,37 @@ err:
break;
}
case LOPT_CAA: /* --caa-record */
{
struct txt_record *new;
char *tag, *value;
int flags;
comma = split(arg);
tag = split(comma);
value = split(tag);
new = opt_malloc(sizeof(struct txt_record));
new->next = daemon->rr;
daemon->rr = new;
if (!atoi_check(comma, &flags) || !tag || !value || !(new->name = canonicalise_opt(arg)))
ret_err(_("bad CAA record"));
unhide_metas(tag);
unhide_metas(value);
new->len = strlen(tag) + strlen(value) + 2;
new->txt = opt_malloc(new->len);
new->txt[0] = flags;
new->txt[1] = strlen(tag);
memcpy(&new->txt[2], tag, strlen(tag));
memcpy(&new->txt[2 + strlen(tag)], value, strlen(value));
new->class = T_CAA;
break;
}
case 'Y': /* --txt-record */
{
struct txt_record *new;
@@ -4132,11 +4202,21 @@ err:
}
#ifdef HAVE_DNSSEC
case LOPT_DNSSEC_STAMP:
case LOPT_DNSSEC_STAMP: /* --dnssec-timestamp */
daemon->timestamp_file = opt_string_alloc(arg);
break;
case LOPT_TRUST_ANCHOR:
case LOPT_DNSSEC_CHECK: /* --dnssec-check-unsigned */
if (arg)
{
if (strcmp(arg, "no") == 0)
set_option_bool(OPT_DNSSEC_IGN_NS);
else
ret_err(_("bad value for dnssec-check-unsigned"));
}
break;
case LOPT_TRUST_ANCHOR: /* --trust-anchor */
{
struct ds_config *new = opt_malloc(sizeof(struct ds_config));
char *cp, *cp1, *keyhex, *digest, *algo = NULL;
@@ -4321,7 +4401,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
if (errmess)
strcpy(daemon->namebuff, errmess);
if (errmess || !one_opt(option, arg, buff, _("error"), 0, hard_opt == LOPT_REV_SERV))
if (errmess || !one_opt(option, arg, daemon->namebuff, _("error"), 0, hard_opt == LOPT_REV_SERV))
{
sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
if (hard_opt != 0)

View File

@@ -788,6 +788,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
newc->addr.cname.uid = 1;
if (cpp)
{
next_uid(newc);
cpp->addr.cname.target.cache = newc;
cpp->addr.cname.uid = newc->uid;
}
@@ -844,6 +845,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD | secflag);
if (newc && cpp)
{
next_uid(newc);
cpp->addr.cname.target.cache = newc;
cpp->addr.cname.uid = newc->uid;
}
@@ -870,6 +872,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));
if (newc && cpp)
{
next_uid(newc);
cpp->addr.cname.target.cache = newc;
cpp->addr.cname.uid = newc->uid;
}
@@ -926,12 +929,11 @@ unsigned int extract_request(struct dns_header *header, size_t qlen, char *name,
return F_QUERY;
}
size_t setup_reply(struct dns_header *header, size_t qlen,
struct all_addr *addrp, unsigned int flags, unsigned long ttl)
{
unsigned char *p;
if (!(p = skip_questions(header, qlen)))
return 0;
@@ -948,7 +950,12 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
else if (flags == F_NXDOMAIN)
SET_RCODE(header, NXDOMAIN);
else if (flags == F_SERVFAIL)
SET_RCODE(header, SERVFAIL);
{
struct all_addr a;
a.addr.rcode.rcode = SERVFAIL;
log_query(F_CONFIG | F_RCODE, "error", &a, NULL);
SET_RCODE(header, SERVFAIL);
}
else if (flags == F_IPV4)
{ /* we know the address */
SET_RCODE(header, NOERROR);
@@ -966,48 +973,48 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
}
#endif
else /* nowhere to forward to */
SET_RCODE(header, REFUSED);
{
struct all_addr a;
a.addr.rcode.rcode = REFUSED;
log_query(F_CONFIG | F_RCODE, "error", &a, NULL);
SET_RCODE(header, REFUSED);
}
return p - (unsigned char *)header;
}
/* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */
int check_for_local_domain(char *name, time_t now)
{
struct crec *crecp;
struct mx_srv_record *mx;
struct txt_record *txt;
struct interface_name *intr;
struct ptr_record *ptr;
struct naptr *naptr;
/* Note: the call to cache_find_by_name is intended to find any record which matches
ie A, AAAA, CNAME. */
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_NO_RR)) &&
(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
return 1;
for (naptr = daemon->naptr; naptr; naptr = naptr->next)
if (hostname_isequal(name, naptr->name))
if (hostname_issubdomain(name, naptr->name))
return 1;
for (mx = daemon->mxnames; mx; mx = mx->next)
if (hostname_isequal(name, mx->name))
if (hostname_issubdomain(name, mx->name))
return 1;
for (txt = daemon->txt; txt; txt = txt->next)
if (hostname_isequal(name, txt->name))
if (hostname_issubdomain(name, txt->name))
return 1;
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(name, intr->name))
if (hostname_issubdomain(name, intr->name))
return 1;
for (ptr = daemon->ptr; ptr; ptr = ptr->next)
if (hostname_isequal(name, ptr->name))
if (hostname_issubdomain(name, ptr->name))
return 1;
if (cache_find_non_terminal(name, now))
return 1;
return 0;
}
@@ -1370,11 +1377,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
sec_data = 0;
if (!dryrun)
{
log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
log_query(F_CONFIG | F_RRNAME, name, NULL, querystr(NULL, t->class));
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->local_ttl, NULL,
t->class, C_IN, "t", t->len, t->txt))
anscount ++;
anscount++;
}
}
@@ -1654,7 +1661,9 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
}
/* If the client asked for DNSSEC don't use cached data. */
if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))
if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
!do_bit ||
(option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
do
{
/* don't answer wildcard queries with data not from /etc/hosts
@@ -1738,7 +1747,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
{
if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | (dryrun ? F_NO_RR : 0))) &&
(qtype == T_CNAME || (crecp->flags & F_CONFIG)) &&
((crecp->flags & F_CONFIG) || !do_bit || !(crecp->flags & F_DNSSECOK)))
((crecp->flags & F_CONFIG) || !do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
{
if (!(crecp->flags & F_DNSSECOK))
sec_data = 0;

View File

@@ -75,7 +75,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
struct dhcp_vendor *vendor;
struct dhcp_mac *mac;
struct dhcp_netid_list *id_list;
int clid_len = 0, ignore = 0, do_classes = 0, selecting = 0, pxearch = -1;
int clid_len = 0, ignore = 0, do_classes = 0, rapid_commit = 0, selecting = 0, pxearch = -1;
struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
unsigned char *end = (unsigned char *)(mess + 1);
unsigned char *real_end = (unsigned char *)(mess + 1);
@@ -626,6 +626,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
}
}
daemon->metrics[METRIC_BOOTP]++;
log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, NULL, message, mess->xid);
return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);
@@ -699,8 +700,39 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
client_hostname = daemon->dhcp_buff;
}
if (client_hostname && option_bool(OPT_LOG_OPTS))
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
if (client_hostname)
{
struct dhcp_match_name *m;
size_t nl = strlen(client_hostname);
if (option_bool(OPT_LOG_OPTS))
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
for (m = daemon->dhcp_name_match; m; m = m->next)
{
size_t ml = strlen(m->name);
char save = 0;
if (nl < ml)
continue;
if (nl > ml)
{
save = client_hostname[ml];
client_hostname[ml] = 0;
}
if (hostname_isequal(client_hostname, m->name) &&
(save == 0 || m->wildcard))
{
m->netid->next = netid;
netid = m->netid;
}
if (save != 0)
client_hostname[ml] = save;
}
}
if (have_config(config, CONFIG_NAME))
{
@@ -928,6 +960,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if ((pxe && !workaround) || !redirect4011)
do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
daemon->metrics[METRIC_PXE]++;
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
log_tags(tagif_netid, ntohl(mess->xid));
if (!ignore)
@@ -962,6 +995,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
return 0;
daemon->metrics[METRIC_DHCPDECLINE]++;
log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, NULL, daemon->dhcp_buff, mess->xid);
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
@@ -994,6 +1028,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
else
message = _("unknown lease");
daemon->metrics[METRIC_DHCPRELEASE]++;
log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
return 0;
@@ -1060,6 +1095,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
message = _("no address available");
}
daemon->metrics[METRIC_DHCPDISCOVER]++;
log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, NULL, message, mess->xid);
if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
@@ -1073,6 +1109,14 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
log_tags(tagif_netid, ntohl(mess->xid));
apply_delay(mess->xid, recvtime, tagif_netid);
if (option_bool(OPT_RAPID_COMMIT) && option_find(mess, sz, OPTION_RAPID_COMMIT, 0))
{
rapid_commit = 1;
goto rapid_commit;
}
daemon->metrics[METRIC_DHCPOFFER]++;
log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
@@ -1085,7 +1129,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
return dhcp_packet_size(mess, agent_id, real_end);
case DHCPREQUEST:
if (ignore || have_config(config, CONFIG_DISABLE))
return 0;
@@ -1183,9 +1228,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
fuzz = rand16();
mess->yiaddr = mess->ciaddr;
}
daemon->metrics[METRIC_DHCPREQUEST]++;
log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
rapid_commit:
if (!message)
{
struct dhcp_config *addr_config;
@@ -1256,7 +1303,12 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (message)
{
log_packet("DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
daemon->metrics[rapid_commit ? METRIC_NOANSWER : METRIC_DHCPNAK]++;
log_packet(rapid_commit ? "NOANSWER" : "DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
/* rapid commit case: lease allocate failed but don't send DHCPNAK */
if (rapid_commit)
return 0;
mess->yiaddr.s_addr = 0;
clear_packet(mess, end);
@@ -1413,13 +1465,16 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
else
override = lease->override;
daemon->metrics[METRIC_DHCPACK]++;
log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
clear_packet(mess, end);
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
if (rapid_commit)
option_put(mess, end, OPTION_RAPID_COMMIT, 0, 0);
do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
}
@@ -1429,6 +1484,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (ignore || have_config(config, CONFIG_DISABLE))
message = _("ignored");
daemon->metrics[METRIC_DHCPINFORM]++;
log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, NULL, mess->xid);
if (message || mess->ciaddr.s_addr == 0)
@@ -1455,6 +1511,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
log_tags(tagif_netid, ntohl(mess->xid));
daemon->metrics[METRIC_DHCPACK]++;
log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
if (lease)
@@ -1621,6 +1678,13 @@ static void log_packet(char *type, void *addr, unsigned char *ext_mac,
daemon->namebuff,
string ? string : "",
err ? err : "");
#ifdef HAVE_UBUS
if (!strcmp(type, "DHCPACK"))
ubus_event_bcast("dhcp.ack", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface);
else if (!strcmp(type, "DHCPRELEASE"))
ubus_event_bcast("dhcp.release", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface);
#endif
}
static void log_options(unsigned char *start, u32 xid)

View File

@@ -639,9 +639,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
int plain_range = 1;
u32 lease_time;
struct dhcp_lease *ltmp;
struct in6_addr *req_addr;
struct in6_addr addr;
struct in6_addr req_addr, addr;
if (!check_ia(state, opt, &ia_end, &ia_option))
continue;
@@ -709,9 +708,10 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
req_addr = opt6_ptr(ia_option, 0);
/* worry about alignment here. */
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if ((c = address6_valid(state->context, req_addr, solicit_tags, plain_range)))
if ((c = address6_valid(state->context, &req_addr, solicit_tags, plain_range)))
{
lease_time = c->lease_time;
/* If the client asks for an address on the same network as a configured address,
@@ -719,14 +719,14 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
addresses automatic. */
if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr) && check_address(state, &addr))
{
req_addr = &addr;
req_addr = addr;
mark_config_used(c, &addr);
if (have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
}
else if (!(c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
else if (!(c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
continue; /* not an address we're allowed */
else if (!check_address(state, req_addr))
else if (!check_address(state, &req_addr))
continue; /* address leased elsewhere */
/* add address to output packet */
@@ -734,8 +734,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
state->send_prefix_class = prefix_class_from_context(c);
#endif
add_address(state, c, lease_time, ia_option, &min_time, req_addr, now);
mark_context_used(state, req_addr);
add_address(state, c, lease_time, ia_option, &min_time, &req_addr, now);
mark_context_used(state, &req_addr);
get_context_tag(state, c);
address_assigned = 1;
}
@@ -768,15 +768,15 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
ltmp = NULL;
while ((ltmp = lease6_find_by_client(ltmp, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state->clid, state->clid_len, state->iaid)))
{
req_addr = &ltmp->addr6;
if ((c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
req_addr = ltmp->addr6;
if ((c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
{
#ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
state->send_prefix_class = prefix_class_from_context(c);
#endif
add_address(state, c, c->lease_time, NULL, &min_time, req_addr, now);
mark_context_used(state, req_addr);
add_address(state, c, c->lease_time, NULL, &min_time, &req_addr, now);
mark_context_used(state, &req_addr);
get_context_tag(state, c);
address_assigned = 1;
}
@@ -892,16 +892,19 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
struct in6_addr req_addr;
struct dhcp_context *dynamic, *c;
unsigned int lease_time;
struct in6_addr addr;
int config_ok = 0;
/* align. */
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if ((c = address6_valid(state->context, req_addr, tagif, 1)))
config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr);
if ((c = address6_valid(state->context, &req_addr, tagif, 1)))
config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, &req_addr);
if ((dynamic = address6_available(state->context, req_addr, tagif, 1)) || c)
if ((dynamic = address6_available(state->context, &req_addr, tagif, 1)) || c)
{
if (!dynamic && !config_ok)
{
@@ -911,7 +914,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
put_opt6_string(_("address unavailable"));
end_opt6(o1);
}
else if (!check_address(state, req_addr))
else if (!check_address(state, &req_addr))
{
/* Address leased to another DUID/IAID */
o1 = new_opt6(OPTION6_STATUS_CODE);
@@ -933,7 +936,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
state->send_prefix_class = prefix_class_from_context(c);
#endif
add_address(state, dynamic, lease_time, ia_option, &min_time, req_addr, now);
add_address(state, dynamic, lease_time, ia_option, &min_time, &req_addr, now);
get_context_tag(state, dynamic);
address_assigned = 1;
}
@@ -996,15 +999,17 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct dhcp_lease *lease = NULL;
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
struct in6_addr req_addr;
unsigned int preferred_time = opt6_uint(ia_option, 16, 4);
unsigned int valid_time = opt6_uint(ia_option, 20, 4);
char *message = NULL;
struct dhcp_context *this_context;
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if (!(lease = lease6_find(state->clid, state->clid_len,
state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
state->iaid, req_addr)))
state->iaid, &req_addr)))
{
/* If the server cannot find a client entry for the IA the server
returns the IA containing no addresses with a Status Code option set
@@ -1012,7 +1017,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
save_counter(iacntr);
t1cntr = 0;
log6_packet(state, "DHCPREPLY", req_addr, _("lease not found"));
log6_packet(state, "DHCPREPLY", &req_addr, _("lease not found"));
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOBINDING);
@@ -1024,15 +1029,15 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
if ((this_context = address6_available(state->context, req_addr, tagif, 1)) ||
(this_context = address6_valid(state->context, req_addr, tagif, 1)))
if ((this_context = address6_available(state->context, &req_addr, tagif, 1)) ||
(this_context = address6_valid(state->context, &req_addr, tagif, 1)))
{
struct in6_addr addr;
unsigned int lease_time;
get_context_tag(state, this_context);
if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr) && have_config(config, CONFIG_TIME))
if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, &req_addr) && have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
else
lease_time = this_context->lease_time;
@@ -1045,7 +1050,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
lease_set_hwaddr(lease, state->mac, state->clid, state->mac_len, state->mac_type, state->clid_len, now, 0);
if (state->ia_type == OPTION6_IA_NA && state->hostname)
{
char *addr_domain = get_domain6(req_addr);
char *addr_domain = get_domain6(&req_addr);
if (!state->send_domain)
state->send_domain = addr_domain;
lease_set_hostname(lease, state->hostname, state->hostname_auth, addr_domain, state->domain);
@@ -1063,12 +1068,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
if (message && (message != state->hostname))
log6_packet(state, "DHCPREPLY", req_addr, message);
log6_packet(state, "DHCPREPLY", &req_addr, message);
else
log6_quiet(state, "DHCPREPLY", req_addr, message);
log6_quiet(state, "DHCPREPLY", &req_addr, message);
o1 = new_opt6(OPTION6_IAADDR);
put_opt6(req_addr, sizeof(*req_addr));
put_opt6(&req_addr, sizeof(req_addr));
put_opt6_long(preferred_time);
put_opt6_long(valid_time);
end_opt6(o1);
@@ -1100,19 +1105,23 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
ia_option;
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
struct in6_addr req_addr;
/* alignment */
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if (!address6_valid(state->context, req_addr, tagif, 1))
if (!address6_valid(state->context, &req_addr, tagif, 1))
{
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOTONLINK);
put_opt6_string(_("confirm failed"));
end_opt6(o1);
log6_quiet(state, "DHCPREPLY", &req_addr, _("confirm failed"));
return 1;
}
good_addr = 1;
log6_quiet(state, "DHCPREPLY", req_addr, state->hostname);
log6_quiet(state, "DHCPREPLY", &req_addr, state->hostname);
}
}
@@ -1171,9 +1180,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct dhcp_lease *lease;
struct in6_addr addr;
/* align */
memcpy(&addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
state->iaid, opt6_ptr(ia_option, 0))))
state->iaid, &addr)))
lease_prune(lease, now);
else
{
@@ -1190,7 +1202,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
o1 = new_opt6(OPTION6_IAADDR);
put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
put_opt6(&addr, IN6ADDRSZ);
put_opt6_long(0);
put_opt6_long(0);
end_opt6(o1);
@@ -1233,12 +1245,15 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct dhcp_lease *lease;
struct in6_addr *addrp = opt6_ptr(ia_option, 0);
struct in6_addr addr;
if (have_config(config, CONFIG_ADDR6) && IN6_ARE_ADDR_EQUAL(&config->addr6, addrp))
/* align */
memcpy(&addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if (have_config(config, CONFIG_ADDR6) && IN6_ARE_ADDR_EQUAL(&config->addr6, &addr))
{
prettyprint_time(daemon->dhcp_buff3, DECLINE_BACKOFF);
inet_ntop(AF_INET6, addrp, daemon->addrbuff, ADDRSTRLEN);
inet_ntop(AF_INET6, &addr, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
daemon->addrbuff, daemon->dhcp_buff3);
config->flags |= CONFIG_DECLINED;
@@ -1250,7 +1265,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
context_tmp->addr_epoch++;
if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
state->iaid, opt6_ptr(ia_option, 0))))
state->iaid, &addr)))
lease_prune(lease, now);
else
{
@@ -1267,7 +1282,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
o1 = new_opt6(OPTION6_IAADDR);
put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
put_opt6(&addr, IN6ADDRSZ);
put_opt6_long(0);
put_opt6_long(0);
end_opt6(o1);
@@ -1935,7 +1950,11 @@ static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_op
}
else if (type == OPTION6_IAADDR)
{
inet_ntop(AF_INET6, opt6_ptr(opt, 0), daemon->addrbuff, ADDRSTRLEN);
struct in6_addr addr;
/* align */
memcpy(&addr, opt6_ptr(opt, 0), IN6ADDRSZ);
inet_ntop(AF_INET6, &addr, daemon->addrbuff, ADDRSTRLEN);
sprintf(daemon->namebuff, "%s PL=%u VL=%u",
daemon->addrbuff, opt6_uint(opt, 16, 4), opt6_uint(opt, 20, 4));
optname = "iaaddr";

107
src/ubus.c Normal file
View File

@@ -0,0 +1,107 @@
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
#ifdef HAVE_UBUS
#include <libubus.h>
static struct ubus_context *ubus = NULL;
static struct blob_buf b;
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg);
static struct ubus_method ubus_object_methods[] = {
{.name = "metrics", .handler = ubus_handle_metrics},
};
static struct ubus_object_type ubus_object_type = UBUS_OBJECT_TYPE("dnsmasq", ubus_object_methods);
static struct ubus_object ubus_object = {
.name = "dnsmasq",
.type = &ubus_object_type,
.methods = ubus_object_methods,
.n_methods = ARRAY_SIZE(ubus_object_methods),
};
void set_ubus_listeners()
{
if (!ubus)
return;
poll_listen(ubus->sock.fd, POLLIN);
poll_listen(ubus->sock.fd, POLLERR);
poll_listen(ubus->sock.fd, POLLHUP);
}
void check_ubus_listeners()
{
if (!ubus)
{
ubus = ubus_connect(NULL);
if (!ubus)
return;
ubus_add_object(ubus, &ubus_object);
}
if (poll_check(ubus->sock.fd, POLLIN))
ubus_handle_event(ubus);
if (poll_check(ubus->sock.fd, POLLHUP))
{
ubus_free(ubus);
ubus = NULL;
}
}
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
int i;
blob_buf_init(&b, 0);
for(i=0; i < __METRIC_MAX; i++)
blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]);
ubus_send_reply(ctx, req, b.head);
return 0;
}
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface)
{
if (!ubus || !ubus_object.has_subscribers)
return;
blob_buf_init(&b, 0);
if (mac)
blobmsg_add_string(&b, "mac", mac);
if (ip)
blobmsg_add_string(&b, "ip", ip);
if (name)
blobmsg_add_string(&b, "name", name);
if (interface)
blobmsg_add_string(&b, "interface", interface);
ubus_notify(ubus, &ubus_object, type, b.head, -1);
}
#endif /* HAVE_UBUS */

View File

@@ -355,6 +355,44 @@ int hostname_isequal(const char *a, const char *b)
return 1;
}
/* is b equal to or a subdomain of a return 2 for equal, 1 for subdomain */
int hostname_issubdomain(char *a, char *b)
{
char *ap, *bp;
unsigned int c1, c2;
/* move to the end */
for (ap = a; *ap; ap++);
for (bp = b; *bp; bp++);
/* a shorter than b or a empty. */
if ((bp - b) < (ap - a) || ap == a)
return 0;
do
{
c1 = (unsigned char) *(--ap);
c2 = (unsigned char) *(--bp);
if (c1 >= 'A' && c1 <= 'Z')
c1 += 'a' - 'A';
if (c2 >= 'A' && c2 <= 'Z')
c2 += 'a' - 'A';
if (c1 != c2)
return 0;
} while (ap != a);
if (bp == b)
return 2;
if (*(--bp) == '.')
return 1;
return 0;
}
time_t dnsmasq_time(void)
{
#ifdef HAVE_BROKEN_RTC