1 //
2 //	dnssec_v2_structs.h
3 //	mDNSResponder
4 //
5 //	Copyright (c) 2020 Apple Inc. All rights reserved.
6 //
7 
8 #ifndef DNSSEC_v2_STRUCTS_H
9 #define DNSSEC_v2_STRUCTS_H
10 
11 #pragma mark - Includes
12 #include "mDNSEmbeddedAPI.h"
13 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
14 #include "list.h"
15 #include "mDNSEmbeddedAPI.h"
16 #include "ClientRequests.h"
17 
18 #pragma mark - Enums
19 
20 
21 
22 #pragma mark dnssec_validation_result_t
23 typedef enum dnssec_validation_result {
24 	// chain of trust validation error
25 	dnssec_validation_invalid,
26 	dnssec_validation_valid,
27 	dnssec_validation_not_trusted,
28 	dnssec_validation_trusted,
29 	dnssec_validation_invalid_internal_state,
30 	dnssec_validation_non_dnskey_ds_record_chain,
31 	dnssec_validation_no_matching_key_tag,
32 
33 	// DNSSEC record general error
34 	dnssec_validation_algorithm_number_not_equal,
35 
36 	// DS validation error
37 	dnssec_validation_ds_digest_not_supported,
38 
39 	// DNSKEY validation error
40 	dnssec_validation_dnskey_algorithm_not_supported,
41 	dnssec_validation_dnskey_invalid_flags,
42 	dnssec_validation_dnskey_wrong_protocol,
43 
44 	// RRSIG validation error
45 	dnssec_validation_rrsig_use_before_inception,
46 	dnssec_validation_rrsig_use_after_expiration,
47 
48 	// NSEC validation error
49 	dnssec_validation_nsec_invalid_nsec_result,
50 	dnssec_validation_nsec_malformated_record,
51 	// Verifiable NSEC error
52 	dnssec_validation_nsec_name_error,
53 	dnssec_validation_nsec_no_data,
54 	dnssec_validation_nsec_wildcard_answer,
55 	dnssec_validation_nsec_wildcard_no_data,
56 
57 	// NSEC3 validation error
58 	dnssec_validation_nsec3_invalid_hash_iteration,
59 	dnssec_validation_nsec3_unsupported_hash_algorithm,
60 	dnssec_validation_nsec3_unsupported_flag,
61 	dnssec_validation_nsec3_different_hash_iteration_salt,
62 	dnssec_validation_nsec3_provable_closest_encloser,
63 	dnssec_validation_nsec3_nsec3_not_from_the_zone,
64 	dnssec_validation_nsec3_malformated_record,
65 	// Verifiable NSEC3 error
66 	dnssec_validation_nsec3_name_error,
67 	dnssec_validation_nsec3_wildcard_no_data,
68 	dnssec_validation_nsec3_no_data_response,
69 	dnssec_validation_nsec3_no_data_response_opt_out,
70 	dnssec_validation_nsec3_wildcard_answer_response,
71 
72 	// path validation error
73 	dnssec_validation_path_invalid_node_type,
74 	dnssec_validation_path_unmatched_owner_name,
75 	dnssec_validation_path_unmatched_class,
76 	dnssec_validation_path_unmatched_type_covered,
77 	dnssec_validation_path_invalid_label_count,
78 
79 	// trust anchor error
80 	dnssec_validation_trust_anchor_not_available,
81 	dnssec_validation_trust_anchor_does_not_macth,
82 
83 	// general error
84 	dnssec_validation_validating,
85 	dnssec_validation_no_memory,
86 	dnssec_validation_bogus
87 } dnssec_validation_result_t;
88 
89 #pragma mark - Structures
90 
91 
92 
93 #pragma mark - DNSSEC-related records wire format
94 
95 
96 
97 #pragma mark dns_type_cname_t
98 // DNS CNAME record data fields (see <https://tools.ietf.org/html/rfc1035#section-3.3.1>)
99 typedef struct dns_type_cname dns_type_cname_t;
100 struct dns_type_cname {
101 	mDNSu8		cname[0];				// To CNAME rdata.
102 };
103 
104 #pragma mark dns_type_ds_t
105 typedef struct dns_type_ds dns_type_ds_t;
106 // DNS DS record data fields (see <https://tools.ietf.org/html/rfc4034#section-5.1>)
107 struct dns_type_ds {
108 	mDNSu16		key_tag;				// key tag that identifies a specific DNSKEY.
109 	mDNSu8		algorithm;				// The DNSKEY algorithm that is used to sign the data.
110 	mDNSu8		digest_type;			// The type of the DS digest.
111 	mDNSu8		digest[0];				// To digest rdata.
112 };
113 
114 #pragma mark dns_type_dnskey_t
115 // DNS DNSKEY record data fields (see <https://tools.ietf.org/html/rfc4034#section-2.1>)
116 typedef struct dns_type_dnskey dns_type_dnskey_t;
117 struct dns_type_dnskey {
118 	mDNSu16		flags;					// The DNSKEY flags.
119 	mDNSu8		protocol;				// Protocol that identifies DNSKEY as a key used in DNSSEC, it should always be 3.
120 	mDNSu8		algorithm;				// The DNSKEY algorithm that is used to sign the data.
121 	mDNSu8		public_key[0];			// To public rdata.
122 };
123 
124 #pragma mark dns_type_rrsig_t
125 // DNS RRSIG record data fields (see <https://tools.ietf.org/html/rfc4034#section-3.1>)
126 typedef struct dns_type_rrsig dns_type_rrsig_t;
127 struct dns_type_rrsig {
128 	mDNSu16		type_covered;			// Indicates which DNS type RRSIG covers
129 	mDNSu8		algorithm;				// The DNSKEY algorithm that is used to sign the data.
130 	mDNSu8		labels;					// The number of labels in the RRSIG owner name, it is used to check wild matching.
131 	mDNSu32		original_TTL;			// The original TTL of the records that are covered by the RRSIG, it is used to reconstruct the signed data.
132 	mDNSu32		signature_expiration;	// The epoch time when the RRSIG expires.
133 	mDNSu32		signature_inception;	// The epoch time when the RRSIG should start to be valid to validate.
134 	mDNSu16		key_tag;				// The key tag that identifies which DNSKEY it uses to generate the current RRSIG.
135 	mDNSu8		signer_name[0];			// To the signer name.
136 	// mDNSu8	signature[0];			// To the signature rdata.
137 };
138 
139 #pragma mark dns_type_nsec_t
140 // DNS NSEC record data fields (see <https://tools.ietf.org/html/rfc4034#section-2.1>)
141 typedef struct dns_type_nsec dns_type_nsec_t;
142 struct dns_type_nsec {
143 	mDNSu8		next_domain_name[0];	// The next domain that exists in the zone
144 	// mDNSu8	type_bit_maps[0];		// To the type bit map that indicates what DNS types are covered by the current NSEC record.
145 };
146 
147 #pragma mark dns_type_nsec3_t
148 // DNS NSEC3 record data fields (see <https://tools.ietf.org/html/rfc5155#section-3.1>)
149 typedef struct dns_type_nsec3 dns_type_nsec3_t;
150 struct dns_type_nsec3 {
151 	mDNSu8		hash_algorithm;			// Which hash algorithm that NSEC3 uses to generate the hash.
152 	mDNSu8		flags;					// The NSEC3 flags
153 	mDNSu16		iterations;				// The iterations of hash operation on the data
154 	mDNSu8		salt_length;
155 	mDNSu8		salt[0];				// varied-size array
156 	// mDNSu8	hash_length;
157 	// mDNSu8	next_hashed_owner_name[0];// The next hashed domain that exists in the zone
158 	// mDNSu8 * type_bit_maps;			// To the type bit map that indicates what DNS types are covered by the current NSEC3 record.
159 };
160 
161 #pragma mark - DNSSEC records in memory
162 
163 #pragma mark dnssec_rr_t
164 typedef struct dnssec_rr dnssec_rr_t;
165 struct dnssec_rr {							// Represents a resource record
166 	mDNSu16						rr_type;				// The DNS type of the resource record.
167 	mDNSu16						rr_class;				// The internet class of the record, should be IN
168 	mDNSu16						rdata_length;			// The length of the rdata
169 	mDNSu32						name_hash;				// The hash of the owner name that is used to compare name quickly
170 	mDNSu32						rdata_hash;				// The hash of the rdata that is used to compare rdata quickly
171 	domainname					name;					// The owner name of the record
172 	mDNSu8 *	_Nullable		rdata;					// The rdata
173 	ResourceRecord * _Nullable	rr;						// Points to ResourceRecord in the mDNSCore cache
174 };
175 
176 #pragma mark dnssec_original_t
177 typedef struct dnssec_original dnssec_original_t;
178 struct dnssec_original {						// The response that answers user's question.
179 	mDNSBool					answer_from_cache;		// Indicates If we get the answer from the cache, instead of refresh response from DNS server.
180 	DNSServiceErrorType			dns_error;				// DNSServiceErrorType when mDNSCore returns the answer.
181 	QC_result					qc_result;				// Event type for the current resource record including QC_add, QC_rmv, QC_supressed.
182 	dnssec_rr_t					dnssec_rr;				// Store the answer returned from mDNSCore.
183 };
184 
185 #pragma mark dnssec_cname_t
186 typedef struct dnssec_cname dnssec_cname_t;
187 struct dnssec_cname {							// The response that does not answer user's question, but provides a CNAME to continue the query
188 	mDNSu8 *	_Nullable		cname;					// The CNAME rdata.
189 	dnssec_rr_t					dnssec_rr;				// Store the answer returned from mDNSCore.
190 };
191 
192 #pragma mark dnssec_ds_t
193 typedef struct dnssec_ds dnssec_ds_t;
194 struct dnssec_ds {							// The response that answers DS query from mDNSResponder
195 	mDNSu16						key_tag;				// ID that identifies the DNSKEY that the current DS verifies.
196 	mDNSu8						algorithm;				// The algorithm of the DNSKEY that the current DS verifies.
197 	mDNSu8						digest_type;			// The digest type that is used to caluclate the current DS from the DNSKEY.
198 	mDNSu16						digest_length;			// The length of the digest.
199 	const mDNSu8 * _Nullable	digest;					// The DS rdata.
200 	dnssec_rr_t					dnssec_rr;				// Store the answer returned from mDNSCore.
201 };
202 
203 // DNSKEY flag bits
204 #define DNSKEY_FLAG_ZONE_KEY				0x100
205 #define DNSKEY_FLAG_SECURITY_ENTRY_POINT	0x1
206 
207 #pragma mark dnssec_dnskey_t
208 typedef struct dnssec_dnskey dnssec_dnskey_t;
209 struct dnssec_dnskey {						// The response that answeres DNSKEY query from mDNSResponder.
210 	mDNSu16						flags;					// The bit flags for DNSKEY.
211 	mDNSu8						protocol;				// Should always be value 3.
212 	mDNSu8						algorithm;				// The type of crypoto algorithm that the current DNSKEY applies to.
213 	mDNSu16						key_tag;				// ID that identifies the current DNSKEY
214 	mDNSu16						public_key_length;		// The length of the DNSKEY.
215 	mDNSu8 * _Nullable			public_key;				// The DNSKEY rdata
216 	dnssec_rr_t					dnssec_rr;				// Store the answer returned from mDNSCore.
217 };
218 
219 #pragma mark dnssec_rrsig_t
220 typedef struct dnssec_rrsig dnssec_rrsig_t;
221 struct dnssec_rrsig {
222 	mDNSu16						type_covered;			// The DNS type that is covered by the current RRSIG
223 	mDNSu8						algorithm;				// The algorithm of DNSKEY that is used to generate the current RRSIG
224 	mDNSu8						labels;					// The number of labels of RRSIG's owner, used for wildcard matching
225 	mDNSu32						original_TTL;			// The original TTL of the records that are used to generate the current RRSIG, used to reconstruct the signed data
226 	mDNSu32						signature_expiration;	// The epoch time when the RRSIG expires.
227 	mDNSu32						signature_inception;	// The epoch time when the RRSIG should start to be valid to validate.
228 	mDNSu16						key_tag;				// The key tag that identifies which DNSKEY it uses to generate the current RRSIG.
229 	mDNSu16						signature_length;		// The length of the signature.
230 	mDNSu8 *	_Nullable		signer_name;			// The name of signer that signs the covered records
231 	mDNSu8 *	_Nullable		signature;				// The signature rdata
232 	dnssec_rr_t					dnssec_rr;				// Store the answer returned from mDNSCore.
233 };
234 
235 #pragma mark dnssec_nsec_t
236 typedef struct dnssec_nsec dnssec_nsec_t;
237 struct dnssec_nsec {
238 	mDNSu8 *	_Nullable		exist_domain_name;		// The owner name of records that exist before next_domain_name by canonical order in the zone.
239 	mDNSu8 *	_Nullable		next_domain_name;		// The owner name of records that exist after next_domain_name by canonical order in the zone.
240 	mDNSu8 *	_Nullable		type_bit_maps;			// The type bit map that indicates what DNS types are covered by the current NSEC record.
241 	mDNSu16						type_bit_maps_length;	// The length of the type bit map.
242 	dnssec_rr_t					dnssec_rr;				// Store the answer returned from mDNSCore.
243 };
244 
245 #pragma mark dnssec_nsec3_t
246 typedef struct dnssec_nsec3 dnssec_nsec3_t;
247 struct dnssec_nsec3 {
248 	mDNSu8						hash_algorithm;			// The hash algorithm that NSEC3 uses to generate the hash
249 	mDNSu8						flags;					// The NSEC3 flags
250 	mDNSu16						iterations;				// The iterations of hash operation on the data
251 	mDNSu8						salt_length;			// The length of the salt added when doing hash
252 	mDNSu8						hash_length;			// The length of the final hash result
253 	mDNSu16						type_bit_maps_length;	// The length of the type bit map.
254 	mDNSu8 *	_Nullable		salt;					// The salt added to the hash result for every iteration
255 	mDNSu8 *	_Nullable		next_hashed_owner_name;	// The binary-format hashed owner name of records that exist after the owner name of current NSEC3 record by canonical order in the zone.
256 	mDNSu8 *	_Nullable		type_bit_maps;			// The type bit map that indicates what DNS types are covered by the current NSEC3 record.
257 	char *		_Nullable		next_hashed_owner_name_b32;			// The b32-format string of hashed owner name
258 	mDNSu32						next_hashed_owner_name_b32_length;	// The length of next_hashed_owner_name_b32 string
259 	dnssec_rr_t					dnssec_rr;				// Store the answer returned from mDNSCore.
260 };
261 
262 #pragma mark - Validation tree structures
263 
264 
265 
266 #pragma mark nsecs_with_rrsig_t
267 typedef struct nsecs_with_rrsig nsecs_with_rrsig_t;
268 struct nsecs_with_rrsig {									// The NSEC response from DNS server that indicates the non-existence of the record in the query.
269 	list_t							nsec_and_rrsigs_same_name;		// list_t<one_nsec_with_rrsigs_t>, the list of one_nsec_with_rrsigs_t structure, each one_nsec_with_rrsigs_t represents one NSEC record with its corresponding RRSIG.
270 	list_t							wildcard_answers;				// list_t<dnssec_rr_t>, the list of dnssec_rr_t structure, each dnssec_rr_t represents one wildcard record.
271 	list_t							wildcard_rrsigs;				// list_t<dnssec_rrsig_t>, the list of dnssec_rrsig_t structure, each dnssec_rrsig_t represents one RRSIG that is used to validate the wildcard answer in wildcard_answers.
272 	ResourceRecord * 	_Nullable	negative_rr;					// The negative answer generated by mDNSResponder, that NSEC records try to prove.
273 	dnssec_validation_result_t		nsec_result;					// The validation result after validating the current NSEC records, it is only meaningful after we finish the validation.
274 };
275 
276 #pragma mark one_nsec_with_rrsigs_t
277 typedef struct one_nsec_with_rrsigs one_nsec_with_rrsigs_t;
278 struct one_nsec_with_rrsigs {								// One NSEC record that form a complete NSEC response with other NSEC records.
279 	const mDNSu8 * _Nullable	owner_name;							// The onwer name of NSEC record, also indicates that this name does exist in the zone.
280 	dnssec_nsec_t				nsec_record;						// The dnssec_nsec_t that holds the NSEC record.
281 	list_t						rrsig_records;						// list_t<dnssec_rrsig_t>, the RRSIGs that generated from the current NSEC record.
282 };
283 
284 #pragma mark nsec3s_with_rrsig_t
285 typedef struct nsec3s_with_rrsig nsec3s_with_rrsig_t;
286 struct nsec3s_with_rrsig {								// The NSEC3 response from DNS server that indicates the non-existence of the record in the query.
287 	list_t								nsec3_and_rrsigs_same_name; // list_t<one_nsec3_with_rrsigs_t>, the list of one_nsec3_with_rrsigs_t structure, each one_nsec3_with_rrsigs_t represents one NSEC3 record with its corresponding RRSIG.
288 	list_t								wildcard_answers;			// list_t<dnssec_rr_t>, the list of dnssec_rr_t structure, each dnssec_rr_t represents one wildcard record.
289 	list_t								wildcard_rrsigs;			// list_t<dnssec_rrsig_t>, the list of dnssec_rrsig_t structure, each dnssec_rrsig_t represents one RRSIG that is used to validate the wildcard answer in wildcard_answers.
290 	ResourceRecord *	_Nullable		negative_rr;				// The negative answer generated by mDNSResponder, that NSEC3 records try to prove.
291 	dnssec_validation_result_t			nsec3_result;				// The validation result after validating the current NSEC3 records, it is only meaningful after we finish the validation.
292 };
293 
294 #pragma mark one_nsec3_with_rrsigs_t
295 typedef struct one_nsec3_with_rrsigs one_nsec3_with_rrsigs_t;
296 struct one_nsec3_with_rrsigs {							// One NSEC3 record that form a complete NSEC response with other NSEC records.
297 	const mDNSu8 * _Nullable	owner_name;							// The onwer name of NSEC3 record, also indicates that this name does exist in the zone.
298 	dnssec_nsec3_t				nsec3_record;						// The dnssec_nsec_t that holds the NSEC3 record.
299 	list_t						rrsig_records;						// list_t<dnssec_rrsig_t>, the RRSIGs that generated from the current NSEC3 record.
300 };
301 
302 #pragma mark cnames_with_rrsig_t
303 typedef struct cnames_with_rrsig cnames_with_rrsig_t;
304 struct cnames_with_rrsig {			// The CNAME response from DNS server that indicates the current query name is a alias of another name.
305 	list_t						cname_records;	// list_t<dnssec_cname_t>, the list of dnssec_cname_t structure, each dnssec_cname_t represents one CNAME, in fact there should only be one CNAME in the list.
306 	list_t						rrsig_records;	// list_t<dnssec_rrsig_t>, the list of dnssec_rrsig_t structure, each dnssec_rrsig_t represents one RRSIG that i sused to validate the CNAME record in cname_records.
307 };
308 
309 #pragma mark trust_anchor_t
310 typedef struct trust_anchors trust_anchors_t;
311 struct trust_anchors {			// The trust anchor structure that mDNSResponder loads during initialization, it stays unchanged during the life time of mDNSResponder.
312 	domainname	name;					// The owner name of the trust anchor
313 	mDNSu32		name_hash;				// The hash of the owner name, used to speed up name comparsion.
314 	list_t		dnskey_trust_anchors;	// list_t<dnssec_dnskey_t>, the list of dnssec_dnskey_t structures, the trust anchor could be a DNSKEY record. When mDNSResponder can use this trusted DNSKEY to validate the record, then the entire validation chain rooted in the validated record could be trusted.
315 	list_t		ds_trust_anchors;		// list_t<dnssec_ds_t>, the list of dnssec_ds_t structures, the trust anchor could also be a DS record. When mDNSResponder can use this trusted DS to match DNSKEY record, then the entire validation chain rooted in the validated DNSKEY record could be trusted.
316 };
317 
318 #pragma mark response_type_t
319 typedef enum response_type {			// The response type for any DNS query in DNSSEC environment.
320 	unknown_response,			// The initial state, which means we have not received any response.
321 	original_response,			// The DNS server returns what the user expects, thus it is a original response for the query.
322 	cname_response,				// The DNS server returns a CNAME for user's NOn-CNAME query
323 	nsec_response,				// The DNS server returns a NSEC response trying to prove that the name or the record type does not exist.
324 	nsec3_response				// The DNS server returns a NSEC3 response trying to prove that the name or the record type does not exist.
325 } response_type_t;
326 
327 #pragma mark originals_with_rrsig_t
328 typedef struct originals_with_rrsig originals_with_rrsig_t;
329 struct originals_with_rrsig {					// This structure holds the response that will be returned to the user after validation.
330 	union {												// The response can only be original_response/cname_response/nsec_response/nsec3_response.
331 		struct {
332 			list_t				original_records;		// list_t<dnssec_original_t>, the list of dnssec_original_t structures, each dnssec_original_t holds one response that user expects.
333 			list_t				rrsig_records;			// list_t<dnssec_rrsig_t>, the list of dnssec_rrsig_t structures, each dnssec_rrsig_t holds one RRSIG generated from the dnssec_original_t above.
334 			ResourceRecord * _Nullable negative_rr;		// The query may be suppressed by mDNSResponder, it is a denial of existence response that does not need NSEC/NSEC3 to validate, just put it in original.
335 			mDNSBool			suppressed_response;	// Indicates if the original response is a suppressed one.
336 		} original;										// Used when the type is original_response.
337 		cnames_with_rrsig_t		cname_with_rrsig;		// Used when the type is cname_response.
338 														// NSEC and NSEC3 RRs can not co-exist in a zone.
339 		nsecs_with_rrsig_t		nsecs_with_rrsig;		// Used when the type is nsec_response.
340 		nsec3s_with_rrsig_t		nsec3s_with_rrsig;		// Used when the type is nsec3_response.
341 	} u;
342 	response_type_t				type;					// original_response/cname_response/nsec_response/nsec3_response.
343 };
344 
345 #pragma mark dses_with_rrsig_t
346 typedef struct dses_with_rrsig dses_with_rrsig_t;
347 struct dses_with_rrsig {						// This structure holds the DS response that DNSSEC handler queries for.
348 	union {												// The response can only be original_response/nsec_response/nsec3_response.
349 		struct {
350 			list_t				ds_records;				// list_t<dnssec_ds_t>, the list of dnssec_ds_t structure, each dnssec_ds_t holds one DS record that could be used to verifies one DNSKEY record
351 			list_t				rrsig_records;			// list_t<dnssec_rrsig_t>, the list of dnssec_rrsig_t structure, each dnssec_rrsig_t holds one RRSIG generated from the dnssec_ds_t above.
352 		} original;
353 														// NSEC and NSEC3 RRs can not co-exist in a zone.
354 		nsecs_with_rrsig_t		nsecs_with_rrsig;		// Used when the type is nsec_response.
355 		nsec3s_with_rrsig_t		nsec3s_with_rrsig;		// Used when the type is nsec3_response.
356 	} u;
357 	response_type_t				type;					// original_response/nsec_response/nsec3_response, CNAME can only be the leaf node, thus there should never be CNAME for DS query.
358 	mDNSBool					set_completed;			// Indicates if we have already get the DS records.
359 };
360 
361 #pragma mark dnskeys_with_rrsig_t
362 typedef struct dnskeys_with_rrsig dnskeys_with_rrsig_t;
363 struct dnskeys_with_rrsig {					// This structure holds the DNSKEY response that DNSSEC handler queries for. The response can only be original_response, because both NSEC and NSEC3 indicate that DNSKEY does exist in order to validate the NSEC/NSEC3.
364 	list_t				dnskey_records;					// list_t<dnssec_dnskey_t>, the list of dnssec_dnskey_t structures, each dnssec_dnskey_t holds one DNSKEY that could be used to validate signer's records with the corresponding RRSIG.
365 	list_t				rrsig_records;					// list_t<dnssec_rrsig_t>, the list of dnssec_rrsig_t structures, each dnssec_rrsig_t holds one RRSIG generated from the dnssec_dnskey_t above.
366 	mDNSBool			set_completed;					// Indicates if we have already get the DNSKEY records.
367 };
368 
369 #pragma mark dnssec_zone_t
370 // This structure represents one zone node in the validation tree. For example, if the user queries for the AAAA record
371 // of "www.internetsociety.org.", there will be 3 zone nodes at last:
372 // Root zone node:	"."							DNSKEY
373 // Zone node:		"org."						DNSKEY/DS
374 // Zone node:		"internetsociety.org."		DNSKEY/DS
375 // Response:		"www.internetsociety.org."	AAAA
376 // Each node contains 2 kinds of records: DNSKEY and DS records
377 typedef struct dnssec_zone dnssec_zone_t;
378 struct dnssec_zone {
379 	// general field that is used to fecth records
380 	domainname					domain_name;			// DNS representation of the zone name.
381 	mDNSu32						name_hash;				// The name hash to speed up name comparison.
382 
383 	// dnssec resource records
384 	// DS record
385 	QueryRecordClientRequest	ds_request;				// The DS request handler
386 	mDNSBool					ds_request_started;		// Indicates if we issued the DS request, sometimes we do not want to issue query such as we are in root "." node, and root node does not have DS record.
387 	mDNSBool					dses_initialized;		// Indicate if the DS list is initialized
388 	dses_with_rrsig_t			dses_with_rrsig;		// list_t<dses_with_rrsig_t>, the list of dses_with_rrsig_t structures, each dses_with_rrsig_t holds the DS records and the corresponding RRSIG records for the current zone.
389 	mDNSs32						last_time_ds_add;		// last time that DS records are added
390 	mDNSs32						last_time_ds_rmv;		// last time that DS records are removed
391 
392 	// DNSKEY record
393 	QueryRecordClientRequest	dnskey_request;			// The DNSKEY request handler
394 	mDNSBool					dnskey_request_started;	// Indicates if we issue the DNSKEY request, sometimes we do not issue the query because the current zone has a trust anchor for DNSKEY.
395 	dnskeys_with_rrsig_t		dnskeys_with_rrsig;		// list_t<dnssec_dnskey_t>, the list of dnskeys_with_rrsig structures, each dnssec_dnskey_t holds the DNSKEY records and the corresponding RRSIG records for the current zone.
396 	mDNSs32						last_time_dnskey_add;	// last time that DNSKEY records are added
397 	mDNSs32						last_time_dnskey_rmv;	// last time that DNSKEY records are removed
398 
399 	// The current zone may have trust anchor installed in the system
400 	const trust_anchors_t * _Nullable	trust_anchor;	// list_t<trust_anchor_t>, the list of trust_anchor_t structures, each trust_anchor_t represent one trust anchor.
401 };
402 
403 #pragma mark original_request_parameters_t
404 typedef struct original_request_parameters original_request_parameters_t;
405 struct original_request_parameters {			// This structure contains the original request paramters set by the user.
406 	mDNSu32						request_id;
407 	domainname					question_name;
408 	mDNSu32						question_name_hash;
409 	mDNSu16						question_type;
410 	mDNSu16						question_class;
411 	mDNSInterfaceID _Nullable	interface_id;
412 	mDNSs32						service_id;
413 	mDNSu32						flags;
414 	mDNSBool					append_search_domains;
415 	mDNSs32						pid;
416 	mDNSu8						uuid[UUID_SIZE];
417 	mDNSs32						uid;
418 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
419 	audit_token_t				peer_audit_token;
420 	mDNSBool					has_peer_audit_token;
421 	audit_token_t				delegate_audit_token;
422 	mDNSBool					has_delegate_audit_token;
423 #endif
424 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
425 	mDNSu8						resolver_uuid[UUID_SIZE];
426 	mDNSBool					need_encryption;
427 	mdns_dns_service_id_t		custom_id;
428 #endif
429 	QueryRecordResultHandler _Nullable	user_handler;
430 	void *	_Nullable			user_context;
431 };
432 
433 #pragma mark denial_of_existence_records_t
434 typedef struct denial_of_existence_records denial_of_existence_records_t;
435 struct denial_of_existence_records {
436 	list_t						resource_records;			//list_t<ResourceRecord>;
437 };
438 
439 #pragma mark original_t
440 typedef struct original original_t;
441 struct original {													// This structure contains all the useful information about the user's original request.
442 	original_request_parameters_t				original_parameters;		// The original paramters getting from the user
443 	originals_with_rrsig_t						original_result_with_rrsig;	// The original response that will be returned to the user.
444 	const trust_anchors_t *			_Nullable	original_trust_anchor;		// It is possible that the returned original response is a trust anchor installed.
445 	mDNSs32										last_time_add;				// Last time that originals_with_rrsig_t records are added.
446 	mDNSs32										last_time_rmv;				// Last time that originals_with_rrsig_t records are removed.
447 };
448 
449 #pragma mark returned_answers_t
450 typedef struct returned_answers returned_answers_t;
451 struct returned_answers {			// This structure contains all the records that are returned to the user, these information is tracked to properly deliver ADD/RMV event to the user
452 	list_t					answers; 		// list_t<ResourceRecord *>, the list of "ResourceRecord *" pointers, each pointer points to a ResourceRecord in the cache that has been returned to the user.
453 	dnssec_result_t			dnssec_result;	// The dnssec_result_t that has been returned to the user.
454 	DNSServiceErrorType		error;			// The returned DNSServiceErrorType
455 	response_type_t			type;			// The type of the returned answer, it could be original_response(including suppressed case)/nsec_response/nsec3_response
456 };
457 
458 #pragma mark dnssec_context_t
459 // This structure contains the DNSSEC context that is needed to track additional information that is not provided by
460 // mDNSCore, each DNSSEC-enabled DNS request would have a seperated DNSSEC context.
461 typedef struct dnssec_context dnssec_context_t;
462 struct dnssec_context {
463 	// Necessary request
464 	QueryRecordClientRequest *		_Nonnull	me;								// The request of the question that we are currently working on.
465 	QueryRecordClientRequest					request_to_follow_cname;		// An idle request unless there is a need to follow the CNAME reference, and start a sub request.
466 
467 	// Zone records that could be used to validate records.
468 	list_t										zone_chain;						// list_t<dnssec_zone_t>, the validation tree consists of zone nodes from root to leaf.
469 
470 	// original request fields
471 	original_t original;														// Information about the user's original request.
472 
473 	// denial of existence fields
474 	denial_of_existence_records_t * _Nullable	denial_of_existence_records;	// It is a temporary field that is used to pass the NSEC/NSEC3 records to the DNSSEC handler, will be cleared after running DNSSEC handler.
475 
476 	// save the records that are returned to the user
477 	returned_answers_t							returned_answers;				// The records that have been returned to the user.
478 
479 	// DNSSEC context pointer
480 	dnssec_context_t *				_Nullable	primary_dnssec_context;			// This points to the initial DNSSEC context of the first query coming from the user, i.e. the first name in the CNAME chain.
481 	dnssec_context_t *				_Nullable	subtask_dnssec_context;			// If the DNSSEC-enabled DNS query has CNAMEs, this field is used to create another new DNSSEC context that resolves and validates the new CNAME.
482 };
483 
484 
485 #pragma mark - Functions
486 
487 
488 
489 #pragma mark - dns_type_*_t records parsing
490 
491 
492 
493 #pragma mark parsse_dns_type_cname_t
494 mDNSexport void
495 parsse_dns_type_cname_t(const void * const _Nonnull rdata, mDNSu8 * _Nullable * const _Nonnull out_cname);
496 
497 #pragma mark parse_dns_type_ds_t
498 mDNSexport mDNSBool
499 parse_dns_type_ds_t(
500 	const void * const	_Nonnull	rdata,
501 	const mDNSu16					rdata_length,
502 	mDNSu16 * const		_Nullable	out_key_tag,
503 	mDNSu8 * const		_Nullable	out_algorithm,
504 	mDNSu8 * const		_Nullable	out_digest_type,
505 	mDNSu16 * const		_Nullable	out_digest_length,
506 	const mDNSu8 * _Nonnull * const _Nullable	out_digest);
507 
508 #pragma mark parse_dns_type_dnskey_t
509 mDNSexport mDNSBool
510 parse_dns_type_dnskey_t(
511 	const void * const	_Nonnull	rdata,
512 	const mDNSu16					rdata_length,
513 	mDNSu16 * const		_Nullable	out_flags,
514 	mDNSu8 * const		_Nullable	out_protocol,
515 	mDNSu8 * const		_Nullable	out_algorithm,
516 	mDNSu16 * const		_Nullable	out_public_key_length,
517 	mDNSu8 * _Nonnull * const _Nullable out_public_key);
518 
519 #pragma mark parse_dns_type_rrsig_t
520 mDNSexport mDNSBool
521 parse_dns_type_rrsig_t(
522 	const void * const	_Nonnull	rdata,
523 	const mDNSu16					rdata_length,
524 	mDNSu16 * const		_Nullable	out_type_covered,
525 	mDNSu8 * const		_Nullable	out_algorithm,
526 	mDNSu8 * const		_Nullable	out_labels,
527 	mDNSu32 * const		_Nullable	out_original_ttl,
528 	mDNSu32 * const		_Nullable	out_signature_expiration,
529 	mDNSu32 * const		_Nullable	out_signature_inception,
530 	mDNSu16 * const		_Nullable	out_key_tag,
531 	mDNSu16 * const		_Nullable	out_signature_length,
532 	mDNSu8 * _Nonnull * const _Nullable out_signer_name,
533 	mDNSu8 * _Nonnull * const _Nullable out_signature);
534 
535 #pragma mark parse_dns_type_nsec_t
536 mDNSexport mDNSBool
537 parse_dns_type_nsec_t(
538 	const void * const	_Nonnull	rdata,
539 	const mDNSu16					rdata_length,
540 	mDNSu16 * const		_Nonnull	out_type_bit_maps_length,
541 	mDNSu8 * _Nonnull * const _Nullable out_next_domain_name,
542 	mDNSu8 * _Nonnull * const _Nullable out_type_bit_maps);
543 
544 #pragma mark parse_dns_type_nsec3_t
545 mDNSexport mDNSBool
546 parse_dns_type_nsec3_t(
547 	const void * const	_Nonnull	rdata,
548 	const mDNSu16					rdata_length,
549 	mDNSu8 * const		_Nullable	out_hash_algorithm,
550 	mDNSu8 * const		_Nullable	out_flags,
551 	mDNSu16 * const		_Nullable	out_iterations,
552 	mDNSu8 * const		_Nullable	out_salt_length,
553 	mDNSu8 * const		_Nullable	out_hash_length,
554 	mDNSu16 * const		_Nullable	out_type_bit_maps_length,
555 	mDNSu8 * _Nonnull * const _Nullable out_salt,
556 	mDNSu8 * _Nonnull * const _Nullable out_next_hashed_owner_name,
557 	mDNSu8 * _Nonnull * const _Nullable out_type_bit_maps);
558 
559 #pragma mark get_covered_type_of_dns_type_rrsig_t
560 mDNSexport mDNSu16
561 get_covered_type_of_dns_type_rrsig_t(const void * const _Nonnull rdata);
562 
563 // dnssec_rr_t function prototypes
564 #pragma mark - dnssec_rr_t functions
565 
566 mDNSexport void
567 initialize_dnssec_rr_t(dnssec_rr_t * const _Nonnull dnssec_rr, ResourceRecord * const _Nonnull rr);
568 
569 mDNSexport void
570 uninitialize_dnssec_rr_t(dnssec_rr_t * const _Nonnull dnssec_rr);
571 
572 mDNSexport mDNSBool
573 equal_dnssec_rr_t(const dnssec_rr_t * const _Nonnull left, const dnssec_rr_t * const _Nonnull right);
574 
575 mDNSexport void
576 print_dnssec_rr_t(const dnssec_rr_t * const _Nonnull dnssec_rr, mDNSu8 num_of_tabs);
577 
578 // dnssec_original_t function prototypes
579 #pragma mark - dnssec_original_t functions
580 
581 mDNSexport void
582 initialize_dnssec_original_t(
583 	dnssec_original_t * const		_Nonnull	original,
584 	ResourceRecord * const			_Nonnull	rr,
585 	const mDNSBool								answer_from_cache,
586 	const DNSServiceErrorType					dns_error,
587 	const QC_result								qc_result);
588 
589 mDNSexport void
590 uninitialize_dnssec_original_t(dnssec_original_t * const _Nonnull original);
591 
592 mDNSexport void
593 print_dnssec_original_t(const dnssec_original_t * const _Nonnull original, mDNSu8 num_of_tabs);
594 
595 #pragma mark - dnssec_cname_t functions
596 
597 mDNSexport void
598 initialize_dnssec_cname_t(dnssec_cname_t * const _Nonnull cname, ResourceRecord * const _Nonnull rr);
599 
600 mDNSexport void
601 uninitialize_dnssec_cname_t(dnssec_cname_t * const _Nonnull cname);
602 
603 mDNSexport void
604 print_dnssec_cname_t(const dnssec_cname_t * const _Nonnull cname, mDNSu8 num_of_tabs);
605 
606 #pragma mark - dnssec_ds_t functions
607 
608 mDNSexport mDNSBool
609 initialize_dnssec_ds_t(dnssec_ds_t * const _Nonnull ds, ResourceRecord * const _Nonnull rr);
610 
611 mDNSexport mDNSBool
612 equals_dnssec_ds_t(const dnssec_ds_t * const _Nonnull left, const dnssec_ds_t * const _Nonnull right);
613 
614 mDNSexport void
615 uninitialize_dnssec_ds_t(dnssec_ds_t * const _Nonnull ds);
616 
617 mDNSexport void
618 print_dnssec_ds_t(const dnssec_ds_t * const _Nonnull ds, mDNSu8 num_of_tabs);
619 
620 #pragma mark - dnssec_dnskey_t functions
621 
622 mDNSexport mDNSBool
623 initialize_dnssec_dnskey_t(dnssec_dnskey_t * const _Nonnull dnskey, ResourceRecord * const _Nonnull rr);
624 
625 mDNSexport mDNSBool
626 equals_dnssec_dnskey_t(const dnssec_dnskey_t * const _Nonnull left, const dnssec_dnskey_t * const _Nonnull right);
627 
628 mDNSexport void
629 uninitialize_dnssec_dnskey_t(dnssec_dnskey_t * const _Nonnull dnskey);
630 
631 mDNSexport void
632 print_dnssec_dnskey_t(const dnssec_dnskey_t * const _Nonnull dnskey, mDNSu8 num_of_tabs);
633 
634 #pragma mark - dnssec_rrsig_t functions
635 
636 mDNSexport mDNSBool
637 initialize_dnssec_rrsig_t(dnssec_rrsig_t * const _Nonnull rrsig, ResourceRecord * const _Nonnull rr);
638 
639 mDNSexport void
640 uninitialize_dnssec_rrsig_t(dnssec_rrsig_t * const _Nonnull rrsig);
641 
642 mDNSexport void
643 print_dnssec_rrsig_t(const dnssec_rrsig_t * const _Nonnull rrsig, mDNSu8 num_of_tabs);
644 
645 #pragma mark - dnssec_nsec_t functions
646 
647 mDNSexport mDNSBool
648 initialize_dnssec_nsec_t(dnssec_nsec_t * const _Nonnull nsec, ResourceRecord * const _Nonnull rr);
649 
650 mDNSexport void
651 uninitialize_dnssec_nsec_t(dnssec_nsec_t * const _Nonnull nsec);
652 
653 mDNSexport void
654 print_dnssec_nsec_t(const dnssec_nsec_t * const _Nonnull nsec, mDNSu8 num_of_tabs);
655 
656 #pragma mark - dnssec_nsec3_t functions
657 
658 mDNSexport mDNSBool
659 initialize_dnssec_nsec3_t(dnssec_nsec3_t * const _Nonnull nsec3, ResourceRecord * const _Nonnull rr);
660 
661 mDNSexport void
662 uninitialize_dnssec_nsec3_t(dnssec_nsec3_t * const _Nonnull nsec3);
663 
664 mDNSexport void
665 print_dnssec_nsec3_t(const dnssec_nsec3_t * const _Nonnull nsec3, mDNSu8 num_of_tabs);
666 
667 #pragma mark - nsecs_with_rrsig_t functions
668 
669 mDNSexport mStatus
670 initialize_nsecs_with_rrsig_t(nsecs_with_rrsig_t * const _Nonnull nsecs);
671 
672 mDNSexport void
673 uninitialize_nsecs_with_rrsig_t(nsecs_with_rrsig_t * const _Nonnull nsecs);
674 
675 mDNSexport void
676 print_nsecs_with_rrsig_t(const nsecs_with_rrsig_t * const _Nonnull nsecs, mDNSu8 num_of_tabs);
677 
678 # pragma mark - one_nsec_with_rrsigs_t functions
679 
680 mDNSexport mDNSBool
681 initialize_one_nsec_with_rrsigs_t(
682 	one_nsec_with_rrsigs_t * const	_Nonnull	one_nsec_with_rrsigs,
683 	ResourceRecord * const 			_Nonnull	rr);
684 
685 mDNSexport void
686 uninitialize_one_nsec_with_rrsigs_t(one_nsec_with_rrsigs_t * const	_Nonnull one_nsec_with_rrsigs);
687 
688 # pragma mark - one_nsec3_with_rrsigs_t functions
689 
690 mDNSexport mDNSBool
691 initialize_one_nsec3_with_rrsigs_t(
692 	one_nsec3_with_rrsigs_t * const _Nonnull	one_nsec3_with_rrsigs,
693 	ResourceRecord * const 			_Nonnull	rr);
694 
695 mDNSexport void
696 uninitialize_one_nsec3_with_rrsigs_t(one_nsec3_with_rrsigs_t * const _Nonnull one_nsec3_with_rrsigs);
697 
698 #pragma mark - nsec3s_with_rrsig_t functions
699 
700 mDNSexport mStatus
701 initialize_nsec3s_with_rrsig_t(nsec3s_with_rrsig_t * const _Nonnull nsec3s);
702 
703 mDNSexport void
704 uninitialize_nsec3s_with_rrsig_t(nsec3s_with_rrsig_t * const _Nonnull nsec3s);
705 
706 mDNSexport void
707 print_nsec3s_with_rrsig_t(const nsec3s_with_rrsig_t * const _Nonnull nsec3s, mDNSu8 num_of_tabs);
708 
709 #pragma mark - cnames_with_rrsig_t
710 
711 mDNSexport void
712 initialize_cname_with_rrsig_t(cnames_with_rrsig_t * const _Nonnull cname);
713 
714 mDNSexport void
715 uninitialize_cname_with_rrsig_t(cnames_with_rrsig_t * const _Nonnull cname);
716 
717 mDNSexport void
718 print_cname_with_rrsig_t(const cnames_with_rrsig_t * const _Nonnull cname, mDNSu8 num_of_tabs);
719 
720 #pragma mark - response_type_t functions
721 
722 mDNSexport const char * _Nonnull
723 response_type_value_to_string(response_type_t type);
724 
725 #pragma mark - originals_with_rrsig_t
726 
727 mDNSexport void
728 initialize_originals_with_rrsig_t(originals_with_rrsig_t * const _Nonnull original, const response_type_t type);
729 
730 mDNSexport void
731 uninitialize_originals_with_rrsig_t(originals_with_rrsig_t * const _Nonnull original);
732 
733 mDNSexport mDNSBool
734 contains_rrsig_in_originals_with_rrsig_t(const originals_with_rrsig_t * const _Nonnull original);
735 
736 mDNSexport void
737 print_originals_with_rrsig_t(const originals_with_rrsig_t * const _Nonnull original, mDNSu8 num_of_tabs);
738 
739 #pragma mark - dses_with_rrsig_t functions
740 
741 mDNSexport void
742 initialize_dses_with_rrsig_t(dses_with_rrsig_t * const _Nonnull ds, const response_type_t type);
743 
744 mDNSexport void
745 uninitialize_dses_with_rrsig_t(dses_with_rrsig_t * const _Nonnull ds);
746 
747 mDNSexport mDNSBool
748 contains_rrsig_in_dses_with_rrsig_t(const dses_with_rrsig_t * const _Nonnull ds);
749 
750 mDNSexport void
751 print_dses_with_rrsig_t(const dses_with_rrsig_t * const _Nonnull ds, mDNSu8 num_of_tabs);
752 
753 #pragma mark - dses_with_rrsig_t functions
754 
755 mDNSexport void
756 initialize_dnskeys_with_rrsig_t(dnskeys_with_rrsig_t * const _Nonnull dnskey);
757 
758 mDNSexport void
759 uninitialize_dnskeys_with_rrsig_t(dnskeys_with_rrsig_t * const _Nonnull dnskey);
760 
761 mDNSexport mDNSBool
762 contains_rrsig_in_dnskeys_with_rrsig_t(const dnskeys_with_rrsig_t * const _Nonnull dnskey);
763 
764 mDNSexport void
765 print_dnskeys_with_rrsig_t(const dnskeys_with_rrsig_t * const _Nonnull dnskey, mDNSu8 num_of_tabs);
766 
767 mDNSexport void
768 print_original_request_parameters_t(const original_request_parameters_t * const _Nonnull parameters, mDNSu8 num_of_tabs);
769 
770 #pragma mark - dnssec_zone_t functions
771 
772 mDNSexport void
773 initialize_dnssec_zone_t(
774 	dnssec_zone_t * const	_Nonnull	zone,
775 	const mDNSu8 * const	_Nonnull	domain_name);
776 
777 mDNSexport void
778 uninitialize_dnssec_zone_t(dnssec_zone_t * const _Nonnull zone);
779 
780 mDNSexport void
781 stop_and_clean_dnssec_zone_t(dnssec_zone_t * const _Nonnull zone);
782 
783 mDNSexport void
784 print_dnssec_zone_t(const dnssec_zone_t * const _Nonnull zone, mDNSu8 num_of_tabs);
785 
786 #pragma mark - returned_answers_t
787 
788 mDNSexport void
789 initialize_returned_answers_t(
790 	returned_answers_t * const	_Nonnull	returned_answers,
791 	const dnssec_result_t					dnssec_result,
792 	const DNSServiceErrorType				error);
793 
794 mDNSexport void
795 uninitialize_returned_answers_t(returned_answers_t * const _Nonnull returned_answers);
796 
797 mDNSexport void
798 print_returned_answers_t(const returned_answers_t * const _Nonnull returned_answers, mDNSu8 num_of_tabs);
799 
800 #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
801 #endif // DNSSEC_v2_STRUCTS_H
802