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 Discussion :

Problème taille sockaddr_ll, rawsocket et version du noyau linux


Sujet :

Réseau

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 2
    Points : 2
    Points
    2
    Par défaut Problème taille sockaddr_ll, rawsocket et version du noyau linux
    Bonjour à tous,
    dans un programme utilisant des rawsockets, une erreur apparaissait "aleatoirement" sur certaines machines linux. Je me suis rendu comptes qu'en fait cette erreur apparaissait lorsque les machines en question possédaient le noyau 2.6.19. Celles où le programme fonctionnait correctement avaient le noyau 2.6.9.

    J'ai donc réalisé un petit programme pour mettre en avant ce problème. Ce programme ouvre juste une rawsocket sur une interface en mode promiscuiss acceptant toutes trames et regarde la taille de la structure sockaddr_ll remonté.

    Le problème vient au moment de l'appel de recvfrom(), qui renvoi une taille de struct sockaddr_ll différent de sizeof(struct sockaddr_ll) sur les noyaux 2.6.19
    et non sur les noyaux 2.6.9., on devrait avoir taille recue : 20 (= à la taille de la structure) et pour les noyaux 2.6.19 on obtient taille recue : 18 ...

    est ce que quelqu'un a déjà eu un problème similaire ? J'ai cherché dans les change logs des versions noyau mais entre le 2.6.9 et le 2.6.19 il y a eu un paquet de modif et je ne trouve rien


    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
     
    #include <netinet/in.h>
    #include <net/if.h>
    #include <netinet/if_ether.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netpacket/packet.h>
    #include <net/ethernet.h>
    #include <linux/sockios.h>
     
    struct packet_mreq mreq;
    struct ifreq ifr;
    struct sockaddr_ll sll;
    struct sockaddr_ll from;
    struct sockaddr_in sockaddrin;
    int ifind;
    int fd_r;
    int i =0;
    int j;
    int taille;
    char pbuf[2000];
    socklen_t size = sizeof(struct sockaddr_ll);
     
    int main(void){
     
      /* ouverture device */
      if( (fd_r = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0){
        printf("pb socket \n");
        exit(1);
      }
     
      /* Recuperation de l'index de l'interface */
      strcpy( ifr.ifr_name, "eth9" );
      if (ioctl(fd_r,SIOGIFINDEX,&ifr) == -1){
        printf("pb Recuperation de l'index de l'interface\n");
        exit(1);
      }
      ifind = ifr.ifr_ifindex;
     
      /* bind la socket sur la bonne interface */
      strcpy( ifr.ifr_name, "eth9");
      if (ioctl( fd_r, SIOCGIFADDR, &ifr ) < 0) {
        printf("pb ioctl - recup @ IP\n");
        exit(1);
      }
      memset(&sll, 0xff, sizeof(sll));
      sll.sll_family = AF_PACKET;
      sll.sll_protocol = htons(ETH_P_ALL);
      sll.sll_ifindex = ifind;
      if (bind(fd_r, (struct sockaddr *)&sll , sizeof(sll)) == -1){
        printf("pb bind\n");
        exit(1);
      }
     
      /* Place l'interface en promisc */
      memset(&mreq,0,sizeof(mreq));
      mreq.mr_ifindex = ifind;
      mreq.mr_type = PACKET_MR_PROMISC;
      if (setsockopt(fd_r,SOL_PACKET, PACKET_ADD_MEMBERSHIP,(char *)&mreq,sizeof(mreq)) == -1){
        printf("Impossible de placer l'interface en PROMISC\n");
        exit(1);
      }
     
      while (i==0){ 
        taille = recvfrom(fd_r, pbuf, 2000, 0,(struct sockaddr *)&from,&size);
        if (size != sizeof(struct sockaddr_ll)){
          printf("Mauvais parametre de recvfrom \n");
          printf("paquet recu : taille recue : %d, taille de la structure : %d\n",size,sizeof(struct sockaddr_ll));
          return;
        }
        printf("paquet recu : taille recue : %d, taille de la structure : %d\n",size,sizeof(struct sockaddr_ll));
     
        // for(j=0;j<taille;j++){
        //  printf("%02x",pbuf[j]);
        //}
        //printf("taille : %d\n",taille);
      }
     
      return 0;
    }

  2. #2
    Membre chevronné

    Profil pro
    Inscrit en
    Mars 2004
    Messages
    1 296
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 296
    Points : 1 803
    Points
    1 803
    Par défaut
    je n ai pas d'explication,mais sur un 2.6.20 même choses :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Mauvais parametre de recvfrom
    paquet recu : taille recue : 18, taille de la structure : 20
    Marc
    Slackware for ever ......
    BASH - KSH ( http://marcg.developpez.com/ksh/ )

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 2
    Points : 2
    Points
    2
    Par défaut
    J'ai la réponse à mon problème !



    En fait, la fonction recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, socklen_t *fromlen) à légèrement changé dans une évolution du noyau entre la 2.6.10 et 2.6.19 (me demandez pas laquelle exactement!).

    Le calcul de fromlen a changé :
    dans les noyaux antérieurs au 2.6.10, fromlen correspondait simplement à un sizeof de struct sockaddr_ll soit 20 mais il remonte sur les noyaux 2.6.19 et + la taille réelle remplie dans la structure ...

    struct sockaddr_ll {
    unsigned short sll_family; /* Toujours AF_PACKET 2o */
    unsigned short sll_protocol; /* Protocole niveau physique 2o */
    int sll_ifindex; /* Numéro d'interface 4o */
    unsigned short sll_hatype; /* Type d'en-tête 2o */
    unsigned char sll_pkttype; /* Type de paquet 1o */
    unsigned char sll_halen; /* Longueur de l'adresse 1o */
    unsigned char sll_addr[8]; /* Adresse niveau physique 8o */
    };

    le dernier champ est un buffer de 8 octets censé recueilir l'adresse de la couche physique mais dans le cas d'ethernet, l'adresse mac ne fait que 6 octets ! Puisque c'est la taille remplie qui est remontée à l'utilisateur désoramais, on se retrouve avec un 18 au lieu d'un 20 que l'on avait sur les noyaux plus anciens.

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

Discussions similaires

  1. Réponses: 65
    Dernier message: 16/04/2015, 12h48
  2. Comment connaitre la version du noyau linux de ma distribution ?
    Par JeSouffreAvecLinux dans le forum Linux
    Réponses: 2
    Dernier message: 08/09/2009, 16h28
  3. Problème pour exporter d'une version 5 à une version 3
    Par vallica dans le forum Installation
    Réponses: 13
    Dernier message: 26/05/2006, 17h57
  4. Réponses: 2
    Dernier message: 04/04/2006, 14h40
  5. Réponses: 2
    Dernier message: 08/03/2004, 16h10

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