#ifndef MESSAGE_HPP #define MESSAGE_HPP #include #include namespace Plains { namespace Resolver { using std::size_t; using std::unique_ptr; class Message { /* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ID | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |QR| OpCode |AA|TC|RD|RA| Z | RCODE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QDCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ANCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | NSCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ARCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ public: struct RCode { enum FLAG { NO_ERR, FORMAT_ERR, SERVER_FAIL, NAME_ERR, NOT_IMPL, REFUSED, YX_DOM, YX_RR_SET, NX_RR_SET, NOT_AUTH, NOT_ZONE }; }; struct OpCode { enum FLAG { QUERY, IQUERY, STATUS, reserved, NOTIFY, UPDATE }; }; struct QR { enum FLAG { QUERY, RESPONSE }; }; struct AA { enum FLAG { NON_AUTHORATATIVE, AUTHORATATIVE }; }; struct TC { enum FLAG { NON_TRUNCATED, TRUNCATED }; }; struct RD { enum FLAG { NOT_DESIRED, DESIRED }; }; struct RA { enum FLAG { NOT_AVAILABLE, AVAILABLE }; }; struct Buffer { size_t size; void* data; }; Message(); Message(const Buffer& buffer); unsigned id() const; // Identifyer unsigned rCode() const; // Response Code unsigned qdCount() const; // Question Count unsigned anCount() const; // Answer Record Count unsigned nsCount() const; // Authority Record Count unsigned arCount() const; // Additional Record Count unsigned opCode() const; // Operation Code bool qr() const; // Query/Respose Flag bool aa() const; // Authoratative Answer Flag bool tc() const; // Truncation Flag bool rd() const; // Recursion Desired Flag bool ra() const; // Recursion Available Flag unique_ptr encodeMessage() const; // Creates network byte-orderd message to be sent void id (unsigned value); void rCode (unsigned value); void qdCount(unsigned value); void anCount(unsigned value); void nsCount(unsigned value); void arCount(unsigned value); void opCode (unsigned value); void qr(QR::FLAG flag); void aa(AA::FLAG flag); void tc(TC::FLAG flag); void rd(RD::FLAG flag); void ra(RA::FLAG flag); void decodeMessage(const Buffer& buffer); private: struct Header { private: unsigned _id : 16; //Identifier: A 16-bit identification field generated by the device that creates the DNS query. It is copied by the server into the response, so it can be used by that device to match that query to the corresponding reply received from a DNS server. This is used in a manner similar to how the Identifier field is used in many of the ICMP message types. bool _qr : 1; //Query/Response Flag: Differentiates between queries and responses. Set to 0 when the query is generated; changed to 1 when that query is changed to a response by a replying server. unsigned _opCode : 4; bool _aa : 1; //Authoritative Answer Flag: This bit is set to 1 in a response to indicate that the server that created the response is authoritative for the zone in which the domain name specified in the Question section is located. If it is 0, the response is non-authoritative. bool _tc : 1; //Truncation Flag: When set to 1, indicates that the message was truncated due to its length being longer than the maximum permitted for the type of transport mechanism used. TCP doesn't have a length limit for messages, while UDP messages are limited to 512 bytes, so this bit being sent usually is an indication that the message was sent using UDP and was too long to fit. The client may need to establish a TCP session to get the full message. On the other hand, if the portion truncated was part of the Additional section, it may choose not to bother. bool _rd : 1; //Recursion Desired: When set in a query, requests that the server receiving the query attempt to answer the query recursively, if the server supports recursive resolution. The value of this bit is not changed in the response. bool _ra : 1; //Recursion Available: Set to 1 or cleared to 0 in a response to indicate whether the server creating the response supports recursive queries. This can then be noted by the device that sent the query for future use. unsigned _z : 3; //Zero: Three reserved bits set to zero. unsigned _rCode : 4; unsigned _qdCount : 16; //Question Count: Specifies the number of questions in the Question section of the message. unsigned _anCount : 16; //Answer Record Count: Specifies the number of resource records in the Answer section of the message. unsigned _nsCount : 16; //Authority Record Count: Specifies the number of resource records in the Authority section of the message. (“NS” stands for “name server”, of course. J) unsigned _arCount : 16; //Additional Record Count: Specifies the number of resource records in the Additional section of the message. }; unsigned _id; bool _qr; unsigned _opCode; bool _aa; bool _tc; bool _rd; bool _ra; unsigned _rCode; unsigned _qdCount; unsigned _anCount; unsigned _nsCount; unsigned _arCount; vector _question; vector _answer; vector _authority; vector _additional; }; }} #endif