2010-07-29 3 views
7

Ich schreibe Code, um rohe Ethernet-Frames zwischen zwei Linux-Boxen zu senden. Um das zu testen, möchte ich nur einen einfachen Client senden und Server empfangen.Linux Roh-Ethernet-Socket binden an spezifisches Protokoll

Ich habe den Client richtig Pakete (ich kann sie mit einem Paket-Sniffer sehen).

Auf der Serverseite initialisieren ich die Fassung wie folgt:

fd = socket(PF_PACKET, SOCK_RAW, htons(MY_ETH_PROTOCOL)); 

wo MY_ETH_PROTOCOL ein 2-Byte-Konstante I als Ethertyp verwenden ist so höre ich keinen äußeren Netzwerkverkehr.

, wenn ich diese Buchse an meine Schnittstelle binden muss ich es ein Protokoll wieder in der socket_addr struct passieren: socket_address.sll_protocol = htons(MY_ETH_PROTOCOL);
Wenn ich den Code wie folgt kompilieren und ausführen, dann scheitert es. Mein Server sieht das Paket nicht. Aber wenn ich den Code so ändere:
socket_address.sll_protocol = htons(ETH_P_ALL);
Der Server kann dann das Paket vom Client gesendet (sowie viele andere Pakete), so muss ich einige Überprüfung des Pakets zu sehen, dass esentspricht.

Aber ich möchte nicht, dass mein Server Datenverkehr empfängt, der nicht auf dem angegebenen Protokoll gesendet wird, also ist dies keine Lösung. Wie mache ich das?

+0

Kannst du den Code einfügen, wo du deine 'socket_address' eingerichtet hast? – bstpierre

Antwort

5

Ich habe das Problem gelöst.

Nach http://linuxreviews.org/dictionary/Ethernet/ an die 2-Byte-Feld bezieht Folgende die MAC-Adressen:

„Werte dieses Feldes zwischen 64 und 1522 zeigte die Verwendung des neuen 802.3-Ethernet-Format mit einem Längenfeld, während Werte von 1536 dezimal (0600 hexadezimal) und größer zeigten die Verwendung des ursprünglichen DIX- oder Ethernet II-Rahmenformats mit einer EtherType-Subprotokollkennung an. "

so muss ich meine Ethertyp sicher ist> = 0x0600.

Gemäß http://standards.ieee.org/regauth/ethertype/eth.txt ist die Verwendung von 0x88b5 und 0x88b6 "für die öffentliche Verwendung für prototyp- und herstellerspezifische Protokollentwicklung verfügbar". Also das werde ich als Ethertype verwenden. Ich sollte keine weitere Filterung benötigen, da der Kernel sicherstellen sollte, dass er nur Ethernet-Frames mit der richtigen Ziel-MAC-Adresse aufnimmt und dieses Protokoll verwendet.

+0

Ich habe getan wie du gesagt hast.Aber mein Client kann das angegebene Protokollpaket nicht empfangen. Können Sie Ihren Code einfügen? Danke! E-Mail: [email protected] –

0

Ich habe dieses Problem in der Vergangenheit mithilfe eines Paketfilters behoben.

Hand Winken (ungetestet Pseudo-Code)

struct bpf_insn my_filter[] = { 
    ... 
} 

s = socket(PF_PACKET, SOCK_DGRAM, htons(protocol)); 
struct sock_fprog pf; 
pf.filter = my_filter; 
pf.len = my_filter_len; 
setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)); 

sll.sll_family = PF_PACKET; 
sll.sll_protocol = htons(protocol); 
sll.sll_ifindex = if_nametoindex("eth0"); 

bind(s, &sll, sizeof(sll)); 

Fehlerprüfung und immer die Paketfilter rechts als eine Übung für den Leser überlassen wird ...

Je nach Anwendung eines Alternative, die leichter zu arbeiten ist, ist libpcap.