TCP and IP header

Started by
3 comments, last by Monder 17 years ago
I'm writing a small program that decodes TCP and IP headers from a file that is a dump of the raw packets, and there's a couple of aspects about them that puzzle me. The layout for the IP and TCP headers are given in their RFCs as this: IP:

    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |Version|  IHL  |Type of Service|          Total Length         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Identification        |Flags|      Fragment Offset    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Time to Live |    Protocol   |         Header Checksum       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                       Source Address                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Destination Address                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
TCP:

    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          Source Port          |       Destination Port        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Sequence Number                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Acknowledgment Number                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Data |           |U|A|P|R|S|F|                               |
   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
   |       |           |G|K|H|T|N|N|                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Checksum            |         Urgent Pointer        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             data                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Now the bits I'm having trouble with are the version and IHL fields in the IP header and the Data Offset field in the TCP header in that they don't seem to be located where these diagrams indicate they are. In the IP header I read the diagram as saying the first 4 bits of the IP header are the version and the next 4 bits are the IHL. However if I look at the first byte of an example IP raw packet dump it's 0x45, so the first nibble (first 4 bits) is 0x5 which is the IHL and the next nibble (next 4 bits) is 0x4 which is the version, this seems to be the opposite way round to what the diagram indicates. Similarly for the Data Offset field if I look at the first byte of the 3rd 32-bit word of the raw TCP packet dump, it's 0xA0, so the first nibble is 0 which is part of the reserved field and the next nibble is A which is the data offset, again they are the opposite way round to what I would expect from the diagram. I'm obviously looking at this in wrong way somewhere, so where am I going wrong?
Advertisement
http://en.wikipedia.org/wiki/Endianness

Also, ntohs and ntohl are functions you might want to look up, and see why they exist.
Note that endianness does not swap the bits, only the bytes.

However, it is true that the specifications are defined in network byte/bit order, which means the most significant bit comes first.
enum Bool { True, False, FileNotFound };
Well for the first byte of the IP header the two nibbles are swapped compared to what I'd expect them to be. I'm well aware of the endianess issue and as hplus0603 pointed out that's to do with byte order not bit order. Now if the first byte was transmitted most significant bit first then I'd either have a complete mirror image of the expected value for the first byte (I'd expect 0x54, so if you mirror its binary representation you get 0x2A) of I'd just have the first byte as expected, in either case the two nibbles would not be simply swapped round.

Also when reading 16-bit fields such as total length in the IP field, internally the bytes are as you would expect you just need to handle the endianess issue using ntohs. So why would the first byte be rearranged compared to what I'd expect but the others not?
I've now realised where I'm going wrong, as hplus0603 said most significant bit is transmitted first and this is bit 0 on the diagram and I was thinking the most significant bit of the first byte would be bit 7 on the diagram which is what confused me [embarrass]. It makes sense now. Thanks for the help.

This topic is closed to new replies.

Advertisement