Reputation: 13
I am learning about raw socket programming in Linux and during a tutorial I noticed a coincidence with this code:
struct ipheader {
unsigned char iph_ihl:5, iph_ver:4; //<--------------These
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_ident;
unsigned char iph_flag;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};
iph_ver
holds the IP version which will be 4, and iph_ihl
holds the header length which will be set to 5. Since header length is described in 4 byte words the actual header length comes out to be 5×4=20 bytes. 20 bytes is the minimum length. With that being said I am curious if the bit fields in this structure, set for iph_ver
and iph_ihl
, are specifically 4 and 5 because it will be IPv4 and the IP header will be 20 bytes in length. However I am unsure how their bit fields would have any effect or correlation on their value. Any explanations would be greatly appreciated.
Link to code: http://www.tenouk.com/Module43a.html
Upvotes: 1
Views: 422
Reputation: 144695
The code fragment from this tutorial is actually wrong!
Here is a correct definition for the IP packet header:
/*
* Structure of an internet header, naked of options.
*
* We declare ip_len and ip_off to be short, rather than u_short
* pragmatically since otherwise unsigned comparisons can result
* against negative integers quite easily, and fail in subtle ways.
*/
struct ip {
#if BYTE_ORDER == LITTLE_ENDIAN
u_char ip_hl:4, /* header length */
ip_v:4; /* version */
#endif
#if BYTE_ORDER == BIG_ENDIAN
u_char ip_v:4, /* version */
ip_hl:4; /* header length */
#endif
u_char ip_tos; /* type of service */
short ip_len; /* total length */
u_short ip_id; /* identification */
short ip_off; /* fragment offset field */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
As you can see, both ip_hl
and ip_v
are 4 bit wide bitfields. The actual names of the fields do not matter, just their position in the packet header.
They are defined in a different order depending on the platform because the compiler allocates bitfields differently depending on endianness. This behavior is actually not specified in the C Standard, but seems to be consistent across platforms.
Upvotes: 1