gosocketsnetwork-programmingwiresharkicmp

Different Datagram Length Field In IP Headers


I am trying to parse a ICMP packet starting with the IP header.

func main() {
    fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_ICMP)
    if err != nil {
        fmt.Println(err)
        return
    }

    for {
        buf := make([]byte, 1024)
        numRead, err := syscall.Read(fd, buf)
        if err != nil {
            fmt.Println(err)
        }

        fmt.Println(hex.EncodeToString(buf[:numRead]))

    }
}

This is my starting Go code.

  1. I run this application
  2. I run Wireshark to listen ICMP packets. Filter: ip.src==192.168.1.109||ip.dst==192.168.1.109
  3. I ping to google.com to capture the echo reply.

I was expecting to reply packets from the Wireshark and my application to be the same but results are like this:

Note: Bytes is starting from IP Header I did not give the Link Layer bytes.

Go: 45004000000000003801c12cd8ef2678c0a8016d00007e72324f0000668e33570008ca4d08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637

Wireshark: 45000054000000003801c12cd8ef2678c0a8016d00007e72324f0000668e33570008ca4d08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637

If we look at the first 20 bytes of the IP Header the only difference is the datagram length. Starting from the 3. byte to the 4. byte.

Go: 4000

Wireshark: 0054

I could not find that why they are different since I am listenning on the same datagram with the same sequence number. Thanks for your time.


Solution

  • It turns out macOS is changing the raw socket header when it arrives. Wireshark can show the true result since it was working on a kernel level. When I run a fedora docker container and run the script it gives the same result as in the Wireshark.