Skip to content

Commit

Permalink
Merge pull request #1230 from pi-hole/update/dnsmasq
Browse files Browse the repository at this point in the history
Update embedded dnsmasq to v2.87test4-6
  • Loading branch information
DL6ER authored Dec 20, 2021
2 parents d987d3c + d294b2f commit 92a27e7
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 48 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
cmake_minimum_required(VERSION 2.8.12)
project(PIHOLE_FTL C)

set(DNSMASQ_VERSION pi-hole-2.87test3)
set(DNSMASQ_VERSION pi-hole-2.87test4-6)

add_subdirectory(src)
10 changes: 6 additions & 4 deletions src/dnsmasq/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1400,10 +1400,12 @@ struct in_addr a_record_from_hosts(char *name, time_t now)
struct crec *crecp = NULL;
struct in_addr ret;

while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
if (crecp->flags & F_HOSTS)
return crecp->addr.addr4;

/* If no DNS service, cache not initialised. */
if (daemon->port != 0)
while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
if (crecp->flags & F_HOSTS)
return crecp->addr.addr4;

my_syslog(MS_DHCP | LOG_WARNING, _("No IPv4 address found for %s"), name);

ret.s_addr = 0;
Expand Down
9 changes: 8 additions & 1 deletion src/dnsmasq/dnsmasq.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
/* Declare static char *compiler_opts in config.h */
#define DNSMASQ_COMPILE_OPTS

/* dnsmasq.h has to be included first as it sources config.h */
#include "dnsmasq.h"

#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2) || defined(LOCALEDIR)
#include <locale.h>
#endif
#include "../dnsmasq_interface.h"
// killed
#include "../signals.h"
Expand Down Expand Up @@ -73,8 +78,10 @@ int main_dnsmasq (int argc, char **argv)
int tftp_prefix_missing = 0;
#endif

#ifdef LOCALEDIR
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2) || defined(LOCALEDIR)
setlocale(LC_ALL, "");
#endif
#ifdef LOCALEDIR
bindtextdomain("dnsmasq", LOCALEDIR);
textdomain("dnsmasq");
#endif
Expand Down
11 changes: 9 additions & 2 deletions src/dnsmasq/dnsmasq.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,9 @@ struct event_desc {
#define OPT_UMBRELLA_DEVID 64
#define OPT_CMARK_ALST_EN 65
#define OPT_QUIET_TFTP 66
#define OPT_LAST 67
#define OPT_FILTER_A 67
#define OPT_FILTER_AAAA 68
#define OPT_LAST 69

#define OPTION_BITS (sizeof(unsigned int)*8)
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
Expand Down Expand Up @@ -1403,6 +1405,7 @@ void safe_pipe(int *fd, int read_noblock);
void *whine_malloc(size_t size);
int sa_len(union mysockaddr *addr);
int sockaddr_isequal(const union mysockaddr *s1, const union mysockaddr *s2);
int hostname_order(const char *a, const char *b);
int hostname_isequal(const char *a, const char *b);
int hostname_issubdomain(char *a, char *b);
time_t dnsmasq_time(void);
Expand Down Expand Up @@ -1789,7 +1792,11 @@ int do_poll(int timeout);
size_t rrfilter(struct dns_header *header, size_t plen, int mode);
u16 *rrfilter_desc(int type);
int expand_workspace(unsigned char ***wkspc, int *szp, int new);

/* modes. */
#define RRFILTER_EDNS0 0
#define RRFILTER_DNSSEC 1
#define RRFILTER_A 2
#define RRFILTER_AAAA 3
/* edns0.c */
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
size_t *len, unsigned char **p, int *is_sign, int *is_last);
Expand Down
11 changes: 5 additions & 6 deletions src/dnsmasq/domain-match.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,8 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
else
addr.addr4 = srv->addr;

header->ancount = htons(ntohs(header->ancount) + 1);
if (!add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_A, C_IN, "4", &addr))
return 0;
if (add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_A, C_IN, "4", &addr))
header->ancount = htons(ntohs(header->ancount) + 1);
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, name, (union all_addr *)&addr, NULL, 0);
}

Expand All @@ -434,8 +433,8 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
else
addr.addr6 = srv->addr;

header->ancount = htons(ntohs(header->ancount) + 1);
add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_AAAA, C_IN, "6", &addr);
if (add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_AAAA, C_IN, "6", &addr))
header->ancount = htons(ntohs(header->ancount) + 1);
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, name, (union all_addr *)&addr, NULL, 0);
}

Expand Down Expand Up @@ -494,7 +493,7 @@ static int order(char *qdomain, size_t qlen, struct server *serv)
if (qlen > dlen)
return -1;

return strcmp(qdomain, serv->domain);
return hostname_order(qdomain, serv->domain);
}

static int order_servers(struct server *s1, struct server *s2)
Expand Down
2 changes: 1 addition & 1 deletion src/dnsmasq/edns0.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
memcpy(buff, datap, rdlen);

/* now, delete OPT RR */
plen = rrfilter(header, plen, 0);
plen = rrfilter(header, plen, RRFILTER_EDNS0);

/* Now, force addition of a new one */
p = NULL;
Expand Down
48 changes: 37 additions & 11 deletions src/dnsmasq/forward.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,20 @@ static int domain_no_rebind(char *domain)
{
struct rebind_domain *rbd;
size_t tlen, dlen = strlen(domain);

char *dots = strchr(domain, '.');

/* Match whole labels only. Empty domain matches no dots (any single label) */
for (rbd = daemon->no_rebind; rbd; rbd = rbd->next)
if (dlen >= (tlen = strlen(rbd->domain)) && strcmp(rbd->domain, &domain[dlen - tlen]) == 0)
{
if (dlen >= (tlen = strlen(rbd->domain)) &&
hostname_isequal(rbd->domain, &domain[dlen - tlen]) &&
(dlen == tlen || domain[dlen - tlen - 1] == '.'))
return 1;

if (tlen == 0 && !dots)
return 1;
}

return 0;
}

Expand All @@ -175,8 +184,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
unsigned int fwd_flags = 0;
int is_dnssec = forward && (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY));
struct server *master;
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
void *hash = hash_questions(header, plen, daemon->namebuff);
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
int old_src = 0, old_reply = 0;
int first, last, start = 0;
Expand Down Expand Up @@ -220,7 +229,11 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
break;

if (src)
old_src = 1;
{
old_src = 1;
/* If a query is retried, use the log_id for the retry when logging the answer. */
src->log_id = daemon->log_id;
}
else
{
/* Existing query, but from new source, just add this
Expand Down Expand Up @@ -294,6 +307,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
goto reply;
/* table full - flags == 0, return REFUSED */

forward->frec_src.log_id = daemon->log_id;
forward->frec_src.source = *udpaddr;
forward->frec_src.orig_id = ntohs(header->id);
forward->frec_src.dest = *dst_addr;
Expand All @@ -315,7 +329,6 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (do_bit)
forward->flags |= FREC_DO_QUESTION;
#endif
forward->frec_src.log_id = daemon->log_id;

start = first;

Expand All @@ -338,7 +351,6 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
}
else
{
/* retry on existing query, from original source. Send to all available servers */
#ifdef HAVE_DNSSEC
/* If we've already got an answer to this query, but we're awaiting keys for validation,
there's no point retrying the query, retry the key query instead...... */
Expand All @@ -349,7 +361,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,

while (forward->blocking_query)
forward = forward->blocking_query;


/* log_id should match previous DNSSEC query. */
daemon->log_display_id = forward->frec_src.log_id;

blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
plen = forward->stash_len;
/* get query for logging. */
Expand Down Expand Up @@ -396,7 +411,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
Note that we can get here EITHER because a client retried,
or an upstream server returned REFUSED. The above only
applied in the later case. For client retries,
keep tyring the last server.. */
keep trying the last server.. */
if (++start == last)
{
if (old_reply)
Expand Down Expand Up @@ -639,7 +654,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
if (added_pheader)
{
/* client didn't send EDNS0, we added one, strip it off before returning answer. */
n = rrfilter(header, n, 0);
n = rrfilter(header, n, RRFILTER_EDNS0);
pheader = NULL;
}
else
Expand Down Expand Up @@ -730,6 +745,17 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
cache_secure = 0;
}
}

/* Before extract_addresses() */
if (rcode == NOERROR)
{
if (option_bool(OPT_FILTER_A))
n = rrfilter(header, n, RRFILTER_A);

if (option_bool(OPT_FILTER_AAAA))
n = rrfilter(header, n, RRFILTER_AAAA);
}

/******************************** Pi-hole modification ********************************/
int ret = extract_addresses(header, n, daemon->namebuff, now, ipsets, nftsets, is_sign, check_rebind, no_cache, cache_secure, &doctored);
if (ret == 2)
Expand Down Expand Up @@ -769,7 +795,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server

/* If the requestor didn't set the DO bit, don't return DNSSEC info. */
if (!do_bit)
n = rrfilter(header, n, 1);
n = rrfilter(header, n, RRFILTER_DNSSEC);
}
#endif

Expand All @@ -793,7 +819,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
u16 swap = htons((u16)ede);
n = add_pseudoheader(header, n, limit, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 1);
}

return n;
}

Expand Down
20 changes: 14 additions & 6 deletions src/dnsmasq/option.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,9 @@ struct myoption {
#define LOPT_CMARK_ALST 366
#define LOPT_QUIET_TFTP 367
#define LOPT_NFTSET 368

#define LOPT_FILTER_A 369
#define LOPT_FILTER_AAAA 370

#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
#else
Expand Down Expand Up @@ -216,6 +218,8 @@ static const struct myoption opts[] =
{ "ignore-address", 1, 0, LOPT_IGNORE_ADDR },
{ "selfmx", 0, 0, 'e' },
{ "filterwin2k", 0, 0, 'f' },
{ "filter-A", 0, 0, LOPT_FILTER_A },
{ "filter-AAAA", 0, 0, LOPT_FILTER_AAAA },
{ "pid-file", 2, 0, 'x' },
{ "strict-order", 0, 0, 'o' },
{ "server", 1, 0, 'S' },
Expand Down Expand Up @@ -386,6 +390,8 @@ static struct {
{ 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
{ 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
{ 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
{ LOPT_FILTER_A, OPT_FILTER_A, NULL, gettext_noop("Don't include IPv4 addresses in DNS answers."), NULL },
{ LOPT_FILTER_AAAA, OPT_FILTER_AAAA, NULL, gettext_noop("Don't include IPv6 addresses in DNS answers."), NULL },
{ 'F', ARG_DUP, "<ipaddr>,...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
{ 'g', ARG_ONE, "<groupname>", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
{ 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
Expand Down Expand Up @@ -661,7 +667,7 @@ static char *canonicalise_opt(char *s)
return 0;

if (strlen(s) == 0)
return opt_string_alloc("");
return opt_malloc(1); /* Heap-allocated empty string */

unhide_metas(s);
if (!(ret = canonicalise(s, &nomem)) && nomem)
Expand Down Expand Up @@ -2231,8 +2237,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
comma = split(arg);

new = opt_malloc(sizeof(struct auth_zone));
new->domain = opt_string_alloc(arg);
new->subnet = NULL;
new->domain = canonicalise_opt(arg);
if (!new->domain)
ret_err_free(_("invalid auth-zone"), new);
new->subnet = NULL;
new->exclude = NULL;
new->interface_names = NULL;
new->next = daemon->auth_zones;
Expand Down Expand Up @@ -2762,7 +2770,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma

if (!arg || !*arg)
flags = SERV_LITERAL_ADDRESS;
else if (option != 'S')
else if (option == 'A')
{
/* # as literal address means return zero address for 4 and 6 */
if (strcmp(arg, "#") == 0)
Expand Down Expand Up @@ -2794,7 +2802,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
flags &= ~SERV_FOR_NODOTS;

/* address=/#/ matches the same as without domain */
if (option != 'S' && domain[0] == '#' && domain[1] == 0)
if (option == 'A' && domain[0] == '#' && domain[1] == 0)
domain[0] = 0;
}

Expand Down
37 changes: 27 additions & 10 deletions src/dnsmasq/rrfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, i
}


/* mode is 0 to remove EDNS0, 1 to filter DNSSEC RRs */
/* mode may be remove EDNS0 or DNSSEC RRs or remove A or AAAA from answer section. */
size_t rrfilter(struct dns_header *header, size_t plen, int mode)
{
static unsigned char **rrs;
Expand Down Expand Up @@ -192,20 +192,37 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode)
if (!ADD_RDLEN(header, p, plen, rdlen))
return plen;

/* Don't remove the answer. */
if (i < ntohs(header->ancount) && type == qtype && class == qclass)
continue;

if (mode == 0) /* EDNS */
if (mode == RRFILTER_EDNS0) /* EDNS */
{
/* EDNS mode, remove T_OPT from additional section only */
if (i < (ntohs(header->nscount) + ntohs(header->ancount)) || type != T_OPT)
continue;
}
else if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
/* DNSSEC mode, remove SIGs and NSECs from all three sections. */
continue;

else if (mode == RRFILTER_DNSSEC)
{
if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
/* DNSSEC mode, remove SIGs and NSECs from all three sections. */
continue;

/* Don't remove the answer. */
if (i < ntohs(header->ancount) && type == qtype && class == qclass)
continue;
}
else
{
/* Only looking at answer section now. */
if (i >= ntohs(header->ancount))
break;

if (class != C_IN)
continue;

if (mode == RRFILTER_A && type != T_A)
continue;

if (mode == RRFILTER_AAAA && type != T_AAAA)
continue;
}

if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
return plen;
Expand Down
Loading

0 comments on commit 92a27e7

Please sign in to comment.