Bonjour à tous !

Voilà mon problème, dans une de mes applications j'ai besoin de savoir si un équipement en face est présent ou non sur le réseau.
Comme je ne peux pas utiliser l'appel systeme system(ping x.x.x.x) , j'ai refait la fonction ping en C (gestion de l'ICMP etc... etc...).

Voilà mon code (sous RTAI mais cela reste trés lisible) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
 
int ping(char *AdresseAPinger)
{
	char				*Paquet;			// Paquet que l'on enverra : le ping
	char				*Buffer;			// Buffer de reception contenant la réponse
	struct	icmp		*HeaderICMP;		// Header contenant les paramètre IPs encapsulant l'header ICMP
	struct	ip			*HeaderIP;			// Header contenant les paramètres ICMP : ECHO_REQUEST etc...
	struct	sockaddr_in	stMachineAPinger;
	struct	sockaddr_in	stMachineQuiPing;
	int					Result 	 = 0;
	int					Longueur = 0;
	int					Socket   = 0;
	int					OptVal   = 0;
 
	// Allocation dynamique du paquet envoyé et du buffer de reception
	Paquet = (char *)malloc(sizeof(struct icmp) + sizeof(struct ip));
	Buffer = (char *)malloc(sizeof(struct icmp) + sizeof(struct ip));
 
	// Association des headers dans le paquet que l'on enverra 
	HeaderIP 	= (struct ip *) Paquet; 
    HeaderICMP	= (struct icmp *) (Paquet + sizeof(HeaderIP)); 
 
	// Remplissage des structures qui gerent les machines : demandantes et répondantes
	stMachineAPinger.sin_family 		= AF_INET;
	stMachineAPinger.sin_addr.s_addr	= inet_addr(AdresseAPinger); 
	stMachineQuiPing.sin_family			= AF_INET;
	stMachineQuiPing.sin_addr.s_addr	= INADDR_ANY;	// Adresse de la machine qui pingue
 
	// Remplissage du header du protocole IP
	rt_printk("Remplissage IP header...\n");
	HeaderIP->ip_hl   	= 5; 									// Longueur de l'en-tête
	HeaderIP->ip_v 		= 4; 									// IPv4 
	HeaderIP->ip_tos   	= 0; 									// Type de service
    HeaderIP->ip_len 	= sizeof(HeaderIP) + sizeof(HeaderICMP);// Longueur total du paquet IP
    HeaderIP->ip_id     = htons(getuid()); 						// Identificateur
    HeaderIP->ip_ttl    = 255;									// Temps de vie 
    HeaderIP->ip_src    = stMachineQuiPing.sin_addr;			// Adresse de la machine qui veut pinguer
    HeaderIP->ip_dst    = stMachineAPinger.sin_addr;			// Adresse de la mahcine qui repondra... ou pas
 
	// Ouverture du socket en mode RAW
	rt_printk("Ouverture Socket...\n");
	Socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
	if(Socket == -1)
	{
		rt_printk("Ping : Erreur socket !!\n");
		return -1;
	}
 
	// Changement des options du socket pour manipuler le datagramme IP
	rt_printk("Changement options Socket...\n");
	Result = setsockopt(Socket, IPPROTO_IP, IP_HDRINCL, &OptVal, sizeof(int)); 
	if(Socket == -1)
	{
		rt_printk("Ping : Erreur setup socket !!\n");
		return -1;
	}
 
	// Remplissage du header du protocole ICMP
	rt_printk("Replissage ICMP header...\n");
	HeaderICMP->icmp_type 	= ICMP_ECHO; 			// Type de message ICMP : Echo request 
	HeaderICMP->icmp_code 	= 0; 					// Code du message (0 pour nous)
	HeaderICMP->icmp_cksum 	= 0;
	// Calcul du checksum pour le datagramme ICMP
	HeaderICMP->icmp_cksum 	= in_cksum((unsigned short *)HeaderICMP, sizeof(HeaderICMP));
 
	// Calcul du checksum du datagramme IP précédent qui encapsule celui en ICMP
	HeaderIP->ip_sum = in_cksum((unsigned short *)HeaderIP, sizeof(HeaderIP));
 
	// Envois de la trame IP sur le reseau
	rt_printk("Envois du ping...\n");
	Result = sendto(Socket, Paquet, HeaderIP->ip_len, 0, (struct sockaddr*)&stMachineAPinger, sizeof(struct sockaddr));
	if(Result != HeaderIP->ip_len)
	{
		rt_printk("Ping : Erreur envois -> longueur envoyee != longueur a envoyer");
		return -1;	
	}
 
	// Reception de la réponse... ou non
	rt_printk("Reception du ping..."); 
	Longueur = sizeof(struct sockaddr);
	Result = recvfrom(Socket, Buffer, (sizeof(HeaderIP) + sizeof(HeaderICMP)), 0, (struct sockaddr*)&stMachineAPinger, &Longueur);
	if(Result == HeaderIP->ip_len)
	{
		rt_printk("ok\n");
		free(Paquet);
		free(Buffer);
		return 1;	// Le ping c'est correctement passé, la machine distante à bien répondue
	}
	else
	{
	    rt_printk("no\n");
	    free(Paquet);
		free(Buffer);
	    return -1;
	}
}
Le soucis c'est que lorsque j'exécute mon programme, j'obtient ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
 
$ ./Ping
Remplissage IP header...
Ouverture Socket...
Changement options Socket...
Replissage ICMP hedaer...
Envois du ping...
Reception du ping...
D'aprés ce résultat, on dirait que le blocage se fait au niveau du recvfrom.
Lorsque je scan ma connexion avec ethreal j'obtiens une entrée sur le protocole ICMP :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
 
Internet Control Message Protocol :
   Type : 69 (Obsolete or malformed)
   Code : 0
   CRC : Incorrect
...
Auriez vous une idée d'où cela pourrait provenir ?

Merci de votre aide
Romain

edit : ortho