Tipps und Code zum einfachen Bestehen der praktischen Computernetzwerkprüfung („Reti di calcolatori“) in Padua. Sie können alles, was in dieser Readme-Datei steht, über man
und die verschiedenen RFCs finden. Ich habe es nur als schnelle Referenz gemacht.
Ein Ethernet-Frame (Datenverbindungsschicht) enthält ein IP-Datagramm (Netzwerkschicht), das eines der folgenden Elemente enthalten kann: { tcp_segment (Transportschicht), icmp_packet } (für den Zweck dieser Prüfung). Eine einfache Möglichkeit, dies zu erkennen, ist:
eth = ( struct eth_frame * ) buffer ;
ip = ( struct ip_datagram * ) eth -> payload ;
tcp = ( struct tcp_segment * ) ip -> payload ;
// or
icmp = ( struct icmp_packet * ) ip -> payload ;
(Hängt von der Architektur ab, aber Sie können davon ausgehen, dass Folgendes für diese Prüfung zutrifft)
unsigned char
: 1 Byteunsigned short
: 2 Bytesunsiged int
: 4 BytesFür die Übertragung im Netzwerk wird Big Endian verwendet. Die meisten Intel-CPUs sind Little-Endian-Prozessoren. Verwenden Sie zum Konvertieren diese beiden Funktionen, die automatisch erkennen, ob eine Konvertierung erforderlich ist:
htonl(x)
oder htons(x)
um x von H ost in Netzwerk -Endianess zu konvertieren, l , wenn Sie eine 4-Byte-Variable konvertieren müssen, s eine 2-Byte-Variable.ntohl(x)
oder ntohs(x)
für das Gegenteil. (Möglicherweise stellen Sie fest, dass die Implementierung von htonx und ntohx gleich ist.) // Frame Ethernet
struct eth_frame {
unsigned char dst [ 6 ]; // mac address
unsigned char src [ 6 ]; // mac address
unsigned short type ; // 0x0800 = ip, 0x0806 = arp
char payload [ 1500 ]; //ARP or IP
};
Dank des type
können wir verstehen, wohin es auf der nächsten Ebene weitergeleitet werden soll (2 Beispiele sind IP oder ARP).
Header-Länge: Überprüfen Sie die zweite Hälfte des ver_ihl
Attributs. Beispiel: Wenn es „5“ ist, beträgt die Headerlänge 4 * 5 = 20 Bytes.
//todo Bild hinzufügen
// Datagramma IP
struct ip_datagram {
unsigned char ver_ihl ; // first 4 bits: version, second 4 bits: (lenght header)/8
unsigned char tos ; //type of service
unsigned short totlen ; // len header + payload
unsigned short id ; // useful in case of fragmentation
unsigned short flags_offs ; //offset/8 related to the original ip package
unsigned char ttl ;
unsigned char protocol ; // TCP = 6, ICMP = 1
unsigned short checksum ; // only header checksum (not of payload). Must be at 0 before the calculation.
unsigned int src ; // ip address
unsigned int dst ; // ip address
unsigned char payload [ 1500 ];
};
Länge des Headers (wie hier definiert): 20
struct tcp_segment {
unsigned short s_port ;
unsigned short d_port ;
unsigned int seq ; // offset in bytes from the start of the tcp segment in the stream (from initial sequance n)
unsigned int ack ; // useful only if ACK flag is 1. Next seq that sender expect
unsigned char d_offs_res ; // first 4 bits: (header len/8)
unsigned char flags ; // check rfc
unsigned short win ; // usually initially a 0 (?)
unsigned short checksum ; // use tcp_pseudo to calculate it. Must be at 0 before the calculation.
unsigned short urgp ;
unsigned char payload [ 1000 ];
};
Um die Prüfsumme eines TCP-Segments zu berechnen, ist es sinnvoll, eine zusätzliche Struktur zu definieren (Überprüfung des entsprechenden RFC). Größe davon, ohne den tcp_segment-Teil
struct tcp_pseudo {
unsigned int ip_src , ip_dst ;
unsigned char zeroes ;
unsigned char proto ; // ip datagram protocol field (tcp = 6, ip = 1)
unsigned short entire_len ; // tcp length (header + data)
unsigned char tcp_segment [ 20 /*to set appropriatly */ ]; // entire tcp packet pointer
};
So berechnen Sie die Größe des gesamten TCP-Segments (oder des ICMP) oder allgemeiner der IP-Nutzlast:
unsigned short ip_total_len = ntohs ( ip -> totlen );
unsigned short ip_header_dim = ( ip -> ver_ihl & 0x0F ) * 4 ;
int ip_payload_len = ip_total_len - ip_header_dim ;
Wir können diese Funktion sowohl für das IP-Datagramm als auch für das TCP-Segment verwenden, müssen aber auf den len
Parameter achten.
unsigned short checksum ( unsigned char * buffer , int len ){
int i ;
unsigned short * p ;
unsigned int tot = 0 ;
p = ( unsigned short * ) buffer ;
for ( i = 0 ; i < len / 2 ; i ++ ){
tot = tot + htons ( p [ i ]);
if ( tot & 0x10000 ) tot = ( tot & 0xFFFF ) + 1 ;
}
return ( unsigned short ) 0xFFFF - tot ;
}
Die 2 Fälle sind:
ip->checksum=htons(checksum((unsigned char*) ip, 20));
` int TCP_TOTAL_LEN = 20 ;
struct tcp_pseudo pseudo ; // size of this: 12
memcpy ( pseudo . tcp_segment , tcp , TCP_TOTAL_LEN );
pseudo . zeroes = 0 ;
pseudo . ip_src = ip -> src ;
pseudo . ip_dst = ip -> dst ;
pseudo . proto = 6 ;
pseudo . entire_len = htons ( TCP_TOTAL_LEN ); // may vary
tcp -> checksum = htons ( checksum (( unsigned char * ) & pseudo , TCP_TOTAL_LEN + 12 ));
#include <arpa/inet.h>
void print_ip ( unsigned int ip ){
struct in_addr ip_addr ;
ip_addr . s_addr = ip ;
printf ( "%sn" , inet_ntoa ( ip_addr ));
}
Ich rate VIM. Und bitte rücken Sie Ihren Code ein.
:wq
zum Speichern und Beenden.esc
wenn Sie nicht verstehen, was passiert/query
, um nach „query“ zu suchen, n
und N
um das vorherige/nächste Ergebnis zu durchsuchen " auto reformat when you pres F7
map <F7> mzgg=G`z
" F8 to save and compile creating np executable
map <F8> :w <CR> :!gcc % -o np -g <CR>
" F9 to execute
map <F9> :!./np <CR>
" make your code look nicer
set tabstop=3
set shiftwidth=3
set softtabstop=0 expandtab
set incsearch
set cindent
" Ctrl+shift+up/down to swap the line up or doen
nnoremap <C-S-Up> <Up>"add"ap<Up>
nnoremap <C-S-Down> "add"ap
" ctrl+h to hilight the last search
nnoremap <C-h> :set hlsearch!<CR>
set number
set cursorline
set mouse=a
set foldmethod=indent
set foldlevelstart=99
let mapleader="<space>"
nnoremap <leader>b :make <CR> :cw <CR>
Erstellen Sie zunächst ein makefile
im Verzeichnis mit den zu kompilierenden Dateien, etwa so:
np : ws18.c
gcc -o np ws18.c
Achten Sie darauf, vor „gcc“ einen Tabulator und keine Leerzeichen einzufügen (wenn Sie expandtab in vim aktiviert haben, verwenden Sie ctrl=v tab
). Hier ist np
das, was Sie generieren möchten (die ausführbare Datei) und ws18.c
die zu kompilierende Datei. In der Zeile darunter befindet sich der Befehl, den Sie jedes Mal aufrufen müssen, wenn Sie :make
in vim schreiben. Drücken Sie dann mit der oben bereitgestellten .vimrc
space
(lassen Sie sie los) und b
( build ). Der Befehl wird ausgeführt und Sie sehen am Ende Ihres Codes die Liste der Fehler. Sie können schnell in die richtige Zeile springen, indem Sie bei jedem Eintrag die Eingabetaste drücken. Um zwischen der oberen und unteren Teilung zu wechseln, drücken Sie CTRL+W
W
. Um die Unteransicht zu schließen (Quickfix) :q
, oder :cw
.
Die vollständige Prüfungserklärung finden Sie auf der Website am Anfang dieser Readme-Datei. Der vollständige Code befindet sich in den Ordnern.
Implementieren Sie den TCP-Drei-Wege-Handshake (ACK+SYN).
Tipps : Sie können mit Wireshark überprüfen, ob Ihre TCP-Prüfsumme korrekt ist oder nicht.
Implementieren Sie eine Echo-Antwort nur für ICMP-Anfragen einer bestimmten Größe
Tipps : Sie können die Größe einer ICMP-Nachricht folgendermaßen berechnen:
unsigned short dimension = ntohs ( ip -> totlen );
unsigned short header_dim = ( ip -> ver_ihl & 0x0F ) * 4 ;
int icmp_dimension = dimension - header_dim ;
Implementieren Sie einen HTTP-Server, der:
Tipps : Der Header Retry-After
wird von den meisten Webbrowsern ignoriert, sodass die Weiterleitung nicht nach 10 Sekunden, sondern sofort erfolgt. In der Lösung gibt es ein Array, das den Verbindungsstatus für jede IP speichert.
Implementieren Sie eine ICMP-Anweisung „Ziel nicht erreichbar“, die besagt, dass der Port nicht verfügbar ist
Tipps : Sie müssen das Paket als Antwort auf eine TCP-Verbindung senden. icmp->type = 3
, icmp->code=3
. Und denken Sie daran, den Inhalt der ursprünglichen ICMP-Nutzlast in die Nutzlast zu kopieren.
Fangen Sie die erste empfangene Verbindung ab und geben Sie deren Reihenfolge und Bestätigungsnummern aus. Dann rekonstruieren Sie die beiden Streams in zwei verschiedenen Puffern und drucken Sie ihren Inhalt aus.
Tipps : Um das Ende der Verbindung abzufangen, prüfen Sie einfach, ob ein Paket das FIN-Bit auf 1 enthält (nachdem alle Pakete gefiltert wurden und nur diejenigen beibehalten wurden, die zur ersten Verbindung gehören). Verwenden Sie das TCP-Sequenzfeld, um den Inhalt am rechten Offset in die beiden Puffer zu kopieren. CODE NICHT DUPLIZIEREN.
Ändern Sie den Proxy, um die Anfrage nur von einem Pool von IP-Adressen zuzulassen und nur die Übertragung von Dateien mit Text oder HTML zuzulassen.
Tipps : Es ist besser, die Antwort vom Server zunächst in einem Puffer zu empfangen und diesen Inhalt dann wie immer in einen anderen Puffer zu kopieren, um Header zu extrahieren. Dies liegt daran, dass die Header-Extraktion den Puffer verändert. Wenn die Bedingung des Inhaltstyps erfüllt ist, leiten Sie einfach den Inhalt des Anfangspuffers weiter.
Senden Sie eine HTTP-Antwort mit einem Chunk-Body.
Tipps : Fügen Sie Content-Type: text/plainrnTransfer-Encoding: chunkedrn
zu HTTP-Headern hinzu. Um dann jeden zu sendenden Block zu erstellen, können Sie Folgendes verwenden:
int build_chunk ( char * s , int len ){
sprintf ( chunk_buffer , "%xrn" , len ); // size in hex
// debug printf("%d in hex: %s",len,chunk_buffer);
int from = strlen ( chunk_buffer );
int i = 0 ;
for (; i < len ; i ++ )
chunk_buffer [ from + i ] = s [ i ];
chunk_buffer [ from + ( i ++ )] = 'r' ;
chunk_buffer [ from + ( i ++ )] = 'n' ;
chunk_buffer [ i + from ] = 0 ;
return i + from ;
}
Implementieren Sie den Last-Modified
Header von HTTP/1.0
Tipps : Einige nützliche Zeitumrechnungsfunktionen im Abschnitt „Verschiedenes“. Es hätte auch ohne diese Umbauten möglich sein können. Das HTTP-Datumsformat ist %a, %d %b %Y %H:%M:%S %Z
1: Inhaltslänge (wurde bereits implementiert) 2: Trace (??)
Ändern Sie icmp echo, um die Anfrage in zwei IP-Datagramme aufzuteilen, eines mit einer Nutzlastgröße von 16 Byte und das andere mit der angeforderten Nutzlastgröße.
Während des Kurses werden einige Hausaufgaben (nicht verpflichtend) vergeben. Auch wenn es sich nicht um Prüfungen handelt, haben sie mehr oder weniger den gleichen Schwierigkeitsgrad.
Implementieren Sie ein Traceroute-Programm, das jeden Knoten verfolgt, den die Pakete besuchen, bevor sie das Ziel erreichen. Hinweis: Wenn die Lebensdauer 0 wird, verwirft ein Knoten das Paket und sendet eine „Time Exceeded Message“ an die Quell-IP-Adresse des Pakets (siehe RFC793).
Verwenden Sie den HTTP-Header WWW-Authenticate
um die Zugangsdaten für den Client anzufordern.
Implementieren Sie einen Client, der Chunked Content akzeptiert.
Das HTTP-Datumsformat ist %a, %d %b %Y %H:%M:%S %Z
char date_buf [ 1000 ];
char * getNowHttpDate (){
time_t now = time ( 0 );
struct tm tm = * gmtime ( & now );
strftime ( date_buf , sizeof date_buf , "%a, %d %b %Y %H:%M:%S %Z" , & tm );
printf ( "Time is: [%s]n" , date_buf );
return date_buf ;
}
// parse time and convert it to millisecond from epoch
time_t httpTimeToEpoch ( char * time ){
struct tm tm ;
char buf [ 255 ];
memset ( & tm , 0 , sizeof ( struct tm ));
strptime ( time , "%a, %d %b %Y %H:%M:%S %Z" , & tm );
return mktime ( & tm );
}
// returns 1 if d1 < d2
unsigned char compareHttpDates ( char * d1 , char * d2 ){
return httpTimeToEpoch ( d1 ) < httpTimeToEpoch ( d2 );
}
unsigned char expired ( char * uri , char * last_modified ){
char * complete_name = uriToCachedFile ( uri );
FILE * fp = fopen ( complete_name , "r" );
if ( fp == NULL ) return 1 ;
//read the first line
char * line = 0 ; size_t len = 0 ;
getline ( & line , & len , fp );
if ( compareHttpDates ( last_modified , line )) return 0 ;
return 1 ;
//todo read First line and compare
}
rewind(FILE*)
setzt den Cursor an den Anfang
FILE * fin ;
if (( fin = fopen ( uri + 1 , "rt" )) == NULL ) { // the t is useless
printf ( "File %s non aperton" , uri + 1 );
sprintf ( response , "HTTP/1.1 404 File not foundrnrn<html>File non trovato</html>" );
t = write ( s2 , response , strlen ( response ));
if ( t == -1 ) {
perror ( "write fallita" );
return -1 ;
}
} else {
content_length = 0 ;
while (( c = fgetc ( fin )) != EOF ) content_length ++ ; // get file lenght
sprintf ( response , "HTTP/1.1 200 OKrnConnection: keep-alivernContent-Length: %drnrn" , content_length );
printf ( "Response: %sn" , response );
//send header
t = write ( s2 , response , strlen ( response ));
//rewind the file
rewind ( fin );
//re-read the file, char per char
while (( c = fgetc ( fin )) != EOF ) {
//printf("%c", c);
//sending the file, char per char
if ( write ( s2 , ( unsigned char * ) & c , 1 ) != 1 ) {
perror ( "Write fallita" );
}
}
fclose ( fin );
}
char car ;
while ( read ( s3 , & car , 1 )) {
write ( s2 , & car , 1 );
// printf("%c",car);
}
unsigned char targetip [ 4 ] = { 147 , 162 , 2 , 100 };
unsigned int netmask = 0x00FFFFFF ;
if (( * (( unsigned int * ) targetip ) & netmask ) == ( * (( unsigned int * ) myip ) & netmask ))
nexthop = targetip ;
else
nexthop = gateway ;
vom Hostnamen (wie www.google.it) zur IP-Adresse
/**
struct hostent {
char *h_name; // official name of host
char **h_aliases; // alias list
int h_addrtype; // host address type
int h_length; // length of address
char **h_addr_list; // list of addresses
}
#define h_addr h_addr_list[0] // for backward compatibility
*/
struct hostent * he ;
he = gethostbyname ( hostname );
printf ( "Indirizzo di %s : %d.%d.%d.%dn" , hostname ,
( unsigned char )( he -> h_addr [ 0 ]), ( unsigned char )( he -> h_addr [ 1 ]),
( unsigned char )( he -> h_addr [ 2 ]), ( unsigned char )( he -> h_addr [ 3 ]));
Zum Zuhören:
int s = socket ( AF_INET , // domain: ipv4
/*
SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams. An out-of-band data
transmission mechanism may be supported.
SOCK_DGRAM Supports datagrams (connectionless, unreliable messages of a fixed maximum length).
SOCK_RAW Provides raw network protocol access.
*/
SOCK_STREAM , // type: stream
0 ); // protocol (0=ip), check /etc/protocols
if ( s == -1 ) {
perror ( "Socket Fallita" );
return 1 ;
}
// https://stackoverflow.com/questions/3229860/what-is-the-meaning-of-so-reuseaddr-setsockopt-option-linux
// SO_REUSEADDR allows your server to bind to an address which is in a TIME_WAIT state.
int yes = 1 ;
if ( setsockopt ( s , SOL_SOCKET , SO_REUSEADDR , & yes , sizeof ( int )) == -1 ) {
perror ( "setsockopt" );
return 1 ;
}
struct sockaddr_in indirizzo ;
indirizzo . sin_family = AF_INET ;
indirizzo . sin_port = htons ( 8987 );
indirizzo . sin_addr . s_addr = 0 ;
t = bind ( s , ( struct sockaddr * ) & indirizzo , sizeof ( struct sockaddr_in ));
if ( t == -1 ) {
perror ( "Bind fallita" );
return 1 ;
}
t = listen ( s ,
// backlog defines the maximum length for the queue of pending connections.
10 );
if ( t == -1 ) {
perror ( "Listen Fallita" );
return 1 ;
}
int lunghezza = sizeof ( struct sockaddr_in );
// the remote address will be placed in indirizzo_remoto
s2 = accept ( s , ( struct sockaddr * ) & indirizzo_remoto , & lunghezza );
if ( s2 == -1 ) {
perror ( "Accept Fallita" );
return 1 ;
}
// now we can read in this way:
char buffer [ 10000 ];
int i ;
for ( i = 0 ; ( t = read ( s2 , buffer + i , 1 )) > 0 ; i ++ ); // ps. it's not a good way
// if the previous read returned -1
if ( t == -1 ) {
perror ( "Read Fallita" );
return 1 ;
}
Denken Sie am Ende daran, alle Sockets mit close(s)
zu schließen (wobei sich s in dem Socket befindet, den Sie schließen möchten).
int s = socket (
//AF_PACKET Low level packet interface packet(7)
AF_PACKET ,
//SOCK_RAW Provides raw network protocol access.
SOCK_RAW ,
// When protocol is set to htons(ETH_P_ALL), then all protocols are received.
htons ( ETH_P_ALL ));
unsigned char buffer [ 1500 ];
bzero ( & sll , sizeof ( struct sockaddr_ll ));
struct sockaddr_ll sll ;
sll . sll_ifindex = if_nametoindex ( "eth0" );
len = sizeof ( sll );
int t = sendto ( s , //socket
buffer , //things to send
14 + 20 + 28 , // len datagram
0 , //flags
( struct sockaddr * ) & sll , // destination addr
len // dest addr len
);
// to receive
t = recvfrom ( s , buffer , 1500 , 0 , ( struct sockaddr * ) & sll , & len );
if ( t == -1 ) {
perror ( "recvfrom fallita" );
return 1 ;
}
void stampa_eth ( struct eth_frame * e ){
printf ( "nn ***** PACCHETTO Ethernet *****n" );
printf ( "Mac destinazione: %x:%x:%x:%x:%x:%xn" , e -> dst [ 0 ], e -> dst [ 1 ], e -> dst [ 2 ], e -> dst [ 3 ], e -> dst [ 4 ], e -> dst [ 5 ] );
printf ( "Mac sorgente: %x:%x:%x:%x:%x:%xn" , e -> src [ 0 ], e -> src [ 1 ], e -> src [ 2 ], e -> src [ 3 ], e -> src [ 4 ], e -> src [ 5 ] );
printf ( "EtherType: 0x%xn" , htons ( e -> type ) );
}
void stampa_ip ( struct ip_datagram * i ){
unsigned int ihl = ( i -> ver_ihl & 0x0F ) * 4 ; // Lunghezza header IP
unsigned int totlen = htons ( i -> totlen ); // Lunghezza totale pacchetto
unsigned int opt_len = ihl - 20 ; // Lunghezza campo opzioni
printf ( "nn ***** PACCHETTO IP *****n" );
printf ( "Version: %dn" , i -> ver_ihl & 0xF0 );
printf ( "IHL (bytes 60max): %dn" , ihl );
printf ( "TOS: %dn" , i -> tos );
printf ( "Lunghezza totale: %dn" , totlen );
printf ( "ID: %xn" , htons ( i -> id ) );
unsigned char flags = ( unsigned char )( htons ( i -> flag_offs ) >> 13 );
printf ( "Flags: %d | %d | %d n" , flags & 4 , flags & 2 , flags & 1 );
printf ( "Fragment Offset: %dn" , htons ( i -> flag_offs ) & 0x1FFF );
printf ( "TTL: %dn" , i -> ttl );
printf ( "Protocol: %dn" , i -> proto );
printf ( "Checksum: %xn" , htons ( i -> checksum ) );
unsigned char * saddr = ( unsigned char * ) & i -> saddr ;
unsigned char * daddr = ( unsigned char * ) & i -> daddr ;
printf ( "IP Source: %d.%d.%d.%dn" , saddr [ 0 ], saddr [ 1 ], saddr [ 2 ], saddr [ 3 ] );
printf ( "IP Destination: %d.%d.%d.%dn" , daddr [ 0 ], daddr [ 1 ], daddr [ 2 ], daddr [ 3 ] );
if ( ihl > 20 ){
// Stampa opzioni
printf ( "Options: " );
for ( int j = 0 ; j < opt_len ; j ++ ){
printf ( "%.3d(%.2x) " , i -> payload [ j ], i -> payload [ j ]);
}
printf ( "n" );
}
}
void stampa_arp ( struct arp_packet * a ){
printf ( "nn ***** PACCHETTO ARP *****n" );
printf ( "Hardware type: %dn" , htons ( a -> htype ) );
printf ( "Protocol type: %xn" , htons ( a -> ptype ) );
printf ( "Hardware Addr len: %dn" , a -> hlen );
printf ( "Protocol Addr len: %dn" , a -> plen );
printf ( "Operation: %dn" , htons ( a -> op ) );
printf ( "HW Addr sorgente: %x:%x:%x:%x:%x:%xn" , a -> hsrc [ 0 ], a -> hsrc [ 1 ], a -> hsrc [ 2 ], a -> hsrc [ 3 ], a -> hsrc [ 4 ], a -> hsrc [ 5 ] );
printf ( "IP Source: %d.%d.%d.%dn" , a -> psrc [ 0 ], a -> psrc [ 1 ], a -> psrc [ 2 ], a -> psrc [ 3 ] );
printf ( "HW Addr Destinazione: %x:%x:%x:%x:%x:%xn" , a -> hdst [ 0 ], a -> hdst [ 1 ], a -> hdst [ 2 ], a -> hdst [ 3 ], a -> hdst [ 4 ], a -> hdst [ 5 ] );
printf ( "IP Dest: %d.%d.%d.%dn" , a -> pdst [ 0 ], a -> pdst [ 1 ], a -> pdst [ 2 ], a -> pdst [ 3 ] );
}
void stampa_icmp ( struct icmp_packet * i ){
printf ( "nn ***** PACCHETTO ICMP *****n" );
printf ( "Type: %dn" , i -> type );
printf ( "Code: %dn" , i -> code );
printf ( "Code: 0x%xn" , htons ( i -> checksum ) );
printf ( "ID: %dn" , htons ( i -> id ) );
printf ( "Sequence: %dn" , htons ( i -> seq ) );
}
void stampa_tcp ( struct tcp_segment * t ){
printf ( "nn ***** PACCHETTO TCP *****n" );
printf ( "Source Port: %dn" , htons ( t -> s_port ) );
printf ( "Source Port: %dn" , htons ( t -> d_port ) );
printf ( "Sequence N: %dn" , ntohl ( t -> seq ) );
printf ( "ACK: %dn" , ntohl ( t -> ack ) );
printf ( "Data offset (bytes): %dn" , ( t -> d_offs_res >> 4 ) * 4 );
printf ( "Flags: " );
printf ( "CWR=%d | " , ( t -> flags & 0x80 ) >> 7 );
printf ( "ECE=%d | " , ( t -> flags & 0x40 ) >> 6 );
printf ( "URG=%d | " , ( t -> flags & 0x20 ) >> 5 );
printf ( "ACK=%d | " , ( t -> flags & 0x10 ) >> 4 );
printf ( "PSH=%d | " , ( t -> flags & 0x08 ) >> 3 );
printf ( "RST=%d | " , ( t -> flags & 0x04 ) >> 2 );
printf ( "SYN=%d | " , ( t -> flags & 0x02 ) >> 1 );
printf ( "FIN=%dn" , ( t -> flags & 0x01 ) );
printf ( "Windows size: %dn" , htons ( t -> win ) );
printf ( "Checksum: 0x%xn" , htons ( t -> checksum ) );
printf ( "Urgent pointer: %dn" , htons ( t -> urgp ) );
}
Nicht wirklich nützlich, aber...
// es. tcp.c
printf ( "%.4d. // delta_sec (unsigned int)
% .6d // delta_usec
% .5d -> % .5d // ports (unsigned short)
% .2 x // tcp flags (unsigned char) in hex: es: "12"
% .10u // seq (unsigned int)
% .10u // ack
% .5u //tcp win
% 4.2f n ", delta_sec , delta_usec , htons ( tcp -> s_port ), htons ( tcp -> d_port ), tcp -> flags , htonl ( tcp -> seq ) - seqzero , htonl ( tcp -> ack ) - ackzero , htons ( tcp -> win ), ( htonl ( tcp -> ack ) - ackzero ) / ( double )( delta_sec * 1000000 + delta_usec ));
/etc/services
: Um alle auf Anwendungsebene verfügbaren TCP-Ports zu kennen./etc/protocols
nslookup <URL>
: findet die IP-Adresse der angegebenen URL ( Beispiel : www.google.com)netstat -rn
zeigt die Routing-Tabelletraceroute
leitet ein IP-Paket weiter, auf welchem Weg es sich bewegt, indem es die IP jedes Gateways ausgibt, das beschließt, das gefälschte Paket mit niedriger TTL-Zählung (Time to Live, dekrementiert bei jedem Hop) zu verwerfen.