Précédent   Forum des professionnels en informatique > Systèmes > Linux > Réseau
Réseau Vos questions autour des réseaux et télécoms sous Linux
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 08/03/2007, 11h13   #1
Invité de passage
 
Inscription : mars 2007
Messages : 2
Détails du profil
Informations forums :
Inscription : mars 2007
Messages : 2
Points : 1
Points : 1
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 :
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;
}
El Fenec est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/03/2007, 10h37   #2
Rédacteur
 
Inscription : mars 2004
Messages : 1 298
Détails du profil
Informations forums :
Inscription : mars 2004
Messages : 1 298
Points : 1 450
Points : 1 450
je n ai pas d'explication,mais sur un 2.6.20 même choses :
Code :
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/ )
MarcG est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/11/2007, 11h18   #3
Invité de passage
 
Inscription : mars 2007
Messages : 2
Détails du profil
Informations forums :
Inscription : mars 2007
Messages : 2
Points : 1
Points : 1
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.
El Fenec est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 08h57.


 
 
 
 
Partenaires

Hébergement Web