2025-05-13 13:17:10 -07:00
|
|
|
#pragma once
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
|
|
|
2025-07-08 13:03:11 -07:00
|
|
|
struct DNSPacketHeader {
|
2025-05-13 13:17:10 -07:00
|
|
|
/*
|
|
|
|
|
* ID (Packet Identifier)
|
|
|
|
|
* a random ID is assigned to query packets.
|
|
|
|
|
* Response packets must contain the same ID as the query.
|
|
|
|
|
*/
|
|
|
|
|
size_t packet_id : 16;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* QR (Query/Response)
|
|
|
|
|
* 0 if the packet is a query
|
|
|
|
|
* 1 if the packet is a response
|
|
|
|
|
*/
|
|
|
|
|
size_t is_response : 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
|
|
|
|
|
*/
|
|
|
|
|
size_t opcode : 4;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* AA (Authoritative Answer)
|
|
|
|
|
*
|
|
|
|
|
* 1 if the responding server is authoritative for the queried domain
|
|
|
|
|
*/
|
|
|
|
|
size_t is_authoritative : 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.
|
|
|
|
|
*/
|
|
|
|
|
size_t is_truncated : 1;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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)
|
|
|
|
|
*/
|
|
|
|
|
size_t recursion_desired : 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* RA (Recursion Available)
|
|
|
|
|
* if set by the server, incicates that the server allows
|
|
|
|
|
* recursive queries.
|
|
|
|
|
*/
|
|
|
|
|
size_t recursion_available : 1;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Z (Reserved)
|
|
|
|
|
* in the original spec, this is reserved for future use.
|
|
|
|
|
*
|
|
|
|
|
* in later RFCs, it is used for DNSSEC queries.
|
|
|
|
|
* (to be implemented)
|
|
|
|
|
*/
|
|
|
|
|
size_t z : 3;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
|
|
|
|
size_t response_code : 4;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* QDCOUNT (Question Count)
|
|
|
|
|
* the number of entries in the question section
|
|
|
|
|
*/
|
|
|
|
|
size_t question_count : 16;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ANCOUNT (Answer Count)
|
|
|
|
|
* the number of entries in the answer section
|
|
|
|
|
*/
|
|
|
|
|
size_t answer_count : 16;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* NSCOUNT (Nameserver Count)
|
|
|
|
|
* the number of entries in the authority records section
|
|
|
|
|
*/
|
|
|
|
|
size_t ns_count : 16;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ARCOUNT (Additional Records Count)
|
|
|
|
|
* the number of entries in the additional records section
|
|
|
|
|
*/
|
|
|
|
|
size_t ar_count : 16;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* RecordPreamble
|
|
|
|
|
* shared fields that all DNS record types use
|
|
|
|
|
*/
|
|
|
|
|
struct RecordPreamble {
|
|
|
|
|
// TODO: add label sequence
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TYPE
|
|
|
|
|
* the record type
|
|
|
|
|
*/
|
|
|
|
|
size_t type : 16;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* CLASS
|
|
|
|
|
* specifies the class of the data in the RDATA field.
|
|
|
|
|
* in practice, always set to 1
|
|
|
|
|
*/
|
|
|
|
|
size_t class : 16;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TTL (Time-To-Live)
|
|
|
|
|
* how long a record can be cached before it should be requeried.
|
|
|
|
|
*/
|
|
|
|
|
size_t ttl : 32;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* RDLENGTH (Record Data Length)
|
|
|
|
|
* length of the record-type-specific data.
|
|
|
|
|
*/
|
|
|
|
|
size_t rd_data_length: 16;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A Record
|
|
|
|
|
* represents the mapping of a domain name to an IPv4 address
|
|
|
|
|
*/
|
|
|
|
|
struct ARecord {
|
|
|
|
|
struct RecordPreamble preamble;
|
|
|
|
|
size_t ip : 32;
|
|
|
|
|
};
|