Compare commits

...

40 Commits

Author SHA1 Message Date
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
35 changed files with 641 additions and 238 deletions

5
.gitignore vendored
View File

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

View File

@@ -1,3 +1,64 @@
version 2.77
Generate an error when configured with a CNAME loop,
rather than a crash. Thanks to George Metz for
spotting this problem.
Calculate the length of TFTP error reply packet
correctly. This fixes a problem when the error
message in a TFTP packet exceeds the arbitrary
limit of 500 characters. The message was correctly
truncated, but not the packet length, so
extra data was appended. This is a possible
security risk, since the extra data comes from
a buffer which is also used for DNS, so that
previous DNS queries or replies may be leaked.
Thanks to Mozilla for funding the security audit
which spotted this bug.
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.
Thanks to Ivan Kokshaysky for the diagnosis and
patch.
Fix problem with --dnssec-timestamp whereby receipt
of SIGHUP would erroneously engage timestamp checking.
Thanks to Kevin Darbyshire-Bryant for this work.
Bump zone serial on reloading /etc/hosts and friends
when providing authoritative DNS. Thanks to Harrald
Dunkel for spotting this.
Handle v4-mapped IPv6 addresses sanely in --synth-domain.
These have standard representation like ::ffff:1.2.3.4
and are now converted to names like
<prefix>--ffff-1-2-3-4.<domain>
Handle binding upstream servers to an interface
(--server=1.2.3.4@eth0) when the named interface
is destroyed and recreated in the kernel. Thanks to
Beniamino Galvani for the patch.
Allow wildcard CNAME records in authoritative zones.
For example --cname=*.example.com,default.example.com
Thanks to Pro Backup for sponsoring this development.
Bump the allowed backlog of TCP connections from 5 to 32,
and make this a compile-time configurable option. Thanks
to Donatas Abraitis for diagnosing this as a potential
problem.
Add DNSMASQ_REQUESTED_OPTIONS environment variable to the
lease-change script. Thanks to ZHAO Yu for the patch.
Fix foobar in rrfilter code, that could cause misformed
replies, especially when DNSSEC validation on, and
the upstream server returns answer with the RRs in a
particular order. The only DNS server known to tickle
this is Nominum's. Thanks to Dave Täht for spotting the
bug and assisting in the fix.
version 2.76
Include 0.0.0.0/8 in DNS rebind checks. This range
translates to hosts on the local network, or, at

59
debian/changelog vendored
View File

@@ -1,3 +1,62 @@
dnsmasq (2.77-1) unstable; urgency=low
* New upstream.
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 14 Dec 2016 18:01:40 +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)

2
debian/init vendored
View File

@@ -33,7 +33,7 @@ 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 -d /usr/share/doc/dnsmasq || exit 0
test -e /usr/share/dnsmasq/installed-marker || exit 0
test -x $DAEMON || exit 0

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.

25
debian/rules vendored
View File

@@ -24,8 +24,21 @@ DEB_COPTS = $(COPTS)
TARGET = install-i18n
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)))
PACKAGE_VERSION = $(shell bld/get-version `pwd` | sed 's/test/~&/; s/[a-z]/~&/; s/-/./g; s/$$/-1/; s/^/-v/';)
@@ -105,6 +118,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
@@ -113,6 +127,7 @@ 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
@@ -136,7 +151,7 @@ binary-arch: checkroot
-d debian/base/usr/share/doc/$(package)/examples \
-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)))
# 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
@@ -168,7 +183,7 @@ endif
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' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
dpkg-shlibdeps --warnings=1 debian/base/usr/sbin/dnsmasq
@@ -184,7 +199,7 @@ ifeq ($(DEB_HOST_ARCH_OS),linux)
-d debian/utils/usr/share/man/man1 \
-d debian/utils/usr/bin \
-d debian/utils/usr/share/doc/dnsmasq-utils
make -C contrib/lease-tools PREFIX=/usr DESTDIR=`pwd`/debian/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=gcc
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
@@ -198,8 +213,8 @@ ifeq ($(DEB_HOST_ARCH_OS),linux)
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_lease_time
endif
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

1
debian/shlibs.local vendored Normal file
View File

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

View File

@@ -1,6 +1,9 @@
[Unit]
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=forking

View File

@@ -242,7 +242,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.
@@ -480,28 +480,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. As for --server,
one or more domains with no address returns a no-such-domain answer, so
--address=/example.com/ is equivalent to --server=/example.com/ and returns
NXDOMAIN for example.com and all its subdomains.
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
@@ -573,7 +581,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>[,<TTL>]
.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
@@ -581,7 +589,9 @@ 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
@@ -619,6 +629,8 @@ 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
@@ -739,7 +751,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.
@@ -756,6 +768,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.
@@ -1037,6 +1053,10 @@ is given, then read all the files contained in that directory. The advantage of
using this option is the same as for --dhcp-hostsfile: the
dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that
it is possible to encode the information in a
.B --dhcp-boot
flag as DHCP options, using the options names bootfile-name,
server-ip-address and tftp-server. This allows these to be included
in a dhcp-optsfile.
.TP
.B --dhcp-hostsdir=<path>
This is equivalent to dhcp-hostsfile, except for the following. The path MUST be a
@@ -1048,11 +1068,6 @@ 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 --dhcp-boot
flag as DHCP options, using the options names bootfile-name,
server-ip-address and tftp-server. This allows these to be included
in a dhcp-optsfile.
.TP
.B \-Z, --read-ethers
Read /etc/ethers for information about hosts for the DHCP server. The
@@ -1528,6 +1543,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,
@@ -2193,7 +2210,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

View File

@@ -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(~(in_addr_t)0 << (32 - subnet->prefixlen));
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;
@@ -99,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;
@@ -115,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;
@@ -389,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;
@@ -514,7 +519,60 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
if (!found)
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
{
/* 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);
}
}

View File

@@ -774,7 +774,8 @@ 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;
@@ -1056,7 +1057,8 @@ 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;
@@ -1177,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;
@@ -1290,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;
@@ -1385,6 +1389,7 @@ 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. */

View File

@@ -18,6 +18,7 @@
#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 SAFE_PKTSZ 1280 /* "go anywhere" UDP packet size */
#define KEYBLOCK_LEN 40 /* choose to mininise fragmentation when storing DNSSEC keys */
@@ -120,6 +121,8 @@ HAVE_LOOP
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
@@ -434,6 +437,9 @@ static char *compile_opts =
"no-"
#endif
"DNSSEC "
#ifdef NO_ID
"no-ID "
#endif
#ifndef HAVE_LOOP
"no-"
#endif

View File

@@ -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,
@@ -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

@@ -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

@@ -280,7 +280,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;
}

View File

@@ -714,10 +714,16 @@ int main (int argc, char **argv)
if (daemon->port == 0)
my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
else if (daemon->cachesize != 0)
my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
else
my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
else
{
if (daemon->cachesize != 0)
my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
else
my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
if (option_bool(OPT_LOCAL_SERVICE))
my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
}
my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
@@ -731,9 +737,6 @@ int main (int argc, char **argv)
}
#endif
if (option_bool(OPT_LOCAL_SERVICE))
my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
{
@@ -750,7 +753,8 @@ int main (int argc, char **argv)
my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
if (option_bool(OPT_DNSSEC_TIME))
daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
if (rc == 1)
@@ -1225,11 +1229,13 @@ static void async_event(int pipe, time_t now)
switch (ev.event)
{
case EVENT_RELOAD:
daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
{
my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
reset_option_bool(OPT_DNSSEC_TIME);
daemon->dnssec_no_time_check = 0;
}
#endif
/* fall through */

View File

@@ -286,6 +286,7 @@ struct naptr {
struct naptr *next;
};
#ifndef NO_ID
#define TXT_STAT_CACHESIZE 1
#define TXT_STAT_INSERTS 2
#define TXT_STAT_EVICTIONS 3
@@ -293,6 +294,7 @@ struct naptr {
#define TXT_STAT_HITS 5
#define TXT_STAT_AUTH 6
#define TXT_STAT_SERVERS 7
#endif
struct txt_record {
char *name;
@@ -308,9 +310,9 @@ struct ptr_record {
};
struct cname {
int ttl;
int ttl, flag;
char *alias, *target;
struct cname *next;
struct cname *next, *targetp;
};
struct ds_config {
@@ -340,6 +342,7 @@ struct auth_zone {
struct auth_name_list *next;
} *interface_names;
struct addrlist *subnet;
struct addrlist *exclude;
struct auth_zone *next;
};
@@ -487,6 +490,7 @@ struct serverfd {
int fd;
union mysockaddr source_addr;
char interface[IF_NAMESIZE+1];
unsigned int ifindex, used;
struct serverfd *next;
};
@@ -992,6 +996,7 @@ 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
@@ -1078,7 +1083,9 @@ 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);
@@ -1470,6 +1477,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);

View File

@@ -522,15 +522,16 @@ static int check_date_range(u32 date_start, u32 date_end)
if (utime(daemon->timestamp_file, NULL) != 0)
my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
my_syslog(LOG_INFO, _("system time considered valid, now checking DNSSEC signature timestamps."));
daemon->back_to_the_future = 1;
set_option_bool(OPT_DNSSEC_TIME);
daemon->dnssec_no_time_check = 0;
queue_event(EVENT_RELOAD); /* purge cache */
}
if (daemon->back_to_the_future == 0)
return 1;
}
else if (option_bool(OPT_DNSSEC_TIME))
else if (daemon->dnssec_no_time_check)
return 1;
/* We must explicitly check against wanted values, because of SERIAL_UNDEF */

View File

@@ -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);

View File

@@ -556,6 +556,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);

View File

@@ -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

@@ -65,7 +65,14 @@ void lease_init(time_t now)
}
/* client-id max length is 255 which is 255*2 digits + 254 colons
borrow DNS packet buffer which is always larger than 1000 bytes */
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 leasfile parsing.
#endif
if (leasestream)
while (fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2) == 2)
{

View File

@@ -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() */
@@ -188,11 +188,17 @@ 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 */
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)
return callback_ok;
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)

View File

@@ -746,7 +746,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)
@@ -1204,6 +1204,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
@@ -1224,11 +1225,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. */
@@ -1250,11 +1255,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;
}
@@ -1429,12 +1436,16 @@ void check_servers(void)
{
struct irec *iface;
struct server *serv;
struct serverfd *sfd, *tmp, **up;
int port = 0, count;
/* interface may be new since startup */
if (!option_bool(OPT_NOWILD))
enumerate_interfaces(0);
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. */
@@ -1505,6 +1516,9 @@ void check_servers(void)
serv->flags |= SERV_MARK;
continue;
}
if (serv->sfd)
serv->sfd->used = 1;
}
if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
@@ -1547,6 +1561,20 @@ void check_servers(void)
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();
}

View File

@@ -452,7 +452,7 @@ static struct {
{ LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
{ LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
{ LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
{ LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<interface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL},
{ LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<iface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL},
{ LOPT_CNAME, ARG_DUP, "<alias>,<target>[,<ttl>]", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
{ LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
{ LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
@@ -475,7 +475,7 @@ static struct {
{ LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
{ LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
{ LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
{ LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
{ LOPT_IPSET, ARG_DUP, "/<domain>[/<domain>...]/<ipset>...", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
{ LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
{ LOPT_SEC_VALID, OPT_DNSSEC_VALID, NULL, gettext_noop("Activate DNSSEC validation"), NULL },
{ LOPT_TRUST_ANCHOR, ARG_DUP, "<domain>,[<class>],...", gettext_noop("Specify trust anchor key digest."), NULL },
@@ -486,7 +486,7 @@ static struct {
#ifdef OPTION6_PREFIX_CLASS
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
#endif
{ LOPT_RA_PARAM, ARG_DUP, "<interface>,[high,|low,]<interval>[,<lifetime>]", gettext_noop("Set priority, resend-interval and router-lifetime"), NULL },
{ LOPT_RA_PARAM, ARG_DUP, "<iface>,[<prio>,]<intval>[,<lifetime>]", gettext_noop("Set priority, resend-interval and router-lifetime"), NULL },
{ LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log routine DHCP."), NULL },
{ LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log routine DHCPv6."), NULL },
{ LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
@@ -657,7 +657,8 @@ static int atoi_check8(char *a, int *res)
return 1;
}
#endif
#ifndef NO_ID
static void add_txt(char *name, char *txt, int stat)
{
struct txt_record *r = opt_malloc(sizeof(struct txt_record));
@@ -670,13 +671,14 @@ static void add_txt(char *name, char *txt, int stat)
*(r->txt) = len;
memcpy((r->txt)+1, txt, len);
}
r->stat = stat;
r->name = opt_string_alloc(name);
r->next = daemon->txt;
daemon->txt = r;
r->class = C_CHAOS;
}
#endif
static void do_usage(void)
{
@@ -721,7 +723,7 @@ static void do_usage(void)
sprintf(buff, " ");
sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
printf("%-40.40s", buff);
printf("%-55.55s", buff);
if (usage[i].arg)
{
@@ -1906,6 +1908,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new = opt_malloc(sizeof(struct auth_zone));
new->domain = opt_string_alloc(arg);
new->subnet = NULL;
new->exclude = NULL;
new->interface_names = NULL;
new->next = daemon->auth_zones;
daemon->auth_zones = new;
@@ -1913,6 +1916,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
while ((arg = comma))
{
int prefixlen = 0;
int is_exclude = 0;
char *prefix;
struct addrlist *subnet = NULL;
struct all_addr addr;
@@ -1923,6 +1927,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (prefix && !atoi_check(prefix, &prefixlen))
ret_err(gen_err);
if (strstr(arg, "exclude:") == arg)
{
is_exclude = 1;
arg = arg+8;
}
if (inet_pton(AF_INET, arg, &addr.addr.addr4))
{
subnet = opt_malloc(sizeof(struct addrlist));
@@ -1960,8 +1970,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (subnet)
{
subnet->addr = addr;
subnet->next = new->subnet;
new->subnet = subnet;
if (is_exclude)
{
subnet->next = new->exclude;
new->exclude = subnet;
}
else
{
subnet->next = new->subnet;
new->subnet = subnet;
}
}
}
break;
@@ -3711,22 +3730,27 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case LOPT_CNAME: /* --cname */
{
struct cname *new;
char *alias, *target, *ttls;
char *alias, *target, *last, *pen;
int ttl = -1;
if (!(comma = split(arg)))
ret_err(gen_err);
if ((ttls = split(comma)) && !atoi_check(ttls, &ttl))
ret_err(_("bad TTL"));
alias = canonicalise_opt(arg);
target = canonicalise_opt(comma);
if (!alias || !target)
ret_err(_("bad CNAME"));
else
for (last = pen = NULL, comma = arg; comma; comma = split(comma))
{
pen = last;
last = comma;
}
if (!pen)
ret_err(_("bad CNAME"));
if (pen != arg && atoi_check(last, &ttl))
last = pen;
target = canonicalise_opt(last);
while (arg != last)
{
alias = canonicalise_opt(arg);
for (new = daemon->cnames; new; new = new->next)
if (hostname_isequal(new->alias, arg))
ret_err(_("duplicate CNAME"));
@@ -3736,6 +3760,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->alias = alias;
new->target = target;
new->ttl = ttl;
arg += strlen(arg)+1;
}
break;
@@ -4515,6 +4541,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
daemon->soa_expiry = SOA_EXPIRY;
daemon->max_port = MAX_PORT;
#ifndef NO_ID
add_txt("version.bind", "dnsmasq-" VERSION, 0 );
add_txt("authors.bind", "Simon Kelley", 0);
add_txt("copyright.bind", COPYRIGHT, 0);
@@ -4527,6 +4554,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
add_txt("auth.bind", NULL, TXT_STAT_AUTH);
#endif
add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
#endif
while (1)
{
@@ -4635,11 +4663,44 @@ void read_opts(int argc, char **argv, char *compile_opts)
if (daemon->cnames)
{
struct cname *cn;
struct cname *cn, *cn2, *cn3;
#define NOLOOP 1
#define TESTLOOP 2
/* Fill in TTL for CNAMES noe we have local_ttl.
Also prepare to do loop detection. */
for (cn = daemon->cnames; cn; cn = cn->next)
if (cn->ttl == -1)
cn->ttl = daemon->local_ttl;
{
if (cn->ttl == -1)
cn->ttl = daemon->local_ttl;
cn->flag = 0;
cn->targetp = NULL;
for (cn2 = daemon->cnames; cn2; cn2 = cn2->next)
if (hostname_isequal(cn->target, cn2->alias))
{
cn->targetp = cn2;
break;
}
}
/* Find any CNAME loops.*/
for (cn = daemon->cnames; cn; cn = cn->next)
{
for (cn2 = cn->targetp; cn2; cn2 = cn2->targetp)
{
if (cn2->flag == NOLOOP)
break;
if (cn2->flag == TESTLOOP)
die(_("CNAME loop involving %s"), cn->alias, EC_BADCONF);
cn2->flag = TESTLOOP;
}
for (cn3 = cn->targetp; cn3 != cn2; cn3 = cn3->targetp)
cn3->flag = NOLOOP;
}
}
if (daemon->if_addrs)

View File

@@ -29,9 +29,19 @@ void end_opt6(int container)
PUTSHORT(len, p);
}
void reset_counter(void)
{
/* Clear out buffer when starting from begining */
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;

View File

@@ -261,8 +261,10 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
parm.adv_interval = calc_interval(ra_param);
parm.prio = calc_prio(ra_param);
save_counter(0);
ra = expand(sizeof(struct ra_packet));
reset_counter();
if (!(ra = expand(sizeof(struct ra_packet))))
return;
ra->type = ND_ROUTER_ADVERT;
ra->code = 0;
@@ -526,7 +528,7 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
}
while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,
save_counter(0), 0, (struct sockaddr *)&addr,
save_counter(-1), 0, (struct sockaddr *)&addr,
sizeof(addr))));
}

View File

@@ -1209,6 +1209,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
struct mx_srv_record *rec;
size_t len;
/* Clear buffer beyond request to avoid risk of
information disclosure. */
memset(((char *)header) + qlen, 0,
(limit - ((char *)header)) - qlen);
if (ntohs(header->ancount) != 0 ||
ntohs(header->nscount) != 0 ||
@@ -1264,6 +1269,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
unsigned long ttl = daemon->local_ttl;
int ok = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
#ifndef NO_ID
/* Dynamically generate stat record */
if (t->stat != 0)
{
@@ -1271,7 +1277,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if (!cache_make_stat(t))
ok = 0;
}
#endif
if (ok && add_resource_record(header, limit, &trunc, nameoffset, &ansp,
ttl, NULL,
T_TXT, t->class, "t", t->len, t->txt))

View File

@@ -186,7 +186,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;
@@ -1303,6 +1304,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);
@@ -1606,7 +1625,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;

View File

@@ -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;
@@ -1975,7 +1975,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
@@ -2084,7 +2084,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
if (hopcount > 32)
return;
save_counter(0);
reset_counter();
if ((header = put_opt6(NULL, 34)))
{
@@ -2127,7 +2127,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
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))
{
@@ -2161,7 +2161,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)
{

View File

@@ -239,7 +239,15 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode)
if (!check_rrs(p, header, plen, 0, rrs, rr_found))
return plen;
/* Third pass, elide records */
/* 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];
@@ -254,14 +262,6 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode)
header->nscount = htons(ntohs(header->nscount) - chop_ns);
header->arcount = htons(ntohs(header->arcount) - chop_ar);
/* Fourth pass, fix up pointers in the remaining 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);
return plen;
}

View File

@@ -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 */

View File

@@ -53,52 +53,6 @@ static char *pfr_strerror(int errnum)
}
}
static int pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
{
struct pfioc_table io;
if (size < 0 || (size && tbl == NULL))
{
errno = EINVAL;
return (-1);
}
bzero(&io, sizeof io);
io.pfrio_flags = flags;
io.pfrio_buffer = tbl;
io.pfrio_esize = sizeof(*tbl);
io.pfrio_size = size;
if (ioctl(dev, DIOCRADDTABLES, &io))
return (-1);
if (nadd != NULL)
*nadd = io.pfrio_nadd;
return (0);
}
static int fill_addr(const struct all_addr *ipaddr, int flags, struct pfr_addr* addr) {
if ( !addr || !ipaddr)
{
my_syslog(LOG_ERR, _("error: fill_addr missused"));
return -1;
}
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;
}
return 1;
}
/*****************************************************************************/
void ipset_init(void)
{
@@ -111,14 +65,13 @@ void ipset_init(void)
}
int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
int flags, int remove)
int flags, int remove)
{
struct pfr_addr addr;
struct pfioc_table io;
struct pfr_table table;
int n = 0, rc = 0;
if ( dev == -1 )
if (dev == -1)
{
my_syslog(LOG_ERR, _("warning: no opened pf devices %s"), pf_device);
return -1;
@@ -126,31 +79,52 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
bzero(&table, sizeof(struct pfr_table));
table.pfrt_flags |= PFR_TFLAG_PERSIST;
if ( strlen(setname) >= PF_TABLE_NAME_SIZE )
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))
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;
}
if ((rc = pfr_add_tables(&table, 1, &n, 0)))
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, _("warning: pfr_add_tables: %s(%d)"),
pfr_strerror(errno),rc);
my_syslog(LOG_WARNING, _("IPset: error:%s"), pfr_strerror(errno));
return -1;
}
table.pfrt_flags &= ~PFR_TFLAG_PERSIST;
if (n)
my_syslog(LOG_INFO, _("info: table created"));
fill_addr(ipaddr,flags,&addr);
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;

View File

@@ -652,20 +652,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;
@@ -681,6 +685,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 */

View File

@@ -244,11 +244,11 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
/* for use during startup */
void *safe_malloc(size_t size)
{
void *ret = malloc(size);
void *ret = calloc(1, size);
if (!ret)
die(_("could not get memory"), NULL, EC_NOMEM);
return ret;
}
@@ -262,11 +262,11 @@ void safe_pipe(int *fd, int read_noblock)
void *whine_malloc(size_t size)
{
void *ret = malloc(size);
void *ret = calloc(1, size);
if (!ret)
my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);
return ret;
}
@@ -323,7 +323,7 @@ int hostname_isequal(const char *a, const char *b)
return 1;
}
time_t dnsmasq_time(void)
{
#ifdef HAVE_BROKEN_RTC
@@ -497,6 +497,10 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
sav = in[(j+1)*2];
in[(j+1)*2] = 0;
}
/* checks above allow mix of hexdigit and *, which
is illegal. */
if (strchr(&in[j*2], '*'))
return -1;
out[i] = strtol(&in[j*2], NULL, 16);
mask = mask << 1;
i++;