diff --git a/2026/Ottaviano/README.md b/2026/Ottaviano/README.md new file mode 100644 index 00000000..3d504179 --- /dev/null +++ b/2026/Ottaviano/README.md @@ -0,0 +1,238 @@ +### Damiano Ottaviano 671944 +# Introduzione + +* Il progetto si basa sull’integrazione del leaky bucket, per limitare il traffico eccessivo dei dati, nel bridge bidirezionale. Il progetto è stato fatto con il **linguaggio c** utilizzando la libreria **pcap** per la trasmissione e ricezione di pacchetti. Come scelte progettuali, per rendere più facile la visione dei pacchetti in transito, ho inserito un filtro manuale (senza l’uso di pcap) che legge solamente pacchetti UDP (quindi con protocollo 17) e con un certo numero identificativo per evitare di leggere pacchetti UDP esterni, con una struttura del pacchetto leggermente diversa, a quelli che inviamo con sender.c. Questo per evitare di confondersi con altri pacchetti in transito ed evitare errori, visto che la struttura del pacchetto è stata leggermente alterata. + +* Nel bridge, ogni volta che arriva un pacchetto, verranno stampati sullo schermo: + * Counter attuale dei pacchetti con il relativo IP sorgente del pacchetto. + * Lista degli indirizzi sorgenti che sono stati catturati di recente e la lista nera. + * Viene specificato il nome dell’interfaccia che sta lavorando in quel momento. Più in avanti si vedrà meglio con degli esempi. + +# Prerequisiti di sistema + +### Pacchetti e librerie software +Il progetto richiede il compilatore `gcc`, il tool `make`e i file della libreria `pcap` (ad ogni file verrà aggiunto il flag -lpcap per la compilazione). Digitare la seguente combinazione di comandi: +1. **Aggiorna l'elenco dei pacchetti del sistema:** +```bash + sudo apt update +``` +2. **Installa il compilatore GCC e il tool make:** +```bash + sudo apt install build-essential +``` +3. **Installa la libreria pcap:** +```bash + sudo apt-get install libpcap-dev +``` + +### Sistema operativo e ambiente +* **OS**: distribuzione linux +* **Configurazione interfacce di rete**: è necessario avere a disposizione due interfacce per far funzionare il bridge. Per cui si procede nel creare una finta scheda di rete, momentanea, che esiste solo nel sistema operativo. Digitare da riga di comando: +```bash + # Creazione e attivazione della prima interfaccia dummy + sudo ip link add dummy0 type dummy + sudo ip link set dummy0 up + + # Creazione e attivazione della seconda interfaccia dummy + sudo ip link add dummy1 type dummy + sudo ip link set dummy1 up +``` +**Alternativa sulla configurazione dell'interfaccia**: invece di aggiungere due interfacce fittizie, nel caso ci si trova in un ambiente virtualizzato (ad es. VirtualBox) si può aggiungere una nuova scheda di rete dalle impostazioni andando su: +* Impostazioni -> Esperto -> Rete -> Selezionare una scheda -> abilità scheda di rete + +# Descrizione + +Nel progetto sono presenti i seguenti file: + +* mybridge.c: bridge bidirezionale +* sender.c: programma per inviare pacchetti all’interfaccia desiderata +* addresses.txt: file di testo da cui prelevare gli indirizzi ip che verranno usati dal sender.c che invia gli stessi pacchetti diversificati solamente dall’ip +* structure.h: contiene le strutture dati necessarie. Sia per la costruzione del pacchetto, e sia quelle per la costruzione di una lista concatenata. +* pcount.c: utilizzato per ricevere pacchetti e ri-inoltrarli sulla stessa interfaccia. +* utils.c: contiene la logica e l'implementazione del leaky bucket, utilizzato nel bridge.c +* utils_leaky_bucket.h: contiene le firme dei metodi implementati in utils.c + +Come scelta progettuale, i pacchetti che verranno trasmessi sono di tipo UDP, aggiungendo un ulteriore struttura dati per l’header dell’udp, affiancato all’header ip. Il pacchetto è costituito anche da un header ethernet e un payload, che contiene: + +* Hop: un intero che rappresenta la quantità di destinazioni raggiunte, utile per capire se il bridge deve inoltrare il pacchetto dalla prima interfaccia (evitando il loop infinito). +* Message: un messaggio che verrà letto sempre nel caso in cui l’indirizzo da cui proviene non si trova nella lista nera. + +```bash +struct eth_header { + uint8_t dst_mac[ETH_ALEN]; + uint8_t src_mac[ETH_ALEN]; + uint16_t ethertype; +} __attribute__((packed)); + +struct ip_header_ { + uint8_t vl; + uint8_t type_service; + uint16_t total_length; + uint16_t identification; + uint16_t fo; + uint8_t ttl; + uint8_t protocol; + uint16_t checksum; + uint32_t src_ip; + uint32_t dst_ip; +} __attribute__((packed)); + +struct udp_header_ { + uint16_t src_port; + uint16_t dst_port; + uint16_t length; + uint16_t checksum; +} __attribute__((packed)); + +struct payload { + uint32_t hop; + char message[32]; +} __attribute__((packed)); +``` + +* Alla fine di ogni struct viene utilizzata la direttiva \_\_attribute\_\_((packed)) per evitare il padding nelle strutture e alcuni disagi per l'accesso ai campi per l'offset, ottimizzando l’uso della memoria. + +* I pacchetti vengono inviati tramite sender.c, che permette di inviare gli stessi pacchetti, differenziati solamente dall’indirizzo ip, utile per capire l’approccio del leaky bucket nel bridge. Il sender prende come input nel prompt: + + * L’interfaccia a cui mandare pacchetti (che sarà l’interfaccia di ingresso del bridge). + * Un file di testo contenente diversi indirizzi ip che verranno scelti, come ip sorgente del pacchetto, tramite un numero digitato sul prompt, utilizzato come indice identificativo di un certo ip all’interno dell’array contenente tutti gli indirizzi del file. + * Il flag identificativo del pacchetto. Usato per differenziare i pacchetti UDP che arrivano da fonti esterne da quelli che vengono mandati con sender.c. + +* Gli indirizzi ip verranno inseriti nelle due liste attraverso una funzione di hash che restituisce un indice di dove dovrà essere inserito quell'indirizzo. L'indice viene restituito sommando gli ottetti dell'indirizzo per poi fare il modulo della dimensione della lista. Prendendo ad esempio il file **addresses.txt** possiamo associare ad ognuno di loro il proprio l'indice dell'array in cui si trovano (ipotizzando che la dimensione della lista sia 10): + * posizione 0: 192.168.1.192 -> (192+168+1+192 mod 10) 3 + * posizione 1: 192.168.1.191 -> 2 + * posizione 2: 192.168.1.120 -> 1 + * posizione 3: 192.168.1.122 -> 3 + * posizione 4: 192.168.1.190 -> 1 + * posizione 5: 192.168.1.123 -> 4 + * posizione 6: 192.168.1.154 -> 5 + * posizione 7: 192.168.1.90 -> 1 + * posizione 8: 192.168.1.100 -> 1 +![Esempio di come vengono inseriti gli ip nella lista](images/sender.png) + +* In questo esempio ho digitato, in sender.c, i seguenti numeri: + * 0 -> Invia un pacchetto con l'indirizzo 192.168.1.192 con hash=3 + * 3 -> Invia un pacchetto con l'indirizzo 192.168.1.122 con hash=3 + * 2 -> Invia un pacchetto con l'indirizzo 192.168.1.120 con hash=1 +* Come si può notare gli indirizzi sono stati inseriti nelle posizioni corrette della lista secondo i loro hash. La stessa cosa vale anche per la blacklist ovviamente + +# Come funziona il Leaky Bucket + +* Vengono utilizzate due liste concatenate, dove una (chiamata table nel bridge di tipo **struct bucket**) serve per registrare gli indirizzi ip recenti, e l’altra (blacklist) per registrare gli indirizzi ip che hanno superato una certa soglia, limitando la loro analisi e l’inoltro dei loro pacchetti alla seconda interfaccia per un certo periodo di tempo. +* Ad ogni indirizzo presente nella lista degli ip recenti (table), viene associato un livello inizializzato ad 1 che rappresenta la frequenza dei pacchetti che arrivano con un quell’indirizzo. Chiaramente, un indirizzo non rimarrà all’infinito nella lista, per cui ho creato una costante che indica il tempo di vita rimasto per un livello che è uguale per ogni indirizzo. L’idea è che ad ogni nuovo pacchetto, viene fatta una revisione in **table**, e se c’è un indirizzo che era li da un certo periodo di tempo, il livello si può decrementare di un certo numero che dipende da quante volte rientra il valore della costante TTL da quanto tempo era passato dall’ultimo pacchetto. Se non arriveranno più pacchetti da quell’indirizzo dopo un po' di tempo, il suo livello può arrivare a 0, per poi eliminare quell’ip dalla **table**. +* Quando arriva un pacchetto, se l’indirizzo ip relativo a quel pacchetto è presente in **table**, il livello verrà incrementato di 1. Se il livello dovesse superare il limite, allora l’ip relativo a quel livello verrà inserito nella lista nera per un certo periodo di tempo. + +* Macro importanti in utils_leacky_bucket: + * Capacity: è la soglia massima. Se viene superato, l’indirizzo viene inserito nella blacklist. + * TTL_IP_IN_BUCKET: è il timer dopo il quale il livello del secchio di un ip si abbassa se smette di inviare pacchetti. + * TTL_IP_IN_BLACKLIST: tempo rimanente dell’indirizzo nella blacklist. +```bash +struct Bucket { + uint32_t ip; + unsigned int level; + time_t timestamp; + struct Bucket* next; +}; + +struct Address_node { + uint32_t ip; + time_t timestamp; + struct Address_node* next; +}; +``` +* Primo esempio di simulazione +![Esempio di come vengono inseriti gli ip nella lista](images/primo_esempio.png) +* Dietro le quinte ovviamente, c’erano anche due pcount attivi per ogni interfaccia. Ogni pacchetto che arriva, viene inserito in **table** tramite un hash che calcola l’indice sommando gli ottetti dell’indirizzo. Quando il pacchetto giunge nella seconda interfaccia del bridge, viene stampato il testo del messaggio (in questo caso hello world). +* Viene sempre specificato il numero dei pacchetti che sono transitati nel bridge e l’ip sorgente del pacchetto. Inoltre, viene anche specificato da quale interfaccia arriva il pacchetto, segnalando anche l’inoltro alla [seconda|prima] interfaccia. + +* Secondo esempio di simulazione +![Esempio di come vengono inseriti gli ip nella lista](images/secondo_esempio.png) + * Qui c’è un caso di spedizione eccessiva di pacchetti da parte dell’indirizzo 192.168.1.191. In questo esempio, CAPACITY è uguale a 2. Infatti, l’indirizzo, al terzo invio, è stato inserito nella blacklist in un intervallo di tempo troppo piccolo rispetto a TTL_IP_IN_BUCKET. +* Bisogna notare che entrando nella lista nera, non è stato analizzato il contenuto del pacchetto, e quindi nessun print di hello world. +# Istruzioni + +* Indispensabile specificare due interfacce nel bridge, in entrata e in uscita, e avviare due pcount.c ognuno per ogni interfaccia. Inoltre, per ogni file.c bisogna inserire una flag che indica il numero identificativo del pacchetto che, come detto nell’introduzione, serve per evitare di leggere altri pacchetti UDP esterni non inviati con sender.c per non andare in confusione cercando di comprendere al meglio come funziona l’algoritmo introdotto. + +* Compilazione: + * Utilizzare il makefile digitando il comando **make** producendo gli eseguibili: mybridge, pcount, sender. + * In caso di problemi con il makefile, compilare i programmi in questo modo: + * ```bash + gcc bridge.c utils.c -o bridge -lpcap + gcc pcount.c -o pcount -lpcap + gcc sender.c -o sender -lpcap + ``` + +* Esecuzione: + * ```bash + Sudo ./sender -i [interface 1] -f [file_indirizzi.txt] -d [packet_id] + Sudo ./bridge -i [interface 1] -o [interface 2] -d [packet_id] + Sudo ./pcount -i [interface1] -d [packet_id] + Sudo ./pcount -i [interface2] -d [packet_id] + ``` + + * Esempio: + * sudo ./pcount -i dummy0 -d 12345 + * sudo ./pcount -i dummy1 -d 12345 + * sudo ./mybridge -i dummy0 -o dummy1 -d 12345 + * sudo ./sender -i dummy0 -f addresses.txt -d 12345 + +# Testing e verifica + +### Preparazione dei terminali + +* **Terminale 1 (monitor di entrata):** si mette in ascolto sulla prima interfaccia +```bash + sudo ./pcount -i dummy0 -d 12345 +``` +* **Terminale 2 (monitor di uscira):** si mette in ascolto sulla seconda interfaccia +```bash + sudo ./pcount -i dummy1 -d 12345 +``` +* **Terminale 3 (bridge):** bridge bidirezionale specificando l'interfaccia di uscita e di entrata, e il flag di identficazione dei pacchetti che deve leggere. +```bash + sudo ./mybridge -i dummy0 -o dummy1 -d 12345 +``` +* **Terminale 4 (sender):** generatore di pacchetti da inviare sulla prima interfaccia. +```bash + sudo ./sender -i dummy0 -f addresses.txt -d 12345 +``` +### Esempi di come funziona il sistema nel tempo +#### Parametri di test in `utils_leaky_bucket.h` +per questa simulazione sono state configurate le seguenti macro di controllo: +* `CAPACITY = 3`: il secchio può contenere al massimo 3 pacchetti prima di traboccare. +* `TTL_IP_IN_BLACKLIST = 5`: durata della punizione (in secondi) per l'ip che esagera con il traffico. +* `TTL_IP_IN_BUCKET = 3`: è il timer dopo il quale il livello del secchio di un ip si decrementa se smette di inviare pacchetti. + +### Esecuzione dei test (verifica del Leaky Bucket) +* **Caso A** traffico regolare (nessun blocco): dal terminale 4 (sender) si inseriscono una serie di numeri (che indicano le posizioni degli ip nell'array in cui vengono salvati), selezionado un ip, inviando un paio di pacchetti a distanza di qualche secondo l'uno dall'altro. Se per ogni ip, il pacchetto viene inviato almeno dopo TTL_IP_IN_BUCKET secondi dopo l'ultimo invio del pacchetto con lo stesso ip, non supererà mai la soglia, e quindi non verrà aggiunto mai nella lista nera. Si possono mandare pacchetti, con un determinato ip, con un alta frequenza arrivando massimo a level = CAPACITY per poi aspettare almeno TTL_IP_IN_BUCKET secondi per l'invio del prossimo pacchetto con quell'ip. Anche in questo caso, l'ip non verrà mai inserito nella blacklist. +* **Caso B** raffica di pacchetti (inserimento nella blacklist): dal terminale 4 viene inviata una raffica di una decina di pacchetti, con lo stesso ip (e quindi digitando sempre lo stesso numero) in 1-2 secondi. Il risultato è che il livello del secchio di quell'ip supera la capacità (dato che in questo esempio, la capacità = 3, lo supera sicuramente) già dal quarto pacchetto. Di conseguenza, l'ip viene inserito nella blacklist, e gli altri pacchetti rimanenti vengono scartati senza stampare il contenuto del messaggio. +* **Caso C** (scadenza timer): sia nella lista (table) degli indirizzi ip recenti e sia nella blacklist, dopo un certo periodo di tempo vengono rimossi dalla lista: +* Dopo un certo periodo di inattività di invio di pacchetti da parte di un indirizzo, si arriverà in un punto in cui il suo livello andrà a 0, per cui verrà rimosso dalla lista table. +* Dopo tot secondi che un indirizzo è stato inserito nella blacklist, verrà anch'esso rimosso, con la possibilità di riprendere l'analisi dei pacchetti di quell'indirizzo. + +### Scenari possibili con linea temporale + +* **scenario di traffico regolare:** + +* t0: Invio pacchetto con IP = 192.168.1.90 +* t1: arriva il pacchetto al bridge. livello del secchio dell'ip viene aumentato di 1, quindi level=1, e viene inizializzato il suo timestamp=t1. +effettuo un controllo level (1) > CAPACITY (3) é falso e quindi non faccio nulla. Viene stampato hello world! +* t2: Invio pacchetto con IP = 192.168.1.90. +* t3: In questo caso verifico se il timer del livello del secchio rientra in un intervallo di tempo > 3, in questo caso t3 (timestamp corrente) - t1 (timestamp dell'arrivo del pacchetto nel tempo t1) = 2 < TTL_IP_IN_BUCKET, per cui il livello non viene decrementato, ma viene portato da level=1 a level=2, e aggiorno il suo timestamp=t3. Il bridge stampa hello world! +* t10: nessun arrivo di un pacchetto, viene fatto un controllo sul registro degli indirizzi ip recenti che hanno inviato pacchetti. In questo caso abbiamo solo 192.168.1.90, si verifica t10 (timestamp corrente) - t3 (ultimo timestamp dell'indirizzo) = 7 < TTL_IP_IN_BUCKET (3), in questo caso la condizione è violata e di conseguenza il livello del secchio dell'ip viene decrementato, ma non di 1, ma ben 2 volte visto che ci sono ben due intervalli di TTL_IP_IN_BUCKET nel tempo passato. Quindi, level -=2, passando a level=0, in questo caso l'ip viene rimosso dalla lista. + +* **Scenario di traffico eccessivo:** + +* t0 e t1 uguali al primo esempio. +* t2: Invio pacchetto con IP = 192.168.1.90. +* t3: arrivo del pacchetto al bridge. Le variabili si aggiornano con level=2 e timestamp=t3. Stampa hello world! +* t4: Invio pacchetto con IP = 192.168.1.90. +* t5: arrivo del pacchetto al bridge. Le variabili si aggiornano con level=3 e timestamp=t5. Stampa hello world! +* t6: Invio pacchetto con IP = 192.168.1.90. +* t7: arrivo del pacchetto al bridge. Le variabili si aggiornano con level=4 e timestamp=t6. in questo caso, c'è stato un eccessivo di invio di +pacchetti in un intervallo di tempo molto piccolo rispetto alla macro TTL_IP_IN_BUCKET dove non c'è stato alcun decremento del livello del secchio. +A questo punto level (4) > CAPACITY (3) superando la soglia, e di conseguenza verrà aggiunto nella blacklist. +* t8: Invio pacchetto con IP = 192.168.1.90. +* t9: arrivo del pacchetto al bridge. Il programma vede che si trova nella lista nera e controlla se ha fatto il suo tempo verificando se sono passati 5 secondi (TTL_IP_IN_BLACKLIST), facendo t9 (timestamp attuale) - t7 (ultimo timestamp dell'ip) = 2 < TTL_IP_IN_BLACKLIST, mancano altri 3 secondi per cui rimane ancora. Non viene stampato il contenuto del pacchetto di quell'indirizzo. +* t13: Invio pacchetto con IP = 192.168.1.90. +* t14: arrivo del pacchetto al bridge. Il programma vede che si trova nella lista nera e fa lo stesso gioco di prima. t14 - t7 = 7 > TTL_IP_IN_BLACKLIST, sono passagi più di 5 secondi per cui viene rimosso il pacchetto dalla lista nera e viene stampato il contenuto del suo messaggio. diff --git a/2026/Ottaviano/addresses.txt b/2026/Ottaviano/addresses.txt new file mode 100644 index 00000000..793d92b7 --- /dev/null +++ b/2026/Ottaviano/addresses.txt @@ -0,0 +1,9 @@ +192.168.1.192 +192.168.1.191 +192.168.1.120 +192.168.1.122 +192.168.1.190 +192.168.1.123 +192.168.1.154 +192.168.1.90 +192.168.1.100 diff --git a/2026/Ottaviano/gestione_reti_relazione.pdf b/2026/Ottaviano/gestione_reti_relazione.pdf new file mode 100644 index 00000000..bbb6c737 Binary files /dev/null and b/2026/Ottaviano/gestione_reti_relazione.pdf differ diff --git a/2026/Ottaviano/images/primo_esempio.png b/2026/Ottaviano/images/primo_esempio.png new file mode 100644 index 00000000..f9404721 Binary files /dev/null and b/2026/Ottaviano/images/primo_esempio.png differ diff --git a/2026/Ottaviano/images/secondo_esempio.png b/2026/Ottaviano/images/secondo_esempio.png new file mode 100644 index 00000000..f1dbb709 Binary files /dev/null and b/2026/Ottaviano/images/secondo_esempio.png differ diff --git a/2026/Ottaviano/images/sender.png b/2026/Ottaviano/images/sender.png new file mode 100644 index 00000000..71923536 Binary files /dev/null and b/2026/Ottaviano/images/sender.png differ diff --git a/2026/Ottaviano/makefile b/2026/Ottaviano/makefile new file mode 100644 index 00000000..3600ed1c --- /dev/null +++ b/2026/Ottaviano/makefile @@ -0,0 +1,28 @@ +CC = gcc +CFLAGS = -Wall + +all: mybridge sender pcount + +pcount: pcount.o + $(CC) $(CFLAGS) -o pcount pcount.o -lpcap + +sender: sender.o + $(CC) $(CFLAGS) -o sender sender.o -lpcap + +mybridge: mybdrige.o utils.o + $(CC) $(CFLAGS) -o mybridge mybridge.o utils.o -lpcap + +mybdrige.o: mybridge.c utils_leaky_bucket.h + $(CC) $(CFLAGS) -c mybridge.c + +pcount.o: pcount.c structure.h + $(CC) $(CFLAGS) -c pcount.c + +sender.o: sender.c structure.h + $(CC) $(CFLAGS) -c sender.c + +utils.o: utils.c utils_leaky_bucket.h structure.h + $(CC) $(CFLAGS) -c utils.c + +clean: + rm -f *.o mybridge sender pcount diff --git a/2026/Ottaviano/mybridge.c b/2026/Ottaviano/mybridge.c new file mode 100644 index 00000000..9d8aa1f4 --- /dev/null +++ b/2026/Ottaviano/mybridge.c @@ -0,0 +1,712 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils_leaky_bucket.h" + + +#define ALARM_SLEEP 1 +#define DEFAULT_SNAPLEN 256 +pcap_t *pd, *pd2; +char* device = NULL; +char* dev2 = NULL; +int verbose = 0; +struct pcap_stat pcapStats; + +/* IDENTIFICATIVO DEL PACCHETTO INVIATO DA SENDER.C */ +uint16_t packet_id = -1; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* the L2 protocols */ + + +static struct timeval startTime; +unsigned long long numPkts = 0, numBytes = 0; +pcap_dumper_t *dumper = NULL; + +/* DEFINIZIONE DELLE LISTE */ +struct Bucket* table[SIZE] = {0}; +struct Address_node* blacklist[SIZE] = {0}; + +/* CONTATORE DEI PACCHETTI */ +int counter_packets = 0; + +void print_ip32(uint32_t ip); + +void print_bucket(struct Bucket** table); +void print_blacklist(struct Address_node** blacklist); +uint8_t hash(uint32_t ip); + +long int calc_rem(struct Bucket* b); + +void update_blacklist(uint8_t index, struct Address_node** blacklist); +bool ipInBlacklist(uint32_t ip, uint8_t index, struct Address_node** blacklist); + +void check_bucket(struct Bucket** table, struct Address_node** blacklist); + +void free_buckets(struct Bucket** table); + +void free_blacklist(struct Address_node** blacklist); +void process_packet(unsigned char* user, + const struct pcap_pkthdr* h, + const unsigned char* packet, pcap_t* in, pcap_t* out, + struct Bucket** table, struct Address_node** blacklist, + char* dev1, char* dev2); + +void insert_ip_in_blacklist(uint32_t ip, uint8_t index, struct Address_node** blacklist); + + +/*FINE DEFINIZIONE STRUTTURE LEACKY BUCKET*/ + +int32_t gmt_to_local(time_t t) { + int dt, dir; + struct tm *gmt, *loc; + struct tm sgmt; + + if (t == 0) + t = time(NULL); + gmt = &sgmt; + *gmt = *gmtime(&t); + loc = localtime(&t); + dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + + (loc->tm_min - gmt->tm_min) * 60; + + /* + * If the year or julian day is different, we span 00:00 GMT + * and must add or subtract a day. Check the year first to + * avoid problems when the julian day wraps. + */ + dir = loc->tm_year - gmt->tm_year; + if (dir == 0) + dir = loc->tm_yday - gmt->tm_yday; + dt += dir * 24 * 60 * 60; + + return (dt); +} + +char* format_numbers(double val, char *buf, unsigned int buf_len, u_int8_t add_decimals) { + unsigned int a1 = ((unsigned long)val / 1000000000) % 1000; + unsigned int a = ((unsigned long)val / 1000000) % 1000; + unsigned int b = ((unsigned long)val / 1000) % 1000; + unsigned int c = (unsigned long)val % 1000; + unsigned int d = (unsigned int)((val - (unsigned long)val)*100) % 100; + + if(add_decimals) { + if(val >= 1000000000) { + snprintf(buf, buf_len, "%u'%03u'%03u'%03u.%02d", a1, a, b, c, d); + } else if(val >= 1000000) { + snprintf(buf, buf_len, "%u'%03u'%03u.%02d", a, b, c, d); + } else if(val >= 100000) { + snprintf(buf, buf_len, "%u'%03u.%02d", b, c, d); + } else if(val >= 1000) { + snprintf(buf, buf_len, "%u'%03u.%02d", b, c, d); + } else + snprintf(buf, buf_len, "%.2f", val); + } else { + if(val >= 1000000000) { + snprintf(buf, buf_len, "%u'%03u'%03u'%03u", a1, a, b, c); + } else if(val >= 1000000) { + snprintf(buf, buf_len, "%u'%03u'%03u", a, b, c); + } else if(val >= 100000) { + snprintf(buf, buf_len, "%u'%03u", b, c); + } else if(val >= 1000) { + snprintf(buf, buf_len, "%u'%03u", b, c); + } else + snprintf(buf, buf_len, "%u", (unsigned int)val); + } + + return(buf); +} + +/* *************************************** */ + +int drop_privileges(const char *username) { + struct passwd *pw = NULL; + + if (getgid() && getuid()) { + fprintf(stderr, "privileges are not dropped as we're not superuser\n"); + return -1; + } + + pw = getpwnam(username); + + if(pw == NULL) { + username = "nobody"; + pw = getpwnam(username); + } + + if(pw != NULL) { + if(setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { + fprintf(stderr, "unable to drop privileges [%s]\n", strerror(errno)); + return -1; + } else { + fprintf(stderr, "user changed to %s\n", username); + } + } else { + fprintf(stderr, "unable to locate user %s\n", username); + return -1; + } + + umask(0); + return 0; +} + +/* *************************************** */ +/* + * The time difference in microseconds + */ +long delta_time (struct timeval * now, + struct timeval * before) { + time_t delta_seconds; + time_t delta_microseconds; + + /* + * compute delta in second, 1/10's and 1/1000's second units + */ + delta_seconds = now -> tv_sec - before -> tv_sec; + delta_microseconds = now -> tv_usec - before -> tv_usec; + + if(delta_microseconds < 0) { + /* manually carry a one from the seconds field */ + delta_microseconds += 1000000; /* 1e6 */ + -- delta_seconds; + } + return((delta_seconds * 1000000) + delta_microseconds); +} + +/* ******************************** */ + +void print_stats() { + struct pcap_stat pcapStat; + struct timeval endTime; + float deltaSec; + static u_int64_t lastPkts = 0; + u_int64_t diff; + static struct timeval lastTime; + char buf1[64], buf2[64]; + + if(startTime.tv_sec == 0) { + lastTime.tv_sec = 0; + gettimeofday(&startTime, NULL); + return; + } + + gettimeofday(&endTime, NULL); + deltaSec = (double)delta_time(&endTime, &startTime)/1000000; + + if(pcap_stats(pd, &pcapStat) >= 0) { + fprintf(stderr, "=========================\n" + "Absolute Stats: [%u pkts rcvd][%u pkts dropped]\n" + "Total Pkts=%u/Dropped=%.1f %%\n", + pcapStat.ps_recv, pcapStat.ps_drop, pcapStat.ps_recv-pcapStat.ps_drop, + pcapStat.ps_recv == 0 ? 0 : (double)(pcapStat.ps_drop*100)/(double)pcapStat.ps_recv); + fprintf(stderr, "%llu pkts [%.1f pkt/sec] - %llu bytes [%.2f Mbit/sec]\n", + numPkts, (double)numPkts/deltaSec, + numBytes, (double)8*numBytes/(double)(deltaSec*1000000)); + + if(lastTime.tv_sec > 0) { + deltaSec = (double)delta_time(&endTime, &lastTime)/1000000; + diff = numPkts-lastPkts; + fprintf(stderr, "=========================\n" + "Actual Stats: %s pkts [%.1f ms][%s pkt/sec]\n", + format_numbers(diff, buf1, sizeof(buf1), 0), deltaSec*1000, + format_numbers(((double)diff/(double)(deltaSec)), buf2, sizeof(buf2), 1)); + lastPkts = numPkts; + } + + fprintf(stderr, "=========================\n"); + } + + lastTime.tv_sec = endTime.tv_sec, lastTime.tv_usec = endTime.tv_usec; +} + +/* ******************************** */ + +void sigproc(int sig) { + static int called = 0; + + fprintf(stderr, "Leaving...\n"); + if (called) return; else called = 1; + + pcap_breakloop(pd); +} + +/* ******************************** */ + +void my_sigalarm(int sig) { + print_stats(); + alarm(ALARM_SLEEP); + signal(SIGALRM, my_sigalarm); +} + +/* ****************************************************** */ + +static char hex[] = "0123456789ABCDEF"; + +char* etheraddr_string(const unsigned char *ep, char *buf) { + unsigned int i, j; + char *cp; + + cp = buf; + if ((j = *ep >> 4) != 0) + *cp++ = hex[j]; + else + *cp++ = '0'; + + *cp++ = hex[*ep++ & 0xf]; + + for(i = 5; (int)--i >= 0;) { + *cp++ = ':'; + if ((j = *ep >> 4) != 0) + *cp++ = hex[j]; + else + *cp++ = '0'; + + *cp++ = hex[*ep++ & 0xf]; + } + + *cp = '\0'; + return (buf); +} + +/* ****************************************************** */ + +/* + * A faster replacement for inet_ntoa(). + */ +char* __intoa(unsigned int addr, char* buf, unsigned short bufLen) { + char *cp, *retStr; + unsigned int byte; + int n; + + cp = &buf[bufLen]; + *--cp = '\0'; + + n = 4; + do { + byte = addr & 0xff; + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) { + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) + *--cp = byte + '0'; + } + *--cp = '.'; + addr >>= 8; + } while (--n > 0); + + /* Convert the string to lowercase */ + retStr = (char*)(cp+1); + + return(retStr); +} + +/* ************************************ */ + +static char buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; + +char* intoa(unsigned int addr) { + return(__intoa(addr, buf, sizeof(buf))); +} + +/* ************************************ */ + +static inline char* in6toa(struct in6_addr addr6) { + snprintf(buf, sizeof(buf), + "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + addr6.s6_addr[0], addr6.s6_addr[1], addr6.s6_addr[2], + addr6.s6_addr[3], addr6.s6_addr[4], addr6.s6_addr[5], addr6.s6_addr[6], + addr6.s6_addr[7], addr6.s6_addr[8], addr6.s6_addr[9], addr6.s6_addr[10], + addr6.s6_addr[11], addr6.s6_addr[12], addr6.s6_addr[13], addr6.s6_addr[14], + addr6.s6_addr[15]); + + return(buf); +} + +/* ****************************************************** */ + +char* proto2str(unsigned short proto) { + static char protoName[8]; + + switch(proto) { + case IPPROTO_TCP: return("TCP"); + case IPPROTO_UDP: return("UDP"); + case IPPROTO_ICMP: return("ICMP"); + default: + snprintf(protoName, sizeof(protoName), "%d", proto); + return(protoName); + } +} + +/* ****************************************************** */ + +static int32_t thiszone; + +void dummyProcesssPacket(unsigned *_deviceId, + const struct pcap_pkthdr *h, + const unsigned char *p) { + + // printf("pcap_sendpacket returned %d\n", pcap_sendpacket(pd, p, h->caplen)); + + if(dumper) + pcap_dump((unsigned char*)dumper, (struct pcap_pkthdr*)h, p); + + /*if(verbose) { + struct ether_header ehdr; + unsigned short eth_type, vlan_id; + char buf1[32], buf2[32]; + struct ip *ip; + struct ip6_hdr ip6; + + int s = (h->ts.tv_sec + thiszone) % 86400; + + printf("%02d:%02d:%02d.%06u ", + s / 3600, (s % 3600) / 60, s % 60, + (unsigned)h->ts.tv_usec); + + memcpy(&ehdr, p, sizeof(struct ether_header)); + eth_type = ntohs(ehdr.ether_type); + printf("[%s -> %s] ", + etheraddr_string(ehdr.ether_shost, buf1), + etheraddr_string(ehdr.ether_dhost, buf2)); + + if(eth_type == 0x8100) { + vlan_id = (p[14] & 15)*256 + p[15]; + eth_type = (p[16])*256 + p[17]; + printf("[vlan %u] ", vlan_id); + p+=4; + } + if(eth_type == 0x0800) { + memcpy(&ip, p+sizeof(ehdr), sizeof(struct ip)); + printf("[%s]", proto2str(ip->ip_p)); + printf("[%s ", intoa(ntohl(ip->ip_src.s_addr))); + printf("-> %s] ", intoa(ntohl(ip->ip_dst.s_addr))); + } else if(eth_type == 0x86DD) { + memcpy(&ip6, p+sizeof(ehdr), sizeof(struct ip6_hdr)); + printf("[%s ", in6toa(ip6.ip6_src)); + printf("-> %s] ", in6toa(ip6.ip6_dst)); + } else if(eth_type == 0x0806) + printf("[ARP]"); + else + printf("[eth_type=0x%04X]", eth_type); + + printf("[caplen=%u][len=%u]\n", h->caplen, h->len); + }*/ + + if(numPkts == 0) gettimeofday(&startTime, NULL); + numPkts++, numBytes += h->len; + + if(verbose == 2) { + int i; + + for(i = 0; i < h->caplen; i++) + printf("%02X ", p[i]); + printf("\n"); + } + } + +/* *************************************** */ + +void printHelp(void) { + char errbuf[PCAP_ERRBUF_SIZE]; + pcap_if_t *devpointer; + + printf("Usage: pcount [-h] -i [-w ] [-f ] [-l ] [-v <1|2>]\n"); + printf("-h [Print help]\n"); + printf("-i [Device name or file path]\n"); + printf("-f [pcap filter]\n"); + printf("-w [pcap write file]\n"); + printf("-l [Capture length]\n"); + printf("-v [Verbose [1: verbose, 2: very verbose (print payload)]]\n"); + + if(pcap_findalldevs(&devpointer, errbuf) == 0) { + int i = 0; + + printf("\nAvailable devices (-i):\n"); + while(devpointer) { + const char *descr = devpointer->description; + + if(descr) + printf(" %d. %s [%s]\n", i++, devpointer->name, descr); + else + printf(" %d. %s\n", i++, devpointer->name); + + devpointer = devpointer->next; + } + } +} + +/* *************************************** */ + +int main(int argc, char* argv[]) { + char*bpfFilter = NULL; + unsigned char c; + char errbuf[PCAP_ERRBUF_SIZE]; + int promisc, snaplen = DEFAULT_SNAPLEN; + struct bpf_program fcode; + struct stat s; + + startTime.tv_sec = 0; + thiszone = gmt_to_local(0); + + while((c = getopt(argc, argv, "hi:o:d:l:v:f:w:")) != '?') { + if((c == 255) || (c == (unsigned char)-1)) break; + + switch(c) { + case 'h': + printHelp(); + exit(0); + break; + + + case 'i': + device = strdup(optarg); + break; + case 'o': + dev2 = strdup(optarg); + break; + case 'd': + packet_id = (uint16_t)atoi(strdup(optarg)); + break; + + case 'l': + snaplen = atoi(optarg); + break; + + case 'v': + verbose = atoi(optarg); + break; + + case 'w': + dumper = pcap_dump_open(pcap_open_dead(DLT_EN10MB, 16384 /* MTU */), optarg); + if(dumper == NULL) { + printf("Unable to open dump file %s\n", optarg); + return(-1); + } + break; + + case 'f': + bpfFilter = strdup(optarg); + break; + } + } + + if(geteuid() != 0) { + printf("Please run this tool as superuser\n"); + return(-1); + } + + if(device == NULL) { + printf("ERROR: Missing -i\n"); + printHelp(); + return(-1); + } + + if(dev2 == NULL){ + printf("ERROR: Missing -o\n"); + printHelp(); + return(-1); + } + + printf("Capturing from %s\n", device); + + if(stat(device, &s) == 0) { + /* Device is a file on filesystem */ + if((pd = pcap_open_offline(device, errbuf)) == NULL) { + printf("pcap_open_offline: %s\n", errbuf); + return(-1); + } + } else { + /* hardcode: promisc=1, to_ms=500 */ + promisc = 1; + if((pd = pcap_open_live(device, snaplen, promisc, 500, errbuf)) == NULL) { + printf("pcap_open_live: %s\n", errbuf); + return(-1); + } + if((pd2 = pcap_open_live(dev2, snaplen, promisc, 500, errbuf)) == NULL) { + printf("pcap_open_live: %s\n", errbuf); + return(-1); + } + } + if(bpfFilter != NULL) { + if(pcap_compile(pd, &fcode, bpfFilter, 1, 0xFFFFFF00) < 0) { + printf("pcap_compile error: '%s'\n", pcap_geterr(pd)); + } else { + if(pcap_setfilter(pd, &fcode) < 0) { + printf("pcap_setfilter error: '%s'\n", pcap_geterr(pd)); + } + } + } + + if(drop_privileges("nobody") < 0) + return(-1); + + /*signal(SIGINT, sigproc); + signal(SIGTERM, sigproc); + + if(!verbose) { + signal(SIGALRM, my_sigalarm); + alarm(ALARM_SLEEP); + }*/ + + int fd_in = pcap_get_selectable_fd(pd); + int fd_out = pcap_get_selectable_fd(pd2); + + fd_set readsfd; + + while(1){ + + FD_ZERO(&readsfd); + FD_SET(fd_in, &readsfd); + FD_SET(fd_out, &readsfd); + + int max = (fd_in > fd_out) ? fd_in : fd_out; + + if(select(max+1, &readsfd, NULL, NULL, NULL) > 0){ + if(FD_ISSET(fd_in, &readsfd)){ + struct pcap_pkthdr* header; + const unsigned char* packet; + + // ricevo il pacchetto + int res = pcap_next_ex(pd, &header, &packet); + struct ip_header_* hdr = (struct ip_header_*)(packet + sizeof(struct eth_header)); + + /* + verifico che sia un pacchetto udp e che abbia l'idenfificativo + indicato nellariga di comando + */ + if(res>0 && hdr->protocol == 17 && packet_id == hdr->identification){ + + /* + verifico se i byte del pacchetto ricevuto non siano meno della + lunghezza della struttura pacchetto + */ + if(header->caplen < SIZE_PACKET){ + printf("Errore nella cattura dei byte del pacchetto\n"); + continue; + } + + /* + copio il contenuto del pacchetto per incrementare la variabile hop + */ + unsigned char* copy = malloc(header->caplen); + memcpy(copy, packet, header->caplen); + struct payload* p = (struct payload*)(copy + sizeof(struct eth_header)+ + sizeof(struct ip_header_) + sizeof(struct udp_header_)); + + if(p->hop == 0){ + + p->hop++; + + printf("\n[%s] pacchetto arrivato!\n", device); + + // processamento del pacchetto e delle liste + + process_packet(NULL, header, copy, pd, pd2, + table, blacklist, device, dev2); + counter_packets++; + struct in_addr addr; + addr.s_addr = hdr->src_ip; + printf("\n==================\n"); + printf("Packet #%d\n", counter_packets); + printf("IP: %s\n", inet_ntoa(addr)); + printf("==================\n\n"); + + /* + stampo il contenuto delle liste + */ + + print_bucket(table); + printf("\n"); + print_blacklist(blacklist); + + } + } + } + + if(FD_ISSET(fd_out, &readsfd)){ + struct pcap_pkthdr* header; + const unsigned char* packet; + int res = pcap_next_ex(pd2, &header, &packet); + struct ip_header_* hdr = (struct ip_header_*)(packet + sizeof(struct eth_header)); + + /* + verifico che sia un pacchetto udp e che abbia l'idenfificativo + indicato nellariga di comando + */ + + if(res > 0 && hdr->protocol == 17 && packet_id == hdr->identification){ + + /* + verifico se i byte del pacchetto ricevuto non siano meno della + lunghezza della struttura pacchetto + */ + + if(header->caplen < SIZE_PACKET){ + printf("Errore nella cattura dei byte del pacchetto\n"); + continue; + } + + /* + copio il contenuto del pacchetto per incrementare la variabile hop + */ + + unsigned char* copy = malloc(header->caplen); + memcpy(copy, packet, header->caplen); + struct payload* p = (struct payload*)(copy + sizeof(struct eth_header)+ + sizeof(struct ip_header_) + sizeof(struct udp_header_)); + + p->hop++; + + printf("[%s] pacchetto arrivato!\n", dev2); + struct in_addr addr; + addr.s_addr = hdr->src_ip; + printf("[%s:%s] : %s\n",dev2, inet_ntoa(addr),p->message); + if(pcap_sendpacket(pd, copy, SIZE_PACKET) != 0){ + printf("[%s] errore nell'invio del pacchetto: %s\n!",dev2, pcap_geterr(pd)); + } + printf("[%s] pacchetto inviato all'interfaccia [%s]!\n", + dev2, device); + } + + } + } + + } + + free_blacklist(blacklist); + free_buckets(table); + + + + //pcap_loop(pd, -1, dummyProcesssPacket, NULL); + + print_stats(); + + pcap_close(pd); + + if(dumper) + pcap_dump_close(dumper); + + return(0); +} diff --git a/2026/Ottaviano/pcount.c b/2026/Ottaviano/pcount.c new file mode 100644 index 00000000..38fb08d8 --- /dev/null +++ b/2026/Ottaviano/pcount.c @@ -0,0 +1,569 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +#define ALARM_SLEEP 1 +#define DEFAULT_SNAPLEN 256 +pcap_t *pd; +int verbose = 0; +struct pcap_stat pcapStats; +char *device = NULL; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* the L2 protocols */ +#include "structure.h" + +static struct timeval startTime; +unsigned long long numPkts = 0, numBytes = 0; +pcap_dumper_t *dumper = NULL; + +/* inizializzo il numero identificativo del pacchetto */ +uint16_t packet_id = -1; + +/* *************************************** */ + +int32_t gmt_to_local(time_t t) { + int dt, dir; + struct tm *gmt, *loc; + struct tm sgmt; + + if (t == 0) + t = time(NULL); + gmt = &sgmt; + *gmt = *gmtime(&t); + loc = localtime(&t); + dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + + (loc->tm_min - gmt->tm_min) * 60; + + /* + * If the year or julian day is different, we span 00:00 GMT + * and must add or subtract a day. Check the year first to + * avoid problems when the julian day wraps. + */ + dir = loc->tm_year - gmt->tm_year; + if (dir == 0) + dir = loc->tm_yday - gmt->tm_yday; + dt += dir * 24 * 60 * 60; + + return (dt); +} + +char* format_numbers(double val, char *buf, unsigned int buf_len, u_int8_t add_decimals) { + unsigned int a1 = ((unsigned long)val / 1000000000) % 1000; + unsigned int a = ((unsigned long)val / 1000000) % 1000; + unsigned int b = ((unsigned long)val / 1000) % 1000; + unsigned int c = (unsigned long)val % 1000; + unsigned int d = (unsigned int)((val - (unsigned long)val)*100) % 100; + + if(add_decimals) { + if(val >= 1000000000) { + snprintf(buf, buf_len, "%u'%03u'%03u'%03u.%02d", a1, a, b, c, d); + } else if(val >= 1000000) { + snprintf(buf, buf_len, "%u'%03u'%03u.%02d", a, b, c, d); + } else if(val >= 100000) { + snprintf(buf, buf_len, "%u'%03u.%02d", b, c, d); + } else if(val >= 1000) { + snprintf(buf, buf_len, "%u'%03u.%02d", b, c, d); + } else + snprintf(buf, buf_len, "%.2f", val); + } else { + if(val >= 1000000000) { + snprintf(buf, buf_len, "%u'%03u'%03u'%03u", a1, a, b, c); + } else if(val >= 1000000) { + snprintf(buf, buf_len, "%u'%03u'%03u", a, b, c); + } else if(val >= 100000) { + snprintf(buf, buf_len, "%u'%03u", b, c); + } else if(val >= 1000) { + snprintf(buf, buf_len, "%u'%03u", b, c); + } else + snprintf(buf, buf_len, "%u", (unsigned int)val); + } + + return(buf); +} + +/* *************************************** */ + +int drop_privileges(const char *username) { + struct passwd *pw = NULL; + + if (getgid() && getuid()) { + fprintf(stderr, "privileges are not dropped as we're not superuser\n"); + return -1; + } + + pw = getpwnam(username); + + if(pw == NULL) { + username = "nobody"; + pw = getpwnam(username); + } + + if(pw != NULL) { + if(setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { + fprintf(stderr, "unable to drop privileges [%s]\n", strerror(errno)); + return -1; + } else { + fprintf(stderr, "user changed to %s\n", username); + } + } else { + fprintf(stderr, "unable to locate user %s\n", username); + return -1; + } + + umask(0); + return 0; +} + +/* *************************************** */ +/* + * The time difference in microseconds + */ +long delta_time (struct timeval * now, + struct timeval * before) { + time_t delta_seconds; + time_t delta_microseconds; + + /* + * compute delta in second, 1/10's and 1/1000's second units + */ + delta_seconds = now -> tv_sec - before -> tv_sec; + delta_microseconds = now -> tv_usec - before -> tv_usec; + + if(delta_microseconds < 0) { + /* manually carry a one from the seconds field */ + delta_microseconds += 1000000; /* 1e6 */ + -- delta_seconds; + } + return((delta_seconds * 1000000) + delta_microseconds); +} + +/* ******************************** */ + +void print_stats() { + struct pcap_stat pcapStat; + struct timeval endTime; + float deltaSec; + static u_int64_t lastPkts = 0; + u_int64_t diff; + static struct timeval lastTime; + char buf1[64], buf2[64]; + + if(startTime.tv_sec == 0) { + lastTime.tv_sec = 0; + gettimeofday(&startTime, NULL); + return; + } + + gettimeofday(&endTime, NULL); + deltaSec = (double)delta_time(&endTime, &startTime)/1000000; + + if(pcap_stats(pd, &pcapStat) >= 0) { + fprintf(stderr, "=========================\n" + "Absolute Stats: [%u pkts rcvd][%u pkts dropped]\n" + "Total Pkts=%u/Dropped=%.1f %%\n", + pcapStat.ps_recv, pcapStat.ps_drop, pcapStat.ps_recv-pcapStat.ps_drop, + pcapStat.ps_recv == 0 ? 0 : (double)(pcapStat.ps_drop*100)/(double)pcapStat.ps_recv); + fprintf(stderr, "%llu pkts [%.1f pkt/sec] - %llu bytes [%.2f Mbit/sec]\n", + numPkts, (double)numPkts/deltaSec, + numBytes, (double)8*numBytes/(double)(deltaSec*1000000)); + + if(lastTime.tv_sec > 0) { + deltaSec = (double)delta_time(&endTime, &lastTime)/1000000; + diff = numPkts-lastPkts; + fprintf(stderr, "=========================\n" + "Actual Stats: %s pkts [%.1f ms][%s pkt/sec]\n", + format_numbers(diff, buf1, sizeof(buf1), 0), deltaSec*1000, + format_numbers(((double)diff/(double)(deltaSec)), buf2, sizeof(buf2), 1)); + lastPkts = numPkts; + } + + fprintf(stderr, "=========================\n"); + } + + lastTime.tv_sec = endTime.tv_sec, lastTime.tv_usec = endTime.tv_usec; +} + +/* ******************************** */ + +void sigproc(int sig) { + static int called = 0; + + fprintf(stderr, "Leaving...\n"); + if (called) return; else called = 1; + + pcap_breakloop(pd); +} + +/* ******************************** */ + +void my_sigalarm(int sig) { + print_stats(); + alarm(ALARM_SLEEP); + signal(SIGALRM, my_sigalarm); +} + +/* ****************************************************** */ + +static char hex[] = "0123456789ABCDEF"; + +char* etheraddr_string(const unsigned char *ep, char *buf) { + unsigned int i, j; + char *cp; + + cp = buf; + if ((j = *ep >> 4) != 0) + *cp++ = hex[j]; + else + *cp++ = '0'; + + *cp++ = hex[*ep++ & 0xf]; + + for(i = 5; (int)--i >= 0;) { + *cp++ = ':'; + if ((j = *ep >> 4) != 0) + *cp++ = hex[j]; + else + *cp++ = '0'; + + *cp++ = hex[*ep++ & 0xf]; + } + + *cp = '\0'; + return (buf); +} + +/* ****************************************************** */ + +/* + * A faster replacement for inet_ntoa(). + */ +char* __intoa(unsigned int addr, char* buf, unsigned short bufLen) { + char *cp, *retStr; + unsigned int byte; + int n; + + cp = &buf[bufLen]; + *--cp = '\0'; + + n = 4; + do { + byte = addr & 0xff; + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) { + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) + *--cp = byte + '0'; + } + *--cp = '.'; + addr >>= 8; + } while (--n > 0); + + /* Convert the string to lowercase */ + retStr = (char*)(cp+1); + + return(retStr); +} + +/* ************************************ */ + +static char buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; + +char* intoa(unsigned int addr) { + return(__intoa(addr, buf, sizeof(buf))); +} + +/* ************************************ */ + +static inline char* in6toa(struct in6_addr addr6) { + snprintf(buf, sizeof(buf), + "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + addr6.s6_addr[0], addr6.s6_addr[1], addr6.s6_addr[2], + addr6.s6_addr[3], addr6.s6_addr[4], addr6.s6_addr[5], addr6.s6_addr[6], + addr6.s6_addr[7], addr6.s6_addr[8], addr6.s6_addr[9], addr6.s6_addr[10], + addr6.s6_addr[11], addr6.s6_addr[12], addr6.s6_addr[13], addr6.s6_addr[14], + addr6.s6_addr[15]); + + return(buf); +} + +/* ****************************************************** */ + +char* proto2str(unsigned short proto) { + static char protoName[8]; + + switch(proto) { + case IPPROTO_TCP: return("TCP"); + case IPPROTO_UDP: return("UDP"); + case IPPROTO_ICMP: return("ICMP"); + default: + snprintf(protoName, sizeof(protoName), "%d", proto); + return(protoName); + } +} + +/* ****************************************************** */ + +static int32_t thiszone; +int count = 0; +void dummyProcesssPacket(unsigned char *_deviceId, + const struct pcap_pkthdr *h, + const unsigned char *p) { + + struct ip_header_* hrd = (struct ip_header_*)(p + sizeof(struct eth_header)); + + /* + verifico che sia un pacchetto udp e che abbia l'idenfificativo + indicato nellariga di comando + */ + + if(hrd->protocol == 17 && hrd->identification == packet_id){ + if(h->caplen < SIZE_PACKET){ + printf("Errore nella cattura dei byte del pacchetto\n"); + return; + } + + /* + vado a copiare il conteuto del pacchetto per incrementare l'hop + */ + unsigned char* cpy = malloc(h->caplen); + memcpy(cpy, p, h->caplen); + struct payload* payload = (struct payload*)(cpy + sizeof(struct eth_header)+ + sizeof(struct ip_header_) + sizeof(struct udp_header_)); + printf("hop: %d\n", payload->hop); + + payload->hop++; + + count++; + printf("===================\ncounter: %d\n",count); + printf("pacchetto arrivato!\n"); + + int send = pcap_sendpacket(pd, cpy, + h->caplen); + if(send != 0){ + fprintf(stderr, "Errore invio pacchetto: %s\n", pcap_geterr(pd)); + } else { + printf("pacchetto inoltrato\n"); + } + printf("===================\n\n"); + } + if(dumper) + pcap_dump((unsigned char*)dumper, (struct pcap_pkthdr*)h, p); + + if(verbose) { + struct ether_header ehdr; + unsigned short eth_type, vlan_id; + char buf1[32], buf2[32]; + struct ip ip; + struct ip6_hdr ip6; + + int s = (h->ts.tv_sec + thiszone) % 86400; + + printf("%02d:%02d:%02d.%06u ", + s / 3600, (s % 3600) / 60, s % 60, + (unsigned)h->ts.tv_usec); + + memcpy(&ehdr, p, sizeof(struct ether_header)); + eth_type = ntohs(ehdr.ether_type); + printf("[%s -> %s] ", + etheraddr_string(ehdr.ether_shost, buf1), + etheraddr_string(ehdr.ether_dhost, buf2)); + + if(eth_type == 0x8100) { + vlan_id = (p[14] & 15)*256 + p[15]; + eth_type = (p[16])*256 + p[17]; + printf("[vlan %u] ", vlan_id); + p+=4; + } + if(eth_type == 0x0800) { + memcpy(&ip, p+sizeof(ehdr), sizeof(struct ip)); + printf("[%s]", proto2str(ip.ip_p)); + printf("[%s ", intoa(ntohl(ip.ip_src.s_addr))); + printf("-> %s] ", intoa(ntohl(ip.ip_dst.s_addr))); + } else if(eth_type == 0x86DD) { + memcpy(&ip6, p+sizeof(ehdr), sizeof(struct ip6_hdr)); + printf("[%s ", in6toa(ip6.ip6_src)); + printf("-> %s] ", in6toa(ip6.ip6_dst)); + } else if(eth_type == 0x0806) + printf("[ARP]"); + else + printf("[eth_type=0x%04X]", eth_type); + + printf("[caplen=%u][len=%u]\n", h->caplen, h->len); + } + + if(numPkts == 0) gettimeofday(&startTime, NULL); + numPkts++, numBytes += h->len; + + if(verbose == 2) { + int i; + + for(i = 0; i < h->caplen; i++) + printf("%02X ", p[i]); + printf("\n"); + } + } + +/* *************************************** */ + +void printHelp(void) { + char errbuf[PCAP_ERRBUF_SIZE]; + pcap_if_t *devpointer; + + printf("Usage: pcount [-h] -i [-w ] [-f ] [-l ] [-v <1|2>]\n"); + printf("-h [Print help]\n"); + printf("-i [Device name or file path]\n"); + printf("-f [pcap filter]\n"); + printf("-w [pcap write file]\n"); + printf("-d [packet id]\n"); + printf("-l [Capture length]\n"); + printf("-v [Verbose [1: verbose, 2: very verbose (print payload)]]\n"); + + if(pcap_findalldevs(&devpointer, errbuf) == 0) { + int i = 0; + + printf("\nAvailable devices (-i):\n"); + while(devpointer) { + const char *descr = devpointer->description; + + if(descr) + printf(" %d. %s [%s]\n", i++, devpointer->name, descr); + else + printf(" %d. %s\n", i++, devpointer->name); + + devpointer = devpointer->next; + } + } +} + +/* *************************************** */ + +int main(int argc, char* argv[]) { + char *bpfFilter = NULL; + unsigned char c; + char errbuf[PCAP_ERRBUF_SIZE]; + int promisc, snaplen = DEFAULT_SNAPLEN; + struct bpf_program fcode; + struct stat s; + + startTime.tv_sec = 0; + thiszone = gmt_to_local(0); + + while((c = getopt(argc, argv, "hi:d:l:v:f:w:")) != '?') { + if((c == 255) || (c == (unsigned char)-1)) break; + + switch(c) { + case 'h': + printHelp(); + exit(0); + break; + + case 'i': + device = strdup(optarg); + break; + case 'd': + packet_id = (uint16_t)atoi(strdup(optarg)); + break; + + case 'l': + snaplen = atoi(optarg); + break; + + case 'v': + verbose = atoi(optarg); + break; + + case 'w': + dumper = pcap_dump_open(pcap_open_dead(DLT_EN10MB, 16384 /* MTU */), optarg); + if(dumper == NULL) { + printf("Unable to open dump file %s\n", optarg); + return(-1); + } + break; + + case 'f': + bpfFilter = strdup(optarg); + break; + } + } + + if(geteuid() != 0) { + printf("Please run this tool as superuser\n"); + return(-1); + } + + if(device == NULL) { + printf("ERROR: Missing -i\n"); + printHelp(); + return(-1); + } + + printf("Capturing from %s\n", device); + + if(stat(device, &s) == 0) { + /* Device is a file on filesystem */ + if((pd = pcap_open_offline(device, errbuf)) == NULL) { + printf("pcap_open_offline: %s\n", errbuf); + return(-1); + } + } else { + /* hardcode: promisc=1, to_ms=500 */ + promisc = 1; + if((pd = pcap_open_live(device, snaplen, promisc, 500, errbuf)) == NULL) { + printf("pcap_open_live: %s\n", errbuf); + return(-1); + } + } + if(bpfFilter != NULL) { + if(pcap_compile(pd, &fcode, bpfFilter, 1, 0xFFFFFF00) < 0) { + printf("pcap_compile error: '%s'\n", pcap_geterr(pd)); + } else { + if(pcap_setfilter(pd, &fcode) < 0) { + printf("pcap_setfilter error: '%s'\n", pcap_geterr(pd)); + } + } + } + + if(drop_privileges("nobody") < 0) + return(-1); + + /*signal(SIGINT, sigproc); + signal(SIGTERM, sigproc); + + if(!verbose) { + signal(SIGALRM, my_sigalarm); + alarm(ALARM_SLEEP); + }*/ + + pcap_loop(pd, -1, dummyProcesssPacket, NULL); + + print_stats(); + + pcap_close(pd); + + if(dumper) + pcap_dump_close(dumper); + + return(0); +} diff --git a/2026/Ottaviano/sender.c b/2026/Ottaviano/sender.c new file mode 100644 index 00000000..157b10d1 --- /dev/null +++ b/2026/Ottaviano/sender.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include +#include "structure.h" + +#define ETHERNET 14 +#define LEN_IP_HEADER 20 +#define LEN_UDP_HEADER 8 +#define LEN_PAYLOAD 36 +#define MAX_LINE 32 +#define MAX_ADDRESSES 32 + +char* interface = NULL; +FILE* fp = NULL; +uint16_t packet_id = -1; + +void print_help(){ + printf("Usage:\n"); + printf("-i [interface]\n"); + printf("-f [file]\n"); + printf("-d [id packet (number)]\n"); +} + +void extract_params(char** argv, int argc){ + + for(int i = 1; i < argc; i++){ + if(strcmp(argv[i], "-i") == 0 && i + 1 < argc){ + interface = malloc(64); + if(!interface){ + perror("malloc"); + exit(1); + } + strcpy(interface, argv[i+1]); + } else if(strcmp(argv[i], "-f") == 0 && i + 1 < argc){ + fp = fopen(argv[i+1], "r"); + if(fp == NULL){ + perror("opening file"); + exit(1); + } + } else if(strcmp(argv[i], "-d") == 0 && i + 1 < argc){ + packet_id = (uint16_t)atoi(argv[i+1]); + } + } + + if(interface == NULL || fp == NULL || packet_id == -1){ + print_help(); + exit(1); + } +} + +int main(int argc, char** argv){ + + /* + estraggo i parametri nella riga di comando + */ + + extract_params(argv, argc); + + char line[MAX_LINE]; + uint32_t addresses[MAX_ADDRESSES]; + int count = 0; + + /* + inserisco gli indirizzi ip nell'array + */ + + while(fgets(line, sizeof(line), fp) != NULL){ + + line[strcspn(line, "\n")] = '\0'; + + if (count >= MAX_ADDRESSES) { + fprintf(stderr, "array pieno\n"); + break; + } + + uint32_t ip; + + if (inet_pton(AF_INET, line, &ip) == 1) { + addresses[count++] = ip; + } else { + fprintf(stderr, "ip non valido: %s\n", line); + } + } + + + char errbuf[PCAP_ERRBUF_SIZE]; + + pcap_t* handle = pcap_open_live(interface, 65535, 1, 500, errbuf); + + if(!handle){ + fprintf(stderr, "pcap error: %s\n", errbuf); + return -1; + } + + unsigned char packet[sizeof(struct eth_header)+ + sizeof(struct ip_header_)+ + sizeof(struct udp_header_) + + sizeof(struct payload)]; + memset(packet, 0, sizeof(packet)); + + // ethernet + struct eth_header *eth = (struct eth_header *)packet; + uint8_t src_mac[6] = {0x00,0x0c,0x29,0x3e,0x5c,0x7d}; + uint8_t dst_mac[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + memcpy(eth->src_mac, src_mac, 6); + memcpy(eth->dst_mac, dst_mac, 6); + eth->ethertype = htons(0x0800); // IPv4 + + // ip + struct ip_header_ *ip = (struct ip_header_ *)(packet + sizeof(struct eth_header)); + ip->vl = (4 << 4) | 5; // Version 4 + IHL 5 + ip->type_service = 0; + ip->total_length = htons(sizeof(struct ip_header_) + sizeof(struct udp_header_)); + ip->identification = packet_id; + ip->fo = 0; + ip->ttl = 64; + ip->protocol = 17; // UDP + ip->src_ip = htonl(0xc0a80164); // 192.168.1.100 + ip->dst_ip = htonl(0xc0a801ff); // 192.168.1.255 + ip->checksum = 0; + + // udp + struct udp_header_ *udp = (struct udp_header_ *)(packet + sizeof(struct eth_header) + sizeof(struct ip_header_)); + udp->src_port = htons(1234); + udp->dst_port = htons(4321); + udp->length = htons(sizeof(struct udp_header_)); + udp->checksum = 0; // opzionale + + struct payload* p = (struct payload*)(packet + sizeof(struct eth_header)+ + sizeof(struct ip_header_) + sizeof(struct udp_header_)); + p->hop = 0; + strcpy(p->message, "hello world!"); + + int option; + printf("range {0-%d}\n",count-1); + + while(1){ + + scanf("%d", &option); + if(option < 0 || option >= count) { + printf("numero inserito fuori dal range!\n\n"); + continue; + } + ip->src_ip = addresses[option]; + + if(pcap_sendpacket(handle, packet, SIZE_PACKET) != 0){ + fprintf(stderr, "send error: %s\n", pcap_geterr(handle)); + return -1; + } else printf("pacchetto inviato!\n"); + } + + printf("pacchetto inviato!\n"); + + free(interface); + return 0; +} diff --git a/2026/Ottaviano/structure.h b/2026/Ottaviano/structure.h new file mode 100644 index 00000000..312fdf16 --- /dev/null +++ b/2026/Ottaviano/structure.h @@ -0,0 +1,54 @@ +#ifndef STRUCTURE_H +#define STRUCTURE_H + +#define ETH_ALEN 6 + + + +struct eth_header { + uint8_t dst_mac[ETH_ALEN]; + uint8_t src_mac[ETH_ALEN]; + uint16_t ethertype; +} __attribute__((packed)); + +struct ip_header_ { + uint8_t vl; + uint8_t type_service; + uint16_t total_length; + uint16_t identification; + uint16_t fo; + uint8_t ttl; + uint8_t protocol; + uint16_t checksum; + uint32_t src_ip; + uint32_t dst_ip; +} __attribute__((packed)); + +struct udp_header_ { + uint16_t src_port; + uint16_t dst_port; + uint16_t length; + uint16_t checksum; +} __attribute__((packed)); + +struct payload { + uint32_t hop; + char message[32]; +} __attribute__((packed)); + +#define SIZE_PACKET (sizeof(struct eth_header) + sizeof(struct ip_header_) + sizeof(struct udp_header_) + sizeof(struct payload)) + +struct Bucket { + uint32_t ip; + unsigned int level; + time_t timestamp; + struct Bucket* next; +}; + +struct Address_node { + uint32_t ip; + time_t timestamp; + struct Address_node* next; +}; + +#endif diff --git a/2026/Ottaviano/utils.c b/2026/Ottaviano/utils.c new file mode 100644 index 00000000..0124244a --- /dev/null +++ b/2026/Ottaviano/utils.c @@ -0,0 +1,349 @@ +#include "utils_leaky_bucket.h" +#include "structure.h" +#include + + +/* + funzione utilizzata nei metodi per stampare le liste +*/ +void print_ip32(uint32_t ip){ + + // converte i byte dell'ip nell ordine giusto + + uint32_t h = ntohl(ip); + + // estrapolo ogni ottetto dall'indirizzo + + uint8_t occ1 = (h >> 24) & 0xff; + uint8_t occ2 = (h >> 16) & 0xff; + uint8_t occ3 = (h >> 8) & 0xff; + uint8_t occ4 = h & 0xff; + + // stampo l'indirizzo + + printf("%d.%d.%d.%d", occ1,occ2,occ3,occ4); +} + +void print_bucket(struct Bucket** table){ + for(int i = 0; SIZE > i; i++){ + struct Bucket* b = table[i]; + if(b == 0) continue; + + printf("Bucket[%d] -> ",i); + print_ip32(b->ip); + + while(b->next != NULL){ + b = b->next; + printf(" -> "); + print_ip32(b->ip); + } + printf("\n"); + } +} + +void print_blacklist(struct Address_node** blacklist){ + for(int i = 0; SIZE > i; i++){ + struct Address_node* b = blacklist[i]; + if(b == 0) continue; + + printf("blacklist[%d] -> ",i); + print_ip32(b->ip); + + while(b->next != NULL){ + b = b->next; + printf(" -> "); + print_ip32(b->ip); + } + printf("\n"); + } +} + +uint8_t hash(uint32_t ip){ + + // converte i byte dell'ip nell ordine giusto + + uint32_t h = ntohl(ip); + + // estrapolo gli ottetti + + uint8_t occ1 = (h >> 24) & 0xff; + uint8_t occ2 = (h >> 16) & 0xff; + uint8_t occ3 = (h >> 8) & 0xff; + uint8_t occ4 = h & 0xff; + + // ritorno l'indice relativo all'ip sommando i suoi ottetti + + return (occ1 + occ2 + occ3 + occ4) % SIZE; +} + +long int calc_rem(struct Bucket* b){ + // calcola quanti invertalli sono passati da quando questo elemento è stato inserito + return (time(NULL) - b->timestamp) / TTL_IP_IN_BUCKET; +} + +void update_blacklist(uint8_t index, struct Address_node** blacklist) { + + /* + aggiorno la lista nera controllando se ci sono indirizzi + che sono rimasti per un certo periodo di tempo + */ + struct Address_node* curr = blacklist[index]; + struct Address_node* prev = NULL; + + while(curr != NULL) { + if((time(NULL) - curr->timestamp) >= TTL_IP_IN_BLACKLIST) { + struct Address_node* temp = curr; + if(prev == NULL) { + // primo nodo + blacklist[index] = curr->next; + curr = curr->next; + } else { + prev->next = curr->next; + curr = curr->next; + } + free(temp); + } else { + prev = curr; + curr = curr->next; + } + } +} + +bool ipInBlacklist(uint32_t ip, uint8_t index, struct Address_node** blacklist){ + + // controllo se l'ip è presente nella lista nera + + struct Address_node* curr = blacklist[index]; + while(curr != NULL) { + if(curr->ip == ip) return true; + curr = curr->next; + } + return false; +} + +void check_bucket(struct Bucket** table, struct Address_node** blacklist){ + + /* + controllo se ci sono indirizzi che non inviano più + pacchetti da un certo periodo di tempo, eliminandoli dalla lista + + */ + + for(uint8_t i = 0; i < SIZE; i++){ + + struct Bucket* prev = NULL; + struct Bucket* b = table[i]; + + /* + AGGIORNO LA LISTA NERA, TOGLIENDO GLI INDIRIZZI CHE + SONO STATI ABBASTANZA TEMPO + */ + update_blacklist(i, blacklist); + + while(b != NULL){ + + /* + rem (remaining) rappresenta numero di + intervalli (TTL bucket) trascorsi dall’inserimento + */ + + long int rem = calc_rem(b); + + /* + level è il livello attuale dell’elemento e lo + aggiorno sottraendo il tempo trascorso + */ + if(rem >= b->level) b->level = 0; + else b->level -= rem; + + // SE IL LIVELLO È ARRIVATO A 0, LO ELIMINO DAL BUCKET + if(b->level == 0 || ipInBlacklist(b->ip, hash(b->ip), blacklist)){ + struct Bucket* temp = b; + + if(prev == NULL){ + table[i] = b->next; + b = table[i]; + } else { + prev->next = b->next; + b = b->next; + } + + struct in_addr addr; + addr.s_addr = temp->ip; + printf("Rimosso l'indirizzo %s dal bucket\n", inet_ntoa(addr)); + free(temp); + } else { + prev = b; + b = b->next; + } + } + } +} + +void free_buckets(struct Bucket** table){ + + /* + libero la memoria + */ + + for(int i = 0; SIZE > i; i++){ + struct Bucket* curr = table[i]; + while(curr != NULL){ + struct Bucket* temp = curr; + curr = curr->next; + free(temp); + } + table[i] = NULL; + } + +} + +void free_blacklist(struct Address_node** blacklist){ + + /* + libero la memoria + */ + + for(int i = 0; SIZE > i; i++){ + struct Address_node* curr = blacklist[i]; + while(curr != NULL){ + struct Address_node* temp = curr; + curr = curr->next; + free(temp); + } + blacklist[i] = NULL; + } + +} + +void process_packet(unsigned char* user, + const struct pcap_pkthdr* h, + const unsigned char* packet, pcap_t* in, pcap_t* out, + struct Bucket** table, struct Address_node** blacklist, + char* dev1, char* dev2){ + + struct ip_header_* header = (struct ip_header_*)(packet + sizeof(struct eth_header)); + + // CONTROLLO SE L'INDIRIZZO È PRESENTE NEL BUCKET + + check_bucket(table, blacklist); + + uint32_t ip = header->src_ip; + struct in_addr addr; + addr.s_addr = ip; + + // CONTROLLO SE È PRESENTE NLLA LISTA NERA + + if(ipInBlacklist(ip, hash(ip), blacklist)){ + + printf("Pacchetto scartato di %s\n", inet_ntoa(addr)); + print_bucket(table); + printf("\n"); + print_blacklist(blacklist); + return; + } + + // PRELEVO L'INDICE DELL'ARRAY IN CUI C'È L'IP CORRENTE + uint8_t index = hash(ip); + + struct Bucket* b = table[index]; + struct Bucket* prev = NULL; + bool found = false; + + /* + CERCO L'IP CORRENTE NEL BUCKET PER: + 1) INCREMENTARE IL LIVELLO + 2) VERIFICARE SE SUPERA LA CAPACITÀ, INSERENDOLO NELLA BLACKLIST + */ + + while(b != NULL){ + if(b->ip == ip){ + // HO TROVATO L'IP NEL BUCKET + found = true; + b->timestamp = time(NULL); + b->level++; + + // SE IL LIVELLO SUPERA LA CAPACITÀ DEL BUCKET, LA INSERISCO NELLA LISTA NERA + if(b->level > CAPACITY){ + if(!ipInBlacklist(ip, hash(ip), blacklist)){ + insert_ip_in_blacklist(ip, index, blacklist); + printf("Pacchetto da %s inserito nella blacklist\n", inet_ntoa(addr)); + //fprintf(fp, "[%ld] pacchetto da %s inserito nella blacklist\n", time(NULL), inet_ntoa(addr)); + //fflush(fp); + } + } else { + // INVIO IL PACCHETTO ALLA SECONDA INTERFACCIA + if(pcap_sendpacket(out, packet, SIZE_PACKET) != 0){ + printf("errore nell'invio del pacchetto: %s\n!",pcap_geterr(in)); + } else { + printf("[%s] pacchetto inviato all'interfaccia [%s]!\n", + dev1, dev2); + } + } + break; + } + // COLLISIONE, ESPLORO NELLA LISTA CONCATENATA + prev = b; + b = b->next; + } + + /* + SE NON HO TROVATO L'IP NEL BUCKET, LO INSERISCO. + */ + + if(!found){ + struct Bucket* newb = malloc(sizeof(struct Bucket)); + if(!newb){ + perror("malloc"); + exit(1); + } + + newb->ip = ip; + newb->level = 1; + newb->timestamp = time(NULL); + newb->next = NULL; + + if(prev == NULL){ + table[index] = newb; + } else { + prev->next = newb; + } + + if(pcap_sendpacket(out, packet, SIZE_PACKET) != 0){ + printf("errore nell'invio del pacchetto: %s\n!",pcap_geterr(in)); + } else { + printf("[%s] pacchetto inviato all'interfaccia [%s]!\n", + dev1, dev2); + } + } + +} + +void insert_ip_in_blacklist(uint32_t ip, uint8_t index, struct Address_node** blacklist){ + + /* + inserisco l'ip nella lista nera + */ + + struct Address_node* node = (struct Address_node*)malloc(sizeof(struct Address_node)); + + if(node == NULL){ + perror("malloc address node"); + exit(0); + } + + node->ip = ip; + node->timestamp = time(NULL); + node->next = NULL; + + if(blacklist[index] == 0){ + blacklist[index] = node; + } else { + struct Address_node* temp = blacklist[index]; + while(temp->next != NULL){ + temp = temp->next; + } + temp->next = node; + } + +} diff --git a/2026/Ottaviano/utils_leaky_bucket.h b/2026/Ottaviano/utils_leaky_bucket.h new file mode 100644 index 00000000..bc460723 --- /dev/null +++ b/2026/Ottaviano/utils_leaky_bucket.h @@ -0,0 +1,41 @@ +#ifndef UTILS_H +#define UTILS_H + +#include +#include +#include +#include + +#define DEFAULT_SNAPLEN 256 +#define CAPACITY 2 +#define TTL_IP_IN_BUCKET 5 +#define TTL_IP_IN_BLACKLIST 7 +#define SIZE 10 + +#include "structure.h" +#include + +void print_ip32(uint32_t ip); + +void print_bucket(struct Bucket** table); +void print_blacklist(struct Address_node** blacklist); +uint8_t hash(uint32_t ip); + +long int calc_rem(struct Bucket* b); + +void update_blacklist(uint8_t index, struct Address_node** blacklist); +bool ipInBlacklist(uint32_t ip, uint8_t index, struct Address_node** blacklist); + +void check_bucket(struct Bucket** table, struct Address_node** blacklist); + +void free_buckets(struct Bucket** table); + +void free_blacklist(struct Address_node** blacklist); +void process_packet(unsigned char* user, + const struct pcap_pkthdr* h, + const unsigned char* packet, pcap_t* in, pcap_t* out, + struct Bucket** table, struct Address_node** blacklist, + char* dev1, char* dev2); + +void insert_ip_in_blacklist(uint32_t ip, uint8_t index, struct Address_node** blacklist); +#endif