progress
This commit is contained in:
parent
58237b1ec4
commit
e9cdb49877
212
src/main.c
212
src/main.c
@ -203,7 +203,7 @@ int read_safe_integer() {
|
|||||||
// Speicher freigeben und mit 0 überschreiben (Prävention von use-after-free-Schwachstelle)
|
// Speicher freigeben und mit 0 überschreiben (Prävention von use-after-free-Schwachstelle)
|
||||||
void cleanup_memory() {
|
void cleanup_memory() {
|
||||||
if (all_entries != NULL) {
|
if (all_entries != NULL) {
|
||||||
printf("%lu Bytes Speicher werden freigegeben\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
|
printf("\nDEBUG: %lu Bytes Speicher werden freigegeben\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
|
||||||
free(all_entries);
|
free(all_entries);
|
||||||
all_entries = NULL;
|
all_entries = NULL;
|
||||||
}
|
}
|
||||||
@ -225,7 +225,7 @@ void mem_expand_dynamically() {
|
|||||||
int old_max = max_entries;
|
int old_max = max_entries;
|
||||||
max_entries = max_entries * GROWTH_FACTOR;
|
max_entries = max_entries * GROWTH_FACTOR;
|
||||||
|
|
||||||
printf("Dynamische Speichererweiterung von %d auf %d Einträge um Faktor %f\n", old_max, max_entries, GROWTH_FACTOR);
|
printf("DEBUG: Dynamische Speichererweiterung von %d auf %d Einträge um Faktor %f\n", old_max, max_entries, GROWTH_FACTOR);
|
||||||
|
|
||||||
struct log_entry *new_ptr = realloc(all_entries, max_entries * sizeof(struct log_entry));
|
struct log_entry *new_ptr = realloc(all_entries, max_entries * sizeof(struct log_entry));
|
||||||
|
|
||||||
@ -236,7 +236,7 @@ void mem_expand_dynamically() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
all_entries = new_ptr;
|
all_entries = new_ptr;
|
||||||
printf("Speicher erfolgreich erweitert auf %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
|
printf("DEBUG: Speicher erfolgreich erweitert auf %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +250,7 @@ void allocate_initial_memory() {
|
|||||||
exit(1); // cleanup_and_exit() nicht nötig, da der Speicherbereich nicht beschrieben wurde - use-after-free unproblematisch
|
exit(1); // cleanup_and_exit() nicht nötig, da der Speicherbereich nicht beschrieben wurde - use-after-free unproblematisch
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Speicher erfolgreich alloziert für %d Log-Einträge (%lu Bytes)\n", max_entries, (unsigned long)(max_entries * sizeof(struct log_entry)));
|
printf("DEBUG: Speicher erfolgreich alloziert für %d Log-Einträge (%lu Bytes)\n", max_entries, (unsigned long)(max_entries * sizeof(struct log_entry)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_current_timestamp(char* buffer, int buffer_size) {
|
void get_current_timestamp(char* buffer, int buffer_size) {
|
||||||
@ -540,7 +540,7 @@ void load_regular_file(char* filename) {
|
|||||||
printf("ERROR: Kann Datei '%s' nicht öffnen!\n", filename);
|
printf("ERROR: Kann Datei '%s' nicht öffnen!\n", filename);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printf("Lade Datei: %s\n", filename);
|
printf("INFO: Lade Datei: %s\n", filename);
|
||||||
char line[MAX_LINE_LENGTH_BUF];
|
char line[MAX_LINE_LENGTH_BUF];
|
||||||
int loaded_from_this_file = 0;
|
int loaded_from_this_file = 0;
|
||||||
while (fgets(line, sizeof(line), file) != NULL) {
|
while (fgets(line, sizeof(line), file) != NULL) {
|
||||||
@ -558,8 +558,8 @@ void load_log_file(char* path) {
|
|||||||
total_entries = 0;
|
total_entries = 0;
|
||||||
|
|
||||||
if (is_directory(path)) {
|
if (is_directory(path)) {
|
||||||
printf("Verzeichnis erkannt: %s\n", path);
|
printf("DEBUG: Verzeichnis erkannt: %s\n", path);
|
||||||
printf("Suche nach .log Dateien...\n");
|
printf("DEBUG: Suche nach .log Dateien...\n");
|
||||||
|
|
||||||
DIR* dir = opendir(path);
|
DIR* dir = opendir(path);
|
||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
@ -585,17 +585,17 @@ void load_log_file(char* path) {
|
|||||||
files_found++;
|
files_found++;
|
||||||
} else if (strstr(filename, ".gz") != NULL) {
|
} else if (strstr(filename, ".gz") != NULL) {
|
||||||
printf("INFO: .gz Datei '%s' übersprungen (nicht unterstützt in dieser Version)\n", filename);
|
printf("INFO: .gz Datei '%s' übersprungen (nicht unterstützt in dieser Version)\n", filename);
|
||||||
printf(" Tipp: Dekomprimieren Sie mit 'gunzip %s'\n", filename);
|
printf(" Tipp: Dekomprimieren Sie mit 'gunzip %s'\n", filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
|
||||||
if (files_found == 0) {
|
if (files_found == 0) {
|
||||||
printf("Keine .log Dateien im Verzeichnis gefunden.\n");
|
printf("WARNING: Keine .log Dateien im Verzeichnis gefunden.\n");
|
||||||
printf("Tipp: Für .gz Dateien verwenden Sie 'gunzip *.gz' zum Dekomprimieren\n");
|
printf(" Tipp: Für .gz Dateien verwenden Sie 'gunzip *.gz' zum Dekomprimieren\n");
|
||||||
} else {
|
} else {
|
||||||
printf("Insgesamt %d .log Dateien verarbeitet.\n", files_found);
|
printf("INFO: Insgesamt %d .log Dateien verarbeitet.\n", files_found);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -603,17 +603,17 @@ void load_log_file(char* path) {
|
|||||||
|
|
||||||
if (strstr(path, ".gz") != NULL) {
|
if (strstr(path, ".gz") != NULL) {
|
||||||
printf("FEHLER: .gz Dateien werden in dieser Version nicht unterstützt!\n");
|
printf("FEHLER: .gz Dateien werden in dieser Version nicht unterstützt!\n");
|
||||||
printf("Lösung: Dekomprimieren Sie die Datei zuerst:\n");
|
printf(" Lösung: Dekomprimieren Sie die Datei zuerst:\n");
|
||||||
printf(" gunzip %s\n", path);
|
printf(" gunzip %s\n", path);
|
||||||
printf(" Dann: %s %.*s\n", "PROGRAMM", (int)(strlen(path)-3), path);
|
printf(" Dann: %s %.*s\n", "PROGRAMM", (int)(strlen(path)-3), path);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
load_regular_file(path);
|
load_regular_file(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Erfolgreich %d Einträge insgesamt geladen.\n", total_entries);
|
printf("INFO: Erfolgreich %d Einträge insgesamt geladen.\n", total_entries);
|
||||||
printf("Aktueller Speicherverbrauch: %lu Bytes für %d Einträge\n", (unsigned long)(max_entries * sizeof(struct log_entry)), max_entries);
|
printf("DEBUG: Aktueller Speicherverbrauch: %lu Bytes für %d Einträge\n", (unsigned long)(max_entries * sizeof(struct log_entry)), max_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Funktion zum suchen eines Suchbegriffs innerhalb eines Strings (lowercase)
|
// Funktion zum suchen eines Suchbegriffs innerhalb eines Strings (lowercase)
|
||||||
@ -981,19 +981,23 @@ void format_iso8601_time(struct simple_time time, char* buffer, int buffer_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Export in Timesketch-kompatiblem Format
|
//Export in Timesketch-kompatiblem Format
|
||||||
void export_filtered_entries() {
|
void export_filtered_entries(char *filepath) {
|
||||||
printf("Dateiname für Timesketch-Export eingeben (ohne .csv): ");
|
|
||||||
//90 chars + delimiter
|
//90 chars + delimiter
|
||||||
char filename[91];
|
char filename[91];
|
||||||
if (scanf("%90s", filename) != 1) {
|
if (filepath == NULL) {
|
||||||
printf("FEHLER: Ungültiger Dateiname!\n");
|
printf("Dateiname für Timesketch-Export eingeben (ohne .csv): ");
|
||||||
clear_input_buffer();
|
if (scanf("%90s", filename) != 1) {
|
||||||
return;
|
printf("FEHLER: Ungültiger Dateiname!\n");
|
||||||
|
clear_input_buffer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strncpy(filename, filepath, sizeof(filename) - 1);
|
||||||
|
filename[sizeof(filename) - 1] = '\0';
|
||||||
}
|
}
|
||||||
clear_input_buffer();
|
|
||||||
// Dateiendung
|
// Dateiendung
|
||||||
strcat(filename, ".csv");
|
strcat(filename, ".csv");
|
||||||
|
printf("\nINFO: Schreibe Datei %s...\n", filename);
|
||||||
FILE* file = fopen(filename, "w");
|
FILE* file = fopen(filename, "w");
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
printf("ERROR: Kann Datei '%s' nicht erstellen!\n", filename);
|
printf("ERROR: Kann Datei '%s' nicht erstellen!\n", filename);
|
||||||
@ -1028,7 +1032,7 @@ void export_filtered_entries() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
printf("%d Logeinträge erfolgreich als Timesketch-kompatible CSV-Datei nach '%s' exportiert.\n", exported_count, filename);
|
printf("INFO: %d Logeinträge erfolgreich als Timesketch-kompatible CSV-Datei nach '%s' exportiert.\n", exported_count, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ip_stat {
|
struct ip_stat {
|
||||||
@ -2150,7 +2154,7 @@ void menu_show_entries() {
|
|||||||
supress_preview = 1;
|
supress_preview = 1;
|
||||||
show_filtered_entries(0);
|
show_filtered_entries(0);
|
||||||
} else if (choice == 2) {
|
} else if (choice == 2) {
|
||||||
export_filtered_entries();
|
export_filtered_entries(0);
|
||||||
} else if (choice == 3) {
|
} else if (choice == 3) {
|
||||||
show_top_x_ips();
|
show_top_x_ips();
|
||||||
} else if (choice == 4) {
|
} else if (choice == 4) {
|
||||||
@ -2165,66 +2169,118 @@ void menu_show_entries() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
void print_help(char* binary) {
|
||||||
if (argc != 2) {
|
|
||||||
printf("Verwendung: %s <nginx-log-datei-oder-verzeichnis>\n", argv[0]);
|
|
||||||
printf("Unterstützte Formate: .log Dateien, sowie für rotierte Logs: .log.1 etc.\n");
|
|
||||||
printf("Beispiele:\n");
|
|
||||||
printf(" %s /var/log/nginx/access.log (einzelne .log Datei)\n", argv[0]);
|
|
||||||
printf(" %s /var/log/nginx/ (Verzeichnis mit .log Dateien)\n", argv[0]);
|
|
||||||
printf("\nRotierte nginx-Logs (.gz-Archive) müssen manuell dekomprimiert werden:\n");
|
|
||||||
printf(" 1. Dekomprimieren: gunzip /var/log/nginx/*.gz\n");
|
|
||||||
printf(" 2. Dann ausführen: %s /var/log/nginx/\n", argv[0]);
|
|
||||||
return 1;
|
|
||||||
} else if (argc == 3) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\nNGINX EXAMINATOR\n");
|
printf("\nNGINX EXAMINATOR\n");
|
||||||
|
printf("Verwendung:\n");
|
||||||
allocate_initial_memory();
|
printf(" %s <LOGDATEI|VERZEICHNIS> -i Interaktiver Modus (Filter/Analyse/Export)\n", binary);
|
||||||
load_log_file(argv[1]);
|
printf(" %s <LOGDATEI|VERZEICHNIS> -e <DATEINAME(optional)> Export generieren\n", binary);
|
||||||
|
printf(" %s -h Diese Hilfe anzeigen\n", binary);
|
||||||
if (total_entries == 0) {
|
|
||||||
printf("Keine gültigen Log-Einträge gefunden. Überprüfen Sie den Pfad und die Dateiformate.\n");
|
printf("\nArgumente:\n");
|
||||||
cleanup_memory();
|
printf(" <LOGDATEI|VERZEICHNIS> Pfad zu einer einzelnen *.log Datei ODER zu einem Ordner,\n");
|
||||||
|
printf(" der eine oder mehrere *.log / *.log.N Dateien enthält.\n");
|
||||||
|
|
||||||
|
printf("\nFlags:\n");
|
||||||
|
printf(" -i Startet interaktiven Modus mit Filtern (Status, Methode, IP, Zeitraum,\n");
|
||||||
|
printf(" User-Agent, URL-Teilstring), Vorschau, Statistiken und CSV-Export (Timesketch).\n");
|
||||||
|
printf(" -e Generiert Timesketch-kompatible CSV-Datei, nimmt optional Dateinamen entgegen.\n");
|
||||||
|
printf(" -h Zeigt diese Hilfe an.\n");
|
||||||
|
|
||||||
|
printf("\nUnterstützte Eingaben:\n");
|
||||||
|
printf(" - Normale NGINX-Access-Logs: *.log\n");
|
||||||
|
printf(" - Rotierte Logs: *.log.1, *.log.2, ... (rein textbasiert)\n");
|
||||||
|
printf(" - GZIP-Archive (*.gz) werden NICHT direkt unterstützt.\n");
|
||||||
|
printf(" Tipp: Dekomprimieren Sie vorher, z.B.:\n");
|
||||||
|
printf(" gunzip /var/log/nginx/*.gz\n");
|
||||||
|
printf(" %s /var/log/nginx/ -i\n", binary);
|
||||||
|
|
||||||
|
printf("\nErwartetes NGINX-Logformat (default `log_format main`):\n");
|
||||||
|
printf(" log_format main '$remote_addr - $remote_user [$time_local] \"$request\" '\n");
|
||||||
|
printf(" '$status $body_bytes_sent \"$http_referer\" '\n");
|
||||||
|
printf(" '\"$http_user_agent\" \"$http_x_forwarded_for\"';\n");
|
||||||
|
|
||||||
|
printf("\nBeispielzeile (eine Zeile pro Request):\n");
|
||||||
|
printf(" 0.0.0.0 - - [31/Aug/2025:00:11:42 +0000] \"GET /.git/config HTTP/1.1\" 400 255 \"-\" \"Mozilla/5.0\" \"-\"\n");
|
||||||
|
|
||||||
|
printf("\nBeispiele:\n");
|
||||||
|
printf(" - Einzeldatei analysieren:\n");
|
||||||
|
printf(" %s /var/log/nginx/access.log -i\n", binary);
|
||||||
|
printf(" - Verzeichnis mit mehreren .log / .log.N Dateien:\n");
|
||||||
|
printf(" %s /var/log/nginx/ -i\n", binary);
|
||||||
|
|
||||||
|
printf("\nCSV-Export (Timesketch-kompatibel):\n");
|
||||||
|
printf(" Spalten: datetime, timestamp_desc, ip_address, method, url_path, status_code,\n");
|
||||||
|
printf(" bytes_sent, user_agent, source_file, parsing_timestamp\n");
|
||||||
|
|
||||||
|
printf("\nHinweise & Einschränkungen:\n");
|
||||||
|
printf(" - Parser erwartet das obige Standardformat. Abweichungen können zum Abbruch führen.\n");
|
||||||
|
printf(" - Zeitzone aus dem Log wird gelesen, aber intern als einfache Felder verarbeitet.\n");
|
||||||
|
printf(" - ATYPICAL-Methode: für fehlerhafte/binäre Requests innerhalb der \"request\"-Spalte.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc <= 3) {
|
||||||
|
print_help(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int choice = 0;
|
printf("\nNGINX EXAMINATOR\n");
|
||||||
int stats_show = 0;
|
|
||||||
while (choice != 4 && choice != -4) {
|
allocate_initial_memory();
|
||||||
show_status();
|
|
||||||
if (stats_show == 1) {
|
if (strcmp(argv[2], "-i") == 0) {
|
||||||
show_stats();
|
load_log_file(argv[1]);
|
||||||
int stats_show = 0;
|
|
||||||
|
if (total_entries == 0) {
|
||||||
|
printf("Keine gültigen Log-Einträge gefunden. Überprüfen Sie den Pfad und die Dateiformate.\n");
|
||||||
|
cleanup_memory();
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
show_main_menu();
|
int choice = 0;
|
||||||
|
int stats_show = 0;
|
||||||
choice = read_menu_input();
|
while (choice != 4 && choice != -4) {
|
||||||
choice = handle_menu_shortcuts(choice);
|
show_status();
|
||||||
|
if (stats_show == 1) {
|
||||||
if (choice == -1) {
|
show_stats();
|
||||||
printf("FEHLER: Bitte geben Sie eine gültige Zahl oder Navigation ein (1-4, b, m, q)!\n");
|
stats_show = 0;
|
||||||
continue;
|
}
|
||||||
|
show_main_menu();
|
||||||
|
|
||||||
|
choice = read_menu_input();
|
||||||
|
choice = handle_menu_shortcuts(choice);
|
||||||
|
|
||||||
|
if (choice == -1) {
|
||||||
|
printf("FEHLER: Bitte geben Sie eine gültige Zahl oder Navigation ein (1-4, b, m, q)!\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (choice == 1) {
|
||||||
|
menu_filter_management();
|
||||||
|
} else if (choice == 2) {
|
||||||
|
menu_show_entries();
|
||||||
|
} else if (choice == 3) {
|
||||||
|
stats_show = 1;
|
||||||
|
} else if (choice == 4) {
|
||||||
|
printf("Programmende\n");
|
||||||
|
break;
|
||||||
|
} else if (choice == -4) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
printf("FEHLER: Ungültige Auswahl! Bitte wählen Sie 1-4 oder b/m/q.\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else if (strcmp(argv[2], "-e") == 0){
|
||||||
if (choice == 1) {
|
load_log_file(argv[1]);
|
||||||
menu_filter_management();
|
if (argc == 4) {
|
||||||
} else if (choice == 2) {
|
export_filtered_entries(argv[3]);
|
||||||
menu_show_entries();
|
|
||||||
} else if (choice == 3) {
|
|
||||||
stats_show =1;
|
|
||||||
} else if (choice == 4) {
|
|
||||||
printf("Programmende\n");
|
|
||||||
break;
|
|
||||||
} else if (choice == -4) {
|
|
||||||
break;
|
|
||||||
} else {
|
} else {
|
||||||
printf("FEHLER: Ungültige Auswahl! Bitte wählen Sie 1-4 oder b/m/q.\n");
|
export_filtered_entries(NULL);
|
||||||
}
|
}
|
||||||
|
} else if (strcmp(argv[2], "-h") == 0){
|
||||||
|
print_help(argv[0]);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup_memory();
|
cleanup_memory();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user