2017-03-03 9 views
1

J'écris un outil en C pour consigner l'utilisation des données des différentes applications s'exécutant sur mon système Linux. Pour cela j'ai créé un socket raw et ensuite je le lie avec "eth0" qui est le nom de mon interface. Mais mon problème est que ces sockets ne capturent que les paquets entrants (ie: les paquets avec l'adresse MAC de destination comme adresse MAC de mon système). Je ne trouve aucun paquet ayant l'adresse MAC source comme adresse MAC de mon système. Cela signifie donc que les paquets écrits par ma propre machine ne sont pas capturés par le socket raw. Mais je veux capturer des paquets dans les deux directions pour identifier la taille des données téléchargées et téléchargées. Quelqu'un peut-il aider?capture des paquets entrants et sortants à l'aide de la socket raw

int main() 
{ 
    int rs,len; 
    struct sockaddr_ll addr; 
    char buf[65535]; 

    rs = socket(PF_PACKET,SOCK_RAW,htons(ETH_ALL)); 
    setsockopt(rs,SOL_SOCKET,SO_BINDDEVICE,"eth0",4); 
    while(recvfrom(rs,buf,65535,&addr,&len) > 0){ 
     //print packets 
    } 
    return 0; 
} 

Répondre

1

J'ai trouvé ceci en recherchant votre problème. Je n'ai pas essayé ça. Peut-être que cela fonctionnera.

int v=0; 
    v = PACKET_MASK_ANY & ~(1<<PACKET_OUTGOING) & ~(1 << PACKET_LOOPBACK); 
    setsockopt(raw_sock, SOL_PACKET, PACKET_RECV_TYPE, &v, sizeof(v)); 
+0

Merci pour votre réponse. Mais il n'y a pas de macro nommé PACKET_MASK_ANY dans mon/usr/include –

+0

#define PACKET_MASK_ANY 0xffffffff/* masque pour les bits de type de paquet */define PACKET_OUTGOING 4/* Sortant de tout type */define PACKET_RECV_TYPE 18 –

+0

Il n'y a pas macro d'opération de socket nommée PACKET_RECV_TYPE. êtes-vous du Kerala? –

1

De socket(7):

SO_BINDTODEVICE

Bind cette prise à un dispositif particulier comme « eth0 », comme spécifié dans le nom d'interface transmis. [...] Notez que cela ne fonctionne que pour certains types de socket, en particulier les sockets AF_INET. Il n'est pas supporté pour les sockets de paquets (utilisez le bind normal (2) ici).

Vous devriez regarder la page de manuel packet(7) pour cela.

Il peut être instructif de télécharger la source de la bibliothèque libpcap et de voir ce qu'elle fait (si vous ne pouvez pas utiliser libpcap au lieu de rouler les vôtres). Il reçoit définitivement les paquets sortants ainsi que ceux entrants.

Il semble faire ces appels (il y a beaucoup d'options prises en charge et configurations, donc vous devez wend à travers une myriade de ifdefs pour découvrir exactement ce qui se passe - voir pcap-linux.c):

fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL); 
... 
struct sockaddr_ll sll; 
memset(&sll, 0, sizeof(sll)); 
sll.sll_family   = AF_PACKET; 
sll.sll_ifindex   = ifindex; // Interface index from SIOCGIFINDEX 
sll.sll_protocol  = htons(ETH_P_ALL); 
bind(fd, (struct sockaddr *) &sll, sizeof(sll)); 
... 
struct packet_mreq  mr; 
memset(&mr, 0, sizeof(mr)); 
mr.mr_ifindex = handlep->ifindex; 
mr.mr_type = PACKET_MR_PROMISC; 
setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) 

Une autre chose garder à l'esprit. Lors de la réception de paquets envoyés par votre propre boîte, il est fréquent que les sommes de contrôle (IP, TCP et UDP) dans les paquets sortants soient incorrectes. En effet, la plupart des contrôleurs réseau modernes prennent en charge le déchargement des sommes de contrôle. Cela signifie que la carte calculera les sommes de contrôle après que les paquets ont été introduits dans la mémoire de la carte. Par conséquent, ceux pour les paquets sortants ne seront pas corrects dans le tampon de votre programme (qui est rempli par le noyau à partir de la mémoire locale).