Next Previous Contents

6. Die Testsuite

Auf dem CVS Server gibt es eine Test-Suite: Je groesser der Bereich ist, den diese Testsuite abdeckt, desto groesser wird Deine Zufriedenheit sein, zu sehen, dass Aenderungen am Code nichts komplett zerbrochen haben. Triviale Tests sind mindestens so wichtig, wie trickreiche Tests: Es sind die trivialen Tests, die die komplexen vereinfachen (da Du weisst, dass die Grundlagen gut funktionieren, bevor die trickreichen Tests ausgefuehrt werden).

Die Tests sind einfach: Sie sind nur Shell-Scripte im /testsuite Verzeichnis, die erfolgreich sein sollen. Die Scripte werden in alphabetischer Reihen- folge ausgefuehrt, '01test' kommt also vor '02test'. Zur Zeit gibt es fuenf Testverzeichnisse:

00netfilter/

Generelle Tests zum Netfilter-Rahmenwerk.

01iptables/

Tests zu iptables.

02conntrack/

Tests zu Connection Tracking.

03NAT/

Tests zu NAT.

04ipchains-compat/

Tests zur Kompatibilitaet von ipchains/ipfwadm.

Im testsuite/ Verzeichnis gibt es ein Script mit dem Namen 'test.sh'. Es konfiguriert zwei Dummy-Schnittstellen (tap0 und tap1), aktiviert Forwarding und beseitigt alle Netfilter-Module. Dann geht es durch die oberen Verzeichnisse und fuehrt dort alle test.sh Scripte aus, bis eins davon nicht funktioniert. Dieses Script hat zwei optionale Argumente: `-v' druckt jeden gerade ausgefuehrten Test aus. Ausserdem kann ein optionaler Testname angegeben werden: Ist dieser gegeben, werden alle anderen Tests ausgelassen, bis dieser eine gefunden wird.

6.1 Einen Test schreiben

Erstelle in dem betreffenden Verzeichnis eine neue Datei: Versuche, Deinen Test so zu numerieren, dass er zur richtigen Zeit ausgefuehrt wird. Um zum Beispiel ICMP Reply Tracking zu testen (02conntrack/02reply.sh), muessen wir zuerst sicher sein, dass ausgehende ICMP Pakete sauber getrackt werden (02conntrack/01simple.sh).

Gewoehnlich ist es besser, mehrere kleine Dateien zu erstellen, von denen jede einen Bereich abdeckt, da das hilft, Probleme fuer die Leute, die auf der Testsuite arbeiten, sofort zu isolieren.

Wenn etwas in dem Test schief laeuft, gib ein 'exit 1', das verursacht einen Fehler; wenn dies etwas ist, das Du schon erwartet hast, solltest Du eine eindeutige Meldung hinterlassen. Dein Test sollte mit 'exit 0' enden, wenn alles gut laeuft. Du solltest den Erfolg eines jeden einzelnen Befehls ueberpruefen, indem an den Anfang des Scripts die Option `set -e' setzt oder indem Du ein '|| exit 1' an jeden Befehl anhaengst.

Die Hilfsfunktionen 'load_module' und 'remove_module' koennen verwendet werden, um Module zu laden: Du solltest Dich nicht auf das automatische Laden von Modulen in der Testsuite verlassen, es sei denn, das ist es spezifisch, was Du testen willst.

6.2 Variablen und Umgebung

Du hast zwei Schnittstellen zum Spielen: tap0 und tap1. Ihre Schnittstellen- adressen stehen jeweils in $TAP0 und $TAP1. Beide haben die Netzmaske 255.255.255.0; ihre Netzwerke stehen jeweils in $TAP0NET und $TAP1NET.

Es gibt eine leere Temporary Datei in $TMPFILE. Sie wird am Ende Deines Tests geloescht.

Dein Script wird aus dem /testsuite Verzeichnis heraus gestartet werden, woimmer das auch sein mag. Also solltest Du Tools (wie iptables) mit Pfadnamen wie '../userspace' verwenden.

Dein Script kann mehr Informationen ausdrucken, wenn $VERBOSE gesetzt ist (was bedeutet, dass der User ein '-v' auf der Kommandozeile angegeben hat.

6.3 Nuetzliche Tools

Es gibt verschiedene nuetzliche Testsuite-Tools im Unterverzeichnis `Tools': Jedes davon endet mit einem Nicht-Null Exit Status, wenn es ein Problem gibt.

gen_ip

Du kannst IP-Pakete mit 'gen_ip' generieren, was IP-Pakete an Standard- Input liefert. Du kannst IP-Pakete an tap0 und tap1 liefern, indem Du Standard-Output an /dev/tap0 oder /dev/tap1 sendest (Falls diese nicht existieren sollten, werden sie beim ersten Verwenden der Testsuite erstellt).

gen_ip ist ein einfaches Programm, das zur Zeit sehr penibel mit der Reihenfolge seiner Argumente ist. Zuerst gibt es die allgemeinen optionalen Argumente:

FRAG=offset,length

Erstelle ein Paket, zerlege es dann in Fragmente von folgendem Offset und folgender Laenge.

MF

Setz das 'More Fragments' Bit in dem Paket.

MAC=xx:xx:xx:xx:xx:xx

Setz die Quell-MAC-Adresse des Pakets.

TOS=tos

Setz das TOS-Feld im Paket (0 - 255).

Als naechstes kommen die erforderlichen Argumente:

source ip

Quell-IP-Adresse des Pakets.

dest ip

Ziel-IP-Adresse des Pakets.

length

Gesamtlaenge des Pakets, einschliesslich Header.

protocol

Protokollnummer des Pakets, 17 ist zum Beispiel UDP.

Die Argumente haengen dann vom Protokoll ab: fuer UDP (17) gibt es Quell- und Ziel-Portnummer. Fuer ICMP (1) gibt es Typ und Code der ICMP Meldung: ist der Typ 0 oder 8 (ping-Antwort oder ping), werden zwei zusaetzliche Argumente (das ID und das Sequenzfeld) benoetigt. Fuer TCP werden Quell- und Zielport, sowie Flags ("SYN", "SYN/ACK", "ACK", "RST" or "FIN") benoetigt. Hier gibt es drei optionale Argumente: "OPT=", gefolgt von einer durch Kommata getrennten Liste von Optionen, "SYN=" gefolgt von einer Sequenznummer, und "ACK=" gefolgt von einer Sequenznummer. Schliesslich sagt das optionale Argument "DATA", dass der Payload des TCP-Pakets mit den Inhalt von Standard-Input gefuellt werden soll.

rcv_ip

Du kannst Dir IP-Pakete mit rcv_ip ansehen, was eine Kommandozeile ausgibt, die so nah wie moeglich an die Originalwerte herankommt, die an gen_ip uebergeben wurden (mit Ausnahme von Fragmenten).

Das ist extrem nuetzlich fuer das Analysieren von Paketen. Es erfordert zwei Argumente:

wait time

Die maximale Zeit in Sekunden, um auf ein Paket von Standard Input zu warten.

iterations

Die Anzahl der zu empfangenden Pakete.

Es gibt ein optionales Argument "DATA", was den Payload des Pakets nach dem Paketheader auf Standard-Output ausdruckt.

Der Standardweg, rcv_ip in einem Shellscript zu verwenden, ist wie folgt:

# Jobkontrolle aufsetzen, damit mir $ in Shellscripten verwenden koennen.
set -m

# Zwei Sekunden auf ein Paket von tap0 warten.
../tools/rcv_ip 2 1 < /dev/tap0 > $TMPFILE &

# Sichergehen, dass rvp_ip laeuft.
sleep 1

# Ein ping-Paket senden
../tools/gen_ip $TAP1NET.2 $TAP0NET.2 100 1 8 0 55 57 > /dev/tap1 || exit 1

# Auf rvp_ip warten
if wait %../tools/rcv_ip; then :
else
    echo rcv_ip failed:
    cat $TMPFILE
    exit 1
fi

gen_err

Dieses Programm nimmt ein Paket (wie zum Beispiel von ip_gen generiert) und wandelt es in einen ICMP Fehler um.

Es hat drei Argumente: Die Quell-IP-Adresse, einen Typ und einen Code. Die Ziel-IP-Adresse wird auf die Quell-IP-Adresse des von Standard- Input uebergebenen Pakets gesetzt.

local_ip

Dies nimmt ein Paket von Standard-Input und injiziert es von einem einfachen Socket ins System. Dies gibt ihm den Anschein eines lokal-generierten Pakets (anders, als ein Paket an eines der Ethertap Devices zu uebergeben, was wie ein Paket aussehen wuerde, das woanders generiert wurde).

6.4 Einige Ratschlaege

All diese Tools nehmen an, dass sie alles mit einem Lesen und Schreiben tun koennen: Dies ist wahr fuer die Ethertap Devices, koennte aber nicht wahr sein, wenn Du etwas Trickreiches mit Pipes machst.

dd can verwendet werden, um Pakete auszuschneiden: dd hat eine obs (output block size) Option, die verwendet werden kann, um Pakete mit einem einzigen Schreiben auszugeben.

Teste zuerst auf Erfolg: z.B. ein Test darauf, ob Pakete erfolgreich geblockt werden. Teste zuerst, ob Pakete normal durchgehen, teste anschliessend, ob Pakete geblockt werden. Andernfalls koennte ein Fehler, der nichts damit zu tun hat, die Pakete aufhalten...

Versuche, exakte Tests zu schreiben, keine 'Schreib zufaelliges Zeug und warte ab, was passiert' Tests. Wenn ein exakter Tests nicht funktioniert, ist es sehr nuetzlich, das zu wissen. Wenn ein zufaelliger Test nicht funktioniert, hilft das nicht viel.

Wenn ein Tests ohne ein Meldung nicht gelingt, kannst Du ein '-x' (ich meine '#! /bin/sh -x') in die erste Zeile des Scripts setzen, um zu sehen, welches Kommando gerade ausgefuehrt wird.

Wenn ein Test mal gelingt, mal nicht, ueberpruefe zufaelligen Netzwerkverkehr, der dazwischenkommen koennte (versuche, alle externen Schnittstellen zu deaktivieren). Da ich an das gleiche Netzwerk wie Andrew Trigell angeschlossen bin, werde ich zum Beispiel staendig von Windows Broadcasts geplagt.


Next Previous Contents