mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-06 15:51:41 +00:00
Compare commits
66
Commits
v2.79test1
...
v2.79
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94b6878821 | ||
|
|
8b96552f0d | ||
|
|
ae290659de | ||
|
|
6b2b564ac3 | ||
|
|
4f7bb57e97 | ||
|
|
56f0623930 | ||
|
|
f3223fbff6 | ||
|
|
4c4f4c2649 | ||
|
|
773af304ea | ||
|
|
4cc944b0d6 | ||
|
|
87e00feb01 | ||
|
|
e7a4af8903 | ||
|
|
2d69d6146d | ||
|
|
30e4a9441e | ||
|
|
232a8f3569 | ||
|
|
1721453d51 | ||
|
|
499d8dde2b | ||
|
|
6f1cbfd000 | ||
|
|
55ecde7f1b | ||
|
|
6b54d69a85 | ||
|
|
246a31cd73 | ||
|
|
83e4b73596 | ||
|
|
6340ca734f | ||
|
|
baf553db0c | ||
|
|
486bcd5a7b | ||
|
|
be9a74d2f8 | ||
|
|
ffcbc0f011 | ||
|
|
a969ba6e2a | ||
|
|
f1781728af | ||
|
|
cd7df612b1 | ||
|
|
c1a4e257a3 | ||
|
|
4fe6744a22 | ||
|
|
3bd4c47f31 | ||
|
|
98196c4931 | ||
|
|
22cd860124 | ||
|
|
3c973ad92d | ||
|
|
faaf306a63 | ||
|
|
c7e6aea81b | ||
|
|
e541245987 | ||
|
|
84a01bee10 | ||
|
|
d1ced3ae38 | ||
|
|
a6cee69af4 | ||
|
|
0039920ab6 | ||
|
|
39d8550a80 | ||
|
|
ef3d137a64 | ||
|
|
8c707e1e37 | ||
|
|
373e917389 | ||
|
|
74f0f9a042 | ||
|
|
ed6bdb0967 | ||
|
|
c88af046b7 | ||
|
|
ae0187d454 | ||
|
|
0c50e3ddc8 | ||
|
|
075366ad6e | ||
|
|
8e8b2d6f63 | ||
|
|
087eb76140 | ||
|
|
ebedcbaeb8 | ||
|
|
0954a977c9 | ||
|
|
b77efc1948 | ||
|
|
3b0cb34710 | ||
|
|
aa6f832d61 | ||
|
|
ad9c6f06c5 | ||
|
|
a6004d7f17 | ||
|
|
c366717e66 | ||
|
|
22dee512f3 | ||
|
|
6fd5d79e73 | ||
|
|
9d6918d32c |
No files matched your search
+2
-3
@@ -7,9 +7,8 @@ src/.copts_*
|
|||||||
contrib/lease-tools/dhcp_lease_time
|
contrib/lease-tools/dhcp_lease_time
|
||||||
contrib/lease-tools/dhcp_release
|
contrib/lease-tools/dhcp_release
|
||||||
contrib/lease-tools/dhcp_release6
|
contrib/lease-tools/dhcp_release6
|
||||||
debian/base/
|
|
||||||
debian/daemon/
|
|
||||||
debian/files
|
debian/files
|
||||||
debian/substvars
|
debian/substvars
|
||||||
debian/utils-substvars
|
debian/utils-substvars
|
||||||
debian/utils/
|
debian/trees/
|
||||||
|
debian/build/
|
||||||
@@ -2,6 +2,67 @@ version 2.79
|
|||||||
Fix parsing of CNAME arguments, which are confused by extra spaces.
|
Fix parsing of CNAME arguments, which are confused by extra spaces.
|
||||||
Thanks to Diego Aguirre for spotting the bug.
|
Thanks to Diego Aguirre for spotting the bug.
|
||||||
|
|
||||||
|
Where available, use IP_UNICAST_IF or IPV6_UNICAST_IF to bind
|
||||||
|
upstream servers to an interface, rather than SO_BINDTODEVICE.
|
||||||
|
Thanks to Beniamino Galvani for the patch.
|
||||||
|
|
||||||
|
Always return a SERVFAIL answer to DNS queries without the
|
||||||
|
recursion desired bit set, UNLESS acting as an authoritative
|
||||||
|
DNS server. This avoids a potential route to cache snooping.
|
||||||
|
|
||||||
|
Add support for Ed25519 signatures in DNSSEC validation.
|
||||||
|
|
||||||
|
No longer support RSA/MD5 signatures in DNSSEC validation,
|
||||||
|
since these are not secure. This behaviour is mandated in
|
||||||
|
RFC-6944.
|
||||||
|
|
||||||
|
Fix incorrect error exit code from dhcp_release6 utility.
|
||||||
|
Thanks Gaudenz Steinlin for the bug report.
|
||||||
|
|
||||||
|
Use SIGINT (instead of overloading SIGHUP) to turn on DNSSEC
|
||||||
|
time validation when --dnssec-no-timecheck is in use.
|
||||||
|
Note that this is an incompatible change from earlier releases.
|
||||||
|
|
||||||
|
Allow more than one --bridge-interface option to refer to an
|
||||||
|
interface, so that we can use
|
||||||
|
--bridge-interface=int1,alias1
|
||||||
|
--bridge-interface=int1,alias2
|
||||||
|
as an alternative to
|
||||||
|
--bridge-interface=int1,alias1,alias2
|
||||||
|
Thanks to Neil Jerram for work on this.
|
||||||
|
|
||||||
|
Fix for DNSSEC with wildcard-derived NSEC records.
|
||||||
|
It's OK for NSEC records to be expanded from wildcards,
|
||||||
|
but in that case, the proof of non-existence is only valid
|
||||||
|
starting at the wildcard name, *.<domain> NOT the name expanded
|
||||||
|
from the wildcard. Without this check it's possible for an
|
||||||
|
attacker to craft an NSEC which wrongly proves non-existence.
|
||||||
|
Thanks to Ralph Dolmans for finding this, and co-ordinating
|
||||||
|
the vulnerability tracking and fix release.
|
||||||
|
CVE-2017-15107 applies.
|
||||||
|
|
||||||
|
Remove special handling of A-for-A DNS queries. These
|
||||||
|
are no longer a significant problem in the global DNS.
|
||||||
|
http://cs.northwestern.edu/~ychen/Papers/DNS_ToN15.pdf
|
||||||
|
Thanks to Mattias Hellström for the initial patch.
|
||||||
|
|
||||||
|
Fix failure to delete dynamically created dhcp options
|
||||||
|
from files in -dhcp-optsdir directories. Thanks to
|
||||||
|
Lindgren Fredrik for the bug report.
|
||||||
|
|
||||||
|
Add to --synth-domain the ability to create names using
|
||||||
|
sequential numbers, as well as encodings of IP addresses.
|
||||||
|
For instance,
|
||||||
|
--synth-domain=thekelleys.org.uk,192.168.0.50,192.168.0.70,internal-*
|
||||||
|
creates 21 domain names of the form
|
||||||
|
internal-4.thekelleys.org.uk over the address range given, with
|
||||||
|
internal-0.thekelleys.org.uk being 192.168.0.50 and
|
||||||
|
internal-20.thekelleys.org.uk being 192.168.0.70
|
||||||
|
Thanks to Andy Hawkins for the suggestion.
|
||||||
|
|
||||||
|
Tidy up Crypto code, removing workarounds for ancient
|
||||||
|
versions of libnettle. We now require libnettle 3.
|
||||||
|
|
||||||
|
|
||||||
version 2.78
|
version 2.78
|
||||||
Fix logic of appending ".<layer>" to PXE basename. Thanks to Chris
|
Fix logic of appending ".<layer>" to PXE basename. Thanks to Chris
|
||||||
@@ -1531,7 +1592,7 @@ version 2.56
|
|||||||
|
|
||||||
By default, setting an IPv4 address for a domain but not
|
By default, setting an IPv4 address for a domain but not
|
||||||
an IPv6 address causes dnsmasq to return
|
an IPv6 address causes dnsmasq to return
|
||||||
an NODATA reply for IPv6 (or vice-versa). So
|
a NODATA reply for IPv6 (or vice-versa). So
|
||||||
--address=/google.com/1.2.3.4 stops IPv6 queries for
|
--address=/google.com/1.2.3.4 stops IPv6 queries for
|
||||||
*google.com from being forwarded. Make it possible to
|
*google.com from being forwarded. Make it possible to
|
||||||
override this behaviour by defining the semantics if the
|
override this behaviour by defining the semantics if the
|
||||||
@@ -2037,13 +2098,13 @@ version 2.47
|
|||||||
|
|
||||||
Support arbitrarily encapsulated DHCP options, suggestion
|
Support arbitrarily encapsulated DHCP options, suggestion
|
||||||
and initial patch from Samium Gromoff. This is useful for
|
and initial patch from Samium Gromoff. This is useful for
|
||||||
(eg) gPXE, which expect all its private options to be
|
(eg) iPXE, which expect all its private options to be
|
||||||
encapsulated inside a single option 175. So, eg,
|
encapsulated inside a single option 175. So, eg,
|
||||||
|
|
||||||
dhcp-option = encap:175, 190, "iscsi-client0"
|
dhcp-option = encap:175, 190, "iscsi-client0"
|
||||||
dhcp-option = encap:175, 191, "iscsi-client0-secret"
|
dhcp-option = encap:175, 191, "iscsi-client0-secret"
|
||||||
|
|
||||||
will provide iSCSI parameters to gPXE.
|
will provide iSCSI parameters to iPXE.
|
||||||
|
|
||||||
Enhance --dhcp-match to allow testing of the contents of a
|
Enhance --dhcp-match to allow testing of the contents of a
|
||||||
client-sent option, as well as its presence. This
|
client-sent option, as well as its presence. This
|
||||||
|
|||||||
+4
-4
@@ -1010,7 +1010,7 @@ release 2.9
|
|||||||
but to the address of another interface were ignored
|
but to the address of another interface were ignored
|
||||||
unless the loopback interface was explicitly configured.
|
unless the loopback interface was explicitly configured.
|
||||||
2) on OpenBSD failure to configure one interface now
|
2) on OpenBSD failure to configure one interface now
|
||||||
causes a fatal error on startup rather than an huge
|
causes a fatal error on startup rather than a huge
|
||||||
stream of log messages. Thanks to Erik Jan Tromp for
|
stream of log messages. Thanks to Erik Jan Tromp for
|
||||||
finding that bug.
|
finding that bug.
|
||||||
|
|
||||||
@@ -2067,7 +2067,7 @@ version 2.36
|
|||||||
kernel. Thanks to Philip Wall for the bug report.
|
kernel. Thanks to Philip Wall for the bug report.
|
||||||
|
|
||||||
Added --dhcp-bridge option, but only to the FreeBSD
|
Added --dhcp-bridge option, but only to the FreeBSD
|
||||||
build. This fixes an oddity with a a particular bridged
|
build. This fixes an oddity with a particular bridged
|
||||||
network configuration on FreeBSD. Thanks to Luigi Rizzo
|
network configuration on FreeBSD. Thanks to Luigi Rizzo
|
||||||
for the patch.
|
for the patch.
|
||||||
|
|
||||||
@@ -2273,7 +2273,7 @@ version 2.40
|
|||||||
this.
|
this.
|
||||||
|
|
||||||
Use client-id as hash-seed for DHCP address allocation
|
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 a MAC
|
||||||
address.
|
address.
|
||||||
|
|
||||||
Tweaked TFTP file-open code to make it behave sensibly
|
Tweaked TFTP file-open code to make it behave sensibly
|
||||||
@@ -2433,7 +2433,7 @@ version 2.41
|
|||||||
|
|
||||||
Add --dhcp-match flag, to check for arbitrary options in
|
Add --dhcp-match flag, to check for arbitrary options in
|
||||||
DHCP messages from clients. This enables use of dnsmasq
|
DHCP messages from clients. This enables use of dnsmasq
|
||||||
with gPXE. Thanks to Rance Hall for the suggestion.
|
with iPXE. Thanks to Rance Hall for the suggestion.
|
||||||
|
|
||||||
Added --dhcp-broadcast, to force broadcast replies to DHCP
|
Added --dhcp-broadcast, to force broadcast replies to DHCP
|
||||||
clients which need them but are too dumb or too old to
|
clients which need them but are too dumb or too old to
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ A: The high ports that dnsmasq opens are for replies from the upstream
|
|||||||
from port 53 the replies would be _to_ port 53 and get blocked.
|
from port 53 the replies would be _to_ port 53 and get blocked.
|
||||||
|
|
||||||
This is not a security hole since dnsmasq will only accept replies to that
|
This is not a security hole since dnsmasq will only accept replies to that
|
||||||
port: queries are dropped. The replies must be to oustanding queries
|
port: queries are dropped. The replies must be to outstanding queries
|
||||||
which dnsmasq has forwarded, otherwise they are dropped too.
|
which dnsmasq has forwarded, otherwise they are dropped too.
|
||||||
|
|
||||||
Addendum: dnsmasq now has the option "query-port" (-Q), which allows
|
Addendum: dnsmasq now has the option "query-port" (-Q), which allows
|
||||||
@@ -297,7 +297,7 @@ A: Dnsmasq from v2.63 can operate in one of three different "networking
|
|||||||
by dnsmasq when in --bind-interfaces mode. In wildcard or bind-dynamic
|
by dnsmasq when in --bind-interfaces mode. In wildcard or bind-dynamic
|
||||||
mode, such interfaces are handled normally.
|
mode, such interfaces are handled normally.
|
||||||
|
|
||||||
A --interface specification for a non-existent interface is a fatal
|
An --interface specification for a non-existent interface is a fatal
|
||||||
error at start-up when in --bind-interfaces mode, by just generates a
|
error at start-up when in --bind-interfaces mode, by just generates a
|
||||||
warning in wildcard or bind-dynamic mode.
|
warning in wildcard or bind-dynamic mode.
|
||||||
|
|
||||||
@@ -320,7 +320,7 @@ A: Yes, new releases of dnsmasq are always announced through
|
|||||||
|
|
||||||
Q: What does the dhcp-authoritative option do?
|
Q: What does the dhcp-authoritative option do?
|
||||||
|
|
||||||
A: The DHCP spec says that when a DHCP server recieves a renewal request
|
A: The DHCP spec says that when a DHCP server receives a renewal request
|
||||||
from a client it has no knowledge of, it should just ignore it.
|
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
|
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.
|
on a network, and another DHCP server may be dealing with the client.
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
|||||||
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
|
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 \
|
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
|
||||||
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
|
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
|
||||||
poll.o rrfilter.o edns0.o arp.o
|
poll.o rrfilter.o edns0.o arp.o crypto.o
|
||||||
|
|
||||||
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
||||||
dns-protocol.h radv-protocol.h ip6addr.h
|
dns-protocol.h radv-protocol.h ip6addr.h
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
|
|||||||
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
||||||
radv.c slaac.c auth.c ipset.c domain.c \
|
radv.c slaac.c auth.c ipset.c domain.c \
|
||||||
dnssec.c dnssec-openssl.c blockdata.c tables.c \
|
dnssec.c dnssec-openssl.c blockdata.c tables.c \
|
||||||
loop.c inotify.c poll.c rrfilter.c edns0.c arp.c
|
loop.c inotify.c poll.c rrfilter.c edns0.c arp.c crypto.c
|
||||||
|
|
||||||
LOCAL_MODULE := dnsmasq
|
LOCAL_MODULE := dnsmasq
|
||||||
|
|
||||||
|
|||||||
+322
-271
@@ -46,7 +46,8 @@ typedef unsigned char u8;
|
|||||||
typedef unsigned short u16;
|
typedef unsigned short u16;
|
||||||
typedef unsigned int u32;
|
typedef unsigned int u32;
|
||||||
|
|
||||||
enum DHCP6_TYPES{
|
enum DHCP6_TYPES
|
||||||
|
{
|
||||||
SOLICIT = 1,
|
SOLICIT = 1,
|
||||||
ADVERTISE = 2,
|
ADVERTISE = 2,
|
||||||
REQUEST = 3,
|
REQUEST = 3,
|
||||||
@@ -61,8 +62,10 @@ enum DHCP6_TYPES{
|
|||||||
RELAY_FORW = 12,
|
RELAY_FORW = 12,
|
||||||
RELAY_REPL = 13
|
RELAY_REPL = 13
|
||||||
|
|
||||||
};
|
};
|
||||||
enum DHCP6_OPTIONS{
|
|
||||||
|
enum DHCP6_OPTIONS
|
||||||
|
{
|
||||||
CLIENTID = 1,
|
CLIENTID = 1,
|
||||||
SERVERID = 2,
|
SERVERID = 2,
|
||||||
IA_NA = 3,
|
IA_NA = 3,
|
||||||
@@ -82,25 +85,27 @@ enum DHCP6_OPTIONS{
|
|||||||
INTERFACE_ID = 18,
|
INTERFACE_ID = 18,
|
||||||
RECONF_MSG = 19,
|
RECONF_MSG = 19,
|
||||||
RECONF_ACCEPT = 20,
|
RECONF_ACCEPT = 20,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DHCP6_STATUSES{
|
enum DHCP6_STATUSES
|
||||||
|
{
|
||||||
SUCCESS = 0,
|
SUCCESS = 0,
|
||||||
UNSPEC_FAIL = 1,
|
UNSPEC_FAIL = 1,
|
||||||
NOADDR_AVAIL=2,
|
NOADDR_AVAIL=2,
|
||||||
NO_BINDING = 3,
|
NO_BINDING = 3,
|
||||||
NOT_ON_LINK = 4,
|
NOT_ON_LINK = 4,
|
||||||
USE_MULTICAST =5
|
USE_MULTICAST =5
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct option longopts[] = {
|
static struct option longopts[] = {
|
||||||
{"ip", required_argument, 0, 'a'},
|
{"ip", required_argument, 0, 'a' },
|
||||||
{"server-id", required_argument, 0, 's'},
|
{"server-id", required_argument, 0, 's' },
|
||||||
{"client-id", required_argument, 0, 'c'},
|
{"client-id", required_argument, 0, 'c' },
|
||||||
{"iface", required_argument, 0, 'n'},
|
{"iface", required_argument, 0, 'n' },
|
||||||
{"iaid", required_argument, 0, 'i'},
|
{"iaid", required_argument, 0, 'i' },
|
||||||
{"dry-run", no_argument, 0, 'd'},
|
{"dry-run", no_argument, 0, 'd' },
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h' },
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
const short DHCP6_CLIENT_PORT = 546;
|
const short DHCP6_CLIENT_PORT = 546;
|
||||||
@@ -108,207 +113,230 @@ const short DHCP6_SERVER_PORT = 547;
|
|||||||
|
|
||||||
const char* DHCP6_MULTICAST_ADDRESS = "ff02::1:2";
|
const char* DHCP6_MULTICAST_ADDRESS = "ff02::1:2";
|
||||||
|
|
||||||
struct dhcp6_option{
|
struct dhcp6_option {
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
char value[1024];
|
char value[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dhcp6_iaaddr_option{
|
struct dhcp6_iaaddr_option {
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
struct in6_addr ip;
|
struct in6_addr ip;
|
||||||
uint32_t preferred_lifetime;
|
uint32_t preferred_lifetime;
|
||||||
uint32_t valid_lifetime;
|
uint32_t valid_lifetime;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dhcp6_iana_option{
|
struct dhcp6_iana_option {
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint32_t iaid;
|
uint32_t iaid;
|
||||||
uint32_t t1;
|
uint32_t t1;
|
||||||
uint32_t t2;
|
uint32_t t2;
|
||||||
char options[1024];
|
char options[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct dhcp6_packet{
|
struct dhcp6_packet {
|
||||||
size_t len;
|
size_t len;
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
|
};
|
||||||
} ;
|
|
||||||
|
|
||||||
size_t pack_duid(const char* str, char* dst){
|
size_t pack_duid(const char* str, char* dst)
|
||||||
|
{
|
||||||
char* tmp = strdup(str);
|
char* tmp = strdup(str);
|
||||||
char* tmp_to_free = tmp;
|
char* tmp_to_free = tmp;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
uint8_t write_pos = 0;
|
uint8_t write_pos = 0;
|
||||||
while ((ptr = strtok (tmp, ":"))) {
|
while ((ptr = strtok (tmp, ":")))
|
||||||
dst[write_pos] = (uint8_t) strtol(ptr, NULL, 16);
|
{
|
||||||
write_pos += 1;
|
dst[write_pos] = (uint8_t) strtol(ptr, NULL, 16);
|
||||||
tmp = NULL;
|
write_pos += 1;
|
||||||
|
tmp = NULL;
|
||||||
}
|
}
|
||||||
free(tmp_to_free);
|
|
||||||
return write_pos;
|
free(tmp_to_free);
|
||||||
|
return write_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dhcp6_option create_client_id_option(const char* duid){
|
struct dhcp6_option create_client_id_option(const char* duid)
|
||||||
struct dhcp6_option option;
|
{
|
||||||
option.type = htons(CLIENTID);
|
struct dhcp6_option option;
|
||||||
bzero(option.value, sizeof(option.value));
|
option.type = htons(CLIENTID);
|
||||||
option.len = htons(pack_duid(duid, option.value));
|
bzero(option.value, sizeof(option.value));
|
||||||
return option;
|
option.len = htons(pack_duid(duid, option.value));
|
||||||
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dhcp6_option create_server_id_option(const char* duid){
|
struct dhcp6_option create_server_id_option(const char* duid)
|
||||||
struct dhcp6_option option;
|
{
|
||||||
option.type = htons(SERVERID);
|
struct dhcp6_option option;
|
||||||
bzero(option.value, sizeof(option.value));
|
option.type = htons(SERVERID);
|
||||||
option.len = htons(pack_duid(duid, option.value));
|
bzero(option.value, sizeof(option.value));
|
||||||
return option;
|
option.len = htons(pack_duid(duid, option.value));
|
||||||
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dhcp6_iaaddr_option create_iaadr_option(const char* ip){
|
struct dhcp6_iaaddr_option create_iaadr_option(const char* ip)
|
||||||
struct dhcp6_iaaddr_option result;
|
{
|
||||||
result.type =htons(IAADDR);
|
struct dhcp6_iaaddr_option result;
|
||||||
/* no suboptions needed here, so length is 24 */
|
result.type =htons(IAADDR);
|
||||||
result.len = htons(24);
|
/* no suboptions needed here, so length is 24 */
|
||||||
result.preferred_lifetime = 0;
|
result.len = htons(24);
|
||||||
result.valid_lifetime = 0;
|
result.preferred_lifetime = 0;
|
||||||
int s = inet_pton(AF_INET6, ip, &(result.ip));
|
result.valid_lifetime = 0;
|
||||||
if (s <= 0) {
|
int s = inet_pton(AF_INET6, ip, &(result.ip));
|
||||||
if (s == 0)
|
if (s <= 0) {
|
||||||
fprintf(stderr, "Not in presentation format");
|
if (s == 0)
|
||||||
else
|
fprintf(stderr, "Not in presentation format");
|
||||||
perror("inet_pton");
|
else
|
||||||
exit(EXIT_FAILURE);
|
perror("inet_pton");
|
||||||
}
|
exit(EXIT_FAILURE);
|
||||||
return result;
|
}
|
||||||
}
|
|
||||||
struct dhcp6_iana_option create_iana_option(const char * iaid, struct dhcp6_iaaddr_option ia_addr){
|
return result;
|
||||||
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_iana_option create_iana_option(const char * iaid, struct dhcp6_iaaddr_option ia_addr)
|
||||||
struct dhcp6_packet result;
|
{
|
||||||
bzero(result.buf, sizeof(result.buf));
|
struct dhcp6_iana_option result;
|
||||||
/* message_type */
|
result.type = htons(IA_NA);
|
||||||
result.buf[0] = RELEASE;
|
result.iaid = htonl(atoi(iaid));
|
||||||
/* tx_id */
|
result.t1 = 0;
|
||||||
bzero(result.buf+1, 3);
|
result.t2 = 0;
|
||||||
|
result.len = htons(12 + ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
|
||||||
struct dhcp6_option client_option = create_client_id_option(client_id);
|
memcpy(result.options, &ia_addr, ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
|
||||||
struct dhcp6_option server_option = create_server_id_option(server_id);
|
return result;
|
||||||
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){
|
struct dhcp6_packet create_release_packet(const char* iaid, const char* ip, const char* client_id, const char* server_id)
|
||||||
size_t current_pos = 0;
|
{
|
||||||
char option_value[1024];
|
struct dhcp6_packet result;
|
||||||
while (current_pos < len) {
|
bzero(result.buf, sizeof(result.buf));
|
||||||
uint16_t option_type, option_len;
|
/* message_type */
|
||||||
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
|
result.buf[0] = RELEASE;
|
||||||
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
|
/* tx_id */
|
||||||
option_type = ntohs(option_type);
|
bzero(result.buf+1, 3);
|
||||||
option_len = ntohs(option_len);
|
|
||||||
current_pos += 2 * sizeof(uint16_t);
|
struct dhcp6_option client_option = create_client_id_option(client_id);
|
||||||
if (option_type == STATUS_CODE){
|
struct dhcp6_option server_option = create_server_id_option(server_id);
|
||||||
uint16_t status;
|
struct dhcp6_iaaddr_option iaaddr_option = create_iaadr_option(ip);
|
||||||
memcpy(&status, buf + current_pos, sizeof(uint16_t));
|
struct dhcp6_iana_option iana_option = create_iana_option(iaid, iaaddr_option);
|
||||||
status = ntohs(status);
|
int offset = 4;
|
||||||
if (status != SUCCESS){
|
memcpy(result.buf + offset, &client_option, ntohs(client_option.len) + 2*sizeof(uint16_t));
|
||||||
memcpy(option_value, buf + current_pos + sizeof(uint16_t) , option_len - sizeof(uint16_t));
|
offset += (ntohs(client_option.len)+ 2 *sizeof(uint16_t) );
|
||||||
option_value[option_len-sizeof(uint16_t)] ='\0';
|
memcpy(result.buf + offset, &server_option, ntohs(server_option.len) + 2*sizeof(uint16_t) );
|
||||||
fprintf(stderr, "Error: %s\n", option_value);
|
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 status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -2;
|
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t parse_packet(char* buf, size_t len){
|
int16_t parse_packet(char* buf, size_t len)
|
||||||
uint8_t type = buf[0];
|
{
|
||||||
/*skipping tx id. you need it, uncomment following line
|
int16_t ret = -1;
|
||||||
uint16_t tx_id = ntohs((buf[1] <<16) + (buf[2] <<8) + buf[3]);
|
uint8_t type = buf[0];
|
||||||
*/
|
/*skipping tx id. you need it, uncomment following line
|
||||||
size_t current_pos = 4;
|
uint16_t tx_id = ntohs((buf[1] <<16) + (buf[2] <<8) + buf[3]);
|
||||||
if (type != REPLY ){
|
*/
|
||||||
return NOT_REPLY_CODE;
|
size_t current_pos = 4;
|
||||||
}
|
if (type != REPLY )
|
||||||
char option_value[1024];
|
return NOT_REPLY_CODE;
|
||||||
while (current_pos < len) {
|
|
||||||
uint16_t option_type, option_len;
|
char option_value[1024];
|
||||||
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
|
while (current_pos < len)
|
||||||
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
|
{
|
||||||
option_type = ntohs(option_type);
|
uint16_t option_type, option_len;
|
||||||
option_len = ntohs(option_len);
|
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
|
||||||
current_pos += 2 * sizeof(uint16_t);
|
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
|
||||||
if (option_type == STATUS_CODE){
|
option_type = ntohs(option_type);
|
||||||
uint16_t status;
|
option_len = ntohs(option_len);
|
||||||
memcpy(&status, buf + current_pos, sizeof(uint16_t));
|
current_pos += 2 * sizeof(uint16_t);
|
||||||
status = ntohs(status);
|
if (option_type == STATUS_CODE)
|
||||||
if (status != SUCCESS){
|
{
|
||||||
memcpy(option_value, buf + current_pos +sizeof(uint16_t) , option_len -sizeof(uint16_t));
|
uint16_t status;
|
||||||
fprintf(stderr, "Error: %d %s\n", status, option_value);
|
memcpy(&status, buf + current_pos, sizeof(uint16_t));
|
||||||
return status;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Got success status, return that if there's no specific error in an IA_NA. */
|
||||||
|
ret = SUCCESS;
|
||||||
}
|
}
|
||||||
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;
|
|
||||||
|
|
||||||
|
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;
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usage(const char* arg, FILE* stream){
|
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);
|
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){
|
int send_release_packet(const char* iface, struct dhcp6_packet* packet)
|
||||||
|
{
|
||||||
struct sockaddr_in6 server_addr, client_addr;
|
struct sockaddr_in6 server_addr, client_addr;
|
||||||
char response[1400];
|
char response[1400];
|
||||||
int sock = socket(PF_INET6, SOCK_DGRAM, 0);
|
int sock = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (sock < 0) {
|
if (sock < 0)
|
||||||
perror("creating socket");
|
{
|
||||||
return -1;
|
perror("creating socket");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
if (setsockopt(sock, SOL_SOCKET, 25, iface, strlen(iface)) == -1) {
|
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, 25, iface, strlen(iface)) == -1)
|
||||||
|
{
|
||||||
perror("SO_BINDTODEVICE");
|
perror("SO_BINDTODEVICE");
|
||||||
close(sock);
|
close(sock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&server_addr, 0, sizeof(server_addr));
|
memset(&server_addr, 0, sizeof(server_addr));
|
||||||
server_addr.sin6_family = AF_INET6;
|
server_addr.sin6_family = AF_INET6;
|
||||||
client_addr.sin6_family = AF_INET6;
|
client_addr.sin6_family = AF_INET6;
|
||||||
@@ -320,126 +348,149 @@ int send_release_packet(const char* iface, struct dhcp6_packet* packet){
|
|||||||
inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
|
inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
|
||||||
server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
|
server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
|
||||||
int16_t recv_size = 0;
|
int16_t recv_size = 0;
|
||||||
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 5; i++)
|
||||||
if (sendto(sock, packet->buf, packet->len, 0,
|
{
|
||||||
(struct sockaddr *)&server_addr,
|
if (sendto(sock, packet->buf, packet->len, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
|
||||||
sizeof(server_addr)) < 0) {
|
{
|
||||||
perror("sendto failed");
|
perror("sendto failed");
|
||||||
exit(4);
|
exit(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
|
recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
|
||||||
if (recv_size == -1){
|
if (recv_size == -1)
|
||||||
if (errno == EAGAIN){
|
{
|
||||||
sleep(1);
|
if (errno == EAGAIN)
|
||||||
continue;
|
{
|
||||||
}else {
|
sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
perror("recvfrom");
|
perror("recvfrom");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t result = parse_packet(response, recv_size);
|
int16_t result = parse_packet(response, recv_size);
|
||||||
if (result == NOT_REPLY_CODE){
|
if (result == NOT_REPLY_CODE)
|
||||||
|
{
|
||||||
sleep(1);
|
sleep(1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Response timed out\n");
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
|
fprintf(stderr, "Response timed out\n");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char * const argv[]) {
|
int main(int argc, char * const argv[])
|
||||||
const char* UNINITIALIZED = "";
|
{
|
||||||
const char* iface = UNINITIALIZED;
|
const char* UNINITIALIZED = "";
|
||||||
const char* ip = UNINITIALIZED;
|
const char* iface = UNINITIALIZED;
|
||||||
const char* client_id = UNINITIALIZED;
|
const char* ip = UNINITIALIZED;
|
||||||
const char* server_id = UNINITIALIZED;
|
const char* client_id = UNINITIALIZED;
|
||||||
const char* iaid = UNINITIALIZED;
|
const char* server_id = UNINITIALIZED;
|
||||||
int dry_run = 0;
|
const char* iaid = UNINITIALIZED;
|
||||||
while (1) {
|
int dry_run = 0;
|
||||||
int option_index = 0;
|
while (1)
|
||||||
int c = getopt_long(argc, argv, "a:s:c:n:i:hd", longopts, &option_index);
|
{
|
||||||
if (c == -1){
|
int option_index = 0;
|
||||||
break;
|
int c = getopt_long(argc, argv, "a:s:c:n:i:hd", longopts, &option_index);
|
||||||
}
|
if (c == -1)
|
||||||
switch(c){
|
break;
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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");
|
if (iaid == UNINITIALIZED)
|
||||||
usage(argv[0], stderr);
|
{
|
||||||
return -1;
|
fprintf(stderr, "Missing required iaid parameter\n");
|
||||||
|
usage(argv[0], stderr);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
if (server_id == UNINITIALIZED){
|
|
||||||
|
if (server_id == UNINITIALIZED)
|
||||||
|
{
|
||||||
fprintf(stderr, "Missing required server-id parameter\n");
|
fprintf(stderr, "Missing required server-id parameter\n");
|
||||||
usage(argv[0], stderr);
|
usage(argv[0], stderr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (client_id == UNINITIALIZED){
|
|
||||||
|
if (client_id == UNINITIALIZED)
|
||||||
|
{
|
||||||
fprintf(stderr, "Missing required client-id parameter\n");
|
fprintf(stderr, "Missing required client-id parameter\n");
|
||||||
usage(argv[0], stderr);
|
usage(argv[0], stderr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (ip == UNINITIALIZED){
|
|
||||||
|
if (ip == UNINITIALIZED)
|
||||||
|
{
|
||||||
fprintf(stderr, "Missing required ip parameter\n");
|
fprintf(stderr, "Missing required ip parameter\n");
|
||||||
usage(argv[0], stderr);
|
usage(argv[0], stderr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (iface == UNINITIALIZED){
|
|
||||||
fprintf(stderr, "Missing required iface parameter\n");
|
if (iface == UNINITIALIZED)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Missing required iface parameter\n");
|
||||||
usage(argv[0], stderr);
|
usage(argv[0], stderr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct dhcp6_packet packet = create_release_packet(iaid, ip, client_id, server_id);
|
struct dhcp6_packet packet = create_release_packet(iaid, ip, client_id, server_id);
|
||||||
if (dry_run){
|
|
||||||
|
if (dry_run)
|
||||||
|
{
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
for(i=0;i<packet.len;i++){
|
|
||||||
printf("%hhx", packet.buf[i]);
|
for(i=0; i<packet.len; i++)
|
||||||
}
|
printf("%hhx", packet.buf[i]);
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return send_release_packet(iface, &packet);
|
return send_release_packet(iface, &packet);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
STATUS_FILE="/tmp/dnsmasq-ip-mac.status"
|
STATUS_FILE="/tmp/dnsmasq-ip-mac.status"
|
||||||
|
|
||||||
# Script for dnsmasq lease-change hook.
|
# Script for dnsmasq lease-change hook.
|
||||||
# Maintains the above file with a IP address/MAC address pairs,
|
# Maintains the above file with an IP address/MAC address pairs,
|
||||||
# one lease per line. Works with IPv4 and IPv6 leases, file is
|
# one lease per line. Works with IPv4 and IPv6 leases, file is
|
||||||
# atomically updated, so no races for users of the data.
|
# atomically updated, so no races for users of the data.
|
||||||
|
|
||||||
|
|||||||
Vendored
+27
-2
@@ -1,8 +1,33 @@
|
|||||||
|
dnsmasq (2.79-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream. (closes: #888200)
|
||||||
|
* Fix trust-anchor regex in init script. (closes: #884347)
|
||||||
|
* Fix exit code for dhcp_release6 (closes: #833596)
|
||||||
|
* Add project homepage to control file. (closes: #887764)
|
||||||
|
* New binary package dnsmasq-base-lua, includes Lua support.
|
||||||
|
* Remove hardwired shlibs dependency for libnettle 3.3 and
|
||||||
|
fix code to avoid ABI breakage as long as compiled against
|
||||||
|
libnettle 3.4 or later. (closes: #891315)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 16 Feb 2018 19:54:22 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.78-3) unstable; urgency=high
|
||||||
|
|
||||||
|
* Make failure of pidfile chown a warning. (closes: #889857)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 8 Feb 2018 21:26:30 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.78-2) unstable; urgency=high
|
||||||
|
|
||||||
|
* Change ownership of pid file, to keep systemd happy. (closes: #889336)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 6 Feb 2018 17:21:30 +0000
|
||||||
|
|
||||||
dnsmasq (2.78-1) unstable; urgency=high
|
dnsmasq (2.78-1) unstable; urgency=high
|
||||||
|
|
||||||
* New upstream.
|
* New upstream.
|
||||||
Security fixes for CVE-2017-13704 (closes: #877102)
|
Security fixes for CVE-2017-13704 (closes: #877102)
|
||||||
Security fixes for CVE-2017-14491 - CVE-2017-14496 inclusive.
|
Security fixes for CVE-2017-14491 - CVE-2017-14496 inclusive.
|
||||||
|
|
||||||
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 29 Sep 2017 21:34:00 +0000
|
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 29 Sep 2017 21:34:00 +0000
|
||||||
|
|
||||||
@@ -19,7 +44,7 @@ dnsmasq (2.77-1) unstable; urgency=low
|
|||||||
includes port=0 to disable DNS.
|
includes port=0 to disable DNS.
|
||||||
* Handle gratuitous format change in /usr/share/dns/root.ds
|
* Handle gratuitous format change in /usr/share/dns/root.ds
|
||||||
(closes: #858506) (closes: #860064)
|
(closes: #858506) (closes: #860064)
|
||||||
* Add lsb-base dependancy.
|
* Add lsb-base dependency.
|
||||||
|
|
||||||
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 11 Apr 2017 14:19:20 +0000
|
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 11 Apr 2017 14:19:20 +0000
|
||||||
|
|
||||||
|
|||||||
Vendored
+21
-3
@@ -3,13 +3,15 @@ Section: net
|
|||||||
Priority: optional
|
Priority: optional
|
||||||
Build-depends: gettext, libnetfilter-conntrack-dev [linux-any],
|
Build-depends: gettext, libnetfilter-conntrack-dev [linux-any],
|
||||||
libidn11-dev, libdbus-1-dev (>=0.61), libgmp-dev,
|
libidn11-dev, libdbus-1-dev (>=0.61), libgmp-dev,
|
||||||
nettle-dev (>=2.4-3), libbsd-dev [!linux-any]
|
nettle-dev (>=2.4-3), libbsd-dev [!linux-any],
|
||||||
|
liblua5.2-dev
|
||||||
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
|
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
|
||||||
|
Homepage: http://www.thekelleys.org.uk/dnsmasq/doc.html
|
||||||
Standards-Version: 3.9.8
|
Standards-Version: 3.9.8
|
||||||
|
|
||||||
Package: dnsmasq
|
Package: dnsmasq
|
||||||
Architecture: all
|
Architecture: all
|
||||||
Depends: netbase, dnsmasq-base(>= ${binary:Version}),
|
Depends: netbase, dnsmasq-base,
|
||||||
init-system-helpers (>= 1.18~), lsb-base (>= 3.0-6)
|
init-system-helpers (>= 1.18~), lsb-base (>= 3.0-6)
|
||||||
Suggests: resolvconf
|
Suggests: resolvconf
|
||||||
Conflicts: resolvconf (<<1.15)
|
Conflicts: resolvconf (<<1.15)
|
||||||
@@ -27,13 +29,29 @@ Package: dnsmasq-base
|
|||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: adduser, ${shlibs:Depends}
|
Depends: adduser, ${shlibs:Depends}
|
||||||
Breaks: dnsmasq (<< 2.63-1~)
|
Breaks: dnsmasq (<< 2.63-1~)
|
||||||
Replaces: dnsmasq (<< 2.63-1~)
|
Replaces: dnsmasq (<< 2.63-1~), dnsmasq-base
|
||||||
Recommends: dns-root-data
|
Recommends: dns-root-data
|
||||||
|
Provides: dnsmasq-base
|
||||||
|
Conflicts: dnsmasq-base-lua
|
||||||
Description: Small caching DNS proxy and DHCP/TFTP server
|
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||||
This package contains the dnsmasq executable and documentation, but
|
This package contains the dnsmasq executable and documentation, but
|
||||||
not the infrastructure required to run it as a system daemon. For
|
not the infrastructure required to run it as a system daemon. For
|
||||||
that, install the dnsmasq package.
|
that, install the dnsmasq package.
|
||||||
|
|
||||||
|
Package: dnsmasq-base-lua
|
||||||
|
Architecture: any
|
||||||
|
Depends: adduser, ${shlibs:Depends}
|
||||||
|
Breaks: dnsmasq (<< 2.63-1~)
|
||||||
|
Replaces: dnsmasq (<< 2.63-1~), dnsmasq-base
|
||||||
|
Recommends: dns-root-data
|
||||||
|
Provides: dnsmasq-base
|
||||||
|
Conflicts: dnsmasq-base
|
||||||
|
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
|
||||||
|
that, install the dnsmasq package. This package is an alternative
|
||||||
|
to dnsmasq-base which includes the LUA interpreter.
|
||||||
|
|
||||||
Package: dnsmasq-utils
|
Package: dnsmasq-utils
|
||||||
Architecture: linux-any
|
Architecture: linux-any
|
||||||
Depends: ${shlibs:Depends}
|
Depends: ${shlibs:Depends}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
dnsmasq is Copyright (c) 2000-2016 Simon Kelley
|
dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
It was downloaded from: http://www.thekelleys.org.uk/dnsmasq/
|
It was downloaded from: http://www.thekelleys.org.uk/dnsmasq/
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -111,7 +111,7 @@ DNSMASQ_OPTS="$DNSMASQ_OPTS --local-service"
|
|||||||
ROOT_DS="/usr/share/dns/root.ds"
|
ROOT_DS="/usr/share/dns/root.ds"
|
||||||
|
|
||||||
if [ -f $ROOT_DS ]; then
|
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' ' '`"
|
DNSMASQ_OPTS="$DNSMASQ_OPTS `env LC_ALL=C 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
|
fi
|
||||||
|
|
||||||
start()
|
start()
|
||||||
|
|||||||
Vendored
+1
-1
@@ -54,7 +54,7 @@ Notes on configuring dnsmasq as packaged for Debian.
|
|||||||
nodhcp : omit DHCP support.
|
nodhcp : omit DHCP support.
|
||||||
nodhcp6 : omit DHCPv6 support.
|
nodhcp6 : omit DHCPv6 support.
|
||||||
noscript : omit lease-change script support.
|
noscript : omit lease-change script support.
|
||||||
use_lua : provide support for lease-change scripts written
|
uselua : provide support for lease-change scripts written
|
||||||
in Lua.
|
in Lua.
|
||||||
noipv6 : omit IPv6 support.
|
noipv6 : omit IPv6 support.
|
||||||
nodbus : omit DBus support.
|
nodbus : omit DBus support.
|
||||||
|
|||||||
Vendored
+150
-111
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/make -f
|
#!/usr/bin/make -f
|
||||||
# debian/rules file - for dnsmasq.
|
# debian/rules file - for dnsmasq.
|
||||||
# Copyright 2001-2011 by Simon Kelley
|
# Copyright 2001-2018 by Simon Kelley
|
||||||
# Based on the sample in the debian hello package which carries the following:
|
# Based on the sample in the debian hello package which carries the following:
|
||||||
# Copyright 1994,1995 by Ian Jackson.
|
# Copyright 1994,1995 by Ian Jackson.
|
||||||
# I hereby give you perpetual unlimited permission to copy,
|
# I hereby give you perpetual unlimited permission to copy,
|
||||||
@@ -103,128 +103,167 @@ ifneq ($(DEB_HOST_ARCH_OS),linux)
|
|||||||
LDFLAGS += -lbsd
|
LDFLAGS += -lbsd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
clean:
|
define build_tree
|
||||||
$(checkdir)
|
rm -rf $1
|
||||||
rm -rf debian/daemon debian/base debian/utils debian/*~ debian/files debian/substvars debian/utils-substvars
|
|
||||||
make clean
|
|
||||||
make -C contrib/lease-tools clean
|
|
||||||
|
|
||||||
binary-indep: checkroot
|
|
||||||
$(checkdir)
|
|
||||||
rm -rf debian/daemon
|
|
||||||
install -m 755 \
|
install -m 755 \
|
||||||
-d debian/daemon/DEBIAN \
|
-d $1/DEBIAN \
|
||||||
-d debian/daemon/usr/share/doc \
|
-d $1/etc/dbus-1/system.d \
|
||||||
-d debian/daemon/etc/init.d \
|
-d $1/usr/share/doc/$(package) \
|
||||||
-d debian/daemon/etc/dnsmasq.d \
|
-d $1/usr/share/doc/$(package)/examples \
|
||||||
-d debian/daemon/etc/resolvconf/update.d \
|
-d $1/usr/share/$(package) \
|
||||||
-d debian/daemon/usr/lib/resolvconf/dpkg-event.d \
|
-d $1/var/lib/misc
|
||||||
-d debian/daemon/usr/share/dnsmasq \
|
|
||||||
-d debian/daemon/etc/default \
|
|
||||||
-d debian/daemon/lib/systemd/system \
|
|
||||||
-d debian/daemon/etc/insserv.conf.d
|
|
||||||
install -m 644 debian/conffiles debian/daemon/DEBIAN
|
|
||||||
install -m 755 debian/postinst debian/postrm debian/prerm debian/daemon/DEBIAN
|
|
||||||
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' | 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 ..
|
|
||||||
|
|
||||||
binary-arch: checkroot
|
endef
|
||||||
$(checkdir)
|
|
||||||
rm -rf debian/base
|
define add_docs
|
||||||
install -m 755 \
|
|
||||||
-d debian/base/DEBIAN \
|
|
||||||
-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/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=$(CC) PKG_CONFIG=$(PKG_CONFIG)
|
|
||||||
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
|
|
||||||
# Need to remove paypal links in Debian Package for policy reasons.
|
# 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
|
sed -e /\<H2\>Donations/Q -e /icon.png/d doc.html -e /favicon.ico/d >$1/usr/share/doc/$(package)/doc.html
|
||||||
echo "</BODY>" >>debian/base/usr/share/doc/$(package)/doc.html
|
echo "</BODY>" >>$1/usr/share/doc/$(package)/doc.html
|
||||||
install -m 644 setup.html debian/base/usr/share/doc/$(package)/.
|
install -m 644 setup.html $1/usr/share/doc/$(package)/.
|
||||||
install -m 644 dnsmasq.conf.example debian/base/usr/share/doc/$(package)/examples/.
|
install -m 644 dnsmasq.conf.example $1/usr/share/doc/$(package)/examples/.
|
||||||
install -m 644 trust-anchors.conf debian/base/usr/share/$(package)/.
|
install -m 644 FAQ $1/usr/share/doc/$(package)/.
|
||||||
install -m 644 FAQ debian/base/usr/share/doc/$(package)/.
|
gzip -9n $1/usr/share/doc/$(package)/FAQ
|
||||||
gzip -9n debian/base/usr/share/doc/$(package)/FAQ
|
install -m 644 CHANGELOG $1/usr/share/doc/$(package)/changelog
|
||||||
install -m 644 CHANGELOG debian/base/usr/share/doc/$(package)/changelog
|
gzip -9n $1/usr/share/doc/$(package)/changelog
|
||||||
gzip -9n debian/base/usr/share/doc/$(package)/changelog
|
install -m 644 CHANGELOG.archive $1/usr/share/doc/$(package)/changelog.archive
|
||||||
install -m 644 CHANGELOG.archive debian/base/usr/share/doc/$(package)/changelog.archive
|
gzip -9n $1/usr/share/doc/$(package)/changelog.archive
|
||||||
gzip -9n debian/base/usr/share/doc/$(package)/changelog.archive
|
install -m 644 dbus/DBus-interface $1/usr/share/doc/$(package)/.
|
||||||
install -m 644 dbus/DBus-interface debian/base/usr/share/doc/$(package)/.
|
gzip -9n $1/usr/share/doc/$(package)/DBus-interface
|
||||||
gzip -9n debian/base/usr/share/doc/$(package)/DBus-interface
|
gzip -9n $1/usr/share/man/man8/dnsmasq.8
|
||||||
endif
|
for f in $1/usr/share/man/*; do \
|
||||||
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 -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 -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 \
|
if [ -f $$f/man8/dnsmasq.8 ]; then \
|
||||||
gzip -9n $$f/man8/dnsmasq.8 ; \
|
gzip -9n $$f/man8/dnsmasq.8 ; \
|
||||||
fi \
|
fi \
|
||||||
done
|
done
|
||||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
endef
|
||||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/base/usr/sbin/dnsmasq
|
|
||||||
|
define add_files
|
||||||
|
install -m 644 trust-anchors.conf $1/usr/share/$(package)/.
|
||||||
|
install -m 644 debian/dnsmasq-base.conffiles $1/DEBIAN/conffiles
|
||||||
|
install -m 755 debian/dnsmasq-base.postinst $1/DEBIAN/postinst
|
||||||
|
install -m 755 debian/dnsmasq-base.postrm $1/DEBIAN/postrm
|
||||||
|
install -m 644 debian/changelog $1/usr/share/doc/$(package)/changelog.Debian
|
||||||
|
gzip -9n $1/usr/share/doc/$(package)/changelog.Debian
|
||||||
|
install -m 644 debian/readme $1/usr/share/doc/$(package)/README.Debian
|
||||||
|
install -m 644 debian/copyright $1/usr/share/doc/$(package)/copyright
|
||||||
|
install -m 644 debian/dbus.conf $1/etc/dbus-1/system.d/dnsmasq.conf
|
||||||
|
endef
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(checkdir)
|
||||||
|
make BUILDDIR=debian/build/no-lua clean
|
||||||
|
make BUILDDIR=debian/build/lua clean
|
||||||
|
make -C contrib/lease-tools clean
|
||||||
|
rm -rf debian/build debian/trees debian/*~ debian/files debian/substvars debian/utils-substvars
|
||||||
|
|
||||||
|
binary-indep: checkroot
|
||||||
|
$(checkdir)
|
||||||
|
rm -rf debian/trees/daemon
|
||||||
|
install -m 755 \
|
||||||
|
-d debian/trees/daemon/DEBIAN \
|
||||||
|
-d debian/trees/daemon/usr/share/doc \
|
||||||
|
-d debian/trees/daemon/etc/init.d \
|
||||||
|
-d debian/trees/daemon/etc/dnsmasq.d \
|
||||||
|
-d debian/trees/daemon/etc/resolvconf/update.d \
|
||||||
|
-d debian/trees/daemon/usr/lib/resolvconf/dpkg-event.d \
|
||||||
|
-d debian/trees/daemon/usr/share/dnsmasq \
|
||||||
|
-d debian/trees/daemon/etc/default \
|
||||||
|
-d debian/trees/daemon/lib/systemd/system \
|
||||||
|
-d debian/trees/daemon/etc/insserv.conf.d
|
||||||
|
install -m 644 debian/conffiles debian/trees/daemon/DEBIAN
|
||||||
|
install -m 755 debian/postinst debian/postrm debian/prerm debian/trees/daemon/DEBIAN
|
||||||
|
install -m 755 debian/init debian/trees/daemon/etc/init.d/dnsmasq
|
||||||
|
install -m 755 debian/resolvconf debian/trees/daemon/etc/resolvconf/update.d/dnsmasq
|
||||||
|
install -m 755 debian/resolvconf-package debian/trees/daemon/usr/lib/resolvconf/dpkg-event.d/dnsmasq
|
||||||
|
install -m 644 debian/installed-marker debian/trees/daemon/usr/share/dnsmasq
|
||||||
|
install -m 644 debian/default debian/trees/daemon/etc/default/dnsmasq
|
||||||
|
install -m 644 dnsmasq.conf.example debian/trees/daemon/etc/dnsmasq.conf
|
||||||
|
install -m 644 debian/readme.dnsmasq.d debian/trees/daemon/etc/dnsmasq.d/README
|
||||||
|
install -m 644 debian/systemd.service debian/trees/daemon/lib/systemd/system/dnsmasq.service
|
||||||
|
install -m 644 debian/insserv debian/trees/daemon/etc/insserv.conf.d/dnsmasq
|
||||||
|
ln -s $(package) debian/trees/daemon/usr/share/doc/dnsmasq
|
||||||
|
cd debian/trees/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/trees/daemon
|
||||||
|
find debian/trees/daemon -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||||
|
chown -R root.root debian/trees/daemon
|
||||||
|
chmod -R g-ws debian/trees/daemon
|
||||||
|
dpkg --build debian/trees/daemon ..
|
||||||
|
|
||||||
|
binary-arch: checkroot
|
||||||
|
$(call build_tree,debian/trees/base)
|
||||||
|
make $(TARGET) BUILDDIR=debian/build/no-lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
|
||||||
|
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
|
||||||
|
$(call add_docs,debian/trees/base)
|
||||||
|
else
|
||||||
|
rm -rf debian/trees/base/usr/share/man
|
||||||
endif
|
endif
|
||||||
cd debian/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
$(call add_files,debian/trees/base)
|
||||||
dpkg-shlibdeps --warnings=1 debian/base/usr/sbin/dnsmasq
|
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||||
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base -Pdebian/base
|
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/base/usr/sbin/dnsmasq
|
||||||
find debian/base -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
endif
|
||||||
chown -R root.root debian/base
|
cd debian/trees/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||||
chmod -R g-ws debian/base
|
dpkg-shlibdeps --warnings=1 debian/trees/base/usr/sbin/dnsmasq
|
||||||
dpkg --build debian/base ..
|
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base -Pdebian/trees/base
|
||||||
|
find debian/trees/base -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||||
|
chown -R root.root debian/trees/base
|
||||||
|
chmod -R g-ws debian/trees/base
|
||||||
|
dpkg --build debian/trees/base ..
|
||||||
|
|
||||||
|
$(call build_tree,debian/trees/lua-base)
|
||||||
|
make $(TARGET) BUILDDIR=debian/build/lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/lua-base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="-DHAVE_LUASCRIPT $(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
|
||||||
|
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
|
||||||
|
$(call add_docs,debian/trees/lua-base)
|
||||||
|
else
|
||||||
|
rm -rf debian/trees/lua-base/usr/share/man
|
||||||
|
endif
|
||||||
|
$(call add_files,debian/trees/lua-base)
|
||||||
|
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||||
|
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/lua-base/usr/sbin/dnsmasq
|
||||||
|
endif
|
||||||
|
cd debian/trees/lua-base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||||
|
dpkg-shlibdeps --warnings=1 debian/trees/lua-base/usr/sbin/dnsmasq
|
||||||
|
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base-lua -Pdebian/trees/lua-base
|
||||||
|
find debian/trees/lua-base -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||||
|
chown -R root.root debian/trees/lua-base
|
||||||
|
chmod -R g-ws debian/trees/lua-base
|
||||||
|
dpkg --build debian/trees/lua-base ..
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(DEB_HOST_ARCH_OS),linux)
|
ifeq ($(DEB_HOST_ARCH_OS),linux)
|
||||||
rm -rf debian/utils
|
rm -rf debian/trees/utils
|
||||||
install -m 755 -d debian/utils/DEBIAN \
|
install -m 755 -d debian/trees/utils/DEBIAN \
|
||||||
-d debian/utils/usr/share/man/man1 \
|
-d debian/trees/utils/usr/bin \
|
||||||
-d debian/utils/usr/bin \
|
-d debian/trees/utils/usr/share/doc/dnsmasq-utils
|
||||||
-d debian/utils/usr/share/doc/dnsmasq-utils
|
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
|
||||||
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 -d debian/trees/utils/usr/share/man/man1
|
||||||
install -m 755 contrib/lease-tools/dhcp_release debian/utils/usr/bin/dhcp_release
|
endif
|
||||||
install -m 644 contrib/lease-tools/dhcp_release.1 debian/utils/usr/share/man/man1/dhcp_release.1
|
make -C contrib/lease-tools PREFIX=/usr DESTDIR=`pwd`/debian/trees/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
|
||||||
gzip -9n debian/utils/usr/share/man/man1/dhcp_release.1
|
install -m 755 contrib/lease-tools/dhcp_release debian/trees/utils/usr/bin/dhcp_release
|
||||||
install -m 755 contrib/lease-tools/dhcp_release6 debian/utils/usr/bin/dhcp_release6
|
install -m 755 contrib/lease-tools/dhcp_release6 debian/trees/utils/usr/bin/dhcp_release6
|
||||||
install -m 644 contrib/lease-tools/dhcp_release6.1 debian/utils/usr/share/man/man1/dhcp_release6.1
|
install -m 755 contrib/lease-tools/dhcp_lease_time debian/trees/utils/usr/bin/dhcp_lease_time
|
||||||
gzip -9n debian/utils/usr/share/man/man1/dhcp_release6.1
|
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
|
||||||
install -m 755 contrib/lease-tools/dhcp_lease_time debian/utils/usr/bin/dhcp_lease_time
|
install -m 644 contrib/lease-tools/dhcp_release.1 debian/trees/utils/usr/share/man/man1/dhcp_release.1
|
||||||
install -m 644 contrib/lease-tools/dhcp_lease_time.1 debian/utils/usr/share/man/man1/dhcp_lease_time.1
|
gzip -9n debian/trees/utils/usr/share/man/man1/dhcp_release.1
|
||||||
install -m 644 debian/copyright debian/utils/usr/share/doc/dnsmasq-utils/copyright
|
install -m 644 contrib/lease-tools/dhcp_release6.1 debian/trees/utils/usr/share/man/man1/dhcp_release6.1
|
||||||
install -m 644 debian/changelog debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
gzip -9n debian/trees/utils/usr/share/man/man1/dhcp_release6.1
|
||||||
gzip -9n debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
install -m 644 contrib/lease-tools/dhcp_lease_time.1 debian/trees/utils/usr/share/man/man1/dhcp_lease_time.1
|
||||||
gzip -9n debian/utils/usr/share/man/man1/dhcp_lease_time.1
|
gzip -9n debian/trees/utils/usr/share/man/man1/dhcp_lease_time.1
|
||||||
|
endif
|
||||||
|
install -m 644 debian/copyright debian/trees/utils/usr/share/doc/dnsmasq-utils/copyright
|
||||||
|
install -m 644 debian/changelog debian/trees/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
||||||
|
gzip -9n debian/trees/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
||||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||||
$(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/trees/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/trees/utils/usr/bin/dhcp_release6
|
||||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/utils/usr/bin/dhcp_lease_time
|
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/utils/usr/bin/dhcp_lease_time
|
||||||
endif
|
endif
|
||||||
cd debian/utils && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
cd debian/trees/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-shlibdeps -Tdebian/utils-substvars debian/trees/utils/usr/bin/dhcp_release debian/trees/utils/usr/bin/dhcp_release6 debian/trees/utils/usr/bin/dhcp_lease_time
|
||||||
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/utils-substvars -pdnsmasq-utils -Pdebian/utils
|
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/utils-substvars -pdnsmasq-utils -Pdebian/trees/utils
|
||||||
find debian/utils -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
find debian/trees/utils -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||||
chown -R root.root debian/utils
|
chown -R root.root debian/trees/utils
|
||||||
chmod -R g-ws debian/utils
|
chmod -R g-ws debian/trees/utils
|
||||||
dpkg --build debian/utils ..
|
dpkg --build debian/trees/utils ..
|
||||||
endif
|
endif
|
||||||
|
|
||||||
define checkdir
|
define checkdir
|
||||||
|
|||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
libnettle 6 libnettle6 (>= 3.3)
|
|
||||||
+13
-13
@@ -90,7 +90,7 @@
|
|||||||
# server=10.1.2.3@eth1
|
# server=10.1.2.3@eth1
|
||||||
|
|
||||||
# and this sets the source (ie local) address used to talk to
|
# and this sets the source (ie local) address used to talk to
|
||||||
# 10.1.2.3 to 192.168.1.1 port 55 (there must be a interface with that
|
# 10.1.2.3 to 192.168.1.1 port 55 (there must be an interface with that
|
||||||
# IP on the machine, obviously).
|
# IP on the machine, obviously).
|
||||||
# server=10.1.2.3@192.168.1.1#55
|
# server=10.1.2.3@192.168.1.1#55
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@
|
|||||||
# Give a fixed IPv6 address and name to client with
|
# 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
|
# 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 the MAC addresses CANNOT be used to identify DHCPv6 clients.
|
||||||
# Note also the they [] around the IPv6 address are obligatory.
|
# Note also that the [] 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]
|
#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
|
# Ignore any clients which are not specified in dhcp-host lines
|
||||||
@@ -354,11 +354,11 @@
|
|||||||
|
|
||||||
# Set option 58 client renewal time (T1). Defaults to half of the
|
# Set option 58 client renewal time (T1). Defaults to half of the
|
||||||
# lease time if not specified. (RFC2132)
|
# lease time if not specified. (RFC2132)
|
||||||
#dhcp-option=option:T1:1m
|
#dhcp-option=option:T1,1m
|
||||||
|
|
||||||
# Set option 59 rebinding time (T2). Defaults to 7/8 of the
|
# Set option 59 rebinding time (T2). Defaults to 7/8 of the
|
||||||
# lease time if not specified. (RFC2132)
|
# lease time if not specified. (RFC2132)
|
||||||
#dhcp-option=option:T2:2m
|
#dhcp-option=option:T2,2m
|
||||||
|
|
||||||
# Set the NTP time server address to be the same machine as
|
# Set the NTP time server address to be the same machine as
|
||||||
# is running dnsmasq
|
# is running dnsmasq
|
||||||
@@ -436,22 +436,22 @@
|
|||||||
#dhcp-option-force=211,30i
|
#dhcp-option-force=211,30i
|
||||||
|
|
||||||
# Set the boot filename for netboot/PXE. You will only need
|
# Set the boot filename for netboot/PXE. You will only need
|
||||||
# this is you want to boot machines over the network and you will need
|
# this if you want to boot machines over the network and you will need
|
||||||
# a TFTP server; either dnsmasq's built in TFTP server or an
|
# a TFTP server; either dnsmasq's built-in TFTP server or an
|
||||||
# external one. (See below for how to enable the TFTP server.)
|
# external one. (See below for how to enable the TFTP server.)
|
||||||
#dhcp-boot=pxelinux.0
|
#dhcp-boot=pxelinux.0
|
||||||
|
|
||||||
# The same as above, but use custom tftp-server instead machine running dnsmasq
|
# The same as above, but use custom tftp-server instead machine running dnsmasq
|
||||||
#dhcp-boot=pxelinux,server.name,192.168.1.100
|
#dhcp-boot=pxelinux,server.name,192.168.1.100
|
||||||
|
|
||||||
# Boot for Etherboot gPXE. The idea is to send two different
|
# Boot for iPXE. The idea is to send two different
|
||||||
# filenames, the first loads gPXE, and the second tells gPXE what to
|
# filenames, the first loads iPXE, and the second tells iPXE what to
|
||||||
# load. The dhcp-match sets the gpxe tag for requests from gPXE.
|
# load. The dhcp-match sets the ipxe tag for requests from iPXE.
|
||||||
#dhcp-match=set:gpxe,175 # gPXE sends a 175 option.
|
#dhcp-boot=undionly.kpxe
|
||||||
#dhcp-boot=tag:!gpxe,undionly.kpxe
|
#dhcp-match=set:ipxe,175 # iPXE sends a 175 option.
|
||||||
#dhcp-boot=mybootimage
|
#dhcp-boot=tag:ipxe,http://boot.ipxe.org/demo/boot.php
|
||||||
|
|
||||||
# Encapsulated options for Etherboot gPXE. All the options are
|
# Encapsulated options for iPXE. All the options are
|
||||||
# encapsulated within option 175
|
# encapsulated within option 175
|
||||||
#dhcp-option=encap:175, 1, 5b # priority code
|
#dhcp-option=encap:175, 1, 5b # priority code
|
||||||
#dhcp-option=encap:175, 176, 1b # no-proxydhcp
|
#dhcp-option=encap:175, 176, 1b # no-proxydhcp
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ the repo, or get a copy using git protocol with the command
|
|||||||
|
|
||||||
<PRE><TT>git clone git://thekelleys.org.uk/dnsmasq.git </TT></PRE>
|
<PRE><TT>git clone git://thekelleys.org.uk/dnsmasq.git </TT></PRE>
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
<PRE><TT>git clone http://thekelleys.org.uk/git/dnsmasq.git </TT></PRE>
|
||||||
|
|
||||||
<H2>License.</H2>
|
<H2>License.</H2>
|
||||||
Dnsmasq is distributed under the GPL, version 2 or version 3 at your discretion. See the files COPYING and COPYING-v3 in the distribution
|
Dnsmasq is distributed under the GPL, version 2 or version 3 at your discretion. See the files COPYING and COPYING-v3 in the distribution
|
||||||
for details.
|
for details.
|
||||||
|
|||||||
+32
-20
@@ -182,7 +182,8 @@ OS: this was the default behaviour in versions prior to 2.43.
|
|||||||
Do not use ports less than that given as source for outbound DNS
|
Do not use ports less than that given as source for outbound DNS
|
||||||
queries. Dnsmasq picks random ports as source for outbound queries:
|
queries. Dnsmasq picks random ports as source for outbound queries:
|
||||||
when this option is given, the ports used will always to larger
|
when this option is given, the ports used will always to larger
|
||||||
than that specified. Useful for systems behind firewalls.
|
than that specified. Useful for systems behind firewalls. If not specified,
|
||||||
|
defaults to 1024.
|
||||||
.TP
|
.TP
|
||||||
.B --max-port=<port>
|
.B --max-port=<port>
|
||||||
Use ports lower than that given as source for outbound DNS queries.
|
Use ports lower than that given as source for outbound DNS queries.
|
||||||
@@ -241,7 +242,7 @@ configuration, indeed
|
|||||||
.B --auth-server
|
.B --auth-server
|
||||||
will override 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
|
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
|
resolve in the global DNS to an A and/or AAAA record which points to
|
||||||
the address dnsmasq is listening on. When an interface is specified,
|
the address dnsmasq is listening on. When an interface is specified,
|
||||||
it may be qualified with "/4" or "/6" to specify only the IPv4 or IPv6
|
it may be qualified with "/4" or "/6" to specify only the IPv4 or IPv6
|
||||||
addresses associated with the interface.
|
addresses associated with the interface.
|
||||||
@@ -464,7 +465,7 @@ is a synonym for
|
|||||||
.B server
|
.B server
|
||||||
to make configuration files clearer in this case.
|
to make configuration files clearer in this case.
|
||||||
|
|
||||||
IPv6 addresses may include a %interface scope-id, eg
|
IPv6 addresses may include an %interface scope-id, eg
|
||||||
fe80::202:a412:4512:7bbf%eth0.
|
fe80::202:a412:4512:7bbf%eth0.
|
||||||
|
|
||||||
The optional string after the @ character tells dnsmasq how to set the source of
|
The optional string after the @ character tells dnsmasq how to set the source of
|
||||||
@@ -597,7 +598,7 @@ hosts files), from DHCP, from --interface-name or from another
|
|||||||
.B --cname.
|
.B --cname.
|
||||||
If the target does not satisfy this
|
If the target does not satisfy this
|
||||||
criteria, the whole cname is ignored. The cname must be unique, but it
|
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. Indeed
|
is permissible 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:
|
it's possible to declare multiple cnames to a target in a single line, like so:
|
||||||
.B --cname=cname1,cname2,target
|
.B --cname=cname1,cname2,target
|
||||||
|
|
||||||
@@ -625,13 +626,16 @@ address by repeating the flag; in that case the first instance is used
|
|||||||
for the reverse address-to-name mapping. Note that a name used in
|
for the reverse address-to-name mapping. Note that a name used in
|
||||||
--interface-name may not appear in /etc/hosts.
|
--interface-name may not appear in /etc/hosts.
|
||||||
.TP
|
.TP
|
||||||
.B --synth-domain=<domain>,<address range>[,<prefix>]
|
.B --synth-domain=<domain>,<address range>[,<prefix>[*]]
|
||||||
Create artificial A/AAAA and PTR records for an address range. The
|
Create artificial A/AAAA and PTR records for an address range. The
|
||||||
records use the address, with periods (or colons for IPv6) replaced
|
records either seqential numbers or the address, with periods (or colons for IPv6) replaced with dashes.
|
||||||
with dashes.
|
|
||||||
|
|
||||||
An example should make this clearer.
|
An examples should make this clearer. First sequential numbers.
|
||||||
.B --synth-domain=thekelleys.org.uk,192.168.0.0/24,internal-
|
.B --synth-domain=thekelleys.org.uk,192.168.0.50,192.168.0.70,internal-*
|
||||||
|
results in the name internal-0.thekelleys.org.uk. returning 192.168.0.50, internal-1.thekelleys.org.uk returning 192.168.0.51 and so on. (note the *) The same principle applies to IPv6 addresses (where the numbers may be very large). Reverse lookups from address to name behave as expected.
|
||||||
|
|
||||||
|
Second,
|
||||||
|
.B --synth-domain=thekelleys.org.uk,192.168.0.0/24,internal- (no *)
|
||||||
will result in a query for internal-192-168-0-56.thekelleys.org.uk returning
|
will result in a query for internal-192-168-0-56.thekelleys.org.uk returning
|
||||||
192.168.0.56 and a reverse query vice versa. The same applies to IPv6,
|
192.168.0.56 and a reverse query vice versa. The same applies to IPv6,
|
||||||
but IPv6 addresses may start with '::'
|
but IPv6 addresses may start with '::'
|
||||||
@@ -641,7 +645,7 @@ 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
|
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
|
The address range can be of the form
|
||||||
<ip address>,<ip address> or <ip address>/<netmask>
|
<ip address>,<ip address> or <ip address>/<netmask> in both forms of the option.
|
||||||
.TP
|
.TP
|
||||||
.B --add-mac[=base64|text]
|
.B --add-mac[=base64|text]
|
||||||
Add the MAC address of the requestor to DNS queries which are
|
Add the MAC address of the requestor to DNS queries which are
|
||||||
@@ -655,7 +659,7 @@ 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.
|
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
|
.TP
|
||||||
.B --add-cpe-id=<string>
|
.B --add-cpe-id=<string>
|
||||||
Add a arbitrary identifying string to o DNS queries which are
|
Add an arbitrary identifying string to o DNS queries which are
|
||||||
forwarded upstream.
|
forwarded upstream.
|
||||||
.TP
|
.TP
|
||||||
.B --add-subnet[[=[<IPv4 address>/]<IPv4 prefix length>][,[<IPv6 address>/]<IPv6 prefix length>]]
|
.B --add-subnet[[=[<IPv4 address>/]<IPv4 prefix length>][,[<IPv6 address>/]<IPv6 prefix length>]]
|
||||||
@@ -715,8 +719,8 @@ is set and the upstream servers don't support DNSSEC, then DNS service will be e
|
|||||||
.TP
|
.TP
|
||||||
.B --trust-anchor=[<class>],<domain>,<key-tag>,<algorithm>,<digest-type>,<digest>
|
.B --trust-anchor=[<class>],<domain>,<key-tag>,<algorithm>,<digest-type>,<digest>
|
||||||
Provide DS records to act a trust anchors for DNSSEC
|
Provide DS records to act a trust anchors for DNSSEC
|
||||||
validation. Typically these will be the DS record(s) for Zone Signing
|
validation. Typically these will be the DS record(s) for Key Signing
|
||||||
key(s) of the root zone,
|
key(s) (KSK) of the root zone,
|
||||||
but trust anchors for limited domains are also possible. The current
|
but trust anchors for limited domains are also possible. The current
|
||||||
root-zone trust anchors may be downloaded from https://data.iana.org/root-anchors/root-anchors.xml
|
root-zone trust anchors may be downloaded from https://data.iana.org/root-anchors/root-anchors.xml
|
||||||
.TP
|
.TP
|
||||||
@@ -736,10 +740,14 @@ section on
|
|||||||
DNSSEC signatures are only valid for specified time windows, and should be rejected outside those windows. This generates an
|
DNSSEC signatures are only valid for specified time windows, and should be rejected outside those windows. This generates an
|
||||||
interesting chicken-and-egg problem for machines which don't have a hardware real time clock. For these machines to determine the correct
|
interesting chicken-and-egg problem for machines which don't have a hardware real time clock. For these machines to determine the correct
|
||||||
time typically requires use of NTP and therefore DNS, but validating DNS requires that the correct time is already known. Setting this flag
|
time typically requires use of NTP and therefore DNS, but validating DNS requires that the correct time is already known. Setting this flag
|
||||||
removes the time-window checks (but not other DNSSEC validation.) only until the dnsmasq process receives SIGHUP. The intention is
|
removes the time-window checks (but not other DNSSEC validation.) only until the dnsmasq process receives SIGINT. The intention is
|
||||||
that dnsmasq should be started with this flag when the platform determines that reliable time is not currently available. As soon as
|
that dnsmasq should be started with this flag when the platform determines that reliable time is not currently available. As soon as
|
||||||
reliable time is established, a SIGHUP should be sent to dnsmasq, which enables time checking, and purges the cache of DNS records
|
reliable time is established, a SIGINT should be sent to dnsmasq, which enables time checking, and purges the cache of DNS records
|
||||||
which have not been throughly checked.
|
which have not been thoroughly checked.
|
||||||
|
|
||||||
|
Earlier versions of dnsmasq overloaded SIGHUP (which re-reads much configuration) to also enable time validation.
|
||||||
|
|
||||||
|
If dnsmasq is run in debug mode (-d flag) then SIGINT retains its usual meaning of terminating the dnsmasq process.
|
||||||
.TP
|
.TP
|
||||||
.B --dnssec-timestamp=<path>
|
.B --dnssec-timestamp=<path>
|
||||||
Enables an alternative way of checking the validity of the system time for DNSSEC (see --dnssec-no-timecheck). In this case, the
|
Enables an alternative way of checking the validity of the system time for DNSSEC (see --dnssec-no-timecheck). In this case, the
|
||||||
@@ -1073,7 +1081,7 @@ in a dhcp-optsfile.
|
|||||||
This is equivalent to dhcp-hostsfile, except for the following. The path MUST be a
|
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
|
directory, and not an individual file. Changed or new files within
|
||||||
the directory are read automatically, without the need to send SIGHUP.
|
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
|
If a file is deleted or changed after it has been read by dnsmasq, then the
|
||||||
host record it contained will remain until dnsmasq receives a SIGHUP, or
|
host record it contained will remain until dnsmasq receives a SIGHUP, or
|
||||||
is restarted; ie host records are only added dynamically.
|
is restarted; ie host records are only added dynamically.
|
||||||
.TP
|
.TP
|
||||||
@@ -1315,7 +1323,7 @@ Perform boolean operations on tags. Any tag appearing as set:<tag> is set if
|
|||||||
all the tags which appear as tag:<tag> are set, (or unset when tag:!<tag> is used)
|
all the tags which appear as tag:<tag> are set, (or unset when tag:!<tag> is used)
|
||||||
If no tag:<tag> appears set:<tag> tags are set unconditionally.
|
If no tag:<tag> appears set:<tag> tags are set unconditionally.
|
||||||
Any number of set: and tag: forms may appear, in any order.
|
Any number of set: and tag: forms may appear, in any order.
|
||||||
Tag-if lines ares executed in order, so if the tag in tag:<tag> is a
|
Tag-if lines are executed in order, so if the tag in tag:<tag> is a
|
||||||
tag set by another
|
tag set by another
|
||||||
.B tag-if,
|
.B tag-if,
|
||||||
the line which sets the tag must precede the one which tests it.
|
the line which sets the tag must precede the one which tests it.
|
||||||
@@ -1691,13 +1699,17 @@ option also forces the leasechange script to be called on changes
|
|||||||
to the client-id and lease length and expiry time.
|
to the client-id and lease length and expiry time.
|
||||||
.TP
|
.TP
|
||||||
.B --bridge-interface=<interface>,<alias>[,<alias>]
|
.B --bridge-interface=<interface>,<alias>[,<alias>]
|
||||||
Treat DHCP (v4 and v6) request and IPv6 Router Solicit packets
|
Treat DHCP (v4 and v6) requests and IPv6 Router Solicit packets
|
||||||
arriving at any of the <alias> interfaces as if they had arrived at
|
arriving at any of the <alias> interfaces as if they had arrived at
|
||||||
<interface>. This option allows dnsmasq to provide DHCP and RA
|
<interface>. This option allows dnsmasq to provide DHCP and RA
|
||||||
service over unaddressed and unbridged Ethernet interfaces, e.g. on an
|
service over unaddressed and unbridged Ethernet interfaces, e.g. on an
|
||||||
OpenStack compute host where each such interface is a TAP interface to
|
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 '*'
|
a VM, or as in "old style bridging" on BSD platforms. A trailing '*'
|
||||||
wildcard can be used in each <alias>.
|
wildcard can be used in each <alias>.
|
||||||
|
|
||||||
|
It is permissible to add more than one alias using more than one --bridge-interface option since
|
||||||
|
--bridge-interface=int1,alias1,alias2 is exactly equivalent to
|
||||||
|
--bridge-interface=int1,alias1 --bridge-interface=int1,alias2
|
||||||
.TP
|
.TP
|
||||||
.B \-s, --domain=<domain>[,<address range>[,local]]
|
.B \-s, --domain=<domain>[,<address range>[,local]]
|
||||||
Specifies DNS domains for the DHCP server. Domains may be be given
|
Specifies DNS domains for the DHCP server. Domains may be be given
|
||||||
@@ -1979,7 +1991,7 @@ and
|
|||||||
|
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
Dnsmasq is a DNS query forwarder: it it not capable of recursively
|
Dnsmasq is a DNS query forwarder: it is not capable of recursively
|
||||||
answering arbitrary queries starting from the root servers but
|
answering arbitrary queries starting from the root servers but
|
||||||
forwards such queries to a fully recursive upstream DNS server which is
|
forwards such queries to a fully recursive upstream DNS server which is
|
||||||
typically provided by an ISP. By default, dnsmasq reads
|
typically provided by an ISP. By default, dnsmasq reads
|
||||||
|
|||||||
+196
-191
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -125,7 +125,7 @@ address of its ethernet card. For the former to work, a machine needs to know it
|
|||||||
requests a DHCP lease. For dhcpcd, the -h option specifies this. The
|
requests a DHCP lease. For dhcpcd, the -h option specifies this. The
|
||||||
names may be anything as far as DHCP is concerned, but dnsmasq adds
|
names may be anything as far as DHCP is concerned, but dnsmasq adds
|
||||||
some limitations. By default the names must no have a domain part, ie
|
some limitations. By default the names must no have a domain part, ie
|
||||||
they must just be a alphanumeric name, without any dots. This is a
|
they must just be alphanumeric names, without any dots. This is a
|
||||||
security feature to stop a machine on your network telling DHCP that
|
security feature to stop a machine on your network telling DHCP that
|
||||||
its name is "www.microsoft.com" and thereby grabbing traffic which
|
its name is "www.microsoft.com" and thereby grabbing traffic which
|
||||||
shouldn't go to it. A domain part is only allowed by dnsmasq in DHCP machine names
|
shouldn't go to it. A domain part is only allowed by dnsmasq in DHCP machine names
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+4
-3
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
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));
|
struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
|
||||||
|
|
||||||
if (n > 0 && new)
|
if (new)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ void blockdata_init(void)
|
|||||||
|
|
||||||
/* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
|
/* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
blockdata_expand((daemon->cachesize * 100) / sizeof(struct blockdata));
|
blockdata_expand(daemon->cachesize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void blockdata_report(void)
|
void blockdata_report(void)
|
||||||
@@ -100,6 +100,7 @@ struct blockdata *blockdata_alloc(char *data, size_t len)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void blockdata_free(struct blockdata *blocks)
|
void blockdata_free(struct blockdata *blocks)
|
||||||
{
|
{
|
||||||
struct blockdata *tmp;
|
struct blockdata *tmp;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+6
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -45,6 +45,7 @@ static const struct {
|
|||||||
{ 24, "SIG" },
|
{ 24, "SIG" },
|
||||||
{ 25, "KEY" },
|
{ 25, "KEY" },
|
||||||
{ 28, "AAAA" },
|
{ 28, "AAAA" },
|
||||||
|
{ 29, "LOC" },
|
||||||
{ 33, "SRV" },
|
{ 33, "SRV" },
|
||||||
{ 35, "NAPTR" },
|
{ 35, "NAPTR" },
|
||||||
{ 36, "KX" },
|
{ 36, "KX" },
|
||||||
@@ -57,6 +58,10 @@ static const struct {
|
|||||||
{ 47, "NSEC" },
|
{ 47, "NSEC" },
|
||||||
{ 48, "DNSKEY" },
|
{ 48, "DNSKEY" },
|
||||||
{ 50, "NSEC3" },
|
{ 50, "NSEC3" },
|
||||||
|
{ 51, "NSEC3PARAM" },
|
||||||
|
{ 52, "TLSA" },
|
||||||
|
{ 53, "SMIMEA" },
|
||||||
|
{ 55, "HIP" },
|
||||||
{ 249, "TKEY" },
|
{ 249, "TKEY" },
|
||||||
{ 250, "TSIG" },
|
{ 250, "TSIG" },
|
||||||
{ 251, "IXFR" },
|
{ 251, "IXFR" },
|
||||||
|
|||||||
+2
-4
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
||||||
#define FORWARD_TEST 50 /* try all servers every 50 queries */
|
#define FORWARD_TEST 50 /* try all servers every 50 queries */
|
||||||
#define FORWARD_TIME 20 /* or 20 seconds */
|
#define FORWARD_TIME 20 /* or 20 seconds */
|
||||||
|
#define UDP_TEST_TIME 60 /* How often to reset our idea of max packet size. */
|
||||||
#define SERVERS_LOGGED 30 /* Only log this many servers when logging state */
|
#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 LOCALS_LOGGED 8 /* Only log this many local addresses when logging state */
|
||||||
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
|
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
|
||||||
@@ -136,9 +137,6 @@ NO_INOTIFY
|
|||||||
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
|
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
|
||||||
which are enabled by default in the distributed source tree. Building dnsmasq
|
which are enabled by default in the distributed source tree. Building dnsmasq
|
||||||
with something like "make COPTS=-DNO_SCRIPT" will do the trick.
|
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
|
NO_GMP
|
||||||
Don't use and link against libgmp, Useful if nettle is built with --enable-mini-gmp.
|
Don't use and link against libgmp, Useful if nettle is built with --enable-mini-gmp.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+460
@@ -0,0 +1,460 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 dated June, 1991, or
|
||||||
|
(at your option) version 3 dated 29 June, 2007.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
|
||||||
|
#include <nettle/rsa.h>
|
||||||
|
#include <nettle/dsa.h>
|
||||||
|
#include <nettle/ecdsa.h>
|
||||||
|
#include <nettle/ecc-curve.h>
|
||||||
|
#include <nettle/eddsa.h>
|
||||||
|
#include <nettle/nettle-meta.h>
|
||||||
|
#include <nettle/bignum.h>
|
||||||
|
|
||||||
|
/* Implement a "hash-function" to the nettle API, which simply returns
|
||||||
|
the input data, concatenated into a single, statically maintained, buffer.
|
||||||
|
|
||||||
|
Used for the EdDSA sigs, which operate on the whole message, rather
|
||||||
|
than a digest. */
|
||||||
|
|
||||||
|
struct null_hash_digest
|
||||||
|
{
|
||||||
|
uint8_t *buff;
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct null_hash_ctx
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t null_hash_buff_sz = 0;
|
||||||
|
static uint8_t *null_hash_buff = NULL;
|
||||||
|
#define BUFF_INCR 128
|
||||||
|
|
||||||
|
static void null_hash_init(void *ctx)
|
||||||
|
{
|
||||||
|
((struct null_hash_ctx *)ctx)->len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void null_hash_update(void *ctxv, size_t length, const uint8_t *src)
|
||||||
|
{
|
||||||
|
struct null_hash_ctx *ctx = ctxv;
|
||||||
|
size_t new_len = ctx->len + length;
|
||||||
|
|
||||||
|
if (new_len > null_hash_buff_sz)
|
||||||
|
{
|
||||||
|
uint8_t *new;
|
||||||
|
|
||||||
|
if (!(new = whine_malloc(new_len + BUFF_INCR)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (null_hash_buff)
|
||||||
|
{
|
||||||
|
if (ctx->len != 0)
|
||||||
|
memcpy(new, null_hash_buff, ctx->len);
|
||||||
|
free(null_hash_buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
null_hash_buff_sz = new_len + BUFF_INCR;
|
||||||
|
null_hash_buff = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(null_hash_buff + ctx->len, src, length);
|
||||||
|
ctx->len += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void null_hash_digest(void *ctx, size_t length, uint8_t *dst)
|
||||||
|
{
|
||||||
|
(void)length;
|
||||||
|
|
||||||
|
((struct null_hash_digest *)dst)->buff = null_hash_buff;
|
||||||
|
((struct null_hash_digest *)dst)->len = ((struct null_hash_ctx *)ctx)->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nettle_hash null_hash = {
|
||||||
|
"null_hash",
|
||||||
|
sizeof(struct null_hash_ctx),
|
||||||
|
sizeof(struct null_hash_digest),
|
||||||
|
0,
|
||||||
|
(nettle_hash_init_func *) null_hash_init,
|
||||||
|
(nettle_hash_update_func *) null_hash_update,
|
||||||
|
(nettle_hash_digest_func *) null_hash_digest
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Find pointer to correct hash function in nettle library */
|
||||||
|
const struct nettle_hash *hash_find(char *name)
|
||||||
|
{
|
||||||
|
if (!name)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* We provide a "null" hash which returns the input data as digest. */
|
||||||
|
if (strcmp(null_hash.name, name) == 0)
|
||||||
|
return &null_hash;
|
||||||
|
|
||||||
|
/* libnettle >= 3.4 provides nettle_lookup_hash() which avoids nasty ABI
|
||||||
|
incompatibilities if sizeof(nettle_hashes) changes between library
|
||||||
|
versions. It also #defines nettle_hashes, so use that to tell
|
||||||
|
if we have the new facilities. */
|
||||||
|
|
||||||
|
#ifdef nettle_hashes
|
||||||
|
return nettle_lookup_hash(name);
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; nettle_hashes[i]; i++)
|
||||||
|
if (strcmp(nettle_hashes[i]->name, name) == 0)
|
||||||
|
return nettle_hashes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expand ctx and digest memory allocations if necessary and init hash function */
|
||||||
|
int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
|
||||||
|
{
|
||||||
|
static void *ctx = NULL;
|
||||||
|
static unsigned char *digest = NULL;
|
||||||
|
static unsigned int ctx_sz = 0;
|
||||||
|
static unsigned int digest_sz = 0;
|
||||||
|
|
||||||
|
void *new;
|
||||||
|
|
||||||
|
if (ctx_sz < hash->context_size)
|
||||||
|
{
|
||||||
|
if (!(new = whine_malloc(hash->context_size)))
|
||||||
|
return 0;
|
||||||
|
if (ctx)
|
||||||
|
free(ctx);
|
||||||
|
ctx = new;
|
||||||
|
ctx_sz = hash->context_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (digest_sz < hash->digest_size)
|
||||||
|
{
|
||||||
|
if (!(new = whine_malloc(hash->digest_size)))
|
||||||
|
return 0;
|
||||||
|
if (digest)
|
||||||
|
free(digest);
|
||||||
|
digest = new;
|
||||||
|
digest_sz = hash->digest_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ctxp = ctx;
|
||||||
|
*digestp = digest;
|
||||||
|
|
||||||
|
hash->init(ctx);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
size_t exp_len;
|
||||||
|
|
||||||
|
static struct rsa_public_key *key = NULL;
|
||||||
|
static mpz_t sig_mpz;
|
||||||
|
|
||||||
|
(void)digest_len;
|
||||||
|
|
||||||
|
if (key == NULL)
|
||||||
|
{
|
||||||
|
if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nettle_rsa_public_key_init(key);
|
||||||
|
mpz_init(sig_mpz);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
key_len--;
|
||||||
|
if ((exp_len = *p++) == 0)
|
||||||
|
{
|
||||||
|
GETSHORT(exp_len, p);
|
||||||
|
key_len -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp_len >= key_len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
key->size = key_len - exp_len;
|
||||||
|
mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
|
||||||
|
mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
|
||||||
|
|
||||||
|
mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
|
||||||
|
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return nettle_rsa_md5_verify_digest(key, digest, sig_mpz);
|
||||||
|
case 5: case 7:
|
||||||
|
return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
|
||||||
|
case 8:
|
||||||
|
return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
|
||||||
|
case 10:
|
||||||
|
return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dnsmasq_dsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
unsigned int t;
|
||||||
|
|
||||||
|
static mpz_t y;
|
||||||
|
static struct dsa_params *params = NULL;
|
||||||
|
static struct dsa_signature *sig_struct;
|
||||||
|
|
||||||
|
(void)digest_len;
|
||||||
|
|
||||||
|
if (params == NULL)
|
||||||
|
{
|
||||||
|
if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
|
||||||
|
!(params = whine_malloc(sizeof(struct dsa_params))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mpz_init(y);
|
||||||
|
nettle_dsa_params_init(params);
|
||||||
|
nettle_dsa_signature_init(sig_struct);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sig_len < 41) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
t = *p++;
|
||||||
|
|
||||||
|
if (key_len < (213 + (t * 24)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mpz_import(params->q, 20, 1, 1, 0, 0, p); p += 20;
|
||||||
|
mpz_import(params->p, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
|
||||||
|
mpz_import(params->g, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
|
||||||
|
mpz_import(y, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
|
||||||
|
|
||||||
|
mpz_import(sig_struct->r, 20, 1, 1, 0, 0, sig+1);
|
||||||
|
mpz_import(sig_struct->s, 20, 1, 1, 0, 0, sig+21);
|
||||||
|
|
||||||
|
(void)algo;
|
||||||
|
|
||||||
|
return nettle_dsa_verify(params, y, digest_len, digest, sig_struct);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len,
|
||||||
|
unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
unsigned int t;
|
||||||
|
struct ecc_point *key;
|
||||||
|
|
||||||
|
static struct ecc_point *key_256 = NULL, *key_384 = NULL;
|
||||||
|
static mpz_t x, y;
|
||||||
|
static struct dsa_signature *sig_struct;
|
||||||
|
|
||||||
|
if (!sig_struct)
|
||||||
|
{
|
||||||
|
if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nettle_dsa_signature_init(sig_struct);
|
||||||
|
mpz_init(x);
|
||||||
|
mpz_init(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case 13:
|
||||||
|
if (!key_256)
|
||||||
|
{
|
||||||
|
if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nettle_ecc_point_init(key_256, &nettle_secp_256r1);
|
||||||
|
}
|
||||||
|
|
||||||
|
key = key_256;
|
||||||
|
t = 32;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 14:
|
||||||
|
if (!key_384)
|
||||||
|
{
|
||||||
|
if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nettle_ecc_point_init(key_384, &nettle_secp_384r1);
|
||||||
|
}
|
||||||
|
|
||||||
|
key = key_384;
|
||||||
|
t = 48;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sig_len != 2*t || key_len != 2*t ||
|
||||||
|
!(p = blockdata_retrieve(key_data, key_len, NULL)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mpz_import(x, t , 1, 1, 0, 0, p);
|
||||||
|
mpz_import(y, t , 1, 1, 0, 0, p + t);
|
||||||
|
|
||||||
|
if (!ecc_point_set(key, x, y))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
|
||||||
|
mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
|
||||||
|
|
||||||
|
return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dnsmasq_eddsa_verify(struct blockdata *key_data, unsigned int key_len,
|
||||||
|
unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
|
if (key_len != ED25519_KEY_SIZE ||
|
||||||
|
sig_len != ED25519_SIGNATURE_SIZE ||
|
||||||
|
digest_len != sizeof(struct null_hash_digest) ||
|
||||||
|
!(p = blockdata_retrieve(key_data, key_len, NULL)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* The "digest" returned by the null_hash function is simply a struct null_hash_digest
|
||||||
|
which has a pointer to the actual data and a length, because the buffer
|
||||||
|
may need to be extended during "hashing". */
|
||||||
|
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case 15:
|
||||||
|
return ed25519_sha512_verify(p,
|
||||||
|
((struct null_hash_digest *)digest)->len,
|
||||||
|
((struct null_hash_digest *)digest)->buff,
|
||||||
|
sig);
|
||||||
|
case 16:
|
||||||
|
/* Ed448 when available */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Enure at runtime that we have support for this digest */
|
||||||
|
if (!hash_find(algo_digest_name(algo)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* This switch defines which sig algorithms we support, can't introspect Nettle for that. */
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case 1: case 5: case 7: case 8: case 10:
|
||||||
|
return dnsmasq_rsa_verify;
|
||||||
|
|
||||||
|
case 3: case 6:
|
||||||
|
return dnsmasq_dsa_verify;
|
||||||
|
|
||||||
|
case 13: case 14:
|
||||||
|
return dnsmasq_ecdsa_verify;
|
||||||
|
|
||||||
|
case 15: case 16:
|
||||||
|
return dnsmasq_eddsa_verify;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo)
|
||||||
|
{
|
||||||
|
|
||||||
|
int (*func)(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo);
|
||||||
|
|
||||||
|
func = verify_func(algo);
|
||||||
|
|
||||||
|
if (!func)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (*func)(key_data, key_len, sig, sig_len, digest, digest_len, algo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note the ds_digest_name(), algo_digest_name() and nsec3_digest_name()
|
||||||
|
define which algo numbers we support. If algo_digest_name() returns
|
||||||
|
non-NULL for an algorithm number, we assume that algorithm is
|
||||||
|
supported by verify(). */
|
||||||
|
|
||||||
|
/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
|
||||||
|
char *ds_digest_name(int digest)
|
||||||
|
{
|
||||||
|
switch (digest)
|
||||||
|
{
|
||||||
|
case 1: return "sha1";
|
||||||
|
case 2: return "sha256";
|
||||||
|
case 3: return "gosthash94";
|
||||||
|
case 4: return "sha384";
|
||||||
|
default: return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
|
||||||
|
char *algo_digest_name(int algo)
|
||||||
|
{
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case 1: return NULL; /* RSA/MD5 - Must Not Implement. RFC 6944 para 2.3. */
|
||||||
|
case 2: return NULL; /* Diffie-Hellman */
|
||||||
|
case 3: return "sha1"; /* DSA/SHA1 */
|
||||||
|
case 5: return "sha1"; /* RSA/SHA1 */
|
||||||
|
case 6: return "sha1"; /* DSA-NSEC3-SHA1 */
|
||||||
|
case 7: return "sha1"; /* RSASHA1-NSEC3-SHA1 */
|
||||||
|
case 8: return "sha256"; /* RSA/SHA-256 */
|
||||||
|
case 10: return "sha512"; /* RSA/SHA-512 */
|
||||||
|
case 12: return NULL; /* ECC-GOST */
|
||||||
|
case 13: return "sha256"; /* ECDSAP256SHA256 */
|
||||||
|
case 14: return "sha384"; /* ECDSAP384SHA384 */
|
||||||
|
case 15: return "null_hash"; /* ED25519 */
|
||||||
|
case 16: return NULL; /* ED448 */
|
||||||
|
default: return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
|
||||||
|
char *nsec3_digest_name(int digest)
|
||||||
|
{
|
||||||
|
switch (digest)
|
||||||
|
{
|
||||||
|
case 1: return "sha1";
|
||||||
|
default: return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+2
-5
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -485,11 +485,8 @@ char *whichdevice(void)
|
|||||||
|
|
||||||
void bindtodevice(char *device, int fd)
|
void bindtodevice(char *device, int fd)
|
||||||
{
|
{
|
||||||
struct ifreq ifr;
|
|
||||||
|
|
||||||
strcpy(ifr.ifr_name, device);
|
|
||||||
/* only allowed by root. */
|
/* only allowed by root. */
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
|
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, IFNAMSIZ) == -1 &&
|
||||||
errno != EPERM)
|
errno != EPERM)
|
||||||
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
|
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+2
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#define NAMESERVER_PORT 53
|
#define NAMESERVER_PORT 53
|
||||||
#define TFTP_PORT 69
|
#define TFTP_PORT 69
|
||||||
|
#define MIN_PORT 1024 /* first non-reserved port */
|
||||||
#define MAX_PORT 65535u
|
#define MAX_PORT 65535u
|
||||||
|
|
||||||
#define IN6ADDRSZ 16
|
#define IN6ADDRSZ 16
|
||||||
|
|||||||
+64
-28
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -48,6 +48,7 @@ int main (int argc, char **argv)
|
|||||||
long i, max_fd = sysconf(_SC_OPEN_MAX);
|
long i, max_fd = sysconf(_SC_OPEN_MAX);
|
||||||
char *baduser = NULL;
|
char *baduser = NULL;
|
||||||
int log_err;
|
int log_err;
|
||||||
|
int chown_warn = 0;
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
cap_user_header_t hdr = NULL;
|
cap_user_header_t hdr = NULL;
|
||||||
cap_user_data_t data = NULL;
|
cap_user_data_t data = NULL;
|
||||||
@@ -77,7 +78,8 @@ int main (int argc, char **argv)
|
|||||||
sigaction(SIGTERM, &sigact, NULL);
|
sigaction(SIGTERM, &sigact, NULL);
|
||||||
sigaction(SIGALRM, &sigact, NULL);
|
sigaction(SIGALRM, &sigact, NULL);
|
||||||
sigaction(SIGCHLD, &sigact, NULL);
|
sigaction(SIGCHLD, &sigact, NULL);
|
||||||
|
sigaction(SIGINT, &sigact, NULL);
|
||||||
|
|
||||||
/* ignore SIGPIPE */
|
/* ignore SIGPIPE */
|
||||||
sigact.sa_handler = SIG_IGN;
|
sigact.sa_handler = SIG_IGN;
|
||||||
sigaction(SIGPIPE, &sigact, NULL);
|
sigaction(SIGPIPE, &sigact, NULL);
|
||||||
@@ -118,6 +120,9 @@ int main (int argc, char **argv)
|
|||||||
daemon->namebuff = safe_malloc(MAXDNAME * 2);
|
daemon->namebuff = safe_malloc(MAXDNAME * 2);
|
||||||
daemon->keyname = safe_malloc(MAXDNAME * 2);
|
daemon->keyname = safe_malloc(MAXDNAME * 2);
|
||||||
daemon->workspacename = safe_malloc(MAXDNAME * 2);
|
daemon->workspacename = safe_malloc(MAXDNAME * 2);
|
||||||
|
/* one char flag per possible RR in answer section (may get extended). */
|
||||||
|
daemon->rr_status_sz = 64;
|
||||||
|
daemon->rr_status = safe_malloc(daemon->rr_status_sz);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -220,9 +225,6 @@ int main (int argc, char **argv)
|
|||||||
die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
|
die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (daemon->max_port != MAX_PORT && daemon->min_port == 0)
|
|
||||||
daemon->min_port = 1024u;
|
|
||||||
|
|
||||||
if (daemon->max_port < daemon->min_port)
|
if (daemon->max_port < daemon->min_port)
|
||||||
die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
|
die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
|
||||||
|
|
||||||
@@ -358,7 +360,8 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_INOTIFY
|
#ifdef HAVE_INOTIFY
|
||||||
if (daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
|
if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
|
||||||
|
&& (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
|
||||||
inotify_dnsmasq_init();
|
inotify_dnsmasq_init();
|
||||||
else
|
else
|
||||||
daemon->inotifyfd = -1;
|
daemon->inotifyfd = -1;
|
||||||
@@ -386,10 +389,12 @@ int main (int argc, char **argv)
|
|||||||
daemon->scriptuser &&
|
daemon->scriptuser &&
|
||||||
(daemon->lease_change_command || daemon->luascript))
|
(daemon->lease_change_command || daemon->luascript))
|
||||||
{
|
{
|
||||||
if ((ent_pw = getpwnam(daemon->scriptuser)))
|
struct passwd *scr_pw;
|
||||||
|
|
||||||
|
if ((scr_pw = getpwnam(daemon->scriptuser)))
|
||||||
{
|
{
|
||||||
script_uid = ent_pw->pw_uid;
|
script_uid = scr_pw->pw_uid;
|
||||||
script_gid = ent_pw->pw_gid;
|
script_gid = scr_pw->pw_gid;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
baduser = daemon->scriptuser;
|
baduser = daemon->scriptuser;
|
||||||
@@ -537,9 +542,18 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* We're still running as root here. Change the ownership of the PID file
|
||||||
|
to the user we will be running as. Note that this is not to allow
|
||||||
|
us to delete the file, since that depends on the permissions
|
||||||
|
of the directory containing the file. That directory will
|
||||||
|
need to by owned by the dnsmasq user, and the ownership of the
|
||||||
|
file has to match, to keep systemd >273 happy. */
|
||||||
|
if (getuid() == 0 && ent_pw && ent_pw->pw_uid != 0 && fchown(fd, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
|
||||||
|
chown_warn = errno;
|
||||||
|
|
||||||
if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
|
if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
|
||||||
err = 1;
|
err = 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (retry_send(close(fd)));
|
while (retry_send(close(fd)));
|
||||||
if (errno != 0)
|
if (errno != 0)
|
||||||
@@ -726,6 +740,9 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
|
my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
|
||||||
|
|
||||||
|
if (chown_warn != 0)
|
||||||
|
my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
|
||||||
|
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
if (option_bool(OPT_DBUS))
|
if (option_bool(OPT_DBUS))
|
||||||
@@ -755,7 +772,7 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
daemon->dnssec_no_time_check = 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)
|
if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
|
||||||
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
|
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
|
||||||
|
|
||||||
if (rc == 1)
|
if (rc == 1)
|
||||||
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
|
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
|
||||||
@@ -1079,7 +1096,7 @@ static void sig_handler(int sig)
|
|||||||
{
|
{
|
||||||
/* ignore anything other than TERM during startup
|
/* ignore anything other than TERM during startup
|
||||||
and in helper proc. (helper ignore TERM too) */
|
and in helper proc. (helper ignore TERM too) */
|
||||||
if (sig == SIGTERM)
|
if (sig == SIGTERM || sig == SIGINT)
|
||||||
exit(EC_MISC);
|
exit(EC_MISC);
|
||||||
}
|
}
|
||||||
else if (pid != getpid())
|
else if (pid != getpid())
|
||||||
@@ -1105,6 +1122,15 @@ static void sig_handler(int sig)
|
|||||||
event = EVENT_DUMP;
|
event = EVENT_DUMP;
|
||||||
else if (sig == SIGUSR2)
|
else if (sig == SIGUSR2)
|
||||||
event = EVENT_REOPEN;
|
event = EVENT_REOPEN;
|
||||||
|
else if (sig == SIGINT)
|
||||||
|
{
|
||||||
|
/* Handle SIGINT normally in debug mode, so
|
||||||
|
ctrl-c continues to operate. */
|
||||||
|
if (option_bool(OPT_DEBUG))
|
||||||
|
exit(EC_MISC);
|
||||||
|
else
|
||||||
|
event = EVENT_TIME;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1187,31 +1213,40 @@ static void fatal_event(struct event_desc *ev, char *msg)
|
|||||||
|
|
||||||
case EVENT_FORK_ERR:
|
case EVENT_FORK_ERR:
|
||||||
die(_("cannot fork into background: %s"), NULL, EC_MISC);
|
die(_("cannot fork into background: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_PIPE_ERR:
|
case EVENT_PIPE_ERR:
|
||||||
die(_("failed to create helper: %s"), NULL, EC_MISC);
|
die(_("failed to create helper: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_CAP_ERR:
|
case EVENT_CAP_ERR:
|
||||||
die(_("setting capabilities failed: %s"), NULL, EC_MISC);
|
die(_("setting capabilities failed: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_USER_ERR:
|
case EVENT_USER_ERR:
|
||||||
die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
|
die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_GROUP_ERR:
|
case EVENT_GROUP_ERR:
|
||||||
die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
|
die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_PIDFILE:
|
case EVENT_PIDFILE:
|
||||||
die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
|
die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_LOG_ERR:
|
case EVENT_LOG_ERR:
|
||||||
die(_("cannot open log %s: %s"), msg, EC_FILE);
|
die(_("cannot open log %s: %s"), msg, EC_FILE);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_LUA_ERR:
|
case EVENT_LUA_ERR:
|
||||||
die(_("failed to load Lua script: %s"), msg, EC_MISC);
|
die(_("failed to load Lua script: %s"), msg, EC_MISC);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_TFTP_ERR:
|
case EVENT_TFTP_ERR:
|
||||||
die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
|
die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_TIME_ERR:
|
case EVENT_TIME_ERR:
|
||||||
die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
|
die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
|
||||||
}
|
}
|
||||||
@@ -1232,14 +1267,7 @@ static void async_event(int pipe, time_t now)
|
|||||||
{
|
{
|
||||||
case EVENT_RELOAD:
|
case EVENT_RELOAD:
|
||||||
daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
|
daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
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"));
|
|
||||||
daemon->dnssec_no_time_check = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
case EVENT_INIT:
|
case EVENT_INIT:
|
||||||
@@ -1348,6 +1376,17 @@ static void async_event(int pipe, time_t now)
|
|||||||
poll_resolv(0, 1, now);
|
poll_resolv(0, 1, now);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EVENT_TIME:
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
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"));
|
||||||
|
daemon->dnssec_no_time_check = 0;
|
||||||
|
clear_cache_and_reload(now);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
case EVENT_TERM:
|
case EVENT_TERM:
|
||||||
/* Knock all our children on the head. */
|
/* Knock all our children on the head. */
|
||||||
for (i = 0; i < MAX_PROCS; i++)
|
for (i = 0; i < MAX_PROCS; i++)
|
||||||
@@ -1472,9 +1511,6 @@ void clear_cache_and_reload(time_t now)
|
|||||||
if (option_bool(OPT_ETHERS))
|
if (option_bool(OPT_ETHERS))
|
||||||
dhcp_read_ethers();
|
dhcp_read_ethers();
|
||||||
reread_dhcp();
|
reread_dhcp();
|
||||||
#ifdef HAVE_INOTIFY
|
|
||||||
set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0);
|
|
||||||
#endif
|
|
||||||
dhcp_update_configs(daemon->dhcp_conf);
|
dhcp_update_configs(daemon->dhcp_conf);
|
||||||
lease_update_from_configs();
|
lease_update_from_configs();
|
||||||
lease_update_file(now);
|
lease_update_file(now);
|
||||||
|
|||||||
+22
-4
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define COPYRIGHT "Copyright (c) 2000-2017 Simon Kelley"
|
#define COPYRIGHT "Copyright (c) 2000-2018 Simon Kelley"
|
||||||
|
|
||||||
/* We do defines that influence behavior of stdio.h, so complain
|
/* We do defines that influence behavior of stdio.h, so complain
|
||||||
if included too early. */
|
if included too early. */
|
||||||
@@ -142,6 +142,10 @@ extern int capget(cap_user_header_t header, cap_user_data_t data);
|
|||||||
#include <priv.h>
|
#include <priv.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
# include <nettle/nettle-meta.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* daemon is function in the C library.... */
|
/* daemon is function in the C library.... */
|
||||||
#define daemon dnsmasq_daemon
|
#define daemon dnsmasq_daemon
|
||||||
|
|
||||||
@@ -175,6 +179,7 @@ struct event_desc {
|
|||||||
#define EVENT_NEWROUTE 23
|
#define EVENT_NEWROUTE 23
|
||||||
#define EVENT_TIME_ERR 24
|
#define EVENT_TIME_ERR 24
|
||||||
#define EVENT_SCRIPT_LOG 25
|
#define EVENT_SCRIPT_LOG 25
|
||||||
|
#define EVENT_TIME 26
|
||||||
|
|
||||||
/* Exit codes. */
|
/* Exit codes. */
|
||||||
#define EC_GOOD 0
|
#define EC_GOOD 0
|
||||||
@@ -452,6 +457,7 @@ struct crec {
|
|||||||
#define F_NO_RR (1u<<25)
|
#define F_NO_RR (1u<<25)
|
||||||
#define F_IPSET (1u<<26)
|
#define F_IPSET (1u<<26)
|
||||||
#define F_NOEXTRA (1u<<27)
|
#define F_NOEXTRA (1u<<27)
|
||||||
|
#define F_SERVFAIL (1u<<28)
|
||||||
|
|
||||||
/* Values of uid in crecs with F_CONFIG bit set. */
|
/* Values of uid in crecs with F_CONFIG bit set. */
|
||||||
#define SRC_INTERFACE 0
|
#define SRC_INTERFACE 0
|
||||||
@@ -514,6 +520,7 @@ struct server {
|
|||||||
struct serverfd *sfd;
|
struct serverfd *sfd;
|
||||||
char *domain; /* set if this server only handles a domain. */
|
char *domain; /* set if this server only handles a domain. */
|
||||||
int flags, tcpfd, edns_pktsz;
|
int flags, tcpfd, edns_pktsz;
|
||||||
|
time_t pktsz_reduced;
|
||||||
unsigned int queries, failed_queries;
|
unsigned int queries, failed_queries;
|
||||||
#ifdef HAVE_LOOP
|
#ifdef HAVE_LOOP
|
||||||
u32 uid;
|
u32 uid;
|
||||||
@@ -832,7 +839,7 @@ struct cond_domain {
|
|||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
struct in6_addr start6, end6;
|
struct in6_addr start6, end6;
|
||||||
#endif
|
#endif
|
||||||
int is6;
|
int is6, indexed;
|
||||||
struct cond_domain *next;
|
struct cond_domain *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1025,6 +1032,8 @@ extern struct daemon {
|
|||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
char *keyname; /* MAXDNAME size buffer */
|
char *keyname; /* MAXDNAME size buffer */
|
||||||
char *workspacename; /* ditto */
|
char *workspacename; /* ditto */
|
||||||
|
char *rr_status; /* flags for individual RRs */
|
||||||
|
int rr_status_sz;
|
||||||
#endif
|
#endif
|
||||||
unsigned int local_answer, queries_forwarded, auth_answer;
|
unsigned int local_answer, queries_forwarded, auth_answer;
|
||||||
struct frec *frec_list;
|
struct frec *frec_list;
|
||||||
@@ -1178,6 +1187,15 @@ size_t filter_rrsigs(struct dns_header *header, size_t plen);
|
|||||||
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
|
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
|
||||||
int setup_timestamp(void);
|
int setup_timestamp(void);
|
||||||
|
|
||||||
|
/* crypto.c */
|
||||||
|
const struct nettle_hash *hash_find(char *name);
|
||||||
|
int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp);
|
||||||
|
int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo);
|
||||||
|
char *ds_digest_name(int digest);
|
||||||
|
char *algo_digest_name(int algo);
|
||||||
|
char *nsec3_digest_name(int digest);
|
||||||
|
|
||||||
/* util.c */
|
/* util.c */
|
||||||
void rand_init(void);
|
void rand_init(void);
|
||||||
unsigned short rand16(void);
|
unsigned short rand16(void);
|
||||||
@@ -1254,7 +1272,7 @@ void free_rfd(struct randfd *rfd);
|
|||||||
|
|
||||||
/* network.c */
|
/* network.c */
|
||||||
int indextoname(int fd, int index, char *name);
|
int indextoname(int fd, int index, char *name);
|
||||||
int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp);
|
int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp);
|
||||||
int random_sock(int family);
|
int random_sock(int family);
|
||||||
void pre_allocate_sfds(void);
|
void pre_allocate_sfds(void);
|
||||||
int reload_servers(char *fname);
|
int reload_servers(char *fname);
|
||||||
|
|||||||
+244
-423
@@ -1,5 +1,5 @@
|
|||||||
/* dnssec.c is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
|
/* dnssec.c is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
|
||||||
and Copyright (c) 2012-2017 Simon Kelley
|
and Copyright (c) 2012-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -19,332 +19,11 @@
|
|||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
|
|
||||||
#include <nettle/rsa.h>
|
|
||||||
#include <nettle/dsa.h>
|
|
||||||
#ifndef NO_NETTLE_ECC
|
|
||||||
# include <nettle/ecdsa.h>
|
|
||||||
# include <nettle/ecc-curve.h>
|
|
||||||
#endif
|
|
||||||
#include <nettle/nettle-meta.h>
|
|
||||||
#include <nettle/bignum.h>
|
|
||||||
|
|
||||||
/* Nettle-3.0 moved to a new API for DSA. We use a name that's defined in the new API
|
|
||||||
to detect Nettle-3, and invoke the backwards compatibility mode. */
|
|
||||||
#ifdef dsa_params_init
|
|
||||||
#include <nettle/dsa-compat.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SERIAL_UNDEF -100
|
#define SERIAL_UNDEF -100
|
||||||
#define SERIAL_EQ 0
|
#define SERIAL_EQ 0
|
||||||
#define SERIAL_LT -1
|
#define SERIAL_LT -1
|
||||||
#define SERIAL_GT 1
|
#define SERIAL_GT 1
|
||||||
|
|
||||||
/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
|
|
||||||
static char *ds_digest_name(int digest)
|
|
||||||
{
|
|
||||||
switch (digest)
|
|
||||||
{
|
|
||||||
case 1: return "sha1";
|
|
||||||
case 2: return "sha256";
|
|
||||||
case 3: return "gosthash94";
|
|
||||||
case 4: return "sha384";
|
|
||||||
default: return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
|
|
||||||
static char *algo_digest_name(int algo)
|
|
||||||
{
|
|
||||||
switch (algo)
|
|
||||||
{
|
|
||||||
case 1: return "md5";
|
|
||||||
case 3: return "sha1";
|
|
||||||
case 5: return "sha1";
|
|
||||||
case 6: return "sha1";
|
|
||||||
case 7: return "sha1";
|
|
||||||
case 8: return "sha256";
|
|
||||||
case 10: return "sha512";
|
|
||||||
case 12: return "gosthash94";
|
|
||||||
case 13: return "sha256";
|
|
||||||
case 14: return "sha384";
|
|
||||||
default: return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
|
|
||||||
static char *nsec3_digest_name(int digest)
|
|
||||||
{
|
|
||||||
switch (digest)
|
|
||||||
{
|
|
||||||
case 1: return "sha1";
|
|
||||||
default: return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find pointer to correct hash function in nettle library */
|
|
||||||
static const struct nettle_hash *hash_find(char *name)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!name)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i = 0; nettle_hashes[i]; i++)
|
|
||||||
{
|
|
||||||
if (strcmp(nettle_hashes[i]->name, name) == 0)
|
|
||||||
return nettle_hashes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* expand ctx and digest memory allocations if necessary and init hash function */
|
|
||||||
static int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
|
|
||||||
{
|
|
||||||
static void *ctx = NULL;
|
|
||||||
static unsigned char *digest = NULL;
|
|
||||||
static unsigned int ctx_sz = 0;
|
|
||||||
static unsigned int digest_sz = 0;
|
|
||||||
|
|
||||||
void *new;
|
|
||||||
|
|
||||||
if (ctx_sz < hash->context_size)
|
|
||||||
{
|
|
||||||
if (!(new = whine_malloc(hash->context_size)))
|
|
||||||
return 0;
|
|
||||||
if (ctx)
|
|
||||||
free(ctx);
|
|
||||||
ctx = new;
|
|
||||||
ctx_sz = hash->context_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (digest_sz < hash->digest_size)
|
|
||||||
{
|
|
||||||
if (!(new = whine_malloc(hash->digest_size)))
|
|
||||||
return 0;
|
|
||||||
if (digest)
|
|
||||||
free(digest);
|
|
||||||
digest = new;
|
|
||||||
digest_sz = hash->digest_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ctxp = ctx;
|
|
||||||
*digestp = digest;
|
|
||||||
|
|
||||||
hash->init(ctx);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
|
||||||
unsigned char *digest, size_t digest_len, int algo)
|
|
||||||
{
|
|
||||||
unsigned char *p;
|
|
||||||
size_t exp_len;
|
|
||||||
|
|
||||||
static struct rsa_public_key *key = NULL;
|
|
||||||
static mpz_t sig_mpz;
|
|
||||||
|
|
||||||
(void)digest_len;
|
|
||||||
|
|
||||||
if (key == NULL)
|
|
||||||
{
|
|
||||||
if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
nettle_rsa_public_key_init(key);
|
|
||||||
mpz_init(sig_mpz);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
key_len--;
|
|
||||||
if ((exp_len = *p++) == 0)
|
|
||||||
{
|
|
||||||
GETSHORT(exp_len, p);
|
|
||||||
key_len -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exp_len >= key_len)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
key->size = key_len - exp_len;
|
|
||||||
mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
|
|
||||||
mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
|
|
||||||
|
|
||||||
mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
|
|
||||||
|
|
||||||
switch (algo)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
return nettle_rsa_md5_verify_digest(key, digest, sig_mpz);
|
|
||||||
case 5: case 7:
|
|
||||||
return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
|
|
||||||
case 8:
|
|
||||||
return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
|
|
||||||
case 10:
|
|
||||||
return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dnsmasq_dsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
|
||||||
unsigned char *digest, size_t digest_len, int algo)
|
|
||||||
{
|
|
||||||
unsigned char *p;
|
|
||||||
unsigned int t;
|
|
||||||
|
|
||||||
static struct dsa_public_key *key = NULL;
|
|
||||||
static struct dsa_signature *sig_struct;
|
|
||||||
|
|
||||||
(void)digest_len;
|
|
||||||
|
|
||||||
if (key == NULL)
|
|
||||||
{
|
|
||||||
if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
|
|
||||||
!(key = whine_malloc(sizeof(struct dsa_public_key))))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
nettle_dsa_public_key_init(key);
|
|
||||||
nettle_dsa_signature_init(sig_struct);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((sig_len < 41) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
t = *p++;
|
|
||||||
|
|
||||||
if (key_len < (213 + (t * 24)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
mpz_import(key->q, 20, 1, 1, 0, 0, p); p += 20;
|
|
||||||
mpz_import(key->p, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
|
|
||||||
mpz_import(key->g, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
|
|
||||||
mpz_import(key->y, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
|
|
||||||
|
|
||||||
mpz_import(sig_struct->r, 20, 1, 1, 0, 0, sig+1);
|
|
||||||
mpz_import(sig_struct->s, 20, 1, 1, 0, 0, sig+21);
|
|
||||||
|
|
||||||
(void)algo;
|
|
||||||
|
|
||||||
return nettle_dsa_sha1_verify_digest(key, digest, sig_struct);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NO_NETTLE_ECC
|
|
||||||
static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len,
|
|
||||||
unsigned char *sig, size_t sig_len,
|
|
||||||
unsigned char *digest, size_t digest_len, int algo)
|
|
||||||
{
|
|
||||||
unsigned char *p;
|
|
||||||
unsigned int t;
|
|
||||||
struct ecc_point *key;
|
|
||||||
|
|
||||||
static struct ecc_point *key_256 = NULL, *key_384 = NULL;
|
|
||||||
static mpz_t x, y;
|
|
||||||
static struct dsa_signature *sig_struct;
|
|
||||||
|
|
||||||
if (!sig_struct)
|
|
||||||
{
|
|
||||||
if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
nettle_dsa_signature_init(sig_struct);
|
|
||||||
mpz_init(x);
|
|
||||||
mpz_init(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (algo)
|
|
||||||
{
|
|
||||||
case 13:
|
|
||||||
if (!key_256)
|
|
||||||
{
|
|
||||||
if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
nettle_ecc_point_init(key_256, &nettle_secp_256r1);
|
|
||||||
}
|
|
||||||
|
|
||||||
key = key_256;
|
|
||||||
t = 32;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 14:
|
|
||||||
if (!key_384)
|
|
||||||
{
|
|
||||||
if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
nettle_ecc_point_init(key_384, &nettle_secp_384r1);
|
|
||||||
}
|
|
||||||
|
|
||||||
key = key_384;
|
|
||||||
t = 48;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sig_len != 2*t || key_len != 2*t ||
|
|
||||||
!(p = blockdata_retrieve(key_data, key_len, NULL)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
mpz_import(x, t , 1, 1, 0, 0, p);
|
|
||||||
mpz_import(y, t , 1, 1, 0, 0, p + t);
|
|
||||||
|
|
||||||
if (!ecc_point_set(key, x, y))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
|
|
||||||
mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
|
|
||||||
|
|
||||||
return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
|
||||||
unsigned char *digest, size_t digest_len, int algo)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* Enure at runtime that we have support for this digest */
|
|
||||||
if (!hash_find(algo_digest_name(algo)))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* This switch defines which sig algorithms we support, can't introspect Nettle for that. */
|
|
||||||
switch (algo)
|
|
||||||
{
|
|
||||||
case 1: case 5: case 7: case 8: case 10:
|
|
||||||
return dnsmasq_rsa_verify;
|
|
||||||
|
|
||||||
case 3: case 6:
|
|
||||||
return dnsmasq_dsa_verify;
|
|
||||||
|
|
||||||
#ifndef NO_NETTLE_ECC
|
|
||||||
case 13: case 14:
|
|
||||||
return dnsmasq_ecdsa_verify;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
|
||||||
unsigned char *digest, size_t digest_len, int algo)
|
|
||||||
{
|
|
||||||
|
|
||||||
int (*func)(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
|
||||||
unsigned char *digest, size_t digest_len, int algo);
|
|
||||||
|
|
||||||
func = verify_func(algo);
|
|
||||||
|
|
||||||
if (!func)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return (*func)(key_data, key_len, sig, sig_len, digest, digest_len, algo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert from presentation format to wire format, in place.
|
/* Convert from presentation format to wire format, in place.
|
||||||
Also map UC -> LC.
|
Also map UC -> LC.
|
||||||
Note that using extract_name to get presentation format
|
Note that using extract_name to get presentation format
|
||||||
@@ -424,15 +103,17 @@ static void from_wire(char *name)
|
|||||||
static int count_labels(char *name)
|
static int count_labels(char *name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
char *p;
|
||||||
|
|
||||||
if (*name == 0)
|
if (*name == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (i = 0; *name; name++)
|
for (p = name, i = 0; *p; p++)
|
||||||
if (*name == '.')
|
if (*p == '.')
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
return i+1;
|
/* Don't count empty first label. */
|
||||||
|
return *name == '.' ? i : i+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Implement RFC1982 wrapped compare for 32-bit numbers */
|
/* Implement RFC1982 wrapped compare for 32-bit numbers */
|
||||||
@@ -598,10 +279,10 @@ static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end,
|
|||||||
leaving the following bytes as deciding the order. Hence the nasty left1 and left2 variables.
|
leaving the following bytes as deciding the order. Hence the nasty left1 and left2 variables.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int rrsetidx,
|
static int sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int rrsetidx,
|
||||||
unsigned char **rrset, char *buff1, char *buff2)
|
unsigned char **rrset, char *buff1, char *buff2)
|
||||||
{
|
{
|
||||||
int swap, quit, i;
|
int swap, quit, i, j;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -663,11 +344,21 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
|
|||||||
rrset[i] = tmp;
|
rrset[i] = tmp;
|
||||||
swap = quit = 1;
|
swap = quit = 1;
|
||||||
}
|
}
|
||||||
|
else if (rc == 0 && quit && len1 == len2)
|
||||||
|
{
|
||||||
|
/* Two RRs are equal, remove one copy. RFC 4034, para 6.3 */
|
||||||
|
for (j = i+1; j < rrsetidx-1; j++)
|
||||||
|
rrset[j] = rrset[j+1];
|
||||||
|
rrsetidx--;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
else if (rc < 0)
|
else if (rc < 0)
|
||||||
quit = 1;
|
quit = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (swap);
|
} while (swap);
|
||||||
|
|
||||||
|
return rrsetidx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char **rrset = NULL, **sigs = NULL;
|
static unsigned char **rrset = NULL, **sigs = NULL;
|
||||||
@@ -812,7 +503,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
|
|||||||
/* Sort RRset records into canonical order.
|
/* Sort RRset records into canonical order.
|
||||||
Note that at this point keyname and daemon->workspacename buffs are
|
Note that at this point keyname and daemon->workspacename buffs are
|
||||||
unused, and used as workspace by the sort. */
|
unused, and used as workspace by the sort. */
|
||||||
sort_rrset(header, plen, rr_desc, rrsetidx, rrset, daemon->workspacename, keyname);
|
rrsetidx = sort_rrset(header, plen, rr_desc, rrsetidx, rrset, daemon->workspacename, keyname);
|
||||||
|
|
||||||
/* Now try all the sigs to try and find one which validates */
|
/* Now try all the sigs to try and find one which validates */
|
||||||
for (j = 0; j <sigidx; j++)
|
for (j = 0; j <sigidx; j++)
|
||||||
@@ -866,6 +557,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
|
|||||||
u16 len, *dp;
|
u16 len, *dp;
|
||||||
|
|
||||||
p = rrset[i];
|
p = rrset[i];
|
||||||
|
|
||||||
if (!extract_name(header, plen, &p, name, 1, 10))
|
if (!extract_name(header, plen, &p, name, 1, 10))
|
||||||
return STAT_BOGUS;
|
return STAT_BOGUS;
|
||||||
|
|
||||||
@@ -1120,7 +812,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
{
|
{
|
||||||
a.addr.log.keytag = keytag;
|
a.addr.log.keytag = keytag;
|
||||||
a.addr.log.algo = algo;
|
a.addr.log.algo = algo;
|
||||||
if (verify_func(algo))
|
if (algo_digest_name(algo))
|
||||||
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %hu, algo %hu");
|
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %hu, algo %hu");
|
||||||
else
|
else
|
||||||
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %hu, algo %hu (not supported)");
|
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %hu, algo %hu (not supported)");
|
||||||
@@ -1181,7 +873,6 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||||||
rc = STAT_BOGUS;
|
rc = STAT_BOGUS;
|
||||||
else
|
else
|
||||||
rc = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons);
|
rc = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons);
|
||||||
/* Note dnssec_validate_reply() will have cached positive answers */
|
|
||||||
|
|
||||||
if (rc == STAT_INSECURE)
|
if (rc == STAT_INSECURE)
|
||||||
rc = STAT_BOGUS;
|
rc = STAT_BOGUS;
|
||||||
@@ -1248,7 +939,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||||||
a.addr.log.keytag = keytag;
|
a.addr.log.keytag = keytag;
|
||||||
a.addr.log.algo = algo;
|
a.addr.log.algo = algo;
|
||||||
a.addr.log.digest = digest;
|
a.addr.log.digest = digest;
|
||||||
if (hash_find(ds_digest_name(digest)) && verify_func(algo))
|
if (ds_digest_name(digest) && algo_digest_name(algo))
|
||||||
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu");
|
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu");
|
||||||
else
|
else
|
||||||
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu (not supported)");
|
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu (not supported)");
|
||||||
@@ -1405,8 +1096,8 @@ static int hostname_cmp(const char *a, const char *b)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count,
|
static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, unsigned char **labels, int nsec_count,
|
||||||
char *workspace1, char *workspace2, char *name, int type, int *nons)
|
char *workspace1_in, char *workspace2, char *name, int type, int *nons)
|
||||||
{
|
{
|
||||||
int i, rc, rdlen;
|
int i, rc, rdlen;
|
||||||
unsigned char *p, *psave;
|
unsigned char *p, *psave;
|
||||||
@@ -1419,6 +1110,9 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
|
|||||||
/* Find NSEC record that proves name doesn't exist */
|
/* Find NSEC record that proves name doesn't exist */
|
||||||
for (i = 0; i < nsec_count; i++)
|
for (i = 0; i < nsec_count; i++)
|
||||||
{
|
{
|
||||||
|
char *workspace1 = workspace1_in;
|
||||||
|
int sig_labels, name_labels;
|
||||||
|
|
||||||
p = nsecs[i];
|
p = nsecs[i];
|
||||||
if (!extract_name(header, plen, &p, workspace1, 1, 10))
|
if (!extract_name(header, plen, &p, workspace1, 1, 10))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1427,7 +1121,27 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
|
|||||||
psave = p;
|
psave = p;
|
||||||
if (!extract_name(header, plen, &p, workspace2, 1, 10))
|
if (!extract_name(header, plen, &p, workspace2, 1, 10))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* If NSEC comes from wildcard expansion, use original wildcard
|
||||||
|
as name for computation. */
|
||||||
|
sig_labels = *labels[i];
|
||||||
|
name_labels = count_labels(workspace1);
|
||||||
|
|
||||||
|
if (sig_labels < name_labels)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
for (k = name_labels - sig_labels; k != 0; k--)
|
||||||
|
{
|
||||||
|
while (*workspace1 != '.' && *workspace1 != 0)
|
||||||
|
workspace1++;
|
||||||
|
if (k != 1 && *workspace1 == '.')
|
||||||
|
workspace1++;
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace1--;
|
||||||
|
*workspace1 = '*';
|
||||||
|
}
|
||||||
|
|
||||||
rc = hostname_cmp(workspace1, name);
|
rc = hostname_cmp(workspace1, name);
|
||||||
|
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
@@ -1453,8 +1167,9 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* If the SOA bit is set for a DS record, then we have the
|
/* If the SOA bit is set for a DS record, then we have the
|
||||||
DS from the wrong side of the delegation. */
|
DS from the wrong side of the delegation. For the root DS,
|
||||||
if (type == T_DS && (p[2] & (0x80 >> T_SOA)) != 0)
|
this is expected. */
|
||||||
|
if (name_labels != 0 && type == T_DS && (p[2] & (0x80 >> T_SOA)) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1559,7 +1274,7 @@ static int base32_decode(char *in, unsigned char *out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int check_nsec3_coverage(struct dns_header *header, size_t plen, int digest_len, unsigned char *digest, int type,
|
static int check_nsec3_coverage(struct dns_header *header, size_t plen, int digest_len, unsigned char *digest, int type,
|
||||||
char *workspace1, char *workspace2, unsigned char **nsecs, int nsec_count, int *nons)
|
char *workspace1, char *workspace2, unsigned char **nsecs, int nsec_count, int *nons, int name_labels)
|
||||||
{
|
{
|
||||||
int i, hash_len, salt_len, base32_len, rdlen, flags;
|
int i, hash_len, salt_len, base32_len, rdlen, flags;
|
||||||
unsigned char *p, *psave;
|
unsigned char *p, *psave;
|
||||||
@@ -1614,8 +1329,9 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* If the SOA bit is set for a DS record, then we have the
|
/* If the SOA bit is set for a DS record, then we have the
|
||||||
DS from the wrong side of the delegation. */
|
DS from the wrong side of the delegation. For the root DS,
|
||||||
if (type == T_DS && (p[2] & (0x80 >> T_SOA)) != 0)
|
this is expected. */
|
||||||
|
if (name_labels != 0 && type == T_DS && (p[2] & (0x80 >> T_SOA)) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1756,7 +1472,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
|
|||||||
if ((digest_len = hash_name(name, &digest, hash, salt, salt_len, iterations)) == 0)
|
if ((digest_len = hash_name(name, &digest, hash, salt, salt_len, iterations)) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, nons))
|
if (check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, nons, count_labels(name)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Can't find an NSEC3 which covers the name directly, we need the "closest encloser NSEC3"
|
/* Can't find an NSEC3 which covers the name directly, we need the "closest encloser NSEC3"
|
||||||
@@ -1801,7 +1517,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
|
|||||||
if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0)
|
if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, NULL))
|
if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, NULL, 1))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Finally, check that there's no seat of wildcard synthesis */
|
/* Finally, check that there's no seat of wildcard synthesis */
|
||||||
@@ -1816,7 +1532,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
|
|||||||
if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0)
|
if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, NULL))
|
if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count, NULL, 1))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1825,24 +1541,26 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
|
|||||||
|
|
||||||
static int prove_non_existence(struct dns_header *header, size_t plen, char *keyname, char *name, int qtype, int qclass, char *wildname, int *nons)
|
static int prove_non_existence(struct dns_header *header, size_t plen, char *keyname, char *name, int qtype, int qclass, char *wildname, int *nons)
|
||||||
{
|
{
|
||||||
static unsigned char **nsecset = NULL;
|
static unsigned char **nsecset = NULL, **rrsig_labels = NULL;
|
||||||
static int nsecset_sz = 0;
|
static int nsecset_sz = 0, rrsig_labels_sz = 0;
|
||||||
|
|
||||||
int type_found = 0;
|
int type_found = 0;
|
||||||
unsigned char *p = skip_questions(header, plen);
|
unsigned char *auth_start, *p = skip_questions(header, plen);
|
||||||
int type, class, rdlen, i, nsecs_found;
|
int type, class, rdlen, i, nsecs_found;
|
||||||
|
|
||||||
/* Move to NS section */
|
/* Move to NS section */
|
||||||
if (!p || !(p = skip_section(p, ntohs(header->ancount), header, plen)))
|
if (!p || !(p = skip_section(p, ntohs(header->ancount), header, plen)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
auth_start = p;
|
||||||
|
|
||||||
for (nsecs_found = 0, i = ntohs(header->nscount); i != 0; i--)
|
for (nsecs_found = 0, i = ntohs(header->nscount); i != 0; i--)
|
||||||
{
|
{
|
||||||
unsigned char *pstart = p;
|
unsigned char *pstart = p;
|
||||||
|
|
||||||
if (!(p = skip_name(p, header, plen, 10)))
|
if (!extract_name(header, plen, &p, daemon->workspacename, 1, 10))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
GETSHORT(type, p);
|
GETSHORT(type, p);
|
||||||
GETSHORT(class, p);
|
GETSHORT(class, p);
|
||||||
p += 4; /* TTL */
|
p += 4; /* TTL */
|
||||||
@@ -1859,7 +1577,69 @@ static int prove_non_existence(struct dns_header *header, size_t plen, char *key
|
|||||||
if (!expand_workspace(&nsecset, &nsecset_sz, nsecs_found))
|
if (!expand_workspace(&nsecset, &nsecset_sz, nsecs_found))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
nsecset[nsecs_found++] = pstart;
|
if (type == T_NSEC)
|
||||||
|
{
|
||||||
|
/* If we're looking for NSECs, find the corresponding SIGs, to
|
||||||
|
extract the labels value, which we need in case the NSECs
|
||||||
|
are the result of wildcard expansion.
|
||||||
|
Note that the NSEC may not have been validated yet
|
||||||
|
so if there are multiple SIGs, make sure the label value
|
||||||
|
is the same in all, to avoid be duped by a rogue one.
|
||||||
|
If there are no SIGs, that's an error */
|
||||||
|
unsigned char *p1 = auth_start;
|
||||||
|
int res, j, rdlen1, type1, class1;
|
||||||
|
|
||||||
|
if (!expand_workspace(&rrsig_labels, &rrsig_labels_sz, nsecs_found))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
rrsig_labels[nsecs_found] = NULL;
|
||||||
|
|
||||||
|
for (j = ntohs(header->nscount); j != 0; j--)
|
||||||
|
{
|
||||||
|
if (!(res = extract_name(header, plen, &p1, daemon->workspacename, 0, 10)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
GETSHORT(type1, p1);
|
||||||
|
GETSHORT(class1, p1);
|
||||||
|
p1 += 4; /* TTL */
|
||||||
|
GETSHORT(rdlen1, p1);
|
||||||
|
|
||||||
|
if (!CHECK_LEN(header, p1, plen, rdlen1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (res == 1 && class1 == qclass && type1 == T_RRSIG)
|
||||||
|
{
|
||||||
|
int type_covered;
|
||||||
|
unsigned char *psav = p1;
|
||||||
|
|
||||||
|
if (rdlen1 < 18)
|
||||||
|
return 0; /* bad packet */
|
||||||
|
|
||||||
|
GETSHORT(type_covered, p1);
|
||||||
|
|
||||||
|
if (type_covered == T_NSEC)
|
||||||
|
{
|
||||||
|
p1++; /* algo */
|
||||||
|
|
||||||
|
/* labels field must be the same in every SIG we find. */
|
||||||
|
if (!rrsig_labels[nsecs_found])
|
||||||
|
rrsig_labels[nsecs_found] = p1;
|
||||||
|
else if (*rrsig_labels[nsecs_found] != *p1) /* algo */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
p1 = psav;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ADD_RDLEN(header, p1, plen, rdlen1))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Must have found at least one sig. */
|
||||||
|
if (!rrsig_labels[nsecs_found])
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsecset[nsecs_found++] = pstart;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ADD_RDLEN(header, p, plen, rdlen))
|
if (!ADD_RDLEN(header, p, plen, rdlen))
|
||||||
@@ -1867,7 +1647,7 @@ static int prove_non_existence(struct dns_header *header, size_t plen, char *key
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type_found == T_NSEC)
|
if (type_found == T_NSEC)
|
||||||
return prove_non_existence_nsec(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, nons);
|
return prove_non_existence_nsec(header, plen, nsecset, rrsig_labels, nsecs_found, daemon->workspacename, keyname, name, qtype, nons);
|
||||||
else if (type_found == T_NSEC3)
|
else if (type_found == T_NSEC3)
|
||||||
return prove_non_existence_nsec3(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, wildname, nons);
|
return prove_non_existence_nsec3(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, wildname, nons);
|
||||||
else
|
else
|
||||||
@@ -1935,8 +1715,8 @@ static int zone_status(char *name, int class, char *keyname, time_t now)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (crecp->uid == (unsigned int)class &&
|
if (crecp->uid == (unsigned int)class &&
|
||||||
hash_find(ds_digest_name(crecp->addr.ds.digest)) &&
|
ds_digest_name(crecp->addr.ds.digest) &&
|
||||||
verify_func(crecp->addr.ds.algo))
|
algo_digest_name(crecp->addr.ds.algo))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while ((crecp = cache_find_by_name(crecp, keyname, now, F_DS)));
|
while ((crecp = cache_find_by_name(crecp, keyname, now, F_DS)));
|
||||||
@@ -1965,7 +1745,10 @@ static int zone_status(char *name, int class, char *keyname, time_t now)
|
|||||||
STAT_INSECURE at least one RRset not validated, because in unsigned zone.
|
STAT_INSECURE at least one RRset not validated, because in unsigned zone.
|
||||||
STAT_BOGUS signature is wrong, bad packet, no validation where there should be.
|
STAT_BOGUS signature is wrong, bad packet, no validation where there should be.
|
||||||
STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname, class in *class)
|
STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname, class in *class)
|
||||||
STAT_NEED_DS need DS to complete validation (name is returned in keyname)
|
STAT_NEED_DS need DS to complete validation (name is returned in keyname)
|
||||||
|
|
||||||
|
daemon->rr_status points to a char array which corressponds to the RRs in the
|
||||||
|
answer section (only). This is set to 1 for each RR which is validated, and 0 for any which aren't.
|
||||||
*/
|
*/
|
||||||
int dnssec_validate_reply(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 *class, int check_unsigned, int *neganswer, int *nons)
|
||||||
@@ -1974,9 +1757,25 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
static int target_sz = 0;
|
static int target_sz = 0;
|
||||||
|
|
||||||
unsigned char *ans_start, *p1, *p2;
|
unsigned char *ans_start, *p1, *p2;
|
||||||
int type1, class1, rdlen1, type2, class2, rdlen2, qclass, qtype, targetidx;
|
int type1, class1, rdlen1 = 0, type2, class2, rdlen2, qclass, qtype, targetidx;
|
||||||
int i, j, rc;
|
int i, j, rc;
|
||||||
|
int secure = STAT_SECURE;
|
||||||
|
|
||||||
|
/* extend rr_status if necessary */
|
||||||
|
if (daemon->rr_status_sz < ntohs(header->ancount))
|
||||||
|
{
|
||||||
|
char *new = whine_malloc(ntohs(header->ancount) + 64);
|
||||||
|
|
||||||
|
if (!new)
|
||||||
|
return STAT_BOGUS;
|
||||||
|
|
||||||
|
free(daemon->rr_status);
|
||||||
|
daemon->rr_status = new;
|
||||||
|
daemon->rr_status_sz = ntohs(header->ancount) + 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(daemon->rr_status, 0, ntohs(header->ancount));
|
||||||
|
|
||||||
if (neganswer)
|
if (neganswer)
|
||||||
*neganswer = 0;
|
*neganswer = 0;
|
||||||
|
|
||||||
@@ -2033,7 +1832,10 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
|
|
||||||
for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
|
for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
|
||||||
{
|
{
|
||||||
if (!extract_name(header, plen, &p1, name, 1, 10))
|
if (i != 0 && !ADD_RDLEN(header, p1, plen, rdlen1))
|
||||||
|
return STAT_BOGUS;
|
||||||
|
|
||||||
|
if (!extract_name(header, plen, &p1, name, 1, 10))
|
||||||
return STAT_BOGUS; /* bad packet */
|
return STAT_BOGUS; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(type1, p1);
|
GETSHORT(type1, p1);
|
||||||
@@ -2042,106 +1844,125 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
GETSHORT(rdlen1, p1);
|
GETSHORT(rdlen1, p1);
|
||||||
|
|
||||||
/* Don't try and validate RRSIGs! */
|
/* Don't try and validate RRSIGs! */
|
||||||
if (type1 != T_RRSIG)
|
if (type1 == T_RRSIG)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Check if we've done this RRset already */
|
||||||
|
for (p2 = ans_start, j = 0; j < i; j++)
|
||||||
{
|
{
|
||||||
/* Check if we've done this RRset already */
|
if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
|
||||||
for (p2 = ans_start, j = 0; j < i; j++)
|
return STAT_BOGUS; /* bad packet */
|
||||||
{
|
|
||||||
if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
|
|
||||||
return STAT_BOGUS; /* bad packet */
|
|
||||||
|
|
||||||
GETSHORT(type2, p2);
|
|
||||||
GETSHORT(class2, p2);
|
|
||||||
p2 += 4; /* TTL */
|
|
||||||
GETSHORT(rdlen2, p2);
|
|
||||||
|
|
||||||
if (type2 == type1 && class2 == class1 && rc == 1)
|
|
||||||
break; /* Done it before: name, type, class all match. */
|
|
||||||
|
|
||||||
if (!ADD_RDLEN(header, p2, plen, rdlen2))
|
|
||||||
return STAT_BOGUS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
GETSHORT(type2, p2);
|
||||||
|
GETSHORT(class2, p2);
|
||||||
|
p2 += 4; /* TTL */
|
||||||
|
GETSHORT(rdlen2, p2);
|
||||||
|
|
||||||
|
if (type2 == type1 && class2 == class1 && rc == 1)
|
||||||
|
break; /* Done it before: name, type, class all match. */
|
||||||
|
|
||||||
|
if (!ADD_RDLEN(header, p2, plen, rdlen2))
|
||||||
|
return STAT_BOGUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j != i)
|
||||||
|
{
|
||||||
|
/* Done already: copy the validation status */
|
||||||
|
if (i < ntohs(header->ancount))
|
||||||
|
daemon->rr_status[i] = daemon->rr_status[j];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Not done, validate now */
|
/* Not done, validate now */
|
||||||
if (j == i)
|
int sigcnt, rrcnt;
|
||||||
|
char *wildname;
|
||||||
|
|
||||||
|
if (!explore_rrset(header, plen, class1, type1, name, keyname, &sigcnt, &rrcnt))
|
||||||
|
return STAT_BOGUS;
|
||||||
|
|
||||||
|
/* No signatures for RRset. We can be configured to assume this is OK and return an INSECURE result. */
|
||||||
|
if (sigcnt == 0)
|
||||||
{
|
{
|
||||||
int sigcnt, rrcnt;
|
if (check_unsigned)
|
||||||
char *wildname;
|
|
||||||
|
|
||||||
if (!explore_rrset(header, plen, class1, type1, name, keyname, &sigcnt, &rrcnt))
|
|
||||||
return STAT_BOGUS;
|
|
||||||
|
|
||||||
/* No signatures for RRset. We can be configured to assume this is OK and return a INSECURE result. */
|
|
||||||
if (sigcnt == 0)
|
|
||||||
{
|
{
|
||||||
if (check_unsigned)
|
rc = zone_status(name, class1, keyname, now);
|
||||||
{
|
if (rc == STAT_SECURE)
|
||||||
rc = zone_status(name, class1, keyname, now);
|
rc = STAT_BOGUS;
|
||||||
if (rc == STAT_SECURE)
|
if (class)
|
||||||
rc = STAT_BOGUS;
|
*class = class1; /* Class for NEED_DS or NEED_KEY */
|
||||||
if (class)
|
|
||||||
*class = class1; /* Class for NEED_DS or NEED_KEY */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rc = STAT_INSECURE;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
rc = STAT_INSECURE;
|
||||||
|
|
||||||
|
if (rc != STAT_INSECURE)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* explore_rrset() gives us key name from sigs in keyname.
|
/* explore_rrset() gives us key name from sigs in keyname.
|
||||||
Can't overwrite name here. */
|
Can't overwrite name here. */
|
||||||
strcpy(daemon->workspacename, keyname);
|
strcpy(daemon->workspacename, keyname);
|
||||||
rc = zone_status(daemon->workspacename, class1, keyname, now);
|
rc = zone_status(daemon->workspacename, class1, keyname, now);
|
||||||
|
|
||||||
if (rc != STAT_SECURE)
|
if (rc == STAT_BOGUS || rc == STAT_NEED_KEY || rc == STAT_NEED_DS)
|
||||||
{
|
{
|
||||||
/* Zone is insecure, don't need to validate RRset */
|
/* Zone is insecure, don't need to validate RRset */
|
||||||
if (class)
|
if (class)
|
||||||
*class = class1; /* Class for NEED_DS or NEED_KEY */
|
*class = class1; /* Class for NEED_DS or NEED_KEY */
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = validate_rrset(now, header, plen, class1, type1, sigcnt, rrcnt, name, keyname, &wildname, NULL, 0, 0, 0);
|
/* Zone is insecure, don't need to validate RRset */
|
||||||
|
if (rc == STAT_SECURE)
|
||||||
if (rc == STAT_BOGUS || rc == STAT_NEED_KEY || rc == STAT_NEED_DS)
|
|
||||||
{
|
|
||||||
if (class)
|
|
||||||
*class = class1; /* Class for DS or DNSKEY */
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
rc = validate_rrset(now, header, plen, class1, type1, sigcnt,
|
||||||
|
rrcnt, name, keyname, &wildname, NULL, 0, 0, 0);
|
||||||
|
|
||||||
|
if (rc == STAT_BOGUS || rc == STAT_NEED_KEY || rc == STAT_NEED_DS)
|
||||||
|
{
|
||||||
|
if (class)
|
||||||
|
*class = class1; /* Class for DS or DNSKEY */
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* rc is now STAT_SECURE or STAT_SECURE_WILDCARD */
|
/* rc is now STAT_SECURE or STAT_SECURE_WILDCARD */
|
||||||
|
|
||||||
|
/* Note that RR is validated */
|
||||||
|
if (i < ntohs(header->ancount))
|
||||||
|
daemon->rr_status[i] = 1;
|
||||||
|
|
||||||
/* Note if we've validated either the answer to the question
|
/* Note if we've validated either the answer to the question
|
||||||
or the target of a CNAME. Any not noted will need NSEC or
|
or the target of a CNAME. Any not noted will need NSEC or
|
||||||
to be in unsigned space. */
|
to be in unsigned space. */
|
||||||
|
|
||||||
for (j = 0; j <targetidx; j++)
|
for (j = 0; j <targetidx; j++)
|
||||||
if ((p2 = targets[j]))
|
if ((p2 = targets[j]))
|
||||||
{
|
{
|
||||||
if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
|
int rc1;
|
||||||
|
if (!(rc1 = extract_name(header, plen, &p2, name, 0, 10)))
|
||||||
return STAT_BOGUS; /* bad packet */
|
return STAT_BOGUS; /* bad packet */
|
||||||
|
|
||||||
if (class1 == qclass && rc == 1 && (type1 == T_CNAME || type1 == qtype || qtype == T_ANY ))
|
if (class1 == qclass && rc1 == 1 && (type1 == T_CNAME || type1 == qtype || qtype == T_ANY ))
|
||||||
targets[j] = NULL;
|
targets[j] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* An attacker replay a wildcard answer with a different
|
/* An attacker replay a wildcard answer with a different
|
||||||
answer and overlay a genuine RR. To prove this
|
answer and overlay a genuine RR. To prove this
|
||||||
hasn't happened, the answer must prove that
|
hasn't happened, the answer must prove that
|
||||||
the genuine record doesn't exist. Check that here.
|
the genuine record doesn't exist. Check that here.
|
||||||
Note that we may not yet have validated the NSEC/NSEC3 RRsets.
|
Note that we may not yet have validated the NSEC/NSEC3 RRsets.
|
||||||
That's not a problem since if the RRsets later fail
|
That's not a problem since if the RRsets later fail
|
||||||
we'll return BOGUS then. */
|
we'll return BOGUS then. */
|
||||||
if (rc == STAT_SECURE_WILDCARD && !prove_non_existence(header, plen, keyname, name, type1, class1, wildname, NULL))
|
if (rc == STAT_SECURE_WILDCARD &&
|
||||||
|
!prove_non_existence(header, plen, keyname, name, type1, class1, wildname, NULL))
|
||||||
return STAT_BOGUS;
|
return STAT_BOGUS;
|
||||||
|
|
||||||
|
rc = STAT_SECURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ADD_RDLEN(header, p1, plen, rdlen1))
|
if (rc == STAT_INSECURE)
|
||||||
return STAT_BOGUS;
|
secure = STAT_INSECURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OK, all the RRsets validate, now see if we have a missing answer or CNAME target. */
|
/* OK, all the RRsets validate, now see if we have a missing answer or CNAME target. */
|
||||||
@@ -2175,7 +1996,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return STAT_SECURE;
|
return secure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+147
-80
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -55,83 +55,133 @@ int is_name_synthetic(int flags, char *name, struct all_addr *addr)
|
|||||||
|
|
||||||
if (pref && *pref != 0)
|
if (pref && *pref != 0)
|
||||||
continue; /* prefix match fail */
|
continue; /* prefix match fail */
|
||||||
|
|
||||||
/* NB, must not alter name if we return zero */
|
if (c->indexed)
|
||||||
for (p = tail; *p; p++)
|
|
||||||
{
|
{
|
||||||
char c = *p;
|
for (p = tail; *p; p++)
|
||||||
|
{
|
||||||
|
char c = *p;
|
||||||
|
|
||||||
|
if (c < '0' || c > '9')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if ((c >='0' && c <= '9') || c == '-')
|
if (*p != '.')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
*p = 0;
|
||||||
if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f')))
|
|
||||||
continue;
|
if (hostname_isequal(c->domain, p+1))
|
||||||
|
{
|
||||||
|
if (prot == AF_INET)
|
||||||
|
{
|
||||||
|
unsigned int index = atoi(tail);
|
||||||
|
|
||||||
|
if (!c->is6 &&
|
||||||
|
index <= ntohl(c->end.s_addr) - ntohl(c->start.s_addr))
|
||||||
|
{
|
||||||
|
addr->addr.addr4.s_addr = htonl(ntohl(c->start.s_addr) + index);
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 index = atoll(tail);
|
||||||
|
|
||||||
|
if (c->is6 &&
|
||||||
|
index <= addr6part(&c->end6) - addr6part(&c->start6))
|
||||||
|
{
|
||||||
|
u64 start = addr6part(&c->start6);
|
||||||
|
addr->addr.addr6 = c->start6;
|
||||||
|
setaddr6part(&addr->addr.addr6, start + index);
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*p != '.')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
*p = 0;
|
|
||||||
|
|
||||||
#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 = '.';
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
/* swap . or : for - */
|
/* NB, must not alter name if we return zero */
|
||||||
for (p = tail; *p; p++)
|
for (p = tail; *p; p++)
|
||||||
if (*p == '-')
|
{
|
||||||
{
|
char c = *p;
|
||||||
if (prot == AF_INET)
|
|
||||||
*p = '.';
|
if ((c >='0' && c <= '9') || c == '-')
|
||||||
|
continue;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else
|
if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f')))
|
||||||
*p = ':';
|
continue;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p != '.')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
#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 = '.';
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (!c->is6 &&
|
||||||
|
ntohl(addr->addr.addr4.s_addr) >= ntohl(c->start.s_addr) &&
|
||||||
|
ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr))
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 addrpart = addr6part(&addr->addr.addr6);
|
||||||
|
|
||||||
|
if (c->is6 &&
|
||||||
|
is_same_net6(&addr->addr.addr6, &c->start6, 64) &&
|
||||||
|
addrpart >= addr6part(&c->start6) &&
|
||||||
|
addrpart <= addr6part(&c->end6))
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
|
|
||||||
{
|
|
||||||
if (prot == AF_INET)
|
|
||||||
{
|
|
||||||
if (!c->is6 &&
|
|
||||||
ntohl(addr->addr.addr4.s_addr) >= ntohl(c->start.s_addr) &&
|
|
||||||
ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr))
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u64 addrpart = addr6part(&addr->addr.addr6);
|
|
||||||
|
|
||||||
if (c->is6 &&
|
|
||||||
is_same_net6(&addr->addr.addr6, &c->start6, 64) &&
|
|
||||||
addrpart >= addr6part(&c->start6) &&
|
|
||||||
addrpart <= addr6part(&c->end6))
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* restore name */
|
/* restore name */
|
||||||
for (p = tail; *p; p++)
|
for (p = tail; *p; p++)
|
||||||
if (*p == '.' || *p == ':')
|
if (*p == '.' || *p == ':')
|
||||||
*p = '-';
|
*p = '-';
|
||||||
|
|
||||||
*p = '.';
|
*p = '.';
|
||||||
|
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -149,14 +199,22 @@ int is_rev_synth(int flag, struct all_addr *addr, char *name)
|
|||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
*name = 0;
|
*name = 0;
|
||||||
if (c->prefix)
|
if (c->indexed)
|
||||||
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
|
{
|
||||||
|
unsigned int index = ntohl(addr->addr.addr4.s_addr) - ntohl(c->start.s_addr);
|
||||||
|
snprintf(name, MAXDNAME, "%s%u", c->prefix ? c->prefix : "", index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (c->prefix)
|
||||||
|
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
|
||||||
|
|
||||||
|
inet_ntop(AF_INET, &addr->addr.addr4, name + strlen(name), ADDRSTRLEN);
|
||||||
|
for (p = name; *p; p++)
|
||||||
|
if (*p == '.')
|
||||||
|
*p = '-';
|
||||||
|
}
|
||||||
|
|
||||||
inet_ntop(AF_INET, &addr->addr.addr4, name + strlen(name), ADDRSTRLEN);
|
|
||||||
for (p = name; *p; p++)
|
|
||||||
if (*p == '.')
|
|
||||||
*p = '-';
|
|
||||||
|
|
||||||
strncat(name, ".", MAXDNAME);
|
strncat(name, ".", MAXDNAME);
|
||||||
strncat(name, c->domain, MAXDNAME);
|
strncat(name, c->domain, MAXDNAME);
|
||||||
|
|
||||||
@@ -169,23 +227,32 @@ int is_rev_synth(int flag, struct all_addr *addr, char *name)
|
|||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
*name = 0;
|
*name = 0;
|
||||||
if (c->prefix)
|
if (c->indexed)
|
||||||
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
|
|
||||||
|
|
||||||
inet_ntop(AF_INET6, &addr->addr.addr6, name + strlen(name), ADDRSTRLEN);
|
|
||||||
|
|
||||||
/* IPv6 presentation address can start with ":", but valid domain names
|
|
||||||
cannot start with "-" so prepend a zero in that case. */
|
|
||||||
if (!c->prefix && *name == ':')
|
|
||||||
{
|
{
|
||||||
*name = '0';
|
u64 index = addr6part(&addr->addr.addr6) - addr6part(&c->start6);
|
||||||
inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
|
snprintf(name, MAXDNAME, "%s%llu", c->prefix ? c->prefix : "", index);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (c->prefix)
|
||||||
|
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
|
||||||
|
|
||||||
|
inet_ntop(AF_INET6, &addr->addr.addr6, name + strlen(name), ADDRSTRLEN);
|
||||||
|
|
||||||
/* V4-mapped have periods.... */
|
/* IPv6 presentation address can start with ":", but valid domain names
|
||||||
for (p = name; *p; p++)
|
cannot start with "-" so prepend a zero in that case. */
|
||||||
if (*p == ':' || *p == '.')
|
if (!c->prefix && *name == ':')
|
||||||
*p = '-';
|
{
|
||||||
|
*name = '0';
|
||||||
|
inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* V4-mapped have periods.... */
|
||||||
|
for (p = name; *p; p++)
|
||||||
|
if (*p == ':' || *p == '.')
|
||||||
|
*p = '-';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
strncat(name, ".", MAXDNAME);
|
strncat(name, ".", MAXDNAME);
|
||||||
strncat(name, c->domain, MAXDNAME);
|
strncat(name, c->domain, MAXDNAME);
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+82
-64
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -272,14 +272,13 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
while (forward->blocking_query)
|
while (forward->blocking_query)
|
||||||
forward = forward->blocking_query;
|
forward = forward->blocking_query;
|
||||||
|
|
||||||
forward->flags |= FREC_TEST_PKTSZ;
|
|
||||||
|
|
||||||
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
|
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
|
||||||
plen = forward->stash_len;
|
plen = forward->stash_len;
|
||||||
|
|
||||||
|
forward->flags |= FREC_TEST_PKTSZ;
|
||||||
if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
|
if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
|
||||||
PUTSHORT(SAFE_PKTSZ, pheader);
|
PUTSHORT(SAFE_PKTSZ, pheader);
|
||||||
|
|
||||||
if (forward->sentto->addr.sa.sa_family == AF_INET)
|
if (forward->sentto->addr.sa.sa_family == AF_INET)
|
||||||
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
|
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
@@ -400,31 +399,22 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
struct server *firstsentto = start;
|
struct server *firstsentto = start;
|
||||||
int subnet, forwarded = 0;
|
int subnet, forwarded = 0;
|
||||||
size_t edns0_len;
|
size_t edns0_len;
|
||||||
|
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
|
||||||
|
unsigned char *pheader;
|
||||||
|
|
||||||
/* If a query is retried, use the log_id for the retry when logging the answer. */
|
/* If a query is retried, use the log_id for the retry when logging the answer. */
|
||||||
forward->log_id = daemon->log_id;
|
forward->log_id = daemon->log_id;
|
||||||
|
|
||||||
edns0_len = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->source, now, &subnet);
|
plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->source, now, &subnet);
|
||||||
|
|
||||||
if (edns0_len != plen)
|
if (subnet)
|
||||||
{
|
forward->flags |= FREC_HAS_SUBNET;
|
||||||
plen = edns0_len;
|
|
||||||
forward->flags |= FREC_ADDED_PHEADER;
|
|
||||||
|
|
||||||
if (subnet)
|
|
||||||
forward->flags |= FREC_HAS_SUBNET;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
|
if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
|
||||||
{
|
{
|
||||||
size_t new = add_do_bit(header, plen, ((unsigned char *) header) + PACKETSZ);
|
plen = add_do_bit(header, plen, ((unsigned char *) header) + PACKETSZ);
|
||||||
|
|
||||||
if (new != plen)
|
|
||||||
forward->flags |= FREC_ADDED_PHEADER;
|
|
||||||
|
|
||||||
plen = new;
|
|
||||||
|
|
||||||
/* For debugging, set Checking Disabled, otherwise, have the upstream check too,
|
/* For debugging, set Checking Disabled, otherwise, have the upstream check too,
|
||||||
this allows it to select auth servers when one is returning bad data. */
|
this allows it to select auth servers when one is returning bad data. */
|
||||||
if (option_bool(OPT_DNSSEC_DEBUG))
|
if (option_bool(OPT_DNSSEC_DEBUG))
|
||||||
@@ -433,9 +423,20 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */
|
if (find_pseudoheader(header, plen, &edns0_len, &pheader, NULL, NULL))
|
||||||
if (find_pseudoheader(header, plen, &edns0_len, NULL, NULL, NULL) && edns0_len > 11)
|
{
|
||||||
forward->flags |= FREC_HAS_EXTRADATA;
|
/* If there wasn't a PH before, and there is now, we added it. */
|
||||||
|
if (!oph)
|
||||||
|
forward->flags |= FREC_ADDED_PHEADER;
|
||||||
|
|
||||||
|
/* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */
|
||||||
|
if (edns0_len > 11)
|
||||||
|
forward->flags |= FREC_HAS_EXTRADATA;
|
||||||
|
|
||||||
|
/* Reduce udp size on retransmits. */
|
||||||
|
if (forward->flags & FREC_TEST_PKTSZ)
|
||||||
|
PUTSHORT(SAFE_PKTSZ, pheader);
|
||||||
|
}
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@@ -563,7 +564,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
|||||||
char **sets = 0;
|
char **sets = 0;
|
||||||
int munged = 0, is_sign;
|
int munged = 0, is_sign;
|
||||||
size_t plen;
|
size_t plen;
|
||||||
|
|
||||||
(void)ad_reqd;
|
(void)ad_reqd;
|
||||||
(void)do_bit;
|
(void)do_bit;
|
||||||
(void)bogusanswer;
|
(void)bogusanswer;
|
||||||
@@ -767,7 +768,11 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
|
|
||||||
if (!server)
|
if (!server)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* If sufficient time has elapsed, try and expand UDP buffer size again. */
|
||||||
|
if (difftime(now, server->pktsz_reduced) > UDP_TEST_TIME)
|
||||||
|
server->edns_pktsz = daemon->edns_pktsz;
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
hash = hash_questions(header, n, daemon->namebuff);
|
hash = hash_questions(header, n, daemon->namebuff);
|
||||||
#else
|
#else
|
||||||
@@ -797,10 +802,20 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
unsigned char *pheader;
|
unsigned char *pheader;
|
||||||
size_t plen;
|
size_t plen;
|
||||||
int is_sign;
|
int is_sign;
|
||||||
|
|
||||||
|
/* In strict order mode, there must be a server later in the chain
|
||||||
|
left to send to, otherwise without the forwardall mechanism,
|
||||||
|
code further on will cycle around the list forwever if they
|
||||||
|
all return REFUSED. Note that server is always non-NULL before
|
||||||
|
this executes. */
|
||||||
|
if (option_bool(OPT_ORDER))
|
||||||
|
for (server = forward->sentto->next; server; server = server->next)
|
||||||
|
if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP)))
|
||||||
|
break;
|
||||||
|
|
||||||
/* recreate query from reply */
|
/* recreate query from reply */
|
||||||
pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
|
pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
|
||||||
if (!is_sign)
|
if (!is_sign && server)
|
||||||
{
|
{
|
||||||
header->ancount = htons(0);
|
header->ancount = htons(0);
|
||||||
header->nscount = htons(0);
|
header->nscount = htons(0);
|
||||||
@@ -844,12 +859,18 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We tried resending to this server with a smaller maximum size and got an answer.
|
/* We tried resending to this server with a smaller maximum size and got an answer.
|
||||||
Make that permanent. To avoid reduxing the packet size for an single dropped packet,
|
Make that permanent. To avoid reduxing the packet size for a single dropped packet,
|
||||||
only do this when we get a truncated answer, or one larger than the safe size. */
|
only do this when we get a truncated answer, or one larger than the safe size. */
|
||||||
if (server && (forward->flags & FREC_TEST_PKTSZ) &&
|
if (server && server->edns_pktsz > SAFE_PKTSZ && (forward->flags & FREC_TEST_PKTSZ) &&
|
||||||
((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
|
((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
|
||||||
server->edns_pktsz = SAFE_PKTSZ;
|
{
|
||||||
|
server->edns_pktsz = SAFE_PKTSZ;
|
||||||
|
server->pktsz_reduced = now;
|
||||||
|
prettyprint_addr(&server->addr, daemon->addrbuff);
|
||||||
|
my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* If the answer is an error, keep the forward record in place in case
|
/* If the answer is an error, keep the forward record in place in case
|
||||||
we get a good reply from another server. Kill it when we've
|
we get a good reply from another server. Kill it when we've
|
||||||
had replies from all to avoid filling the forwarding table when
|
had replies from all to avoid filling the forwarding table when
|
||||||
@@ -858,7 +879,7 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
(RCODE(header) != REFUSED && RCODE(header) != SERVFAIL))
|
(RCODE(header) != REFUSED && RCODE(header) != SERVFAIL))
|
||||||
{
|
{
|
||||||
int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
|
int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
|
||||||
|
|
||||||
if (option_bool(OPT_NO_REBIND))
|
if (option_bool(OPT_NO_REBIND))
|
||||||
check_rebind = !(forward->flags & FREC_NOREBIND);
|
check_rebind = !(forward->flags & FREC_NOREBIND);
|
||||||
|
|
||||||
@@ -898,7 +919,8 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
|
status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
|
||||||
else
|
else
|
||||||
status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
|
status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
|
||||||
option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC), NULL, NULL);
|
option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC),
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can't validate, as we're missing key data. Put this
|
/* Can't validate, as we're missing key data. Put this
|
||||||
@@ -1095,7 +1117,7 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
header->hb4 |= HB4_RA; /* recursion if available */
|
header->hb4 |= HB4_RA; /* recursion if available */
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
/* We added an EDNSO header for the purpose of getting DNSSEC RRs, and set the value of the UDP payload size
|
/* We added an EDNSO header for the purpose of getting DNSSEC RRs, and set the value of the UDP payload size
|
||||||
greater than the no-EDNS0-implied 512 to have if space for the RRSIGS. If, having stripped them and the EDNS0
|
greater than the no-EDNS0-implied 512 to have space for the RRSIGS. If, having stripped them and the EDNS0
|
||||||
header, the answer is still bigger than 512, truncate it and mark it so. The client then retries with TCP. */
|
header, the answer is still bigger than 512, truncate it and mark it so. The client then retries with TCP. */
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER) && (nn > PACKETSZ))
|
if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER) && (nn > PACKETSZ))
|
||||||
{
|
{
|
||||||
@@ -1482,7 +1504,8 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
|||||||
new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
|
new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
|
||||||
else
|
else
|
||||||
new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
|
new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
|
||||||
option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC), NULL, NULL);
|
option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
|
if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
|
||||||
break;
|
break;
|
||||||
@@ -1551,7 +1574,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
|||||||
setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
|
setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 1) ||
|
if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 0, 1) ||
|
||||||
connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
|
connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
|
||||||
{
|
{
|
||||||
close(server->tcpfd);
|
close(server->tcpfd);
|
||||||
@@ -1783,17 +1806,30 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
struct all_addr *addrp = NULL;
|
struct all_addr *addrp = NULL;
|
||||||
int type = SERV_DO_DNSSEC;
|
int type = SERV_DO_DNSSEC;
|
||||||
char *domain = NULL;
|
char *domain = NULL;
|
||||||
size_t new_size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet);
|
unsigned char *oph = find_pseudoheader(header, size, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet);
|
||||||
|
|
||||||
if (size != new_size)
|
|
||||||
{
|
|
||||||
added_pheader = 1;
|
|
||||||
size = new_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gotname)
|
if (gotname)
|
||||||
flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
|
flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
|
||||||
|
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (option_bool(OPT_DNSSEC_VALID) && (type & SERV_DO_DNSSEC))
|
||||||
|
{
|
||||||
|
size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
|
||||||
|
|
||||||
|
/* For debugging, set Checking Disabled, otherwise, have the upstream check too,
|
||||||
|
this allows it to select auth servers when one is returning bad data. */
|
||||||
|
if (option_bool(OPT_DNSSEC_DEBUG))
|
||||||
|
header->hb4 |= HB4_CD;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check if we added a pheader on forwarding - may need to
|
||||||
|
strip it from the reply. */
|
||||||
|
if (!oph && find_pseudoheader(header, size, NULL, NULL, NULL, NULL))
|
||||||
|
added_pheader = 1;
|
||||||
|
|
||||||
type &= ~SERV_DO_DNSSEC;
|
type &= ~SERV_DO_DNSSEC;
|
||||||
|
|
||||||
if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
|
if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
|
||||||
@@ -1847,7 +1883,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
|
setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 1) ||
|
if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 0, 1) ||
|
||||||
connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
|
connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
|
||||||
{
|
{
|
||||||
close(last_server->tcpfd);
|
close(last_server->tcpfd);
|
||||||
@@ -1858,24 +1894,6 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
last_server->flags &= ~SERV_GOT_TCP;
|
last_server->flags &= ~SERV_GOT_TCP;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && (last_server->flags & SERV_DO_DNSSEC))
|
|
||||||
{
|
|
||||||
new_size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
|
|
||||||
|
|
||||||
if (size != new_size)
|
|
||||||
{
|
|
||||||
added_pheader = 1;
|
|
||||||
size = new_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For debugging, set Checking Disabled, otherwise, have the upstream check too,
|
|
||||||
this allows it to select auth servers when one is returning bad data. */
|
|
||||||
if (option_bool(OPT_DNSSEC_DEBUG))
|
|
||||||
header->hb4 |= HB4_CD;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*length = htons(size);
|
*length = htons(size);
|
||||||
|
|
||||||
/* get query name again for logging - may have been overwritten */
|
/* get query name again for logging - may have been overwritten */
|
||||||
|
|||||||
+3
-2
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -97,13 +97,14 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
return pipefd[1];
|
return pipefd[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ignore SIGTERM, so that we can clean up when the main process gets hit
|
/* ignore SIGTERM and SIGINT, so that we can clean up when the main process gets hit
|
||||||
and SIGALRM so that we can use sleep() */
|
and SIGALRM so that we can use sleep() */
|
||||||
sigact.sa_handler = SIG_IGN;
|
sigact.sa_handler = SIG_IGN;
|
||||||
sigact.sa_flags = 0;
|
sigact.sa_flags = 0;
|
||||||
sigemptyset(&sigact.sa_mask);
|
sigemptyset(&sigact.sa_mask);
|
||||||
sigaction(SIGTERM, &sigact, NULL);
|
sigaction(SIGTERM, &sigact, NULL);
|
||||||
sigaction(SIGALRM, &sigact, NULL);
|
sigaction(SIGALRM, &sigact, NULL);
|
||||||
|
sigaction(SIGINT, &sigact, NULL);
|
||||||
|
|
||||||
if (!option_bool(OPT_DEBUG) && uid != 0)
|
if (!option_bool(OPT_DEBUG) && uid != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
+12
-10
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
#include <sys/param.h> /* For MAXSYMLINKS */
|
#include <sys/param.h> /* For MAXSYMLINKS */
|
||||||
|
|
||||||
/* the strategy is to set a inotify on the directories containing
|
/* the strategy is to set an inotify on the directories containing
|
||||||
resolv files, for any files in the directory which are close-write
|
resolv files, for any files in the directory which are close-write
|
||||||
or moved into the directory.
|
or moved into the directory.
|
||||||
|
|
||||||
@@ -227,19 +227,21 @@ int inotify_check(time_t now)
|
|||||||
|
|
||||||
for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len)
|
for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len)
|
||||||
{
|
{
|
||||||
|
size_t namelen;
|
||||||
|
|
||||||
in = (struct inotify_event*)p;
|
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 */
|
/* ignore emacs backups and dotfiles */
|
||||||
if (in->len == 0 ||
|
if (in->len == 0 || (namelen = strlen(in->name)) == 0 ||
|
||||||
in->name[in->len - 1] == '~' ||
|
in->name[namelen - 1] == '~' ||
|
||||||
(in->name[0] == '#' && in->name[in->len - 1] == '#') ||
|
(in->name[0] == '#' && in->name[namelen - 1] == '#') ||
|
||||||
in->name[0] == '.')
|
in->name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
for (res = daemon->resolv_files; res; res = res->next)
|
||||||
|
if (res->wd == in->wd && strcmp(res->file, in->name) == 0)
|
||||||
|
hit = 1;
|
||||||
|
|
||||||
for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
|
for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
|
||||||
if (ah->wd == in->wd)
|
if (ah->wd == in->wd)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+23
-8
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -1149,10 +1149,7 @@ int random_sock(int family)
|
|||||||
if (fix_fd(fd))
|
if (fix_fd(fd))
|
||||||
while(tries--)
|
while(tries--)
|
||||||
{
|
{
|
||||||
unsigned short port = rand16();
|
unsigned short port = htons(daemon->min_port + (rand16() % ((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)
|
if (family == AF_INET)
|
||||||
{
|
{
|
||||||
@@ -1187,7 +1184,7 @@ int random_sock(int family)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
|
int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp)
|
||||||
{
|
{
|
||||||
union mysockaddr addr_copy = *addr;
|
union mysockaddr addr_copy = *addr;
|
||||||
|
|
||||||
@@ -1204,7 +1201,25 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
|
|||||||
|
|
||||||
if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
|
if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (!is_tcp && ifindex > 0)
|
||||||
|
{
|
||||||
|
#if defined(IP_UNICAST_IF)
|
||||||
|
if (addr_copy.sa.sa_family == AF_INET)
|
||||||
|
{
|
||||||
|
uint32_t ifindex_opt = htonl(ifindex);
|
||||||
|
return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE_IPV6) && defined (IPV6_UNICAST_IF)
|
||||||
|
if (addr_copy.sa.sa_family == AF_INET6)
|
||||||
|
{
|
||||||
|
uint32_t ifindex_opt = htonl(ifindex);
|
||||||
|
return setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(SO_BINDTODEVICE)
|
#if defined(SO_BINDTODEVICE)
|
||||||
if (intname[0] != 0 &&
|
if (intname[0] != 0 &&
|
||||||
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
|
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
|
||||||
@@ -1260,7 +1275,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
|
if (!local_bind(sfd->fd, addr, intname, ifindex, 0) || !fix_fd(sfd->fd))
|
||||||
{
|
{
|
||||||
errsave = errno; /* save error from bind. */
|
errsave = errno; /* save error from bind. */
|
||||||
close(sfd->fd);
|
close(sfd->fd);
|
||||||
|
|||||||
+132
-86
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -1163,7 +1163,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|||||||
case 'd':
|
case 'd':
|
||||||
case 'D':
|
case 'D':
|
||||||
fac *= 24;
|
fac *= 24;
|
||||||
/* fall though */
|
/* fall through */
|
||||||
case 'h':
|
case 'h':
|
||||||
case 'H':
|
case 'H':
|
||||||
fac *= 60;
|
fac *= 60;
|
||||||
@@ -2071,7 +2071,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
char *netpart;
|
char *netpart;
|
||||||
|
|
||||||
new->prefix = NULL;
|
new->prefix = NULL;
|
||||||
|
new->indexed = 0;
|
||||||
|
|
||||||
unhide_metas(comma);
|
unhide_metas(comma);
|
||||||
if ((netpart = split_chr(comma, '/')))
|
if ((netpart = split_chr(comma, '/')))
|
||||||
{
|
{
|
||||||
@@ -2208,8 +2209,14 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
char *star;
|
||||||
new->next = daemon->synth_domains;
|
new->next = daemon->synth_domains;
|
||||||
daemon->synth_domains = new;
|
daemon->synth_domains = new;
|
||||||
|
if ((star = strrchr(new->prefix, '*')) && *(star+1) == 0)
|
||||||
|
{
|
||||||
|
*star = 0;
|
||||||
|
new->indexed = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (option == 's')
|
else if (option == 's')
|
||||||
@@ -2733,15 +2740,24 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
|
|
||||||
case LOPT_BRIDGE: /* --bridge-interface */
|
case LOPT_BRIDGE: /* --bridge-interface */
|
||||||
{
|
{
|
||||||
struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
|
struct dhcp_bridge *new;
|
||||||
|
|
||||||
if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
|
if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
|
||||||
ret_err(_("bad bridge-interface"));
|
ret_err(_("bad bridge-interface"));
|
||||||
|
|
||||||
strcpy(new->iface, arg);
|
|
||||||
new->alias = NULL;
|
|
||||||
new->next = daemon->bridges;
|
|
||||||
daemon->bridges = new;
|
|
||||||
|
|
||||||
|
for (new = daemon->bridges; new; new = new->next)
|
||||||
|
if (strcmp(new->iface, arg) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!new)
|
||||||
|
{
|
||||||
|
new = opt_malloc(sizeof(struct dhcp_bridge));
|
||||||
|
strcpy(new->iface, arg);
|
||||||
|
new->alias = NULL;
|
||||||
|
new->next = daemon->bridges;
|
||||||
|
daemon->bridges = new;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
arg = comma;
|
arg = comma;
|
||||||
comma = split(arg);
|
comma = split(arg);
|
||||||
@@ -2961,7 +2977,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
case 'd':
|
case 'd':
|
||||||
case 'D':
|
case 'D':
|
||||||
fac *= 24;
|
fac *= 24;
|
||||||
/* fall though */
|
/* fall through */
|
||||||
case 'h':
|
case 'h':
|
||||||
case 'H':
|
case 'H':
|
||||||
fac *= 60;
|
fac *= 60;
|
||||||
@@ -3847,6 +3863,7 @@ err:
|
|||||||
|
|
||||||
while (arg != last)
|
while (arg != last)
|
||||||
{
|
{
|
||||||
|
int arglen = strlen(arg);
|
||||||
alias = canonicalise_opt(arg);
|
alias = canonicalise_opt(arg);
|
||||||
|
|
||||||
if (!alias || !target)
|
if (!alias || !target)
|
||||||
@@ -3862,7 +3879,7 @@ err:
|
|||||||
new->target = target;
|
new->target = target;
|
||||||
new->ttl = ttl;
|
new->ttl = ttl;
|
||||||
|
|
||||||
for (arg += strlen(arg)+1; *arg == ' '; arg++);
|
for (arg += arglen+1; *arg && isspace(*arg); arg++);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -4318,7 +4335,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#if defined(HAVE_DHCP) && defined(HAVE_INOTIFY)
|
||||||
int option_read_dynfile(char *file, int flags)
|
int option_read_dynfile(char *file, int flags)
|
||||||
{
|
{
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("read %s"), file);
|
my_syslog(MS_DHCP | LOG_INFO, _("read %s"), file);
|
||||||
@@ -4519,86 +4536,99 @@ void read_servers_file(void)
|
|||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
|
static void clear_dynamic_conf(void)
|
||||||
|
{
|
||||||
|
struct dhcp_config *configs, *cp, **up;
|
||||||
|
|
||||||
|
/* remove existing... */
|
||||||
|
for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
|
||||||
|
{
|
||||||
|
cp = configs->next;
|
||||||
|
|
||||||
|
if (configs->flags & CONFIG_BANK)
|
||||||
|
{
|
||||||
|
struct hwaddr_config *mac, *tmp;
|
||||||
|
struct dhcp_netid_list *list, *tmplist;
|
||||||
|
|
||||||
|
for (mac = configs->hwaddr; mac; mac = tmp)
|
||||||
|
{
|
||||||
|
tmp = mac->next;
|
||||||
|
free(mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configs->flags & CONFIG_CLID)
|
||||||
|
free(configs->clid);
|
||||||
|
|
||||||
|
for (list = configs->netid; list; list = tmplist)
|
||||||
|
{
|
||||||
|
free(list->list);
|
||||||
|
tmplist = list->next;
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configs->flags & CONFIG_NAME)
|
||||||
|
free(configs->hostname);
|
||||||
|
|
||||||
|
*up = configs->next;
|
||||||
|
free(configs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
up = &configs->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_dynamic_opt(void)
|
||||||
|
{
|
||||||
|
struct dhcp_opt *opts, *cp, **up;
|
||||||
|
struct dhcp_netid *id, *next;
|
||||||
|
|
||||||
|
for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
|
||||||
|
{
|
||||||
|
cp = opts->next;
|
||||||
|
|
||||||
|
if (opts->flags & DHOPT_BANK)
|
||||||
|
{
|
||||||
|
if ((opts->flags & DHOPT_VENDOR))
|
||||||
|
free(opts->u.vendor_class);
|
||||||
|
free(opts->val);
|
||||||
|
for (id = opts->netid; id; id = next)
|
||||||
|
{
|
||||||
|
next = id->next;
|
||||||
|
free(id->net);
|
||||||
|
free(id);
|
||||||
|
}
|
||||||
|
*up = opts->next;
|
||||||
|
free(opts);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
up = &opts->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void reread_dhcp(void)
|
void reread_dhcp(void)
|
||||||
{
|
{
|
||||||
struct hostsfile *hf;
|
struct hostsfile *hf;
|
||||||
|
|
||||||
if (daemon->dhcp_hosts_file)
|
/* Do these even if there is no daemon->dhcp_hosts_file or
|
||||||
|
daemon->dhcp_opts_file since entries may have been created by the
|
||||||
|
inotify dynamic file reading system. */
|
||||||
|
|
||||||
|
clear_dynamic_conf();
|
||||||
|
clear_dynamic_opt();
|
||||||
|
|
||||||
|
if (daemon->dhcp_hosts_file)
|
||||||
{
|
{
|
||||||
struct dhcp_config *configs, *cp, **up;
|
|
||||||
|
|
||||||
/* remove existing... */
|
|
||||||
for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
|
|
||||||
{
|
|
||||||
cp = configs->next;
|
|
||||||
|
|
||||||
if (configs->flags & CONFIG_BANK)
|
|
||||||
{
|
|
||||||
struct hwaddr_config *mac, *tmp;
|
|
||||||
struct dhcp_netid_list *list, *tmplist;
|
|
||||||
|
|
||||||
for (mac = configs->hwaddr; mac; mac = tmp)
|
|
||||||
{
|
|
||||||
tmp = mac->next;
|
|
||||||
free(mac);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configs->flags & CONFIG_CLID)
|
|
||||||
free(configs->clid);
|
|
||||||
|
|
||||||
for (list = configs->netid; list; list = tmplist)
|
|
||||||
{
|
|
||||||
free(list->list);
|
|
||||||
tmplist = list->next;
|
|
||||||
free(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configs->flags & CONFIG_NAME)
|
|
||||||
free(configs->hostname);
|
|
||||||
|
|
||||||
*up = configs->next;
|
|
||||||
free(configs);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
up = &configs->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
|
daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
|
||||||
for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
|
for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
|
||||||
if (!(hf->flags & AH_INACTIVE))
|
if (!(hf->flags & AH_INACTIVE))
|
||||||
{
|
{
|
||||||
if (one_file(hf->fname, LOPT_BANK))
|
if (one_file(hf->fname, LOPT_BANK))
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
|
my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daemon->dhcp_opts_file)
|
if (daemon->dhcp_opts_file)
|
||||||
{
|
{
|
||||||
struct dhcp_opt *opts, *cp, **up;
|
|
||||||
struct dhcp_netid *id, *next;
|
|
||||||
|
|
||||||
for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
|
|
||||||
{
|
|
||||||
cp = opts->next;
|
|
||||||
|
|
||||||
if (opts->flags & DHOPT_BANK)
|
|
||||||
{
|
|
||||||
if ((opts->flags & DHOPT_VENDOR))
|
|
||||||
free(opts->u.vendor_class);
|
|
||||||
free(opts->val);
|
|
||||||
for (id = opts->netid; id; id = next)
|
|
||||||
{
|
|
||||||
next = id->next;
|
|
||||||
free(id->net);
|
|
||||||
free(id);
|
|
||||||
}
|
|
||||||
*up = opts->next;
|
|
||||||
free(opts);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
up = &opts->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
|
daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
|
||||||
for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
|
for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
|
||||||
if (!(hf->flags & AH_INACTIVE))
|
if (!(hf->flags & AH_INACTIVE))
|
||||||
@@ -4607,11 +4637,18 @@ void reread_dhcp(void)
|
|||||||
my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
|
my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ifdef HAVE_INOTIFY
|
||||||
|
/* Setup notify and read pre-existing files. */
|
||||||
|
set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0);
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void read_opts(int argc, char **argv, char *compile_opts)
|
void read_opts(int argc, char **argv, char *compile_opts)
|
||||||
{
|
{
|
||||||
|
size_t argbuf_size = MAXDNAME;
|
||||||
|
char *argbuf = opt_malloc(argbuf_size);
|
||||||
char *buff = opt_malloc(MAXDNAME);
|
char *buff = opt_malloc(MAXDNAME);
|
||||||
int option, conffile_opt = '7', testmode = 0;
|
int option, conffile_opt = '7', testmode = 0;
|
||||||
char *arg, *conffile = CONFFILE;
|
char *arg, *conffile = CONFFILE;
|
||||||
@@ -4642,6 +4679,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||||||
daemon->soa_retry = SOA_RETRY;
|
daemon->soa_retry = SOA_RETRY;
|
||||||
daemon->soa_expiry = SOA_EXPIRY;
|
daemon->soa_expiry = SOA_EXPIRY;
|
||||||
daemon->max_port = MAX_PORT;
|
daemon->max_port = MAX_PORT;
|
||||||
|
daemon->min_port = MIN_PORT;
|
||||||
|
|
||||||
#ifndef NO_ID
|
#ifndef NO_ID
|
||||||
add_txt("version.bind", "dnsmasq-" VERSION, 0 );
|
add_txt("version.bind", "dnsmasq-" VERSION, 0 );
|
||||||
@@ -4681,9 +4719,15 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||||||
/* Copy optarg so that argv doesn't get changed */
|
/* Copy optarg so that argv doesn't get changed */
|
||||||
if (optarg)
|
if (optarg)
|
||||||
{
|
{
|
||||||
strncpy(buff, optarg, MAXDNAME);
|
if (strlen(optarg) >= argbuf_size)
|
||||||
buff[MAXDNAME-1] = 0;
|
{
|
||||||
arg = buff;
|
free(argbuf);
|
||||||
|
argbuf_size = strlen(optarg) + 1;
|
||||||
|
argbuf = opt_malloc(argbuf_size);
|
||||||
|
}
|
||||||
|
strncpy(argbuf, optarg, argbuf_size);
|
||||||
|
argbuf[argbuf_size-1] = 0;
|
||||||
|
arg = argbuf;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
arg = NULL;
|
arg = NULL;
|
||||||
@@ -4731,6 +4775,8 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(argbuf);
|
||||||
|
|
||||||
if (conffile)
|
if (conffile)
|
||||||
{
|
{
|
||||||
one_file(conffile, conffile_opt);
|
one_file(conffile, conffile_opt);
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -407,7 +407,7 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
|
|||||||
if (ra_param)
|
if (ra_param)
|
||||||
mtu = ra_param->mtu;
|
mtu = ra_param->mtu;
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
/* Note that IPv6 MTU is not neccessarily the same as the IPv4 MTU
|
/* Note that IPv6 MTU is not necessarily the same as the IPv4 MTU
|
||||||
available from SIOCGIFMTU */
|
available from SIOCGIFMTU */
|
||||||
if (mtu == 0)
|
if (mtu == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
+76
-87
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -36,7 +36,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
if ((l = *p++) == 0)
|
if ((l = *p++) == 0)
|
||||||
/* end marker */
|
/* end marker */
|
||||||
{
|
{
|
||||||
/* check that there are the correct no of bytes after the name */
|
/* check that there are the correct no. of bytes after the name */
|
||||||
if (!CHECK_LEN(header, p1 ? p1 : p, plen, extrabytes))
|
if (!CHECK_LEN(header, p1 ? p1 : p, plen, extrabytes))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
|
|||||||
memset(addrp, 0, sizeof(struct all_addr));
|
memset(addrp, 0, sizeof(struct all_addr));
|
||||||
|
|
||||||
/* turn name into a series of asciiz strings */
|
/* turn name into a series of asciiz strings */
|
||||||
/* j counts no of labels */
|
/* j counts no. of labels */
|
||||||
for(j = 1,cp1 = name; *namein; cp1++, namein++)
|
for(j = 1,cp1 = name; *namein; cp1++, namein++)
|
||||||
if (*namein == '.')
|
if (*namein == '.')
|
||||||
{
|
{
|
||||||
@@ -584,7 +584,8 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name, int *doc
|
|||||||
expired and cleaned out that way.
|
expired and cleaned out that way.
|
||||||
Return 1 if we reject an address because it look like part of dns-rebinding attack. */
|
Return 1 if we reject an address because it look like part of dns-rebinding attack. */
|
||||||
int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now,
|
int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now,
|
||||||
char **ipsets, int is_sign, int check_rebind, int no_cache_dnssec, int secure, int *doctored)
|
char **ipsets, int is_sign, int check_rebind, int no_cache_dnssec,
|
||||||
|
int secure, int *doctored)
|
||||||
{
|
{
|
||||||
unsigned char *p, *p1, *endrr, *namep;
|
unsigned char *p, *p1, *endrr, *namep;
|
||||||
int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
|
int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
|
||||||
@@ -595,6 +596,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
#else
|
#else
|
||||||
(void)ipsets; /* unused */
|
(void)ipsets; /* unused */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
cache_start_insert();
|
cache_start_insert();
|
||||||
|
|
||||||
@@ -603,10 +605,18 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
{
|
{
|
||||||
searched_soa = 1;
|
searched_soa = 1;
|
||||||
ttl = find_soa(header, qlen, name, doctored);
|
ttl = find_soa(header, qlen, name, doctored);
|
||||||
|
|
||||||
|
if (*doctored)
|
||||||
|
{
|
||||||
|
if (secure)
|
||||||
|
return 0;
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (*doctored && secure)
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
return 0;
|
for (i = 0; i < ntohs(header->ancount); i++)
|
||||||
|
if (daemon->rr_status[i])
|
||||||
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* go through the questions. */
|
/* go through the questions. */
|
||||||
@@ -617,7 +627,9 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
int found = 0, cname_count = CNAME_CHAIN;
|
int found = 0, cname_count = CNAME_CHAIN;
|
||||||
struct crec *cpp = NULL;
|
struct crec *cpp = NULL;
|
||||||
int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
|
int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
|
||||||
int secflag = secure ? F_DNSSECOK : 0;
|
#ifdef HAVE_DNSSEC
|
||||||
|
int cname_short = 0;
|
||||||
|
#endif
|
||||||
unsigned long cttl = ULONG_MAX, attl;
|
unsigned long cttl = ULONG_MAX, attl;
|
||||||
|
|
||||||
namep = p;
|
namep = p;
|
||||||
@@ -645,8 +657,9 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
if (!(p1 = skip_questions(header, qlen)))
|
if (!(p1 = skip_questions(header, qlen)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (j = ntohs(header->ancount); j != 0; j--)
|
for (j = 0; j < ntohs(header->ancount); j++)
|
||||||
{
|
{
|
||||||
|
int secflag = 0;
|
||||||
unsigned char *tmp = namep;
|
unsigned char *tmp = namep;
|
||||||
/* the loop body overwrites the original name, so get it back here. */
|
/* the loop body overwrites the original name, so get it back here. */
|
||||||
if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
|
if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
|
||||||
@@ -672,11 +685,24 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
{
|
{
|
||||||
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (option_bool(OPT_DNSSEC_VALID) && daemon->rr_status[j])
|
||||||
|
{
|
||||||
|
/* validated RR anywhere in CNAME chain, don't cache. */
|
||||||
|
if (cname_short || aqtype == T_CNAME)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
secflag = F_DNSSECOK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (aqtype == T_CNAME)
|
if (aqtype == T_CNAME)
|
||||||
{
|
{
|
||||||
if (!cname_count-- || secure)
|
if (!cname_count--)
|
||||||
return 0; /* looped CNAMES, or DNSSEC, which we can't cache. */
|
return 0; /* looped CNAMES, we can't cache. */
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
cname_short = 1;
|
||||||
|
#endif
|
||||||
goto cname_loop;
|
goto cname_loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,7 +724,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
ttl = find_soa(header, qlen, NULL, doctored);
|
ttl = find_soa(header, qlen, NULL, doctored);
|
||||||
}
|
}
|
||||||
if (ttl)
|
if (ttl)
|
||||||
cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | secflag);
|
cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | (secure ? F_DNSSECOK : 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -726,8 +752,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
if (!(p1 = skip_questions(header, qlen)))
|
if (!(p1 = skip_questions(header, qlen)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (j = ntohs(header->ancount); j != 0; j--)
|
for (j = 0; j < ntohs(header->ancount); j++)
|
||||||
{
|
{
|
||||||
|
int secflag = 0;
|
||||||
|
|
||||||
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
|
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
|
||||||
return 0; /* bad packet */
|
return 0; /* bad packet */
|
||||||
|
|
||||||
@@ -744,6 +772,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
|
|
||||||
if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype))
|
if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype))
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (option_bool(OPT_DNSSEC_VALID) && daemon->rr_status[j])
|
||||||
|
secflag = F_DNSSECOK;
|
||||||
|
#endif
|
||||||
if (aqtype == T_CNAME)
|
if (aqtype == T_CNAME)
|
||||||
{
|
{
|
||||||
if (!cname_count--)
|
if (!cname_count--)
|
||||||
@@ -835,7 +867,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
pointing at this, inherit its TTL */
|
pointing at this, inherit its TTL */
|
||||||
if (ttl || cpp)
|
if (ttl || cpp)
|
||||||
{
|
{
|
||||||
newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags | secflag);
|
newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));
|
||||||
if (newc && cpp)
|
if (newc && cpp)
|
||||||
{
|
{
|
||||||
cpp->addr.cname.target.cache = newc;
|
cpp->addr.cname.target.cache = newc;
|
||||||
@@ -915,6 +947,8 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
|
|||||||
SET_RCODE(header, NOERROR); /* empty domain */
|
SET_RCODE(header, NOERROR); /* empty domain */
|
||||||
else if (flags == F_NXDOMAIN)
|
else if (flags == F_NXDOMAIN)
|
||||||
SET_RCODE(header, NXDOMAIN);
|
SET_RCODE(header, NXDOMAIN);
|
||||||
|
else if (flags == F_SERVFAIL)
|
||||||
|
SET_RCODE(header, SERVFAIL);
|
||||||
else if (flags == F_IPV4)
|
else if (flags == F_IPV4)
|
||||||
{ /* we know the address */
|
{ /* we know the address */
|
||||||
SET_RCODE(header, NOERROR);
|
SET_RCODE(header, NOERROR);
|
||||||
@@ -950,7 +984,7 @@ int check_for_local_domain(char *name, time_t now)
|
|||||||
/* Note: the call to cache_find_by_name is intended to find any record which matches
|
/* Note: the call to cache_find_by_name is intended to find any record which matches
|
||||||
ie A, AAAA, CNAME. */
|
ie A, AAAA, CNAME. */
|
||||||
|
|
||||||
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME |F_NO_RR)) &&
|
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_NO_RR)) &&
|
||||||
(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
|
(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -1074,18 +1108,15 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
|||||||
unsigned short usval;
|
unsigned short usval;
|
||||||
long lval;
|
long lval;
|
||||||
char *sval;
|
char *sval;
|
||||||
|
|
||||||
#define CHECK_LIMIT(size) \
|
#define CHECK_LIMIT(size) \
|
||||||
if (limit && p + (size) > (unsigned char*)limit) \
|
if (limit && p + (size) > (unsigned char*)limit) goto truncated;
|
||||||
{ \
|
|
||||||
va_end(ap); \
|
|
||||||
goto truncated; \
|
|
||||||
}
|
|
||||||
|
|
||||||
if (truncp && *truncp)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
va_start(ap, format); /* make ap point to 1st unamed argument */
|
va_start(ap, format); /* make ap point to 1st unamed argument */
|
||||||
|
|
||||||
|
if (truncp && *truncp)
|
||||||
|
goto truncated;
|
||||||
|
|
||||||
if (nameoffset > 0)
|
if (nameoffset > 0)
|
||||||
{
|
{
|
||||||
CHECK_LIMIT(2);
|
CHECK_LIMIT(2);
|
||||||
@@ -1095,10 +1126,7 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
|||||||
{
|
{
|
||||||
char *name = va_arg(ap, char *);
|
char *name = va_arg(ap, char *);
|
||||||
if (name && !(p = do_rfc1035_name(p, name, limit)))
|
if (name && !(p = do_rfc1035_name(p, name, limit)))
|
||||||
{
|
goto truncated;
|
||||||
va_end(ap);
|
|
||||||
goto truncated;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nameoffset < 0)
|
if (nameoffset < 0)
|
||||||
{
|
{
|
||||||
@@ -1163,13 +1191,9 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
|||||||
/* get domain-name answer arg and store it in RDATA field */
|
/* get domain-name answer arg and store it in RDATA field */
|
||||||
if (offset)
|
if (offset)
|
||||||
*offset = p - (unsigned char *)header;
|
*offset = p - (unsigned char *)header;
|
||||||
p = do_rfc1035_name(p, va_arg(ap, char *), limit);
|
if (!(p = do_rfc1035_name(p, va_arg(ap, char *), limit)))
|
||||||
if (!p)
|
goto truncated;
|
||||||
{
|
CHECK_LIMIT(1);
|
||||||
va_end(ap);
|
|
||||||
goto truncated;
|
|
||||||
}
|
|
||||||
CHECK_LIMIT(1);
|
|
||||||
*p++ = 0;
|
*p++ = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1194,24 +1218,22 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef CHECK_LIMIT
|
|
||||||
va_end(ap); /* clean up variable argument pointer */
|
va_end(ap); /* clean up variable argument pointer */
|
||||||
|
|
||||||
|
/* Now, store real RDLength. sav already checked against limit. */
|
||||||
j = p - sav - 2;
|
j = p - sav - 2;
|
||||||
/* this has already been checked against limit before */
|
PUTSHORT(j, sav);
|
||||||
PUTSHORT(j, sav); /* Now, store real RDLength */
|
|
||||||
|
|
||||||
/* check for overflow of buffer */
|
|
||||||
if (limit && ((unsigned char *)limit - p) < 0)
|
|
||||||
{
|
|
||||||
truncated:
|
|
||||||
if (truncp)
|
|
||||||
*truncp = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pp = p;
|
*pp = p;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
truncated:
|
||||||
|
va_end(ap);
|
||||||
|
if (truncp)
|
||||||
|
*truncp = 1;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#undef CHECK_LIMIT
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long crec_ttl(struct crec *crecp, time_t now)
|
static unsigned long crec_ttl(struct crec *crecp, time_t now)
|
||||||
@@ -1265,6 +1287,10 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
ntohs(header->qdcount) == 0 ||
|
ntohs(header->qdcount) == 0 ||
|
||||||
OPCODE(header) != QUERY )
|
OPCODE(header) != QUERY )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* always servfail queries with RD unset, to avoid cache snooping. */
|
||||||
|
if (!(header->hb3 & HB3_RD))
|
||||||
|
return setup_reply(header, qlen, NULL, F_SERVFAIL, 0);
|
||||||
|
|
||||||
/* Don't return AD set if checking disabled. */
|
/* Don't return AD set if checking disabled. */
|
||||||
if (header->hb4 & HB4_CD)
|
if (header->hb4 & HB4_CD)
|
||||||
@@ -1542,44 +1568,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (qtype != type && qtype != T_ANY)
|
if (qtype != type && qtype != T_ANY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Check for "A for A" queries; be rather conservative
|
|
||||||
about what looks like dotted-quad. */
|
|
||||||
if (qtype == T_A)
|
|
||||||
{
|
|
||||||
char *cp;
|
|
||||||
unsigned int i, a;
|
|
||||||
int x;
|
|
||||||
|
|
||||||
for (cp = name, i = 0, a = 0; *cp; i++)
|
|
||||||
{
|
|
||||||
if (!isdigit((unsigned char)*cp) || (x = strtol(cp, &cp, 10)) > 255)
|
|
||||||
{
|
|
||||||
i = 5;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = (a << 8) + x;
|
|
||||||
|
|
||||||
if (*cp == '.')
|
|
||||||
cp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 4)
|
|
||||||
{
|
|
||||||
ans = 1;
|
|
||||||
sec_data = 0;
|
|
||||||
if (!dryrun)
|
|
||||||
{
|
|
||||||
addr.addr.addr4.s_addr = htonl(a);
|
|
||||||
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
|
||||||
daemon->local_ttl, NULL, type, C_IN, "4", &addr))
|
|
||||||
anscount++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* interface name stuff */
|
/* interface name stuff */
|
||||||
intname_restart:
|
intname_restart:
|
||||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||||
@@ -1748,8 +1736,9 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
|
|
||||||
if (qtype == T_CNAME || qtype == T_ANY)
|
if (qtype == T_CNAME || qtype == T_ANY)
|
||||||
{
|
{
|
||||||
if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)) &&
|
if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | (dryrun ? F_NO_RR : 0))) &&
|
||||||
(qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG | (dryrun ? F_NO_RR : 0)))))
|
(qtype == T_CNAME || (crecp->flags & F_CONFIG)) &&
|
||||||
|
((crecp->flags & F_CONFIG) || !do_bit || !(crecp->flags & F_DNSSECOK)))
|
||||||
{
|
{
|
||||||
if (!(crecp->flags & F_DNSSECOK))
|
if (!(crecp->flags & F_DNSSECOK))
|
||||||
sec_data = 0;
|
sec_data = 0;
|
||||||
|
|||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -909,7 +909,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
|
|
||||||
if (!workaround && boot)
|
if (!workaround && boot)
|
||||||
{
|
{
|
||||||
/* Provide the bootfile here, for gPXE, and in case we have no menu items
|
/* Provide the bootfile here, for iPXE, and in case we have no menu items
|
||||||
and set discovery_control = 8 */
|
and set discovery_control = 8 */
|
||||||
if (boot->next_server.s_addr)
|
if (boot->next_server.s_addr)
|
||||||
mess->siaddr = boot->next_server;
|
mess->siaddr = boot->next_server;
|
||||||
@@ -2284,7 +2284,7 @@ static void do_options(struct dhcp_context *context,
|
|||||||
/* See if we can send the boot stuff as options.
|
/* See if we can send the boot stuff as options.
|
||||||
To do this we need a requested option list, BOOTP
|
To do this we need a requested option list, BOOTP
|
||||||
and very old DHCP clients won't have this, we also
|
and very old DHCP clients won't have this, we also
|
||||||
provide an manual option to disable it.
|
provide a manual option to disable it.
|
||||||
Some PXE ROMs have bugs (surprise!) and need zero-terminated
|
Some PXE ROMs have bugs (surprise!) and need zero-terminated
|
||||||
names, so we always send those. */
|
names, so we always send those. */
|
||||||
if ((boot = find_boot(tagif)))
|
if ((boot = find_boot(tagif)))
|
||||||
|
|||||||
+5
-5
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -216,9 +216,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
|||||||
|
|
||||||
for (opt = opts; opt; opt = opt6_next(opt, end))
|
for (opt = opts; opt; opt = opt6_next(opt, end))
|
||||||
{
|
{
|
||||||
if (opt6_ptr(opt, 0) + opt6_len(opt) >= end) {
|
if (opt6_ptr(opt, 0) + opt6_len(opt) > end)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
int o = new_opt6(opt6_type(opt));
|
int o = new_opt6(opt6_type(opt));
|
||||||
if (opt6_type(opt) == OPTION6_RELAY_MSG)
|
if (opt6_type(opt) == OPTION6_RELAY_MSG)
|
||||||
{
|
{
|
||||||
@@ -882,7 +882,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
|
|
||||||
if (!ia_option)
|
if (!ia_option)
|
||||||
{
|
{
|
||||||
/* If we get a request with a IA_*A without addresses, treat it exactly like
|
/* If we get a request with an IA_*A without addresses, treat it exactly like
|
||||||
a SOLICT with rapid commit set. */
|
a SOLICT with rapid commit set. */
|
||||||
save_counter(start);
|
save_counter(start);
|
||||||
goto request_no_address;
|
goto request_no_address;
|
||||||
@@ -1625,7 +1625,7 @@ static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz)
|
|||||||
{
|
{
|
||||||
if (t1cntr != 0)
|
if (t1cntr != 0)
|
||||||
{
|
{
|
||||||
/* go back an fill in fields in IA_NA option */
|
/* go back and fill in fields in IA_NA option */
|
||||||
int sav = save_counter(t1cntr);
|
int sav = save_counter(t1cntr);
|
||||||
unsigned int t1, t2, fuzz = 0;
|
unsigned int t1, t2, fuzz = 0;
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Code to safely remove RRs from an DNS answer */
|
/* Code to safely remove RRs from a DNS answer */
|
||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
@@ -247,7 +247,7 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode)
|
|||||||
|
|
||||||
check_rrs(p, header, plen, 1, rrs, rr_found);
|
check_rrs(p, header, plen, 1, rrs, rr_found);
|
||||||
|
|
||||||
/* Fouth pass, elide records */
|
/* Fourth pass, elide records */
|
||||||
for (p = rrs[0], i = 1; i < rr_found; i += 2)
|
for (p = rrs[0], i = 1; i < rr_found; i += 2)
|
||||||
{
|
{
|
||||||
unsigned char *start = rrs[i];
|
unsigned char *start = rrs[i];
|
||||||
@@ -270,7 +270,7 @@ u16 *rrfilter_desc(int type)
|
|||||||
{
|
{
|
||||||
/* List of RRtypes which include domains in the data.
|
/* List of RRtypes which include domains in the data.
|
||||||
0 -> domain
|
0 -> domain
|
||||||
integer -> no of plain bytes
|
integer -> no. of plain bytes
|
||||||
-1 -> end
|
-1 -> end
|
||||||
|
|
||||||
zero is not a valid RRtype, so the final entry is returned for
|
zero is not a valid RRtype, so the final entry is returned for
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+9
-5
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -246,14 +246,16 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
|
|||||||
|
|
||||||
while (sval && *sval)
|
while (sval && *sval)
|
||||||
{
|
{
|
||||||
if (limit && p + 1 > (unsigned char*)limit)
|
|
||||||
return p;
|
|
||||||
|
|
||||||
unsigned char *cp = p++;
|
unsigned char *cp = p++;
|
||||||
|
|
||||||
|
if (limit && p > (unsigned char*)limit)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
for (j = 0; *sval && (*sval != '.'); sval++, j++)
|
for (j = 0; *sval && (*sval != '.'); sval++, j++)
|
||||||
{
|
{
|
||||||
if (limit && p + 1 > (unsigned char*)limit)
|
if (limit && p + 1 > (unsigned char*)limit)
|
||||||
return p;
|
return NULL;
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
|
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
|
||||||
*p++ = (*(++sval))-1;
|
*p++ = (*(++sval))-1;
|
||||||
@@ -261,10 +263,12 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
|
|||||||
#endif
|
#endif
|
||||||
*p++ = *sval;
|
*p++ = *sval;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cp = j;
|
*cp = j;
|
||||||
if (*sval)
|
if (*sval)
|
||||||
sval++;
|
sval++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user