/* ***********************IMPORTANT *********************************************
 *  Copyright (C) 2004-2007 Thierry Lagarde <tlagarde@users.sourceforge.net>
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License.
 *
 *
 *                      ********************
 *
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *
 *                      ********************
 *
 *
 * You are highly encouraged to send your changes to <tlagarde@users.sourceforge.net>
 * for possible incorporation into the main distribution.
 * By sending these changes to <tlagarde@users.sourceforge.net>,
 * it is assumed that you are offering <tlagarde@users.sourceforge.net>
 * the unlimited, non-exclusive right to reuse, modify, and relicense the code.
 *
 *
 *                      ********************
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **************************************************************************************/
#include <errno.h>
#include "Scan_Port.h"
#include "Debug.h"
#include "Info.h"
#include "Com/Initialisation_Com.h"
#include "Macro.h"


char      Syn[] = { 0x45, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02, 0x1F, 0xFE, 0x00, 0x00, 0x00, 0x00 };
char      Udp[] = { 0x45, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x26, 0x00, 0x00, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee };

	
#ifndef         __WINDOWS_ENABLE
void Envoie_Trame_Scan_Port (struct Struct_Liste_Equipement *Equip, gint Num_Port, gint Socket, struct sockaddr *sock,struct Struct_Port *Port_Equipement)
#else
void Envoie_Trame_Scan_Port (struct Struct_Liste_Equipement *Equip, gint Num_Port, pcap_t * captureHandle,struct Struct_Port *Port_Equipement)
#endif
{
	ERROR_if (Equip == NULL);
#ifndef         __WINDOWS_ENABLE
	ERROR_if (sock == NULL);
#else
	ERROR_if (captureHandle == NULL);
#endif
	
	bzero (&Equip->PacketScan, sizeof (struct struct_trame));
	usleep (SURCHARGE_EQUIPEMENT);	
	Equip->Id_Ip = (unsigned short) rand_r(&graine_rand_r);//random ();
	Equip->MonNumSeq = (int)  rand_r(&graine_rand_r);//random ();
	Equip->Port = ((unsigned short)  rand_r(&graine_rand_r));//random ());
	Equip->Port = (Equip->Port & 0x0FFF) + 0xF000;
	Equip->MonNumSeq = htonl (Equip->MonNumSeq);

	if (Port_Equipement!=NULL){
		Port_Equipement->Port_Scan = Equip->Port;
		Port_Equipement->MonNumSeq_Scan = Equip->MonNumSeq;
	}
	memcpy (&Equip->PacketScan.Dest_MAC, &Equip->Adresse_MAC, ETH_ALEN);
	memcpy (&Equip->PacketScan.Source_MAC, Mon_Adresse_MAC, ETH_ALEN);
	Equip->PacketScan.Proto = htons (TRAME_IP);
	memcpy (&Equip->PacketScan.Datagramme, Syn, 40);
	Equip->PacketScan.Datagramme[4] = (Equip->Id_Ip >> 8) & 0xFF;
	Equip->PacketScan.Datagramme[5] = Equip->Id_Ip & 0xFF;
	memcpy (&Equip->PacketScan.Datagramme[12], &Mon_Adresse_Ip, IP_ADDR_LEN);
	memcpy (&Equip->PacketScan.Datagramme[16], &Equip->Adresse_Ip, IP_ADDR_LEN);
	ckecksum_r(Equip,&Equip->PacketScan.Datagramme[0], 20, 0);
	Equip->CheckSum_Calc = htons (Equip->CheckSum_Calc);
	memcpy (&Equip->PacketScan.Datagramme[10], &Equip->CheckSum_Calc, 2);
	Equip->PacketScan.Datagramme[20] = (Equip->Port >> 8) & 0xFF;
	Equip->PacketScan.Datagramme[21] = Equip->Port & 0xFF;
	Equip->PacketScan.Datagramme[22] = (Num_Port >> 8) & 0xFF;
	Equip->PacketScan.Datagramme[23] = Num_Port & 0xFF;
	memcpy (&Equip->PacketScan.Datagramme[24], &Equip->MonNumSeq, 4);
	ckecksum_r(Equip,&Equip->PacketScan.Datagramme[12], 24, 26);
	Equip->CheckSum_Calc = htons (Equip->CheckSum_Calc);
	memcpy (&Equip->PacketScan.Datagramme[36], &Equip->CheckSum_Calc, 2);
	Nouveau_Octet_Envoye (54);
	
#ifndef         __WINDOWS_ENABLE
	if ((sendto (Socket, &Equip->PacketScan, 54, 0, sock, sizeof (struct sockaddr))) < 0) {
		if ((errno != EPIPE) && (errno != ESPIPE))
			debug_printf (D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s", strerror (errno));
	}
#else
 	if (pcap_sendpacket(captureHandle,(u_char *) &Equip->PacketScan, 54) != 0)
		debug_printf (D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Error sending the packet: \n", pcap_geterr(captureHandle));
#endif
}

void Cherche_Un_Port_Avec_Etat (struct Struct_Liste_Equipement * Equip, gint Etat, gint *resultat)
{
	ERROR_if (Equip == NULL);
	ERROR_if (resultat == NULL);
	Equip->Nb_Objet = g_list_length (Equip->GList_Port);
	for (Equip->i = 0; Equip->i < Equip->Nb_Objet; Equip->i++) {
		Equip->Port_Equipement = g_list_nth_data (Equip->GList_Port, Equip->i);
		if (Equip->Port_Equipement->Etat_Port == Etat){
			*resultat = Equip->Port_Equipement->Num_Port;
			return;
		}
	}
	*resultat = -1;
	return;
}

void Cherche_Si_Port_Ouvert (struct Struct_Liste_Equipement * Equip, gint Num_Port)
{
	ERROR_if (Equip == NULL);
	Equip->Nb_Objet = g_list_length (Equip->GList_Port);
	for (Equip->i = 0; Equip->i < Equip->Nb_Objet; Equip->i++) {
		Equip->Port_Equipement = g_list_nth_data (Equip->GList_Port, Equip->i);
		if (Equip->Port_Equipement->Num_Port == Num_Port){
			Equip->Resultat_Test_Port_Ouvert = (Equip->Port_Equipement->Etat_Port == OUVERT);
			return;
		}
	}
	Equip->Resultat_Test_Port_Ouvert = FALSE;
	return;	
}


struct Struct_Port *Recupere_Pointeur_Port_Glist (struct Struct_Liste_Equipement *Equipement, gint Num_Port)
{
	struct Struct_Port *Port_Equipement = NULL;
	gint      Nb_Objet_Liste, i;

	ERROR_if (Equipement == NULL);
	Nb_Objet_Liste = g_list_length (Equipement->GList_Port);
	for (i = 0; i < Nb_Objet_Liste; i++) {
		Port_Equipement = g_list_nth_data (Equipement->GList_Port, i);
		if (Port_Equipement->Num_Port == Num_Port)
			return Port_Equipement;
	}
	return NULL;
}

void Modifie_Etat_Port_Equipement (struct Struct_Liste_Equipement *Equipement, gint Num_Port,gint Num_Port_D, gint Nouvelle_Etat,unsigned int Ip_MonNum,unsigned char Flags)
{
	struct Struct_Port *Port_Equipement = NULL;
	struct struct_Retour_Rachaichir_Liste_Ports Message;
	gchar	 *Texte = NULL, *cEtat = NULL;
	gint      Nb_Objet_Liste, i;

	ERROR_if (Equipement == NULL);
	i = 0;
	Nb_Objet_Liste = g_list_length (Equipement->GList_Port);
	while (i < Nb_Objet_Liste) {
		Port_Equipement = g_list_nth_data (Equipement->GList_Port, i);
		if (Port_Equipement->Num_Port == Num_Port) {
		
			if ((Equipement->Scan_Port_En_Cours) && (Num_Port_D == Port_Equipement->Port_Scan)
				&& (htonl(Ip_MonNum) == htonl(Port_Equipement->MonNumSeq_Scan)+1)){
				
#ifdef __LOG_ENABLE
					if ((Nouvelle_Etat == OUVERT) && (Port_Equipement->Etat_Port !=OUVERT) 
						|| (Nouvelle_Etat == FERMER) &&   (Port_Equipement->Etat_Port == OUVERT)){
						switch (Nouvelle_Etat){
							case OUVERT :
									cEtat = "OUVERT";
									break;
							case FERMER :
									cEtat = "FERMER";
									break;
							default :
									cEtat = "UNKOWN";
						}
						Texte = g_strdup_printf("[LOG] [%s](%s:%d): Etat du port %d = [%s]   Ack_number[0x%08X]  Flags[0x%02X]\n",__FILE__, __PRETTY_FUNCTION__, __LINE__,Num_Port,cEtat,htonl(Ip_MonNum),Flags);
						Log_Equipement(Equipement,Texte);
						MYFREE(Texte);
					}
#endif
					Port_Equipement->Etat_Port = Nouvelle_Etat;
					Port_Equipement->Flags = Flags;
			}
			
		
			if ((!Equipement->Scan_Port_En_Cours) && (Nouvelle_Etat == OUVERT)) {
				Port_Equipement->Etat_Port = Nouvelle_Etat;
				Port_Equipement->Compteur_Notification = 0;
				if (Port_Equipement->Alerte_Port_Active) {
					bzero (&Message, sizeof (struct struct_Retour_Rachaichir_Liste_Ports));
					Message.ID_Reseau = Info_Demarrage.ID_Reseau;
					memcpy (Message.ID_Equipement, Equipement->ID_Equipement, MAC_ADDR_LEN + IP_ADDR_LEN + 1);
					Message.Num_Port = Num_Port;
					Message.Etat_Port = TRUE;
					time (&Port_Equipement->Derniere_Modification_Etat_Port);
					Message.Derniere_Modification_Etat_Port = Port_Equipement->Derniere_Modification_Etat_Port;
					Communication_Envoie_Donnee (RETOUR_RAFRAICHIR_LISTE_PORTS, (gpointer *) & Message, sizeof (Message));
					Port_Equipement->Alerte_Port_Active = FALSE;
				}
			}
			return;
		}
		i++;
	}
}

void Initialisation_Liste_Port_TCP_Equipement (struct Struct_Liste_Equipement *Equip)
{
	ERROR_if (Equip == NULL);
	Equip->Nb_Objet = g_list_length (Equip->GList_Port);
	for (Equip->i = 0; Equip->i < Equip->Nb_Objet; Equip->i++) {
		Equip->Port_Equipement = g_list_nth_data (Equip->GList_Port, Equip->i);
		Equip->Port_Equipement->Etat_Port = FIREWALLED;
	}
}

void Test_Retour_Port_Equipement (struct Struct_Liste_Equipement *Equip)
{
	ERROR_if (Equip == NULL);
	Equip->Nb_Objet = g_list_length (Equip->GList_Port);
	for (Equip->i = 0; Equip->i < Equip->Nb_Objet; Equip->i++) {
		Equip->Port_Equipement = g_list_nth_data (Equip->GList_Port, Equip->i);
		if (Equip->Port_Equipement->Etat_Port == FIREWALLED) {
			Equip->Test_Retour_Port = FALSE;
			return;
		}
	}
	Equip->Test_Retour_Port = TRUE;
	return;
}


void Scanne_Local_Equipement (struct Struct_Liste_Equipement *Equip)
{
	ERROR_if (Equip == NULL);
	Initialisation_Liste_Port_TCP_Equipement (Equip);
	Equip->Nb_Objet = g_list_length (Equip->GList_Port);
	for (Equip->i = 0; Equip->i < Equip->Nb_Objet; Equip->i++) {
		Equip->Port_Equipement = g_list_nth_data (Equip->GList_Port, Equip->i);
#ifndef         __WINDOWS_ENABLE
		if ((Equip->IdSocket = Connection_Equipement ("127.0.0.1",NULL, Equip->Port_Equipement->Num_Port, 1, 0, TRUE)) != -1) {
#else
		if ((Equip->IdSocket = Connection_Equipement ("127.0.0.1",NULL, Equip->Port_Equipement->Num_Port, 1, 20, FALSE)) != -1) {
#endif
			Equip->Port_Equipement->Etat_Port = OUVERT;
			if (close_control (Equip->IdSocket) < 0)
				debug_printf (D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s\nSocket ouvert[%d]  Thread[%d][%d]\n Nb equipement (%d)", strerror (errno), Nb_Socket_Ouverte, Info_Demarrage.Nb_Thread_Max, Info_Demarrage.Nb_Thread_Max - Valeur_Semaphore (&Semaphore_Thread_Scan), g_list_length (GList_Equipement));
		}
		else
			Equip->Port_Equipement->Etat_Port = FERMER;
	}
}

void Scanne_Toutes_Les_Ports_TCP (struct Struct_Liste_Equipement *Equip){
	
	ERROR_if (Equip == NULL);
	if (memcmp (Equip->ID_Equipement, Mon_Adresse_MAC, MAC_ADDR_LEN) == 0) {
		Scanne_Local_Equipement (Equip);
		return;
	}

	Initialisation_Liste_Port_TCP_Equipement (Equip);	
   
#ifndef         __WINDOWS_ENABLE
	strcpy (Equip->sock.sa_data, Info_Demarrage.Interface);
	Equip->sock.sa_family = AF_INET;
	if ((Equip->IdSocket = socket_control (AF_INET, SOCK_PACKET, htons (ETH_P_ALL))) < 0)
		debug_printf (D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s\nSocket ouvert[%d]  Thread[%d][%d]\n Nb equipement (%d)", strerror (errno), Nb_Socket_Ouverte, Info_Demarrage.Nb_Thread_Max, Info_Demarrage.Nb_Thread_Max - Valeur_Semaphore (&Semaphore_Thread_Scan), g_list_length (GList_Equipement));
#else
	if ( (Equip->captureHandle = pcap_open(Info_Demarrage.nom, 65535, PCAP_OPENFLAG_PROMISCUOUS, 1, NULL, Equip->errbuf ) ) == NULL)
		debug_printf (D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Unable to open the adapter. %s is not supported by WinPcap\n", Info_Demarrage.nom);
#endif
	Equip->Tentative = 0;	
	Equip->Nb_Objet = g_list_length (Equip->GList_Port);
	do {
		for (Equip->i = 0; Equip->i < Equip->Nb_Objet; Equip->i++) {
			Equip->Port_Equipement = g_list_nth_data (Equip->GList_Port, Equip->i);
			if (Equip->Port_Equipement->Etat_Port == FIREWALLED)
#ifndef         __WINDOWS_ENABLE
				Envoie_Trame_Scan_Port (Equip, Equip->Port_Equipement->Num_Port, Equip->IdSocket, &Equip->sock,Equip->Port_Equipement);
#else
				Envoie_Trame_Scan_Port (Equip, Equip->Port_Equipement->Num_Port, Equip->captureHandle,Equip->Port_Equipement);
#endif
		}
		if ((!Info_Demarrage.Normal_Mode) && (Equip->Tentative == 2))
			break;
		
		switch (Equip->Tentative) {
		    case 0:
			    sleep (1);
			    break;
		    case 1:
			    debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Tentative 2");
			    sleep (1);
			    break;
		    case 2:
			    debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Tentative 3");
			    sleep (2);
			    break;
		    case 3:
			    debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Tentative 4");
			    sleep (3);
			    break;
		    case 4:
			    debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Tentative 5");
			    sleep (4);
			    break;
		    case 5:
			    debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Attend reponse");
			    sleep (4);
			    break;
		}
		Equip->Tentative++;
		Test_Retour_Port_Equipement (Equip);
	}
	while (!(Equip->Test_Retour_Port) && (Equip->Tentative != 6));
	debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Scanne port fini");
#ifndef         __WINDOWS_ENABLE
	if (close_control (Equip->IdSocket) < 0)
		debug_printf (D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s\nSocket ouvert[%d]  Thread[%d][%d]\n Nb equipement (%d)", strerror (errno), Nb_Socket_Ouverte, Info_Demarrage.Nb_Thread_Max, Info_Demarrage.Nb_Thread_Max - Valeur_Semaphore (&Semaphore_Thread_Scan), g_list_length (GList_Equipement));
#else
	pcap_close(Equip->captureHandle);
#endif
}




struct Struct_Liste_Port_UDP Liste_Port_UDP[] = {
	{DHCPC,68},
	{SVRLOC,427},
	{LISTENER,1025},
	{UPNP,1900},
	{SIP, 5060},
	{ZEROCONF,5353}	
};

void Initialisation_Liste_Port_UDP_Equipement (struct Struct_Liste_Equipement *Equip)
{
	ERROR_if (Equip == NULL);
	for (Equip->i = 0; Equip->i < NB_PORT_UDP; Equip->i++) {
		Equip->Liste_Etat_Udp[Equip->i] = UNKOWN_UDP;
	}
}

void Test_Retour_Port_UDP_Equipement (struct Struct_Liste_Equipement *Equip)
{
	ERROR_if (Equip == NULL);
	for (Equip->i = 0; Equip->i < NB_PORT_UDP; Equip->i++) {
		if (Equip->Liste_Etat_Udp[Equip->i] == UNKOWN_UDP) {
			debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Toujours pas de reponse  port %d", Liste_Port_UDP[Equip->i].Num_Port_UDP);
			Equip->Test_Retour_Port = FALSE;
			return;
		}
	}
	Equip->Test_Retour_Port = TRUE;
	return;
}

void Modifie_Etat_Port_UDP_Equipement (struct Struct_Liste_Equipement *Equip, gint Num_Port, gint Nouvelle_Etat)
{
	struct Struct_Port *Port_Equipement = NULL;
	struct struct_Retour_Rachaichir_Liste_Ports Message;
	gchar *cEtat = NULL, *Texte = NULL;
	gint      Nb_Objet_Liste, i;

	ERROR_if (Equip == NULL);
	for (Equip->i = 0; Equip->i < NB_PORT_UDP; Equip->i++) {
		if (Liste_Port_UDP[Equip->i].Num_Port_UDP == Num_Port) {
			Equip->Liste_Etat_Udp[Equip->i] = Nouvelle_Etat;
			switch (Nouvelle_Etat){
						case FERMER_UDP :
							cEtat = "FERMER_UDP";
							break;
						default :
							cEtat = "UNKOWN";
			}
#ifdef __LOG_ENABLE
			Texte = g_strdup_printf("[LOG] [%s](%s:%d): Etat du port %d = [%s]\n",__FILE__, __PRETTY_FUNCTION__, __LINE__,Num_Port,cEtat);
			Log_Equipement(Equip,Texte);
			MYFREE(Texte);
#endif
			return;
		}
	}
	debug_printf (D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Port %d Inconnu", Num_Port);
}

gboolean Traitement_Port_UDP_Fermer (struct Struct_Liste_Equipement *Equipement, struct struct_trame *Packet, unsigned char Taille_Trame, unsigned short Taille_Ip, unsigned char Type_ICMP, unsigned char Code_ICMP)
{
	unsigned short Icmp_Id, Icmp_Seq, Port_Destination, Port_Source, Id_Ip;
	gint      Id_Reponse_Trame;

	ERROR_if (Equipement == NULL);
	ERROR_if (Packet == NULL);

	if (Equipement->Scanne_Port_En_Cours) {
		Id_Reponse_Trame = 0;
		if ((Type_ICMP == DESTINATION_UNREACHABLE) && (Code_ICMP == PORT_UNREACHABLE)) {
			memcpy (&Id_Ip, &Packet->Datagramme[Taille_Ip + 12], 2);
			Id_Ip = htons (Id_Ip);
			memcpy (&Port_Source, &Packet->Datagramme[Taille_Ip + 28], 2);
			Port_Source = htons (Port_Source);
			memcpy (&Port_Destination, &Packet->Datagramme[Taille_Ip + 30], 2);
			Port_Destination = htons (Port_Destination);
			Modifie_Etat_Port_UDP_Equipement(Equipement,Port_Destination,FERMER_UDP);
			Nouveau_Octet_Recu (Taille_Trame);
		}
	}
	return FALSE;
}


#ifndef         __WINDOWS_ENABLE
void Envoie_Trame_Scan_Port_UDP (struct Struct_Liste_Equipement *Equip, gint Num_Port, gint Socket, struct sockaddr *sock)
#else
void Envoie_Trame_Scan_Port_UDP (struct Struct_Liste_Equipement *Equip, gint Num_Port, pcap_t * captureHandle)
#endif
{
	ERROR_if (Equip == NULL);
	usleep (SURCHARGE_EQUIPEMENT);	
	bzero (&Equip->PacketScan, sizeof (struct struct_trame));
	Equip->Id_Ip = (unsigned short) rand_r(&graine_rand_r);//random ();
	Equip->Port = ((unsigned short) rand_r(&graine_rand_r));//random ());
	Equip->Port = (Equip->Port & 0x0FFF) + 0xF000;
	debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Envoie UDP (%d)   ID(%02X)  PORT(%d)", Num_Port,Equip->Id_Ip, Equip->Port);

	memcpy (&Equip->PacketScan.Dest_MAC, &Equip->Adresse_MAC, ETH_ALEN);
	memcpy (&Equip->PacketScan.Source_MAC, Mon_Adresse_MAC, ETH_ALEN);
	Equip->PacketScan.Proto = htons (TRAME_IP);
	memcpy (&Equip->PacketScan.Datagramme,Udp , 58);
	Equip->PacketScan.Datagramme[4] = (Equip->Id_Ip >> 8) & 0xFF;
	Equip->PacketScan.Datagramme[5] = Equip->Id_Ip & 0xFF;
	memcpy (&Equip->PacketScan.Datagramme[12], &Mon_Adresse_Ip, IP_ADDR_LEN);
	memcpy (&Equip->PacketScan.Datagramme[16], &Equip->Adresse_Ip, IP_ADDR_LEN);
	ckecksum_r(Equip,&Equip->PacketScan.Datagramme[0], 20, 0);
	Equip->CheckSum_Calc = htons (Equip->CheckSum_Calc);
	memcpy (&Equip->PacketScan.Datagramme[10], &Equip->CheckSum_Calc, 2);
	Equip->PacketScan.Datagramme[20] = (Equip->Port >> 8) & 0xFF;
	Equip->PacketScan.Datagramme[21] = Equip->Port & 0xFF;
	Equip->PacketScan.Datagramme[22] = (Num_Port >> 8) & 0xFF;
	Equip->PacketScan.Datagramme[23] = Num_Port & 0xFF;
	ckecksum_r(Equip,&Equip->PacketScan.Datagramme[12], 46, 38 + 17);
	Equip->CheckSum_Calc = htons (Equip->CheckSum_Calc);
	memcpy (&Equip->PacketScan.Datagramme[26], &Equip->CheckSum_Calc, 2);
	
	Nouveau_Octet_Envoye (72);
#ifndef         __WINDOWS_ENABLE
	if ((sendto (Socket, &Equip->PacketScan, 72, 0, sock, sizeof (struct sockaddr))) < 0) {
		if ((errno != EPIPE) && (errno != ESPIPE))
			debug_printf (D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s", strerror (errno));
	}
#else
	if (pcap_sendpacket(captureHandle,(u_char *) &Equip->PacketScan, 72) != 0)
		debug_printf (D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Error sending the packet: \n", pcap_geterr(captureHandle));
#endif
}

void Scanne_Toutes_Les_Ports_UDP (struct Struct_Liste_Equipement *Equip){
	
	ERROR_if (Equip == NULL);
	if (memcmp (Equip->ID_Equipement, Mon_Adresse_MAC, MAC_ADDR_LEN) == 0)
		return;
		

	Initialisation_Liste_Port_UDP_Equipement (Equip);
	
	Equip->Scanne_Port_En_Cours = TRUE;
   
#ifndef         __WINDOWS_ENABLE
	strcpy (Equip->sock.sa_data, Info_Demarrage.Interface);
	Equip->sock.sa_family = AF_INET;
	if ((Equip->IdSocket = socket_control (AF_INET, SOCK_PACKET, htons (ETH_P_ALL))) < 0)
		debug_printf (D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s\nSocket ouvert[%d]  Thread[%d][%d]\n Nb equipement (%d)", strerror (errno), Nb_Socket_Ouverte, Info_Demarrage.Nb_Thread_Max, Info_Demarrage.Nb_Thread_Max - Valeur_Semaphore (&Semaphore_Thread_Scan), g_list_length (GList_Equipement));
#else
	if ( (Equip->captureHandle = pcap_open(Info_Demarrage.nom, 65535, PCAP_OPENFLAG_PROMISCUOUS, 1, NULL, Equip->errbuf ) ) == NULL)
		debug_printf (D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Unable to open the adapter. %s is not supported by WinPcap\n", Info_Demarrage.nom);
#endif
	Equip->Tentative = 0;	
	Equip->Nb_Objet = g_list_length (Equip->GList_Port);
	do {
		for (Equip->i = 0; Equip->i < NB_PORT_UDP; Equip->i++) {
			if (Equip->Liste_Etat_Udp[Equip->i] == UNKOWN_UDP) {
#ifndef         __WINDOWS_ENABLE
				Envoie_Trame_Scan_Port_UDP (Equip, Liste_Port_UDP[Equip->i].Num_Port_UDP, Equip->IdSocket, &Equip->sock);
#else
				Envoie_Trame_Scan_Port_UDP (Equip, Liste_Port_UDP[Equip->i].Num_Port_UDP, Equip->captureHandle);
#endif
				if (Equip->Tentative>=1)
					sleep(1); 
			}
		}
		switch (Equip->Tentative) {
		    case 0:
			    sleep (1);
			    break;
		    case 1:
			    debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Tentative 2");
			    sleep (1);
			    break;
		}
		Equip->Tentative++;
		Test_Retour_Port_UDP_Equipement (Equip);
	}
	while (!(Equip->Test_Retour_Port) && (Equip->Tentative != 2));
		
	debug_printf (D_INFO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Scanne port UDP fini");
#ifndef         __WINDOWS_ENABLE
	if (close_control (Equip->IdSocket) < 0)
		debug_printf (D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "%s\nSocket ouvert[%d]  Thread[%d][%d]\n Nb equipement (%d)", strerror (errno), Nb_Socket_Ouverte, Info_Demarrage.Nb_Thread_Max, Info_Demarrage.Nb_Thread_Max - Valeur_Semaphore (&Semaphore_Thread_Scan), g_list_length (GList_Equipement));
#else
	pcap_close(Equip->captureHandle);
#endif
	Equip->Scanne_Port_En_Cours = FALSE;
}


void Creer_Liste_Port_Equipement (struct Struct_Liste_Equipement *Equipement)
{
	struct Struct_Port *Port_Equipement = NULL;
	struct struct_Liste_Port *Port = NULL;
	gint      Nb_Objet_Liste, i;

	ERROR_if (Equipement == NULL);
	Nb_Objet_Liste = g_list_length (GList_Port);
	for (i = 0; i < Nb_Objet_Liste; i++) {
		Port_Equipement = NULL;
		Port = g_list_nth_data (GList_Port, i);
		MALLOC(Port_Equipement,sizeof (struct Struct_Port));
		Port_Equipement->Num_Port = Port->Num_Port;
		Port_Equipement->Notification = FALSE;
		Port_Equipement->Niveau_Notification = NOTIFICATION_STANDARD;
		Port_Equipement->Etat_Port = FIREWALLED;
		Port_Equipement->Alerte_Port_Active = FALSE;
		Port_Equipement->Derniere_Modification_Etat_Port = 0;
		Port_Equipement->Compteur_Notification = 0;
		Port_Equipement->Port_Scan = 0;
		Port_Equipement->MonNumSeq_Scan = 0;
		G_LIST_APPEND (Equipement->GList_Port, Port_Equipement);
	}
}


void Ajout_Un_Port (gpointer * Donnee)
{
	struct struct_Liste_Port *Port = NULL, *Donnee_Port = (struct struct_Liste_Port *) Donnee;

	ERROR_if (Donnee == NULL);
	MALLOC(Port,sizeof (struct struct_Liste_Port));
	Port->Num_Port = Donnee_Port->Num_Port;
	Port->Serveur = Donnee_Port->Serveur;
	G_LIST_APPEND (GList_Port, Port);
}

void Initialisation_Liste_port (void)
{
	GList_Port = NULL;
}
