I am looking into the standard ping implementation. Here the icmp structure is created and the data is filled in. The IP layer is added by the kernel. However when we receive a message using the function http://linux.die.net/man/2/recvfrom I observe that they are first parsing the IP packet and then parsing the ICMp packet. Why is this happening. The code I am referrring to is the standard ping implementation available online.
Best How To :
It's because the header is always included when receiving an IPv4 packet on a raw socket. Notice the following in
raw(7) (emphasis mine):
The IPv4 layer generates an IP header when sending a packet unless the
IP_HDRINCL socket option is enabled on the socket. When it is enabled, the packet must contain an IP header. For receiving the IP header is always included in the packet.
Since the header is always included and has variable length (for IPv4), it must be parsed to figure out where the ICMP data starts.
As for why the header isn't removed (sorry if that was the only thing you were wondering), I don't know. My wild guess is that enough programs that deal in raw IPv4 want to look at the header that it didn't seem worthwhile to include stripping it as an option. From a quick look it seems the header is stripped for IPv6.
ping6 come from iputils by the way, where ping_common.c, ping.c, and ping6.c are the most relevant source files.