diff --git a/main.c b/main.c
new file mode 100644
index 0000000..e59aef8
--- /dev/null
+++ b/main.c
@@ -0,0 +1,308 @@
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#define ALLOWED_PATTERNS_FILE "allowed_patterns.txt"
+#define ALLOWED_IPS_FILE "allowed_ips.txt"
+#define PATTERNS_FILE "patterns.txt"
+#define ACCESS_LOG_FILE "access.log.1"
+// #define ACCESS_LOG_FILE "/var/log/nginx/access.log"
+
+typedef struct
+{
+ char** patterns;
+ char** allowed_patterns;
+ char** allowedIps;
+ // size_t allowedIpCount;
+ char** bannedIps;
+ size_t bannedIpCount;
+ size_t bannedIpSize;
+} MatchRules;
+
+
+bool print_allowed_ip = false;
+bool print_allowed_pattern = false;
+bool print_banned_ip = false;
+// bool print_allowed_ip = strcmp(getenv("PRINT_"), "1") == 0;
+
+void* xmalloc(size_t size)
+{
+ void* ptr = malloc(size);
+ if (ptr == NULL)
+ {
+ fprintf(stderr, "Memory allocation failed\n");
+ exit(EXIT_FAILURE);
+ }
+ return ptr;
+}
+
+void read_lines_cb(const char* filename, void cb(char*, void*), void* cbData)
+{
+ if (cb == nullptr)
+ {
+ fprintf(stderr, "Callback function is null\n");
+ return;
+ }
+
+ clock_t ctime = clock(), lastPrint = clock();
+ FILE* file = fopen(filename, "r");
+ if (file == NULL)
+ {
+ fprintf(stderr, "Error opening file %s: ", filename);
+ perror("");
+ return;
+ }
+
+ int count = 0;
+ char* buf = xmalloc(10000);
+ while (fgets(buf, 10000, file) != NULL)
+ {
+ if (buf[0] == '#')
+ {
+ continue;
+ }
+ count++;
+ buf[strcspn(buf, "\n")] = 0;
+ char* line = strdup(buf);
+
+ if (cb != nullptr)
+ cb(line, cbData);
+ free(line);
+
+ if (count % 10 == 0)
+ {
+ double elapsed = (clock() - lastPrint) * 1000.0 / CLOCKS_PER_SEC;
+ if (elapsed > 50.0)
+ {
+ fprintf(stderr, "\rRead %d lines from %s in %.3f ms (%.3f/s)\r", count, filename, (clock() - ctime) * 1000.0 / CLOCKS_PER_SEC,
+ count * 1000.0 / (clock() - ctime));
+ lastPrint = clock();
+ }
+ }
+ }
+
+ free(buf);
+
+ fclose(file);
+ printf("Read %d definitions from %s in %.3f ms (%.3f/s)\n", count, filename, (clock() - ctime) * 1000.0 / CLOCKS_PER_SEC, count * 1000.0 / (clock() - ctime));
+}
+
+char** read_lines(const char* filename)
+{
+ clock_t ctime = clock(), lastPrint = clock();
+ FILE* file = fopen(filename, "r");
+ if (file == NULL)
+ {
+ fprintf(stderr, "Error opening file %s: ", filename);
+ perror("");
+ return nullptr;
+ }
+
+ int count = 0;
+ {
+ char* buf = xmalloc(10000);
+ while (fgets(buf, 10000, file) != NULL)
+ {
+ if (buf[0] == '#')
+ {
+ continue;
+ }
+ count++;
+ }
+
+ free(buf);
+ rewind(file);
+ }
+ fprintf(stderr, "Counted %d lines from %s in %.3f ms\n", count, filename, (clock() - ctime) * 1000.0 / CLOCKS_PER_SEC);
+
+ // count = count_lines(file);
+ // printf("Counted %d lines from %s in %.3f ms\n", count, filename, (clock() - ctime) * 1000.0 / CLOCKS_PER_SEC);
+
+
+ rewind(file);
+ char** lines = xmalloc((count + 1) * sizeof(char*));
+
+ char* buf = xmalloc(10000);
+ for (int i = 0; i < count; i++)
+ {
+ if (fgets(buf, 10000, file) == NULL)
+ {
+ fprintf(stderr, "Error reading line %d from %s\n", i + 1, filename);
+ free(buf);
+ return nullptr;
+ }
+
+ if (buf[0] == '#')
+ {
+ i--;
+ continue;
+ }
+
+ buf[strcspn(buf, "\n")] = 0;
+ lines[i] = strdup(buf);
+
+
+ double elapsed = (clock() - lastPrint) * 1000.0 / CLOCKS_PER_SEC;
+ if (elapsed > 50)
+ {
+ fprintf(stderr, "\rRead %d lines from %s in %.3f ms\r", i + 1, filename, (clock() - ctime) * 1000.0 / CLOCKS_PER_SEC);
+ lastPrint = clock();
+ }
+ }
+ free(buf);
+ lines[count] = nullptr;
+
+ fclose(file);
+ printf("Read %d definitions from %s in %.3f ms\n", count, filename, (clock() - ctime) * 1000.0 / CLOCKS_PER_SEC);
+ return lines;
+}
+
+char** grow_string_array(char** array, size_t newSize)
+{
+ printf("Growing charptr array to %zu\n", newSize);
+ char** newArray = realloc(array, sizeof(char*) * newSize);
+ if (newArray == NULL)
+ {
+ fprintf(stderr, "Memory allocation failed\n");
+ exit(EXIT_FAILURE);
+ }
+ return newArray;
+}
+
+void process_line(char* line, void* cbData)
+{
+ MatchRules* rules = cbData;
+
+ if (line == NULL)
+ {
+ fprintf(stderr, "Line is null @ process_line!\n");
+ return;
+ }
+
+
+ char* ip = xmalloc(32);
+ for (int i = 0; i < 32; i++)
+ {
+ ip[i] = 0;
+ }
+ strncpy(ip, line, strcspn(line, " "));
+
+ // printf("meow %s\n", ip);
+
+
+ for (int j = 0; rules->allowedIps[j] != NULL; j++)
+ {
+ if (strstr(ip, rules->allowedIps[j]) == ip)
+ {
+ if (print_allowed_ip)
+ printf("Allowed IP: \"%s\" (~%s): %s\r", ip, rules->allowedIps[j], line);
+ free(ip);
+ return;
+ }
+ }
+
+ // printf("Checking IP %s against %d banned IPs\n", ip, rules->bannedIpCount);
+ for (size_t j = 0; j < rules->bannedIpCount; j++)
+ {
+ if (strstr(ip, rules->bannedIps[j]) == ip)
+ {
+ if (print_banned_ip)
+ printf("Banned IP: \"%s\": %s\r", rules->bannedIps[j], line);
+ free(ip);
+ return;
+ }
+ }
+
+ for (int i = 0; rules->allowed_patterns[i] != NULL; i++)
+ {
+ if (strstr(line, rules->allowed_patterns[i]) != NULL)
+ {
+ if (print_allowed_pattern)
+ printf("%15s matched allowed pattern \"%s\": %s\n", ip, rules->allowed_patterns[i], line);
+ return;
+ }
+ }
+
+ for (int i = 0; rules->patterns[i] != NULL; i++)
+ {
+ if (strstr(line, rules->patterns[i]) != NULL)
+ {
+ if (rules->bannedIpCount >= rules->bannedIpSize)
+ {
+ rules->bannedIpSize *= 2;
+ rules->bannedIps = grow_string_array(rules->bannedIps, rules->bannedIpSize);
+ }
+
+ rules->bannedIps[rules->bannedIpCount] = ip;
+ rules->bannedIps[rules->bannedIpCount][strcspn(rules->bannedIps[rules->bannedIpCount], "\n")] = 0;
+ rules->bannedIps[rules->bannedIpCount + 1] = nullptr;
+ rules->bannedIpCount++;
+ printf("[Bans=%6lu] %15s matched pattern \"%s\": %s\n", rules->bannedIpCount, ip, rules->patterns[i], line);
+
+
+ signal(SIGCHLD, nullptr);
+ __pid_t pid = fork();
+ if (pid == 0)
+ {
+ if (execvp("iptables", (char*[]){"iptables", "-A", "INPUT", "-s", ip, "-j", "DROP", nullptr}) != 0)
+ {
+ fprintf(stderr, "Error executing iptables: ");
+ perror("");
+ }
+ }
+ else if (pid < 0)
+ {
+ perror("Fork failed");
+ exit(1);
+ }
+
+ return;
+ }
+ }
+
+ free(ip);
+}
+
+
+int main(void)
+{
+ printf("Hello, World!\n");
+ print_allowed_ip = getenv("D_PRINT_ALLOWED_IP") != NULL && strcmp(getenv("D_PRINT_ALLOWED_IP"), "1") == 0;
+ print_allowed_pattern = getenv("D_PRINT_ALLOWED_PATTERN") != NULL && strcmp(getenv("D_PRINT_ALLOWED_PATTERN"), "1") == 0;
+ print_banned_ip = getenv("D_PRINT_BANNED_IP") != NULL && strcmp(getenv("D_PRINT_BANNED_IP"), "1") == 0;
+
+ MatchRules rules;
+ rules.patterns = read_lines(PATTERNS_FILE);
+ rules.allowed_patterns = read_lines(ALLOWED_PATTERNS_FILE);
+ rules.allowedIps = read_lines(ALLOWED_IPS_FILE);
+ rules.bannedIpSize = 64;
+ rules.bannedIpCount = 0;
+ rules.bannedIps = xmalloc(sizeof(char**) * rules.bannedIpSize);
+ //rules.bannedIps[0] = ;
+
+ read_lines_cb(ACCESS_LOG_FILE, process_line, &rules);
+
+ for (int i = 0; rules.bannedIps[i] != NULL; i++)
+ {
+ free(rules.bannedIps[i]);
+ }
+ free(rules.bannedIps);
+
+ for (int i = 0; rules.patterns[i] != NULL; i++)
+ {
+ free(rules.patterns[i]);
+ }
+ free(rules.patterns);
+ free(rules.allowedIps);
+ for (int i = 0; rules.bannedIps[i] != NULL; i++)
+ {
+ free(rules.bannedIps[i]);
+ }
+ free(rules.bannedIps);
+
+ return 0;
+}
|