Winsock raw socket ping icmp recv [Résolu]

4aBestWord 4 Messages postés mardi 2 janvier 2007Date d'inscription 13 février 2007 Dernière intervention - 25 janv. 2007 à 17:43 - Dernière réponse : 4aBestWord 4 Messages postés mardi 2 janvier 2007Date d'inscription 13 février 2007 Dernière intervention
- 13 févr. 2007 à 14:30
bonjour,
j'ai repris un code source en c pour faire un un ping icmp en utilisant les raw sockets sous windows (XP). L'envoie du ping fontionne bien par contre je n'arrive pas à obtenir le retour. Le problème vient surement de l'utilisation de la fonction recv mais je ne vois pas le pb. Si quelqu'un veut bien m'éclairer

le code source compte 2 parties prog.c et packets .h :

prog.c :
/*
/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/
/-  Nom : prog.exe                                           -/
/-  Auteur : 4aBestWorld                                     -/
/-  Date : 25/01/2007                                        -/ 
/-  Description :  essai ping                                -/
/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/
*/

/*
Les Includes standards
*/
#include <stdio.h>
#include <winsock2.h>
/*
Les Includes de ce programme
*/
#include "packets.h"

/*
directives du PreProcesseur
*/
#pragma comment(lib, "ws2_32.lib")

/*
fonction checksum
*/
unsigned short in_cksum(u_short * addr, int len)
{
    register int nleft = len;
    register u_short *w = addr;
    register int sum = 0;
    u_short answer = 0;

    while (nleft > 1) {
    sum += *w++;
    nleft -= 2;
    }

    if (nleft == 1) {
    *(u_char *) (&answer) = *(u_char *) w;
    sum += answer;
    }

    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
    answer = ~sum;

    return (answer);
}

/*
Fonction Main
*/

int main(int argc, char *argv[])
{
    WORD wVersionRequested;
    WSADATA WSAData;
    unsigned short packet_size, ip_version, ip_len;    /* Taille de notre paquet, ip version, longueur */
    int retour;
    int socket;            /* Notre Socket */
    int optval = 1;        /* Pour les options */
    struct sockaddr_in sin;    /* Notre structure sockaddr_in */
    struct iphdr *ip;        /* Notre structure ip */
    struct icmphdr *icmp;    /* Notre structure icmp */    char *ptr NULL, packet[32];    /* Notre paquet, 32 sizeof(struct icmphdr) + sizeof(struct iphdr) */
    char buffer[2];
   
    if (argc < 3) {
    //fprintf(stderr, "Usage: %s <source host> <destination host>\n",argv[0]);
    printf("Usage: %s <source host> <destination host>\n",argv[0]);
    exit(-5);
    }

    /* On initialise Winsock 2 */
    wVersionRequested = MAKEWORD(2, 2);
    if (WSAStartup(wVersionRequested, &WSAData) != 0) {
    perror("WSAStartup");
    exit(-2);
    }

    /* Création de notre Raw socket */
    socket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_RAW, NULL, 0, 0);
    if (socket == INVALID_SOCKET) {
    perror("WSASocket");
    WSACleanup();
    exit(-3);
    }

    /* On assigne les bonnes options à notre Raw socket */
    if (setsockopt(socket, IPPROTO_IP, 2, (char *) &optval, sizeof(optval))
    == SOCKET_ERROR) {
    perror("setsockopt");
    WSACleanup();
    exit(-4);
    }

    /* On initialise toutes les données nécéssaires pour la structure IP */

    /* Taille de notre paquet */
    packet_size = sizeof(struct iphdr) + sizeof(struct icmphdr);

    /* On alloue un espace mémoire pour notre structure IP */
    ip = (struct iphdr *) malloc(sizeof(struct iphdr));
    memset(ip, 0x0, sizeof(struct iphdr));

    /* Longueur de l'en tête IP */
    ip_len = sizeof(struct iphdr) / sizeof(unsigned long);

    /* IP Version */
    ip_version = 4;

    /* On remplie la structure IP */
    ip->ip_verlen = (ip_version << 4) | ip_len;
    ip->ip_tos = 0;
    ip->ip_tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmphdr));
    ip->ip_id = 1;
    ip->ip_offset = 0;
    ip->ip_ttl = 255;
    ip->ip_protocol = IPPROTO_ICMP;
    ip->ip_saddr = inet_addr(argv[1]);
    ip->ip_daddr = inet_addr(argv[2]);
    ip->ip_checksum = 0;
    ip->ip_checksum = in_cksum((unsigned short *) ip, sizeof(struct iphdr));    /* Calcul du checksum avec la fonction
                                           déja connu */
    /* Maintenant passons à la structure ICMP */
    /* On alloue de la mémoire pour celle ci */
    icmp = (struct icmphdr *) malloc(sizeof(struct icmphdr));
    memset(icmp, 0x0, sizeof(struct icmphdr));

    /* On la remplie */
    icmp->icmp_type = 8;        /* Type ICMP ECHO REQUEST */
    icmp->icmp_code = 0;
    icmp->icmp_id = (USHORT) GetCurrentProcessId();
    icmp->icmp_seq = (USHORT) GetCurrentProcessId();
    icmp->icmp_checksum = 0;
    icmp->icmp_checksum = in_cksum((unsigned short *) icmp, sizeof(struct icmphdr));

    /* Maintenant on créé notre paquet */
    ZeroMemory(packet, sizeof(packet));
    ptr = packet;
    memcpy(ptr, ip, sizeof(struct iphdr));
    ptr += sizeof(struct iphdr);
    memcpy(ptr, icmp, sizeof(struct icmphdr));
    ptr += sizeof(struct icmphdr);

    /* On rempli notre structure sockaddr_in */
    sin.sin_family = AF_INET;
    sin.sin_addr.S_un.S_addr = inet_addr(argv[2]);

       
    /* Envoye du paquet à destination */
    if (sendto
    (socket, packet, sizeof(packet), 0x0, (struct sockaddr *) &sin,
     sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
    perror("sendto");
    }
    /* reception du paquet retour */
    else {
         retour = recv(socket,buffer,sizeof(buffer),0);
         if ( retour == SOCKET_ERROR){
         printf("recv : %d",WSAGetLastError());             
         }//finduif
    }//finduelse
   
    system("PAUSE");
   
    free(ip);
    free(icmp);
    WSACleanup();
       
  return 0;
}

packets.h :
typedef struct iphdr
{
    unsigned char  ip_verlen;
    unsigned char  ip_tos;          
    unsigned short ip_tot_len;      
    unsigned short ip_id;           
    unsigned short ip_offset;       
    unsigned char  ip_ttl;          
    unsigned char  ip_protocol;     
    unsigned short ip_checksum;     
    unsigned int   ip_saddr;        
    unsigned int   ip_daddr;    
} IPHDR;

typedef struct icmphdr
{
 unsigned char icmp_type;
 unsigned char icmp_code;
 unsigned short icmp_checksum;
 unsigned short icmp_id;
 unsigned short icmp_seq;
 unsigned long  timestamp;
} ICMPHDR;
   
typedef struct opt_packet
{
      char *saddr;
      char *daddr;
      unsigned int icmp_type;
      unsigned int icmp_code;
      unsigned int ttl;
      int nbpackets;
      unsigned int interval;
} OPT_PACKET;

Merci pour votre temps.
Afficher la suite 

Votre réponse

3 réponses

Meilleure réponse
4aBestWord 4 Messages postés mardi 2 janvier 2007Date d'inscription 13 février 2007 Dernière intervention - 13 févr. 2007 à 14:30
3
Merci
J'ai trouve sur ce site un code source déposé par Roswell117 en 2003 qui correspond exactement à  ce que je veux.
A+

Merci 4aBestWord 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 73 internautes ce mois-ci

Commenter la réponse de 4aBestWord
xbabilone 47 Messages postés vendredi 18 février 2005Date d'inscription 7 janvier 2018 Dernière intervention - 26 janv. 2007 à 17:18
0
Merci
Je suis pas un pro mais t'as configurer ton firewall pour laisser passer les paquets.
Si tu essaye ton code entre deux machines test desactive le firewall sur les deux machines.Car souvent les firewalls sont configurer pour ne pas repondre au ping.
Et sinon good luck .
Commenter la réponse de xbabilone
4aBestWord 4 Messages postés mardi 2 janvier 2007Date d'inscription 13 février 2007 Dernière intervention - 27 janv. 2007 à 10:24
0
Merci
J'y ai pensé aussi au début mais j'ai lancé une capture avec WireShark (ancien ethereal). Et en fait je reçois bien le reply.
Je pense que le pb vient du buffer du retour de la fonction recv() ou bien faut-il faire une synchro entre le sendto et le recv. On m'a parlé de la fonction select().

Voila je cherche toujours donc si quelqu'un a une explication ou une piste, il/elle est le/la bienvenue.
Commenter la réponse de 4aBestWord

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.