Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update embedded dnsmasq to v2.89 #1522

Merged
merged 7 commits into from Feb 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Expand Up @@ -11,6 +11,6 @@
cmake_minimum_required(VERSION 2.8.12)
project(PIHOLE_FTL C)

set(DNSMASQ_VERSION pi-hole-v2.88)
set(DNSMASQ_VERSION pi-hole-v2.89)

add_subdirectory(src)
202 changes: 108 additions & 94 deletions src/dnsmasq/cache.c
Expand Up @@ -29,6 +29,7 @@ static int bignames_left, hash_size;
static void make_non_terminals(struct crec *source);
static struct crec *really_insert(char *name, union all_addr *addr, unsigned short class,
time_t now, unsigned long ttl, unsigned int flags);
static void dump_cache_entry(struct crec *cache, time_t now);

/* type->string mapping: this is also used by the name-hash function as a mixing table. */
/* taken from https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml */
Expand Down Expand Up @@ -236,19 +237,23 @@ static void cache_hash(struct crec *crecp)

char *name = cache_get_name(crecp);
struct crec **up = hash_bucket(name);

if (!(crecp->flags & F_REVERSE))
unsigned int flags = crecp->flags & (F_IMMORTAL | F_REVERSE);

if (!(flags & F_REVERSE))
{
while (*up && ((*up)->flags & F_REVERSE))
up = &((*up)->hash_next);

if (crecp->flags & F_IMMORTAL)
if (flags & F_IMMORTAL)
while (*up && !((*up)->flags & F_IMMORTAL))
up = &((*up)->hash_next);
}

/* Preserve order when inserting the same name multiple times. */
while (*up && hostname_isequal(cache_get_name(*up), name))
/* Preserve order when inserting the same name multiple times.
Do not mess up the flag invariants. */
while (*up &&
hostname_isequal(cache_get_name(*up), name) &&
flags == ((*up)->flags & (F_IMMORTAL | F_REVERSE)))
up = &((*up)->hash_next);

crecp->hash_next = *up;
Expand Down Expand Up @@ -595,7 +600,7 @@ static struct crec *really_insert(char *name, union all_addr *addr, unsigned sho
struct crec *new, *target_crec = NULL;
union bigname *big_name = NULL;
int freed_all = (flags & F_REVERSE);
int free_avail = 0;
struct crec *free_avail = NULL;
unsigned int target_uid;

/* if previous insertion failed give up now. */
Expand Down Expand Up @@ -643,7 +648,7 @@ static struct crec *really_insert(char *name, union all_addr *addr, unsigned sho

/* Free entry at end of LRU list, use it. */
if (!(new->flags & (F_FORWARD | F_REVERSE)))
break;
break;

/* End of LRU list is still in use: if we didn't scan all the hash
chains for expired entries do that now. If we already tried that
Expand All @@ -655,26 +660,23 @@ static struct crec *really_insert(char *name, union all_addr *addr, unsigned sho
insert. Once in this state, all inserts will probably fail. */
if (free_avail)
{
static int warned = 0;
if (!warned)
{
my_syslog(LOG_ERR, _("Internal error in cache."));
warned = 1;
}
my_syslog(LOG_ERR, _("Internal error in cache."));
/* Log the entry we tried to delete. */
dump_cache_entry(free_avail, now);
insert_error = 1;
return NULL;
}

if (freed_all)
{
/* For DNSSEC records, uid holds class. */
free_avail = 1; /* Must be free space now. */
free_avail = new; /* Must be free space now. */

/* condition valid when stale-caching */
if (difftime(now, new->ttd) < 0)
daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]++;

cache_scan_free(cache_get_name(new), &new->addr, new->uid, now, new->flags, NULL, NULL);
cache_scan_free(cache_get_name(new), &new->addr, new->uid, now, new->flags, NULL, NULL);
}
else
{
Expand Down Expand Up @@ -1081,7 +1083,6 @@ void add_hosts_entry(struct crec *cache, union all_addr *addr, int addrlen,
the array rhash, hashed on address. Note that rhash and the values
in ->next are only valid whilst reading hosts files: the buckets are
then freed, and the ->next pointer used for other things.

Only insert each unique address once into this hashing structure.

This complexity avoids O(n^2) divergent CPU use whilst reading
Expand Down Expand Up @@ -1767,6 +1768,95 @@ static char *sanitise(char *name)
return name;
}

static void dump_cache_entry(struct crec *cache, time_t now)
{
(void)now;
static char *buff = NULL;

char *p, *t = " ";
char *a = daemon->addrbuff, *n = cache_get_name(cache);

/* String length is limited below */
if (!buff && !(buff = whine_malloc(150)))
return;

p = buff;

*a = 0;
if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
n = "<Root>";
p += sprintf(p, "%-30.30s ", sanitise(n));
if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
a = sanitise(cache_get_cname_target(cache));
else if ((cache->flags & F_SRV) && !(cache->flags & F_NEG))
{
int targetlen = cache->addr.srv.targetlen;
ssize_t len = sprintf(a, "%u %u %u ", cache->addr.srv.priority,
cache->addr.srv.weight, cache->addr.srv.srvport);

if (targetlen > (40 - len))
targetlen = 40 - len;
blockdata_retrieve(cache->addr.srv.target, targetlen, a + len);
a[len + targetlen] = 0;
}
#ifdef HAVE_DNSSEC
else if (cache->flags & F_DS)
{
if (!(cache->flags & F_NEG))
sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
cache->addr.ds.algo, cache->addr.ds.digest);
}
else if (cache->flags & F_DNSKEY)
sprintf(a, "%5u %3u %3u", cache->addr.key.keytag,
cache->addr.key.algo, cache->addr.key.flags);
#endif
else if (!(cache->flags & F_NEG) || !(cache->flags & F_FORWARD))
{
a = daemon->addrbuff;
if (cache->flags & F_IPV4)
inet_ntop(AF_INET, &cache->addr, a, ADDRSTRLEN);
else if (cache->flags & F_IPV6)
inet_ntop(AF_INET6, &cache->addr, a, ADDRSTRLEN);
}

if (cache->flags & F_IPV4)
t = "4";
else if (cache->flags & F_IPV6)
t = "6";
else if (cache->flags & F_CNAME)
t = "C";
else if (cache->flags & F_SRV)
t = "V";
#ifdef HAVE_DNSSEC
else if (cache->flags & F_DS)
t = "S";
else if (cache->flags & F_DNSKEY)
t = "K";
#endif
else if (!(cache->flags & F_NXDOMAIN)) /* non-terminal */
t = "!";

p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s%s ", a, t,
cache->flags & F_FORWARD ? "F" : " ",
cache->flags & F_REVERSE ? "R" : " ",
cache->flags & F_IMMORTAL ? "I" : " ",
cache->flags & F_DHCP ? "D" : " ",
cache->flags & F_NEG ? "N" : " ",
cache->flags & F_NXDOMAIN ? "X" : " ",
cache->flags & F_HOSTS ? "H" : " ",
cache->flags & F_CONFIG ? "C" : " ",
cache->flags & F_DNSSECOK ? "V" : " ");
#ifdef HAVE_BROKEN_RTC
p += sprintf(p, "%-24lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
#else
p += sprintf(p, "%-24.24s", cache->flags & F_IMMORTAL ? "" : ctime(&(cache->ttd)));
#endif
if(cache->flags & (F_HOSTS | F_CONFIG) && cache->uid > 0)
p += sprintf(p, " %-40.40s", record_source(cache->uid));

my_syslog(LOG_INFO, "%s", buff);
}

/***************** Pi-hole modification *****************/
void get_dnsmasq_cache_info(struct cache_info *ci)
{
Expand Down Expand Up @@ -1847,90 +1937,14 @@ void dump_cache(time_t now)

if (option_bool(OPT_DEBUG) || option_bool(OPT_LOG))
{
struct crec *cache ;
struct crec *cache;
int i;
my_syslog(LOG_INFO, "Host Address Flags Expires Source");
my_syslog(LOG_INFO, "------------------------------ ---------------------------------------- ---------- ------------------------ ------------");

for (i=0; i<hash_size; i++)
for (cache = hash_table[i]; cache; cache = cache->hash_next)
{
char *t = " ";
char *a = daemon->addrbuff, *p = daemon->namebuff, *n = cache_get_name(cache);
*a = 0;
if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
n = "<Root>";
p += sprintf(p, "%-30.30s ", sanitise(n));
if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
a = sanitise(cache_get_cname_target(cache));
else if ((cache->flags & F_SRV) && !(cache->flags & F_NEG))
{
int targetlen = cache->addr.srv.targetlen;
ssize_t len = sprintf(a, "%u %u %u ", cache->addr.srv.priority,
cache->addr.srv.weight, cache->addr.srv.srvport);

if (targetlen > (40 - len))
targetlen = 40 - len;
blockdata_retrieve(cache->addr.srv.target, targetlen, a + len);
a[len + targetlen] = 0;
}
#ifdef HAVE_DNSSEC
else if (cache->flags & F_DS)
{
if (!(cache->flags & F_NEG))
sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
cache->addr.ds.algo, cache->addr.ds.digest);
}
else if (cache->flags & F_DNSKEY)
sprintf(a, "%5u %3u %3u", cache->addr.key.keytag,
cache->addr.key.algo, cache->addr.key.flags);
#endif
else if (!(cache->flags & F_NEG) || !(cache->flags & F_FORWARD))
{
a = daemon->addrbuff;
if (cache->flags & F_IPV4)
inet_ntop(AF_INET, &cache->addr, a, ADDRSTRLEN);
else if (cache->flags & F_IPV6)
inet_ntop(AF_INET6, &cache->addr, a, ADDRSTRLEN);
}

if (cache->flags & F_IPV4)
t = "4";
else if (cache->flags & F_IPV6)
t = "6";
else if (cache->flags & F_CNAME)
t = "C";
else if (cache->flags & F_SRV)
t = "V";
#ifdef HAVE_DNSSEC
else if (cache->flags & F_DS)
t = "S";
else if (cache->flags & F_DNSKEY)
t = "K";
#endif
else /* non-terminal */
t = "!";

p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s%s ", a, t,
cache->flags & F_FORWARD ? "F" : " ",
cache->flags & F_REVERSE ? "R" : " ",
cache->flags & F_IMMORTAL ? "I" : " ",
cache->flags & F_DHCP ? "D" : " ",
cache->flags & F_NEG ? "N" : " ",
cache->flags & F_NXDOMAIN ? "X" : " ",
cache->flags & F_HOSTS ? "H" : " ",
cache->flags & F_CONFIG ? "C" : " ",
cache->flags & F_DNSSECOK ? "V" : " ");
#ifdef HAVE_BROKEN_RTC
p += sprintf(p, "%-24lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
#else
p += sprintf(p, "%-24.24s", cache->flags & F_IMMORTAL ? "" : ctime(&(cache->ttd)));
#endif
if(cache->flags & (F_HOSTS | F_CONFIG) && cache->uid > 0)
p += sprintf(p, " %s", record_source(cache->uid));

my_syslog(LOG_INFO, "%s", daemon->namebuff);
}
dump_cache_entry(cache, now);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/dnsmasq/dnsmasq.h
Expand Up @@ -281,7 +281,8 @@ struct event_desc {
#define OPT_STRIP_ECS 69
#define OPT_STRIP_MAC 70
#define OPT_NORR 71
#define OPT_LAST 72
#define OPT_NO_IDENT 72
#define OPT_LAST 73

#define OPTION_BITS (sizeof(unsigned int)*8)
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
Expand Down
49 changes: 28 additions & 21 deletions src/dnsmasq/option.c
Expand Up @@ -189,6 +189,7 @@ struct myoption {
#define LOPT_FAST_RETRY 376
#define LOPT_STALE_CACHE 377
#define LOPT_NORR 378
#define LOPT_NO_IDENT 379

#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
Expand Down Expand Up @@ -378,6 +379,7 @@ static const struct myoption opts[] =
{ "port-limit", 1, 0, LOPT_RANDPORT_LIM },
{ "fast-dns-retry", 2, 0, LOPT_FAST_RETRY },
{ "use-stale-cache", 2, 0 , LOPT_STALE_CACHE },
{ "no-ident", 0, 0, LOPT_NO_IDENT },
{ NULL, 0, 0, 0 }
};

Expand Down Expand Up @@ -574,6 +576,7 @@ static struct {
{ LOPT_UMBRELLA, ARG_ONE, "[=<optspec>]", gettext_noop("Send Cisco Umbrella identifiers including remote IP."), NULL },
{ LOPT_QUIET_TFTP, OPT_QUIET_TFTP, NULL, gettext_noop("Do not log routine TFTP."), NULL },
{ LOPT_NORR, OPT_NORR, NULL, gettext_noop("Suppress round-robin ordering of DNS records."), NULL },
{ LOPT_NO_IDENT, OPT_NO_IDENT, NULL, gettext_noop("Do not add CHAOS TXT records."), NULL },
{ 0, 0, NULL, NULL, NULL }
};

Expand Down Expand Up @@ -5761,27 +5764,6 @@ void read_opts(int argc, char **argv, char *compile_opts)
daemon->randport_limit = 1;
daemon->host_index = SRC_AH;

#ifndef NO_ID
add_txt("version.bind", "dnsmasq-" VERSION, 0 );
add_txt("authors.bind", "Simon Kelley", 0);
add_txt("copyright.bind", COPYRIGHT, 0);
add_txt("cachesize.bind", NULL, TXT_STAT_CACHESIZE);
add_txt("insertions.bind", NULL, TXT_STAT_INSERTS);
add_txt("evictions.bind", NULL, TXT_STAT_EVICTIONS);
add_txt("misses.bind", NULL, TXT_STAT_MISSES);
add_txt("hits.bind", NULL, TXT_STAT_HITS);
#ifdef HAVE_AUTH
add_txt("auth.bind", NULL, TXT_STAT_AUTH);
#endif
add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
/* Pi-hole modification */
add_txt("privacylevel.pihole", NULL, TXT_PRIVACYLEVEL);
/************************/
#endif
/******** Pi-hole modification ********/
add_txt("version.FTL", (char*)get_FTL_version(), 0 );
/**************************************/

/* See comment above make_servers(). Optimises server-read code. */
mark_servers(0);

Expand Down Expand Up @@ -5879,6 +5861,31 @@ void read_opts(int argc, char **argv, char *compile_opts)
else
one_file(CONFFILE, LOPT_CONF_OPT);

/* Add TXT records if wanted */
#ifndef NO_ID
if (!option_bool(OPT_NO_IDENT))
{
add_txt("version.bind", "dnsmasq-" VERSION, 0 );
add_txt("authors.bind", "Simon Kelley", 0);
add_txt("copyright.bind", COPYRIGHT, 0);
add_txt("cachesize.bind", NULL, TXT_STAT_CACHESIZE);
add_txt("insertions.bind", NULL, TXT_STAT_INSERTS);
add_txt("evictions.bind", NULL, TXT_STAT_EVICTIONS);
add_txt("misses.bind", NULL, TXT_STAT_MISSES);
add_txt("hits.bind", NULL, TXT_STAT_HITS);
#ifdef HAVE_AUTH
add_txt("auth.bind", NULL, TXT_STAT_AUTH);
#endif
add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
/* Pi-hole modification */
add_txt("privacylevel.pihole", NULL, TXT_PRIVACYLEVEL);
/************************/
}
#endif
/******** Pi-hole modification ********/
add_txt("version.FTL", (char*)get_FTL_version(), 0 );
/**************************************/

/* port might not be known when the address is parsed - fill in here */
if (daemon->servers)
{
Expand Down