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;
}