Astuces et code pour réussir facilement l'examen pratique des réseaux informatiques ("Reti di calcolatori") à Padoue. Vous pouvez trouver tout ce qui se trouve dans ce fichier readme via man
et les différents RFC. Je l'ai fait juste pour une référence rapide.
Une trame Ethernet (couche liaison de données) contient un datagramme IP (couche réseau) qui peut contenir l'un des éléments suivants { tcp_segment (couche transport), icmp_packet } (pour les besoins de cet examen). Un moyen simple de s’en rendre compte est :
eth = ( struct eth_frame * ) buffer ;
ip = ( struct ip_datagram * ) eth -> payload ;
tcp = ( struct tcp_segment * ) ip -> payload ;
// or
icmp = ( struct icmp_packet * ) ip -> payload ;
(cela dépend de l'architecture, mais vous pouvez supposer que ce qui suit est vrai pour cet examen)
unsigned char
: 1 octetunsigned short
: 2 octetsunsiged int
: 4 octetsPour transférer sur le réseau on utilise Big endian. La plupart des processeurs Intel sont des petits endians. Pour convertir, utilisez ces 2 fonctions qui comprennent automatiquement si une conversion est nécessaire :
htonl(x)
ou htons(x)
pour convertir x de l'hôte en réseau , l si vous devez convertir une variable de 4 octets, une variable de 2 octets.ntohl(x)
ou ntohs(x)
pour le contraire. (Vous remarquerez peut-être que l'implémentation de htonx et ntohx est la même) // 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
};
Grâce au type
nous pouvons comprendre où le transmettre au niveau suivant (2 exemples sont ip ou arp)
Longueur de l'en-tête : vérifiez la seconde moitié de l'attribut ver_ihl
. Exemple : s'il s'agit de « 5 », alors la longueur de l'en-tête est de 4 * 5 = 20 octets.
//à faire ajouter une image
// 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 ];
};
Longueur de l'en-tête (tel que défini ici) : 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 ];
};
Pour calculer la somme de contrôle d'un segment TCP, il est utile de définir une structure supplémentaire (vérifier sur le RFC relatif). Taille de celui-ci, sans la partie tcp_segment
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
};
Pour calculer la taille de l'ensemble du segment TCP (ou de l'icmp), ou plus généralement de la charge utile ip :
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 ;
Nous pouvons utiliser cette fonction aussi bien pour le datagramme IP que pour le segment TCP, mais il faut faire attention au paramètre len
.
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 ;
}
Les 2 cas sont :
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 ));
}
Je conseille VIM. Et s'il vous plaît, indentez votre code.
:wq
pour enregistrer et quitter.esc
si vous ne comprenez pas ce qui se passe/query
pour rechercher "query", n
et N
pour rechercher le résultat précédent/suivant " 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>
Créez tout d’abord un makefile
dans le répertoire contenant les fichiers à compiler, comme ceci :
np : ws18.c
gcc -o np ws18.c
Faites attention à mettre une tabulation avant "gcc", et non des espaces (si vous avez activé expandtab dans vim, utilisez ctrl=v tab
). Ici, np
est ce que vous voulez générer (l'exécutable), et ws18.c
le fichier à compiler. Dans la ligne ci-dessous se trouve la commande à appeler à chaque fois que vous écrivez :make
dans vim. Ensuite, avec le .vimrc
fourni ci-dessus, appuyez sur space
(relâchez-le) et b
( build ). La commande sera exécutée, et vous verrez en bas de votre code la liste des erreurs. Vous pouvez rapidement sauter dans la bonne ligne en appuyant sur Entrée dans chaque entrée. Pour vous déplacer entre la division supérieure et inférieure, appuyez sur CTRL+W
W
. Pour fermer la vue inférieure (quickfix) :q
, ou :cw
.
Vous pouvez trouver le relevé complet de l'examen sur le site au début de ce fichier Lisez-moi. Le code complet est dans les dossiers.
Implémentez une négociation à trois voies TCP (ACK+SYN).
Conseils : Vous pouvez vérifier avec Wireshark si votre somme de contrôle TCP est correcte ou non.
Implémenter la réponse d'écho uniquement pour les requêtes icmp d'une certaine taille
Astuces : Vous pouvez calculer la taille d'un message icmp de cette manière :
unsigned short dimension = ntohs ( ip -> totlen );
unsigned short header_dim = ( ip -> ver_ihl & 0x0F ) * 4 ;
int icmp_dimension = dimension - header_dim ;
Implémentez un serveur HTTP qui :
Astuces : L'en-tête Retry-After
est ignoré par la plupart des navigateurs web, la redirection n'aura donc pas lieu au bout de 10 secondes, mais immédiatement. Dans la solution, il existe un tableau qui conserve l'état de la connexion pour chaque adresse IP.
Implémenter une "Destination inaccessible" ICMP indiquant que le port est indisponible
Astuces : vous devez envoyer le package en réponse à une connexion TCP. icmp->type = 3
, icmp->code=3
. Et n'oubliez pas de copier dans le payload le contenu du payload original icmp.
Interceptez la première connexion reçue, imprimez la séquence et accusez réception de leurs numéros. Reconstruisez ensuite les 2 flux dans 2 buffers différents, et imprimez leur contenu.
Astuces : Pour intercepter la fin de la connexion, il suffit de vérifier si un package contient le bit FIN à 1 (après avoir filtré tous les packages en ne conservant que ceux appartenant à la première connexion). Utilisez le champ séquence TCP pour copier le contnet au bon décalage dans les 2 tampons. NE PAS DUPLIQUER LE CODE.
Modifiez le proxy pour autoriser la demande uniquement à partir d'un pool d'adresses IP et autorisez uniquement le transfert de fichiers avec du texte ou du HTML.
Astuces : Il est préférable de recevoir d'abord la réponse du serveur dans un buffer, puis de copier ce contenu dans un autre buffer pour extraire les en-têtes comme toujours. En effet, la procédure d'extraction d'en-tête modifie le tampon. Si la condition du type de contenu est remplie, transférez simplement le contenu du tampon initial.
Envoyez une réponse HTTP avec un corps fragmenté.
Astuces : Ajoutez Content-Type: text/plainrnTransfer-Encoding: chunkedrn
aux en-têtes HTTP. Ensuite, pour construire chaque morceau à envoyer, vous pouvez utiliser quelque chose comme :
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 ;
}
Implémentez l'en-tête Last-Modified
de HTTP/1.0
Astuces : Quelques fonctions de conversion de temps utiles dans la section divers. Cela aurait également pu être réalisé sans avoir besoin de ces conversions. Le format de date HTTP est %a, %d %b %Y %H:%M:%S %Z
1 : longueur du contenu (était déjà implémenté) 2 : trace (??)
Modifiez icmp echo pour diviser la requête en deux datagrammes IP, l'un avec une taille de charge utile de 16 octets et l'autre avec la taille de charge utile demandée.
Durant le cours certains devoirs (non obligatoires) sont assignés. Même s’il ne s’agit pas d’examens, ils ont plus ou moins le même niveau de difficulté.
Implémentez un programme traceroute, suivant chaque nœud visité par les paquets avant d'atteindre la destination. Astuce : lorsque la durée de vie devient 0, un nœud rejette le paquet et envoie un "Message de temps dépassé" à l'adresse IP source du paquet (voir RFC793).
utilisez l'en-tête HTTP WWW-Authenticate
pour exiger les informations d'identification d'accès au client.
implémentez un client qui accepte le contenu fragmenté.
Le format de date HTTP est %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*)
placer le curseur au début
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 ;
du nom d'hôte (comme www.google.it) à l'adresse IP
/**
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 ]));
Pour l'écoute :
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 ;
}
A la fin, pensez à fermer toutes les sockets avec close(s)
(où s dans la socket que vous souhaitez fermer)
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 ) );
}
Pas vraiment utile, mais...
// 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
: Pour connaître tous les ports TCP disponibles au niveau de l'application./etc/protocols
nslookup <URL>
: trouve l'adresse ip de l'URL spécifiée ( exemple : www.google.com)netstat -rn
affiche la table de routagetraceroute
achemine un paquet IP sur quel chemin il parcourt en imprimant l'adresse IP de chaque passerelle qui décide d'abandonner le paquet qui a été forgé avec un faible nombre de TTL (durée de vie, décrémentée à chaque saut).