'Confusion with AF_INET, with SOCK_RAW as the socket type, V/S AF_PACKET, with SOCK_DGRAM and SOCK_RAW as the socket type

I am quite new to network programming and have been trying to wrap my head around this for quite sometime now. After going through numerous resources over the internet, I have the below conclusion and following it the confusion.

Conclusion 1: When we are talking about creating a socket as :

s = socket(AF_INET, SOCK_RAW, 0);

we are basically trying to create a raw socket. With a raw socket created this way one would be able to bypass TCP/UDP layer in the OSI stack. Meaning, when the packet is received by the application over this socket, the application would have the packet containing the network layer (layer 3) headers wrapping the layer 2 headers wrapping the actual data. So the application is free to process this packet, beyond layer 3, in anyway it wants to.

Similarly, when sending a packet through this socket also, the application is free to handle the packet creation till layer 4 and then pass it down to layer 3, from which point on the kernel would handle things.

Conclusion 2: When we are talking about creating a socket as :

s = socket(AF_PACKET, SOCK_RAW, 0);

we are again trying to create a raw socket. With a raw socket created this way one would be able to bypass all the layers of the OSI altogether. A pure raw packet would be available to the user land application and it is free to do whatever it wants with that packet. A packets received over such a socket would have all the headers intact and the application would also have access to all of those headers.

Similarly, when sending data over such a socket as well, the user application is the one that would have to handle everything with regards to the creation of the packet and the wrapping of the actual data with the headers of each layer before it is actually placed on the physical medium to be transmitted across.

Conclusion 3: When we are talking about creating a socket as :

s = socket(AF_PACKET, SOCK_DGRAM, 0);

we are again trying to create a raw socket. With a raw socket created this way one would be able to bypass data link layer (layer 2) in the OSI stack. Meaning, when a packet over such a socket is received by the user land application, data link layer header is removed from the packet.

Similarly, while sending a packet through this socket, a suitable data link layer header is added to the packet, based on the information in the sockaddr_ll destination address.

Now below are my queries/points of confusion:

  1. Are the conclusions that I have drawn above about raw sockets correct ?
  2. I did not quite clearly understand the conclusion 3 above. Can someone please explain ? Like, does it mean that when the user land application receives a packet through this socket, it is only the data link layer headers that would have been handled by the kernel? And so the packet would be like the message wrapped with directly the layer 3 headers and wrapped subsequently by the layers above it?
  3. If the conclusions drawn above are correct, conclusion 1 and conclusion 2 still make sense. But if conclusion 3 above (and the speculations around it in 2 above) are correct, when exactly would any application ever need to do that ?

Some resources that I have referred to trying to understand the above:

https://docs.freebsd.org/44doc/psd/21.ipc/paper.pdf

https://sock-raw.org/papers/sock_raw

https://www.quora.com/in/Whats-the-difference-between-the-AF_PACKET-and-AF_INET-in-python-socket

http://www.linuxcertif.com/man/7/PF_PACKET/

http://opensourceforu.com/2015/03/a-guide-to-using-raw-sockets/

'SOCK_RAW' option in 'socket' system call

http://stevendanna.github.io/blog/2013/06/23/a-short-sock-raw-adventure/

https://www.intervalzero.com/library/RTX/WebHelp/Content/PROJECTS/Application%20Development/Understanding_Network/Using_RAW_Sockets.htm



Solution 1:[1]

You got quite closer to their real explanation. Here I've got something to tell you what I think you're missing or wrong about.

First, for s = socket(AF_INET, SOCK_RAW, 0);, when packet is received over such socket, it will contain an IP header always. If IP_HDRINCL is not enabled, for sending, the packet must contain the IP header, the TCP/IP stack will not generate this for you. All other upper layers can be received by this socket.

Secondly, s = socket(AF_PACKET, SOCK_RAW, 0);:

This is a special type of Raw Socket and called Packet-socket in Linux system. This type of socket allows to send and receive packet at OSI layer 2 that's why APIs used for such socket are referred to as Link Layer API. Any protocol can be implemented on the top of physical layer by using this socket. Interestingly, we can also interact with the packet's trailer with this socket what though we don't frequently need.

Thirdly, In case of s = socket(AF_PACKET, SOCK_DGRAM, 0);, your conclusion is right. In this type of Packet Socket, you don't need to think about Ethernet header. It's a bit upper layer than previous type.

So, we can say that the main distinction amongst these types of sockets is their possibility of access. To summarize:

  1. Raw-Socket access:

| Layer 3 header | Layer 4 header | Payload |

  1. Packet-Socket access:

| Layer 2 header | Layer 3 header | Layer 4 header | Payload | Layer 2 trailer |

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mateen