IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

mapping de donnees "a plat" vers structure ipv6


Sujet :

Réseau C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Par défaut mapping de donnees "a plat" vers structure ipv6
    Bonjour a tous,

    J'ai besoin d'ecouter et de parser des trames IPv6 pour un besoin particulier. J'utilise la libpcap pour sniffer les paquets et pas de soucis de ce cote la. Mon probleme, c'est lorsque j'essaie de mapper le packet renvoye par pcap_next vers ma structure ipv6. Je n'arrive pas a mettre les bons entetes dans les bons champs de ma structure. C'est sans doute une erreur relativement simple ou une incomprehension de ma part. Voici les extraits de codes:

    ip6.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
     
    #define ETHER_ADDR_LEN  6
    #define ETHER_HEADER_LEN  14
    #define IP6_ADDR_LEN  16
    #define IP6_HEADER_LEN  40
     
    typedef struct {
      unsigned char dst[ETHER_ADDR_LEN];
      unsigned char src[ETHER_ADDR_LEN];
      unsigned short type;
    } ether_header;
     
    typedef struct {
      unsigned char version:4;
      unsigned char cl;
      unsigned int label:20;
      unsigned short length;
      unsigned char next_header;
      unsigned char ttl;
      unsigned char src[IP6_ADDR_LEN];
      unsigned char dst[IP6_ADDR_LEN];
    } ip6_header;
    sniffer.c, packet est un pointeur vers u_char contenant les valeurs "a plat" du paquet:
    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
     
    ether_header *ether;
    ip6_header *ip6;
    // If the datalink is standard ethernet
    if (datalink == DLT_EN10MB) {
        ether = (ether_header *)packet;
        printf("Ether_type: %x\n", ntohs(ether->type));
        // If IPv6, then map the remaining of the packet to our ipv6 structure
        if (ntohs(ether->type) == 0x86dd)
          ip6 = (ip6_header *)(packet + sizeof(ether_header));
    }
    printf("ip6 version: %x, class: %x, label: %x, len: %x, next-h: %x, ttl: %x\n", (ip6->version & 0xf0) >> 4, ip6->cl, (ip6->label & 0x000fffff), ip6->length, ip6->next_header, ip6->ttl);
    // Print source ip.
    for (int i = 0; i < IP6_ADDR_LEN; i++) {
        printf("%02x", ip6->src[i]);
    }
    Je ne comprends pas les resultats que j'obtiens, c'est peut etre du a mon incomprehension des bits fields, mais je vois pas comment specifier de maniere fine l'alignement des donnes. A l'execution:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    //IP version devrait etre 6. Cela marche si je modifie unsigned char version:4 en unsigned char version;
    ip6 version: 0, class: 0, label: a4000, len: 550, next-h: 10, ttl: 2
    //IP source devrait etre 50051002300450067008900ab00c2222, mais est decalee de 4 octets
    300450067008900ab00c222250051002
    Si je lance le tout dans gdb, je vois bien que les structures en memoire ne sont pas alignees de la meme maniere que ma structure:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    (gdb) print &ip6.version
    $4 = (unsigned char *) 0x100801020 "`"
    (gdb) print &ip6.cl     
    $5 = (unsigned char *) 0x100801021 ""
    (gdb) print &ip6.label
    $6 = (unsigned int *) 0x100801024
    (gdb) print &ip6.length
    $7 = (short unsigned int *) 0x100801028
    (gdb) print &ip6.next_header
    $8 = (unsigned char *) 0x10080102a
    entre ip6.version et ip6.cl, j'ai un octet, alors que j'utilise un bit field de 4 bits. entre ip6.cl et ip6.label, j'ai 3 octets, alors que j'utilise un unsigned short. Mes donnees se decalent donc, et mon addresse ipv6 source se retrouve decalee de 4 octets.
    Je pense que c'est du a l'alignement des donnees par le compilateur, mais je vois pas comment gerer ca.
    Mes questions:
    • Est-ce que je peux mapper une zone de memoire vers une structure, comme je le fait? Peut-on se reposer sur le fait que les donnes soient contigues?
    • Si oui, est-ce que le compilateur gere les offset supplementaires en memoire vers la structure a la compilation?
    • Si non, quelle est la methode utilisee dans ce genre de cas - donnees a plat vers donnes mises en forme?


    Merci a ceux qui ont lu jusque la.

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    Ta structure ip6_header n'est pas bonne. Là tu définit "version" sur 4 bits, ce qui est bon, mais ensuite tu as les 4 autres bits du char qui ne sont pas utilisés. Donc tu lis ton "cl" 4 bits trop loin, et tout est décalé. Pareil pour "label", où tu laisses 12 bits non occupés.

  3. #3
    Membre chevronné
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Par défaut
    Merci, effectivement ca marche beaucoup mieux.
    Pour ceux qui connaissent pas les bits fields, l'ensemble des bits doit etre contenu dans un champ type. La version correcte est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    typedef struct {
      unsigned int version:4;
      unsigned int class:8;
      unsigned int label:20;
      unsigned short length;
      unsigned char next_header;
      unsigned char ttl;
      unsigned char src[IP6_ADDR_LEN];
      unsigned char dst[IP6_ADDR_LEN];
    } ip6_header;
    J'ai des problemes d'indianness maintenant. Je comprends pas comment je peux avoir un probleme d'indianness au niveau octet d'ailleur...

    EDIT:
    Je crois que j'ai compris. J'ai lu ici que l'ordre des bits dans un bitfield n'est pas standard et depend de l'implementation.
    Je vois pas trop comment m'en sortir, a moins de considerer version, class et label sur un int et de parser a coup de decalage/masquage. Ca m'embete de parser de cette maniere, parce que je peux pas calquer ma structure directement sur la memoire et je dois ecrire un petit parseur.

    Y'a-t-il une solution plus elegante/interessante/utile a ce probleme?

  4. #4
    Membre très actif

    Femme Profil pro
    Collégien
    Inscrit en
    Juillet 2010
    Messages
    593
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Juillet 2010
    Messages : 593
    Par défaut
    Salut!

    J'ai lu ici que l'ordre des bits dans un bitfield n'est pas standard et depend de l'implementation.
    Je vois pas trop comment m'en sortir, a moins de considerer version, class et label sur un int et de parser a coup de decalage/masquage. Ca m'embete de parser de cette maniere, parce que je peux pas calquer ma structure directement sur la memoire et je dois ecrire un petit parseur.

    Y'a-t-il une solution plus elegante/interessante/utile a ce probleme?
    C'est un problème au quel je suis souvent confronté. Pour le moment je n'est pas trouvé d'autre solution que de parser mes structures à la main...

    Je suis également preneur si quelqu'un connait une meilleur méthode!!

  5. #5
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    Je n'ai pas de solution non plus...

    De toute façon, mapper des données sur une structure c'est fondamentalement non portable, même sans parler de bit fields. Rien ne dit que le compilo ne va pas ajouter du padding entre les champs.

  6. #6
    Membre chevronné
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Par défaut
    Citation Envoyé par matafan Voir le message
    De toute façon, mapper des données sur une structure c'est fondamentalement non portable, même sans parler de bit fields. Rien ne dit que le compilo ne va pas ajouter du padding entre les champs.
    Je pense pas qu'il y ai de probleme dans ce cas la. Je suis sur que les donnees sont adjacentes en memoire, car le la libpcap ne fait que copier le contenu du paquet vers une adresse connue. Ce n'est pas une structure qui est ecrite en memoire, mais simplement le contenu d'un paquet qui est dumpe a un emplacement memoire.
    Je ne fait que mettre ces donnees en forme. D'ailleurs un parseur n'apporte rien de plus, car je dois avancer en offset fixes pour mapper mes champs. S'il y a padding (mais ce n'est pas possible), la structure sera incorrect de toute facon.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. transferer les donnees d'une BD paradox vers access
    Par denza1 dans le forum Bases de données
    Réponses: 5
    Dernier message: 31/10/2004, 14h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo