1

My question pertains to constructing a DNS header for a DNS query as defined by RFC 1035. The RFC states every DNS messages is in the following format:

+----------------------------------+
|            HEADER                |
+----------------------------------+
|            QUESTION              |
+----------------------------------+
|            ANSWER                |
+----------------------------------+
|           AUTHORITY              |
+----------------------------------+
|           ADDITIONAL             |
+----------------------------------+

And That the header field/section follows this format:

 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                     ID                        |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR|   OPCODE  |AA|TC|RD|RA|   Z    |   RCODE   |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    QDCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ANCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    NSCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ARCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

How would I define a header struct/object to hold the values for the second row? The trouble i'm seeing is setting specifics bits in this field for the different situations. The only designs i've come up with that still compile and don't violate the RFC's definition require a lot of bit manipulation and bit masking.

These are the two implementations I have considered however I wouldn't consider either an ideal solution.

    struct messageHeader{
        short ID;
     //Start of second row which is broken into 2 bytes
        unsigned int QR : 1;
        unsigned int OPCODE : 4;
        unsigned int AA : 1;
        unsigned int TC : 1;
        unsigned int RD : 1;
     //Start of Second byte needed for row 2
        unsigned int RA : 1;
        unsigned int Z : 3;
        unsigned int RCODE : 4;
     //End Second row
        short QDCNT;
        short ANCNT;
        short NSCNT;
        short ARCNT;

    };//End Message Header Struct

I've never worked with bit fields like this before so I don't fully understand how I would pack the bits into this...all I know is it compiled without errors even using the -pedantic flag and that kinda scares me.

The second is:

struct messageHeader{
    short ID;
    short row2;
    short QDCNT;
    short ANCNT;
    short NSCNT;
    short ARCNT;
};/End Message Header Struct

For the second option I would use the << operator to shift bits into the correct location for the short being used for row 2. This seems like an awful lot of bit manipulation and bit masking to me especially for all of the different combinations these codes could be.

HopAlongPolly
  • 1,347
  • 1
  • 20
  • 48

1 Answers1

1

This is really dangerous to use C-structure, because of over network need to send ints in big endian format (like powerPC), but most popular proceesors (intel) uses little-endian. Also, depends on compiler, you don't know, how your compiler distribute bits in the words, when you use bitfield ops.

I suggest you to search some lightweight DNS implementation, and use it as base for your exercises.

For example, you can use DNS-server from EmerCoin project:

https://github.com/EvgenijM86/emercoin/blob/master/src/emcdns.cpp

olegarch
  • 3,670
  • 1
  • 20
  • 19