Add pihole-fTL gravity checkList <file> option

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER 2023-06-15 11:36:34 +02:00
parent 3e10f67a65
commit b2ad7af693
No known key found for this signature in database
GPG Key ID: 00135ACBD90B28DD
4 changed files with 60 additions and 15 deletions

View File

@ -331,7 +331,14 @@ void parse_args(int argc, char* argv[])
if(argc == 6 && strcmp(argv[2], "parseList") == 0)
{
// Parse the given list and write the result to the given file
exit(gravity_parseList(argv[3], argv[4], argv[5]));
exit(gravity_parseList(argv[3], argv[4], argv[5], true));
}
// pihole-FTL gravity checkList <infile>
if(argc == 4 && strcmp(argv[2], "checkList") == 0)
{
// Parse the given list and write the result to the given file
exit(gravity_parseList(argv[3], "", "-1", true));
}
printf("Incorrect usage of pihole-FTL gravity subcommand\n");
@ -783,11 +790,18 @@ void parse_args(int argc, char* argv[])
printf("\t%s--teleporter%s file%s Import the Teleporter archive %sfile%s\n\n", green, cyan, normal, cyan, normal);
printf("%sTLS X.509 certificate generator:%s\n", yellow, normal);
printf(" Generate a self-signed certificate suitable for SSL/TLS\n\n");
printf(" Generate a self-signed certificate suitable for SSL/TLS\n");
printf(" and store it in %soutfile%s.\n\n", cyan, normal);
printf(" By default, this new certificate is based on the elliptic\n");
printf(" curve secp521r1. If the optional flag %s[rsa]%s is specified,\n", purple, normal);
printf(" an RSA (4096 bit) key will be generated instead.\n\n");
printf(" Usage: %spihole-FTL --gen-x509 %s<outfile> %s[rsa]%s\n\n", green, yellow, purple, normal);
printf(" Usage: %spihole-FTL --gen-x509 %soutfile %s[rsa]%s\n\n", green, cyan, purple, normal);
printf("%sGravity tools:%s\n", yellow, normal);
printf(" Check domains in a given file for validity using Pi-hole's\n");
printf(" gravity filters. The expected input format is one domain\n");
printf(" per line (no HOSTS lists, etc.)\n\n");
printf(" Usage: %spihole-FTL gravity checkList %sinfile%s\n\n", green, cyan, normal);
printf("%sOther:%s\n", yellow, normal);
printf("\t%sdhcp-discover%s Discover DHCP servers in the local\n", green, normal);

View File

@ -267,7 +267,7 @@ struct mntent *get_filesystem_details(const char *path)
/* iterate through the list of devices */
FILE *file = setmntent("/proc/mounts", "r");
struct mntent *ent;
struct mntent *ent = NULL;
while(file != NULL && (ent = getmntent(file)) != NULL)
{
/* stat the mount point */

View File

@ -42,7 +42,7 @@
// Number of invalid domains to print before skipping the rest
#define MAX_INVALID_DOMAINS 5
int gravity_parseList(const char *infile, const char *outfile, const char *adlistIDstr)
int gravity_parseList(const char *infile, const char *outfile, const char *adlistIDstr, const bool checkOnly)
{
const char *info = cli_info();
const char *tick = cli_tick();
@ -60,7 +60,7 @@ int gravity_parseList(const char *infile, const char *outfile, const char *adlis
// Open output file
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
if(sqlite3_open_v2(outfile, &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK)
if(!checkOnly && sqlite3_open_v2(outfile, &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK)
{
printf("%s %s Unable to open database file %s for writing\n", over, cross, outfile);
fclose(fpin);
@ -78,7 +78,8 @@ int gravity_parseList(const char *infile, const char *outfile, const char *adlis
printf("%s %s Unable to compile regular expression to validate exact domains\n",
over, cross);
fclose(fpin);
sqlite3_close(db);
if(!checkOnly)
sqlite3_close(db);
return EXIT_FAILURE;
}
if(regcomp(&abp_regex, ABP_DOMAIN_REXEX, REG_EXTENDED) != 0)
@ -86,7 +87,8 @@ int gravity_parseList(const char *infile, const char *outfile, const char *adlis
printf("%s %s Unable to compile regular expression to validate ABP-style domains\n",
over, cross);
fclose(fpin);
sqlite3_close(db);
if(!checkOnly)
sqlite3_close(db);
return EXIT_FAILURE;
}
if(regcomp(&false_positives_regex, FALSE_POSITIVES, REG_EXTENDED | REG_NOSUB) != 0)
@ -94,12 +96,13 @@ int gravity_parseList(const char *infile, const char *outfile, const char *adlis
printf("%s %s Unable to compile regular expression to identify false positives\n",
over, cross);
fclose(fpin);
sqlite3_close(db);
if(!checkOnly)
sqlite3_close(db);
return EXIT_FAILURE;
}
// Begin transaction
if(sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL) != SQLITE_OK)
if(!checkOnly && sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL) != SQLITE_OK)
{
printf("%s %s Unable to begin transaction to insert domains into database file %s\n",
over, cross, outfile);
@ -110,7 +113,7 @@ int gravity_parseList(const char *infile, const char *outfile, const char *adlis
// Prepare SQL statement
const char *sql = "INSERT INTO gravity (domain, adlist_id) VALUES (?, ?);";
if(sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK)
if(!checkOnly && sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK)
{
printf("%s %s Unable to prepare SQL statement to insert domains into database file %s\n",
over, cross, outfile);
@ -121,7 +124,7 @@ int gravity_parseList(const char *infile, const char *outfile, const char *adlis
// Bind adlistID
const int adlistID = atoi(adlistIDstr);
if(sqlite3_bind_int(stmt, 2, adlistID) != SQLITE_OK)
if(!checkOnly && sqlite3_bind_int(stmt, 2, adlistID) != SQLITE_OK)
{
printf("%s %s Unable to bind adlistID to SQL statement to insert domains into database file %s\n",
over, cross, outfile);
@ -162,6 +165,14 @@ int gravity_parseList(const char *infile, const char *outfile, const char *adlis
match.rm_so == 0 && match.rm_eo == read) // <- Match covers entire line
{
// Exact match found
if(checkOnly)
{
// Increment counter
exact_domains++;
continue;
}
// else: Append domain to database using prepared statement
// Append domain to database using prepared statement
if(sqlite3_bind_text(stmt, 1, line, -1, SQLITE_STATIC) != SQLITE_OK)
{
@ -187,8 +198,14 @@ int gravity_parseList(const char *infile, const char *outfile, const char *adlis
match.rm_so == 0 && match.rm_eo == read) // <- Match covers entire line
{
// ABP-style match (see comments above)
if(checkOnly)
{
// Increment counter
abp_domains++;
continue;
}
// Append pattern to database using prepared statement
// else: Append pattern to database using prepared statement
if(sqlite3_bind_text(stmt, 1, line, -1, SQLITE_STATIC) != SQLITE_OK)
{
printf("%s %s Unable to bind domain to SQL statement to insert domains into database file %s\n",
@ -214,6 +231,13 @@ int gravity_parseList(const char *infile, const char *outfile, const char *adlis
// Ignore false positives - they don't count as invalid domains
if(regexec(&false_positives_regex, line, 0, NULL, 0) != 0)
{
if(checkOnly)
{
// Increment counter
invalid_domains++;
printf("%s %s Invalid domain on line %zu: %s\n", over, cross, lineno, line);
continue;
}
// Add the domain to invalid_domains_list only
// if the list contains < MAX_INVALID_DOMAINS
if(invalid_domains_list_len < MAX_INVALID_DOMAINS)
@ -239,6 +263,7 @@ int gravity_parseList(const char *infile, const char *outfile, const char *adlis
}
// Print progress if the file is large enough every 100 lines
// This code cannot be reached if checkOnly is true
if(fsize > PRINT_PROGRESS_THRESHOLD && lineno % 100 == 1)
{
// Calculate progress
@ -253,6 +278,10 @@ int gravity_parseList(const char *infile, const char *outfile, const char *adlis
}
}
// Skip to end of parseList if we are only checking the list
if(checkOnly)
goto end_of_parseList;
// Finalize SQL statement
if(sqlite3_finalize(stmt) != SQLITE_OK)
{
@ -348,6 +377,7 @@ int gravity_parseList(const char *infile, const char *outfile, const char *adlis
return EXIT_FAILURE;
}
end_of_parseList:
// Print summary
printf("%s %s Parsed %u exact domains and %u ABP-style domains (ignored %u non-domain entries)\n",
over, tick, exact_domains, abp_domains, invalid_domains);
@ -370,7 +400,8 @@ int gravity_parseList(const char *infile, const char *outfile, const char *adlis
// Close files
fclose(fpin);
sqlite3_close(db);
if(db != NULL)
sqlite3_close(db);
// Return success
return EXIT_SUCCESS;

View File

@ -10,4 +10,4 @@
#include "FTL.h"
int gravity_parseList(const char *infile, const char *outfile, const char *adlistID);
int gravity_parseList(const char *infile, const char *outfile, const char *adlistID, const bool checkOnly);