From 08b00d2b0539a7f0f9847ca63efe2018ee4a7cb5 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 13 Jul 2020 20:39:48 +0200 Subject: [PATCH 1/7] Add additional_info column to queries table. We fill it with the domain that caused blocking the entire CNAME chain. Signed-off-by: DL6ER --- src/database/common.c | 18 ++++++++++++++++++ src/database/query-table.c | 17 ++++++++++++++++- src/dnsmasq_interface.c | 4 ++-- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/database/common.c b/src/database/common.c index ddffa2e5..51c7b73b 100644 --- a/src/database/common.c +++ b/src/database/common.c @@ -361,6 +361,24 @@ void db_init(void) dbversion = db_get_FTL_property(DB_VERSION); } + // Update to version 7 if lower + if(dbversion < 7) + { + // Update to version 7: Create message table + logg("Updating long-term database to version 7"); + if(dbquery("ALTER TABLE queries ADD COLUMN additional_info TEXT;") != SQLITE_OK || + !db_set_FTL_property(DB_VERSION, 7)) + { + logg("Column additional_info not initialized, database not available"); + dbclose(); + + database = false; + return; + } + // Get updated version + dbversion = db_get_FTL_property(DB_VERSION); + } + // Close database to prevent having it opened all time // We already closed the database when we returned earlier dbclose(); diff --git a/src/database/query-table.c b/src/database/query-table.c index e27c8e50..b4424979 100644 --- a/src/database/query-table.c +++ b/src/database/query-table.c @@ -85,7 +85,7 @@ void DB_save_queries(void) return; } - rc = sqlite3_prepare_v2(FTL_db, "INSERT INTO queries VALUES (NULL,?,?,?,?,?,?)", -1, &stmt, NULL); + rc = sqlite3_prepare_v2(FTL_db, "INSERT INTO queries VALUES (NULL,?,?,?,?,?,?,?)", -1, &stmt, NULL); if( rc != SQLITE_OK ) { const char *text, *spaces; @@ -169,6 +169,21 @@ void DB_save_queries(void) sqlite3_bind_null(stmt, 6); } + // Fill additional information column + if(query->status == QUERY_GRAVITY_CNAME || + query->status == QUERY_REGEX_CNAME || + query->status == QUERY_BLACKLIST_CNAME) + { + // Get domain blocked during deep CNAME inspection, if applicable + const char* cname = getCNAMEDomainString(query); + sqlite3_bind_text(stmt, 7, cname, -1, SQLITE_STATIC); + } + else + { + // Nothing to add here + sqlite3_bind_null(stmt, 7); + } + // Step and check if successful rc = sqlite3_step(stmt); sqlite3_clear_bindings(stmt); diff --git a/src/dnsmasq_interface.c b/src/dnsmasq_interface.c index 00b50be6..8e9d8564 100644 --- a/src/dnsmasq_interface.c +++ b/src/dnsmasq_interface.c @@ -163,7 +163,7 @@ static bool _FTL_check_blocking(int queryID, int domainID, int clientID, const c } // Do not block if the entire query is to be permitted - // as sometving along the CNAME path hit the whitelist + // as something along the CNAME path hit the whitelist if(!query->whitelisted) { query_blocked(query, domain, client, QUERY_BLACKLIST); @@ -357,7 +357,7 @@ bool _FTL_CNAME(const char *domain, const struct crec *cpp, const int id, const // If we find during a CNAME inspection that we want to block the entire chain, // the originally queried domain itself was not counted as blocked (but as - // (permitted). Later in the chain, when we find that this is a bad guy, we + // permitted). Later in the chain, when we find that this is a bad guy, we // short-circuit it. We need to correct the domain counter of the domain at the // head of the chain, otherwise, the data for the top lists is misleading. // For this, we go back the entire path and change the original request to blocked From 0e6b5a66a721fe62db8eef7c461e0f7137b7f2fc Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 13 Jul 2020 20:43:19 +0200 Subject: [PATCH 2/7] Log CNAME blocking to pihole.log Signed-off-by: DL6ER --- src/dnsmasq/cache.c | 29 +++++++++++++---------------- src/dnsmasq/rfc1035.c | 6 ++++-- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/dnsmasq/cache.c b/src/dnsmasq/cache.c index e294813d..797b66ab 100644 --- a/src/dnsmasq/cache.c +++ b/src/dnsmasq/cache.c @@ -1965,22 +1965,7 @@ void _log_query(unsigned int flags, char *name, union all_addr *addr, char *arg, if (strlen(name) == 0) name = "."; /************************************************************** Pi-hole modification **************************************************************/ -if(debug_dnsmasq_lines == 0) -{ -/***************************************************************************************************************************************************/ - if (option_bool(OPT_EXTRALOG)) - { - int port = prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2); - if (flags & F_NOEXTRA) - my_syslog(LOG_INFO, "* %s/%u %s %s %s %s", daemon->addrbuff2, port, source, name, verb, dest); - else - my_syslog(LOG_INFO, "%u %s/%u %s %s %s %s", daemon->log_display_id, daemon->addrbuff2, port, source, name, verb, dest); - } - else - my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest); -/************************************************************** Pi-hole modification **************************************************************/ -} -else +if(debug_dnsmasq_lines != 0) { if (option_bool(OPT_EXTRALOG)) { @@ -1992,8 +1977,20 @@ else } else my_syslog(LOG_INFO, "%s %s %s %s (%s:%d)", source, name, verb, dest, file, line); + + return; } /***************************************************************************************************************************************************/ + if (option_bool(OPT_EXTRALOG)) + { + int port = prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2); + if (flags & F_NOEXTRA) + my_syslog(LOG_INFO, "* %s/%u %s %s %s %s", daemon->addrbuff2, port, source, name, verb, dest); + else + my_syslog(LOG_INFO, "%u %s/%u %s %s %s %s", daemon->log_display_id, daemon->addrbuff2, port, source, name, verb, dest); + } + else + my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest); } diff --git a/src/dnsmasq/rfc1035.c b/src/dnsmasq/rfc1035.c index 7cf06626..4bcff034 100644 --- a/src/dnsmasq/rfc1035.c +++ b/src/dnsmasq/rfc1035.c @@ -785,8 +785,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t // ****************************** Pi-hole modification ****************************** if(FTL_CNAME(name, cpp, daemon->log_display_id)) { - // This query is to be blocked as we found a blocked domain while walking - // the CNAME path. + // This query is to be blocked as we found a blocked + // domain while walking the CNAME path. + // Log to pihole.log: "cached domainabc.com is blocked (Pi-hole CNAME inspection)" + log_query(F_UPSTREAM, name, NULL, "blocked during CNAME inspection"); return 2; } // ********************************************************************************** From be3c75d1fbec834b54d3d638d1af82f80398e4c7 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 13 Jul 2020 22:06:25 +0200 Subject: [PATCH 3/7] Include new column in database schema test Signed-off-by: DL6ER --- test/test_suite.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_suite.bats b/test/test_suite.bats index d56b4661..9d9ad37a 100644 --- a/test/test_suite.bats +++ b/test/test_suite.bats @@ -339,7 +339,7 @@ @test "pihole-FTL.db schema as expected" { run bash -c 'sqlite3 /etc/pihole/pihole-FTL.db .dump' printf "%s\n" "${lines[@]}" - [[ "${lines[@]}" == *"CREATE TABLE queries ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER NOT NULL, type INTEGER NOT NULL, status INTEGER NOT NULL, domain TEXT NOT NULL, client TEXT NOT NULL, forward TEXT );"* ]] + [[ "${lines[@]}" == *"CREATE TABLE queries ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER NOT NULL, type INTEGER NOT NULL, status INTEGER NOT NULL, domain TEXT NOT NULL, client TEXT NOT NULL, forward TEXT , additional_info TEXT);"* ]] [[ "${lines[@]}" == *"CREATE TABLE ftl ( id INTEGER PRIMARY KEY NOT NULL, value BLOB NOT NULL );"* ]] [[ "${lines[@]}" == *"CREATE TABLE counters ( id INTEGER PRIMARY KEY NOT NULL, value INTEGER NOT NULL );"* ]] [[ "${lines[@]}" == *"CREATE TABLE IF NOT EXISTS \"network\" ( id INTEGER PRIMARY KEY NOT NULL, hwaddr TEXT UNIQUE NOT NULL, interface TEXT NOT NULL, name TEXT, firstSeen INTEGER NOT NULL, lastQuery INTEGER NOT NULL, numQueries INTEGER NOT NULL, macVendor TEXT);"* ]] From e661bd5389242e4869b50fa02439184f06b5f14a Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 13 Jul 2020 23:12:47 +0200 Subject: [PATCH 4/7] Load domain causing the blocking in a CNAME inspection from the database during import. This ensures restarting FTL does not mean we lost this information. Signed-off-by: DL6ER --- src/database/query-table.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/database/query-table.c b/src/database/query-table.c index b4424979..af8cb5e2 100644 --- a/src/database/query-table.c +++ b/src/database/query-table.c @@ -474,15 +474,28 @@ void DB_read_queries(void) counters->unknown++; break; + case QUERY_GRAVITY_CNAME: // Blocked by gravity (inside CNAME path) + case QUERY_REGEX_CNAME: // Blocked by regex blacklist (inside CNAME path) + case QUERY_BLACKLIST_CNAME: // Blocked by exact blacklist (inside CNAME path) + { + // Load domain actually causing the blocking from the database + const char *CNAMEdomain = (const char *)sqlite3_column_text(stmt, 7); + if(CNAMEdomain != NULL && strlen(CNAMEdomain) > 0) + { + // Add domain to FTL's memory but do not count it. Seeing a + // domain in the middle of a CNAME trajectory does not mean + // it was queried intentionally. + const int CNAMEdomainID = findDomainID(CNAMEdomain, false); + query->CNAME_domainID = CNAMEdomainID; + } + } + // fall through case QUERY_GRAVITY: // Blocked by gravity case QUERY_REGEX: // Blocked by regex blacklist case QUERY_BLACKLIST: // Blocked by exact blacklist case QUERY_EXTERNAL_BLOCKED_IP: // Blocked by external provider case QUERY_EXTERNAL_BLOCKED_NULL: // Blocked by external provider case QUERY_EXTERNAL_BLOCKED_NXRA: // Blocked by external provider - case QUERY_GRAVITY_CNAME: // Blocked by gravity - case QUERY_REGEX_CNAME: // Blocked by regex blacklist - case QUERY_BLACKLIST_CNAME: // Blocked by exact blacklist counters->blocked++; // Get domain pointer domainsData* domain = getDomain(domainID, true); From 42e9ccc4890d9c4b3b0a83c8a988384114781be3 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Tue, 14 Jul 2020 18:44:22 +0200 Subject: [PATCH 5/7] Store + import ID of regex used for blocking in additional_info field Signed-off-by: DL6ER --- src/database/query-table.c | 60 ++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/src/database/query-table.c b/src/database/query-table.c index af8cb5e2..48cb2c65 100644 --- a/src/database/query-table.c +++ b/src/database/query-table.c @@ -169,15 +169,25 @@ void DB_save_queries(void) sqlite3_bind_null(stmt, 6); } - // Fill additional information column + // ADDITIONAL_INFO if(query->status == QUERY_GRAVITY_CNAME || query->status == QUERY_REGEX_CNAME || query->status == QUERY_BLACKLIST_CNAME) { - // Get domain blocked during deep CNAME inspection, if applicable + // Restore domain blocked during deep CNAME inspection if applicable const char* cname = getCNAMEDomainString(query); sqlite3_bind_text(stmt, 7, cname, -1, SQLITE_STATIC); } + else if(query->status == QUERY_REGEX) + { + // Restore regex ID if applicable + const int cacheID = findCacheID(query->domainID, query->clientID); + DNSCacheData *cache = getDNSCache(cacheID, true); + if(cache != NULL) + sqlite3_bind_int(stmt, 7, cache->black_regex_idx); + else + sqlite3_bind_null(stmt, 7); + } else { // Nothing to add here @@ -467,6 +477,33 @@ void DB_read_queries(void) // Increase DNS queries counter counters->queries++; + // Get additional information from the additional_info column if applicable + if(status == QUERY_GRAVITY_CNAME || + status == QUERY_REGEX_CNAME || + status == QUERY_BLACKLIST_CNAME) + { + // QUERY_*_CNAME: Getdomain causing the blocking + const char *CNAMEdomain = (const char *)sqlite3_column_text(stmt, 7); + if(CNAMEdomain != NULL && strlen(CNAMEdomain) > 0) + { + // Add domain to FTL's memory but do not count it. Seeing a + // domain in the middle of a CNAME trajectory does not mean + // it was queried intentionally. + const int CNAMEdomainID = findDomainID(CNAMEdomain, false); + query->CNAME_domainID = CNAMEdomainID; + } + } + else if(status == QUERY_REGEX) + { + // QUERY_REGEX: Set ID regex which was the reson for blocking + const int cacheID = findCacheID(query->domainID, query->clientID); + const DNSCacheData *cache = getDNSCache(cacheID, true); + if(cache != NULL) + sqlite3_bind_int(stmt, 7, cache->black_regex_idx); + else + sqlite3_bind_null(stmt, 7); + } + // Increment status counters switch(status) { @@ -474,28 +511,15 @@ void DB_read_queries(void) counters->unknown++; break; - case QUERY_GRAVITY_CNAME: // Blocked by gravity (inside CNAME path) - case QUERY_REGEX_CNAME: // Blocked by regex blacklist (inside CNAME path) - case QUERY_BLACKLIST_CNAME: // Blocked by exact blacklist (inside CNAME path) - { - // Load domain actually causing the blocking from the database - const char *CNAMEdomain = (const char *)sqlite3_column_text(stmt, 7); - if(CNAMEdomain != NULL && strlen(CNAMEdomain) > 0) - { - // Add domain to FTL's memory but do not count it. Seeing a - // domain in the middle of a CNAME trajectory does not mean - // it was queried intentionally. - const int CNAMEdomainID = findDomainID(CNAMEdomain, false); - query->CNAME_domainID = CNAMEdomainID; - } - } - // fall through case QUERY_GRAVITY: // Blocked by gravity case QUERY_REGEX: // Blocked by regex blacklist case QUERY_BLACKLIST: // Blocked by exact blacklist case QUERY_EXTERNAL_BLOCKED_IP: // Blocked by external provider case QUERY_EXTERNAL_BLOCKED_NULL: // Blocked by external provider case QUERY_EXTERNAL_BLOCKED_NXRA: // Blocked by external provider + case QUERY_GRAVITY_CNAME: // Blocked by gravity (inside CNAME path) + case QUERY_REGEX_CNAME: // Blocked by regex blacklist (inside CNAME path) + case QUERY_BLACKLIST_CNAME: // Blocked by exact blacklist (inside CNAME path) counters->blocked++; // Get domain pointer domainsData* domain = getDomain(domainID, true); From cfda3a0b2f42a9219b60c883e68c895da27ebe0e Mon Sep 17 00:00:00 2001 From: DL6ER Date: Tue, 14 Jul 2020 18:56:56 +0200 Subject: [PATCH 6/7] Fix an edge-case where CNAME blocking can be foiled when parts of the CNAME chain are already in the cache Signed-off-by: DL6ER --- src/dnsmasq/rfc1035.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/dnsmasq/rfc1035.c b/src/dnsmasq/rfc1035.c index 4bcff034..d0df42bc 100644 --- a/src/dnsmasq/rfc1035.c +++ b/src/dnsmasq/rfc1035.c @@ -1819,6 +1819,15 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, FTL_cache(crecp->flags & ~F_REVERSE, name, &crecp->addr, record_source(crecp->uid), daemon->log_display_id); + // ****************************** Pi-hole modification ****************************** + if(FTL_CNAME(name, crecp, daemon->log_display_id)) + { + // This query is to be blocked as we found a blocked domain while walking the CNAME path. + // Log to pihole.log: "cached domainabc.com is blocked (Pi-hole CNAME inspection)" + log_query(F_UPSTREAM, name, NULL, "blocked during CNAME inspection"); + break; + } + // ********************************************************************************** if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, crec_ttl(crecp, now), NULL, type, C_IN, From 4a4681318c422cfb6479882a11e50aefea4b98ea Mon Sep 17 00:00:00 2001 From: DL6ER Date: Tue, 14 Jul 2020 19:05:14 +0200 Subject: [PATCH 7/7] Fix incorrect attribution of the blocked status to the wrong domain. This also simplifies the terminology in the CNAME inspection routine. Signed-off-by: DL6ER --- src/dnsmasq_interface.c | 95 +++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 41 deletions(-) diff --git a/src/dnsmasq_interface.c b/src/dnsmasq_interface.c index 8e9d8564..17371dc6 100644 --- a/src/dnsmasq_interface.c +++ b/src/dnsmasq_interface.c @@ -60,14 +60,14 @@ char debug_dnsmasq_lines = 0; unsigned char* pihole_privacylevel = &config.privacylevel; const char flagnames[][12] = {"F_IMMORTAL ", "F_NAMEP ", "F_REVERSE ", "F_FORWARD ", "F_DHCP ", "F_NEG ", "F_HOSTS ", "F_IPV4 ", "F_IPV6 ", "F_BIGNAME ", "F_NXDOMAIN ", "F_CNAME ", "F_DNSKEY ", "F_CONFIG ", "F_DS ", "F_DNSSECOK ", "F_UPSTREAM ", "F_RRNAME ", "F_SERVER ", "F_QUERY ", "F_NOERR ", "F_AUTH ", "F_DNSSEC ", "F_KEYTAG ", "F_SECSTAT ", "F_NO_RR ", "F_IPSET ", "F_NOEXTRA ", "F_SERVFAIL", "F_RCODE"}; -static bool check_domain_blocked(const char *domainString, const int clientID, +static bool check_domain_blocked(const char *domain, const int clientID, clientsData *client, queriesData *query, DNSCacheData *dns_cache, const char **blockingreason, unsigned char *new_status) { // Check domains against exact blacklist // Skipped when the domain is whitelisted bool blockDomain = false; - if(in_blacklist(domainString, clientID, client)) + if(in_blacklist(domain, clientID, client)) { // We block this domain blockDomain = true; @@ -82,7 +82,7 @@ static bool check_domain_blocked(const char *domainString, const int clientID, // Check domains against gravity domains // Skipped when the domain is whitelisted or blocked by exact blacklist if(!query->whitelisted && !blockDomain && - in_gravity(domainString, clientID, client)) + in_gravity(domain, clientID, client)) { // We block this domain blockDomain = true; @@ -98,7 +98,7 @@ static bool check_domain_blocked(const char *domainString, const int clientID, // Skipped when the domain is whitelisted or blocked by exact blacklist or gravity int regex_idx = 0; if(!query->whitelisted && !blockDomain && - (regex_idx = match_regex(domainString, clientID, REGEX_BLACKLIST)) > -1) + (regex_idx = match_regex(domain, clientID, REGEX_BLACKLIST)) > -1) { // We block this domain blockDomain = true; @@ -250,27 +250,27 @@ static bool _FTL_check_blocking(int queryID, int domainID, int clientID, const c } // Check whitelist (exact + regex) for match - const char *domainString = getstr(domain->domainpos); - const char *blockedDomain = domainString; - query->whitelisted = in_whitelist(domainString, clientID, client); + const char *blockedDomain = domainstr; + query->whitelisted = in_whitelist(domainstr, clientID, client); bool blockDomain = false; unsigned char new_status = QUERY_UNKNOWN; + // Check blacklist (exact + regex) and gravity for queried domain if(!query->whitelisted) { - blockDomain = check_domain_blocked(domainString, clientID, client, query, dns_cache, blockingreason, &new_status); + blockDomain = check_domain_blocked(domainstr, clientID, client, query, dns_cache, blockingreason, &new_status); } // Check blacklist (exact + regex) and gravity for _esni.domain if enabled (defaulting to true) - if(config.block_esni && !query->whitelisted && !blockDomain && strncasecmp(domainString, "_esni.", 6u) == 0) + if(config.block_esni && !query->whitelisted && !blockDomain && strncasecmp(domainstr, "_esni.", 6u) == 0) { - blockDomain = check_domain_blocked(domainString + 6u, clientID, client, query, dns_cache, blockingreason, &new_status); + blockDomain = check_domain_blocked(domainstr + 6u, clientID, client, query, dns_cache, blockingreason, &new_status); if(blockDomain) { // Truncate "_esni." from queried domain if the parenting domain was the reason for blocking this query - blockedDomain = domainString + 6u; + blockedDomain = domainstr + 6u; // Force next DNS reply to be NXDOMAIN for _esni.* queries force_next_DNS_reply = NXDOMAIN; dns_cache->force_reply = NXDOMAIN; @@ -285,7 +285,7 @@ static bool _FTL_check_blocking(int queryID, int domainID, int clientID, const c // Debug output if(config.debug & DEBUG_QUERIES) - logg("Blocking %s as %s is %s", domainString, blockedDomain, *blockingreason); + logg("Blocking %s as %s is %s", domainstr, blockedDomain, *blockingreason); } else { @@ -339,35 +339,40 @@ bool _FTL_CNAME(const char *domain, const struct crec *cpp, const int id, const return false; } - // Go through already knows domains and see if it is one of them - // As this domain might have been found in the middle of a CNAME-path, - // it may be not have been seen by FTL_new_query() before - char *domainString = strdup(domain); - strtolower(domainString); - const int domainID = findDomainID(domainString, false); + // Example to make the terminology used in here clear: + // CNAME abc -> 123 + // CNAME 123 -> 456 + // CNAME 456 -> 789 + // parent_domain: abc + // child_domains: [123, 456, 789] - // Get client ID from original query + // parent_domain = Domain at the top of the CNAME path + // This is the domain which was queried first in this chain + const int parent_domainID = query->domainID; + + // child_domain = Intermediate domain in CNAME path + // This is the domain which was queried later in this chain + char *child_domain = strdup(domain); + // Convert to lowercase for matching + strtolower(child_domain); + const int child_domainID = findDomainID(child_domain, false); + + // Get client ID from the original query (the entire chain always + // belongs to the same client) const int clientID = query->clientID; - // Perform per-client blocking evaluation for this domain. The result for this - // domain-client combination will be cached to be immediately available for later - // queries of the same domain by the same client + // Check per-client blocking for the child domain const char *blockingreason = NULL; - bool block = FTL_check_blocking(queryID, domainID, clientID, &blockingreason); + const bool block = FTL_check_blocking(queryID, child_domainID, clientID, &blockingreason); // If we find during a CNAME inspection that we want to block the entire chain, - // the originally queried domain itself was not counted as blocked (but as - // permitted). Later in the chain, when we find that this is a bad guy, we - // short-circuit it. We need to correct the domain counter of the domain at the - // head of the chain, otherwise, the data for the top lists is misleading. - // For this, we go back the entire path and change the original request to blocked - // by increasing the blocked count of this domain by one. Fortunately, each CNAME - // path can easily be tracked back to the original head in FTL's data so we do not - // need to search it. This makes the change able to happen without causing any delay. + // the originally queried domain itself was not counted as blocked. We have to + // correct this when we are going to short-circuit the entire query if(block) { - domainsData* head_domain = getDomain(query->domainID, true); - head_domain->blockedcount++; + // Increase blocked count of parent domain + domainsData* parent_domain = getDomain(parent_domainID, true); + parent_domain->blockedcount++; // Store query response as CNAME type struct timeval response; @@ -375,29 +380,37 @@ bool _FTL_CNAME(const char *domain, const struct crec *cpp, const int id, const save_reply_type(F_CNAME, NULL, query, response); // Store domain that was the reason for blocking the entire chain - query->CNAME_domainID = domainID; + query->CNAME_domainID = child_domainID; // Change blocking reason into CNAME-caused blocking if(query->status == QUERY_GRAVITY) + { query->status = QUERY_GRAVITY_CNAME; + } else if(query->status == QUERY_REGEX) { // Get parent and child DNS cache entries - unsigned int parent_cacheID = findCacheID(domainID, query->clientID); - unsigned int child_cacheID = findCacheID(query->domainID, query->clientID); + const int parent_cacheID = findCacheID(parent_domainID, clientID); + const int child_cacheID = findCacheID(child_domainID, clientID); // Get cache pointers - DNSCacheData *parent_dns_cache = getDNSCache(parent_cacheID, true); - DNSCacheData *child_dns_cache = getDNSCache(child_cacheID, true); + DNSCacheData *parent_cache = getDNSCache(parent_cacheID, true); + DNSCacheData *child_cache = getDNSCache(child_cacheID, true); // Propagate ID of responsible regex up from the child to the parent domain - if(parent_dns_cache != NULL && child_dns_cache != NULL) - child_dns_cache->black_regex_idx = parent_dns_cache->black_regex_idx; + if(parent_cache != NULL && child_cache != NULL) + { + child_cache->black_regex_idx = parent_cache->black_regex_idx; + } + // Set status query->status = QUERY_REGEX_CNAME; } else if(query->status == QUERY_BLACKLIST) + { + // Only set status query->status = QUERY_BLACKLIST_CNAME; + } } // Debug logging for deep CNAME inspection (if enabled) @@ -410,7 +423,7 @@ bool _FTL_CNAME(const char *domain, const struct crec *cpp, const int id, const } // Return result - free(domainString); + free(child_domain); unlock_shm(); return block; }