1

I have a problem to understand how I can use this macro to get the lenght of the IP header. I have a file called framehdr.h and I have included that file in my main.c. The struct in the framehdr.h file look like this:

struct ip_hdr {
    unsigned char vhl;     /* Version and header length */
    unsigned char tos;     /* Type of service */
    unsigned short len;    /* Total length */
    unsigned short id;     /* Identification */
    unsigned short off;    /* Fragment offset field */
    unsigned char ttl;     /* Time to live */
    unsigned char p;       /* Protocol */
    unsigned short ip_sum; /* Checksum */
    unsigned int src, dst; /* Source and dest address */
};

I can manually get the lentgh by adding all the sizes like this:

unsigned int sizeIP = sizeof(testOne.vhl) + sizeof(testOne.tos)    +
                      sizeof(testOne.len) + sizeof(testOne.id)     + 
                      sizeof(testOne.off) + sizeof(testOne.ttl)    + 
                      sizeof(testOne.p)   + sizeof(testOne.ip_sum) +
                      sizeof(testOne.src) + sizeof(testOne.dst);

But I'm suppose to use the macro that look like this to get the size:

#define IP_HL(ip) ((((ip)->vhl) & 0x0f) * 4)

What does this macro return? Is it a digit so I can store it in a int and then print it or how does it work?

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
anderssinho
  • 298
  • 2
  • 7
  • 21
  • 2
    Since when a MACRO `return`s anything? – Sourav Ghosh Dec 14 '17 at 09:25
  • 1
    @SouravGhosh Okay does it not return anything? How do I use it then? Can you maybe give me a tip of any material I can read up on this subject? – anderssinho Dec 14 '17 at 09:26
  • 1
    `int header_length = IP_HL(pointer_to_struct);` – mch Dec 14 '17 at 09:27
  • 2
    Macro invocations are *replaced* by the preprocessor. If you have e.g. `IP_HL(x)` then that will be replaced by `((((x)->vhl) & 0x0f) * 4)`. – Some programmer dude Dec 14 '17 at 09:27
  • @mch okay will try that! But I tried that before so must have done something wrong then. I'll get back when I tried it – anderssinho Dec 14 '17 at 09:28
  • 2
    A macro does not return anything, but in this case, it evaluates to an `int`. – mch Dec 14 '17 at 09:28
  • 4
    Also note that [the size of a `struct` might not be the same as the sum of the size of all its members](http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member). – Some programmer dude Dec 14 '17 at 09:28
  • @Someprogrammerdude yeah I have already noticed that but we are suppose to use this macro. But thanks for the notice – anderssinho Dec 14 '17 at 09:29
  • @mch If I have a created a struct ip_hdr testOne in the main.c file. Can I make it a pointer by using the &testOne and give it to the IP_HL() macro or do I need to create a new pointer and point it to the testOne since the testOne is where I read in the values from a file to? – anderssinho Dec 14 '17 at 09:36

1 Answers1

4

It looks like vhl (which is an 8 bit member, unless CHAR_BIT is a weird value on your platform) is used to store the version in the significant 4 bits and the header length in the other 4 bits.

((ip)->vhl) & 0x0f) extracts the least significant 4 bits of the vhl member of the struct to which ip is pointing.

The multiplication by 4 to get the actual length is merely obeying the conventions of that member.

The way you are using sizeof to "manually get the length" is making assumptions about the header length corresponding to the sum of the sizes of the individual members. Member padding and undocumented conventions centred around the serialisation technique used for your struct might mean this is not the case.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • Given the name of the struct, this is probably ipv4. And, [well](https://tools.ietf.org/html/rfc791#page-11), "*Internet Header Length is the length of the internet header in 32 bit words*", thus probably the `* 4`. – dhke Dec 14 '17 at 09:29