Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add support for conditional domain suffices in HOSTNAMEFQDN mode #1250

Merged
merged 1 commit into from
Nov 30, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 66 additions & 28 deletions src/dnsmasq_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ static void alladdr_extract_ip(union all_addr *addr, const sa_family_t family, c
static void check_pihole_PTR(char *domain);
#define query_set_dnssec(query, dnssec) _query_set_dnssec(query, dnssec, __FILE__, __LINE__)
static void _query_set_dnssec(queriesData *query, const enum dnssec_status dnssec, const char *file, const int line);
static char *get_ptrname(struct in_addr *addr);

// Static blocking metadata
static const char *blockingreason = "";
Expand Down Expand Up @@ -1060,6 +1061,23 @@ static void check_pihole_PTR(char *domain)
// The last PTR record in daemon->ptr is reserved for Pi-hole
free(pihole_ptr->name);
pihole_ptr->name = strdup(domain);
if(family == AF_INET)
{
// IPv4 supports conditional domains
struct in_addr addrv4 = { 0 };
addrv4.s_addr = iface->addr.in.sin_addr.s_addr;
pihole_ptr->ptr = get_ptrname(&addrv4);
}
else
{
// IPv6 does not support conditional domains
pihole_ptr->ptr = get_ptrname(NULL);
}

// Debug logging
if(config.debug & DEBUG_QUERIES)
logg("Generating PTR response: %s -> %s", pihole_ptr->name, pihole_ptr->ptr);

return;
}
}
Expand Down Expand Up @@ -2765,7 +2783,35 @@ void FTL_fork_and_bind_sockets(struct passwd *ent_pw)
// Obtain DNS port from dnsmasq daemon
config.dns_port = daemon->port;

char *ptrname = NULL;
// Obtain PTR record used for Pi-hole PTR injection (if enabled)
if(config.pihole_ptr != PTR_NONE)
{
// Add PTR record for pi.hole, the address will be injected later
pihole_ptr = calloc(1, sizeof(struct ptr_record));
pihole_ptr->name = strdup("x.x.x.x.in-addr.arpa");
pihole_ptr->ptr = (char*)"";
pihole_ptr->next = NULL;
// Add our PTR record to the end of the linked list
if(daemon->ptr != NULL)
{
// Interate to the last PTR entry in dnsmasq's structure
struct ptr_record *ptr;
for(ptr = daemon->ptr; ptr && ptr->next; ptr = ptr->next);

// Add our record after the last existing ptr-record
ptr->next = pihole_ptr;
}
else
{
// Ours is the only record for daemon->ptr
daemon->ptr = pihole_ptr;
}
}
}

static char *get_ptrname(struct in_addr *addr)
{
static char *ptrname = NULL;
// Determine name that should be replied to with on Pi-hole PTRs
switch (config.pihole_ptr)
{
Expand All @@ -2781,13 +2827,28 @@ void FTL_fork_and_bind_sockets(struct passwd *ent_pw)

case PTR_HOSTNAMEFQDN:
{
char *suffix = daemon->domain_suffix;
char *suffix;
size_t ptrnamesize = 0;
// get_domain() will also check conditional domains configured like
// domain=<domain>[,<address range>[,local]]
if(addr)
suffix = get_domain(*addr);
else
suffix = daemon->domain_suffix;
// If local suffix is not available, we substitute "no_fqdn_available"
// see the comment about PIHOLE_PTR=HOSTNAMEFQDN in the Pi-hole docs
// for further details on why this was chosen
if(!suffix)
suffix = (char*)"no_fqdn_available";
ptrname = calloc(strlen(hostname()) + strlen(suffix) + 2, sizeof(char));

// Get enough space for domain building
size_t needspace = strlen(hostname()) + strlen(suffix) + 2;
if(ptrnamesize < needspace)
{
ptrname = realloc(ptrname, needspace);
ptrnamesize = needspace;
}

if(ptrname)
{
// Build "<hostname>.<local suffix>" domain
Expand All @@ -2800,34 +2861,11 @@ void FTL_fork_and_bind_sockets(struct passwd *ent_pw)
// Fallback to "<hostname>" on memory error
ptrname = (char*)hostname();
}
}
break;
}

// Obtain PTR record used for Pi-hole PTR injection (if enabled)
if(config.pihole_ptr != PTR_NONE)
{
// Add PTR record for pi.hole, the address will be injected later
pihole_ptr = calloc(1, sizeof(struct ptr_record));
pihole_ptr->name = strdup("x.x.x.x.in-addr.arpa");
pihole_ptr->ptr = ptrname;
pihole_ptr->next = NULL;
// Add our PTR record to the end of the linked list
if(daemon->ptr != NULL)
{
// Interate to the last PTR entry in dnsmasq's structure
struct ptr_record *ptr;
for(ptr = daemon->ptr; ptr && ptr->next; ptr = ptr->next);

// Add our record after the last existing ptr-record
ptr->next = pihole_ptr;
}
else
{
// Ours is the only record for daemon->ptr
daemon->ptr = pihole_ptr;
}
}

return ptrname;
}

// int cache_inserted, cache_live_freed are defined in dnsmasq/cache.c
Expand Down