Linux raw ethernet socket binds to a specific protocol

I am writing code to send raw Ethernet frames between two Linux boxes. To test this, I just want to get a simple client-send and server-receive.

I have a client that creates packages correctly (I see them using the packet sniffer).

On the server side, I initialize the socket as follows:

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

where MY_ETH_PROTOCOL is a 2-byte constant, I use ethertype as a type, so I don’t hear extraneous network traffic.

when I bind this socket to my interface, I must pass the protocol to it again in the socket_addr structure: socket_address.sll_protocol = htons(MY_ETH_PROTOCOL);
If I compile and run such code, then it fails. My server does not see the package. However, if I changed the code like this:
socket_address.sll_protocol = htons(ETH_P_ALL);
Then the server can see the packet sent from the client (like many other packets), so I have to do some packet checking to see if it matches MY_ETH_PROTOCOL .

But I do not want my server to hear traffic that is not sent over the specified protocol, so this is not a solution. How to do it?

+7
linux sockets ethernet
source share
2 answers

I solved the problem.

According to http://linuxreviews.org/dictionary/Ethernet/ , referring to a field of 2 bytes, following the MAC addresses:

"values ​​of this field between 64 and 1522 indicate the use of the new Ethernet 802.3 format with a length field, and values ​​of 1536 decimal (hexadecimal number 0600) and higher indicate the use of the original DIX or Ethernet II frame format with the EtherType sub-protocol identifier."

so I have to make sure my ethertype> = 0x0600.

According to http://standards.ieee.org/regauth/ethertype/eth.txt, the use of 0x88b5 and 0x88b6 "is available for general use for prototype and vendor-specific development." So this is what I am going to use as an ether. I do not need any additional filtering, since the kernel must ensure that it only collects Ethernet frames with the correct destination MAC address and uses this protocol.

+5
source share

In the past, I worked on this issue using a packet filter.

Hand Waving (untested 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)); 

Error checking and getting the packet filter on the right is left as an exercise for the reader ...

Depending on your application, an alternative that may be easier to get work is libpcap .

0
source share

All Articles