Denis Stein
Denis Stein

Reputation: 11

How to calculate tcp packet checksum correctly?

I am trying to implement a checksum calculation algorithm using this link Here is an example of a byte slice and checksums for it. And also my implementation code, tell me what I'm doing wrong.

    //https://gist.github.com/david-hoze/0c7021434796997a4ca42d7731a7073a
  func chksum(iph *ipv4.Header,payload []byte)uint16{

                // https://github.com/mikioh/-stdyng/blob/master/afpacket.go
                var htons = func(i uint16) uint16 {return (i<<8)&0xff00 | i>>8}

            tcpLen := iph.TotalLen - iph.Len
            src := iph.Src
            dst := iph.Dst
            var csum uint32

            for i := 0; i < 16; i += 2 {
                csum += uint32(src[i]) << 8
                csum += uint32(src[i+1])
                csum += uint32(dst[i]) << 8
                csum += uint32(dst[i+1])
            }

            csum += uint32(htons(6)) // TCP PROTO
            csum += uint32(htons(uint16(tcpLen)))

            // old chksum
            payload[16] = 0
            payload[17] = 0

            var i int
            for tcpLen > 1 {
                csum += uint32(payload[i]) << 8
                csum += uint32(payload[i+1])
                tcpLen -= 2
                i++
            }

            if tcpLen % 2 == 1 {
                csum += uint32(payload[tcpLen - 1]) << 8
            }

            for csum > 0xffff{
                csum = (csum >> 16) + (csum & 0xffff)
            }
             return ^uint16(csum)
          }
// output
 [69 0 0 60 179 32 64 0 64 6 108 0 192 168 77 61 192 168 77 13 203 50 
0 22 69 21 146 157 0 0 0 0 160 194 250 240 65 21 0 0 2 4 5 180 4 2 8
10 38 105 38 58 0 0 0 0 1 3 3 7]
src chkSumOriginaltcp = 0x4115 calc chkSumFaketcp = 0x72e8

Please tell me where I could be mistaken, it is very important to me

Upvotes: 0

Views: 409

Answers (1)

Denis Stein
Denis Stein

Reputation: 11

func chksum(data []byte, srcip, dstip []byte) uint16 {
         data[16],data[17] = 0,0 //zero on original check sum
       psheader := []byte{
         srcip[0], srcip[1], srcip[2], srcip[3],
         dstip[0], dstip[1], dstip[2], dstip[3],
         0,
         6,                  //  TCP
         0, byte(len(data)), //  length (16 bits)
       }

       csum := make([]byte, 0, len(psheader)+len(data))
       csum = append(csum, psheader...)
       csum = append(csum, data...)


       lenSumThis := len(csum)
       var word uint16
       var sum uint32
       for i := 0; i+1 < lenSumThis; i += 2 {
         word = uint16(csum[i])<<8 | uint16(csum[i+1])
         sum += uint32(word)
       }
       if lenSumThis%2 != 0 {
               sum += uint32(csum[len(csum)-1])
       }

       sum = (sum >> 16) + (sum & 0xffff)
       sum = sum + (sum >> 16)

       return uint16(^sum)
     }

Upvotes: 1

Related Questions