#pragma once #include #define DNS_HEADER_BYTES 12 struct DNSPacketHeader { /* * ID (Packet Identifier) * a random ID is assigned to query packets. * Response packets must contain the same ID as the query. */ unsigned int packet_id : 16; /* * RD (Recursion Desired) * if set by the client, the server should * attempt to resolve the query recursively * * the server may not allow recursive resolution. * (see RA / Recursion Available) */ unsigned int recursion_desired : 1; /* * TC (Truncated) * if true, this message was truncated. * usually happens when the response payload * is larger than the max UDP packet size * * if set, the query may be re-issued over TCP for the full payload. */ unsigned int is_truncated : 1; /* * AA (Authoritative Answer) * * 1 if the responding server is authoritative for the queried domain */ unsigned int is_authoritative : 1; /* * OPCODE (Operation Code) * * 0 - standard query (QUERY) * 1 - inverse query (IQUERY) * 2 - server status request (STATUS) * 3-15 - reserved * * almost always will be 0 */ unsigned int opcode : 4; /* * QR (Query/Response) * 0 if the packet is a query * 1 if the packet is a response */ unsigned int is_response : 1; /* * RCODE (Response Code) * Set by the server to indicate success or failure of the query. * Provides details about the cause of any failure. * * 0 - No error * 1 - Format error - the nameserver was unable to interpret the query * 2 - Server failure - the nameserver was unable to process the query due to an internal problem * 3 - Name error - Meaningful only from authoritative nameserver -- the domain name specified in the query does not exist. * 4 - Not implemented - the nameserver does not support the requested query type * 5 - Refused - the nameserver refuses to perform the requested operation. for example, it may refuse a zone transfer. * 6-15 - Reserved for future use */ unsigned int response_code : 4; /* * Z (Reserved) * in the original spec, this is reserved for future use. * * in later RFCs, it is used for DNSSEC queries. * (to be implemented) */ unsigned int z : 3; /* * RA (Recursion Available) * if set by the server, incicates that the server allows * recursive queries. */ unsigned int recursion_available : 1; /* * QDCOUNT (Question Count) * the number of entries in the question section */ unsigned int question_count : 16; /* * ANCOUNT (Answer Count) * the number of entries in the answer section */ unsigned int answer_count : 16; /* * NSCOUNT (Nameserver Count) * the number of entries in the authority records section */ unsigned int ns_count : 16; /* * ARCOUNT (Additional Records Count) * the number of entries in the additional records section */ unsigned int ar_count : 16; }; /* * RecordPreamble * shared fields that all DNS record types use */ struct RecordPreamble { // TODO: add label sequence /* * TYPE * the record type */ unsigned int type : 16; /* * CLASS * specifies the class of the data in the RDATA field. * in practice, always set to 1 */ unsigned int class : 16; /* * TTL (Time-To-Live) * how long a record can be cached before it should be requeried. */ unsigned int ttl : 32; /* * RDLENGTH (Record Data Length) * length of the record-type-specific data. */ unsigned int rd_data_length: 16; }; /* * A Record * represents the mapping of a domain name to an IPv4 address */ struct ARecord { struct RecordPreamble preamble; unsigned int ip : 32; };