5 Travail à effectuer
Après les exercices précédents destinés à vous familiariser avec l'environnement de
développement de la pile TCP/IP, vous allez enfin contribuer à l'écriture de cette
pile.
5.1 Protocole ICMP
Faites vos armes sur un protocole assez simple comme ICMP. Les deux fonctions à coder
sont icmpDecodePacket et icmpSendPacket. La fonction icmpSendPacket
construit l'entête ICMP devant les données fournies lors de l'appel puis appelle la
couche inférieure, c'est à dire IP. Attention, pour optimiser l'espace mémoire, il
est recommandé d'utiliser realloc plutôt que malloc. Regardez comment
cet appel système est utilisé dans ipFillHeader. La fonction icmpDecodePacket
doit implanter au moins deux fonctions; traiter les echo request en envoyant
un echo reply et sur réception d'un ICMP port unreachable propager
l'information au processus UDP concerné. Testez votre implantation dans les cas
suivants :
-
connectez vous avec nc sur un port TCP quelconque; vous devez recevoir
un message ICMP indiquant que le protocole TCP n'est pas géré par la pile ;
- connectez vous sur un port UDP non lié à un processus, nc doit se
terminer instantanément sur réception d'un ICMP port unreachable ;
- lancez un ping sur votre pile TCP/IP, l'utilitaire doit indiquer que
les ICMP echo reply sont bien reçus, trouvez comment diminuer le temps
d'aller-retour de la première sonde ;
- enfin écrivez un processus UDP client et faites lui traiter le cas de l'absence
de serveur UDP; implantez le serveur UDP sur la machine de TP avec nc
et les options -u -l, si le serveur UDP existe faites en sorte que
le client UDP de votre pile affiche la réponse du serveur, dans le cas
contraire affichez un message mentionnant l'absence de serveur.
Donnez la taille mémoire utilisée sur le tas dans les situations suivantes :
-
réception d'un echo request et réponse avec un echo reply
quand l'adresse IP de la destination du echo reply n'est pas
dans le cache ARP de la pile ;
- même question dans le cas où l'adresse IP est dans le cache ARP.
Détaillez l'utilisation mémoire selon les couches de la pile.
5.2 Protocole TCP
Votre travail proprement dit commence ici avec l'implantation du protocole TCP. Il
vous est demandé de réaliser les tâches décrites ci-après.
-
Définissez la structure des paquets TCP sur le modèle de la structure des
paquets IP.
- Définissez la structure des connexions TCP stockant en particulier les
numéros de séquence et l'état des connexions TCP
(voir http://en.wikipedia.org/wiki/File:Tcp_state_diagram_fixed.svg).
Il faut, bien évidement, écrire les fonctions de gestion du tableau des connexions
TCP; ajout d'une connexion en utilisant éventuellement realloc, suppression
d'une connexion et recherche d'une connexion.
- Ecrivez la fonction tcpDecodePacket dont la principale fonction est
de vérifier la somme de contrôle TCP, de s'assurer que le paquet est bien le suivant
dans la séquence TCP et dans l'affirmative de traiter ce paquet. Le traitement consiste
soit à répondre à un paquet SYN ou FIN, soit à fournir au processus correspondant les
données TCP (voire envoyer un paquet TCP RST si aucun processus n'est lié au port
précisé). Le traitement inclut aussi l'envoi d'un accusé de réception. L'accusé
peut être soit envoyé directement, soit être programmé pour inclusion dans un prochain
paquet de données à destination du correspondant. Dans ce dernier cas il faut prévoir
un minuteur pour envoi de l'accusé dans le cas où aucun paquet de donnée n'est envoyé
au correspondant durant un certain laps de temps.
- Ecrivez la fonction tcpSendPacket pour envoyer un paquet TCP. Cette
fonction va remplir les champs des entêtes TCP et calculer la somme de contrôle. Le
cas échéant (voir discussion ci-dessus), un accusé de réception peut être ajouté au
paquet. Le paquet est alors envoyé via la couche inférieure, c'est à dire IP. Une
ré-émission du même paquet doit être programmé au bout d'un temps raisonnable. Pour
réaliser cette ré-émission il est conseillé de déclencher un appel identique à la
fonction tcpSendPacket à l'aide de la fonction eventsSchedule. Il faudra
donc vérifier en début de la fonction tcpSendPacket que le numéro de séquence
du paquet à envoyer ne soit pas inférieur à la séquence courante. Le cas écheant le
paquet doit être supprimé sans déclencher de ré-émission.
- Ecrivez une fonction dans le fichier stack.c pour envoyer un paquet
TCP sur le modèle de la fonction qui génère un paquet UDP (stackUDPSendDatagram).
L'appel de cette fonction avec un tableau de données vide doit avoir une sémantique
particulière. Si la connexion TCP avec le correspondant n'est pas déjà établie, alors
une structure connexion est allouée et le premier paquet TCP SYN est envoyé au
correspondant. Si la connexion TCP avec le correspondant est déjà établie, alors
un paquet FIN est envoyé au correspondant, la structure de connexion sera libérée
sur réception du paquet FIN du correspondant.
- Ecrivez dans processes.c la fonction tcp_echo qui va réaliser le
serveur d'écho TCP. Le serveur doit afficher un message sur sa sortie standard quand un
client se connecte (avec les coordonnées du client) et quand un client se déconnecte
(toujours avec les coordonnées du client).
5.3 Tests TCP
Pour tester votre implantation TCP, connectez vous avec l'utilitaire nc sur
votre pile TCP/IP. Connectez-vous à la fois sur des ports sans processus liée
et sur le port sur lequel écoute votre serveur écho. Testez votre serveur écho avec
plusieurs clients simultanés. Testez votre implantation en liant le serveur écho
à plusieurs ports TCP, là encore tentez plusieurs connexions simultanées.