IP header data structure problem

My sniffer that uses raw sockets displays some data related to ip header in a wrong way, three unsigned shorts in particular. The rest of data output seems to be correct.

This is a piece of output of random packet:


Header information:
 45 00 00 3c 73 85 00 00 80 11 45 72 c0 a8 00 60          E..<s.....Er...` 
 c0 a8 00 09                                              .... 

1) IP header length: 5 
2) IP protocol version: 4 
3) Type of service : 0 
4) Total length : 15360 - wrong!
5) Identification : 34163 - wrong! 
6) Fragment offset field : 0 
7) More fragment: 0 
8) Don't' fragment: 0 
9) Reserver to zero: 0 
10) Fragment offset again: 0 
11) Time to live: 128 
12) Protocol: 17 
13) IP checksum: 29253 - wrong!
14) Source: 192.168.0.96 
15) Destination: 192.168.0.9 


This is my data structure for IP header:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct IP_HEADER
{
    unsigned char  iph_header_len    :4;	
    unsigned char  iph_version       :4;	
    unsigned char  iph_tos;					 
    unsigned short iph_total_length;		
    unsigned short iph_id;					
    unsigned char  iph_frag_offset   :5;	
    unsigned char  iph_more_fragment :1;	
    unsigned char  iph_dont_fragment :1;	
    unsigned char  iph_reserved_zero :1;	
    unsigned char  iph_frag_offset1;		
    unsigned char  iph_ttl;					
    unsigned char  iph_protocol;			
    unsigned short iph_checksum;			
    IN_ADDR        iph_source;				
    IN_ADDR        iph_destination;			
};


Let's take packet length value, it is byte 3 and 4.
00 3c in hex equals 60 in decimal. This is correct value, packet is 60 bytes long, this is what output is supposed to show.

But whenever I use ip_header->iph_header_len to output data, two bytes that unsigned short occupies for some reason get twisted. Instead of 60 I get 15360 which equals 3c 00 in hex. This happens for each of three unsigned shorts in this structure. Why are they changing order?

What's wrong? I suppose this is related to alignment because it's not the first time I come across a problem with shorts inside structs. Compiler is MSVC 2010.
Last edited on
The byte order is backwards... Try this cheat:
1
2
unsigned short bad_len = ip_header->iph_header_len; 
unsigned short real_len = ((bad_len & 0x00FF) << 8) | ((bad_len & 0xFF00) >> 8); //swaping the bytes 
That sounds like an endianness issue. x86 is a little-endian architecture, wherein the least significant bytes come first. However, that short is a big-endian short, where the most significant bytes come first.

EDIT: Ninja'd.

http://en.wikipedia.org/wiki/Endianness

-Albatross
Last edited on
If you want to know an explanation of how it works, this can help: http://rclermont.blogspot.ca/2010/02/convert-long-into-byte-array-in-cc.html
(the int casts are unnecessary and "|" is equal to "+"
Thanks for links and advice! Changing byte order with ntohs helped. I'd like to make sure I understand this concept correctly: every time I read or write packet do I have to shift byte order this way? Is this a must not just for headers but for payload data as well?

Let's assume I want to construct packet and send it, using htons to convert byte order. Would the following piece of code be correct?

1
2
3
4
5
6
7
8
9
10
11
12
13
struct some_packet
{
    // some members here
    unsigned short some_short;
    unsigned int some_int;
    // some members there
}PACKET;

unsigned short short_to_fill = 123;
PACKET.some_short = htons(short_to_fill);

unsigned int int_to_fill = 123;
PACKET.some_int = htons(int_to_fill);

> Is this a must not just for headers but for payload data as well?

Favour sending payload data as plain text (ideally utf-8).
http://catb.org/~esr/writings/taoup/html/ch05s01.html

If binary data is to be sent and received:
you'll want to convert the numbers to Network Byte Order before they go out on the wire, and convert them to Host Byte Order as they come in off the wire.
http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#byteorder

In addition, the layout of some_packet (size and alignment of members) would have to be the same on both sides.
Alright, thanks for clearing it up.
Topic archived. No new replies allowed.