From 4a2218034881b7c3324c9a4c5f0d6b38d2c3d875 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 30 Jan 2022 12:20:41 +0100 Subject: [PATCH 1/6] Add new FORCE_IP4 and FORCE_IP6 config options Signed-off-by: DL6ER --- src/config.c | 64 ++++++++++++++++++++++++++++++++--------- src/config.h | 18 ++++++++---- src/dnsmasq_interface.c | 63 ++++++++++++++++++++-------------------- 3 files changed, 95 insertions(+), 50 deletions(-) diff --git a/src/config.c b/src/config.c index 14c5d349..5629eacc 100644 --- a/src/config.c +++ b/src/config.c @@ -506,17 +506,17 @@ void read_FTLconf(void) // Use a specific IP address instead of automatically detecting the // IPv4 interface address a query arrived on // defaults to: not set - config.reply_addr.overwrite_v4 = false; - config.reply_addr.v4.s_addr = 0; + config.reply_addr.own_host.overwrite_v4 = false; + config.reply_addr.own_host.v4.s_addr = 0; buffer = parse_FTLconf(fp, "REPLY_ADDR4"); - if(buffer != NULL && inet_pton(AF_INET, buffer, &config.reply_addr.v4)) - config.reply_addr.overwrite_v4 = true; + if(buffer != NULL && inet_pton(AF_INET, buffer, &config.reply_addr.own_host.v4)) + config.reply_addr.own_host.overwrite_v4 = true; - if(config.reply_addr.overwrite_v4) + if(config.reply_addr.own_host.overwrite_v4) { char addr[INET_ADDRSTRLEN] = { 0 }; - inet_ntop(AF_INET, &config.reply_addr.v4, addr, INET_ADDRSTRLEN); - logg(" REPLY_ADDR4: Using IPv4 address %s in IP blocking mode", addr); + inet_ntop(AF_INET, &config.reply_addr.own_host.v4, addr, INET_ADDRSTRLEN); + logg(" REPLY_ADDR4: Using IPv4 address %s for pi.hole and hostname", addr); } else logg(" REPLY_ADDR4: Automatic interface-dependent detection of address"); @@ -525,21 +525,57 @@ void read_FTLconf(void) // Use a specific IP address instead of automatically detecting the // IPv6 interface address a query arrived on // defaults to: not set - config.reply_addr.overwrite_v6 = false; - memset(&config.reply_addr.v6, 0, sizeof(config.reply_addr.v6)); + config.reply_addr.own_host.overwrite_v6 = false; + memset(&config.reply_addr.own_host.v6, 0, sizeof(config.reply_addr.own_host.v6)); buffer = parse_FTLconf(fp, "REPLY_ADDR6"); - if(buffer != NULL && inet_pton(AF_INET6, buffer, &config.reply_addr.v6)) - config.reply_addr.overwrite_v6 = true; + if(buffer != NULL && inet_pton(AF_INET6, buffer, &config.reply_addr.own_host.v6)) + config.reply_addr.own_host.overwrite_v6 = true; - if(config.reply_addr.overwrite_v6) + if(config.reply_addr.own_host.overwrite_v6) { char addr[INET6_ADDRSTRLEN] = { 0 }; - inet_ntop(AF_INET6, &config.reply_addr.v6, addr, INET6_ADDRSTRLEN); - logg(" REPLY_ADDR6: Using IPv6 address %s in IP blocking mode", addr); + inet_ntop(AF_INET6, &config.reply_addr.own_host.v6, addr, INET6_ADDRSTRLEN); + logg(" REPLY_ADDR6: Using IPv6 address %s for pi.hole and hostname", addr); } else logg(" REPLY_ADDR6: Automatic interface-dependent detection of address"); + // FORCE_IP4 + // Use a specific IPv4 address for IP blocking mode replies + // defaults to: REPLY_ADDR4 setting + config.reply_addr.ip_blocking.overwrite_v4 = config.reply_addr.own_host.overwrite_v4; + config.reply_addr.ip_blocking.v4.s_addr = config.reply_addr.own_host.v4.s_addr; + buffer = parse_FTLconf(fp, "FORCE_IP4"); + if(buffer != NULL && inet_pton(AF_INET, buffer, &config.reply_addr.ip_blocking.v4)) + config.reply_addr.ip_blocking.overwrite_v4 = true; + + if(config.reply_addr.ip_blocking.overwrite_v4) + { + char addr[INET_ADDRSTRLEN] = { 0 }; + inet_ntop(AF_INET, &config.reply_addr.ip_blocking.v4, addr, INET_ADDRSTRLEN); + logg(" FORCE_IP4: Using IPv4 address %s in IP blocking mode", addr); + } + else + logg(" FORCE_IP4: Automatic interface-dependent detection of address"); + + // FORCE_IP6 + // Use a specific IPv6 address for IP blocking mode replies + // defaults to: REPLY_ADDR6 setting + config.reply_addr.ip_blocking.overwrite_v6 = config.reply_addr.own_host.overwrite_v6; + memcpy(&config.reply_addr.ip_blocking.v6, &config.reply_addr.own_host.v6, sizeof(config.reply_addr.ip_blocking.v6)); + buffer = parse_FTLconf(fp, "FORCE_IP6"); + if(buffer != NULL && inet_pton(AF_INET6, buffer, &config.reply_addr.ip_blocking.v6)) + config.reply_addr.ip_blocking.overwrite_v6 = true; + + if(config.reply_addr.ip_blocking.overwrite_v6) + { + char addr[INET6_ADDRSTRLEN] = { 0 }; + inet_ntop(AF_INET6, &config.reply_addr.ip_blocking.v6, addr, INET6_ADDRSTRLEN); + logg(" FORCE_IP6: Using IPv6 address %s in IP blocking mode", addr); + } + else + logg(" FORCE_IP6: Automatic interface-dependent detection of address"); + // SHOW_DNSSEC // Should FTL analyze and include automatically generated DNSSEC queries in the Query Log? // defaults to: true diff --git a/src/config.h b/src/config.h index 8836bb2e..332d2a4a 100644 --- a/src/config.h +++ b/src/config.h @@ -77,13 +77,21 @@ typedef struct { enum debug_flags debug; time_t DBinterval; struct { - bool overwrite_v4 :1; - bool overwrite_v6 :1; - struct in_addr v4; - struct in6_addr v6; + struct { + bool overwrite_v4 :1; + bool overwrite_v6 :1; + struct in_addr v4; + struct in6_addr v6; + } own_host; + struct { + bool overwrite_v4 :1; + bool overwrite_v6 :1; + struct in_addr v4; + struct in6_addr v6; + } ip_blocking; } reply_addr; } ConfigStruct; -ASSERT_SIZEOF(ConfigStruct, 88, 80, 80); +ASSERT_SIZEOF(ConfigStruct, 112, 104, 104); typedef struct { const char* conf; diff --git a/src/dnsmasq_interface.c b/src/dnsmasq_interface.c index e19f1304..23da04bb 100644 --- a/src/dnsmasq_interface.c +++ b/src/dnsmasq_interface.c @@ -73,7 +73,6 @@ static char *get_ptrname(struct in_addr *addr); // Static blocking metadata static const char *blockingreason = ""; -static union all_addr null_addrp = {{ 0 }}; static enum reply_type force_next_DNS_reply = REPLY_UNKNOWN; static int last_regex_idx = -1; static struct ptr_record *pihole_ptr = NULL; @@ -322,21 +321,28 @@ size_t _FTL_make_answer(struct dns_header *header, char *limit, const size_t len // Add A answer record if requested if(flags & F_IPV4) { - union all_addr *addr = &null_addrp; + union all_addr addr = {{ 0 }}; // Overwrite with IP address if requested if(redirecting) - addr = &redirect_addr4; + memcpy(&addr, &redirect_addr4, sizeof(addr)); else if(config.blockingmode == MODE_IP || config.blockingmode == MODE_IP_NODATA_AAAA || forced_ip) - addr = &next_iface.addr4; + { + if(hostname && config.reply_addr.own_host.overwrite_v4) + memcpy(&addr, &config.reply_addr.own_host.v4, sizeof(addr)); + else if(!hostname && config.reply_addr.ip_blocking.overwrite_v4) + memcpy(&addr, &config.reply_addr.ip_blocking.v4, sizeof(addr)); + else + memcpy(&addr, &next_iface.addr4, sizeof(addr)); + } // Debug logging if(config.debug & DEBUG_QUERIES) { char ip[ADDRSTRLEN+1] = { 0 }; - alladdr_extract_ip(addr, AF_INET, ip); + alladdr_extract_ip(&addr, AF_INET, ip); logg(" Adding RR: \"%s A %s\"", name, ip); } @@ -344,27 +350,34 @@ size_t _FTL_make_answer(struct dns_header *header, char *limit, const size_t len header->ancount = htons(ntohs(header->ancount) + 1); if(add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, hostname ? daemon->local_ttl : config.block_ttl, - NULL, T_A, C_IN, (char*)"4", &addr->addr4)) - log_query(flags & ~F_IPV6, name, addr, (char*)blockingreason, 0); + NULL, T_A, C_IN, (char*)"4", &addr.addr4)) + log_query(flags & ~F_IPV6, name, &addr, (char*)blockingreason, 0); } // Add AAAA answer record if requested if(flags & F_IPV6) { - union all_addr *addr = &null_addrp; + union all_addr addr = {{ 0 }}; // Overwrite with IP address if requested if(redirecting) - addr = &redirect_addr6; + memcpy(&addr, &redirect_addr6, sizeof(addr)); else if(config.blockingmode == MODE_IP || forced_ip) - addr = &next_iface.addr6; + { + if(hostname && config.reply_addr.own_host.overwrite_v6) + memcpy(&addr, &config.reply_addr.own_host.v6, sizeof(addr)); + else if(!hostname && config.reply_addr.ip_blocking.overwrite_v6) + memcpy(&addr, &config.reply_addr.ip_blocking.v6, sizeof(addr)); + else + memcpy(&addr, &next_iface.addr6, sizeof(addr)); + } // Debug logging if(config.debug & DEBUG_QUERIES) { char ip[ADDRSTRLEN+1] = { 0 }; - alladdr_extract_ip(addr, AF_INET6, ip); + alladdr_extract_ip(&addr, AF_INET6, ip); logg(" Adding RR: \"%s AAAA %s\"", name, ip); } @@ -372,8 +385,8 @@ size_t _FTL_make_answer(struct dns_header *header, char *limit, const size_t len header->ancount = htons(ntohs(header->ancount) + 1); if(add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, hostname ? daemon->local_ttl : config.block_ttl, - NULL, T_AAAA, C_IN, (char*)"6", &addr->addr6)) - log_query(flags & ~F_IPV4, name, addr, (char*)blockingreason, 0); + NULL, T_AAAA, C_IN, (char*)"6", &addr.addr6)) + log_query(flags & ~F_IPV4, name, &addr, (char*)blockingreason, 0); } // Log empty replies @@ -821,29 +834,17 @@ void _FTL_iface(struct irec *recviface, const union all_addr *addr, const sa_fam logg("Interfaces: Called from %s:%d", short_path(file), line); // Copy overwrite addresses if configured via REPLY_ADDR4 and/or REPLY_ADDR6 settings - if(config.reply_addr.overwrite_v4) + if(config.reply_addr.own_host.overwrite_v4) { - memcpy(&next_iface.addr4, &config.reply_addr.v4, sizeof(config.reply_addr.v4)); next_iface.haveIPv4 = true; - if(config.debug & DEBUG_NETWORKING) - { - char buffer[ADDRSTRLEN+1] = { 0 }; - inet_ntop(AF_INET, &next_iface.addr4, buffer, ADDRSTRLEN); - logg("Configuration overwrites IPv4 address: %s", buffer); - } + logg("Configuration overwrites IPv4 address"); } - if(config.reply_addr.overwrite_v6) + if(config.reply_addr.own_host.overwrite_v6) { - memcpy(&next_iface.addr6, &config.reply_addr.v6, sizeof(config.reply_addr.v6)); next_iface.haveIPv6 = true; - if(config.debug & DEBUG_NETWORKING) - { - char buffer[ADDRSTRLEN+1] = { 0 }; - inet_ntop(AF_INET6, &next_iface.addr6, buffer, ADDRSTRLEN); - logg("Configuration overwrites IPv6 address: %s", buffer); - } + logg("Configuration overwrites IPv6 address"); } // Use dummy when interface record is not available @@ -955,8 +956,8 @@ void _FTL_iface(struct irec *recviface, const union all_addr *addr, const sa_fam // Check if this family type is overwritten by config settings // We logged this above - if((config.reply_addr.overwrite_v4 && family == AF_INET) || - (config.reply_addr.overwrite_v6 && family == AF_INET6)) + if((config.reply_addr.own_host.overwrite_v4 && family == AF_INET) || + (config.reply_addr.own_host.overwrite_v6 && family == AF_INET6)) { if(config.debug & DEBUG_NETWORKING) logg(" - SKIP IPv%d interface %s: REPLY_ADDR%d used", From e5f69e1f0f0a4db4eab6e3e430fefc3c24f2fd5a Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 30 Jan 2022 20:06:17 +0100 Subject: [PATCH 2/6] Check all 128 bits of the IPv6 address instead of only the first 32 bits for deciding if the address is unspecified. Signed-off-by: DL6ER --- src/dnsmasq_interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dnsmasq_interface.c b/src/dnsmasq_interface.c index 23da04bb..de5fb589 100644 --- a/src/dnsmasq_interface.c +++ b/src/dnsmasq_interface.c @@ -853,8 +853,8 @@ void _FTL_iface(struct irec *recviface, const union all_addr *addr, const sa_fam // Check if we need to identify the receving interface by its address if(!recviface && addr && - ((addrfamily == AF_INET && addr->addr4.s_addr != 0) || - (addrfamily == AF_INET6 && addr->addr6.s6_addr[0] != 0))) + ((addrfamily == AF_INET && addr->addr4.s_addr != INADDR_ANY) || + (addrfamily == AF_INET6 && !IN6_IS_ADDR_UNSPECIFIED(&addr->addr6)))) { if(config.debug & DEBUG_NETWORKING) { From ffa83b05c20f1e870f8d99389950ef137090db3f Mon Sep 17 00:00:00 2001 From: DL6ER Date: Tue, 1 Feb 2022 08:06:26 +0100 Subject: [PATCH 3/6] Deprecate REPLY_ADDR4/6 in favor of the two new settings LOCAL_IPV4/6 and BLOCK_IPV4/6. If REPLY_ADDR4/6 is set and neither LOCAL_IPV4/6 nor BLOCK_IPV4/6, we use the value for both to preserve current behavior. Signed-off-by: DL6ER --- src/config.c | 94 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 22 deletions(-) diff --git a/src/config.c b/src/config.c index 5629eacc..e2069caa 100644 --- a/src/config.c +++ b/src/config.c @@ -502,13 +502,13 @@ void read_FTLconf(void) else logg(" RATE_LIMIT: Disabled"); - // REPLY_ADDR4 + // LOCAL_IPV4 // Use a specific IP address instead of automatically detecting the - // IPv4 interface address a query arrived on + // IPv4 interface address a query arrived on for A hostname queries // defaults to: not set config.reply_addr.own_host.overwrite_v4 = false; config.reply_addr.own_host.v4.s_addr = 0; - buffer = parse_FTLconf(fp, "REPLY_ADDR4"); + buffer = parse_FTLconf(fp, "LOCAL_IPV4"); if(buffer != NULL && inet_pton(AF_INET, buffer, &config.reply_addr.own_host.v4)) config.reply_addr.own_host.overwrite_v4 = true; @@ -516,18 +516,18 @@ void read_FTLconf(void) { char addr[INET_ADDRSTRLEN] = { 0 }; inet_ntop(AF_INET, &config.reply_addr.own_host.v4, addr, INET_ADDRSTRLEN); - logg(" REPLY_ADDR4: Using IPv4 address %s for pi.hole and hostname", addr); + logg(" LOCAL_IPV4: Using IPv4 address %s for pi.hole and hostname", addr); } else - logg(" REPLY_ADDR4: Automatic interface-dependent detection of address"); + logg(" LOCAL_IPV4: Automatic interface-dependent detection of address"); - // REPLY_ADDR6 + // LOCAL_IPV6 // Use a specific IP address instead of automatically detecting the - // IPv6 interface address a query arrived on + // IPv4 interface address a query arrived on for AAAA hostname queries // defaults to: not set config.reply_addr.own_host.overwrite_v6 = false; memset(&config.reply_addr.own_host.v6, 0, sizeof(config.reply_addr.own_host.v6)); - buffer = parse_FTLconf(fp, "REPLY_ADDR6"); + buffer = parse_FTLconf(fp, "LOCAL_IPV6"); if(buffer != NULL && inet_pton(AF_INET6, buffer, &config.reply_addr.own_host.v6)) config.reply_addr.own_host.overwrite_v6 = true; @@ -535,17 +535,17 @@ void read_FTLconf(void) { char addr[INET6_ADDRSTRLEN] = { 0 }; inet_ntop(AF_INET6, &config.reply_addr.own_host.v6, addr, INET6_ADDRSTRLEN); - logg(" REPLY_ADDR6: Using IPv6 address %s for pi.hole and hostname", addr); + logg(" LOCAL_IPV6: Using IPv6 address %s for pi.hole and hostname", addr); } else - logg(" REPLY_ADDR6: Automatic interface-dependent detection of address"); + logg(" LOCAL_IPV6: Automatic interface-dependent detection of address"); - // FORCE_IP4 + // BLOCK_IPV4 // Use a specific IPv4 address for IP blocking mode replies // defaults to: REPLY_ADDR4 setting - config.reply_addr.ip_blocking.overwrite_v4 = config.reply_addr.own_host.overwrite_v4; - config.reply_addr.ip_blocking.v4.s_addr = config.reply_addr.own_host.v4.s_addr; - buffer = parse_FTLconf(fp, "FORCE_IP4"); + config.reply_addr.ip_blocking.overwrite_v4 = false; + config.reply_addr.ip_blocking.v4.s_addr = 0; + buffer = parse_FTLconf(fp, "BLOCK_IPV4"); if(buffer != NULL && inet_pton(AF_INET, buffer, &config.reply_addr.ip_blocking.v4)) config.reply_addr.ip_blocking.overwrite_v4 = true; @@ -553,17 +553,17 @@ void read_FTLconf(void) { char addr[INET_ADDRSTRLEN] = { 0 }; inet_ntop(AF_INET, &config.reply_addr.ip_blocking.v4, addr, INET_ADDRSTRLEN); - logg(" FORCE_IP4: Using IPv4 address %s in IP blocking mode", addr); + logg(" BLOCK_IPV4: Using IPv4 address %s in IP blocking mode", addr); } else - logg(" FORCE_IP4: Automatic interface-dependent detection of address"); + logg(" BLOCK_IPV4: Automatic interface-dependent detection of address"); - // FORCE_IP6 + // BLOCK_IPV6 // Use a specific IPv6 address for IP blocking mode replies // defaults to: REPLY_ADDR6 setting - config.reply_addr.ip_blocking.overwrite_v6 = config.reply_addr.own_host.overwrite_v6; - memcpy(&config.reply_addr.ip_blocking.v6, &config.reply_addr.own_host.v6, sizeof(config.reply_addr.ip_blocking.v6)); - buffer = parse_FTLconf(fp, "FORCE_IP6"); + config.reply_addr.ip_blocking.overwrite_v6 = false; + memset(&config.reply_addr.ip_blocking.v6, 0, sizeof(config.reply_addr.own_host.v6)); + buffer = parse_FTLconf(fp, "BLOCK_IPV6"); if(buffer != NULL && inet_pton(AF_INET6, buffer, &config.reply_addr.ip_blocking.v6)) config.reply_addr.ip_blocking.overwrite_v6 = true; @@ -571,10 +571,60 @@ void read_FTLconf(void) { char addr[INET6_ADDRSTRLEN] = { 0 }; inet_ntop(AF_INET6, &config.reply_addr.ip_blocking.v6, addr, INET6_ADDRSTRLEN); - logg(" FORCE_IP6: Using IPv6 address %s in IP blocking mode", addr); + logg(" BLOCK_IPV6: Using IPv6 address %s in IP blocking mode", addr); } else - logg(" FORCE_IP6: Automatic interface-dependent detection of address"); + logg(" BLOCK_IPV6: Automatic interface-dependent detection of address"); + + // REPLY_ADDR4 (deprecated setting) + // Use a specific IP address instead of automatically detecting the + // IPv4 interface address a query arrived on A hostname and IP blocked queries + // defaults to: not set + struct in_addr reply_addr4; + buffer = parse_FTLconf(fp, "REPLY_ADDR4"); + if(buffer != NULL && inet_pton(AF_INET, buffer, &reply_addr4)) + { + if(config.reply_addr.own_host.overwrite_v4 || config.reply_addr.ip_blocking.overwrite_v4) + { + logg(" WARNING: Ignoring REPLY_ADDR4 as LOCAL_IPV4 or BLOCK_IPV4 has been specified."); + } + else + { + config.reply_addr.own_host.overwrite_v4 = true; + memcpy(&config.reply_addr.own_host.v4, &reply_addr4, sizeof(reply_addr4)); + config.reply_addr.ip_blocking.overwrite_v4 = true; + memcpy(&config.reply_addr.ip_blocking.v4, &reply_addr4, sizeof(reply_addr4)); + + char addr[INET_ADDRSTRLEN] = { 0 }; + inet_ntop(AF_INET, &reply_addr4, addr, INET_ADDRSTRLEN); + logg(" REPLY_ADDR4: Using IPv4 address %s instead of automatically determined IP address", addr); + } + } + + // REPLY_ADDR6 (deprecated setting) + // Use a specific IP address instead of automatically detecting the + // IPv4 interface address a query arrived on A hostname and IP blocked queries + // defaults to: not set + struct in6_addr reply_addr6; + buffer = parse_FTLconf(fp, "REPLY_ADDR6"); + if(buffer != NULL && inet_pton(AF_INET, buffer, &reply_addr6)) + { + if(config.reply_addr.own_host.overwrite_v6 || config.reply_addr.ip_blocking.overwrite_v6) + { + logg(" WARNING: Ignoring REPLY_ADDR6 as LOCAL_IPV6 or BLOCK_IPV6 has been specified."); + } + else + { + config.reply_addr.own_host.overwrite_v6 = true; + memcpy(&config.reply_addr.own_host.v6, &reply_addr6, sizeof(reply_addr6)); + config.reply_addr.ip_blocking.overwrite_v6 = true; + memcpy(&config.reply_addr.ip_blocking.v6, &reply_addr6, sizeof(reply_addr6)); + + char addr[INET6_ADDRSTRLEN] = { 0 }; + inet_ntop(AF_INET6, &reply_addr6, addr, INET6_ADDRSTRLEN); + logg(" REPLY_ADDR6: Using IPv6 address %s instead of automatically determined IP address", addr); + } + } // SHOW_DNSSEC // Should FTL analyze and include automatically generated DNSSEC queries in the Query Log? From a668a6c8f231525d57fecd391de8710e67c708d9 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Tue, 1 Feb 2022 08:27:28 +0100 Subject: [PATCH 4/6] Scan all address types even if we don't use them later. We may want to replace the blocking IP address but not the local one and need to determine the latter. Signed-off-by: DL6ER --- src/dnsmasq_interface.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/dnsmasq_interface.c b/src/dnsmasq_interface.c index de5fb589..d755dcd6 100644 --- a/src/dnsmasq_interface.c +++ b/src/dnsmasq_interface.c @@ -833,20 +833,6 @@ void _FTL_iface(struct irec *recviface, const union all_addr *addr, const sa_fam if(config.debug & DEBUG_NETWORKING) logg("Interfaces: Called from %s:%d", short_path(file), line); - // Copy overwrite addresses if configured via REPLY_ADDR4 and/or REPLY_ADDR6 settings - if(config.reply_addr.own_host.overwrite_v4) - { - next_iface.haveIPv4 = true; - if(config.debug & DEBUG_NETWORKING) - logg("Configuration overwrites IPv4 address"); - } - if(config.reply_addr.own_host.overwrite_v6) - { - next_iface.haveIPv6 = true; - if(config.debug & DEBUG_NETWORKING) - logg("Configuration overwrites IPv6 address"); - } - // Use dummy when interface record is not available next_iface.name[0] = '-'; next_iface.name[1] = '\0'; @@ -954,17 +940,6 @@ void _FTL_iface(struct irec *recviface, const union all_addr *addr, const sa_fam strncpy(next_iface.name, iname, sizeof(next_iface.name)-1); next_iface.name[sizeof(next_iface.name)-1] = '\0'; - // Check if this family type is overwritten by config settings - // We logged this above - if((config.reply_addr.own_host.overwrite_v4 && family == AF_INET) || - (config.reply_addr.own_host.overwrite_v6 && family == AF_INET6)) - { - if(config.debug & DEBUG_NETWORKING) - logg(" - SKIP IPv%d interface %s: REPLY_ADDR%d used", - family == AF_INET ? 4 : 6, iname, family == AF_INET ? 4 : 6); - continue; - } - bool isULA = false, isGUA = false, isLL = false; // Check if this address is different from 0000:0000:0000:0000:0000:0000:0000:0000 if(family == AF_INET6 && memcmp(&next_iface.addr6.addr6, &iface->addr.in6.sin6_addr, sizeof(iface->addr.in6.sin6_addr)) != 0) From 25e9adeded439ad6507397741033f2304a5fad78 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Tue, 1 Feb 2022 10:15:17 +0100 Subject: [PATCH 5/6] Apply suggestions from code review Co-authored-by: yubiuser Signed-off-by: DL6ER --- src/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index e2069caa..76e49c07 100644 --- a/src/config.c +++ b/src/config.c @@ -523,7 +523,7 @@ void read_FTLconf(void) // LOCAL_IPV6 // Use a specific IP address instead of automatically detecting the - // IPv4 interface address a query arrived on for AAAA hostname queries + // IPv6 interface address a query arrived on for AAAA hostname queries // defaults to: not set config.reply_addr.own_host.overwrite_v6 = false; memset(&config.reply_addr.own_host.v6, 0, sizeof(config.reply_addr.own_host.v6)); From 23776e6c083c48273d278cb763164ad20fdd811a Mon Sep 17 00:00:00 2001 From: DL6ER Date: Tue, 1 Feb 2022 14:07:59 +0100 Subject: [PATCH 6/6] Add tests for LOCAL_IPV4/6 and BLOCK_IPV4/6 Signed-off-by: DL6ER --- src/dnsmasq_interface.c | 8 ++++++-- test/pihole-FTL.conf | 4 ++++ test/test_suite.bats | 30 ++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/dnsmasq_interface.c b/src/dnsmasq_interface.c index d755dcd6..0141d357 100644 --- a/src/dnsmasq_interface.c +++ b/src/dnsmasq_interface.c @@ -520,8 +520,12 @@ bool _FTL_new_query(const unsigned int flags, const char *name, // Send NODATA when the current interface doesn't have // the requested IP address, for instance AAAA on an // virtual interface that has only an IPv4 address - if((querytype == TYPE_A && !next_iface.haveIPv4) || - (querytype == TYPE_AAAA && !next_iface.haveIPv6)) + if((querytype == TYPE_A && + !next_iface.haveIPv4 && + !config.reply_addr.own_host.overwrite_v4) || + (querytype == TYPE_AAAA && + !next_iface.haveIPv6 && + !config.reply_addr.own_host.overwrite_v6)) force_next_DNS_reply = REPLY_NODATA; else force_next_DNS_reply = REPLY_IP; diff --git a/test/pihole-FTL.conf b/test/pihole-FTL.conf index 060727c3..2d562a67 100644 --- a/test/pihole-FTL.conf +++ b/test/pihole-FTL.conf @@ -2,3 +2,7 @@ DEBUG_ALL=true RESOLVE_IPV4=no RESOLVE_IPV6=no CHECK_LOAD=false +LOCAL_IPV4=10.100.0.10 +LOCAL_IPV6=fe80::10 +BLOCK_IPV4=10.100.0.11 +BLOCK_IPV6=fe80::11 diff --git a/test/test_suite.bats b/test/test_suite.bats index c72701bc..9ed4b73f 100644 --- a/test/test_suite.bats +++ b/test/test_suite.bats @@ -1272,3 +1272,33 @@ printf "%s\n" "${lines[@]}" [[ "${lines[0]}" == "" ]] } + +@test "Pi-hole uses LOCAL_IPV4/6 for pi.hole" { + run bash -c "dig A pi.hole +short @127.0.0.1" + printf "%s\n" "${lines[@]}" + [[ "${lines[0]}" == "10.100.0.10" ]] + run bash -c "dig AAAA pi.hole +short @127.0.0.1" + printf "%s\n" "${lines[@]}" + [[ "${lines[0]}" == "fe80::10" ]] +} + +@test "Pi-hole uses LOCAL_IPV4/6 for hostname" { + run bash -c "dig A $(hostname) +short @127.0.0.1" + printf "%s\n" "${lines[@]}" + [[ "${lines[0]}" == "10.100.0.10" ]] + run bash -c "dig AAAA $(hostname) +short @127.0.0.1" + printf "%s\n" "${lines[@]}" + [[ "${lines[0]}" == "fe80::10" ]] +} + +@test "Pi-hole uses BLOCK_IPV4/6 for blocked domain" { + echo "BLOCKINGMODE=IP" >> /etc/pihole/pihole-FTL.conf + run bash -c "kill -HUP $(cat /run/pihole-FTL.pid)" + sleep 2 + run bash -c "dig A blacklisted.ftl +short @127.0.0.1" + printf "%s\n" "${lines[@]}" + [[ "${lines[0]}" == "10.100.0.11" ]] + run bash -c "dig AAAA blacklisted.ftl +short @127.0.0.1" + printf "%s\n" "${lines[@]}" + [[ "${lines[0]}" == "fe80::11" ]] +}