mirror of
https://github.com/ChronosX88/netsukuku.git
synced 2024-12-23 01:11:47 +00:00
1209 lines
60 KiB
Plaintext
1209 lines
60 KiB
Plaintext
|
|
|
|
Netsukuku
|
|
|
|
- Close the world, txEn eht nepO -
|
|
|
|
|
|
|
|
--
|
|
|
|
0. Preface
|
|
|
|
1. The old wired
|
|
|
|
2. The Netsukuku wired
|
|
|
|
2.1 Gandhi
|
|
2.2 No name, no identity
|
|
2.3 So, WTF is it?
|
|
2.4 Other implementations
|
|
2.5 The born
|
|
|
|
--
|
|
|
|
3. Netukuku Protocol v7: the seventh son of Ipv7
|
|
|
|
3.1 #define Npv7
|
|
|
|
4. Npv7_II: Laser Broadcast
|
|
|
|
5. Npv7 Hybrid Theory: the final way
|
|
|
|
5.1 QSPN: Quantum Shortest Path Netsukuku
|
|
5.1.1 QSPN screenshot
|
|
5.1.2 Continual qspn starters
|
|
5.1.3 The Qspn sickness: RequestForRoute
|
|
5.1.4 Qspn round
|
|
|
|
5.2 Npv7_HT Hook & Unhook
|
|
5.2.1 Qspn Hook & Unhook
|
|
|
|
5.3 The truly Gnode^n for n<=INFINITE
|
|
5.3.1 Groupnode: one entity
|
|
5.3.2 Gnode fusion
|
|
|
|
6. Broadcast: There can be only one!
|
|
|
|
6.1 Tracer pkt: one flood, one route
|
|
|
|
7. ANDNA: Abnormal Netsukuku Domain Name Anarchy
|
|
|
|
7.1 ANDNA Metalloid elements: registration recipe
|
|
7.1.1 ANDNA hook
|
|
7.1.2 Don't rob my hostname!
|
|
7.1.3 Count again
|
|
7.1.4 Registration step by step
|
|
7.1.5 Endless rest and rebirth
|
|
7.1.6 Hash_gnodes mutation
|
|
7.1.7 Yaq: Yet another queue
|
|
|
|
7.8 Hostname resolution
|
|
7.8.1 Distributed cache for hostname resolution
|
|
7.8.2 noituloser emantsoh esreveR
|
|
|
|
7.9 dns wrapper
|
|
|
|
8. Heavy Load: flood your ass!
|
|
|
|
9. Spoof the Wired: happy kiddies
|
|
|
|
10. /dev/Accessibility
|
|
|
|
11. Internet compatibility
|
|
|
|
12. Implementation: let's code
|
|
|
|
13. What to do
|
|
|
|
14. The smoked ones who made Netsukuku
|
|
|
|
--
|
|
|
|
0. Preface
|
|
|
|
Questo documento ed il codice sorgente relativo sono disponibili su:
|
|
http://netsukuku.freaknet.org
|
|
|
|
Le future modifiche e aggiunte a questo documento possono essere trovate
|
|
e proposte qui: http://lab.dyne.org/Netsukuku
|
|
|
|
Nota: questa NON e' l'ultima versione del documento.
|
|
L'ultima versione e' quella inglese:
|
|
http://netsukuku.freaknet.org/doc/netsukuku
|
|
Se vuoi tradurre le parti mancanti, non fare complimenti ;)
|
|
|
|
|
|
1. The old wired
|
|
|
|
Internet e' una rete gerarchica gestita da multinazionali ed enti che vengono
|
|
supportati dai governi. Ogni bit di traffico dati passa attraverso le loro
|
|
backbone e i loro router.
|
|
Gli Internet Service Provider offrono la connettivita' a tutti gli utenti,
|
|
che si trovano nelle parti piu' basse di questa scala gerarchica.
|
|
Non esiste alcun modo per condividere la proprieta' di Internet e quindi,
|
|
gli utenti, per connettersi alla grande Rete, sono costretti a sottostare
|
|
alle pesanti condizioni imposte dalle mega-corporation.
|
|
Internet e' oggi il mezzo di comunicazione per eccellenza che permette la
|
|
diffusione e la condivisione globale del sapere e dell'informazione.
|
|
Circa 1 miliardo di persone possono connettersi a questa grande rete
|
|
proprietaria, ma le restanti 5 miliardi, che non hanno sufficienti
|
|
risorse economiche, aspettano tutt'ora che le multinazionali offrano loro
|
|
un servizio realmente accessibile.
|
|
|
|
Internet e' nato per garantire una comunicazione sicura e inattaccabile tra
|
|
i vari nodi della rete, ma adesso, paradossalmente, quando un ISP decide di
|
|
non fornire piu' il suo servizio intere sono immediatamente tagliate fuori
|
|
da Internet.
|
|
|
|
Inoltre, Internet non e' una rete anonima: gli ISP e le multinazionali
|
|
possono intercettare e analizzare il traffico che passa dai loro server
|
|
senza alcun vincolo.
|
|
|
|
La struttura gerarchica e centralizzata di Internet crea, di conseguenza,
|
|
altri sistemi identici che poggiano su di essa, come ad esempio il DNS.
|
|
I server del Domain Name System vengono anch'essi gestiti dai vari ISP, i
|
|
domini vengono letteralmente venduti e le maglie di un sistema centralizzato
|
|
rimangono immutate.
|
|
Questo tipo di struttura permette, in modo semplice ed efficace, di
|
|
localizzare fisicamente qualsiasi computer connesso ad Internet in
|
|
pochissimo tempo e senza alcuno sforzo.
|
|
|
|
In Cina, l'intera rete e' sorvegliata continuamente da numerosi computer che
|
|
filtrano il traffico Internet: un cinese non potra' mai vedere e in ogni
|
|
caso venire a conoscenza di un sito che contiene delle parole chiavi
|
|
censurate dallo Stato. Se, poi, egli osasse esprimere sulla rete un pensiero
|
|
contrario alla dottrina politica del governo, rischierebbe perfino la pena
|
|
di morte.
|
|
|
|
Internet e' nato per soddisfare le esigenze di sicurezza militare
|
|
dell'amministrazione della difesa degli USA, e nel corso del tempo, la
|
|
sua struttura originaria non e' cambiata, ne' mai potra' mutare.
|
|
La liberta' di comunicazione e d'informazione su Internet saranno sempre
|
|
negate: per comunicare saremo sempre costretti a chiedere il preventivo
|
|
beneplacito di autorita' statali e mendicare il supporto di gigantesche
|
|
multinazionali che, in tal modo, continueranno ad espandere il proprio
|
|
dominio.
|
|
Se, di fatto, i tentativi di rendere Internet il mezzo di comunicazione
|
|
libero per eccellenza, sono destinati a fallire, allora non ci resta altro
|
|
da fare che sostituirlo.
|
|
Come?
|
|
Con una rete distribuita, decentralizzata e pienamente efficiente, una rete
|
|
che non possa essere sottoposta a nessun tipo di governo.
|
|
|
|
2. The Netsukuku wired
|
|
|
|
Netsukuku e' una mesh network o un sistema p2p che si crea e si mantiene
|
|
autonomamente.
|
|
Netsukuku e' stato progettato per gestire un numero illimitato di nodi con
|
|
un minimo uso di CPU e memoria. Questa sua caratteristica puo' essere
|
|
sfruttata per costruire, senza il supporto di alcun server o ISP, una rete
|
|
globale distribuita, anonima e non controllata, separata da Internet.
|
|
Questa rete e' formata da computer collegati fisicamente tra loro, quindi
|
|
non e' costruita su alcuna altra rete. Netsukuku si occupa solamente di
|
|
costruire le rotte che collegano tutti i computer della rete.
|
|
In altre parole, Netsukuku sostituisce il livello 3 del modello iso/osi con
|
|
un altro protocollo di routing.
|
|
|
|
Poiche' Netsukuku, e' una rete distribuita, e non centralizzata, e'
|
|
possibile implementare su di essa effettivi sistemi distribuiti, come ad
|
|
esempio l'Abnormal Netsukuku Domain Name Anarchy (ANDNA), che sostituira'
|
|
l'attuale sistema gerarchico e centralizzato dei DNS.
|
|
|
|
2.1 Gandhi
|
|
|
|
Netsukuku si crea e si gestisce da se'.
|
|
Un nodo si aggancia a Netsukuku, la rete si auto-riscrive e tutti gli altri
|
|
nodi conoscono quali sono le strade piu' veloci ed efficienti per comunicare
|
|
con il nuovo arrivato.
|
|
I nodi non hanno privilegi o limitazioni rispetto ad altri nodi, fanno parte
|
|
della rete e contribuiscono alla sua espansione ed efficienza.
|
|
Con l'aumentare del loro numero, la rete cresce e si perfeziona.
|
|
In Netsukuku non vi e' alcuna differenza tra reti private e pubbliche e non
|
|
ha piu' alcun significato parlare di LAN.
|
|
|
|
Netsukuku non puo' essere controllato ne' distrutto poiche' e' totalmente
|
|
decentralizzato e distribuito. L'unico modo per sorvegliare o smantellare
|
|
Netsukuku e' abbattere fisicamente ogni singolo nodo che lo compone.
|
|
|
|
2.2 No name, no identity
|
|
|
|
In Netsukuku chiunque, in qualunque luogo e in qualsiasi momento puo'
|
|
agganciarsi immediatamente alla rete senza dover passare attraverso
|
|
adempimenti burocratici o contrattuali.
|
|
Inoltre, ogni elemento della rete e' estremamente dinamico e non rimane mai
|
|
uguale a se' stesso. L'indirizzo IP che identifica un computer e' scelto
|
|
casualmente, quindi e' impossibile associarlo ad una localita' fisica
|
|
precisa, e le stesse rotte, essendo formate da un numero innumerevole di
|
|
nodi, tendono ad avere una complessita' e densita' talmente elevata da
|
|
rendere il tracciamento di un nodo un'impresa epica.
|
|
Poiche' non esiste alcun contratto con alcuna societa', la velocita' del
|
|
trasferimento dei dati e' limitata unicamente dalla tecnologia attuale delle
|
|
schede di rete.
|
|
|
|
2.3 So, WTF is it?
|
|
|
|
Netsukuku e' una mesh network o rete p2p composta da un protocollo di rete
|
|
per il routing dinamico, chiamato Npv7_HT.
|
|
Attualmente esistono molti protocolli ed algoritmi per il routing dinamico,
|
|
ma a differenza dell'Npv7_HT, vengono utilizzati solo per creare piccole e
|
|
medie reti. Anche i router di Internet sono gestisti da vari protocoli come
|
|
l'OSPF, il RIP o il BGP, che usano diversi algoritmi classici per trovare
|
|
il percorso migliore per raggiungere un nodo in una rete.
|
|
Questi protocolli richiedono un consumo di cpu e memoria elevatissimo, ed e'
|
|
per questo motivo che i router di Internet sono dei computer appositamente
|
|
dedicati. Sarebbe impossibile adottare uno di questi protocolli per creare
|
|
e mantenere una rete come Netsukuku, dove ogni nodo e' a sua volta un
|
|
router, perche' la mappa di tutte le rotte richiederebbe uno spazio, su
|
|
ciascun pc connesso alla rete, di circa dieci Gb.
|
|
|
|
L'Npv7 struttura l'intera rete come un frattale, ed usa un particolare
|
|
algoritmo chiamato Quantum Shortest Path Netsukuku (QSPN) per calcolare
|
|
tutte le rotte necessarie a collegare un nodo ad ogni altro nodo.
|
|
Un frattale e' una struttura matematica che si puo' comprimere all'infinito,
|
|
proprio perche', al suo interno, ogni sua parte e' formata dal frattale
|
|
stesso. Si ha quindi una compressione elevata di una struttura che
|
|
puo' espandersi infinitamente. Questo significa che bastano pochi Kb per
|
|
mantenere l'intera mappa di Netsukuku.
|
|
La struttura della mappa puo' anche essere definita in modo piu' preciso
|
|
come un grafo altamente clusterizzato.
|
|
|
|
Il QSPN, invece, e' un meta-algoritmo perche' non esegue una sequenza di
|
|
istruzioni matematiche definite ma sfrutta il caso e il caos, che non
|
|
richiedono nessun calcolo pesante.
|
|
Il QSPN deve essere eseguito su una rete reale (o simulata). I nodi devono
|
|
mandare i pacchetti QSPN per "eseguire" l'algoritmo, e per questo motivo
|
|
non e' sempre vero che un determinato pacchetto sara' mandato prima di un
|
|
altro.
|
|
|
|
2.4 Other implementations
|
|
|
|
Netsukuku non e' limitato alla creazione di una rete di soli computer, e' un
|
|
protocollo che implementa una rete pura, e cosi' come ogni protocollo di rete
|
|
puo' essere usato in tutte le situazioni in cui si ha bisogno di collegare
|
|
piu' nodi fra loro.
|
|
Prendiamo in esame il caso dei cellulari. Anche la rete dei cellulari e' una
|
|
rete gerarchica e centralizzata. Migliaia di nodi si appoggiano ad una
|
|
stessa cella, che poi smistera' il traffico alle altre celle, che, infine,
|
|
consegneranno i dati ai nodi destinatari. Bene, Netsukuku puo' essere
|
|
adottato anche dai cellulari, rendendo superflua l'esistenza degli attuali
|
|
gestori di telefonia mobile.
|
|
Questo ragionamento puo' essere applicato a tutti i sistemi di comunicazione
|
|
che esistono attualmente.
|
|
|
|
2.5 The born
|
|
|
|
La storia di come si sia arrivati a Netsukuku e' lunga e travagliata.
|
|
Durante un storica trasmissione di radio Cybernet, all'Hackmeeting del
|
|
2000, nasce l'idea dell'Ipv7, di nocoder e nocrypt: sono assurdi scherzi
|
|
teorici che trattano protocolli di rete, compilatori intelligenti e
|
|
programmi cryptografici.
|
|
Nel lontano 2003, un gruppo di pazzi deliranti continua a espandere i
|
|
concetti dell'Ipv7: una rete in cui tutti i pacchetti vengono mandati in
|
|
broadcast, compressi con le zlib7, un algoritmo che comprime l'attuale
|
|
Internet in 32 byte ( Vedi http://idiki.dyne.org/wiki/Zlib7 ).
|
|
In Ipv7 nessun nodo possiede un indirizzo IP e la rete e' estremamente
|
|
decentralizzata e libera. Quelle persone erano felici, e dopo la stesura del
|
|
primo RFC, un sorriso sereno e una luce angelica avvolgeva le loro figure.
|
|
|
|
Un anno trascorre, il progetto si perde tra le infinite diramazioni del
|
|
tempo, ma dopo non molto la polvere viene scrollata dal grande libro
|
|
dell'Ipv7. Si comincia a delirare sull'implementazione di una rete pura.
|
|
I mesi passano. La rete viene definita sempre di piu', diventa quasi
|
|
tangibile...
|
|
<<Ma deve anche supportare una qualche forma di antiflood e antispoofing>>.
|
|
<<Gia'! E si deve fare in modo che le rotte non siano mai uguali tra loro>>.
|
|
<<Si, si, e perche' non facciamo che non esistano piu' in assoluto dei server
|
|
centrali?>>.
|
|
Tre mesi dopo, a seguito di numerosissime peregrinazioni mistiche, il cuore
|
|
teorico e' pronto. Gli algoritmi sono definiti.
|
|
Si comincia a codare. La maledizione dei coder di protocolli di rete del
|
|
sacro faraone Mortedelprimogenito si riversa sul codice di Netsukuku. La
|
|
pazzia e il delirio sono la giusta ricompensa a tutti coloro i quali
|
|
osano addentrarsi nella creazione di protocolli di reti pure.
|
|
|
|
Nonostante tutto, esattamente dopo un anno e 14 mila righe di codice,
|
|
Netsukuku e' pronto e diventa Beta.
|
|
Due mesi dopo la presentazione di Netsukuku all'Hackmeeting 2005, il
|
|
protocollo di ANDNA, cosi' come il suo codice, e' completamente
|
|
definito e documentato.
|
|
In Ottobre, viene stata rilasciata la prima versione publica di Netsukuku.
|
|
|
|
Nel corso dei mesi il protocollo e il demone sono stati profondamente
|
|
migliorati e adesso, a Maggio del 2006, il codice ha raggiunto quaranta mila
|
|
righe.
|
|
|
|
Il resto giace in potenza e deve ancora divenire.
|
|
|
|
|
|
--
|
|
|
|
The Netsukuku Protocol
|
|
Npv7
|
|
|
|
|
|
|
|
3. Netsukukuku protocol v7
|
|
|
|
Netsukuku, usa l'Npv7 (Netsukuku protocol version 7), il suo protocollo, che
|
|
deriva da tre precedenti versioni.
|
|
La prima era strutturata in maniera simile agli attuali protocolli di rete
|
|
utilizzati per il routing dinamico: la rete era divisa in gruppi di nodi,
|
|
ogni nodo possedeva la mappa dell'intera rete.
|
|
Questo sistema, non ottimale, non e' adottato da Netsukuku poiche' prevede
|
|
l'aggiornamento continuo della mappa, ed ogni aggiornamento crea un overload
|
|
nella rete. Inoltre, ogni volta che la mappa cambia bisogna ricalcolarsi tutte
|
|
le rotte.
|
|
|
|
3.1 #define Npv7
|
|
|
|
Le definizioni basilari utilizzate per Netsukuku sono state e, tuttora sono:
|
|
|
|
src_node: Il Source node e' il nodo che manda un pacchetto al dst_node.
|
|
dst_node: Destination node, il node the riceve il pacchetto mandato dal
|
|
src_node.
|
|
|
|
r_node: Considerando un nodo X, un remote node (r_node) e' un qualsiasi
|
|
nodo direttamente collegato ad X.
|
|
g_node: Group node, un gruppo di nodi, o un gruppo di gruppi di nodi, e
|
|
cosi' via.
|
|
b_node: Border node, un nodo che ha rnodes di diversi gnode.
|
|
h_node: Hooking node, un nodo che si sta agganciando a netsukuku.
|
|
|
|
int_map: Internal map, mappa interna. La mappa interna del nodo X e' la mappa
|
|
che contiene le informazioni sui nodi che appartengono al gnode a cui
|
|
appartiene X.
|
|
ext_map: External map, mappa esterna. La mappa che contiene le informzioni sui
|
|
gnode.
|
|
bmap / bnode_map: Border node map. E' la mappa che tiene la lista dei
|
|
border node.
|
|
|
|
quadro_group: Un nodo, o un groupnode di qualsiasi livello, scomposto nelle
|
|
sue parti essenziali.
|
|
|
|
|
|
4. Npv7_II: Laser Broadcast
|
|
|
|
Npv7_II e' la seconda versione dell'Npv7.
|
|
Netsukuku viene suddiviso in tanti piccoli groupnode che contengono al
|
|
massimo 600 nodi. Ogni nodo di Netsukuku possiedera' solamente la mappa
|
|
esterna, quella dei groupnode.
|
|
Gli stessi groupnode vengono raggruppati in multi-groupnode, chiamati quadro
|
|
groupnode.
|
|
Per creare una rotta e raggiungere un determinato dst_node, il src_node,
|
|
usando la mappa esterna, calcola il percorso migliore per raggiungere il
|
|
gnode di destinazione a cui appartiene il dst_node.
|
|
La rotta cosi' trovata viene memorizzata nel pacchetto che viene spedito in
|
|
broadcast all'interno del gnode a cui appartiene l'src_node.
|
|
I border_node del gnode del src_node ricevono il pkt e controllano se il
|
|
prossimo gnode a cui deve essere mandato in broadcast il pkt e' proprio un
|
|
gnode con cui confinano. Se la condizione viene rispettata, i border_node
|
|
mandano in broadcast il pkt in quel gnode. In caso contrario il pkt viene
|
|
ignorato.
|
|
E cosi' via...
|
|
In questo modo il pacchetto arrivera' al gnode di destinazione.
|
|
Quando il dst_node riceve il pkt non deve far altro che settare una
|
|
rotta inversa usando la rotta memorizzata nel pkt.
|
|
L'Npv7_II e la sua versione precedente non vengono usate, ma sono alla base
|
|
dell'Npv7_HT, l'attuale versione del protocollo Netsukuku.
|
|
|
|
5. Npv7 Hybrid Theory: the final way
|
|
|
|
Dall'unione di Npv7 e Npv7_II e' derivato Npv7 Hybrid Theory.
|
|
Questa nuova versione, sfrutta i vantaggi della mappa interna e del laser
|
|
broadcast e cosi' facendo supera le loro imperfezioni.
|
|
In Npv7_HT il numero massimo di nodi presenti in un group node (MAXGROUPNODE)
|
|
e' pari a 2^8, i groupnode sono quindi relativamente piccoli.
|
|
In Npv7_HT il cambiamento principale riguarda la sua stessa essenza, infatti,
|
|
si basa su un algoritmo creato appositamente per Netsukuku, chiamato
|
|
Quantum Shortest Path Netsukuku, che permette di ottenere in un solo colpo la
|
|
situazione completa del g_node, tutte le rotte migliori, la riduzione del
|
|
carico del g_node, un'efficace gestione dei gnode molto dinamici,
|
|
l'abolizione del bisogno di autenticazione tra i nodi.
|
|
|
|
5.1 QSPN: Quantum Shortest Path Netsukuku
|
|
|
|
In Netsukuku, come in natura, non vi e' alcun bisogno di usare schemi
|
|
matematici. Un ruscello, per raggiungere il mare, calcolera' mai la strada
|
|
che dovra' percorrere quando ancora si trova in cima alla montagna? Il
|
|
ruscello scorrera' semplicemente, trasportato dal suo stesso flusso,
|
|
trovando cosi', prima o poi, la sua rotta ideale.
|
|
|
|
Netsukuku sfrutta lo stesso principio caotico. Il risultato finale
|
|
restituito dall'algoritmo che esplora la rete puo' essere constituito da
|
|
risultati intermedi ogni volta differenti, poiche' quest'algoritmo viene
|
|
"eseguito" dalla rete stessa.
|
|
|
|
L'uso di una mappa, in un protocollo di reti dinamiche, crea troppi
|
|
problemi, dovendo tenerla sempre aggiornata. La soluzione e' semplice: non
|
|
usare affatto una mappa e far diventare ogni richiesta mandata in broadcast
|
|
un tracer_pkt (Vedi 6.1 Tracer pkt).
|
|
In questo modo ogni nodo che ricevera' il pkt sapra' qual e' la rotta
|
|
migliore per raggiungere il src_node e tutti i nodi che stanno
|
|
in mezzo alla rotta, si memorizzera' queste info nella sua mappa interna,
|
|
aggiungera' la sua entry nel tracer_pkt e fara' continuare il broadcast del
|
|
pkt.
|
|
Rimane un grosso problema: per avere tutte le rotte per tutti i nodi
|
|
bisogna che tutti i nodi mandino in broadcast un tracer_pkt. In realta' questo
|
|
problema e' del tutto inconsistente. Infatti, con il tracer_pkt possiamo
|
|
ricavare anche le rotte per i nodi intermedi; questo vuol dire che abbiamo
|
|
bisogno di un numero < di n pacchetti, dove n e' il numero dei nodi.
|
|
Se ogni nodo rimanda indietro un tracer_pkt ogni volta che ne riceve uno,
|
|
siamo sicuri che tutti i nodi ricevono tutte le rotte possibili, cosi'
|
|
facendo ricaviamo lo stesso risultato raggiunto dal far mandare un
|
|
tracer_pkt da tutti i nodi.
|
|
|
|
Per chi ha presente la fisica delle onde, il funzionamento del qspn puo'
|
|
essere facilmente compreso. Se lanciamo un sassolino in uno specchio d'acqua,
|
|
contenuto in una bacinella, dal punto di impatto incominciano a propagarsi
|
|
delle onde circolari. Ogni onda genera un'onda figlia che continua ad
|
|
espandersi ed a generare figli che generano figli e cosi' via...
|
|
Quando un'onda colpisce i bordi della bacinella, viene riflessa e ritorna
|
|
verso il punto d'origine; lo stesso avviene se l'onda incontra un ostacolo.
|
|
Il qspn_starter e' il sassolino gettato nel groupnode ed ogni onda e' un
|
|
tracerpkt. Ogni onda figlia porta con se' l'informazione dell'onda padre.
|
|
Quando l'onda arriva in un extreme_node (un ostacolo, un vicolo cieco) parte
|
|
il qspn_open (l'onda riflessa).
|
|
|
|
Il QSPN si basa su questo principio. Per iniziare il tracciamento del g_node,
|
|
un qualsiasi nodo manda un qspn_pkt (chiamato qspn_close), questo nodo diventa
|
|
quindi un qspn_starter.
|
|
Un qspn_pkt e' un normale tracer_pkt, ma il modo in cui si diffonde in
|
|
broadcast e' leggermente diverso dal normale.
|
|
Ogni nodo che riceve il qspn_pkt "chiude" il link da cui ha ricevuto il pkt,
|
|
e spedisce il pkt a tutti gli altri link. Tutti i successivi pacchetti
|
|
qspn_close che arriveranno al nodo saranno mandati a tutti i link ancora non
|
|
chiusi.
|
|
Una volta che il qspn_close e' diffuso, alcuni nodi si troveranno con tutti i
|
|
link chiusi. Questi nodi saranno gli extreme_node che invieranno un altro
|
|
qspn_pkt di risposta (chiamato qspn_open), che contiene l'informazione gia'
|
|
accumulata, a tutti i link, tranne a quello da cui hanno ricevuto l'ultimo
|
|
qspn_close che li ha completamente chiusi a cui invieranno un qspn_open
|
|
vuoto.
|
|
Il qspn_open e' un normale qspn_pkt, quindi "apre" tutti i link alla stessa
|
|
maniera del qspn_close. I nodi che si troveranno con tutti i link aperti non
|
|
faranno assolutamente nulla, questo garantisce la fine del qspn_open.
|
|
Un qspn_open possiede anche un sub_id, un numero che indentifica nella mappa
|
|
interna l'extreme_node che l'ha creato. Il sub_id, che rimane inalterato per
|
|
tutti i pacchetti qspn_open figli generati dal primo pacchetto, viene usato
|
|
per gestire piu' qspn_pkt simultaneamente, poiche' ogni extreme_node genera
|
|
un qspn_open ed ognuno dovra' essere indipendente dall'altro.
|
|
Tutti i nodi con un solo link sono gli e_node per eccellenza, infatti non
|
|
appena ricevono un qspn_close sono gia' chiusi.
|
|
|
|
Una volta che un nodo ha mandato un qspn_open non rispondera' piu' a
|
|
qualsiasi qspn_pkt che gli arrivera' (sempre relativamente alla sessione
|
|
corrente), quindi non mandera' piu' qspn_close ne' qspn_open.
|
|
Il qspn_starter, il nodo che ha innescato il qspn, si comporta come un
|
|
normale nodo pero' non puo' mandare qspn_open perche' ha gia' mandato il
|
|
primo qspn_close in assoluto, inoltre tutti i qspn_close che riceve li usa
|
|
per aggiornare la sua mappa, ma se hanno gia' percorso piu' hop o se sono
|
|
stati spediti da lui stesso, vengono ignorati; questo accorgimento garantisce
|
|
la stabilita' nel caso ci siano piu' qspn_starter simultanei. La descrizione
|
|
approfondita del qspn_starter e' nella sezione successiva 5.1.1.
|
|
|
|
Alla fine i pacchetti di broadcast che vengono generati con qspn sono pari al
|
|
numero degli e_node, ovvero 2 per ogni segmento di rete ciclico e 1 per un
|
|
segmento singolo non ciclico.
|
|
|
|
L'informazione per le rotte viene in ogni caso accumulata ogni volta che
|
|
qualche tracer_pkt gira per la rete. Un nodo ricevera' molto probabilmente
|
|
diverse rotte per raggiungere uno stesso nodo, ma memorizzera' solamente le
|
|
prime MAXROUTES (10) rotte migliori.
|
|
|
|
Il pkt_id dei qspn_pkt inizia da 1 e viene incrementato di 1 ogni volta che
|
|
un nodo ne spedisce uno nuovo.
|
|
Quindi, tutti i nodi conoscono il pkt_id corrente. Ogni qualvolta un nodo
|
|
deve far aggiornare la mappa interna o esterna manda un qspn_close, solamente
|
|
se non ha ricevuto entro i precedenti QSPN_WAIT secondi un altro qspn_close.
|
|
Se due nodi mandano nello stesso momento un qspn_close, useranno lo stesso
|
|
pkt_id, perche' nessuno dei due sa che ne e' stato gia' spedito un altro; in
|
|
questo caso il funzionamento del qspn non cambia, anzi se i due qspn_pkt
|
|
sono partiti da due luogi molto distanti allora il qspn_pkt si diffondera'
|
|
molto rapidamente.
|
|
|
|
Quando un nodo prende la mappa interna da un altro nodo, non deve
|
|
far altro che aggiungere l'r_node, da cui ha preso la mappa, all'inizio
|
|
di tutte le rotte. Se scarica la mappa da piu' r_node, dovra' confrontare
|
|
tutte le rotte e scegliere la piu' breve. La mappa risultante avra' tutte
|
|
le rotte migliori.
|
|
|
|
Le rotte della mappa interna ed esterna verranno sempre ricopiate nella
|
|
tabella di routing del kernel. In questo modo non ci sara' alcun bisogno di
|
|
creare ogni volta la rotta necessaria per raggiungere il nodo di
|
|
destinazione.
|
|
|
|
5.1.1 QSPN screenshot
|
|
|
|
(A)-----(B)
|
|
/ | \ | \
|
|
(E) | \ | (F)
|
|
\ | \ | /
|
|
(C)-----(D)
|
|
|
|
Ricapitolando, tutti i nodi estremi dovrebbero inviare un tracer_pkt, ma non
|
|
si puo' sapere quali essi siano. In questo disegnino e' facile individuarli,
|
|
perche', appunto, la mappa e' disegnata, me nella realta' (nel codice di
|
|
Netsukuku) non esiste una mappa topologica, quindi non si puo' sapere dove
|
|
inizia un gruppo di nodi e dove finisce.
|
|
|
|
Ecco cosa succede, in uno scenario immaginario, se il nodo E manda un
|
|
qspn_close:
|
|
E ha mandato il primo qspn_close del nuovo qspn_round, quindi e' diventato
|
|
un qspn_starter.
|
|
Consideriamo il caso in cui il nodo A riceve prima di C il qspn_close.
|
|
A chiude il link E, manda il pkt a B, C, e D.
|
|
C riceve il pkt, chiude il link E, lo manda ad A ed a D.
|
|
C riceve da A, chiude il link.
|
|
|
|
B e D hanno ricevuto, e chiudono i rispettivi link.
|
|
Consideriamo il caso in cui il nodo B manda per primo il pkt ad F.
|
|
D lo manda ad F subito dopo, ma nello stesso momento F lo manda a D.
|
|
D ha ricevuto il pkt anche da B.
|
|
D ed F hanno tutti i link chiusi.
|
|
Mandano un qspn_open.
|
|
Tutto avviene nel senso opposto.
|
|
Finisce il qspn_open.
|
|
Tutti hanno le rotte per raggiungere tutti.
|
|
|
|
In genere, la topologia base a cui si riconduce il qspn e' un rombo con i
|
|
nodi ai vertici, per renderla piu' complessa e' possibile aggiungere altri
|
|
rombi uniti tra di loro con i vertici.
|
|
Tutte le altre situazioni derivano piu' o meno da questa.
|
|
|
|
5.1.2 Continual qspn starters
|
|
|
|
Se piu' qspn_starter che lanciano un qspn sono contigui fra loro allora
|
|
il funzionamento del qspn varia leggermente. Un gruppo di nodi qspn_starter
|
|
e' contiguo quando tutti i suoi nodi sono collegati a nodi che sono a
|
|
loro volta dei qspn_starter. In questo scenario i qspn_starter continuano a
|
|
inoltrare tra di loro solo i qspn_close mandati dai qspn_starter; si
|
|
comportano quindi come dei normali nodi, infatti non appena ricevono dei
|
|
pacchetti provenienti dall'esterno del gruppo contiguo di qspn_starters
|
|
ritornano a seguire le loro istruzioni originarie. Quindi se A manda un
|
|
qspn_close e B ha mandato pure un qspn_close, quando B riceve il qspn_close
|
|
di A lo inoltra come un normale tracer_pkt con la flag BCAST_TRACER_STARTERS
|
|
che si diffonde solo tra gli altri starter.
|
|
Il motivo di tutto questo deriva dal fatto che in quel gruppo contiguo di
|
|
nodi, ogni singolo nodi manda un tracer_pkt, quindi, i qspn_pkt vengono
|
|
declassati a normali tracer_pkt.
|
|
|
|
5.1.3 The Qspn sickness: RequestForRoute
|
|
|
|
/* Da codare, e non realmente necessario */
|
|
L'unico grande difetto di qspn e' l'impossibilita' di avere molte piu' rotte
|
|
per raggiungere uno stesso nodo. Con il qspn si e' sicuri di avere solamente
|
|
le rotte migliori, e basta. In realta' il qspn puo' anche generare infinite
|
|
rotte, basta che si lasci circolare il broadcast all'infinito (^_-).
|
|
Ovviamente e' impensabile aspettare un'intera eternita' o due, quindi si usa
|
|
il RequestForRoute! Il RFR verra' usato ogni volta che un nodo si connette
|
|
ad un altro.
|
|
Ecco cosa succede:
|
|
il nodo manda a tutti i suoi rnode una richiesta RFR per una determinata
|
|
rotta, questa richiesta contiene anche il numero di sub richieste
|
|
(total_routes) che gli rnode devono mandare ai loro rnode. In pratica il
|
|
nodo decide quante rotte ricevere e si calcola il numero di sub richieste
|
|
che dovranno mandare i suoi rnode:
|
|
subrfr = (total_routes - r_node.links) / r_node.links
|
|
Dopo invia il RFR.
|
|
I suoi rnode, dopo avergli mandato la rotta che loro usano per raggiungere il
|
|
dst_node specificato nel rfr_pkt, mandano allo stesso modo un RFR che pero'
|
|
ha total_routes pari a subrfr. Gli rnode degli rnode eseguiranno la stessa
|
|
procedura e risponderanno direttamente al nodo interessato.
|
|
|
|
5.1.4 Qspn round
|
|
|
|
Se un nodo riscontra un cambiamento attorno a se', ad esempio un suo
|
|
rnode e' morto oppure l'rtt che lo distanzia dal suo rnode e' cambiato
|
|
considerevolmente, allora mandera' un QSPN. Per evitare che vengano creati
|
|
dei QSPN continuamente, il nodo deve prima verificare che il QSPN_WAIT_ROUND
|
|
(60 secondi) sia scaduto. Il QSPN_WAIT_ROUND scade nello stesso momento per
|
|
tutti i nodi appartenenti allo stesso gnode. Per far si' che i nodi che si
|
|
agganciano al gnode siano sincronizzati ai nodi del gnode stesso, gli viene
|
|
dato il numero di secondi che sono passati dal precedente QSPN, in questo
|
|
modo tutti i nodi sapranno quando si verifichera' la prossima scadenza,
|
|
ovvero avverra' dopo (current_time - prev_qspn_round) + QSPN_WAIT_ROUND
|
|
secondi.
|
|
Quando un qspn_starter manda un nuovo qspn_pkt, incrementa l'id del
|
|
qspn_round di 1.
|
|
Se il nodo che riceve un qspn_pkt, vede che il suo id e' maggiore del
|
|
qspn_round id precedente che ha memorizzato, allora vuol dire che ha ricevuto
|
|
un nuovo qspn_round; in questo caso aggiornera' il suo id locale e il suo
|
|
qspn_time (la variabile che indica quando e' stato ricevuto/mandato l'ultimo
|
|
qspn).
|
|
Per aggiornare il qspn_time, dovra' settarlo a
|
|
current_time - somma_degli_rtt_contenuti_nel_tracer_pkt.
|
|
|
|
5.2 Npv7_HT Hook & Unhook
|
|
|
|
Un nodo, per entrare a far parte di Netsukuku, deve agganciarsi ai suoi
|
|
rnode.
|
|
L'hook in Netsukuku non si riferisce ad un aggancio alla rete "fisico",
|
|
poiche' si presuppone gia' che un nodo sia linkato ad altri (r)_node.
|
|
Quando un nodo si aggancia significa che comunica con un il suo rnode piu'
|
|
vicino, se non gli risponde ne sceglie un altro. In pratica durante l'hook,
|
|
il nodo si prende la mappa interna, quella esterna, la mappa dei border
|
|
node, e si sceglie un IP libero. A questo punto fa ufficialmente parte della
|
|
rete, quindi manda un normale tracer_pkt. I suoi rnode manderanno in seguito,
|
|
un qspn.
|
|
|
|
Ecco cosa avviene piu' in dettaglio:
|
|
Il nodo si prende un IP compreso tra 10.0.0.1 <= x <= 10.0.0.1+256,
|
|
rimuove le reti di loopback dalla tabella locale di routing e setta come
|
|
default gateway l'IP scelto.
|
|
Il primo passo e' quello di lanciare il primo radar per vedere quali sono i
|
|
suoi r_nodes. Se non ci sono rnodes, crea un nuovo gnode e l'hook termina qui.
|
|
Poi chiede all'rnode piu' vicino la lista di nodi liberi (free_nodes)
|
|
presenti nel gnode dell'rnode. Se l'rnode non accetta la richiesta (il gnode
|
|
potrebbe essere pieno), il nodo chiede la lista ad un altro rnode.
|
|
Dai free_nodes ricevuti sceglie un IP e lo setta all'interfaccia di rete,
|
|
modificando il default gw.
|
|
A questo punto richiede la mappa esterna allo stesso rnode da cui ha preso la
|
|
list di nodi liberi. Usando la lista di free_nodes vede se deve creare un
|
|
nuovo gnode. Se non deve, prende l'int_map da ogni r_node.
|
|
Unisce tutte le int_map ricevute in un unica mappa, in questo modo ha gia'
|
|
tutte le rotte. Infine, si prende la bnode_map.
|
|
Se tutto e' andato a buon fine, rilancia un secondo radar, manda un semplice
|
|
tracer_pkt e aggiorna la sua tabella di routing. Fin.
|
|
|
|
5.2.1 Qspn Hook & Unhook
|
|
|
|
Un nodo, dopo essersi agganciato al gnode, non deve far altro che mandare
|
|
un tracer_pkt. In questo modo tutti i nodi avranno gia' la rotta esatta
|
|
per raggiungerlo, aggiorneranno qualche rotta e saranno felici. Poi per
|
|
quanto riguarda le rotte secondarie ci pensera' il round successivo di QSPN.
|
|
Quando un nodo muore o si sgancia, non dice nulla a nessuno. I suoi rnode si
|
|
accorgeranno della sua morte e manderanno un nuovo qspn_round.
|
|
|
|
5.3 The truly Gnode^n for n<=INFINITE
|
|
|
|
Nel mondo ci sono 6*10^9 di persone, se andremo a colonizzare
|
|
altri pianeti arriveremo a circa (6*10^9)^n, dove n e' un numero random > 0.
|
|
E' anche vero che ci estingueremo molto prima in una delle solite stupide
|
|
guerre. In sostanza netsukuku deve provvedere a un numero ENORME di nodi,
|
|
per questo, come gia' sai, si usano i gnode.
|
|
Ma questo non basta, perche' anche cosi' ci vorrebbero 300Mb circa per
|
|
tenere l'intera extern map! Come si fa quindi?
|
|
Si dividono i gnode in ulteriori gruppi, stavolta pero' questi gruppi non
|
|
contengono nodi normali ma degli interi gnode, che vengono considerati dei
|
|
nodi a tutti gli effetti... Procedendo recursivamente netsukuku puo'
|
|
contenere all'incirca INFINITI nodi.
|
|
Tutto rimane invariato.
|
|
Per implementare questi gnode frattali e' necessario usare piu' di una mappa
|
|
esterna che conterranno l'informazione su questi gruppi di gruppi. Questi
|
|
"gruppi di gruppi" li continuiamo a chiamare groupnode.
|
|
Ogni mappa di groupnode appartiene ad un determinato livello. Quindi il
|
|
groupnode normale, che racchiude singoli nodi si trova a livello 0, la mappa
|
|
del primo groupnode di gruppi di nodi si trova al primo livello, e la mappa
|
|
di groupnode di groupnode di groupnode e' al secondo, e cosi' via.
|
|
Un nodo per poter contattare qualsiasi altro nodo in qualsiasi parte del
|
|
globo deve avere solamente la sua mappa interna, che non e' nient'altro
|
|
che la mappa a livello 0 e poi le mappe di tutti i livelli superiori in
|
|
cui lui e' presente. Facendo qualche calcolo con l'ipv4, per usare tutti
|
|
gli IP, si devono usare solamente 3 livelli di mappe. Il che significa che
|
|
prima c'e' il normale groupnode, poi ci sono MAXGROUPNODE di groupnode,
|
|
e infine ci sono MAXGROUPNODE di questi ultimi. Nell'IPv6 invece, abbiamo
|
|
una quantita' abnorme di IP, percio' i livelli ammontano a 16. Facendo una
|
|
stima approssimativa, tutte le mappe esterne dei groups nell'IPv4 occupano
|
|
144K di memoria e nell'IPv6 1996K. Questo significa che nessuno si deve
|
|
preoccupare di usare lo swap!
|
|
|
|
Per trovare le rotte che connettono i vari gruppi verra' usato il QSPN,
|
|
avevi dubbi -_^ ? Il qspn verra' ristretto e lanciato per ogni livello, in
|
|
questo modo, ad esempio, trovera' tutte le rotte che legano i nodi
|
|
appartenenti al secondo livello...
|
|
Questo sistema dei livelli in relta' non e' complesso, basta tenere
|
|
presente il funzionamento della mappa interna in unione a quello della
|
|
mappa esterna ed applicare recursivamente ad ogni grouppo lo stesso concetto.
|
|
Basta considerare ogni grouppo un singolo nodo.
|
|
La rotta usata per raggiungere un groupnode, nella routing table, e' formata
|
|
da range di IP (da IP x ad IP y) invece di un singolo IP.
|
|
In questo modo, per poter raggiungere tutti i nodi presenti in netsukuku
|
|
bisogna tenere nella routing table MAXGROUPNODE*(levels+1) rotte.
|
|
Consideriamo il caso dell'IPv4 che ha 3 livelli.
|
|
Intanto un nodo deve avere tutte le rotte per raggiungere tutti
|
|
i nodi all'interno del suo groupnode, percio' gia' abbiamo MAXGROUPNODE
|
|
di rotte, poi dobbiamo aggiungere tutte le rotte per raggiungere gli
|
|
altri groupnode del suo livello superiore, percio' aggiungiamo altri
|
|
MAXGROUPNODE di rotte. Proseguendo arriviamo all'ultimo livello ed abbiamo
|
|
MAXGROUPNODE*(3+1). Con l'IPv4 abbiamo 1024 rotte, con l'IPv6 4352.
|
|
Tutte queste rotte risiederanno direttamente nel kernel.
|
|
|
|
5.3.1 Groupnode: one entity
|
|
|
|
Per avere il qspn effettivo dei groupnode la storia cambia un po'.
|
|
La differenza tra un groupnode ed un nodo singolo risiede nel fatto che il
|
|
nodo e' un'unica entita' che gestisce i suoi link direttamente da se', il
|
|
groupnode, invece, e' un nodo composto da piu' nodi e i suoi link sono
|
|
gestisti da altri nodi che sono i border node. Per rendere il groupnode
|
|
un'unica entita' che si comporti esattamente come un nodo singolo basta che
|
|
tutti i bnode del groupnode comunichino tra loro. Quindi, quando un bnode
|
|
riceve un qspn_close da un altro groupnode, chiudera' il suo link e quando
|
|
avra' tutti i suoi link con gli altri gnode chiusi, lo comunichera' agli
|
|
altri bnode del suo groupnode. Lo stesso faranno gli altri. In questo modo
|
|
il qspn_open sara' mandato solamente quando tutti i bnode avranno tutti i
|
|
loro link esterni chiusi.
|
|
Quando parliamo di groupnode di alti livelli allora un bnode non e' piu' un
|
|
singolo nodo, ma e' a sua volta un gnode. Il procedimento resta invariato:
|
|
questo bnode-gnode e' rappresentato da tutti i suoi bnodes interni.
|
|
Ma come fanno i bnode a comunicare fra loro?
|
|
Ovviamente in modo passivo: quando un bnode chiude tutti i suoi link esterni
|
|
dopo aver ricevuto un qspn_close, setta nel tracer_pkt che sta per
|
|
forwardare la flag BNODE_CLOSED, in questo modo gli altri bnode, vedendo
|
|
questa flag, incrementeranno il loro contatore di bnodes chiusi. Quando i
|
|
numero di bnode chiusi e' pari a quello dei bnode presenti nel gnode, allora
|
|
verra' mandato il qspn_open.
|
|
Un ultimo accorgimento: quando un bnode riceve un qspn_close mandato da un
|
|
bnode del suo stesso gnode, allora, anche lui si considerera' un
|
|
QSPN_STARTER e forwardera' il pkt senza aggiungere la sua entry, questo
|
|
perche' il gnode deve essere come un unico nodo; inoltre, i bnode chiudono
|
|
ed aprono solo i link esterni, cioe' quelli che li collegano ai bnode dei
|
|
gnode confinanti.
|
|
Tutto questo discorso vale anche per il qspn_open.
|
|
|
|
5.3.2 Gnode fusion
|
|
|
|
Quando un nodo crea un nuovo group_node, ne sceglie uno completamente random,
|
|
usando quindi un IP random. Se due gnode, dapprima isolati, per disgrazia
|
|
hanno lo stesso groupnode id (e quindi lo stesso intervallo di IP), uno
|
|
di loro due deve cambiare; questo significa cambiare l'IP di tutti i nodi
|
|
del gnode.
|
|
|
|
La soluzione e' descritta nell'NTK_RFC 0001:
|
|
http://lab.dyne.org/Ntk_gnodes_contiguity
|
|
|
|
6. Broadcast: There can be only one!
|
|
|
|
Quando vengono mandati dei pkt in broadcast si deve fare in modo che non
|
|
vaghino in eterno in Netsukuku. Ogni nodo mantiene una cache composta
|
|
da un numero di slot pari a MAXGROUPNODE. (La cache e' all'interno della
|
|
mappa interna). Ogni slot corrisponde ad un nodo del g_node. Questo slot
|
|
contiene il pkt_id dell'ultimo pkt broadcast mandato da quel nodo.
|
|
Quindi:
|
|
u_int brdcast; /*Pkt_id of the last brdcast_pkt sent by this node*/
|
|
|
|
Un nodo quando riceve un pkt broadcast lo analizza:
|
|
se vede che il pkt_id e' <= a quello memorizzato nella cache lo rigetta,
|
|
perche' e' sicuramente un pkt vecchio che non deve piu' diffondersi.
|
|
Ovviamente i pkt_id vengono incrementati ogni volta dal src_node.
|
|
Se il pkt supera questo check allora il nodo esegue l'azione che il pkt
|
|
richiede e forwarda il pkt a tutti i suoi r_node, escludendo quelli che gli
|
|
hanno spedito il pkt. Se si vuole che il broadcast sia delimitato entro
|
|
un'area di raggio prefissato, basta settare il ttl al numero di hop di questo
|
|
raggio.
|
|
|
|
6.1 Tracer pkt: one flood, one route
|
|
|
|
Il tracer pkt non e' altro che il modo per trovare la rotta migliore
|
|
con il broadcast. Se il pkt che viene mandato in broadcast avra' la flag
|
|
"tracer_pkt" settata allora ogni nodo che attraversera', aggiungera' in coda
|
|
al pkt il suo IP. Quindi l'intera rotta che il pkt compie viene memorizzata
|
|
nel pacchetto stesso. Il primo pacchetto che arrivera' a destinazione sara'
|
|
sicuramente quello che avra' percorso la rotta migliore, percio' il dst_node
|
|
non fara' altro che settare la rotta memorizzata nel pacchetto ed avviare
|
|
la connessione. Il tracer_pkt introduce anche un altro subdolo vantaggio,
|
|
infatti, il tracer_pkt non solo trasporta la rotta migliore per il src_node,
|
|
ma anche quella per i nodi che fanno parte della rotta perche' se questo pkt
|
|
ha davvero percorso la rotta migliore significa che ha anche percorso _TUTTE_
|
|
le rotte migliori per gli hop intermediari.
|
|
Concludendo, con un tracer pkt possiamo conoscere la rotta migliore per
|
|
raggiungere il src_node (il nodo che ha spedito il pkt), e conseguentemente
|
|
le rotte per raggiungere tutti i nodi intermediari.
|
|
I border_node quando aggiungono la loro entry in un tracer_pkt settano la
|
|
flag b_node ed aggiungono in coda l'id del gnode con cui confinano, ma
|
|
solamente se quel gnode appartiene al livello superiore a quello in cui il
|
|
tracer_pkt si sta propagando.
|
|
Con questo sistema tutti riceveranno tutte le rotte migliori per raggiungere
|
|
tutti i nodi del g_node e tutti i g_node confinanti.
|
|
|
|
Per ottimizzare al massimo lo spazio utilizzato in un tracer_pkt,
|
|
gli IP vengono scritti nel formato IP2MAP, che corrisponde all'id dei nodi
|
|
nel gnode di livello zero. Con questo formato e' richiesto solamente un
|
|
u_char (1 byte invece di 20).
|
|
|
|
7. ANDNA: Abnormal Netsukuku Domain Name Anarchy
|
|
|
|
ANDNA e' il sistema distribuito, non gerarchico e decentralizzato, di
|
|
gestione di hostname in Netsukuku. Sostituisce il DNS.
|
|
Il database dell'ANDNA e' sparso in tutto Netsukuku e nel peggiore dei casi
|
|
ogni nodo dovra' usare circa 355Kb di memoria.
|
|
|
|
Il funzionamento base di ANDNA si articola nel seguente modo:
|
|
per risolvere un hostname basta calcolarsi il suo hash.
|
|
L'hash non e' nient'altro che un numero e questo numero noi lo consideriamo
|
|
come un IP. Il nodo che corrisponde a questo IP lo chiamiamo
|
|
andna_hash_node. In pratica l'hash_node manterra' un piccolo database che
|
|
associa gli hostname, che corrispondono a lui, con l'IP del nodo che ha
|
|
registrato quello stesso hostname.
|
|
|
|
|
|
Nodo X
|
|
IP: 123.123.123.123
|
|
hash( hostname: "andna.acus" ) == 11.22.33.44
|
|
||
|
|
||
|
|
Nodo Y
|
|
IP: 11.22.33.44
|
|
{ [ Database andna del nodo Y ] }
|
|
{hash_11.22.33.44 ---> 123.123.123.123}
|
|
|
|
|
|
Le richieste di revoca non esistono, l'hostname viene cancellato
|
|
automaticamente se non viene aggiornato.
|
|
|
|
7.1 ANDNA Metalloid elements: registration recipe
|
|
|
|
In realta', non e' detto che l'hash_node esista nella rete, perche' puo'
|
|
essere un IP a caso tra i 2^32 IP disponibili, ed ammesso che esista puo'
|
|
sempre morire e uscire dalla rete. Quindi, per garantire la funzionalita'
|
|
effettiva di ANDNA, ed anche un minimo di backup, gli hostname non vengono
|
|
gestiti da singoli nodi, ma da interi gnode. Il gnode che corrisponde
|
|
all'hash e' l'hash_gnode, all'interno ci sara' anche l'hash_node.
|
|
|
|
Poiche' gli hash_gnode possono anche non esistere al momento, viene adottata
|
|
una strategia di approsimazione: viene usato il gnode che piu' si avvicina
|
|
all'hash_gnode, che viene chiamato, rounded_hash_gnode, o in forma breve
|
|
rounded_gnode. Ad esempio, se l'hash gnode e' il 210, il piu' vicino a lui
|
|
sara' il 211 e il 209.
|
|
In generale, quando si considera solamente il gnode che ha accettato una
|
|
registrazione, non si fa differenza tra i due tipi e il gnode si chiama
|
|
sempre hash_gnode.
|
|
|
|
Per consentire un pronto recupero degli hostname quando un intero hash_gnode
|
|
viene tagliato fuori da Netsukuku perdendo tutti i suoi link, o quando tutti
|
|
i nodi che lo compongono muoiono, si usano dei rounded_gnode di backup.
|
|
Un backup_gnode e' sempre un gnode rounded_gnode, ma mette a disposizione
|
|
solo alcuni dei suoi nodi per mantenere l'informazione dell'hostname
|
|
registrato.
|
|
Il numero dei nodi che fanno da backup in un backup_gnode e' proporzionale
|
|
al suo numero totale di nodi (seeds):
|
|
if(seeds > 8) { backup_nodes = (seeds * 32) / MAXGROUPNODE ); }
|
|
else { backup_nodes = seeds; }
|
|
Il numero di backup_gnodes utilizzati per ogni hash_gnode e' pari a
|
|
MAX_ANDNA_BACKUP_GNODES (2).
|
|
|
|
7.1.1 ANDNA hook
|
|
|
|
Quando un nodo si aggancia a Netsukuku diventando parte di un hash_gnode,
|
|
dovra' anche preoccuparsi di agganciarsi ad ANDNA con l'andna_hook.
|
|
Con l'andna_hook si prendera' dai suoi rnode tutte le cache ed i database
|
|
che i nodi di quel gnode posseggono. Ovviamente e' prima necessario che il
|
|
nodo si agganci a Netsukuku.
|
|
|
|
7.1.2 Don't rob my hostname!
|
|
|
|
Un nodo, prima di fare una richiesta ad ANDNA, genera una coppia di chiavi
|
|
RSA, una pubblica (pub_key) ed una privata (priv_key). La dimensione della
|
|
pub_key sara' limitata, per questioni di spazio.
|
|
La richiesta di un hostname fatta ad ANDNA verra' firmata con la chiave
|
|
privata e nella richiesta stessa sara' allegata la chiave pubblica.
|
|
In questo modo il nodo potra' far certificare l'originalita' delle sue future
|
|
richieste.
|
|
|
|
7.1.3 Count again
|
|
|
|
Il numero massimo di hostnames che un nodo puo' registrare e' pari a 256,
|
|
per prevenire la registrazione massiccia di hostnames formati da parole
|
|
comuni da parte di spammer.
|
|
L'unico problema in andna sarebbe quello di contare. Il sistema e'
|
|
totalmente distribuito e, quindi, non si puo' tenere il conto di quanti
|
|
hostname ha registrato un nodo. Esiste pero' una soluzione: introdurre un
|
|
nuovo elemento, gli andna_counter_nodes.
|
|
Un counter_node e' un nodo che ha un IP uguale all'hash della public key
|
|
del nodo che registra gli hostname. Quindi esiste un counter_node per ogni
|
|
register_node. Il counter_node si occupa di memorizzare il numero di
|
|
hostname che ha registrato il register_node che gli corrisponde. Quindi,
|
|
quando un hash_gnode riceve una richiesta di registrazione, prima di tutto
|
|
contatta il relativo counter_node, che gli comunica quanti hostname sono
|
|
gia' stati registrati dal register_node: se il nodo non ha sforato il
|
|
proprio limite, allora il counter node incrementa il contatore e
|
|
l'hash_gnode registra effettivamente l'hostname.
|
|
L'attivazione di un counter_node avviene con la richiesta di controllo da
|
|
parte dell'hash_gnode e viene mantenuta dalle successive richieste.
|
|
Il meccanismo e' identico a quello dell'andna, e pertanto il register_node si
|
|
deve anche preoccupare di mantenere il suo counter_node attivo seguendo le
|
|
stesse regole dell'ibernazione (vedi sotto).
|
|
In pratica, se il counter_node non riceve piu' richieste di controllo da
|
|
parte degli hash_gnode, si disattiva, e tutti gli hostname registrati non
|
|
sono piu' validi (non si possono piu' aggiornare).
|
|
La stessa regola degli hash_gnode viene applicata anche al counter_node: non
|
|
esistera' piu' un singolo counter_node, ma un intero gnode di counter_node,
|
|
chiamato appunto counter_gnode.
|
|
|
|
7.1.4 Registration step by step
|
|
|
|
Il nodo x, che vuole registrare il suo hostname, trova il gnode piu' vicino
|
|
all'hash_gnode (o l'hash_gnode stesso), contatta un nodo a caso (il nodo y)
|
|
di quel gnode e gli manda la richiesta.
|
|
La richiesta include una public key della sua coppia di chiavi RSA che
|
|
rimane valida per tutte le future richieste. Il pkt viene anche firmato con
|
|
la priv_key.
|
|
Il nodo y controlla di essere effettivamente nel gnode piu' vicino
|
|
all'hash_node, in caso contrario rigetta la richiesta. Viene controllata
|
|
anche la validita' della firma apposta nella richiesta.
|
|
Il nodo y contatta il counter_gnode e gli manda l'IP, l'hostname del
|
|
register_node e la copia della richiesta.
|
|
Il counter verifica i dati e controlla che la firma apposta sulla richiesta
|
|
sia valida, e da' l'ok.
|
|
Il nodo y, dopo l'ok, accetta la richiesta, crea l'entry nel suo db
|
|
annotando la data di registrazione, e manda in broadcast, all'interno del
|
|
gnode, la richiesta.
|
|
Gli altri nodi dell'hash_gnode che ricevono la richiesta controllano la sua
|
|
validita' e la memorizzano in un'entry del loro db.
|
|
A questo punto il nodo x deve solo preoccuparsi di mandare la richiesta ai
|
|
backup_gnode. Quando i nodi dei backup_gnode ricevono la richiesta,
|
|
controllano di essere nel range dei gnode piu' vicini, e riapplicano la
|
|
stessa procedura.
|
|
|
|
7.1.5 Endless rest and rebirth
|
|
|
|
Gli hash_gnode mantengono gli hostname in uno stato di ibernazione per circa
|
|
3 giorni dal momento della loro registrazione od aggiornamento.
|
|
Il tempo di decadimento e' volutamente molto alto per mantenere i domini
|
|
stabili. In questo modo, anche se qualcuno attacca un nodo per appropriarsi
|
|
del suo dominio, dovra' aspettare 3 giorni.
|
|
Quando il tempo di ibernazione si e' esaurito allora tutti gli hostname
|
|
scaduti vengono cancellati e vengono sostituiti dagli altri hostname in
|
|
coda.
|
|
Un nodo deve mandare una richiesta di aggiornamento dei suoi hostname ogni
|
|
qualvolta il suo IP cambia e in ogni caso prima dello scadere del tempo di
|
|
ibernazione, in questo modo il suo hostname non sara' cancellato.
|
|
Il pacchetto della richiesta di aggiornamento ha un id che indica il numero
|
|
di aggiornamenti gia' mandati. Il pacchetto viene anche firmato con la
|
|
chiave privata del nodo, per garantire l'autenticita' della richiesta.
|
|
Il pkt viene mandato ad un nodo qualsiasi dell'hash_gnode. Quest'ultimo nodo
|
|
contattera' il counter_node, mandando anche una copia della richiesta, per
|
|
aggiornare le sue entry e per verificare che sia ancora attivo e che l'entry
|
|
relativa all'hostname da aggiornare sia presente. In caso contrario, la
|
|
richiesta di aggiornamento viene rigettata.
|
|
Se tutto va bene, il nodo dell'hash_gnode manda in broadcast la richiesta
|
|
di aggiornamento all'interno del suo gnode.
|
|
Il register_node deve poi mandare la richiesta di aggiornamento anche ai
|
|
backup_gnode.
|
|
Se la richiesta di aggiornamento viene mandata troppo presto (nel primo
|
|
giorno) verra' considerata invalida e sara' ignorata.
|
|
|
|
7.1.6 Hash_gnodes mutation
|
|
|
|
Se un generico rounded_gnode viene scavalcato da un nuovo gnode che e' piu'
|
|
vicino all'hash_gnode deve lasciargli il posto, quindi avviene un
|
|
trasferimento dal vecchio rounded_gnode al nuovo.
|
|
La transizione, pero', avviene in maniera semi-passiva: quando il
|
|
register_node fara' l'aggiornamento dell'hostname, si rivolgera'
|
|
direttamente al nuovo rounded_gnode. L'hostname presente nel vecchio
|
|
rounded_gnode, non essendo piu' aggiornato, decadera'.
|
|
Nel frattempo, quando ancora l'hostname non e' stato aggiornato, tutti i
|
|
nodi che vogliono risolverlo troveranno il nuovo rounded_gnode come gnode
|
|
piu' vicino all'hash_gnode, quindi manderanno le richieste al nuovo gnode.
|
|
Il nuovo rounded_gnode, non avendo ancora il db, chiedera' al vecchio
|
|
hash_gnode di dargli la sua andna_cache relativa all'hostname da risolvere.
|
|
Una volta ricevuta, rispondera' al nodo che ha chiesto la risoluzione
|
|
dell'hname e nel frattempo mandera' in broadcast, all'intero del suo gnode,
|
|
l'andna_cache appena ottenuta. In questo modo la registrazione di
|
|
quell'hostname viene automaticamente trasferita nel nuovo gnode.
|
|
Per evitare che un nodo sottragga l'hostname al leggittimo proprietario
|
|
prima che il trasferimento dell'andna_cache avvenga, tutti i nodi del nuovo
|
|
hash_gnode, per accettare una richiesta di registrazione, controllano se
|
|
quell'hostname esiste gia' in un hash_gnode vecchio: se questa condizione
|
|
e' verificata avvieranno il trasferimento dell'andna_cache ed aggiungeranno
|
|
il nodo che vuole registrare l'hostname nella coda.
|
|
|
|
7.1.7 Yaq: Yet another queue
|
|
|
|
Ogni nodo ha la liberta' di scegliersi un qualsiasi nome host, ed anche se
|
|
l'hostname e' gia' stato preso da un altro nodo, puo' sempre decidere di
|
|
proseguire nella registrazione. Proseguendo, il nodo manda una richiesta al
|
|
gnode che conservera' l'hostname, la richiesta viene accettata, e
|
|
viene aggiunta in coda, dove massimo possono esserci MAX_ANDNA_QUEUE (5)
|
|
hostname. Nell'hash_gnode il nodo viene associato al nome host che ha
|
|
richiesto e viene memorizzata anche la data di richiesta.
|
|
Quando l'hostname, che sta' in cima alla coda, scade, verra' sostituito
|
|
automaticamente dal secondo, e cosi' via.
|
|
|
|
Un nodo che vuole risolvere l'hostame, puo' anche richiedere la lista dei
|
|
nodi presenti nella andna_queue. In questo modo se il primo nodo non e'
|
|
raggiungibile, potra' provare a contattare gli altri.
|
|
|
|
7.8 Hostname resolution
|
|
|
|
Per risolvere un hostname il nodo X deve semplicemente trovare l'hash_gnode
|
|
relativo all'hostname e mandare ad un nodo a caso di quel gnode la richiesta
|
|
di risoluzione.
|
|
|
|
7.8.1 Distributed cache for hostname resolution
|
|
|
|
Per incrementare l'efficienza di risoluzione di hostname, si adotta una
|
|
piccola strategia: un nodo, ogni volta che risolve un hostname, memorizza
|
|
il risultato in una cache. Per ogni risoluzione successiva dello stesso
|
|
hostname, il nodo avra' gia' il risultato nella sua cache.
|
|
Poiche' nei pacchetti di risoluzione degli hostname e' indicato il tempo
|
|
dell'ultima volta in cui sono stati registrati o aggiornati, un'entry nella
|
|
cache scade esattamente quando l'hostname non e' piu' valido in ANDNA e deve
|
|
essere aggiornato.
|
|
La resolved_hnames cache e' accessibile a qualunque nodo.
|
|
Un nodo X, sfruttando questa proprieta', se non ha l'hostname da risolvere
|
|
nella sua cache, puo' decidere di chiedere ad un qualsiasi bnode Y scelto a
|
|
caso del suo stesso gnode di risolvere per lui l'hostname desiderato.
|
|
Il bnode Y, cerchera' nella sua resolved cache l'hostname e in caso di esito
|
|
negativo, risolvera' l'hostname in modo standard facendo mandare la risposta
|
|
al nodo X.
|
|
Questo sistema previene l'overload degli hash_gnode che mantengono hostname
|
|
molto famosi.
|
|
|
|
7.8.2 noituloser emantsoh esreveR
|
|
|
|
Se un nodo vuole conoscere gli hostname associati a un IP, contatta
|
|
direttamente il nodo che ha quell'IP.
|
|
|
|
7.9 dns wrapper
|
|
|
|
Un wrapper di richieste DNS si occupera' di mandare al demone di ANDNA gli
|
|
hostname da risolvere e di restituire gli IP associati ad essi.
|
|
Grazie al wrapper sara' possibile usare ANDNA senza modificare alcun
|
|
programma esistente: bastera' usare come server DNS il proprio computer.
|
|
|
|
8. Heavy Load: flood your ass!
|
|
|
|
Le rotte settate da Netsukuku sono create col supporto nexthop, che permette
|
|
ad un nodo di raggiungere un altro nodo usando piu' rotte simultaneamente
|
|
(multipath), garantendo uno smistamento equo del traffico dei pkts.
|
|
Lo scudo anti-flood e' una conseguenza dell'avere delle rotte
|
|
multipath, ed essere collegati a piu' rnodes. Infatti, anche quando un
|
|
nodo e' bombardato da un flusso di dati continuo e sostenuto, riceve
|
|
quel flusso diviso in differenti rotte e differenti link, e quindi puo'
|
|
sempre comunicare con altri nodi.
|
|
|
|
9. Spoof the Wired: happy kiddies
|
|
|
|
Se un nodo si aggancia a Netsukuku falsificando un IP, non concludera' nulla
|
|
semplicemente perche' nessun nodo sapra' come raggiungerlo, avendo gia' la
|
|
rotta esatta per raggiungere il nodo originale.
|
|
In secondo luogo, gli rnode non permettono un aggancio di un IP che e' gia'
|
|
presente nelle mappe.
|
|
|
|
10. /dev/accessibility
|
|
|
|
Il mezzo ideale per connettere i nodi tra loro e', ovviamente, il wifi, ma
|
|
qualunque tipo di link che connette due nodi serve allo scopo.
|
|
I cellulari sono un ottimo dispositivo, su cui far girare Netsukuku.
|
|
Alcuni dei nuovi modelli usano Linux come kernel.
|
|
|
|
11. Internet compatibility
|
|
|
|
Netsukuku non puo' diffondersi instantaneamente, ed e' impossibile pensare
|
|
di poter migrare da Internet a Netsukuku immediatamente.
|
|
Bisogna, quindi, che durante la sua iniziale diffusione, rimanga compatibile
|
|
con il vecchio Internet e l'unico modo e' quello di limitare temporaneamente
|
|
l'espandibilita' di Netsukuku.
|
|
|
|
Un nodo che usa Netsukuku non puo' uscire su Internet perche', quando
|
|
ntkd viene avviato, come default gw viene settato lo stesso indirizzo
|
|
IP assegnato all'interfaccia di rete, in questo modo le classi di IP non
|
|
esistono piu', e qualsiasi nodo puo' prendersi qualsiasi IP random; inoltre,
|
|
dato che gli IP vengono scelti in maniera random, possono accadere molte
|
|
collisioni con gli attuali IP di Internet.
|
|
|
|
Per mantenere la compabilita' con Internet, Netsukuku deve essere ristretto
|
|
ad una sotto classe di IP, in modo da non interferire con il default gw che
|
|
esce su Internet. Allora, per non interferire in nessun modo con Internet,
|
|
usiamo la classe A degli indirizzi privati per l'IPv4, e la classe
|
|
Site-Local per l'IPv6.
|
|
|
|
Il passaggio dal Netsukuku ristretto al Netsukuku completo e' semplice:
|
|
nel momento stesso in cui un utente decide di abbandonare Internet, riavvia
|
|
NetsukukuD senza l'opzione di restrizione.
|
|
|
|
Ovviamente le altre classi private di IP non vengono toccate, per lasciare la
|
|
possibilita' di creare una LAN con un solo gw/nodo netsukuku.
|
|
|
|
12. Implementation: let's code
|
|
|
|
Il protocollo di Netsukuku non e' low-level, perche' tutto quello che deve
|
|
fare e' settare le rotte nella tabella di routing del kernel, percio' il
|
|
demone NetsukukuD gira in userspace.
|
|
Tutto il sistema viene quindi gestito dal demone che gira su ogni nodo.
|
|
NetsukukuD comunica con gli altri nodi attraverso l'udp e il tcp e setta le
|
|
rotte nella tabella del kernel.
|
|
|
|
Tutto il codice e' scritto in C ed e' commentato, quindi non dovrebbe essere
|
|
difficile seguire il flusso del programma, in ogni caso, prima di leggere un
|
|
.c e' consigliato sbirciare il relativo .h .
|
|
|
|
Netsukuku.c si occupa di lanciare i thread principali.
|
|
Ogni porta su cui ascolta NetsukukuD e' gestita da un demone che viene
|
|
lanciato come un singolo thread. Le porte usate sono le 269-udp, 269-tcp,
|
|
271-udp, 277-udp e 277-tcp.
|
|
Tutti i pacchetti ricevuti dai demoni vengono filtrati da accept.c e da
|
|
request.c che grazie ad una piccola tabella prevengono eventuali attacchi
|
|
di flood (accept.c e' lo stesso codice usato per patchare la vulnerabita'
|
|
user-level-denial-of-service di OpenSSH). In secondo luogo vengono passati
|
|
a pkts.c/pkt_exec().
|
|
Quando tutti i demoni sono attivi, viene lanciato hook.c/netsukuku_hook(),
|
|
il codice che gestisce l'hook alla rete.
|
|
|
|
Hook.c avviera' per la prima volta il primo radar scan con
|
|
radar.c/radar_scan(). Tutti i pacchetti ricevuti relativi al radar sono
|
|
gestiti da radar.c/radard() e da radar.c/radar_recv_reply().
|
|
Dopo l'aggancio alla rete, verra' avviato il radar_scan thread che non fara'
|
|
altro che eseguire in eterno la funzione radar.c/radar_daemon(), la quale
|
|
lancia un radar_scan() ogni MAX_RADAR_WAIT secondi. Quando il
|
|
radar_update_map() si accorge di un cambiamento nei suoi rnode spedisce un
|
|
nuovo qspn_close con qspn.c/qspn_send().
|
|
Tutto il codice relativo al qspn e ai tracer_pkt si trova in qspn.c e in
|
|
tracer.c.
|
|
|
|
Il codice di ANDNA e' diviso in andna_cache.c, che contiene tutte le
|
|
funzioni usate per gestire le relative cache e in andna.c dove risiede il
|
|
codice che si occupa dei pkt del protocollo ANDNA.
|
|
|
|
I socket, sockaddr, le connect, i recv(), i send, etc... sono tutte in
|
|
inet.c, e vengono utilizzate da pkts.c.
|
|
pkts.c si occupa di ricevere le richieste con pkt_exec() e mandarne con
|
|
send_rq(), un front-end utilizzato per impacchettare e spedire la grande
|
|
maggioranza delle richieste.
|
|
ipv6-gmp.c usa la libreria GMP (GNU multiple precision arithmetic library)
|
|
per poter manipolare i 16 byte di un IPv6 come se fossero un unico grande
|
|
numero, questo e' essenziale per alcune formule che agiscono direttamente
|
|
sull'IP per poter ricavare molte informazioni, infatti, in Netsukuku un IP
|
|
e' un numero a tutti gli effetti.
|
|
|
|
Il codice che si interfaccia al kernel per settare le rotte nella route
|
|
table e per configurare un'interfaccia di rete si trova in:
|
|
krnl_route.c, if.c, ll_map.c, krnl_rule.c, libnetlink.c.
|
|
Route.c fa da intermediario tra il codice che gestisce il protocollo di
|
|
netsukuku e tra le funzioni che comunicano con il kernel.
|
|
|
|
Per quanto riguarda le mappe tutto si basa su map.c, il sorgente che
|
|
si occupa di prendersi cura della mappa interna. Tutte le altre mappe si
|
|
appogiano su map.c, e sono:
|
|
bmap.c per la border node map, gmap.c per le mappe esterne.
|
|
|
|
Per compilare il codice di Netsukuku non e' necessario usare autoconf,
|
|
automake e famiglia, ma basta usare il comodo scons (http://www.scons.org).
|
|
|
|
L'ultima versione del codice e' sempre disponibile sul cvs degli
|
|
hinezumilabs:
|
|
|
|
cvs -d :pserver:anoncvs@hinezumilabs.org:/home/cvsroot login
|
|
|
|
oppure date un'occhiata da qui:
|
|
|
|
http://hinezumilabs.org/cgi-bin/viewcvs.cgi/netsukuku/
|
|
|
|
|
|
13. What to do
|
|
|
|
- Testare su larga scala Netsukuku ed ANDNA.
|
|
- Completare i src/TODO.
|
|
- Codare, codare, codare.
|
|
- Varie ed eventuali.
|
|
|
|
Chi vuole imbarcarsi faccia un fischio.
|
|
|
|
|
|
14. The smoked ones who made Netsukuku
|
|
|
|
Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
|
|
|
|
|
|
Special thanks to:
|
|
|
|
Valvoline the non-existent entity for the implementation advices,
|
|
Newmark, the hibernated guy who helped in some ANDNA problems,
|
|
Crash aka "il nipponico bionico" who takes BSD, breathes the 2.4Ghz and
|
|
worship the great Disagio,
|
|
Tomak aka "il magnanimo" who watches everything with his crypto eyes and
|
|
talks in the unrandomish slang,
|
|
Asbesto aka "l'iniziatore" who lives to destroy the old to build the new,
|
|
Nirvana who exists everywhere to bring peace in your data,
|
|
Ram aka "il maledetto poeta" who builds streams of null filled with the
|
|
infinite,
|
|
Quest who taught me to look in the Code,
|
|
Martin, the immortal coder and our beloved father,
|
|
Elibus, the eternal packet present in your lines,
|
|
Pallotron, the biatomic super AI used to build stream of consciousness,
|
|
Entropika, the Great Mother of Enea,
|
|
Uscinziatu, the attentive,
|
|
Shezzan, the holy bard of the two worlds,
|
|
Katolaz,
|
|
Gamel,
|
|
...
|
|
the list goes on...
|
|
V C G R A N Q E M P N E T S U K
|
|
|
|
and finally thanks to all the
|
|
|
|
Freaknet Medialab <www.freaknet.org>
|
|
|
|
whose we are all part, and the poetry
|
|
|
|
Poetry Hacklab <poetry.freaknet.org - poetry.homelinux.org>
|
|
|
|
|
|
--
|
|
This file is part of Netsukuku.
|
|
This text is free documentation; you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 2 of the License, or (at your option) any
|
|
later version. For more information read the COPYING file.
|