parse a DNS header!

This commit is contained in:
Piper Pentagram 2025-07-18 16:25:26 -07:00
parent ee7c7d3714
commit 5cd390f7b1
7 changed files with 146 additions and 76 deletions

View file

@ -5,7 +5,7 @@
#define PB_OUT_OF_BOUNDS 9999;
struct DNSPacketBuffer {
char buf[PB_SIZE];
unsigned char buf[PB_SIZE];
size_t pos;
};
@ -13,4 +13,4 @@ struct DNSPacketBuffer *new_dns_packet_buffer();
struct DNSPacketHeader *dns_header(struct DNSPacketBuffer);
char pb_read_byte(struct DNSPacketBuffer *);
unsigned char pb_read_byte(struct DNSPacketBuffer *);

View file

@ -1,6 +1,7 @@
#pragma once
#include <stddef.h>
#define DNS_HEADER_BYTES 12
struct DNSPacketHeader {
/*
@ -8,14 +9,34 @@ struct DNSPacketHeader {
* a random ID is assigned to query packets.
* Response packets must contain the same ID as the query.
*/
size_t packet_id : 16;
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;
/*
* QR (Query/Response)
* 0 if the packet is a query
* 1 if the packet is a response
* 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_response : 1;
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)
@ -27,51 +48,14 @@ struct DNSPacketHeader {
*
* almost always will be 0
*/
size_t opcode : 4;
unsigned int opcode : 4;
/*
* AA (Authoritative Answer)
*
* 1 if the responding server is authoritative for the queried domain
* QR (Query/Response)
* 0 if the packet is a query
* 1 if the packet is a response
*/
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;
unsigned int is_response : 1;
/*
* RCODE (Response Code)
@ -86,31 +70,47 @@ struct DNSPacketHeader {
* 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;
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
*/
size_t question_count : 16;
unsigned int question_count : 16;
/*
* ANCOUNT (Answer Count)
* the number of entries in the answer section
*/
size_t answer_count : 16;
unsigned int answer_count : 16;
/*
* NSCOUNT (Nameserver Count)
* the number of entries in the authority records section
*/
size_t ns_count : 16;
unsigned int ns_count : 16;
/*
* ARCOUNT (Additional Records Count)
* the number of entries in the additional records section
*/
size_t ar_count : 16;
unsigned int ar_count : 16;
};
@ -125,26 +125,26 @@ struct RecordPreamble {
* TYPE
* the record type
*/
size_t type : 16;
unsigned int type : 16;
/*
* CLASS
* specifies the class of the data in the RDATA field.
* in practice, always set to 1
*/
size_t class : 16;
unsigned int class : 16;
/*
* TTL (Time-To-Live)
* how long a record can be cached before it should be requeried.
*/
size_t ttl : 32;
unsigned int ttl : 32;
/*
* RDLENGTH (Record Data Length)
* length of the record-type-specific data.
*/
size_t rd_data_length: 16;
unsigned int rd_data_length: 16;
};
/*
@ -153,5 +153,5 @@ struct RecordPreamble {
*/
struct ARecord {
struct RecordPreamble preamble;
size_t ip : 32;
unsigned int ip : 32;
};

View file

@ -7,4 +7,4 @@ struct DNSRequest {
struct DNSPacketHeader *header;
};
struct DNSRequest *new_dns_request(struct DNSPacketBuffer *pb);
struct DNSRequest *parse_dns_query(struct DNSPacketBuffer *pb);