From dd773b0d2ff114ec079228514a879c2a5b56e8d2 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 13 Feb 2021 16:49:37 +0100 Subject: [PATCH] Fix queries sent upstream being counted incorrectly when modified later on (blocked externally, blocked during CNAME inspection). This also applies to queries loaded from the database. Signed-off-by: DL6ER --- src/database/query-table.c | 17 +++++++++++------ src/datastructure.c | 14 ++------------ src/datastructure.h | 2 +- src/dnsmasq_interface.c | 38 ++++++++++++++++++-------------------- 4 files changed, 32 insertions(+), 39 deletions(-) diff --git a/src/database/query-table.c b/src/database/query-table.c index cbbc87df..d31f7e67 100644 --- a/src/database/query-table.c +++ b/src/database/query-table.c @@ -388,12 +388,11 @@ void DB_read_queries(void) continue; } - const char *upstream = NULL; + const char *buffer = NULL; int upstreamID = -1; // Default if not forwarded - // Determine upstreamID only when status == 2 (forwarded) as the - // field need not to be filled for other query status types + // Try to extract the upstream from the "forward" column if non-empty if(sqlite3_column_bytes(stmt, 6) > 0 && - (upstream = (const char *)sqlite3_column_text(stmt, 6)) != NULL) + (buffer = (const char *)sqlite3_column_text(stmt, 6)) != NULL) { // Get IP address and port of upstream destination char serv_addr[INET6_ADDRSTRLEN] = { 0 }; @@ -401,9 +400,9 @@ void DB_read_queries(void) // We limit the number of bytes written into the serv_addr buffer // to prevent buffer overflows. If there is no port available in // the database, we skip extracting them and use the default port - sscanf(upstream, "%"xstr(INET6_ADDRSTRLEN)"[^#]#%u", serv_addr, &serv_port); + sscanf(buffer, "%"xstr(INET6_ADDRSTRLEN)"[^#]#%u", serv_addr, &serv_port); serv_addr[INET6_ADDRSTRLEN-1] = '\0'; - upstreamID = findUpstreamID(serv_addr, (in_port_t)serv_port, true); + upstreamID = findUpstreamID(serv_addr, (in_port_t)serv_port); } // Obtain IDs only after filtering which queries we want to keep @@ -524,6 +523,12 @@ void DB_read_queries(void) case QUERY_FORWARDED: // Forwarded counters->forwarded++; + upstreamsData *upstream = getUpstream(upstreamID, true); + if(upstream != NULL) + { + upstream->count++; + upstream->lastQuery = queryTimeStamp; + } // Update overTime data structure overTime[timeidx].forwarded++; break; diff --git a/src/datastructure.c b/src/datastructure.c index cd009373..4f1adc2d 100644 --- a/src/datastructure.c +++ b/src/datastructure.c @@ -69,7 +69,7 @@ int findQueryID(const int id) return -1; } -int findUpstreamID(const char * upstreamString, const in_port_t port, const bool count) +int findUpstreamID(const char * upstreamString, const in_port_t port) { // Go through already knows upstream servers and see if we used one of those for(int upstreamID=0; upstreamID < counters->upstreams; upstreamID++) @@ -82,14 +82,7 @@ int findUpstreamID(const char * upstreamString, const in_port_t port, const bool continue; if(strcmp(getstr(upstream->ippos), upstreamString) == 0 && upstream->port == port) - { - if(count) - { - upstream->count++; - upstream->lastQuery = time(NULL); - } return upstreamID; - } } // This upstream server is not known // Store ID @@ -110,10 +103,7 @@ int findUpstreamID(const char * upstreamString, const in_port_t port, const bool // Set magic byte upstream->magic = MAGICBYTE; // Initialize its counter - if(count) - upstream->count = 1; - else - upstream->count = 0; + upstream->count = 0; // Save upstream destination IP address upstream->ippos = addstr(upstreamString); upstream->failed = 0; diff --git a/src/datastructure.h b/src/datastructure.h index e8e77f68..3f8302b2 100644 --- a/src/datastructure.h +++ b/src/datastructure.h @@ -111,7 +111,7 @@ ASSERT_SIZEOF(DNSCacheData, 16, 16, 16); void strtolower(char *str); int findQueryID(const int id); -int findUpstreamID(const char * upstream, const in_port_t port, const bool count); +int findUpstreamID(const char * upstream, const in_port_t port); int findDomainID(const char *domain, const bool count); int findClientID(const char *client, const bool count, const bool aliasclient); int findCacheID(int domainID, int clientID, enum query_types query_type); diff --git a/src/dnsmasq_interface.c b/src/dnsmasq_interface.c index eafb3701..3c629558 100644 --- a/src/dnsmasq_interface.c +++ b/src/dnsmasq_interface.c @@ -867,9 +867,19 @@ void _FTL_forwarded(const unsigned int flags, const char *name, const struct ser // Get ID of upstream destination, create new upstream record // if not found in current data structure - const int upstreamID = findUpstreamID(upstreamIP, upstreamPort, true); + const int upstreamID = findUpstreamID(upstreamIP, upstreamPort); query->upstreamID = upstreamID; + upstreamsData *upstream = getUpstream(upstreamID, true); + if(upstream != NULL) + { + upstream->count++; + upstream->lastQuery = time(NULL); + } + + // Update counter for forwarded queries + counters->forwarded++; + // Get time index for this query const unsigned int timeidx = query->timeidx; @@ -920,9 +930,6 @@ void _FTL_forwarded(const unsigned int flags, const char *name, const struct ser // Update overTime data overTime[timeidx].forwarded++; - // Update counter for forwarded queries - counters->forwarded++; - // Release allocated memory free(upstreamIP); @@ -1258,9 +1265,6 @@ static void query_externally_blocked(const int queryID, const enum query_status return; } - // Get time index - const unsigned int timeidx = query->timeidx; - // If query is already known to be externally blocked, // then we have nothing to do here if(query->status == QUERY_EXTERNAL_BLOCKED_IP || @@ -1268,18 +1272,6 @@ static void query_externally_blocked(const int queryID, const enum query_status query->status == QUERY_EXTERNAL_BLOCKED_NXRA) return; - // Correct counters if necessary ... - if(query->status == QUERY_FORWARDED) - { - counters->forwarded--; - overTime[timeidx].forwarded--; - - // Get forward pointer - upstreamsData* upstream = getUpstream(query->upstreamID, true); - if(upstream != NULL) - upstream->count--; - } - // Mark query as blocked domainsData* domain = getDomain(query->domainID, true); clientsData* client = getClient(query->clientID, true); @@ -1427,6 +1419,12 @@ static void query_blocked(queriesData* query, domainsData* domain, clientsData* else if(query->status == QUERY_FORWARDED) { counters->forwarded--; + overTime[query->timeidx].forwarded--; + + // Get forward pointer + upstreamsData* upstream = getUpstream(query->upstreamID, true); + if(upstream != NULL) + upstream->count--; } else if(query->status == QUERY_CACHE) { @@ -1883,7 +1881,7 @@ void FTL_forwarding_retried(const struct server *serv, const int oldID, const in strtolower(upstreamIP); // Get upstream ID - const int upstreamID = findUpstreamID(upstreamIP, upstreamPort, false); + const int upstreamID = findUpstreamID(upstreamIP, upstreamPort); // Possible debugging information if(config.debug & DEBUG_QUERIES)