Why are there differences between ETH_P_IP and ETH_P_ALL when doing a read()

A G picture A G · Oct 8, 2012 · Viewed 19.1k times · Source

I have the following setup:

client(eth0) --- (eth2) linux bridge (eth1) --- (eth1) server

When I open a RAW socket on the linux bridge using

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

I have the socket bound to eth2. When the client sends a packet to the server, wireshark running on the bridge reports the packet with a source mac address of client(eth0) and a destination mac address of server(eth1).

When I do a read(), the first 6 bytes of the data read is the destination mac address, which is correctly read as server(eth1).

However when I change the statement to

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

When I do a read(), the first 6 bytes of the data read shows the destination mac address is linux bridge (eth2).

Why would this be? Is the kernel or ethernet card driver placing its own mac address in the buffer instead of reading off the wire with ETH_P_IP?

Answer

user1500049 picture user1500049 · Oct 9, 2012

For the ETH_P_IP case, what you are describing sounds like a normal "routing" scenario. (i.e. The routing mac is destination mac.)

It would make sense if your client and server are on different subnet/vlan, and a router in between.

However, the diagram is indicating a linux "bridge". Does it do bridging only and no routing at all?

EDIT

ETH_P_IP only captures incoming IP packet according to this answer: Packet Sniffing using Raw Sockets in Linux in C