J
J
jajabin2020-06-11 14:48:48
go
jajabin, 2020-06-11 14:48:48

How to correctly calculate the tcp checksum of a packet?

I'm trying to implement a checksum calculation algorithm using this link
. Here is an example of a byte slice and checksums for it.

[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
[69 0 0 60 0 0 64 0 64 6 31 33 192 168 77 13 192 168 77 61 0 22 203 50 88 167 128 107 69 21 146 158 160 82 113 32 198 58 0 0 2 4 5 180 4 2 8 10 246 88 53 174 38 105 38 58 1 3 3 7]
src chkSumOriginaltcp = 0xc63a calc chkSumFaketcp = 0xa550

And also my code for implementation, tell me what I'm doing wrong.
var buff = make([]byte,len(payload))
    copy(buff,payload)
    ip, _ := ipv4.ParseHeader(buff)
    checkSum := chksum(ip,buff[ip.Len:])
    tcp := payload[ip.Len:]
    checkSumTcp := binary.BigEndian.Uint16(tcp[16:])
    fmt.Printf("src chkSumOriginaltcp = %#x calc chkSumFaketcp = %#x\n",checkSumTcp,checkSum)


//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)))

  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)
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
J
jajabin, 2020-06-13
@jajabin

I'll leave this here for anyone who needs it.

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)
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question