TCP Checksum C# - TCP-IP

This is a discussion on TCP Checksum C# - TCP-IP ; Hi, I am generating packets manually and seem to have some trouble getting the TCP checksum generation functioning correctly. Can anyone see what the problem may be? static ushort GetChecksum(byte[] IPHeader, byte[] TCPHeader) { int sum = 0; for (int ...

+ Reply to Thread
Results 1 to 10 of 10

Thread: TCP Checksum C#

  1. TCP Checksum C#

    Hi,

    I am generating packets manually and seem to have some trouble getting
    the TCP checksum generation functioning correctly. Can anyone see
    what
    the problem may be?

    static ushort GetChecksum(byte[] IPHeader, byte[] TCPHeader)
    {
    int sum = 0;
    for (int x = 0; x < TCPHeader.Length; x += 2)
    {
    sum +=
    IPAddress.NetworkToHostOrder(BitConverter.ToInt16( TCPHeader,
    x));
    }
    sum +=
    IPAddress.NetworkToHostOrder(BitConverter.ToInt16( IPHeader,
    12));
    sum +=
    IPAddress.NetworkToHostOrder(BitConverter.ToInt16( IPHeader,
    14));
    sum +=
    IPAddress.NetworkToHostOrder(BitConverter.ToInt16( IPHeader,
    16));
    sum +=
    IPAddress.NetworkToHostOrder(BitConverter.ToInt16( IPHeader,
    18));
    sum += 6;
    sum += TCPHeader.Length;
    while ((sum >> 16) != 0) { sum = ((sum & 0xFFFF) + (sum >>
    16)); }
    sum = ~sum;
    return (ushort)IPAddress.NetworkToHostOrder((short)sum) ;
    }

    It always comes out pretty close though, within 1 or 2? (I check this
    using Wireshark)

    Thanks in advance!

    Tris


  2. Re: TCP Checksum C#

    Tris.Phillips@gmail.com writes:

    > I am generating packets manually and seem to have some trouble getting
    > the TCP checksum generation functioning correctly. Can anyone see
    > what the problem may be?
    >...
    > sum +=
    > IPAddress.NetworkToHostOrder(BitConverter.ToInt16( TCPHeader,
    > x));
    >...


    Everything in the checksum should be in network order.

    >...
    > return (ushort)IPAddress.NetworkToHostOrder((short)sum) ;


    And the resulting checksum should be left in network order.
    -don

  3. Re: TCP Checksum C#

    In article , don provan writes:
    > Tris.Phillips@gmail.com writes:
    >
    >> I am generating packets manually and seem to have some trouble getting
    >> the TCP checksum generation functioning correctly. Can anyone see
    >> what the problem may be?
    >>...
    >> sum +=
    >> IPAddress.NetworkToHostOrder(BitConverter.ToInt16( TCPHeader,
    >> x));
    >>...

    >
    > Everything in the checksum should be in network order.
    >
    >>...
    >> return (ushort)IPAddress.NetworkToHostOrder((short)sum) ;

    >
    > And the resulting checksum should be left in network order.


    As you're probably aware, it will work either way. Leaving the bytes
    in network order is more efficient -- it saves a lot of byte flipping.
    But flipping each word to host byte order, adding up the column of
    numbers and then flipping the resulting sum back to network byte order
    will give the same result.

    One gotcha...

    >> sum += 6;
    >> sum += TCPHeader.Length;


    If you were to change the checksum calculation to work in a network
    byte order convention then these two words would need to be flipped
    to network byte order before being added into the sum.

    I couldn't find any flaws with the original posted code except for
    the buffer overrun on odd length packets.

  4. Re: TCP Checksum C#

    On Sep 18, 5:53 pm, bri...@encompasserve.org wrote:
    > In article , don provan writes:
    > > Tris.Phill...@gmail.com writes:

    >
    > >> I am generating packets manually and seem to have some trouble getting
    > >> the TCP checksum generation functioning correctly. Can anyone see
    > >> what the problem may be?
    > >>...
    > >> sum +=
    > >> IPAddress.NetworkToHostOrder(BitConverter.ToInt16( TCPHeader,
    > >> x));
    > >>...

    >
    > > Everything in the checksum should be in network order.

    >
    > >>...
    > >> return (ushort)IPAddress.NetworkToHostOrder((short)sum) ;

    >
    > > And the resulting checksum should be left in network order.

    >
    > As you're probably aware, it will work either way. Leaving the bytes
    > in network order is more efficient -- it saves a lot of byte flipping.
    > But flipping each word to host byte order, adding up the column of
    > numbers and then flipping the resulting sum back to network byte order
    > will give the same result.
    >
    > One gotcha...
    >
    > >> sum += 6;
    > >> sum += TCPHeader.Length;

    >
    > If you were to change the checksum calculation to work in a network
    > byte order convention then these two words would need to be flipped
    > to network byte order before being added into the sum.
    >
    > I couldn't find any flaws with the original posted code except for
    > the buffer overrun on odd length packets.


    Hmmmm, so none the wiser... As this is just SYN packets at the moment,
    there is no data, so no odd length issue.
    Thanks for your response though.


  5. Re: TCP Checksum C#

    briggs@encompasserve.org writes:

    > don provan writes:
    >> Tris.Phillips@gmail.com writes:
    >>
    >>> I am generating packets manually and seem to have some trouble getting
    >>> the TCP checksum generation functioning correctly. Can anyone see
    >>> what the problem may be?

    >>
    >> And the resulting checksum should be left in network order.

    >
    > As you're probably aware, it will work either way.


    I thought he was only swapping addresses into host order, but I guess
    I didn't understand the code well enough. Obviously everything has to
    be added to the checksum in the same order.

    Still, swapping into host order is the equivalent of summing a bunch
    of numbers by first negating all of them before summing, and then
    negating the results of the sum. Yeah, it works, but what's the point?
    Besides, in a case like this, the problem's probably going to turn out
    to be some value he missed swapping.

    -don

  6. Re: TCP Checksum C#

    In article , don provan writes:
    > briggs@encompasserve.org writes:
    >
    >> don provan writes:
    >>> Tris.Phillips@gmail.com writes:
    >>>
    >>>> I am generating packets manually and seem to have some trouble getting
    >>>> the TCP checksum generation functioning correctly. Can anyone see
    >>>> what the problem may be?
    >>>
    >>> And the resulting checksum should be left in network order.

    >>
    >> As you're probably aware, it will work either way.

    >
    > I thought he was only swapping addresses into host order, but I guess
    > I didn't understand the code well enough. Obviously everything has to
    > be added to the checksum in the same order.
    >
    > Still, swapping into host order is the equivalent of summing a bunch
    > of numbers by first negating all of them before summing, and then
    > negating the results of the sum. Yeah, it works, but what's the point?


    Agreed.

    > Besides, in a case like this, the problem's probably going to turn out
    > to be some value he missed swapping.


    I didn't see any. And he claimed that it was only "off by one or two".

    A swap error would be likely to mangle the checksum pretty severely.
    With an off by one or two, the plausible errors are more in the
    area of a failed end-around carry calculation, a mistaken length
    convention, a buffer overrun with a low value in the next cell
    or a problem with signed versus unsigned arithmetic (which would
    then affect the end-around carry and create an off-by-one-or-two
    error).

    If I were the OP, I'd be lacing that code liberally with "print"
    statements for debugging and I'd make sure that all the intermediate
    results are as expected and that everything matches a hand
    calculation.

  7. Re: TCP Checksum C#

    On Sep 20, 6:23 pm, bri...@encompasserve.org wrote:
    > In article , don provan writes:
    > > bri...@encompasserve.org writes:

    >
    > >> don provan writes:
    > >>> Tris.Phill...@gmail.com writes:

    >
    > >>>> I am generating packets manually and seem to have some trouble getting
    > >>>> the TCP checksum generation functioning correctly. Can anyone see
    > >>>> what the problem may be?

    >
    > >>> And the resulting checksum should be left in network order.

    >
    > >> As you're probably aware, it will work either way.

    >
    > > I thought he was only swapping addresses into host order, but I guess
    > > I didn't understand the code well enough. Obviously everything has to
    > > be added to the checksum in the same order.

    >
    > > Still, swapping into host order is the equivalent of summing a bunch
    > > of numbers by first negating all of them before summing, and then
    > > negating the results of the sum. Yeah, it works, but what's the point?

    >
    > Agreed.
    >
    > > Besides, in a case like this, the problem's probably going to turn out
    > > to be some value he missed swapping.

    >
    > I didn't see any. And he claimed that it was only "off by one or two".
    >
    > A swap error would be likely to mangle the checksum pretty severely.
    > With an off by one or two, the plausible errors are more in the
    > area of a failed end-around carry calculation, a mistaken length
    > convention, a buffer overrun with a low value in the next cell
    > or a problem with signed versus unsigned arithmetic (which would
    > then affect the end-around carry and create an off-by-one-or-two
    > error).
    >
    > If I were the OP, I'd be lacing that code liberally with "print"
    > statements for debugging and I'd make sure that all the intermediate
    > results are as expected and that everything matches a hand
    > calculation.


    Yep, I'm coming round to the idea its probably a signing error.
    Ill try to check as I go.
    Thanks for your help.
    Tris


  8. Re: TCP Checksum C#

    On Sep 21, 10:15 am, Tris.Phill...@gmail.com wrote:
    > On Sep 20, 6:23 pm, bri...@encompasserve.org wrote:
    >
    >
    >
    > > In article , don provan writes:
    > > > bri...@encompasserve.org writes:

    >
    > > >> don provan writes:
    > > >>> Tris.Phill...@gmail.com writes:

    >
    > > >>>> I am generating packets manually and seem to have some trouble getting
    > > >>>> the TCP checksum generation functioning correctly. Can anyone see
    > > >>>> what the problem may be?

    >
    > > >>> And the resulting checksum should be left in network order.

    >
    > > >> As you're probably aware, it will work either way.

    >
    > > > I thought he was only swapping addresses into host order, but I guess
    > > > I didn't understand the code well enough. Obviously everything has to
    > > > be added to the checksum in the same order.

    >
    > > > Still, swapping into host order is the equivalent of summing a bunch
    > > > of numbers by first negating all of them before summing, and then
    > > > negating the results of the sum. Yeah, it works, but what's the point?

    >
    > > Agreed.

    >
    > > > Besides, in a case like this, the problem's probably going to turn out
    > > > to be some value he missed swapping.

    >
    > > I didn't see any. And he claimed that it was only "off by one or two".

    >
    > > A swap error would be likely to mangle the checksum pretty severely.
    > > With an off by one or two, the plausible errors are more in the
    > > area of a failed end-around carry calculation, a mistaken length
    > > convention, a buffer overrun with a low value in the next cell
    > > or a problem with signed versus unsigned arithmetic (which would
    > > then affect the end-around carry and create an off-by-one-or-two
    > > error).

    >
    > > If I were the OP, I'd be lacing that code liberally with "print"
    > > statements for debugging and I'd make sure that all the intermediate
    > > results are as expected and that everything matches a hand
    > > calculation.

    >
    > Yep, I'm coming round to the idea its probably a signing error.
    > Ill try to check as I go.
    > Thanks for your help.
    > Tris


    Got it!

    Signing was indeed the issue.
    To aid others, here is the working code:

    ushort GetTCPChecksum(byte[] IPHeader, byte[] TCPHeader)
    {
    uint sum = 0;
    // TCP Header
    for (int x = 0; x < TCPHeader.Length; x += 2)
    {
    sum += ntoh(BitConverter.ToUInt16(TCPHeader, x));
    }
    // Pseudo header - Source Address
    sum += ntoh(BitConverter.ToUInt16(IPHeader, 12));
    sum += ntoh(BitConverter.ToUInt16(IPHeader, 14));
    // Pseudo header - Dest Address
    sum += ntoh(BitConverter.ToUInt16(IPHeader, 16));
    sum += ntoh(BitConverter.ToUInt16(IPHeader, 18));
    // Pseudo header - Protocol
    sum += ntoh(BitConverter.ToUInt16(new byte[] { 0, IPHeader[9] }, 0));
    // Pseudo header - TCP Header length
    sum += (UInt16)TCPHeader.Length;
    // 16 bit 1's compliment
    while ((sum >> 16) != 0) { sum = ((sum & 0xFFFF) + (sum >> 16)); }
    sum = ~sum;
    return (ushort)ntoh((UInt16)sum);
    }

    private ushort ntoh(UInt16 In)
    {
    int x = IPAddress.NetworkToHostOrder(In);
    return (ushort) (x >> 16);
    }

    Thanks to all.

    Tris


  9. Re: TCP Checksum C#

    Tris.Phillips@gmail.com writes:

    > Got it!
    >
    > Signing was indeed the issue.
    > To aid others, here is the working code:


    Now get rid of the ntoh routine altogether, and you'll have a
    reasonable checksum routine.

    > private ushort ntoh(UInt16 In)
    > {
    > int x = IPAddress.NetworkToHostOrder(In);
    > return (ushort) (x >> 16);
    > }


    The whole idea behind ntoh class functions is to make the code
    portable, so it's ironic that what you've implemented here is little
    endian specific. You might as well have called it "swap" and
    implemented it as "return (x >> 8) | ((x & 0xff) << 8)". But, again,
    you're much better off working entirely in network order which,
    magically, will make your code portable.

    -don

  10. Re: TCP Checksum C#

    On Sep 21, 5:53 pm, don provan wrote:
    > Tris.Phill...@gmail.com writes:
    > > Got it!

    >
    > > Signing was indeed the issue.
    > > To aid others, here is the working code:

    >
    > Now get rid of the ntoh routine altogether, and you'll have a
    > reasonable checksum routine.
    >
    > > private ushort ntoh(UInt16 In)
    > > {
    > > int x = IPAddress.NetworkToHostOrder(In);
    > > return (ushort) (x >> 16);
    > > }

    >
    > The whole idea behind ntoh class functions is to make the code
    > portable, so it's ironic that what you've implemented here is little
    > endian specific. You might as well have called it "swap" and
    > implemented it as "return (x >> 8) | ((x & 0xff) << 8)". But, again,
    > you're much better off working entirely in network order which,
    > magically, will make your code portable.
    >
    > -don


    Thanks Don, Ill take a look at doing that.


+ Reply to Thread