Skip to content

Commit 392db95

Browse files
authored
Merge pull request #1607 from pi-hole/tweak/query_details
Provide regex ID for API
2 parents 9079c4e + 4f1a9dd commit 392db95

File tree

9 files changed

+121
-91
lines changed

9 files changed

+121
-91
lines changed

src/api/docs/content/specs/queries.yaml

+4-8
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,10 @@ components:
208208
time:
209209
type: number
210210
description: Time until the response was received (ms, negative if N/A)
211-
ttl:
212-
type: integer
213-
description: Query's Time-To-Live (TTL) value (`-1` if N/A)
214211
regex_id:
215212
type: integer
216-
description: ID of blocking regex (`-1` if N/A)
213+
description: ID of regex (`NULL` if N/A)
214+
nullable: true
217215
upstream:
218216
type: string
219217
description: IP or name + port of upstream server
@@ -231,8 +229,7 @@ components:
231229
reply:
232230
type: "IP"
233231
time: 19
234-
ttl: -1
235-
regex_id: -1
232+
regex_id: NULL
236233
upstream: "localhost#5353"
237234
dbid: 112421354
238235
- time: 1581907871.583821
@@ -247,8 +244,7 @@ components:
247244
reply:
248245
type: "IP"
249246
time: 12.3
250-
ttl: 7
251-
regex_id: -1
247+
regex_id: NULL
252248
upstream: "localhost#5353"
253249
dbid: 112421355
254250
cursor:

src/api/queries.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ int api_queries_suggestions(struct ftl_conn *api)
174174
JSON_SEND_OBJECT(json);
175175
}
176176

177-
#define QUERYSTR "SELECT q.id,timestamp,q.type,status,d.domain,f.forward,additional_info,reply_type,reply_time,dnssec,c.ip,c.name,a.content" // ttl, regex_id
177+
#define QUERYSTR "SELECT q.id,timestamp,q.type,status,d.domain,f.forward,additional_info,reply_type,reply_time,dnssec,c.ip,c.name,a.content,regex_id"
178178
// JOIN: Only return rows where there is a match in BOTH tables
179179
// LEFT JOIN: Return all rows from the left table, and the matched rows from the right table
180180
#define JOINSTR "JOIN client_by_id c ON q.client = c.id JOIN domain_by_id d ON q.domain = d.id LEFT JOIN forward_by_id f ON q.forward = f.id LEFT JOIN addinfo_by_id a ON a.id = q.additional_info"
@@ -692,8 +692,11 @@ int api_queries(struct ftl_conn *api)
692692
JSON_ADD_NULL_TO_OBJECT(client, "name");
693693
JSON_ADD_ITEM_TO_OBJECT(item, "client", client);
694694

695-
JSON_ADD_NUMBER_TO_OBJECT(item, "ttl", 0); // sqlite3_column_int(read_stmt, 12));
696-
JSON_ADD_NUMBER_TO_OBJECT(item, "regex_id", 0); // sqlite3_column_int(read_stmt, 13));
695+
// Add regex_id if it exists
696+
if(sqlite3_column_type(read_stmt, 13) == SQLITE_INTEGER)
697+
JSON_ADD_NUMBER_TO_OBJECT(item, "regex_id", sqlite3_column_int(read_stmt, 13));
698+
else
699+
JSON_ADD_NULL_TO_OBJECT(item, "regex_id");
697700

698701
const unsigned char *cname = NULL;
699702
switch(query.status)

src/database/common.c

+15
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,21 @@ void db_init(void)
478478
dbversion = db_get_int(db, DB_VERSION);
479479
}
480480

481+
// Update to version 13 if lower
482+
if(dbversion < 13)
483+
{
484+
// Update to version 13: Add additional column for regex ID
485+
log_info("Updating long-term database to version 13");
486+
if(!add_query_storage_column_regex_id(db))
487+
{
488+
log_info("Additional records not generated, database not available");
489+
dbclose(&db);
490+
return;
491+
}
492+
// Get updated version
493+
dbversion = db_get_int(db, DB_VERSION);
494+
}
495+
481496
lock_shm();
482497
import_aliasclients(db);
483498
unlock_shm();

src/database/query-table.c

+58-40
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,38 @@ bool add_query_storage_columns(sqlite3 *db)
710710
return true;
711711
}
712712

713+
bool add_query_storage_column_regex_id(sqlite3 *db)
714+
{
715+
// Start transaction of database update
716+
SQL_bool(db, "BEGIN TRANSACTION");
717+
718+
// Add additional column to the query_storage table
719+
SQL_bool(db, "ALTER TABLE query_storage ADD COLUMN regex_id INTEGER");
720+
721+
// Update VIEW queries
722+
SQL_bool(db, "DROP VIEW queries");
723+
SQL_bool(db, "CREATE VIEW queries AS "
724+
"SELECT id, timestamp, type, status, "
725+
"CASE typeof(domain) WHEN 'integer' THEN (SELECT domain FROM domain_by_id d WHERE d.id = q.domain) ELSE domain END domain,"
726+
"CASE typeof(client) WHEN 'integer' THEN (SELECT ip FROM client_by_id c WHERE c.id = q.client) ELSE client END client,"
727+
"CASE typeof(forward) WHEN 'integer' THEN (SELECT forward FROM forward_by_id f WHERE f.id = q.forward) ELSE forward END forward,"
728+
"CASE typeof(additional_info) WHEN 'integer' THEN (SELECT content FROM addinfo_by_id a WHERE a.id = q.additional_info) ELSE additional_info END additional_info, "
729+
"reply_type, reply_time, dnssec, regex_id "
730+
"FROM query_storage q");
731+
732+
// Update database version to 13
733+
if(!db_set_FTL_property(db, DB_VERSION, 13))
734+
{
735+
log_err("add_query_storage_column_regex_id(): Failed to update database version!");
736+
return false;
737+
}
738+
739+
// Finish transaction
740+
SQL_bool(db, "COMMIT");
741+
742+
return true;
743+
}
744+
713745
bool optimize_queries_table(sqlite3 *db)
714746
{
715747
// Start transaction of database update
@@ -1208,7 +1240,8 @@ bool queries_to_database(void)
12081240
"(SELECT id FROM addinfo_by_id WHERE type = ?9 AND content = ?10),"
12091241
"?11," \
12101242
"?12," \
1211-
"?13)", -1, SQLITE_PREPARE_PERSISTENT, &query_stmt, NULL);
1243+
"?13," \
1244+
"?14)", -1, SQLITE_PREPARE_PERSISTENT, &query_stmt, NULL);
12121245
if( rc != SQLITE_OK )
12131246
{
12141247
log_err("queries_to_database(query_storage) - SQL error step: %s", sqlite3_errstr(rc));
@@ -1380,10 +1413,14 @@ bool queries_to_database(void)
13801413
sqlite3_bind_null(query_stmt, 8);
13811414
}
13821415

1416+
// Get cache entry for this query
1417+
const int cacheID = findCacheID(query->domainID, query->clientID, query->type, false);
1418+
DNSCacheData *cache = cacheID < 0 ? NULL : getDNSCache(cacheID, true);
1419+
13831420
// ADDITIONAL_INFO
13841421
if(query->status == QUERY_GRAVITY_CNAME ||
1385-
query->status == QUERY_REGEX_CNAME ||
1386-
query->status == QUERY_DENYLIST_CNAME)
1422+
query->status == QUERY_REGEX_CNAME ||
1423+
query->status == QUERY_DENYLIST_CNAME)
13871424
{
13881425
// Save domain blocked during deep CNAME inspection
13891426
const char *cname = getCNAMEDomainString(query);
@@ -1403,30 +1440,23 @@ bool queries_to_database(void)
14031440
break;
14041441
}
14051442
}
1406-
else if(query->status == QUERY_REGEX)
1443+
else if(cache != NULL && query->status == QUERY_REGEX)
14071444
{
14081445
// Restore regex ID if applicable
1409-
const int cacheID = findCacheID(query->domainID, query->clientID, query->type, false);
1410-
DNSCacheData *cache = getDNSCache(cacheID, true);
1411-
if(cache != NULL)
1446+
sqlite3_bind_int(query_stmt, 9, ADDINFO_REGEX_ID);
1447+
sqlite3_bind_int(query_stmt, 10, cache->domainlist_id);
1448+
1449+
// Execute prepared addinfo statement and check if successful
1450+
sqlite3_bind_int(addinfo_stmt, 1, ADDINFO_REGEX_ID);
1451+
sqlite3_bind_int(addinfo_stmt, 2, cache->domainlist_id);
1452+
rc = sqlite3_step(addinfo_stmt);
1453+
sqlite3_clear_bindings(addinfo_stmt);
1454+
sqlite3_reset(addinfo_stmt);
1455+
if(rc != SQLITE_DONE)
14121456
{
1413-
sqlite3_bind_int(query_stmt, 9, ADDINFO_REGEX_ID);
1414-
sqlite3_bind_int(query_stmt, 10, cache->domainlist_id);
1415-
1416-
// Execute prepared addinfo statement and check if successful
1417-
sqlite3_bind_int(addinfo_stmt, 1, ADDINFO_REGEX_ID);
1418-
sqlite3_bind_int(addinfo_stmt, 2, cache->domainlist_id);
1419-
rc = sqlite3_step(addinfo_stmt);
1420-
sqlite3_clear_bindings(addinfo_stmt);
1421-
sqlite3_reset(addinfo_stmt);
1422-
if(rc != SQLITE_DONE)
1423-
{
1424-
log_err("Encountered error while trying to store addinfo");
1425-
break;
1426-
}
1457+
log_err("Encountered error while trying to store addinfo");
1458+
break;
14271459
}
1428-
else
1429-
sqlite3_bind_null(query_stmt, 9);
14301460
}
14311461
else
14321462
{
@@ -1449,25 +1479,13 @@ bool queries_to_database(void)
14491479
// DNSSEC
14501480
sqlite3_bind_int(query_stmt, 13, query->dnssec);
14511481

1452-
/* // TTL
1453-
sqlite3_bind_int(query_stmt, 14, query->ttl);
1454-
14551482
// REGEX_ID
1456-
if(query->status == QUERY_REGEX)
1457-
{
1458-
// Restore regex ID if applicable
1459-
const int cacheID = findCacheID(query->domainID, query->clientID, query->type);
1460-
DNSCacheData *cache = getDNSCache(cacheID, true);
1461-
if(cache != NULL)
1462-
sqlite3_bind_int(query_stmt, 15, cache->deny_regex_id);
1463-
else
1464-
sqlite3_bind_null(query_stmt, 15);
1465-
}
1483+
if(cache != NULL && cache->domainlist_id > -1)
1484+
sqlite3_bind_int(query_stmt, 14, cache->domainlist_id);
14661485
else
1467-
{
1468-
sqlite3_bind_null(query_stmt, 15);
1469-
}
1470-
*/
1486+
// Not applicable, setting NULL
1487+
sqlite3_bind_null(query_stmt, 14);
1488+
14711489
// Step and check if successful
14721490
rc = sqlite3_step(query_stmt);
14731491
sqlite3_clear_bindings(query_stmt);

src/database/query-table.h

+8-6
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"client TEXT NOT NULL, " \
2424
"forward TEXT );"
2525

26-
#define CREATE_QUERY_STORAGE_TABLE_V12 "CREATE TABLE query_storage ( id INTEGER PRIMARY KEY AUTOINCREMENT, " \
26+
#define CREATE_QUERY_STORAGE_TABLE_V13 "CREATE TABLE query_storage ( id INTEGER PRIMARY KEY AUTOINCREMENT, " \
2727
"timestamp INTEGER NOT NULL, " \
2828
"type INTEGER NOT NULL, " \
2929
"status INTEGER NOT NULL, " \
@@ -33,9 +33,10 @@
3333
"additional_info INTEGER, " \
3434
"reply_type INTEGER, " \
3535
"reply_time REAL, " \
36-
"dnssec INTEGER );"
36+
"dnssec INTEGER, " \
37+
"regex_id INTEGER );"
3738

38-
#define CREATE_QUERIES_VIEW_V12 "CREATE VIEW queries AS " \
39+
#define CREATE_QUERIES_VIEW_V13 "CREATE VIEW queries AS " \
3940
"SELECT id, timestamp, type, status, " \
4041
"CASE typeof(domain) " \
4142
"WHEN 'integer' THEN (SELECT domain FROM domain_by_id d WHERE d.id = q.domain) ELSE domain END domain," \
@@ -45,7 +46,7 @@
4546
"WHEN 'integer' THEN (SELECT forward FROM forward_by_id f WHERE f.id = q.forward) ELSE forward END forward," \
4647
"CASE typeof(additional_info) "\
4748
"WHEN 'integer' THEN (SELECT content FROM addinfo_by_id a WHERE a.id = q.additional_info) ELSE additional_info END additional_info, " \
48-
"reply_type, reply_time, dnssec FROM query_storage q"
49+
"reply_type, reply_time, dnssec, regex_id FROM query_storage q"
4950

5051
// Version 1
5152
#define CREATE_QUERIES_TIMESTAMP_INDEX "CREATE INDEX idx_queries_timestamp ON queries (timestamp);"
@@ -76,12 +77,12 @@
7677

7778
#ifdef QUERY_TABLE_PRIVATE
7879
const char *table_creation[] = {
79-
CREATE_QUERY_STORAGE_TABLE_V12,
80+
CREATE_QUERY_STORAGE_TABLE_V13,
8081
CREATE_DOMAINS_BY_ID,
8182
CREATE_CLIENTS_BY_ID,
8283
CREATE_FORWARD_BY_ID,
8384
CREATE_ADDINFO_BY_ID,
84-
CREATE_QUERIES_VIEW_V12,
85+
CREATE_QUERIES_VIEW_V13,
8586
};
8687
const char *index_creation[] = {
8788
CREATE_QUERY_STORAGE_ID_INDEX,
@@ -124,5 +125,6 @@ bool queries_to_database(void);
124125
bool optimize_queries_table(sqlite3 *db);
125126
bool create_addinfo_table(sqlite3 *db);
126127
bool add_query_storage_columns(sqlite3 *db);
128+
bool add_query_storage_column_regex_id(sqlite3 *db);
127129

128130
#endif //QUERY_TABLE_PRIVATE_H

src/datastructure.h

-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ typedef struct {
3333
int id; // the ID is a (signed) int in dnsmasq, so no need for a long int here
3434
int CNAME_domainID; // only valid if query has a CNAME blocking status
3535
int ede;
36-
unsigned int ttl;
3736
double response;
3837
double timestamp;
3938
int64_t db;

src/dnsmasq/rfc1035.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1975,7 +1975,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
19751975
(crecp->flags & F_HOSTS) &&
19761976
!is_same_net(crecp->addr.addr4, local_addr, local_netmask))
19771977
continue;
1978-
1978+
19791979
ans = 1;
19801980
if (!dryrun)
19811981
{
@@ -1994,7 +1994,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
19941994
break;
19951995
}
19961996
// **********************************************************************************
1997-
1997+
19981998
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
19991999
crec_ttl(crecp, now), NULL, type, C_IN,
20002000
type == T_A ? "4" : "6", &crecp->addr))

0 commit comments

Comments
 (0)