Force-update embedded dnsmasq version. We are loosing the individual dnsmasq history of the ~ last year, however, given the multitude of merge conflicts and the fact that this code will soon(ish) be replaced by development-v6 (where the history is 100% intact), this isn't much of an issue
Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
parent
0a90f07d68
commit
45c342af05
|
@ -276,7 +276,7 @@ void parse_args(int argc, char* argv[])
|
|||
const char *arg[2];
|
||||
arg[0] = "";
|
||||
arg[1] = "--test";
|
||||
exit(main_dnsmasq(2, arg));
|
||||
exit(main_dnsmasq(2, (char**)arg));
|
||||
}
|
||||
|
||||
// If we find "--" we collect everything behind that for dnsmasq
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
# Pi-hole: A black hole for Internet advertisements
|
||||
# (c) 2020 Pi-hole, LLC (https://pi-hole.net)
|
||||
# Network-wide ad blocking via your own hardware.
|
||||
#
|
||||
# FTL Engine
|
||||
# /src/dnsmasq/CMakeList.txt
|
||||
#
|
||||
# This file is copyright under the latest version of the EUPL.
|
||||
# Please see LICENSE file for your rights under this license.
|
||||
|
||||
set(sources
|
||||
arp.c
|
||||
auth.c
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -19,7 +19,7 @@
|
|||
static struct blockdata *keyblock_free;
|
||||
static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
|
||||
|
||||
static void blockdata_expand(int n)
|
||||
static void add_blocks(int n)
|
||||
{
|
||||
struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
|
||||
|
||||
|
@ -47,7 +47,7 @@ void blockdata_init(void)
|
|||
|
||||
/* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
|
||||
if (option_bool(OPT_DNSSEC_VALID))
|
||||
blockdata_expand(daemon->cachesize);
|
||||
add_blocks(daemon->cachesize);
|
||||
}
|
||||
|
||||
void blockdata_report(void)
|
||||
|
@ -58,50 +58,61 @@ void blockdata_report(void)
|
|||
blockdata_alloced * sizeof(struct blockdata));
|
||||
}
|
||||
|
||||
static struct blockdata *new_block(void)
|
||||
{
|
||||
struct blockdata *block;
|
||||
|
||||
if (!keyblock_free)
|
||||
add_blocks(50);
|
||||
|
||||
if (keyblock_free)
|
||||
{
|
||||
block = keyblock_free;
|
||||
keyblock_free = block->next;
|
||||
blockdata_count++;
|
||||
if (blockdata_hwm < blockdata_count)
|
||||
blockdata_hwm = blockdata_count;
|
||||
block->next = NULL;
|
||||
return block;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct blockdata *blockdata_alloc_real(int fd, char *data, size_t len)
|
||||
{
|
||||
struct blockdata *block, *ret = NULL;
|
||||
struct blockdata **prev = &ret;
|
||||
size_t blen;
|
||||
|
||||
while (len > 0)
|
||||
do
|
||||
{
|
||||
if (!keyblock_free)
|
||||
blockdata_expand(50);
|
||||
|
||||
if (keyblock_free)
|
||||
{
|
||||
block = keyblock_free;
|
||||
keyblock_free = block->next;
|
||||
blockdata_count++;
|
||||
}
|
||||
else
|
||||
if (!(block = new_block()))
|
||||
{
|
||||
/* failed to alloc, free partial chain */
|
||||
blockdata_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (blockdata_hwm < blockdata_count)
|
||||
blockdata_hwm = blockdata_count;
|
||||
|
||||
if ((blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len) > 0)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
memcpy(block->key, data, blen);
|
||||
data += blen;
|
||||
}
|
||||
else if (!read_write(fd, block->key, blen, 1))
|
||||
{
|
||||
/* failed read free partial chain */
|
||||
blockdata_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
|
||||
if (data)
|
||||
{
|
||||
memcpy(block->key, data, blen);
|
||||
data += blen;
|
||||
}
|
||||
else if (!read_write(fd, block->key, blen, 1))
|
||||
{
|
||||
/* failed read free partial chain */
|
||||
blockdata_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
len -= blen;
|
||||
*prev = block;
|
||||
prev = &block->next;
|
||||
block->next = NULL;
|
||||
}
|
||||
} while (len != 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -111,6 +122,58 @@ struct blockdata *blockdata_alloc(char *data, size_t len)
|
|||
return blockdata_alloc_real(0, data, len);
|
||||
}
|
||||
|
||||
/* Add data to the end of the block.
|
||||
newlen is length of new data, NOT total new length.
|
||||
Use blockdata_alloc(NULL, 0) to make empty block to add to. */
|
||||
int blockdata_expand(struct blockdata *block, size_t oldlen, char *data, size_t newlen)
|
||||
{
|
||||
struct blockdata *b;
|
||||
|
||||
/* find size of current final block */
|
||||
for (b = block; oldlen > KEYBLOCK_LEN && b; b = b->next, oldlen -= KEYBLOCK_LEN);
|
||||
|
||||
/* chain to short for length, something is broken */
|
||||
if (oldlen > KEYBLOCK_LEN)
|
||||
{
|
||||
blockdata_free(block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
struct blockdata *new;
|
||||
size_t blocksize = KEYBLOCK_LEN - oldlen;
|
||||
size_t size = (newlen <= blocksize) ? newlen : blocksize;
|
||||
|
||||
if (size != 0)
|
||||
{
|
||||
memcpy(&b->key[oldlen], data, size);
|
||||
data += size;
|
||||
newlen -= size;
|
||||
}
|
||||
|
||||
/* full blocks from now on. */
|
||||
oldlen = 0;
|
||||
|
||||
if (newlen == 0)
|
||||
break;
|
||||
|
||||
if ((new = new_block()))
|
||||
{
|
||||
b->next = new;
|
||||
b = new;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* failed to alloc, free partial chain */
|
||||
blockdata_free(block);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void blockdata_free(struct blockdata *blocks)
|
||||
{
|
||||
struct blockdata *tmp;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
#include "../dnsmasq_interface.h"
|
||||
#include "dnsmasq_interface.h"
|
||||
|
||||
static struct crec *cache_head = NULL, *cache_tail = NULL, **hash_table = NULL;
|
||||
#ifdef HAVE_DHCP
|
||||
|
@ -30,6 +30,7 @@ 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);
|
||||
char *querystr(char *desc, unsigned short type);
|
||||
|
||||
/* 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 */
|
||||
|
@ -124,6 +125,7 @@ static const struct {
|
|||
{ 258, "AVC" }, /* Application Visibility and Control [Wolfgang_Riedel] AVC/avc-completed-template 2016-02-26*/
|
||||
{ 259, "DOA" }, /* Digital Object Architecture [draft-durand-doa-over-dns] DOA/doa-completed-template 2017-08-30*/
|
||||
{ 260, "AMTRELAY" }, /* Automatic Multicast Tunneling Relay [RFC8777] AMTRELAY/amtrelay-completed-template 2019-02-06*/
|
||||
{ 261, "RESINFO" }, /* Resolver Information as Key/Value Pairs https://datatracker.ietf.org/doc/draft-ietf-add-resolver-info/06/ */
|
||||
{ 32768, "TA" }, /* DNSSEC Trust Authorities [Sam_Weiler][http://cameo.library.cmu.edu/][ Deploying DNSSEC Without a Signed Root. Technical Report 1999-19, Information Networking Institute, Carnegie Mellon University, April 2004.] 2005-12-13*/
|
||||
{ 32769, "DLV" }, /* DNSSEC Lookaside Validation (OBSOLETE) [RFC8749][RFC4431] */
|
||||
};
|
||||
|
@ -134,6 +136,32 @@ static void cache_link(struct crec *crecp);
|
|||
void rehash(int size);
|
||||
static void cache_hash(struct crec *crecp);
|
||||
|
||||
unsigned short rrtype(char *in)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
|
||||
if (strcasecmp(in, typestr[i].name) == 0)
|
||||
return typestr[i].type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Pi-hole function: return name of RR type */
|
||||
const char *rrtype_name(unsigned short type)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if(type == 0)
|
||||
return "OTHER";
|
||||
|
||||
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
|
||||
if (typestr[i].type == type)
|
||||
return typestr[i].name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void next_uid(struct crec *crecp)
|
||||
{
|
||||
static unsigned int uid = 0;
|
||||
|
@ -264,8 +292,8 @@ static void cache_blockdata_free(struct crec *crecp)
|
|||
{
|
||||
if (!(crecp->flags & F_NEG))
|
||||
{
|
||||
if (crecp->flags & F_SRV)
|
||||
blockdata_free(crecp->addr.srv.target);
|
||||
if ((crecp->flags & F_RR) && (crecp->flags & F_KEYTAG))
|
||||
blockdata_free(crecp->addr.rrblock.rrdata);
|
||||
#ifdef HAVE_DNSSEC
|
||||
else if (crecp->flags & F_DNSKEY)
|
||||
blockdata_free(crecp->addr.key.keydata);
|
||||
|
@ -413,18 +441,21 @@ unsigned int cache_remove_uid(const unsigned int uid)
|
|||
{
|
||||
int i;
|
||||
unsigned int removed = 0;
|
||||
struct crec *crecp, **up;
|
||||
struct crec *crecp, *tmp, **up;
|
||||
|
||||
for (i = 0; i < hash_size; i++)
|
||||
for (crecp = hash_table[i], up = &hash_table[i]; crecp; crecp = crecp->hash_next)
|
||||
if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && crecp->uid == uid)
|
||||
{
|
||||
*up = crecp->hash_next;
|
||||
free(crecp);
|
||||
removed++;
|
||||
}
|
||||
else
|
||||
up = &crecp->hash_next;
|
||||
for (crecp = hash_table[i], up = &hash_table[i]; crecp; crecp = tmp)
|
||||
{
|
||||
tmp = crecp->hash_next;
|
||||
if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && crecp->uid == uid)
|
||||
{
|
||||
*up = tmp;
|
||||
free(crecp);
|
||||
removed++;
|
||||
}
|
||||
else
|
||||
up = &crecp->hash_next;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
@ -458,9 +489,20 @@ static struct crec *cache_scan_free(char *name, union all_addr *addr, unsigned s
|
|||
{
|
||||
if ((crecp->flags & F_FORWARD) && hostname_isequal(cache_get_name(crecp), name))
|
||||
{
|
||||
int rrmatch = 0;
|
||||
if (crecp->flags & flags & F_RR)
|
||||
{
|
||||
unsigned short rrc = (crecp->flags & F_KEYTAG) ? crecp->addr.rrblock.rrtype : crecp->addr.rrdata.rrtype;
|
||||
unsigned short rra = (flags & F_KEYTAG) ? addr->rrblock.rrtype : addr->rrdata.rrtype;
|
||||
|
||||
if (rrc == rra)
|
||||
rrmatch = 1;
|
||||
}
|
||||
|
||||
/* Don't delete DNSSEC in favour of a CNAME, they can co-exist */
|
||||
if ((flags & crecp->flags & (F_IPV4 | F_IPV6 | F_SRV | F_NXDOMAIN)) ||
|
||||
(((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))))
|
||||
if ((flags & crecp->flags & (F_IPV4 | F_IPV6 | F_NXDOMAIN)) ||
|
||||
(((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))) ||
|
||||
rrmatch)
|
||||
{
|
||||
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
|
||||
return crecp;
|
||||
|
@ -607,8 +649,8 @@ static struct crec *really_insert(char *name, union all_addr *addr, unsigned sho
|
|||
if (insert_error)
|
||||
return NULL;
|
||||
|
||||
/* we don't cache zero-TTL records. */
|
||||
if (ttl == 0)
|
||||
/* we don't cache zero-TTL records unless we're doing stale-caching. */
|
||||
if (daemon->cache_max_expiry == 0 && ttl == 0)
|
||||
{
|
||||
insert_error = 1;
|
||||
return NULL;
|
||||
|
@ -776,14 +818,13 @@ void cache_end_insert(void)
|
|||
read_write(daemon->pipe_to_parent, (unsigned char *)name, m, 0);
|
||||
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->ttd, sizeof(new_chain->ttd), 0);
|
||||
read_write(daemon->pipe_to_parent, (unsigned char *)&flags, sizeof(flags), 0);
|
||||
|
||||
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_SRV))
|
||||
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), 0);
|
||||
if (flags & F_SRV)
|
||||
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), 0);
|
||||
|
||||
if (flags & F_RR)
|
||||
{
|
||||
/* A negative SRV entry is possible and has no data, obviously. */
|
||||
if (!(flags & F_NEG))
|
||||
blockdata_write(new_chain->addr.srv.target, new_chain->addr.srv.targetlen, daemon->pipe_to_parent);
|
||||
/* A negative RR entry is possible and has no data, obviously. */
|
||||
if (!(flags & F_NEG) && (flags & F_KEYTAG))
|
||||
blockdata_write(new_chain->addr.rrblock.rrdata, new_chain->addr.rrblock.datalen, daemon->pipe_to_parent);
|
||||
}
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (flags & F_DNSKEY)
|
||||
|
@ -842,41 +883,15 @@ int cache_recv_insert(time_t now, int fd)
|
|||
|
||||
if (!read_write(fd, (unsigned char *)daemon->namebuff, m, 1) ||
|
||||
!read_write(fd, (unsigned char *)&ttd, sizeof(ttd), 1) ||
|
||||
!read_write(fd, (unsigned char *)&flags, sizeof(flags), 1))
|
||||
!read_write(fd, (unsigned char *)&flags, sizeof(flags), 1) ||
|
||||
!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
|
||||
return 0;
|
||||
|
||||
daemon->namebuff[m] = 0;
|
||||
|
||||
ttl = difftime(ttd, now);
|
||||
|
||||
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_SRV))
|
||||
{
|
||||
unsigned short class = C_IN;
|
||||
|
||||
if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
|
||||
return 0;
|
||||
|
||||
if ((flags & F_SRV) && !(flags & F_NEG) && !(addr.srv.target = blockdata_read(fd, addr.srv.targetlen)))
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (flags & F_DNSKEY)
|
||||
{
|
||||
if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1) ||
|
||||
!(addr.key.keydata = blockdata_read(fd, addr.key.keylen)))
|
||||
return 0;
|
||||
}
|
||||
else if (flags & F_DS)
|
||||
{
|
||||
if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1) ||
|
||||
(!(flags & F_NEG) && !(addr.key.keydata = blockdata_read(fd, addr.key.keylen))))
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
crecp = really_insert(daemon->namebuff, &addr, class, now, ttl, flags);
|
||||
}
|
||||
else if (flags & F_CNAME)
|
||||
if (flags & F_CNAME)
|
||||
{
|
||||
struct crec *newc = really_insert(daemon->namebuff, NULL, C_IN, now, ttl, flags);
|
||||
/* This relies on the fact that the target of a CNAME immediately precedes
|
||||
|
@ -884,11 +899,11 @@ int cache_recv_insert(time_t now, int fd)
|
|||
the order reversal on the new_chain. */
|
||||
if (newc)
|
||||
{
|
||||
newc->addr.cname.is_name_ptr = 0;
|
||||
|
||||
if (!crecp)
|
||||
newc->addr.cname.target.cache = NULL;
|
||||
else
|
||||
newc->addr.cname.is_name_ptr = 0;
|
||||
|
||||
if (!crecp)
|
||||
newc->addr.cname.target.cache = NULL;
|
||||
else
|
||||
{
|
||||
next_uid(crecp);
|
||||
newc->addr.cname.target.cache = crecp;
|
||||
|
@ -896,6 +911,29 @@ int cache_recv_insert(time_t now, int fd)
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned short class = C_IN;
|
||||
|
||||
if ((flags & F_RR) && !(flags & F_NEG) && (flags & F_KEYTAG)
|
||||
&& !(addr.rrblock.rrdata = blockdata_read(fd, addr.rrblock.datalen)))
|
||||
return 0;
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (flags & F_DNSKEY)
|
||||
{
|
||||
if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1) ||
|
||||
!(addr.key.keydata = blockdata_read(fd, addr.key.keylen)))
|
||||
return 0;
|
||||
}
|
||||
else if (flags & F_DS)
|
||||
{
|
||||
if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1) ||
|
||||
(!(flags & F_NEG) && !(addr.key.keydata = blockdata_read(fd, addr.key.keylen))))
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
crecp = really_insert(daemon->namebuff, &addr, class, now, ttl, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1588,7 +1626,7 @@ static void make_non_terminals(struct crec *source)
|
|||
if (!is_outdated_cname_pointer(crecp) &&
|
||||
(crecp->flags & F_FORWARD) &&
|
||||
(crecp->flags & type) &&
|
||||
!(crecp->flags & (F_IPV4 | F_IPV6 | F_CNAME | F_SRV | F_DNSKEY | F_DS)) &&
|
||||
!(crecp->flags & (F_IPV4 | F_IPV6 | F_CNAME | F_DNSKEY | F_DS | F_RR)) &&
|
||||
hostname_isequal(name, cache_get_name(crecp)))
|
||||
{
|
||||
*up = crecp->hash_next;
|
||||
|
@ -1645,7 +1683,7 @@ static void make_non_terminals(struct crec *source)
|
|||
|
||||
if (crecp)
|
||||
{
|
||||
crecp->flags = (source->flags | F_NAMEP) & ~(F_IPV4 | F_IPV6 | F_CNAME | F_SRV | F_DNSKEY | F_DS | F_REVERSE);
|
||||
crecp->flags = (source->flags | F_NAMEP) & ~(F_IPV4 | F_IPV6 | F_CNAME | F_RR | F_DNSKEY | F_DS | F_REVERSE);
|
||||
if (!(crecp->flags & F_IMMORTAL))
|
||||
crecp->ttd = source->ttd;
|
||||
crecp->name.namep = name;
|
||||
|
@ -1697,12 +1735,6 @@ int cache_make_stat(struct txt_record *t)
|
|||
break;
|
||||
#endif
|
||||
|
||||
/* Pi-hole modification */
|
||||
case TXT_PRIVACYLEVEL:
|
||||
sprintf(buff+1, "%d", *pihole_privacylevel);
|
||||
break;
|
||||
/* -------------------- */
|
||||
|
||||
case TXT_STAT_SERVERS:
|
||||
/* sum counts from different records for same server */
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
|
@ -1783,21 +1815,27 @@ static void dump_cache_entry(struct crec *cache, time_t now)
|
|||
p = buff;
|
||||
|
||||
*a = 0;
|
||||
if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
|
||||
n = "<Root>";
|
||||
|
||||
if (cache->flags & F_REVERSE)
|
||||
{
|
||||
if ((cache->flags & F_NEG))
|
||||
n = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(n) == 0)
|
||||
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))
|
||||
else if (cache->flags & F_RR)
|
||||
{
|
||||
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;
|
||||
if (cache->flags & F_KEYTAG)
|
||||
sprintf(a, "%s", querystr(NULL, cache->addr.rrblock.rrtype));
|
||||
else
|
||||
sprintf(a, "%s", querystr(NULL, cache->addr.rrdata.rrtype));
|
||||
}
|
||||
#ifdef HAVE_DNSSEC
|
||||
else if (cache->flags & F_DS)
|
||||
|
@ -1825,8 +1863,8 @@ static void dump_cache_entry(struct crec *cache, time_t now)
|
|||
t = "6";
|
||||
else if (cache->flags & F_CNAME)
|
||||
t = "C";
|
||||
else if (cache->flags & F_SRV)
|
||||
t = "V";
|
||||
else if (cache->flags & F_RR)
|
||||
t = "T";
|
||||
#ifdef HAVE_DNSSEC
|
||||
else if (cache->flags & F_DS)
|
||||
t = "S";
|
||||
|
@ -1872,8 +1910,6 @@ void get_dnsmasq_cache_info(struct cache_info *ci)
|
|||
ci->valid.ipv6++;
|
||||
else if (cache->flags & F_CNAME)
|
||||
ci->valid.cname++;
|
||||
else if (cache->flags & F_SRV)
|
||||
ci->valid.srv++;
|
||||
#ifdef HAVE_DNSSEC
|
||||
else if (cache->flags & F_DS)
|
||||
ci->valid.ds++;
|
||||
|
@ -1907,7 +1943,12 @@ void dump_cache(time_t now)
|
|||
#endif
|
||||
|
||||
blockdata_report();
|
||||
|
||||
my_syslog(LOG_INFO, _("child processes for TCP requests: in use %zu, highest since last SIGUSR1 %zu, max allowed %zu."),
|
||||
daemon->metrics[METRIC_TCP_CONNECTIONS],
|
||||
daemon->max_procs_used,
|
||||
daemon->max_procs);
|
||||
daemon->max_procs_used = daemon->metrics[METRIC_TCP_CONNECTIONS];
|
||||
|
||||
/* sum counts from different records for same server */
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
serv->flags &= ~SERV_MARK;
|
||||
|
@ -2096,7 +2137,14 @@ void _log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
|
|||
{
|
||||
dest = daemon->addrbuff;
|
||||
|
||||
if (flags & F_KEYTAG)
|
||||
if (flags & F_RR)
|
||||
{
|
||||
if (flags & F_KEYTAG)
|
||||
dest = querystr(NULL, addr->rrblock.rrtype);
|
||||
else
|
||||
dest = querystr(NULL, addr->rrdata.rrtype);
|
||||
}
|
||||
else if (flags & F_KEYTAG)
|
||||
sprintf(daemon->addrbuff, arg, addr->log.keytag, addr->log.algo, addr->log.digest);
|
||||
else if (flags & F_RCODE)
|
||||
{
|
||||
|
@ -2153,8 +2201,6 @@ void _log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
|
|||
}
|
||||
else if (flags & F_CNAME)
|
||||
dest = "<CNAME>";
|
||||
else if (flags & F_SRV)
|
||||
dest = "<SRV>";
|
||||
else if (flags & F_RRNAME)
|
||||
dest = arg;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests (default) */
|
||||
#define MAX_PROCS 60 /* max no children for TCP requests */
|
||||
#define MAX_PROCS 60 /* default max no children for TCP requests */
|
||||
#define CHILD_LIFETIME 300 /* secs 'till terminated (RFC1035 suggests > 120s) */
|
||||
#define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */
|
||||
#define TCP_BACKLOG 32 /* kernel backlog limit for TCP connections */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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,6 +106,7 @@ const char* introspection_xml_template =
|
|||
"</node>\n";
|
||||
|
||||
static char *introspection_xml = NULL;
|
||||
static int watches_modified = 0;
|
||||
|
||||
struct watch {
|
||||
DBusWatch *watch;
|
||||
|
@ -127,6 +128,7 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data)
|
|||
w->watch = watch;
|
||||
w->next = daemon->watches;
|
||||
daemon->watches = w;
|
||||
watches_modified++;
|
||||
|
||||
(void)data; /* no warning */
|
||||
return TRUE;
|
||||
|
@ -134,7 +136,7 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data)
|
|||
|
||||
static void remove_watch(DBusWatch *watch, void *data)
|
||||
{
|
||||
struct watch **up, *w, *tmp;
|
||||
struct watch **up, *w, *tmp;
|
||||
|
||||
for (up = &(daemon->watches), w = daemon->watches; w; w = tmp)
|
||||
{
|
||||
|
@ -143,6 +145,7 @@ static void remove_watch(DBusWatch *watch, void *data)
|
|||
{
|
||||
*up = tmp;
|
||||
free(w);
|
||||
watches_modified++;
|
||||
}
|
||||
else
|
||||
up = &(w->next);
|
||||
|
@ -825,11 +828,25 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
|||
}
|
||||
else if (strcmp(method, "SetFilterA") == 0)
|
||||
{
|
||||
reply = dbus_set_bool(message, OPT_FILTER_A, "filter-A");
|
||||
static int done = 0;
|
||||
static struct rrlist list = { T_A, NULL };
|
||||
|
||||
if (!done)
|
||||
{
|
||||
list.next = daemon->filter_rr;
|
||||
daemon->filter_rr = &list;
|
||||
}
|
||||
}
|
||||
else if (strcmp(method, "SetFilterAAAA") == 0)
|
||||
{
|
||||
reply = dbus_set_bool(message, OPT_FILTER_AAAA, "filter-AAAA");
|
||||
static int done = 0;
|
||||
static struct rrlist list = { T_AAAA, NULL };
|
||||
|
||||
if (!done)
|
||||
{
|
||||
list.next = daemon->filter_rr;
|
||||
daemon->filter_rr = &list;
|
||||
}
|
||||
}
|
||||
else if (strcmp(method, "SetLocaliseQueriesOption") == 0)
|
||||
{
|
||||
|
@ -941,41 +958,53 @@ void set_dbus_listeners(void)
|
|||
{
|
||||
unsigned int flags = dbus_watch_get_flags(w->watch);
|
||||
int fd = dbus_watch_get_unix_fd(w->watch);
|
||||
int poll_flags = POLLERR;
|
||||
|
||||
if (flags & DBUS_WATCH_READABLE)
|
||||
poll_listen(fd, POLLIN);
|
||||
|
||||
poll_flags |= POLLIN;
|
||||
if (flags & DBUS_WATCH_WRITABLE)
|
||||
poll_listen(fd, POLLOUT);
|
||||
poll_flags |= POLLOUT;
|
||||
|
||||
poll_listen(fd, POLLERR);
|
||||
poll_listen(fd, poll_flags);
|
||||
}
|
||||
}
|
||||
|
||||
void check_dbus_listeners()
|
||||
static int check_dbus_watches()
|
||||
{
|
||||
DBusConnection *connection = (DBusConnection *)daemon->dbus;
|
||||
struct watch *w;
|
||||
|
||||
watches_modified = 0;
|
||||
for (w = daemon->watches; w; w = w->next)
|
||||
if (dbus_watch_get_enabled(w->watch))
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
int fd = dbus_watch_get_unix_fd(w->watch);
|
||||
|
||||
if (poll_check(fd, POLLIN))
|
||||
int poll_flags = poll_check(fd, POLLIN|POLLOUT|POLLERR);
|
||||
|
||||
if ((poll_flags & POLLIN) != 0)
|
||||
flags |= DBUS_WATCH_READABLE;
|
||||
|
||||
if (poll_check(fd, POLLOUT))
|
||||
if ((poll_flags & POLLOUT) != 0)
|
||||
flags |= DBUS_WATCH_WRITABLE;
|
||||
|
||||
if (poll_check(fd, POLLERR))
|
||||
if ((poll_flags & POLLERR) != 0)
|
||||
flags |= DBUS_WATCH_ERROR;
|
||||
|
||||
if (flags != 0)
|
||||
dbus_watch_handle(w->watch, flags);
|
||||
{
|
||||
dbus_watch_handle(w->watch, flags);
|
||||
if (watches_modified)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void check_dbus_listeners()
|
||||
{
|
||||
DBusConnection *connection = (DBusConnection *)daemon->dbus;
|
||||
|
||||
while (!check_dbus_watches()) ;
|
||||
|
||||
if (connection)
|
||||
{
|
||||
dbus_connection_ref (connection);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -553,11 +553,11 @@ char *whichdevice(void)
|
|||
return NULL;
|
||||
|
||||
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
|
||||
if (if_tmp->name && (!if_tmp->used || strchr(if_tmp->name, '*')))
|
||||
if (if_tmp->name && (!(if_tmp->flags & INAME_USED) || strchr(if_tmp->name, '*')))
|
||||
return NULL;
|
||||
|
||||
for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
|
||||
if (iface->dhcp_ok)
|
||||
if (iface->dhcp4_ok || iface->dhcp6_ok)
|
||||
{
|
||||
if (!found)
|
||||
found = iface;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -297,7 +297,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||
}
|
||||
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
if (tmp->name && (tmp->flags & INAME_4) && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
/* unlinked contexts/relays are marked by context->current == context */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -92,7 +92,7 @@ void dhcp6_packet(time_t now)
|
|||
struct iface_param parm;
|
||||
struct cmsghdr *cmptr;
|
||||
struct msghdr msg;
|
||||
int if_index = 0;
|
||||
uint32_t if_index = 0;
|
||||
union {
|
||||
struct cmsghdr align; /* this ensures alignment */
|
||||
char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
|
||||
|
@ -118,11 +118,6 @@ void dhcp6_packet(time_t now)
|
|||
if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz,
|
||||
(union mysockaddr *)&from, NULL, daemon->dhcp6fd);
|
||||
#endif
|
||||
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
|
||||
{
|
||||
|
@ -138,6 +133,34 @@ void dhcp6_packet(time_t now)
|
|||
|
||||
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
/* This works around a possible Linux kernel bug when using interfaces
|
||||
enslaved to a VRF. The scope_id in the source address gets set
|
||||
to the index of the VRF interface, not the slave. Fortunately,
|
||||
the interface index returned by packetinfo is correct so we use
|
||||
that instead. Log this once, so if it triggers in other circumstances
|
||||
we've not anticipated and breaks things, we get some clues. */
|
||||
if (from.sin6_scope_id != if_index)
|
||||
{
|
||||
static int logged = 0;
|
||||
|
||||
if (!logged)
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_WARNING,
|
||||
_("Working around kernel bug: faulty source address scope for VRF slave %s"),
|
||||
ifr.ifr_name);
|
||||
logged = 1;
|
||||
}
|
||||
|
||||
from.sin6_scope_id = if_index;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz,
|
||||
(union mysockaddr *)&from, NULL, daemon->dhcp6fd);
|
||||
#endif
|
||||
|
||||
if (relay_reply6(&from, sz, ifr.ifr_name))
|
||||
{
|
||||
|
@ -159,7 +182,8 @@ void dhcp6_packet(time_t now)
|
|||
return;
|
||||
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
if (tmp->name && (tmp->flags & INAME_6) &&
|
||||
wildcard_match(tmp->name, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
parm.current = NULL;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -23,23 +23,27 @@
|
|||
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2) || defined(LOCALEDIR)
|
||||
#include <locale.h>
|
||||
#endif
|
||||
#include "../dnsmasq_interface.h"
|
||||
#include "dnsmasq_interface.h"
|
||||
// killed
|
||||
#include "../signals.h"
|
||||
#include "signals.h"
|
||||
// FTL_fork_and_bind_sockets()
|
||||
#include "main.h"
|
||||
|
||||
struct daemon *daemon;
|
||||
|
||||
static volatile pid_t pid = 0;
|
||||
static volatile int pipewrite;
|
||||
static char terminate = 0;
|
||||
volatile char FTL_terminate = 0;
|
||||
|
||||
static void set_dns_listeners(void);
|
||||
static void set_tftp_listeners(void);
|
||||
static void check_dns_listeners(time_t now);
|
||||
static void sig_handler(int sig);
|
||||
static void async_event(int pipe, time_t now);
|
||||
static void fatal_event(struct event_desc *ev, char *msg);
|
||||
static int read_event(int fd, struct event_desc *evp, char **msg);
|
||||
static void poll_resolv(int force, int do_reload, time_t now);
|
||||
static void tcp_init(void);
|
||||
|
||||
int main_dnsmasq (int argc, char **argv)
|
||||
{
|
||||
|
@ -79,10 +83,7 @@ int main_dnsmasq (int argc, char **argv)
|
|||
#endif
|
||||
|
||||
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2) || defined(LOCALEDIR)
|
||||
setlocale(LC_ALL, "");
|
||||
/*** Pi-hole modification ***/
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
/****************************/
|
||||
/*** Pi-hole modification: Locale is already initialized in main.c ***/
|
||||
#endif
|
||||
#ifdef LOCALEDIR
|
||||
bindtextdomain("dnsmasq", LOCALEDIR);
|
||||
|
@ -95,7 +96,7 @@ int main_dnsmasq (int argc, char **argv)
|
|||
sigaction(SIGUSR1, &sigact, NULL);
|
||||
sigaction(SIGUSR2, &sigact, NULL);
|
||||
sigaction(SIGHUP, &sigact, NULL);
|
||||
sigaction(SIGTERM, &sigact, NULL);
|
||||
sigaction(SIGUSR6, &sigact, NULL); // Pi-hole modification
|
||||
sigaction(SIGALRM, &sigact, NULL);
|
||||
sigaction(SIGCHLD, &sigact, NULL);
|
||||
sigaction(SIGINT, &sigact, NULL);
|
||||
|
@ -132,29 +133,15 @@ int main_dnsmasq (int argc, char **argv)
|
|||
{
|
||||
/* Note that both /000 and '.' are allowed within labels. These get
|
||||
represented in presentation format using NAME_ESCAPE as an escape
|
||||
character when in DNSSEC mode.
|
||||
In theory, if all the characters in a name were /000 or
|
||||
character. In theory, if all the characters in a name were /000 or
|
||||
'.' or NAME_ESCAPE then all would have to be escaped, so the
|
||||
presentation format would be twice as long as the spec.
|
||||
|
||||
daemon->namebuff was previously allocated by the option-reading
|
||||
code before we knew if we're in DNSSEC mode, so reallocate here. */
|
||||
free(daemon->namebuff);
|
||||
daemon->namebuff = safe_malloc(MAXDNAME * 2);
|
||||
daemon->keyname = safe_malloc(MAXDNAME * 2);
|
||||
daemon->workspacename = safe_malloc(MAXDNAME * 2);
|
||||
presentation format would be twice as long as the spec. */
|
||||
daemon->keyname = safe_malloc((MAXDNAME * 2) + 1);
|
||||
/* one char flag per possible RR in answer section (may get extended). */
|
||||
daemon->rr_status_sz = 64;
|
||||
daemon->rr_status = safe_malloc(sizeof(*daemon->rr_status) * daemon->rr_status_sz);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
|
||||
/* CONNTRACK UBUS code uses this buffer, so if not allocated above,
|
||||
we need to allocate it here. */
|
||||
if (option_bool(OPT_CMARK_ALST_EN) && !daemon->workspacename)
|
||||
daemon->workspacename = safe_malloc(MAXDNAME);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
if (!daemon->lease_file)
|
||||
|
@ -385,6 +372,13 @@ int main_dnsmasq (int argc, char **argv)
|
|||
|
||||
if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
|
||||
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
/* Determine lease FQDNs after enumerate_interfaces() call, since it needs
|
||||
to call get_domain and that's only valid for some domain configs once we
|
||||
have interface addresses. */
|
||||
lease_calc_fqdns();
|
||||
#endif
|
||||
|
||||
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
|
||||
{
|
||||
|
@ -392,7 +386,7 @@ int main_dnsmasq (int argc, char **argv)
|
|||
|
||||
if (!option_bool(OPT_CLEVERBIND))
|
||||
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
|
||||
if (if_tmp->name && !if_tmp->used)
|
||||
if (if_tmp->name && !(if_tmp->flags & INAME_USED))
|
||||
die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
|
||||
|
||||
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
|
||||
|
@ -428,11 +422,13 @@ int main_dnsmasq (int argc, char **argv)
|
|||
daemon->numrrand = max_fd/3;
|
||||
/* safe_malloc returns zero'd memory */
|
||||
daemon->randomsocks = safe_malloc(daemon->numrrand * sizeof(struct randfd));
|
||||
|
||||
tcp_init();
|
||||
}
|
||||
|
||||
#ifdef HAVE_INOTIFY
|
||||
if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
|
||||
&& (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
|
||||
if ((daemon->port != 0 && !option_bool(OPT_NO_RESOLV)) ||
|
||||
daemon->dynamic_dirs)
|
||||
inotify_dnsmasq_init();
|
||||
else
|
||||
daemon->inotifyfd = -1;
|
||||
|
@ -872,6 +868,8 @@ int main_dnsmasq (int argc, char **argv)
|
|||
|
||||
if (option_bool(OPT_LOCAL_SERVICE))
|
||||
my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
|
||||
else if (option_bool(OPT_LOCALHOST_SERVICE))
|
||||
my_syslog(LOG_INFO, _("DNS service limited to localhost"));
|
||||
}
|
||||
|
||||
my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
|
||||
|
@ -950,7 +948,7 @@ int main_dnsmasq (int argc, char **argv)
|
|||
|
||||
if (!option_bool(OPT_NOWILD))
|
||||
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
|
||||
if (if_tmp->name && !if_tmp->used)
|
||||
if (if_tmp->name && !(if_tmp->flags & INAME_USED))
|
||||
my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
|
||||
|
||||
if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
|
||||
|
@ -1058,8 +1056,10 @@ int main_dnsmasq (int argc, char **argv)
|
|||
pid = getpid();
|
||||
|
||||
daemon->pipe_to_parent = -1;
|
||||
for (i = 0; i < MAX_PROCS; i++)
|
||||
daemon->tcp_pipes[i] = -1;
|
||||
|
||||
if (daemon->port != 0)
|
||||
for (i = 0; i < daemon->max_procs; i++)
|
||||
daemon->tcp_pipes[i] = -1;
|
||||
|
||||
#ifdef HAVE_INOTIFY
|
||||
/* Using inotify, have to select a resolv file at startup */
|
||||
|
@ -1067,10 +1067,10 @@ int main_dnsmasq (int argc, char **argv)
|
|||
#endif
|
||||
|
||||
/*** Pi-hole modification ***/
|
||||
terminate = killed;
|
||||
FTL_terminate = killed;
|
||||
/****************************/
|
||||
|
||||
while (!terminate)
|
||||
while (!FTL_terminate)
|
||||
{
|
||||
int timeout = fast_retry(now);
|
||||
|
||||
|
@ -1086,7 +1086,12 @@ int main_dnsmasq (int argc, char **argv)
|
|||
(timeout == -1 || timeout > 1000))
|
||||
timeout = 1000;
|
||||
|
||||
set_dns_listeners();
|
||||
if (daemon->port != 0)
|
||||
set_dns_listeners();
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
set_tftp_listeners();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
if (option_bool(OPT_DBUS))
|
||||
|
@ -1271,8 +1276,9 @@ int main_dnsmasq (int argc, char **argv)
|
|||
check_ubus_listeners();
|
||||
}
|
||||
#endif
|
||||
|
||||
check_dns_listeners(now);
|
||||
|
||||
if (daemon->port != 0)
|
||||
check_dns_listeners(now);
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
check_tftp_listeners(now);
|
||||
|
@ -1337,7 +1343,7 @@ static void sig_handler(int sig)
|
|||
event = EVENT_CHILD;
|
||||
else if (sig == SIGALRM)
|
||||
event = EVENT_ALARM;
|
||||
else if (sig == SIGTERM)
|
||||
else if (sig == SIGUSR6) // Pi-hole modified
|
||||
event = EVENT_TERM;
|
||||
else if (sig == SIGUSR1)
|
||||
event = EVENT_DUMP;
|
||||
|
@ -1545,10 +1551,15 @@ static void async_event(int pipe, time_t now)
|
|||
if (errno != EINTR)
|
||||
break;
|
||||
}
|
||||
else
|
||||
for (i = 0 ; i < MAX_PROCS; i++)
|
||||
else if (daemon->port != 0)
|
||||
for (i = 0 ; i < daemon->max_procs; i++)
|
||||
if (daemon->tcp_pids[i] == p)
|
||||
daemon->tcp_pids[i] = 0;
|
||||
{
|
||||
daemon->tcp_pids[i] = 0;
|
||||
/* tcp_pipes == -1 && tcp_pids == 0 required to free slot */
|
||||
if (daemon->tcp_pipes[i] == -1)
|
||||
daemon->metrics[METRIC_TCP_CONNECTIONS]--;
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(HAVE_SCRIPT)
|
||||
|
@ -1611,9 +1622,10 @@ static void async_event(int pipe, time_t now)
|
|||
|
||||
case EVENT_TERM:
|
||||
/* Knock all our children on the head. */
|
||||
for (i = 0; i < MAX_PROCS; i++)
|
||||
if (daemon->tcp_pids[i] != 0)
|
||||
kill(daemon->tcp_pids[i], SIGALRM);
|
||||
if (daemon->port != 0)
|
||||
for (i = 0; i < daemon->max_procs; i++)
|
||||
if (daemon->tcp_pids[i] != 0)
|
||||
kill(daemon->tcp_pids[i], SIGALRM);
|
||||
|
||||
#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
|
||||
/* handle pending lease transitions */
|
||||
|
@ -1653,7 +1665,7 @@ static void async_event(int pipe, time_t now)
|
|||
flush_log();
|
||||
/*** Pi-hole modification ***/
|
||||
// exit(EC_GOOD);
|
||||
terminate = 1;
|
||||
FTL_terminate = 1;
|
||||
/*** Pi-hole modification ***/
|
||||
}
|
||||
}
|
||||
|
@ -1763,23 +1775,33 @@ void clear_cache_and_reload(time_t now)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void set_dns_listeners(void)
|
||||
{
|
||||
struct serverfd *serverfdp;
|
||||
struct listener *listener;
|
||||
struct randfd_list *rfl;
|
||||
int i;
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
static void set_tftp_listeners(void)
|
||||
{
|
||||
int tftp = 0;
|
||||
struct tftp_transfer *transfer;
|
||||
struct listener *listener;
|
||||
|
||||
if (!option_bool(OPT_SINGLE_PORT))
|
||||
for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
|
||||
{
|
||||
tftp++;
|
||||
poll_listen(transfer->sockfd, POLLIN);
|
||||
}
|
||||
|
||||
for (listener = daemon->listeners; listener; listener = listener->next)
|
||||
/* tftp == 0 in single-port mode. */
|
||||
if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
|
||||
poll_listen(listener->tftpfd, POLLIN);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void set_dns_listeners(void)
|
||||
{
|
||||
struct serverfd *serverfdp;
|
||||
struct listener *listener;
|
||||
struct randfd_list *rfl;
|
||||
int i;
|
||||
|
||||
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
|
||||
poll_listen(serverfdp->fd, POLLIN);
|
||||
|
@ -1793,7 +1815,7 @@ static void set_dns_listeners(void)
|
|||
poll_listen(rfl->rfd->fd, POLLIN);
|
||||
|
||||
/* check to see if we have free tcp process slots. */
|
||||
for (i = MAX_PROCS - 1; i >= 0; i--)
|
||||
for (i = daemon->max_procs - 1; i >= 0; i--)
|
||||
if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
|
||||
break;
|
||||
|
||||
|
@ -1808,16 +1830,10 @@ static void set_dns_listeners(void)
|
|||
we'll be called again when a slot becomes available. */
|
||||
if (listener->tcpfd != -1 && i >= 0)
|
||||
poll_listen(listener->tcpfd, POLLIN);
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
/* tftp == 0 in single-port mode. */
|
||||
if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
|
||||
poll_listen(listener->tftpfd, POLLIN);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!option_bool(OPT_DEBUG))
|
||||
for (i = 0; i < MAX_PROCS; i++)
|
||||
for (i = 0; i < daemon->max_procs; i++)
|
||||
if (daemon->tcp_pipes[i] != -1)
|
||||
poll_listen(daemon->tcp_pipes[i], POLLIN);
|
||||
}
|
||||
|
@ -1852,13 +1868,16 @@ static void check_dns_listeners(time_t now)
|
|||
to free the process slot. Once the child process has gone, poll()
|
||||
returns POLLHUP, not POLLIN, so have to check for both here. */
|
||||
if (!option_bool(OPT_DEBUG))
|
||||
for (i = 0; i < MAX_PROCS; i++)
|
||||
for (i = 0; i < daemon->max_procs; i++)
|
||||
if (daemon->tcp_pipes[i] != -1 &&
|
||||
poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) &&
|
||||
!cache_recv_insert(now, daemon->tcp_pipes[i]))
|
||||
{
|
||||
close(daemon->tcp_pipes[i]);
|
||||
daemon->tcp_pipes[i] = -1;
|
||||
/* tcp_pipes == -1 && tcp_pids == 0 required to free slot */
|
||||
if (daemon->tcp_pids[i] == 0)
|
||||
daemon->metrics[METRIC_TCP_CONNECTIONS]--;
|
||||
}
|
||||
|
||||
for (listener = daemon->listeners; listener; listener = listener->next)
|
||||
|
@ -1867,17 +1886,12 @@ static void check_dns_listeners(time_t now)
|
|||
if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
|
||||
receive_query(listener, now);
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
|
||||
tftp_request(listener, now);
|
||||
#endif
|
||||
|
||||
/* check to see if we have a free tcp process slot.
|
||||
Note that we can't assume that because we had
|
||||
at least one a poll() time, that we still do.
|
||||
There may be more waiting connections after
|
||||
poll() returns then free process slots. */
|
||||
for (i = MAX_PROCS - 1; i >= 0; i--)
|
||||
for (i = daemon->max_procs - 1; i >= 0; i--)
|
||||
if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
|
||||
break;
|
||||
|
||||
|
@ -1993,6 +2007,9 @@ static void check_dns_listeners(time_t now)
|
|||
/* i holds index of free slot */
|
||||
daemon->tcp_pids[i] = p;
|
||||
daemon->tcp_pipes[i] = pipefd[0];
|
||||
daemon->metrics[METRIC_TCP_CONNECTIONS]++;
|
||||
if (daemon->metrics[METRIC_TCP_CONNECTIONS] > daemon->max_procs_used)
|
||||
daemon->max_procs_used = daemon->metrics[METRIC_TCP_CONNECTIONS];
|
||||
}
|
||||
close(confd);
|
||||
|
||||
|
@ -2178,7 +2195,11 @@ int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
|
|||
poll_reset();
|
||||
if (fd != -1)
|
||||
poll_listen(fd, POLLIN);
|
||||
set_dns_listeners();
|
||||
if (daemon->port != 0)
|
||||
set_dns_listeners();
|
||||
#ifdef HAVE_TFTP
|
||||
set_tftp_listeners();
|
||||
#endif
|
||||
set_log_writer();
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
|
@ -2196,7 +2217,8 @@ int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
|
|||
now = dnsmasq_time();
|
||||
|
||||
check_log_writer(0);
|
||||
check_dns_listeners(now);
|
||||
if (daemon->port != 0)
|
||||
check_dns_listeners(now);
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
|
||||
|
@ -2239,3 +2261,9 @@ void print_dnsmasq_version(const char *yellow, const char *green, const char *bo
|
|||
printf(_("Features: %s\n\n"), compile_opts);
|
||||
}
|
||||
/**************************************************************************************/
|
||||
|
||||
void tcp_init(void)
|
||||
{
|
||||
daemon->tcp_pids = safe_malloc(daemon->max_procs*sizeof(pid_t));
|
||||
daemon->tcp_pipes = safe_malloc(daemon->max_procs*sizeof(int));
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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-2022 Simon Kelley"
|
||||
#define COPYRIGHT "Copyright (c) 2000-2024 Simon Kelley"
|
||||
|
||||
/* We do defines that influence behavior of stdio.h, so complain
|
||||
if included too early. */
|
||||
|
@ -276,12 +276,12 @@ struct event_desc {
|
|||
#define OPT_UMBRELLA_DEVID 64
|
||||
#define OPT_CMARK_ALST_EN 65
|
||||
#define OPT_QUIET_TFTP 66
|
||||
#define OPT_FILTER_A 67
|
||||
#define OPT_FILTER_AAAA 68
|
||||
#define OPT_STRIP_ECS 69
|
||||
#define OPT_STRIP_MAC 70
|
||||
#define OPT_NORR 71
|
||||
#define OPT_NO_IDENT 72
|
||||
#define OPT_STRIP_ECS 67
|
||||
#define OPT_STRIP_MAC 68
|
||||
#define OPT_NORR 69
|
||||
#define OPT_NO_IDENT 70
|
||||
#define OPT_CACHE_RR 71
|
||||
#define OPT_LOCALHOST_SERVICE 72
|
||||
#define OPT_LAST 73
|
||||
|
||||
#define OPTION_BITS (sizeof(unsigned int)*8)
|
||||
|
@ -325,17 +325,28 @@ union all_addr {
|
|||
unsigned char algo;
|
||||
unsigned char digest;
|
||||
} ds;
|
||||
struct {
|
||||
struct blockdata *target;
|
||||
unsigned short targetlen, srvport, priority, weight;
|
||||
} srv;
|
||||
/* for log_query */
|
||||
struct {
|
||||
unsigned short keytag, algo, digest, rcode;
|
||||
int ede;
|
||||
} log;
|
||||
/* for arbitrary RR record stored in block */
|
||||
struct {
|
||||
unsigned short rrtype;
|
||||
unsigned short datalen;
|
||||
struct blockdata *rrdata;
|
||||
} rrblock;
|
||||
/* for arbitrary RR record small enough to go in addr.
|
||||
NOTE: rrblock and rrdata are discriminated by the F_KEYTAG bit
|
||||
in the cache flags. */
|
||||
struct datablock {
|
||||
unsigned short rrtype;
|
||||
unsigned char datalen; /* also length of SOA in negative records. */
|
||||
char data[];
|
||||
} rrdata;
|
||||
};
|
||||
|
||||
#define RR_IMDATALEN (sizeof(union all_addr) - offsetof(struct datablock, data))
|
||||
|
||||
struct bogus_addr {
|
||||
int is6, prefix;
|
||||
|
@ -371,7 +382,8 @@ struct naptr {
|
|||
#define TXT_STAT_AUTH 6
|
||||
#define TXT_STAT_SERVERS 7
|
||||
/* Pi-hole modification */
|
||||
#define TXT_PRIVACYLEVEL 123
|
||||
#define TXT_API_DOMAIN 124
|
||||
#define TXT_API_LOCAL 125
|
||||
/************************/
|
||||
#endif
|
||||
|
||||
|
@ -515,7 +527,7 @@ struct crec {
|
|||
#define F_NOEXTRA (1u<<27)
|
||||
#define F_DOMAINSRV (1u<<28)
|
||||
#define F_RCODE (1u<<29)
|
||||
#define F_SRV (1u<<30)
|
||||
#define F_RR (1u<<30)
|
||||
#define F_STALE (1u<<31)
|
||||
|
||||
#define UID_NONE 0
|
||||
|
@ -640,7 +652,8 @@ struct allowlist {
|
|||
struct irec {
|
||||
union mysockaddr addr;
|
||||
struct in_addr netmask; /* only valid for IPv4 */
|
||||
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found, label;
|
||||
int tftp_ok, dhcp4_ok, dhcp6_ok, mtu, done, warned, dad;
|
||||
int dns_auth, index, multicast_done, found, label;
|
||||
char *name;
|
||||
/* Pi-hole modification */
|
||||
char *slabel;
|
||||
|
@ -659,10 +672,19 @@ struct listener {
|
|||
struct iname {
|
||||
char *name;
|
||||
union mysockaddr addr;
|
||||
int used;
|
||||
int flags;
|
||||
struct iname *next;
|
||||
};
|
||||
|
||||
#define INAME_USED 1
|
||||
#define INAME_4 2
|
||||
#define INAME_6 4
|
||||
|
||||
struct rrlist {
|
||||
unsigned short rr;
|
||||
struct rrlist *next;
|
||||
};
|
||||
|
||||
/* subnet parameters from command line */
|
||||
struct mysubnet {
|
||||
union mysockaddr addr;
|
||||
|
@ -1128,6 +1150,7 @@ extern struct daemon {
|
|||
struct naptr *naptr;
|
||||
struct txt_record *txt, *rr;
|
||||
struct ptr_record *ptr;
|
||||
struct rrlist *cache_rr, *filter_rr;
|
||||
struct host_record *host_records, *host_records_tail;
|
||||
struct cname *cnames;
|
||||
struct auth_zone *auth_zones;
|
||||
|
@ -1216,10 +1239,7 @@ extern struct daemon {
|
|||
char *packet; /* packet buffer */
|
||||
int packet_buff_sz; /* size of above */
|
||||
char *namebuff; /* MAXDNAME size buffer */
|
||||
#if (defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)) || defined(HAVE_DNSSEC)
|
||||
/* CONNTRACK UBUS code uses this buffer, as well as DNSSEC code. */
|
||||
char *workspacename;
|
||||
#endif
|
||||
#ifdef HAVE_DNSSEC
|
||||
char *keyname; /* MAXDNAME size buffer */
|
||||
unsigned long *rr_status; /* ceiling in TTL from DNSSEC or zero for insecure */
|
||||
|
@ -1236,8 +1256,8 @@ extern struct daemon {
|
|||
struct server *srv_save; /* Used for resend on DoD */
|
||||
size_t packet_len; /* " " */
|
||||
int fd_save; /* " " */
|
||||
pid_t tcp_pids[MAX_PROCS];
|
||||
int tcp_pipes[MAX_PROCS];
|
||||
pid_t *tcp_pids;
|
||||
int *tcp_pipes;
|
||||
int pipe_to_parent;
|
||||
int numrrand;
|
||||
struct randfd *randomsocks;
|
||||
|
@ -1297,6 +1317,8 @@ extern struct daemon {
|
|||
/* file for packet dumps. */
|
||||
int dumpfd;
|
||||
#endif
|
||||
int max_procs;
|
||||
uint max_procs_used;
|
||||
} *daemon;
|
||||
|
||||
struct server_details {
|
||||
|
@ -1309,6 +1331,7 @@ struct server_details {
|
|||
|
||||
/* cache.c */
|
||||
void cache_init(void);
|
||||
unsigned short rrtype(char *in);
|
||||
void next_uid(struct crec *crecp);
|
||||
/********************************************* Pi-hole modification ***********************************************/
|
||||
#define log_query(flags,name,addr,arg,type) _log_query(flags, name, addr, arg, type, __FILE__, __LINE__)
|
||||
|
@ -1359,6 +1382,8 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size,
|
|||
void blockdata_init(void);
|
||||
void blockdata_report(void);
|
||||
struct blockdata *blockdata_alloc(char *data, size_t len);
|
||||
int blockdata_expand(struct blockdata *block, size_t oldlen,
|
||||
char *data, size_t newlen);
|
||||
void *blockdata_retrieve(struct blockdata *block, size_t len, void *data);
|
||||
struct blockdata *blockdata_read(int fd, size_t len);
|
||||
void blockdata_write(struct blockdata *block, size_t len, int fd);
|
||||
|
@ -1371,6 +1396,7 @@ int is_name_synthetic(int flags, char *name, union all_addr *addr);
|
|||
int is_rev_synth(int flag, union all_addr *addr, char *name);
|
||||
|
||||
/* rfc1035.c */
|
||||
int do_doctor(struct dns_header *header, size_t qlen, char *namebuff);
|
||||
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||
char *name, int isExtract, int extrabytes);
|
||||
unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, size_t plen, int extrabytes);
|
||||
|
@ -1381,14 +1407,14 @@ unsigned int extract_request(struct dns_header *header, size_t qlen,
|
|||
void setup_reply(struct dns_header *header, unsigned int flags, int ede);
|
||||
int extract_addresses(struct dns_header *header, size_t qlen, char *name,
|
||||
time_t now, struct ipsets *ipsets, struct ipsets *nftsets, int is_sign,
|
||||
int check_rebind, int no_cache_dnssec, int secure, int *doctored);
|
||||
int check_rebind, int no_cache_dnssec, int secure);
|
||||
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
|
||||
void report_addresses(struct dns_header *header, size_t len, u32 mark);
|
||||
#endif
|
||||
size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
struct in_addr local_addr, struct in_addr local_netmask,
|
||||
time_t now, int ad_reqd, int do_bit, int have_pseudoheader,
|
||||
int *stale);
|
||||
int *stale, int *filtered);
|
||||
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
||||
time_t now);
|
||||
int check_for_ignored_address(struct dns_header *header, size_t qlen);
|
||||
|
@ -1440,6 +1466,7 @@ void rand_init(void);
|
|||
unsigned short rand16(void);
|
||||
u32 rand32(void);
|
||||
u64 rand64(void);
|
||||
int rr_on_list(struct rrlist *list, unsigned short rr);
|
||||
int legal_hostname(char *name);
|
||||
char *canonicalise(char *in, int *nomem);
|
||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
|
||||
|
@ -1600,6 +1627,7 @@ void lease_update_from_configs(void);
|
|||
int do_script_run(time_t now);
|
||||
void rerun_scripts(void);
|
||||
void lease_find_interfaces(time_t now);
|
||||
void lease_calc_fqdns(void);
|
||||
#ifdef HAVE_SCRIPT
|
||||
void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data,
|
||||
unsigned int len, int delim);
|
||||
|
@ -1844,14 +1872,16 @@ void poll_listen(int fd, short event);
|
|||
int do_poll(int timeout);
|
||||
|
||||
/* rrfilter.c */
|
||||
size_t rrfilter(struct dns_header *header, size_t plen, int mode);
|
||||
u16 *rrfilter_desc(int type);
|
||||
size_t rrfilter(struct dns_header *header, size_t *plen, int mode);
|
||||
short *rrfilter_desc(int type);
|
||||
int expand_workspace(unsigned char ***wkspc, int *szp, int new);
|
||||
int to_wire(char *name);
|
||||
void from_wire(char *name);
|
||||
/* modes. */
|
||||
#define RRFILTER_EDNS0 0
|
||||
#define RRFILTER_DNSSEC 1
|
||||
#define RRFILTER_A 2
|
||||
#define RRFILTER_AAAA 3
|
||||
#define RRFILTER_CONF 2
|
||||
|
||||
/* 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);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* dnssec.c is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
|
||||
and Copyright (c) 2012-2020 Simon Kelley
|
||||
and Copyright (c) 2012-2023 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
|
||||
|
@ -24,81 +24,6 @@
|
|||
#define SERIAL_LT -1
|
||||
#define SERIAL_GT 1
|
||||
|
||||
/* Convert from presentation format to wire format, in place.
|
||||
Also map UC -> LC.
|
||||
Note that using extract_name to get presentation format
|
||||
then calling to_wire() removes compression and maps case,
|
||||
thus generating names in canonical form.
|
||||
Calling to_wire followed by from_wire is almost an identity,
|
||||
except that the UC remains mapped to LC.
|
||||
|
||||
Note that both /000 and '.' are allowed within labels. These get
|
||||
represented in presentation format using NAME_ESCAPE as an escape
|
||||
character. In theory, if all the characters in a name were /000 or
|
||||
'.' or NAME_ESCAPE then all would have to be escaped, so the
|
||||
presentation format would be twice as long as the spec (1024).
|
||||
The buffers are all declared as 2049 (allowing for the trailing zero)
|
||||
for this reason.
|
||||
*/
|
||||
static int to_wire(char *name)
|
||||
{
|
||||
unsigned char *l, *p, *q, term;
|
||||
int len;
|
||||
|
||||
for (l = (unsigned char*)name; *l != 0; l = p)
|
||||
{
|
||||
for (p = l; *p != '.' && *p != 0; p++)
|
||||
if (*p >= 'A' && *p <= 'Z')
|
||||
*p = *p - 'A' + 'a';
|
||||
else if (*p == NAME_ESCAPE)
|
||||
{
|
||||
for (q = p; *q; q++)
|
||||
*q = *(q+1);
|
||||
(*p)--;
|
||||
}
|
||||
term = *p;
|
||||
|
||||
if ((len = p - l) != 0)
|
||||
memmove(l+1, l, len);
|
||||
*l = len;
|
||||
|
||||
p++;
|
||||
|
||||
if (term == 0)
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
return l + 1 - (unsigned char *)name;
|
||||
}
|
||||
|
||||
/* Note: no compression allowed in input. */
|
||||
static void from_wire(char *name)
|
||||
{
|
||||
unsigned char *l, *p, *last;
|
||||
int len;
|
||||
|
||||
for (last = (unsigned char *)name; *last != 0; last += *last+1);
|
||||
|
||||
for (l = (unsigned char *)name; *l != 0; l += len+1)
|
||||
{
|
||||
len = *l;
|
||||
memmove(l, l+1, len);
|
||||
for (p = l; p < l + len; p++)
|
||||
if (*p == '.' || *p == 0 || *p == NAME_ESCAPE)
|
||||
{
|
||||
memmove(p+1, p, 1 + last - p);
|
||||
len++;
|
||||
*p++ = NAME_ESCAPE;
|
||||
(*p)++;
|
||||
}
|
||||
|
||||
l[len] = '.';
|
||||
}
|
||||
|
||||
if ((char *)l != name)
|
||||
*(l-1) = 0;
|
||||
}
|
||||
|
||||
/* Input in presentation format */
|
||||
static int count_labels(char *name)
|
||||
{
|
||||
|
@ -225,7 +150,7 @@ static int is_check_date(unsigned long curtime)
|
|||
On returning 0, the end has been reached.
|
||||
*/
|
||||
struct rdata_state {
|
||||
u16 *desc;
|
||||
short *desc;
|
||||
size_t c;
|
||||
unsigned char *end, *ip, *op;
|
||||
char *buff;
|
||||
|
@ -246,7 +171,7 @@ static int get_rdata(struct dns_header *header, size_t plen, struct rdata_state
|
|||
{
|
||||
d = *(state->desc);
|
||||
|
||||
if (d == (u16)-1)
|
||||
if (d == -1)
|
||||
{
|
||||
/* all the bytes to the end. */
|
||||
if ((state->c = state->end - state->ip) != 0)
|
||||
|
@ -294,7 +219,7 @@ static int get_rdata(struct dns_header *header, size_t plen, struct rdata_state
|
|||
|
||||
/* Bubble sort the RRset into the canonical order. */
|
||||
|
||||
static int 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, short *rr_desc, int rrsetidx,
|
||||
unsigned char **rrset, char *buff1, char *buff2)
|
||||
{
|
||||
int swap, i, j;
|
||||
|
@ -331,7 +256,7 @@ static int sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
|
|||
is the identity function and we can compare
|
||||
the RRs directly. If not we compare the
|
||||
canonicalised RRs one byte at a time. */
|
||||
if (*rr_desc == (u16)-1)
|
||||
if (*rr_desc == -1)
|
||||
{
|
||||
int rdmin = rdlen1 > rdlen2 ? rdlen2 : rdlen1;
|
||||
int cmp = memcmp(state1.ip, state2.ip, rdmin);
|
||||
|
@ -524,7 +449,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
|
|||
unsigned char *p;
|
||||
int rdlen, j, name_labels, algo, labels, key_tag;
|
||||
struct crec *crecp = NULL;
|
||||
u16 *rr_desc = rrfilter_desc(type);
|
||||
short *rr_desc = rrfilter_desc(type);
|
||||
u32 sig_expiration, sig_inception;
|
||||
int failflags = DNSSEC_FAIL_NOSIG | DNSSEC_FAIL_NYV | DNSSEC_FAIL_EXP | DNSSEC_FAIL_NOKEYSUP;
|
||||
|
||||
|
@ -671,7 +596,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
|
|||
|
||||
If canonicalisation is not needed, a simple insertion into the hash works.
|
||||
*/
|
||||
if (*rr_desc == (u16)-1)
|
||||
if (*rr_desc == -1)
|
||||
{
|
||||
len = htons(rdlen);
|
||||
hash->update(ctx, 2, (unsigned char *)&len);
|
||||
|
@ -996,7 +921,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
|
|||
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)(header+1);
|
||||
int qtype, qclass, rc, i, neganswer, nons, neg_ttl = 0, found_supported = 0;
|
||||
int qtype, qclass, rc, i, neganswer = 0, nons = 0, servfail = 0, neg_ttl = 0, found_supported = 0;
|
||||
int aclass, atype, rdlen, flags;
|
||||
unsigned long ttl;
|
||||
union all_addr a;
|
||||
|
@ -1009,35 +934,43 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||
GETSHORT(qclass, p);
|
||||
|
||||
if (qtype != T_DS || qclass != class)
|
||||
rc = STAT_BOGUS;
|
||||
else
|
||||
rc = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons, &neg_ttl);
|
||||
|
||||
if (STAT_ISEQUAL(rc, STAT_INSECURE))
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("Insecure DS reply received for %s, check domain configuration and upstream DNS server DNSSEC support"), name);
|
||||
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS - not secure", 0);
|
||||
return STAT_BOGUS | DNSSEC_FAIL_INDET;
|
||||
}
|
||||
|
||||
p = (unsigned char *)(header+1);
|
||||
if (!extract_name(header, plen, &p, name, 1, 4))
|
||||
return STAT_BOGUS;
|
||||
return STAT_BOGUS;
|
||||
|
||||
p += 4; /* qtype, qclass */
|
||||
|
||||
/* If the key needed to validate the DS is on the same domain as the DS, we'll
|
||||
loop getting nowhere. Stop that now. This can happen of the DS answer comes
|
||||
from the DS's zone, and not the parent zone. */
|
||||
if (STAT_ISEQUAL(rc, STAT_NEED_KEY) && hostname_isequal(name, keyname))
|
||||
/* A SERVFAIL answer has been seen to a DS query not at start of authority,
|
||||
so treat it as such and continue to search for a DS or proof of no existence
|
||||
further down the tree. */
|
||||
if (RCODE(header) == SERVFAIL)
|
||||
servfail = neganswer = nons = 1;
|
||||
else
|
||||
{
|
||||
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS", 0);
|
||||
return STAT_BOGUS;
|
||||
rc = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons, &neg_ttl);
|
||||
|
||||
if (STAT_ISEQUAL(rc, STAT_INSECURE))
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("Insecure DS reply received for %s, check domain configuration and upstream DNS server DNSSEC support"), name);
|
||||
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS - not secure", 0);
|
||||
return STAT_BOGUS | DNSSEC_FAIL_INDET;
|
||||
}
|
||||
|
||||
p = (unsigned char *)(header+1);
|
||||
if (!extract_name(header, plen, &p, name, 1, 4))
|
||||
return STAT_BOGUS;
|
||||
|
||||
p += 4; /* qtype, qclass */
|
||||
|
||||
/* If the key needed to validate the DS is on the same domain as the DS, we'll
|
||||
loop getting nowhere. Stop that now. This can happen of the DS answer comes
|
||||
from the DS's zone, and not the parent zone. */
|
||||
if (STAT_ISEQUAL(rc, STAT_NEED_KEY) && hostname_isequal(name, keyname))
|
||||
{
|
||||
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS", 0);
|
||||
return STAT_BOGUS;
|
||||
}
|
||||
|
||||
if (!STAT_ISEQUAL(rc, STAT_SECURE))
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (!STAT_ISEQUAL(rc, STAT_SECURE))
|
||||
return rc;
|
||||
|
||||
if (!neganswer)
|
||||
{
|
||||
cache_start_insert();
|
||||
|
@ -1135,7 +1068,8 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||
cache_end_insert();
|
||||
|
||||
if (neganswer)
|
||||
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no DS/cut" : "no DS", 0);
|
||||
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL,
|
||||
servfail ? "SERVFAIL" : (nons ? "no DS/cut" : "no DS"), 0);
|
||||
|
||||
return STAT_OK;
|
||||
}
|
||||
|
@ -1870,7 +1804,7 @@ static int zone_status(char *name, int class, char *keyname, time_t now)
|
|||
|
||||
When validating replies to DS records, we're only interested in the NSEC{3} RRs in the auth section.
|
||||
Other RRs in that section missing sigs will not cause am INSECURE reply. We determine this mode
|
||||
is the nons argument is non-NULL.
|
||||
if the nons argument is non-NULL.
|
||||
*/
|
||||
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 *nsec_ttl)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -22,12 +22,13 @@ static int match_domain(struct in_addr addr, struct cond_domain *c);
|
|||
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c);
|
||||
static int match_domain6(struct in6_addr *addr, struct cond_domain *c);
|
||||
|
||||
int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
||||
int is_name_synthetic(int flags, char *name, union all_addr *addrp)
|
||||
{
|
||||
char *p;
|
||||
struct cond_domain *c = NULL;
|
||||
int prot = (flags & F_IPV6) ? AF_INET6 : AF_INET;
|
||||
|
||||
union all_addr addr;
|
||||
|
||||
for (c = daemon->synth_domains; c; c = c->next)
|
||||
{
|
||||
int found = 0;
|
||||
|
@ -74,7 +75,7 @@ int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
|||
if (!c->is6 &&
|
||||
index <= ntohl(c->end.s_addr) - ntohl(c->start.s_addr))
|
||||
{
|
||||
addr->addr4.s_addr = htonl(ntohl(c->start.s_addr) + index);
|
||||
addr.addr4.s_addr = htonl(ntohl(c->start.s_addr) + index);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
@ -86,8 +87,8 @@ int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
|||
index <= addr6part(&c->end6) - addr6part(&c->start6))
|
||||
{
|
||||
u64 start = addr6part(&c->start6);
|
||||
addr->addr6 = c->start6;
|
||||
setaddr6part(&addr->addr6, start + index);
|
||||
addr.addr6 = c->start6;
|
||||
setaddr6part(&addr.addr6, start + index);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
@ -135,8 +136,8 @@ int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
|||
}
|
||||
}
|
||||
|
||||
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
|
||||
found = (prot == AF_INET) ? match_domain(addr->addr4, c) : match_domain6(&addr->addr6, c);
|
||||
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, &addr))
|
||||
found = (prot == AF_INET) ? match_domain(addr.addr4, c) : match_domain6(&addr.addr6, c);
|
||||
}
|
||||
|
||||
/* restore name */
|
||||
|
@ -148,7 +149,12 @@ int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
|||
|
||||
|
||||
if (found)
|
||||
return 1;
|
||||
{
|
||||
if (addrp)
|
||||
*addrp = addr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -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, RRFILTER_EDNS0);
|
||||
rrfilter(header, &plen, RRFILTER_EDNS0);
|
||||
|
||||
/* Now, force addition of a new one */
|
||||
p = NULL;
|
||||
|
@ -191,16 +191,13 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
|||
if (!(p = skip_questions(header, plen)) ||
|
||||
!(p = skip_section(p,
|
||||
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
|
||||
header, plen)))
|
||||
{
|
||||
free(buff);
|
||||
return plen;
|
||||
}
|
||||
if (p + 11 > limit)
|
||||
{
|
||||
free(buff);
|
||||
return plen; /* Too big */
|
||||
}
|
||||
header, plen)) ||
|
||||
p + 11 > limit)
|
||||
{
|
||||
free(buff);
|
||||
return plen; /* bad packet */
|
||||
}
|
||||
|
||||
*p++ = 0; /* empty name */
|
||||
PUTSHORT(T_OPT, p);
|
||||
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -697,7 +697,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
|||
{
|
||||
unsigned char *pheader, *sizep;
|
||||
struct ipsets *ipsets = NULL, *nftsets = NULL;
|
||||
int munged = 0, is_sign;
|
||||
int is_sign;
|
||||
unsigned int rcode = RCODE(header);
|
||||
size_t plen;
|
||||
/******** Pi-hole modification ********/
|
||||
|
@ -706,8 +706,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
|||
|
||||
(void)ad_reqd;
|
||||
(void)do_bit;
|
||||
(void)bogusanswer;
|
||||
|
||||
|
||||
#ifdef HAVE_IPSET
|
||||
if (daemon->ipsets && extract_request(header, n, daemon->namebuff, NULL))
|
||||
ipsets = domain_find_sets(daemon->ipsets, daemon->namebuff);
|
||||
|
@ -738,7 +737,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, RRFILTER_EDNS0);
|
||||
rrfilter(header, &n, RRFILTER_EDNS0);
|
||||
pheader = NULL;
|
||||
}
|
||||
else
|
||||
|
@ -801,119 +800,118 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
|||
server->flags |= SERV_WARNED_RECURSIVE;
|
||||
}
|
||||
|
||||
if (daemon->bogus_addr && rcode != NXDOMAIN &&
|
||||
check_for_bogus_wildcard(header, n, daemon->namebuff, now))
|
||||
if (header->hb3 & HB3_TC)
|
||||
{
|
||||
munged = 1;
|
||||
SET_RCODE(header, NXDOMAIN);
|
||||
header->hb3 &= ~HB3_AA;
|
||||
cache_secure = 0;
|
||||
ede = EDE_BLOCKED;
|
||||
log_query(F_UPSTREAM, NULL, NULL, "truncated", 0);
|
||||
header->ancount = htons(0);
|
||||
header->nscount = htons(0);
|
||||
header->arcount = htons(0);
|
||||
}
|
||||
else
|
||||
|
||||
if (!(header->hb3 & HB3_TC) && (!bogusanswer || (header->hb4 & HB4_CD)))
|
||||
{
|
||||
int doctored = 0;
|
||||
if (rcode == NXDOMAIN && extract_request(header, n, daemon->namebuff, NULL) &&
|
||||
(check_for_local_domain(daemon->namebuff, now) || lookup_domain(daemon->namebuff, F_CONFIG, NULL, NULL)))
|
||||
{
|
||||
/* if we forwarded a query for a locally known name (because it was for
|
||||
an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
|
||||
since we know that the domain exists, even if upstream doesn't */
|
||||
header->hb3 |= HB3_AA;
|
||||
SET_RCODE(header, NOERROR);
|
||||
cache_secure = 0;
|
||||
}
|
||||
|
||||
if (rcode == NXDOMAIN &&
|
||||
extract_request(header, n, daemon->namebuff, NULL))
|
||||
if (daemon->doctors && do_doctor(header, n, daemon->namebuff))
|
||||
cache_secure = 0;
|
||||
|
||||
/* check_for_bogus_wildcard() does it's own caching, so
|
||||
don't call extract_addresses() if it triggers. */
|
||||
if (daemon->bogus_addr && rcode != NXDOMAIN &&
|
||||
check_for_bogus_wildcard(header, n, daemon->namebuff, now))
|
||||
{
|
||||
if (check_for_local_domain(daemon->namebuff, now) ||
|
||||
lookup_domain(daemon->namebuff, F_CONFIG, NULL, NULL))
|
||||
{
|
||||
/* if we forwarded a query for a locally known name (because it was for
|
||||
an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
|
||||
since we know that the domain exists, even if upstream doesn't */
|
||||
munged = 1;
|
||||
header->hb3 |= HB3_AA;
|
||||
SET_RCODE(header, NOERROR);
|
||||
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);
|
||||
}
|
||||
|
||||
switch (extract_addresses(header, n, daemon->namebuff, now, ipsets, nftsets, is_sign, check_rebind, no_cache, cache_secure, &doctored))
|
||||
{
|
||||
case 1:
|
||||
my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
|
||||
munged = 1;
|
||||
header->ancount = htons(0);
|
||||
header->nscount = htons(0);
|
||||
header->arcount = htons(0);
|
||||
SET_RCODE(header, NXDOMAIN);
|
||||
header->hb3 &= ~HB3_AA;
|
||||
cache_secure = 0;
|
||||
ede = EDE_BLOCKED;
|
||||
break;
|
||||
|
||||
/* extract_addresses() found a malformed answer. */
|
||||
case 2:
|
||||
munged = 1;
|
||||
SET_RCODE(header, SERVFAIL);
|
||||
cache_secure = 0;
|
||||
ede = EDE_OTHER;
|
||||
break;
|
||||
|
||||
/* Pi-hole modification */
|
||||
case 99:
|
||||
cache_secure = 0;
|
||||
// Make a private copy of the pheader to ensure
|
||||
// we are not accidentially rewriting what is in
|
||||
// the pheader when we're creating a crafted reply
|
||||
// further below (when a query is to be blocked)
|
||||
if (pheader)
|
||||
{
|
||||
pheader_copy = calloc(1, plen);
|
||||
memcpy(pheader_copy, pheader, plen);
|
||||
}
|
||||
|
||||
// Generate DNS packet for reply, a possibly existing pseudo header
|
||||
// will be restored later inside resize_packet()
|
||||
n = FTL_make_answer(header, ((char *) header) + 65536, n, &ede);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
int rc = extract_addresses(header, n, daemon->namebuff, now, ipsets, nftsets, is_sign, check_rebind, no_cache, cache_secure);
|
||||
|
||||
if (doctored)
|
||||
cache_secure = 0;
|
||||
if (rc != 0)
|
||||
{
|
||||
header->ancount = htons(0);
|
||||
header->nscount = htons(0);
|
||||
header->arcount = htons(0);
|
||||
cache_secure = 0;
|
||||
}
|
||||
|
||||
if (rc == 1)
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
|
||||
ede = EDE_BLOCKED;
|
||||
}
|
||||
|
||||
if (rc == 2)
|
||||
{
|
||||
/* extract_addresses() found a malformed answer. */
|
||||
SET_RCODE(header, SERVFAIL);
|
||||
ede = EDE_OTHER;
|
||||
}
|
||||
|
||||
/* Pi-hole modification */
|
||||
if(rc == 99)
|
||||
{
|
||||
cache_secure = 0;
|
||||
// Make a private copy of the pheader to ensure
|
||||
// we are not accidentially rewriting what is in
|
||||
// the pheader when we're creating a crafted reply
|
||||
// further below (when a query is to be blocked)
|
||||
if (pheader)
|
||||
{
|
||||
pheader_copy = calloc(1, plen);
|
||||
memcpy(pheader_copy, pheader, plen);
|
||||
}
|
||||
|
||||
// Generate DNS packet for reply, a possibly existing pseudo header
|
||||
// will be restored later inside resize_packet()
|
||||
n = FTL_make_answer(header, ((char *) header) + 65536, n, &ede);
|
||||
}
|
||||
}
|
||||
|
||||
if (RCODE(header) == NOERROR && rrfilter(header, &n, RRFILTER_CONF) > 0)
|
||||
ede = EDE_FILTERED;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (bogusanswer && !(header->hb4 & HB4_CD) && !option_bool(OPT_DNSSEC_DEBUG))
|
||||
{
|
||||
/* Bogus reply, turn into SERVFAIL */
|
||||
SET_RCODE(header, SERVFAIL);
|
||||
munged = 1;
|
||||
}
|
||||
|
||||
if (option_bool(OPT_DNSSEC_VALID))
|
||||
{
|
||||
header->hb4 &= ~HB4_AD;
|
||||
|
||||
if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
|
||||
if (bogusanswer)
|
||||
{
|
||||
if (!(header->hb4 & HB4_CD) && !option_bool(OPT_DNSSEC_DEBUG))
|
||||
{
|
||||
/* Bogus reply, turn into SERVFAIL */
|
||||
SET_RCODE(header, SERVFAIL);
|
||||
header->ancount = htons(0);
|
||||
header->nscount = htons(0);
|
||||
header->arcount = htons(0);
|
||||
ede = EDE_DNSSEC_BOGUS;
|
||||
}
|
||||
}
|
||||
else if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure)
|
||||
header->hb4 |= HB4_AD;
|
||||
|
||||
/* If the requestor didn't set the DO bit, don't return DNSSEC info. */
|
||||
if (!do_bit)
|
||||
n = rrfilter(header, n, RRFILTER_DNSSEC);
|
||||
rrfilter(header, &n, RRFILTER_DNSSEC);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* do this after extract_addresses. Ensure NODATA reply and remove
|
||||
nameserver info. */
|
||||
if (munged)
|
||||
{
|
||||
header->ancount = htons(0);
|
||||
header->nscount = htons(0);
|
||||
header->arcount = htons(0);
|
||||
header->hb3 &= ~HB3_TC;
|
||||
}
|
||||
|
||||
/* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
|
||||
sections of the packet. Find the new length here and put back pseudoheader
|
||||
if it was removed. */
|
||||
/* the code above can elide sections of the packet. Find the new length here
|
||||
and put back pseudoheader if it was removed. */
|
||||
n = resize_packet(header, n, pheader_copy ? pheader_copy : pheader, plen);
|
||||
/******** Pi-hole modification ********/
|
||||
// The line above was modified to use
|
||||
|
@ -1882,10 +1880,10 @@ void receive_query(struct listener *listen, time_t now)
|
|||
#endif
|
||||
else
|
||||
{
|
||||
int stale;
|
||||
int stale, filtered;
|
||||
int ad_reqd = do_bit;
|
||||
u16 hb3 = header->hb3, hb4 = header->hb4;
|
||||
int fd = listen->fd;
|
||||
struct blockdata *saved_question = blockdata_alloc((char *) header, (size_t)n);
|
||||
|
||||
/* RFC 6840 5.7 */
|
||||
if (header->hb4 & HB4_AD)
|
||||
|
@ -1922,17 +1920,27 @@ void receive_query(struct listener *listen, time_t now)
|
|||
/**********************************************/
|
||||
|
||||
m = answer_request(header, ((char *) header) + udp_size, (size_t)n,
|
||||
dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader, &stale);
|
||||
dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader, &stale, &filtered);
|
||||
|
||||
if (m >= 1)
|
||||
{
|
||||
if (stale && have_pseudoheader)
|
||||
if (have_pseudoheader)
|
||||
{
|
||||
u16 swap = htons(EDE_STALE);
|
||||
|
||||
m = add_pseudoheader(header, m, ((unsigned char *) header) + udp_size, daemon->edns_pktsz,
|
||||
EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
|
||||
int ede = EDE_UNSET;
|
||||
if (filtered)
|
||||
ede = EDE_FILTERED;
|
||||
else if (stale)
|
||||
ede = EDE_STALE;
|
||||
|
||||
if (ede != EDE_UNSET)
|
||||
{
|
||||
u16 swap = htons(ede);
|
||||
|
||||
m = add_pseudoheader(header, m, ((unsigned char *) header) + udp_size, daemon->edns_pktsz,
|
||||
EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, listen->fd);
|
||||
#endif
|
||||
|
@ -1947,34 +1955,31 @@ void receive_query(struct listener *listen, time_t now)
|
|||
daemon->metrics[METRIC_DNS_STALE_ANSWERED]++;
|
||||
}
|
||||
|
||||
if (m == 0 || stale)
|
||||
if (stale)
|
||||
{
|
||||
if (m != 0)
|
||||
/* We answered with stale cache data, so forward the query anyway to
|
||||
refresh that. */
|
||||
m = 0;
|
||||
|
||||
/* We've already answered the client, so don't send it the answer
|
||||
when it comes back. */
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
if (saved_question)
|
||||
{
|
||||
if (m == 0)
|
||||
{
|
||||
size_t plen;
|
||||
blockdata_retrieve(saved_question, (size_t)n, header);
|
||||
|
||||
/* We answered with stale cache data, so forward the query anyway to
|
||||
refresh that. Restore the query from the answer packet. */
|
||||
pheader = find_pseudoheader(header, (size_t)m, &plen, NULL, NULL, NULL);
|
||||
|
||||
header->hb3 = hb3;
|
||||
header->hb4 = hb4;
|
||||
header->ancount = htons(0);
|
||||
header->nscount = htons(0);
|
||||
header->arcount = htons(0);
|
||||
|
||||
m = resize_packet(header, m, pheader, plen);
|
||||
|
||||
/* We've already answered the client, so don't send it the answer
|
||||
when it comes back. */
|
||||
fd = -1;
|
||||
if (forward_query(fd, &source_addr, &dst_addr, if_index,
|
||||
header, (size_t)n, ((char *) header) + udp_size, now, NULL, ad_reqd, do_bit, 0))
|
||||
daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++;
|
||||
else
|
||||
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
|
||||
}
|
||||
|
||||
if (forward_query(fd, &source_addr, &dst_addr, if_index,
|
||||
header, (size_t)n, ((char *) header) + udp_size, now, NULL, ad_reqd, do_bit, 0))
|
||||
daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++;
|
||||
else
|
||||
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
|
||||
blockdata_free(saved_question);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2163,7 +2168,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
|||
daemon->log_display_id = ++daemon->log_id;
|
||||
|
||||
log_query_mysockaddr(F_NOEXTRA | F_DNSSEC | F_SERVER, keyname, &server->addr,
|
||||
STAT_ISEQUAL(status, STAT_NEED_KEY) ? "dnssec-query[DNSKEY]" : "dnssec-query[DS]", 0);
|
||||
STAT_ISEQUAL(new_status, STAT_NEED_KEY) ? "dnssec-query[DNSKEY]" : "dnssec-query[DS]", 0);
|
||||
|
||||
new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
|
||||
|
||||
|
@ -2188,7 +2193,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
|||
unsigned char *tcp_request(int confd, time_t now,
|
||||
union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
|
||||
{
|
||||
size_t size = 0;
|
||||
size_t size = 0, saved_size = 0;
|
||||
int norebind;
|
||||
#ifdef HAVE_CONNTRACK
|
||||
int is_single_query = 0, allowed = 1;
|
||||
|
@ -2199,6 +2204,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
|
||||
int cacheable, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
|
||||
size_t m;
|
||||
struct blockdata *saved_question = NULL;
|
||||
unsigned short qtype;
|
||||
unsigned int gotname;
|
||||
/* Max TCP packet + slop + size */
|
||||
|
@ -2216,9 +2222,8 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
unsigned char *pheader;
|
||||
unsigned int mark = 0;
|
||||
int have_mark = 0;
|
||||
int first, last, stale, do_stale = 0;
|
||||
int first, last, filtered, stale, do_stale = 0;
|
||||
unsigned int flags = 0;
|
||||
u16 hb3, hb4;
|
||||
|
||||
/************ Pi-hole modification ************/
|
||||
bool piholeblocked = false;
|
||||
|
@ -2277,35 +2282,15 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
{
|
||||
int ede = EDE_UNSET;
|
||||
|
||||
if (query_count == TCP_MAX_QUERIES)
|
||||
return packet;
|
||||
|
||||
if (do_stale)
|
||||
if (!do_stale)
|
||||
{
|
||||
size_t plen;
|
||||
|
||||
/* We answered the last query with stale data. Now try and get fresh data.
|
||||
Restore query from answer. */
|
||||
pheader = find_pseudoheader(header, m, &plen, NULL, NULL, NULL);
|
||||
if (query_count == TCP_MAX_QUERIES)
|
||||
break;
|
||||
|
||||
header->hb3 = hb3;
|
||||
header->hb4 = hb4;
|
||||
header->ancount = htons(0);
|
||||
header->nscount = htons(0);
|
||||
header->arcount = htons(0);
|
||||
|
||||
size = resize_packet(header, m, pheader, plen);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
|
||||
!(size = c1 << 8 | c2) ||
|
||||
!read_write(confd, payload, size, 1))
|
||||
return packet;
|
||||
|
||||
/* for stale-answer processing. */
|
||||
hb3 = header->hb3;
|
||||
hb4 = header->hb4;
|
||||
break;
|
||||
}
|
||||
|
||||
if (size < (int)sizeof(struct dns_header))
|
||||
|
@ -2327,7 +2312,6 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
no_cache_dnssec = 1;
|
||||
|
||||
//********************** Pi-hole modification **********************//
|
||||
unsigned char *pheader = NULL;
|
||||
pheader = find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL);
|
||||
FTL_parse_pseudoheaders(pheader, (size_t)size);
|
||||
//******************************************************************//
|
||||
|
@ -2447,18 +2431,28 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
if (do_stale)
|
||||
m = 0;
|
||||
else
|
||||
/* m > 0 if answered from cache */
|
||||
m = answer_request(header, ((char *) header) + 65536, (size_t)size,
|
||||
dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader, &stale);
|
||||
|
||||
{
|
||||
if (saved_question)
|
||||
blockdata_free(saved_question);
|
||||
|
||||
saved_question = blockdata_alloc((char *) header, (size_t)size);
|
||||
saved_size = size;
|
||||
|
||||
/* m > 0 if answered from cache */
|
||||
m = answer_request(header, ((char *) header) + 65536, (size_t)size,
|
||||
dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader, &stale, &filtered);
|
||||
}
|
||||
/* Do this by steam now we're not in the select() loop */
|
||||
check_log_writer(1);
|
||||
|
||||
if (m == 0)
|
||||
if (m == 0 && saved_question)
|
||||
{
|
||||
struct server *master;
|
||||
int start;
|
||||
|
||||
blockdata_retrieve(saved_question, (size_t)saved_size, header);
|
||||
size = saved_size;
|
||||
|
||||
if (lookup_domain(daemon->namebuff, gotname, &first, &last))
|
||||
flags = is_local_answer(now, first, daemon->namebuff);
|
||||
else
|
||||
|
@ -2591,13 +2585,23 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
|
||||
}
|
||||
}
|
||||
else if (stale)
|
||||
{
|
||||
u16 swap = htons((u16)EDE_STALE);
|
||||
|
||||
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
|
||||
}
|
||||
|
||||
else if (have_pseudoheader)
|
||||
{
|
||||
ede = EDE_UNSET;
|
||||
|
||||
if (filtered)
|
||||
ede = EDE_FILTERED;
|
||||
else if (stale)
|
||||
ede = EDE_STALE;
|
||||
|
||||
if (ede != EDE_UNSET)
|
||||
{
|
||||
u16 swap = htons((u16)ede);
|
||||
|
||||
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
check_log_writer(1);
|
||||
|
||||
*length = htons(m);
|
||||
|
@ -2613,7 +2617,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
break;
|
||||
|
||||
/* If we answered with stale data, this process will now try and get fresh data into
|
||||
the cache then and cannot therefore accept new queries. Close the incoming
|
||||
the cache and cannot therefore accept new queries. Close the incoming
|
||||
connection to signal that to the client. Then set do_stale and loop round
|
||||
once more to try and get fresh data, after which we exit. */
|
||||
if (stale)
|
||||
|
@ -2631,6 +2635,9 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||
close(confd);
|
||||
}
|
||||
|
||||
if (saved_question)
|
||||
blockdata_free(saved_question);
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2012-2020 Simon Kelley
|
||||
/* Copyright (c) 2012-2023 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
|
||||
|
@ -165,7 +165,7 @@ static void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
|
|||
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
|
||||
|
||||
for (i = 0, j = 0; i < 16; ++i, j += 4)
|
||||
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
|
||||
m[i] = (((WORD)data[j]) << 24) | (((WORD)data[j + 1]) << 16) | (((WORD)data[j + 2]) << 8) | (((WORD)data[j + 3]));
|
||||
for ( ; i < 64; ++i)
|
||||
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -99,7 +99,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||
}
|
||||
|
||||
/**** Pi-hole modification ****/
|
||||
logg("Started dnsmasq helper");
|
||||
logg("Started script helper");
|
||||
/******************************/
|
||||
|
||||
/* ignore SIGTERM and SIGINT, so that we can clean up when the main process gets hit
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -94,7 +94,7 @@ void inotify_dnsmasq_init()
|
|||
if (daemon->inotifyfd == -1)
|
||||
die(_("failed to create inotify: %s"), NULL, EC_MISC);
|
||||
|
||||
if (option_bool(OPT_NO_RESOLV))
|
||||
if (daemon->port == 0 || option_bool(OPT_NO_RESOLV))
|
||||
return;
|
||||
|
||||
for (res = daemon->resolv_files; res; res = res->next)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
|
||||
static struct dhcp_lease *leases = NULL, *old_leases = NULL;
|
||||
|
@ -28,8 +27,7 @@ static int read_leases(time_t now, FILE *leasestream)
|
|||
struct dhcp_lease *lease;
|
||||
int clid_len, hw_len, hw_type;
|
||||
int items;
|
||||
char *domain = NULL;
|
||||
|
||||
|
||||
*daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
|
||||
|
||||
/* client-id max length is 255 which is 255*2 digits + 254 colons
|
||||
|
@ -69,8 +67,8 @@ static int read_leases(time_t now, FILE *leasestream)
|
|||
|
||||
if (inet_pton(AF_INET, daemon->namebuff, &addr.addr4))
|
||||
{
|
||||
if ((lease = lease4_allocate(addr.addr4)))
|
||||
domain = get_domain(lease->addr);
|
||||
lease = lease4_allocate(addr.addr4);
|
||||
|
||||
|
||||
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
|
||||
/* For backwards compatibility, no explicit MAC address type means ether. */
|
||||
|
@ -90,10 +88,7 @@ static int read_leases(time_t now, FILE *leasestream)
|
|||
}
|
||||
|
||||
if ((lease = lease6_allocate(&addr.addr6, lease_type)))
|
||||
{
|
||||
lease_set_iaid(lease, strtoul(s, NULL, 10));
|
||||
domain = get_domain6(&lease->addr6);
|
||||
}
|
||||
lease_set_iaid(lease, strtoul(s, NULL, 10));
|
||||
}
|
||||
#endif
|
||||
else
|
||||
|
@ -114,7 +109,7 @@ static int read_leases(time_t now, FILE *leasestream)
|
|||
hw_len, hw_type, clid_len, now, 0);
|
||||
|
||||
if (strcmp(daemon->dhcp_buff, "*") != 0)
|
||||
lease_set_hostname(lease, daemon->dhcp_buff, 0, domain, NULL);
|
||||
lease_set_hostname(lease, daemon->dhcp_buff, 0, NULL, NULL);
|
||||
|
||||
ei = atol(daemon->dhcp_buff3);
|
||||
|
||||
|
@ -946,6 +941,36 @@ static void kill_name(struct dhcp_lease *lease)
|
|||
lease->hostname = lease->fqdn = NULL;
|
||||
}
|
||||
|
||||
void lease_calc_fqdns(void)
|
||||
{
|
||||
struct dhcp_lease *lease;
|
||||
|
||||
for (lease = leases; lease; lease = lease->next)
|
||||
{
|
||||
char *domain;
|
||||
|
||||
if (lease->hostname)
|
||||
{
|
||||
#ifdef HAVE_DHCP6
|
||||
if (lease->flags & (LEASE_TA | LEASE_NA))
|
||||
domain = get_domain6(&lease->addr6);
|
||||
else
|
||||
#endif
|
||||
domain = get_domain(lease->addr);
|
||||
|
||||
if (domain)
|
||||
{
|
||||
/* This is called only during startup, before forking, hence safe_malloc() */
|
||||
lease->fqdn = safe_malloc(strlen(lease->hostname) + strlen(domain) + 2);
|
||||
|
||||
strcpy(lease->fqdn, lease->hostname);
|
||||
strcat(lease->fqdn, ".");
|
||||
strcat(lease->fqdn, domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lease_set_hostname(struct dhcp_lease *lease, const char *name, int auth, char *domain, char *config_domain)
|
||||
{
|
||||
struct dhcp_lease *lease_tmp;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -15,7 +15,11 @@
|
|||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
#include "../log.h"
|
||||
/******* Pi-hole modification *******/
|
||||
#include "log.h"
|
||||
#include "dnsmasq_interface.h"
|
||||
#include "main.h"
|
||||
/************************************/
|
||||
|
||||
#ifdef __ANDROID__
|
||||
# include <android/log.h>
|
||||
|
@ -507,6 +511,4 @@ void die(char *message, char *arg1, int exit_code)
|
|||
/********** Pi-hole modification *************/
|
||||
FTL_log_dnsmasq_fatal(message, arg1, errmess);
|
||||
/*********************************************/
|
||||
|
||||
exit(exit_code);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -39,6 +39,7 @@ const char * metric_names[] = {
|
|||
"leases_pruned_4",
|
||||
"leases_allocated_6",
|
||||
"leases_pruned_6",
|
||||
"tcp_connections",
|
||||
};
|
||||
|
||||
const char* get_metric_name(int i) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -38,6 +38,7 @@ enum {
|
|||
METRIC_LEASES_PRUNED_4,
|
||||
METRIC_LEASES_ALLOCATED_6,
|
||||
METRIC_LEASES_PRUNED_6,
|
||||
METRIC_TCP_CONNECTIONS,
|
||||
|
||||
__METRIC_MAX,
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -125,7 +125,10 @@ int iface_check(int family, union all_addr *addr, char *name, int *auth)
|
|||
|
||||
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, name))
|
||||
ret = tmp->used = 1;
|
||||
{
|
||||
tmp->flags |= INAME_USED;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (addr)
|
||||
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
||||
|
@ -133,11 +136,17 @@ int iface_check(int family, union all_addr *addr, char *name, int *auth)
|
|||
{
|
||||
if (family == AF_INET &&
|
||||
tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
|
||||
ret = match_addr = tmp->used = 1;
|
||||
{
|
||||
tmp->flags |= INAME_USED;
|
||||
ret = match_addr = 1;
|
||||
}
|
||||
else if (family == AF_INET6 &&
|
||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
|
||||
&addr->addr6))
|
||||
ret = match_addr = tmp->used = 1;
|
||||
{
|
||||
tmp->flags |= INAME_USED;
|
||||
ret = match_addr = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,7 +246,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||
int loopback;
|
||||
struct ifreq ifr;
|
||||
int tftp_ok = !!option_bool(OPT_TFTP);
|
||||
int dhcp_ok = 1;
|
||||
int dhcp4_ok = 1;
|
||||
int dhcp6_ok = 1;
|
||||
int auth_dns = 0;
|
||||
int is_label = 0;
|
||||
#if defined(HAVE_DHCP) || defined(HAVE_TFTP)
|
||||
|
@ -253,7 +263,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||
loopback = ifr.ifr_flags & IFF_LOOPBACK;
|
||||
|
||||
if (loopback)
|
||||
dhcp_ok = 0;
|
||||
dhcp4_ok = dhcp6_ok = 0;
|
||||
|
||||
if (!label)
|
||||
label = ifr.ifr_name;
|
||||
|
@ -503,7 +513,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||
if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
|
||||
{
|
||||
strcpy(lo->name, ifr.ifr_name);
|
||||
lo->used = 1;
|
||||
lo->flags |= INAME_USED;
|
||||
lo->next = daemon->if_names;
|
||||
daemon->if_names = lo;
|
||||
}
|
||||
|
@ -525,14 +535,17 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||
if (auth_dns)
|
||||
{
|
||||
tftp_ok = 0;
|
||||
dhcp_ok = 0;
|
||||
dhcp4_ok = dhcp6_ok = 0;
|
||||
}
|
||||
else
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
{
|
||||
tftp_ok = 0;
|
||||
dhcp_ok = 0;
|
||||
if (tmp->flags & INAME_4)
|
||||
dhcp4_ok = 0;
|
||||
if (tmp->flags & INAME_6)
|
||||
dhcp6_ok = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -559,7 +572,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||
iface->addr = *addr;
|
||||
iface->netmask = netmask;
|
||||
iface->tftp_ok = tftp_ok;
|
||||
iface->dhcp_ok = dhcp_ok;
|
||||
iface->dhcp4_ok = dhcp4_ok;
|
||||
iface->dhcp6_ok = dhcp6_ok;
|
||||
iface->dns_auth = auth_dns;
|
||||
iface->mtu = mtu;
|
||||
iface->dad = !!(iface_flags & IFACE_TENTATIVE);
|
||||
|
@ -699,8 +713,7 @@ static int release_listener(struct listener *l)
|
|||
/* In case it ever returns */
|
||||
l->iface->done = 0;
|
||||
// Pi-hole modification
|
||||
logg("stopped listening on %s(#%d): %s port %d",
|
||||
l->iface->name, l->iface->index, daemon->addrbuff, port);
|
||||
logg("stopped listening on %s(#%d): %s port %d", l->iface->name, l->iface->index, daemon->addrbuff, port);
|
||||
}
|
||||
|
||||
if (l->fd != -1)
|
||||
|
@ -915,15 +928,24 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
|
|||
|
||||
errno = errsave;
|
||||
|
||||
if (dienow)
|
||||
/* Failure to bind addresses given by --listen-address at this point
|
||||
because there's no interface with the address is OK if we're doing bind-dynamic.
|
||||
If/when an interface is created with the relevant address we'll notice
|
||||
and attempt to bind it then. This is in the generic error path so we close the socket,
|
||||
but EADDRNOTAVAIL is only a possible error from bind()
|
||||
|
||||
When a new address is created and we call this code again (dienow == 0) there
|
||||
may still be configured addresses when don't exist, (consider >1 --listen-address,
|
||||
when the first is created, the second will still be missing) so we suppress
|
||||
EADDRNOTAVAIL even in that case to avoid confusing log entries.
|
||||
*/
|
||||
if (!option_bool(OPT_CLEVERBIND) || errno != EADDRNOTAVAIL)
|
||||
{
|
||||
/* failure to bind addresses given by --listen-address at this point
|
||||
is OK if we're doing bind-dynamic */
|
||||
if (!option_bool(OPT_CLEVERBIND))
|
||||
if (dienow)
|
||||
die(s, daemon->addrbuff, EC_BADNET);
|
||||
else
|
||||
my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
|
||||
}
|
||||
else
|
||||
my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -1199,7 +1221,7 @@ void create_bound_listeners(int dienow)
|
|||
// Pi-hole modification
|
||||
const int port = prettyprint_addr(&iface->addr, daemon->addrbuff);
|
||||
logg("listening on %s(#%d): %s port %d",
|
||||
iface->name, iface->index, daemon->addrbuff, port);
|
||||
iface->name, iface->index, daemon->addrbuff, port);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1215,7 +1237,7 @@ void create_bound_listeners(int dienow)
|
|||
(no netmask) and some MTU login the tftp code. */
|
||||
|
||||
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
|
||||
if (!if_tmp->used &&
|
||||
if (!(if_tmp->flags & INAME_USED) &&
|
||||
(new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
|
||||
{
|
||||
new->next = daemon->listeners;
|
||||
|
@ -1227,7 +1249,7 @@ void create_bound_listeners(int dienow)
|
|||
my_syslog(LOG_DEBUG|MS_DEBUG, _("listening on %s port %d"), daemon->addrbuff, port);
|
||||
}
|
||||
// Pi-hole modification
|
||||
const int port = prettyprint_addr(&if_tmp->addr, daemon->addrbuff);
|
||||
const int port = prettyprint_addr(&if_tmp->addr, daemon->addrbuff);
|
||||
logg("listening on %s port %d", daemon->addrbuff, port);
|
||||
}
|
||||
}
|
||||
|
@ -1306,7 +1328,7 @@ void join_multicast(int dienow)
|
|||
struct irec *iface, *tmp;
|
||||
|
||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||
if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
|
||||
if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp6_ok && !iface->multicast_done)
|
||||
{
|
||||
/* There's an irec per address but we only want to join for multicast
|
||||
once per interface. Weed out duplicates. */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -43,7 +43,8 @@ int add_to_nftset(const char *setname, const union all_addr *ipaddr, int flags,
|
|||
const char *cmd = remove ? cmd_del : cmd_add;
|
||||
int ret, af = (flags & F_IPV4) ? AF_INET : AF_INET6;
|
||||
size_t new_sz;
|
||||
char *new, *err, *nl;
|
||||
char *err_str, *new, *nl;
|
||||
const char *err;
|
||||
static char *cmd_buf = NULL;
|
||||
static size_t cmd_buf_sz = 0;
|
||||
|
||||
|
@ -78,14 +79,19 @@ int add_to_nftset(const char *setname, const union all_addr *ipaddr, int flags,
|
|||
}
|
||||
|
||||
ret = nft_run_cmd_from_buffer(ctx, cmd_buf);
|
||||
err = (char *)nft_ctx_get_error_buffer(ctx);
|
||||
err = nft_ctx_get_error_buffer(ctx);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
/* Log only first line of error return. */
|
||||
if ((nl = strchr(err, '\n')))
|
||||
*nl = 0;
|
||||
my_syslog(LOG_ERR, "nftset %s %s", setname, err);
|
||||
if ((err_str = whine_malloc(strlen(err) + 1)))
|
||||
{
|
||||
strcpy(err_str, err);
|
||||
if ((nl = strchr(err_str, '\n')))
|
||||
*nl = 0;
|
||||
my_syslog(LOG_ERR, "nftset %s %s", setname, err_str);
|
||||
free(err_str);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -190,6 +190,11 @@ struct myoption {
|
|||
#define LOPT_STALE_CACHE 377
|
||||
#define LOPT_NORR 378
|
||||
#define LOPT_NO_IDENT 379
|
||||
#define LOPT_CACHE_RR 380
|
||||
#define LOPT_FILTER_RR 381
|
||||
#define LOPT_NO_DHCP6 382
|
||||
#define LOPT_NO_DHCP4 383
|
||||
#define LOPT_MAX_PROCS 384
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static const struct option opts[] =
|
||||
|
@ -221,7 +226,7 @@ static const struct myoption opts[] =
|
|||
{ "domain-suffix", 1, 0, 's' },
|
||||
{ "interface", 1, 0, 'i' },
|
||||
{ "listen-address", 1, 0, 'a' },
|
||||
{ "local-service", 0, 0, LOPT_LOCAL_SERVICE },
|
||||
{ "local-service", 2, 0, LOPT_LOCAL_SERVICE },
|
||||
{ "bogus-priv", 0, 0, 'b' },
|
||||
{ "bogus-nxdomain", 1, 0, 'B' },
|
||||
{ "ignore-address", 1, 0, LOPT_IGNORE_ADDR },
|
||||
|
@ -229,6 +234,7 @@ static const struct myoption opts[] =
|
|||
{ "filterwin2k", 0, 0, 'f' },
|
||||
{ "filter-A", 0, 0, LOPT_FILTER_A },
|
||||
{ "filter-AAAA", 0, 0, LOPT_FILTER_AAAA },
|
||||
{ "filter-rr", 1, 0, LOPT_FILTER_RR },
|
||||
{ "pid-file", 2, 0, 'x' },
|
||||
{ "strict-order", 0, 0, 'o' },
|
||||
{ "server", 1, 0, 'S' },
|
||||
|
@ -243,11 +249,14 @@ static const struct myoption opts[] =
|
|||
{ "local-ttl", 1, 0, 'T' },
|
||||
{ "no-negcache", 0, 0, 'N' },
|
||||
{ "no-round-robin", 0, 0, LOPT_NORR },
|
||||
{ "cache-rr", 1, 0, LOPT_CACHE_RR },
|
||||
{ "addn-hosts", 1, 0, 'H' },
|
||||
{ "hostsdir", 1, 0, LOPT_HOST_INOTIFY },
|
||||
{ "query-port", 1, 0, 'Q' },
|
||||
{ "except-interface", 1, 0, 'I' },
|
||||
{ "no-dhcp-interface", 1, 0, '2' },
|
||||
{ "no-dhcpv4-interface", 1, 0, LOPT_NO_DHCP4 },
|
||||
{ "no-dhcpv6-interface", 1, 0, LOPT_NO_DHCP6 },
|
||||
{ "domain-needed", 0, 0, 'D' },
|
||||
{ "dhcp-lease-max", 1, 0, 'X' },
|
||||
{ "bind-interfaces", 0, 0, 'z' },
|
||||
|
@ -380,6 +389,7 @@ static const struct myoption opts[] =
|
|||
{ "fast-dns-retry", 2, 0, LOPT_FAST_RETRY },
|
||||
{ "use-stale-cache", 2, 0 , LOPT_STALE_CACHE },
|
||||
{ "no-ident", 0, 0, LOPT_NO_IDENT },
|
||||
{ "max-tcp-connections", 1, 0, LOPT_MAX_PROCS },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
@ -407,8 +417,9 @@ 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 },
|
||||
{ LOPT_FILTER_A, ARG_DUP, NULL, gettext_noop("Don't include IPv4 addresses in DNS answers."), NULL },
|
||||
{ LOPT_FILTER_AAAA, ARG_DUP, NULL, gettext_noop("Don't include IPv6 addresses in DNS answers."), NULL },
|
||||
{ LOPT_FILTER_RR, ARG_DUP, "<RR-type>", gettext_noop("Don't include resource records of the given type 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 },
|
||||
|
@ -477,6 +488,8 @@ static struct {
|
|||
{ '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
|
||||
{ LOPT_UBUS, ARG_ONE, "[=<busname>]", gettext_noop("Enable the UBus interface."), NULL },
|
||||
{ '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
|
||||
{ LOPT_NO_DHCP6, ARG_DUP, "<interface>", gettext_noop("Do not provide DHCPv6 on this interface."), NULL },
|
||||
{ LOPT_NO_DHCP4, ARG_DUP, "<interface>", gettext_noop("Do not provide DHCPv4 on this interface."), NULL },
|
||||
{ '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
|
||||
{ '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
|
||||
{ LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
|
||||
|
@ -564,19 +577,21 @@ static struct {
|
|||
{ LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log routine DHCPv6."), NULL },
|
||||
{ LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
|
||||
{ LOPT_LOG_DEBUG, OPT_LOG_DEBUG, NULL, gettext_noop("Log debugging information."), NULL },
|
||||
{ LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, gettext_noop("Accept queries only from directly-connected networks."), NULL },
|
||||
{ LOPT_LOCAL_SERVICE, ARG_ONE, NULL, gettext_noop("Accept queries only from directly-connected networks."), NULL },
|
||||
{ LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Detect and remove DNS forwarding loops."), NULL },
|
||||
{ LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>", gettext_noop("Ignore DNS responses containing ipaddr."), NULL },
|
||||
{ LOPT_DHCPTTL, ARG_ONE, "<ttl>", gettext_noop("Set TTL in DNS responses with DHCP-derived addresses."), NULL },
|
||||
{ LOPT_REPLY_DELAY, ARG_ONE, "<integer>", gettext_noop("Delay DHCP replies for at least number of seconds."), NULL },
|
||||
{ LOPT_RAPID_COMMIT, OPT_RAPID_COMMIT, NULL, gettext_noop("Enables DHCPv4 Rapid Commit option."), NULL },
|
||||
{ LOPT_DUMPFILE, ARG_ONE, "<path>", gettext_noop("Path to debug packet dump file"), NULL },
|
||||
{ LOPT_DUMPMASK, ARG_ONE, "<hex>", gettext_noop("Mask which packets to dump"), NULL },
|
||||
{ LOPT_DUMPFILE, ARG_ONE, "<path>", gettext_noop("Path to debug packet dump file."), NULL },
|
||||
{ LOPT_DUMPMASK, ARG_ONE, "<hex>", gettext_noop("Mask which packets to dump."), NULL },
|
||||
{ LOPT_SCRIPT_TIME, OPT_LEASE_RENEW, NULL, gettext_noop("Call dhcp-script when lease expiry changes."), NULL },
|
||||
{ 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 },
|
||||
{ LOPT_CACHE_RR, ARG_DUP, "<RR-type>", gettext_noop("Cache this DNS resource record type."), NULL },
|
||||
{ LOPT_MAX_PROCS, ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent tcp connections."), NULL },
|
||||
{ 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -1271,6 +1286,17 @@ static char *domain_rev6(int from_file, char *server, struct in6_addr *addr6, in
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void if_names_add(const char *ifname)
|
||||
{
|
||||
struct iname *new = opt_malloc(sizeof(struct iname));
|
||||
new->next = daemon->if_names;
|
||||
daemon->if_names = new;
|
||||
/* new->name may be NULL if someone does
|
||||
"interface=" to disable all interfaces except loop. */
|
||||
new->name = opt_string_alloc(ifname);
|
||||
new->flags = 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
|
||||
static int is_tag_prefix(char *arg)
|
||||
|
@ -1400,7 +1426,6 @@ static void dhcp_opt_free(struct dhcp_opt *opt)
|
|||
free(opt);
|
||||
}
|
||||
|
||||
|
||||
/* This is too insanely large to keep in-line in the switch */
|
||||
static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
||||
{
|
||||
|
@ -2566,179 +2591,182 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||
|
||||
case 's': /* --domain */
|
||||
case LOPT_SYNTH: /* --synth-domain */
|
||||
if (strcmp (arg, "#") == 0)
|
||||
set_option_bool(OPT_RESOLV_DOMAIN);
|
||||
else
|
||||
{
|
||||
char *d, *d_raw = arg;
|
||||
comma = split(arg);
|
||||
if (!(d = canonicalise_opt(d_raw)))
|
||||
ret_err(gen_err);
|
||||
else
|
||||
{
|
||||
free(d); /* allocate this again below. */
|
||||
if (comma)
|
||||
{
|
||||
struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
|
||||
char *netpart;
|
||||
|
||||
new->prefix = NULL;
|
||||
new->indexed = 0;
|
||||
new->prefixlen = 0;
|
||||
|
||||
unhide_metas(comma);
|
||||
if ((netpart = split_chr(comma, '/')))
|
||||
{
|
||||
int msize;
|
||||
|
||||
arg = split(netpart);
|
||||
if (!atoi_check(netpart, &msize))
|
||||
ret_err_free(gen_err, new);
|
||||
else if (inet_pton(AF_INET, comma, &new->start))
|
||||
{
|
||||
int mask;
|
||||
|
||||
if (msize > 32)
|
||||
ret_err_free(_("bad prefix length"), new);
|
||||
{
|
||||
char *d, *d_raw = arg;
|
||||
comma = split(arg);
|
||||
if (!(d = canonicalise_opt(d_raw)))
|
||||
ret_err(gen_err);
|
||||
else
|
||||
{
|
||||
free(d); /* allocate this again below. */
|
||||
if (comma)
|
||||
{
|
||||
struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
|
||||
char *netpart;
|
||||
|
||||
new->prefix = NULL;
|
||||
new->indexed = 0;
|
||||
new->prefixlen = 0;
|
||||
|
||||
unhide_metas(comma);
|
||||
if ((netpart = split_chr(comma, '/')))
|
||||
{
|
||||
int msize;
|
||||
|
||||
arg = split(netpart);
|
||||
if (!atoi_check(netpart, &msize))
|
||||
ret_err_free(gen_err, new);
|
||||
else if (inet_pton(AF_INET, comma, &new->start))
|
||||
{
|
||||
int mask;
|
||||
|
||||
if (msize > 32)
|
||||
ret_err_free(_("bad prefix length"), new);
|
||||
|
||||
mask = (1 << (32 - msize)) - 1;
|
||||
new->is6 = 0;
|
||||
new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
|
||||
new->end.s_addr = new->start.s_addr | htonl(mask);
|
||||
if (arg)
|
||||
{
|
||||
if (option != 's')
|
||||
{
|
||||
if (!(new->prefix = canonicalise_opt(arg)) ||
|
||||
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
|
||||
ret_err_free(_("bad prefix"), new);
|
||||
}
|
||||
else if (strcmp(arg, "local") != 0)
|
||||
ret_err_free(gen_err, new);
|
||||
else
|
||||
{
|
||||
/* local=/xxx.yyy.zzz.in-addr.arpa/ */
|
||||
domain_rev4(0, NULL, &new->start, msize);
|
||||
|
||||
/* local=/<domain>/ */
|
||||
/* d_raw can't failed to canonicalise here, checked above. */
|
||||
add_update_server(SERV_LITERAL_ADDRESS, NULL, NULL, NULL, d_raw, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (inet_pton(AF_INET6, comma, &new->start6))
|
||||
{
|
||||
u64 mask, addrpart = addr6part(&new->start6);
|
||||
|
||||
if (msize > 128)
|
||||
ret_err_free(_("bad prefix length"), new);
|
||||
|
||||
mask = (1LLU << (128 - msize)) - 1LLU;
|
||||
|
||||
new->is6 = 1;
|
||||
new->prefixlen = msize;
|
||||
|
||||
/* prefix==64 overflows the mask calculation above */
|
||||
if (msize <= 64)
|
||||
mask = (u64)-1LL;
|
||||
|
||||
mask = (1 << (32 - msize)) - 1;
|
||||
new->is6 = 0;
|
||||
new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
|
||||
new->end.s_addr = new->start.s_addr | htonl(mask);
|
||||
if (arg)
|
||||
{
|
||||
if (option != 's')
|
||||
{
|
||||
if (!(new->prefix = canonicalise_opt(arg)) ||
|
||||
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
|
||||
ret_err_free(_("bad prefix"), new);
|
||||
}
|
||||
else if (strcmp(arg, "local") != 0)
|
||||
ret_err_free(gen_err, new);
|
||||
else
|
||||
{
|
||||
/* local=/xxx.yyy.zzz.in-addr.arpa/ */
|
||||
domain_rev4(0, NULL, &new->start, msize);
|
||||
|
||||
/* local=/<domain>/ */
|
||||
/* d_raw can't failed to canonicalise here, checked above. */
|
||||
add_update_server(SERV_LITERAL_ADDRESS, NULL, NULL, NULL, d_raw, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (inet_pton(AF_INET6, comma, &new->start6))
|
||||
{
|
||||
u64 mask, addrpart = addr6part(&new->start6);
|
||||
|
||||
if (msize > 128)
|
||||
ret_err_free(_("bad prefix length"), new);
|
||||
|
||||
mask = (1LLU << (128 - msize)) - 1LLU;
|
||||
|
||||
new->is6 = 1;
|
||||
new->prefixlen = msize;
|
||||
|
||||
/* prefix==64 overflows the mask calculation above */
|
||||
if (msize <= 64)
|
||||
mask = (u64)-1LL;
|
||||
|
||||
new->end6 = new->start6;
|
||||
setaddr6part(&new->start6, addrpart & ~mask);
|
||||
setaddr6part(&new->end6, addrpart | mask);
|
||||
|
||||
if (arg)
|
||||
{
|
||||
if (option != 's')
|
||||
{
|
||||
if (!(new->prefix = canonicalise_opt(arg)) ||
|
||||
strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
|
||||
ret_err_free(_("bad prefix"), new);
|
||||
}
|
||||
else if (strcmp(arg, "local") != 0)
|
||||
ret_err_free(gen_err, new);
|
||||
else
|
||||
{
|
||||
/* generate the equivalent of
|
||||
local=/xxx.yyy.zzz.ip6.arpa/ */
|
||||
domain_rev6(0, NULL, &new->start6, msize);
|
||||
|
||||
/* local=/<domain>/ */
|
||||
/* d_raw can't failed to canonicalise here, checked above. */
|
||||
add_update_server(SERV_LITERAL_ADDRESS, NULL, NULL, NULL, d_raw, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
ret_err_free(gen_err, new);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *prefstr;
|
||||
arg = split(comma);
|
||||
prefstr = split(arg);
|
||||
|
||||
if (inet_pton(AF_INET, comma, &new->start))
|
||||
{
|
||||
new->is6 = 0;
|
||||
if (!arg)
|
||||
new->end.s_addr = new->start.s_addr;
|
||||
else if (!inet_pton(AF_INET, arg, &new->end))
|
||||
ret_err_free(gen_err, new);
|
||||
}
|
||||
else if (inet_pton(AF_INET6, comma, &new->start6))
|
||||
{
|
||||
new->is6 = 1;
|
||||
if (!arg)
|
||||
memcpy(&new->end6, &new->start6, IN6ADDRSZ);
|
||||
else if (!inet_pton(AF_INET6, arg, &new->end6))
|
||||
ret_err_free(gen_err, new);
|
||||
}
|
||||
else if (option == 's')
|
||||
{
|
||||
/* subnet from interface. */
|
||||
new->interface = opt_string_alloc(comma);
|
||||
new->al = NULL;
|
||||
}
|
||||
else
|
||||
ret_err_free(gen_err, new);
|
||||
|
||||
if (option != 's' && prefstr)
|
||||
{
|
||||
if (!(new->prefix = canonicalise_opt(prefstr)) ||
|
||||
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
|
||||
ret_err_free(_("bad prefix"), new);
|
||||
}
|
||||
}
|
||||
|
||||
new->domain = canonicalise_opt(d_raw);
|
||||
if (option == 's')
|
||||
{
|
||||
new->next = daemon->cond_domain;
|
||||
daemon->cond_domain = new;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *star;
|
||||
if (new->prefix &&
|
||||
(star = strrchr(new->prefix, '*'))
|
||||
&& *(star+1) == 0)
|
||||
{
|
||||
*star = 0;
|
||||
new->indexed = 1;
|
||||
if (new->is6 && new->prefixlen < 64)
|
||||
ret_err_free(_("prefix length too small"), new);
|
||||
}
|
||||
new->next = daemon->synth_domains;
|
||||
daemon->synth_domains = new;
|
||||
}
|
||||
}
|
||||
else if (option == 's')
|
||||
daemon->domain_suffix = canonicalise_opt(d_raw);
|
||||
else
|
||||
ret_err(gen_err);
|
||||
}
|
||||
}
|
||||
break;
|
||||
new->end6 = new->start6;
|
||||
setaddr6part(&new->start6, addrpart & ~mask);
|
||||
setaddr6part(&new->end6, addrpart | mask);
|
||||
|
||||
if (arg)
|
||||
{
|
||||
if (option != 's')
|
||||
{
|
||||
if (!(new->prefix = canonicalise_opt(arg)) ||
|
||||
strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
|
||||
ret_err_free(_("bad prefix"), new);
|
||||
}
|
||||
else if (strcmp(arg, "local") != 0)
|
||||
ret_err_free(gen_err, new);
|
||||
else
|
||||
{
|
||||
/* generate the equivalent of
|
||||
local=/xxx.yyy.zzz.ip6.arpa/ */
|
||||
domain_rev6(0, NULL, &new->start6, msize);
|
||||
|
||||
/* local=/<domain>/ */
|
||||
/* d_raw can't failed to canonicalise here, checked above. */
|
||||
add_update_server(SERV_LITERAL_ADDRESS, NULL, NULL, NULL, d_raw, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
ret_err_free(gen_err, new);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *prefstr;
|
||||
arg = split(comma);
|
||||
prefstr = split(arg);
|
||||
|
||||
if (inet_pton(AF_INET, comma, &new->start))
|
||||
{
|
||||
new->is6 = 0;
|
||||
if (!arg)
|
||||
new->end.s_addr = new->start.s_addr;
|
||||
else if (!inet_pton(AF_INET, arg, &new->end))
|
||||
ret_err_free(gen_err, new);
|
||||
}
|
||||
else if (inet_pton(AF_INET6, comma, &new->start6))
|
||||
{
|
||||
new->is6 = 1;
|
||||
if (!arg)
|
||||
memcpy(&new->end6, &new->start6, IN6ADDRSZ);
|
||||
else if (!inet_pton(AF_INET6, arg, &new->end6))
|
||||
ret_err_free(gen_err, new);
|
||||
}
|
||||
else if (option == 's')
|
||||
{
|
||||
/* subnet from interface. */
|
||||
new->interface = opt_string_alloc(comma);
|
||||
new->al = NULL;
|
||||
}
|
||||
else
|
||||
ret_err_free(gen_err, new);
|
||||
|
||||
if (option != 's' && prefstr)
|
||||
{
|
||||
if (!(new->prefix = canonicalise_opt(prefstr)) ||
|
||||
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
|
||||
ret_err_free(_("bad prefix"), new);
|
||||
}
|
||||
}
|
||||
|
||||
new->domain = canonicalise_opt(d_raw);
|
||||
if (option == 's')
|
||||
{
|
||||
new->next = daemon->cond_domain;
|
||||
daemon->cond_domain = new;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *star;
|
||||
if (new->prefix &&
|
||||
(star = strrchr(new->prefix, '*'))
|
||||
&& *(star+1) == 0)
|
||||
{
|
||||
*star = 0;
|
||||
new->indexed = 1;
|
||||
if (new->is6 && new->prefixlen < 64)
|
||||
ret_err_free(_("prefix length too small"), new);
|
||||
}
|
||||
new->next = daemon->synth_domains;
|
||||
daemon->synth_domains = new;
|
||||
}
|
||||
}
|
||||
else if (option == 's')
|
||||
{
|
||||
if (strcmp (arg, "#") == 0)
|
||||
set_option_bool(OPT_RESOLV_DOMAIN);
|
||||
else
|
||||
daemon->domain_suffix = canonicalise_opt(d_raw);
|
||||
}
|
||||
else
|
||||
ret_err(gen_err);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case LOPT_CPE_ID: /* --add-dns-client */
|
||||
if (arg)
|
||||
|
@ -2821,14 +2849,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||
|
||||
case 'i': /* --interface */
|
||||
do {
|
||||
struct iname *new = opt_malloc(sizeof(struct iname));
|
||||
comma = split(arg);
|
||||
new->next = daemon->if_names;
|
||||
daemon->if_names = new;
|
||||
/* new->name may be NULL if someone does
|
||||
"interface=" to disable all interfaces except loop. */
|
||||
new->name = opt_string_alloc(arg);
|
||||
new->used = 0;
|
||||
comma = split(arg);
|
||||
if_names_add(arg);
|
||||
arg = comma;
|
||||
} while (arg);
|
||||
break;
|
||||
|
@ -2841,10 +2863,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||
|
||||
case 'I': /* --except-interface */
|
||||
case '2': /* --no-dhcp-interface */
|
||||
case LOPT_NO_DHCP6: /* --no-dhcpv6-interface */
|
||||
case LOPT_NO_DHCP4: /* --no-dhcpv4-interface */
|
||||
do {
|
||||
struct iname *new = opt_malloc(sizeof(struct iname));
|
||||
comma = split(arg);
|
||||
new->name = opt_string_alloc(arg);
|
||||
new->flags = INAME_4 | INAME_6;
|
||||
if (option == 'I')
|
||||
{
|
||||
new->next = daemon->if_except;
|
||||
|
@ -2857,6 +2882,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||
}
|
||||
else
|
||||
{
|
||||
if (option == LOPT_NO_DHCP6)
|
||||
new->flags &= ~INAME_4;
|
||||
if (option == LOPT_NO_DHCP4)
|
||||
new->flags &= ~INAME_6;
|
||||
new->next = daemon->dhcp_except;
|
||||
daemon->dhcp_except = new;
|
||||
}
|
||||
|
@ -2938,7 +2967,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||
else
|
||||
ret_err_free(gen_err, new);
|
||||
|
||||
new->used = 0;
|
||||
new->flags = 0;
|
||||
if (option == 'a')
|
||||
{
|
||||
new->next = daemon->if_addrs;
|
||||
|
@ -3053,8 +3082,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||
else
|
||||
flags &= ~SERV_FOR_NODOTS;
|
||||
|
||||
/* address=/#/ matches the same as without domain */
|
||||
if (option == 'A' && cur_domain[0] == '#' && cur_domain[1] == 0)
|
||||
/* address=/#/ matches the same as without domain, as does server=/#/.... for consistency. */
|
||||
if (cur_domain[0] == '#' && cur_domain[1] == 0)
|
||||
cur_domain[0] = 0;
|
||||
}
|
||||
|
||||
|
@ -3387,6 +3416,15 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||
ret_err(gen_err);
|
||||
else if (daemon->max_logs > 100)
|
||||
daemon->max_logs = 100;
|
||||
break;
|
||||
|
||||
case LOPT_LOCAL_SERVICE: /* --local-service */
|
||||
if (!arg || !strcmp(arg, "net"))
|
||||
set_option_bool(OPT_LOCAL_SERVICE);
|
||||
else if (!strcmp(arg, "host"))
|
||||
set_option_bool(OPT_LOCALHOST_SERVICE);
|
||||
else
|
||||
ret_err(gen_err);
|
||||
break;
|
||||
|
||||
case 'P': /* --edns-packet-max */
|
||||
|
@ -3447,7 +3485,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||
break;
|
||||
}
|
||||
|
||||
case LOPT_FAST_RETRY:
|
||||
case LOPT_FAST_RETRY: /* --fast-dns-retry */
|
||||
daemon->fast_retry_timeout = TIMEOUT;
|
||||
|
||||
if (!arg)
|
||||
|
@ -3469,6 +3507,47 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LOPT_CACHE_RR: /* --cache-rr */
|
||||
case LOPT_FILTER_RR: /* --filter-rr */
|
||||
case LOPT_FILTER_A: /* --filter-A */
|
||||
case LOPT_FILTER_AAAA: /* --filter-AAAA */
|
||||
while (1) {
|
||||
int type;
|
||||
struct rrlist *new;
|
||||
|
||||
comma = NULL;
|
||||
|
||||
if (option == LOPT_FILTER_A)
|
||||
type = T_A;
|
||||
else if (option == LOPT_FILTER_AAAA)
|
||||
type = T_AAAA;
|
||||
else
|
||||
{
|
||||
comma = split(arg);
|
||||
if (!atoi_check(arg, &type) && (type = rrtype(arg)) == 0)
|
||||
ret_err(_("bad RR type"));
|
||||
}
|
||||
|
||||
new = opt_malloc(sizeof(struct rrlist));
|
||||
new->rr = type;
|
||||
|
||||
if (option == LOPT_CACHE_RR)
|
||||
{
|
||||
new->next = daemon->cache_rr;
|
||||
daemon->cache_rr = new;
|
||||
}
|
||||
else
|
||||
{
|
||||
new->next = daemon->filter_rr;
|
||||
daemon->filter_rr = new;
|
||||
}
|
||||
|
||||
if (!comma) break;
|
||||
arg = comma;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
case 'X': /* --dhcp-lease-max */
|
||||
|
@ -5164,7 +5243,7 @@ err:
|
|||
break;
|
||||
}
|
||||
|
||||
case LOPT_STALE_CACHE:
|
||||
case LOPT_STALE_CACHE: /* --use-stale-cache */
|
||||
{
|
||||
int max_expiry = STALE_CACHE_EXPIRY;
|
||||
if (arg)
|
||||
|
@ -5254,7 +5333,17 @@ err:
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
case LOPT_MAX_PROCS: /* --max-tcp-connections */
|
||||
{
|
||||
int max_procs;
|
||||
/* Don't accept numbers less than 1. */
|
||||
if (!atoi_check(arg, &max_procs) || max_procs < 1)
|
||||
ret_err(gen_err);
|
||||
daemon->max_procs = max_procs;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ret_err(_("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DNSSEC/DBus support)"));
|
||||
|
||||
|
@ -5675,11 +5764,11 @@ static void clear_dynamic_conf(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void clear_dynamic_opt(void)
|
||||
static void clear_dhcp_opt(struct dhcp_opt **dhcp_opts)
|
||||
{
|
||||
struct dhcp_opt *opts, *cp, **up;
|
||||
|
||||
for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
|
||||
for (up = dhcp_opts, opts = *dhcp_opts; opts; opts = cp)
|
||||
{
|
||||
cp = opts->next;
|
||||
|
||||
|
@ -5693,6 +5782,14 @@ static void clear_dynamic_opt(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void clear_dynamic_opt(void)
|
||||
{
|
||||
clear_dhcp_opt(&daemon->dhcp_opts);
|
||||
#ifdef HAVE_DHCP6
|
||||
clear_dhcp_opt(&daemon->dhcp_opts6);
|
||||
#endif
|
||||
}
|
||||
|
||||
void reread_dhcp(void)
|
||||
{
|
||||
struct hostsfile *hf;
|
||||
|
@ -5737,15 +5834,21 @@ 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);
|
||||
/* Note that both /000 and '.' are allowed within labels. These get
|
||||
represented in presentation format using NAME_ESCAPE as an escape
|
||||
character. In theory, if all the characters in a name were /000 or
|
||||
'.' or NAME_ESCAPE then all would have to be escaped, so the
|
||||
presentation format would be twice as long as the spec. */
|
||||
char *buff = opt_malloc((MAXDNAME * 2) + 1);
|
||||
int option, testmode = 0;
|
||||
char *arg, *conffile = NULL;
|
||||
|
||||
|
||||
opterr = 0;
|
||||
|
||||
daemon = opt_malloc(sizeof(struct daemon));
|
||||
memset(daemon, 0, sizeof(struct daemon));
|
||||
daemon->namebuff = buff;
|
||||
daemon->workspacename = safe_malloc((MAXDNAME * 2) + 1);
|
||||
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
|
||||
|
||||
/* Set defaults - everything else is zero or NULL */
|
||||
|
@ -5769,6 +5872,8 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||
daemon->soa_expiry = SOA_EXPIRY;
|
||||
daemon->randport_limit = 1;
|
||||
daemon->host_index = SRC_AH;
|
||||
daemon->max_procs = MAX_PROCS;
|
||||
daemon->max_procs_used = 0;
|
||||
|
||||
/* See comment above make_servers(). Optimises server-read code. */
|
||||
mark_servers(0);
|
||||
|
@ -5884,8 +5989,10 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||
#endif
|
||||
add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
|
||||
/* Pi-hole modification */
|
||||
add_txt("privacylevel.pihole", NULL, TXT_PRIVACYLEVEL);
|
||||
add_txt("version.FTL", (char*)get_FTL_version(), 0 );
|
||||
add_txt("version.ftl", (char*)get_FTL_version(), 0 );
|
||||
add_txt("api.ftl", NULL, TXT_API_DOMAIN);
|
||||
add_txt("domain.api.ftl", NULL, TXT_API_DOMAIN);
|
||||
add_txt("local.api.ftl", NULL, TXT_API_LOCAL);
|
||||
/************************/
|
||||
}
|
||||
#endif
|
||||
|
@ -6070,7 +6177,16 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||
/* If there's access-control config, then ignore --local-service, it's intended
|
||||
as a system default to keep otherwise unconfigured installations safe. */
|
||||
if (daemon->if_names || daemon->if_except || daemon->if_addrs || daemon->authserver)
|
||||
reset_option_bool(OPT_LOCAL_SERVICE);
|
||||
{
|
||||
reset_option_bool(OPT_LOCAL_SERVICE);
|
||||
reset_option_bool(OPT_LOCALHOST_SERVICE);
|
||||
}
|
||||
else if (option_bool(OPT_LOCALHOST_SERVICE) && !option_bool(OPT_LOCAL_SERVICE))
|
||||
{
|
||||
/* listen only on localhost, emulate --interface=lo --bind-interfaces */
|
||||
if_names_add(NULL);
|
||||
set_option_bool(OPT_NOWILD);
|
||||
}
|
||||
|
||||
if (testmode)
|
||||
{
|
||||
|
@ -6078,3 +6194,13 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/******************** Pi-hole extension ********************/
|
||||
void reset_usage_indicator(void)
|
||||
{
|
||||
for (unsigned int i = 0; usage[i].opt != 0; i++)
|
||||
if(usage[i].rept == ARG_USED_CL ||
|
||||
usage[i].rept == ARG_USED_FILE)
|
||||
usage[i].rept = ARG_ONE;
|
||||
}
|
||||
/**********************************************************/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -186,7 +186,8 @@ void icmp6_packet(time_t now)
|
|||
return;
|
||||
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, interface))
|
||||
if (tmp->name && (tmp->flags & INAME_6) &&
|
||||
wildcard_match(tmp->name, interface))
|
||||
return;
|
||||
|
||||
if (packet[1] != 0)
|
||||
|
@ -835,7 +836,8 @@ time_t periodic_ra(time_t now)
|
|||
{
|
||||
struct iname *tmp;
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, param.name))
|
||||
if (tmp->name && (tmp->flags & INAME_6) &&
|
||||
wildcard_match(tmp->name, param.name))
|
||||
break;
|
||||
if (!tmp)
|
||||
{
|
||||
|
@ -934,7 +936,8 @@ static int iface_search(struct in6_addr *local, int prefix,
|
|||
return 1;
|
||||
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, param->name))
|
||||
if (tmp->name && (tmp->flags & INAME_6) &&
|
||||
wildcard_match(tmp->name, param->name))
|
||||
return 1;
|
||||
|
||||
for (context = daemon->dhcp6; context; context = context->next)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -77,7 +77,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||
struct dhcp_vendor *vendor;
|
||||
struct dhcp_mac *mac;
|
||||
struct dhcp_netid_list *id_list;
|
||||
int clid_len = 0, ignore = 0, do_classes = 0, rapid_commit = 0, selecting = 0, pxearch = -1;
|
||||
int clid_len = 0, ignore = 0, do_classes = 0, rapidCommit = 0, selecting = 0, pxearch = -1;
|
||||
const char *pxevendor = NULL;
|
||||
struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
|
||||
unsigned char *end = (unsigned char *)(mess + 1);
|
||||
|
@ -1157,14 +1157,14 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||
|
||||
if (option_bool(OPT_RAPID_COMMIT) && option_find(mess, sz, OPTION_RAPID_COMMIT, 0))
|
||||
{
|
||||
rapid_commit = 1;
|
||||
rapidCommit = 1;
|
||||
/* If a lease exists for this host and another address, squash it. */
|
||||
if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
|
||||
{
|
||||
lease_prune(lease, now);
|
||||
lease = NULL;
|
||||
}
|
||||
goto rapid_commit;
|
||||
goto rapidCommit;
|
||||
}
|
||||
|
||||
log_tags(tagif_netid, ntohl(mess->xid));
|
||||
|
@ -1285,7 +1285,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||
daemon->metrics[METRIC_DHCPREQUEST]++;
|
||||
log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
|
||||
|
||||
rapid_commit:
|
||||
rapidCommit:
|
||||
if (!message)
|
||||
{
|
||||
struct dhcp_config *addr_config;
|
||||
|
@ -1357,11 +1357,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||
|
||||
if (message)
|
||||
{
|
||||
daemon->metrics[rapid_commit ? METRIC_NOANSWER : METRIC_DHCPNAK]++;
|
||||
log_packet(rapid_commit ? "NOANSWER" : "DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
|
||||
daemon->metrics[rapidCommit ? METRIC_NOANSWER : METRIC_DHCPNAK]++;
|
||||
log_packet(rapidCommit ? "NOANSWER" : "DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
|
||||
|
||||
/* rapid commit case: lease allocate failed but don't send DHCPNAK */
|
||||
if (rapid_commit)
|
||||
if (rapidCommit)
|
||||
return 0;
|
||||
|
||||
mess->yiaddr.s_addr = 0;
|
||||
|
@ -1523,7 +1523,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
||||
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
||||
if (rapid_commit)
|
||||
if (rapidCommit)
|
||||
option_put(mess, end, OPTION_RAPID_COMMIT, 0, 0);
|
||||
do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
|
||||
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz, pxevendor);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -333,12 +333,29 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
|||
else if (msg_type != DHCP6IREQ)
|
||||
return 0;
|
||||
|
||||
/* server-id must match except for SOLICIT, CONFIRM and REBIND messages */
|
||||
if (msg_type != DHCP6SOLICIT && msg_type != DHCP6CONFIRM && msg_type != DHCP6IREQ && msg_type != DHCP6REBIND &&
|
||||
(!(opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1)) ||
|
||||
opt6_len(opt) != daemon->duid_len ||
|
||||
memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0))
|
||||
return 0;
|
||||
/* server-id must match except for SOLICIT, CONFIRM and REBIND messages, which MUST NOT
|
||||
have a server-id. 3315 para 15.x */
|
||||
opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1);
|
||||
|
||||
if (msg_type == DHCP6SOLICIT || msg_type == DHCP6CONFIRM || msg_type == DHCP6REBIND)
|
||||
{
|
||||
if (opt)
|
||||
return 0;
|
||||
}
|
||||
else if (msg_type == DHCP6IREQ)
|
||||
{
|
||||
/* If server-id provided, it must match. */
|
||||
if (opt && (opt6_len(opt) != daemon->duid_len ||
|
||||
memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Everything else MUST have a server-id that matches ours. */
|
||||
if (!opt || opt6_len(opt) != daemon->duid_len ||
|
||||
memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
o = new_opt6(OPTION6_SERVER_ID);
|
||||
put_opt6(daemon->duid, daemon->duid_len);
|
||||
|
@ -457,6 +474,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
|||
state->tags = &mac_opt->netid;
|
||||
}
|
||||
}
|
||||
else if (option_bool(OPT_LOG_OPTS))
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("%u cannot determine client MAC address"), state->xid);
|
||||
|
||||
if ((opt = opt6_find(state->packet_options, state->end, OPTION6_FQDN, 1)))
|
||||
{
|
||||
|
@ -1055,7 +1074,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
|||
|
||||
case DHCP6CONFIRM:
|
||||
{
|
||||
int good_addr = 0;
|
||||
int good_addr = 0, bad_addr = 0;
|
||||
|
||||
/* set reply message type */
|
||||
outmsgtype = DHCP6REPLY;
|
||||
|
@ -1077,32 +1096,35 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
|
|||
|
||||
if (!address6_valid(state->context, &req_addr, tagif, 1))
|
||||
{
|
||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||
put_opt6_short(DHCP6NOTONLINK);
|
||||
put_opt6_string(_("confirm failed"));
|
||||
end_opt6(o1);
|
||||
bad_addr = 1;
|
||||
log6_quiet(state, "DHCPREPLY", &req_addr, _("confirm failed"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
good_addr = 1;
|
||||
log6_quiet(state, "DHCPREPLY", &req_addr, state->hostname);
|
||||
else
|
||||
{
|
||||
good_addr = 1;
|
||||
log6_quiet(state, "DHCPREPLY", &req_addr, state->hostname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No addresses, no reply: RFC 3315 18.2.2 */
|
||||
if (!good_addr)
|
||||
if (!good_addr && !bad_addr)
|
||||
return 0;
|
||||
|
||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||
put_opt6_short(DHCP6SUCCESS );
|
||||
put_opt6_string(_("all addresses still on link"));
|
||||
put_opt6_short(bad_addr ? DHCP6NOTONLINK : DHCP6SUCCESS);
|
||||
put_opt6_string(bad_addr ? (_("confirm failed")) : (_("all addresses still on link")));
|
||||
end_opt6(o1);
|
||||
break;
|
||||
}
|
||||
|
||||
case DHCP6IREQ:
|
||||
{
|
||||
/* 3315 para 15.12 */
|
||||
if (opt6_find(state->packet_options, state->end, OPTION6_IA_NA, 1) ||
|
||||
opt6_find(state->packet_options, state->end, OPTION6_IA_TA, 1))
|
||||
return 0;
|
||||
|
||||
/* We can't discriminate contexts based on address, as we don't know it.
|
||||
If there is only one possible context, we can use its tags */
|
||||
if (state->context && state->context->netid.net && !state->context->current)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -136,9 +136,9 @@ static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, i
|
|||
|
||||
if (class == C_IN)
|
||||
{
|
||||
u16 *d;
|
||||
short *d;
|
||||
|
||||
for (pp = p, d = rrfilter_desc(type); *d != (u16)-1; d++)
|
||||
for (pp = p, d = rrfilter_desc(type); *d != -1; d++)
|
||||
{
|
||||
if (*d != 0)
|
||||
pp += *d;
|
||||
|
@ -156,41 +156,46 @@ static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, i
|
|||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
/* mode may be remove EDNS0 or DNSSEC RRs or remove A or AAAA from answer section.
|
||||
* returns number of modified records. */
|
||||
size_t rrfilter(struct dns_header *header, size_t *plen, int mode)
|
||||
{
|
||||
static unsigned char **rrs = NULL;
|
||||
static int rr_sz = 0;
|
||||
|
||||
unsigned char *p = (unsigned char *)(header+1);
|
||||
int i, rdlen, qtype, qclass, rr_found, chop_an, chop_ns, chop_ar;
|
||||
size_t rr_found = 0;
|
||||
int i, rdlen, qtype, qclass, chop_an, chop_ns, chop_ar;
|
||||
|
||||
if (mode == RRFILTER_CONF && !daemon->filter_rr)
|
||||
return 0;
|
||||
|
||||
if (ntohs(header->qdcount) != 1 ||
|
||||
!(p = skip_name(p, header, plen, 4)))
|
||||
return plen;
|
||||
!(p = skip_name(p, header, *plen, 4)))
|
||||
return 0;
|
||||
|
||||
GETSHORT(qtype, p);
|
||||
GETSHORT(qclass, p);
|
||||
|
||||
/* First pass, find pointers to start and end of all the records we wish to elide:
|
||||
records added for DNSSEC, unless explicitly queried for */
|
||||
for (rr_found = 0, chop_ns = 0, chop_an = 0, chop_ar = 0, i = 0;
|
||||
for (chop_ns = 0, chop_an = 0, chop_ar = 0, i = 0;
|
||||
i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount);
|
||||
i++)
|
||||
{
|
||||
unsigned char *pstart = p;
|
||||
int type, class;
|
||||
|
||||
if (!(p = skip_name(p, header, plen, 10)))
|
||||
return plen;
|
||||
if (!(p = skip_name(p, header, *plen, 10)))
|
||||
return rr_found;
|
||||
|
||||
GETSHORT(type, p);
|
||||
GETSHORT(class, p);
|
||||
p += 4; /* TTL */
|
||||
GETSHORT(rdlen, p);
|
||||
|
||||
if (!ADD_RDLEN(header, p, plen, rdlen))
|
||||
return plen;
|
||||
if (!ADD_RDLEN(header, p, *plen, rdlen))
|
||||
return rr_found;
|
||||
|
||||
if (mode == RRFILTER_EDNS0) /* EDNS */
|
||||
{
|
||||
|
@ -217,15 +222,12 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode)
|
|||
if (class != C_IN)
|
||||
continue;
|
||||
|
||||
if (mode == RRFILTER_A && type != T_A)
|
||||
continue;
|
||||
|
||||
if (mode == RRFILTER_AAAA && type != T_AAAA)
|
||||
if (!rr_on_list(daemon->filter_rr, type))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
|
||||
return plen;
|
||||
return rr_found;
|
||||
|
||||
rrs[rr_found++] = pstart;
|
||||
rrs[rr_found++] = p;
|
||||
|
@ -240,7 +242,7 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode)
|
|||
|
||||
/* Nothing to do. */
|
||||
if (rr_found == 0)
|
||||
return plen;
|
||||
return rr_found;
|
||||
|
||||
/* Second pass, look for pointers in names in the records we're keeping and make sure they don't
|
||||
point to records we're going to elide. This is theoretically possible, but unlikely. If
|
||||
|
@ -248,42 +250,42 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode)
|
|||
p = (unsigned char *)(header+1);
|
||||
|
||||
/* question first */
|
||||
if (!check_name(&p, header, plen, 0, rrs, rr_found))
|
||||
return plen;
|
||||
if (!check_name(&p, header, *plen, 0, rrs, rr_found))
|
||||
return rr_found;
|
||||
p += 4; /* qclass, qtype */
|
||||
|
||||
/* Now answers and NS */
|
||||
if (!check_rrs(p, header, plen, 0, rrs, rr_found))
|
||||
return plen;
|
||||
if (!check_rrs(p, header, *plen, 0, rrs, rr_found))
|
||||
return rr_found;
|
||||
|
||||
/* Third pass, actually fix up pointers in the records */
|
||||
p = (unsigned char *)(header+1);
|
||||
|
||||
check_name(&p, header, plen, 1, rrs, rr_found);
|
||||
check_name(&p, header, *plen, 1, rrs, rr_found);
|
||||
p += 4; /* qclass, qtype */
|
||||
|
||||
check_rrs(p, header, plen, 1, rrs, rr_found);
|
||||
check_rrs(p, header, *plen, 1, rrs, rr_found);
|
||||
|
||||
/* Fourth pass, elide records */
|
||||
for (p = rrs[0], i = 1; i < rr_found; i += 2)
|
||||
for (p = rrs[0], i = 1; (unsigned)i < rr_found; i += 2)
|
||||
{
|
||||
unsigned char *start = rrs[i];
|
||||
unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)header) + plen;
|
||||
unsigned char *end = ((unsigned)i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)header) + *plen;
|
||||
|
||||
memmove(p, start, end-start);
|
||||
p += end-start;
|
||||
}
|
||||
|
||||
plen = p - (unsigned char *)header;
|
||||
*plen = p - (unsigned char *)header;
|
||||
header->ancount = htons(ntohs(header->ancount) - chop_an);
|
||||
header->nscount = htons(ntohs(header->nscount) - chop_ns);
|
||||
header->arcount = htons(ntohs(header->arcount) - chop_ar);
|
||||
|
||||
return plen;
|
||||
return rr_found;
|
||||
}
|
||||
|
||||
/* This is used in the DNSSEC code too, hence it's exported */
|
||||
u16 *rrfilter_desc(int type)
|
||||
short *rrfilter_desc(int type)
|
||||
{
|
||||
/* List of RRtypes which include domains in the data.
|
||||
0 -> domain
|
||||
|
@ -294,7 +296,7 @@ u16 *rrfilter_desc(int type)
|
|||
anything which needs no mangling.
|
||||
*/
|
||||
|
||||
static u16 rr_desc[] =
|
||||
static short rr_desc[] =
|
||||
{
|
||||
T_NS, 0, -1,
|
||||
T_MD, 0, -1,
|
||||
|
@ -319,10 +321,10 @@ u16 *rrfilter_desc(int type)
|
|||
0, -1 /* wildcard/catchall */
|
||||
};
|
||||
|
||||
u16 *p = rr_desc;
|
||||
short *p = rr_desc;
|
||||
|
||||
while (*p != type && *p != 0)
|
||||
while (*p++ != (u16)-1);
|
||||
while (*p++ != -1);
|
||||
|
||||
return p+1;
|
||||
}
|
||||
|
@ -350,3 +352,78 @@ int expand_workspace(unsigned char ***wkspc, int *szp, int new)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Convert from presentation format to wire format, in place.
|
||||
Also map UC -> LC.
|
||||
Note that using extract_name to get presentation format
|
||||
then calling to_wire() removes compression and maps case,
|
||||
thus generating names in canonical form.
|
||||
Calling to_wire followed by from_wire is almost an identity,
|
||||
except that the UC remains mapped to LC.
|
||||
|
||||
Note that both /000 and '.' are allowed within labels. These get
|
||||
represented in presentation format using NAME_ESCAPE as an escape
|
||||
character. In theory, if all the characters in a name were /000 or
|
||||
'.' or NAME_ESCAPE then all would have to be escaped, so the
|
||||
presentation format would be twice as long as the spec (1024).
|
||||
The buffers are all declared as 2049 (allowing for the trailing zero)
|
||||
for this reason.
|
||||
*/
|
||||
int to_wire(char *name)
|
||||
{
|
||||
unsigned char *l, *p, *q, term;
|
||||
int len;
|
||||
|
||||
for (l = (unsigned char*)name; *l != 0; l = p)
|
||||
{
|
||||
for (p = l; *p != '.' && *p != 0; p++)
|
||||
if (*p >= 'A' && *p <= 'Z')
|
||||
*p = *p - 'A' + 'a';
|
||||
else if (*p == NAME_ESCAPE)
|
||||
{
|
||||
for (q = p; *q; q++)
|
||||
*q = *(q+1);
|
||||
(*p)--;
|
||||
}
|
||||
term = *p;
|
||||
|
||||
if ((len = p - l) != 0)
|
||||
memmove(l+1, l, len);
|
||||
*l = len;
|
||||
|
||||
p++;
|
||||
|
||||
if (term == 0)
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
return l + 1 - (unsigned char *)name;
|
||||
}
|
||||
|
||||
/* Note: no compression allowed in input. */
|
||||
void from_wire(char *name)
|
||||
{
|
||||
unsigned char *l, *p, *last;
|
||||
int len;
|
||||
|
||||
for (last = (unsigned char *)name; *last != 0; last += *last+1);
|
||||
|
||||
for (l = (unsigned char *)name; *l != 0; l += len+1)
|
||||
{
|
||||
len = *l;
|
||||
memmove(l, l+1, len);
|
||||
for (p = l; p < l + len; p++)
|
||||
if (*p == '.' || *p == 0 || *p == NAME_ESCAPE)
|
||||
{
|
||||
memmove(p+1, p, 1 + last - p);
|
||||
len++;
|
||||
*p++ = NAME_ESCAPE;
|
||||
(*p)++;
|
||||
}
|
||||
|
||||
l[len] = '.';
|
||||
}
|
||||
|
||||
if ((char *)l != name)
|
||||
*(l-1) = 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -228,7 +228,8 @@ void tftp_request(struct listener *listen, time_t now)
|
|||
#ifdef HAVE_DHCP
|
||||
/* allowed interfaces are the same as for DHCP */
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, name))
|
||||
if (tmp->name && (tmp->flags & INAME_4) && (tmp->flags & INAME_6) &&
|
||||
wildcard_match(tmp->name, name))
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
@ -584,8 +585,13 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, char *c
|
|||
|
||||
void check_tftp_listeners(time_t now)
|
||||
{
|
||||
struct listener *listener;
|
||||
struct tftp_transfer *transfer, *tmp, **up;
|
||||
|
||||
for (listener = daemon->listeners; listener; listener = listener->next)
|
||||
if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
|
||||
tftp_request(listener, now);
|
||||
|
||||
/* In single port mode, all packets come via port 69 and tftp_request() */
|
||||
if (!option_bool(OPT_SINGLE_PORT))
|
||||
for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
@ -115,6 +115,19 @@ u64 rand64(void)
|
|||
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
|
||||
}
|
||||
|
||||
int rr_on_list(struct rrlist *list, unsigned short rr)
|
||||
{
|
||||
while (list)
|
||||
{
|
||||
if (list->rr == rr || list->rr == T_ANY)
|
||||
return 1;
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns 1 if name is OK and ascii printable
|
||||
* returns 2 if name should be processed by IDN */
|
||||
static int check_name(char *in)
|
||||
|
@ -280,11 +293,9 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
|
|||
if (limit && p + 1 > (unsigned char*)limit)
|
||||
return NULL;
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
|
||||
if (*sval == NAME_ESCAPE)
|
||||
*p++ = (*(++sval))-1;
|
||||
else
|
||||
#endif
|
||||
*p++ = *sval;
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ int main (int argc, char* argv[])
|
|||
for(int i = 0; i < argc_dnsmasq; i++)
|
||||
logg("DEBUG: argv[%i] = \"%s\"", i, argv_dnsmasq[i]);
|
||||
}
|
||||
main_dnsmasq(argc_dnsmasq, argv_dnsmasq);
|
||||
main_dnsmasq(argc_dnsmasq, (char**)argv_dnsmasq);
|
||||
|
||||
logg("Shutting down...");
|
||||
// Extra grace time is needed as dnsmasq script-helpers may not be
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
int main_dnsmasq(int argc, const char ** argv);
|
||||
int main_dnsmasq(int argc, char ** argv);
|
||||
|
||||
extern char *username;
|
||||
extern bool startup;
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#include "enums.h"
|
||||
|
||||
#define SIGUSR6 (SIGRTMIN + 6)
|
||||
|
||||
void handle_signals(void);
|
||||
void handle_realtime_signals(void);
|
||||
pid_t main_pid(void);
|
||||
|
|
|
@ -17,6 +17,10 @@ src/dnsmasq/cache.c
|
|||
"the name exists in %s with address %s"),
|
||||
host_name, daemon->addrbuff,
|
||||
record_source(fail_crec->uid), daemon->namebuff);
|
||||
src/dnsmasq/dhcp6.c
|
||||
my_syslog(MS_DHCP | LOG_WARNING,
|
||||
_("Working around kernel bug: faulty source address scope for VRF slave %s"),
|
||||
ifr.ifr_name);
|
||||
src/dnsmasq/dhcp6.c
|
||||
my_syslog(MS_DHCP | LOG_WARNING,
|
||||
_("unknown interface %s in bridge-interface"),
|
||||
|
@ -81,7 +85,7 @@ src/dnsmasq/forward.c
|
|||
src/dnsmasq/forward.c
|
||||
my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
|
||||
src/dnsmasq/forward.c
|
||||
my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
|
||||
my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
|
||||
src/dnsmasq/forward.c
|
||||
my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ);
|
||||
src/dnsmasq/forward.c
|
||||
|
@ -104,7 +108,7 @@ src/dnsmasq/lease.c
|
|||
src/dnsmasq/log.c
|
||||
my_syslog(LOG_WARNING, _("overflow: %d log entries lost"), e);
|
||||
src/dnsmasq/network.c
|
||||
my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
|
||||
my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
|
||||
src/dnsmasq/network.c
|
||||
my_syslog(LOG_WARNING,
|
||||
_("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
|
||||
|
|
|
@ -453,20 +453,20 @@
|
|||
#[[ ${lines[8]} == "clients_ever_seen 8" ]]
|
||||
#[[ ${lines[9]} == "unique_clients 8" ]]
|
||||
[[ ${lines[10]} == "dns_queries_all_types 54" ]]
|
||||
[[ ${lines[11]} == "reply_UNKNOWN 0" ]]
|
||||
[[ ${lines[11]} == "reply_UNKNOWN 1" ]]
|
||||
[[ ${lines[12]} == "reply_NODATA 0" ]]
|
||||
[[ ${lines[13]} == "reply_NXDOMAIN 1" ]]
|
||||
[[ ${lines[14]} == "reply_CNAME 7" ]]
|
||||
[[ ${lines[15]} == "reply_IP 25" ]]
|
||||
[[ ${lines[15]} == "reply_IP 24" ]]
|
||||
[[ ${lines[16]} == "reply_DOMAIN 0" ]]
|
||||
[[ ${lines[17]} == "reply_RRNAME 5" ]]
|
||||
[[ ${lines[17]} == "reply_RRNAME 6" ]]
|
||||
[[ ${lines[18]} == "reply_SERVFAIL 0" ]]
|
||||
[[ ${lines[19]} == "reply_REFUSED 0" ]]
|
||||
[[ ${lines[20]} == "reply_NOTIMP 0" ]]
|
||||
[[ ${lines[21]} == "reply_OTHER 0" ]]
|
||||
[[ ${lines[22]} == "reply_DNSSEC 6" ]]
|
||||
[[ ${lines[22]} == "reply_DNSSEC 7" ]]
|
||||
[[ ${lines[23]} == "reply_NONE 0" ]]
|
||||
[[ ${lines[24]} == "reply_BLOB 10" ]]
|
||||
[[ ${lines[24]} == "reply_BLOB 8" ]]
|
||||
[[ ${lines[25]} == "dns_queries_all_replies 54" ]]
|
||||
[[ ${lines[26]} == "privacy_level 0" ]]
|
||||
[[ ${lines[27]} == "status enabled" ]]
|
||||
|
@ -617,9 +617,9 @@
|
|||
[[ ${lines[25]} == *" A use-application-dns.net 127.0.0.1 16 2 2 "*" N/A -1 N/A#0 \"\" \"24\""* ]]
|
||||
[[ ${lines[26]} == *" A a.ftl 127.0.0.1 3 2 4 "*" N/A -1 N/A#0 \"\" \"25\""* ]]
|
||||
[[ ${lines[27]} == *" AAAA aaaa.ftl 127.0.0.1 3 2 4 "*" N/A -1 N/A#0 \"\" \"26\""* ]]
|
||||
[[ ${lines[28]} == *" ANY any.ftl 127.0.0.1 2 2 13 "*" N/A -1 127.0.0.1#5555 \"\" \"27\""* ]]
|
||||
[[ ${lines[28]} == *" ANY any.ftl 127.0.0.1 2 2 6 "*" N/A -1 127.0.0.1#5555 \"\" \"27\""* ]]
|
||||
[[ ${lines[29]} == *" [CNAME] cname-ok.ftl 127.0.0.1 2 2 3 "*" N/A -1 127.0.0.1#5555 \"\" \"28\""* ]]
|
||||
[[ ${lines[30]} == *" SRV srv.ftl 127.0.0.1 2 2 13 "*" N/A -1 127.0.0.1#5555 \"\" \"29\""* ]]
|
||||
[[ ${lines[30]} == *" SRV srv.ftl 127.0.0.1 2 2 11 "*" N/A -1 127.0.0.1#5555 \"\" \"29\""* ]]
|
||||
[[ ${lines[31]} == *" SOA ftl 127.0.0.1 2 2 13 "*" N/A -1 127.0.0.1#5555 \"\" \"30\""* ]]
|
||||
[[ ${lines[32]} == *" PTR ptr.ftl 127.0.0.1 2 2 13 "*" N/A -1 127.0.0.1#5555 \"\" \"31\""* ]]
|
||||
[[ ${lines[33]} == *" TXT txt.ftl 127.0.0.1 2 2 13 "*" N/A -1 127.0.0.1#5555 \"\" \"32\""* ]]
|
||||
|
@ -640,7 +640,7 @@
|
|||
[[ ${lines[48]} == *" DS dnssec.works :: 2 1 11 "*" N/A -1 127.0.0.1#5555 \"\" \"47\""* ]]
|
||||
[[ ${lines[49]} == *" DNSKEY works :: 2 1 11 "*" N/A -1 127.0.0.1#5555 \"\" \"48\""* ]]
|
||||
[[ ${lines[50]} == *" DNSKEY dnssec.works :: 2 1 11 "*" N/A -1 127.0.0.1#5555 \"\" \"49\""* ]]
|
||||
[[ ${lines[51]} == *" A fail01.dnssec.works 127.0.0.1 2 3 4 "*" N/A -1 127.0.0.1#5555 \"RRSIG missing\" \"50\""* ]]
|
||||
[[ ${lines[51]} == *" A fail01.dnssec.works 127.0.0.1 2 3 0 "*" N/A -1 127.0.0.1#5555 \"RRSIG missing\" \"50\""* ]]
|
||||
[[ ${lines[52]} == *" DS fail01.dnssec.works :: 2 1 11 "*" N/A -1 127.0.0.1#5555 \"\" \"51\""* ]]
|
||||
[[ ${lines[53]} == *" A special.gravity.ftl 127.0.0.1 1 2 4 "*" N/A -1 N/A#0 \"\" \"52\""* ]]
|
||||
[[ ${lines[54]} == *" A a.b.c.d.special.gravity.ftl 127.0.0.1 1 2 4 "*" N/A -1 N/A#0 \"\" \"53\""* ]]
|
||||
|
|
Loading…
Reference in New Issue