Compare commits

...

14 Commits

Author SHA1 Message Date
Simon Kelley
d05dd58de1 Fix wrong reply to simple name when --domain-needed set and no servers configured.
Also return REFUSED and not SERVFAIL when out of memory.

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

The rationale is that the chain-of-trust will not be complete to
private servers. If it was, it would not be necessary to access the
server direct.
2016-01-11 22:50:00 +00:00
Simon Kelley
b633de9413 Fix FTBFS when scripts excluded at compilation time. 2016-01-06 22:51:17 +00:00
Simon Kelley
c49778df4a Update copyright notices. Happy new year! 2016-01-06 18:52:33 +00:00
Simon Kelley
53a9173fc0 Handle building with script support enabled and DHCP disabled. 2016-01-06 17:59:13 +00:00
44 changed files with 316 additions and 103 deletions

View File

@@ -18,6 +18,19 @@ version 2.76
that the same name is empty. Thanks to Edwin Török for
the patch.
Fix failure to correctly calculate cache-size when
reading a hosts-file fails. Thanks to André Glüpker
for the patch.
Fix wrong answer to simple name query when --domain-needed
set, but no upstream servers configured. Dnsmasq returned
REFUSED, in this case, when it should be the same as when
upstream servers are configured - NOERROR. Thanks to
Allain Legacy for spotting the problem.
Return REFUSED when running out of forwarding table slots,
not SERVFAIL.
version 2.75
Fix reversion on 2.74 which caused 100% CPU use when a

View File

@@ -1,4 +1,4 @@
# dnsmasq is Copyright (c) 2000-2015 Simon Kelley
# dnsmasq is Copyright (c) 2000-2016 Simon Kelley
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

2
debian/copyright vendored
View File

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

View File

@@ -405,7 +405,10 @@ xxx.internal.thekelleys.org.uk at 192.168.1.1 then giving the flag
.B -S /internal.thekelleys.org.uk/192.168.1.1
will send all queries for
internal machines to that nameserver, everything else will go to the
servers in /etc/resolv.conf. An empty domain specification,
servers in /etc/resolv.conf. DNSSEC validation is turned off for such
private nameservers, UNLESS a
.B --trust-anchor
is specified for the domain in question. An empty domain specification,
.B //
has the special meaning of "unqualified names only" ie names without any
dots in them. A non-standard port may be specified as

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -132,7 +132,7 @@ int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now)
}
#endif
/* Only accept poitive entries unless in lazy mode. */
/* Only accept positive entries unless in lazy mode. */
if (arp->status != ARP_EMPTY || lazy || updated)
{
if (mac && arp->hwlen != 0)
@@ -148,7 +148,7 @@ int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now)
last = now;
/* Mark all non-negative entries */
for (arp = arps, up = &arps; arp; arp = arp->next)
for (arp = arps; arp; arp = arp->next)
if (arp->status != ARP_EMPTY)
arp->status = ARP_MARK;
@@ -188,7 +188,8 @@ int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now)
arps = arp;
arp->status = ARP_EMPTY;
arp->family = addr->sa.sa_family;
arp->hwlen = 0;
if (addr->sa.sa_family == AF_INET)
arp->addr.addr.addr4.s_addr = addr->in.sin_addr.s_addr;
#ifdef HAVE_IPV6

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -919,7 +919,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
if (!f)
{
my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
return 0;
return cache_size;
}
eatspace(f);

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -169,8 +169,16 @@ int main (int argc, char **argv)
if (option_bool(OPT_DNSSEC_VALID))
{
#ifdef HAVE_DNSSEC
if (!daemon->ds)
die(_("no trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
struct ds_config *ds;
/* Must have at least a root trust anchor, or the DNSSEC code
can loop forever. */
for (ds = daemon->ds; ds; ds = ds->next)
if (ds->name[0] == 0)
break;
if (!ds)
die(_("no root trust anchor provided for DNSSEC"), NULL, EC_BADCONF);
if (daemon->cachesize < CACHESIZ)
die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
@@ -919,7 +927,10 @@ int main (int argc, char **argv)
poll_listen(piperead, POLLIN);
#ifdef HAVE_SCRIPT
# ifdef HAVE_DHCP
while (helper_buf_empty() && do_script_run(now));
# endif
while (helper_buf_empty() && do_arp_script_run());
# ifdef HAVE_TFTP
@@ -930,8 +941,11 @@ int main (int argc, char **argv)
poll_listen(daemon->helperfd, POLLOUT);
#else
/* need this for other side-effects */
# ifdef HAVE_DHCP
while (do_script_run(now));
while (do_arp_script_run(now));
# endif
while (do_arp_script_run());
# ifdef HAVE_TFTP
while (do_tftp_script_run());
@@ -1312,7 +1326,7 @@ static void async_event(int pipe, time_t now)
if (daemon->tcp_pids[i] != 0)
kill(daemon->tcp_pids[i], SIGALRM);
#if defined(HAVE_SCRIPT)
#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
/* handle pending lease transitions */
if (daemon->helperfd != -1)
{

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define COPYRIGHT "Copyright (c) 2000-2015 Simon Kelley"
#define COPYRIGHT "Copyright (c) 2000-2016 Simon Kelley"
#ifndef NO_LARGEFILE
/* Ensure we can use files >2GB (log files may grow this big) */
@@ -477,6 +477,7 @@ union mysockaddr {
#define SERV_NO_REBIND 2048 /* inhibit dns-rebind protection */
#define SERV_FROM_FILE 4096 /* read from --servers-file */
#define SERV_LOOP 8192 /* server causes forwarding loop */
#define SERV_DO_DNSSEC 16384 /* Validate DNSSEC when using this server */
struct serverfd {
int fd;

View File

@@ -1,5 +1,5 @@
/* dnssec.c is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
and Copyright (c) 2012-2015 Simon Kelley
and Copyright (c) 2012-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1873,10 +1873,27 @@ static int prove_non_existence(struct dns_header *header, size_t plen, char *key
*/
static int zone_status(char *name, int class, char *keyname, time_t now)
{
int name_start = strlen(name);
int name_start = strlen(name); /* for when TA is root */
struct crec *crecp;
char *p;
/* First, work towards the root, looking for a trust anchor.
This can either be one configured, or one previously cached.
We can assume, if we don't find one first, that there is
a trust anchor at the root. */
for (p = name; p; p = strchr(p, '.'))
{
if (*p == '.')
p++;
if (cache_find_by_name(NULL, p, now, F_DS))
{
name_start = p - name;
break;
}
}
/* Now work away from the trust anchor */
while (1)
{
strcpy(keyname, &name[name_start]);

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -106,8 +106,8 @@ int send_from(int fd, int nowild, char *packet, size_t len,
return 1;
}
static unsigned int search_servers(time_t now, struct all_addr **addrpp,
unsigned int qtype, char *qdomain, int *type, char **domain, int *norebind)
static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigned int qtype,
char *qdomain, int *type, char **domain, int *norebind)
{
/* If the query ends in the domain in one of our servers, set
@@ -151,7 +151,7 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp,
hostname_isequal(matchstart, serv->domain) &&
(domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
{
if (serv->flags & SERV_NO_REBIND)
if ((serv->flags & SERV_NO_REBIND) && norebind)
*norebind = 1;
else
{
@@ -175,7 +175,7 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp,
if (domainlen >= matchlen)
{
*type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND);
*type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_DO_DNSSEC);
*domain = serv->domain;
matchlen = domainlen;
if (serv->flags & SERV_NO_ADDR)
@@ -233,12 +233,13 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
struct frec *forward, int ad_reqd, int do_bit)
{
char *domain = NULL;
int type = 0, norebind = 0;
int type = SERV_DO_DNSSEC, norebind = 0;
struct all_addr *addrp = NULL;
unsigned int flags = 0;
struct server *start = NULL;
#ifdef HAVE_DNSSEC
void *hash = hash_questions(header, plen, daemon->namebuff);
int do_dnssec = 0;
#else
unsigned int crc = questions_crc(header, plen, daemon->namebuff);
void *hash = &crc;
@@ -248,9 +249,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
(void)do_bit;
/* may be no servers available. */
if (!daemon->servers)
forward = NULL;
else if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
{
/* If we didn't get an answer advertising a maximal packet in EDNS,
fall back to 1280, which should work everywhere on IPv6.
@@ -315,6 +314,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
daemon->last_server = NULL;
}
type = forward->sentto->flags & SERV_TYPE;
#ifdef HAVE_DNSSEC
do_dnssec = forward->sentto->flags & SERV_DO_DNSSEC;
#endif
if (!(start = forward->sentto->next))
start = daemon->servers; /* at end of list, recycle */
header->id = htons(forward->new_id);
@@ -324,9 +327,14 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (gotname)
flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
if (!flags && !(forward = get_new_frec(now, NULL, 0)))
/* table full - server failure. */
flags = F_NEG;
#ifdef HAVE_DNSSEC
do_dnssec = type & SERV_DO_DNSSEC;
#endif
type &= ~SERV_DO_DNSSEC;
if (daemon->servers && !flags)
forward = get_new_frec(now, NULL, 0);
/* table full - flags == 0, return REFUSED */
if (forward)
{
@@ -406,7 +414,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
}
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
{
size_t new = add_do_bit(header, plen, ((unsigned char *) header) + PACKETSZ);
@@ -634,7 +642,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
return resize_packet(header, n, pheader, plen);
/* Complain loudly if the upstream server is non-recursive. */
if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR && ntohs(header->ancount) == 0 &&
if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR &&
server && !(server->flags & SERV_WARNED_RECURSIVE))
{
prettyprint_addr(&server->addr, daemon->namebuff);
@@ -800,9 +808,9 @@ void reply_query(int fd, int family, time_t now)
{
header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC);
header->hb4 &= ~(HB4_RA | HB4_RCODE | HB4_CD | HB4_AD);
if (forward->flags |= FREC_CHECKING_DISABLED)
if (forward->flags & FREC_CHECKING_DISABLED)
header->hb4 |= HB4_CD;
if (forward->flags |= FREC_AD_QUESTION)
if (forward->flags & FREC_AD_QUESTION)
header->hb4 |= HB4_AD;
if (forward->flags & FREC_DO_QUESTION)
add_do_bit(header, nn, (unsigned char *)pheader + plen);
@@ -858,7 +866,8 @@ void reply_query(int fd, int family, time_t now)
no_cache_dnssec = 1;
#ifdef HAVE_DNSSEC
if (server && option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
if (server && (server->flags & SERV_DO_DNSSEC) &&
option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
{
int status = 0;
@@ -912,12 +921,48 @@ void reply_query(int fd, int family, time_t now)
status = STAT_ABANDONED;
else
{
int fd;
int fd, type = SERV_DO_DNSSEC;
struct frec *next = new->next;
char *domain;
*new = *forward; /* copy everything, then overwrite */
new->next = next;
new->blocking_query = NULL;
/* Find server to forward to. This will normally be the
same as for the original query, but may be another if
servers for domains are involved. */
if (search_servers(now, NULL, F_QUERY, daemon->keyname, &type, &domain, NULL) == 0)
{
struct server *start = server, *new_server = NULL;
type &= ~SERV_DO_DNSSEC;
while (1)
{
if (type == (start->flags & SERV_TYPE) &&
(type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
!(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
{
new_server = start;
if (server == start)
{
new_server = NULL;
break;
}
}
if (!(start = start->next))
start = daemon->servers;
if (start == server)
break;
}
if (new_server)
server = new_server;
}
new->sentto = server;
new->rfd4 = NULL;
#ifdef HAVE_IPV6
new->rfd6 = NULL;
@@ -971,6 +1016,15 @@ void reply_query(int fd, int family, time_t now)
if (fd != -1)
{
#ifdef HAVE_CONNTRACK
/* Copy connection mark of incoming query to outgoing connection. */
if (option_bool(OPT_CONNTRACK))
{
unsigned int mark;
if (get_incoming_mark(&orig->source, &orig->dest, 0, &mark))
setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
}
#endif
while (retry_send(sendto(fd, (char *)header, nn, 0,
&server->addr.sa,
sa_len(&server->addr))));
@@ -1033,7 +1087,7 @@ void reply_query(int fd, int family, time_t now)
else
header->hb4 &= ~HB4_CD;
if ((nn = process_reply(header, now, server, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer,
if ((nn = process_reply(header, now, forward->sentto, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer,
forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION,
forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->source)))
{
@@ -1394,20 +1448,24 @@ void receive_query(struct listener *listen, time_t now)
}
#ifdef HAVE_DNSSEC
/* Recurse up the key heirarchy */
static int tcp_key_recurse(time_t now, int status, struct dns_header *header, size_t n,
int class, char *name, char *keyname, struct server *server, int *keycount)
int class, char *name, char *keyname, struct server *server,
int have_mark, unsigned int mark, int *keycount)
{
/* Recurse up the key heirarchy */
int new_status;
unsigned char *packet = NULL;
size_t m;
unsigned char *payload = NULL;
struct dns_header *new_header = NULL;
u16 *length = NULL;
unsigned char c1, c2;
while (1)
{
int type = SERV_DO_DNSSEC;
char *domain;
size_t m;
unsigned char c1, c2;
/* limit the amount of work we do, to avoid cycling forever on loops in the DNS */
if (--(*keycount) == 0)
new_status = STAT_ABANDONED;
@@ -1441,6 +1499,67 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr, server->edns_pktsz);
*length = htons(m);
/* Find server to forward to. This will normally be the
same as for the original query, but may be another if
servers for domains are involved. */
if (search_servers(now, NULL, F_QUERY, keyname, &type, &domain, NULL) == 0)
{
struct server *start = server, *new_server = NULL;
type &= ~SERV_DO_DNSSEC;
while (1)
{
if (type == (start->flags & SERV_TYPE) &&
(type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
!(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
{
new_server = start;
if (server == start)
{
new_server = NULL;
break;
}
}
if (!(start = start->next))
start = daemon->servers;
if (start == server)
break;
}
if (new_server)
{
server = new_server;
/* may need to make new connection. */
if (server->tcpfd == -1)
{
if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
{
new_status = STAT_ABANDONED;
break;
}
#ifdef HAVE_CONNTRACK
/* Copy connection mark of incoming query to outgoing connection. */
if (have_mark)
setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
#endif
if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 1) ||
connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
{
close(server->tcpfd);
server->tcpfd = -1;
new_status = STAT_ABANDONED;
break;
}
}
}
}
if (!read_write(server->tcpfd, packet, m + sizeof(u16), 0) ||
!read_write(server->tcpfd, &c1, 1, 1) ||
@@ -1453,7 +1572,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
m = (c1 << 8) | c2;
new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, keycount);
new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
if (new_status != STAT_OK)
break;
@@ -1497,10 +1616,31 @@ unsigned char *tcp_request(int confd, time_t now,
socklen_t peer_len = sizeof(union mysockaddr);
int query_count = 0;
unsigned char *pheader;
unsigned int mark = 0;
int have_mark = 0;
(void)mark;
(void)have_mark;
if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
return packet;
#ifdef HAVE_CONNTRACK
/* Get connection mark of incoming query to set on outgoing connections. */
if (option_bool(OPT_CONNTRACK))
{
struct all_addr local;
#ifdef HAVE_IPV6
if (local_addr->sa.sa_family == AF_INET6)
local.addr.addr6 = local_addr->in6.sin6_addr;
else
#endif
local.addr.addr4 = local_addr->in.sin_addr;
have_mark = get_incoming_mark(&peer_addr, &local, 1, &mark);
}
#endif
/* We can be configured to only accept queries from at-most-one-hop-away addresses. */
if (option_bool(OPT_LOCAL_SERVICE))
{
@@ -1626,7 +1766,7 @@ unsigned char *tcp_request(int confd, time_t now,
{
unsigned int flags = 0;
struct all_addr *addrp = NULL;
int type = 0;
int type = SERV_DO_DNSSEC;
char *domain = NULL;
size_t new_size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet);
@@ -1639,6 +1779,8 @@ unsigned char *tcp_request(int confd, time_t now,
if (gotname)
flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
type &= ~SERV_DO_DNSSEC;
if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
last_server = daemon->servers;
else
@@ -1685,20 +1827,8 @@ unsigned char *tcp_request(int confd, time_t now,
#ifdef HAVE_CONNTRACK
/* Copy connection mark of incoming query to outgoing connection. */
if (option_bool(OPT_CONNTRACK))
{
unsigned int mark;
struct all_addr local;
#ifdef HAVE_IPV6
if (local_addr->sa.sa_family == AF_INET6)
local.addr.addr6 = local_addr->in6.sin6_addr;
else
#endif
local.addr.addr4 = local_addr->in.sin_addr;
if (get_incoming_mark(&peer_addr, &local, 1, &mark))
setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
}
if (have_mark)
setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
#endif
if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 1) ||
@@ -1710,7 +1840,7 @@ unsigned char *tcp_request(int confd, time_t now,
}
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
if (option_bool(OPT_DNSSEC_VALID) && (last_server->flags & SERV_DO_DNSSEC))
{
new_size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
@@ -1756,10 +1886,11 @@ unsigned char *tcp_request(int confd, time_t now,
#endif
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled)
if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC))
{
int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname, last_server, &keycount);
int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
last_server, have_mark, mark, &keycount);
char *result, *domain = "result";
if (status == STAT_ABANDONED)

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1430,12 +1430,43 @@ void check_servers(void)
if (!option_bool(OPT_NOWILD))
enumerate_interfaces(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 (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)))
{
port = prettyprint_addr(&serv->addr, daemon->namebuff);
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
{
if (serv->flags & SERV_HAS_DOMAIN)
{
struct ds_config *ds;
char *domain = serv->domain;
/* .example.com is valid */
while (*domain == '.')
domain++;
for (ds = daemon->ds; ds; ds = ds->next)
if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
break;
if (!ds)
serv->flags &= ~SERV_DO_DNSSEC;
}
else if (serv->flags & SERV_FOR_NODOTS)
serv->flags &= ~SERV_DO_DNSSEC;
}
#endif
port = prettyprint_addr(&serv->addr, daemon->namebuff);
/* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
if (serv->addr.sa.sa_family == AF_INET &&
serv->addr.in.sin_addr.s_addr == 0)
@@ -1471,7 +1502,11 @@ void check_servers(void)
{
if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
{
char *s1, *s2;
char *s1, *s2, *s3 = "";
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
s3 = _("(no DNSSEC)");
#endif
if (!(serv->flags & SERV_HAS_DOMAIN))
s1 = _("unqualified"), s2 = _("names");
else if (strlen(serv->domain) == 0)
@@ -1484,7 +1519,7 @@ void check_servers(void)
else if (serv->flags & SERV_USE_RESOLV)
my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
else
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s %s"), daemon->namebuff, port, s1, s2, s3);
}
#ifdef HAVE_LOOP
else if (serv->flags & SERV_LOOP)

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -896,9 +896,7 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
header->nscount = htons(0);
header->arcount = htons(0);
header->ancount = htons(0); /* no answers unless changed below */
if (flags == F_NEG)
SET_RCODE(header, SERVFAIL); /* couldn't get memory */
else if (flags == F_NOERR)
if (flags == F_NOERR)
SET_RCODE(header, NOERROR); /* empty domain */
else if (flags == F_NXDOMAIN)
SET_RCODE(header, NXDOMAIN);

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by