Librairie LibrairieSocket.lib

Librairie LibrairieSocket.lib

1 – Suivi du développement

1.1 – Problème restant

1.2 – RoadMap

1.3 – Suivi du projet

  • V3.12
    Correction orthographique de Opocode en opcode
  • V3.11
    Problème, les résolutions ARP dure au minimum 1 seconde. Résolution en changeant la fonction resolution_arp() en positionnant le timeout de pcap_open_live() de 1000ms à 1ms.
    Compilation en mode release
  • V3.10
    Ajout des fonctions :
    – struct gestion_des_interfaces recuperation_des_interfaces(); Permettant de récupèrer tous les renseignements des interfaces du système ainsi que leur nombre.
    – struct adresse_mac recuperation_de_l_adresse_mac(char [1000]); Permettant de récupèrer l’adresse MAC de l’interface selectionnée.
    – struct adresse_mac transformation_string_en_mac(char *); Permettant de transformer une chaîne de caractère en adresse MAC.
    – struct adresse_mac resolution_arp(char [1000],bool,char [16],unsigned int); Permettant de trouver l’adresse MAC d’une IP donnée.
    – void gestion_des_erreurs(unsigned int,char *,unsigned int,bool); Permettant de gérer les erreurs rencontrées.
  • V3.9
    Les fonctions de calcul des checksums nécessitent désormais un argument supplémentaire afin de préciser la taille des data passé.
  • V3.9
    Remplacement des Strcp par Memcpy en insérant une variable géant la taille des chaînes de caractères. Ceci gère donc maintenant les 00 dans les chaînes hexa.
    Les valeurs Hexa suppérieur à FF n’étaient pas pris en compte. C’était dû au fait que la valeur int était signé. J’ai résolue le problème comme ceci : if (tempo_non_signe<0) tempo_non_signe+=256;
  • V3.8
    Ajout des fonctions char * conversion_string_hexa(char [65535],unsigned int); et char * conversion_hexa_string(char [65535],unsigned int); permettant de convertir une chaine Hexa en Ascii et vis versa
  • V3.8
    Ajout de la fonction char * convertion_ip(int adresse_ip) permettant la convertion Ip au format Inetaddr en format texte
  • V3.8
    Ajout dans le .h de : #define SIO_RCVALL _WSAIOW(IOC_VENDOR,1) // Permet d’éviter d’intégrer #include <ws2tcpip.h> qui ne veux plus fonctionner
  • V3.7
    Publication du code source
  • V3.7
    Résolution du problème de calcul checksum IP. Je viens de comprendre que le calcul ne doit s’effectuer que sur l’entête IP et pas sur les couches de dessus. De plus, le champ ip_length ne fonctionnant pas, je ne le calculais pas et l’id était en automatique donc le calcul du checksum IP était toujours faux! J’ai donc supprimé le troisième paramètre (data) de la fonction unsigned short calcul_du_checksum_ip(bool liberation, struct ipv4 ipv4_tampon).
  • V3.6
    Le champ tcp_offset est bien sur 4 bits et non pas sur 6 comme j’ai cru le voir dans Netmon. Netmon en fait, indique le nombre multiplié par 4 et interprète un peu de trop à mon goût. Par exemple pour une entête de 5 mot de 32 bits il indique 20, mais la valeur hexa est bien 5. Modification donc de l’entête TCP pour passer l’offset à 4 bits.
  • V3.6
    Test sur la longueur de data afin d’éviter la division par 0 dans la fonction dimensionnement_de_data_a_envoyer.
  • V3.6
    Intégration de la nouvelle entête TCP afin d’intégrer directement les options et le reserved.
  • V3.6
    Remplacement de unsigned short offset2:8; par unsigned char offset2;
  • V3.5
    Changement de déclaration de int en short de la fonction gotoxy.
    Ajout de Sleep(1) dans la fonction pause pour éviter que le processeur soit à 100%.
  • V3.4
    Intégration de la fonction void gotoxy(int x,int y) permettant de placer le curseur à X et Y.
    Intégration de la fonction void clear_screen(void) permettant d’effectuer un cls.
  • V3.3
    Correction du problème du calcul checksum TCP et UDP qui ne fonctionnaient pas quand il y avait des data. Remplacement de : memcpy(tampon+sizeof(pseudo_tcp)+sizeof(struct tcp),&data_tampon,strlen(data_tampon)); Par : memcpy(tampon+sizeof(pseudo_tcp)+sizeof(struct tcp),data_tampon,strlen(data_tampon));
  • V3.2
    Ajout de la fonction unsigned short convertion_offset_control_tcp(int,unsigned char,unsigned char,bool,bool,bool,bool,bool,bool) permettant de convertir les différent petits champs TCP en un seul unsigned short afin d’être mis dans la structure TCP.
  • V3.1
    Commentaire pour chaque fonction dans le .H
  • V3.0
    Ajout de la fonction unsigned long generation_d_une_adresse_ip_aleatoire(int) permettant de tirer une adresse ip aléatoirement.
    Ajout d’un variable int non utilisée pour anticiper les futur besoin sans retravailler les ancien programme.
  • V2.4
    Ajout des fonctions de calcul checksum comme par exemple unsigned short calcul_du_checksum_icmp(bool,struct ip,char [65535]) permettant le calcul du checksum de l’entete ICMP.
  • V2.3
    Recompilation en mode Multiprocess ce qui résout tous les problème de migration VC++6 vers .net.
  • V2.2
    Ajout de la fonction DWORD pid_de_la_console_parente(void) permettant donc de récupérer le PID de la fenêtre console ayant lancé l’exe.
  • V2.1
    Compilation en .net. La seul erreur était le chemin statique du .h et du .lib.
  • V2.0
    Ajout dans toutes les procédures la variable de type bool afin de permettre à l’utilisateur de demander ou pas la libération du jeton.
  • V1.2
    Création de la fonction gestion_des_arguments. struct gestion_des_arguments recuperation_des_arguments(void);
  • V1.1
    Création de la fonction pause. void pause(unsigned int,bool);
  • V1.0
    Insértion des fonction existante dans Pingicmp et FrameIp
    unsigned long resolution_de_nom(char [65535]);
    struct structure_ip_local recuperation_ip_local(void);
    unsigned short calcul_du_checksum(unsigned short *, int);
    unsigned short calcul_du_checksum_icmp(struct icmp,char [65535]);
    unsigned short calcul_du_checksum_igmp(struct igmp,char [65535]);
    unsigned short calcul_du_checksum_tcp(unsigned long,unsigned long,struct tcp,char [65535]);
    unsigned short calcul_du_checksum_udp(unsigned long,unsigned long,struct udp,char [65535]);
    char * dimensionnement_de_data_a_envoyer(char [65535],unsigned int);
    void liberation_du_jeton (void);

2 – Download

Nom : LibrairieSocket.lib
Mode : Librairie
Version : 3.11
Taille : 22 ko
Auteur : _SebF
Date de création : 01 Mai 2003
Dernière compilation : 16 Novembre 2006

3 – Code source

3.1 – LibrairieSocket.h

// ********************************************************
// Permet que la structure de arp soit bien égale à 28, sans "#pragma pack(2);", la taille de la structure arp est de 32
// ********************************************************
#pragma pack(2)

// ********************************************************
// Les includes
// ********************************************************
#include <winsock2.h>
#include <cstdio>                                // Pour les Sprintf
const int IP_HDRINCL=2;      // Permet d'éviter d'intégrer #include <ws2tcpip.h> qui ne veux plus fonctionner
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1) 

// ********************************************************
// Les librairies
// ********************************************************
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"C:\\RepPerso\\Personnel\\Developpement\\Projets\\LibrairieSocket\\LibrairieSocket.lib")
//#pragma pack(1) // Permet de préciser l'arondie des variable de type :4 :7 etc ...

// ********************************************************
// Les fonctions
// ********************************************************
unsigned long resolution_de_nom(bool,char [65535]);
// Permet     : Résoud un nom d'hôte en adresse IP. Vérifie aussi si le nom d'hôte n'est pas déjà une IP.
// Argument 1 : Bool activant ou désactivant le rendu processeur à la fenêtre graphique.
// Argument 2 : Char de 65535 contennant l'adresse IP à résoudre.
// Renvoi     : Unsigned Long contennant l'inet_addr de l'IP résolu.

struct structure_ip_local recuperation_ip_local(bool);
// Permet     : Récupère la liste de toutes les adresses IP locales à la machines.
// Argument 1 : Bool activant ou désactivant le rendu processeur à la fenêtre graphique.
// Renvoi     : Struct structure_ip_local contennant La liste des ip locales ainsi que le nombre d'adresse ip locales présentent sur la machine.

unsigned short calcul_du_checksum(bool,unsigned short *, int);
// Permet     : Permet le calcul basique du checksum.
// Argument 1 : Bool activant ou désactivant le rendu processeur à la fenêtre graphique.
// Argument 2 : Les data au format char 65535 convertit en pointeur unsigned short.
// Argument 3 : longueur des data. Cet argument est présent car il ne faut pas utilser strlen(data) car data pourrait contenir des 0.
// Renvoi     : Le checksum sur deux octets (unsigned short).

unsigned short calcul_du_checksum_ip(bool,struct ipv4);
// Permet     : Permet le calcul du checksum de l'entête IP.
// Argument 1 : Bool activant ou désactivant le rendu processeur à la fenêtre graphique.
// Argument 2 : Structure de l'entête IP dont il faut calculer le checksum.
// Argument 3 : Char 65535 contennant tous ce qu'il y après l'entête IP (Les entêtes tels que TCP UDP ainsi que les data).
// Renvoi     : Le checksum sur deux octets (unsigned short).
// Fonction ne travail pas correctement. Mauvais résultat obtenu.

unsigned short calcul_du_checksum_icmp(bool,struct icmp,char [65535],unsigned int);
// Permet     : Permet le calcul du checksum de l'entête ICMP.
// Argument 1 : Bool activant ou désactivant le rendu processeur à la fenêtre graphique.
// Argument 2 : Structure de l'entête ICMP dont il faut calculer le checksum.
// Argument 3 : Char 65535 contennant tous ce qu'il y après l'entête ICMP.
// Argument 4 : longueur des data. Cet argument est présent car il ne faut pas utilser strlen(data) car data pourrait contenir des 0.
// Renvoi     : Le checksum sur deux octets (unsigned short).

unsigned short calcul_du_checksum_igmp(bool,struct igmp,char [65535],unsigned int);
// Permet     : Permet le calcul du checksum de l'entête IGMP.
// Argument 1 : Bool activant ou désactivant le rendu processeur à la fenêtre graphique.
// Argument 2 : Structure de l'entête IGMP dont il faut calculer le checksum.
// Argument 3 : Char 65535 contennant tous ce qu'il y après l'entête IGMP.
// Argument 4 : longueur des data. Cet argument est présent car il ne faut pas utilser strlen(data) car data pourrait contenir des 0.
// Renvoi     : Le checksum sur deux octets (unsigned short).

unsigned short calcul_du_checksum_tcp(bool,unsigned long,unsigned long,struct tcp,char [65535],unsigned int);
// Permet     : Permet le calcul du checksum de l'entête TCP.
// Argument 1 : Bool activant ou désactivant le rendu processeur à la fenêtre graphique.
// Argument 2 : Adresse IP source (de l'entête IP) au format Inet_addr (unsigned long).
// Argument 3 : Adresse IP destination (de l'entête IP) au format Inet_addr (unsigned long).
// Argument 4 : Structure de l'entête TCP dont il faut calculer le checksum.
// Argument 5 : Char 65535 contennant tous ce qu'il y après l'entête TCP.
// Argument 6 : longueur des data. Cet argument est présent car il ne faut pas utilser strlen(data) car data pourrait contenir des 0.
// Renvoi     : Le checksum sur deux octets (unsigned short).

unsigned short calcul_du_checksum_udp(bool,unsigned long,unsigned long,struct udp,char [65535],unsigned int);
// Permet     : Permet le calcul du checksum de l'entête UDP.
// Argument 1 : Bool activant ou désactivant le rendu processeur à la fenêtre graphique.
// Argument 2 : Adresse IP source (de l'entête IP) au format Inet_addr (unsigned long).
// Argument 3 : Adresse IP destination (de l'entête IP) au format Inet_addr (unsigned long).
// Argument 4 : Structure de l'entête UDP dont il faut calculer le checksum.
// Argument 5 : Char 65535 contennant tous ce qu'il y après l'entête UDP.
// Argument 6 : longueur des data. Cet argument est présent car il ne faut pas utilser strlen(data) car data pourrait contenir des 0.
// Renvoi     : Le checksum sur deux octets (unsigned short).

char * dimensionnement_de_data_a_envoyer(bool,char [65535],unsigned int,unsigned int);
// Permet     : Permet de multiplier une chaie existante sur une longueur données.
// Argument 1 : Bool activant ou désactivant le rendu processeur à la fenêtre graphique.
// Argument 2 : Chaine de caractères servant de référence.
// Argument 3 : longueur des data. Cet argument est présent car il ne faut pas utilser strlen(data) car data pourrait contenir des 0.
// Argument 4 : Taille désirée de la chaine. 
// Renvoi     : Un char * contennant la chaine référence dimentionnée à la longueur voulut. Exemple, data="abcd" taille=10 la chaine retournée sera alors "abcdabcdab".

void liberation_du_jeton (void);
// Permet     : Rend le processeur à la fenêtre graphique afin d'éviter quelle soit figée.

void pause(bool,unsigned int);
// Permet     : Fournit une pause au miliseconde près. De plus, elle permet d'obtenir une pause sans figer la fenêtre graphique.
// Argument 1 : Bool activant ou désactivant le rendu processeur à la fenêtre graphique.
// Argument 2 : Nombre de miliseconde à attendre.

struct gestion_des_arguments recuperation_des_arguments(bool);
// Permet     : Récupère tous les arguments entré après l'exe ainsi que leurs nombres.
// Argument 1 : Bool activant ou désactivant le rendu processeur à la fenêtre graphique.
// Renvoi     : La structure gestion_des_arguments contennant la liste des arguments ainsi que leur nombre.

DWORD pid_de_la_console_parente(bool);
// Permet     : Récupère le PID de la fenêtre console qui lancé l'exe.
// Argument 1 : Bool activant ou désactivant le rendu processeur à la fenêtre graphique.
// Renvoi     : Le PID au format DWORD.

unsigned long generation_d_une_adresse_ip_aleatoire(int);
// Permet     : Génère une adresse IPV4 aléatoirement.
// Argument 1 : Argument ne servant pas. Présent pour de futurs besoins et permet donc de garder une compatibilité. Mettre à 0.
// Renvoi     : L'adresse IP aléatoire au format Inet_addr (unsigned long).

unsigned short convertion_offset_control_tcp(int,unsigned char,unsigned char,bool,bool,bool,bool,bool,bool);
// Cette fonction n'est plus utilisée, Une nouvelle structure Tcp permet de ne pas réunir tous les variable en une seule
// Permet     : Convertit les champs Offset, Résérvé et Control de l'entête TCP en un seul nombre 16 bits.
// Argument 1 : Argument ne servant pas. Présent pour de futurs besoins et permet donc de garder une compatibilité. Mettre à 0.
// Argument 2 : Valeur du champ Offset (4 bits). Doit être compris entre 0 et 15.
// Argument 3 : Valeur du champ Résérvé (6 bits). Doit être compris entre 0 et 63.
// Argument 4 : Active ou désactive le champ URG.
// Argument 5 : Active ou désactive le champ ACK.
// Argument 6 : Active ou désactive le champ PSH.
// Argument 7 : Active ou désactive le champ RST.
// Argument 8 : Active ou désactive le champ SYN.
// Argument 9 : Active ou désactive le champ FIN.
// Renvoi     : Renvoi le nombre 16 bits (unsigned short) correspondant à la définition de la structure de l'entête TCP.

void gotoxy(short x,short y);
// Permet     : Place le curseur aux coordonnées x et y
// Argument 1 : coordonnées x.
// Argument 1 : coordonnées y.

void clear_screen(void);
// Permet     : D'effectuer un cls de la fenêtre console

char * convertion_ip(int);
// Permet     : De convertir une adresse IP du format Inet_addr en chaine du type "xxx.xxx.xxx.xxx";
// Argument 1 : Adresse IP de type Inet_addr.
// Renvoi     : Renvoi l'adresse IP du type chaine de caractère.

char * conversion_string_hexa(char [65535],unsigned int);
// Permet     : De convertir une chaine de caractère en Hexa
// Argument 1 : Chaine de caractere
// Argument 1 : Longueur de la chaine
// Renvoi     : Renvoi la correspondance Hexa de la chaine de caractere

char * conversion_hexa_string(char [65535],unsigned int);
// Permet     : De convertir une chaine hexa en chaine de caractère
// Argument 1 : Chaine Hexa
// Argument 1 : Longueur de la chaine
// Renvoi     : Renvoi la chaine de caractere correspondant

struct gestion_des_interfaces recuperation_des_interfaces();
// Permet     : Récupère tous les renseignements des interfaces du système ainsi que leur nombre.
// Renvoi     : La structure gestion_des_interfaces contennant la liste des interfaces ainsi que leur nombre.

struct adresse_mac recuperation_de_l_adresse_mac(char [1000]);
// Permet     : Récupère l'adresse MAC de l'interface selectionnée.
// Argument 1 : Indique le nom de l'interface demandée.
// Renvoi     : Une structure contennant l'adresse MAC décomposée en 6 octets.

struct adresse_mac transformation_string_en_mac(char *);
// Permet     : Transforme une chaine de caractère en adresse MAC.
// Argument 1 : Chaine de caractère à transformer.
// Renvoi     : Une structure contennant l'adresse MAC décomposée en 6 octets.

struct adresse_mac resolution_arp(char [1000],bool,char [16],unsigned int);
// Permet     : Trouve l'adresse MAC d'une IP donnée.
// Argument 1 : Numéro de l'interface à utiliser.
// Argument 2 : Indique l'activation ou pas du mode promiscuite.
// Argument 3 : Adresse IP à convertir.
// Argument 4 : Temps d'attente maximum pour la réponse ARP avant de considérer qu'il n'y a pas de réponse (En seconde).
// Renvoi     : Une structure contennant l'adresse MAC décomposée en 6 octets.

void gestion_des_erreurs(unsigned int,char *,unsigned int,bool);
// Permet     : Gère les erreurs rencontrées.
// Argument 1 : Si une fonction est utilisée plusieurs fois dans le programme, cette identifiant permet de savoir si c'est la première, seconde ....
// Argument 2 : Nom de la fonction en erreur.
// Argument 3 : permet d'indiquer si il ya un affichage (0=pas d'affichage - 1=affichage printf - 2=affichage graphique).
// Argument 4 : Indique si on doit arrêter le programme ou laisser continuer (true=stop).

// ********************************************************
// Les structures
// ********************************************************
struct gestion_des_arguments
            {
            unsigned int argc;                                             // Nombre d'argument
            char * argv[1024];                                          // Tableau contennant tous les arguments
            };

struct gestion_des_interfaces
            {
            unsigned int nombre;                                            // Nombre d'interface
            char description[100][1000];                                   // Tableau contennant toutes les descriptions
            char nom[100][1000];                                                                // Tableau contennant toutes les noms
            };

struct structure_ip_local
            {
            int                                            nombre_d_ip_local;
            char                                         adresse_ip_local[1000][16];
            };

struct adresse_mac
            {
            unsigned char               adresse[6];
            };

struct mac
            {
            unsigned char               destination[6];
            unsigned char               source[6];
            unsigned short              type;
            };

struct arp
            {
            unsigned short              mac_type;
            unsigned short              protocol_type;
            unsigned char               mac_taille;
            unsigned char               protocol_taille;
            unsigned short              opocode;
            unsigned char               mac_source[6];
            unsigned long                                       ip_source;
            unsigned char               mac_destination[6];
            unsigned long                                       ip_destination;
            };

struct ipv4 // htons pour les ushort et htonl pour les ulong
            {
            unsigned char               ihl:4;                 // L'ordre des champs ihl et Version est inversé
            unsigned char               version:4;                     // L'ordre des champs ihl et Version est inversé
            unsigned char               tos;
            unsigned short              length;
            unsigned short              id;
            unsigned short              offset:5;                       // Ajout d'offset2 afin de pouvoir utiliser l'invertion qui se fait de 8 bits en 8 bits et non pas en unsigned short
            unsigned short              flag_mf:1;                     // L'ordre des champs offset et flag est inversé
            unsigned short              flag_df:1;                     // L'ordre des champs offset et flag est inversé
            unsigned short              flag_zero:1;      // L'ordre des champs offset et flag est inversé
            unsigned short              offset2:8;                     // L'ordre des champs offset et flag est inversé
            unsigned char               ttl;
            unsigned char               type;
            unsigned short              checksum;
            unsigned long               ip_source;
            unsigned long               ip_destination;
            };

struct icmp // htons pour les ushort et htonl pour les ulong
            {
            unsigned char               type;
            unsigned char               code;
            unsigned short              checksum;
            unsigned short              id;
            unsigned short              sequence;
            };

struct igmp // htons pour les ushort et htonl pour les ulong
            {
            unsigned char               type:4;                         // L'ordre des champs Type et Version est inversé
            unsigned char               version:4;                     // L'ordre des champs Type et Version est inversé
            unsigned char               reserve;
            unsigned short              checksum;
            unsigned long               ip_destination;
            };

/*
// **********************************
// Ancienne structure TCP
// **********************************
struct tcp // htons pour les ushort et htonl pour les ulong
            {
            unsigned short              port_source;
      unsigned short                    port_destination;
            unsigned long               sequence;
            unsigned long               accuse;
            unsigned short              offset;
            unsigned short              window;
            unsigned short              checksum;
            unsigned short              pointeur;
            };
*/


// **********************************
// Nouvelle structure TCP
// **********************************
struct tcp  // htons pour les ushort et htonl pour les ulong
            { 
            unsigned short              port_source;
      unsigned short                    port_destination;
            unsigned long               sequence;
            unsigned long               accuse;

            unsigned short              reserved:4;       // Reserved est divisé en deux afin d'être directement intégré à la bonne place
            unsigned short              offset:4;
            unsigned short              flag_fin:1;         // L'ordre des champs sont inversé
            unsigned short              flag_syn:1;        // L'ordre des champs sont inversé
            unsigned short              flag_rst:1;         // L'ordre des champs sont inversé
            unsigned short              flag_psh:1;       // L'ordre des champs sont inversé
            unsigned short              flag_ack:1;       // L'ordre des champs sont inversé
            unsigned short              flag_urg:1;        // L'ordre des champs sont inversé
            unsigned short              reserved2:2;

            unsigned short              window;
            unsigned short              checksum;
            unsigned short              pointeur;
            };


struct udp // htons pour les ushort et htonl pour les ulong
            {
            unsigned short              port_source;
            unsigned short              port_destination;
            unsigned short              length;
            unsigned short              checksum;
            };

struct pseudo_entete 
            {  
            unsigned long               ip_source;                               // Adresse ip source
            unsigned long               ip_destination;              // Adresse ip destination
            char                                         mbz;                                        // Champs à 0
            char                                         type;                                        // Type de protocole (6->TCP et 17->UDP)
            unsigned short              length;                          // ( Taille de l'entete Pseudo + Entete TCP ou UDP + Data )
    };

3.2 – LibrairieSocket.cpp

// ********************************************
// Nom : LibrairieSocket.cpp
// Auteur : SebF@frameIP.com.pas.de.spam
// Date de création : 01 Mai 2003
// version : 3.10
// Licence : Cette librairie est libre de toute utilisation.
//           La seule condition existante est de faire référence
//           au site http://www.frameip.com afin de respecter le travail d'autrui.
// ********************************************

// ********************************************************
// Les includes
// ********************************************************
// Il faut ajouter dans les proprités du projet => C++ => Command Line :
// /I "C:\RepPerso\Personnel\Developpement\Projets\LibrairiePcap\Include"
// /I "C:\RepPerso\Personnel\Developpement\Projets\LibrairieSocket"
#include "LibrairieSocket.h"
#include "pcap.h"
#include "packet32.h"
#include "ntddndis.h"

// ********************************************************
// Les fonctions
// ********************************************************
unsigned long resolution_de_nom(bool liberation, char *nom_a_resoudre)
            {
            HOSTENT *structure_nom_de_lhote; // déclare la variable structure_nom_de_lhote de type HOSTENT permetant la recupération du gethostbyname
            WSADATA initialisation_win32;

            // ********************************************************
            // Vérifie si le nom_a_resoudre est déjà une adresse ip
            // ********************************************************
            if (inet_addr(nom_a_resoudre)!=-1)    //Vérifie si nom_de_lhote_distant est un nom ou une IP
                        return(inet_addr(nom_a_resoudre));
            else
                        {
                        // ********************************************************
                        // Initialisation des socket Win32
                        // ********************************************************
                        WSAStartup(MAKEWORD(2,2),&initialisation_win32);

                        // ********************************************************
                        // Résolution du nom d'hote en adresse ip
                        // ********************************************************
                        if (liberation==TRUE)
                                   liberation_du_jeton(); // Rend la main à la fenêtre principale
                        structure_nom_de_lhote=gethostbyname(nom_a_resoudre);
                        if (liberation==TRUE)
                                   liberation_du_jeton(); // Rend la main à la fenêtre principale

                        WSACleanup();
                        if (structure_nom_de_lhote!=0)
                                   return(*((unsigned int*)structure_nom_de_lhote->h_addr_list[0]));
                        else
                                   return(0); // Présent uniquement pour éviter un warning durant la compilation

                        }
            }

struct structure_ip_local recuperation_ip_local(bool liberation)
            {
            struct structure_ip_local renvoi_des_ip_locales;
            char tampon[64];
            struct hostent *informations_recupere;
            struct in_addr *adresse_ip;
            WSADATA initialisation_win32;

            // ********************************************************
            // Initialisation
            // ********************************************************
            WSAStartup(MAKEWORD(2,2),&initialisation_win32);
            renvoi_des_ip_locales.nombre_d_ip_local=0;

            // ********************************************************
            // Récupération du nom
            // ********************************************************
            gethostname(tampon,sizeof(tampon)) ;

            // ********************************************************
            // Récupération de l'IP locale
            // ********************************************************
            informations_recupere=gethostbyname(tampon) ;

            // ********************************************************
            // Quite propement le winsock ouvert avec la commande WSAStartup
            // ********************************************************
            WSACleanup(); //  (A appeller autant de fois qu'il a été ouvert)

            // ********************************************************
            // Renvoi de la liste de toutes les IP locales
            // ********************************************************
            while ( (adresse_ip=(struct in_addr *)*informations_recupere->h_addr_list++) != NULL )
                        {
                        if (liberation==TRUE)
                                   liberation_du_jeton(); // Rend la main à la fenêtre principale
                        strcpy(renvoi_des_ip_locales.adresse_ip_local[renvoi_des_ip_locales.nombre_d_ip_local],inet_ntoa(*adresse_ip));
                        renvoi_des_ip_locales.nombre_d_ip_local++;
                        }

            return(renvoi_des_ip_locales);
            }

unsigned short calcul_du_checksum(bool liberation, unsigned short *data, int taille_de_data)
            {
            unsigned long checksum=0;

            // ********************************************************
            // Complément à 1 de la somme des complément à 1 sur 16 bits
            // ********************************************************
            while(taille_de_data>1)
                        {
                        if (liberation==TRUE)
                                   liberation_du_jeton(); // Rend la main à la fenêtre principale
                        checksum=checksum+*data++;
                        taille_de_data=taille_de_data-sizeof(unsigned short);
                        }
            if(taille_de_data)
                        checksum=checksum+*(unsigned char*)data;
            checksum=(checksum>>16)+(checksum&0xffff);
            checksum=checksum+(checksum>>16);

            return (unsigned short)(~checksum);
            }

unsigned short calcul_du_checksum_ip(bool liberation, struct ipv4 ipv4_tampon)
            {          
            unsigned short checksum;

            // ********************************************************
            // Initialisation du checksum
            // ********************************************************
            ipv4_tampon.checksum=0; // Doit être à 0 pour le calcul

            // ********************************************************
            // Calcul du IP
            // ********************************************************
            checksum=calcul_du_checksum(liberation,(unsigned short *)&ipv4_tampon,sizeof(struct ipv4));
            
            return checksum;
            }

unsigned short calcul_du_checksum_icmp(bool liberation, struct icmp icmp_tampon,char data_tampon[65535],unsigned int taille_de_data_tampon)
            {
            char tampon[65535];
            unsigned short checksum;

            // ********************************************************
            // Initialisation du checksum
            // ********************************************************
            icmp_tampon.checksum=0; // Doit être à 0 pour le calcul

            // ********************************************************
            // Calcul du ICMP
            // ********************************************************
            memcpy(tampon,(unsigned short *)&icmp_tampon,sizeof(struct icmp));
            memcpy(tampon+sizeof(struct icmp),data_tampon,taille_de_data_tampon);
            checksum=calcul_du_checksum(liberation,(unsigned short*)tampon,sizeof(struct icmp)+taille_de_data_tampon);
            
            return(checksum);
            }

unsigned short calcul_du_checksum_igmp(bool liberation, struct igmp igmp_tampon,char data_tampon[65535],unsigned int taille_de_data_tampon)
            {
            char tampon[65535];
            unsigned short checksum;

            // ********************************************************
            // Initialisation du checksum
            // ********************************************************
            igmp_tampon.checksum=0; // Doit être à 0 pour le calcul

            // ********************************************************
            // Calcul du checksum IGMP
            // ********************************************************
            memcpy(tampon,(unsigned short *)&igmp_tampon,sizeof(struct igmp));
            memcpy(tampon+sizeof(struct igmp),data_tampon,taille_de_data_tampon);
            checksum=calcul_du_checksum(liberation,(unsigned short*)tampon,sizeof(struct igmp)+taille_de_data_tampon);
            
            return(checksum);
            }

unsigned short calcul_du_checksum_tcp(bool liberation, unsigned long ip_source_tampon,unsigned long ip_destination_tampon,struct tcp tcp_tampon,char data_tampon[65535],unsigned int taille_de_data_tampon)
            {
            struct pseudo_entete pseudo_tcp;
            char tampon[65535];
            unsigned short checksum;
            
            // ********************************************************
            // Initialisation du checksum
            // ********************************************************
            tcp_tampon.checksum=0; // Doit être à 0 pour le calcul

            // ********************************************************
            // Le calcul du Checksum TCP (Idem à UDP)
            // ********************************************************
            // Le calcul passe par une pseudo entete TCP + l'entete TCP + les Data
            pseudo_tcp.ip_source=ip_source_tampon;
            pseudo_tcp.ip_destination=ip_destination_tampon;
            pseudo_tcp.mbz=0;
            pseudo_tcp.type=IPPROTO_TCP;
            pseudo_tcp.length=htons((unsigned short)(sizeof(struct tcp)+taille_de_data_tampon));
            memcpy(tampon,&pseudo_tcp,sizeof(pseudo_tcp));
            memcpy(tampon+sizeof(pseudo_tcp),&tcp_tampon,sizeof(struct tcp));
            memcpy(tampon+sizeof(pseudo_tcp)+sizeof(struct tcp),data_tampon,taille_de_data_tampon);
            checksum=calcul_du_checksum(liberation,(unsigned short*)tampon,sizeof(pseudo_tcp)+sizeof(struct tcp)+taille_de_data_tampon);

            return(checksum);
            }

unsigned short calcul_du_checksum_udp(bool liberation, unsigned long ip_source_tampon,unsigned long ip_destination_tampon,struct udp udp_tampon,char data_tampon[65535],unsigned int taille_de_data_tampon)
            {
            struct pseudo_entete pseudo_udp;
            char tampon[65535];
            unsigned short checksum;

            // ********************************************************
            // Initialisation du checksum
            // ********************************************************
            udp_tampon.checksum=0; // Doit être à 0 pour le calcul

            // ********************************************************
            // Le calcul du Checksum UDP (Idem à TCP)
            // ********************************************************
            // Le calcul passe par une pseudo entete UDP + l'entete UDP + les Data
            pseudo_udp.ip_source=ip_source_tampon;
            pseudo_udp.ip_destination=ip_destination_tampon;
            pseudo_udp.mbz=0;
            pseudo_udp.type=IPPROTO_UDP;
            pseudo_udp.length=htons((unsigned short)(sizeof(struct udp)+taille_de_data_tampon));
            memcpy(tampon,&pseudo_udp,sizeof(pseudo_udp));
            memcpy(tampon+sizeof(pseudo_udp),&udp_tampon,sizeof(struct udp));
            memcpy(tampon+sizeof(pseudo_udp)+sizeof(struct udp),data_tampon,taille_de_data_tampon);
            checksum=calcul_du_checksum(liberation,(unsigned short*)tampon,sizeof(pseudo_udp)+sizeof(struct udp)+taille_de_data_tampon);

            return(checksum);
            }

char * dimensionnement_de_data_a_envoyer(bool liberation, char data[65535],unsigned int taille_de_data,unsigned int taille_desiree)
             {
            char tampon[65535];
            int i,nombre_de_fois;

            // ********************************************************
            // Test sur la longueur de data afin d'éviter la division par 0
            // ********************************************************
            if (taille_de_data==0)
                        return "";

            // ********************************************************
            // Evite les dépassement de buffer
            // ********************************************************
            if (taille_desiree>65000)
                        taille_desiree=65000;

            // ********************************************************
            // Dimensionne les data
            // ********************************************************
            if(taille_desiree==0)
                        sprintf(tampon,"");
            else
                        {
                        // ********************************************************
                        // Création d'une chaine de 65535 contennant x fois les data_a_envoyer
                        // ********************************************************
                        nombre_de_fois=taille_desiree/taille_de_data;
                        for (i=0;i<nombre_de_fois;i++)
                                   {
                                   memcpy(tampon+i*taille_de_data,data,taille_de_data);
                                   if (liberation==TRUE)
                                               liberation_du_jeton(); // Rend la main à la fenêtre principale
                                   }

                        // ********************************************************
                        // Ajoute les derniers caratères. Exemple : "coucou coucou" il manque couc à la fin si la taille est de 17
                        // ********************************************************
                        if (taille_desiree-(nombre_de_fois*taille_de_data)!=0)
                                   memcpy(tampon+(nombre_de_fois*taille_de_data),data,taille_desiree-(nombre_de_fois*taille_de_data));

                        // ********************************************************
                        // Ajoute un 0 pour terminer la chaine
                        // ********************************************************
                        tampon[taille_desiree]=0;
                        }
            return(tampon);
            }

void liberation_du_jeton(void)
            {
            // **************************************************
            // DoEvents
            // **************************************************
            // Se place dans une boucle et rend la main à la fenetre principale afin de permettre à l'utilisateur de manipuler la fenêtre malgrès une boucle
            // C'est l'équivalent de la fonction DoEvents en VB

            MSG Msg;
            while (PeekMessage(&Msg,NULL,0,0,PM_REMOVE))
                        {
                        TranslateMessage(&Msg);
                        DispatchMessage(&Msg);
                        }
            }

void pause(bool liberation, unsigned int temps_demande)
            {
            bool sortie_de_la_boucle=FALSE;                 // Condition de sortie de la boucle
            LARGE_INTEGER cpu_frequence;                // Fréquence du CPU
            LARGE_INTEGER temps_de_reponse1;       // Nombre de clock CPU
            LARGE_INTEGER temps_de_reponse2;       // Nombre de clock CPU
            double temps_ecoule;                                      // Temps en ms entre réponse 1 et réponse 2

            // **************************************************
            // Initiation de la fréquence du cpu
            // **************************************************
            QueryPerformanceFrequency((LARGE_INTEGER *)&cpu_frequence);

            // **************************************************
            // Réccupération du temps de référence
            // **************************************************
            QueryPerformanceCounter((LARGE_INTEGER *) &temps_de_reponse1);

            // **************************************************
            // Boucle d'attente
            // **************************************************
            while(sortie_de_la_boucle==FALSE)
                        {
                        // **************************************************
                        // Attente pour éviter l'occupation processeur
                        // **************************************************
                        Sleep(1);

                        // **************************************************
                        // Rend la main à la fenêtre principale pour ne pas la bloqué
                        // **************************************************
                        if (liberation==TRUE)
                                   liberation_du_jeton();

                        // **************************************************
                        // Calcul du temps écoulé en ms
                        // **************************************************
                        QueryPerformanceCounter((LARGE_INTEGER *)&temps_de_reponse2);
                        temps_ecoule=((double)((temps_de_reponse2.QuadPart-temps_de_reponse1.QuadPart)*(double)1000.0/(double)cpu_frequence.QuadPart));
            
                        // **************************************************
                        // Vérification du temps écoulé
                        // **************************************************
                        if (temps_ecoule>=temps_demande)
                                   sortie_de_la_boucle=TRUE;
                        }
            }

struct gestion_des_arguments recuperation_des_arguments(bool liberation)
            {
            char * ligne_de_commande;
            struct gestion_des_arguments arguments_tampon;
            unsigned int nombre_d_argument;
            
            // **************************************************
            // Initialisation des variables
            // **************************************************
            nombre_d_argument=0;
            ligne_de_commande=(char *)malloc(65535);
            
            // **************************************************
            // Récupération des arguments sous forme d'un chaine
            // **************************************************
            strcpy(ligne_de_commande,GetCommandLine());

            // **************************************************
            // Extraction du premier argument (le nom et chemain de l'executable)
            // **************************************************
            arguments_tampon.argv[nombre_d_argument]=strtok(ligne_de_commande," ");
            
            // **************************************************
            // Boucle pour extraire tout les autres arguments
            // **************************************************
            while (arguments_tampon.argv[nombre_d_argument]!=NULL)
                        {
                        nombre_d_argument++;
                        arguments_tampon.argv[nombre_d_argument]=strtok(NULL," ");
                        if (liberation==TRUE)
                                   liberation_du_jeton(); // Rend la main à la fenêtre principale
                        }

            // **************************************************
            // Récupère le nombre d'arguments (incluant le nom de l'executable)
            // **************************************************
            arguments_tampon.argc=nombre_d_argument;

            return(arguments_tampon);
            }

DWORD pid_de_la_console_parente(bool liberation)
            {
            DWORD console_pid; // Numéro PID de la fenetre mode console parente
            HWND console_hwnd; // HWND de la fenetre mode console parente

            // **************************************************
            // Trouve le HWND de la console
            // **************************************************
            // Même si il y a plusieur cmd de démarré, FindWindows donne la bonne.
            // Je ne sais pas comment il fait.
            // Une hypothèse est qu'il commence par celle en premier plan
            // Pour tous soucis une fonction officiel existe voir la KB 124103

            if (liberation==TRUE)
                        liberation_du_jeton(); // Rend la main à la fenêtre principale
            console_hwnd=FindWindow("ConsoleWindowClass",NULL);
            if (liberation==TRUE)
                        liberation_du_jeton(); // Rend la main à la fenêtre principale
            
            // **************************************************
            // Convertit un HWND en PID
            // **************************************************
            GetWindowThreadProcessId(console_hwnd,&console_pid);

            return (console_pid);
            }

unsigned long generation_d_une_adresse_ip_aleatoire(int ne_sert_a_rien)
            {
            struct in_addr convertion_ip;
            
            ne_sert_a_rien=0;                       // Utilise la variable pour éviter un Warning
            convertion_ip.S_un.S_un_b.s_b1=(unsigned char)rand()%255+1;
            convertion_ip.S_un.S_un_b.s_b2=(unsigned char)rand()%255+1;
            convertion_ip.S_un.S_un_b.s_b3=(unsigned char)rand()%255+1;
            convertion_ip.S_un.S_un_b.s_b4=(unsigned char)rand()%255+1;

            return(convertion_ip.S_un.S_addr);
            }

unsigned short convertion_offset_control_tcp(int ne_sert_a_rien,unsigned char offset,unsigned char reserved,bool urg,bool ack,bool psh,bool rst ,bool syn,bool fin)
            {
            unsigned short convertion;

            ne_sert_a_rien=0;                       // Utilise la variable pour éviter un Warning

            // << n        décale de n vers la gauche. Ajoute donc n 0 binaire à droite.
            // >> n        décale de n vers la droite. Ajoute donc n 0 binaire à gauche.
            
            // **************************************************
            // Tronque les variables pour s'assurer quelles soient dans leurs ranges
            // **************************************************
            offset=offset<<2; // Offset étant sur 6 bits, je vires les deux bits de gauches
            offset=offset>>2; //Je remet deux 0 à gauche pour revenir au nombre d'origine
            reserved=reserved<<4; // Reserved étant sur 4 bits, je vires les quatres bits de gauche
            reserved=reserved>>4; // Je remet quatre 0 à gauche afin de revenir au nombre d'origine

            // **************************************************
            // Intégration d'Offset
            // **************************************************
            convertion=offset;

            // **************************************************
            // Intégration de Reserved
            // **************************************************
            convertion=convertion<<4;
            convertion=convertion+reserved;

            // **************************************************
            // Intégration des controles
            // **************************************************
            convertion=convertion<<1;
            convertion=convertion+urg;
            convertion=convertion<<1;
            convertion=convertion+ack;
            convertion=convertion<<1;
            convertion=convertion+psh;
            convertion=convertion<<1;
            convertion=convertion+rst;
            convertion=convertion<<1;
            convertion=convertion+syn;
            convertion=convertion<<1;
            convertion=convertion+fin;

            return(htons(convertion));
            }

void gotoxy(short x,short y)
            {
            HANDLE handle_de_la_console;        // Handle correspondant à la sortie du printf
            COORD coordonnees;                                               // Structure contenant les coordonnées x et y

            // **************************************************
            // Initialisation des coordonnées X et Y
            // **************************************************
            coordonnees.X=x;
            coordonnees.Y=y;
    
            // **************************************************
            // Récupère le Handle de la sortie du printf
            // **************************************************
            handle_de_la_console=GetStdHandle(STD_OUTPUT_HANDLE);
    
            // **************************************************
            // Place le pointer à x et à y
            // **************************************************
            SetConsoleCursorPosition(handle_de_la_console,coordonnees);
            }

void clear_screen(void)                           
            {
            HANDLE handle_de_la_console;                                           // Handle correspondant à la sortie du printf
            CONSOLE_SCREEN_BUFFER_INFO info_console;          // Structure récupérant les informations de la console
            DWORD tampon;                                                                                          // Tampon recupère le nombre de caractère écrit pour effacer l'écran (non utilisé) 
            COORD coordonnees={0,0};                                                // Structure contenant les coordonnées x et y

            // **************************************************
            // Récupération des informations concernant la fenetre console
            // **************************************************
            handle_de_la_console=GetStdHandle(STD_OUTPUT_HANDLE);                          // Récupère le Handle de la console (sortie du printf)
            GetConsoleScreenBufferInfo(handle_de_la_console,&info_console); // Récupère les information de la console

            // **************************************************
            // Efface l'écran
            // **************************************************
            FillConsoleOutputCharacter(handle_de_la_console,' ',info_console.dwSize.X*info_console.dwSize.Y,coordonnees,&tampon);

            // **************************************************
            // Place le pointer à x et à y
            // **************************************************
            gotoxy(0,0); // positionne le curseur en haut à gauche de l'écran
            }

char * convertion_ip(int adresse_ip)
            {
            SOCKADDR_IN translation;
            char tampon[65535];

            // ********************************************************
            // Transformation en IP de type xxx.xxx.xxx.xxx
            // ********************************************************
            translation.sin_addr.s_addr=adresse_ip;
            strcpy(tampon,inet_ntoa(translation.sin_addr));

            return (tampon);
            }

char *  conversion_string_hexa(char data[65535],unsigned int taille_de_data)
            {
            char tampon[65535];
            unsigned int i;
            int tempo_non_signe;

            // ********************************************************
            // Test sur la longueur de data afin d'éviter la division par 0
            // ********************************************************
            if (taille_de_data==0)
                        return "";

            // ********************************************************
            // Evite les dépassement de buffer
            // ********************************************************
            if (taille_de_data>65000)
                        taille_de_data=32000;

            // ********************************************************
            // Convertion en Hexa
            // ********************************************************
            for (i=0;i<taille_de_data;i++)
                        {
                        tempo_non_signe=data[i];
                        if (tempo_non_signe<0) // Permet de convertir le nombre de -128;128 en 0;255
                                   tempo_non_signe+=256;
                        sprintf(tampon+i*2,"%.2x",tempo_non_signe); // .2 permet de mettre le 0 des nombres inférieurs à 0F
                        }

            return (tampon);
            }
            
char *  conversion_hexa_string(char data[65535],unsigned int taille_de_data)
            {
            char tampon[65535];
            unsigned int i;
            char a,b,c;

            // ********************************************************
            // Test sur la longueur de data afin d'éviter la division par 0
            // ********************************************************
            if (taille_de_data==0)
                        return "";

            // ********************************************************
            // Passe tout en majuscule
            // ********************************************************
            memcpy(data,strupr(data),taille_de_data);

            // ********************************************************
            // Convertion en Hexa
            // ********************************************************
            for (i=0;i<taille_de_data;i=i+2)
                        {
                        a=data[i];
                        b=data[i+1];

                        c=(a>='0'&&a<='9')*(a-'0')+(a>='A'&&a<='F')*(a-'A'+10);
                        c=c*16;
                        c=c+(b>='0'&&b<='9')*(b-'0')+(b>='A'&&b<='F')*(b-'A'+10);
                        sprintf(tampon+i/2,"%c",c);
                        }

            return (tampon);
            }
            
struct gestion_des_interfaces recuperation_des_interfaces()
            {
            pcap_if_t *liste_des_interfaces;                                                          // Liste des interfaces
            pcap_if_t *liste_des_interfaces_copie;                                    // Copie de la liste des interfaces
    char buffer_d_erreur[PCAP_ERRBUF_SIZE+1];                          // Buffer de l'erreur réccupéré
            struct gestion_des_interfaces interfaces_tampon;          // Structure qui sera renvoyée
            unsigned int nombre_d_interface=0;                                                    // Nombre d'interface présente
            unsigned i;                                                                                                                             // Pour les boucles for

            // ********************************************************
            // Récupération des interfaces
            // ********************************************************
            if(pcap_findalldevs(&liste_des_interfaces,buffer_d_erreur)==-1)
                        interfaces_tampon.nombre=0;
            else
                        {
                        // ********************************************************
                        // Compte le nombre d'interface
                        // ********************************************************
                        liste_des_interfaces_copie=liste_des_interfaces;
                        for(liste_des_interfaces_copie=liste_des_interfaces; liste_des_interfaces_copie; liste_des_interfaces_copie=liste_des_interfaces_copie->next)
                                   nombre_d_interface++;
                        interfaces_tampon.nombre=nombre_d_interface;

                        // ********************************************************
                        // Récupère les informations relatives aux interfaces
                        // ********************************************************
                        liste_des_interfaces_copie=liste_des_interfaces;
                        for (i=0;i<nombre_d_interface;i++)
                                   {
                                   sprintf(interfaces_tampon.description[i],liste_des_interfaces_copie->description);
                                   sprintf(interfaces_tampon.nom[i],liste_des_interfaces_copie->name);
                                   liste_des_interfaces_copie=liste_des_interfaces_copie->next;
                                   }

                        // ********************************************************
                        // Libère les interfaces
                        // ********************************************************
                        pcap_freealldevs(liste_des_interfaces);
                        }

            return(interfaces_tampon);
            }

struct adresse_mac recuperation_de_l_adresse_mac(char nom_de_l_interface_tampon[1000])
            {
            struct adresse_mac adresse_mac_tampon;       // structure contenant l'adresse MAC qui sera renvoyée
            LPADAPTER lpAdapter=0;                                                   // Pointeur d'accès à l'interface
            PPACKET_OID_DATA OidData;                                        // Structure contenant la requête permettant de connaitre l'adresse MAC
            
            // ********************************************************
            // Accède à l'interface
            // ********************************************************
            lpAdapter=PacketOpenAdapter(nom_de_l_interface_tampon);

            // ********************************************************
            // Prépare un buffer à recevoir l'adresse MAC
            // ********************************************************
            // ! J'ai du convertir via la commande (PPACKET_OID_DATA) sinon erreur.
            OidData=(PPACKET_OID_DATA)malloc(6 + sizeof(PACKET_OID_DATA));

            // ********************************************************
            // Récupération de l'adresse MAC
            // ********************************************************
            OidData->Oid=OID_802_3_CURRENT_ADDRESS;
            OidData->Length=6;
            ZeroMemory(OidData->Data,6);
            PacketRequest(lpAdapter,FALSE,OidData);

            // ********************************************************
            // Transfert de l'adresse MAC dans la structure de retour
            // ********************************************************
            adresse_mac_tampon.adresse[0]=(unsigned char)(PCHAR)(OidData->Data)[0];
            adresse_mac_tampon.adresse[1]=(unsigned char)(PCHAR)(OidData->Data)[1];
            adresse_mac_tampon.adresse[2]=(unsigned char)(PCHAR)(OidData->Data)[2];
            adresse_mac_tampon.adresse[3]=(unsigned char)(PCHAR)(OidData->Data)[3];
            adresse_mac_tampon.adresse[4]=(unsigned char)(PCHAR)(OidData->Data)[4];
            adresse_mac_tampon.adresse[5]=(unsigned char)(PCHAR)(OidData->Data)[5];

            // ********************************************************
            // Libération du buffer de reception
            // ********************************************************
            free(OidData);

            // ********************************************************
            // Libération de l'accés à l'interface
            // ********************************************************
            PacketCloseAdapter(lpAdapter);

            return(adresse_mac_tampon);
            }

struct adresse_mac transformation_string_en_mac(char * string)
            {
            unsigned int nombre_d_octet=0;                                             // Compte le nombre d'octets traité dans la chaine de caractère
            char * tampon;                                                                                   // Récupère les différent octets séparé par des -
            bool erreur=false;                                                                               // Permet de vérifier si la chaine à convertir correspond à une adresse MAC
            struct adresse_mac adresse_mac_tampon;                  // Adresse MAC qui sera retournée
            unsigned short octet1,octet2;                                       // Permet de gérer un octet pas deux lettres pour C3 => C et 3
            unsigned int i;                                                                                      // Pour les boucles for

            // ********************************************************
            // Initialisation de adresse_mac_tampon afin d'éviter un warning
            // qui stipule la possibilité d'utilisation sans avoir été initialisé
            // ********************************************************
            adresse_mac_tampon.adresse[0]=0; // J'utilise pas de boucle for, sinon le compilateur m'indique toujours le Warning
            adresse_mac_tampon.adresse[1]=0;
            adresse_mac_tampon.adresse[2]=0;
            adresse_mac_tampon.adresse[3]=0;
            adresse_mac_tampon.adresse[4]=0;
            adresse_mac_tampon.adresse[5]=0;

            // ********************************************************
            // Récupère les caractères avant le "-"
            // ********************************************************
            tampon=strtok(string,"-");

            while (tampon!=NULL)
                        {
                        // ********************************************************
                        // Valide que c'est bien sur 2 octets
                        // ********************************************************
                        if (strlen(tampon)!=2)
                                   erreur=true;
                        else
                                   {
                                   // ********************************************************
                                   // Convertit en majuscule
                                   // ********************************************************
                                   tampon=strupr(tampon);

                                   // ********************************************************
                                   // Compare si c'est entre 0-9 ou A-F
                                   // ********************************************************
                                   if (( ((tampon[0]>=48)&&(tampon[0]<=57)) || ((tampon[0]>=65)&&(tampon[0]<=70)) ) && ( ((tampon[1]>=48)&&(tampon[1]<=57)) || ((tampon[1]>=65)&&(tampon[1]<=70)) ))
                                               {
                                               // ********************************************************
                                               // Réunis les deux caractères et les convertient en leurs valeurs hexa
                                               // ********************************************************
                                               if ((tampon[0]>=48)&&(tampon[0]<=57))
                                                           octet1=16*(tampon[0]-48);
                                               else
                                                           octet1=16*(tampon[0]-48-7); // 7 correspond au nombre de caracteres compris entre le 0 et le A
                                               if ((tampon[1]>=48)&&(tampon[1]<=57))
                                                           octet2=tampon[1]-48;
                                               else
                                                           octet2=tampon[1]-48-7; // 7 correspond au nombre de caracteres compris entre le 0 et le A
                                               adresse_mac_tampon.adresse[nombre_d_octet]=(unsigned char)(octet1+octet2);
                                               }
                                   else
                                               erreur=true;
                                   }

                        // ********************************************************
                        // Incrémente le nombre d'octet traité
                        // ********************************************************
                        nombre_d_octet++;

                        // ********************************************************
                        // Récupère les caractères avant le "-" suivant
                        // ********************************************************
                        tampon=strtok(NULL,"-");
                        }

            // ********************************************************
            // Valide que le nombre d'octet de la chaine était bien 6
            // ********************************************************
            if ((nombre_d_octet!=6)||(erreur==true))
                        for (i=0;i<6;i++)
                                   adresse_mac_tampon.adresse[i]=0;

            // ********************************************************
            // Renvoi l'adresse MAC
            // ********************************************************
            return (adresse_mac_tampon);
            }

struct adresse_mac resolution_arp(char nom_de_l_interface_tampon[1000],bool mode_promiscuite_tampon,char adresse_ip_tampon[16],unsigned int attente_maximum)
            {
            pcap_t *pointeur_interface;                                                                            // Pointeur indiquant l'interface utilisée
            char buffer_d_erreur[PCAP_ERRBUF_SIZE];                                              // Buffer de l'erreur réccupéré
            unsigned int i;                                                                                                             // Pour les boucles for
            struct mac entete_mac;                                                                                   // Entete MAC qui sera emis
            struct arp entete_arp;                                                                                     // Entete ARP qui sera envoyé
            struct adresse_mac adresse_mac_tampon;                                          // Adresse MAC tempo
            struct adresse_mac adresse_mac_de_retour;                           // Adresse MAC qui sera retournée
            structure_ip_local reception_des_ip_locales;               // Structure permettant de récupérer l'adresse IP source
            unsigned char trame_a_envoyer[65535];                                             // Chaine de caratère comprennant les entêtes et la data
            unsigned short taille_de_la_trame_a_envoyer=0;                     // Taille de la trame qui sera emise
            char ip_source[16];                                                                                                    // IP Source
            int resultat_de_l_envoi;                                                                       // Resultat de l'envoi
            const u_char *trame_recue;                                                                            // Chaine contenant la trame recue
            struct pcap_pkthdr *header;
            int compteur=0;                                                                                                                     // Compteur permettant de compter le nombre de comparaison correcte
            int temps_avant_la_boucle;                                                                             // Temps pris avant de rentrer dans la boucle. Ca permettra de connaitre la durée de la boucle.
            bool sortie_de_la_boucle;                                                                              // Condition de sortie de la boucle

            // ********************************************************
            // Initialisation de adresse_mac_tampon afin d'éviter un warning
            // qui stipule la possibilité d'utilisation sans avoir été initialisé
            // ********************************************************
            adresse_mac_de_retour.adresse[0]=0; // J'utilise pas de boucle for, sinon le compilateur m'indique toujours le Warning
            adresse_mac_de_retour.adresse[1]=0;
            adresse_mac_de_retour.adresse[2]=0;
            adresse_mac_de_retour.adresse[3]=0;
            adresse_mac_de_retour.adresse[4]=0;
            adresse_mac_de_retour.adresse[5]=0;

            // ********************************************************
            // Accède à l'interface
            // ********************************************************
            if ((pointeur_interface=pcap_open_live(nom_de_l_interface_tampon,65536,mode_promiscuite_tampon,1000,buffer_d_erreur))!=NULL)
                        {
                        // ********************************************************
                        // Initialisation de l'entête MAC
                        // ********************************************************
                        adresse_mac_tampon=recuperation_de_l_adresse_mac(nom_de_l_interface_tampon);
                        for (i=0;i<6;i++)
                                   {
                                   entete_mac.source[i]=adresse_mac_tampon.adresse[i];
                                   entete_mac.destination[i]=255;
                                   }
                        entete_mac.type=htons(2054);

                        // ********************************************************
                        // Initialisation de l'entête ARP
                        // ********************************************************
                        entete_arp.mac_type=htons(1);
                        entete_arp.protocol_type=htons(2048);
                        entete_arp.mac_taille=6;
                        entete_arp.protocol_taille=4;
                        entete_arp.opocode=htons(1);
                        for (i=0;i<6;i++)
                                   entete_arp.mac_source[i]=entete_mac.source[i];
                        reception_des_ip_locales=recuperation_ip_local(false);
                        strcpy(ip_source,reception_des_ip_locales.adresse_ip_local[0]);
                        entete_arp.ip_source=resolution_de_nom(false,ip_source);
                        for (i=0;i<6;i++)
                                   entete_arp.mac_destination[i]=entete_mac.destination[i];
                        entete_arp.ip_destination=resolution_de_nom(false,adresse_ip_tampon);

                        // ********************************************************
                        // Concatenation des différentes couches
                        // ********************************************************
                        memcpy(trame_a_envoyer,(unsigned short *)&entete_mac,sizeof(struct mac));   
                        memcpy(trame_a_envoyer+14,(unsigned short *)&entete_arp,sizeof(struct arp));
                        taille_de_la_trame_a_envoyer=sizeof(struct mac)+sizeof(struct arp);

                        // ********************************************************
                        // Envoi de la trame
                        // ********************************************************
                        if (pcap_sendpacket(pointeur_interface,trame_a_envoyer,taille_de_la_trame_a_envoyer)== 0)
                                   {
                                   // ********************************************************
                                   // Initialisation avant de rentrer dans la boucle
                                   // ********************************************************
                                   temps_avant_la_boucle=GetTickCount();
                                   sortie_de_la_boucle=false;
                                   for(i=0;i<6;i++)
                                               adresse_mac_de_retour.adresse[i]=0;

                                   // ********************************************************
                                   // Boucle de reception
                                   // ********************************************************
                                   while(sortie_de_la_boucle==false)
                                               {
                                               // ********************************************************
                                               // Se met en attente de recupèrer la prochaine trame. Maximum une seconde
                                               // ********************************************************
                                               resultat_de_l_envoi=pcap_next_ex(pointeur_interface,&header,&trame_recue);
                        
                                               // ********************************************************
                                               // Vérifie si la boucle dure trop longtemps
                                               // ********************************************************
                                               if (GetTickCount()-temps_avant_la_boucle>=1000*attente_maximum)
                                                           sortie_de_la_boucle=true;

                                               // ********************************************************
                                               // Vérifie si il y a une trame recue
                                               // ********************************************************
                                               if (resultat_de_l_envoi!=0)
                                                           {
                                                           compteur=0;

                                                           // ********************************************************
                                                           // Vérification de l'adresse MAC source
                                                           // ********************************************************
                                                           for (i=0;i<6;i++)
                                                                       if (trame_recue[i]==entete_mac.source[i])
                                                                                  compteur++;

                                                           // ********************************************************
                                                           // Vérification de l'Ether Type
                                                           // ********************************************************
                                                           if (trame_recue[12]==8)
                                                                       compteur++;
                                                           if (trame_recue[13]==6)
                                                                       compteur++;

                                                           // ********************************************************
                                                           // Vérification de l'Hardware Type
                                                           // ********************************************************
                                                           if (trame_recue[14]==0)
                                                                       compteur++;
                                                           if (trame_recue[15]==1)
                                                                       compteur++;
                                   
                                                           // ********************************************************
                                                           // Vérification de Protocol Type
                                                           // ********************************************************
                                                           if (trame_recue[16]==8)
                                                                       compteur++;
                                                           if (trame_recue[17]==0)
                                                                       compteur++;

                                                           // ********************************************************
                                                           // Vérification de l'Hardware Size
                                                           // ********************************************************
                                                           if (trame_recue[18]==6)
                                                                       compteur++;

                                                           // ********************************************************
                                                           // Vérification de Protocol Size
                                                           // ********************************************************
                                                           if (trame_recue[19]==4)
                                                                       compteur++;

                                                           // ********************************************************
                                                           // Vérification de Opocode
                                                           // ********************************************************
                                                           if (trame_recue[20]==0)
                                                                       compteur++;
                                                           if (trame_recue[21]==2)
                                                                       compteur++;

                                                           // ********************************************************
                                                           // Vérification de l'adresse MAC source
                                                           // ********************************************************
                                                           for (i=0;i<6;i++)
                                                                       if (trame_recue[i+32]==entete_mac.source[i])
                                                                                  compteur++;

                                                           // ********************************************************
                                                           // Vérification si toutes les comparaisons sont OK
                                                           // ********************************************************
                                                           if (compteur==22)
                                                                       {
                                                                       for(i=0;i<6;i++)
                                                                                  adresse_mac_de_retour.adresse[i]=trame_recue[i+22]; // 22 permet de se décalet pour réccuperer la mac address de l'emetteur
                                                                       sortie_de_la_boucle=true;
                                                                       }

/*
                                                           // ********************************************************
                                                           // Affichage des trames recues
                                                           // ********************************************************
                                                           printf("\n");
                                                           printf("Taille : %d Entete MAC : ",header->len);
                                                           for (i=0;i<header->len;i++)
                                                                       printf("%.2X ",trame_recue[i]);
                                                           printf("\n");
*/
                                                           }
                                               }
                                   }

                        // ********************************************************
                        // Fermeture de l'accès à l'interface
                        // ********************************************************
                        pcap_close(pointeur_interface);           
                        }

            // ********************************************************
            // Renvoi l'adresse MAC trouvée
            // ********************************************************
            return(adresse_mac_de_retour);
            }

void gestion_des_erreurs(unsigned int numero,char * fonction,unsigned int affichage,bool sortie)
            {
            char message[1000]="Error number 000 : Error in the errors engine";

            // ********************************************************
            // Message d'erreur Winsock 1xx
            // ********************************************************
            if (strlwr(fonction)==(char *)"wsastartup")
                        sprintf(message,"Error number 101.%d : Unable to initialize WSAStartup.",numero);
            if (strlwr(fonction)==(char *)"socket")
                        sprintf(message,"Error number 102.%d : Unable to initialize Socket.",numero);
            if (strlwr(fonction)==(char *)"setsockopt")
                        sprintf(message,"Error number 103.%d : Unable to initialize SetSockOpt.",numero);
            if (strlwr(fonction)==(char *)"sendto")
                        switch (WSAGetLastError())
                                   {
                                   case 10004:
                                               sprintf(message,"Error number 112.%d : Unable to send your IP frame, Sorry, but your WinXP SP1 ou SP2 deny all TCP et spoofing IP, WSAGetLastError %d",numero,WSAGetLastError());
                                               break;
                                   case 10013:
                                               sprintf(message,"Error number 113.%d : Unable to send your IP frame, You must be local administrator, WSAGetLastError %d",numero,WSAGetLastError());
                                               break;
                                   default :
                                               sprintf(message,"Error number 111.%d : Unable to send your IP frame, WSAGetLastError %d",numero,WSAGetLastError());
                                               break;
                                   }

            // ********************************************************
            // Message d'erreur Pcap 2xx
            // ********************************************************
            if (strlwr(fonction)==(char *)"pcap_open_live")
                        sprintf(message,"Error number 201.%d : Unable to open your adapter.",numero);
            if (strlwr(fonction)==(char *)"pcap_sendpacket")
                        sprintf(message,"Error number 202.%d : Unable to send your Ethernet frame.",numero);

            // ********************************************************
            // Affichage de l'erreur en printf
            // ********************************************************
            if (affichage==1)
                        printf("\n\n%s\n\n",message);

            // ********************************************************
            // Arrêt du programme
            // ********************************************************
            if (sortie==true)
                        exit(0);
            }