FAQ
Hi All, i'm try to calculate checksum of ip packet and stuck =(.
My code looks like

func checksum(b []byte) (sum uint16) {
         if len(b)%2 != 0 {
                 b = append(b, byte(0))
         }

         for _, v := range b {
                 sum += uint16(v)
         }

         sum = (sum & 0xffff) + (sum >> 16)
         sum += (sum >> 16)
         return (^sum & 0xffff)
}

That used like this:
func main() {
         hdr := new(bytes.Buffer)
         buf := new(bytes.Buffer)
         var verIhl uint8 = (i.Version << 4) + i.IHL
         binary.Write(hdr, binary.BigEndian, verIhl)
         var dscpEcn uint8 = (i.DSCP << 2) + i.ECN
         binary.Write(hdr, binary.BigEndian, dscpEcn)
         binary.Write(hdr, binary.BigEndian, i.Length)
         binary.Write(hdr, binary.BigEndian, i.ID)
         var flagsFrag uint16 = (i.Flags << 13) + i.FragmentOffset
         binary.Write(hdr, binary.BigEndian, flagsFrag)
         binary.Write(hdr, binary.BigEndian, i.TTL)
         binary.Write(hdr, binary.BigEndian, i.Protocol)
         binary.Write(hdr, binary.BigEndian, i.Checksum)
         binary.Write(hdr, binary.BigEndian, i.NWSrc)
         binary.Write(hdr, binary.BigEndian, i.NWDst)
         binary.Write(hdr, binary.BigEndian, i.Options)
         if i.Checksum == 0 {
                 i.Checksum = checksum(hdr.Bytes())
         }
         io.CopyN(buf, hdr, 10)
         binary.Write(buf, binary.BigEndian, i.Checksum)
         binary.Write(buf, binary.BigEndian, i.NWSrc)
         binary.Write(buf, binary.BigEndian, i.NWDst)
         binary.Write(buf, binary.BigEndian, i.Options)
}

but wireshark says that my checksum not right.
Can somebody helps me?
--
Vasiliy Tolstov,
e-mail: v.tolstov@selfip.ru
jabber: vase@selfip.ru

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Search Discussions

  • Jan Mercl at Sep 19, 2013 at 6:53 am

    On Thu, Sep 19, 2013 at 8:40 AM, Vasiliy Tolstov wrote:
    func checksum(b []byte) (sum uint16) {
    if len(b)%2 != 0 {
    b = append(b, byte(0))
    }
    The 3 lines above do nothing observable wrt the returned result.
    for _, v := range b {
    sum += uint16(v)
    }

    sum = (sum & 0xffff) + (sum >> 16)
    Above line is a no operation.
    sum += (sum >> 16)
    Above line is a no operation.
    return (^sum & 0xffff)
    Above line is equal to 'return' ^sum.
    }

    You're using parenthesis in places where they are not changing the
    evaluation order. And 'return (expression)' can be written as 'return
    expression'.

    -j

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Vasiliy Tolstov at Sep 19, 2013 at 7:18 am

    2013/9/19 Jan Mercl <0xjnml@gmail.com>:
    On Thu, Sep 19, 2013 at 8:40 AM, Vasiliy Tolstov wrote:
    func checksum(b []byte) (sum uint16) {
    if len(b)%2 != 0 {
    b = append(b, byte(0))
    }
    The 3 lines above do nothing observable wrt the returned result.
    for _, v := range b {
    sum += uint16(v)
    }

    sum = (sum & 0xffff) + (sum >> 16)
    Above line is a no operation.
    sum += (sum >> 16)
    Above line is a no operation.
    return (^sum & 0xffff)
    Above line is equal to 'return' ^sum.
    }

    You're using parenthesis in places where they are not changing the
    evaluation order. And 'return (expression)' can be written as 'return
    expression'.

    Thanks for suggestions. I'm using as base this C code:
    http://web.cecs.pdx.edu/~jrb/tcpip/misc.src/checksum.c

    --
    Vasiliy Tolstov,
    e-mail: v.tolstov@selfip.ru
    jabber: vase@selfip.ru

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Chris dollin at Sep 19, 2013 at 7:29 am

    On 19 September 2013 07:40, Vasiliy Tolstov wrote:

    Hi All, i'm try to calculate checksum of ip packet and stuck =(.
    My code looks like

    func checksum(b []byte) (sum uint16) {
    if len(b)%2 != 0 {
    b = append(b, byte(0))
    }

    for _, v := range b {
    sum += uint16(v)
    }

    sum = (sum & 0xffff) + (sum >> 16)
    sum += (sum >> 16)
    return (^sum & 0xffff)
    }

    That used like this:
    func main() {
    hdr := new(bytes.Buffer)
    buf := new(bytes.Buffer)
    var verIhl uint8 = (i.Version << 4) + i.IHL
    binary.Write(hdr, binary.BigEndian, verIhl)
    var dscpEcn uint8 = (i.DSCP << 2) + i.ECN
    binary.Write(hdr, binary.BigEndian, dscpEcn)
    binary.Write(hdr, binary.BigEndian, i.Length)
    binary.Write(hdr, binary.BigEndian, i.ID)
    var flagsFrag uint16 = (i.Flags << 13) + i.FragmentOffset
    binary.Write(hdr, binary.BigEndian, flagsFrag)
    binary.Write(hdr, binary.BigEndian, i.TTL)
    binary.Write(hdr, binary.BigEndian, i.Protocol)
    binary.Write(hdr, binary.BigEndian, i.Checksum)
    binary.Write(hdr, binary.BigEndian, i.NWSrc)
    binary.Write(hdr, binary.BigEndian, i.NWDst)
    binary.Write(hdr, binary.BigEndian, i.Options)
    if i.Checksum == 0 {
    i.Checksum = checksum(hdr.Bytes())
    }
    io.CopyN(buf, hdr, 10)
    binary.Write(buf, binary.BigEndian, i.Checksum)
    binary.Write(buf, binary.BigEndian, i.NWSrc)
    binary.Write(buf, binary.BigEndian, i.NWDst)
    binary.Write(buf, binary.BigEndian, i.Options)
    }

    but wireshark says that my checksum not right.
    Can somebody helps me?
    The C version has `sum` as a 32-bit variable, not a 16-bit variable.
    So it will hold bits "to the left" of the low 16 bits, which will be
    available when you do the right shifts (and make the 16-bit mask
    relevant).

    Chris

    --
    Chris "allusive" Dollin

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Vasiliy Tolstov at Sep 19, 2013 at 7:38 am

    2013/9/19 chris dollin <ehog.hedge@googlemail.com>:
    The C version has `sum` as a 32-bit variable, not a 16-bit variable.
    So it will hold bits "to the left" of the low 16 bits, which will be
    available when you do the right shifts (and make the 16-bit mask
    relevant).

    Okay. Does this looks correct?

    func checksum(b []byte) uint16 {
       csumcv := len(b) - 1
       s := uint32(0)
       for i := 0; i < csumcv; i += 2 {
         s += uint32(b[i])
       }
       if csumcv&1 == 0 {
         s += uint32(b[csumcv])
       }
       s = s>>16 + s&0xffff
       s += s>>16

       return uint16(^s & 0xffff)
    }


    --
    Vasiliy Tolstov,
    e-mail: v.tolstov@selfip.ru
    jabber: vase@selfip.ru

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Rémy Oudompheng at Sep 19, 2013 at 7:48 am
    This loop only sums half of the input bytes.

    Rémy.

    2013/9/19, Vasiliy Tolstov <v.tolstov@selfip.ru>:
    2013/9/19 chris dollin <ehog.hedge@googlemail.com>:
    The C version has `sum` as a 32-bit variable, not a 16-bit variable.
    So it will hold bits "to the left" of the low 16 bits, which will be
    available when you do the right shifts (and make the 16-bit mask
    relevant).

    Okay. Does this looks correct?

    func checksum(b []byte) uint16 {
    csumcv := len(b) - 1
    s := uint32(0)
    for i := 0; i < csumcv; i += 2 {
    s += uint32(b[i])
    }
    if csumcv&1 == 0 {
    s += uint32(b[csumcv])
    }
    s = s>>16 + s&0xffff
    s += s>>16

    return uint16(^s & 0xffff)
    }


    --
    Vasiliy Tolstov,
    e-mail: v.tolstov@selfip.ru
    jabber: vase@selfip.ru

    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Vasiliy Tolstov at Sep 19, 2013 at 7:56 am

    2013/9/19 Rémy Oudompheng <remyoudompheng@gmail.com>:
    This loop only sums half of the input bytes.
    my mistake. now its sums all bytes, but sum now right =(

    func checksum(b []byte) uint16 {
             csumcv := len(b) - 1
             s := uint32(0)
             for i := 0; i < csumcv; i++ {
                     s += uint32(b[i])
             }
             if csumcv&1 == 0 {
                     s += uint32(b[csumcv])
             }
             s = s>>16 + s&0xffff
             s += s >> 16

             return uint16(^s & 0xffff)
    }


    --
    Vasiliy Tolstov,
    e-mail: v.tolstov@selfip.ru
    jabber: vase@selfip.ru

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Vasiliy Tolstov at Sep 19, 2013 at 9:42 am
    Okay i'm write checksum calc like this:

    func checksum(b []byte) uint16 {
             csumcv := len(b) - 1 // checksum coverage
             s := uint32(0)
             for i := 0; i < csumcv; i += 2 {
                     s += uint32(b[i+1])<<8 | uint32(b[i])
             }
             if csumcv&1 == 0 {
                     s += uint32(b[csumcv])
             }
             s = s>>16 + s&0xffff
             s = s + s>>16
             return uint16(s & 0xffff)
    }

    it provides correct checksum, but after writing it via
    binary.BigEndian i get swapped bytes.
    For ex. 0xfe76 but righ sum is 0x76fe.
    How can i return from checksum func bytes that after writing via
    encoding/binary provide correct sum?


    2013/9/19 Vasiliy Tolstov <v.tolstov@selfip.ru>:
    2013/9/19 Rémy Oudompheng <remyoudompheng@gmail.com>:
    This loop only sums half of the input bytes.
    my mistake. now its sums all bytes, but sum now right =(

    func checksum(b []byte) uint16 {
    csumcv := len(b) - 1
    s := uint32(0)
    for i := 0; i < csumcv; i++ {
    s += uint32(b[i])
    }
    if csumcv&1 == 0 {
    s += uint32(b[csumcv])
    }
    s = s>>16 + s&0xffff
    s += s >> 16

    return uint16(^s & 0xffff)
    }


    --
    Vasiliy Tolstov,
    e-mail: v.tolstov@selfip.ru
    jabber: vase@selfip.ru


    --
    Vasiliy Tolstov,
    e-mail: v.tolstov@selfip.ru
    jabber: vase@selfip.ru

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedSep 19, '13 at 6:40a
activeSep 19, '13 at 9:42a
posts8
users4
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase