How to validate the checksum of an ICMP echo packet?

216 views Asked by At

I have a working implementation of ping utility which I did as a hobby project. I'm having difficulty figuring out how I shall verify the checksum on receiving the echo reply packet. I will explain why.

Here's how I create an ICMP echo request packet.

type ICMPHeader struct {
    Type           uint8
    Code           uint8
    Checksum       uint16
    Identifier     uint16
    SequenceNumber uint16
}

type ICMPPacket struct {
    Header *ICMPHeader
}

func (pinger *Pinger) createICMPPacket(seqNo int) (*ICMPPacket, error) {  
    packet := &ICMPPacket{  
       Header: &ICMPHeader{  
          Type:           ICMPHeaderType,  
          Code:           ICMPHeaderSubtype,  
          Checksum:       0, // initially zeroed
          Identifier:     0,  
          SequenceNumber: uint16(seqNo),  
       },  
    }  
  
    packetSerialized, err := packet.Serialize()  
    if err != nil {  
       return nil, errors.Wrapf(err, "error serializing ICMP packet")  
    }  
  
    packet.Header.Checksum = calculateChecksum(packetSerialized)  
  
    return packet, nil  
}

There is no payload/data portion in the packet because, for my use case of sending an echo request packet, I have all the relevant fields in the header.

ICMP checksum is calculated over the entire message(including header and data). But since there is no data in this scenario, the calculation is done solely using the header bytes 08 00 00 00 00 00 00 00 which yields f7 ff as the checksum.

So the ICMP portion of the byte stream I eventually send out is, 08 00 f7 ff 00 00 00 00

But in Wireshark, I see that some arbitrary 22 bytes were added as data in my ICMP packet byte stream. It appears that these bytes contain some information from the IPv4 header.

echo request

First question, How are these bytes getting added?


Moving on, as per what's written in RFC792, page 15,

The data received in the echo message must be returned in the echo reply message.

My echo reply packet contains the same stream of 22 bytes as packet data.

enter image description here

I understand that upon receiving the ICMP echo reply packet, the checksum validation should involve zeroing the checksum field, recalculating the checksum over the entire ICMP packet (including both the header and payload), and then comparing it to the previously calculated checksum.

This leads to my next set of questions

  • Will the presence of arbitrary bytes in ICMP packets, which were not included during checksum calculation (based solely on the header data), affect my checksum validation logic? Should I take them into account, or should I only consider just the header data for validation?
  • Even if I choose to ignore the arbitrary bytes, there's still the issue of the Type field differing between the echo packet (Type 8) and the echo reply packet (Type 0). This discrepancy in the Type field ensures that the checksums won't match. How should I address this?

I didn't find any rules about how to validate checksum for ICMP echo replies, even the actual ping implementation doesn't bother with csfailed variable for echo replies.

Any help is appreciated.

0

There are 0 answers