diff --git a/.gitignore b/.gitignore index 3151d03..b8560ea 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,5 @@ Module.symvers Mkfile.old dkms.conf +.vscode +bin/main \ No newline at end of file diff --git a/src/main.c b/src/main.c index e8247a0..261bdab 100644 --- a/src/main.c +++ b/src/main.c @@ -102,7 +102,7 @@ char* skip_spaces(char* str) { return str; } -// Kopiert einen Eingabestring von einem Quellbereich zu einem Zielbereich, bis ein Leerzeichen (oder Nullterminator) erreicht wird +// Kopiert einen Eingabestring von einem Quellbereich zu einem Zielbereich, bis ein Leerzeichen (oder Nullterminator) erreicht wird oder die max. Zeilenlänge nicht überschritten wird void copy_until_space(char* destination, char* source, int max_length) { int i = 0; while (source[i] != ' ' && source[i] != '\0' && i < max_length - 1) { @@ -181,7 +181,7 @@ void cleanup_memory() { // sauberes Schließen und bereinigen bei Fehlerstatus, sofern Speicher nicht alloziert werden kann void cleanup_and_exit() { - printf("Speicherfehler, Programmende\n"); + printf("Programmende. Speicher wird freigegeben und mit NULL überschrieben.\n"); cleanup_memory(); exit(1); } @@ -257,23 +257,39 @@ Parser. Regex Parser und strtok haben sich als schwieriger herausgestellt, da ng Daher ist das Parsing am einfachsten, wenn ein Pointer-basierter Algorithmus die Zeile Stück für Stück einliest und die Erwartungswerte in die struct schreibt. Fehleranfällig, wenn das Logformat nicht dem Standard entspricht - das gilt aber auch für andere Parser. */ +// Standard-nginx-accesslog: +// 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-" int parse_simple_log_line(char* line, int entry_index) { // Nimmt den Pointer auf die Zeile und einen Index entgegen - dieser ist anfangs 0 (globale Variable) und wird pro Eintrag inkrementiert char* current_pos = line; - + // leere Zeichen am Anfang überspringen current_pos = skip_spaces(current_pos); + + // kopieren der IP-Adresse in die globale all_entries Struktur unter gegebenen index + // 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-" + // ^ copy_until_space(all_entries[entry_index].ip_address, current_pos, sizeof(all_entries[entry_index].ip_address)); + // weiter zum nächsten Leerzeichen while (*current_pos != ' ' && *current_pos != '\0') current_pos++; + // 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-" + // ^ + // überspringe Leerzeichen current_pos = skip_spaces(current_pos); - + // 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-" + // ^ + // mehrmaliges Überspringen des Wertes, der nicht von Interesse ist, Überspringen des Leerzeichens while (*current_pos != ' ' && *current_pos != '\0') current_pos++; current_pos = skip_spaces(current_pos); while (*current_pos != ' ' && *current_pos != '\0') current_pos++; current_pos = skip_spaces(current_pos); - + // 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-" + // ^ + // Timestamp-Parsing if (*current_pos == '[') { current_pos++; - + // 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-" + // ^ + // es folgt nach und nach das Einlesen von Datum und Uhrzeit, und wiederholtes Verschieben des Pointers all_entries[entry_index].time.day = 0; while (*current_pos >= '0' && *current_pos <= '9') { all_entries[entry_index].time.day = all_entries[entry_index].time.day * 10 + (*current_pos - '0'); @@ -322,20 +338,29 @@ int parse_simple_log_line(char* line, int entry_index) { // Nimmt den Pointer au all_entries[entry_index].time.second = all_entries[entry_index].time.second * 10 + (*current_pos - '0'); current_pos++; } - + // der Zeitzonen-Deskriptor wird übersprungen while (*current_pos != ']' && *current_pos != '\0') current_pos++; if (*current_pos == ']') current_pos++; + // 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-" + // ^ + } else { + printf("ERROR: Unerwartetes Log-Format. Lediglich mit standard-nginx-accesslog kompatibel.\nDer Fehler ist beim Prüfen des Timestamps aufgetreten, dieser sollte folgendes Format haben:\n[DD/MMM/YYYY:HH:MM:SS +0000]\nProgramm wird beendet.\n"); + cleanup_and_exit(); } current_pos = skip_spaces(current_pos); - + // Weiter mit dem String innerhalb "", aus dem die HTTP-Methode und der URL-Pfad zu entnehmen ist if (*current_pos == '"') { current_pos++; - + // 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-" + // ^ + // HTTP-Methode bis zum nächsten Leerzeichen einlesen und speichern copy_until_space(all_entries[entry_index].request_method, current_pos, sizeof(all_entries[entry_index].request_method)); while (*current_pos != ' ' && *current_pos != '\0') current_pos++; current_pos = skip_spaces(current_pos); - + // 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-" + // ^ + // Einlesen des URL-Path bis zum abschließenden " int i = 0; while (*current_pos != ' ' && *current_pos != '"' && *current_pos != '\0' && i < sizeof(all_entries[entry_index].url_path) - 1) { all_entries[entry_index].url_path[i] = *current_pos; @@ -346,10 +371,15 @@ int parse_simple_log_line(char* line, int entry_index) { // Nimmt den Pointer au while (*current_pos != '"' && *current_pos != '\0') current_pos++; if (*current_pos == '"') current_pos++; + } else { + printf("ERROR: Unerwartetes Log-Format. Lediglich mit standard-nginx-accesslog kompatibel.\nDer Fehler ist beim Prüfen der HTTP-Methode aufgetreten. Diese steht innerhalb eines Strings zusammen mit dem URL-Pfad:\n\"GET /.git/config HTTP/1.1\"\nProgramm wird beendet.\n"); + cleanup_and_exit(); } current_pos = skip_spaces(current_pos); - + // 107.170.27.248 - - [31/Aug/2025:00:11:42 +0000] "GET /.git/config HTTP/1.1" 400 255 "-" "Mozilla/5.0; Keydrop.io/1.0(onlyscans.com/about);" "-" + // ^ + // Parsen ded HTTP-Status Codes, der eine Zahl sein muss all_entries[entry_index].status_code = 0; while (*current_pos >= '0' && *current_pos <= '9') { all_entries[entry_index].status_code = all_entries[entry_index].status_code * 10 + (*current_pos - '0'); @@ -357,20 +387,21 @@ int parse_simple_log_line(char* line, int entry_index) { // Nimmt den Pointer au } current_pos = skip_spaces(current_pos); - + // genauso mit bytegröße der Anfrage all_entries[entry_index].bytes_sent = 0; while (*current_pos >= '0' && *current_pos <= '9') { all_entries[entry_index].bytes_sent = all_entries[entry_index].bytes_sent * 10 + (*current_pos - '0'); current_pos++; } - + // TODO: Der User Agent wäre noch eine interessante Metrik. Kann relativ einfach implementiert werden. return 1; } +// TODO void load_regular_file(char* filename) { FILE* file = fopen(filename, "r"); if (file == NULL) { - printf("WARNUNG: Kann Datei '%s' nicht öffnen!\n", filename); + printf("ERROR: Kann Datei '%s' nicht öffnen!\n", filename); return; }