Skip to content

Commit 94e8e60

Browse files
prevent infinite cname follow loop
1 parent bf51704 commit 94e8e60

2 files changed

Lines changed: 237 additions & 72 deletions

File tree

include/dns.h

Lines changed: 226 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2,137 +2,295 @@
22
* @file dns.h
33
* @author Craig Edwards (craigedwards@brainbox.cc)
44
* @copyright Copyright (c) 2012-2026
5+
*
6+
* @brief Non-blocking DNS resolver support
57
*/
68
#pragma once
79

810
#include "kernel.h"
911

10-
/* highest 6 bits in a DN label header */
11-
#define DN_COMP_BITMASK 0xC000
12+
/**
13+
* @brief DNS compression pointer marker bits
14+
*
15+
* DNS names may use a two-byte compression pointer. The top two bits are set
16+
* to indicate that the remaining fourteen bits are an offset into the DNS
17+
* message.
18+
*/
19+
#define DN_COMP_BITMASK 0xC000
1220

13-
/* Result is an error */
21+
/**
22+
* @brief Resolver result flag indicating failure
23+
*/
1424
#define ERROR_MASK 0x10000
1525

16-
#define FLAGS_MASK_RD 0x01 /* Recursive */
26+
/**
27+
* @brief DNS recursion desired flag
28+
*/
29+
#define FLAGS_MASK_RD 0x01
30+
31+
/**
32+
* @brief DNS truncated response flag
33+
*/
1734
#define FLAGS_MASK_TC 0x02
18-
#define FLAGS_MASK_AA 0x04 /* Authoritative */
35+
36+
/**
37+
* @brief DNS authoritative answer flag
38+
*/
39+
#define FLAGS_MASK_AA 0x04
40+
41+
/**
42+
* @brief DNS opcode mask
43+
*/
1944
#define FLAGS_MASK_OPCODE 0x78
45+
46+
/**
47+
* @brief DNS query/response flag
48+
*/
2049
#define FLAGS_MASK_QR 0x80
21-
#define FLAGS_MASK_RCODE 0x0F /* Request */
50+
51+
/**
52+
* @brief DNS response code mask
53+
*/
54+
#define FLAGS_MASK_RCODE 0x0F
55+
56+
/**
57+
* @brief DNS reserved flag mask
58+
*/
2259
#define FLAGS_MASK_Z 0x70
60+
61+
/**
62+
* @brief DNS recursion available flag
63+
*/
2364
#define FLAGS_MASK_RA 0x80
2465

2566
/**
26-
* Returned by dns_lookup_host_async() if the result is immediately
27-
* available in the ip parameter, and the ip parameter was non-NULL.
67+
* @brief Returned by dns_lookup_host_async() when the result is cached
68+
*
69+
* This value is returned if the result is immediately available in the ip
70+
* parameter, and the ip parameter was non-NULL.
2871
*/
2972
#define DNS_RESULT_CACHED 0xFFFFFFFF
3073

74+
/**
75+
* @brief DNS query and resource record types
76+
*/
3177
enum query_type_t {
32-
/** Uninitialized Query */
33-
DNS_QUERY_NONE = 0,
34-
/** 'A' record: an ipv4 address */
35-
DNS_QUERY_A = 1,
36-
/** 'CNAME' record: An alias */
37-
DNS_QUERY_CNAME = 5,
38-
/** 'PTR' record: a hostname */
39-
DNS_QUERY_PTR = 12,
40-
/** 'AAAA' record: an ipv6 address */
41-
DNS_QUERY_AAAA = 28,
42-
43-
/** Force 'PTR' to use IPV4 scemantics */
44-
DNS_QUERY_PTR4 = 0xFFFD,
45-
/** Force 'PTR' to use IPV6 scemantics */
46-
DNS_QUERY_PTR6 = 0xFFFE
78+
/** Uninitialised query */
79+
DNS_QUERY_NONE = 0,
80+
81+
/** A record: an IPv4 address */
82+
DNS_QUERY_A = 1,
83+
84+
/** CNAME record: an alias to another hostname */
85+
DNS_QUERY_CNAME = 5,
86+
87+
/** PTR record: a reverse lookup hostname */
88+
DNS_QUERY_PTR = 12,
89+
90+
/** AAAA record: an IPv6 address */
91+
DNS_QUERY_AAAA = 28,
92+
93+
/** Force PTR to use IPv4 semantics */
94+
DNS_QUERY_PTR4 = 0xFFFD,
95+
96+
/** Force PTR to use IPv6 semantics */
97+
DNS_QUERY_PTR6 = 0xFFFE
4798
};
4899

100+
/**
101+
* @brief Size of the fixed DNS packet header
102+
*/
49103
#define DNS_HEADER_SIZE 12
50104

105+
/**
106+
* @brief Size of the fixed part of a DNS resource record after the name
107+
*
108+
* This covers TYPE, CLASS, TTL, and RDLENGTH. It does not include the owner
109+
* name or RDATA.
110+
*/
51111
#define DNS_RR_FIXED_SIZE 10
52112

113+
/**
114+
* @brief Maximum decoded DNS result size used by the resolver
115+
*/
53116
#define DNS_RESULT_MAX 1023
54117

55-
/** Represents a dns request/reply header, and its payload as opaque data.
118+
/**
119+
* @brief Maximum number of CNAME redirects followed for one request
120+
*/
121+
#define DNS_MAX_CNAME_DEPTH 8
122+
123+
/**
124+
* @brief Standard DNS server UDP port
125+
*/
126+
#define DNS_DST_PORT 53
127+
128+
/**
129+
* @brief DNS request/reply header with opaque packet payload
56130
*/
57131
typedef struct dns_header {
58-
uint16_t id; /* Request id */
59-
uint8_t flags1; /* Flags */
60-
uint8_t flags2; /* Flags */
132+
/** Request or reply identifier */
133+
uint16_t id;
134+
135+
/** First DNS flags byte */
136+
uint8_t flags1;
137+
138+
/** Second DNS flags byte */
139+
uint8_t flags2;
140+
141+
/** Question count */
61142
uint16_t qdcount;
62-
uint16_t ancount; /* Answer count */
63-
uint16_t nscount; /* Nameserver count */
143+
144+
/** Answer count */
145+
uint16_t ancount;
146+
147+
/** Authority resource record count */
148+
uint16_t nscount;
149+
150+
/** Additional resource record count */
64151
uint16_t arcount;
65-
uint8_t payload[512]; /* Packet payload */
152+
153+
/** Packet payload following the fixed DNS header */
154+
uint8_t payload[512];
66155
} __attribute__((packed)) dns_header_t;
67156

157+
/**
158+
* @brief Callback for completed IPv4 A lookups
159+
*
160+
* @param result IPv4 address result, or 0 on failure
161+
* @param hostname Original hostname supplied to the lookup
162+
* @param reply_id DNS request identifier
163+
*/
68164
typedef void (*dns_reply_callback_a)(uint32_t result, const char* hostname, uint16_t reply_id);
165+
166+
/**
167+
* @brief Callback for completed IPv6 AAAA lookups
168+
*
169+
* @param result IPv6 address result
170+
* @param hostname Original hostname supplied to the lookup
171+
* @param reply_id DNS request identifier
172+
*/
69173
typedef void (*dns_reply_callback_aaaa)(uint8_t* result, const char* hostname, uint16_t reply_id);
174+
175+
/**
176+
* @brief Callback for completed PTR lookups
177+
*
178+
* @param result Hostname result
179+
* @param ip Original IP address supplied to the lookup
180+
* @param reply_id DNS request identifier
181+
*/
70182
typedef void (*dns_reply_callback_ptr)(const char* const result, const uint32_t ip, uint16_t reply_id);
71183

184+
/**
185+
* @brief Pending DNS request state
186+
*/
72187
typedef struct dns_request {
73-
uint16_t id; /* Request id */
74-
uint32_t rr_class; /* Request class */
188+
/** Request identifier */
189+
uint16_t id;
190+
191+
/** Requested resource record class */
192+
uint32_t rr_class;
193+
194+
/** Time to live from the accepted resource record */
75195
uint32_t ttl;
76-
uint16_t type; /* Request type */
77-
unsigned char* orig; /* Original requested name/ip */
196+
197+
/** Requested resource record type */
198+
uint16_t type;
199+
200+
/** Original requested hostname or IP string */
201+
unsigned char* orig;
202+
203+
/** Result buffer for resolved binary or textual data */
78204
char result[256];
205+
206+
/** Number of valid bytes in result */
79207
uint8_t result_length;
80-
dns_reply_callback_a callback_a; /* For later */
81-
dns_reply_callback_aaaa callback_aaaa; /* For later */
82-
dns_reply_callback_ptr callback_ptr; /* For later */
83-
uint32_t resolver_ip; /* Resolver IP address */
208+
209+
/** Completion callback for A lookups */
210+
dns_reply_callback_a callback_a;
211+
212+
/** Completion callback for AAAA lookups */
213+
dns_reply_callback_aaaa callback_aaaa;
214+
215+
/** Completion callback for PTR lookups */
216+
dns_reply_callback_ptr callback_ptr;
217+
218+
/** Resolver IPv4 address */
219+
uint32_t resolver_ip;
220+
221+
/** Number of CNAME redirects followed by this request */
222+
uint8_t cname_depth;
84223
} dns_request_t;
85224

225+
/**
226+
* @brief Cached DNS lookup entry
227+
*/
86228
typedef struct dns_cache_entry_t {
229+
/** Cached hostname */
87230
const char* host;
231+
232+
/** Cached result string */
88233
const char* result;
89234
} dns_cache_entry_t;
90235

236+
/**
237+
* @brief DNS resource record metadata
238+
*/
91239
typedef struct resource_record {
92-
uint16_t type; /* Record type */
93-
uint16_t rr_class; /* Record class */
94-
uint32_t ttl; /* Time to live */
95-
uint16_t rdlength; /* Record length */
240+
/** Resource record type */
241+
uint16_t type;
242+
243+
/** Resource record class */
244+
uint16_t rr_class;
245+
246+
/** Time to live */
247+
uint32_t ttl;
248+
249+
/** Resource data length */
250+
uint16_t rdlength;
96251
} __attribute__((packed)) resource_record_t;
97252

253+
/**
254+
* @brief DNS resolver result metadata
255+
*/
98256
struct dns_result_t {
257+
/** Error string, or NULL if no error occurred */
99258
char* error;
100259
};
101260

102-
#define DNS_DST_PORT 53
103-
104261
/**
105-
* @brief Look up an IPV4 hostname to IP address, with timeout
106-
* @note This function is synchronous! It will block until a suitable DNS request
107-
* has been obtained from the DNS server you specify, or a timeout is reached.
108-
*
109-
* @param resolver_ip The IP of the resolver to use, in network byte order
110-
* @param hostname Host address to resolve
111-
* @param timeout_ms Timeout in millisseconds
112-
* @return uint32_t Resolved IP address. On error or timeout, the return value is 0,
113-
* which translates to 0.0.0.0.
262+
* @brief Look up an IPv4 hostname to IP address, with timeout
263+
*
264+
* @note This function is synchronous. It blocks until a suitable DNS response
265+
* has been obtained from the specified DNS server, or a timeout is reached.
266+
*
267+
* @param resolver_ip IP address of the resolver to use, in network byte order
268+
* @param hostname Hostname to resolve
269+
* @param timeout_ms Timeout in milliseconds
270+
* @return Resolved IP address. On error or timeout, the return value is 0,
271+
* which represents 0.0.0.0.
114272
*/
115273
uint32_t dns_lookup_host(uint32_t resolver_ip, const char* hostname, uint32_t timeout_ms);
116274

117275
/**
118-
* @brief Look up an IPV4 hostname to IP address, with timeout
119-
* @note This function is asynchronous. It will return the ID of the request,
120-
* and will call the callback once the request has completed.
121-
*
122-
* @param resolver_ip The IP of the resolver to use, in network byte order
123-
* @param hostname Host address to resolve
124-
* @param ip Pointer to uint32_t IP address to immediately return if the result is cached
125-
* @param dns_reply_callback_a Callback to receive the resolved IP address.
126-
* If an error occured during resolution, the received IP address will be 0,
127-
* which is a representation of 0.0.0.0.
128-
* @return uint16_t Request ID that was submitted, or 0 on error.
129-
* a special value DNS_RESULT_CACHED (0xffffffff) is returned if the result was immediately
130-
* filled from the DNS cache.
276+
* @brief Look up an IPv4 hostname to IP address asynchronously
277+
*
278+
* @note This function returns the ID of the submitted request. The callback is
279+
* called once the request has completed. If the result is already cached and ip
280+
* is non-NULL, DNS_RESULT_CACHED is returned and ip is filled immediately.
281+
*
282+
* @param resolver_ip IP address of the resolver to use, in network byte order
283+
* @param hostname Hostname to resolve
284+
* @param ip Optional pointer to receive an immediate cached result
285+
* @param callback Callback to receive the resolved IP address
286+
* @return Request ID that was submitted, 0 on error, or DNS_RESULT_CACHED if
287+
* the result was returned from cache.
131288
*/
132289
uint32_t dns_lookup_host_async(uint32_t resolver_ip, const char* hostname, uint32_t* ip, dns_reply_callback_a callback);
133290

134291
/**
135-
* @brief Initialise DNS protocol.
136-
* This binds a UDP port for use with replies.
292+
* @brief Initialise DNS protocol support
293+
*
294+
* This binds a UDP port for use with DNS replies.
137295
*/
138296
void init_dns();

0 commit comments

Comments
 (0)