Outil Ping ICMP

Outil Ping ICMP

1 – Définition de l’exécutable

L’utilitaire Ping permet à la base de  tester la présence d’un hôte distant via une trame de type ICMP. PingIcmp apporte les trois avantages suivants :

  • Mesure du temps de réponse inférieur à la milliseconde.
  • Changement d’adresse IP source.
  • Envoi massif permettant d’atteindre des débits élevés tel que ~65 Mbps sur une carte 100 Mbps.

2 – Screen shot

2.1 – Version console

pingicmp screen shot console

2.2 – Version graphique

pingicmp screen shot gui

3 – Download

Nom : PingIcmp_gui.exe
Mode : Graphique
Version : 2.5
Librairie : Spécifique à PingIcmp
Taille : 1.456 Mo
Auteur : _SebF
Date de création : 29 Mars 2003
Dernière compilation : 08 Février 2004

Nom : PingIcmp.exe
Mode : Console
Version : 3.9
Librairie : Spécifique à PingIcmp
Taille : 0.132 Mo
Auteur : _SebF@FrameIP.com.pas.de.spam
Date de création : 21 Janvier 2003
Dernière compilation : 08 Février 2004

4 – Suivi du développement de la version console

4.1 – Problème restant

  • Finir la traduction us.
  • PingIcmp.exe /? émet un ping au lieu d’afficher l’exemple.

4.2 – RoadMap

  • Intégration à la librairie commune.

4.3 – Suivi du projet

  • V3.9
    Séparation du suivit mode console et mode graphique. Recompilation avec le nouveau numéro de version.
  • V3.9
    Changement de l’email dans l’aide.
    Remplacement de l’email par l’url www.frameip.com dans les data.
    Changement de l’icône.
  • V3.8
    Migration du projet sur VC++ .net.
    Desactivation de la librairie libcd grâce à la commande /NODEFAULTLIB:libcd.lib.
    Changement des chemains statiques de la librairie socket.
  • V3.8
    Comparaison des arguments indépendamment des minuscules et majuscules grâce à la fonction strlwr.
  • V3.7
    Transformation du numéro de séquence avec htons() pour faire circuler dans les trames un numéro 1 2 3 4 … au lieu de 256 512 768 1024 …
  • V3.7
    Migration du projet en intégrant le pingicmp.h comme fichier de liaison.
    Insertion du numéro de sequence.
  • V3.6
    Passage du retour de la fonction resolution_de_nom en unsigned long au lieu de int pour garder la compatibilité avec inet_addr.
  • V3.6
    Suppression de sous repertoire Debug afin que le resultat des compilations se trouve à la racine (Project – Setting – General).
  • V3.5
    Passage du debug en Level 4 et resolution des Warning de compilation C++.
    Remplacement de clrscr par system(« cls »);
    Rajout de (unsigned int) sur 5 strtod qui générés des warning.
    Passage du mode Cmd de la valeur par defaut de la taille à 32.
  • V3.4
    Renomage de tous les .c en .cpp et recompilation de tous les modules en VC++ 6.0.
    Modification de la fonction recuperation_ip_local() pour permettre de retourner la liste de toutes les ip locales.
  • V3.2
    Refonte de la procedure DNS afin d’intégrer le cas ou l’host demandé n’existe pas.
    Modification des Data par mon adresse Email.
  • V2.4
    Modification de la fonction recuperation_ip_local pour lui intégrer le Return.
  • V2.4
    Intégration du numéro du process dans l’Id Icmp afin de le rendre unique sur cette machine.
    Incrémentation de Séquence Icmp afin de différentier chaque paquet.
  • V2.3
    Résolution du problème de la perte de ping du au décalage dans le buffer. Pour cela j’ai crée la boucle sur un durée de timeout qui lit plusieurs fois le buffer afin de vérifier si la trame attendu n’est pas en seconde position voir plus.
    Récupération de l’ip local dans la procédure initiation permettant de faire apparaître l’ip source par défaut qui sera utilisée.
  • V2.2
    Avancement de la documentation Icmp (inclus aux document IP).
    Vérification que le paquet retour et bien pour celui attendu. Evitant le problème ou un retour de type host unresearchable était interprété comme le retour au ping.
  • V2.1
    Résolution du problème de temps de réponse. GetTickCount est approximatif de 10ms sous NT et 55 ms sous 9.x. J’ai inséré la fonction QueryPerformanceCounter qui se base sur le cycle du cpu.
    Avancement de la documentation Icmp (inclus aux document IP).
  • V2.0
    Résolution du problème de la taille maximum de réception. 65000 maximum maintenant. Le problème été la valeur de 1024 dans la fonction RECV. Je l’ai passé à 65535.
    28 à l’affichage du nombre d’octets reçu afin d’indiquer la taille réel des data sans les entêtes.
    Résolution du problème de RECV bloquant avec l’option SetSockOpt(…,SOL_SOCKET,SO_RCVTIMEO,…,…).
    Ajout du paramètre timeout.
    Le problème du temps de réponse vient du fait que la commande GetTickCount est approximative. Sous NT à 10 Ms et sous Win9x à 55 ms. Il ne reste plus qu’à trouver une solution.
  • V1.3
    Change de la boucle for en while.
    Ajout du paramètre -t pour un bouclage bouclage_infinie.
    Découverte d’un nouveau problème. Le ping ne fonctionne plus si un autre est en parallèle.
    Essai d’incrémentation de id et seq dans l’entête ICMP, mais cela ne résout pas le problème.
    Changement des array de 65000 à 65535 pour prendre le maximum de 2 octets
  • V1.2
    Résolution du problème de montée en charge de la mémoire et du temps de réponse. En sortant la préparation des entêtes de la boucles.
    Utilisation de la fonction inet_ntoa afin de transformer le numéro IP au format xxx.xxx.xxx.xxx.
    Récupération de l’Ip source, attention sur un pc multi carte!
    Avancement de la documentation Icmp (inclus aux document IP)
  • V1.1
    Dépannage de la réception de trame qui ne fonctionnait pas.
    Ajout des options Nombre de fois et temps entre chaque ping.
    Création de la documentation Icmp (inclus aux document IP).
  • V1.0
    Début du développement afin de créer un ping permettant de choisir l’ip source.
    Copie du programme « Générateur de trames ».
    Mon arrière idée est de refaire le ping sans le nouveau bridage Microsoft -w 1.
    Mon choix du compilateur s’est porté sur LCC 3.3 du au faite qu’il soit Light à installer.

5 – Suivi du développement de la version graphique

5.1 – Problème restant

  • Plantage de l’application lorsque le champs reception dépasse la déclaration de la variable char [100000], le mettre en cyclique.

5.2 – RoadMap

  • Intégration à la librairie commune.

5.3 – Suivi du projet

  • V2.5
    Séparation du suivit mode console et mode graphique. Recompilation avec le nouveau numéro de version.
  • V2.4
    Changement de l’email dans l’aide.
    Remplacement de l’email par l’url www.frameip.com dans les data.
    Changement de l’icône.
  • V2.3
    Suppression de toutes les variables de types Values.
    Passage de la compilation en mode Release.
    Passage du SetSockOpt Recv dans la boucle.
    Ajout des unités de mesures dans l’affichage de la fenêtres.
  • V2.3
    Passage de la procédure du PID parent dans la librairie.
    Découverte que l’exe rend instantanément la main à la console permettant à l’utilisateur d’intéragir avec le cmd pendant l’execution de l’exe.
    Suppression de la variable mode_windows qui n’a plus lieu d’être.
  • V2.3
    Ajout du readonly de timeout lors de la deselction de reception.
    Test de performance à 45 Mps (P4 1,8Ghz).
    Résolution du problème du pid de la console grâce aux commande FindWindow et GetWindowThreadProcessId.
    Cela fonctionne même avec plusieurs cmd actifs. Le problème restant est l’attente de l’appuis d’une touche par l’utilisateur pour rendre la main..
  • V2.3
    J’ai réussit à écrire dans la console en l’attachant grâce à la commande AttachConsole(pid). Le problème est que j’ai pris le pid dans le gestionnaire des tâche!
  • V2.3
    Traduction en anglais des champs et de l’About.
    Redimentionnement de la taille des objets et de la fanêtre.
    Sélection par défaut des champs ip local et host name en fonction du Get appelant.
    Affichage du TTL dans le milieu au lieu de la fin.
  • V2.2
    Ajout du champ IpAddressCtrl.
    Déplacement du combobox dans la fenêtre ip_address.
    Résolution du problème du champ Combobox qui ne s’ouvrait plus. Pour cela deux opérations. Le nettoyage des doublons de ressouce.h et l’edition notepad de PingIcmp.rc et remplacement des deux lignes du Combobox (attention aux coordonnées ???).
    Création d’une variable externe permetant le dialogue entre deux ccp via la commande extern.
  • V2.2
    Création de la fenêtre ip_address afin de demander la saisie de l’adresse ip.
  • V2.1
    Migration du projet sur VC++ .net.
    Desactivation de la librairie libcd grâce à la commande /NODEFAULTLIB:libcd.lib.
    Changement des chemains statiques de la librairie socket.
  • V2.0
    Désactivation du spin nfois quand l’on passe en boucle infine.
    Suppression de tous les répertoires et bascule de tous les fichiers dans le répertoire racine PingIcmp.
    Renommage du fichier de suivi de projet avec un _ devant.
  • V2.0
    Intégration du modules gestion_des_arguments.
  • V2.0
    Refonte complète du programme pour n’intégrer qu’un seul Exe.
    Convertion des sprintf en memcpy.
    Intégration du module Pause afin de permettre de rendre la main à la fenetre principale pendant l’attente.
  • V1.3
    Remplacement des fonctions SetRange par SetRange32 afin de supporter 65535.
  • V1.3
    Déplacement des fichiers icône de /res à la racine.
  • V1.3
    Activation du menu about.
    Création du bouton About.
    Affichage de la fenetre About avec réccupération des informations dans la librairie.
  • V1.2
    Affectation des raccourcits clavier.
  • V1.1
    Réglage du problème des nouveaux Spins dont leurs valeurs ne varié que de -1 à 1. Pour cela passage de la limite max de 65535 à 10000.
    Resolution du problème des Spins qui ne marchaient plus. Pour les associer à au champ désirer, il faut qu’ils se suivent dans l’ordre des tabulations.
    Ajout de la procédure liberation_du_jeton qui permet de continuer à gérer la fenêtre principale pendant la boucle Ping.
    Ajout du bouton Stop afin de pouvoir stoper la boucle.
    Desactivation du bouton Ping pendant l’execution afin de marquer si l’on se trouve dans la boucle ou pas.
    Activation de la procédure OnClose afin de fermer la boucle pour éviter que le process tourne en mémoire sans interface graphique.
  • V1.0
    Erreur docteur waston lors de la fermeture de la fenetre. Passage de la commande exit(0) en //.
    Transformation du numéro de séquence avec htons() pour faire circuler dans les trames un numéro 1 2 3 4 … au lieu de 256 512 768 1024 …
    Passage du retour de la fonction resolution_de_nom en unsigned long au lieu de int pour garder la compatibilité avec inet_addr.
    Suppression de sous repertoire Debug afin que le resultat des compilations se trouve à la racine (Project – Setting – General).
    Acivation de l’icône dans la fenetre minimize et dans le haut à gauche. Pour ce dernier, l’objet de l’icône doit s’appeler IDR_MAINFRAME.
    Gestion de l’ordre des tabulation grace au menu Layout -> Tab order (Il faut au préalable avoir la Form).
    Activation du bouton Ping comme bouton par defaut (dans les properties du bouton).
    Passage du debug en Level 4 et resolution des Warning de compilation C++.
    Remplacement de #include <tcconio.h> par #include <windows.h>.
    Rajout de (unsigned int) sur 5 strtod qui générés des warning.
    Passage de la decente du croll de 100 à 100000.
    Renomage de tous les .c en .cpp et recompilation de tous les modules en VC++ 6.0.
    J’ai séparé le programme en deux parties. L’une pour le coeur et l’autre pour l’intérface.
    Intégration d’un frontal graphique à l’aide de VC++ 6.0.

6 – Code source de la version console

6.1 – pingicmp.cpp

// ********************************************************
// Les includes
// ********************************************************
#include <stdio.h>
//#include <tcconio.h>  // Pour Lcc
#include <windows.h> // Pour VC++
//#include <C:\\lcc\\projects\\PingIcmp\\Lib\\pingicmp.h>
#include <C:\\RepPerso\\Personnel\\Developpement\\Projets\\PingIcmp\\Lib\\pingicmp.h>


// ********************************************************
// Les procédures
// ********************************************************
void initiation_des_variables(void);
void gestion_des_arguments(int argc, char* argv[]);
void affichage_du_resultat();

// ********************************************************
// Les variables
// ********************************************************
struct echange echange_reception;
char ip_source[1000];
char ip_destination[1000];
unsigned char valeur_du_ttl;
unsigned int taille;
unsigned int nombre_de_ping;
bool bouclage_infinie;
unsigned int pause_entre_chaque_ping;
unsigned int timeout;
unsigned short sequence;







int main (int argc, char* argv[])
            {
            // system("cls");
            initiation_des_variables();
            gestion_des_arguments(argc,argv);
            while (nombre_de_ping>0) // Boucle du nombre de ping à envoyer
                        {
                        echange_reception=pingicmp_main(resolution_de_nom(ip_source), resolution_de_nom(ip_destination),valeur_du_ttl, taille,timeout,sequence);
                        if (sequence==65535) // Incrémente le champ sequence          
                                   sequence=0;
                        else
                                   sequence++;
                        affichage_du_resultat();
                        if (bouclage_infinie==TRUE)
                                   nombre_de_ping=1;
                        else
                                   nombre_de_ping--;
                        if (nombre_de_ping>0)
                                   Sleep(pause_entre_chaque_ping);
                        }
            printf("\n");
            return(1);
            }












void initiation_des_variables(void)
            {
            struct structure_ip_local reception_des_ip_locales;
            struct structure_version version_reception;
            int i;

            reception_des_ip_locales=recuperation_ip_local();
            strcpy(ip_source,reception_des_ip_locales.adresse_ip_local[0]);
            strcpy(ip_destination,"217.12.3.11");
            valeur_du_ttl=100;
            taille=32;
            nombre_de_ping=1;
            bouclage_infinie=FALSE;
            pause_entre_chaque_ping=1000;
            timeout=2;
            sequence=1;

            // ********************************************************
            // Affichage de la banniere
            // ********************************************************
            version_reception=version();
            printf("\n");
            for (i=0;i<version_reception.nombre_d_element;i++)
                        printf("\n%s",version_reception.tableau[i]);
            printf("\n\n");
            }












void gestion_des_arguments(int argc,char* argv[])
            {
            char * caractere_non_convertit;
            int i;

            if ( (argc>1) && (strcmp(argv[1],"-?")==0) || (argc==1) )
                        {
                        printf("\nParametres        Descriptions                  Valeurs par defaut");
                        printf("\n");
                        printf("\n-?                Aide");
                        printf("\n-ip_source        @Ip ou nom d'hote.            %s",ip_source);
                        printf("\n-ip_destination   @Ip ou nom d'hote.            %s",ip_destination);
                        printf("\n-ttl              Entre 0 et 255.               %d",valeur_du_ttl);
                        printf("\n-taille           Entre 0 et 65535.             %d",taille);
                        printf("\n-nfois            Entre 1 et 65535.             %d",nombre_de_ping);
                        printf("\n-t                Bouclage inifie");
                        printf("\n-pause            Temps entre les ping (ms).    %d",pause_entre_chaque_ping);
                        printf("\n-timeout          Temps d'attente max (s).      %d (0 supprime la reception)",timeout);
                        printf("\n\nExemple           pingicmp -ip_destination www.cisco.com -nfois 3");
                        printf("\n\n");
                        exit(0);
                        }
            for (i=1;i<argc;i=i+1)
                        {
                        if (strcmp(strlwr(argv[i]),"-ip_source")==0)
                                   strcpy(ip_source,argv[i+1]);
                        if (strcmp(strlwr(argv[i]),"-ip_destination")==0)
                                   strcpy(ip_destination,argv[i+1]);
                        if (strcmp(strlwr(argv[i]),"-ttl")==0)
                                   valeur_du_ttl=(unsigned char)strtod(argv[i+1],&caractere_non_convertit);
                        if (strcmp(strlwr(argv[i]),"-taille")==0)
                                   taille=(unsigned int)strtod(argv[i+1],&caractere_non_convertit);
                        if (strcmp(strlwr(argv[i]),"-nfois")==0)
                                   nombre_de_ping=(unsigned int)strtod(argv[i+1],&caractere_non_convertit);
                        if (strcmp(strlwr(argv[i]),"-t")==0)
                                   bouclage_infinie=1;
                        if (strcmp(strlwr(argv[i]),"-pause")==0)
                                   pause_entre_chaque_ping=(unsigned int)strtod(argv[i+1],&caractere_non_convertit);
                        if (strcmp(strlwr(argv[i]),"-timeout")==0)
                                   timeout=(unsigned int)strtod(argv[i+1],&caractere_non_convertit);
                        }
            }





 




void affichage_du_resultat(void)
            {
            if (echange_reception.nombre_de_caractere_emis==-1)
                        printf("\nLa trame n'a pas pu etre emise");
            else
                        {
                        if (echange_reception.nombre_de_caractere_recu==-1)
                                   printf("\nLa trame retour attendu n'a pas ete receptionnee");
                        if (echange_reception.nombre_de_caractere_recu>0)
                                   {
                                   printf("\n");
                                   if (sequence==0)
                                               printf("65535");
                                   else
                                               printf("%d",sequence-1);
                                   printf("   %s",echange_reception.ip_source);
                                   printf("   %s",echange_reception.ip_destination);
                                   printf("   %d Octets",echange_reception.nombre_de_caractere_recu-28);
                                   printf("   %.2f ms",echange_reception.temps_de_reponse);
                                   printf("   ttl : %d",echange_reception.ttl);
                                   }
                        }
            }

7 – Les vidéos

  • 7.1 - How does traceroute work ? Vidéo en Anglais

    Cette video en anglais vous présente comment fonctionne un Traceroute. Traceroute is one interesting tool enabled by ICMP. And the way that it works also illustrates an interesting feature of the IP packet header ​the time to live (TTL) field.

    How does traceroute work ?

  • 7.2 - Ping entre 2 machines à travers un routeur Cisco Vidéo en Français

    Cette vidéo vous présente comment faire communiquer deux machines qui sont sur des différents réseaux via un Routeur Cisco.

    Ping entre 2 machines à travers un routeur Cisco

8 – Discussion autour de l’outil Ping ICMP

Vous pouvez poser toutes vos questions, faire part de vos remarques et partager vos expériences à propos de l’outil Ping ICMP. Pour cela, n’hésitez pas à laisser un commentaire ci-dessous :

Commentaire et discussion

6 commentaires sur la page : “Outil Ping ICMP”

  1. Bonjour, j’aurai aimer savoir si le destinataire des Packets doit être un serveur ? et si le destinataire peut être un windows, un Linux ou un mac ?

  2. Bonjour !

    Logiciel très intéressant.
    Bravo !

    Serait-il possible d’y ajouter les possibilités suivantes :

    -choix du protocole : TCP ou UDP
    -choix du port de destination

    Salutations

    1. Lu Daniel,

      C’est une très bonne idée, mais je ne maintient plus l’interface graphique qui utilise les MFC Microsoft.
      Pour la version en ligne de commande, je n’ai pas le temps en ce moment, mais je le note.

      @+

      Sebastien FONTAINE

    1. Lu Christophe,

      Merci pour ton message.

      Si tu ne te trouve pas dans le réseau de la VRF, tu ne peux pas la pinguer, c’est le principe fondmentale d’étanchéité des VRF.

      Le seul moyen, c’est de lancer un ping directement à partir du PE ou CE en mode étendu afin de spécifier l’interface/@IP source.

      @+

      Sebastien FONTAINE

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *