Bonjour,
je souhaite en apprendre plus sur les réseaux (relativement bas niveaux sous linux) en utilisant SOCK_RAW, et j'ai un probleme, pour u petit programme pour lancer un ping et recevoir le pong.

Le packet n'est pas envoyé et sendto renvoie 0 et en sniffant les entrées/sortie du PC je vois bien la requète et la réponse DNS mais pas la requete ICMP , (la commande ping fonctionne très bien en shell).
Et la reception fonctionne aussi ( j'arive à recvoir le ping d'autre postes)

voici mon code:

ping.h
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
#ifdef WIN32 /*  si vous êtes sous Windows */
 
#include <winsock2.h> 
 
#elif defined (linux) /*  si vous êtes sous Linux */
 
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h> /*  close */
#include <netdb.h> /*  gethostbyname */
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(s) close(s)
#define PORT 8080
#define PCKT_LEN 8192
#define REMOTE "www.google.com"
 
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
typedef struct in_addr IN_ADDR;
typedef struct ipheader IPHEADER;
 
 
typedef struct icmpheader {
	 unsigned char  type;
	 unsigned char  code;
	 unsigned short somme;
} ICMPHEADER;
 
typedef struct icmppingmessage {
	    /*  'En-tete' ICMP */
	  unsigned char  type;
		unsigned char  code;
		unsigned short  somme;
 
							    /*  'Donnees' (definis par le programmeur) */
		char  id; /*  Ce champ nous permettra de reconnaitre notre message */
		char  timestamp; /*  Celui-ci nous permettra de savoir quand ce message a ete envoye */
} ICMPPINGMESSAGE;
 
#define ICMP_ECHO_REQ 8
#define ICMP_ECHO_REPLY 0
 
 
struct ipheader {
	unsigned char      iph_ihl:5,  iph_ver:4;
	unsigned char      iph_tos;
	unsigned short int iph_len;
	unsigned short int iph_ident;
	unsigned char      iph_flag;
	unsigned short int iph_offset;
	unsigned char      iph_ttl;
	unsigned char      iph_protocol;
	unsigned short int iph_chksum;
	unsigned int       iph_sourceip;
	unsigned int       iph_destip;
};
 
 
#else 
 
#error not defined for this platform
 
#endif
ping.c
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "ping.h"
 
struct hostent * resolve_addr(char * name,  unsigned long * p_addr)
{
	    struct hostent * h = gethostbyname(name);
			if (h != NULL)
			       memcpy(p_addr,  h->h_addr_list[0],  sizeof(unsigned long));
 
			return h;
}
 
 
struct hostent * resolve_computer_addr(unsigned long * p_addr)
{
	    struct hostent * h = NULL;
			char computer_name[100];
 
			if (gethostname(computer_name,  sizeof(computer_name)) == 0)
			     h = resolve_addr(computer_name,  p_addr);
 
			return h;
}
 
unsigned short csum(unsigned short *buf,  int nwords)
{       
  unsigned long sum;
  for(sum=0; nwords>0; nwords--)				
	    sum += *buf++;
 
	sum = (sum >> 16) + (sum &0xffff);
	sum += (sum >> 16);											
	return (unsigned short)(~sum);						
}
 
int main(int argc,  char **argv)
{
	SOCKET s = socket(AF_INET,  SOCK_RAW,  IPPROTO_ICMP);
	if(s == INVALID_SOCKET)
	{
	  	  perror("socket()");
				    exit(-1);
	}
 
	int sockopt=1;
	if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, &sockopt, sizeof(sockopt))==SOCKET_ERROR)
	{
			perror("setsockopt() IPPROTO_IP:");
			exit(-1);
	}
 
	struct timeval sockopt2={0};
	sockopt2.tv_sec=10;
	if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO,(char*) &sockopt2, sizeof(sockopt2))==SOCKET_ERROR)
	{
		perror("setsockopt() SOL_SOQUET:");
		exit(-1);
	}
 
	char *buf;
	unsigned int len = sizeof(IPHEADER)+sizeof(ICMPPINGMESSAGE);
	buf=malloc(len);
	if(buf==NULL)
	{
		perror("malloc(): ");
		exit(-1);
	}
 
	unsigned long ip_source;
	unsigned char tmp[4]={78, 122, 225, 103};
	unsigned char tmp2[4]={192., 168, 1, 42};
	if(resolve_computer_addr(&ip_source)==NULL)
	{
		perror("resolve_computer_addr(): ");
		ip_source=(unsigned long) tmp;
	}
 
	unsigned long ip_dest;
	if(resolve_addr(REMOTE, &ip_dest)==NULL)
	{
		perror("resolve_addr(): ");
		ip_dest=(unsigned long) tmp2;
	}
 
	SOCKADDR_IN remote={0};
	int remote_len = (int)sizeof(remote);
	IPHEADER ip;
	ICMPPINGMESSAGE icmp;
 
	ip.iph_ver=4;
	ip.iph_ihl=5;
	ip.iph_tos=0;
	ip.iph_len=htons(len);
	ip.iph_ident=htons(1);
	ip.iph_flag=0;
	ip.iph_offset=0;
	ip.iph_ttl=200;
	ip.iph_protocol=IPPROTO_ICMP;
	ip.iph_chksum=0;
	ip.iph_sourceip=ip_source;
	ip.iph_destip=ip_dest;
 
	ip.iph_chksum=csum((unsigned short*)&ip, sizeof(ip)+1);
 
 
	struct timeval tv;
	icmp.type=ICMP_ECHO_REQ;
	icmp.code=0;
	icmp.somme=0;
	icmp.id=(char)getpid();
	icmp.timestamp=gettimeofday(&tv, NULL);
 
	icmp.somme=csum((unsigned short*)&icmp, sizeof(icmp));
 
	memcpy(buf, &ip,  sizeof(ip));
	memcpy(buf+sizeof(ip), &icmp,  sizeof(icmp));
 
	remote.sin_family=AF_INET;
	remote.sin_addr.s_addr=ip_dest;
 
	printf("Envoie de la requete a : %s avec %hu octet\n", inet_ntoa(remote.sin_addr), len);
 
	int n=0;
	if(n=sendto(s, buf, len, 0, (SOCKADDR*)&remote, sizeof(remote))==SOCKET_ERROR)
	{
		perror("sendto(): ");
		exit(-1);
	}
	printf("taille ,n=%d\n", n);perror("error");
 
	printf("Attente de réponse\n");
 
	if(recvfrom(s, buf, len, 0, (SOCKADDR*)&remote, &remote_len)==SOCKET_ERROR)
	{
		perror("timeout ou recvfrom(): ");
		exit(-1);
	}
 
	struct timeval tv2;
	int ping = gettimeofday(&tv, NULL) - icmp.timestamp;
 
	memset(&ip, 0, sizeof(ip));
	memset(&icmp, 0, sizeof(icmp));
 
	memcpy(&ip, buf, sizeof(ip));
	memcpy(&icmp, buf+(ip.iph_ihl*4), sizeof(icmp));
 
	if(icmp.id!=getpid())
	{
		printf("Paquet different\n");
		exit(-1);
	}
 
	if(icmp.type==ICMP_ECHO_REQ)
		printf("Réponse recu en %lu ms\n",ping );
	else
		printf("Réponse inatendue !\n");
 
	free(buf);
 
	closesocket(s);
	return 0;
}

Merci