2017-03-03 1 views
1

Ich schreibe ein Tool in C für die Protokollierung der Datennutzung von verschiedenen Anwendungen auf meinem Linux-System. Dafür habe ich einen rohen Socket erstellt und dann binde ich ihn mit "eth0", was der Name meiner Schnittstelle ist. Aber mein Problem ist, dass diese Sockets nur eingehende Pakete erfassen (dh: Pakete mit Ziel-MAC-Adresse als MAC-Adresse meines Systems). Ich kann keine Pakete finden, deren Quell-MAC-Adresse die MAC-Adresse meines Systems ist. Es bedeutet also, dass Pakete, die von meiner eigenen Maschine geschrieben wurden, nicht vom rohen Socket erfasst werden. Aber ich möchte Pakete in beiden Richtungen erfassen, um die hochgeladene und heruntergeladene Datengröße zu identifizieren. Kann jemand helfen?Erfassen von eingehenden und ausgehenden Paketen mit Raw-Socket

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

Antwort

1

Ich habe dies bei der Suche nach Ihrem Problem gefunden. Ich habe das nicht versucht. Möge das funktionieren.

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

Vielen Dank für Ihre Antwort. Aber es gibt keinen Makro mit dem Namen PACKET_MASK_ANY in meinem/usr/include –

+0

#define PACKET_MASK_ANY 0xffffffff/* Maske für Pakettyp Bits */ #define PACKET_OUTGOING 4/* Abgehende jeglicher Art */ #define PACKET_RECV_TYPE 18 –

+0

Es gibt keine Socket-Operationsmakro namens PACKET_RECV_TYPE. bist du aus Kerala? –

1

Von socket(7):

SO_BINDTODEVICE

Bind diese Buchse an ein bestimmtes Gerät wie „eth0“, wie in den übergebenen Schnittstellennamen angegeben. [...] Beachten Sie, dass dies nur für einige Socket-Typen funktioniert, insbesondere AF_INET-Sockets. Es wird nicht für Paket-Sockets unterstützt (verwenden Sie dort normal bind (2)).

Sie sollten diese an der packet(7) Manpage suchen.

Es kann lehrreich sein, die libpcap-Bibliotheksquelle herunterzuladen und sich anzusehen, was sie tut (wenn Sie nicht einfach libpcap verwenden können, statt selbst zu rollen). Es erhält definitiv ausgehende Pakete sowie eingehende.

Es scheint diese Anrufe zu machen (es gibt viele unterstützten Optionen und Konfigurationen, so dass Sie durch eine Vielzahl von ifdefs wend genau zu entdecken, was los ist - siehe 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)) 

Eine andere Sache, im Kopf behalten. Wenn Sie Pakete empfangen, die von Ihrer eigenen Box gesendet werden, ist es häufig der Fall, dass die Prüfsummen (IP, TCP und UDP) in den ausgehenden Paketen inkorrekt sind. Das liegt daran, dass die meisten modernen Netzwerk-Controller die Prüfsummenverschiebung unterstützen. Das bedeutet, dass die Karte die Prüfsummen berechnet, nachdem die Pakete in den Speicher der Karte DMA übertragen wurden. Daher sind diejenigen für ausgehende Pakete nicht korrekt in Ihrem Programm Puffer (der vom Kernel aus dem lokalen Speicher gefüllt ist).

Verwandte Themen