mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-04 13:48:30 +00:00
Compare commits
95
Commits
v2.78test1
...
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 | ||
|
|
a49c5c2265 | ||
|
|
30858e3b9b | ||
|
|
30df7efc96 | ||
|
|
3e8c42cba5 | ||
|
|
62cb936cb7 | ||
|
|
39921d03ba | ||
|
|
6a0b00f0d6 | ||
|
|
51eadb692a | ||
|
|
897c113fda | ||
|
|
33e3f1029c | ||
|
|
3d4ff1ba84 | ||
|
|
24036ea507 | ||
|
|
0549c73b7e | ||
|
|
b697fbb7f1 | ||
|
|
96e063c43d | ||
|
|
4e841da1a6 | ||
|
|
09ce307bdb | ||
|
|
a3303e196e | ||
|
|
63437ffbb5 | ||
|
|
69a815aa8f | ||
|
|
1d224949cc | ||
|
|
391f708a09 | ||
|
|
cbd29e5da8 | ||
|
|
50a2841d34 | ||
|
|
9396752c11 | ||
|
|
712dadb287 | ||
|
|
32be32eab8 | ||
|
|
1649f709e7 | ||
|
|
50ca85504c |
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/
|
||||||
+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
|
||||||
|
|
||||||
|
|||||||
@@ -206,13 +206,13 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
if ((x = t/86400))
|
if ((x = t/86400))
|
||||||
printf("%dd", x);
|
printf("%ud", x);
|
||||||
if ((x = (t/3600)%24))
|
if ((x = (t/3600)%24))
|
||||||
printf("%dh", x);
|
printf("%uh", x);
|
||||||
if ((x = (t/60)%60))
|
if ((x = (t/60)%60))
|
||||||
printf("%dm", x);
|
printf("%um", x);
|
||||||
if ((x = t%60))
|
if ((x = t%60))
|
||||||
printf("%ds", x);
|
printf("%us", x);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+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.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
Hi,
|
||||||
|
I updated the try-all-ns patch to work with the latest version of git. Ended up implementing it on top of master, 2.78test2-7-g63437ff. As that specific if-clause has been changed in the last few commits, it's not compatible for 2.77, sadly.
|
||||||
|
|
||||||
|
Find the patch attached.
|
||||||
|
|
||||||
|
Regards,
|
||||||
|
|
||||||
|
Rasmus Ahlberg
|
||||||
|
Software Developer, R&D
|
||||||
|
Electrolux Small Appliances
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
diff --git a/src/forward.c b/src/forward.c
|
||||||
|
index e3fa94b..ecf3b98 100644
|
||||||
|
--- a/src/forward.c
|
||||||
|
+++ b/src/forward.c
|
||||||
|
@@ -789,9 +789,12 @@ void reply_query(int fd, int family, time_t now)
|
||||||
|
|
||||||
|
/* Note: if we send extra options in the EDNS0 header, we can't recreate
|
||||||
|
the query from the reply. */
|
||||||
|
- if (RCODE(header) == REFUSED &&
|
||||||
|
- forward->forwardall == 0 &&
|
||||||
|
- !(forward->flags & FREC_HAS_EXTRADATA))
|
||||||
|
+ if ((RCODE(header) == REFUSED &&
|
||||||
|
+ forward->forwardall == 0 &&
|
||||||
|
+ !(forward->flags & FREC_HAS_EXTRADATA)) ||
|
||||||
|
+ /* If strict-order is set, try next server on NXDOMAIN reply */
|
||||||
|
+ (RCODE(header) == NXDOMAIN && option_bool(OPT_ORDER) &&
|
||||||
|
+ server->next != NULL))
|
||||||
|
/* for broken servers, attempt to send to another one. */
|
||||||
|
{
|
||||||
|
unsigned char *pheader;
|
||||||
Vendored
+34
-1
@@ -1,3 +1,36 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
* New upstream.
|
||||||
|
Security fixes for CVE-2017-13704 (closes: #877102)
|
||||||
|
Security fixes for CVE-2017-14491 - CVE-2017-14496 inclusive.
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 29 Sep 2017 21:34:00 +0000
|
||||||
|
|
||||||
dnsmasq (2.77-2) unstable; urgency=low
|
dnsmasq (2.77-2) unstable; urgency=low
|
||||||
|
|
||||||
* Improve sed regexp for parsing root.ds.
|
* Improve sed regexp for parsing root.ds.
|
||||||
@@ -11,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.
|
||||||
|
|||||||
+33
-21
@@ -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
|
||||||
@@ -2048,7 +2060,7 @@ include set:<tag>, including one from the
|
|||||||
.B dhcp-range
|
.B dhcp-range
|
||||||
used to allocate the address, one from any matching
|
used to allocate the address, one from any matching
|
||||||
.B dhcp-host
|
.B dhcp-host
|
||||||
(and "known" if a dhcp-host matches)
|
(and "known" or "known-othernet" if a dhcp-host matches)
|
||||||
The tag "bootp" is set for BOOTP requests, and a tag whose name is the
|
The tag "bootp" is set for BOOTP requests, and a tag whose name is the
|
||||||
name of the interface on which the request arrived is also set.
|
name of the interface on which the request arrived is also set.
|
||||||
|
|
||||||
|
|||||||
+547
-503
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-2016 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
-9
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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
|
||||||
@@ -119,11 +119,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
struct cname *a, *candidate;
|
struct cname *a, *candidate;
|
||||||
unsigned int wclen;
|
unsigned int wclen;
|
||||||
|
|
||||||
/* Clear buffer beyond request to avoid risk of
|
|
||||||
information disclosure. */
|
|
||||||
memset(((char *)header) + qlen, 0,
|
|
||||||
(limit - ((char *)header)) - qlen);
|
|
||||||
|
|
||||||
if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
|
if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -597,12 +592,12 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
char *p = name;
|
char *p = name;
|
||||||
|
|
||||||
if (subnet->prefixlen >= 24)
|
if (subnet->prefixlen >= 24)
|
||||||
p += sprintf(p, "%d.", a & 0xff);
|
p += sprintf(p, "%u.", a & 0xff);
|
||||||
a = a >> 8;
|
a = a >> 8;
|
||||||
if (subnet->prefixlen >= 16 )
|
if (subnet->prefixlen >= 16 )
|
||||||
p += sprintf(p, "%d.", a & 0xff);
|
p += sprintf(p, "%u.", a & 0xff);
|
||||||
a = a >> 8;
|
a = a >> 8;
|
||||||
p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
|
p += sprintf(p, "%u.in-addr.arpa", a & 0xff);
|
||||||
|
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
|
|||||||
+4
-3
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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-2016 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
|
||||||
|
|||||||
+7
-2
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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" },
|
||||||
@@ -1511,7 +1516,7 @@ void dump_cache(time_t now)
|
|||||||
/* ctime includes trailing \n - eat it */
|
/* ctime includes trailing \n - eat it */
|
||||||
*(p-1) = 0;
|
*(p-1) = 0;
|
||||||
#endif
|
#endif
|
||||||
my_syslog(LOG_INFO, daemon->namebuff);
|
my_syslog(LOG_INFO, "%s", daemon->namebuff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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-2016 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-2016 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-2016 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-2016 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
|
||||||
|
|||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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
|
||||||
@@ -273,8 +273,8 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
if ((relay = relay_reply4((struct dhcp_packet *)daemon->dhcp_packet.iov_base, ifr.ifr_name)))
|
if ((relay = relay_reply4((struct dhcp_packet *)daemon->dhcp_packet.iov_base, ifr.ifr_name)))
|
||||||
{
|
{
|
||||||
/* Reply from server, using us as relay. */
|
/* Reply from server, using us as relay. */
|
||||||
iface_index = relay->iface_index;
|
rcvd_iface_index = relay->iface_index;
|
||||||
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
|
if (!indextoname(daemon->dhcpfd, rcvd_iface_index, ifr.ifr_name))
|
||||||
return;
|
return;
|
||||||
is_relay_reply = 1;
|
is_relay_reply = 1;
|
||||||
iov.iov_len = sz;
|
iov.iov_len = sz;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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-2016 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-2016 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-2016 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);
|
||||||
|
|||||||
+50
-24
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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,13 @@
|
|||||||
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-2016 Simon Kelley"
|
#define COPYRIGHT "Copyright (c) 2000-2018 Simon Kelley"
|
||||||
|
|
||||||
|
/* We do defines that influence behavior of stdio.h, so complain
|
||||||
|
if included too early. */
|
||||||
|
#ifdef _STDIO_H
|
||||||
|
# error "Header file stdio.h included too early!"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef NO_LARGEFILE
|
#ifndef NO_LARGEFILE
|
||||||
/* Ensure we can use files >2GB (log files may grow this big) */
|
/* Ensure we can use files >2GB (log files may grow this big) */
|
||||||
@@ -136,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
|
||||||
|
|
||||||
@@ -169,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
|
||||||
@@ -446,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
|
||||||
@@ -508,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;
|
||||||
@@ -826,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1019,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;
|
||||||
@@ -1130,18 +1145,18 @@ unsigned int extract_request(struct dns_header *header, size_t qlen,
|
|||||||
char *name, unsigned short *typep);
|
char *name, unsigned short *typep);
|
||||||
size_t setup_reply(struct dns_header *header, size_t qlen,
|
size_t setup_reply(struct dns_header *header, size_t qlen,
|
||||||
struct all_addr *addrp, unsigned int flags,
|
struct all_addr *addrp, unsigned int flags,
|
||||||
unsigned long local_ttl);
|
unsigned long ttl);
|
||||||
int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff,
|
int extract_addresses(struct dns_header *header, size_t qlen, char *name,
|
||||||
time_t now, char **ipsets, int is_sign, int checkrebind,
|
time_t now, char **ipsets, int is_sign, int check_rebind,
|
||||||
int no_cache, int secure, int *doctored);
|
int no_cache_dnssec, int secure, int *doctored);
|
||||||
size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||||
struct in_addr local_addr, struct in_addr local_netmask,
|
struct in_addr local_addr, struct in_addr local_netmask,
|
||||||
time_t now, int ad_reqd, int do_bit, int have_pseudoheader);
|
time_t now, int ad_reqd, int do_bit, int have_pseudoheader);
|
||||||
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
||||||
struct bogus_addr *addr, time_t now);
|
struct bogus_addr *baddr, time_t now);
|
||||||
int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
|
int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
|
||||||
int check_for_local_domain(char *name, time_t now);
|
int check_for_local_domain(char *name, time_t now);
|
||||||
unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
|
unsigned int questions_crc(struct dns_header *header, size_t plen, char *name);
|
||||||
size_t resize_packet(struct dns_header *header, size_t plen,
|
size_t resize_packet(struct dns_header *header, size_t plen,
|
||||||
unsigned char *pheader, size_t hlen);
|
unsigned char *pheader, size_t hlen);
|
||||||
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
|
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
|
||||||
@@ -1163,23 +1178,32 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
|
|||||||
|
|
||||||
/* dnssec.c */
|
/* dnssec.c */
|
||||||
size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
|
size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
|
||||||
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, char *name, char *keyname, int class);
|
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
|
||||||
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
|
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
|
||||||
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class,
|
int 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 check_unsigned, int *neganswer, int *nons);
|
||||||
int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
|
int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen);
|
||||||
size_t filter_rrsigs(struct dns_header *header, size_t plen);
|
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);
|
||||||
u32 rand32(void);
|
u32 rand32(void);
|
||||||
u64 rand64(void);
|
u64 rand64(void);
|
||||||
int legal_hostname(char *c);
|
int legal_hostname(char *name);
|
||||||
char *canonicalise(char *s, int *nomem);
|
char *canonicalise(char *in, int *nomem);
|
||||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
|
unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
|
||||||
void *safe_malloc(size_t size);
|
void *safe_malloc(size_t size);
|
||||||
void safe_pipe(int *fd, int read_noblock);
|
void safe_pipe(int *fd, int read_noblock);
|
||||||
void *whine_malloc(size_t size);
|
void *whine_malloc(size_t size);
|
||||||
@@ -1212,7 +1236,9 @@ int wildcard_matchn(const char* wildcard, const char* match, int num);
|
|||||||
void die(char *message, char *arg1, int exit_code);
|
void die(char *message, char *arg1, int exit_code);
|
||||||
int log_start(struct passwd *ent_pw, int errfd);
|
int log_start(struct passwd *ent_pw, int errfd);
|
||||||
int log_reopen(char *log_file);
|
int log_reopen(char *log_file);
|
||||||
|
|
||||||
void my_syslog(int priority, const char *format, ...);
|
void my_syslog(int priority, const char *format, ...);
|
||||||
|
|
||||||
void set_log_writer(void);
|
void set_log_writer(void);
|
||||||
void check_log_writer(int force);
|
void check_log_writer(int force);
|
||||||
void flush_log(void);
|
void flush_log(void);
|
||||||
@@ -1240,13 +1266,13 @@ struct frec *get_new_frec(time_t now, int *wait, int force);
|
|||||||
int send_from(int fd, int nowild, char *packet, size_t len,
|
int send_from(int fd, int nowild, char *packet, size_t len,
|
||||||
union mysockaddr *to, struct all_addr *source,
|
union mysockaddr *to, struct all_addr *source,
|
||||||
unsigned int iface);
|
unsigned int iface);
|
||||||
void resend_query();
|
void resend_query(void);
|
||||||
struct randfd *allocate_rfd(int family);
|
struct randfd *allocate_rfd(int family);
|
||||||
void free_rfd(struct randfd *rfd);
|
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);
|
||||||
@@ -1260,12 +1286,12 @@ void add_update_server(int flags,
|
|||||||
void check_servers(void);
|
void check_servers(void);
|
||||||
int enumerate_interfaces(int reset);
|
int enumerate_interfaces(int reset);
|
||||||
void create_wildcard_listeners(void);
|
void create_wildcard_listeners(void);
|
||||||
void create_bound_listeners(int die);
|
void create_bound_listeners(int dienow);
|
||||||
void warn_bound_listeners(void);
|
void warn_bound_listeners(void);
|
||||||
void warn_wild_labels(void);
|
void warn_wild_labels(void);
|
||||||
void warn_int_names(void);
|
void warn_int_names(void);
|
||||||
int is_dad_listeners(void);
|
int is_dad_listeners(void);
|
||||||
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
|
int iface_check(int family, struct all_addr *addr, char *name, int *auth);
|
||||||
int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
|
int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
|
||||||
int label_exception(int index, int family, struct all_addr *addr);
|
int label_exception(int index, int family, struct all_addr *addr);
|
||||||
int fix_fd(int fd);
|
int fix_fd(int fd);
|
||||||
@@ -1286,7 +1312,7 @@ void newaddress(time_t now);
|
|||||||
void dhcp_init(void);
|
void dhcp_init(void);
|
||||||
void dhcp_packet(time_t now, int pxe_fd);
|
void dhcp_packet(time_t now, int pxe_fd);
|
||||||
struct dhcp_context *address_available(struct dhcp_context *context,
|
struct dhcp_context *address_available(struct dhcp_context *context,
|
||||||
struct in_addr addr,
|
struct in_addr taddr,
|
||||||
struct dhcp_netid *netids);
|
struct dhcp_netid *netids);
|
||||||
struct dhcp_context *narrow_context(struct dhcp_context *context,
|
struct dhcp_context *narrow_context(struct dhcp_context *context,
|
||||||
struct in_addr taddr,
|
struct in_addr taddr,
|
||||||
@@ -1345,7 +1371,7 @@ void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data,
|
|||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||||
size_t sz, time_t now, int unicast_dest, int loopback,
|
size_t sz, time_t now, int unicast_dest, int loopback,
|
||||||
int *is_inform, int pxe_fd, struct in_addr fallback, time_t recvtime);
|
int *is_inform, int pxe, struct in_addr fallback, time_t recvtime);
|
||||||
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
||||||
int clid_len, unsigned char *clid, int *len_out);
|
int clid_len, unsigned char *clid, int *len_out);
|
||||||
#endif
|
#endif
|
||||||
@@ -1460,10 +1486,10 @@ unsigned short relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arriva
|
|||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
void dhcp_common_init(void);
|
void dhcp_common_init(void);
|
||||||
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg);
|
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg);
|
||||||
struct dhcp_netid *run_tag_if(struct dhcp_netid *input);
|
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags);
|
||||||
struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *context_tags,
|
struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *context_tags,
|
||||||
struct dhcp_opt *opts);
|
struct dhcp_opt *opts);
|
||||||
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);
|
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded);
|
||||||
char *strip_hostname(char *hostname);
|
char *strip_hostname(char *hostname);
|
||||||
void log_tags(struct dhcp_netid *netid, u32 xid);
|
void log_tags(struct dhcp_netid *netid, u32 xid);
|
||||||
int match_bytes(struct dhcp_opt *o, unsigned char *p, int len);
|
int match_bytes(struct dhcp_opt *o, unsigned char *p, int len);
|
||||||
@@ -1521,13 +1547,13 @@ void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
|
|||||||
|
|
||||||
/* loop.c */
|
/* loop.c */
|
||||||
#ifdef HAVE_LOOP
|
#ifdef HAVE_LOOP
|
||||||
void loop_send_probes();
|
void loop_send_probes(void);
|
||||||
int detect_loop(char *query, int type);
|
int detect_loop(char *query, int type);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* inotify.c */
|
/* inotify.c */
|
||||||
#ifdef HAVE_INOTIFY
|
#ifdef HAVE_INOTIFY
|
||||||
void inotify_dnsmasq_init();
|
void inotify_dnsmasq_init(void);
|
||||||
int inotify_check(time_t now);
|
int inotify_check(time_t now);
|
||||||
void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz);
|
void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+245
-424
@@ -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-2016 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2230,7 +2051,7 @@ size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char
|
|||||||
|
|
||||||
p = (unsigned char *)(header+1);
|
p = (unsigned char *)(header+1);
|
||||||
|
|
||||||
p = do_rfc1035_name(p, name);
|
p = do_rfc1035_name(p, name, NULL);
|
||||||
*p++ = 0;
|
*p++ = 0;
|
||||||
PUTSHORT(type, p);
|
PUTSHORT(type, p);
|
||||||
PUTSHORT(class, p);
|
PUTSHORT(class, p);
|
||||||
|
|||||||
+147
-80
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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);
|
||||||
|
|||||||
+24
-4
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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
|
||||||
@@ -144,7 +144,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
|||||||
GETSHORT(len, p);
|
GETSHORT(len, p);
|
||||||
|
|
||||||
/* malformed option, delete the whole OPT RR and start again. */
|
/* malformed option, delete the whole OPT RR and start again. */
|
||||||
if (i + len > rdlen)
|
if (i + 4 + len > rdlen)
|
||||||
{
|
{
|
||||||
rdlen = 0;
|
rdlen = 0;
|
||||||
is_last = 0;
|
is_last = 0;
|
||||||
@@ -159,7 +159,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
|||||||
/* delete option if we're to replace it. */
|
/* delete option if we're to replace it. */
|
||||||
p -= 4;
|
p -= 4;
|
||||||
rdlen -= len + 4;
|
rdlen -= len + 4;
|
||||||
memcpy(p, p+len+4, rdlen - i);
|
memmove(p, p+len+4, rdlen - i);
|
||||||
PUTSHORT(rdlen, lenp);
|
PUTSHORT(rdlen, lenp);
|
||||||
lenp -= 2;
|
lenp -= 2;
|
||||||
}
|
}
|
||||||
@@ -192,7 +192,15 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
|||||||
!(p = skip_section(p,
|
!(p = skip_section(p,
|
||||||
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
|
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
|
||||||
header, plen)))
|
header, plen)))
|
||||||
|
{
|
||||||
|
free(buff);
|
||||||
return plen;
|
return plen;
|
||||||
|
}
|
||||||
|
if (p + 11 > limit)
|
||||||
|
{
|
||||||
|
free(buff);
|
||||||
|
return plen; /* Too big */
|
||||||
|
}
|
||||||
*p++ = 0; /* empty name */
|
*p++ = 0; /* empty name */
|
||||||
PUTSHORT(T_OPT, p);
|
PUTSHORT(T_OPT, p);
|
||||||
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
|
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
|
||||||
@@ -204,11 +212,19 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
|||||||
/* Copy back any options */
|
/* Copy back any options */
|
||||||
if (buff)
|
if (buff)
|
||||||
{
|
{
|
||||||
|
if (p + rdlen > limit)
|
||||||
|
{
|
||||||
|
free(buff);
|
||||||
|
return plen; /* Too big */
|
||||||
|
}
|
||||||
memcpy(p, buff, rdlen);
|
memcpy(p, buff, rdlen);
|
||||||
free(buff);
|
free(buff);
|
||||||
p += rdlen;
|
p += rdlen;
|
||||||
}
|
}
|
||||||
header->arcount = htons(ntohs(header->arcount) + 1);
|
|
||||||
|
/* Only bump arcount if RR is going to fit */
|
||||||
|
if (((ssize_t)optlen) <= (limit - (p + 4)))
|
||||||
|
header->arcount = htons(ntohs(header->arcount) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((ssize_t)optlen) > (limit - (p + 4)))
|
if (((ssize_t)optlen) > (limit - (p + 4)))
|
||||||
@@ -217,8 +233,12 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
|||||||
/* Add new option */
|
/* Add new option */
|
||||||
if (optno != 0 && replace != 2)
|
if (optno != 0 && replace != 2)
|
||||||
{
|
{
|
||||||
|
if (p + 4 > limit)
|
||||||
|
return plen; /* Too big */
|
||||||
PUTSHORT(optno, p);
|
PUTSHORT(optno, p);
|
||||||
PUTSHORT(optlen, p);
|
PUTSHORT(optlen, p);
|
||||||
|
if (p + optlen > limit)
|
||||||
|
return plen; /* Too big */
|
||||||
memcpy(p, opt, optlen);
|
memcpy(p, opt, optlen);
|
||||||
p += optlen;
|
p += optlen;
|
||||||
PUTSHORT(p - datap, lenp);
|
PUTSHORT(p - datap, lenp);
|
||||||
|
|||||||
+92
-65
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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
|
||||||
@@ -790,7 +795,6 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
/* Note: if we send extra options in the EDNS0 header, we can't recreate
|
/* Note: if we send extra options in the EDNS0 header, we can't recreate
|
||||||
the query from the reply. */
|
the query from the reply. */
|
||||||
if (RCODE(header) == REFUSED &&
|
if (RCODE(header) == REFUSED &&
|
||||||
!option_bool(OPT_ORDER) &&
|
|
||||||
forward->forwardall == 0 &&
|
forward->forwardall == 0 &&
|
||||||
!(forward->flags & FREC_HAS_EXTRADATA))
|
!(forward->flags & FREC_HAS_EXTRADATA))
|
||||||
/* for broken servers, attempt to send to another one. */
|
/* for broken servers, attempt to send to another one. */
|
||||||
@@ -798,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);
|
||||||
@@ -845,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
|
||||||
@@ -859,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);
|
||||||
|
|
||||||
@@ -899,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
|
||||||
@@ -1096,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))
|
||||||
{
|
{
|
||||||
@@ -1189,6 +1210,10 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
(msg.msg_flags & MSG_TRUNC) ||
|
(msg.msg_flags & MSG_TRUNC) ||
|
||||||
(header->hb3 & HB3_QR))
|
(header->hb3 & HB3_QR))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Clear buffer beyond request to avoid risk of
|
||||||
|
information disclosure. */
|
||||||
|
memset(daemon->packet + n, 0, daemon->edns_pktsz - n);
|
||||||
|
|
||||||
source_addr.sa.sa_family = listen->family;
|
source_addr.sa.sa_family = listen->family;
|
||||||
|
|
||||||
@@ -1409,6 +1434,8 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
defaults to 512 */
|
defaults to 512 */
|
||||||
if (udp_size > daemon->edns_pktsz)
|
if (udp_size > daemon->edns_pktsz)
|
||||||
udp_size = daemon->edns_pktsz;
|
udp_size = daemon->edns_pktsz;
|
||||||
|
else if (udp_size < PACKETSZ)
|
||||||
|
udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_AUTH
|
#ifdef HAVE_AUTH
|
||||||
@@ -1477,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;
|
||||||
@@ -1546,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);
|
||||||
@@ -1689,6 +1717,10 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
|
|
||||||
if (size < (int)sizeof(struct dns_header))
|
if (size < (int)sizeof(struct dns_header))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Clear buffer beyond request to avoid risk of
|
||||||
|
information disclosure. */
|
||||||
|
memset(payload + size, 0, 65536 - size);
|
||||||
|
|
||||||
query_count++;
|
query_count++;
|
||||||
|
|
||||||
@@ -1774,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)
|
||||||
@@ -1838,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);
|
||||||
@@ -1849,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
-3
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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,6 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
#ifdef HAVE_SCRIPT
|
#ifdef HAVE_SCRIPT
|
||||||
@@ -98,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-2016 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-2016 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-2016 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
|
||||||
@@ -229,7 +229,7 @@ void lease_update_from_configs(void)
|
|||||||
else if ((name = host_from_dns(lease->addr)))
|
else if ((name = host_from_dns(lease->addr)))
|
||||||
lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */
|
lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ourprintf(int *errp, char *format, ...)
|
static void ourprintf(int *errp, char *format, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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-2016 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-2016 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
|
||||||
|
|||||||
+28
-17
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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);
|
||||||
@@ -1460,13 +1475,6 @@ void check_servers(void)
|
|||||||
for (sfd = daemon->sfds; sfd; sfd = sfd->next)
|
for (sfd = daemon->sfds; sfd; sfd = sfd->next)
|
||||||
sfd->used = 0;
|
sfd->used = 0;
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
/* Disable DNSSEC validation when using server=/domain/.... servers
|
|
||||||
unless there's a configured trust anchor. */
|
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
|
||||||
serv->flags |= SERV_DO_DNSSEC;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (count = 0, serv = daemon->servers; serv; serv = serv->next)
|
for (count = 0, serv = daemon->servers; serv; serv = serv->next)
|
||||||
{
|
{
|
||||||
if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
|
if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
|
||||||
@@ -1478,6 +1486,11 @@ void check_servers(void)
|
|||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
{
|
{
|
||||||
|
if (!(serv->flags & SERV_FOR_NODOTS))
|
||||||
|
serv->flags |= SERV_DO_DNSSEC;
|
||||||
|
|
||||||
|
/* Disable DNSSEC validation when using server=/domain/.... servers
|
||||||
|
unless there's a configured trust anchor. */
|
||||||
if (serv->flags & SERV_HAS_DOMAIN)
|
if (serv->flags & SERV_HAS_DOMAIN)
|
||||||
{
|
{
|
||||||
struct ds_config *ds;
|
struct ds_config *ds;
|
||||||
@@ -1494,8 +1507,6 @@ void check_servers(void)
|
|||||||
if (!ds)
|
if (!ds)
|
||||||
serv->flags &= ~SERV_DO_DNSSEC;
|
serv->flags &= ~SERV_DO_DNSSEC;
|
||||||
}
|
}
|
||||||
else if (serv->flags & SERV_FOR_NODOTS)
|
|
||||||
serv->flags &= ~SERV_DO_DNSSEC;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+134
-88
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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
|
||||||
@@ -882,7 +882,7 @@ static struct server *add_rev4(struct in_addr addr, int msize)
|
|||||||
switch (msize)
|
switch (msize)
|
||||||
{
|
{
|
||||||
case 32:
|
case 32:
|
||||||
p += sprintf(p, "%d.", a & 0xff);
|
p += sprintf(p, "%u.", a & 0xff);
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 24:
|
case 24:
|
||||||
p += sprintf(p, "%d.", (a >> 8) & 0xff);
|
p += sprintf(p, "%d.", (a >> 8) & 0xff);
|
||||||
@@ -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;
|
||||||
@@ -1415,7 +1415,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
p = newp;
|
p = newp;
|
||||||
end = do_rfc1035_name(p + len, dom);
|
end = do_rfc1035_name(p + len, dom, NULL);
|
||||||
*end++ = 0;
|
*end++ = 0;
|
||||||
len = end - p;
|
len = end - p;
|
||||||
free(dom);
|
free(dom);
|
||||||
@@ -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;
|
||||||
|
|
||||||
arg += strlen(arg)+1;
|
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-2016 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-2016 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-2016 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
|
||||||
|
|||||||
+5
-2
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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
|
||||||
@@ -198,6 +198,9 @@ void icmp6_packet(time_t now)
|
|||||||
/* look for link-layer address option for logging */
|
/* look for link-layer address option for logging */
|
||||||
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
|
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
|
||||||
{
|
{
|
||||||
|
if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
|
print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
|
||||||
mac = daemon->namebuff;
|
mac = daemon->namebuff;
|
||||||
}
|
}
|
||||||
@@ -404,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)
|
||||||
{
|
{
|
||||||
|
|||||||
+102
-81
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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,8 +36,8 @@ 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, p, plen, extrabytes))
|
if (!CHECK_LEN(header, p1 ? p1 : p, plen, extrabytes))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (isExtract)
|
if (isExtract)
|
||||||
@@ -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 == '.')
|
||||||
{
|
{
|
||||||
@@ -498,6 +498,8 @@ static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *
|
|||||||
{
|
{
|
||||||
unsigned int i, len = *p1;
|
unsigned int i, len = *p1;
|
||||||
unsigned char *p2 = p1;
|
unsigned char *p2 = p1;
|
||||||
|
if ((p1 + len - p) >= rdlen)
|
||||||
|
return 0; /* bad packet */
|
||||||
/* make counted string zero-term and sanitise */
|
/* make counted string zero-term and sanitise */
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
@@ -582,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;
|
||||||
@@ -593,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();
|
||||||
|
|
||||||
@@ -601,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. */
|
||||||
@@ -615,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;
|
||||||
@@ -643,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) ||
|
||||||
@@ -670,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,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
|
||||||
@@ -724,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 */
|
||||||
|
|
||||||
@@ -742,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--)
|
||||||
@@ -833,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;
|
||||||
@@ -913,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);
|
||||||
@@ -948,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;
|
||||||
|
|
||||||
@@ -1062,6 +1098,7 @@ int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bog
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
|
int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
|
||||||
unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
|
unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
|
||||||
{
|
{
|
||||||
@@ -1071,29 +1108,41 @@ 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) \
|
||||||
|
if (limit && p + (size) > (unsigned char*)limit) 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);
|
||||||
PUTSHORT(nameoffset | 0xc000, p);
|
PUTSHORT(nameoffset | 0xc000, p);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *name = va_arg(ap, char *);
|
char *name = va_arg(ap, char *);
|
||||||
if (name)
|
if (name && !(p = do_rfc1035_name(p, name, limit)))
|
||||||
p = do_rfc1035_name(p, name);
|
goto truncated;
|
||||||
|
|
||||||
if (nameoffset < 0)
|
if (nameoffset < 0)
|
||||||
{
|
{
|
||||||
|
CHECK_LIMIT(2);
|
||||||
PUTSHORT(-nameoffset | 0xc000, p);
|
PUTSHORT(-nameoffset | 0xc000, p);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*p++ = 0;
|
{
|
||||||
|
CHECK_LIMIT(1);
|
||||||
|
*p++ = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* type (2) + class (2) + ttl (4) + rdlen (2) */
|
||||||
|
CHECK_LIMIT(10);
|
||||||
|
|
||||||
PUTSHORT(type, p);
|
PUTSHORT(type, p);
|
||||||
PUTSHORT(class, p);
|
PUTSHORT(class, p);
|
||||||
PUTLONG(ttl, p); /* TTL */
|
PUTLONG(ttl, p); /* TTL */
|
||||||
@@ -1106,6 +1155,7 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
|||||||
{
|
{
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
case '6':
|
case '6':
|
||||||
|
CHECK_LIMIT(IN6ADDRSZ);
|
||||||
sval = va_arg(ap, char *);
|
sval = va_arg(ap, char *);
|
||||||
memcpy(p, sval, IN6ADDRSZ);
|
memcpy(p, sval, IN6ADDRSZ);
|
||||||
p += IN6ADDRSZ;
|
p += IN6ADDRSZ;
|
||||||
@@ -1113,36 +1163,43 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
case '4':
|
case '4':
|
||||||
|
CHECK_LIMIT(INADDRSZ);
|
||||||
sval = va_arg(ap, char *);
|
sval = va_arg(ap, char *);
|
||||||
memcpy(p, sval, INADDRSZ);
|
memcpy(p, sval, INADDRSZ);
|
||||||
p += INADDRSZ;
|
p += INADDRSZ;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
|
CHECK_LIMIT(1);
|
||||||
usval = va_arg(ap, int);
|
usval = va_arg(ap, int);
|
||||||
*p++ = usval;
|
*p++ = usval;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
|
CHECK_LIMIT(2);
|
||||||
usval = va_arg(ap, int);
|
usval = va_arg(ap, int);
|
||||||
PUTSHORT(usval, p);
|
PUTSHORT(usval, p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
|
CHECK_LIMIT(4);
|
||||||
lval = va_arg(ap, long);
|
lval = va_arg(ap, long);
|
||||||
PUTLONG(lval, p);
|
PUTLONG(lval, p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
/* 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 *));
|
if (!(p = do_rfc1035_name(p, va_arg(ap, char *), limit)))
|
||||||
*p++ = 0;
|
goto truncated;
|
||||||
|
CHECK_LIMIT(1);
|
||||||
|
*p++ = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
usval = va_arg(ap, int);
|
usval = va_arg(ap, int);
|
||||||
|
CHECK_LIMIT(usval);
|
||||||
sval = va_arg(ap, char *);
|
sval = va_arg(ap, char *);
|
||||||
if (usval != 0)
|
if (usval != 0)
|
||||||
memcpy(p, sval, usval);
|
memcpy(p, sval, usval);
|
||||||
@@ -1154,6 +1211,7 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
|||||||
usval = sval ? strlen(sval) : 0;
|
usval = sval ? strlen(sval) : 0;
|
||||||
if (usval > 255)
|
if (usval > 255)
|
||||||
usval = 255;
|
usval = 255;
|
||||||
|
CHECK_LIMIT(usval + 1);
|
||||||
*p++ = (unsigned char)usval;
|
*p++ = (unsigned char)usval;
|
||||||
memcpy(p, sval, usval);
|
memcpy(p, sval, usval);
|
||||||
p += usval;
|
p += usval;
|
||||||
@@ -1162,19 +1220,20 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
|||||||
|
|
||||||
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;
|
||||||
PUTSHORT(j, sav); /* Now, store real RDLength */
|
PUTSHORT(j, sav);
|
||||||
|
|
||||||
/* check for overflow of buffer */
|
|
||||||
if (limit && ((unsigned char *)limit - p) < 0)
|
|
||||||
{
|
|
||||||
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)
|
||||||
@@ -1223,16 +1282,15 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
struct mx_srv_record *rec;
|
struct mx_srv_record *rec;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
/* Clear buffer beyond request to avoid risk of
|
|
||||||
information disclosure. */
|
|
||||||
memset(((char *)header) + qlen, 0,
|
|
||||||
(limit - ((char *)header)) - qlen);
|
|
||||||
|
|
||||||
if (ntohs(header->ancount) != 0 ||
|
if (ntohs(header->ancount) != 0 ||
|
||||||
ntohs(header->nscount) != 0 ||
|
ntohs(header->nscount) != 0 ||
|
||||||
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)
|
||||||
@@ -1510,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)
|
||||||
@@ -1716,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;
|
||||||
|
|||||||
+11
-13
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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
|
||||||
@@ -32,7 +32,7 @@ static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, in
|
|||||||
static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
|
static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
|
||||||
int opt, char *string, int null_term);
|
int opt, char *string, int null_term);
|
||||||
static struct in_addr option_addr(unsigned char *opt);
|
static struct in_addr option_addr(unsigned char *opt);
|
||||||
static unsigned int option_uint(unsigned char *opt, int i, int size);
|
static unsigned int option_uint(unsigned char *opt, int offset, int size);
|
||||||
static void log_packet(char *type, void *addr, unsigned char *ext_mac,
|
static void log_packet(char *type, void *addr, unsigned char *ext_mac,
|
||||||
int mac_len, char *interface, char *string, char *err, u32 xid);
|
int mac_len, char *interface, char *string, char *err, u32 xid);
|
||||||
static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
|
static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
|
||||||
@@ -42,14 +42,14 @@ static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
|
|||||||
static int in_list(unsigned char *list, int opt);
|
static int in_list(unsigned char *list, int opt);
|
||||||
static void do_options(struct dhcp_context *context,
|
static void do_options(struct dhcp_context *context,
|
||||||
struct dhcp_packet *mess,
|
struct dhcp_packet *mess,
|
||||||
unsigned char *real_end,
|
unsigned char *end,
|
||||||
unsigned char *req_options,
|
unsigned char *req_options,
|
||||||
char *hostname,
|
char *hostname,
|
||||||
char *config_domain,
|
char *domain,
|
||||||
struct dhcp_netid *netid,
|
struct dhcp_netid *netid,
|
||||||
struct in_addr subnet_addr,
|
struct in_addr subnet_addr,
|
||||||
unsigned char fqdn_flags,
|
unsigned char fqdn_flags,
|
||||||
int null_term, int pxearch,
|
int null_term, int pxe_arch,
|
||||||
unsigned char *uuid,
|
unsigned char *uuid,
|
||||||
int vendor_class_len,
|
int vendor_class_len,
|
||||||
time_t now,
|
time_t now,
|
||||||
@@ -58,7 +58,7 @@ static void do_options(struct dhcp_context *context,
|
|||||||
|
|
||||||
|
|
||||||
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
|
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
|
||||||
static int do_encap_opts(struct dhcp_opt *opts, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
|
static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
|
||||||
static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid);
|
static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid);
|
||||||
static int prune_vendor_opts(struct dhcp_netid *netid);
|
static int prune_vendor_opts(struct dhcp_netid *netid);
|
||||||
static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now);
|
static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now);
|
||||||
@@ -157,7 +157,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
for (offset = 0; offset < (len - 5); offset += elen + 5)
|
for (offset = 0; offset < (len - 5); offset += elen + 5)
|
||||||
{
|
{
|
||||||
elen = option_uint(opt, offset + 4 , 1);
|
elen = option_uint(opt, offset + 4 , 1);
|
||||||
if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA)
|
if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA && offset + elen + 5 <= len)
|
||||||
{
|
{
|
||||||
unsigned char *x = option_ptr(opt, offset + 5);
|
unsigned char *x = option_ptr(opt, offset + 5);
|
||||||
unsigned char *y = option_ptr(opt, offset + elen + 5);
|
unsigned char *y = option_ptr(opt, offset + elen + 5);
|
||||||
@@ -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;
|
||||||
@@ -1040,8 +1040,6 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
else if (have_config(config, CONFIG_DECLINED) &&
|
else if (have_config(config, CONFIG_DECLINED) &&
|
||||||
difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
|
difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs);
|
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs);
|
||||||
else if ((!lease || lease->addr.s_addr != config->addr.s_addr) && !do_icmp_ping(now, config->addr, 0, loopback))
|
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by another host"), addrs);
|
|
||||||
else
|
else
|
||||||
conf = config->addr;
|
conf = config->addr;
|
||||||
}
|
}
|
||||||
@@ -2286,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)))
|
||||||
@@ -2454,10 +2452,10 @@ static void do_options(struct dhcp_context *context,
|
|||||||
|
|
||||||
if (fqdn_flags & 0x04)
|
if (fqdn_flags & 0x04)
|
||||||
{
|
{
|
||||||
p = do_rfc1035_name(p, hostname);
|
p = do_rfc1035_name(p, hostname, NULL);
|
||||||
if (domain)
|
if (domain)
|
||||||
{
|
{
|
||||||
p = do_rfc1035_name(p, domain);
|
p = do_rfc1035_name(p, domain, NULL);
|
||||||
*p++ = 0;
|
*p++ = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-5
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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
|
||||||
@@ -206,6 +206,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
|||||||
/* RFC-6939 */
|
/* RFC-6939 */
|
||||||
if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3)))
|
if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3)))
|
||||||
{
|
{
|
||||||
|
if (opt6_len(opt) - 2 > DHCP_CHADDR_MAX) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
state->mac_type = opt6_uint(opt, 0, 2);
|
state->mac_type = opt6_uint(opt, 0, 2);
|
||||||
state->mac_len = opt6_len(opt) - 2;
|
state->mac_len = opt6_len(opt) - 2;
|
||||||
memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);
|
memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);
|
||||||
@@ -213,6 +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)
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
@@ -876,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;
|
||||||
@@ -1479,10 +1485,10 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
|
|||||||
if ((p = expand(len + 2)))
|
if ((p = expand(len + 2)))
|
||||||
{
|
{
|
||||||
*(p++) = state->fqdn_flags;
|
*(p++) = state->fqdn_flags;
|
||||||
p = do_rfc1035_name(p, state->hostname);
|
p = do_rfc1035_name(p, state->hostname, NULL);
|
||||||
if (state->send_domain)
|
if (state->send_domain)
|
||||||
{
|
{
|
||||||
p = do_rfc1035_name(p, state->send_domain);
|
p = do_rfc1035_name(p, state->send_domain, NULL);
|
||||||
*p = 0;
|
*p = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1619,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-2016 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-2016 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
|
||||||
|
|||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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 @@
|
|||||||
|
|
||||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
|
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
|
||||||
static void free_transfer(struct tftp_transfer *transfer);
|
static void free_transfer(struct tftp_transfer *transfer);
|
||||||
static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
|
static ssize_t tftp_err(int err, char *packet, char *message, char *file);
|
||||||
static ssize_t tftp_err_oops(char *packet, char *file);
|
static ssize_t tftp_err_oops(char *packet, char *file);
|
||||||
static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
|
static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
|
||||||
static char *next(char **p, char *end);
|
static char *next(char **p, char *end);
|
||||||
@@ -734,7 +734,7 @@ static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
|
|||||||
if (transfer->opt_blocksize)
|
if (transfer->opt_blocksize)
|
||||||
{
|
{
|
||||||
p += (sprintf(p, "blksize") + 1);
|
p += (sprintf(p, "blksize") + 1);
|
||||||
p += (sprintf(p, "%d", transfer->blocksize) + 1);
|
p += (sprintf(p, "%u", transfer->blocksize) + 1);
|
||||||
}
|
}
|
||||||
if (transfer->opt_transize)
|
if (transfer->opt_transize)
|
||||||
{
|
{
|
||||||
|
|||||||
+52
-30
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2016 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
|
||||||
@@ -111,6 +111,7 @@ u64 rand64(void)
|
|||||||
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
|
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* returns 2 if names is OK but contains one or more underscores */
|
||||||
static int check_name(char *in)
|
static int check_name(char *in)
|
||||||
{
|
{
|
||||||
/* remove trailing .
|
/* remove trailing .
|
||||||
@@ -118,6 +119,7 @@ static int check_name(char *in)
|
|||||||
size_t dotgap = 0, l = strlen(in);
|
size_t dotgap = 0, l = strlen(in);
|
||||||
char c;
|
char c;
|
||||||
int nowhite = 0;
|
int nowhite = 0;
|
||||||
|
int hasuscore = 0;
|
||||||
|
|
||||||
if (l == 0 || l > MAXDNAME) return 0;
|
if (l == 0 || l > MAXDNAME) return 0;
|
||||||
|
|
||||||
@@ -141,13 +143,17 @@ static int check_name(char *in)
|
|||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
else if (c != ' ')
|
else if (c != ' ')
|
||||||
nowhite = 1;
|
{
|
||||||
|
nowhite = 1;
|
||||||
|
if (c == '_')
|
||||||
|
hasuscore = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nowhite)
|
if (!nowhite)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return hasuscore ? 2 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hostnames have a more limited valid charset than domain names
|
/* Hostnames have a more limited valid charset than domain names
|
||||||
@@ -186,56 +192,70 @@ int legal_hostname(char *name)
|
|||||||
char *canonicalise(char *in, int *nomem)
|
char *canonicalise(char *in, int *nomem)
|
||||||
{
|
{
|
||||||
char *ret = NULL;
|
char *ret = NULL;
|
||||||
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2)
|
|
||||||
int rc;
|
int rc;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (nomem)
|
if (nomem)
|
||||||
*nomem = 0;
|
*nomem = 0;
|
||||||
|
|
||||||
if (!check_name(in))
|
if (!(rc = check_name(in)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2)
|
#if defined(HAVE_LIBIDN2) && (!defined(IDN2_VERSION_NUMBER) || IDN2_VERSION_NUMBER < 0x02000003)
|
||||||
#ifdef HAVE_LIBIDN2
|
/* older libidn2 strips underscores, so don't do IDN processing
|
||||||
rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
|
if the name has an underscore (check_name() returned 2) */
|
||||||
if (rc == IDN2_DISALLOWED)
|
if (rc != 2)
|
||||||
rc = idn2_to_ascii_lz(in, &ret, IDN2_TRANSITIONAL);
|
|
||||||
#else
|
|
||||||
rc = idna_to_ascii_lz(in, &ret, 0);
|
|
||||||
#endif
|
#endif
|
||||||
if (rc != IDNA_SUCCESS)
|
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2)
|
||||||
{
|
{
|
||||||
if (ret)
|
# ifdef HAVE_LIBIDN2
|
||||||
free(ret);
|
rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
|
||||||
|
if (rc == IDN2_DISALLOWED)
|
||||||
if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
|
rc = idn2_to_ascii_lz(in, &ret, IDN2_TRANSITIONAL);
|
||||||
|
# else
|
||||||
|
rc = idna_to_ascii_lz(in, &ret, 0);
|
||||||
|
# endif
|
||||||
|
if (rc != IDNA_SUCCESS)
|
||||||
{
|
{
|
||||||
my_syslog(LOG_ERR, _("failed to allocate memory"));
|
if (ret)
|
||||||
*nomem = 1;
|
free(ret);
|
||||||
|
|
||||||
|
if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("failed to allocate memory"));
|
||||||
|
*nomem = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
if ((ret = whine_malloc(strlen(in)+1)))
|
if ((ret = whine_malloc(strlen(in)+1)))
|
||||||
strcpy(ret, in);
|
strcpy(ret, in);
|
||||||
else if (nomem)
|
else if (nomem)
|
||||||
*nomem = 1;
|
*nomem = 1;
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
|
unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
while (sval && *sval)
|
while (sval && *sval)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
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;
|
||||||
@@ -243,10 +263,12 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
|
|||||||
#endif
|
#endif
|
||||||
*p++ = *sval;
|
*p++ = *sval;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cp = j;
|
*cp = j;
|
||||||
if (*sval)
|
if (*sval)
|
||||||
sval++;
|
sval++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,13 +470,13 @@ void prettyprint_time(char *buf, unsigned int t)
|
|||||||
{
|
{
|
||||||
unsigned int x, p = 0;
|
unsigned int x, p = 0;
|
||||||
if ((x = t/86400))
|
if ((x = t/86400))
|
||||||
p += sprintf(&buf[p], "%dd", x);
|
p += sprintf(&buf[p], "%ud", x);
|
||||||
if ((x = (t/3600)%24))
|
if ((x = (t/3600)%24))
|
||||||
p += sprintf(&buf[p], "%dh", x);
|
p += sprintf(&buf[p], "%uh", x);
|
||||||
if ((x = (t/60)%60))
|
if ((x = (t/60)%60))
|
||||||
p += sprintf(&buf[p], "%dm", x);
|
p += sprintf(&buf[p], "%um", x);
|
||||||
if ((x = t%60))
|
if ((x = t%60))
|
||||||
p += sprintf(&buf[p], "%ds", x);
|
p += sprintf(&buf[p], "%us", x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user