Compare commits

...

418 Commits

Author SHA1 Message Date
Simon Kelley
712dadb287 Bump Debian version to 2.78-1 2017-06-25 21:35:47 +01:00
Simon Kelley
32be32eab8 Formatting fixes for CHANGELOG 2017-06-25 21:33:28 +01:00
Simon Kelley
1649f709e7 Fix DHCP relay, broken by ff325644c7
Thanks to John Fitzgibbon for initial patch.
2017-06-25 21:19:30 +01:00
Simon Kelley
50ca85504c Bump year in copyrights. 2017-06-24 22:43:18 +01:00
Simon Kelley
4bb68866a8 Tweak ICMP ping check logic for DHCPv4. 2017-06-15 23:23:25 +01:00
Chris Novakovic
2446514e71 Fix logic of appending ".<layer>" to PXE basename
Commit f77700aa, which fixes a compiler warning, also breaks the
behaviour of prepending ".<layer>" to basenames in --pxe-service: in
situations where the basename contains a ".", the ".<layer>" suffix is
erroneously added, and in situations where the basename doesn't contain
a ".", the ".<layer>" suffix is erroneously omitted.

A patch against the git HEAD is attached that inverts this logic and
restores the expected behaviour of --pxe-service.
2017-06-06 23:02:59 +01:00
Simon Kelley
109d0e74f1 Debian: improve regexp for parsing root.ds. 2017-06-05 20:50:54 +01:00
Simon Kelley
74ea91531a Fix typo and format in CHANGELOG 2017-05-22 22:58:46 +01:00
Matthias Andree
9828ab115e Fix compiler warning. 2017-05-21 22:41:16 +01:00
Matthias Andree
f77700aa27 Fix compiler warning. 2017-05-21 22:36:09 +01:00
Simon Kelley
0fbd980639 Fix compiler warning. 2017-05-21 22:24:43 +01:00
Simon Kelley
43cdf1c3d0 Remove automatic IDN support when building i18n.
Remove historic automatic inclusion of IDN support when
building internationalisation support. This doesn't
fit now there is a choice of IDN libraries. Be sure
to include either -DHAVE_IDN or _DHAVE_LIBIDN2 for
IDN support
2017-05-21 22:12:44 +01:00
Simon Kelley
ff19b1a97d Fix &/&& confusion. 2017-05-21 21:15:32 +01:00
Conrad Kostecki
1835343acd Update German translation. 2017-05-12 15:16:02 +01:00
Simon Kelley
2aaea18f43 Add .gitattributes to substitute VERSION on export. 2017-05-12 13:14:17 +01:00
Simon Kelley
7ab78b937f Fix c7be0164ce 2017-05-11 20:33:21 +01:00
Simon Kelley
c7be0164ce Suppress DHCP ping checks when allocating on the loopback interface. 2017-05-10 22:21:53 +01:00
Petr Menšík
d203af4a02 Add optional support for libidn2 and therefore IDNA2008. 2017-05-10 21:41:57 +01:00
Simon Kelley
05f76dab89 Don't die() on failing to parse lease-script output. 2017-05-09 22:57:04 +01:00
Simon Kelley
bf05f8ff20 Fix crash introduced by 09f3b2cd9c. 2017-05-09 22:37:46 +01:00
Simon Kelley
09f3b2cd9c Fix case of DS queries to domains marked as not doing DNSSEC.
This was causing confusion: DNSSEC queries would be sent to
servers for domains that don't do DNSSEC, but because of that status
the answers would be treated as answers to ordinary queries,
sometimes resulting in a crash.
2017-05-09 01:34:02 +01:00
Simon Kelley
22827870fa Fix botch introduced by 561441320f 2017-05-08 21:39:04 +01:00
Vladislav Grishenko
4583dd9e42 Replace obsolete utime() usage with utimes().
This fixes build time warnings with POSIX.1-2008-aware c libraries.
2017-05-03 23:16:51 +01:00
Simon Kelley
561441320f Fix a couple of crashes on malformed config files.
Thanks to Stephan Zeisberg and
american fuzzy lop http://lcamtuf.coredump.cx/afl/
2017-05-03 22:54:09 +01:00
Simon Kelley
b2a9c571eb Add "known-othernet" DHCP tag. 2017-04-30 18:21:31 +01:00
Simon Kelley
efff74c1ae Tweak logging introduced in 3a8b0f6fcc 2017-04-28 23:01:23 +01:00
Simon Kelley
a9df0e30b0 Revert "Implement RFC-6842 (Client-ids in DHCP replies.)"
This reverts commit 88a77a78ad.

A least one client has been found which breaks with this change. Since
the use-case is not clear, I'm reverting the change, at least for now.
2017-04-28 22:44:24 +01:00
Simon Kelley
5ce3e76fbf DHCPv4: do ICMP-ping check in all cases other that current lease. 2017-04-28 22:14:20 +01:00
Vladislav Grishenko
6ec5f5c427 Extend --ra-param mtu: field to allow an interface name. 2017-04-24 22:34:45 +01:00
Vladislav Grishenko
5a7212c70e Make --rev-server work in the presence of --bogus-priv. 2017-04-24 22:21:04 +01:00
Petr Menšík
3a8b0f6fcc Improve error handling with shcp-script "init" mode. 2017-04-23 14:12:37 +01:00
Simon Kelley
a24c31e023 Debian: enable PIE and BINDNOW hardening in build. 2017-04-16 22:45:53 +01:00
Simon Kelley
f5a3679f1d Merge branch 'master' of ssh://thekelleys.org.uk/var/cache/git/dnsmasq 2017-04-16 22:27:51 +01:00
Simon Kelley
5ac813cb86 Bump Lua version to 5.2. 2017-04-16 20:47:11 +01:00
Simon Kelley
a93b02e321 Compile option string: show script-support independent of DHCP. 2017-04-16 20:38:22 +01:00
Petr Menšík
c77fb9d8f0 Capture and log STDOUT and STDERR output from dhcp-script. 2017-04-16 20:20:08 +01:00
Simon Kelley
facc18f2a8 Bump Debian standards version. 2017-04-11 18:52:36 +01:00
Simon Kelley
bc515b71ec Merge branch 'master' of ssh://thekelleys.org.uk/var/cache/git/dnsmasq 2017-04-11 18:49:59 +01:00
Simon Kelley
7bfa26399b FreeBSD compilation tweak. 2017-04-11 18:49:27 +01:00
Simon Kelley
461b7b43b4 Debian: readme typos. 2017-04-11 18:06:13 +01:00
Simon Kelley
b1cefa57f1 Debian: strip dhcp_release6 binary. 2017-04-11 15:55:26 +01:00
Simon Kelley
ce9a9704c6 Debian: add lsb-base dep. 2017-04-11 15:34:25 +01:00
Simon Kelley
93a9a55055 Debian changelog format fixup. 2017-04-11 15:21:30 +01:00
Simon Kelley
44eb875a5a Handle change in format of Debian /usr/share/dns/root.ds. 2017-04-11 15:13:09 +01:00
Floris Bos
bc87e609c2 Debian initscript tweak.
Dnsmasq's startup script seems to assume users always want to use
dnsmasq as local DNS resolver, and tells resolvconf to put
"nameserver 127.0.0.1" in /etc/resolv.conf
The problem with this is that if users just want to use dnsmasq
as DHCP server, and put port=0 in /etc/dnsmasq.conf to disable
the DNS functionality, they end up with broken name resolving.

Put a basic check in the startup script that skips resolvconf
configuration if a line starting with port=0 is in /etc/dnsmasq.conf
This doesn't cover all cases (e.g. configuration could also be in
different file in /etc/dnsmasq.d), but is better than current
situation.
2017-04-11 14:19:57 +01:00
David Flamand
005c46d6f5 Add mtu facility to --ra-param. 2017-04-11 11:49:54 +01:00
Floris Bos
503c609149 --dhcp-reply-delay option to workaround PXE client bugs.
Adds option to delay replying to DHCP packets by one or more seconds.
This provides a workaround for a PXE boot firmware implementation
that has a bug causing it to fail if it receives a (proxy) DHCP
reply instantly.

On Linux it looks up the exact receive time of the UDP packet with
the SIOCGSTAMP ioctl to prevent multiple delays if multiple packets
come in around the same time.
2017-04-09 23:07:13 +01:00
Floris Bos
60704f5e2e Add support for unique TFTP root per MAC.
It is currently only possible to let the TFTP server serve a different
folder depending on the client's IP address.
However it isn't always possible to predict what the client's
IP address will be, especially in situations in which we are not
responsible for handing them out (e.g. proxy dhcp setups).

Extend the current --tftp-unique-root parameter to support having a
separate folder per MAC address instead.
2017-04-09 22:22:49 +01:00
Kristian Evensen
4e7694d710 Allow binding to both source address and interface in server specs.
The current --server syntax allows for binding to interface or
address. However, in some (admittedly special) cases it is useful to
be able to specify both. This commit introduces the following syntax
to support binding to both interface and address:

--server X.X.X.X@IP@interface#port

Based on my tests, the syntax is backwards compatible with the current
@IP/interface#port. The code will fail if two interface names are given.

v1->v2:
* Add man page description of the extended server syntax (thanks Simon Kelley)

Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
2017-03-22 21:32:50 +00:00
James Bottomley
e33b48700e When forwarding a query to a non-DNSSEC nameserver, don't verify the lack of DNSSEC.
The man page says that we don't do DNSSEC on forwarded domains, but if
you turn on dnssec_check_signatures this turns out to be untrue,
because we try to build up a DS chain to them.  Since forwarded domains
are usually used for split DNS to hidden domains, they're unlikely to
verify to the DNS root anyway, so the way to do DNSSEC for them (as the
manual says) is to provide a trust anchor for each forwarder.

The problem I've run into is a split DNS setup where I want DNSSEC to
work mostly, but one of the forwarding domains doesn't have an internal
DNSSEC capable resolver. Without this patch the entire domain goes
unresolvable because the DS record query to the internal resolver
returns a failure which is interpreted as the domain being BOGUS.

The fix is not to do the DS record chase for forwarded domains.
2017-03-17 21:44:10 +00:00
Petr Menšík
ad59f278c6 Fix man page re interface labels and add warning when used badly. 2017-03-17 17:22:19 +00:00
Bert Gijsbers
16f03e7139 Check for failure of "git describe" in get-version. 2017-03-06 23:07:32 +00:00
Olivier Gayot
dc99058d83 Improve error checking for --rev-server.
The rev-server directive only handles the following CIDR prefixes
properly: /8, /16, /24, /32.

Any other value was silently converted to /16 which could result in
unexpected behaviour.

This patch rejects any other value instead of making a silent
conversion.
2017-03-06 22:17:21 +00:00
Olivier Gayot
916959c188 Fix rev-server with /32 prefix.
[ excerpt from the man page ]
The rev-server directive provides a syntactic sugar to make specifying
address-to-name queries easier. For example
--rev-server=1.2.3.0/24,192.168.0.1 is exactly equivalent to
--server=/3.2.1.in-addr.arpa/192.168.0.1

It is not mentioned in the man page but the only prefixes that the
directive properly handles when dealing with IPv4 are /8, /16 and /24.
Specifying anything else as the same effect as specifying /16.

It is not a big deal for subnets on non-octet boundaries since they
cannot be represented using a single in-addr.arpa address. However, it
is unconvenient for /32 prefix while the analogous server directive
behaves as expected. E.g. the following server directive work
as expected:

    server=/42.10.168.192.in-addr.arpa/1.2.3.4

but the following does not:

    rev-server=192.168.10.42/32,1.2.3.4

and, in practice, the later behaves the same as:

    server=/168.192.in-addr.arpa/1.2.3.4

This strange behaviour is fixed by accepting /32 CIDR prefixes as a
valid value. Any other value will still be considered the same as /16.
2017-03-06 22:14:50 +00:00
Simon Kelley
864913c0f3 Man page typo. 2017-02-28 18:07:18 +00:00
Simon Kelley
13dee6f49e Compilation warning fixes. 2017-02-28 16:51:58 +00:00
Simon Kelley
62f9c0d470 Fix CNAME wildcard in auth-mode.
A domain can only have a CNAME if it has not other records.

Don't return a CNAME when there are records of other types on the name.
2017-02-19 23:07:01 +00:00
Simon Kelley
54bb3639d4 Update FAQ to fix a couple of dead links.
Thanks to Federico Bianchi for reporting this.
2017-02-19 22:13:36 +00:00
Simon Kelley
fca008d8d4 Make --bogus-priv apply to IPv6. 2017-02-19 18:50:41 +00:00
klemens
43517fcaf5 Spelling fixes. 2017-02-19 15:53:37 +00:00
Simon Kelley
88a77a78ad Implement RFC-6842 (Client-ids in DHCP replies.) 2017-02-11 17:02:02 +00:00
Hannu Nyman
3e2496fb16 Decrease the number of individual sites listed in log.
By default 30 first servers are listed individually to system log, and
then a count of the remaining items. With e.g. a NXDOMAIN based adblock
service, dnsmasq lists 30 unnecessary ad sites every time when dnsmasq
evaluates the list. But the actual nameservers in use are evaluated last
and are not displayed as they get included in the "remaining items" total.

Handle the "local addresses only" separately and list only a few of them.
Remove the "local addresses only" from the general count.
2017-02-11 13:44:08 +00:00
Simon Kelley
05da782f8f Add forthcoming 2017 root zone trust anchor to trust-anchors.conf. 2017-02-10 21:32:45 +00:00
Simon Kelley
361dfe5158 Improve connection handling when talking to TCP upsteam servers.
Specifically, be prepared to open a new connection when we
want to make multiple queries but the upstream server accepts
fewer queries per connection.
2017-02-10 21:12:30 +00:00
Baptiste Jonglez
68f6312d4b Stop treating SERVFAIL as a successful response from upstream servers.
This effectively reverts most of 51967f9807 ("SERVFAIL is an expected
error return, don't try all servers.") and 4ace25c5d6 ("Treat REFUSED (not
SERVFAIL) as an unsuccessful upstream response").

With the current behaviour, as soon as dnsmasq receives a SERVFAIL from an
upstream server, it stops trying to resolve the query and simply returns
SERVFAIL to the client.  With this commit, dnsmasq will instead try to
query other upstream servers upon receiving a SERVFAIL response.

According to RFC 1034 and 1035, the semantic of SERVFAIL is that of a
temporary error condition.  Recursive resolvers are expected to encounter
network or resources issues from time to time, and will respond with
SERVFAIL in this case.  Similarly, if a validating DNSSEC resolver [RFC
4033] encounters issues when checking signatures (unknown signing
algorithm, missing signatures, expired signatures because of a wrong
system clock, etc), it will respond with SERVFAIL.

Note that all those behaviours are entirely different from a negative
response, which would provide a definite indication that the requested
name does not exist.  In our case, if an upstream server responds with
SERVFAIL, another upstream server may well provide a positive answer for
the same query.

Thus, this commit will increase robustness whenever some upstream servers
encounter temporary issues or are misconfigured.

Quoting RFC 1034, Section 4.3.1. "Queries and responses":

    If recursive service is requested and available, the recursive response
    to a query will be one of the following:

       - The answer to the query, possibly preface by one or more CNAME
         RRs that specify aliases encountered on the way to an answer.

       - A name error indicating that the name does not exist.  This
         may include CNAME RRs that indicate that the original query
	  name was an alias for a name which does not exist.

       - A temporary error indication.

Here is Section 5.2.3. of RFC 1034, "Temporary failures":

    In a less than perfect world, all resolvers will occasionally be unable
    to resolve a particular request.  This condition can be caused by a
    resolver which becomes separated from the rest of the network due to a
    link failure or gateway problem, or less often by coincident failure or
    unavailability of all servers for a particular domain.

And finally, RFC 1035 specifies RRCODE 2 for this usage, which is now more
widely known as SERVFAIL (RFC 1035, Section 4.1.1. "Header section format"):

    RCODE           Response code - this 4 bit field is set as part of
                    responses.  The values have the following
                    interpretation:
                    (...)

                    2               Server failure - The name server was
                                    unable to process this query due to a
                                    problem with the name server.

For the DNSSEC-related usage of SERVFAIL, here is RFC 4033
Section 5. "Scope of the DNSSEC Document Set and Last Hop Issues":

    A validating resolver can determine the following 4 states:
    (...)

    Insecure: The validating resolver has a trust anchor, a chain of
       trust, and, at some delegation point, signed proof of the
       non-existence of a DS record.  This indicates that subsequent
       branches in the tree are provably insecure.  A validating resolver
       may have a local policy to mark parts of the domain space as
       insecure.

    Bogus: The validating resolver has a trust anchor and a secure
       delegation indicating that subsidiary data is signed, but the
       response fails to validate for some reason: missing signatures,
       expired signatures, signatures with unsupported algorithms, data
       missing that the relevant NSEC RR says should be present, and so
       forth.
    (...)

    This specification only defines how security-aware name servers can
    signal non-validating stub resolvers that data was found to be bogus
    (using RCODE=2, "Server Failure"; see [RFC4035]).

Notice the difference between a definite negative answer ("Insecure"
state), and an indefinite error condition ("Bogus" state).  The second
type of error may be specific to a recursive resolver, for instance
because its system clock has been incorrectly set, or because it does not
implement newer cryptographic primitives.  Another recursive resolver may
succeed for the same query.

There are other similar situations in which the specified behaviour is
similar to the one implemented by this commit.

For instance, RFC 2136 specifies the behaviour of a "requestor" that wants
to update a zone using the DNS UPDATE mechanism.  The requestor tries to
contact all authoritative name servers for the zone, with the following
behaviour specified in RFC 2136, Section 4:

    4.6. If a response is received whose RCODE is SERVFAIL or NOTIMP, or
    if no response is received within an implementation dependent timeout
    period, or if an ICMP error is received indicating that the server's
    port is unreachable, then the requestor will delete the unusable
    server from its internal name server list and try the next one,
    repeating until the name server list is empty.  If the requestor runs
    out of servers to try, an appropriate error will be returned to the
    requestor's caller.
2017-02-06 21:09:11 +00:00
Josh Soref
730c6745f0 Comprehensive spelling/typo fixes.
Thanks to Josh Soref for generating these fixes.
2017-02-06 16:14:04 +00:00
Simon Kelley
d42d4706bb Make --localise-queries apply to names from --interface-name. 2017-02-02 16:52:06 +00:00
Simon Kelley
0740e43e20 Fix rrfilter bug leading to malformed replies.
Bug tickled by Nominum upstream when DNSSEC enabled, due to
unusual order of RRs in reply from upstream server.
2017-01-26 18:02:54 +00:00
Simon Kelley
903df07bcb Detect and error loops in --cname configuration. 2017-01-19 17:22:00 +00:00
Simon Kelley
0ef1334d78 Tweak start-up logging 2017-01-15 16:42:39 +00:00
Reiter Wolfgang
5eb9dde09c Fix getsockname error return check. 2017-01-08 17:39:06 +00:00
Simon Kelley
ae3154aca9 Additional syntax check on MAC wildcards. 2017-01-01 22:59:46 +00:00
Simon Kelley
3ebe62d1b7 Merge branch 'master' of ssh://thekelleys.org.uk/var/cache/git/dnsmasq 2017-01-01 22:42:31 +00:00
ZHAO Yu
f89cae3ecf Add DNSMASQ_REQUESTED_OPTIONS env-var to lease change script. 2016-12-22 22:32:31 +00:00
Simon Kelley
09b768efa4 Bump TCP connection backlog from 5 to 32. 2016-12-22 22:16:58 +00:00
Simon Kelley
a1d973f987 Allow multiple CNAMEs in a single --cname= option. 2016-12-22 22:09:50 +00:00
Simon Kelley
0682b7795c Debian packaging update. 2016-12-14 17:59:45 +00:00
Simon Kelley
b637d7815d Allow wildcard CNAME records in authoritative zones. 2016-12-13 16:44:11 +00:00
Kevin Darbyshire-Bryant
7ac9ae1125 Compile time option NO_ID
Some consider it good practice to obscure software version numbers to
clients.  Compiling with -DNO_ID removes the *.bind info structure.
This includes: version, author, copyright, cachesize, cache insertions,
evictions, misses & hits, auth & servers.
2016-09-09 20:52:08 +01:00
Simon Kelley
c6af3a32f2 Support cross-builds in Debian packaging. 2016-08-31 22:38:48 +01:00
Simon Kelley
16800ea072 Fix crash introduced in 2675f20615 2016-08-30 23:07:06 +01:00
Simon Kelley
b5e33ae53a Log ipset errors. 2016-08-28 21:26:42 +01:00
Peter Wu
3c0c1111fe Improve --address and --ipset docs, fix --help output
Manual page: clarify that the --address and --ipset options take one or
more domains rather than just two. Clarify that --ipset puts addresses
in all ipsets, it is not a 1:1 mapping from addresses.

Also increase the width for options output in --help, some options were
truncated leading to confusing output. Almost all options and
descriptions are now within the 120 colums limit.
2016-08-28 20:53:09 +01:00
Beniamino Galvani
2675f20615 Handle binding upstream servers to an interface
(--server=1.2.3.4@eth0) when the named interface
is destroyed and recreated in the kernel.
2016-08-28 20:44:05 +01:00
Simon Kelley
e94ad0fa01 Suppress useless warning about DHCP packets of interfaces without addresses.
This only makes sense for interfaces which we're configured to listen on.
Thanks to Andrew Shadura for bug report.
2016-08-28 18:09:17 +01:00
Simon Kelley
396750cef5 Refactor openBSD pftables code to remove blatant copyright violation. 2016-08-13 22:34:11 +01:00
Simon Kelley
6c45519e18 2.76-3 debian release. 2016-08-13 21:49:17 +01:00
Simon Kelley
6d95099c56 Handle v4-mapped IPv6 addresses sanely for --synth-domain. 2016-08-11 23:38:54 +01:00
Simon Kelley
c8328ecde8 Bump auth zone serial when reloading /etc/hosts and friends. 2016-08-05 16:54:58 +01:00
Mathias Kresin
094bfaeb4f auth-zone: allow to exclude ip addresses from answer. 2016-07-24 14:15:22 +01:00
Simon Kelley
bf4e62c19e Compile-time check on buffer sizes for leasefile parsing code. 2016-07-22 21:37:59 +01:00
Simon Kelley
6b1c464d6d Don't reset packet length on transmission, in case of retransmission. 2016-07-22 20:59:16 +01:00
Simon Kelley
fa78573778 Zero packet buffers before building output, to reduce risk of information leakage. 2016-07-22 20:56:01 +01:00
Simon Kelley
cd2ddb9904 Debian systemd bugfix. 2016-07-16 22:23:49 +01:00
Simon Kelley
9bb3998da4 Merge 2.76-1.2 Debian NMU. 2016-07-16 22:06:01 +01:00
Simon Kelley
d6dce53e08 malloc(); memset() -> calloc() for efficiency. 2016-07-11 21:34:31 +01:00
Kevin Darbyshire-Bryant
06093a9a84 Fix problem with --dnssec-timestamp
whereby receipt of SIGHUP would erroneously engage timestamp checking.
2016-07-11 21:03:27 +01:00
Ivan Kokshaysky
1d07667ac7 Fix logic error in Linux netlink code.
This could cause dnsmasq to enter a tight loop on systems
with a very large number of network interfaces.
2016-07-11 18:36:05 +01:00
Simon Kelley
591ed1e905 Fix bad behaviour with some DHCP option arrangements.
The check that there's enough space to store the DHCP agent-id
at the end of the packet could succeed when it should fail
if the END option is in either of the oprion-overload areas.
That could overwrite legit options in the request and cause
bad behaviour. It's highly unlikely that any sane DHCP client
would trigger this bug, and it's never been seen, but this
fixes the problem.

Also fix off-by-one in bounds checking of option processing.
Worst case scenario on that is a read one byte beyond the
end off a buffer with a crafted packet, and maybe therefore
a SIGV crash if the memory after the buffer is not mapped.

Thanks to Timothy Becker for spotting these.
2016-07-11 18:18:42 +01:00
Kristjan Onu
907efeb2dc Manpage typo. 2016-07-10 22:37:57 +01:00
Simon Kelley
beea62cb66 Update .gitignore for change contrib/wrt -> contrib/lease-tools. 2016-07-10 22:13:57 +01:00
Simon Kelley
5874f3e922 Fix editing error on man page.
Thanks to Eric Westbrook for spotting this.
2016-07-10 22:12:08 +01:00
zeha@debian.org
04cb536f16 Merge 2.67-1.1 Debian NMU. 2016-07-06 22:30:10 +01:00
Simon Kelley
8ee8524016 Bump Debian version. 2016-07-06 22:23:22 +01:00
Simon Kelley
ce7845bf54 Check return of expand() always. 2016-07-06 21:42:27 +01:00
Simon Kelley
d55f81f5fd Zero newly malloc'ed memory. 2016-07-06 21:33:56 +01:00
Simon Kelley
294d36df47 Calculate length of TFTP error reply correctly. 2016-07-06 21:30:25 +01:00
Simon Kelley
f186bdcbc7 Fix debian changelog. 2016-05-18 15:51:54 +01:00
Jan Psota
ed1bd54b5c Update Polish translation.
Thanks to Jan Psota.
2016-05-18 15:16:29 +01:00
Simon Kelley
da2cad4b14 Doc about --pxe-service basename change into CHANGELOG. 2016-05-18 15:14:08 +01:00
Simon Kelley
0a4a04969d Final PXE tweak, and release-note to reflect changes. 2016-05-15 20:13:45 +01:00
Sergey Nechaev
45cb8dd9be Stricter command line args validation to dhcp_release6. 2016-05-14 21:36:15 +01:00
Simon Kelley
88b09aaddc Merge messages into translation files. 2016-05-14 20:56:02 +01:00
Simon Kelley
fe71bba356 Tweak UEFI workaround code. 2016-05-14 20:50:45 +01:00
Simon Kelley
cbc100fc81 Tweak CSAs affected by UEFI PXE workaround code. 2016-05-11 22:17:18 +01:00
Simon Kelley
68bea10bbf Fix error in PXE arch names and add ARM32 and ARM64. 2016-05-11 22:15:06 +01:00
Simon Kelley
8628cd603f Workaround for UEFI PXE boot problems. 2016-05-10 17:31:48 +01:00
Neil Jerram
ff325644c7 Fix for DHCP in transmission interface when --bridge-interface in use.
From f3d832b41f44c856003517c583fbd7af4dca722c Mon Sep 17 00:00:00 2001
From: Neil Jerram <Neil.Jerram@metaswitch.com>
Date: Fri, 8 Apr 2016 19:23:47 +0100
Subject: [PATCH] Fix DHCPv4 reply via --bridge-interface alias interface

Sending a DHCPv4 reply through a --bridge-interface alias interface
was inadvertently broken by

  commit 65c7212000
  Author: Lung-Pin Chang <changlp@cs.nctu.edu.tw>
  Date:   Thu Mar 19 23:22:21 2015 +0000

      dhcp: set outbound interface via cmsg in unicast reply

        If multiple routes to the same network exist, Linux blindly picks
        the first interface (route) based on destination address, which might not be
        the one we're actually offering leases. Rather than relying on this,
        always set the interface for outgoing unicast DHCP packets.

because in the aliasing case, iface_index is changed from the index of
the interface on which the packet was received, to be the interface
index of the 'bridge' interface (where the DHCP context is expected to
be defined, and so needs to be looked up).

For the cmsg code that the cited commit added, we need the original
iface_index; so this commit saves that off before the aliasing code
can change it, as rcvd_iface_index, and then uses rcvd_iface_index
instead of iface_index for the cmsg code.
2016-05-03 22:49:46 +01:00
Simon Kelley
b97026035e Limit number of upstream nameservers when logging configuration. 2016-05-03 22:34:06 +01:00
Simon Kelley
69cbf78bb6 Add contrib/lease-tools/dhcp_release6 2016-05-03 21:33:38 +01:00
Simon Kelley
c6cdf6bbee Move dhcp_release and dhcp_lease_time to contrib/lease_tools. 2016-05-03 21:14:14 +01:00
Simon Kelley
09217a1a87 Add --help to manpage . 2016-05-03 17:04:35 +01:00
Simon Kelley
332c41e2ff Debian init.d script fix. 2016-05-01 22:36:46 +01:00
Simon Kelley
2c0c36f54b Fix problem with IPv6 in new ARP-search code. 2016-05-01 20:57:08 +01:00
Simon Kelley
d6b749af91 Fix typo in SDBM hash function.
Thanks to Luis Carvalho for spotting the error.
2016-04-25 17:05:15 +01:00
Simon Kelley
14ffa0770b Fix init of per server EDNS UDP packet size. 2016-04-25 16:36:44 +01:00
Simon Kelley
87985855ad Remove pre-existing EDNS0_OPTION_NOMDEVICEID if MAC address unknown. 2016-04-25 15:33:30 +01:00
Simon Kelley
a2bc254bed Check return-code of inet_pton when parsing DHCPv4 options. 2016-04-21 22:41:31 +01:00
Simon Kelley
a7b27e84fa NULL pointer check. 2016-03-16 19:11:52 +00:00
Simon Kelley
529b030228 Tidy code. 2016-03-16 19:00:45 +00:00
Simon Kelley
4caa86dd7d Tidy. 2016-03-16 18:44:16 +00:00
Simon Kelley
e1abeeeec2 Fix memory leak in inotify code. 2016-03-16 18:12:35 +00:00
Simon Kelley
40205a053e Bound hash-iterations in DNSSEC NSEC3 checking. 2016-03-14 21:24:00 +00:00
Simon Kelley
b8ac466209 Tidy code. 2016-03-10 18:40:53 +00:00
Simon Kelley
d1377fa3c4 Account for TFTP packet headers in IPv6 correctly. 2016-03-04 21:32:21 +00:00
Simon Kelley
fa79466c2a Tighten syntax checking for dhcp-range and clarify man page. 2016-03-03 20:33:54 +00:00
Simon Kelley
a93bd4b016 Fix broken DNSMASQ_USER<x> envvars in script with more than one class. 2016-03-01 18:58:01 +00:00
Simon Kelley
407a1f3e95 Tidy parsing code. 2016-03-01 17:06:07 +00:00
Simon Kelley
4b6af5d53f Fix pointer declaration botch. 2016-03-01 17:00:26 +00:00
Simon Kelley
7aa3f9af66 format fix. 2016-03-01 16:32:30 +00:00
Simon Kelley
f7cf749943 Check return code from open() 2016-03-01 16:19:23 +00:00
Simon Kelley
aa300f7167 Fix typo in last commit. 2016-03-01 15:19:13 +00:00
Simon Kelley
c7f3bd2ac8 Replace incoming EDNS0_OPTION_NOMDEVICEID and EDNS0_OPTION_NOMCPEID options. 2016-02-28 21:48:34 +00:00
Simon Kelley
22fe2fd038 Fix --add-subnet when returning empty or default subnet. 2016-02-28 17:07:10 +00:00
Simon Kelley
7480aeffc8 Apply ceiling of lease length to TTL when --dhcp-ttl in use. 2016-02-26 21:58:20 +00:00
Simon Kelley
bec366b404 Add --tftp-mtu option. 2016-02-24 22:03:26 +00:00
Simon Kelley
e06e6e34bf Update CHANGELOG. 2016-02-24 21:26:16 +00:00
Simon Kelley
832e47beab Add --dhcp-ttl option. 2016-02-24 21:24:45 +00:00
Simon Kelley
df3d54f776 Add TTL parameter to --host-record and --cname. 2016-02-24 21:03:38 +00:00
Simon Kelley
22c0f4fe87 Fix previous commit. 2016-02-17 22:12:31 +00:00
Simon Kelley
9e4cf47ee8 Add --add-mac=text option. 2016-02-17 20:26:32 +00:00
Simon Kelley
fdc97e1383 Avoid divide-by-zero when dhcp-range is a whole /64 2016-02-13 17:47:17 +00:00
S L
a18bf3149a Avoid losing timer when deleting a RA context. 2016-02-12 17:36:20 +00:00
Simon Kelley
1566bacb2c Fix breakage in ARP code when IPV6 support not compiled in. 2016-02-05 14:48:25 +00:00
Simon Kelley
e6e751b066 Make names of ARP script actions consistent. 2016-02-01 17:59:07 +00:00
Andy Stormont
8de875f0fb Fix FTBFS on illumos 2016-02-01 12:07:57 +00:00
Chris Novakovic
4ace25c5d6 Treat REFUSED (not SERVFAIL) as an unsuccessful upstream response
Commit 51967f9807 began treating SERVFAIL
as a successful response from an upstream server (thus ignoring future
responses to the query from other upstream servers), but a typo in that
commit means that REFUSED responses are accidentally being treated as
successful instead of SERVFAIL responses.

This commit corrects this typo and provides the behaviour intended by
commit 51967f9: SERVFAIL responses are considered successful (and will
be sent back to the requester), while REFUSED responses are considered
unsuccessful (and dnsmasq will wait for responses from other upstream
servers that haven't responded yet).
2016-01-25 21:54:35 +00:00
Simon Kelley
1e5051228d Final form of configuration for EDNS0 MAC-address code. 2016-01-25 21:29:23 +00:00
Hans Dedecker
926332a764 Add --max-port config option. 2016-01-23 10:48:12 +00:00
Simon Kelley
d05dd58de1 Fix wrong reply to simple name when --domain-needed set and no servers configured.
Also return REFUSED and not SERVFAIL when out of memory.

Thanks to Allain Legacy for problem report.
2016-01-19 21:23:30 +00:00
Simon Kelley
f7443d76f7 Fix problems in last commit when DNSSEC not enabled. 2016-01-19 20:29:57 +00:00
Simon Kelley
f344dbc622 Complete DNSSEC server-selection code and set conntrack on DNSSEC queries. 2016-01-18 18:11:54 +00:00
Simon Kelley
f4d0c660ca Fix sporadic crash in find_mac() - hwlen must be zero for empty entries. 2016-01-18 12:51:08 +00:00
Simon Kelley
1801a29226 Fix botch in forward.c flags code.
Thanks to Matthias Anfree for spotting this.
2016-01-17 21:53:57 +00:00
Simon Kelley
92be34a407 Complete work to allow DNSSEC validation with private DNS servers. 2016-01-16 18:39:54 +00:00
Simon Kelley
bb58f63ce5 arp.c tidy up. 2016-01-14 19:23:10 +00:00
Simon Kelley
367341f745 Disable DNSSEC for server=/domain/.. servers unless trust-anchor provided. 2016-01-12 15:58:23 +00:00
André Glüpker
eddf365284 Fix bad cache-size calculation when hosts-file read fails. 2016-01-12 12:54:17 +00:00
Simon Kelley
a63b8b89e6 DNSSEC: Handle non-root trust anchors, and check we have a root trust anchor. 2016-01-12 11:28:58 +00:00
Simon Kelley
5757371d43 Inhibit DNSSEC validation when forwarding to private servers for a domain.
server=/example.com/<ip-of-server>

The rationale is that the chain-of-trust will not be complete to
private servers. If it was, it would not be necessary to access the
server direct.
2016-01-11 22:50:00 +00:00
Simon Kelley
b633de9413 Fix FTBFS when scripts excluded at compilation time. 2016-01-06 22:51:17 +00:00
Simon Kelley
c49778df4a Update copyright notices. Happy new year! 2016-01-06 18:52:33 +00:00
Simon Kelley
53a9173fc0 Handle building with script support enabled and DHCP disabled. 2016-01-06 17:59:13 +00:00
Simon Kelley
d917275e48 Fix botch in new arp-cache linked-list code resulting in 100% CPU spin. 2016-01-04 17:17:41 +00:00
Simon Kelley
cc7cb0b893 Fix datatype-sixe botch which broke DNSSEC sig timestamps when far in the future. 2016-01-04 16:04:51 +00:00
Simon Kelley
ec0628c4b2 Trivial code tweak. 2015-12-31 20:55:39 +00:00
Simon Kelley
97b1d25764 Correct logic for when to start helper. 2015-12-31 18:52:38 +00:00
Simon Kelley
33702ab1f8 First complete version of DNS-client-id EDNS0 and ARP tracking code. 2015-12-28 23:17:15 +00:00
Simon Kelley
11867dc28c Cache access to the kernel's ARP table. 2015-12-23 16:15:58 +00:00
Simon Kelley
d3a8b39c7d More EDNS0 packet-size tweaks. 2015-12-23 12:27:37 +00:00
Simon Kelley
15379ea1f2 Log signature algo with DNSKEY and DS, also digest with DS. 2015-12-21 18:31:55 +00:00
Simon Kelley
efef497b89 Fix build failure when DNSSEC code omitted. 2015-12-21 17:30:44 +00:00
Simon Kelley
5aa5f0ff2f Truncate DNS replies >512 bytes that the client isn't expecting. 2015-12-21 17:20:35 +00:00
Simon Kelley
5bb88f0963 Handle extending EDNS0 OPT RR. 2015-12-21 16:23:47 +00:00
Simon Kelley
1d03016bbc Split EDNS0 stuff into its own source file. 2015-12-21 14:17:06 +00:00
Simon Kelley
ce5732e84f NSEC3 check: RFC5155 para 8.2 2015-12-20 21:39:19 +00:00
Simon Kelley
a86fdf437e Minor tweak to previous commit. 2015-12-20 21:19:20 +00:00
Simon Kelley
3e86d316c4 Nasty, rare and obscure off-by-one in DNSSEC hostname_cmp(). 2015-12-20 20:50:05 +00:00
Simon Kelley
d67ecac59d More tweaks in handling unknown DNSSEC algorithms. 2015-12-20 20:44:23 +00:00
Simon Kelley
fa14bec83b Major tidy up of EDNS0 handling and computation/use of udp packet size. 2015-12-20 17:12:16 +00:00
Simon Kelley
14a4ae883d Do a better job of determining which DNSSEC sig algos are supported. 2015-12-17 17:29:57 +00:00
Simon Kelley
3b799c826d Fix brace botch in dnssec_validate_ds()
Thanks to Michał Kępień for spotting this.
2015-12-17 16:58:04 +00:00
Simon Kelley
b40f26c019 Tidy up DNSSEC non-existence code. Check zone status is NSEC proof bad. 2015-12-17 11:57:26 +00:00
Simon Kelley
dd4ad9ac7e Tweaks to EDNS0 handling in DNS replies. 2015-12-17 10:44:58 +00:00
Simon Kelley
2dbba34b2c DNSSEC validation tweak.
A zone which has at least one key with an algorithm we don't
support should be considered as insecure.
2015-12-16 13:41:58 +00:00
Simon Kelley
c2bcd1e183 Generalise RR-filtering code, for use with EDNS0. 2015-12-15 17:25:21 +00:00
Simon Kelley
d64c81fff7 Move code which caches DS records to a more logical place. 2015-12-15 16:11:06 +00:00
Simon Kelley
93be5b1e02 Abandon caching RRSIGs and returning them from cache.
The list of exceptions to being able to locally answer
cached data for validated records when DNSSEC data is requested
was getting too long, so don't ever do that. This means
that the cache no longer has to hold RRSIGS and allows
us to lose lots of code. Note that cached validated
answers are still returned as long as do=0
2015-12-15 12:04:40 +00:00
Simon Kelley
9a31b68b59 Major rationalisation of DNSSEC validation.
Much gnarly special-case code removed and replaced with correct
general implementaion. Checking of zone-status moved to DNSSEC code,
where it should be, vastly simplifying query-forwarding code.
2015-12-15 10:20:39 +00:00
Simon Kelley
0007ee9064 Fix crash at start up with conf-dir=/path,*
Thanks to Brian Carpenter and American Fuzzy Lop for finding the bug.
2015-11-21 21:47:41 +00:00
Simon Kelley
67ab3285b5 Handle unknown DS hash algos correctly.
When we can validate a DS RRset, but don't speak the hash algo it
contains, treat that the same as an NSEC/3 proving that the DS
doesn't exist. 4025 5.2
2015-11-20 23:20:47 +00:00
Edwin Török
41a8d9e99b Fix crash when empty address from DNS overlays A record from hosts. 2015-11-14 17:55:41 +00:00
Simon Kelley
90477fb794 Update list of subnet for --bogus-priv
RFC6303 specifies & recommends following zones not be forwarded
to globally facing servers.
+------------------------------+-----------------------+
| Zone                         | Description           |
+------------------------------+-----------------------+
| 0.IN-ADDR.ARPA               | IPv4 "THIS" NETWORK   |
| 127.IN-ADDR.ARPA             | IPv4 Loopback NETWORK |
| 254.169.IN-ADDR.ARPA         | IPv4 LINK LOCAL       |
| 2.0.192.IN-ADDR.ARPA         | IPv4 TEST-NET-1       |
| 100.51.198.IN-ADDR.ARPA      | IPv4 TEST-NET-2       |
| 113.0.203.IN-ADDR.ARPA       | IPv4 TEST-NET-3       |
| 255.255.255.255.IN-ADDR.ARPA | IPv4 BROADCAST        |
+------------------------------+-----------------------+

Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
2015-10-20 21:21:32 +01:00
Simon Kelley
98079ea898 Catch errors from sendmsg in DHCP code.
Logs, eg,  iptables DROPS of dest 255.255.255.255
2015-10-13 20:32:21 +01:00
Simon Kelley
4790115455 Use /run/dnsmasq instead of /var/run/dnsmasq in Debian package. 2015-09-29 22:54:41 +01:00
Simon Kelley
27b78d990b Rationalise 5e3e464ac4 2015-09-26 21:40:45 +01:00
Simon Kelley
77607cbea0 Respect the --no-resolv flag in inotify code. 2015-09-10 23:08:43 +01:00
Simon Kelley
102208df69 DHCPv6 option 56 does not hold an address list. (RFC 5908). 2015-09-10 21:50:00 +01:00
Simon Kelley
6de81f1250 Handle signed dangling CNAME replies to DS queries. 2015-09-09 22:51:13 +01:00
Simon Kelley
20fd11e11a Clarify man page on RDNSS set in router advertisement. 2015-08-26 22:48:13 +01:00
Simon Kelley
9cdcfe9f19 Suggest solution to ENOMEM error with IPv6 multicast. 2015-08-26 22:38:08 +01:00
Simon Kelley
5e3e464ac4 Fix behaviour of empty dhcp-option=option6:dns-server, which should inhibit sending option. 2015-08-25 23:08:39 +01:00
Simon Kelley
3a3965ac21 Don't answer non-auth queries for auth zones locally when --localise-queries set. 2015-08-09 17:45:06 +01:00
Ed Bardsley
a7369bef8a Enhance --add-subnet to allow arbitary subnet addresses. 2015-08-05 21:17:18 +01:00
Simon Kelley
d2aa7dfbb6 Include 0.0.0.0/8 in DNS rebind checks. 2015-08-03 21:52:12 +01:00
Simon Kelley
63ec5d1264 Fix new poll() code for helper pipe. Removed CPU-spin. 2015-07-30 20:59:07 +01:00
Simon Kelley
f6381cf482 Declare utime(). 2015-07-27 19:48:43 +01:00
Kevin Darbyshire-Bryant
34b5d19488 Update DNSSEC timestamp file on process TERM. 2015-07-27 19:34:23 +01:00
Conrad Kostecki
d6cb7e4815 Update german translation 2015-07-27 19:22:49 +01:00
Simon Kelley
d389e0191b DNSSEC fix: correct logic for signed records in unsigned DNS space. 2015-07-27 18:56:43 +01:00
Simon Kelley
d3699bb6bc Small tweak to DNSSEC fix. 2015-07-16 22:37:37 +01:00
Simon Kelley
13480e8c2a DNSSEC fix, signed wildcard CNAME to unsigned domain. 2015-07-16 22:23:13 +01:00
Jan Psota
5b3b93f80a Update Polish translation. 2015-07-15 19:57:47 +01:00
Simon Kelley
b69e845b1c Close Lauchpad bug in Debian changelog. 2015-07-15 19:54:50 +01:00
Simon Kelley
90c3822bfa Grow pollfds array exponentially. 2015-07-13 12:47:52 +01:00
Simon Kelley
c895a0626d Merge messages for translations. 2015-07-12 21:27:40 +01:00
Simon Kelley
b842bc97bb Use poll() instead of select() to remove limits on open file descriptors. 2015-07-12 21:09:11 +01:00
Simon Kelley
0f38fa05a6 Log message typo. 2015-07-08 22:42:14 +01:00
Simon Kelley
45c5cb1f8f Fix compilation warning. 2015-07-08 22:40:57 +01:00
Simon Kelley
f6d6956261 Test for overflowing platform FD_SET size. 2015-07-08 22:38:13 +01:00
Simon Kelley
60176c7bf4 Bump version in Debian changelog. 2015-07-07 21:54:55 +01:00
Simon Kelley
362c9303da Fix inotify code to handle dangling symlinks better. 2015-07-06 21:48:49 +01:00
Simon Kelley
5e95a552ee Avoid hanngs in DHCP ping code when system time goes backwards. 2015-07-05 22:31:30 +01:00
Simon Kelley
90cb222551 --conf-file should read no file, not try and read the default file. 2015-07-05 21:59:10 +01:00
Ján Sáreník
850163288d Manpage typo fix. 2015-07-05 21:23:27 +01:00
Simon Kelley
e3ec6f0bd7 Handle CNAMEs to DS records when confirming absence of DS for DNSSEC. 2015-06-12 21:39:11 +01:00
Simon Kelley
f7bfbdc872 Merge messages and fix makefile process to do this. 2015-06-10 22:31:02 +01:00
Neil Jerram
4918bd5505 Documenation updates for --bridge-interface and "off-link". 2015-06-10 22:23:20 +01:00
Neil Jerram
9bad339af8 Apply --bridge-interfaces to unsolicited router advertisements. 2015-06-10 22:16:35 +01:00
Neil Jerram
ba4fc0f996 Upply --bridge-interface aliasing to solicited router advertisements. 2015-06-10 22:14:49 +01:00
Neil Jerram
2fd5bc952d Allow router advertisements to have the "off-link" bit set. 2015-06-10 22:13:06 +01:00
Neil Jerram
0ddb8769bb Extend --bridge-interface aliasing to DHCPv6. 2015-06-10 22:11:06 +01:00
Neil Jerram
654f59e762 Fix logging of unknown interface in --bridge-interface, DHPCv4. 2015-06-10 22:06:33 +01:00
Simon Kelley
d91b1fd402 Add a couple of missed logging strings to the catalogue. 2015-06-09 20:45:07 +01:00
Nicolas Cavallari
c6d82c9ba6 Add Dbus methods to create and delete DHCP leases. 2015-06-09 20:42:20 +01:00
Simon Kelley
4d25cf89d5 Handle corner cases in NSEC coverage checks. 2015-06-06 23:13:57 +01:00
Simon Kelley
24e9207e13 More reproducibility fixes for Debian package. 2015-06-04 22:32:43 +01:00
Simon Kelley
89130d91d6 DHCPv6: DHCPCONFIRM should be OK for any address on link, not just dynamic addresses. 2015-06-03 22:34:14 +01:00
Simon Kelley
d644b2a17d Close Debian bug for bug fixed upstream. 2015-06-01 21:00:16 +01:00
swigger
bd7bfa21c4 Correctly sanitise DNS header bits in answer when recreating query for retry. 2015-06-01 20:54:59 +01:00
Simon Kelley
403de05925 Merge branch 'master' of ssh://thekelleys.org.uk/var/cache/git/dnsmasq 2015-05-26 22:12:01 +01:00
John Hanks
46c89f2bd0 Add infiniband to example config file. 2015-05-26 22:07:57 +01:00
Christian Demsar
23facf0d77 Man page typo. 2015-05-20 20:26:23 +01:00
Simon Kelley
549b1a478c Tweak immediately previous patch. 2015-05-20 20:20:24 +01:00
Simon Kelley
7f8565b94c Select correct DHCP context when in PXE bootserver mode. 2015-05-19 23:01:27 +01:00
Simon Kelley
06568c6636 Remove support for DNS Extended Label Types.
The support was only partial, and the whole concept is
now deprecated in the standards.
2015-05-15 20:43:48 +01:00
Simon Kelley
5d07d77e75 Fix buffer overflow introduced in 2.73rc6.
Fix off-by-one in code which checks for over-long domain names
in received DNS packets. This enables buffer overflow attacks
which can certainly crash dnsmasq and may allow for arbitrary
code execution. The problem was introduced in commit b8f16556d,
release 2.73rc6, so has not escaped into any stable release.
Note that the off-by-one was in the label length determination,
so the buffer can be overflowed by as many bytes as there are
labels in the name - ie, many.

Thanks to Ron Bowes, who used lcmatuf's afl-fuzz tool to find
the problem.
2015-05-15 18:13:06 +01:00
Simon Kelley
62018e1f72 Use correct DHCP context for PXE-proxy server-id. 2015-05-14 21:30:00 +01:00
Simon Kelley
7c0f2543a7 Tweak last commit. 2015-05-14 21:16:18 +01:00
Simon Kelley
ca85a28241 Allow T1 and T2 DHCPv4 options to be set. 2015-05-13 22:33:04 +01:00
Simon Kelley
585840b033 Pointer to mail-archive mailing list mirror in doc.html. 2015-05-13 12:35:57 +01:00
Simon Kelley
dec180ac00 Tweak Debian systemd unit file. 2015-05-13 12:16:13 +01:00
Simon Kelley
86fa104692 Tweak EDNS timeout code. 2015-05-10 14:04:06 +01:00
Simon Kelley
b059c96dc6 Check IPv4-mapped IPv6 addresses with --stop-rebind. 2015-05-08 20:25:51 +01:00
Simon Kelley
a77cec8d58 Handle UDP packet loss when fragmentation of large packets is broken. 2015-05-08 16:25:38 +01:00
Nicolas Cavallari
64bcff1c7c Constify some DHCP lease management functions. 2015-04-28 21:55:18 +01:00
Simon Kelley
2ed162ac20 Don't remove RRSIG RR from answers to ANY queries when the do bit is not set. 2015-04-28 21:26:35 +01:00
Simon Kelley
e66b4dff3c Fix argument-order botch which broke DNSSEC for TCP queries. 2015-04-28 20:45:57 +01:00
Johnny S. Lee
8efd731cc4 Make get-version work when repo is a git submodule. 2015-04-26 22:23:57 +01:00
Simon Kelley
a5ae1f8587 Logs in DHCPv6 not suppressed by dhcp6-quiet. 2015-04-25 21:46:10 +01:00
Simon Kelley
b8f16556d3 Tweaks to previous, DNS label charset commit. 2015-04-22 21:14:31 +01:00
Simon Kelley
cbe379ad6b Handle domain names with '.' or /000 within labels.
Only in DNSSEC mode, where we might need to validate or store
such names. In none-DNSSEC mode, simply don't cache these, as before.
2015-04-21 22:57:06 +01:00
Simon Kelley
338b340be9 Revert 61b838dd57 and just quieten log instead. 2015-04-20 21:34:05 +01:00
Moshe Levi
a006eb7e14 Check IP address command line arg in dhcp_release.c 2015-04-19 22:10:40 +01:00
Simon Kelley
554b580e97 Log domain when reporting DNSSEC validation failure. 2015-04-17 22:50:20 +01:00
Simon Kelley
0df29f5e23 Note CVE-2015-3294 2015-04-16 15:24:52 +01:00
Stefan Tomanek
b4c0f092d8 Fix (srk induced) crash in new tftp_no_fail code. 2015-04-16 15:20:59 +01:00
Simon Kelley
78c6184752 Auth: correct replies to NS and SOA in .arpa zones. 2015-04-16 15:05:30 +01:00
Simon Kelley
38440b204d Fix crash in auth code with odd configuration. 2015-04-12 21:52:47 +01:00
Simon Kelley
ad4a8ff7d9 Fix crash on receipt of certain malformed DNS requests. 2015-04-09 21:48:00 +01:00
Simon Kelley
04b0ac0537 Fix crash caused by looking up servers.bind when many servers defined. 2015-04-06 17:19:13 +01:00
Simon Kelley
982faf4024 Fix compiler warning when not including DNSSEC. 2015-04-03 21:42:30 +01:00
Simon Kelley
fe3992f9fa Return INSECURE, rather than BOGUS when DS proved not to exist.
Return INSECURE when validating DNS replies which have RRSIGs, but
when a needed DS record in the trust chain is proved not to exist.
It's allowed for a zone to set up DNSKEY and RRSIG records first, then
add a DS later, completing the chain of trust.

Also, since we don't have the infrastructure to track that these
non-validated replies have RRSIGS, don't cache them, so we don't
provide answers with missing RRSIGS from the cache.
2015-04-03 21:25:05 +01:00
Stefan Tomanek
7aa970e2c7 Whitespace fixes. 2015-04-01 17:55:07 +01:00
Stefan Tomanek
30d0879ed5 add --tftp-no-fail to ignore missing tftp root 2015-03-31 22:32:11 +01:00
Simon Kelley
fd6ad9e481 Merge message translations. 2015-03-30 07:52:21 +01:00
Simon Kelley
794fccca7f Fix crash in last commit. 2015-03-29 22:35:44 +01:00
Simon Kelley
394ff492da Allow control characters in names in the cache, handle when logging. 2015-03-29 22:17:14 +01:00
Simon Kelley
1e153945de DNSSEC fix for non-ascii characters in labels. 2015-03-28 21:34:07 +00:00
Simon Kelley
0b8a5a30a7 Protect against broken DNSSEC upstreams. 2015-03-27 11:44:55 +00:00
Simon Kelley
150162bc37 Return SERVFAIL when validation abandoned. 2015-03-27 09:58:26 +00:00
Simon Kelley
8805283088 Don't fail DNSSEC when a signed CNAME dangles into an unsigned zone. 2015-03-26 21:15:43 +00:00
Lung-Pin Chang
65c7212000 dhcp: set outbound interface via cmsg in unicast reply
If multiple routes to the same network exist, Linux blindly picks
  the first interface (route) based on destination address, which might not be
  the one we're actually offering leases. Rather than relying on this,
  always set the interface for outgoing unicast DHCP packets.
2015-03-19 23:22:21 +00:00
Simon Kelley
979fe86bc8 Make --address=/example.com/ equivalent to --server=/example.com/ 2015-03-19 22:50:22 +00:00
Simon Kelley
ff841ebf5a Fix boilerplate code for re-running system calls on EINTR and EAGAIN etc.
The nasty code with static variable in retry_send() which
avoids looping forever needs to be called on success of the syscall,
to reset the static variable.
2015-03-11 21:36:30 +00:00
Simon Kelley
360f2513ab Tweak DNSSEC timestamp code to create file later, removing need to chown it. 2015-03-07 18:28:06 +00:00
Simon Kelley
4c960fa90a New version of contrib/reverse-dns 2015-03-04 20:32:26 +00:00
Simon Kelley
9003b50b13 Fix last commit to not crash if uid changing not configured. 2015-03-02 22:47:23 +00:00
Simon Kelley
f6e62e2af9 Add --dnssec-timestamp option and facility. 2015-03-01 18:17:54 +00:00
Joachim Zobel
47b9ac59c7 Log parsing utils in contrib/reverse-dns 2015-02-23 21:38:11 +00:00
Tomas Hozza
0705a7e2d5 Fix uninitialized value used in get_client_mac() 2015-02-23 21:26:26 +00:00
Chen Wei
28b879ac47 Fix trivial memory leaks to quieten valgrind. 2015-02-17 22:07:35 +00:00
Simon Kelley
caeea190f1 Make dynamic hosts files work when --no-hosts set. 2015-02-14 20:08:56 +00:00
Simon Kelley
8ff70de618 Typos. 2015-02-14 20:02:37 +00:00
Simon Kelley
ee4d1cea92 Debian systemd fixes. 2015-02-12 18:30:32 +00:00
Shantanu Gadgil
f4f400776b Fix get-version script which returned wrong tag in some situations. 2015-02-11 20:16:59 +00:00
Chris Lamb
b467a454b4 Make Debian build reproducible. 2015-02-09 11:52:30 +00:00
Simon Kelley
efb8b5566a man page typo. 2015-02-07 22:36:34 +00:00
Simon Kelley
f9c863708c Extra logging for inotify code. 2015-02-03 21:52:48 +00:00
Simon Kelley
2941d3ac89 Fixup dhcp-configs after reading extra hostfiles with inotify. 2015-02-02 22:36:42 +00:00
Thiébaud Weksteen
d36b732c4c Manpage typo fix. 2015-02-02 21:38:27 +00:00
Simon Kelley
d2c5458e31 Debian changelog bugfix. 2015-02-02 21:27:39 +00:00
Simon Kelley
8d8a54ec79 Fix build failure on openBSD. 2015-02-01 21:48:46 +00:00
Simon Kelley
1062667618 BSD make support 2015-02-01 00:15:16 +00:00
Simon Kelley
6ef15b34ca Fix broken ECDSA DNSSEC signatures. 2015-01-31 22:44:26 +00:00
Simon Kelley
3d04f46334 inotify documentation updates. 2015-01-31 21:59:13 +00:00
Simon Kelley
aff3396280 Update copyrights for dawn of 2015. 2015-01-31 20:13:40 +00:00
Simon Kelley
70d1873dd9 Expand inotify code to dhcp-hostsdir, dhcp-optsdir and hostsdir. 2015-01-31 19:59:29 +00:00
Simon Kelley
0491805d2f Allow inotify to be disabled at compile time on Linux. 2015-01-26 11:23:43 +00:00
Win King Wan
61b838dd57 Don't reply to DHCPv6 SOLICIT messages when not configured for statefull DHCPv6. 2015-01-21 20:41:48 +00:00
Conrad Kostecki
fbf01f7046 Update German translation. 2015-01-20 21:07:56 +00:00
Simon Kelley
5f4dc5c6ca Add --dhcp-hostsdir config option. 2015-01-20 20:51:02 +00:00
Simon Kelley
2ae195f5a7 Don't treat SERVFAIL as a recoverable error..... 2015-01-18 22:20:48 +00:00
Simon Kelley
393415597c Cope with multiple interfaces with the same LL address. 2015-01-18 22:11:10 +00:00
Simon Kelley
ae4624bf46 Logs for DS records consistent. 2015-01-12 23:22:08 +00:00
Simon Kelley
5e321739db Don't answer from cache RRsets from wildcards, as we don't have NSECs. 2015-01-12 23:16:56 +00:00
Simon Kelley
9f79ee4ae3 Log port of requestor when doing extra logging. 2015-01-12 20:18:18 +00:00
RinSatsuki
28de38768e Add --min-cache-ttl option. 2015-01-10 15:22:21 +00:00
Simon Kelley
25cf5e373e Add --log-queries=extra option for more complete logging. 2015-01-09 15:53:03 +00:00
Simon Kelley
424c4a8a53 Merge branch 'unsigned' 2015-01-07 22:01:14 +00:00
Simon Kelley
97e618a0e3 DNSSEC: do top-down search for limit of secure delegation. 2015-01-07 21:55:43 +00:00
Yousong Zhou
d8dbd903d0 Fix race condition issue in makefile. 2015-01-05 17:03:35 +00:00
Yousong Zhou
81c538efce Implement makefile dependencies on COPTS variable. 2015-01-03 16:36:14 +00:00
Matthias Andree
d310ab7ecb Fix build failure in new inotify code on BSD. 2014-12-27 15:36:38 +00:00
Simon Kelley
0b1008d367 Bad packet protection. 2014-12-27 15:33:32 +00:00
Glen Huang
32fc6dbe03 Add --ignore-address option. 2014-12-27 15:28:12 +00:00
Simon Kelley
83d2ed09fc Initialise return value. 2014-12-23 18:42:38 +00:00
Simon Kelley
fbc5205702 Fix problems validating NSEC3 and wildcards. 2014-12-23 15:46:08 +00:00
Simon Kelley
cbc6524234 Make caching work for CNAMEs pointing to A/AAAA records shadowed in /etc/hosts
If the answer to an upstream query is a CNAME which points to an
A/AAAA record which also exists in /etc/hosts and friends, then
caching is suppressed, to avoid inconsistent answers. This is
now modified to allow caching when the upstream and local A/AAAA
records have the same value.
2014-12-21 21:21:53 +00:00
Simon Kelley
094b5c3d90 Fix crash in DNSSEC code when attempting to verify large RRs. 2014-12-21 16:11:52 +00:00
Simon Kelley
3267804598 Tweak field width in cache dump to avoid truncating IPv6 addresses. 2014-12-17 20:38:20 +00:00
Simon Kelley
476693678e Eliminate IPv6 privacy addresses from --interface-name answers. 2014-12-17 12:41:56 +00:00
Simon Kelley
bd9520b7ad Remove redundant IN6_IS_ADDR_ULA(a) macro defn. 2014-12-16 20:41:29 +00:00
Simon Kelley
3ad3f3bbd4 Fix breakage of --domain=<domain>,<subnet>,local 2014-12-16 18:25:17 +00:00
Simon Kelley
ad946d555d CHANGELOG re. inotify. 2014-12-15 17:52:22 +00:00
Simon Kelley
800c5cc1e7 Remove floor on EDNS0 packet size with DNSSEC. 2014-12-15 17:50:15 +00:00
Simon Kelley
857973e6f7 Teach the new inotify code about symlinks. 2014-12-15 15:58:13 +00:00
Simon Kelley
9c448c8018 Merge branch 'inotify' 2014-12-10 17:40:03 +00:00
Simon Kelley
193de4abf5 Use inotify instead of polling on Linux.
This should solve problems people are seeing when a file changes
twice within a second and thus is missed for polling.
2014-12-10 17:32:16 +00:00
Hans Dedecker
98906275a0 Fix conntrack with --bind-interfaces
Make sure dst_addr is assigned the correct address in receive_query when OPTNOWILD is
enabled so the assigned mark can be correctly retrieved and set in forward_query when
conntrack is enabled.

Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
2014-12-09 22:22:53 +00:00
Vladislav Grishenko
b9ff5c8f43 Improve RFC-compliance when unable to supply addresses in DHCPv6
While testing https://github.com/sbyx/odhcp6c client I have noticed it
permanently crashes after startup.

The reason was it (odhcp6c) doesn't expect empty IA options in ADVERTISE
message without any suboptions.

Despite this validation bug of odhcp6c, dnsmasq should not generate
ADVERTISE messages with IA if there's nothing to advert per  RFC 3315
17.2.2:

   If the server will not assign any addresses to any IAs in a

   subsequent Request from the client, the server MUST send an Advertise

   message to the client that includes only a Status Code option with

   code NoAddrsAvail and a status message for the user, a Server

   Identifier option with the server's DUID, and a Client Identifier

   option with the client's DUID.

Meanwhile it's need to add status code for every IA in REPLY message per
RFC3315 18.2.1:

   If the server cannot assign any addresses to an IA in the message
   from the client, the server MUST include the IA in the Reply message
   with no addresses in the IA and a Status Code option in the IA
   containing status code NoAddrsAvail.

So, I've changed the logic to skip IA completely from ADVERTISE messages and
to add NoAddrsAvail subcode into IA of REPLY messages.

As for overhead, yes, I believe it's ok to return NoAddrsAvail twice in IA
and in global section for compatibility with all old and new clients.
2014-10-06 14:34:24 +01:00
Tomas Hozza
3d9d2dd001 Fit example conf file typo. 2014-10-06 10:46:48 +01:00
Daniel Collins
17b475912f Fix typo in new Dbus code.
Simon's fault.
2014-10-03 21:58:43 +01:00
Karl Vogel
e9828b6f66 Set conntrack mark before connect() call.
SO_MARK has to be done before issuing the connect() call on the
TCP socket.
2014-10-03 21:45:15 +01:00
Simon Kelley
72eba2bffc Bump Debian version. 2014-10-03 08:50:37 +01:00
Simon Kelley
6ac3bc0452 Debian build fixes for kFreeBSD 2014-10-03 08:48:11 +01:00
Simon Kelley
00cd9d5519 crash at startup when an empty suffix is supplied to --conf-dir 2014-10-02 21:44:21 +01:00
Simon Kelley
f2658275b2 Add newline at the end of example config file. 2014-09-25 21:51:25 +01:00
Jan Psota
25e27235dd Update Polish translation. 2014-09-23 22:16:15 +01:00
Simon Kelley
bf2db4b084 Fix CHANGELOG entry under wrong version. 2014-09-18 22:10:46 +01:00
Simon Kelley
5782649ad9 Fix bug which caused dnsmasq to become unresponsive when an interface goes. 2014-09-18 22:08:58 +01:00
Simon Kelley
288df49c96 Fix bug when resulted in NXDOMAIN answers instead of NODATA.
check_for_local_domain() was broken due to new code matching F_*
bits in cache entries for DNSSEC. Because F_DNSKEY | F_DS is
used to match RRSIG entries, cache_find_by_name() insists on an exact match
of those bits. So adding F_DS to the bits that check_for_local_domain()
sends to cache_find_by_name() won't result in DS records as well
as the others, it results in only DS records. Add a new bit, F_NSIGMATCH
which suitably changes the behaviour of cache_find_by_name().
2014-09-18 21:55:27 +01:00
Richard Genoud
10cfc0ddb3 Fix length->netmask conversions to avoid undefined behaviour. 2014-09-17 21:17:39 +01:00
Richard Genoud
15b1b7e9c3 Fix endian bug in --local-service code. 2014-09-17 21:12:00 +01:00
Simon Kelley
00c0f69aa5 Debian bug closure. 2014-09-16 11:22:33 +01:00
Ilya Ponetaev
51943369e3 Supply "Success" status code in reply to DHCPDECLINE. 2014-09-13 21:19:01 +01:00
Ilya Ponetaev
2d75f2e4a5 Don't reply to DHCPCONFIRM messages with no addresses in them. 2014-09-13 21:11:16 +01:00
Ilya Ponetaev
976afc93e4 Set DHCPv6 message type when returning "use multicast". 2014-09-13 20:56:14 +01:00
Ilya Ponetaev
7f68f82146 DHCPv6 REBIND messages don't need a server-id. 2014-09-13 20:52:27 +01:00
Simon Kelley
85900a246c Revert route-information option in RA. There are problems with some clients.
http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2014q3/008796.html
2014-09-13 20:42:54 +01:00
Simon Kelley
b4f971a081 Update *.po files for new release. 2014-09-13 20:28:30 +01:00
Simon Kelley
3e1551a1de Extend --conf-dir to allow filtering on file suffixes. 2014-09-09 21:46:07 +01:00
Simon Kelley
af292dae6d Bump Debian standards version. 2014-09-09 16:01:49 +01:00
Simon Kelley
933878f2c8 Remove paypal links and icond refs from Debian package. 2014-09-09 15:59:32 +01:00
Simon Kelley
d54409dcd3 Fix debian changelog date snafu. 2014-09-09 14:06:13 +01:00
Ilya Ponetaev
5bf50af2d0 RFC4191 route information option. 2014-09-09 12:46:21 +01:00
Simon Kelley
c43b8a6326 Debian package: use dns-root-data. 2014-09-07 19:34:39 +01:00
Simon Danner
b06900d1a3 Mention name in systemd. 2014-08-18 22:19:50 +01:00
Simon Kelley
f2f02fc3fb Merge branch 'loop' 2014-08-12 18:41:24 +01:00
Simon Kelley
aaeea9f6ed GetLoopServers Dbus method. 2014-08-12 18:30:44 +01:00
Simon Kelley
2bb6f7735f Missed update of DHCP lease datastructure. 2014-08-06 10:16:32 +01:00
Simon Kelley
40766e55e8 Check all servers loopiness, when any subset is changed. 2014-07-29 16:52:00 +01:00
Simon Kelley
b5ea1cc255 Add --dns-loop-detect feature. 2014-07-29 16:34:14 +01:00
Simon Kelley
6d8e8ac0fa Tidy up previous commit. 2014-07-13 22:18:57 +01:00
Simon Kelley
24b167ada8 Fix logic for associating leases with interfaces.
This handles the case that more than one interface contains
the network the lease address is on, but the interfaces have different
prefix lengths. Use the longest prefix length.
2014-07-12 16:39:00 +01:00
Chen Yufei
993f8cbb1b Don't do IPSET on Apple. Needed header files are missing. 2014-07-08 22:40:03 +01:00
Simon Kelley
47a9516980 Use event system to re-send query on new route. Tidies module boundaries. 2014-07-08 22:22:02 +01:00
Lung-Pin Chang
dc8a1b1bcf Set interface with longest prefix in DHCP & DHCPv6 lease
- With nested prefixes reside on different interfaces of single host

  (e.g., in 6to4, 2002::/16 on WAN and 2002:<IPv4>:<subnet>::/64 on LAN),

  current matching mechanism might return the interface with shorter prefix

  length instead of the longer one, if it appears later in the netlink message.

Signed-off-by: Lung-Pin Chang <changlp@cs.nctu.edu.tw>
2014-07-06 21:08:47 +08:00
Simon Kelley
cdb755c5f1 Fix FTBFS with Nettle-3.0. 2014-06-18 20:52:53 +01:00
Simon Kelley
063efb330a Build config: add -DNO_GMP for use with nettle/mini-gmp 2014-06-17 19:49:31 +01:00
Neil Jerram
70772c9091 Allow wildcard aliases in --bridge-interface option
This is useful when using dnsmasq as DHCP server for a set of VMs
whose data is routed by the host instead of being bridged.  In this
scenario:

- There is an unbounded set of TAP interfaces that have no IP address
  at the host end.

- DHCP allocation is done from an IPv4 address range associated with a
  dummy interface.

- We run dnsmasq with --interface dummy --interface tap*
  --bind-dynamic, so that it listens on all the TAP interfaces, and
  --bridge-interface=dummy,tap*, so that it will allocate IP addresses
  via the TAP interfaces from the range associated with the dummy
  interface.
2014-06-11 21:22:40 +01:00
Simon Kelley
10d8540f62 Makefile typo. 2014-06-11 20:51:27 +01:00
Simon Kelley
006c162382 Fix bug when >1 IPv6 address supplied to Dbus SetServers method. 2014-06-08 21:51:29 +01:00
Simon Kelley
6799a46605 Attribution update. 2014-06-07 21:23:34 +01:00
Daniel Collins
c4638f9e66 New DBus methods. 2014-06-07 21:21:44 +01:00
Simon Kelley
4b34f5d22f Copyright update. 2014-06-07 20:05:08 +01:00
Simon Kelley
a0358e5ddb Handle async notification of address changes using the event system. 2014-06-07 13:38:48 +01:00
Simon Kelley
a03f8d4c37 Suppress re-entrant calls to dhcp_construct_contexts() 2014-06-05 22:38:53 +01:00
Simon Kelley
c4a0937683 ipsets equivalent in *BSD, using pf tables. 2014-06-02 20:30:07 +01:00
Simon Kelley
2f4c4b6076 LOG error of ARP-injection fails. 2014-05-23 20:44:59 +01:00
Simon Kelley
a008a843cf Bump Debian version. 2014-05-20 21:01:34 +01:00
Simon Kelley
d92c53e700 Debian: Dynamically create /var/run/dnsmasq when systemd in use too. 2014-05-20 21:00:02 +01:00
Simon Kelley
a754e1d7b2 Debian: Write pid-file in the correct place when using systemd. 2014-05-20 20:56:55 +01:00
Simon Kelley
8e9ffba66e Merge branch 'mobile-ra'
Conflicts:
	CHANGELOG
2014-05-20 20:38:25 +01:00
Simon Kelley
15a97ad6fb Use ECC crypto in Nettle now. 2014-05-20 20:34:41 +01:00
Simon Ruderich
91f4a5e4b5 Debian/rules fixes to enable hardening. 2014-05-20 20:34:00 +01:00
Simon Kelley
0fa7e62947 Bump Debian version. 2014-05-20 19:54:25 +01:00
Andreas Metzler
62f992f06c Debian fix: Enable dnsmasq systemd unit on install. 2014-05-11 17:53:54 +01:00
Simon Kelley
a23949d44d Debian change: write pid-file even using systemd. 2014-05-11 17:43:29 +01:00
Simon Kelley
b692f23466 Fix DNS failure of cachesize set to zero. 2014-05-09 10:29:43 +01:00
Simon Kelley
8aa999ef69 Debian packaging fixes. 2014-05-04 21:45:26 +01:00
Conrad Kostecki
20b215f293 Update German translation. 2014-05-04 20:43:49 +01:00
Simon Kelley
e6096e643a Another filter_rrsigs fix. 2014-05-01 18:19:12 +01:00
Simon Kelley
8938ae05ac Get packet size right when removing pseudoheader. 2014-05-01 17:46:25 +01:00
Simon Kelley
9d1b22aac2 Fix DNSSEC validation of ANY queries. 2014-04-29 13:02:41 +01:00
Simon Kelley
1fc02680af Do SERVFAIL, therefore continue when searching for DS in TCP path too. 2014-04-29 12:30:18 +01:00
Simon Kelley
4872aa747b Handle SERVFAIL replies when looking for proven-nonexistence of DS. 2014-04-26 22:13:31 +01:00
Simon Kelley
7ea3d3fdca ra-advrouter mode for RFC-3775 mobile IPv6 support. 2014-04-25 22:04:05 +01:00
102 changed files with 18278 additions and 9908 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
VERSION export-subst

7
.gitignore vendored
View File

@@ -3,9 +3,10 @@ src/*.mo
src/dnsmasq.pot
src/dnsmasq
src/dnsmasq_baseline
src/.configured
contrib/wrt/dhcp_lease_time
contrib/wrt/dhcp_release
src/.copts_*
contrib/lease-tools/dhcp_lease_time
contrib/lease-tools/dhcp_release
contrib/lease-tools/dhcp_release6
debian/base/
debian/daemon/
debian/files

3190
CHANGELOG

File diff suppressed because it is too large Load Diff

View File

@@ -56,7 +56,7 @@ release 0.95 Major rewrite: remove calls to gethostbyname() and talk
any more memory after start-up. The NAT-like forwarding was
inspired by a suggestion from Eli Chen <eli@routefree.com>
release 0.96 Fixed embarrasing thinko in cache linked-list code.
release 0.96 Fixed embarrassing thinko in cache linked-list code.
release 0.98 Some enhancements and bug-fixes.
Thanks to "Denis Carre" <denis.carre@laposte.net> and Martin
@@ -78,7 +78,7 @@ release 0.98 Some enhancements and bug-fixes.
ids, to thwart DNS spoofers.
(7) Dnsmasq no longer forwards queries when the
"recursion desired" bit is not set in the header.
(8) Fixed getopt code to work on compliers with unsigned char.
(8) Fixed getopt code to work on compilers with unsigned char.
release 0.991 Added -b flag: when set causes dnsmasq to always answer
reverse queries on the RFC 1918 private IP space itself and
@@ -88,7 +88,7 @@ release 0.991 Added -b flag: when set causes dnsmasq to always answer
Fixed a bug which stopped dnsmasq working on a box with
two or more interfaces with the same IP address.
Fixed cacheing of CNAMEs. Previously, a CNAME which pointed
Fixed caching of CNAMEs. Previously, a CNAME which pointed
to a name with many A records would not have all the addresses
returned when being answered from the cache.
@@ -191,7 +191,7 @@ release 1.1 Added --user argument to allow user to change to
release 1.2 Added IPv6 DNS record support. AAAA records are cached
and read from /etc/hosts. Reverse-lookups in the
ip6.int and ip6.arpa domains are suppored. Dnsmasq can
ip6.int and ip6.arpa domains are supported. Dnsmasq can
talk to upstream servers via IPv6 if it finds IP6 addresses
in /etc/resolv.conf and it offers DNS service automatically
if IPv6 support is present in the kernel.
@@ -214,7 +214,7 @@ release 1.3 Some versions of the Linux kernel return EINVAL rather
starting, rather than after the first query - principle
of least surprise applies here.
release 1.4 Fix a bug with DHPC lease parsing which broke in
release 1.4 Fix a bug with DHCP lease parsing which broke in
non-UTC timezones. Thanks to Mark Wormgoor for
spotting and diagnosing this. Fixed versions in
the .spec files this time. Fixed bug in Suse startup
@@ -258,7 +258,7 @@ release 1.7 Fix a problem with cache not clearing properly
on receipt of SIGHUP. Bug spotted by Sat Deshpande.
In group-id changing code:
1) Drop supplimentary groups.
1) Drop supplementary groups.
2) Change gid before dropping root (patch from Soewono Effendi.)
3) Change group to "dip" if it exists, to allow access
to /etc/ppp/resolv.conf (suggestion from Jorg Sommer.)
@@ -297,7 +297,7 @@ release 1.9 Fixes to rpm .spec files.
required. The difference is not really visible with
bloated libcs like glibc, but should dramatically reduce
memory requirements when linked against ulibc for use on
embeded routers, and that's the point really. Thanks to
embedded routers, and that's the point really. Thanks to
Matthew Natalier for prompting this.
Changed debug mode (-d) so that all logging appears on
@@ -319,12 +319,12 @@ release 1.9 Fixes to rpm .spec files.
uClinux. Thanks to Matthew Natalier for uClinux stuff.
release 1.10 Log warnings if resolv.conf or dhcp.leases are not
accessable for any reason, as suggested by Hinrich Eilts.
accessible for any reason, as suggested by Hinrich Eilts.
Fixed wrong address printing in error message about
no interface with address.
Updated docs and split installation instuctions into setup.html.
Updated docs and split installation instructions into setup.html.
Fix bug in CNAME chasing code: One CNAME pointing
to many A records would lose A records after the
@@ -346,7 +346,7 @@ release 1.10 Log warnings if resolv.conf or dhcp.leases are not
Added -S option to directly specify upstream servers and
added ability to direct queries for specific domains to
specfic servers. Suggested by Jens Vonderheide.
specific servers. Suggested by Jens Vonderheide.
Upgraded random ID generation - patch from Rob Funk.
@@ -386,13 +386,13 @@ release 1.11 Actually implement the -R flag promised in the 1.10 man page.
names in /etc/hosts -suggestion from Phil Harman.
Always return a zero time-to-live for names derived from
DHCP which stops anthing else caching these
DHCP which stops anything else caching these
names. Previously the TTL was derived from the lease
time but that is incorrect since a lease can be given
up early: dnsmasq would know this but anything with the
name cached with long TTL would not be updated.
Extended HAVE_IPV6 config flag to allow compliation on
Extended HAVE_IPV6 config flag to allow compilation on
old systems which don't have modern library routines
like inet_ntop(). Thanks to Phil Harman for the patch.
@@ -471,7 +471,7 @@ release 1.14 Fixed man page description of -b option which confused
/etc/resolv.conf.
(Thanks to Klaas Teschauer)
Check that recieved queries have only rfc1035-legal characters
Check that received queries have only rfc1035-legal characters
in them. This check is mainly to avoid bad strings being
sent to syslog.
@@ -549,7 +549,7 @@ release 1.16 Allow "/" characters in domain names - this fixes
release 1.17 Fixed crash with DHCP hostnames > 40 characters.
Fixed name-comparision routines to not depend on Locale,
Fixed name-comparison routines to not depend on Locale,
in theory this versions since 1.15 could lock up or give
wrong results when run with locale != 'C'.
@@ -574,7 +574,7 @@ release 1.18 Added round-robin DNS for names which have more than one
forwarded because -D is in effect, return NXDOMAIN not
an empty reply.
Add code to return the software version in repsonse to the
Add code to return the software version in response to the
correct magic query in the same way as BIND. Use
"dig version.bind chaos txt" to make the query.
@@ -635,7 +635,7 @@ release 2.0
dynamic allocation.
Allow dhcp-host options for the same host with different
IP adresses where the correct one will be selected for
IP addresses where the correct one will be selected for
the network the host appears on.
Fix parsing of --dhcp-option to allow more than one
@@ -674,7 +674,7 @@ release 2.1
Fix unaligned access warnings on BSD/Alpha.
Allow empty DHCP options, like so: dhpc-option=44
Allow empty DHCP options, like so: dhcp-option=44
Allow single-byte DHCP options like so: dhcp-option=20,1
@@ -745,7 +745,7 @@ release 2.3
around a bug in the DHCP client in HP Jetdirect printers.
Thanks to Marko Stolle for finding this problem.
Return DHCP T1 and T2 times, with "fuzz" to desychronise lease
Return DHCP T1 and T2 times, with "fuzz" to desynchronise lease
renewals, as specified in the RFC.
Ensure that the END option is always present in DHCP
@@ -838,7 +838,7 @@ release 2.4
by Chad Skeeters.
Fixed bug in /etc/ethers parsing code triggered by tab
characters. Qudos to Dag Wieers for hepling to nail that
characters. Kudos to Dag Wieers for helping to nail that
one.
Added "bind-interfaces" option correctly.
@@ -975,7 +975,7 @@ release 2.8
configuration. Specifically: (1) options are matched on
the netids from dhcp-range, dhcp-host, vendor class and
user class(es). Multiple net-ids are allowed and options
are searched on them all. (2) matches agains vendor class
are searched on them all. (2) matches against vendor class
and user class are now on a substring, if the given
string is a substring of the vendor/user class, then a
match occurs. Thanks again to Richard Musil for prompting
@@ -997,7 +997,7 @@ release 2.8
Add checks against DHCP clients which return zero-length
hostnames. This avoids the potential lease-loss problems
reffered to above. Also, if a client sends a hostname when
referred to above. Also, if a client sends a hostname when
it creates a lease but subsequently sends no or a
zero-length hostname whilst renewing, continue to use the
existing hostname, don't wipe it out.
@@ -1019,7 +1019,7 @@ release 2.9
broken. The new algorithm is to pick as before for the
first try, but if a query is retried, to send to all
available servers in parallel. The first one to reply
then becomes prefered for the next query. This should
then becomes preferred for the next query. This should
improve reliability without generating significant extra
upstream load.
@@ -1027,7 +1027,7 @@ release 2.9
unqualified domains introduced in version 2.8
Allow fallback to "bind-interfaces" at runtime: Some
verions of *BSD seem to have enough stuff in the header
versions of *BSD seem to have enough stuff in the header
files to build but no kernel support. Also now log if
"bind-interfaces" is forced on.
@@ -1049,7 +1049,7 @@ release 2.9
first name found is now returned for reverse lookups,
rather than all of them.
Add back fatal errors when nonexistant
Add back fatal errors when nonexistent
interfaces or interface addresses are given but only in
"bind-interfaces" mode. Principle of least surprise applies.
@@ -1193,7 +1193,7 @@ version 2.14
version 2.15
Fixed NXDOMAIN/NODATA confusion for locally known
names. We now return a NODATA reponse for names which are
names. We now return a NODATA response for names which are
locally known. Now a query for (eg AAAA or MX) for a name
with an IPv4 address in /etc/hosts which fails upstream
will generate a NODATA response. Note that the query
@@ -1229,7 +1229,7 @@ version 2.16
Set NONBLOCK on all listening sockets to workaround non-POSIX
compliance in Linux 2.4 and 2.6. This fixes rare hangs which
occured when corrupted packets were received. Thanks to
occurred when corrupted packets were received. Thanks to
Joris van Rantwijk for chasing that down.
Updated config.h for NetBSD. Thanks to Martin Lambers.
@@ -1297,7 +1297,7 @@ version 2.18
interfaces with more than one IPv6 address. Thanks to
Martin Pels for help with that.
Fix problems which occured when more than one dhcp-range
Fix problems which occurred when more than one dhcp-range
was specified in the same subnet: sometimes parameters
(lease time, network-id tag) from the wrong one would be
used. Thanks to Rory Campbell-Lange for the bug report.
@@ -1314,7 +1314,7 @@ version 2.19
Thanks to Richard Atterer for the bug report.
Check for under-length option fields in DHCP packets, a
zero length client-id, in particluar, could seriously
zero length client-id, in particular, could seriously
confuse dnsmasq 'till now. Thanks to Will Murname for help
with that.
@@ -1389,7 +1389,7 @@ version 2.21
recursive queries.
Fix DHCP address allocation problem when netid tags are in
use. Thanks to Will Murnane for the bug report and
use. Thanks to Will Murname for the bug report and
subsequent testing.
Add an additional data section to the reply for MX and SRV
@@ -1505,7 +1505,7 @@ version 2.23
from dnsmasq --version. Thanks to Dirk Schenkewitz for
the suggestion.
Fix pathalogical behaviour when a broken client keeps sending
Fix pathological behaviour when a broken client keeps sending
DHCPDISCOVER messages repeatedly and fast. Because dealing with
each of these takes a few seconds, (because of the ping) then a
queue of DHCP packets could build up. Now, the results of a ping
@@ -1593,7 +1593,7 @@ version 2.24
than one dhcp-range is available. Thanks to Sorin Panca
for help chasing this down.
Added more explict error mesages to the hosts file and
Added more explicit error messages to the hosts file and
ethers file reading code. Markus Kaiserswerth suffered to
make this happen.
@@ -1617,7 +1617,7 @@ version 2.25
Fixed Suse spec file - thanks to Steven Springl.
Fixed DHCP bug when two distict subnets are on the same
Fixed DHCP bug when two distinct subnets are on the same
physical interface. Thanks to Pawel Zawora for finding
this and suggesting the fix.
@@ -1740,7 +1740,7 @@ version 2.28
Fixed regression in netlink code under 2.2.x kernels which
occurred in 2.27. Erik Jan Tromp is the vintage kernel fan
who found this. P.S. It looks like this "netlink bind:
permission denied" problem occured in kernels at least as
permission denied" problem occurred in kernels at least as
late a 2.4.18. Good information from Alain Richoux.
Added a warning when it's impossible to give a host its
@@ -1761,7 +1761,7 @@ version 2.28
Eric House and Eric Spakman for help in chasing this down.
Tolerate configuration screwups which lead to the DHCP
server attemping to allocate its own address to a
server attempting to allocate its own address to a
client; eg setting the whole subnet range as a DHCP
range. Addresses in use by the server are now excluded
from use by clients.
@@ -2273,7 +2273,7 @@ version 2.40
this.
Use client-id as hash-seed for DHCP address allocation
with Firewire and Infiniband, as these don't supply an MAC
with Firewire and InfiniBand, as these don't supply an MAC
address.
Tweaked TFTP file-open code to make it behave sensibly
@@ -2307,7 +2307,7 @@ version 2.40
Continue to use unqualified hostnames provided by DHCP
clients, even if the domain part is illegal. (The domain
is ignored, and an error logged.) Previously in this
situation, the whole name whould have been
situation, the whole name would have been
rejected. Thanks to Jima for the patch.
Handle EINTR returns from wait() correctly and reap
@@ -2319,7 +2319,7 @@ version 2.40
leases file and passed to the lease-change
script. Suggestion from Ben Voigt.
Re-run the lease chamge script with an "old" event for
Re-run the lease change script with an "old" event for
each lease when dnsmasq receives a SIGHUP.
Added more useful exit codes, including passing on a
@@ -2417,7 +2417,7 @@ version 2.41
Changed behavior of DHCP server to always return total length of
a new lease in DHCPOFFER, even if an existing lease
exists. (It used to return the time remaining on the lease
whne one existed.) This fixes problems with the Sony Ericsson
when one existed.) This fixes problems with the Sony Ericsson
K610i phone. Thanks to Hakon Stordahl for finding and
fixing this.
@@ -2476,7 +2476,7 @@ version 2.42
Fix OS detection logic to cope with GNU/FreeBSD.
Fix unitialised variable in DBus code - thanks to Roy
Fix uninitialised variable in DBus code - thanks to Roy
Marples.
Fix network enumeration code to work on later NetBSD -

88
FAQ
View File

@@ -59,7 +59,7 @@ A: Yes, there is explicit support for *BSD and MacOS X and Solaris.
Q: My company's nameserver knows about some names which aren't in the
public DNS. Even though I put it first in /etc/resolv.conf, it
dosen't work: dnsmasq seems not to use the nameservers in the order
doesn't work: dnsmasq seems not to use the nameservers in the order
given. What am I doing wrong?
A: By default, dnsmasq treats all the nameservers it knows about as
@@ -144,19 +144,19 @@ Q: Who are Verisign, what do they have to do with the bogus-nxdomain
option in dnsmasq and why should I wory about it?
A: [note: this was written in September 2003, things may well change.]
Versign run the .com and .net top-level-domains. They have just
Verisign run the .com and .net top-level-domains. They have just
changed the configuration of their servers so that unknown .com and
.net domains, instead of returning an error code NXDOMAIN, (no such
domain) return the address of a host at Versign which runs a web
domain) return the address of a host at Verisign which runs a web
server showing a search page. Most right-thinking people regard
this new behaviour as broken :-). You can test to see if you are
suffering Versign brokeness by run a command like
suffering Verisign brokenness by run a command like
host jlsdajkdalld.com
If you get "jlsdajkdalld.com" does not exist, then all is fine, if
host returns an IP address, then the DNS is broken. (Try a few
different unlikely domains, just in case you picked a wierd one
different unlikely domains, just in case you picked a weird one
which really _is_ registered.)
Assuming that your DNS is broken, and you want to fix it, simply
@@ -180,7 +180,7 @@ A: There are a couple of configuration gotchas which have been
whilst the ISC one works.
The first thing to check is the broadcast address set for the
ethernet interface. This is normally the adddress on the connected
ethernet interface. This is normally the address on the connected
network with all ones in the host part. For instance if the
address of the ethernet interface is 192.168.55.7 and the netmask
is 255.255.255.0 then the broadcast address should be
@@ -205,7 +205,7 @@ A: By default, none of the DHCP clients send the host-name when asking
send with the "hostname" keyword in /etc/network/interfaces. (See
"man interfaces" for details.) That doesn't work for dhclient, were
you have to add something like "send host-name daisy" to
/etc/dhclient.conf [Update: the lastest dhcpcd packages _do_ send
/etc/dhclient.conf [Update: the latest dhcpcd packages _do_ send
the hostname by default.
Q: I'm network booting my machines, and trying to give them static
@@ -240,7 +240,7 @@ Q: What are these strange "bind-interface" and "bind-dynamic" options?
A: Dnsmasq from v2.63 can operate in one of three different "networking
modes". This is unfortunate as it requires users configuring dnsmasq
to take into account some rather bizzare contraints and select the
to take into account some rather bizarre constraints and select the
mode which best fits the requirements of a particular installation.
The origin of these are deficiencies in the Unix networking
model and APIs and each mode has different advantages and
@@ -252,10 +252,10 @@ A: Dnsmasq from v2.63 can operate in one of three different "networking
The three modes are "wildcard", "bind-interfaces" and "bind-dynamic".
In "wildcard" mode, dnsmasq binds the wildcard IP address (0.0.0.0 or
::). This allows it to recieve all the packets sent to the server on
::). This allows it to receive all the packets sent to the server on
the relevant port. Access control (--interface, --except-interface,
--listen-address, etc) is implemented by dnsmasq: it queries the
kernel to determine the interface on which a packet was recieved and
kernel to determine the interface on which a packet was received and
the address to which it was sent, and applies the configured
rules. Wildcard mode is the default if neither of the other modes are
specified.
@@ -276,7 +276,7 @@ A: Dnsmasq from v2.63 can operate in one of three different "networking
The mode chosen has four different effects: co-existence with other
servers, semantics of --interface access control, effect of new
interfaces, and legality of --interface specifications for
non-existent inferfaces. We will deal with these in order.
non-existent interfaces. We will deal with these in order.
A dnsmasq instance running in wildcard mode precludes a machine from
running a second instance of dnsmasq or any other DNS, TFTP or DHCP
@@ -313,15 +313,25 @@ Q: Can I get email notification when a new version of dnsmasq is
released?
A: Yes, new releases of dnsmasq are always announced through
freshmeat.net, and they allow you to subcribe to email alerts when
freshmeat.net, and they allow you to subscribe to email alerts when
new versions of particular projects are released. New releases are
also announced in the dnsmasq-discuss mailing list, subscribe at
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
Q: What does the dhcp-authoritative option do?
A: See http://www.isc.org/files/auth.html - that's
for the ISC daemon, but the same applies to dnsmasq.
A: The DHCP spec says that when a DHCP server recieves a renewal request
from a client it has no knowledge of, it should just ignore it.
This is because it's supported to have more than one DHCP server
on a network, and another DHCP server may be dealing with the client.
This has the unfortunate effect that when _no_ DHCP replies to
the client, it takes some time for the client to time-out and start
to get a new lease. Setting this option makes dnsmasq violate the
standard to the extent that it will send a NAK reply to the client,
causing it to immediately start to get a new lease. This improves
behaviour when machines move networks, and in the case that the DHCP
lease database is lost. As long as there are not more tha one DHCP
server on the network, it's safe to enable the option.
Q: Why does my Gentoo box pause for a minute before getting a new
lease?
@@ -349,18 +359,64 @@ A: By default, the identity of a machine is determined by using the
method for setting the client-id varies with DHCP client software,
dhcpcd uses the "-I" flag. Windows uses a registry setting,
see http://www.jsiinc.com/SUBF/TIP2800/rh2845.htm
Addendum:
From version 2.46, dnsmasq has a solution to this which doesn't
involve setting client-IDs. It's possible to put more than one MAC
address in a --dhcp-host configuration. This tells dnsmasq that it
should use the specified IP for any of the specified MAC addresses,
and furthermore it gives dnsmasq permission to sumarily abandon a
and furthermore it gives dnsmasq permission to summarily abandon a
lease to one of the MAC addresses if another one comes along. Note
that this will work fine only as longer as only one interface is
up at any time. There is no way for dnsmasq to enforce this
constraint: if you configure multiple MAC addresses and violate
this rule, bad things will happen.
Addendum-II: The link above is dead, the former contents of the link are:
------------------------------------------------------------------------------
How can I keep the same DHCP client reservation, if the MAC address changes?
When you reserve an IP address for a DHCP client, you provide the
MAC address of the client's NIC.
It is possible to use a custom identifier, which is sent as
option 61 in the client's DHCP Discover and Request packet.
The DhcpClientIdentifier is a REG_DWORD value that is located at:
Windows NT 4.0 SP2+
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<Adapter Name>'X'\Parameters\Tcpip
where <Adapter Name> is the NIC driver name and 'X' is the number of the NIC.
Windows 2000
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TcpIp\Parameters\Interfaces\<NIC GUID>
where <NIC GUID> is the GUID of the NIC.
The valid range of data is 0x0 - 0xFFFFFFFF. The custom identifier is send as 4 bytes,
8 hexadecimal character, in groups of 2 hexadecimal characters, with the groups being
sent in reverse order. If the custom identifier is less than 8 hexadeciaml characters,
it is zero padded at the end. Examples:
Custom Client Client Reservation
Identifier on DHCP Server
12345678 78563412
123456 56341200
1234 34120000
1234567 67452301
12345 45230100
123 23010000
A18F42 428FA100
CF432 32F40C00
C32D1BE BED1320C
-------------------------------------------------------------------------------------------------------
Q: Can dnsmasq do DHCP on IP-alias interfaces?
A: Yes, from version-2.21. The support is only available running under
@@ -488,7 +544,7 @@ Q: DHCP doesn't work with windows 7 but everything else is fine.
A: There seems to be a problem if Windows 7 doesn't get a value for
DHCP option 252 in DHCP packets it gets from the server. The
symtoms have beeen variously reported as continual DHCPINFORM
symptoms have been variously reported as continual DHCPINFORM
requests in an attempt to get an option-252, or even ignoring DHCP
offers completely (and failing to get an IP address) if there is no
option-252 supplied. DHCP option 252 is for WPAD, WWW Proxy

View File

@@ -1,4 +1,4 @@
# dnsmasq is Copyright (c) 2000-2014 Simon Kelley
# dnsmasq is Copyright (c) 2000-2016 Simon Kelley
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -55,21 +55,28 @@ dbus_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG)
dbus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1`
idn_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn`
idn_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn`
idn2_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --cflags libidn2`
idn2_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --libs libidn2`
ct_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --cflags libnetfilter_conntrack`
ct_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --libs libnetfilter_conntrack`
lua_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --cflags lua5.1`
lua_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.1`
lua_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --cflags lua5.2`
lua_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.2`
nettle_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --cflags nettle hogweed`
nettle_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --libs nettle hogweed`
gmp_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --copy -lgmp`
gmp_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC NO_GMP --copy -lgmp`
sunos_libs = `if uname | grep SunOS >/dev/null 2>&1; then echo -lsocket -lnsl -lposix4; fi`
version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
sum?=$(shell $(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' ')
sum!=$(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' '
copts_conf = .copts_$(sum)
objs = cache.o rfc1035.o util.o option.o forward.o network.o \
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
domain.o dnssec.o blockdata.o
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
poll.o rrfilter.o edns0.o arp.o
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
dns-protocol.h radv-protocol.h ip6addr.h
@@ -77,13 +84,13 @@ hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
all : $(BUILDDIR)
@cd $(BUILDDIR) && $(MAKE) \
top="$(top)" \
build_cflags="$(version) $(dbus_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
build_libs="$(dbus_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
-f $(top)/Makefile dnsmasq
mostly_clean :
rm -f $(BUILDDIR)/*.mo $(BUILDDIR)/*.pot
rm -f $(BUILDDIR)/.configured $(BUILDDIR)/*.o $(BUILDDIR)/dnsmasq.a $(BUILDDIR)/dnsmasq
rm -f $(BUILDDIR)/.copts_* $(BUILDDIR)/*.o $(BUILDDIR)/dnsmasq.a $(BUILDDIR)/dnsmasq
clean : mostly_clean
rm -f $(BUILDDIR)/dnsmasq_baseline
@@ -101,8 +108,8 @@ all-i18n : $(BUILDDIR)
@cd $(BUILDDIR) && $(MAKE) \
top="$(top)" \
i18n=-DLOCALEDIR=\'\"$(LOCALEDIR)\"\' \
build_cflags="$(version) $(dbus_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) `$(PKG_CONFIG) --cflags libidn`" \
build_libs="$(dbus_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) `$(PKG_CONFIG) --libs libidn`" \
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
-f $(top)/Makefile dnsmasq
for f in `cd $(PO); echo *.po`; do \
cd $(top) && cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile $${f%.po}.mo; \
@@ -113,12 +120,12 @@ install-i18n : all-i18n install-common
cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR) $(INSTALL)
merge :
@cd $(BUILDDIR) && $(MAKE) -f $(top)/Makefile dnsmasq.pot
@cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile dnsmasq.pot
for f in `cd $(PO); echo *.po`; do \
echo -n msgmerge $(PO)/$$f && $(MSGMERGE) --no-wrap -U $(PO)/$$f $(BUILDDIR)/dnsmasq.pot; \
done
# Cannonicalise .po file.
# Canonicalise .po file.
%.po :
@cd $(BUILDDIR) && $(MAKE) -f $(top)/Makefile dnsmasq.pot
mv $(PO)/$*.po $(PO)/$*.po.orig && $(MSGMERGE) --no-wrap $(PO)/$*.po.orig $(BUILDDIR)/dnsmasq.pot >$(PO)/$*.po;
@@ -137,19 +144,21 @@ bloatcheck : $(BUILDDIR)/dnsmasq_baseline mostly_clean all
$(top)/bld/bloat-o-meter dnsmasq_baseline dnsmasq; \
size dnsmasq_baseline dnsmasq
# rules below are targets in recusive makes with cwd=$(BUILDDIR)
# rules below are targets in recursive makes with cwd=$(BUILDDIR)
.configured: $(hdrs)
@rm -f *.o
$(copts_conf): $(hdrs)
@rm -f *.o .copts_*
@touch $@
$(objs:.o=.c) $(hdrs):
ln -s $(top)/$(SRC)/$@ .
$(objs): $(copts_conf) $(hdrs)
.c.o:
$(CC) $(CFLAGS) $(COPTS) $(i18n) $(build_cflags) $(RPM_OPT_FLAGS) -c $<
dnsmasq : .configured $(hdrs) $(objs)
dnsmasq : $(objs)
$(CC) $(LDFLAGS) -o $@ $(objs) $(build_libs) $(LIBS)
dnsmasq.pot : $(objs:.o=.c) $(hdrs)

View File

@@ -9,7 +9,8 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
rfc2131.c tftp.c util.c conntrack.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
dnssec.c dnssec-openssl.c blockdata.c tables.c \
loop.c inotify.c poll.c rrfilter.c edns0.c arp.c
LOCAL_MODULE := dnsmasq

View File

@@ -11,16 +11,24 @@
# If there is more than one v[0-9].* tag, sort them and use the
# first. This favours, eg v2.63 over 2.63rc6.
if which git >/dev/null 2>&1 && [ -d $1/.git ]; then
cd $1; git describe | sed 's/^v//'
# Change directory to the toplevel source directory.
if test -z "$1" || ! test -d "$1" || ! cd "$1"; then
echo "$0: First argument $1 must be toplevel dir." >&2
exit 1
fi
if which git >/dev/null 2>&1 && \
([ -d .git ] || grep '^gitdir:' .git >/dev/null 2>&1) && \
git describe >/dev/null 2>&1; then
git describe | sed 's/^v//'
elif grep '\$Format:%d\$' $1/VERSION >/dev/null 2>&1; then
# unsubstituted VERSION, but no git available.
# unsubstituted VERSION, but no git available.
echo UNKNOWN
else
vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep ^v[0-9]`
if [ $? -eq 0 ]; then
echo "${vers}" | sort | head -n 1 | sed 's/^v//'
echo "${vers}" | sort -r | head -n 1 | sed 's/^v//'
else
cat $1/VERSION
fi

View File

@@ -11,9 +11,14 @@ in=`cat`
if grep "^\#[[:space:]]*define[[:space:]]*$search" config.h >/dev/null 2>&1 || \
echo $in | grep $search >/dev/null 2>&1; then
# Nasty, nasty, in --copy, arg 2 is another config to search for, use with NO_GMP
if [ $op = "--copy" ]; then
pkg="$*"
if grep "^\#[[:space:]]*define[[:space:]]*$pkg" config.h >/dev/null 2>&1 || \
echo $in | grep $pkg >/dev/null 2>&1; then
pkg=""
else
pkg="$*"
fi
elif grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
pkg=`$pkg --static $op $*`

View File

@@ -22,7 +22,7 @@ sudo chmod 644 /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
Optionally, edit your dnsmasq configuration file to your liking.
To start the launchd job, which starts dnsmaq, reboot or use the command:
To start the launchd job, which starts dnsmasq, reboot or use the command:
sudo launchctl load /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
To stop the launchd job, which stops dnsmasq, use the command:

View File

@@ -1,9 +1,9 @@
This is a patch against SuSEfirewall2-3.1-206 (SuSE 9.x and older)
It fixes the depancy from the dns daemon name 'named'
It fixes the dependency from the dns daemon name 'named'
After appending the patch, the SuSEfirewall is again able to autodetect
the dnsmasq named service.
This is a very old bug in the SuSEfirewall script.
The SuSE people think the name of the dns server will allways 'named'
The SuSE people think the name of the dns server will always 'named'
--- /sbin/SuSEfirewall2.orig 2004-01-23 13:30:09.000000000 +0100

View File

@@ -13,10 +13,10 @@ connection comes out of the other side. However, sometimes, we want to
maintain that relationship through the proxy and continue the connection
mark on packets upstream of our proxy
DNSMasq includes such a feature enabled by the --conntrack
Dnsmasq includes such a feature enabled by the --conntrack
option. This allows, for example, using iptables to mark traffic from
a particular IP, and that mark to be persisted to requests made *by*
DNSMasq. Such a feature could be useful for bandwidth accounting,
Dnsmasq. Such a feature could be useful for bandwidth accounting,
captive portals and the like. Note a similar feature has been
implemented in Squid 2.2
@@ -40,7 +40,7 @@ on IP address. 3) Saves the firewall mark back to the connection mark
(which will persist it across related packets)
4) is applied to the OUTPUT table, which is where we first see packets
generated locally. DNSMasq will have already copied the firewall mark
generated locally. Dnsmasq will have already copied the firewall mark
from the request, across to the new packet, and so all that remains is
for iptables to copy it to the connection mark so it's persisted across
packets.

View File

@@ -55,7 +55,7 @@ Index: src/dnsmasq.c
}
@@ -434,7 +433,7 @@
/* lose the setuid and setgid capbilities */
/* lose the setuid and setgid capabilities */
if (capset(hdr, data) == -1)
{
- send_event(err_pipe[1], EVENT_CAP_ERR, errno);

View File

@@ -0,0 +1,6 @@
CFLAGS?= -O2 -Wall -W
all: dhcp_release dhcp_release6 dhcp_lease_time
clean:
rm -f *~ *.o core dhcp_release dhcp_release6 dhcp_lease_time

View File

@@ -168,7 +168,7 @@ int main(int argc, char **argv)
*(p++) = 1;
*(p++) = DHCPINFORM;
/* Explicity request the lease time, it won't be sent otherwise:
/* Explicitly request the lease time, it won't be sent otherwise:
this is a dnsmasq extension, not standard. */
*(p++) = OPTION_REQUESTED_OPTIONS;
*(p++) = 1;

View File

@@ -117,7 +117,7 @@ static ssize_t netlink_recv(int fd)
msg.msg_flags = 0;
while ((rc = recvmsg(fd, &msg, MSG_PEEK)) == -1 && errno == EINTR);
/* 2.2.x doesn't suport MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a
/* 2.2.x doesn't support MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a
big buffer and pray in that case. */
if (rc == -1 && errno == EOPNOTSUPP)
{
@@ -277,6 +277,11 @@ int main(int argc, char **argv)
exit(1);
}
if (inet_addr(argv[2]) == INADDR_NONE)
{
perror("invalid ip address");
exit(1);
}
lease.s_addr = inet_addr(argv[2]);
server = find_interface(lease, nl, if_nametoindex(argv[1]));

View File

@@ -0,0 +1,38 @@
.TH DHCP_RELEASE 1
.SH NAME
dhcp_release6 \- Release a DHCPv6 lease on a the local dnsmasq DHCP server.
.SH SYNOPSIS
.B dhcp_release6 --iface <interface> --client-id <client-id> --server-id
server-id --iaid <iaid> --ip <IP> [--dry-run] [--help]
.SH "DESCRIPTION"
A utility which forces the DHCP server running on this machine to release a
DHCPv6 lease.
.SS OPTIONS
.IP "-a, --ip"
IPv6 address to release.
.IP "-c, --client-id"
Colon-separated hex string representing DHCPv6 client id. Normally
it can be found in leases file both on client and server.
.IP "-d, --dry-run"
Print hexadecimal representation of generated DHCPv6 release packet to standard
output and exit.
.IP "-h, --help"
print usage information to standard output and exit.
.IP "-i, --iaid"
Decimal representation of DHCPv6 IAID. Normally it can be found in leases file
both on client and server.
.IP "-n, --iface"
Network interface to send a DHCPv6 release packet from.
.IP "-s, --server-id"
Colon-separated hex string representing DHCPv6 server id. Normally
it can be found in leases file both on client and server.
.SH NOTES
MUST be run as root - will fail otherwise.
.SH LIMITATIONS
Only usable on IPv6 DHCP leases.
.SH SEE ALSO
.BR dnsmasq (8)
.SH AUTHOR
This manual page was written by Simon Kelley <simon@thekelleys.org.uk>.

View File

@@ -0,0 +1,445 @@
/*
dhcp_release6 --iface <interface> --client-id <client-id> --server-id
server-id --iaid <iaid> --ip <IP> [--dry-run] [--help]
MUST be run as root - will fail otherwise
*/
/* Send a DHCPRELEASE message to IPv6 multicast address via the specified interface
to tell the local DHCP server to delete a particular lease.
The interface argument is the interface in which a DHCP
request _would_ be received if it was coming from the client,
rather than being faked up here.
The client-id argument is colon-separated hex string and mandatory. Normally
it can be found in leases file both on client and server
The server-id argument is colon-separated hex string and mandatory. Normally
it can be found in leases file both on client and server.
The iaid argument is numeric string and mandatory. Normally
it can be found in leases file both on client and server.
IP is an IPv6 address to release
If --dry-run is specified, dhcp_release6 just prints hexadecimal representation of
packet to send to stdout and exits.
If --help is specified, dhcp_release6 print usage information to stdout and exits
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <getopt.h>
#include <errno.h>
#include <unistd.h>
#define NOT_REPLY_CODE 115
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
enum DHCP6_TYPES{
SOLICIT = 1,
ADVERTISE = 2,
REQUEST = 3,
CONFIRM = 4,
RENEW = 5,
REBIND = 6,
REPLY = 7,
RELEASE = 8,
DECLINE = 9,
RECONFIGURE = 10,
INFORMATION_REQUEST = 11,
RELAY_FORW = 12,
RELAY_REPL = 13
};
enum DHCP6_OPTIONS{
CLIENTID = 1,
SERVERID = 2,
IA_NA = 3,
IA_TA = 4,
IAADDR = 5,
ORO = 6,
PREFERENCE = 7,
ELAPSED_TIME = 8,
RELAY_MSG = 9,
AUTH = 11,
UNICAST = 12,
STATUS_CODE = 13,
RAPID_COMMIT = 14,
USER_CLASS = 15,
VENDOR_CLASS = 16,
VENDOR_OPTS = 17,
INTERFACE_ID = 18,
RECONF_MSG = 19,
RECONF_ACCEPT = 20,
};
enum DHCP6_STATUSES{
SUCCESS = 0,
UNSPEC_FAIL = 1,
NOADDR_AVAIL=2,
NO_BINDING = 3,
NOT_ON_LINK = 4,
USE_MULTICAST =5
};
static struct option longopts[] = {
{"ip", required_argument, 0, 'a'},
{"server-id", required_argument, 0, 's'},
{"client-id", required_argument, 0, 'c'},
{"iface", required_argument, 0, 'n'},
{"iaid", required_argument, 0, 'i'},
{"dry-run", no_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
const short DHCP6_CLIENT_PORT = 546;
const short DHCP6_SERVER_PORT = 547;
const char* DHCP6_MULTICAST_ADDRESS = "ff02::1:2";
struct dhcp6_option{
uint16_t type;
uint16_t len;
char value[1024];
};
struct dhcp6_iaaddr_option{
uint16_t type;
uint16_t len;
struct in6_addr ip;
uint32_t preferred_lifetime;
uint32_t valid_lifetime;
};
struct dhcp6_iana_option{
uint16_t type;
uint16_t len;
uint32_t iaid;
uint32_t t1;
uint32_t t2;
char options[1024];
};
struct dhcp6_packet{
size_t len;
char buf[2048];
} ;
size_t pack_duid(const char* str, char* dst){
char* tmp = strdup(str);
char* tmp_to_free = tmp;
char *ptr;
uint8_t write_pos = 0;
while ((ptr = strtok (tmp, ":"))) {
dst[write_pos] = (uint8_t) strtol(ptr, NULL, 16);
write_pos += 1;
tmp = NULL;
}
free(tmp_to_free);
return write_pos;
}
struct dhcp6_option create_client_id_option(const char* duid){
struct dhcp6_option option;
option.type = htons(CLIENTID);
bzero(option.value, sizeof(option.value));
option.len = htons(pack_duid(duid, option.value));
return option;
}
struct dhcp6_option create_server_id_option(const char* duid){
struct dhcp6_option option;
option.type = htons(SERVERID);
bzero(option.value, sizeof(option.value));
option.len = htons(pack_duid(duid, option.value));
return option;
}
struct dhcp6_iaaddr_option create_iaadr_option(const char* ip){
struct dhcp6_iaaddr_option result;
result.type =htons(IAADDR);
/* no suboptions needed here, so length is 24 */
result.len = htons(24);
result.preferred_lifetime = 0;
result.valid_lifetime = 0;
int s = inet_pton(AF_INET6, ip, &(result.ip));
if (s <= 0) {
if (s == 0)
fprintf(stderr, "Not in presentation format");
else
perror("inet_pton");
exit(EXIT_FAILURE);
}
return result;
}
struct dhcp6_iana_option create_iana_option(const char * iaid, struct dhcp6_iaaddr_option ia_addr){
struct dhcp6_iana_option result;
result.type = htons(IA_NA);
result.iaid = htonl(atoi(iaid));
result.t1 = 0;
result.t2 = 0;
result.len = htons(12 + ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
memcpy(result.options, &ia_addr, ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
return result;
}
struct dhcp6_packet create_release_packet(const char* iaid, const char* ip, const char* client_id, const char* server_id){
struct dhcp6_packet result;
bzero(result.buf, sizeof(result.buf));
/* message_type */
result.buf[0] = RELEASE;
/* tx_id */
bzero(result.buf+1, 3);
struct dhcp6_option client_option = create_client_id_option(client_id);
struct dhcp6_option server_option = create_server_id_option(server_id);
struct dhcp6_iaaddr_option iaaddr_option = create_iaadr_option(ip);
struct dhcp6_iana_option iana_option = create_iana_option(iaid, iaaddr_option);
int offset = 4;
memcpy(result.buf + offset, &client_option, ntohs(client_option.len) + 2*sizeof(uint16_t));
offset += (ntohs(client_option.len)+ 2 *sizeof(uint16_t) );
memcpy(result.buf + offset, &server_option, ntohs(server_option.len) + 2*sizeof(uint16_t) );
offset += (ntohs(server_option.len)+ 2* sizeof(uint16_t));
memcpy(result.buf + offset, &iana_option, ntohs(iana_option.len) + 2*sizeof(uint16_t) );
offset += (ntohs(iana_option.len)+ 2* sizeof(uint16_t));
result.len = offset;
return result;
}
uint16_t parse_iana_suboption(char* buf, size_t len){
size_t current_pos = 0;
char option_value[1024];
while (current_pos < len) {
uint16_t option_type, option_len;
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
option_type = ntohs(option_type);
option_len = ntohs(option_len);
current_pos += 2 * sizeof(uint16_t);
if (option_type == STATUS_CODE){
uint16_t status;
memcpy(&status, buf + current_pos, sizeof(uint16_t));
status = ntohs(status);
if (status != SUCCESS){
memcpy(option_value, buf + current_pos + sizeof(uint16_t) , option_len - sizeof(uint16_t));
option_value[option_len-sizeof(uint16_t)] ='\0';
fprintf(stderr, "Error: %s\n", option_value);
}
return status;
}
}
return -2;
}
int16_t parse_packet(char* buf, size_t len){
uint8_t type = buf[0];
/*skipping tx id. you need it, uncomment following line
uint16_t tx_id = ntohs((buf[1] <<16) + (buf[2] <<8) + buf[3]);
*/
size_t current_pos = 4;
if (type != REPLY ){
return NOT_REPLY_CODE;
}
char option_value[1024];
while (current_pos < len) {
uint16_t option_type, option_len;
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
option_type = ntohs(option_type);
option_len = ntohs(option_len);
current_pos += 2 * sizeof(uint16_t);
if (option_type == STATUS_CODE){
uint16_t status;
memcpy(&status, buf + current_pos, sizeof(uint16_t));
status = ntohs(status);
if (status != SUCCESS){
memcpy(option_value, buf + current_pos +sizeof(uint16_t) , option_len -sizeof(uint16_t));
fprintf(stderr, "Error: %d %s\n", status, option_value);
return status;
}
}
if (option_type == IA_NA ){
uint16_t result = parse_iana_suboption(buf + current_pos +24, option_len -24);
if (result){
return result;
}
}
current_pos += option_len;
}
return -1;
}
void usage(const char* arg, FILE* stream){
const char* usage_string ="--ip IPv6 --iface IFACE --server-id SERVER_ID --client-id CLIENT_ID --iaid IAID [--dry-run] | --help";
fprintf (stream, "Usage: %s %s\n", arg, usage_string);
}
int send_release_packet(const char* iface, struct dhcp6_packet* packet){
struct sockaddr_in6 server_addr, client_addr;
char response[1400];
int sock = socket(PF_INET6, SOCK_DGRAM, 0);
int i = 0;
if (sock < 0) {
perror("creating socket");
return -1;
}
if (setsockopt(sock, SOL_SOCKET, 25, iface, strlen(iface)) == -1) {
perror("SO_BINDTODEVICE");
close(sock);
return -1;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_family = AF_INET6;
client_addr.sin6_family = AF_INET6;
client_addr.sin6_port = htons(DHCP6_CLIENT_PORT);
client_addr.sin6_flowinfo = 0;
client_addr.sin6_scope_id =0;
inet_pton(AF_INET6, "::", &client_addr.sin6_addr);
bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6));
inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
int16_t recv_size = 0;
for (i = 0; i < 5; i++) {
if (sendto(sock, packet->buf, packet->len, 0,
(struct sockaddr *)&server_addr,
sizeof(server_addr)) < 0) {
perror("sendto failed");
exit(4);
}
recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
if (recv_size == -1){
if (errno == EAGAIN){
sleep(1);
continue;
}else {
perror("recvfrom");
}
}
int16_t result = parse_packet(response, recv_size);
if (result == NOT_REPLY_CODE){
sleep(1);
continue;
}
return result;
}
fprintf(stderr, "Response timed out\n");
return -1;
}
int main(int argc, char * const argv[]) {
const char* UNINITIALIZED = "";
const char* iface = UNINITIALIZED;
const char* ip = UNINITIALIZED;
const char* client_id = UNINITIALIZED;
const char* server_id = UNINITIALIZED;
const char* iaid = UNINITIALIZED;
int dry_run = 0;
while (1) {
int option_index = 0;
int c = getopt_long(argc, argv, "a:s:c:n:i:hd", longopts, &option_index);
if (c == -1){
break;
}
switch(c){
case 0:
if (longopts[option_index].flag !=0){
break;
}
printf ("option %s", longopts[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'i':
iaid = optarg;
break;
case 'n':
iface = optarg;
break;
case 'a':
ip = optarg;
break;
case 'c':
client_id = optarg;
break;
case 'd':
dry_run = 1;
break;
case 's':
server_id = optarg;
break;
case 'h':
usage(argv[0], stdout);
return 0;
case '?':
usage(argv[0], stderr);
return -1;
default:
abort();
}
}
if (iaid == UNINITIALIZED){
fprintf(stderr, "Missing required iaid parameter\n");
usage(argv[0], stderr);
return -1;
}
if (server_id == UNINITIALIZED){
fprintf(stderr, "Missing required server-id parameter\n");
usage(argv[0], stderr);
return -1;
}
if (client_id == UNINITIALIZED){
fprintf(stderr, "Missing required client-id parameter\n");
usage(argv[0], stderr);
return -1;
}
if (ip == UNINITIALIZED){
fprintf(stderr, "Missing required ip parameter\n");
usage(argv[0], stderr);
return -1;
}
if (iface == UNINITIALIZED){
fprintf(stderr, "Missing required iface parameter\n");
usage(argv[0], stderr);
return -1;
}
struct dhcp6_packet packet = create_release_packet(iaid, ip, client_id, server_id);
if (dry_run){
uint16_t i;
for(i=0;i<packet.len;i++){
printf("%hhx", packet.buf[i]);
}
printf("\n");
return 0;
}
return send_release_packet(iface, &packet);
}

View File

@@ -3,7 +3,7 @@
# first column of this file, then a DNAT port-forward will be set up
# to the address which has just been allocated by DHCP . The second field
# is port number(s). If there is only one, then the port-forward goes to
# the same port on the DHCP-client, if there are two seperated with a
# the same port on the DHCP-client, if there are two separated with a
# colon, then the second number is the port to which the connection
# is forwarded on the DHCP-client. By default, forwarding is set up
# for TCP, but it can done for UDP instead by prefixing the port to "u".

View File

@@ -0,0 +1,18 @@
The script reads stdin and replaces all IP addresses with names before
outputting it again. IPs from private networks are reverse looked up
via dns. Other IP addresses are searched for in the dnsmasq query log.
This gives names (CNAMEs if I understand DNS correctly) that are closer
to the name the client originally asked for then the names obtained by
reverse lookup. Just run
netstat -n -4 | ./reverse_replace.sh
to see what it does. It needs
log-queries
log-facility=/var/log/dnsmasq.log
in the dnsmasq configuration.
The script runs on debian (with ash installed) and on busybox.

View File

@@ -0,0 +1,125 @@
#!/bin/ash
# $Id: reverse_replace.sh 18 2015-03-01 16:12:35Z jo $
#
# Usage e.g.: netstat -n -4 | reverse_replace.sh
# Parses stdin for IP4 addresses and replaces them
# with names retrieved by parsing the dnsmasq log.
# This currently only gives CNAMEs. But these
# usually tell you more than the ones from reverse
# lookups.
#
# This has been tested on debian and asuswrt. Please
# report successful tests on other platforms.
#
# Author: Joachim Zobel <jz-2014@heute-morgen.de>
# License: Consider this MIT style licensed. You can
# do as you ike, but you must not remove my name.
#
LOG=/var/log/dnsmasq.log
MAX_LINES=15000
# sed regex do match IPs
IP_regex='[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
# private IP ranges
IP_private='\(^127\.\)\|\(^192\.168\.\)\|\(^10\.\)\|\(^172\.1[6-9]\.\)\|\(^172\.2[0-9]\.\)\|\(^172\.3[0-1]\.\)'
#######################################################################
# Find Commands
HOST=nslookup
if type host > /dev/null 2>&1; then
# echo "No need for nslookup, host is there"
HOST=host
fi
#######################################################################
# Functions
# Use shell variables for an (IP) lookup table
create_lookup_table()
{
# Parse log into lookup table
local CMDS="$( tail -"$MAX_LINES" "$LOG" | \
grep " is $IP_regex" | \
sed "s#.* \([^ ]*\) is \($IP_regex\).*#set_val \2 \1;#" )"
local IFS='
'
for CMD in $CMDS
do
eval $CMD
done
}
set_val()
{
local _IP=$(echo $1 | tr . _)
local KEY="__IP__$_IP"
eval "$KEY"=$2
}
get_val()
{
local _IP=$(echo $1 | tr . _)
local KEY="__IP__$_IP"
eval echo -n '${'"$KEY"'}'
}
dns_lookup()
{
local IP=$1
local RTN="$($HOST $IP | \
sed 's#\s\+#\n#g' | \
grep -v '^$' | \
tail -1 | tr -d '\n' | \
sed 's#\.$##')"
if echo $RTN | grep -q NXDOMAIN; then
echo -n $IP
else
echo -n "$RTN"
fi
}
reverse_dns()
{
local IP=$1
# Skip if it is not an IP
if ! echo $IP | grep -q "^$IP_regex$"; then
echo -n $IP
return
fi
# Do a dns lookup, if it is a local IP
if echo $IP | grep -q $IP_private; then
dns_lookup $IP
return
fi
local NAME="$(get_val $IP)"
if [ -z "$NAME" ]; then
echo -n $IP
else
echo -n $NAME
fi
}
#######################################################################
# Main
create_lookup_table
while read LINE; do
for IP in $(echo "$LINE" | \
sed "s#\b\($IP_regex\)\b#\n\1\n#g" | \
grep $IP_regex)
do
NAME=`reverse_dns $IP `
# echo "$NAME $IP"
LINE=`echo "$LINE" | sed "s#$IP#$NAME#" `
done
echo $LINE
done

View File

@@ -1,5 +1,5 @@
[Unit]
Description=A lightweight DHCP and caching DNS server
Description=dnsmasq - A lightweight DHCP and caching DNS server
[Service]
Type=dbus

View File

@@ -2,7 +2,7 @@ A remake of patch Bob Carroll had posted to dnsmasq,
now compatible with version 2.47. Hopefully he doesn't
mind (sending a copy of this mail to him too).
Maybe the patch in question is not acceptible
Maybe the patch in question is not acceptable
as it doesn't add new switch, rather it binds itself to "strict-order".
What it does is: if you have strict-order in the

View File

@@ -1,5 +1,5 @@
This is the README for the DNSmasq webmin module.
This is the README for the Dnsmasq webmin module.
Problems:
@@ -48,7 +48,7 @@ wade through the config file and man pages again.
If you modify it, or add a language file, and you have a spare moment,
please e-mail me - I won't be upset at all if you fix my poor coding!
(rather the opposite - I'd be pleased someone found it usefull)
(rather the opposite - I'd be pleased someone found it useful)
Cheers,
Neil Fisher <neil@magnecor.com.au>

View File

@@ -1,6 +0,0 @@
CFLAGS?= -O2 -Wall -W
all: dhcp_release dhcp_lease_time
clean:
rm -f *~ *.o core dhcp_release dhcp_lease_time

View File

@@ -4,7 +4,7 @@ reboot, then it will eventually be restored as hosts renew their
leases. Until a host renews (which may take hours/days) it will
not exist in the DNS if dnsmasq's DDNS function is in use.
*WRT systems remount all non-volatile fileystems read-only after boot,
*WRT systems remount all non-volatile filesystems read-only after boot,
so the normal leasefile will not work. They do, however have NV
storage, accessed with the nvram command:
@@ -62,7 +62,7 @@ about 100 bytes, so restricting the number of leases to 50 will limit
use to half that. (The default limit in the distributed source is 150)
Any UI script which reads the dnsmasq leasefile will have to be
ammended, probably by changing it to read the output of
amended, probably by changing it to read the output of
`lease_update init` instead.

View File

@@ -40,6 +40,14 @@ ClearCache
Returns nothing. Clears the domain name cache and re-reads
/etc/hosts. The same as sending dnsmasq a HUP signal.
SetFilterWin2KOption
--------------------
Takes boolean, sets or resets the --filterwin2k option.
SetBogusPrivOption
------------------
Takes boolean, sets or resets the --bogus-priv option.
SetServers
----------
Returns nothing. Takes a set of arguments representing the new
@@ -152,6 +160,89 @@ for SetServersEx is represented as
"/eng.mycorp.com/lab.mycorp.com/1003:1234:abcd::1%eth0"
]
GetLoopServers
--------------
(Only available if dnsmasq compiled with HAVE_LOOP)
Return an array of strings, each string is the IP address of an upstream
server which has been found to loop queries back to this dnsmasq instance, and
it therefore not being used.
AddDhcpLease
------------
Returns nothing. Adds or updates a DHCP or DHCPv6 lease to the internal lease
database, as if a client requested and obtained a lease.
If a lease for the IPv4 or IPv6 address already exist, it is overwritten.
Note that this function will trigger the DhcpLeaseAdded or DhcpLeaseUpdated
D-Bus signal and will run the configured DHCP lease script accordingly.
This function takes many arguments which are the lease parameters:
- A string with the textual representation of the IPv4 or IPv6 address of the
client.
Examples:
"192.168.1.115"
"1003:1234:abcd::1%eth0"
"2001:db8:abcd::1"
- A string representing the hardware address of the client, using the same
format as the one used in the lease database.
Examples:
"00:23:45:67:89:ab"
"06-00:20:e0:3b:13:af" (token ring)
- The hostname of the client, as an array of bytes (so there is no problem
with non-ASCII character encoding). May be empty.
Example (for "hostname.or.fqdn"):
[104, 111, 115, 116, 110, 97, 109, 101, 46, 111, 114, 46, 102, 113, 100, 110]
- The client identifier (IPv4) or DUID (IPv6) as an array of bytes. May be
empty.
Examples:
DHCPv6 DUID:
[0, 3, 0, 1, 0, 35, 69, 103, 137, 171]
DHCPv4 client identifier:
[255, 12, 34, 56, 78, 0, 1, 0, 1, 29, 9, 99, 190, 35, 69, 103, 137, 171]
- The duration of the lease, in seconds. If the lease is updated, then
the duration replaces the previous duration.
Example:
7200
- The IAID (Identity association identifier) of the DHCPv6 lease, as a network
byte-order unsigned integer. For DHCPv4 leases, this must be set to 0.
Example (for IPv6):
203569230
- A boolean which, if true, indicates that the DHCPv6 lease is for a temporary
address (IA_TA). If false, the DHCPv6 lease is for a non-temporary address
(IA_NA). For DHCPv4 leases, this must be set to false.
RemoveDhcpLease
---------------
Returns nothing. Removes a DHCP or DHCPv6 lease to the internal lease
database, as if a client sent a release message to abandon a lease.
This function takes only one parameter: the text representation of the
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.
2. SIGNALS

189
debian/changelog vendored
View File

@@ -1,3 +1,174 @@
dnsmasq (2.78-1) unstable; urgency=low
* New upstream.
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 25 Jun 2017 21:34:00 +0000
dnsmasq (2.77-2) unstable; urgency=low
* Improve sed regexp for parsing root.ds.
-- Simon Kelley <simon@thekelleys.org.uk> Mon, 5 Jun 2017 20:46:32 +0000
dnsmasq (2.77-1) unstable; urgency=low
* New upstream.
* Don't register as a resolvconf source when config file
includes port=0 to disable DNS.
* Handle gratuitous format change in /usr/share/dns/root.ds
(closes: #858506) (closes: #860064)
* Add lsb-base dependancy.
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 11 Apr 2017 14:19:20 +0000
dnsmasq (2.76-5) unstable; urgency=medium
* Nail libnettle dependency to avoid ABI incompatibility.
(closes: #846642)
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 14 Dec 2016 17:58:10 +0000
dnsmasq (2.76-4.1) unstable; urgency=medium
* Non-maintainer upload.
* Add two upstream patches to fix binding to an interface being
destroyed and recreated. Closes: #834722.
+ 2675f2061525bc954be14988d64384b74aa7bf8b
+ 16800ea072dd0cdf14d951c4bb8d2808b3dfe53d
-- Vincent Bernat <bernat@debian.org> Sat, 26 Nov 2016 20:15:34 +0100
dnsmasq (2.76-4) unstable; urgency=medium
* Non-maintainer upload.
* Fix FTCBFS: Use triplet-prefixed tools. (closes: #836072)
-- Helmut Grohne <helmut@subdivi.de> Tue, 30 Aug 2016 13:59:12 +0200
dnsmasq (2.76-3) unstable; urgency=medium
* Bump auth zone serial on SIGHUP. (closes: #833733)
-- Simon Kelley <simon@thekelleys.org.uk> Sat, 13 Aug 2016 21:43:10 +0000
dnsmasq (2.76-2) unstable; urgency=medium
* Fix to systemd to fix failure to start with bridge interface.
(Closes: #831372)
-- Simon Kelley <simon@thekelleys.org.uk> Sat, 16 Jul 2016 22:09:10 +0000
dnsmasq (2.76-1.2) unstable; urgency=medium
* Non-maintainer upload.
* dnsmasq: Install marker file to determine package installed state,
for the benefit of the init script. (Closes: #819856)
-- Christian Hofstaedtler <zeha@debian.org> Sat, 16 Jul 2016 00:17:57 +0000
dnsmasq (2.76-1.1) unstable; urgency=medium
* Non-maintainer upload.
* Provide nss-lookup.target for systemd, without relying on insserv.
Patch from Michael Biebl <biebl@debian.org>. (Closes: #826242)
-- Christian Hofstaedtler <zeha@debian.org> Fri, 01 Jul 2016 13:41:11 +0000
dnsmasq (2.76-1) unstable; urgency=low
* New upstream. (closes: #798586)
* Use /run/dnsmasq directly, rather than relying on link from /var/run
to avoid problems before /var is mounted. (closes: #800351)
* Test for the existence of /usr/share/doc/dnsmasq rather then
/etc/dnsmasq.d/README in the daemon startup script. (closes: #819856)
* Add --help to manpage and mention dhcp6 in summary. (closes: #821226)
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 10 Sep 2015 23:07:21 +0000
dnsmasq (2.75-1) unstable; urgency=low
* New upstream. (closes: #794095)
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 30 Jul 2015 20:58:31 +0000
dnsmasq (2.74-1) unstable; urgency=low
* New upstream. (LP: #1468611)
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 15 Jul 2015 21:54:11 +0000
dnsmasq (2.73-2) unstable; urgency=low
* Fix behaviour of empty --conf-file (closes: #790341)
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 7 Jul 2015 21:46:42 +0000
dnsmasq (2.73-1) unstable; urgency=low
* New upstream. (closes: #786996)
* Tweak field width in cache dump to avoid truncating IPv6
addresses. (closes: #771557)
* Add newline at the end of example config file. (LP: #1416895)
* Make Debian package build reproducible. (closes: #777323)
* Add Requires=network.target to systemd unit.
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 4 Jun 2015 22:31:42 +0000
dnsmasq (2.72-3) unstable; urgency=medium
* debian/systemd.service: switch from Type=dbus to Type=forking.
dnsmasq does not depend on dbus, but Type=dbus systemd services cannot
work without it. (Closes: #769486, #776530)
- debian/init: when called with systemd-exec argument, let dnsmasq
go into the background, so Type=forking can detect when it is ready
* Remove line containing only whitespace in debian/control.
(closes: #777571)
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 11 Feb 2015 21:56:12 +0000
dnsmasq (2.72-2) unstable; urgency=low
* Fix build in Debian-kFreeBSD. (closes: #763693)
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 02 Oct 2014 22:34:12 +0000
dnsmasq (2.72-1) unstable; urgency=low
* New upstream.
* If dns-root-data package is installed, use it to set the DNSSEC
trust anchor(s). Recommend dns-root-data. (closes: #760460)
* Handle AD bit correctly in replies from cache. (closes: #761654)
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 20 May 2014 21:01:11 +0000
dnsmasq (2.71-1) unstable; urgency=low
* New upstream.
* Fix 100% CPU-usage bug when dnsmasq started with cachesize
set to zero. (LP: #1314697)
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 16 May 2014 20:17:10 +0000
dnsmasq (2.70-3) unstable; urgency=medium
* Write a pid-file, even when being started using systemd, since
other components may wish to signal dnsmasq.
* Enable dnsmasq systemd unit on install. Otherwise dnsmasq does not run on
fresh installations (without administrator handholding) and even worse it
is disabled on systems switching from sysv to systemd. Modify
postinst/postrm exactly as dh_systemd would, add dependency on
init-system-helpers. Closes: #724602
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 11 May 2014 17:45:21 +0000
dnsmasq (2.70-2) unstable; urgency=low
* Ensure daemon not stared if dnsmasq package has been removed,
even if dnsmasq-base is still installed. (closes: #746941)
* Tidy cruft in initscript. (closes: #746940)
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 04 May 2014 21:34:11 +0000
dnsmasq (2.70-1) unstable; urgency=low
* New upstream.
@@ -562,7 +733,7 @@ dnsmasq (2.26-1) unstable; urgency=high
dnsmasq (2.25-1) unstable; urgency=low
* Remove bashisms in postinst and prerm scripts.
* Remove misconcieved dependency on locales.
* Remove misconceived dependency on locales.
* Depend on adduser.
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 01 Dec 2005 21:02:12 +0000
@@ -584,7 +755,7 @@ dnsmasq (2.23-1) unstable; urgency=low
* Add support for DNSMASQ_EXCEPT in /etc/defaults/dnsmasq.
putting "lo" in this also disables resolvconf support.
* No longer delete pre-existing /etc/init.d symlinks. The
change in default runlevels which neccesitated this
change in default runlevels which necessitated this
is now ancient history and anyway the startup script now
behaves when called twice. (closes: #312111)
* Tightened config-file parser. (closes: #317030)
@@ -769,7 +940,7 @@ dnsmasq (2.6-3) unstable; urgency=low
* Removed reload command from start script and moved force-reload
to be equivalent to restart. This is needed to be policy compliant
since SIHGUP doesn't cause dnsmasq to reload its configuration file,
since SIGHUP doesn't cause dnsmasq to reload its configuration file,
only the /etc/hosts, /etc/resolv.conf etc. (closes: #244208)
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 18 Apr 2004 14:40:51 +0000
@@ -859,8 +1030,8 @@ dnsmasq (2.0-1) unstable; urgency=low
* New upstream: This removes the ability to read the
the leases file of ISC DHCP and replaces it with a built-in
DHCP server. Apologies in advance for breaking backwards
compatibilty, but this replaces a bit of a hack (the ISC stuff)
with a nicely engineered and much more apropriate solution.
compatibility, but this replaces a bit of a hack (the ISC stuff)
with a nicely engineered and much more appropriate solution.
Wearing my upstream-maintainer hat, I want to lose the hack now,
rather than have to support it into Sarge.
* New upstream closes some bugs since they become
@@ -886,7 +1057,7 @@ dnsmasq (1.18-1) unstable; urgency=low
* New upstream which does round-robin. (closes: #215460)
* Removed conflicts with other dns servers since it is now
possible to control exactly where dnsmasq listens on multi-homed
hosts, making co-existance with another nameserver
hosts, making co-existence with another nameserver
a viable proposition. (closes #176163)
* New upstream allows _ in hostnames and check for illegal
names in /etc/hosts. (closes: #218842)
@@ -972,13 +1143,13 @@ dnsmasq (1.11-2) unstable; urgency=low
dnsmasq (1.11-1) unstable; urgency=low
* New uptream.
* New upstream.
-- Simon Kelley <simon@thekelleys.org.uk> Tues, 12 Jan 2003 22:25:17 -0100
dnsmasq (1.10-1) unstable; urgency=low
* New uptream.
* New upstream.
* Force service to stop in postinst before restarting. I don't
understand the circumstances under which it would still be running at
this point, but this is the correct fix anyway. (closes: #169718)
@@ -990,7 +1161,7 @@ dnsmasq (1.10-1) unstable; urgency=low
dnsmasq (1.9-1) unstable; urgency=low
* New uptream.
* New upstream.
-- Simon Kelley <simon@thekelleys.org.uk> Mon, 23 Sept 2002 21:35:07 -0100

11
debian/control vendored
View File

@@ -2,13 +2,15 @@ Source: dnsmasq
Section: net
Priority: optional
Build-depends: gettext, libnetfilter-conntrack-dev [linux-any],
libidn11-dev, libdbus-1-dev (>=0.61), libgmp-dev, nettle-dev (>=2.4-3)
libidn11-dev, libdbus-1-dev (>=0.61), libgmp-dev,
nettle-dev (>=2.4-3), libbsd-dev [!linux-any]
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
Standards-Version: 3.9.3
Standards-Version: 3.9.8
Package: dnsmasq
Architecture: all
Depends: netbase, dnsmasq-base(>= ${binary:Version})
Depends: netbase, dnsmasq-base(>= ${binary:Version}),
init-system-helpers (>= 1.18~), lsb-base (>= 3.0-6)
Suggests: resolvconf
Conflicts: resolvconf (<<1.15)
Description: Small caching DNS proxy and DHCP/TFTP server
@@ -26,6 +28,7 @@ Architecture: any
Depends: adduser, ${shlibs:Depends}
Breaks: dnsmasq (<< 2.63-1~)
Replaces: dnsmasq (<< 2.63-1~)
Recommends: dns-root-data
Description: Small caching DNS proxy and DHCP/TFTP server
This package contains the dnsmasq executable and documentation, but
not the infrastructure required to run it as a system daemon. For
@@ -39,5 +42,3 @@ Description: Utilities for manipulating DHCP leases
Small utilities to query a DHCP server's lease database and
remove leases from it. These programs are distributed with dnsmasq
and may not work correctly with other DHCP servers.

2
debian/copyright vendored
View File

@@ -1,4 +1,4 @@
dnsmasq is Copyright (c) 2000-2013 Simon Kelley
dnsmasq is Copyright (c) 2000-2016 Simon Kelley
It was downloaded from: http://www.thekelleys.org.uk/dnsmasq/

View File

@@ -17,8 +17,8 @@ if [ "$1" = "configure" ]; then
# dnsmasq-base, but it's much easier to create it here so that
# we don't have synchronisation issues with the creation of the
# dnsmasq user.
if [ ! -d /var/run/dnsmasq ]; then
mkdir /var/run/dnsmasq
chown dnsmasq:nogroup /var/run/dnsmasq
if [ ! -d /run/dnsmasq ]; then
mkdir /run/dnsmasq
chown dnsmasq:nogroup /run/dnsmasq
fi
fi

View File

@@ -7,5 +7,5 @@ if [ purge = "$1" ]; then
else
echo >&2 "not removing dnsmasq system account because deluser command was not found"
fi
rm -rf /var/run/dnsmasq
rm -rf /run/dnsmasq
fi

62
debian/init vendored
View File

@@ -8,7 +8,8 @@
# Description: DHCP and DNS server
### END INIT INFO
set +e # Don't exit on error status
# Don't exit on error status
set +e
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/dnsmasq
@@ -29,6 +30,11 @@ if [ -r /etc/default/locale ]; then
export LANG
fi
# The following test ensures the dnsmasq service is not started, when the
# package 'dnsmasq' is removed but not purged, even if the dnsmasq-base
# package is still in place.
test -e /usr/share/dnsmasq/installed-marker || exit 0
test -x $DAEMON || exit 0
# Provide skeleton LSB log functions for backports which don't have LSB functions.
@@ -75,7 +81,7 @@ if [ ! "$RESOLV_CONF" ] &&
[ "$IGNORE_RESOLVCONF" != "yes" ] &&
[ -x /sbin/resolvconf ]
then
RESOLV_CONF=/var/run/dnsmasq/resolv.conf
RESOLV_CONF=/run/dnsmasq/resolv.conf
fi
for INTERFACE in $DNSMASQ_INTERFACE; do
@@ -98,6 +104,16 @@ fi
DNSMASQ_OPTS="$DNSMASQ_OPTS --local-service"
# If the dns-root-data package is installed, then the trust anchors will be
# available in $ROOT_DS, in BIND zone-file format. Reformat as dnsmasq
# --trust-anchor options.
ROOT_DS="/usr/share/dns/root.ds"
if [ -f $ROOT_DS ]; then
DNSMASQ_OPTS="$DNSMASQ_OPTS `sed -rne "s/^([.a-ZA-Z0-9]+)([[:space:]]+[0-9]+)*([[:space:]]+IN)*[[:space:]]+DS[[:space:]]+/--trust-anchor=\1,/;s/[[:space:]]+/,/gp" $ROOT_DS | tr '\n' ' '`"
fi
start()
{
# Return
@@ -105,16 +121,16 @@ start()
# 1 if daemon was already running
# 2 if daemon could not be started
# /var/run may be volatile, so we need to ensure that
# /var/run/dnsmasq exists here as well as in postinst
if [ ! -d /var/run/dnsmasq ]; then
mkdir /var/run/dnsmasq || return 2
chown dnsmasq:nogroup /var/run/dnsmasq || return 2
# /run may be volatile, so we need to ensure that
# /run/dnsmasq exists here as well as in postinst
if [ ! -d /run/dnsmasq ]; then
mkdir /run/dnsmasq || return 2
chown dnsmasq:nogroup /run/dnsmasq || return 2
fi
start-stop-daemon --start --quiet --pidfile /var/run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null || return 1
start-stop-daemon --start --quiet --pidfile /var/run/dnsmasq/$NAME.pid --exec $DAEMON -- \
-x /var/run/dnsmasq/$NAME.pid \
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null || return 1
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/$NAME.pid --exec $DAEMON -- \
-x /run/dnsmasq/$NAME.pid \
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
${MAILTARGET:+ -t $MAILTARGET} \
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \
@@ -138,6 +154,11 @@ start_resolvconf()
[ $interface = lo ] && return
done
# Also skip this if DNS functionality is disabled in /etc/dnsmasq.conf
if grep -qs '^port=0' /etc/dnsmasq.conf; then
return
fi
if [ -x /sbin/resolvconf ] ; then
echo "nameserver 127.0.0.1" | /sbin/resolvconf -a lo.$NAME
fi
@@ -151,10 +172,7 @@ stop()
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile /var/run/dnsmasq/$NAME.pid --name $NAME
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
return "$RETVAL"
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile /run/dnsmasq/$NAME.pid --name $NAME
}
stop_resolvconf()
@@ -172,9 +190,9 @@ status()
# 1 if daemon is dead and pid file exists
# 3 if daemon is not running
# 4 if daemon status is unknown
start-stop-daemon --start --quiet --pidfile /var/run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null
case "$?" in
0) [ -e "/var/run/dnsmasq/$NAME.pid" ] && return 1 ; return 3 ;;
0) [ -e "/run/dnsmasq/$NAME.pid" ] && return 1 ; return 3 ;;
1) return 0 ;;
*) return 4 ;;
esac
@@ -265,7 +283,7 @@ case "$1" in
esac
;;
dump-stats)
kill -s USR1 `cat /var/run/dnsmasq/$NAME.pid`
kill -s USR1 `cat /run/dnsmasq/$NAME.pid`
;;
systemd-start-resolvconf)
start_resolvconf
@@ -274,9 +292,13 @@ case "$1" in
stop_resolvconf
;;
systemd-exec)
# --pid-file without argument disables writing a PIDfile, we don't need one with sytemd.
# Enable DBus by default because we use DBus activation with systemd.
exec $DAEMON --keep-in-foreground --pid-file --enable-dbus \
# /run may be volatile, so we need to ensure that
# /run/dnsmasq exists here as well as in postinst
if [ ! -d /run/dnsmasq ]; then
mkdir /run/dnsmasq || return 2
chown dnsmasq:nogroup /run/dnsmasq || return 2
fi
exec $DAEMON -x /run/dnsmasq/$NAME.pid \
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
${MAILTARGET:+ -t $MAILTARGET} \
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \

2
debian/installed-marker vendored Normal file
View File

@@ -0,0 +1,2 @@
# This file indicates dnsmasq (and not just dnsmasq-base) is installed.
# It is an implementation detail of the dnsmasq init script.

18
debian/postinst vendored
View File

@@ -1,11 +1,27 @@
#!/bin/sh
set -e
# Code copied from dh_systemd_enable ----------------------
# This will only remove masks created by d-s-h on package removal.
deb-systemd-helper unmask dnsmasq.service >/dev/null || true
# was-enabled defaults to true, so new installations run enable.
if deb-systemd-helper --quiet was-enabled dnsmasq.service; then
# Enables the unit on first installation, creates new
# symlinks on upgrades if the unit file has changed.
deb-systemd-helper enable dnsmasq.service >/dev/null || true
else
# Update the statefile to add new symlinks (if any), which need to be
# cleaned up on purge. Also remove old symlinks.
deb-systemd-helper update-state dnsmasq.service >/dev/null || true
fi
# End code copied from dh_systemd_enable ------------------
if [ -x /etc/init.d/dnsmasq ]; then
update-rc.d dnsmasq defaults 15 85 >/dev/null
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then
if [ -e /var/run/dnsmasq/dnsmasq.pid ]; then
if [ -e /run/dnsmasq/dnsmasq.pid ]; then
ACTION=restart
else
ACTION=start

16
debian/postrm vendored
View File

@@ -4,3 +4,19 @@ set -e
if [ purge = "$1" ]; then
update-rc.d dnsmasq remove >/dev/null
fi
# Code copied from dh_systemd_enable ----------------------
if [ "$1" = "remove" ]; then
if [ -x "/usr/bin/deb-systemd-helper" ]; then
deb-systemd-helper mask dnsmasq.service >/dev/null
fi
fi
if [ "$1" = "purge" ]; then
if [ -x "/usr/bin/deb-systemd-helper" ]; then
deb-systemd-helper purge dnsmasq.service >/dev/null
deb-systemd-helper unmask dnsmasq.service >/dev/null
fi
fi
# End code copied from dh_systemd_enable ------------------

4
debian/readme vendored
View File

@@ -31,7 +31,7 @@ Notes on configuring dnsmasq as packaged for Debian.
as the first nameserver address in /etc/resolv.conf.
(6) In the absence of resolvconf, dns-nameservers lines in
/etc/network/interfaces are ignored. If you do do not use
/etc/network/interfaces are ignored. If you do not use
resolvconf, list 127.0.0.1 as the first nameserver address
in /etc/resolv.conf and configure your nameservers using
"server=<IP-address>" lines in /etc/dnsmasq.conf.
@@ -66,7 +66,7 @@ Notes on configuring dnsmasq as packaged for Debian.
combined with noi18n to be effective.
gitversion : set the version of the produced packages from the
git-derived versioning information on the source,
rather the the debian changelog.
rather than the debian changelog.
(9) Dnsmasq comes as three packages - dnsmasq-utils, dnsmasq-base and
dnsmasq. Dnsmasq-base provides the dnsmasq executable and

2
debian/resolvconf vendored
View File

@@ -13,7 +13,7 @@
set -e
RUN_DIR="/var/run/dnsmasq"
RUN_DIR="/run/dnsmasq"
RSLVRLIST_FILE="${RUN_DIR}/resolv.conf"
TMP_FILE="${RSLVRLIST_FILE}_new.$$"
MY_NAME_FOR_RESOLVCONF="dnsmasq"

104
debian/rules vendored
View File

@@ -11,21 +11,33 @@
package=dnsmasq-base
CFLAGS = $(shell export DEB_BUILD_OPTIONS=$(DEB_BUILD_OPTIONS); dpkg-buildflags --get CFLAGS)
CFLAGS += $(shell dpkg-buildflags --get CPPFLAGS)
dpkg_buildflags := DEB_BUILD_MAINT_OPTIONS="hardening=+all,+pie,+bindnow" dpkg-buildflags
CFLAGS = $(shell $(dpkg_buildflags) --get CFLAGS)
CFLAGS += $(shell $(dpkg_buildflags) --get CPPFLAGS)
CFLAGS += -Wall -W
LDFLAGS = $(shell dpkg-buildflags --get LDFLAGS)
LDFLAGS = $(shell $(dpkg_buildflags) --get LDFLAGS)
DEB_COPTS = $(COPTS)
# The nettle library in Debian is too old to include
# ECC support.
DEB_COPTS += -DNO_NETTLE_ECC
TARGET = install-i18n
DEB_BUILD_ARCH_OS := $(shell dpkg-architecture -qDEB_BUILD_ARCH_OS)
DEB_HOST_ARCH_OS := $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
DEB_HOST_GNU_TYPE := $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE := $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
BUILD_DATE := $(shell dpkg-parsechangelog --show-field Date)
ifeq ($(origin CC),default)
CC = $(DEB_HOST_GNU_TYPE)-gcc
endif
# Support non-cross-builds on systems without gnu-triplet-binaries for pkg-config.
ifeq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
PKG_CONFIG=pkg-config
else
PKG_CONFIG=$(DEB_HOST_GNU_TYPE)-pkg-config
endif
# Force package version based on git tags.
ifneq (,$(filter gitversion,$(DEB_BUILD_OPTIONS)))
@@ -36,8 +48,12 @@ ifeq (,$(filter nodbus,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DHAVE_DBUS
endif
ifeq (,$(filter noidn, $(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DHAVE_IDN
endif
ifeq (,$(filter noconntrack,$(DEB_BUILD_OPTIONS)))
ifeq ($(DEB_BUILD_ARCH_OS),linux)
ifeq ($(DEB_HOST_ARCH_OS),linux)
DEB_COPTS += -DHAVE_CONNTRACK
endif
endif
@@ -72,9 +88,6 @@ endif
ifneq (,$(filter noi18n,$(DEB_BUILD_OPTIONS)))
TARGET = install
ifeq (,$(filter noidn, $(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DHAVE_IDN
endif
endif
ifneq (,$(filter uselua,$(DEB_BUILD_OPTIONS)))
@@ -85,11 +98,16 @@ ifeq (,$(filter nodnssec,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DHAVE_DNSSEC
endif
ifneq ($(DEB_HOST_ARCH_OS),linux)
# For strlcpy in FreeBSD
LDFLAGS += -lbsd
endif
clean:
$(checkdir)
rm -rf debian/daemon debian/base debian/utils debian/*~ debian/files debian/substvars debian/utils-substvars
make clean
make -C contrib/wrt clean
make -C contrib/lease-tools clean
binary-indep: checkroot
$(checkdir)
@@ -101,6 +119,7 @@ binary-indep: checkroot
-d debian/daemon/etc/dnsmasq.d \
-d debian/daemon/etc/resolvconf/update.d \
-d debian/daemon/usr/lib/resolvconf/dpkg-event.d \
-d debian/daemon/usr/share/dnsmasq \
-d debian/daemon/etc/default \
-d debian/daemon/lib/systemd/system \
-d debian/daemon/etc/insserv.conf.d
@@ -109,14 +128,16 @@ binary-indep: checkroot
install -m 755 debian/init debian/daemon/etc/init.d/dnsmasq
install -m 755 debian/resolvconf debian/daemon/etc/resolvconf/update.d/dnsmasq
install -m 755 debian/resolvconf-package debian/daemon/usr/lib/resolvconf/dpkg-event.d/dnsmasq
install -m 644 debian/installed-marker debian/daemon/usr/share/dnsmasq
install -m 644 debian/default debian/daemon/etc/default/dnsmasq
install -m 644 dnsmasq.conf.example debian/daemon/etc/dnsmasq.conf
install -m 644 debian/readme.dnsmasq.d debian/daemon/etc/dnsmasq.d/README
install -m 644 debian/systemd.service debian/daemon/lib/systemd/system/dnsmasq.service
install -m 644 debian/insserv debian/daemon/etc/insserv.conf.d/dnsmasq
ln -s $(package) debian/daemon/usr/share/doc/dnsmasq
cd debian/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | xargs -r0 md5sum > DEBIAN/md5sums
cd debian/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
dpkg-gencontrol $(PACKAGE_VERSION) -T -pdnsmasq -Pdebian/daemon
find debian/daemon -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
chown -R root.root debian/daemon
chmod -R g-ws debian/daemon
dpkg --build debian/daemon ..
@@ -129,71 +150,78 @@ binary-arch: checkroot
-d debian/base/etc/dbus-1/system.d \
-d debian/base/usr/share/doc/$(package) \
-d debian/base/usr/share/doc/$(package)/examples \
-d debian/base/var/run \
-d debian/base/usr/share/$(package) \
-d debian/base/var/lib/misc
make $(TARGET) PREFIX=/usr DESTDIR=`pwd`/debian/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=gcc
make $(TARGET) PREFIX=/usr DESTDIR=`pwd`/debian/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
install -m 644 doc.html debian/base/usr/share/doc/$(package)/.
# Need to remove paypal links in Debian Package for policy reasons.
sed -e /\<H2\>Donations/Q -e /icon.png/d doc.html -e /favicon.ico/d >debian/base/usr/share/doc/$(package)/doc.html
echo "</BODY>" >>debian/base/usr/share/doc/$(package)/doc.html
install -m 644 setup.html debian/base/usr/share/doc/$(package)/.
install -m 644 dnsmasq.conf.example debian/base/usr/share/doc/$(package)/examples/.
install -m 644 trust-anchors.conf debian/base/usr/share/$(package)/.
install -m 644 FAQ debian/base/usr/share/doc/$(package)/.
gzip -9 debian/base/usr/share/doc/$(package)/FAQ
gzip -9n debian/base/usr/share/doc/$(package)/FAQ
install -m 644 CHANGELOG debian/base/usr/share/doc/$(package)/changelog
gzip -9 debian/base/usr/share/doc/$(package)/changelog
gzip -9n debian/base/usr/share/doc/$(package)/changelog
install -m 644 CHANGELOG.archive debian/base/usr/share/doc/$(package)/changelog.archive
gzip -9 debian/base/usr/share/doc/$(package)/changelog.archive
gzip -9n debian/base/usr/share/doc/$(package)/changelog.archive
install -m 644 dbus/DBus-interface debian/base/usr/share/doc/$(package)/.
gzip -9 debian/base/usr/share/doc/$(package)/DBus-interface
gzip -9n debian/base/usr/share/doc/$(package)/DBus-interface
endif
install -m 644 debian/dnsmasq-base.conffiles debian/base/DEBIAN/conffiles
install -m 755 debian/dnsmasq-base.postinst debian/base/DEBIAN/postinst
install -m 755 debian/dnsmasq-base.postrm debian/base/DEBIAN/postrm
install -m 644 debian/changelog debian/base/usr/share/doc/$(package)/changelog.Debian
gzip -9 debian/base/usr/share/doc/$(package)/changelog.Debian
gzip -9n debian/base/usr/share/doc/$(package)/changelog.Debian
install -m 644 debian/readme debian/base/usr/share/doc/$(package)/README.Debian
install -m 644 debian/copyright debian/base/usr/share/doc/$(package)/copyright
install -m 644 debian/dbus.conf debian/base/etc/dbus-1/system.d/dnsmasq.conf
gzip -9 debian/base/usr/share/man/man8/dnsmasq.8
gzip -9n debian/base/usr/share/man/man8/dnsmasq.8
for f in debian/base/usr/share/man/*; do \
if [ -f $$f/man8/dnsmasq.8 ]; then \
gzip -9 $$f/man8/dnsmasq.8 ; \
gzip -9n $$f/man8/dnsmasq.8 ; \
fi \
done
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
strip -R .note -R .comment debian/base/usr/sbin/dnsmasq
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/base/usr/sbin/dnsmasq
endif
cd debian/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | xargs -r0 md5sum > DEBIAN/md5sums
cd debian/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
dpkg-shlibdeps --warnings=1 debian/base/usr/sbin/dnsmasq
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base -Pdebian/base
find debian/base -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
chown -R root.root debian/base
chmod -R g-ws debian/base
dpkg --build debian/base ..
ifeq ($(DEB_BUILD_ARCH_OS),linux)
ifeq ($(DEB_HOST_ARCH_OS),linux)
rm -rf debian/utils
install -m 755 -d debian/utils/DEBIAN \
-d debian/utils/usr/share/man/man1 \
-d debian/utils/usr/bin \
-d debian/utils/usr/share/doc/dnsmasq-utils
make -C contrib/wrt PREFIX=/usr DESTDIR=`pwd`/debian/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=gcc
install -m 755 contrib/wrt/dhcp_release debian/utils/usr/bin/dhcp_release
install -m 644 contrib/wrt/dhcp_release.1 debian/utils/usr/share/man/man1/dhcp_release.1
gzip -9 debian/utils/usr/share/man/man1/dhcp_release.1
install -m 755 contrib/wrt/dhcp_lease_time debian/utils/usr/bin/dhcp_lease_time
install -m 644 contrib/wrt/dhcp_lease_time.1 debian/utils/usr/share/man/man1/dhcp_lease_time.1
make -C contrib/lease-tools PREFIX=/usr DESTDIR=`pwd`/debian/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
install -m 755 contrib/lease-tools/dhcp_release debian/utils/usr/bin/dhcp_release
install -m 644 contrib/lease-tools/dhcp_release.1 debian/utils/usr/share/man/man1/dhcp_release.1
gzip -9n debian/utils/usr/share/man/man1/dhcp_release.1
install -m 755 contrib/lease-tools/dhcp_release6 debian/utils/usr/bin/dhcp_release6
install -m 644 contrib/lease-tools/dhcp_release6.1 debian/utils/usr/share/man/man1/dhcp_release6.1
gzip -9n debian/utils/usr/share/man/man1/dhcp_release6.1
install -m 755 contrib/lease-tools/dhcp_lease_time debian/utils/usr/bin/dhcp_lease_time
install -m 644 contrib/lease-tools/dhcp_lease_time.1 debian/utils/usr/share/man/man1/dhcp_lease_time.1
install -m 644 debian/copyright debian/utils/usr/share/doc/dnsmasq-utils/copyright
install -m 644 debian/changelog debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
gzip -9 debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
gzip -9 debian/utils/usr/share/man/man1/dhcp_lease_time.1
gzip -9n debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
gzip -9n debian/utils/usr/share/man/man1/dhcp_lease_time.1
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
strip -R .note -R .comment debian/utils/usr/bin/dhcp_release
strip -R .note -R .comment debian/utils/usr/bin/dhcp_lease_time
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/utils/usr/bin/dhcp_release
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/utils/usr/bin/dhcp_release6
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/utils/usr/bin/dhcp_lease_time
endif
cd debian/utils && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | xargs -r0 md5sum > DEBIAN/md5sums
cd debian/utils && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
dpkg-shlibdeps -Tdebian/utils-substvars debian/utils/usr/bin/dhcp_release debian/utils/usr/bin/dhcp_lease_time
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/utils-substvars -pdnsmasq-utils -Pdebian/utils
find debian/utils -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
chown -R root.root debian/utils
chmod -R g-ws debian/utils
dpkg --build debian/utils ..

1
debian/shlibs.local vendored Normal file
View File

@@ -0,0 +1 @@
libnettle 6 libnettle6 (>= 3.3)

View File

@@ -1,9 +1,13 @@
[Unit]
Description=A lightweight DHCP and caching DNS server
Description=dnsmasq - A lightweight DHCP and caching DNS server
Requires=network.target
Wants=nss-lookup.target
Before=nss-lookup.target
After=network.target
[Service]
Type=dbus
BusName=uk.org.thekelleys.dnsmasq
Type=forking
PIDFile=/run/dnsmasq/dnsmasq.pid
# Test the config file and refuse starting if it is not valid.
ExecStartPre=/usr/sbin/dnsmasq --test
@@ -11,16 +15,10 @@ ExecStartPre=/usr/sbin/dnsmasq --test
# We run dnsmasq via the /etc/init.d/dnsmasq script which acts as a
# wrapper picking up extra configuration files and then execs dnsmasq
# itself, when called with the "systemd-exec" function.
#
# It also adds the command-line flags
# --keep-in-foreground --pid-file --enable-dbus
# to disable writing a pid-file (not needed with systemd) and
# enable DBus by default because we use DBus activation.
#
ExecStart=/etc/init.d/dnsmasq systemd-exec
# The systemd-*-resolvconf functions configure (and deconfigure)
# resolvconf to work with the dnsmasq DNS server. They're called liek
# resolvconf to work with the dnsmasq DNS server. They're called like
# this to get correct error handling (ie don't start-resolvconf if the
# dnsmasq daemon fails to start.
ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf

View File

@@ -189,7 +189,7 @@
# add names to the DNS for the IPv6 address of SLAAC-configured dual-stack
# hosts. Use the DHCPv4 lease to derive the name, network segment and
# MAC address and assume that the host will also have an
# IPv6 address calculated using the SLAAC alogrithm.
# IPv6 address calculated using the SLAAC algorithm.
#dhcp-range=1234::, ra-names
# Do Router Advertisements, BUT NOT DHCP for this subnet.
@@ -210,7 +210,7 @@
#dhcp-range=1234::, ra-stateless, ra-names
# Do router advertisements for all subnets where we're doing DHCPv6
# Unless overriden by ra-stateless, ra-names, et al, the router
# Unless overridden by ra-stateless, ra-names, et al, the router
# advertisements will have the M and O bits set, so that the clients
# get addresses and configuration from DHCPv6, and the A bit reset, so the
# clients don't use SLAAC addresses.
@@ -251,6 +251,13 @@
# the IP address 192.168.0.60
#dhcp-host=id:01:02:02:04,192.168.0.60
# Always give the InfiniBand interface with hardware address
# 80:00:00:48:fe:80:00:00:00:00:00:00:f4:52:14:03:00:28:05:81 the
# ip address 192.168.0.61. The client id is derived from the prefix
# ff:00:00:00:00:00:02:00:00:02:c9:00 and the last 8 pairs of
# hex digits of the hardware address.
#dhcp-host=id:ff:00:00:00:00:00:02:00:00:02:c9:00:f4:52:14:03:00:28:05:81,192.168.0.61
# Always give the host with client identifier "marjorie"
# the IP address 192.168.0.60
#dhcp-host=id:marjorie,192.168.0.60
@@ -281,7 +288,7 @@
# Give a fixed IPv6 address and name to client with
# DUID 00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2
# Note the MAC addresses CANNOT be used to identify DHCPv6 clients.
# Note also the they [] around the IPv6 address are obilgatory.
# Note also the they [] around the IPv6 address are obligatory.
#dhcp-host=id:00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2, fred, [1234::5]
# Ignore any clients which are not specified in dhcp-host lines
@@ -345,6 +352,14 @@
# Ask client to poll for option changes every six hours. (RFC4242)
#dhcp-option=option6:information-refresh-time,6h
# Set option 58 client renewal time (T1). Defaults to half of the
# lease time if not specified. (RFC2132)
#dhcp-option=option:T1:1m
# Set option 59 rebinding time (T2). Defaults to 7/8 of the
# lease time if not specified. (RFC2132)
#dhcp-option=option:T2:2m
# Set the NTP time server address to be the same machine as
# is running dnsmasq
#dhcp-option=42,0.0.0.0
@@ -486,6 +501,9 @@
# Set the root directory for files available via FTP.
#tftp-root=/var/ftpd
# Do not abort if the tftp-root is unavailable
#tftp-no-fail
# Make the TFTP server more secure: with this set, only files owned by
# the user dnsmasq is running as will be send over the net.
#tftp-secure
@@ -507,7 +525,7 @@
# (using /etc/hosts) then that name can be specified as the
# tftp_servername (the third option to dhcp-boot) and in that
# case dnsmasq resolves this name and returns the resultant IP
# addresses in round robin fasion. This facility can be used to
# addresses in round robin fashion. This facility can be used to
# load balance the tftp load among a set of servers.
#dhcp-boot=/var/ftpd/pxelinux.0,boothost,tftp_server_name
@@ -640,3 +658,9 @@
# Include another lot of configuration options.
#conf-file=/etc/dnsmasq.more.conf
#conf-dir=/etc/dnsmasq.d
# Include all the files in a directory except those ending in .bak
#conf-dir=/etc/dnsmasq.d,.bak
# Include all files in a directory which end in .conf
#conf-dir=/etc/dnsmasq.d/,*.conf

View File

@@ -1,8 +1,7 @@
<HTML>
<HEAD>
<TITLE> Dnsmasq - network services for small networks.</TITLE>
<link rel="icon"
href="http://www.thekelleys.org.uk/dnsmasq/images/favicon.ico">
<link rel="icon" href="http://www.thekelleys.org.uk/dnsmasq/images/favicon.ico">
</HEAD>
<BODY BGCOLOR="WHITE">
<table width="100%" border="0" cellpadding="0" cellspacing="0">
@@ -19,7 +18,7 @@ Linux distributions and the ports systems of FreeBSD, OpenBSD and NetBSD. Dnsmas
<P>
The DNS subsystem provides a local DNS server for the network, with forwarding of all query types to upstream recursive DNS servers and
cacheing of common record types (A, AAAA, CNAME and PTR, also DNSKEY and DS when DNSSEC is enabled).
caching of common record types (A, AAAA, CNAME and PTR, also DNSKEY and DS when DNSSEC is enabled).
<DIR>
<LI>Local DNS names can be defined by reading /etc/hosts, by importing names from the DHCP subsystem, or by configuration of a wide range of useful record types.</LI>
<LI>Upstream servers can be configured in a variety of convenient ways, including dynamic configuration as these change on moving upstream network.
@@ -75,7 +74,9 @@ for details.
There is a dnsmasq mailing list at <A
HREF="http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss">
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss</A> which should be the
first location for queries, bugreports, suggestions etc.
first location for queries, bugreports, suggestions etc. The list is mirrored, with a
search facility, at <A HREF="https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/">
https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/</A>.
You can contact me at <A
HREF="mailto:simon@thekelleys.org.uk">simon@thekelleys.org.uk</A>.

View File

@@ -30,7 +30,7 @@ DHCPv4 server, and in addition, it includes router advertisements and
a neat feature which allows nameing for clients which use DHCPv4 and
stateless autoconfiguration only for IPv6 configuration. There is support for doing address allocation (both DHCPv6 and RA) from subnets which are dynamically delegated via DHCPv6 prefix delegation.
.PP
Dnsmasq is coded with small embedded systems in mind. It aims for the smallest possible memory footprint compatible with the supported functions, and allows uneeded functions to be omitted from the compiled binary.
Dnsmasq is coded with small embedded systems in mind. It aims for the smallest possible memory footprint compatible with the supported functions, and allows unneeded functions to be omitted from the compiled binary.
.SH OPTIONS
Note that in general missing parameters are allowed and switch off
functions, for instance "--pid-file" disables writing a PID file. On
@@ -42,6 +42,13 @@ the configuration file.
Read and syntax check configuration file(s). Exit with code 0 if all
is OK, or a non-zero code otherwise. Do not start up dnsmasq.
.TP
.B \-w, --help
Display all command-line options.
.B --help dhcp
will display known DHCPv4 configuration options, and
.B --help dhcp6
will display DHCPv6 options.
.TP
.B \-h, --no-hosts
Don't read the hostnames in /etc/hosts.
.TP
@@ -50,13 +57,17 @@ Additional hosts file. Read the specified file as well as /etc/hosts. If -h is g
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.
.TP
.B \-E, --expand-hosts
Add the domain to simple names (without a period) in /etc/hosts
in the same way as for DHCP-derived names. Note that this does not
apply to domain names in cnames, PTR records, TXT records etc.
.TP
.B \-T, --local-ttl=<time>
When replying with information from /etc/hosts or the DHCP leases
When replying with information from /etc/hosts or configuration or the DHCP leases
file dnsmasq by default sets the time-to-live field to zero, meaning
that the requester should not itself cache the information. This is
the correct thing to do in almost all situations. This option allows a
@@ -64,6 +75,9 @@ time-to-live (in seconds) to be given for these replies. This will
reduce the load on the server at the expense of clients using stale
data under some circumstances.
.TP
.B --dhcp-ttl=<time>
As for --local-ttl, but affects only replies with information from DHCP leases. If both are given, --dhcp-ttl applies for DHCP information, and --local-ttl for others. Setting this to zero eliminates the effect of --local-ttl for DHCP.
.TP
.B --neg-ttl=<time>
Negative replies from upstream servers normally contain time-to-live
information in SOA records which dnsmasq uses for caching. If the
@@ -81,6 +95,12 @@ the upstream DNS servers.
.B --max-cache-ttl=<time>
Set a maximum TTL value for entries in the cache.
.TP
.B --min-cache-ttl=<time>
Extend short TTL values to the time given when caching them. Note that
artificially extending TTL values is in general a bad idea, do not do it
unless you have a good reason, and understand what you are doing.
Dnsmasq limits the value of this option to one hour, unless recompiled.
.TP
.B --auth-ttl=<time>
Set the TTL value returned in answers from the authoritative server.
.TP
@@ -98,7 +118,10 @@ only, to stop dnsmasq daemonising in production, use
.B -k.
.TP
.B \-q, --log-queries
Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1.
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
.B --log-queries=extra
then the log has extra information at the start of each line.
This consists of a serial number which ties together the log lines associated with an individual query, and the IP address of the requestor.
.TP
.B \-8, --log-facility=<facility>
Set the facility to which dnsmasq will send syslog entries, this
@@ -161,6 +184,13 @@ queries. Dnsmasq picks random ports as source for outbound queries:
when this option is given, the ports used will always to larger
than that specified. Useful for systems behind firewalls.
.TP
.B --max-port=<port>
Use ports lower than that given as source for outbound DNS queries.
Dnsmasq picks random ports as source for outbound queries:
when this option is given, the ports used will always be lower
than that specified. Useful for systems behind firewalls.
.TP
.B \-i, --interface=<interface name>
Listen only on the specified interface(s). Dnsmasq automatically adds
the loopback (local) interface to the list of interfaces to use when
@@ -173,12 +203,17 @@ or
options are given dnsmasq listens on all available interfaces except any
given in
.B \--except-interface
options. IP alias interfaces (eg "eth1:0") cannot be used with
.B --interface
options. On Linux, when
.B \--bind-interfaces
or
.B --except-interface
options, use --listen-address instead. A simple wildcard, consisting
of a trailing '*', can be used in
.B \--bind-dynamic
are in effect, IP alias interface labels (eg "eth1:0") are checked, rather than
interface names. In the degenerate case when an interface has one address, this amounts to the same thing but when an interface has multiple addresses it
allows control over which of those addresses are accepted.
The same effect is achievable in default mode by using
.B \--listen-address.
A simple wildcard, consisting of a trailing '*',
can be used in
.B \--interface
and
.B \--except-interface
@@ -192,7 +227,9 @@ and
.B --except-interface
options does not matter and that
.B --except-interface
options always override the others.
options always override the others. The comments about interface labels for
.B --listen-address
apply here.
.TP
.B --auth-server=<domain>,<interface>|<ip-address>
Enable DNS authoritative mode for queries arriving at an interface or address. Note that the interface or address
@@ -202,7 +239,7 @@ or
.B --listen-address
configuration, indeed
.B --auth-server
will overide these and provide a different DNS service on the
will override these and provide a different DNS service on the
specified interface. The <domain> is the "glue record". It should
resolve in the global DNS to a A and/or AAAA record which points to
the address dnsmasq is listening on. When an interface is specified,
@@ -212,7 +249,7 @@ addresses associated with the interface.
.B --local-service
Accept DNS queries only from hosts whose address is on a local subnet,
ie a subnet for which an interface exists on the server. This option
only has effect is there are no --interface --except-interface,
only has effect if there are no --interface --except-interface,
--listen-address or --auth-server options. It is intended to be set as
a default on installation, to allow unconfigured installations to be
useful but also safe from being used for DNS amplification attacks.
@@ -259,8 +296,8 @@ option requires non-standard networking APIs and it is only available
under Linux. On other platforms it falls-back to --bind-interfaces mode.
.TP
.B \-y, --localise-queries
Return answers to DNS queries from /etc/hosts which depend on the interface over which the query was
received. If a name in /etc/hosts has more than one address associated with
Return answers to DNS queries from /etc/hosts and --interface-name which depend on the interface over which the query was
received. If a name has more than one address associated with
it, and at least one of those addresses is on the same subnet as the
interface to which the query was sent, then return only the
address(es) on that subnet. This allows for a server to have multiple
@@ -271,7 +308,8 @@ attached to. Currently this facility is limited to IPv4.
.B \-b, --bogus-priv
Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc)
which are not found in /etc/hosts or the DHCP leases file are answered
with "no such domain" rather than being forwarded upstream.
with "no such domain" rather than being forwarded upstream. The
set of prefixes affected is the list given in RFC6303, for IPv4 and IPv6.
.TP
.B \-V, --alias=[<old-ip>]|[<start-ip>-<end-ip>],<new-ip>[,<mask>]
Modify IPv4 addresses returned from upstream nameservers; old-ip is
@@ -293,6 +331,12 @@ an advertising web page in response to queries for unregistered names,
instead of the correct NXDOMAIN response. This option tells dnsmasq to
fake the correct response when it sees this behaviour. As at Sept 2003
the IP address being returned by Verisign is 64.94.110.11
.TP
.B --ignore-address=<ipaddr>
Ignore replies to A-record queries which include the specified address.
No error is generated, dnsmasq simply continues to listen for another reply.
This is useful to defeat blocking strategies which rely on quickly supplying a
forged answer to a DNS request for certain domain, before the correct answer can arrive.
.TP
.B \-f, --filterwin2k
Later versions of windows make periodic DNS requests which don't get sensible answers from
@@ -334,6 +378,16 @@ it will send queries to just one server. Setting this flag forces
dnsmasq to send all queries to all available servers. The reply from
the server which answers first will be returned to the original requester.
.TP
.B --dns-loop-detect
Enable code to detect DNS forwarding loops; ie the situation where a query sent to one
of the upstream server eventually returns as a new query to the dnsmasq instance. The
process works by generating TXT queries of the form <hex>.test and sending them to
each upstream server. The hex is a UID which encodes the instance of dnsmasq sending the query
and the upstream server to which it was sent. If the query returns to the server which sent it, then
the upstream server through which it was sent is disabled and this event is logged. Each time the
set of upstream servers changes, the test is re-run on all of them, including ones which
were previously disabled.
.TP
.B --stop-dns-rebind
Reject (and log) addresses from upstream nameservers which are in the
private IP ranges. This blocks an attack where a browser behind a
@@ -376,7 +430,10 @@ xxx.internal.thekelleys.org.uk at 192.168.1.1 then giving the flag
.B -S /internal.thekelleys.org.uk/192.168.1.1
will send all queries for
internal machines to that nameserver, everything else will go to the
servers in /etc/resolv.conf. An empty domain specification,
servers in /etc/resolv.conf. DNSSEC validation is turned off for such
private nameservers, UNLESS a
.B --trust-anchor
is specified for the domain in question. An empty domain specification,
.B //
has the special meaning of "unqualified names only" ie names without any
dots in them. A non-standard port may be specified as
@@ -385,7 +442,7 @@ address using a # character.
More than one -S flag is allowed, with
repeated domain or ipaddr parts as required.
More specific domains take precendence over less specific domains, so:
More specific domains take precedence over less specific domains, so:
.B --server=/google.com/1.2.3.4
.B --server=/www.google.com/2.3.4.5
will send queries for *.google.com to 1.2.3.4, except *www.google.com,
@@ -410,14 +467,14 @@ to make configuration files clearer in this case.
IPv6 addresses may include a %interface scope-id, eg
fe80::202:a412:4512:7bbf%eth0.
The optional string after the @ character tells
dnsmasq how to set the source of the queries to this
nameserver. It should be an ip-address, which should belong to the machine on which
dnsmasq is running otherwise this server line will be logged and then
ignored, or an interface name. If an interface name is given, then
queries to the server will be forced via that interface; if an
ip-address is given then the source address of the queries will be set
to that address.
The optional string after the @ character tells dnsmasq how to set the source of
the queries to this nameserver. It can either be an ip-address, an interface
name or both. The ip-address should belong to the machine on which dnsmasq is
running, otherwise this server line will be logged and then ignored. If an
interface name is given, then queries to the server will be forced via that
interface; if an ip-address is given then the source address of the queries will
be set to that address; and if both are given then a combination of ip-address
and interface name will be used to steer requests to the server.
The query-port flag is ignored for any servers which have a
source address specified but the port may be specified directly as
part of the source address. Forcing queries to an interface is not
@@ -431,25 +488,36 @@ but provides some syntactic sugar to make specifying address-to-name queries eas
is exactly equivalent to
.B --server=/3.2.1.in-addr.arpa/192.168.0.1
.TP
.B \-A, --address=/<domain>/[domain/]<ipaddr>
.B \-A, --address=/<domain>[/<domain>...]/[<ipaddr>]
Specify an IP address to return for any host in the given domains.
Queries in the domains are never forwarded and always replied to
with the specified IP address which may be IPv4 or IPv6. To give
both IPv4 and IPv6 addresses for a domain, use repeated -A flags.
both IPv4 and IPv6 addresses for a domain, use repeated \fB-A\fP flags.
To include multiple IP addresses for a single query, use
\fB--addn-hosts=<path>\fP instead.
Note that /etc/hosts and DHCP leases override this for individual
names. A common use of this is to redirect the entire doubleclick.net
domain to some friendly local web server to avoid banner ads. The
domain specification works in the same was as for --server, with the
additional facility that /#/ matches any domain. Thus
--address=/#/1.2.3.4 will always return 1.2.3.4 for any query not
answered from /etc/hosts or DHCP and not sent to an upstream
nameserver by a more specific --server directive.
domain specification works in the same was as for \fB--server\fP, with
the additional facility that \fB/#/\fP matches any domain. Thus
\fB--address=/#/1.2.3.4\fP will always return \fB1.2.3.4\fP for any
query not answered from \fB/etc/hosts\fP or DHCP and not sent to an
upstream nameserver by a more specific \fB--server\fP directive. As for
\fB--server\fP, one or more domains with no address returns a
no-such-domain answer, so \fB--address=/example.com/\fP is equivalent to
\fB--server=/example.com/\fP and returns NXDOMAIN for example.com and
all its subdomains.
.TP
.B --ipset=/<domain>/[domain/]<ipset>[,<ipset>]
Places the resolved IP addresses of queries for the specified domains
in the specified netfilter ip sets. Domains and subdomains are matched
in the same way as --address. These ip sets must already exist. See
ipset(8) for more details.
.B --ipset=/<domain>[/<domain>...]/<ipset>[,<ipset>...]
Places the resolved IP addresses of queries for one or more domains in
the specified Netfilter IP set. If multiple setnames are given, then the
addresses are placed in each of them, subject to the limitations of an
IP set (IPv4 addresses cannot be stored in an IPv6 IP set and vice
versa). Domains and subdomains are matched in the same way as
\fB--address\fP.
These IP sets must already exist. See
.BR ipset (8)
for more details.
.TP
.B \-m, --mx-host=<mx name>[[,<hostname>],<preference>]
Return an MX record named <mx name> pointing to the given hostname (if
@@ -487,7 +555,7 @@ zone files: the port, weight and priority numbers are in a different
order. More than one SRV record for a given service/domain is allowed,
all that match are returned.
.TP
.B --host-record=<name>[,<name>....][<IPv4-address>],[<IPv6-address>]
.B --host-record=<name>[,<name>....],[<IPv4-address>],[<IPv6-address>][,<TTL>]
Add A, AAAA and PTR records to the DNS. This adds one or more names to
the DNS with associated IPv4 (A) and IPv6 (AAAA) records. A name may
appear in more than one
@@ -504,6 +572,10 @@ is in effect. Short and long names may appear in the same
.B host-record,
eg.
.B --host-record=laptop,laptop.thekelleys.org,192.168.0.1,1234::100
If the time-to-live is given, it overrides the default, which is zero
or the value of --local-ttl. The value is a positive integer and gives
the time-to-live in seconds.
.TP
.B \-Y, --txt-record=<name>[[,<text>],<text>]
Return a TXT DNS record. The value of TXT record is a set of strings,
@@ -517,7 +589,7 @@ Return a PTR DNS record.
.B --naptr-record=<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<replacement>]
Return an NAPTR DNS record, as specified in RFC3403.
.TP
.B --cname=<cname>,<target>
.B --cname=<cname>,[<cname>,]<target>[,<TTL>]
Return a CNAME record which indicates that <cname> is really
<target>. There are significant limitations on the target; it must be a
DNS name which is known to dnsmasq from /etc/hosts (or additional
@@ -525,7 +597,13 @@ hosts files), from DHCP, from --interface-name or from another
.B --cname.
If the target does not satisfy this
criteria, the whole cname is ignored. The cname must be unique, but it
is permissable to have more than one cname pointing to the same target.
is permissable to have more than one cname pointing to the same target. Indeed
it's possible to declare multiple cnames to a target in a single line, like so:
.B --cname=cname1,cname2,target
If the time-to-live is given, it overrides the default, which is zero
or the value of -local-ttl. The value is a positive integer and gives
the time-to-live in seconds.
.TP
.B --dns-rr=<name>,<RR-number>,[<hex data>]
Return an arbitrary DNS Resource Record. The number is the type of the
@@ -534,7 +612,7 @@ given by the hex data, which may be of the form 01:23:45 or 01 23 45 or
012345 or any mixture of these.
.TP
.B --interface-name=<name>,<interface>[/4|/6]
Return a DNS record associating the name with the primary address on
Return DNS records associating the name with the address(es) of
the given interface. This flag specifies an A or AAAA record for the given
name in the same way as an /etc/hosts line, except that the address is
not constant, but taken from the given interface. The interface may be
@@ -544,7 +622,8 @@ down, not configured or non-existent, an empty record is returned. The
matching PTR record is also created, mapping the interface address to
the name. More than one name may be associated with an interface
address by repeating the flag; in that case the first instance is used
for the reverse address-to-name mapping.
for the reverse address-to-name mapping. Note that a name used in
--interface-name may not appear in /etc/hosts.
.TP
.B --synth-domain=<domain>,<address range>[,<prefix>]
Create artificial A/AAAA and PTR records for an address range. The
@@ -559,10 +638,12 @@ but IPv6 addresses may start with '::'
but DNS labels may not start with '-' so in this case if no prefix is
configured a zero is added in front of the label. ::1 becomes 0--1.
V4 mapped IPv6 addresses, which have a representation like ::ffff:1.2.3.4 are handled specially, and become like 0--ffff-1-2-3-4
The address range can be of the form
<ip address>,<ip address> or <ip address>/<netmask>
.TP
.B --add-mac
.B --add-mac[=base64|text]
Add the MAC address of the requestor to DNS queries which are
forwarded upstream. This may be used to DNS filtering by the upstream
server. The MAC address can only be added if the requestor is on the same
@@ -570,19 +651,34 @@ subnet as the dnsmasq server. Note that the mechanism used to achieve this (an E
is not yet standardised, so this should be considered
experimental. Also note that exposing MAC addresses in this way may
have security and privacy implications. The warning about caching
given for --add-subnet applies to --add-mac too.
given for --add-subnet applies to --add-mac too. An alternative encoding of the
MAC, as base64, is enabled by adding the "base64" parameter and a human-readable encoding of hex-and-colons is enabled by added the "text" parameter.
.TP
.B --add-cpe-id=<string>
Add a arbitrary identifying string to o DNS queries which are
forwarded upstream.
.TP
.B --add-subnet[[=<IPv4 prefix length>],<IPv6 prefix length>]
Add the subnet address of the requestor to the DNS queries which are
forwarded upstream. The amount of the address forwarded depends on the
prefix length parameter: 32 (128 for IPv6) forwards the whole address,
zero forwards none of it but still marks the request so that no
upstream nameserver will add client address information either. The
default is zero for both IPv4 and IPv6. Note that upstream nameservers
may be configured to return different results based on this
information, but the dnsmasq cache does not take account. If a dnsmasq
instance is configured such that different results may be encountered,
caching should be disabled.
.B --add-subnet[[=[<IPv4 address>/]<IPv4 prefix length>][,[<IPv6 address>/]<IPv6 prefix length>]]
Add a subnet address to the DNS queries which are forwarded
upstream. If an address is specified in the flag, it will be used,
otherwise, the address of the requestor will be used. The amount of
the address forwarded depends on the prefix length parameter: 32 (128
for IPv6) forwards the whole address, zero forwards none of it but
still marks the request so that no upstream nameserver will add client
address information either. The default is zero for both IPv4 and
IPv6. Note that upstream nameservers may be configured to return
different results based on this information, but the dnsmasq cache
does not take account. If a dnsmasq instance is configured such that
different results may be encountered, caching should be disabled.
For example,
.B --add-subnet=24,96
will add the /24 and /96 subnets of the requestor for IPv4 and IPv6 requestors, respectively.
.B --add-subnet=1.2.3.4/24
will add 1.2.3.0/24 for IPv4 requestors and ::/0 for IPv6 requestors.
.B --add-subnet=1.2.3.4/24,1.2.3.4/24
will add 1.2.3.0/24 for both IPv4 and IPv6 requestors.
.TP
.B \-c, --cache-size=<cachesize>
Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching.
@@ -612,7 +708,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 menas that all replies will be
answers. In the default mode, this means that all replies will be
marked as untrusted. If
.B --dnssec-check-unsigned
is set and the upstream servers don't support DNSSEC, then DNS service will be entirely broken.
@@ -622,7 +718,7 @@ Provide DS records to act a trust anchors for DNSSEC
validation. Typically these will be the DS record(s) for Zone Signing
key(s) of the root zone,
but trust anchors for limited domains are also possible. The current
root-zone trust anchors may be donwloaded from https://data.iana.org/root-anchors/root-anchors.xml
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
@@ -645,6 +741,13 @@ that dnsmasq should be started with this flag when the platform determines that
reliable time is established, a SIGHUP should be sent to dnsmasq, which enables time checking, and purges the cache of DNS records
which have not been throughly checked.
.TP
.B --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
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
unprivileged user that dnsmasq runs as.
.TP
.B --proxy-dnssec
Copy the DNSSEC Authenticated Data bit from upstream servers to downstream clients and cache it. This is an
alternative to having dnsmasq validate DNSSEC, but it depends on the security of the network between
@@ -657,7 +760,7 @@ a return code of SERVFAIL. Note that
setting this may affect DNS behaviour in bad ways, it is not an
extra-logging flag and should not be set in production.
.TP
.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....]]
.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....][,exclude:<subnet>[/<prefix length>]].....]
Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain
will be served. If subnet(s) are given, A and AAAA records must be in one of the
specified subnets.
@@ -674,6 +777,10 @@ appear in the zone, but RFC1918 IPv4 addresses which should not.
Interface-name and address-literal subnet specifications may be used
freely in the same --auth-zone declaration.
It's possible to exclude certain IP addresses from responses. It can be
used, to make sure that answers contain only global routeable IP
addresses (by excluding loopback, RFC1918 and ULA addresses).
The subnet(s) are also used to define in-addr.arpa and
ip6.arpa domains which are served for reverse-DNS queries. If not
specified, the prefix length defaults to 24 for IPv4 and 64 for IPv6.
@@ -708,7 +815,7 @@ compiled in and the kernel must have conntrack support
included and configured. This option cannot be combined with
--query-port.
.TP
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-addr>[,<end-addr>][,<mode>][,<netmask>[,<broadcast>]][,<lease time>]
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-addr>[,<end-addr>|<mode>][,<netmask>[,<broadcast>]][,<lease time>]
.TP
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-IPv6addr>[,<end-IPv6addr>|constructor:<interface>][,<mode>][,<prefix-len>][,<lease time>]
@@ -740,7 +847,7 @@ For IPv6, the parameters are slightly different: instead of netmask
and broadcast address, there is an optional prefix length which must
be equal to or larger then the prefix length on the local interface. If not
given, this defaults to 64. Unlike the IPv4 case, the prefix length is not
automatically derived from the interface configuration. The mimimum
automatically derived from the interface configuration. The minimum
size of the prefix length is 64.
IPv6 (only) supports another type of range. In this, the start address and optional end address contain only the network part (ie ::1) and they are followed by
@@ -794,7 +901,7 @@ and
for details.)
For IPv6, the mode may be some combination of
.B ra-only, slaac, ra-names, ra-stateless.
.B ra-only, slaac, ra-names, ra-stateless, ra-advrouter, off-link.
.B ra-only
tells dnsmasq to offer Router Advertisement only on this subnet,
@@ -829,6 +936,14 @@ can be combined with
and
.B slaac.
.B ra-advrouter
enables a mode where router address(es) rather than prefix(es) are included in the advertisements.
This is described in RFC-3775 section 7.2 and is used in mobile IPv6. In this mode the interval option
is also included, as described in RFC-3775 section 7.3.
.B off-link
tells dnsmasq to advertise the prefix without the on-link (aka L) bit set.
.TP
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
Specify per host parameters for the DHCP server. This allows a machine
@@ -854,7 +969,7 @@ subnets which don't need a pool of dynamically allocated addresses,
use the "static" keyword in the dhcp-range declaration.
It is allowed to use client identifiers (called client
DUID in IPv6-land rather than
DUID in IPv6-land) rather than
hardware addresses to identify hosts by prefixing with 'id:'. Thus:
.B --dhcp-host=id:01:02:03:04,.....
refers to the host with client identifier 01:02:03:04. It is also
@@ -906,6 +1021,8 @@ dhcp-host directive (or one implied by /etc/ethers) then the special
tag "known" is set. This allows dnsmasq to be configured to
ignore requests from unknown machines using
.B --dhcp-ignore=tag:!known
If the host matches only a dhcp-host directive which cannot
be used because it specifies an address on different subnet, the tag "known-othernet" is set.
Ethernet addresses (but not client-ids) may have
wildcard bytes, so for example
.B --dhcp-host=00:20:e0:3b:13:*,ignore
@@ -951,6 +1068,17 @@ it is possible to encode the information in a
flag as DHCP options, using the options names bootfile-name,
server-ip-address and tftp-server. This allows these to be included
in a dhcp-optsfile.
.TP
.B --dhcp-hostsdir=<path>
This is equivalent to dhcp-hostsfile, except for the following. The path MUST be a
directory, and not an individual file. Changed or new files within
the directory are read automatically, without the need to send SIGHUP.
If a file is deleted for changed after it has been read by dnsmasq, then the
host record it contained will remain until dnsmasq receives a SIGHUP, or
is restarted; ie host records are only added dynamically.
.TP
.B --dhcp-optsdir=<path>
This is equivalent to dhcp-optsfile, with the differences noted for --dhcp-hostsdir.
.TP
.B \-Z, --read-ethers
Read /etc/ethers for information about hosts for the DHCP server. The
@@ -1256,7 +1384,7 @@ functions when supported by a suitable DHCP server.
This specifies a boot option which may appear in a PXE boot menu. <CSA> is
client system type, only services of the correct type will appear in a
menu. The known types are x86PC, PC98, IA64_EFI, Alpha, Arc_x86,
Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI and X86-64_EFI; an
Intel_Lean_Client, IA32_EFI, X86-64_EFI, Xscale_EFI, BC_EFI, ARM32_EFI and ARM64_EFI; an
integer may be used for other types. The
parameter after the menu text may be a file name, in which case dnsmasq acts as a
boot server and directs the PXE client to download the file by TFTP,
@@ -1265,8 +1393,9 @@ either from itself (
must be set for this to work) or another TFTP server if the final server
address/name is given.
Note that the "layer"
suffix (normally ".0") is supplied by PXE, and should not be added to
the basename. If an integer boot service type, rather than a basename
suffix (normally ".0") is supplied by PXE, and need not be added to
the basename. Alternatively, the basename may be a filename, complete with suffix, in which case
no layer suffix is added. If an integer boot service type, rather than a basename
is given, then the PXE client will search for a
suitable boot service for that type on the network. This search may be done
by broadcast, or direct to a server if its IP address/name is provided.
@@ -1332,7 +1461,7 @@ enables dynamic allocation. With tags, only when the tags are all
set. It may be repeated with different tag sets.
.TP
.B \-5, --no-ping
(IPv4 only) By default, the DHCP server will attempt to ensure that an address in
(IPv4 only) By default, the DHCP server will attempt to ensure that an address is
not in use before allocating it to a host. It does this by sending an
ICMP echo request (aka "ping") to the address in question. If it gets
a reply, then the address must already be in use, and another is
@@ -1357,7 +1486,7 @@ DUID automatically when it is first needed. When given, this option
provides dnsmasq the data required to create a DUID-EN type DUID. Note
that once set, the DUID is stored in the lease database, so to change between DUID-EN and
automatically created DUIDs or vice-versa, the lease database must be
re-intialised. The enterprise-id is assigned by IANA, and the uid is a
re-initialised. The enterprise-id is assigned by IANA, and the uid is a
string of hex octets unique to a particular device.
.TP
.B \-6 --dhcp-script=<path>
@@ -1425,6 +1554,8 @@ DHCP relay-agent added any of these options.
If the client provides vendor-class, DNSMASQ_VENDOR_CLASS.
DNSMASQ_REQUESTED_OPTIONS a string containing the decimal values in the Parameter Request List option, comma separated, if the parameter request list option is provided by the client.
For IPv6 only:
If the client provides vendor-class, DNSMASQ_VENDOR_CLASS_ID,
@@ -1448,8 +1579,8 @@ database.
All file descriptors are
closed except stdin, stdout and stderr which are open to /dev/null
(except in debug mode).
closed except stdin, which is open to /dev/null, and stdout and stderr which capture output for logging by dnsmasq.
(In debug mode, stdio, stdout and stderr file are left as those inherited from the invoker of dnsmasq).
The script is not invoked concurrently: at most one instance
of the script is ever running (dnsmasq waits for an instance of script to exit
@@ -1464,11 +1595,11 @@ At dnsmasq startup, the script will be invoked for
all existing leases as they are read from the lease file. Expired
leases will be called with "del" and others with "old". When dnsmasq
receives a HUP signal, the script will be invoked for existing leases
with an "old " event.
with an "old" event.
There are two further actions which may appear as the first argument
to the script, "init" and "tftp". More may be added in the future, so
There are four further actions which may appear as the first argument
to the script, "init", "arp-add", "arp-del" and "tftp". More may be added in the future, so
scripts should be written to ignore unknown actions. "init" is
described below in
.B --leasefile-ro
@@ -1476,11 +1607,16 @@ The "tftp" action is invoked when a TFTP file transfer completes: the
arguments are the file size in bytes, the address to which the file
was sent, and the complete pathname of the file.
The "arp-add" and "arp-del" actions are only called if enabled with
.B --script-arp
They are are supplied with a MAC address and IP address as arguments. "arp-add" indicates
the arrival of a new entry in the ARP or neighbour table, and "arp-del" indicates the deletion of same.
.TP
.B --dhcp-luascript=<path>
Specify a script written in Lua, to be run when leases are created,
destroyed or changed. To use this option, dnsmasq must be compiled
with the correct support. The Lua interpreter is intialised once, when
with the correct support. The Lua interpreter is initialised once, when
dnsmasq starts, so that global variables persist between lease
events. The Lua code must define a
.B lease
@@ -1522,10 +1658,24 @@ table holds the tags
.B file_name
and
.B file_size.
The
.B arp
and
.B arp-old
functions are called only when enabled with
.B --script-arp
and have a table which holds the tags
.B mac_address
and
.B client_address.
.TP
.B --dhcp-scriptuser
Specify the user as which to run the lease-change script or Lua script. This defaults to root, but can be changed to another user using this flag.
.TP
.TP
.B --script-arp
Enable the "arp" and "arp-old" functions in the dhcp-script and dhcp-luascript.
.TP
.B \-9, --leasefile-ro
Completely suppress use of the lease database file. The file will not
be created, read, or written. Change the way the lease-change
@@ -1541,10 +1691,13 @@ option also forces the leasechange script to be called on changes
to the client-id and lease length and expiry time.
.TP
.B --bridge-interface=<interface>,<alias>[,<alias>]
Treat DHCP request packets arriving at any of the <alias> interfaces
as if they had arrived at <interface>. This option is necessary when
using "old style" bridging on BSD platforms, since
packets arrive at tap interfaces which don't have an IP address.
Treat DHCP (v4 and v6) request and IPv6 Router Solicit packets
arriving at any of the <alias> interfaces as if they had arrived at
<interface>. This option allows dnsmasq to provide DHCP and RA
service over unaddressed and unbridged Ethernet interfaces, e.g. on an
OpenStack compute host where each such interface is a TAP interface to
a VM, or as in "old style bridging" on BSD platforms. A trailing '*'
wildcard can be used in each <alias>.
.TP
.B \-s, --domain=<domain>[,<address range>[,local]]
Specifies DNS domains for the DHCP server. Domains may be be given
@@ -1615,17 +1768,17 @@ creation are handled by a different protocol. When DHCP is in use,
only a subset of this is needed, and dnsmasq can handle it, using
existing DHCP configuration to provide most data. When RA is enabled,
dnsmasq will advertise a prefix for each dhcp-range, with default
router and recursive DNS server as the relevant link-local address on
the machine running dnsmasq. By default, he "managed address" bits are set, and
router as the relevant link-local address on
the machine running dnsmasq. By default, the "managed address" bits are set, and
the "use SLAAC" bit is reset. This can be changed for individual
subnets with the mode keywords described in
.B --dhcp-range.
RFC6106 DNS parameters are included in the advertisements. By default,
the relevant link-local address of the machine running dnsmasq is sent
as recursive DNS server. If provided, the DHCPv6 options dns-server and
domain-search are used for RDNSS and DNSSL.
domain-search are used for the DNS server (RDNSS) and the domain search list (DNSSL).
.TP
.B --ra-param=<interface>,[high|low],[[<ra-interval>],<router lifetime>]
.B --ra-param=<interface>,[mtu:<integer>|<interface>|off,][high,|low,]<ra-interval>[,<router lifetime>]
Set non-default values for router advertisements sent via an
interface. The priority field for the router may be altered from the
default of medium with eg
@@ -1635,16 +1788,26 @@ The interval between router advertisements may be set (in seconds) with
The lifetime of the route may be changed or set to zero, which allows
a router to advertise prefixes but not a route via itself.
.B --ra-parm=eth0,0,0
(A value of zero for the interval means the default value.) All three parameters may be set at once.
.B --ra-param=low,60,1200
(A value of zero for the interval means the default value.) All four parameters may be set at once.
.B --ra-param=eth0,mtu:1280,low,60,1200
The interface field may include a wildcard.
The mtu: parameter may be an arbitrary interface name, in which case the MTU value for that interface is used. This is useful
for (eg) advertising the MTU of a WAN interface on the other interfaces of a router.
.TP
.B --dhcp-reply-delay=[tag:<tag>,]<integer>
Delays sending DHCPOFFER and proxydhcp replies for at least the specified number of seconds.
This can be used as workaround for bugs in PXE boot firmware that does not function properly when
receiving an instant reply.
This option takes into account the time already spent waiting (e.g. performing ping check) if any.
.TP
.B --enable-tftp[=<interface>[,<interface>]]
Enable the TFTP server function. This is deliberately limited to that
needed to net-boot a client. Only reading is allowed; the tsize and
blksize extensions are supported (tsize is only supported in octet
mode). Without an argument, the TFTP service is provided to the same set of interfaces as DHCP service.
If the list of interfaces is provided, that defines which interfaces recieve TFTP service.
If the list of interfaces is provided, that defines which interfaces receive TFTP service.
.TP
.B --tftp-root=<directory>[,<interface>]
Look for files to transfer using TFTP relative to the given
@@ -1654,12 +1817,19 @@ Absolute paths (starting with /) are allowed, but they must be within
the tftp-root. If the optional interface argument is given, the
directory is only used for TFTP requests via that interface.
.TP
.B --tftp-unique-root
Add the IP address of the TFTP client as a path component on the end
of the TFTP-root (in standard dotted-quad format). Only valid if a
tftp-root is set and the directory exists. For instance, if tftp-root is "/tftp" and client
1.2.3.4 requests file "myfile" then the effective path will be
"/tftp/1.2.3.4/myfile" if /tftp/1.2.3.4 exists or /tftp/myfile otherwise.
.B --tftp-no-fail
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.
Defaults to adding IP address (in standard dotted-quad format).
For instance, if tftp-root is "/tftp" and client 1.2.3.4 requests file "myfile"
then the effective path will be "/tftp/1.2.3.4/myfile" if /tftp/1.2.3.4 exists or /tftp/myfile otherwise.
When "=mac" is specified it will append the MAC address instead, using lowercase zero padded digits
separated by dashes, e.g.: 01-02-03-04-aa-bb
Note that resolving MAC addresses is only possible if the client is in the local network or obtained
a DHCP lease from us.
.TP
.B --tftp-secure
Enable TFTP secure mode: without this, any file which is readable by
@@ -1690,6 +1860,10 @@ require about (2*n) + 10 descriptors. If
.B --tftp-port-range
is given, that can affect the number of concurrent connections.
.TP
.B --tftp-mtu=<mtu size>
Use size as the ceiling of the MTU supported by the intervening network when
negotiating TFTP blocksize, overriding the MTU setting of the local interface if it is larger.
.TP
.B --tftp-no-blocksize
Stop the TFTP server from negotiating the "blocksize" option with a
client. Some buggy clients request this option but then behave badly
@@ -1709,19 +1883,23 @@ Specify a different configuration file. The conf-file option is also allowed in
configuration files, to include multiple configuration files. A
filename of "-" causes dnsmasq to read configuration from stdin.
.TP
.B \-7, --conf-dir=<directory>[,<file-extension>......]
.B \-7, --conf-dir=<directory>[,<file-extension>......],
Read all the files in the given directory as configuration
files. If extension(s) are given, any files which end in those
extensions are skipped. Any files whose names end in ~ or start with . or start and end
with # are always skipped. This flag may be given on the command
line or in a configuration file.
with # are always skipped. If the extension starts with * then only files
which have that extension are loaded. So
.B --conf-dir=/path/to/dir,*.conf
loads all files with the suffix .conf in /path/to/dir. This flag may be given on the command
line or in a configuration file. If giving it on the command line, be sure to
escape * characters.
.TP
.B --servers-file=<file>
A special case of
.B --conf-file
which differs in two respects. Firstly, only --server and --rev-server are allowed
in the configuration file included. Secondly, the file is re-read and the configuration
therein is updated when dnsmasq recieves SIGHUP.
therein is updated when dnsmasq receives SIGHUP.
.SH CONFIG FILE
At startup, dnsmasq reads
.I /etc/dnsmasq.conf,
@@ -1747,7 +1925,8 @@ clears its cache and then re-loads
.I /etc/hosts
and
.I /etc/ethers
and any file given by --dhcp-hostsfile, --dhcp-optsfile or --addn-hosts.
and any file given by --dhcp-hostsfile, --dhcp-hostsdir, --dhcp-optsfile,
--dhcp-optsdir, --addn-hosts or --hostsdir.
The dhcp lease change script is called for all
existing DHCP leases. If
.B
@@ -2056,7 +2235,12 @@ following data is used to populate the authoritative zone.
.B --cname
as long as the record name is in the authoritative domain. If the
target of the CNAME is unqualified, then it is qualified with the
authoritative zone name.
authoritative zone name. CNAME used in this way (only) may be wildcards, as in
.nf
.B cname=*.example.com,default.example.com
.fi
.PP
IPv4 and IPv6 addresses from /etc/hosts (and
.B --addn-hosts
@@ -2069,7 +2253,7 @@ provided the address falls into one of the subnets specified in the
.PP
Addresses of DHCP leases, provided the address falls into one of the subnets specified in the
.B --auth-zone.
(If contructed DHCP ranges are is use, which depend on the address dynamically
(If constructed DHCP ranges are is use, which depend on the address dynamically
assigned to an interface, then the form of
.B --auth-zone
which defines subnets by the dynamic address of an interface should

View File

@@ -1062,10 +1062,14 @@ esta opci
cuando hay cambios hechos a el client-id y tiempos de arriendo y vencimiento.
.TP
.B --bridge-interface=<nombre de interface>,<alias>[,<alias>]
Tratar paquetes de pedidos DHCP que llegan a cualquiera de las interfaces <alias>
como si hubieran llegado a la interface <nombre de interface>. Esta opción
es necesaria al usar bridging estilo viejo en plataformas BSD, dado a que
los paquetes llegan a interfaces tap que no tienen una dirección IP.
Tratar paquetes de pedidos DHCP (v4 y v6) y de IPv6 Router Solicit que
llegan a cualquiera de las interfaces <alias> como si hubieran llegado
a la interface <nombre de interface>. Esta opción permite que dnsmasq
puede proporcionar los servicios DHCP y RA a través de interfaces
ethernet sin dirección y sin puente; por ejemplo en un nodo de cálculo
de OpenStack, donde cada una de esas interfaces es una interfaz TAP
para una máquina virtual, o al usar bridging estilo viejo en
plataformas BSD.
.TP
.B \-s, --domain=<dominio>[,<rango de IPs>]
Especifica los dominios DNS para el servidor DHCP. Dominios pueden ser

View File

@@ -852,7 +852,7 @@ et
pour plus de détails).
Pour IPv6, le mode peut-être une combinaison des valeurs
.B ra-only, slaac, ra-names, ra-stateless.
.B ra-only, slaac, ra-names, ra-stateless, off-link.
.B ra-only
indique à dnsmasq de n'effectuer que des annonces de routeur (Router
@@ -888,6 +888,9 @@ peut-être combiné avec
et
.B slaac.
.B off-link
indique à dnsmasq d'annoncer le préfixe sans le bit L (sur lien).
.TP
.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,set:<label>][,<adresse IP>][,<nom d'hôte>][,<durée de bail>][,ignore]
Spécifie les paramètres DHCP relatifs à un hôte. Cela permet à une machine
@@ -1655,11 +1658,14 @@ changement d'état de bail à chaque changement de l'identifiant de client, de
longueur de bail ou de date d'expiration.
.TP
.B --bridge-interface=<interface>,<alias>[,<alias>]
Traiter les requêtes DHCP arrivant sur n'importe laquelle des interfaces <alias>
comme si elles arrivaient de l'interface <interface>. Cette option est
nécessaire lors de l'utilisation de pont ethernet "ancien mode" sur plate-forme
BSD, puisque dans ce cas les paquets arrivent sur des interfaces "tap" n'ont
pas d'adresse IP.
Traiter les requêtes DHCP (v4 et v6) et IPv6 Router Solicit arrivant
sur n'importe laquelle des interfaces <alias> comme si elles
arrivaient de l'interface <interface>. Cette option permet à dnsmasq
de fournir les service DHCP et RA sur les interfaces ethernet non
adressés et non pontés; par exemple sur un hôte de calcul d'OpenStack
où chaque telle interface est une interface TAP à une machine
virtuelle, ou lors de l'utilisation de pont ethernet "ancien mode" sur
plate-forme BSD. Chaque <alias> peut finir avec un simple '*' joker.
.TP
.B \-s, --domain=<domaine>[,<gamme d'adresses>[,local]]
Spécifie le domaine du serveur DHCP. Le domaine peut être donné de manière
@@ -1750,20 +1756,20 @@ dnsmasq est spécifiée comme DNS récursif. Si elles sont fournies, les
options dns-server et domain-search sont utilisées respectivement pour RDNSS et
DNSSL.
.TP
.B --ra-param=<interface>,[high|low],[[<intervalle d'annonce routeur>],<durée de vie route>]
.B --ra-param=<interface>,[mtu:<valeur>|<interface>|off,][high,|low,]<intervalle d'annonce routeur>[,<durée de vie route>]
Configure pour une interface donnée des valeurs pour les annonces routeurs
différentes des valeurs par défaut. La valeur par défaut du champ priorité
pour le routeur peut-être changée de "medium" (moyen) à "high" (haute) ou
"low" (basse). Par exemple :
.B --ra-param=eth0,high.
.B --ra-param=eth0,high,0.
Un intervalle (en secondes) entre les annonces routeur peut-être fourni par :
.B --ra-param=eth0,60.
La durée de vie de la route peut-être changée ou mise à zéro, auquel cas
le routeur peut annoncer les préfixes mais pas de route :
.B --ra-parm=eth0,0,0
(une valeur de zéro pour l'intervalle signifie qu'il garde la valeur par défaut).
Ces trois paramètres peuvent-être configurés en une fois :
.B --ra-param=low,60,1200
Ces quatre paramètres peuvent-être configurés en une fois :
.B --ra-param=eth0,mtu:1280,low,60,1200
La valeur pour l'interface peut inclure un caractère joker.
.TP
.B --enable-tftp[=<interface>[,<interface>]]

1361
po/de.po

File diff suppressed because it is too large Load Diff

1166
po/es.po

File diff suppressed because it is too large Load Diff

1420
po/fi.po

File diff suppressed because it is too large Load Diff

1159
po/fr.po

File diff suppressed because it is too large Load Diff

1198
po/id.po

File diff suppressed because it is too large Load Diff

1420
po/it.po

File diff suppressed because it is too large Load Diff

1162
po/no.po

File diff suppressed because it is too large Load Diff

1164
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1162
po/ro.po

File diff suppressed because it is too large Load Diff

View File

@@ -78,7 +78,7 @@ by modifying MODIFY_RESOLV_CONF_DYNAMICALLY="no" in <TT>/etc/sysconfig/network/c
<h3>Automatic DNS server configuration with DHCP.</h3>
You need to get your DHCP client to write the addresse(s) of the DNS
You need to get your DHCP client to write the address(es) of the DNS
servers to a file other than <TT>/etc/resolv.conf</TT>. For dhcpcd, the
<TT>dhcpcd.exe</TT> script gets run with the addresses of the nameserver(s) in
the shell variable <TT>$DNS</TT>. The following bit of shell script
@@ -86,8 +86,8 @@ uses that to write a file suitable for dnsmasq.
<PRE>
echo -n >|/etc/dhcpc/resolv.conf
dnsservs=${DNS//,/ }
for serv in $dnsservs; do
dnsservers=${DNS//,/ }
for serv in $dnsservers; do
echo "nameserver $serv" >>/etc/dhcpc/resolv.conf
done
@@ -186,7 +186,7 @@ more than one nameserver just include as many
<H2>Local domains.</H2>
Sometimes people have local domains which they do not want forwarded
to upstream servers. This is accomodated by using server options
to upstream servers. This is accommodated by using server options
without the server IP address. To make things clearer <TT>local</TT>
is a synonym for <TT>server</TT>. For example the option
<TT>local=/localnet/</TT> ensures that any domain name query which ends in

247
src/arp.c Normal file
View File

@@ -0,0 +1,247 @@
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
/* Time between forced re-loads from kernel. */
#define INTERVAL 90
#define ARP_MARK 0
#define ARP_FOUND 1 /* Confirmed */
#define ARP_NEW 2 /* Newly created */
#define ARP_EMPTY 3 /* No MAC addr */
struct arp_record {
unsigned short hwlen, status;
int family;
unsigned char hwaddr[DHCP_CHADDR_MAX];
struct all_addr addr;
struct arp_record *next;
};
static struct arp_record *arps = NULL, *old = NULL, *freelist = NULL;
static time_t last = 0;
static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
{
struct arp_record *arp;
(void)parmv;
if (maclen > DHCP_CHADDR_MAX)
return 1;
#ifndef HAVE_IPV6
if (family != AF_INET)
return 1;
#endif
/* Look for existing entry */
for (arp = arps; arp; arp = arp->next)
{
if (family != arp->family || arp->status == ARP_NEW)
continue;
if (family == AF_INET)
{
if (arp->addr.addr.addr4.s_addr != ((struct in_addr *)addrp)->s_addr)
continue;
}
#ifdef HAVE_IPV6
else
{
if (!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, (struct in6_addr *)addrp))
continue;
}
#endif
if (arp->status == ARP_EMPTY)
{
/* existing address, was negative. */
arp->status = ARP_NEW;
arp->hwlen = maclen;
memcpy(arp->hwaddr, mac, maclen);
}
else if (arp->hwlen == maclen && memcmp(arp->hwaddr, mac, maclen) == 0)
/* Existing entry matches - confirm. */
arp->status = ARP_FOUND;
else
continue;
break;
}
if (!arp)
{
/* New entry */
if (freelist)
{
arp = freelist;
freelist = freelist->next;
}
else if (!(arp = whine_malloc(sizeof(struct arp_record))))
return 1;
arp->next = arps;
arps = arp;
arp->status = ARP_NEW;
arp->hwlen = maclen;
arp->family = family;
memcpy(arp->hwaddr, mac, maclen);
if (family == AF_INET)
arp->addr.addr.addr4.s_addr = ((struct in_addr *)addrp)->s_addr;
#ifdef HAVE_IPV6
else
memcpy(&arp->addr.addr.addr6, addrp, IN6ADDRSZ);
#endif
}
return 1;
}
/* If in lazy mode, we cache absence of ARP entries. */
int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now)
{
struct arp_record *arp, *tmp, **up;
int updated = 0;
again:
/* If the database is less then INTERVAL old, look in there */
if (difftime(now, last) < INTERVAL)
{
/* addr == NULL -> just make cache up-to-date */
if (!addr)
return 0;
for (arp = arps; arp; arp = arp->next)
{
if (addr->sa.sa_family != arp->family)
continue;
if (arp->family == AF_INET &&
arp->addr.addr.addr4.s_addr != addr->in.sin_addr.s_addr)
continue;
#ifdef HAVE_IPV6
if (arp->family == AF_INET6 &&
!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, &addr->in6.sin6_addr))
continue;
#endif
/* Only accept positive entries unless in lazy mode. */
if (arp->status != ARP_EMPTY || lazy || updated)
{
if (mac && arp->hwlen != 0)
memcpy(mac, arp->hwaddr, arp->hwlen);
return arp->hwlen;
}
}
}
/* Not found, try the kernel */
if (!updated)
{
updated = 1;
last = now;
/* Mark all non-negative entries */
for (arp = arps; arp; arp = arp->next)
if (arp->status != ARP_EMPTY)
arp->status = ARP_MARK;
iface_enumerate(AF_UNSPEC, NULL, filter_mac);
/* Remove all unconfirmed entries to old list. */
for (arp = arps, up = &arps; arp; arp = tmp)
{
tmp = arp->next;
if (arp->status == ARP_MARK)
{
*up = arp->next;
arp->next = old;
old = arp;
}
else
up = &arp->next;
}
goto again;
}
/* record failure, so we don't consult the kernel each time
we're asked for this address */
if (freelist)
{
arp = freelist;
freelist = freelist->next;
}
else
arp = whine_malloc(sizeof(struct arp_record));
if (arp)
{
arp->next = arps;
arps = arp;
arp->status = ARP_EMPTY;
arp->family = addr->sa.sa_family;
arp->hwlen = 0;
if (addr->sa.sa_family == AF_INET)
arp->addr.addr.addr4.s_addr = addr->in.sin_addr.s_addr;
#ifdef HAVE_IPV6
else
memcpy(&arp->addr.addr.addr6, &addr->in6.sin6_addr, IN6ADDRSZ);
#endif
}
return 0;
}
int do_arp_script_run(void)
{
struct arp_record *arp;
/* Notify any which went, then move to free list */
if (old)
{
#ifdef HAVE_SCRIPT
if (option_bool(OPT_SCRIPT_ARP))
queue_arp(ACTION_ARP_DEL, old->hwaddr, old->hwlen, old->family, &old->addr);
#endif
arp = old;
old = arp->next;
arp->next = freelist;
freelist = arp;
return 1;
}
for (arp = arps; arp; arp = arp->next)
if (arp->status == ARP_NEW)
{
#ifdef HAVE_SCRIPT
if (option_bool(OPT_SCRIPT_ARP))
queue_arp(ACTION_ARP, arp->hwaddr, arp->hwlen, arp->family, &arp->addr);
#endif
arp->status = ARP_FOUND;
return 1;
}
return 0;
}

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,36 +18,53 @@
#ifdef HAVE_AUTH
static struct addrlist *find_addrlist(struct addrlist *list, int flag, struct all_addr *addr_u)
{
do {
if (!(list->flags & ADDRLIST_IPV6))
{
struct in_addr netmask, addr = addr_u->addr.addr4;
if (!(flag & F_IPV4))
continue;
netmask.s_addr = htonl(~(in_addr_t)0 << (32 - list->prefixlen));
if (is_same_net(addr, list->addr.addr.addr4, netmask))
return list;
}
#ifdef HAVE_IPV6
else if (is_same_net6(&(addr_u->addr.addr6), &list->addr.addr.addr6, list->prefixlen))
return list;
#endif
} while ((list = list->next));
return NULL;
}
static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u)
{
struct addrlist *subnet;
if (!zone->subnet)
return NULL;
return find_addrlist(zone->subnet, flag, addr_u);
}
for (subnet = zone->subnet; subnet; subnet = subnet->next)
{
if (!(subnet->flags & ADDRLIST_IPV6))
{
struct in_addr netmask, addr = addr_u->addr.addr4;
if (!(flag & F_IPV4))
continue;
netmask.s_addr = htonl(~((1 << (32 - subnet->prefixlen)) - 1));
if (is_same_net(addr, subnet->addr.addr.addr4, netmask))
return subnet;
}
#ifdef HAVE_IPV6
else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr.addr.addr6, subnet->prefixlen))
return subnet;
#endif
}
return NULL;
static struct addrlist *find_exclude(struct auth_zone *zone, int flag, struct all_addr *addr_u)
{
if (!zone->exclude)
return NULL;
return find_addrlist(zone->exclude, flag, addr_u);
}
static int filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
{
/* No zones specified, no filter */
if (find_exclude(zone, flag, addr_u))
return 0;
/* No subnets specified, no filter */
if (!zone->subnet)
return 1;
@@ -81,7 +98,8 @@ int in_zone(struct auth_zone *zone, char *name, char **cut)
}
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr, int local_query)
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr,
int local_query, int do_bit, int have_pseudoheader)
{
char *name = daemon->namebuff;
unsigned char *p, *ansp;
@@ -98,7 +116,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
struct interface_name *intr;
struct naptr *na;
struct all_addr addr;
struct cname *a;
struct cname *a, *candidate;
unsigned int wclen;
/* Clear buffer beyond request to avoid risk of
information disclosure. */
memset(((char *)header) + qlen, 0,
(limit - ((char *)header)) - qlen);
if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
return 0;
@@ -114,6 +138,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
{
unsigned short flag = 0;
int found = 0;
int cname_wildcard = 0;
/* save pointer to name for copying into answers */
nameoffset = p - (unsigned char *)header;
@@ -131,24 +156,27 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
continue;
}
if (qtype == T_PTR)
if ((qtype == T_PTR || qtype == T_SOA || qtype == T_NS) &&
(flag = in_arpa_name_2_addr(name, &addr)) &&
!local_query)
{
if (!(flag = in_arpa_name_2_addr(name, &addr)))
continue;
if (!local_query)
for (zone = daemon->auth_zones; zone; zone = zone->next)
if ((subnet = find_subnet(zone, flag, &addr)))
break;
if (!zone)
{
for (zone = daemon->auth_zones; zone; zone = zone->next)
if ((subnet = find_subnet(zone, flag, &addr)))
break;
if (!zone)
{
auth = 0;
continue;
}
auth = 0;
continue;
}
else if (qtype == T_SOA)
soa = 1, found = 1;
else if (qtype == T_NS)
ns = 1, found = 1;
}
if (qtype == T_PTR && flag)
{
intr = NULL;
if (flag == F_IPV4)
@@ -186,7 +214,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (intr)
{
if (in_zone(zone, intr->name, NULL))
if (local_query || in_zone(zone, intr->name, NULL))
{
found = 1;
log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
@@ -208,8 +236,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
*p = 0; /* must be bare name */
/* add external domain */
strcat(name, ".");
strcat(name, zone->domain);
if (zone)
{
strcat(name, ".");
strcat(name, zone->domain);
}
log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid));
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
@@ -217,7 +248,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
T_PTR, C_IN, "d", name))
anscount++;
}
else if (crecp->flags & (F_DHCP | F_HOSTS) && in_zone(zone, name, NULL))
else if (crecp->flags & (F_DHCP | F_HOSTS) && (local_query || in_zone(zone, name, NULL)))
{
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
found = 1;
@@ -240,14 +271,20 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
cname_restart:
for (zone = daemon->auth_zones; zone; zone = zone->next)
if (in_zone(zone, name, &cut))
break;
if (!zone)
if (found)
/* NS and SOA .arpa requests have set found above. */
cut = NULL;
else
{
auth = 0;
continue;
for (zone = daemon->auth_zones; zone; zone = zone->next)
if (in_zone(zone, name, &cut))
break;
if (!zone)
{
auth = 0;
continue;
}
}
for (rec = daemon->mxnames; rec; rec = rec->next)
@@ -363,6 +400,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype &&
(local_query || filter_zone(zone, flag, &addrlist->addr)))
{
#ifdef HAVE_IPV6
if (addrlist->flags & ADDRLIST_REVONLY)
continue;
#endif
found = 1;
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
@@ -372,25 +413,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
}
for (a = daemon->cnames; a; a = a->next)
if (hostname_isequal(name, a->alias) )
{
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
strcpy(name, a->target);
if (!strchr(name, '.'))
{
strcat(name, ".");
strcat(name, zone->domain);
}
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, &nameoffset,
T_CNAME, C_IN, "d", name))
anscount++;
goto cname_restart;
}
if (!cut)
{
nxdomain = 0;
@@ -409,7 +431,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
peer_addr->in.sin_port = 0;
#ifdef HAVE_IPV6
else
peer_addr->in6.sin6_port = 0;
{
peer_addr->in6.sin6_port = 0;
peer_addr->in6.sin6_scope_id = 0;
}
#endif
for (peers = daemon->auth_peers; peers; peers = peers->next)
@@ -493,8 +518,62 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
} while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
}
if (!found)
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
/* Only supply CNAME if no record for any type is known. */
if (nxdomain)
{
/* Check for possible wildcard match against *.domain
return length of match, to get longest.
Note that if return length of wildcard section, so
we match b.simon to _both_ *.simon and b.simon
but return a longer (better) match to b.simon.
*/
for (wclen = 0, candidate = NULL, a = daemon->cnames; a; a = a->next)
if (a->alias[0] == '*')
{
char *test = name;
while ((test = strchr(test+1, '.')))
{
if (hostname_isequal(test, &(a->alias[1])))
{
if (strlen(test) > wclen && !cname_wildcard)
{
wclen = strlen(test);
candidate = a;
cname_wildcard = 1;
}
break;
}
}
}
else if (hostname_isequal(a->alias, name) && strlen(a->alias) > wclen)
{
/* Simple case, no wildcard */
wclen = strlen(a->alias);
candidate = a;
}
if (candidate)
{
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
strcpy(name, candidate->target);
if (!strchr(name, '.'))
{
strcat(name, ".");
strcat(name, zone->domain);
}
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, &nameoffset,
T_CNAME, C_IN, "d", name))
anscount++;
goto cname_restart;
}
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
}
}
@@ -786,7 +865,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
header->hb4 &= ~HB4_RA;
}
/* authoritive */
/* authoritative */
if (auth)
header->hb3 |= HB3_AA;
@@ -801,6 +880,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
header->ancount = htons(anscount);
header->nscount = htons(authcount);
header->arcount = htons(0);
/* Advertise our packet size limit in our reply */
if (have_pseudoheader)
return add_pseudoheader(header, ansp - (unsigned char *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
return ansp - (unsigned char *)header;
}

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@ static void blockdata_expand(int n)
{
struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
if (new)
if (n > 0 && new)
{
int i;
@@ -46,14 +46,19 @@ void blockdata_init(void)
blockdata_alloced = 0;
blockdata_count = 0;
blockdata_hwm = 0;
blockdata_expand((daemon->cachesize * 100) / sizeof(struct blockdata));
/* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
if (option_bool(OPT_DNSSEC_VALID))
blockdata_expand((daemon->cachesize * 100) / sizeof(struct blockdata));
}
void blockdata_report(void)
{
my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u, allocated %u"),
blockdata_count * sizeof(struct blockdata), blockdata_hwm * sizeof(struct blockdata), blockdata_alloced * sizeof(struct blockdata));
if (option_bool(OPT_DNSSEC_VALID))
my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u, allocated %u"),
blockdata_count * sizeof(struct blockdata),
blockdata_hwm * sizeof(struct blockdata),
blockdata_alloced * sizeof(struct blockdata));
}
struct blockdata *blockdata_alloc(char *data, size_t len)

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,7 +20,9 @@
#include <ifaddrs.h>
#include <sys/param.h>
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
#include <sys/sysctl.h>
#endif
#include <net/if.h>
#include <net/route.h>
#include <net/if_dl.h>
@@ -103,7 +105,7 @@ int arp_enumerate(void *parm, int (*callback)())
int iface_enumerate(int family, void *parm, int (*callback)())
{
struct ifaddrs *head, *addrs;
int errsav, fd = -1, ret = 0;
int errsave, fd = -1, ret = 0;
if (family == AF_UNSPEC)
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
@@ -235,11 +237,11 @@ int iface_enumerate(int family, void *parm, int (*callback)())
ret = 1;
err:
errsav = errno;
errsave = errno;
freeifaddrs(head);
if (fd != -1)
close(fd);
errno = errsav;
errno = errsave;
return ret;
}
@@ -359,7 +361,7 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
iov[3].iov_base = mess;
iov[3].iov_len = len;
while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
while (retry_send(writev(daemon->dhcp_raw_fd, iov, 4)));
}
#endif /* defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) */
@@ -376,7 +378,7 @@ void route_init(void)
die(_("cannot create PF_ROUTE socket: %s"), NULL, EC_BADNET);
}
void route_sock(time_t now)
void route_sock(void)
{
struct if_msghdr *msg;
int rc = recv(daemon->routefd, daemon->packet, daemon->packet_buff_sz, 0);
@@ -401,7 +403,7 @@ void route_sock(time_t now)
else if (msg->ifm_type == RTM_NEWADDR)
{
del_family = 0;
newaddress(now);
queue_event(EVENT_NEWADDR);
}
else if (msg->ifm_type == RTM_DELADDR)
{
@@ -439,7 +441,7 @@ void route_sock(time_t now)
of += sizeof(long) - (diff & (sizeof(long) - 1));
}
newaddress(now);
queue_event(EVENT_NEWADDR);
}
}

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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
@@ -189,12 +189,7 @@ static void cache_hash(struct crec *crecp)
static void cache_blockdata_free(struct crec *crecp)
{
if (crecp->flags & F_DNSKEY)
{
if (crecp->flags & F_DS)
blockdata_free(crecp->addr.sig.keydata);
else
blockdata_free(crecp->addr.key.keydata);
}
blockdata_free(crecp->addr.key.keydata);
else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG))
blockdata_free(crecp->addr.ds.keydata);
}
@@ -322,7 +317,7 @@ static int is_expired(time_t now, struct crec *crecp)
return 1;
}
static int 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)
{
/* Scan and remove old entries.
If (flags & F_FORWARD) then remove any forward entries for name and any expired
@@ -331,8 +326,8 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
entries in the whole cache.
If (flags == 0) remove any expired entries in the whole cache.
In the flags & F_FORWARD case, the return code is valid, and returns zero if the
name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
In the flags & F_FORWARD case, the return code is valid, and returns a non-NULL pointer
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. */
@@ -361,7 +356,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
(((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))))
{
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
return 0;
return crecp;
*up = crecp->hash_next;
cache_unlink(crecp);
cache_free(crecp);
@@ -369,16 +364,11 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
}
#ifdef HAVE_DNSSEC
/* Deletion has to be class-sensitive for DS, DNSKEY, RRSIG, also
type-covered sensitive for RRSIG */
if ((flags & (F_DNSKEY | F_DS)) &&
(flags & (F_DNSKEY | F_DS)) == (crecp->flags & (F_DNSKEY | F_DS)) &&
crecp->uid == addr->addr.dnssec.class &&
(!((flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY)) ||
crecp->addr.sig.type_covered == addr->addr.dnssec.type))
/* Deletion has to be class-sensitive for DS and DNSKEY */
if ((flags & crecp->flags & (F_DNSKEY | F_DS)) && crecp->uid == addr->addr.dnssec.class)
{
if (crecp->flags & F_CONFIG)
return 0;
return crecp;
*up = crecp->hash_next;
cache_unlink(crecp);
cache_free(crecp);
@@ -423,7 +413,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
up = &crecp->hash_next;
}
return 1;
return NULL;
}
/* Note: The normal calling sequence is
@@ -461,9 +451,11 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
{
log_query(flags | F_UPSTREAM, name, addr, NULL);
/* Don;t mess with TTL for DNSSEC records. */
/* Don't mess with TTL for DNSSEC records. */
if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
ttl = daemon->max_cache_ttl;
if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl)
ttl = daemon->min_cache_ttl;
}
/* if previous insertion failed give up now. */
@@ -471,10 +463,26 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
return NULL;
/* First remove any expired entries and entries for the name/address we
are currently inserting. Fail if we attempt to delete a name from
/etc/hosts or DHCP. */
if (!cache_scan_free(name, addr, now, flags))
are currently inserting. */
if ((new = cache_scan_free(name, addr, now, flags)))
{
/* We're trying to insert a record over one from
/etc/hosts or DHCP, or other config. If the
existing record is for an A or AAAA and
the record we're trying to insert is the same,
just drop the insert, but don't error the whole process. */
if ((flags & (F_IPV4 | F_IPV6)) && (flags & F_FORWARD) && addr)
{
if ((flags & F_IPV4) && (new->flags & F_IPV4) &&
new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr)
return new;
#ifdef HAVE_IPV6
else if ((flags & F_IPV6) && (new->flags & F_IPV6) &&
IN6_ARE_ADDR_EQUAL(&new->addr.addr.addr.addr6, &addr->addr.addr6))
return new;
#endif
}
insert_error = 1;
return NULL;
}
@@ -514,13 +522,9 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
struct all_addr free_addr = new->addr.addr;;
#ifdef HAVE_DNSSEC
/* For DNSSEC records, addr holds class and type_covered for RRSIG */
/* For DNSSEC records, addr holds class. */
if (new->flags & (F_DS | F_DNSKEY))
{
free_addr.addr.dnssec.class = new->uid;
if ((new->flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY))
free_addr.addr.dnssec.type = new->addr.sig.type_covered;
}
free_addr.addr.dnssec.class = new->uid;
#endif
free_avail = 1; /* Must be free space now. */
@@ -635,9 +639,6 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp))
{
if ((crecp->flags & F_FORWARD) &&
#ifdef HAVE_DNSSEC
((crecp->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) &&
#endif
(crecp->flags & prot) &&
hostname_isequal(cache_get_name(crecp), name))
{
@@ -695,9 +696,6 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
if (ans &&
(ans->flags & F_FORWARD) &&
#ifdef HAVE_DNSSEC
((ans->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) &&
#endif
(ans->flags & prot) &&
hostname_isequal(cache_get_name(ans), name))
return ans;
@@ -776,10 +774,12 @@ static void add_hosts_cname(struct crec *target)
struct cname *a;
for (a = daemon->cnames; a; a = a->next)
if (hostname_isequal(cache_get_name(target), a->target) &&
if (a->alias[1] != '*' &&
hostname_isequal(cache_get_name(target), a->target) &&
(crec = whine_malloc(sizeof(struct crec))))
{
crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
crec->ttd = a->ttl;
crec->name.namep = a->alias;
crec->addr.cname.target.cache = target;
crec->addr.cname.uid = target->uid;
@@ -817,27 +817,42 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
Only insert each unique address once into this hashing structure.
This complexity avoids O(n^2) divergent CPU use whilst reading
large (10000 entry) hosts files. */
large (10000 entry) hosts files.
Note that we only do this process when bulk-reading hosts files,
for incremental reads, rhash is NULL, and we use cache lookups
instead.
*/
/* hash address */
for (j = 0, i = 0; i < addrlen; i++)
j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
for (lookup = rhash[j]; lookup; lookup = lookup->next)
if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) &&
memcmp(&lookup->addr.addr, addr, addrlen) == 0)
{
cache->flags &= ~F_REVERSE;
break;
}
/* maintain address hash chain, insert new unique address */
if (!lookup)
if (rhash)
{
cache->next = rhash[j];
rhash[j] = cache;
/* hash address */
for (j = 0, i = 0; i < addrlen; i++)
j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
for (lookup = rhash[j]; lookup; lookup = lookup->next)
if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) &&
memcmp(&lookup->addr.addr, addr, addrlen) == 0)
{
cache->flags &= ~F_REVERSE;
break;
}
/* maintain address hash chain, insert new unique address */
if (!lookup)
{
cache->next = rhash[j];
rhash[j] = cache;
}
}
else
{
/* incremental read, lookup in cache */
lookup = cache_find_by_addr(NULL, addr, 0, cache->flags & (F_IPV4 | F_IPV6));
if (lookup && lookup->flags & F_HOSTS)
cache->flags &= ~F_REVERSE;
}
cache->uid = index;
memcpy(&cache->addr.addr, addr, addrlen);
cache_hash(cache);
@@ -894,7 +909,7 @@ static int gettok(FILE *f, char *token)
}
}
static int read_hostsfile(char *filename, unsigned int index, int cache_size, struct crec **rhash, int hashsz)
int read_hostsfile(char *filename, unsigned int index, int cache_size, struct crec **rhash, int hashsz)
{
FILE *f = fopen(filename, "r");
char *token = daemon->namebuff, *domain_suffix = NULL;
@@ -906,7 +921,7 @@ static int read_hostsfile(char *filename, unsigned int index, int cache_size, st
if (!f)
{
my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
return 0;
return cache_size;
}
eatspace(f);
@@ -940,7 +955,7 @@ static int read_hostsfile(char *filename, unsigned int index, int cache_size, st
addr_count++;
/* rehash every 1000 names. */
if ((name_count - cache_size) > 1000)
if (rhash && ((name_count - cache_size) > 1000))
{
rehash(name_count);
cache_size = name_count;
@@ -968,6 +983,7 @@ static int read_hostsfile(char *filename, unsigned int index, int cache_size, st
strcat(cache->name.sname, ".");
strcat(cache->name.sname, domain_suffix);
cache->flags = flags;
cache->ttd = daemon->local_ttl;
add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
name_count++;
}
@@ -975,6 +991,7 @@ static int read_hostsfile(char *filename, unsigned int index, int cache_size, st
{
strcpy(cache->name.sname, canon);
cache->flags = flags;
cache->ttd = daemon->local_ttl;
add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
name_count++;
}
@@ -987,7 +1004,9 @@ static int read_hostsfile(char *filename, unsigned int index, int cache_size, st
}
fclose(f);
rehash(name_count);
if (rhash)
rehash(name_count);
my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
@@ -1038,10 +1057,12 @@ void cache_reload(void)
/* Add CNAMEs to interface_names to the cache */
for (a = daemon->cnames; a; a = a->next)
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(a->target, intr->name) &&
if (a->alias[1] != '*' &&
hostname_isequal(a->target, intr->name) &&
((cache = whine_malloc(sizeof(struct crec)))))
{
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
cache->ttd = a->ttl;
cache->name.namep = a->alias;
cache->addr.cname.target.int_name = intr;
cache->addr.cname.uid = SRC_INTERFACE;
@@ -1056,6 +1077,7 @@ void cache_reload(void)
(cache->addr.ds.keydata = blockdata_alloc(ds->digest, ds->digestlen)))
{
cache->flags = F_FORWARD | F_IMMORTAL | F_DS | F_CONFIG | F_NAMEP;
cache->ttd = daemon->local_ttl;
cache->name.namep = ds->name;
cache->addr.ds.keylen = ds->digestlen;
cache->addr.ds.algo = ds->algo;
@@ -1080,6 +1102,7 @@ void cache_reload(void)
(cache = whine_malloc(sizeof(struct crec))))
{
cache->name.namep = nl->name;
cache->ttd = hr->ttl;
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG;
add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
}
@@ -1088,6 +1111,7 @@ void cache_reload(void)
(cache = whine_malloc(sizeof(struct crec))))
{
cache->name.namep = nl->name;
cache->ttd = hr->ttl;
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG;
add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
}
@@ -1098,16 +1122,22 @@ void cache_reload(void)
{
if (daemon->cachesize > 0)
my_syslog(LOG_INFO, _("cleared cache"));
return;
}
if (!option_bool(OPT_NO_HOSTS))
total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
for (ah = daemon->addn_hosts; ah; ah = ah->next)
if (!(ah->flags & AH_INACTIVE))
total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
else
{
if (!option_bool(OPT_NO_HOSTS))
total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
for (ah = daemon->addn_hosts; ah; ah = ah->next)
if (!(ah->flags & AH_INACTIVE))
total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
}
#ifdef HAVE_INOTIFY
set_dynamic_inotify(AH_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
#endif
}
#ifdef HAVE_DHCP
@@ -1149,7 +1179,8 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
struct cname *a;
for (a = daemon->cnames; a; a = a->next)
if (hostname_isequal(cache_get_name(target), a->target))
if (a->alias[1] != '*' &&
hostname_isequal(cache_get_name(target), a->target))
{
if ((aliasc = dhcp_spare))
dhcp_spare = dhcp_spare->next;
@@ -1262,6 +1293,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
}
#endif
#ifndef NO_ID
int cache_make_stat(struct txt_record *t)
{
static char *buff = NULL;
@@ -1326,7 +1358,7 @@ int cache_make_stat(struct txt_record *t)
}
port = prettyprint_addr(&serv->addr, daemon->addrbuff);
lenp = p++; /* length */
bytes_avail = (p - buff) + bufflen;
bytes_avail = bufflen - (p - buff );
bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
if (bytes_needed >= bytes_avail)
{
@@ -1340,7 +1372,7 @@ int cache_make_stat(struct txt_record *t)
lenp = p - 1;
buff = new;
bufflen = newlen;
bytes_avail = (p - buff) + bufflen;
bytes_avail = bufflen - (p - buff );
bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
}
*lenp = bytes_needed;
@@ -1357,6 +1389,21 @@ int cache_make_stat(struct txt_record *t)
*buff = len;
return 1;
}
#endif
/* There can be names in the cache containing control chars, don't
mess up logging or open security holes. */
static char *sanitise(char *name)
{
unsigned char *r;
if (name)
for (r = (unsigned char *)name; *r; r++)
if (!isprint((int)*r))
return "<name unprintable>";
return name;
}
void dump_cache(time_t now)
{
@@ -1411,17 +1458,13 @@ void dump_cache(time_t now)
*a = 0;
if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
n = "<Root>";
p += sprintf(p, "%-40.40s ", n);
p += sprintf(p, "%-30.30s ", sanitise(n));
if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
a = cache_get_cname_target(cache);
a = sanitise(cache_get_cname_target(cache));
#ifdef HAVE_DNSSEC
else if (cache->flags & F_DS)
{
if (cache->flags & F_DNSKEY)
/* RRSIG */
sprintf(a, "%5u %3u %s", cache->addr.sig.keytag,
cache->addr.sig.algo, querystr("", cache->addr.sig.type_covered));
else if (!(cache->flags & F_NEG))
if (!(cache->flags & F_NEG))
sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
cache->addr.ds.algo, cache->addr.ds.digest);
}
@@ -1447,14 +1490,12 @@ void dump_cache(time_t now)
else if (cache->flags & F_CNAME)
t = "C";
#ifdef HAVE_DNSSEC
else if ((cache->flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY))
t = "G"; /* DNSKEY and DS set -> RRISG */
else if (cache->flags & F_DS)
t = "S";
else if (cache->flags & F_DNSKEY)
t = "K";
#endif
p += sprintf(p, "%-30.30s %s%s%s%s%s%s%s%s%s ", a, t,
p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s ", a, t,
cache->flags & F_FORWARD ? "F" : " ",
cache->flags & F_REVERSE ? "R" : " ",
cache->flags & F_IMMORTAL ? "I" : " ",
@@ -1487,7 +1528,13 @@ char *record_source(unsigned int index)
for (ah = daemon->addn_hosts; ah; ah = ah->next)
if (ah->index == index)
return ah->fname;
#ifdef HAVE_INOTIFY
for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
if (ah->index == index)
return ah->fname;
#endif
return "<unknown>";
}
@@ -1540,10 +1587,12 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
if (!option_bool(OPT_LOG))
return;
name = sanitise(name);
if (addr)
{
if (flags & F_KEYTAG)
sprintf(daemon->addrbuff, arg, addr->addr.keytag);
sprintf(daemon->addrbuff, arg, addr->addr.log.keytag, addr->addr.log.algo, addr->addr.log.digest);
else
{
#ifdef HAVE_IPV6
@@ -1622,7 +1671,16 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
if (strlen(name) == 0)
name = ".";
my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
if (option_bool(OPT_EXTRALOG))
{
int port = prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2);
if (flags & F_NOEXTRA)
my_syslog(LOG_INFO, "* %s/%u %s %s %s %s", daemon->addrbuff2, port, source, name, verb, dest);
else
my_syslog(LOG_INFO, "%u %s/%u %s %s %s %s", daemon->log_display_id, daemon->addrbuff2, port, source, name, verb, dest);
}
else
my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
}

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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
@@ -17,15 +17,21 @@
#define FTABSIZ 150 /* max number of outstanding requests (default) */
#define MAX_PROCS 20 /* max no children for TCP requests */
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
#define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */
#define TCP_BACKLOG 32 /* kernel backlog limit for TCP connections */
#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
#define KEYBLOCK_LEN 40 /* choose to mininise fragmentation when storing DNSSEC keys */
#define SAFE_PKTSZ 1280 /* "go anywhere" UDP packet size */
#define KEYBLOCK_LEN 40 /* choose to minimise fragmentation when storing DNSSEC keys */
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
#define FORWARD_TEST 50 /* try all servers every 50 queries */
#define FORWARD_TIME 20 /* or 20 seconds */
#define SERVERS_LOGGED 30 /* Only log this many servers when logging state */
#define LOCALS_LOGGED 8 /* Only log this many local addresses when logging state */
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
#define CACHESIZ 150 /* default cache size */
#define TTL_FLOOR_LIMIT 3600 /* don't allow --min-cache-ttl to raise TTL above this under any circumstances */
#define MAXLEASES 1000 /* maximum number of DHCP leases */
#define PING_WAIT 3 /* wait for ping address-in-use test */
#define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */
@@ -47,6 +53,8 @@
#define SOA_REFRESH 1200 /* SOA refresh default */
#define SOA_RETRY 180 /* SOA retry default */
#define SOA_EXPIRY 1209600 /* SOA expiry default */
#define LOOP_TEST_DOMAIN "test" /* domain for loop testing, "test" is reserved by RFC 2606 and won't therefore clash */
#define LOOP_TEST_TYPE T_TXT
/* compile-time options: uncomment below to enable or do eg.
make COPTS=-DHAVE_BROKEN_RTC
@@ -86,13 +94,13 @@ HAVE_DBUS
servers via DBus.
HAVE_IDN
define this if you want international domain name support.
NOTE: for backwards compatibility, IDN support is automatically
included when internationalisation support is built, using the
*-i18n makefile targets, even if HAVE_IDN is not explicitly set.
define this if you want international domain name 2003 support.
HAVE_LIBIDN2
define this if you want international domain name 2008 support.
HAVE_CONNTRACK
define this to include code which propogates conntrack marks from
define this to include code which propagates conntrack marks from
incoming DNS queries to the corresponding upstream queries. This adds
a build-dependency on libnetfilter_conntrack, but the resulting binary will
still run happily on a kernel without conntrack support.
@@ -105,7 +113,17 @@ HAVE_AUTH
define this to include the facility to act as an authoritative DNS
server for one or more zones.
HAVE_DNSSEC
include DNSSEC validator.
HAVE_LOOP
include functionality to probe for and remove DNS forwarding loops.
HAVE_INOTIFY
use the Linux inotify facility to efficiently re-read configuration files.
NO_ID
Don't report *.bind CHAOS info to clients, forward such requests upstream instead.
NO_IPV6
NO_TFTP
NO_DHCP
@@ -113,11 +131,17 @@ NO_DHCP6
NO_SCRIPT
NO_LARGEFILE
NO_AUTH
these are avilable to explictly disable compile time options which would
NO_INOTIFY
these are available to explicitly disable compile time options which would
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
which are enabled by default in the distributed source tree. Building dnsmasq
with something like "make COPTS=-DNO_SCRIPT" will do the trick.
NO_NETTLE_ECC
Don't include the ECDSA cypher in DNSSEC validation. Needed for older Nettle versions.
NO_GMP
Don't use and link against libgmp, Useful if nettle is built with --enable-mini-gmp.
LEASEFILE
CONFFILE
RESOLVFILE
@@ -141,6 +165,7 @@ RESOLVFILE
#define HAVE_SCRIPT
#define HAVE_AUTH
#define HAVE_IPSET
#define HAVE_LOOP
/* Build options which require external libraries.
@@ -152,6 +177,7 @@ RESOLVFILE
/* #define HAVE_LUASCRIPT */
/* #define HAVE_DBUS */
/* #define HAVE_IDN */
/* #define HAVE_LIBIDN2 */
/* #define HAVE_CONNTRACK */
/* #define HAVE_DNSSEC */
@@ -208,7 +234,7 @@ HAVE_SOCKADDR_SA_LEN
defined if struct sockaddr has sa_len field (*BSD)
*/
/* Must preceed __linux__ since uClinux defines __linux__ too. */
/* Must precede __linux__ since uClinux defines __linux__ too. */
#if defined(__uClinux__)
#define HAVE_LINUX_NETWORK
#define HAVE_GETOPT_LONG
@@ -246,7 +272,7 @@ HAVE_SOCKADDR_SA_LEN
defined(__DragonFly__) || \
defined(__FreeBSD_kernel__)
#define HAVE_BSD_NETWORK
/* Later verions of FreeBSD have getopt_long() */
/* Later versions of FreeBSD have getopt_long() */
#if defined(optional_argument) && defined(required_argument)
# define HAVE_GETOPT_LONG
#endif
@@ -261,6 +287,7 @@ HAVE_SOCKADDR_SA_LEN
/* Select the RFC_3542 version of the IPv6 socket API.
Define before netinet6/in6.h is included. */
#define __APPLE_USE_RFC_3542
#define NO_IPSET
#elif defined(__NetBSD__)
#define HAVE_BSD_NETWORK
@@ -316,7 +343,7 @@ HAVE_SOCKADDR_SA_LEN
#define HAVE_DHCP
#endif
#if defined(NO_SCRIPT) || !defined(HAVE_DHCP) || defined(NO_FORK)
#if defined(NO_SCRIPT) || defined(NO_FORK)
#undef HAVE_SCRIPT
#undef HAVE_LUASCRIPT
#endif
@@ -330,12 +357,20 @@ HAVE_SOCKADDR_SA_LEN
#undef HAVE_AUTH
#endif
#if defined(NO_IPSET) || !defined(HAVE_LINUX_NETWORK)
#if defined(NO_IPSET)
#undef HAVE_IPSET
#endif
#ifdef NO_LOOP
#undef HAVE_LOOP
#endif
#if defined (HAVE_LINUX_NETWORK) && !defined(NO_INOTIFY)
#define HAVE_INOTIFY
#endif
/* Define a string indicating which options are in use.
DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */
DNSMASQ_COMPILE_OPTS is only defined in dnsmasq.c */
#ifdef DNSMASQ_COMPILE_OPTS
@@ -362,10 +397,14 @@ static char *compile_opts =
"no-"
#endif
"i18n "
#if !defined(LOCALEDIR) && !defined(HAVE_IDN)
#if defined(HAVE_LIBIDN2)
"IDN2 "
#else
#if !defined(HAVE_IDN)
"no-"
#endif
"IDN "
#endif
"IDN "
#endif
#ifndef HAVE_DHCP
"no-"
#endif
@@ -375,14 +414,14 @@ static char *compile_opts =
"no-"
# endif
"DHCPv6 "
# if !defined(HAVE_SCRIPT)
#endif
#if !defined(HAVE_SCRIPT)
"no-scripts "
# else
# if !defined(HAVE_LUASCRIPT)
"no-"
# endif
"Lua "
#else
# if !defined(HAVE_LUASCRIPT)
"no-"
# endif
"Lua "
#endif
#ifndef HAVE_TFTP
"no-"
@@ -403,7 +442,18 @@ static char *compile_opts =
#ifndef HAVE_DNSSEC
"no-"
#endif
"DNSSEC";
"DNSSEC "
#ifdef NO_ID
"no-ID "
#endif
#ifndef HAVE_LOOP
"no-"
#endif
"loop-detect "
#ifndef HAVE_INOTIFY
"no-"
#endif
"inotify";
#endif

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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
@@ -35,6 +35,11 @@ const char* introspection_xml_template =
" <method name=\"GetVersion\">\n"
" <arg name=\"version\" direction=\"out\" type=\"s\"/>\n"
" </method>\n"
#ifdef HAVE_LOOP
" <method name=\"GetLoopServers\">\n"
" <arg name=\"server\" direction=\"out\" type=\"as\"/>\n"
" </method>\n"
#endif
" <method name=\"SetServers\">\n"
" <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"
" </method>\n"
@@ -44,6 +49,12 @@ const char* introspection_xml_template =
" <method name=\"SetServersEx\">\n"
" <arg name=\"servers\" direction=\"in\" type=\"aas\"/>\n"
" </method>\n"
" <method name=\"SetFilterWin2KOption\">\n"
" <arg name=\"filterwin2k\" direction=\"in\" type=\"b\"/>\n"
" </method>\n"
" <method name=\"SetBogusPrivOption\">\n"
" <arg name=\"boguspriv\" direction=\"in\" type=\"b\"/>\n"
" </method>\n"
" <signal name=\"DhcpLeaseAdded\">\n"
" <arg name=\"ipaddr\" type=\"s\"/>\n"
" <arg name=\"hwaddr\" type=\"s\"/>\n"
@@ -59,6 +70,21 @@ const char* introspection_xml_template =
" <arg name=\"hwaddr\" type=\"s\"/>\n"
" <arg name=\"hostname\" type=\"s\"/>\n"
" </signal>\n"
#ifdef HAVE_DHCP
" <method name=\"AddDhcpLease\">\n"
" <arg name=\"ipaddr\" type=\"s\"/>\n"
" <arg name=\"hwaddr\" type=\"s\"/>\n"
" <arg name=\"hostname\" type=\"ay\"/>\n"
" <arg name=\"clid\" type=\"ay\"/>\n"
" <arg name=\"lease_duration\" type=\"u\"/>\n"
" <arg name=\"ia_id\" type=\"u\"/>\n"
" <arg name=\"is_temporary\" type=\"b\"/>\n"
" </method>\n"
" <method name=\"DeleteDhcpLease\">\n"
" <arg name=\"ipaddr\" type=\"s\"/>\n"
" <arg name=\"success\" type=\"b\" direction=\"out\"/>\n"
" </method>\n"
#endif
" </interface>\n"
"</node>\n";
@@ -150,13 +176,16 @@ static void dbus_read_servers(DBusMessage *message)
dbus_message_iter_get_basic(&iter, &p[i]);
dbus_message_iter_next (&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BYTE)
break;
{
i++;
break;
}
}
#ifndef HAVE_IPV6
my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support"));
#else
if (i == sizeof(struct in6_addr)-1)
if (i == sizeof(struct in6_addr))
{
memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr));
#ifdef HAVE_SOCKADDR_SA_LEN
@@ -196,6 +225,29 @@ static void dbus_read_servers(DBusMessage *message)
cleanup_servers();
}
#ifdef HAVE_LOOP
static DBusMessage *dbus_reply_server_loop(DBusMessage *message)
{
DBusMessageIter args, args_iter;
struct server *serv;
DBusMessage *reply = dbus_message_new_method_return(message);
dbus_message_iter_init_append (reply, &args);
dbus_message_iter_open_container (&args, DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING, &args_iter);
for (serv = daemon->servers; serv; serv = serv->next)
if (serv->flags & SERV_LOOP)
{
prettyprint_addr(&serv->addr, daemon->addrbuff);
dbus_message_iter_append_basic (&args_iter, DBUS_TYPE_STRING, &daemon->addrbuff);
}
dbus_message_iter_close_container (&args, &args_iter);
return reply;
}
#endif
static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
{
DBusMessageIter iter, array_iter, string_iter;
@@ -372,6 +424,195 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
return error;
}
static DBusMessage *dbus_set_bool(DBusMessage *message, int flag, char *name)
{
DBusMessageIter iter;
dbus_bool_t enabled;
if (!dbus_message_iter_init(message, &iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Expected boolean argument");
dbus_message_iter_get_basic(&iter, &enabled);
if (enabled)
{
my_syslog(LOG_INFO, _("Enabling --%s option from D-Bus"), name);
set_option_bool(flag);
}
else
{
my_syslog(LOG_INFO, _("Disabling --%s option from D-Bus"), name);
reset_option_bool(flag);
}
return NULL;
}
#ifdef HAVE_DHCP
static DBusMessage *dbus_add_lease(DBusMessage* message)
{
struct dhcp_lease *lease;
const char *ipaddr, *hwaddr, *hostname, *tmp;
const unsigned char* clid;
int clid_len, hostname_len, hw_len, hw_type;
dbus_uint32_t expires, ia_id;
dbus_bool_t is_temporary;
struct all_addr addr;
time_t now = dnsmasq_time();
unsigned char dhcp_chaddr[DHCP_CHADDR_MAX];
DBusMessageIter iter, array_iter;
if (!dbus_message_iter_init(message, &iter))
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Failed to initialize dbus message iter");
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected string as first argument");
dbus_message_iter_get_basic(&iter, &ipaddr);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected string as second argument");
dbus_message_iter_get_basic(&iter, &hwaddr);
dbus_message_iter_next(&iter);
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
(dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected byte array as third argument");
dbus_message_iter_recurse(&iter, &array_iter);
dbus_message_iter_get_fixed_array(&array_iter, &hostname, &hostname_len);
tmp = memchr(hostname, '\0', hostname_len);
if (tmp)
{
if (tmp == &hostname[hostname_len - 1])
hostname_len--;
else
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Hostname contains an embedded NUL character");
}
dbus_message_iter_next(&iter);
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
(dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected byte array as fourth argument");
dbus_message_iter_recurse(&iter, &array_iter);
dbus_message_iter_get_fixed_array(&array_iter, &clid, &clid_len);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected uint32 as fifth argument");
dbus_message_iter_get_basic(&iter, &expires);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected uint32 as sixth argument");
dbus_message_iter_get_basic(&iter, &ia_id);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected uint32 as sixth argument");
dbus_message_iter_get_basic(&iter, &is_temporary);
if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
{
if (ia_id != 0 || is_temporary)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"ia_id and is_temporary must be zero for IPv4 lease");
if (!(lease = lease_find_by_addr(addr.addr.addr4)))
lease = lease4_allocate(addr.addr.addr4);
}
#ifdef HAVE_DHCP6
else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
{
if (!(lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0)))
lease = lease6_allocate(&addr.addr.addr6,
is_temporary ? LEASE_TA : LEASE_NA);
lease_set_iaid(lease, ia_id);
}
#endif
else
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
"Invalid IP address '%s'", ipaddr);
hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
if (hw_type == 0 && hw_len != 0)
hw_type = ARPHRD_ETHER;
lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
clid_len, now, 0);
lease_set_expires(lease, expires, now);
if (hostname_len != 0)
lease_set_hostname(lease, hostname, 0, get_domain(lease->addr), NULL);
lease_update_file(now);
lease_update_dns(0);
return NULL;
}
static DBusMessage *dbus_del_lease(DBusMessage* message)
{
struct dhcp_lease *lease;
DBusMessageIter iter;
const char *ipaddr;
DBusMessage *reply;
struct all_addr addr;
dbus_bool_t ret = 1;
time_t now = dnsmasq_time();
if (!dbus_message_iter_init(message, &iter))
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Failed to initialize dbus message iter");
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected string as first argument");
dbus_message_iter_get_basic(&iter, &ipaddr);
if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
lease = lease_find_by_addr(addr.addr.addr4);
#ifdef HAVE_DHCP6
else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0);
#endif
else
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
"Invalid IP address '%s'", ipaddr);
if (lease)
{
lease_prune(lease, now);
lease_update_file(now);
lease_update_dns(0);
}
else
ret = 0;
if ((reply = dbus_message_new_method_return(message)))
dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &ret,
DBUS_TYPE_INVALID);
return reply;
}
#endif
DBusHandlerResult message_handler(DBusConnection *connection,
DBusMessage *message,
void *user_data)
@@ -400,6 +641,12 @@ DBusHandlerResult message_handler(DBusConnection *connection,
dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID);
}
#ifdef HAVE_LOOP
else if (strcmp(method, "GetLoopServers") == 0)
{
reply = dbus_reply_server_loop(message);
}
#endif
else if (strcmp(method, "SetServers") == 0)
{
dbus_read_servers(message);
@@ -415,6 +662,24 @@ DBusHandlerResult message_handler(DBusConnection *connection,
reply = dbus_read_servers_ex(message, 1);
new_servers = 1;
}
else if (strcmp(method, "SetFilterWin2KOption") == 0)
{
reply = dbus_set_bool(message, OPT_FILTER, "filterwin2k");
}
else if (strcmp(method, "SetBogusPrivOption") == 0)
{
reply = dbus_set_bool(message, OPT_BOGUSPRIV, "bogus-priv");
}
#ifdef HAVE_DHCP
else if (strcmp(method, "AddDhcpLease") == 0)
{
reply = dbus_add_lease(message);
}
else if (strcmp(method, "DeleteDhcpLease") == 0)
{
reply = dbus_del_lease(message);
}
#endif
else if (strcmp(method, "ClearCache") == 0)
clear_cache = 1;
else
@@ -483,8 +748,7 @@ char *dbus_init(void)
}
void set_dbus_listeners(int *maxfdp,
fd_set *rset, fd_set *wset, fd_set *eset)
void set_dbus_listeners(void)
{
struct watch *w;
@@ -494,19 +758,17 @@ void set_dbus_listeners(int *maxfdp,
unsigned int flags = dbus_watch_get_flags(w->watch);
int fd = dbus_watch_get_unix_fd(w->watch);
bump_maxfd(fd, maxfdp);
if (flags & DBUS_WATCH_READABLE)
FD_SET(fd, rset);
poll_listen(fd, POLLIN);
if (flags & DBUS_WATCH_WRITABLE)
FD_SET(fd, wset);
poll_listen(fd, POLLOUT);
FD_SET(fd, eset);
poll_listen(fd, POLLERR);
}
}
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
void check_dbus_listeners()
{
DBusConnection *connection = (DBusConnection *)daemon->dbus;
struct watch *w;
@@ -517,13 +779,13 @@ void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
unsigned int flags = 0;
int fd = dbus_watch_get_unix_fd(w->watch);
if (FD_ISSET(fd, rset))
if (poll_check(fd, POLLIN))
flags |= DBUS_WATCH_READABLE;
if (FD_ISSET(fd, wset))
if (poll_check(fd, POLLOUT))
flags |= DBUS_WATCH_WRITABLE;
if (FD_ISSET(fd, eset))
if (poll_check(fd, POLLERR))
flags |= DBUS_WATCH_ERROR;
if (flags != 0)
@@ -558,7 +820,7 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname)
if (lease->flags & (LEASE_TA | LEASE_NA))
{
print_mac(mac, lease->clid, lease->clid_len);
inet_ntop(AF_INET6, lease->hwaddr, daemon->addrbuff, ADDRSTRLEN);
inet_ntop(AF_INET6, &lease->addr6, daemon->addrbuff, ADDRSTRLEN);
}
else
#endif

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,11 +20,11 @@
void dhcp_common_init(void)
{
/* These each hold a DHCP option max size 255
and get a terminating zero added */
daemon->dhcp_buff = safe_malloc(256);
daemon->dhcp_buff2 = safe_malloc(256);
daemon->dhcp_buff3 = safe_malloc(256);
/* These each hold a DHCP option max size 255
and get a terminating zero added */
daemon->dhcp_buff = safe_malloc(DHCP_BUFF_SZ);
daemon->dhcp_buff2 = safe_malloc(DHCP_BUFF_SZ);
daemon->dhcp_buff3 = safe_malloc(DHCP_BUFF_SZ);
/* dhcp_packet is used by v4 and v6, outpacket only by v6
sizeof(struct dhcp_packet) is as good an initial size as any,
@@ -545,8 +545,8 @@ static const struct opttab_t {
{ "parameter-request", 55, OT_INTERNAL },
{ "message", 56, OT_INTERNAL },
{ "max-message-size", 57, OT_INTERNAL },
{ "T1", 58, OT_INTERNAL | OT_TIME},
{ "T2", 59, OT_INTERNAL | OT_TIME},
{ "T1", 58, OT_TIME},
{ "T2", 59, OT_TIME},
{ "vendor-class", 60, 0 },
{ "client-id", 61, OT_INTERNAL },
{ "nis+-domain", 64, OT_NAME },
@@ -599,7 +599,7 @@ static const struct opttab_t opttab6[] = {
{ "sntp-server", 31, OT_ADDR_LIST },
{ "information-refresh-time", 32, OT_TIME },
{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
{ "ntp-server", 56, OT_ADDR_LIST },
{ "ntp-server", 56, 0 },
{ "bootfile-url", 59, OT_NAME },
{ "bootfile-param", 60, OT_CSTRING },
{ NULL, 0, 0 }
@@ -855,14 +855,14 @@ void log_context(int family, struct dhcp_context *context)
if (context->flags & CONTEXT_RA_STATELESS)
{
if (context->flags & CONTEXT_TEMPLATE)
strncpy(daemon->dhcp_buff, context->template_interface, 256);
strncpy(daemon->dhcp_buff, context->template_interface, DHCP_BUFF_SZ);
else
strcpy(daemon->dhcp_buff, daemon->addrbuff);
}
else
#endif
inet_ntop(family, start, daemon->dhcp_buff, 256);
inet_ntop(family, end, daemon->dhcp_buff3, 256);
inet_ntop(family, start, daemon->dhcp_buff, DHCP_BUFF_SZ);
inet_ntop(family, end, daemon->dhcp_buff3, DHCP_BUFF_SZ);
my_syslog(MS_DHCP | LOG_INFO,
(context->flags & CONTEXT_RA_STATELESS) ?
_("%s stateless on %s%.0s%.0s%s") :

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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
@@ -19,6 +19,10 @@
#define DHCP_CLIENT_ALTPORT 1068
#define PXE_PORT 4011
/* These each hold a DHCP option max size 255
and get a terminating zero added */
#define DHCP_BUFF_SZ 256
#define BOOTREQUEST 1
#define BOOTREPLY 2
#define DHCP_COOKIE 0x63825363

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -67,9 +67,9 @@ static int make_fd(int port)
setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1)
die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET);
/* When bind-interfaces is set, there might be more than one dnmsasq
/* When bind-interfaces is set, there might be more than one dnsmasq
instance binding port 67. That's OK if they serve different networks.
Need to set REUSEADDR|REUSEPORT to make this posible.
Need to set REUSEADDR|REUSEPORT to make this possible.
Handle the case that REUSEPORT is defined, but the kernel doesn't
support it. This handles the introduction of REUSEPORT on Linux. */
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
@@ -145,11 +145,14 @@ void dhcp_packet(time_t now, int pxe_fd)
struct cmsghdr *cmptr;
struct iovec iov;
ssize_t sz;
int iface_index = 0, unicast_dest = 0, is_inform = 0;
int iface_index = 0, unicast_dest = 0, is_inform = 0, loopback = 0;
int rcvd_iface_index;
struct in_addr iface_addr;
struct iface_param parm;
time_t recvtime = now;
#ifdef HAVE_LINUX_NETWORK
struct arpreq arp_req;
struct timeval tv;
#endif
union {
@@ -176,6 +179,9 @@ void dhcp_packet(time_t now, int pxe_fd)
return;
#if defined (HAVE_LINUX_NETWORK)
if (ioctl(fd, SIOCGSTAMP, &tv) == 0)
recvtime = tv.tv_sec;
if (msg.msg_controllen >= sizeof(struct cmsghdr))
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
@@ -217,26 +223,34 @@ void dhcp_packet(time_t now, int pxe_fd)
}
#endif
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name) ||
ioctl(daemon->dhcpfd, SIOCGIFFLAGS, &ifr) != 0)
return;
mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
loopback = !mess->giaddr.s_addr && (ifr.ifr_flags & IFF_LOOPBACK);
#ifdef HAVE_LINUX_NETWORK
/* ARP fiddling uses original interface even if we pretend to use a different one. */
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
#endif
/* One form of bridging on BSD has the property that packets
can be recieved on bridge interfaces which do not have an IP address.
We allow these to be treated as aliases of another interface which does have
an IP address with --dhcp-bridge=interface,alias,alias */
/* If the interface on which the DHCP request was received is an
alias of some other interface (as specified by the
--bridge-interface option), change ifr.ifr_name so that we look
for DHCP contexts associated with the aliased interface instead
of with the aliasing one. */
rcvd_iface_index = iface_index;
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
{
for (alias = bridge->alias; alias; alias = alias->next)
if (strncmp(ifr.ifr_name, alias->iface, IF_NAMESIZE) == 0)
if (wildcard_matchn(alias->iface, ifr.ifr_name, IF_NAMESIZE))
{
if (!(iface_index = if_nametoindex(bridge->iface)))
{
my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), ifr.ifr_name);
my_syslog(MS_DHCP | LOG_WARNING,
_("unknown interface %s in bridge-interface"),
bridge->iface);
return;
}
else
@@ -259,8 +273,8 @@ void dhcp_packet(time_t now, int pxe_fd)
if ((relay = relay_reply4((struct dhcp_packet *)daemon->dhcp_packet.iov_base, ifr.ifr_name)))
{
/* Reply from server, using us as relay. */
iface_index = relay->iface_index;
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
rcvd_iface_index = relay->iface_index;
if (!indextoname(daemon->dhcpfd, rcvd_iface_index, ifr.ifr_name))
return;
is_relay_reply = 1;
iov.iov_len = sz;
@@ -275,7 +289,8 @@ void dhcp_packet(time_t now, int pxe_fd)
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
else
{
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
if (iface_check(AF_INET, NULL, ifr.ifr_name, NULL))
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
return;
}
@@ -320,7 +335,7 @@ void dhcp_packet(time_t now, int pxe_fd)
/* We're relaying this request */
if (parm.relay_local.s_addr != 0 &&
relay_upstream4(parm.relay, (struct dhcp_packet *)daemon->dhcp_packet.iov_base, (size_t)sz, iface_index))
relay_upstream4(parm.relay, mess, (size_t)sz, iface_index))
return;
/* May have configured relay, but not DHCP server */
@@ -329,14 +344,14 @@ void dhcp_packet(time_t now, int pxe_fd)
lease_prune(NULL, now); /* lose any expired leases */
iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz,
now, unicast_dest, &is_inform, pxe_fd, iface_addr);
now, unicast_dest, loopback, &is_inform, pxe_fd, iface_addr, recvtime);
lease_update_file(now);
lease_update_dns(0);
if (iov.iov_len == 0)
return;
}
msg.msg_name = &dest;
msg.msg_namelen = sizeof(dest);
msg.msg_control = NULL;
@@ -376,35 +391,41 @@ void dhcp_packet(time_t now, int pxe_fd)
}
}
#if defined(HAVE_LINUX_NETWORK)
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
else
{
/* broadcast to 255.255.255.255 (or mac address invalid) */
/* fill cmsg for outbound interface (both broadcast & unicast) */
struct in_pktinfo *pkt;
msg.msg_control = control_u.control;
msg.msg_controllen = sizeof(control_u);
cmptr = CMSG_FIRSTHDR(&msg);
pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
pkt->ipi_ifindex = iface_index;
pkt->ipi_ifindex = rcvd_iface_index;
pkt->ipi_spec_dst.s_addr = 0;
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
cmptr->cmsg_level = IPPROTO_IP;
cmptr->cmsg_type = IP_PKTINFO;
dest.sin_addr.s_addr = INADDR_BROADCAST;
dest.sin_port = htons(daemon->dhcp_client_port);
}
else
{
/* unicast to unconfigured client. Inject mac address direct into ARP cache.
struct sockaddr limits size to 14 bytes. */
dest.sin_addr = mess->yiaddr;
dest.sin_port = htons(daemon->dhcp_client_port);
memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
arp_req.arp_ha.sa_family = mess->htype;
memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
/* interface name already copied in */
arp_req.arp_flags = ATF_COM;
ioctl(daemon->dhcpfd, SIOCSARP, &arp_req);
cmptr->cmsg_type = IP_PKTINFO;
if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
{
/* broadcast to 255.255.255.255 (or mac address invalid) */
dest.sin_addr.s_addr = INADDR_BROADCAST;
dest.sin_port = htons(daemon->dhcp_client_port);
}
else
{
/* unicast to unconfigured client. Inject mac address direct into ARP cache.
struct sockaddr limits size to 14 bytes. */
dest.sin_addr = mess->yiaddr;
dest.sin_port = htons(daemon->dhcp_client_port);
memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
arp_req.arp_ha.sa_family = mess->htype;
memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
/* interface name already copied in */
arp_req.arp_flags = ATF_COM;
if (ioctl(daemon->dhcpfd, SIOCSARP, &arp_req) == -1)
my_syslog(MS_DHCP | LOG_ERR, _("ARP-cache injection failed: %s"), strerror(errno));
}
}
#elif defined(HAVE_SOLARIS_NETWORK)
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
@@ -442,9 +463,14 @@ void dhcp_packet(time_t now, int pxe_fd)
setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
#endif
while(sendmsg(fd, &msg, 0) == -1 && retry_send());
while(retry_send(sendmsg(fd, &msg, 0)));
/* This can fail when, eg, iptables DROPS destination 255.255.255.255 */
if (errno != 0)
my_syslog(MS_DHCP | LOG_WARNING, _("Error sending DHCP packet to %s: %s"),
inet_ntoa(dest.sin_addr), strerror(errno));
}
/* check against secondary interface addresses */
static int check_listen_addrs(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam)
@@ -479,7 +505,7 @@ static int check_listen_addrs(struct in_addr local, int if_index, char *label,
3) Fills in local (this host) and router (this host or relay) addresses.
4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current.
Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
Note that the current chain may be superseded later for configured hosts or those coming via gateways. */
static int complete_context(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam)
@@ -579,7 +605,7 @@ struct dhcp_context *narrow_context(struct dhcp_context *context,
{
/* We start of with a set of possible contexts, all on the current physical interface.
These are chained on ->current.
Here we have an address, and return the actual context correponding to that
Here we have an address, and return the actual context corresponding to that
address. Note that none may fit, if the address came a dhcp-host and is outside
any dhcp-range. In that case we return a static range if possible, or failing that,
any context on the correct subnet. (If there's more than one, this is a dodgy
@@ -621,9 +647,69 @@ struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct i
return NULL;
}
/* Check if and address is in use by sending ICMP ping.
This wrapper handles a cache and load-limiting.
Return is NULL is address in use, or a pointer to a cache entry
recording that it isn't. */
struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, unsigned int hash, int loopback)
{
static struct ping_result dummy;
struct ping_result *r, *victim = NULL;
int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
((float)PING_WAIT)));
/* check if we failed to ping addr sometime in the last
PING_CACHE_TIME seconds. If so, assume the same situation still exists.
This avoids problems when a stupid client bangs
on us repeatedly. As a final check, if we did more
than 60% of the possible ping checks in the last
PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
for (count = 0, r = daemon->ping_results; r; r = r->next)
if (difftime(now, r->time) > (float)PING_CACHE_TIME)
victim = r; /* old record */
else
{
count++;
if (r->addr.s_addr == addr.s_addr)
return r;
}
/* didn't find cached entry */
if ((count >= max) || option_bool(OPT_NO_PING) || loopback)
{
/* overloaded, or configured not to check, loopback interface, return "not in use" */
dummy.hash = 0;
return &dummy;
}
else if (icmp_ping(addr))
return NULL; /* address in use. */
else
{
/* at this point victim may hold an expired record */
if (!victim)
{
if ((victim = whine_malloc(sizeof(struct ping_result))))
{
victim->next = daemon->ping_results;
daemon->ping_results = victim;
}
}
/* record that this address is OK for 30s
without more ping checks */
if (victim)
{
victim->addr = addr;
victim->time = now;
victim->hash = hash;
}
return victim;
}
}
int address_allocate(struct dhcp_context *context,
struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
struct dhcp_netid *netids, time_t now)
struct dhcp_netid *netids, time_t now, int loopback)
{
/* Find a free address: exclude anything in use and anything allocated to
a particular hwaddr/clientid/hostname in our configuration.
@@ -637,7 +723,11 @@ int address_allocate(struct dhcp_context *context,
/* hash hwaddr: use the SDBM hashing algorithm. Seems to give good
dispersal even with similarly-valued "strings". */
for (j = 0, i = 0; i < hw_len; i++)
j += hwaddr[i] + (j << 6) + (j << 16) - j;
j = hwaddr[i] + (j << 6) + (j << 16) - j;
/* j == 0 is marker */
if (j == 0)
j = 1;
for (pass = 0; pass <= 1; pass++)
for (c = context; c; c = c->current)
@@ -675,69 +765,27 @@ int address_allocate(struct dhcp_context *context,
(!IN_CLASSC(ntohl(addr.s_addr)) ||
((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
{
struct ping_result *r, *victim = NULL;
int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
((float)PING_WAIT)));
struct ping_result *r;
*addrp = addr;
/* check if we failed to ping addr sometime in the last
PING_CACHE_TIME seconds. If so, assume the same situation still exists.
This avoids problems when a stupid client bangs
on us repeatedly. As a final check, if we did more
than 60% of the possible ping checks in the last
PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
for (count = 0, r = daemon->ping_results; r; r = r->next)
if (difftime(now, r->time) > (float)PING_CACHE_TIME)
victim = r; /* old record */
else
{
count++;
if (r->addr.s_addr == addr.s_addr)
{
/* consec-ip mode: we offered this address for another client
(different hash) recently, don't offer it to this one. */
if (option_bool(OPT_CONSEC_ADDR) && r->hash != j)
break;
return 1;
}
}
if (!r)
{
if ((count < max) && !option_bool(OPT_NO_PING) && icmp_ping(addr))
if ((r = do_icmp_ping(now, addr, j, loopback)))
{
/* consec-ip mode: we offered this address for another client
(different hash) recently, don't offer it to this one. */
if (!option_bool(OPT_CONSEC_ADDR) || r->hash == j)
{
/* address in use: perturb address selection so that we are
less likely to try this address again. */
if (!option_bool(OPT_CONSEC_ADDR))
c->addr_epoch++;
}
else
{
/* at this point victim may hold an expired record */
if (!victim)
{
if ((victim = whine_malloc(sizeof(struct ping_result))))
{
victim->next = daemon->ping_results;
daemon->ping_results = victim;
}
}
/* record that this address is OK for 30s
without more ping checks */
if (victim)
{
victim->addr = addr;
victim->time = now;
victim->hash = j;
}
*addrp = addr;
return 1;
}
}
else
{
/* address in use: perturb address selection so that we are
less likely to try this address again. */
if (!option_bool(OPT_CONSEC_ADDR))
c->addr_epoch++;
}
}
addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1))

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -27,17 +27,10 @@ struct iface_param {
int ind, addr_match;
};
struct mac_param {
struct in6_addr *target;
unsigned char *mac;
unsigned int maclen;
};
static int complete_context6(struct in6_addr *local, int prefix,
int scope, int if_index, int flags,
unsigned int preferred, unsigned int valid, void *vparam);
static int find_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv);
static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm);
void dhcp6_init(void)
@@ -58,9 +51,9 @@ void dhcp6_init(void)
!set_ipv6pktinfo(fd))
die (_("cannot create DHCPv6 socket: %s"), NULL, EC_BADNET);
/* When bind-interfaces is set, there might be more than one dnmsasq
/* When bind-interfaces is set, there might be more than one dnsmasq
instance binding port 547. That's OK if they serve different networks.
Need to set REUSEADDR|REUSEPORT to make this posible.
Need to set REUSEADDR|REUSEPORT to make this possible.
Handle the case that REUSEPORT is defined, but the kernel doesn't
support it. This handles the introduction of REUSEPORT on Linux. */
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
@@ -144,6 +137,8 @@ void dhcp6_packet(time_t now)
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) == 0)
{
struct dhcp_bridge *bridge, *alias;
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
return;
@@ -160,6 +155,30 @@ void dhcp6_packet(time_t now)
memset(&parm.fallback, 0, IN6ADDRSZ);
memset(&parm.ll_addr, 0, IN6ADDRSZ);
memset(&parm.ula_addr, 0, IN6ADDRSZ);
/* If the interface on which the DHCPv6 request was received is
an alias of some other interface (as specified by the
--bridge-interface option), change parm.ind so that we look
for DHCPv6 contexts associated with the aliased interface
instead of with the aliasing one. */
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
{
for (alias = bridge->alias; alias; alias = alias->next)
if (wildcard_matchn(alias->iface, ifr.ifr_name, IF_NAMESIZE))
{
parm.ind = if_nametoindex(bridge->iface);
if (!parm.ind)
{
my_syslog(MS_DHCP | LOG_WARNING,
_("unknown interface %s in bridge-interface"),
bridge->iface);
return;
}
break;
}
if (alias)
break;
}
for (context = daemon->dhcp6; context; context = context->next)
if (IN6_IS_ADDR_UNSPECIFIED(&context->start6) && context->prefix == 0)
@@ -201,14 +220,14 @@ void dhcp6_packet(time_t now)
inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id);
relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id, now);
return;
}
/* May have configured relay, but not DHCP server */
if (!daemon->doing_dhcp6)
return;
lease_prune(NULL, now); /* lose any expired leases */
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
@@ -225,79 +244,56 @@ void dhcp6_packet(time_t now)
if (port != 0)
{
from.sin6_port = htons(port);
while (sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, save_counter(0),
0, (struct sockaddr *)&from, sizeof(from)) == -1 &&
retry_send());
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
save_counter(0), 0, (struct sockaddr *)&from,
sizeof(from))));
}
}
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned int *maclenp, unsigned int *mactypep)
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned int *maclenp, unsigned int *mactypep, time_t now)
{
/* Recieving a packet from a host does not populate the neighbour
/* Receiving a packet from a host does not populate the neighbour
cache, so we send a neighbour discovery request if we can't
find the sender. Repeat a few times in case of packet loss. */
struct neigh_packet neigh;
struct sockaddr_in6 addr;
struct mac_param mac_param;
int i;
union mysockaddr addr;
int i, maclen;
neigh.type = ND_NEIGHBOR_SOLICIT;
neigh.code = 0;
neigh.reserved = 0;
neigh.target = *client;
/* RFC4443 section-2.3: checksum has to be zero to be calculated */
neigh.checksum = 0;
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN
addr.sin6_len = sizeof(struct sockaddr_in6);
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(IPPROTO_ICMPV6);
addr.sin6_addr = *client;
addr.sin6_scope_id = iface;
mac_param.target = client;
mac_param.maclen = 0;
mac_param.mac = mac;
addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_port = htons(IPPROTO_ICMPV6);
addr.in6.sin6_addr = *client;
addr.in6.sin6_scope_id = iface;
for (i = 0; i < 5; i++)
{
struct timespec ts;
iface_enumerate(AF_UNSPEC, &mac_param, find_mac);
if (mac_param.maclen != 0)
if ((maclen = find_mac(&addr, mac, 0, now)) != 0)
break;
sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, (struct sockaddr *)&addr, sizeof(addr));
sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr));
ts.tv_sec = 0;
ts.tv_nsec = 100000000; /* 100ms */
nanosleep(&ts, NULL);
}
*maclenp = mac_param.maclen;
*maclenp = maclen;
*mactypep = ARPHRD_ETHER;
}
static int find_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
{
struct mac_param *parm = parmv;
if (family == AF_INET6 && IN6_ARE_ADDR_EQUAL(parm->target, (struct in6_addr *)addrp))
{
if (maclen <= DHCP_CHADDR_MAX)
{
parm->maclen = maclen;
memcpy(parm->mac, mac, maclen);
}
return 0; /* found, abort */
}
return 1;
}
static int complete_context6(struct in6_addr *local, int prefix,
int scope, int if_index, int flags, unsigned int preferred,
unsigned int valid, void *vparam)
@@ -348,7 +344,7 @@ static int complete_context6(struct in6_addr *local, int prefix,
{
struct dhcp_context *tmp, **up;
/* use interface values only for contructed contexts */
/* use interface values only for constructed contexts */
if (!(context->flags & CONTEXT_CONSTRUCTED))
preferred = valid = 0xffffffff;
else if (flags & IFACE_DEPRECATED)
@@ -424,7 +420,7 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
j = rand64();
else
for (j = iaid, i = 0; i < clid_len; i++)
j += clid[i] + (j << 6) + (j << 16) - j;
j = clid[i] + (j << 6) + (j << 16) - j;
for (pass = 0; pass <= plain_range ? 1 : 0; pass++)
for (c = context; c; c = c->current)
@@ -438,7 +434,16 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
/* seed is largest extant lease addr in this context */
start = lease_find_max_addr6(c) + serial;
else
start = addr6part(&c->start6) + ((j + c->addr_epoch) % (1 + addr6part(&c->end6) - addr6part(&c->start6)));
{
u64 range = 1 + addr6part(&c->end6) - addr6part(&c->start6);
u64 offset = j + c->addr_epoch;
/* don't divide by zero if range is whole 2^64 */
if (range != 0)
offset = offset % range;
start = addr6part(&c->start6) + offset;
}
/* iterate until we find a free address. */
addr = start;
@@ -667,7 +672,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
/* address went, now it's back */
log_context(AF_INET6, context);
/* fast RAs for a while */
ra_start_unsolicted(param->now, context);
ra_start_unsolicited(param->now, context);
param->newone = 1;
/* Add address to name again */
if (context->flags & CONTEXT_RA_NAME)
@@ -690,7 +695,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
context->next = daemon->dhcp6;
daemon->dhcp6 = context;
ra_start_unsolicted(param->now, context);
ra_start_unsolicited(param->now, context);
/* we created a new one, need to call
lease_update_file to get periodic functions called */
param->newone = 1;
@@ -727,8 +732,7 @@ void dhcp_construct_contexts(time_t now)
if (context->flags & CONTEXT_GC && !(context->flags & CONTEXT_OLD))
{
if ((context->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)) ||
option_bool(OPT_RA))
if ((context->flags & CONTEXT_RA) || option_bool(OPT_RA))
{
/* previously constructed context has gone. advertise it's demise */
context->flags |= CONTEXT_OLD;
@@ -739,7 +743,7 @@ void dhcp_construct_contexts(time_t now)
/* maximum time is 2 hours, from RFC */
if (context->saved_valid > 7200) /* 2 hours */
context->saved_valid = 7200;
ra_start_unsolicted(now, context);
ra_start_unsolicited(now, context);
param.newone = 1; /* include deletion */
if (context->flags & CONTEXT_RA_NAME)

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,6 +16,7 @@
#define NAMESERVER_PORT 53
#define TFTP_PORT 69
#define MAX_PORT 65535u
#define IN6ADDRSZ 16
#define INADDRSZ 4
@@ -77,6 +78,8 @@
#define EDNS0_OPTION_MAC 65001 /* dyndns.org temporary assignment */
#define EDNS0_OPTION_CLIENT_SUBNET 8 /* IANA */
#define EDNS0_OPTION_NOMDEVICEID 65073 /* Nominum temporary assignment */
#define EDNS0_OPTION_NOMCPEID 65074 /* Nominum temporary assignment */
struct dns_header {
u16 id;
@@ -84,15 +87,15 @@ struct dns_header {
u16 qdcount,ancount,nscount,arcount;
};
#define HB3_QR 0x80
#define HB3_QR 0x80 /* Query */
#define HB3_OPCODE 0x78
#define HB3_AA 0x04
#define HB3_TC 0x02
#define HB3_RD 0x01
#define HB3_AA 0x04 /* Authoritative Answer */
#define HB3_TC 0x02 /* TrunCated */
#define HB3_RD 0x01 /* Recursion Desired */
#define HB4_RA 0x80
#define HB4_AD 0x20
#define HB4_CD 0x10
#define HB4_RA 0x80 /* Recursion Available */
#define HB4_AD 0x20 /* Authenticated Data */
#define HB4_CD 0x10 /* Checking Disabled */
#define HB4_RCODE 0x0f
#define OPCODE(x) (((x)->hb3 & HB3_OPCODE) >> 3)
@@ -142,3 +145,11 @@ struct dns_header {
#define ADD_RDLEN(header, pp, plen, len) \
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
/* Escape character in our presentation format for names.
Cannot be '.' or /000 and must be !isprint().
Note that escaped chars are stored as
<NAME_ESCAPE> <orig-char+1>
to ensure that the escaped form of /000 doesn't include /000
*/
#define NAME_ESCAPE 1

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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
@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define COPYRIGHT "Copyright (c) 2000-2014 Simon Kelley"
#define COPYRIGHT "Copyright (c) 2000-2017 Simon Kelley"
#ifndef NO_LARGEFILE
/* Ensure we can use files >2GB (log files may grow this big) */
@@ -82,7 +82,7 @@ typedef unsigned long long u64;
#if defined(HAVE_SOLARIS_NETWORK)
# include <sys/sockio.h>
#endif
#include <sys/select.h>
#include <sys/poll.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/un.h>
@@ -124,7 +124,7 @@ typedef unsigned long long u64;
#if defined(HAVE_LINUX_NETWORK)
#include <linux/capability.h>
/* There doesn't seem to be a universally-available
userpace header for these. */
userspace header for these. */
extern int capset(cap_user_header_t header, cap_user_data_t data);
extern int capget(cap_user_header_t header, cap_user_data_t data);
#define LINUX_CAPABILITY_VERSION_1 0x19980330
@@ -144,27 +144,31 @@ struct event_desc {
int event, data, msg_sz;
};
#define EVENT_RELOAD 1
#define EVENT_DUMP 2
#define EVENT_ALARM 3
#define EVENT_TERM 4
#define EVENT_CHILD 5
#define EVENT_REOPEN 6
#define EVENT_EXITED 7
#define EVENT_KILLED 8
#define EVENT_EXEC_ERR 9
#define EVENT_PIPE_ERR 10
#define EVENT_USER_ERR 11
#define EVENT_CAP_ERR 12
#define EVENT_PIDFILE 13
#define EVENT_HUSER_ERR 14
#define EVENT_GROUP_ERR 15
#define EVENT_DIE 16
#define EVENT_LOG_ERR 17
#define EVENT_FORK_ERR 18
#define EVENT_LUA_ERR 19
#define EVENT_TFTP_ERR 20
#define EVENT_INIT 21
#define EVENT_RELOAD 1
#define EVENT_DUMP 2
#define EVENT_ALARM 3
#define EVENT_TERM 4
#define EVENT_CHILD 5
#define EVENT_REOPEN 6
#define EVENT_EXITED 7
#define EVENT_KILLED 8
#define EVENT_EXEC_ERR 9
#define EVENT_PIPE_ERR 10
#define EVENT_USER_ERR 11
#define EVENT_CAP_ERR 12
#define EVENT_PIDFILE 13
#define EVENT_HUSER_ERR 14
#define EVENT_GROUP_ERR 15
#define EVENT_DIE 16
#define EVENT_LOG_ERR 17
#define EVENT_FORK_ERR 18
#define EVENT_LUA_ERR 19
#define EVENT_TFTP_ERR 20
#define EVENT_INIT 21
#define EVENT_NEWADDR 22
#define EVENT_NEWROUTE 23
#define EVENT_TIME_ERR 24
#define EVENT_SCRIPT_LOG 25
/* Exit codes. */
#define EC_GOOD 0
@@ -175,13 +179,6 @@ struct event_desc {
#define EC_MISC 5
#define EC_INIT_OFFSET 10
/* Min buffer size: we check after adding each record, so there must be
memory for the largest packet, and the largest record so the
min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
This might be increased is EDNS packet size if greater than the minimum.
*/
#define DNSMASQ_PACKETSZ PACKETSZ+MAXDNAME+RRFIXEDSZ
/* Trust the compiler dead-code eliminator.... */
#define option_bool(x) (((x) < 32) ? daemon->options & (1u << (x)) : daemon->options2 & (1u << ((x) - 32)))
@@ -214,7 +211,7 @@ struct event_desc {
#define OPT_TFTP_SECURE 26
#define OPT_TFTP_NOBLOCK 27
#define OPT_LOG_OPTS 28
#define OPT_TFTP_APREF 29
#define OPT_TFTP_APREF_IP 29
#define OPT_NO_OVERRIDE 30
#define OPT_NO_REBIND 31
#define OPT_ADD_MAC 32
@@ -235,12 +232,20 @@ struct event_desc {
#define OPT_DNSSEC_DEBUG 47
#define OPT_DNSSEC_NO_SIGN 48
#define OPT_LOCAL_SERVICE 49
#define OPT_LAST 50
#define OPT_LOOP_DETECT 50
#define OPT_EXTRALOG 51
#define OPT_TFTP_NO_FAIL 52
#define OPT_SCRIPT_ARP 53
#define OPT_MAC_B64 54
#define OPT_MAC_HEX 55
#define OPT_TFTP_APREF_MAC 56
#define OPT_LAST 57
/* extra flags for my_syslog, we use a couple of facilities since they are known
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
#define MS_TFTP LOG_USER
#define MS_DHCP LOG_DAEMON
#define MS_TFTP LOG_USER
#define MS_DHCP LOG_DAEMON
#define MS_SCRIPT LOG_MAIL
struct all_addr {
union {
@@ -249,8 +254,10 @@ struct all_addr {
struct in6_addr addr6;
#endif
/* for log_query */
unsigned int keytag;
/* for cache_insert if RRSIG, DNSKEY, DS */
struct {
unsigned short keytag, algo, digest;
} log;
/* for cache_insert of DNSKEY, DS */
struct {
unsigned short class, type;
} dnssec;
@@ -281,6 +288,7 @@ struct naptr {
struct naptr *next;
};
#ifndef NO_ID
#define TXT_STAT_CACHESIZE 1
#define TXT_STAT_INSERTS 2
#define TXT_STAT_EVICTIONS 3
@@ -288,6 +296,7 @@ struct naptr {
#define TXT_STAT_HITS 5
#define TXT_STAT_AUTH 6
#define TXT_STAT_SERVERS 7
#endif
struct txt_record {
char *name;
@@ -303,8 +312,9 @@ struct ptr_record {
};
struct cname {
int ttl, flag;
char *alias, *target;
struct cname *next;
struct cname *next, *targetp;
};
struct ds_config {
@@ -315,6 +325,7 @@ struct ds_config {
#define ADDRLIST_LITERAL 1
#define ADDRLIST_IPV6 2
#define ADDRLIST_REVONLY 4
struct addrlist {
struct all_addr addr;
@@ -333,11 +344,13 @@ struct auth_zone {
struct auth_name_list *next;
} *interface_names;
struct addrlist *subnet;
struct addrlist *exclude;
struct auth_zone *next;
};
struct host_record {
int ttl;
struct name_list {
char *name;
struct name_list *next;
@@ -390,14 +403,9 @@ struct crec {
unsigned char algo;
unsigned char digest;
} ds;
struct {
struct blockdata *keydata;
unsigned short keylen, type_covered, keytag;
char algo;
} sig;
} addr;
time_t ttd; /* time to die */
/* used as class if DNSKEY/DS/RRSIG, index to source for F_HOSTS */
/* used as class if DNSKEY/DS, index to source for F_HOSTS */
unsigned int uid;
unsigned short flags;
union {
@@ -437,6 +445,7 @@ struct crec {
#define F_SECSTAT (1u<<24)
#define F_NO_RR (1u<<25)
#define F_IPSET (1u<<26)
#define F_NOEXTRA (1u<<27)
/* Values of uid in crecs with F_CONFIG bit set. */
#define SRC_INTERFACE 0
@@ -476,11 +485,15 @@ union mysockaddr {
#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */
#define SERV_NO_REBIND 2048 /* inhibit dns-rebind protection */
#define SERV_FROM_FILE 4096 /* read from --servers-file */
#define SERV_LOOP 8192 /* server causes forwarding loop */
#define SERV_DO_DNSSEC 16384 /* Validate DNSSEC when using this server */
#define SERV_GOT_TCP 32768 /* Got some data from the TCP connection */
struct serverfd {
int fd;
union mysockaddr source_addr;
char interface[IF_NAMESIZE+1];
unsigned int ifindex, used;
struct serverfd *next;
};
@@ -494,8 +507,11 @@ struct server {
char interface[IF_NAMESIZE+1];
struct serverfd *sfd;
char *domain; /* set if this server only handles a domain. */
int flags, tcpfd;
int flags, tcpfd, edns_pktsz;
unsigned int queries, failed_queries;
#ifdef HAVE_LOOP
u32 uid;
#endif
struct server *next;
};
@@ -508,7 +524,7 @@ struct ipsets {
struct irec {
union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found;
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found, label;
char *name;
struct irec *next;
};
@@ -527,21 +543,39 @@ struct iname {
struct iname *next;
};
/* subnet parameters from command line */
struct mysubnet {
union mysockaddr addr;
int addr_used;
int mask;
};
/* resolv-file parms from command-line */
struct resolvc {
struct resolvc *next;
int is_default, logged;
time_t mtime;
char *name;
#ifdef HAVE_INOTIFY
int wd; /* inotify watch descriptor */
char *file; /* pointer to file part if path */
#endif
};
/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile */
/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile and dhcp-hostsdir*/
#define AH_DIR 1
#define AH_INACTIVE 2
#define AH_WD_DONE 4
#define AH_HOSTS 8
#define AH_DHCP_HST 16
#define AH_DHCP_OPT 32
struct hostsfile {
struct hostsfile *next;
int flags;
char *fname;
#ifdef HAVE_INOTIFY
int wd; /* inotify watch descriptor */
#endif
unsigned int index; /* matches to cache entries for logging */
};
@@ -554,10 +588,8 @@ struct hostsfile {
#define STAT_NEED_KEY 5
#define STAT_TRUNCATED 6
#define STAT_SECURE_WILDCARD 7
#define STAT_NO_SIG 8
#define STAT_NO_DS 9
#define STAT_NEED_DS_NEG 10
#define STAT_CHASE_CNAME 11
#define STAT_OK 8
#define STAT_ABANDONED 9
#define FREC_NOREBIND 1
#define FREC_CHECKING_DISABLED 2
@@ -567,7 +599,8 @@ struct hostsfile {
#define FREC_AD_QUESTION 32
#define FREC_DO_QUESTION 64
#define FREC_ADDED_PHEADER 128
#define FREC_CHECK_NOSIGN 256
#define FREC_TEST_PKTSZ 256
#define FREC_HAS_EXTRADATA 512
#ifdef HAVE_DNSSEC
#define HASH_SIZE 20 /* SHA-1 digest size */
@@ -585,7 +618,7 @@ struct frec {
#endif
unsigned int iface;
unsigned short orig_id, new_id;
int fd, forwardall, flags;
int log_id, fd, forwardall, flags;
time_t time;
unsigned char *hash[HASH_SIZE];
#ifdef HAVE_DNSSEC
@@ -613,6 +646,8 @@ struct frec {
#define ACTION_OLD 3
#define ACTION_ADD 4
#define ACTION_TFTP 5
#define ACTION_ARP 6
#define ACTION_ARP_DEL 7
#define LEASE_NEW 1 /* newly created */
#define LEASE_CHANGED 2 /* modified */
@@ -639,6 +674,8 @@ struct dhcp_lease {
unsigned char *extradata;
unsigned int extradata_len, extradata_size;
int last_interface;
int new_interface; /* save possible originated interface */
int new_prefixlen; /* and its prefix length */
#ifdef HAVE_DHCP6
struct in6_addr addr6;
int iaid;
@@ -669,6 +706,12 @@ struct tag_if {
struct tag_if *next;
};
struct delay_config {
int delay;
struct dhcp_netid *netid;
struct delay_config *next;
};
struct hwaddr_config {
int hwaddr_len, hwaddr_type;
unsigned char hwaddr[DHCP_CHADDR_MAX];
@@ -755,7 +798,7 @@ struct pxe_service {
#define MATCH_REMOTE 4
#define MATCH_SUBSCRIBER 5
/* vendorclass, userclass, remote-id or cicuit-id */
/* vendorclass, userclass, remote-id or circuit-id */
struct dhcp_vendor {
int len, match_type;
unsigned int enterprise;
@@ -797,7 +840,8 @@ struct prefix_class {
struct ra_interface {
char *name;
int interval, lifetime, prio;
char *mtu_name;
int interval, lifetime, prio, mtu;
struct ra_interface *next;
};
@@ -823,7 +867,7 @@ struct dhcp_context {
#define CONTEXT_NETMASK (1u<<1)
#define CONTEXT_BRDCAST (1u<<2)
#define CONTEXT_PROXY (1u<<3)
#define CONTEXT_RA_ONLY (1u<<4)
#define CONTEXT_RA_ROUTER (1u<<4)
#define CONTEXT_RA_DONE (1u<<5)
#define CONTEXT_RA_NAME (1u<<6)
#define CONTEXT_RA_STATELESS (1u<<7)
@@ -837,7 +881,7 @@ struct dhcp_context {
#define CONTEXT_USED (1u<<15)
#define CONTEXT_OLD (1u<<16)
#define CONTEXT_V6 (1u<<17)
#define CONTEXT_RA_OFF_LINK (1u<<18)
struct ping_result {
struct in_addr addr;
@@ -874,6 +918,7 @@ struct addr_list {
struct tftp_prefix {
char *interface;
char *prefix;
int missing;
struct tftp_prefix *next;
};
@@ -902,9 +947,9 @@ extern struct daemon {
struct auth_zone *auth_zones;
struct interface_name *int_names;
char *mxtarget;
int addr4_netmask;
int addr6_netmask;
char *lease_file;
struct mysubnet *add_subnet4;
struct mysubnet *add_subnet6;
char *lease_file;
char *username, *groupname, *scriptuser;
char *luascript;
char *authserver, *hostmaster;
@@ -916,15 +961,16 @@ extern struct daemon {
char *runfile;
char *lease_change_command;
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
struct bogus_addr *bogus_addr;
struct bogus_addr *bogus_addr, *ignore_addr;
struct server *servers;
struct ipsets *ipsets;
int log_fac; /* log facility */
char *log_file; /* optional log file */
int max_logs; /* queue limit */
int cachesize, ftabsize;
int port, query_port, min_port;
unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl, auth_ttl;
int port, query_port, min_port, max_port;
unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl, dhcp_ttl, use_dhcp_ttl;
char *dns_client_id;
struct hostsfile *addn_hosts;
struct dhcp_context *dhcp, *dhcp6;
struct ra_interface *ra_interfaces;
@@ -937,13 +983,14 @@ extern struct daemon {
struct tag_if *tag_if;
struct addr_list *override_relays;
struct dhcp_relay *relay4, *relay6;
struct delay_config *delay_conf;
int override;
int enable_pxe;
int doing_ra, doing_dhcp6;
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file;
int dhcp_max, tftp_max;
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *dynamic_dirs;
int dhcp_max, tftp_max, tftp_mtu;
int dhcp_server_port, dhcp_client_port;
int start_tftp_port, end_tftp_port;
unsigned int min_leasetime;
@@ -960,6 +1007,9 @@ extern struct daemon {
#endif
#ifdef HAVE_DNSSEC
struct ds_config *ds;
int dnssec_no_time_check;
int back_to_the_future;
char *timestamp_file;
#endif
/* globally used stuff for DNS */
@@ -985,9 +1035,14 @@ extern struct daemon {
struct randfd randomsocks[RANDOM_SOCKS];
int v6pktinfo;
struct addrlist *interface_addrs; /* list of all addresses/prefix lengths associated with all local interfaces */
int log_id, log_display_id; /* ids of transactions for logging */
union mysockaddr *log_source_addr;
/* DHCP state */
int dhcpfd, helperfd, pxefd;
#ifdef HAVE_INOTIFY
int inotifyfd;
#endif
#if defined(HAVE_LINUX_NETWORK)
int netlinkfd;
#elif defined(HAVE_BSD_NETWORK)
@@ -1016,6 +1071,7 @@ extern struct daemon {
/* utility string buffer, hold max sized IP address as string */
char *addrbuff;
char *addrbuff2; /* only allocated when OPT_EXTRALOG */
} *daemon;
@@ -1038,10 +1094,14 @@ void cache_add_dhcp_entry(char *host_name, int prot, struct all_addr *host_addre
struct in_addr a_record_from_hosts(char *name, time_t now);
void cache_unhash_dhcp(void);
void dump_cache(time_t now);
#ifndef NO_ID
int cache_make_stat(struct txt_record *t);
#endif
char *cache_get_name(struct crec *crecp);
char *cache_get_cname_target(struct crec *crecp);
struct crec *cache_enumerate(int init);
int read_hostsfile(char *filename, unsigned int index, int cache_size,
struct crec **rhash, int hashsz);
/* blockdata.c */
#ifdef HAVE_DNSSEC
@@ -1076,21 +1136,14 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff,
int no_cache, int secure, int *doctored);
size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
struct in_addr local_addr, struct in_addr local_netmask,
time_t now, int *ad_reqd, int *do_bit);
time_t now, int ad_reqd, int do_bit, int have_pseudoheader);
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
struct bogus_addr *addr, time_t now);
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
size_t *len, unsigned char **p, int *is_sign);
int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
int check_for_local_domain(char *name, time_t now);
unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
size_t resize_packet(struct dns_header *header, size_t plen,
unsigned char *pheader, size_t hlen);
size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, union mysockaddr *source);
#ifdef HAVE_DNSSEC
size_t add_do_bit(struct dns_header *header, size_t plen, char *limit);
#endif
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer);
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
int nameoffset, unsigned char **pp, unsigned long ttl,
int *offset, unsigned short type, unsigned short class, char *format, ...);
@@ -1103,23 +1156,26 @@ int private_net(struct in_addr addr, int ban_localhost);
/* auth.c */
#ifdef HAVE_AUTH
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen,
time_t now, union mysockaddr *peer_addr, int local_query);
time_t now, union mysockaddr *peer_addr, int local_query,
int do_bit, int have_pseudoheader);
int in_zone(struct auth_zone *zone, char *name, char **cut);
#endif
/* dnssec.c */
size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr);
size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, char *name, char *keyname, int class);
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int *neganswer);
int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname);
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class,
int check_unsigned, int *neganswer, int *nons);
int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
size_t filter_rrsigs(struct dns_header *header, size_t plen);
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
int setup_timestamp(void);
/* util.c */
void rand_init(void);
unsigned short rand16(void);
u32 rand32(void);
u64 rand64(void);
int legal_hostname(char *c);
char *canonicalise(char *s, int *nomem);
@@ -1131,13 +1187,14 @@ int sa_len(union mysockaddr *addr);
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
int hostname_isequal(const char *a, const 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);
#ifdef HAVE_IPV6
int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen);
u64 addr6part(struct in6_addr *addr);
void setaddr6part(struct in6_addr *addr, u64 host);
#endif
int retry_send(void);
int retry_send(ssize_t rc);
void prettyprint_time(char *buf, unsigned int t);
int prettyprint_addr(union mysockaddr *addr, char *buf);
int parse_hex(char *in, unsigned char *out, int maxlen,
@@ -1146,18 +1203,18 @@ int memcmp_masked(unsigned char *a, unsigned char *b, int len,
unsigned int mask);
int expand_buf(struct iovec *iov, size_t size);
char *print_mac(char *buff, unsigned char *mac, int len);
void bump_maxfd(int fd, int *max);
int read_write(int fd, unsigned char *packet, int size, int rw);
int wildcard_match(const char* wildcard, const char* match);
int wildcard_matchn(const char* wildcard, const char* match, int num);
/* log.c */
void die(char *message, char *arg1, int exit_code);
int log_start(struct passwd *ent_pw, int errfd);
int log_reopen(char *log_file);
void my_syslog(int priority, const char *format, ...);
void set_log_writer(fd_set *set, int *maxfdp);
void check_log_writer(fd_set *set);
void set_log_writer(void);
void check_log_writer(int force);
void flush_log(void);
/* option.c */
@@ -1171,6 +1228,7 @@ void reset_option_bool(unsigned int opt);
struct hostsfile *expand_filelist(struct hostsfile *list);
char *parse_server(char *arg, union mysockaddr *addr,
union mysockaddr *source_addr, char *interface, int *flags);
int option_read_dynfile(char *file, int flags);
/* forward.c */
void reply_query(int fd, int family, time_t now);
@@ -1182,6 +1240,9 @@ struct frec *get_new_frec(time_t now, int *wait, int force);
int send_from(int fd, int nowild, char *packet, size_t len,
union mysockaddr *to, struct all_addr *source,
unsigned int iface);
void resend_query();
struct randfd *allocate_rfd(int family);
void free_rfd(struct randfd *rfd);
/* network.c */
int indextoname(int fd, int index, char *name);
@@ -1201,6 +1262,7 @@ int enumerate_interfaces(int reset);
void create_wildcard_listeners(void);
void create_bound_listeners(int die);
void warn_bound_listeners(void);
void warn_wild_labels(void);
void warn_int_names(void);
int is_dad_listeners(void);
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
@@ -1229,9 +1291,11 @@ struct dhcp_context *address_available(struct dhcp_context *context,
struct dhcp_context *narrow_context(struct dhcp_context *context,
struct in_addr taddr,
struct dhcp_netid *netids);
struct ping_result *do_icmp_ping(time_t now, struct in_addr addr,
unsigned int hash, int loopback);
int address_allocate(struct dhcp_context *context,
struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
struct dhcp_netid *netids, time_t now);
struct dhcp_netid *netids, time_t now, int loopback);
void dhcp_read_ethers(void);
struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr);
char *host_from_dns(struct in_addr addr);
@@ -1256,9 +1320,10 @@ void lease_update_slaac(time_t now);
void lease_set_iaid(struct dhcp_lease *lease, int iaid);
void lease_make_duid(time_t now);
#endif
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
unsigned char *clid, int hw_len, int hw_type, int clid_len, time_t now, int force);
void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth, char *domain, char *config_domain);
void lease_set_hwaddr(struct dhcp_lease *lease, const unsigned char *hwaddr,
const unsigned char *clid, int hw_len, int hw_type,
int clid_len, time_t now, int force);
void lease_set_hostname(struct dhcp_lease *lease, const char *name, int auth, char *domain, char *config_domain);
void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now);
void lease_set_interface(struct dhcp_lease *lease, int interface, time_t now);
struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type,
@@ -1279,7 +1344,8 @@ void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data,
/* rfc2131.c */
#ifdef HAVE_DHCP
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe_fd, struct in_addr fallback);
size_t sz, time_t now, int unicast_dest, int loopback,
int *is_inform, int pxe_fd, struct in_addr fallback, time_t recvtime);
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
int clid_len, unsigned char *clid, int *len_out);
#endif
@@ -1288,16 +1354,17 @@ unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
#ifdef HAVE_DHCP
int make_icmp_sock(void);
int icmp_ping(struct in_addr addr);
int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id);
#endif
void queue_event(int event);
void send_alarm(time_t event, time_t now);
void send_event(int fd, int event, int data, char *msg);
void clear_cache_and_reload(time_t now);
void poll_resolv(int force, int do_reload, time_t now);
/* netlink.c */
#ifdef HAVE_LINUX_NETWORK
void netlink_init(void);
void netlink_multicast(time_t now);
void netlink_multicast(void);
#endif
/* bpf.c */
@@ -1306,7 +1373,7 @@ void init_bpf(void);
void send_via_bpf(struct dhcp_packet *mess, size_t len,
struct in_addr iface_addr, struct ifreq *ifr);
void route_init(void);
void route_sock(time_t now);
void route_sock(void);
#endif
/* bpf.c or netlink.c */
@@ -1315,8 +1382,8 @@ int iface_enumerate(int family, void *parm, int (callback)());
/* dbus.c */
#ifdef HAVE_DBUS
char *dbus_init(void);
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset);
void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset);
void check_dbus_listeners(void);
void set_dbus_listeners(void);
# ifdef HAVE_DHCP
void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
# endif
@@ -1337,13 +1404,15 @@ void queue_script(int action, struct dhcp_lease *lease,
#ifdef HAVE_TFTP
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer);
#endif
void queue_arp(int action, unsigned char *mac, int maclen,
int family, struct all_addr *addr);
int helper_buf_empty(void);
#endif
/* tftp.c */
#ifdef HAVE_TFTP
void tftp_request(struct listener *listen, time_t now);
void check_tftp_listeners(fd_set *rset, time_t now);
void check_tftp_listeners(time_t now);
int do_tftp_script_run(void);
#endif
@@ -1373,7 +1442,7 @@ struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct
void make_duid(time_t now);
void dhcp_construct_contexts(time_t now);
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac,
unsigned int *maclenp, unsigned int *mactypep);
unsigned int *maclenp, unsigned int *mactypep, time_t now);
#endif
/* rfc3315.c */
@@ -1381,7 +1450,8 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac,
unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name,
struct in6_addr *fallback, struct in6_addr *ll_addr, struct in6_addr *ula_addr,
size_t sz, struct in6_addr *client_addr, time_t now);
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, u32 scope_id);
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address,
u32 scope_id, time_t now);
unsigned short relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface);
#endif
@@ -1423,6 +1493,7 @@ void log_relay(int family, struct dhcp_relay *relay);
/* outpacket.c */
#ifdef HAVE_DHCP6
void end_opt6(int container);
void reset_counter(void);
int save_counter(int newval);
void *expand(size_t headroom);
int new_opt6(int opt);
@@ -1438,7 +1509,7 @@ void put_opt6_string(char *s);
void ra_init(time_t now);
void icmp6_packet(time_t now);
time_t periodic_ra(time_t now);
void ra_start_unsolicted(time_t now, struct dhcp_context *context);
void ra_start_unsolicited(time_t now, struct dhcp_context *context);
#endif
/* slaac.c */
@@ -1447,3 +1518,41 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force);
time_t periodic_slaac(time_t now, struct dhcp_lease *leases);
void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface, struct dhcp_lease *leases);
#endif
/* loop.c */
#ifdef HAVE_LOOP
void loop_send_probes();
int detect_loop(char *query, int type);
#endif
/* inotify.c */
#ifdef HAVE_INOTIFY
void inotify_dnsmasq_init();
int inotify_check(time_t now);
void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz);
#endif
/* poll.c */
void poll_reset(void);
int poll_check(int fd, short event);
void poll_listen(int fd, short event);
int do_poll(int timeout);
/* rrfilter.c */
size_t rrfilter(struct dns_header *header, size_t plen, int mode);
u16 *rrfilter_desc(int type);
int expand_workspace(unsigned char ***wkspc, int *szp, int new);
/* edns0.c */
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
size_t *len, unsigned char **p, int *is_sign, int *is_last);
size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace);
size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char *limit);
size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit,
union mysockaddr *source, time_t now, int *check_subnet);
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer);
/* arp.c */
int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now);
int do_arp_script_run(void);

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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
@@ -77,18 +77,31 @@ int is_name_synthetic(int flags, char *name, struct all_addr *addr)
*p = 0;
/* swap . or : for - */
for (p = tail; *p; p++)
if (*p == '-')
{
if (prot == AF_INET)
#ifdef HAVE_IPV6
if (prot == AF_INET6 && strstr(tail, "--ffff-") == tail)
{
/* special hack for v4-mapped. */
memcpy(tail, "::ffff:", 7);
for (p = tail + 7; *p; p++)
if (*p == '-')
*p = '.';
#ifdef HAVE_IPV6
else
*p = ':';
}
else
#endif
}
{
/* swap . or : for - */
for (p = tail; *p; p++)
if (*p == '-')
{
if (prot == AF_INET)
*p = '.';
#ifdef HAVE_IPV6
else
*p = ':';
#endif
}
}
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
{
if (prot == AF_INET)
@@ -169,8 +182,9 @@ int is_rev_synth(int flag, struct all_addr *addr, char *name)
inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
}
/* V4-mapped have periods.... */
for (p = name; *p; p++)
if (*p == ':')
if (*p == ':' || *p == '.')
*p = '-';
strncat(name, ".", MAXDNAME);

429
src/edns0.c Normal file
View File

@@ -0,0 +1,429 @@
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t *len, unsigned char **p, int *is_sign, int *is_last)
{
/* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
also return length of pseudoheader in *len and pointer to the UDP size in *p
Finally, check to see if a packet is signed. If it is we cannot change a single bit before
forwarding. We look for TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
int i, arcount = ntohs(header->arcount);
unsigned char *ansp = (unsigned char *)(header+1);
unsigned short rdlen, type, class;
unsigned char *ret = NULL;
if (is_sign)
{
*is_sign = 0;
if (OPCODE(header) == QUERY)
{
for (i = ntohs(header->qdcount); i != 0; i--)
{
if (!(ansp = skip_name(ansp, header, plen, 4)))
return NULL;
GETSHORT(type, ansp);
GETSHORT(class, ansp);
if (class == C_IN && type == T_TKEY)
*is_sign = 1;
}
}
}
else
{
if (!(ansp = skip_questions(header, plen)))
return NULL;
}
if (arcount == 0)
return NULL;
if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount), header, plen)))
return NULL;
for (i = 0; i < arcount; i++)
{
unsigned char *save, *start = ansp;
if (!(ansp = skip_name(ansp, header, plen, 10)))
return NULL;
GETSHORT(type, ansp);
save = ansp;
GETSHORT(class, ansp);
ansp += 4; /* TTL */
GETSHORT(rdlen, ansp);
if (!ADD_RDLEN(header, ansp, plen, rdlen))
return NULL;
if (type == T_OPT)
{
if (len)
*len = ansp - start;
if (p)
*p = save;
if (is_last)
*is_last = (i == arcount-1);
ret = start;
}
else if (is_sign &&
i == arcount - 1 &&
class == C_ANY &&
type == T_TSIG)
*is_sign = 1;
}
return ret;
}
/* replace == 2 ->delete existing option only. */
size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace)
{
unsigned char *lenp, *datap, *p, *udp_len, *buff = NULL;
int rdlen = 0, is_sign, is_last;
unsigned short flags = set_do ? 0x8000 : 0, rcode = 0;
p = find_pseudoheader(header, plen, NULL, &udp_len, &is_sign, &is_last);
if (is_sign)
return plen;
if (p)
{
/* Existing header */
int i;
unsigned short code, len;
p = udp_len;
GETSHORT(udp_sz, p);
GETSHORT(rcode, p);
GETSHORT(flags, p);
if (set_do)
{
p -= 2;
flags |= 0x8000;
PUTSHORT(flags, p);
}
lenp = p;
GETSHORT(rdlen, p);
if (!CHECK_LEN(header, p, plen, rdlen))
return plen; /* bad packet */
datap = p;
/* no option to add */
if (optno == 0)
return plen;
/* check if option already there */
for (i = 0; i + 4 < rdlen;)
{
GETSHORT(code, p);
GETSHORT(len, p);
/* malformed option, delete the whole OPT RR and start again. */
if (i + len > rdlen)
{
rdlen = 0;
is_last = 0;
break;
}
if (code == optno)
{
if (replace == 0)
return plen;
/* delete option if we're to replace it. */
p -= 4;
rdlen -= len + 4;
memcpy(p, p+len+4, rdlen - i);
PUTSHORT(rdlen, lenp);
lenp -= 2;
}
else
{
p += len;
i += len + 4;
}
}
/* If we're going to extend the RR, it has to be the last RR in the packet */
if (!is_last)
{
/* First, take a copy of the options. */
if (rdlen != 0 && (buff = whine_malloc(rdlen)))
memcpy(buff, datap, rdlen);
/* now, delete OPT RR */
plen = rrfilter(header, plen, 0);
/* Now, force addition of a new one */
p = NULL;
}
}
if (!p)
{
/* We are (re)adding the pseudoheader */
if (!(p = skip_questions(header, plen)) ||
!(p = skip_section(p,
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
header, plen)))
return plen;
*p++ = 0; /* empty name */
PUTSHORT(T_OPT, p);
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
PUTSHORT(rcode, p); /* extended RCODE and version */
PUTSHORT(flags, p); /* DO flag */
lenp = p;
PUTSHORT(rdlen, p); /* RDLEN */
datap = p;
/* Copy back any options */
if (buff)
{
memcpy(p, buff, rdlen);
free(buff);
p += rdlen;
}
header->arcount = htons(ntohs(header->arcount) + 1);
}
if (((ssize_t)optlen) > (limit - (p + 4)))
return plen; /* Too big */
/* Add new option */
if (optno != 0 && replace != 2)
{
PUTSHORT(optno, p);
PUTSHORT(optlen, p);
memcpy(p, opt, optlen);
p += optlen;
PUTSHORT(p - datap, lenp);
}
return p - (unsigned char *)header;
}
size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char *limit)
{
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, 0, NULL, 0, 1, 0);
}
static unsigned char char64(unsigned char c)
{
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c & 0x3f];
}
static void encoder(unsigned char *in, char *out)
{
out[0] = char64(in[0]>>2);
out[1] = char64((in[0]<<4) | (in[1]>>4));
out[2] = char64((in[1]<<2) | (in[2]>>6));
out[3] = char64(in[2]);
}
static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *l3, time_t now)
{
int maclen, replace = 2; /* can't get mac address, just delete any incoming. */
unsigned char mac[DHCP_CHADDR_MAX];
char encode[18]; /* handle 6 byte MACs */
if ((maclen = find_mac(l3, mac, 1, now)) == 6)
{
replace = 1;
if (option_bool(OPT_MAC_HEX))
print_mac(encode, mac, maclen);
else
{
encoder(mac, encode);
encoder(mac+3, encode+4);
encode[8] = 0;
}
}
return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);
}
static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *l3, time_t now)
{
int maclen;
unsigned char mac[DHCP_CHADDR_MAX];
if ((maclen = find_mac(l3, mac, 1, now)) != 0)
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, 0);
return plen;
}
struct subnet_opt {
u16 family;
u8 source_netmask, scope_netmask;
#ifdef HAVE_IPV6
u8 addr[IN6ADDRSZ];
#else
u8 addr[INADDRSZ];
#endif
};
static void *get_addrp(union mysockaddr *addr, const short family)
{
#ifdef HAVE_IPV6
if (family == AF_INET6)
return &addr->in6.sin6_addr;
#endif
return &addr->in.sin_addr;
}
static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
{
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
int len;
void *addrp = NULL;
int sa_family = source->sa.sa_family;
opt->source_netmask = 0;
opt->scope_netmask = 0;
#ifdef HAVE_IPV6
if (source->sa.sa_family == AF_INET6 && daemon->add_subnet6)
{
opt->source_netmask = daemon->add_subnet6->mask;
if (daemon->add_subnet6->addr_used)
{
sa_family = daemon->add_subnet6->addr.sa.sa_family;
addrp = get_addrp(&daemon->add_subnet6->addr, sa_family);
}
else
addrp = &source->in6.sin6_addr;
}
#endif
if (source->sa.sa_family == AF_INET && daemon->add_subnet4)
{
opt->source_netmask = daemon->add_subnet4->mask;
if (daemon->add_subnet4->addr_used)
{
sa_family = daemon->add_subnet4->addr.sa.sa_family;
addrp = get_addrp(&daemon->add_subnet4->addr, sa_family);
}
else
addrp = &source->in.sin_addr;
}
#ifdef HAVE_IPV6
opt->family = htons(sa_family == AF_INET6 ? 2 : 1);
#else
opt->family = htons(1);
#endif
len = 0;
if (addrp && opt->source_netmask != 0)
{
len = ((opt->source_netmask - 1) >> 3) + 1;
memcpy(opt->addr, addrp, len);
if (opt->source_netmask & 7)
opt->addr[len-1] &= 0xff << (8 - (opt->source_netmask & 7));
}
return len + 4;
}
static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *source)
{
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
int len;
struct subnet_opt opt;
len = calc_subnet_opt(&opt, source);
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, 0);
}
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)
{
/* Section 9.2, Check that subnet option in reply matches. */
int len, calc_len;
struct subnet_opt opt;
unsigned char *p;
int code, i, rdlen;
calc_len = calc_subnet_opt(&opt, peer);
if (!(p = skip_name(pseudoheader, header, plen, 10)))
return 1;
p += 8; /* skip UDP length and RCODE */
GETSHORT(rdlen, p);
if (!CHECK_LEN(header, p, plen, rdlen))
return 1; /* bad packet */
/* check if option there */
for (i = 0; i + 4 < rdlen; i += len + 4)
{
GETSHORT(code, p);
GETSHORT(len, p);
if (code == EDNS0_OPTION_CLIENT_SUBNET)
{
/* make sure this doesn't mismatch. */
opt.scope_netmask = p[3];
if (len != calc_len || memcmp(p, &opt, len) != 0)
return 0;
}
p += len;
}
return 1;
}
size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit,
union mysockaddr *source, time_t now, int *check_subnet)
{
*check_subnet = 0;
if (option_bool(OPT_ADD_MAC))
plen = add_mac(header, plen, limit, source, now);
if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX))
plen = add_dns_client(header, plen, limit, source, now);
if (daemon->dns_client_id)
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID,
(unsigned char *)daemon->dns_client_id, strlen(daemon->dns_client_id), 0, 1);
if (option_bool(OPT_CLIENT_SUBNET))
{
plen = add_source_addr(header, plen, limit, source);
*check_subnet = 1;
}
return plen;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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
@@ -14,11 +14,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "dnsmasq.h"
#ifdef HAVE_SCRIPT
/* This file has code to fork a helper process which recieves data via a pipe
/* This file has code to fork a helper process which receives data via a pipe
shared with the main process and which is responsible for calling a script when
DHCP leases change.
@@ -135,7 +136,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
max_fd != STDIN_FILENO && max_fd != pipefd[0] &&
max_fd != event_fd && max_fd != err_fd)
close(max_fd);
#ifdef HAVE_LUASCRIPT
if (daemon->luascript)
{
@@ -189,6 +190,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
unsigned char *buf = (unsigned char *)daemon->namebuff;
unsigned char *end, *extradata, *alloc_buff = NULL;
int is6, err = 0;
int pipeout[2];
free(alloc_buff);
@@ -219,7 +221,18 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
action_str = "tftp";
is6 = (data.flags != AF_INET);
}
else
else if (data.action == ACTION_ARP)
{
action_str = "arp-add";
is6 = (data.flags != AF_INET);
}
else if (data.action == ACTION_ARP_DEL)
{
action_str = "arp-del";
is6 = (data.flags != AF_INET);
data.action = ACTION_ARP;
}
else
continue;
@@ -289,7 +302,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
if (!is6)
inet_ntop(AF_INET, &data.addr, daemon->addrbuff, ADDRSTRLEN);
#ifdef HAVE_DHCP6
#ifdef HAVE_IPV6
else
inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN);
#endif
@@ -321,6 +334,22 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
}
}
else if (data.action == ACTION_ARP)
{
lua_getglobal(lua, "arp");
if (lua_type(lua, -1) != LUA_TFUNCTION)
lua_pop(lua, 1); /* arp function optional */
else
{
lua_pushstring(lua, action_str); /* arg1 - action */
lua_newtable(lua); /* arg2 - data table */
lua_pushstring(lua, daemon->addrbuff);
lua_setfield(lua, -2, "client_address");
lua_pushstring(lua, daemon->dhcp_buff);
lua_setfield(lua, -2, "mac_address");
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
}
}
else
{
lua_getglobal(lua, "lease"); /* function to call */
@@ -445,16 +474,54 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
if (!daemon->lease_change_command)
continue;
/* Pipe to capture stdout and stderr from script */
if (!option_bool(OPT_DEBUG) && pipe(pipeout) == -1)
continue;
/* possible fork errors are all temporary resource problems */
while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM))
sleep(2);
if (pid == -1)
continue;
{
if (!option_bool(OPT_DEBUG))
{
close(pipeout[0]);
close(pipeout[1]);
}
continue;
}
/* wait for child to complete */
if (pid != 0)
{
if (!option_bool(OPT_DEBUG))
{
FILE *fp;
close(pipeout[1]);
/* Read lines sent to stdout/err by the script and pass them back to be logged */
if (!(fp = fdopen(pipeout[0], "r")))
close(pipeout[0]);
else
{
while (fgets(daemon->packet, daemon->packet_buff_sz, fp))
{
/* do not include new lines, log will append them */
size_t len = strlen(daemon->packet);
if (len > 0)
{
--len;
if (daemon->packet[len] == '\n')
daemon->packet[len] = 0;
}
send_event(event_fd, EVENT_SCRIPT_LOG, 0, daemon->packet);
}
fclose(fp);
}
}
/* reap our children's children, if necessary */
while (1)
{
@@ -477,8 +544,17 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
continue;
}
if (!option_bool(OPT_DEBUG))
{
/* map stdout/stderr of script to pipeout */
close(pipeout[0]);
dup2(pipeout[1], STDOUT_FILENO);
dup2(pipeout[1], STDERR_FILENO);
close(pipeout[1]);
}
if (data.action != ACTION_TFTP)
if (data.action != ACTION_TFTP && data.action != ACTION_ARP)
{
#ifdef HAVE_DHCP6
my_setenv("DNSMASQ_IAID", is6 ? daemon->dhcp_buff3 : NULL, &err);
@@ -529,6 +605,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
buf = grab_extradata(buf, end, "DNSMASQ_CIRCUIT_ID", &err);
buf = grab_extradata(buf, end, "DNSMASQ_SUBSCRIBER_ID", &err);
buf = grab_extradata(buf, end, "DNSMASQ_REMOTE_ID", &err);
buf = grab_extradata(buf, end, "DNSMASQ_REQUESTED_OPTIONS", &err);
}
buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err);
@@ -550,9 +627,9 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
my_setenv("DNSMASQ_OLD_HOSTNAME", data.action == ACTION_OLD_HOSTNAME ? hostname : NULL, &err);
if (data.action == ACTION_OLD_HOSTNAME)
hostname = NULL;
my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err);
}
my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err);
/* we need to have the event_fd around if exec fails */
if ((i = fcntl(event_fd, F_GETFD)) != -1)
@@ -563,8 +640,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
if (err == 0)
{
execl(daemon->lease_change_command,
p ? p+1 : daemon->lease_change_command,
action_str, is6 ? daemon->packet : daemon->dhcp_buff,
p ? p+1 : daemon->lease_change_command, action_str,
(is6 && data.action != ACTION_ARP) ? daemon->packet : daemon->dhcp_buff,
daemon->addrbuff, hostname, (char*)NULL);
err = errno;
}
@@ -760,6 +837,30 @@ void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)
}
#endif
void queue_arp(int action, unsigned char *mac, int maclen, int family, struct all_addr *addr)
{
/* no script */
if (daemon->helperfd == -1)
return;
buff_alloc(sizeof(struct script_data));
memset(buf, 0, sizeof(struct script_data));
buf->action = action;
buf->hwaddr_len = maclen;
buf->hwaddr_type = ARPHRD_ETHER;
if ((buf->flags = family) == AF_INET)
buf->addr = addr->addr.addr4;
#ifdef HAVE_IPV6
else
buf->addr6 = addr->addr.addr6;
#endif
memcpy(buf->hwaddr, mac, maclen);
bytes_in_buf = sizeof(struct script_data);
}
int helper_buf_empty(void)
{
return bytes_in_buf == 0;

296
src/inotify.c Normal file
View File

@@ -0,0 +1,296 @@
/* dnsmasq is Copyright (c) 2000-2017 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_INOTIFY
#include <sys/inotify.h>
#include <sys/param.h> /* For MAXSYMLINKS */
/* the strategy is to set a inotify on the directories containing
resolv files, for any files in the directory which are close-write
or moved into the directory.
When either of those happen, we look to see if the file involved
is actually a resolv-file, and if so, call poll-resolv with
the "force" argument, to ensure it's read.
This adds one new error condition: the directories containing
all specified resolv-files must exist at start-up, even if the actual
files don't.
*/
static char *inotify_buffer;
#define INOTIFY_SZ (sizeof(struct inotify_event) + NAME_MAX + 1)
/* If path is a symbolic link, return the path it
points to, made absolute if relative.
If path doesn't exist or is not a symlink, return NULL.
Return value is malloc'ed */
static char *my_readlink(char *path)
{
ssize_t rc, size = 64;
char *buf;
while (1)
{
buf = safe_malloc(size);
rc = readlink(path, buf, (size_t)size);
if (rc == -1)
{
/* Not link or doesn't exist. */
if (errno == EINVAL || errno == ENOENT)
{
free(buf);
return NULL;
}
else
die(_("cannot access path %s: %s"), path, EC_MISC);
}
else if (rc < size-1)
{
char *d;
buf[rc] = 0;
if (buf[0] != '/' && ((d = strrchr(path, '/'))))
{
/* Add path to relative link */
char *new_buf = safe_malloc((d - path) + strlen(buf) + 2);
*(d+1) = 0;
strcpy(new_buf, path);
strcat(new_buf, buf);
free(buf);
buf = new_buf;
}
return buf;
}
/* Buffer too small, increase and retry */
size += 64;
free(buf);
}
}
void inotify_dnsmasq_init()
{
struct resolvc *res;
inotify_buffer = safe_malloc(INOTIFY_SZ);
daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
if (daemon->inotifyfd == -1)
die(_("failed to create inotify: %s"), NULL, EC_MISC);
if (option_bool(OPT_NO_RESOLV))
return;
for (res = daemon->resolv_files; res; res = res->next)
{
char *d, *new_path, *path = safe_malloc(strlen(res->name) + 1);
int links = MAXSYMLINKS;
strcpy(path, res->name);
/* Follow symlinks until we reach a non-symlink, or a non-existent file. */
while ((new_path = my_readlink(path)))
{
if (links-- == 0)
die(_("too many symlinks following %s"), res->name, EC_MISC);
free(path);
path = new_path;
}
res->wd = -1;
if ((d = strrchr(path, '/')))
{
*d = 0; /* make path just directory */
res->wd = inotify_add_watch(daemon->inotifyfd, path, IN_CLOSE_WRITE | IN_MOVED_TO);
res->file = d+1; /* pointer to filename */
*d = '/';
if (res->wd == -1 && errno == ENOENT)
die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC);
}
if (res->wd == -1)
die(_("failed to create inotify for %s: %s"), res->name, EC_MISC);
}
}
/* initialisation for dynamic-dir. Set inotify watch for each directory, and read pre-existing files */
void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz)
{
struct hostsfile *ah;
for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
{
DIR *dir_stream = NULL;
struct dirent *ent;
struct stat buf;
if (!(ah->flags & flag))
continue;
if (stat(ah->fname, &buf) == -1 || !(S_ISDIR(buf.st_mode)))
{
my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"),
ah->fname, strerror(errno));
continue;
}
if (!(ah->flags & AH_WD_DONE))
{
ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO);
ah->flags |= AH_WD_DONE;
}
/* Read contents of dir _after_ calling add_watch, in the hope of avoiding
a race which misses files being added as we start */
if (ah->wd == -1 || !(dir_stream = opendir(ah->fname)))
{
my_syslog(LOG_ERR, _("failed to create inotify for %s: %s"),
ah->fname, strerror(errno));
continue;
}
while ((ent = readdir(dir_stream)))
{
size_t lendir = strlen(ah->fname);
size_t lenfile = strlen(ent->d_name);
char *path;
/* ignore emacs backups and dotfiles */
if (lenfile == 0 ||
ent->d_name[lenfile - 1] == '~' ||
(ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
ent->d_name[0] == '.')
continue;
if ((path = whine_malloc(lendir + lenfile + 2)))
{
strcpy(path, ah->fname);
strcat(path, "/");
strcat(path, ent->d_name);
/* ignore non-regular files */
if (stat(path, &buf) != -1 && S_ISREG(buf.st_mode))
{
if (ah->flags & AH_HOSTS)
total_size = read_hostsfile(path, ah->index, total_size, rhash, revhashsz);
#ifdef HAVE_DHCP
else if (ah->flags & (AH_DHCP_HST | AH_DHCP_OPT))
option_read_dynfile(path, ah->flags);
#endif
}
free(path);
}
}
closedir(dir_stream);
}
}
int inotify_check(time_t now)
{
int hit = 0;
struct hostsfile *ah;
while (1)
{
int rc;
char *p;
struct resolvc *res;
struct inotify_event *in;
while ((rc = read(daemon->inotifyfd, inotify_buffer, INOTIFY_SZ)) == -1 && errno == EINTR);
if (rc <= 0)
break;
for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len)
{
in = (struct inotify_event*)p;
for (res = daemon->resolv_files; res; res = res->next)
if (res->wd == in->wd && in->len != 0 && strcmp(res->file, in->name) == 0)
hit = 1;
/* ignore emacs backups and dotfiles */
if (in->len == 0 ||
in->name[in->len - 1] == '~' ||
(in->name[0] == '#' && in->name[in->len - 1] == '#') ||
in->name[0] == '.')
continue;
for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
if (ah->wd == in->wd)
{
size_t lendir = strlen(ah->fname);
char *path;
if ((path = whine_malloc(lendir + in->len + 2)))
{
strcpy(path, ah->fname);
strcat(path, "/");
strcat(path, in->name);
my_syslog(LOG_INFO, _("inotify, new or changed file %s"), path);
if (ah->flags & AH_HOSTS)
{
read_hostsfile(path, ah->index, 0, NULL, 0);
#ifdef HAVE_DHCP
if (daemon->dhcp || daemon->doing_dhcp6)
{
/* Propagate the consequences of loading a new dhcp-host */
dhcp_update_configs(daemon->dhcp_conf);
lease_update_from_configs();
lease_update_file(now);
lease_update_dns(1);
}
#endif
}
#ifdef HAVE_DHCP
else if (ah->flags & AH_DHCP_HST)
{
if (option_read_dynfile(path, AH_DHCP_HST))
{
/* Propagate the consequences of loading a new dhcp-host */
dhcp_update_configs(daemon->dhcp_conf);
lease_update_from_configs();
lease_update_file(now);
lease_update_dns(1);
}
}
else if (ah->flags & AH_DHCP_OPT)
option_read_dynfile(path, AH_DHCP_OPT);
#endif
free(path);
}
}
}
}
return hit;
}
#endif /* INOTIFY */

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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

View File

@@ -16,7 +16,7 @@
#include "dnsmasq.h"
#ifdef HAVE_IPSET
#if defined(HAVE_IPSET) && defined(HAVE_LINUX_NETWORK)
#include <string.h>
#include <errno.h>
@@ -121,7 +121,6 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
struct my_nlattr *nested[2];
uint8_t proto;
int addrsz = INADDRSZ;
ssize_t rc;
#ifdef HAVE_IPV6
if (af == AF_INET6)
@@ -162,9 +161,10 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
nested[1]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[1];
nested[0]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[0];
while ((rc = sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
(struct sockaddr *)&snl, sizeof(snl))) == -1 && retry_send());
return rc;
while (retry_send(sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
(struct sockaddr *)&snl, sizeof(snl))));
return errno == 0 ? 0 : -1;
}
@@ -211,7 +211,7 @@ static int old_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags, int remove)
{
int af = AF_INET;
int ret = 0, af = AF_INET;
#ifdef HAVE_IPV6
if (flags & F_IPV6)
@@ -219,11 +219,20 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags,
af = AF_INET6;
/* old method only supports IPv4 */
if (old_kernel)
return -1;
{
errno = EAFNOSUPPORT ;
ret = -1;
}
}
#endif
return old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);
if (ret != -1)
ret = old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);
if (ret == -1)
my_syslog(LOG_ERR, _("failed to update ipset %s: %s"), setname, strerror(errno));
return ret;
}
#endif

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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
@@ -21,21 +21,126 @@
static struct dhcp_lease *leases = NULL, *old_leases = NULL;
static int dns_dirty, file_dirty, leases_left;
void lease_init(time_t now)
static int read_leases(time_t now, FILE *leasestream)
{
unsigned long ei;
struct all_addr addr;
struct dhcp_lease *lease;
int clid_len, hw_len, hw_type;
int items;
char *domain = NULL;
*daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
/* client-id max length is 255 which is 255*2 digits + 254 colons
borrow DNS packet buffer which is always larger than 1000 bytes
Check various buffers are big enough for the code below */
#if (DHCP_BUFF_SZ < 255) || (MAXDNAME < 64) || (PACKETSZ+MAXDNAME+RRFIXEDSZ < 764)
# error Buffer size breakage in leasefile parsing.
#endif
while ((items=fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2)) == 2)
{
*daemon->namebuff = *daemon->dhcp_buff = *daemon->packet = '\0';
hw_len = hw_type = clid_len = 0;
#ifdef HAVE_DHCP6
if (strcmp(daemon->dhcp_buff3, "duid") == 0)
{
daemon->duid_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, 130, NULL, NULL);
if (daemon->duid_len < 0)
return 0;
daemon->duid = safe_malloc(daemon->duid_len);
memcpy(daemon->duid, daemon->dhcp_buff2, daemon->duid_len);
continue;
}
#endif
if (fscanf(leasestream, " %64s %255s %764s",
daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3)
return 0;
if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4))
{
if ((lease = lease4_allocate(addr.addr.addr4)))
domain = get_domain(lease->addr);
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
/* For backwards compatibility, no explicit MAC address type means ether. */
if (hw_type == 0 && hw_len != 0)
hw_type = ARPHRD_ETHER;
}
#ifdef HAVE_DHCP6
else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6))
{
char *s = daemon->dhcp_buff2;
int lease_type = LEASE_NA;
if (s[0] == 'T')
{
lease_type = LEASE_TA;
s++;
}
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);
}
}
#endif
else
return 0;
if (!lease)
die (_("too many stored leases"), NULL, EC_MISC);
if (strcmp(daemon->packet, "*") != 0)
clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet,
hw_len, hw_type, clid_len, now, 0);
if (strcmp(daemon->dhcp_buff, "*") != 0)
lease_set_hostname(lease, daemon->dhcp_buff, 0, domain, NULL);
ei = atol(daemon->dhcp_buff3);
#ifdef HAVE_BROKEN_RTC
if (ei != 0)
lease->expires = (time_t)ei + now;
else
lease->expires = (time_t)0;
lease->length = ei;
#else
/* strictly time_t is opaque, but this hack should work on all sane systems,
even when sizeof(time_t) == 8 */
lease->expires = (time_t)ei;
#endif
/* set these correctly: the "old" events are generated later from
the startup synthesised SIGHUP. */
lease->flags &= ~(LEASE_NEW | LEASE_CHANGED);
*daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
}
return (items == 0 || items == EOF);
}
void lease_init(time_t now)
{
FILE *leasestream;
leases_left = daemon->dhcp_max;
if (option_bool(OPT_LEASE_RO))
{
/* run "<lease_change_script> init" once to get the
initial state of the database. If leasefile-ro is
set without a script, we just do without any
set without a script, we just do without any
lease database. */
#ifdef HAVE_SCRIPT
if (daemon->lease_change_command)
@@ -56,99 +161,24 @@ void lease_init(time_t now)
{
/* NOTE: need a+ mode to create file if it doesn't exist */
leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
if (!leasestream)
die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
/* a+ mode leaves pointer at end. */
rewind(leasestream);
}
/* client-id max length is 255 which is 255*2 digits + 254 colons
borrow DNS packet buffer which is always larger than 1000 bytes */
if (leasestream)
while (fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2) == 2)
{
#ifdef HAVE_DHCP6
if (strcmp(daemon->dhcp_buff3, "duid") == 0)
{
daemon->duid_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, 130, NULL, NULL);
daemon->duid = safe_malloc(daemon->duid_len);
memcpy(daemon->duid, daemon->dhcp_buff2, daemon->duid_len);
continue;
}
#endif
{
if (!read_leases(now, leasestream))
my_syslog(MS_DHCP | LOG_ERR, _("failed to parse lease database, invalid line: %s %s %s %s ..."),
daemon->dhcp_buff3, daemon->dhcp_buff2,
daemon->namebuff, daemon->dhcp_buff);
ei = atol(daemon->dhcp_buff3);
if (fscanf(leasestream, " %64s %255s %764s",
daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3)
break;
clid_len = 0;
if (strcmp(daemon->packet, "*") != 0)
clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4) &&
(lease = lease4_allocate(addr.addr.addr4)))
{
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
/* For backwards compatibility, no explict MAC address type means ether. */
if (hw_type == 0 && hw_len != 0)
hw_type = ARPHRD_ETHER;
lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet,
hw_len, hw_type, clid_len, now, 0);
if (strcmp(daemon->dhcp_buff, "*") != 0)
lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain(lease->addr), NULL);
}
#ifdef HAVE_DHCP6
else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6))
{
char *s = daemon->dhcp_buff2;
int lease_type = LEASE_NA;
int iaid;
if (s[0] == 'T')
{
lease_type = LEASE_TA;
s++;
}
iaid = strtoul(s, NULL, 10);
if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
{
lease_set_hwaddr(lease, NULL, (unsigned char *)daemon->packet, 0, 0, clid_len, now, 0);
lease_set_iaid(lease, iaid);
if (strcmp(daemon->dhcp_buff, "*") != 0)
lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain6((struct in6_addr *)lease->hwaddr), NULL);
}
}
#endif
else
break;
if (!lease)
die (_("too many stored leases"), NULL, EC_MISC);
#ifdef HAVE_BROKEN_RTC
if (ei != 0)
lease->expires = (time_t)ei + now;
else
lease->expires = (time_t)0;
lease->length = ei;
#else
/* strictly time_t is opaque, but this hack should work on all sane systems,
even when sizeof(time_t) == 8 */
lease->expires = (time_t)ei;
#endif
/* set these correctly: the "old" events are generated later from
the startup synthesised SIGHUP. */
lease->flags &= ~(LEASE_NEW | LEASE_CHANGED);
}
if (ferror(leasestream))
die(_("failed to read lease file %s: %s"), daemon->lease_file, EC_FILE);
}
#ifdef HAVE_SCRIPT
if (!daemon->lease_stream)
@@ -162,6 +192,7 @@ void lease_init(time_t now)
errno = ENOENT;
else if (WEXITSTATUS(rc) == 126)
errno = EACCES;
die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE);
}
@@ -352,16 +383,21 @@ static int find_interface_v4(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam)
{
struct dhcp_lease *lease;
int prefix = netmask_length(netmask);
(void) label;
(void) broadcast;
(void) vparam;
for (lease = leases; lease; lease = lease->next)
if (!(lease->flags & (LEASE_TA | LEASE_NA)))
if (is_same_net(local, lease->addr, netmask))
lease_set_interface(lease, if_index, *((time_t *)vparam));
if (!(lease->flags & (LEASE_TA | LEASE_NA)) &&
is_same_net(local, lease->addr, netmask) &&
prefix > lease->new_prefixlen)
{
lease->new_interface = if_index;
lease->new_prefixlen = prefix;
}
return 1;
}
@@ -371,17 +407,23 @@ static int find_interface_v6(struct in6_addr *local, int prefix,
int preferred, int valid, void *vparam)
{
struct dhcp_lease *lease;
(void)scope;
(void)flags;
(void)preferred;
(void)valid;
(void)vparam;
for (lease = leases; lease; lease = lease->next)
if ((lease->flags & (LEASE_TA | LEASE_NA)))
if (is_same_net6(local, &lease->addr6, prefix))
lease_set_interface(lease, if_index, *((time_t *)vparam));
if (is_same_net6(local, &lease->addr6, prefix) && prefix > lease->new_prefixlen) {
/* save prefix length for comparison, as we might get shorter matching
* prefix in upcoming netlink GETADDR responses
* */
lease->new_interface = if_index;
lease->new_prefixlen = prefix;
}
return 1;
}
@@ -395,7 +437,7 @@ void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
void lease_update_slaac(time_t now)
{
/* Called when we contruct a new RA-names context, to add putative
/* Called when we construct a new RA-names context, to add putative
new SLAAC addresses to existing leases. */
struct dhcp_lease *lease;
@@ -414,10 +456,19 @@ void lease_update_slaac(time_t now)
start-time. */
void lease_find_interfaces(time_t now)
{
struct dhcp_lease *lease;
for (lease = leases; lease; lease = lease->next)
lease->new_prefixlen = lease->new_interface = 0;
iface_enumerate(AF_INET, &now, find_interface_v4);
#ifdef HAVE_DHCP6
iface_enumerate(AF_INET6, &now, find_interface_v6);
#endif
for (lease = leases; lease; lease = lease->next)
if (lease->new_interface != 0)
lease_set_interface(lease, lease->new_interface, now);
}
#ifdef HAVE_DHCP6
@@ -756,7 +807,7 @@ void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now)
{
exp = now + (time_t)len;
/* Check for 2038 overflow. Make the lease
inifinite in that case, as the least disruptive
infinite in that case, as the least disruptive
thing we can do. */
if (difftime(exp, now) <= 0.0)
exp = 0;
@@ -793,9 +844,9 @@ void lease_set_iaid(struct dhcp_lease *lease, int iaid)
}
#endif
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
unsigned char *clid, int hw_len, int hw_type, int clid_len,
time_t now, int force)
void lease_set_hwaddr(struct dhcp_lease *lease, const unsigned char *hwaddr,
const unsigned char *clid, int hw_len, int hw_type,
int clid_len, time_t now, int force)
{
#ifdef HAVE_DHCP6
int change = force;
@@ -877,7 +928,7 @@ static void kill_name(struct dhcp_lease *lease)
lease->hostname = lease->fqdn = NULL;
}
void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth, char *domain, char *config_domain)
void lease_set_hostname(struct dhcp_lease *lease, const char *name, int auth, char *domain, char *config_domain)
{
struct dhcp_lease *lease_tmp;
char *new_name = NULL, *new_fqdn = NULL;
@@ -1090,18 +1141,22 @@ int do_script_run(time_t now)
}
#ifdef HAVE_SCRIPT
/* delim == -1 -> delim = 0, but embedded 0s, creating extra records, are OK. */
void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data, unsigned int len, int delim)
{
unsigned int i;
/* check for embeded NULLs */
for (i = 0; i < len; i++)
if (data[i] == 0)
{
len = i;
break;
}
if (delim == -1)
delim = 0;
else
/* check for embedded NULLs */
for (i = 0; i < len; i++)
if (data[i] == 0)
{
len = i;
break;
}
if ((lease->extradata_size - lease->extradata_len) < (len + 1))
{
size_t newsz = lease->extradata_len + len + 100;

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -154,7 +154,7 @@ static void log_write(void)
while (entries)
{
/* The data in the payoad is written with a terminating zero character
/* The data in the payload is written with a terminating zero character
and the length reflects this. For a stream connection we need to
send the zero as a record terminator, but this isn't done for a
datagram connection, so treat the length as one less than reality
@@ -288,7 +288,9 @@ void my_syslog(int priority, const char *format, ...)
func = "-tftp";
else if ((LOG_FACMASK & priority) == MS_DHCP)
func = "-dhcp";
else if ((LOG_FACMASK & priority) == MS_SCRIPT)
func = "-script";
#ifdef LOG_PRI
priority = LOG_PRI(priority);
#else
@@ -421,25 +423,22 @@ void my_syslog(int priority, const char *format, ...)
}
}
void set_log_writer(fd_set *set, int *maxfdp)
void set_log_writer(void)
{
if (entries && log_fd != -1 && connection_good)
{
FD_SET(log_fd, set);
bump_maxfd(log_fd, maxfdp);
}
poll_listen(log_fd, POLLOUT);
}
void check_log_writer(fd_set *set)
void check_log_writer(int force)
{
if (log_fd != -1 && (!set || FD_ISSET(log_fd, set)))
if (log_fd != -1 && (force || poll_check(log_fd, POLLOUT)))
log_write();
}
void flush_log(void)
{
/* write until queue empty, but don't loop forever if there's
no connection to the syslog in existance */
no connection to the syslog in existence */
while (log_fd != -1)
{
struct timespec waiter;

117
src/loop.c Normal file
View File

@@ -0,0 +1,117 @@
/* dnsmasq is Copyright (c) 2000-2017 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_LOOP
static ssize_t loop_make_probe(u32 uid);
void loop_send_probes()
{
struct server *serv;
if (!option_bool(OPT_LOOP_DETECT))
return;
/* Loop through all upstream servers not for particular domains, and send a query to that server which is
identifiable, via the uid. If we see that query back again, then the server is looping, and we should not use it. */
for (serv = daemon->servers; serv; serv = serv->next)
if (!(serv->flags &
(SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_LOOP)))
{
ssize_t len = loop_make_probe(serv->uid);
int fd;
struct randfd *rfd = NULL;
if (serv->sfd)
fd = serv->sfd->fd;
else
{
if (!(rfd = allocate_rfd(serv->addr.sa.sa_family)))
continue;
fd = rfd->fd;
}
while (retry_send(sendto(fd, daemon->packet, len, 0,
&serv->addr.sa, sa_len(&serv->addr))));
free_rfd(rfd);
}
}
static ssize_t loop_make_probe(u32 uid)
{
struct dns_header *header = (struct dns_header *)daemon->packet;
unsigned char *p = (unsigned char *)(header+1);
/* packet buffer overwritten */
daemon->srv_save = NULL;
header->id = rand16();
header->ancount = header->nscount = header->arcount = htons(0);
header->qdcount = htons(1);
header->hb3 = HB3_RD;
header->hb4 = 0;
SET_OPCODE(header, QUERY);
*p++ = 8;
sprintf((char *)p, "%.8x", uid);
p += 8;
*p++ = strlen(LOOP_TEST_DOMAIN);
strcpy((char *)p, LOOP_TEST_DOMAIN); /* Add terminating zero */
p += strlen(LOOP_TEST_DOMAIN) + 1;
PUTSHORT(LOOP_TEST_TYPE, p);
PUTSHORT(C_IN, p);
return p - (unsigned char *)header;
}
int detect_loop(char *query, int type)
{
int i;
u32 uid;
struct server *serv;
if (!option_bool(OPT_LOOP_DETECT))
return 0;
if (type != LOOP_TEST_TYPE ||
strlen(LOOP_TEST_DOMAIN) + 9 != strlen(query) ||
strstr(query, LOOP_TEST_DOMAIN) != query + 9)
return 0;
for (i = 0; i < 8; i++)
if (!isxdigit(query[i]))
return 0;
uid = strtol(query, NULL, 16);
for (serv = daemon->servers; serv; serv = serv->next)
if (!(serv->flags &
(SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_LOOP)) &&
uid == serv->uid)
{
serv->flags |= SERV_LOOP;
check_servers(); /* log new state */
return 1;
}
return 0;
}
#endif

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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
@@ -38,7 +38,7 @@
static struct iovec iov;
static u32 netlink_pid;
static int nl_async(struct nlmsghdr *h);
static void nl_async(struct nlmsghdr *h);
void netlink_init(void)
{
@@ -73,7 +73,7 @@ void netlink_init(void)
}
if (daemon->netlinkfd == -1 ||
getsockname(daemon->netlinkfd, (struct sockaddr *)&addr, &slen) == 1)
getsockname(daemon->netlinkfd, (struct sockaddr *)&addr, &slen) == -1)
die(_("cannot create netlink socket: %s"), NULL, EC_MISC);
/* save pid assigned by bind() and retrieved by getsockname() */
@@ -142,7 +142,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
struct nlmsghdr *h;
ssize_t len;
static unsigned int seq = 0;
int callback_ok = 1, newaddr = 0;
int callback_ok = 1;
struct {
struct nlmsghdr nlh;
@@ -169,10 +169,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
req.g.rtgen_family = family;
/* Don't block in recvfrom if send fails */
while((len = sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0,
(struct sockaddr *)&addr, sizeof(addr))) == -1 && retry_send());
if (len == -1)
while(retry_send(sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0,
(struct sockaddr *)&addr, sizeof(addr))));
if (errno != 0)
return 0;
while (1)
@@ -188,24 +188,19 @@ int iface_enumerate(int family, void *parm, int (*callback)())
}
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
if (h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
{
/* May be multicast arriving async */
if (nl_async(h))
{
newaddr = 1;
enumerate_interfaces(1); /* reset */
}
nl_async(h);
}
else if (h->nlmsg_seq != seq)
{
/* May be part of incomplete response to previous request after
ENOBUFS. Drop it. */
continue;
}
else if (h->nlmsg_type == NLMSG_DONE)
{
/* handle async new interface address arrivals, these have to be done
after we complete as we're not re-entrant */
if (newaddr)
newaddress(dnsmasq_time());
return callback_ok;
}
return callback_ok;
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
{
struct ifaddrmsg *ifa = NLMSG_DATA(h);
@@ -219,7 +214,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
struct in_addr netmask, addr, broadcast;
char *label = NULL;
netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen));
netmask.s_addr = htonl(~(in_addr_t)0 << (32 - ifa->ifa_prefixlen));
addr.s_addr = 0;
broadcast.s_addr = 0;
@@ -298,7 +294,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
rta = RTA_NEXT(rta, len1);
}
if (inaddr && mac && callback_ok)
if (!(neigh->ndm_state & (NUD_NOARP | NUD_INCOMPLETE | NUD_FAILED)) &&
inaddr && mac && callback_ok)
if (!((*callback)(neigh->ndm_family, inaddr, mac, maclen, parm)))
callback_ok = 0;
}
@@ -330,11 +327,11 @@ int iface_enumerate(int family, void *parm, int (*callback)())
}
}
void netlink_multicast(time_t now)
void netlink_multicast(void)
{
ssize_t len;
struct nlmsghdr *h;
int flags, newaddr = 0;
int flags;
/* don't risk blocking reading netlink messages here. */
if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 ||
@@ -343,24 +340,19 @@ void netlink_multicast(time_t now)
if ((len = netlink_recv()) != -1)
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
if (nl_async(h))
newaddr = 1;
nl_async(h);
/* restore non-blocking status */
fcntl(daemon->netlinkfd, F_SETFL, flags);
if (newaddr)
newaddress(now);
}
static int nl_async(struct nlmsghdr *h)
static void nl_async(struct nlmsghdr *h)
{
if (h->nlmsg_type == NLMSG_ERROR)
{
struct nlmsgerr *err = NLMSG_DATA(h);
if (err->error != 0)
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
return 0;
}
else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
{
@@ -372,31 +364,10 @@ static int nl_async(struct nlmsghdr *h)
struct rtmsg *rtm = NLMSG_DATA(h);
if (rtm->rtm_type == RTN_UNICAST && rtm->rtm_scope == RT_SCOPE_LINK)
{
/* Force re-reading resolv file right now, for luck. */
daemon->last_resolv = 0;
if (daemon->srv_save)
{
int fd;
if (daemon->srv_save->sfd)
fd = daemon->srv_save->sfd->fd;
else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
fd = daemon->rfd_save->fd;
else
return 0;
while(sendto(fd, daemon->packet, daemon->packet_len, 0,
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
}
}
return 0;
queue_event(EVENT_NEWROUTE);
}
else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
return 1; /* clever bind mode - rescan */
return 0;
queue_event(EVENT_NEWADDR);
}
#endif

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,10 +16,6 @@
#include "dnsmasq.h"
#ifndef IN6_IS_ADDR_ULA
#define IN6_IS_ADDR_ULA(a) ((((__const uint32_t *) (a))[0] & htonl (0xfe00000)) == htonl (0xfc000000))
#endif
#ifdef HAVE_LINUX_NETWORK
int indextoname(int fd, int index, char *name)
@@ -182,7 +178,7 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth)
}
/* Fix for problem that the kernel sometimes reports the loopback inerface as the
/* Fix for problem that the kernel sometimes reports the loopback interface as the
arrival interface when a packet originates locally, even when sent to address of
an interface other than the loopback. Accept packet if it arrived via a loopback
interface, even when we're not accepting packets that way, as long as the destination
@@ -240,7 +236,7 @@ struct iface_param {
};
static int iface_allowed(struct iface_param *param, int if_index, char *label,
union mysockaddr *addr, struct in_addr netmask, int prefixlen, int dad)
union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags)
{
struct irec *iface;
int mtu = 0, loopback;
@@ -248,6 +244,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
int tftp_ok = !!option_bool(OPT_TFTP);
int dhcp_ok = 1;
int auth_dns = 0;
int is_label = 0;
#if defined(HAVE_DHCP) || defined(HAVE_TFTP)
struct iname *tmp;
#endif
@@ -268,6 +265,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
if (!label)
label = ifr.ifr_name;
else
is_label = strcmp(label, ifr.ifr_name);
/* maintain a list of all addresses on all interfaces for --local-service option */
if (option_bool(OPT_LOCAL_SERVICE))
@@ -392,6 +391,10 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
{
al->addr.addr.addr6 = addr->in6.sin6_addr;
al->flags = ADDRLIST_IPV6;
/* Privacy addresses and addresses still undergoing DAD and deprecated addresses
don't appear in forward queries, but will in reverse ones. */
if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
al->flags |= ADDRLIST_REVONLY;
}
#endif
}
@@ -403,7 +406,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, addr))
{
iface->dad = dad;
iface->dad = !!(iface_flags & IFACE_TENTATIVE);
iface->found = 1; /* for garbage collection */
return 1;
}
@@ -478,10 +481,11 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
iface->dhcp_ok = dhcp_ok;
iface->dns_auth = auth_dns;
iface->mtu = mtu;
iface->dad = dad;
iface->dad = !!(iface_flags & IFACE_TENTATIVE);
iface->found = 1;
iface->done = iface->multicast_done = iface->warned = 0;
iface->index = if_index;
iface->label = is_label;
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
{
strcpy(iface->name, ifr.ifr_name);
@@ -523,7 +527,7 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
else
addr.in6.sin6_scope_id = 0;
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, !!(flags & IFACE_TENTATIVE));
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
}
#endif
@@ -532,13 +536,14 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
{
union mysockaddr addr;
int prefix, bit;
(void)broadcast; /* warning */
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in.sin_len = sizeof(addr.in);
#endif
addr.in.sin_family = AF_INET;
addr.in.sin_addr = broadcast; /* warning */
addr.in.sin_addr = local;
addr.in.sin_port = htons(daemon->port);
@@ -551,7 +556,7 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
int enumerate_interfaces(int reset)
{
static struct addrlist *spare = NULL;
static int done = 0, active = 0;
static int done = 0;
struct iface_param param;
int errsave, ret = 1;
struct addrlist *addr, *tmp;
@@ -570,14 +575,11 @@ int enumerate_interfaces(int reset)
return 1;
}
if (done || active)
if (done)
return 1;
done = 1;
/* protect against recusive calls from iface_enumerate(); */
active = 1;
if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return 0;
@@ -646,7 +648,7 @@ int enumerate_interfaces(int reset)
/* Garbage-collect listeners listening on addresses that no longer exist.
Does nothing when not binding interfaces or for listeners on localhost,
since the ->iface field is NULL. Note that this needs the protections
against re-entrancy, hence it's here. It also means there's a possibility,
against reentrancy, hence it's here. It also means there's a possibility,
in OPT_CLEVERBIND mode, that at listener will just disappear after
a call to enumerate_interfaces, this is checked OK on all calls. */
struct listener *l, *tmp, **up;
@@ -677,10 +679,8 @@ int enumerate_interfaces(int reset)
}
errno = errsave;
spare = param.spare;
active = 0;
return ret;
}
@@ -703,7 +703,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if ((fd = socket(family, type, 0)) == -1)
{
int port, errsav;
int port, errsave;
char *s;
/* No error if the kernel just doesn't support this IP flavour */
@@ -713,7 +713,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
return -1;
err:
errsav = errno;
errsave = errno;
port = prettyprint_addr(addr, daemon->addrbuff);
if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
sprintf(daemon->addrbuff, "port %d", port);
@@ -722,7 +722,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if (fd != -1)
close (fd);
errno = errsav;
errno = errsave;
if (dienow)
{
@@ -750,7 +750,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if (type == SOCK_STREAM)
{
if (listen(fd, 5) == -1)
if (listen(fd, TCP_BACKLOG) == -1)
goto err;
}
else if (family == AF_INET)
@@ -814,10 +814,11 @@ int tcp_interface(int fd, int af)
int opt = 1;
struct cmsghdr *cmptr;
struct msghdr msg;
socklen_t len;
/* use mshdr do that the CMSDG_* macros are available */
/* use mshdr so that the CMSDG_* macros are available */
msg.msg_control = daemon->packet;
msg.msg_controllen = daemon->packet_buff_sz;
msg.msg_controllen = len = daemon->packet_buff_sz;
/* we overwrote the buffer... */
daemon->srv_save = NULL;
@@ -825,18 +826,21 @@ int tcp_interface(int fd, int af)
if (af == AF_INET)
{
if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
{
union {
unsigned char *c;
struct in_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr);
if_index = p.p->ipi_ifindex;
}
getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
{
msg.msg_controllen = len;
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
{
union {
unsigned char *c;
struct in_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr);
if_index = p.p->ipi_ifindex;
}
}
}
#ifdef HAVE_IPV6
else
@@ -854,9 +858,10 @@ int tcp_interface(int fd, int af)
#endif
if (set_ipv6pktinfo(fd) &&
getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, &len) != -1)
{
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
msg.msg_controllen = len;
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
{
union {
@@ -1033,6 +1038,15 @@ void warn_bound_listeners(void)
my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"));
}
void warn_wild_labels(void)
{
struct irec *iface;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->found && iface->name && iface->label)
my_syslog(LOG_WARNING, _("warning: using interface %s instead"), iface->name);
}
void warn_int_names(void)
{
struct interface_name *intname;
@@ -1081,23 +1095,30 @@ void join_multicast(int dienow)
if ((daemon->doing_dhcp6 || daemon->relay6) &&
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
err = 1;
err = errno;
inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
if (daemon->doing_dhcp6 &&
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
err = 1;
err = errno;
inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
if (daemon->doing_ra &&
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
err = 1;
err = errno;
if (err)
{
char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
errno = err;
#ifdef HAVE_LINUX_NETWORK
if (errno == ENOMEM)
my_syslog(LOG_ERR, _("try increasing /proc/sys/net/core/optmem_max"));
#endif
if (dienow)
die(s, iface->name, EC_BADNET);
else
@@ -1117,7 +1138,7 @@ int random_sock(int family)
if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
{
union mysockaddr addr;
unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
int tries = ports_avail < 30 ? 3 * ports_avail : 100;
memset(&addr, 0, sizeof(addr));
@@ -1130,8 +1151,8 @@ int random_sock(int family)
{
unsigned short port = rand16();
if (daemon->min_port != 0)
port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
if (daemon->min_port != 0 || daemon->max_port != MAX_PORT)
port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
if (family == AF_INET)
{
@@ -1196,6 +1217,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
{
struct serverfd *sfd;
unsigned int ifindex = 0;
int errsave;
/* when using random ports, servers which would otherwise use
@@ -1216,11 +1238,15 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
return NULL;
#endif
}
if (intname && strlen(intname) != 0)
ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
/* may have a suitable one already */
for (sfd = daemon->sfds; sfd; sfd = sfd->next )
if (sockaddr_isequal(&sfd->source_addr, addr) &&
strcmp(intname, sfd->interface) == 0)
strcmp(intname, sfd->interface) == 0 &&
ifindex == sfd->ifindex)
return sfd;
/* need to make a new one. */
@@ -1242,11 +1268,13 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
errno = errsave;
return NULL;
}
strcpy(sfd->interface, intname);
sfd->source_addr = *addr;
sfd->next = daemon->sfds;
sfd->ifindex = ifindex;
daemon->sfds = sfd;
return sfd;
}
@@ -1302,8 +1330,14 @@ void mark_servers(int flag)
/* mark everything with argument flag */
for (serv = daemon->servers; serv; serv = serv->next)
if (serv->flags & flag)
serv->flags |= SERV_MARK;
{
if (serv->flags & flag)
serv->flags |= SERV_MARK;
#ifdef HAVE_LOOP
/* Give looped servers another chance */
serv->flags &= ~SERV_LOOP;
#endif
}
}
void cleanup_servers(void)
@@ -1325,6 +1359,11 @@ void cleanup_servers(void)
else
up = &serv->next;
}
#ifdef HAVE_LOOP
/* Now we have a new set of servers, test for loops. */
loop_send_probes();
#endif
}
void add_update_server(int flags,
@@ -1390,7 +1429,10 @@ void add_update_server(int flags,
serv->domain = domain_str;
serv->next = next;
serv->queries = serv->failed_queries = 0;
#ifdef HAVE_LOOP
serv->uid = rand32();
#endif
if (domain)
serv->flags |= SERV_HAS_DOMAIN;
@@ -1407,18 +1449,58 @@ void check_servers(void)
{
struct irec *iface;
struct server *serv;
int port = 0;
struct serverfd *sfd, *tmp, **up;
int port = 0, count;
int locals = 0;
/* interface may be new since startup */
if (!option_bool(OPT_NOWILD))
enumerate_interfaces(0);
for (serv = daemon->servers; serv; serv = serv->next)
{
if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
{
port = prettyprint_addr(&serv->addr, daemon->namebuff);
for (sfd = daemon->sfds; sfd; sfd = sfd->next)
sfd->used = 0;
#ifdef HAVE_DNSSEC
/* Disable DNSSEC validation when using server=/domain/.... servers
unless there's a configured trust anchor. */
for (serv = daemon->servers; serv; serv = serv->next)
serv->flags |= SERV_DO_DNSSEC;
#endif
for (count = 0, serv = daemon->servers; serv; serv = serv->next)
{
if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
{
/* Init edns_pktsz for newly created server records. */
if (serv->edns_pktsz == 0)
serv->edns_pktsz = daemon->edns_pktsz;
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
{
if (serv->flags & SERV_HAS_DOMAIN)
{
struct ds_config *ds;
char *domain = serv->domain;
/* .example.com is valid */
while (*domain == '.')
domain++;
for (ds = daemon->ds; ds; ds = ds->next)
if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
break;
if (!ds)
serv->flags &= ~SERV_DO_DNSSEC;
}
else if (serv->flags & SERV_FOR_NODOTS)
serv->flags &= ~SERV_DO_DNSSEC;
}
#endif
port = prettyprint_addr(&serv->addr, daemon->namebuff);
/* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
if (serv->addr.sa.sa_family == AF_INET &&
serv->addr.in.sin_addr.s_addr == 0)
@@ -1448,13 +1530,23 @@ void check_servers(void)
serv->flags |= SERV_MARK;
continue;
}
if (serv->sfd)
serv->sfd->used = 1;
}
if (!(serv->flags & SERV_NO_REBIND))
if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
{
if (++count > SERVERS_LOGGED)
continue;
if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
{
char *s1, *s2;
char *s1, *s2, *s3 = "";
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
s3 = _("(no DNSSEC)");
#endif
if (!(serv->flags & SERV_HAS_DOMAIN))
s1 = _("unqualified"), s2 = _("names");
else if (strlen(serv->domain) == 0)
@@ -1463,19 +1555,46 @@ void check_servers(void)
s1 = _("domain"), s2 = serv->domain;
if (serv->flags & SERV_NO_ADDR)
my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
{
count--;
if (++locals <= LOCALS_LOGGED)
my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
}
else if (serv->flags & SERV_USE_RESOLV)
my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
else if (!(serv->flags & SERV_LITERAL_ADDRESS))
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
else
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s %s"), daemon->namebuff, port, s1, s2, s3);
}
#ifdef HAVE_LOOP
else if (serv->flags & SERV_LOOP)
my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port);
#endif
else if (serv->interface[0] != 0)
my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
else
my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
}
}
if (locals > LOCALS_LOGGED)
my_syslog(LOG_INFO, _("using %d more local addresses"), locals - LOCALS_LOGGED);
if (count - 1 > SERVERS_LOGGED)
my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
/* Remove unused sfds */
for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
{
tmp = sfd->next;
if (!sfd->used)
{
*up = sfd->next;
close(sfd->fd);
free(sfd);
}
else
up = &sfd->next;
}
cleanup_servers();
}
@@ -1564,7 +1683,6 @@ int reload_servers(char *fname)
return gotone;
}
#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_BSD_NETWORK)
/* Called when addresses are added or deleted from an interface */
void newaddress(time_t now)
{
@@ -1589,7 +1707,6 @@ void newaddress(time_t now)
#endif
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -29,9 +29,19 @@ void end_opt6(int container)
PUTSHORT(len, p);
}
void reset_counter(void)
{
/* Clear out buffer when starting from beginning */
if (daemon->outpacket.iov_base)
memset(daemon->outpacket.iov_base, 0, daemon->outpacket.iov_len);
save_counter(0);
}
int save_counter(int newval)
{
int ret = outpacket_counter;
if (newval != -1)
outpacket_counter = newval;

125
src/poll.c Normal file
View File

@@ -0,0 +1,125 @@
/* dnsmasq is Copyright (c) 2000-2017 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"
/* Wrapper for poll(). Allocates and extends array of struct pollfds,
keeps them in fd order so that we can set and test conditions on
fd using a simple but efficient binary chop. */
/* poll_reset()
poll_listen(fd, event)
.
.
poll_listen(fd, event);
hits = do_poll(timeout);
if (poll_check(fd, event)
.
.
if (poll_check(fd, event)
.
.
event is OR of POLLIN, POLLOUT, POLLERR, etc
*/
static struct pollfd *pollfds = NULL;
static nfds_t nfds, arrsize = 0;
/* Binary search. Returns either the pollfd with fd, or
if the fd doesn't match, or return equals nfds, the entry
to the left of which a new record should be inserted. */
static nfds_t fd_search(int fd)
{
nfds_t left, right, mid;
if ((right = nfds) == 0)
return 0;
left = 0;
while (1)
{
if (right == left + 1)
return (pollfds[left].fd >= fd) ? left : right;
mid = (left + right)/2;
if (pollfds[mid].fd > fd)
right = mid;
else
left = mid;
}
}
void poll_reset(void)
{
nfds = 0;
}
int do_poll(int timeout)
{
return poll(pollfds, nfds, timeout);
}
int poll_check(int fd, short event)
{
nfds_t i = fd_search(fd);
if (i < nfds && pollfds[i].fd == fd)
return pollfds[i].revents & event;
return 0;
}
void poll_listen(int fd, short event)
{
nfds_t i = fd_search(fd);
if (i < nfds && pollfds[i].fd == fd)
pollfds[i].events |= event;
else
{
if (arrsize != nfds)
memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
else
{
/* Array too small, extend. */
struct pollfd *new;
arrsize = (arrsize == 0) ? 64 : arrsize * 2;
if (!(new = whine_malloc(arrsize * sizeof(struct pollfd))))
return;
if (pollfds)
{
memcpy(new, pollfds, i * sizeof(struct pollfd));
memcpy(&new[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
free(pollfds);
}
pollfds = new;
}
pollfds[i].fd = fd;
pollfds[i].events = event;
nfds++;
}
}

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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
@@ -49,6 +49,8 @@ struct prefix_opt {
#define ICMP6_OPT_SOURCE_MAC 1
#define ICMP6_OPT_PREFIX 3
#define ICMP6_OPT_MTU 5
#define ICMP6_OPT_ADV_INTERVAL 7
#define ICMP6_OPT_RT_INFO 24
#define ICMP6_OPT_RDNSS 25
#define ICMP6_OPT_DNSSL 31

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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
@@ -28,11 +28,12 @@
struct ra_param {
time_t now;
int ind, managed, other, found_context, first;
int ind, managed, other, first, adv_router;
char *if_name;
struct dhcp_netid *tags;
struct in6_addr link_local, link_global, ula;
unsigned int glob_pref_time, link_pref_time, ula_pref_time, adv_interval;
unsigned int glob_pref_time, link_pref_time, ula_pref_time, adv_interval, prio;
struct dhcp_context *found_context;
};
struct search_param {
@@ -40,7 +41,18 @@ struct search_param {
char name[IF_NAMESIZE+1];
};
struct alias_param {
int iface;
struct dhcp_bridge *bridge;
int num_alias_ifs;
int max_alias_ifs;
int *alias_ifs;
};
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest);
static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_addr *dest,
int send_iface);
static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t maclen, void *parm);
static int add_prefixes(struct in6_addr *local, int prefix,
int scope, int if_index, int flags,
unsigned int preferred, unsigned int valid, void *vparam);
@@ -70,7 +82,7 @@ void ra_init(time_t now)
/* ensure this is around even if we're not doing DHCPv6 */
expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));
/* See if we're guessing SLAAC addresses, if so we need to recieve ping replies */
/* See if we're guessing SLAAC addresses, if so we need to receive ping replies */
for (context = daemon->dhcp6; context; context = context->next)
if ((context->flags & CONTEXT_RA_NAME))
break;
@@ -100,10 +112,10 @@ void ra_init(time_t now)
daemon->icmp6fd = fd;
if (daemon->doing_ra)
ra_start_unsolicted(now, NULL);
ra_start_unsolicited(now, NULL);
}
void ra_start_unsolicted(time_t now, struct dhcp_context *context)
void ra_start_unsolicited(time_t now, struct dhcp_context *context)
{
/* init timers so that we do ra's for some/all soon. some ra_times will end up zeroed
if it's not appropriate to advertise those contexts.
@@ -181,6 +193,7 @@ void icmp6_packet(time_t now)
else if (packet[0] == ND_ROUTER_SOLICIT)
{
char *mac = "";
struct dhcp_bridge *bridge, *alias;
/* look for link-layer address option for logging */
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
@@ -191,12 +204,37 @@ void icmp6_packet(time_t now)
if (!option_bool(OPT_QUIET_RA))
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
/* source address may not be valid in solicit request. */
send_ra(now, if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
/* If the incoming interface is an alias of some other one (as
specified by the --bridge-interface option), send an RA using
the context of the aliased interface. */
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
{
int bridge_index = if_nametoindex(bridge->iface);
if (bridge_index)
{
for (alias = bridge->alias; alias; alias = alias->next)
if (wildcard_matchn(alias->iface, interface, IF_NAMESIZE))
{
/* Send an RA on if_index with information from
bridge_index. */
send_ra_alias(now, bridge_index, bridge->iface, NULL, if_index);
break;
}
if (alias)
break;
}
}
/* If the incoming interface wasn't an alias, send an RA using
the context of the incoming interface. */
if (!bridge)
/* source address may not be valid in solicit request. */
send_ra(now, if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
}
}
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest)
static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_addr *dest, int send_iface)
{
struct ra_packet *ra;
struct ra_param parm;
@@ -205,33 +243,37 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
struct dhcp_netid iface_id;
struct dhcp_opt *opt_cfg;
struct ra_interface *ra_param = find_iface_param(iface_name);
int done_dns = 0, old_prefix = 0;
int done_dns = 0, old_prefix = 0, mtu = 0;
unsigned int min_pref_time;
#ifdef HAVE_LINUX_NETWORK
FILE *f;
#endif
save_counter(0);
ra = expand(sizeof(struct ra_packet));
ra->type = ND_ROUTER_ADVERT;
ra->code = 0;
ra->hop_limit = hop_limit;
ra->flags = calc_prio(ra_param);
ra->lifetime = htons(calc_lifetime(ra_param));
ra->reachable_time = 0;
ra->retrans_time = 0;
parm.ind = iface;
parm.managed = 0;
parm.other = 0;
parm.found_context = 0;
parm.found_context = NULL;
parm.adv_router = 0;
parm.if_name = iface_name;
parm.first = 1;
parm.now = now;
parm.glob_pref_time = parm.link_pref_time = parm.ula_pref_time = 0;
parm.adv_interval = calc_interval(ra_param);
parm.prio = calc_prio(ra_param);
reset_counter();
if (!(ra = expand(sizeof(struct ra_packet))))
return;
ra->type = ND_ROUTER_ADVERT;
ra->code = 0;
ra->hop_limit = hop_limit;
ra->flags = parm.prio;
ra->lifetime = htons(calc_lifetime(ra_param));
ra->reachable_time = 0;
ra->retrans_time = 0;
/* set tag with name == interface */
iface_id.net = iface_name;
iface_id.next = NULL;
@@ -269,8 +311,14 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
unsigned int old = difftime(now, context->address_lost_time);
if (old > context->saved_valid)
{
{
/* We've advertised this enough, time to go */
/* If this context held the timeout, and there's another context in use
transfer the timeout there. */
if (context->ra_time != 0 && parm.found_context && parm.found_context->ra_time == 0)
new_timeout(parm.found_context, iface_name, now);
*up = context->next;
free(context);
}
@@ -286,8 +334,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
setaddr6part(&local, addr6part(&local) & ~((context->prefix == 64) ? (u64)-1LL : (1LLU << (128 - context->prefix)) - 1LLU));
if ((context->flags &
(CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
if (context->flags & CONTEXT_RA)
{
do_slaac = 1;
if (context->flags & CONTEXT_DHCP)
@@ -312,8 +359,10 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
opt->type = ICMP6_OPT_PREFIX;
opt->len = 4;
opt->prefix_len = context->prefix;
/* autonomous only if we're not doing dhcp, always set "on-link" */
opt->flags = do_slaac ? 0xC0 : 0x80;
/* autonomous only if we're not doing dhcp, set
"on-link" unless "off-link" was specified */
opt->flags = (do_slaac ? 0x40 : 0) |
((context->flags & CONTEXT_RA_OFF_LINK) ? 0 : 0x80);
opt->valid_lifetime = htonl(context->saved_valid - old);
opt->preferred_lifetime = htonl(0);
opt->reserved = 0;
@@ -339,24 +388,45 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
if (!old_prefix && !parm.found_context)
return;
#ifdef HAVE_LINUX_NETWORK
/* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU
available from SIOCGIFMTU */
sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", iface_name);
if ((f = fopen(daemon->namebuff, "r")))
/* If we're sending router address instead of prefix in at least on prefix,
include the advertisement interval option. */
if (parm.adv_router)
{
if (fgets(daemon->namebuff, MAXDNAME, f))
{
put_opt6_char(ICMP6_OPT_MTU);
put_opt6_char(1);
put_opt6_short(0);
put_opt6_long(atoi(daemon->namebuff));
}
fclose(f);
put_opt6_char(ICMP6_OPT_ADV_INTERVAL);
put_opt6_char(1);
put_opt6_short(0);
/* interval value is in milliseconds */
put_opt6_long(1000 * calc_interval(find_iface_param(iface_name)));
}
/* Set the MTU from ra_param if any, an MTU of 0 mean automatic for linux, */
/* an MTU of -1 prevents the option from being sent. */
if (ra_param)
mtu = ra_param->mtu;
#ifdef HAVE_LINUX_NETWORK
/* Note that IPv6 MTU is not neccessarily the same as the IPv4 MTU
available from SIOCGIFMTU */
if (mtu == 0)
{
char *mtu_name = ra_param ? ra_param->mtu_name : NULL;
sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", mtu_name ? : iface_name);
if ((f = fopen(daemon->namebuff, "r")))
{
if (fgets(daemon->namebuff, MAXDNAME, f))
mtu = atoi(daemon->namebuff);
fclose(f);
}
}
#endif
if (mtu > 0)
{
put_opt6_char(ICMP6_OPT_MTU);
put_opt6_char(1);
put_opt6_short(0);
put_opt6_long(mtu);
}
iface_enumerate(AF_LOCAL, &iface, add_lla);
iface_enumerate(AF_LOCAL, &send_iface, add_lla);
/* RDNSS, RFC 6106, use relevant DHCP6 options */
(void)option_filter(parm.tags, NULL, daemon->dhcp_opts6);
@@ -464,14 +534,22 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
else
{
inet_pton(AF_INET6, ALL_NODES, &addr.sin6_addr);
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface, sizeof(iface));
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &send_iface, sizeof(send_iface));
}
while (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0,
(struct sockaddr *)&addr, sizeof(addr)) == -1 && retry_send());
while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,
save_counter(-1), 0, (struct sockaddr *)&addr,
sizeof(addr))));
}
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest)
{
/* Send an RA on the same interface that the RA content is based
on. */
send_ra_alias(now, iface, iface_name, dest, iface);
}
static int add_prefixes(struct in6_addr *local, int prefix,
int scope, int if_index, int flags,
unsigned int preferred, unsigned int valid, void *vparam)
@@ -500,6 +578,8 @@ static int add_prefixes(struct in6_addr *local, int prefix,
int do_slaac = 0;
int deprecate = 0;
int constructed = 0;
int adv_router = 0;
int off_link = 0;
unsigned int time = 0xffffffff;
struct dhcp_context *context;
@@ -511,8 +591,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
{
context->saved_valid = valid;
if ((context->flags &
(CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
if (context->flags & CONTEXT_RA)
{
do_slaac = 1;
if (context->flags & CONTEXT_DHCP)
@@ -530,7 +609,17 @@ static int add_prefixes(struct in6_addr *local, int prefix,
param->managed = 1;
param->other = 1;
}
/* Configured to advertise router address, not prefix. See RFC 3775 7.2
In this case we do all addresses associated with a context,
hence the real_prefix setting here. */
if (context->flags & CONTEXT_RA_ROUTER)
{
adv_router = 1;
param->adv_router = 1;
real_prefix = context->prefix;
}
/* find floor time, don't reduce below 3 * RA interval. */
if (time > context->lease_time)
{
@@ -556,17 +645,20 @@ static int add_prefixes(struct in6_addr *local, int prefix,
/* subsequent prefixes on the same interface
and subsequent instances of this prefix don't need timers.
Be careful not to find the same prefix twice with different
addresses. */
addresses unless we're advertising the actual addresses. */
if (!(context->flags & CONTEXT_RA_DONE))
{
if (!param->first)
context->ra_time = 0;
context->flags |= CONTEXT_RA_DONE;
real_prefix = context->prefix;
off_link = (context->flags & CONTEXT_RA_OFF_LINK);
}
param->first = 0;
param->found_context = 1;
param->first = 0;
/* found_context is the _last_ one we found, so if there's
more than one, it's not the first. */
param->found_context = context;
}
/* configured time is ceiling */
@@ -607,13 +699,19 @@ static int add_prefixes(struct in6_addr *local, int prefix,
if ((opt = expand(sizeof(struct prefix_opt))))
{
/* zero net part of address */
setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU));
if (!adv_router)
setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU));
opt->type = ICMP6_OPT_PREFIX;
opt->len = 4;
opt->prefix_len = real_prefix;
/* autonomous only if we're not doing dhcp, always set "on-link" */
opt->flags = do_slaac ? 0xC0 : 0x80;
/* autonomous only if we're not doing dhcp, set
"on-link" unless "off-link" was specified */
opt->flags = (off_link ? 0 : 0x80);
if (do_slaac)
opt->flags |= 0x40;
if (adv_router)
opt->flags |= 0x20;
opt->valid_lifetime = htonl(valid);
opt->preferred_lifetime = htonl(preferred);
opt->reserved = 0;
@@ -655,6 +753,7 @@ time_t periodic_ra(time_t now)
struct search_param param;
struct dhcp_context *context;
time_t next_event;
struct alias_param aparam;
param.now = now;
param.iface = 0;
@@ -691,7 +790,7 @@ time_t periodic_ra(time_t now)
associated with it, because it's for a subnet we dont
have an interface on. Probably we're doing DHCP on
a remote subnet via a relay. Zero the timer, since we won't
ever be able to send ra's and satistfy it. */
ever be able to send ra's and satisfy it. */
context->ra_time = 0;
if (param.iface != 0 &&
@@ -702,12 +801,84 @@ time_t periodic_ra(time_t now)
if (tmp->name && wildcard_match(tmp->name, param.name))
break;
if (!tmp)
send_ra(now, param.iface, param.name, NULL);
{
send_ra(now, param.iface, param.name, NULL);
/* Also send on all interfaces that are aliases of this
one. */
for (aparam.bridge = daemon->bridges;
aparam.bridge;
aparam.bridge = aparam.bridge->next)
if ((int)if_nametoindex(aparam.bridge->iface) == param.iface)
{
/* Count the number of alias interfaces for this
'bridge', by calling iface_enumerate with
send_ra_to_aliases and NULL alias_ifs. */
aparam.iface = param.iface;
aparam.alias_ifs = NULL;
aparam.num_alias_ifs = 0;
iface_enumerate(AF_LOCAL, &aparam, send_ra_to_aliases);
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s => %d alias(es)",
param.name, daemon->addrbuff, aparam.num_alias_ifs);
/* Allocate memory to store the alias interface
indices. */
aparam.alias_ifs = (int *)whine_malloc(aparam.num_alias_ifs *
sizeof(int));
if (aparam.alias_ifs)
{
/* Use iface_enumerate again to get the alias
interface indices, then send on each of
those. */
aparam.max_alias_ifs = aparam.num_alias_ifs;
aparam.num_alias_ifs = 0;
iface_enumerate(AF_LOCAL, &aparam, send_ra_to_aliases);
for (; aparam.num_alias_ifs; aparam.num_alias_ifs--)
{
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s => i/f %d",
param.name, daemon->addrbuff,
aparam.alias_ifs[aparam.num_alias_ifs - 1]);
send_ra_alias(now,
param.iface,
param.name,
NULL,
aparam.alias_ifs[aparam.num_alias_ifs - 1]);
}
free(aparam.alias_ifs);
}
/* The source interface can only appear in at most
one --bridge-interface. */
break;
}
}
}
}
return next_event;
}
static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t maclen, void *parm)
{
struct alias_param *aparam = (struct alias_param *)parm;
char ifrn_name[IFNAMSIZ];
struct dhcp_bridge *alias;
(void)type;
(void)mac;
(void)maclen;
if (if_indextoname(index, ifrn_name))
for (alias = aparam->bridge->alias; alias; alias = alias->next)
if (wildcard_matchn(alias->iface, ifrn_name, IFNAMSIZ))
{
if (aparam->alias_ifs && (aparam->num_alias_ifs < aparam->max_alias_ifs))
aparam->alias_ifs[aparam->num_alias_ifs] = index;
aparam->num_alias_ifs++;
}
return 1;
}
static int iface_search(struct in6_addr *local, int prefix,
int scope, int if_index, int flags,
int preferred, int valid, void *vparam)

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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
@@ -52,7 +52,9 @@ static void do_options(struct dhcp_context *context,
int null_term, int pxearch,
unsigned char *uuid,
int vendor_class_len,
time_t now);
time_t now,
unsigned int lease_time,
unsigned short fuzz);
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
@@ -61,10 +63,12 @@ static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char
static int prune_vendor_opts(struct dhcp_netid *netid);
static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now);
struct dhcp_boot *find_boot(struct dhcp_netid *netid);
static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dhcp_packet *mess, struct in_addr local, time_t now, int pxe);
static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid);
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe, struct in_addr fallback)
size_t sz, time_t now, int unicast_dest, int loopback,
int *is_inform, int pxe, struct in_addr fallback, time_t recvtime)
{
unsigned char *opt, *clid = NULL;
struct dhcp_lease *ltmp, *lease = NULL;
@@ -184,7 +188,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
be enough free space at the end of the packet to copy the option. */
unsigned char *sopt;
unsigned int total = option_len(opt) + 2;
unsigned char *last_opt = option_find(mess, sz, OPTION_END, 0);
unsigned char *last_opt = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + sz,
OPTION_END, 0);
if (last_opt && last_opt < end - total)
{
end -= total;
@@ -362,7 +367,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
/* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
Otherwise assume the option is an array, and look for a matching element.
If no data given, existance of the option is enough. This code handles
If no data given, existence of the option is enough. This code handles
rfc3925 V-I classes too. */
for (o = daemon->dhcp_match; o; o = o->next)
{
@@ -378,7 +383,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
{
len = option_uint(opt, offset + 4 , 1);
/* Need to take care that bad data can't run us off the end of the packet */
if ((offset + len + 5 <= (option_len(opt))) &&
if ((offset + len + 5 <= (unsigned)(option_len(opt))) &&
(option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
{
@@ -483,6 +488,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
known_id.next = netid;
netid = &known_id;
}
else if (find_config(daemon->dhcp_conf, NULL, clid, clid_len,
mess->chaddr, mess->hlen, mess->htype, NULL))
{
known_id.net = "known-othernet";
known_id.next = netid;
netid = &known_id;
}
if (mess_type == 0 && !pxe)
{
@@ -564,7 +576,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
lease_prune(lease, now);
lease = NULL;
}
if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now))
if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now, loopback))
message = _("no address available");
}
else
@@ -610,7 +622,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
clear_packet(mess, end);
do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now);
netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now, 0xffffffff, 0);
}
}
@@ -803,9 +815,14 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (service->type == type)
break;
if (!service || !service->basename)
return 0;
for (; context; context = context->current)
if (match_netid(context->filter, tagif_netid, 1) &&
is_same_net(mess->ciaddr, context->start, context->netmask))
break;
if (!service || !service->basename || !context)
return 0;
clear_packet(mess, end);
mess->yiaddr = mess->ciaddr;
@@ -817,7 +834,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
else
mess->siaddr = context->local;
snprintf((char *)mess->file, sizeof(mess->file), "%s.%d", service->basename, layer);
if (strchr(service->basename, '.'))
snprintf((char *)mess->file, sizeof(mess->file),
"%s", service->basename);
else
snprintf((char *)mess->file, sizeof(mess->file),
"%s.%d", service->basename, layer);
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
pxe_misc(mess, end, uuid);
@@ -844,6 +867,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if ((mess_type == DHCPDISCOVER || (pxe && mess_type == DHCPREQUEST)))
{
struct dhcp_context *tmp;
int workaround = 0;
for (tmp = context; tmp; tmp = tmp->current)
if ((tmp->flags & CONTEXT_PROXY) &&
@@ -853,7 +877,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (tmp)
{
struct dhcp_boot *boot;
int redirect4011 = 0;
if (tmp->netid.net)
{
tmp->netid.next = netid;
@@ -871,10 +896,21 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
clear_packet(mess, end);
/* Provide the bootfile here, for gPXE, and in case we have no menu items
and set discovery_control = 8 */
if (boot)
/* Redirect EFI clients to port 4011 */
if (pxearch >= 6)
{
redirect4011 = 1;
mess->siaddr = tmp->local;
}
/* Returns true if only one matching service is available. On port 4011,
it also inserts the boot file and server name. */
workaround = pxe_uefi_workaround(pxearch, tagif_netid, mess, tmp->local, now, pxe);
if (!workaround && boot)
{
/* Provide the bootfile here, for gPXE, and in case we have no menu items
and set discovery_control = 8 */
if (boot->next_server.s_addr)
mess->siaddr = boot->next_server;
else if (boot->tftp_sname)
@@ -886,13 +922,16 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(tmp->local.s_addr));
pxe_misc(mess, end, uuid);
prune_vendor_opts(tagif_netid);
do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
if ((pxe && !workaround) || !redirect4011)
do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
log_tags(tagif_netid, ntohl(mess->xid));
if (!ignore)
apply_delay(mess->xid, recvtime, tagif_netid);
return ignore ? 0 : dhcp_packet_size(mess, agent_id, real_end);
}
}
@@ -1001,6 +1040,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
else if (have_config(config, CONFIG_DECLINED) &&
difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs);
else if ((!lease || lease->addr.s_addr != config->addr.s_addr) && !do_icmp_ping(now, config->addr, 0, loopback))
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by another host"), addrs);
else
conf = config->addr;
}
@@ -1013,11 +1054,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
!config_find_by_address(daemon->dhcp_conf, lease->addr))
mess->yiaddr = lease->addr;
else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) &&
!config_find_by_address(daemon->dhcp_conf, addr))
!config_find_by_address(daemon->dhcp_conf, addr) && do_icmp_ping(now, addr, 0, loopback))
mess->yiaddr = addr;
else if (emac_len == 0)
message = _("no unique-id");
else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now))
else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now, loopback))
message = _("no address available");
}
@@ -1033,7 +1074,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
}
log_tags(tagif_netid, ntohl(mess->xid));
apply_delay(mess->xid, recvtime, tagif_netid);
log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
@@ -1042,13 +1083,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
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);
/* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
if (time != 0xffffffff)
{
option_put(mess, end, OPTION_T1, 4, (time/2));
option_put(mess, end, OPTION_T2, 4, (time*7)/8);
}
do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
return dhcp_packet_size(mess, agent_id, real_end);
@@ -1284,6 +1320,24 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
add_extradata_opt(lease, NULL);
}
/* DNSMASQ_REQUESTED_OPTIONS */
if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 1)))
{
int len = option_len(opt);
unsigned char *rop = option_ptr(opt, 0);
char *q = daemon->namebuff;
int i;
for (i = 0; i < len; i++)
{
q += snprintf(q, MAXDNAME - (q - daemon->namebuff), "%d%s", rop[i], i + 1 == len ? "" : ",");
}
lease_add_extradata(lease, (unsigned char *)daemon->namebuff, (q - daemon->namebuff), 0);
}
else
{
add_extradata_opt(lease, NULL);
}
/* space-concat tag set */
if (!tagif_netid)
add_extradata_opt(lease, NULL);
@@ -1306,7 +1360,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
/* If the user-class option started as counted strings, the first byte will be zero. */
if (len != 0 && ucp[0] == 0)
ucp++, len--;
lease_add_extradata(lease, ucp, len, 0);
lease_add_extradata(lease, ucp, len, -1);
}
}
#endif
@@ -1367,15 +1421,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
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);
if (time != 0xffffffff)
{
while (fuzz > (time/16))
fuzz = fuzz/2;
option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz);
option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz);
}
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);
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
}
return dhcp_packet_size(mess, agent_id, real_end);
@@ -1440,7 +1487,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
}
do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, 0xffffffff, 0);
*is_inform = 1; /* handle reply differently */
return dhcp_packet_size(mess, agent_id, real_end);
@@ -1594,7 +1641,7 @@ static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt
{
while (1)
{
if (p > end)
if (p >= end)
return NULL;
else if (*p == OPTION_END)
return opt == OPTION_END ? p : NULL;
@@ -1980,6 +2027,56 @@ static int prune_vendor_opts(struct dhcp_netid *netid)
return force;
}
/* Many UEFI PXE implementations have badly broken menu code.
If there's exactly one relevant menu item, we abandon the menu system,
and jamb the data direct into the DHCP file, siaddr and sname fields.
Note that in this case, we have to assume that layer zero would be requested
by the client PXE stack. */
static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dhcp_packet *mess, struct in_addr local, time_t now, int pxe)
{
struct pxe_service *service, *found;
/* Only workaround UEFI archs. */
if (pxe_arch < 6)
return 0;
for (found = NULL, service = daemon->pxe_services; service; service = service->next)
if (pxe_arch == service->CSA && service->basename && match_netid(service->netid, netid, 1))
{
if (found)
return 0; /* More than one relevant menu item */
found = service;
}
if (!found)
return 0; /* No relevant menu items. */
if (!pxe)
return 1;
if (found->sname)
{
mess->siaddr = a_record_from_hosts(found->sname, now);
snprintf((char *)mess->sname, sizeof(mess->sname), "%s", found->sname);
}
else
{
if (found->server.s_addr != 0)
mess->siaddr = found->server;
else
mess->siaddr = local;
inet_ntop(AF_INET, &mess->siaddr, (char *)mess->sname, INET_ADDRSTRLEN);
}
snprintf((char *)mess->file, sizeof(mess->file),
strchr(found->basename, '.') ? "%s" : "%s.0", found->basename);
return 1;
}
static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now)
{
#define NUM_OPTS 4
@@ -2137,7 +2234,9 @@ static void do_options(struct dhcp_context *context,
int null_term, int pxe_arch,
unsigned char *uuid,
int vendor_class_len,
time_t now)
time_t now,
unsigned int lease_time,
unsigned short fuzz)
{
struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
struct dhcp_boot *boot;
@@ -2261,7 +2360,42 @@ static void do_options(struct dhcp_context *context,
/* rfc3011 says this doesn't need to be in the requested options list. */
if (subnet_addr.s_addr)
option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
if (lease_time != 0xffffffff)
{
unsigned int t1val = lease_time/2;
unsigned int t2val = (lease_time*7)/8;
unsigned int hval;
/* If set by user, sanity check, so not longer than lease. */
if ((opt = option_find2(OPTION_T1)))
{
hval = ntohl(*((unsigned int *)opt->val));
if (hval < lease_time && hval > 2)
t1val = hval;
}
if ((opt = option_find2(OPTION_T2)))
{
hval = ntohl(*((unsigned int *)opt->val));
if (hval < lease_time && hval > 2)
t2val = hval;
}
/* ensure T1 is still < T2 */
if (t2val <= t1val)
t1val = t2val - 1;
while (fuzz > (t1val/8))
fuzz = fuzz/2;
t1val -= fuzz;
t2val -= fuzz;
option_put(mess, end, OPTION_T1, 4, t1val);
option_put(mess, end, OPTION_T2, 4, t2val);
}
/* replies to DHCPINFORM may not have a valid context */
if (context)
{
@@ -2356,12 +2490,14 @@ static void do_options(struct dhcp_context *context,
if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
continue;
/* prohibit some used-internally options */
/* prohibit some used-internally options. T1 and T2 already handled. */
if (optno == OPTION_CLIENT_FQDN ||
optno == OPTION_MAXMESSAGE ||
optno == OPTION_OVERLOAD ||
optno == OPTION_PAD ||
optno == OPTION_END)
optno == OPTION_END ||
optno == OPTION_T1 ||
optno == OPTION_T2)
continue;
if (optno == OPTION_SNAME && done_server)
@@ -2475,7 +2611,8 @@ static void do_options(struct dhcp_context *context,
if (context && pxe_arch != -1)
{
pxe_misc(mess, end, uuid);
config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
if (!pxe_uefi_workaround(pxe_arch, tagif, mess, context->local, now, 0))
config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
}
if ((force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT)) &&
@@ -2494,6 +2631,29 @@ static void do_options(struct dhcp_context *context,
}
}
static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid)
{
struct delay_config *delay_conf;
/* Decide which delay_config option we're using */
for (delay_conf = daemon->delay_conf; delay_conf; delay_conf = delay_conf->next)
if (match_netid(delay_conf->netid, netid, 0))
break;
if (!delay_conf)
/* No match, look for one without a netid */
for (delay_conf = daemon->delay_conf; delay_conf; delay_conf = delay_conf->next)
if (match_netid(delay_conf->netid, netid, 1))
break;
if (delay_conf)
{
if (!option_bool(OPT_QUIET_DHCP))
my_syslog(MS_DHCP | LOG_INFO, _("%u reply delay: %d"), ntohl(xid), delay_conf->delay);
delay_dhcp(recvtime, delay_conf->delay, -1, 0, 0);
}
}
#endif

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -89,7 +89,7 @@ unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *if
for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
vendor->netid.next = &vendor->netid;
save_counter(0);
reset_counter();
state.context = context;
state.interface = interface;
state.iface_name = iface_name;
@@ -118,7 +118,7 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
void *opt;
struct dhcp_vendor *vendor;
/* if not an encaplsulated relayed message, just do the stuff */
/* if not an encapsulated relayed message, just do the stuff */
if (msg_type != DHCP6RELAYFORW)
{
/* if link_address != NULL if points to the link address field of the
@@ -130,7 +130,7 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
MAC address from the local ND cache. */
if (!state->link_address)
get_client_mac(client_addr, state->interface, state->mac, &state->mac_len, &state->mac_type);
get_client_mac(client_addr, state->interface, state->mac, &state->mac_len, &state->mac_type, now);
else
{
struct dhcp_context *c;
@@ -262,7 +262,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
state->hostname_auth = 0;
state->hostname = NULL;
state->client_hostname = NULL;
state->fqdn_flags = 0x01; /* default to send if we recieve no FQDN option */
state->fqdn_flags = 0x01; /* default to send if we receive no FQDN option */
#ifdef OPTION6_PREFIX_CLASS
state->send_prefix_class = NULL;
#endif
@@ -313,8 +313,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
else if (msg_type != DHCP6IREQ)
return 0;
/* server-id must match except for SOLICIT and CONFIRM messages */
if (msg_type != DHCP6SOLICIT && msg_type != DHCP6CONFIRM && msg_type != DHCP6IREQ &&
/* server-id must match except for SOLICIT, CONFIRM and REBIND messages */
if (msg_type != DHCP6SOLICIT && msg_type != DHCP6CONFIRM && msg_type != DHCP6IREQ && msg_type != DHCP6REBIND &&
(!(opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1)) ||
opt6_len(opt) != daemon->duid_len ||
memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0))
@@ -328,6 +328,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
(msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE))
{
*outmsgtypep = DHCP6REPLY;
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6USEMULTI);
put_opt6_string("Use multicast");
@@ -380,7 +381,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
/* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
Otherwise assume the option is an array, and look for a matching element.
If no data given, existance of the option is enough. This code handles
If no data given, existence of the option is enough. This code handles
V-I opts too. */
for (opt_cfg = daemon->dhcp_match6; opt_cfg; opt_cfg = opt_cfg->next)
{
@@ -525,7 +526,14 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
if (have_config(config, CONFIG_DISABLE))
ignore = 1;
}
else if (state->clid &&
find_config(daemon->dhcp_conf, NULL, state->clid, state->clid_len, state->mac, state->mac_len, state->mac_type, NULL))
{
known_id.net = "known-othernet";
known_id.next = state->tags;
state->tags = &known_id;
}
#ifdef OPTION6_PREFIX_CLASS
/* OPTION_PREFIX_CLASS in ORO, send addresses in all prefix classes */
if (daemon->prefix_classes && (msg_type == DHCP6SOLICIT || msg_type == DHCP6REQUEST))
@@ -690,6 +698,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
#endif
o = build_ia(state, &t1cntr);
if (address_assigned)
address_assigned = 2;
for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
@@ -780,6 +790,27 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
address_assigned = 1;
}
if (address_assigned != 1)
{
/* If the server will not assign any addresses to any IAs in a
subsequent Request from the client, the server MUST send an Advertise
message to the client that doesn't include any IA options. */
if (!state->lease_allocate)
{
save_counter(o);
continue;
}
/* If the server cannot assign any addresses to an IA in the message
from the client, the server MUST include the IA in the Reply message
with no addresses in the IA and a Status Code option in the IA
containing status code NoAddrsAvail. */
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOADDRS);
put_opt6_string(_("address unavailable"));
end_opt6(o1);
}
end_ia(t1cntr, min_time, 0);
end_opt6(o);
}
@@ -805,7 +836,16 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
put_opt6_short(DHCP6NOADDRS);
put_opt6_string(_("no addresses available"));
end_opt6(o1);
log6_packet(state, "DHCPADVERTISE", NULL, _("no addresses available"));
/* Some clients will ask repeatedly when we're not giving
out addresses because we're in stateless mode. Avoid spamming
the log in that case. */
for (c = state->context; c; c = c->current)
if (!(c->flags & CONTEXT_RA_STATELESS))
{
log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", NULL, _("no addresses available"));
break;
}
}
break;
@@ -861,7 +901,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
{
/* Static range, not configured. */
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6UNSPEC);
put_opt6_short(DHCP6NOADDRS);
put_opt6_string(_("address unavailable"));
end_opt6(o1);
}
@@ -1014,9 +1054,9 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
{
preferred_time = valid_time = 0;
message = _("address invalid");
}
}
if (message)
if (message && (message != state->hostname))
log6_packet(state, "DHCPREPLY", req_addr, message);
else
log6_quiet(state, "DHCPREPLY", req_addr, message);
@@ -1039,6 +1079,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
case DHCP6CONFIRM:
{
int good_addr = 0;
/* set reply message type */
*outmsgtypep = DHCP6REPLY;
@@ -1054,7 +1096,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
{
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
if (!address6_available(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);
@@ -1063,9 +1105,14 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
return 1;
}
good_addr = 1;
log6_quiet(state, "DHCPREPLY", req_addr, state->hostname);
}
}
/* No addresses, no reply: RFC 3315 18.2.2 */
if (!good_addr)
return 0;
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6SUCCESS );
@@ -1232,6 +1279,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
}
/* We must answer with 'success' in global section anyway */
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6SUCCESS);
put_opt6_string(_("success"));
end_opt6(o1);
break;
}
@@ -1274,15 +1327,15 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
if (opt_cfg->opt == OPTION6_REFRESH_TIME)
done_refresh = 1;
if (opt_cfg->opt == OPTION6_DNS_SERVER)
done_dns = 1;
if (opt_cfg->flags & DHOPT_ADDR6)
{
int len, j;
struct in6_addr *a;
if (opt_cfg->opt == OPTION6_DNS_SERVER)
done_dns = 1;
for (a = (struct in6_addr *)opt_cfg->val, len = opt_cfg->len, j = 0;
j < opt_cfg->len; j += IN6ADDRSZ, a++)
if ((IN6_IS_ADDR_ULA_ZERO(a) && IN6_IS_ADDR_UNSPECIFIED(state->ula_addr)) ||
@@ -1341,7 +1394,7 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
unsigned int lease_time = 0xffffffff;
/* Find the smallest lease tie of all contexts,
subjext to the RFC-4242 stipulation that this must not
subject to the RFC-4242 stipulation that this must not
be less than 600. */
for (c = state->context; c; c = c->next)
if (c->lease_time < lease_time)
@@ -1929,7 +1982,7 @@ static void log6_packet(struct state *state, char *type, struct in6_addr *addr,
if (addr)
{
inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, 255);
inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, DHCP_BUFF_SZ - 1);
strcat(daemon->dhcp_buff2, " ");
}
else
@@ -2008,7 +2061,8 @@ static unsigned int opt6_uint(unsigned char *opt, int offset, int size)
return ret;
}
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, u32 scope_id)
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
struct in6_addr *peer_address, u32 scope_id, time_t now)
{
/* ->local is same value for all relays on ->current chain */
@@ -2022,7 +2076,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer
unsigned char mac[DHCP_CHADDR_MAX];
inet_pton(AF_INET6, ALL_SERVERS, &multicast);
get_client_mac(peer_address, scope_id, mac, &maclen, &mactype);
get_client_mac(peer_address, scope_id, mac, &maclen, &mactype, now);
/* source address == relay address */
from.addr.addr6 = relay->local.addr.addr6;
@@ -2037,7 +2091,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer
if (hopcount > 32)
return;
save_counter(0);
reset_counter();
if ((header = put_opt6(NULL, 34)))
{
@@ -2080,7 +2134,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer
my_syslog(MS_DHCP | LOG_ERR, _("Cannot multicast to DHCPv6 server without correct interface"));
}
send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(0), &to, &from, 0);
send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(-1), &to, &from, 0);
if (option_bool(OPT_LOG_OPTS))
{
@@ -2114,7 +2168,7 @@ unsigned short relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival
(!relay->interface || wildcard_match(relay->interface, arrival_interface)))
break;
save_counter(0);
reset_counter();
if (relay)
{

339
src/rrfilter.c Normal file
View File

@@ -0,0 +1,339 @@
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Code to safely remove RRs from an DNS answer */
#include "dnsmasq.h"
/* Go through a domain name, find "pointers" and fix them up based on how many bytes
we've chopped out of the packet, or check they don't point into an elided part. */
static int check_name(unsigned char **namep, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
{
unsigned char *ansp = *namep;
while(1)
{
unsigned int label_type;
if (!CHECK_LEN(header, ansp, plen, 1))
return 0;
label_type = (*ansp) & 0xc0;
if (label_type == 0xc0)
{
/* pointer for compression. */
unsigned int offset;
int i;
unsigned char *p;
if (!CHECK_LEN(header, ansp, plen, 2))
return 0;
offset = ((*ansp++) & 0x3f) << 8;
offset |= *ansp++;
p = offset + (unsigned char *)header;
for (i = 0; i < rr_count; i++)
if (p < rrs[i])
break;
else
if (i & 1)
offset -= rrs[i] - rrs[i-1];
/* does the pointer end up in an elided RR? */
if (i & 1)
return 0;
/* No, scale the pointer */
if (fixup)
{
ansp -= 2;
*ansp++ = (offset >> 8) | 0xc0;
*ansp++ = offset & 0xff;
}
break;
}
else if (label_type == 0x80)
return 0; /* reserved */
else if (label_type == 0x40)
{
/* Extended label type */
unsigned int count;
if (!CHECK_LEN(header, ansp, plen, 2))
return 0;
if (((*ansp++) & 0x3f) != 1)
return 0; /* we only understand bitstrings */
count = *(ansp++); /* Bits in bitstring */
if (count == 0) /* count == 0 means 256 bits */
ansp += 32;
else
ansp += ((count-1)>>3)+1;
}
else
{ /* label type == 0 Bottom six bits is length */
unsigned int len = (*ansp++) & 0x3f;
if (!ADD_RDLEN(header, ansp, plen, len))
return 0;
if (len == 0)
break; /* zero length label marks the end. */
}
}
*namep = ansp;
return 1;
}
/* Go through RRs and check or fixup the domain names contained within */
static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
{
int i, j, type, class, rdlen;
unsigned char *pp;
for (i = 0; i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount); i++)
{
pp = p;
if (!(p = skip_name(p, header, plen, 10)))
return 0;
GETSHORT(type, p);
GETSHORT(class, p);
p += 4; /* TTL */
GETSHORT(rdlen, p);
/* If this RR is to be elided, don't fix up its contents */
for (j = 0; j < rr_count; j += 2)
if (rrs[j] == pp)
break;
if (j >= rr_count)
{
/* fixup name of RR */
if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
return 0;
if (class == C_IN)
{
u16 *d;
for (pp = p, d = rrfilter_desc(type); *d != (u16)-1; d++)
{
if (*d != 0)
pp += *d;
else if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
return 0;
}
}
}
if (!ADD_RDLEN(header, p, plen, rdlen))
return 0;
}
return 1;
}
/* mode is 0 to remove EDNS0, 1 to filter DNSSEC RRs */
size_t rrfilter(struct dns_header *header, size_t plen, int mode)
{
static unsigned char **rrs;
static int rr_sz = 0;
unsigned char *p = (unsigned char *)(header+1);
int i, rdlen, qtype, qclass, rr_found, chop_an, chop_ns, chop_ar;
if (ntohs(header->qdcount) != 1 ||
!(p = skip_name(p, header, plen, 4)))
return plen;
GETSHORT(qtype, p);
GETSHORT(qclass, p);
/* First pass, find pointers to start and end of all the records we wish to elide:
records added for DNSSEC, unless explicitly queried for */
for (rr_found = 0, chop_ns = 0, chop_an = 0, chop_ar = 0, i = 0;
i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount);
i++)
{
unsigned char *pstart = p;
int type, class;
if (!(p = skip_name(p, header, plen, 10)))
return plen;
GETSHORT(type, p);
GETSHORT(class, p);
p += 4; /* TTL */
GETSHORT(rdlen, p);
if (!ADD_RDLEN(header, p, plen, rdlen))
return plen;
/* Don't remove the answer. */
if (i < ntohs(header->ancount) && type == qtype && class == qclass)
continue;
if (mode == 0) /* EDNS */
{
/* EDNS mode, remove T_OPT from additional section only */
if (i < (ntohs(header->nscount) + ntohs(header->ancount)) || type != T_OPT)
continue;
}
else if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
/* DNSSEC mode, remove SIGs and NSECs from all three sections. */
continue;
if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
return plen;
rrs[rr_found++] = pstart;
rrs[rr_found++] = p;
if (i < ntohs(header->ancount))
chop_an++;
else if (i < (ntohs(header->nscount) + ntohs(header->ancount)))
chop_ns++;
else
chop_ar++;
}
/* Nothing to do. */
if (rr_found == 0)
return plen;
/* Second pass, look for pointers in names in the records we're keeping and make sure they don't
point to records we're going to elide. This is theoretically possible, but unlikely. If
it happens, we give up and leave the answer unchanged. */
p = (unsigned char *)(header+1);
/* question first */
if (!check_name(&p, header, plen, 0, rrs, rr_found))
return plen;
p += 4; /* qclass, qtype */
/* Now answers and NS */
if (!check_rrs(p, header, plen, 0, rrs, rr_found))
return plen;
/* Third pass, actually fix up pointers in the records */
p = (unsigned char *)(header+1);
check_name(&p, header, plen, 1, rrs, rr_found);
p += 4; /* qclass, qtype */
check_rrs(p, header, plen, 1, rrs, rr_found);
/* Fouth pass, elide records */
for (p = rrs[0], i = 1; i < rr_found; i += 2)
{
unsigned char *start = rrs[i];
unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)header) + plen;
memmove(p, start, end-start);
p += end-start;
}
plen = p - (unsigned char *)header;
header->ancount = htons(ntohs(header->ancount) - chop_an);
header->nscount = htons(ntohs(header->nscount) - chop_ns);
header->arcount = htons(ntohs(header->arcount) - chop_ar);
return plen;
}
/* This is used in the DNSSEC code too, hence it's exported */
u16 *rrfilter_desc(int type)
{
/* List of RRtypes which include domains in the data.
0 -> domain
integer -> no of plain bytes
-1 -> end
zero is not a valid RRtype, so the final entry is returned for
anything which needs no mangling.
*/
static u16 rr_desc[] =
{
T_NS, 0, -1,
T_MD, 0, -1,
T_MF, 0, -1,
T_CNAME, 0, -1,
T_SOA, 0, 0, -1,
T_MB, 0, -1,
T_MG, 0, -1,
T_MR, 0, -1,
T_PTR, 0, -1,
T_MINFO, 0, 0, -1,
T_MX, 2, 0, -1,
T_RP, 0, 0, -1,
T_AFSDB, 2, 0, -1,
T_RT, 2, 0, -1,
T_SIG, 18, 0, -1,
T_PX, 2, 0, 0, -1,
T_NXT, 0, -1,
T_KX, 2, 0, -1,
T_SRV, 6, 0, -1,
T_DNAME, 0, -1,
0, -1 /* wildcard/catchall */
};
u16 *p = rr_desc;
while (*p != type && *p != 0)
while (*p++ != (u16)-1);
return p+1;
}
int expand_workspace(unsigned char ***wkspc, int *szp, int new)
{
unsigned char **p;
int old = *szp;
if (old >= new+1)
return 1;
if (new >= 100)
return 0;
new += 5;
if (!(p = whine_malloc(new * sizeof(unsigned char *))))
return 0;
if (old != 0 && *wkspc)
{
memcpy(p, *wkspc, old * sizeof(unsigned char *));
free(*wkspc);
}
*wkspc = p;
*szp = new;
return 1;
}

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -94,7 +94,7 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
slaac->backoff = 1;
slaac->addr = addr;
/* Do RA's to prod it */
ra_start_unsolicted(now, context);
ra_start_unsolicited(now, context);
}
if (slaac)
@@ -146,8 +146,11 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
struct ping_packet *ping;
struct sockaddr_in6 addr;
save_counter(0);
ping = expand(sizeof(struct ping_packet));
reset_counter();
if (!(ping = expand(sizeof(struct ping_packet))))
continue;
ping->type = ICMP6_ECHO_REQUEST;
ping->code = 0;
ping->identifier = ping_id;
@@ -161,7 +164,7 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
addr.sin6_port = htons(IPPROTO_ICMPV6);
addr.sin6_addr = slaac->addr;
if (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0,
if (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(-1), 0,
(struct sockaddr *)&addr, sizeof(addr)) == -1 &&
errno == EHOSTUNREACH)
slaac->ping_time = 0; /* Give up */

145
src/tables.c Normal file
View File

@@ -0,0 +1,145 @@
/* tables.c is Copyright (c) 2014 Sven Falempin All Rights Reserved.
Author's email: sfalempin@citypassenger.com
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"
#if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK)
#include <string.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <net/pfvar.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#define UNUSED(x) (void)(x)
static char *pf_device = "/dev/pf";
static int dev = -1;
static char *pfr_strerror(int errnum)
{
switch (errnum)
{
case ESRCH:
return "Table does not exist";
case ENOENT:
return "Anchor or Ruleset does not exist";
default:
return strerror(errnum);
}
}
void ipset_init(void)
{
dev = open( pf_device, O_RDWR);
if (dev == -1)
{
err(1, "%s", pf_device);
die (_("failed to access pf devices: %s"), NULL, EC_MISC);
}
}
int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
int flags, int remove)
{
struct pfr_addr addr;
struct pfioc_table io;
struct pfr_table table;
if (dev == -1)
{
my_syslog(LOG_ERR, _("warning: no opened pf devices %s"), pf_device);
return -1;
}
bzero(&table, sizeof(struct pfr_table));
table.pfrt_flags |= PFR_TFLAG_PERSIST;
if (strlen(setname) >= PF_TABLE_NAME_SIZE)
{
my_syslog(LOG_ERR, _("error: cannot use table name %s"), setname);
errno = ENAMETOOLONG;
return -1;
}
if (strlcpy(table.pfrt_name, setname,
sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name))
{
my_syslog(LOG_ERR, _("error: cannot strlcpy table name %s"), setname);
return -1;
}
bzero(&io, sizeof io);
io.pfrio_flags = 0;
io.pfrio_buffer = &table;
io.pfrio_esize = sizeof(table);
io.pfrio_size = 1;
if (ioctl(dev, DIOCRADDTABLES, &io))
{
my_syslog(LOG_WARNING, _("IPset: error:%s"), pfr_strerror(errno));
return -1;
}
table.pfrt_flags &= ~PFR_TFLAG_PERSIST;
if (io.pfrio_nadd)
my_syslog(LOG_INFO, _("info: table created"));
bzero(&addr, sizeof(addr));
#ifdef HAVE_IPV6
if (flags & F_IPV6)
{
addr.pfra_af = AF_INET6;
addr.pfra_net = 0x80;
memcpy(&(addr.pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
}
else
#endif
{
addr.pfra_af = AF_INET;
addr.pfra_net = 0x20;
addr.pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
}
bzero(&io, sizeof(io));
io.pfrio_flags = 0;
io.pfrio_table = table;
io.pfrio_buffer = &addr;
io.pfrio_esize = sizeof(addr);
io.pfrio_size = 1;
if (ioctl(dev, ( remove ? DIOCRDELADDRS : DIOCRADDADDRS ), &io))
{
my_syslog(LOG_WARNING, _("warning: DIOCR%sADDRS: %s"), ( remove ? "DEL" : "ADD" ), pfr_strerror(errno));
return -1;
}
my_syslog(LOG_INFO, _("%d addresses %s"),
io.pfrio_nadd, ( remove ? "removed" : "added" ));
return io.pfrio_nadd;
}
#endif

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2017 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
@@ -103,8 +103,10 @@ void tftp_request(struct listener *listen, time_t now)
if (listen->iface)
{
addr = listen->iface->addr;
mtu = listen->iface->mtu;
name = listen->iface->name;
mtu = listen->iface->mtu;
if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu)
mtu = daemon->tftp_mtu;
}
else
{
@@ -234,9 +236,17 @@ void tftp_request(struct listener *listen, time_t now)
strncpy(ifr.ifr_name, name, IF_NAMESIZE);
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
mtu = ifr.ifr_mtu;
{
mtu = ifr.ifr_mtu;
if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu)
mtu = daemon->tftp_mtu;
}
}
/* Failed to get interface mtu - can use configured value. */
if (mtu == 0)
mtu = daemon->tftp_mtu;
if (name)
{
/* check for per-interface prefix */
@@ -336,14 +346,15 @@ void tftp_request(struct listener *listen, time_t now)
{
if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
{
/* 32 bytes for IP, UDP and TFTP headers, 52 bytes for IPv6 */
int overhead = (listen->family == AF_INET) ? 32 : 52;
transfer->blocksize = atoi(opt);
if (transfer->blocksize < 1)
transfer->blocksize = 1;
if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
/* 32 bytes for IP, UDP and TFTP headers */
if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32)
transfer->blocksize = (unsigned)mtu - 32;
if (mtu != 0 && transfer->blocksize > (unsigned)mtu - overhead)
transfer->blocksize = (unsigned)mtu - overhead;
transfer->opt_blocksize = 1;
transfer->block = 0;
}
@@ -371,7 +382,7 @@ void tftp_request(struct listener *listen, time_t now)
if (prefix[strlen(prefix)-1] != '/')
strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
if (option_bool(OPT_TFTP_APREF))
if (option_bool(OPT_TFTP_APREF_IP))
{
size_t oldlen = strlen(daemon->namebuff);
struct stat statbuf;
@@ -383,7 +394,40 @@ void tftp_request(struct listener *listen, time_t now)
if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
daemon->namebuff[oldlen] = 0;
}
if (option_bool(OPT_TFTP_APREF_MAC))
{
unsigned char *macaddr = NULL;
unsigned char macbuf[DHCP_CHADDR_MAX];
#ifdef HAVE_DHCP
if (daemon->dhcp && peer.sa.sa_family == AF_INET)
{
/* Check if the client IP is in our lease database */
struct dhcp_lease *lease = lease_find_by_addr(peer.in.sin_addr);
if (lease && lease->hwaddr_type == ARPHRD_ETHER && lease->hwaddr_len == ETHER_ADDR_LEN)
macaddr = lease->hwaddr;
}
#endif
/* If no luck, try to find in ARP table. This only works if client is in same (V)LAN */
if (!macaddr && find_mac(&peer, macbuf, 1, now) > 0)
macaddr = macbuf;
if (macaddr)
{
size_t oldlen = strlen(daemon->namebuff);
struct stat statbuf;
snprintf(daemon->namebuff + oldlen, (MAXDNAME-1) - oldlen, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x/",
macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
/* remove unique-directory if it doesn't exist */
if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
daemon->namebuff[oldlen] = 0;
}
}
/* Absolute pathnames OK if they match prefix */
if (filename[0] == '/')
{
@@ -396,7 +440,7 @@ void tftp_request(struct listener *listen, time_t now)
else if (filename[0] == '/')
daemon->namebuff[0] = 0;
strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
/* check permissions and open file */
if ((transfer->file = check_tftp_fileperm(&len, prefix)))
{
@@ -459,7 +503,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
else if (option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid)
goto perm;
/* If we're doing many tranfers from the same file, only
/* If we're doing many transfers from the same file, only
open it once this saves lots of file descriptors
when mass-booting a big cluster, for instance.
Be conservative and only share when inode and name match
@@ -502,7 +546,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
return NULL;
}
void check_tftp_listeners(fd_set *rset, time_t now)
void check_tftp_listeners(time_t now)
{
struct tftp_transfer *transfer, *tmp, **up;
ssize_t len;
@@ -518,7 +562,7 @@ void check_tftp_listeners(fd_set *rset, time_t now)
prettyprint_addr(&transfer->peer, daemon->addrbuff);
if (FD_ISSET(transfer->sockfd, rset))
if (poll_check(transfer->sockfd, POLLIN))
{
/* we overwrote the buffer... */
daemon->srv_save = NULL;
@@ -641,20 +685,24 @@ static void sanitise(char *buf)
}
#define MAXMESSAGE 500 /* limit to make packet < 512 bytes and definitely smaller than buffer */
static ssize_t tftp_err(int err, char *packet, char *message, char *file)
{
struct errmess {
unsigned short op, err;
char message[];
} *mess = (struct errmess *)packet;
ssize_t ret = 4;
ssize_t len, ret = 4;
char *errstr = strerror(errno);
memset(packet, 0, daemon->packet_buff_sz);
sanitise(file);
mess->op = htons(OP_ERR);
mess->err = htons(err);
ret += (snprintf(mess->message, 500, message, file, errstr) + 1);
len = snprintf(mess->message, MAXMESSAGE, message, file, errstr);
ret += (len < MAXMESSAGE) ? len + 1 : MAXMESSAGE; /* include terminating zero */
my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message);
return ret;
@@ -670,6 +718,8 @@ static ssize_t tftp_err_oops(char *packet, char *file)
/* return -1 for error, zero for done. */
static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
{
memset(packet, 0, daemon->packet_buff_sz);
if (transfer->block == 0)
{
/* send OACK */

Some files were not shown because too many files have changed in this diff Show More