1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * SPDX-License-Identifier: MPL-2.0
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 #ifndef DNS_CLIENT_H
15 #define DNS_CLIENT_H 1
16 
17 /*****
18 ***** Module Info
19 *****/
20 
21 /*! \file
22  *
23  * \brief
24  * The DNS client module provides convenient programming interfaces to various
25  * DNS services, such as name resolution with or without DNSSEC validation or
26  * dynamic DNS update.  This module is primarily expected to be used by other
27  * applications than BIND9-related ones that need such advanced DNS features.
28  *
29  * MP:
30  *\li	In the typical usage of this module, application threads will not share
31  *	the same data structures created and manipulated in this module.
32  *	However, the module still ensures appropriate synchronization of such
33  *	data structures.
34  *
35  * Resources:
36  *\li	TBS
37  *
38  * Security:
39  *\li	This module does not handle any low-level data directly, and so no
40  *	security issue specific to this module is anticipated.
41  */
42 
43 #include <isc/event.h>
44 #include <isc/sockaddr.h>
45 
46 #include <dns/tsig.h>
47 #include <dns/types.h>
48 
49 #include <dst/dst.h>
50 
51 typedef enum {
52 	updateop_none = 0,
53 	updateop_add = 1,
54 	updateop_delete = 2,
55 	updateop_exist = 3,
56 	updateop_notexist = 4,
57 	updateop_max = 5
58 } dns_client_updateop_t;
59 
60 ISC_LANG_BEGINDECLS
61 
62 /***
63  *** Types
64  ***/
65 
66 /*%
67  * Optional flags for dns_client_create(x).
68  */
69 /*%< Enable caching resolution results (experimental). */
70 #define DNS_CLIENTCREATEOPT_USECACHE 0x8000
71 
72 /*%
73  * Optional flags for dns_client_(start)resolve.
74  */
75 /*%< Do not return DNSSEC data (e.g. RRSIGS) with response. */
76 #define DNS_CLIENTRESOPT_NODNSSEC 0x01
77 /*%< Allow running external context. */
78 #define DNS_CLIENTRESOPT_RESERVED 0x02
79 /*%< Don't validate responses. */
80 #define DNS_CLIENTRESOPT_NOVALIDATE 0x04
81 /*%< Don't set the CD flag on upstream queries. */
82 #define DNS_CLIENTRESOPT_NOCDFLAG 0x08
83 /*%< Use TCP transport. */
84 #define DNS_CLIENTRESOPT_TCP 0x10
85 
86 /*%
87  * Optional flags for dns_client_(start)request.
88  */
89 /*%< Allow running external context. */
90 #define DNS_CLIENTREQOPT_RESERVED 0x01
91 /*%< Use TCP transport. */
92 #define DNS_CLIENTREQOPT_TCP 0x02
93 
94 /*%
95  * Optional flags for dns_client_(start)update.
96  */
97 /*%< Allow running external context. */
98 #define DNS_CLIENTUPDOPT_RESERVED 0x01
99 /*%< Use TCP transport. */
100 #define DNS_CLIENTUPDOPT_TCP 0x02
101 
102 /*%
103  * View name used in dns_client.
104  */
105 #define DNS_CLIENTVIEW_NAME "_dnsclient"
106 
107 /*%
108  * A dns_clientresevent_t is sent when name resolution performed by a client
109  * completes.  'result' stores the result code of the entire resolution
110  * procedure.  'vresult' specifically stores the result code of DNSSEC
111  * validation if it is performed.  When name resolution successfully completes,
112  * 'answerlist' is typically non empty, containing answer names along with
113  * RRsets.  It is the receiver's responsibility to free this list by calling
114  * dns_client_freeresanswer() before freeing the event structure.
115  */
116 typedef struct dns_clientresevent {
117 	ISC_EVENT_COMMON(struct dns_clientresevent);
118 	isc_result_t   result;
119 	isc_result_t   vresult;
120 	dns_namelist_t answerlist;
121 } dns_clientresevent_t; /* too long? */
122 
123 /*%
124  * A dns_clientreqevent_t is sent when a DNS request is completed by a client.
125  * 'result' stores the result code of the entire transaction.
126  * If the transaction is successfully completed but the response packet cannot
127  * be parsed, 'result' will store the result code of dns_message_parse().
128  * If the response packet is received, 'rmessage' will contain the response
129  * message, whether it is successfully parsed or not.
130  */
131 typedef struct dns_clientreqevent {
132 	ISC_EVENT_COMMON(struct dns_clientreqevent);
133 	isc_result_t   result;
134 	dns_message_t *rmessage;
135 } dns_clientreqevent_t; /* too long? */
136 
137 isc_result_t
138 dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
139 		  isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr,
140 		  unsigned int options, dns_client_t **clientp,
141 		  const isc_sockaddr_t *localaddr4,
142 		  const isc_sockaddr_t *localaddr6);
143 /*%<
144  * Create a DNS client object with minimal internal resources, such as
145  * a default view for the IN class and IPv4/IPv6 dispatches for the view.
146  *
147  * dns_client_create() takes 'manager' arguments so that the caller can
148  * control the behavior of the client through the underlying event framework.
149  * 'localaddr4' and 'localaddr6' specify the local addresses to use for
150  * each address family; if both are set to NULL, then wildcard addresses
151  * will be used for both families. If only one is NULL, then the other
152  * address will be used as the local address, and the NULL protocol family
153  * will not be used.
154  *
155  * Requires:
156  *
157  *\li	'mctx' is a valid memory context.
158  *
159  *\li	'actx' is a valid application context.
160  *
161  *\li	'taskmgr' is a valid task manager.
162  *
163  *\li	'socketmgr' is a valid socket manager.
164  *
165  *\li	'timermgr' is a valid timer manager.
166  *
167  *\li	clientp != NULL && *clientp == NULL.
168  *
169  * Returns:
170  *
171  *\li	#ISC_R_SUCCESS				On success.
172  *
173  *\li	Anything else				Failure.
174  */
175 
176 void
177 dns_client_destroy(dns_client_t **clientp);
178 /*%<
179  * Destroy 'client'.
180  *
181  * Requires:
182  *
183  *\li	'*clientp' is a valid client.
184  *
185  * Ensures:
186  *
187  *\li	*clientp == NULL.
188  */
189 
190 isc_result_t
191 dns_client_setservers(dns_client_t *client, dns_rdataclass_t rdclass,
192 		      const dns_name_t *name_space, isc_sockaddrlist_t *addrs);
193 /*%<
194  * Specify a list of addresses of recursive name servers that the client will
195  * use for name resolution.  A view for the 'rdclass' class must be created
196  * beforehand.  If 'name_space' is non NULL, the specified server will be used
197  * if and only if the query name is a subdomain of 'name_space'.  When servers
198  * for multiple 'name_space's are provided, and a query name is covered by
199  * more than one 'name_space', the servers for the best (longest) matching
200  * name_space will be used.  If 'name_space' is NULL, it works as if
201  * dns_rootname (.) were specified.
202  *
203  * Requires:
204  *
205  *\li	'client' is a valid client.
206  *
207  *\li	'name_space' is NULL or a valid name.
208  *
209  *\li	'addrs' != NULL.
210  *
211  * Returns:
212  *
213  *\li	#ISC_R_SUCCESS				On success.
214  *
215  *\li	Anything else				Failure.
216  */
217 
218 isc_result_t
219 dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass,
220 			const dns_name_t *name_space);
221 /*%<
222  * Remove configured recursive name servers for the 'rdclass' and 'name_space'
223  * from the client.  See the description of dns_client_setservers() for
224  * the requirements about 'rdclass' and 'name_space'.
225  *
226  * Requires:
227  *
228  *\li	'client' is a valid client.
229  *
230  *\li	'name_space' is NULL or a valid name.
231  *
232  * Returns:
233  *
234  *\li	#ISC_R_SUCCESS				On success.
235  *
236  *\li	Anything else				Failure.
237  */
238 
239 isc_result_t
240 dns_client_resolve(dns_client_t *client, const dns_name_t *name,
241 		   dns_rdataclass_t rdclass, dns_rdatatype_t type,
242 		   unsigned int options, dns_namelist_t *namelist);
243 
244 isc_result_t
245 dns_client_startresolve(dns_client_t *client, const dns_name_t *name,
246 			dns_rdataclass_t rdclass, dns_rdatatype_t type,
247 			unsigned int options, isc_task_t *task,
248 			isc_taskaction_t action, void *arg,
249 			dns_clientrestrans_t **transp);
250 /*%<
251  * Perform name resolution for 'name', 'rdclass', and 'type'.
252  *
253  * If any trusted keys are configured and the query name is considered to
254  * belong to a secure zone, these functions also validate the responses
255  * using DNSSEC by default.  If the DNS_CLIENTRESOPT_NOVALIDATE flag is set
256  * in 'options', DNSSEC validation is disabled regardless of the configured
257  * trusted keys or the query name. With DNS_CLIENTRESOPT_NODNSSEC
258  * DNSSEC data is not returned with response. DNS_CLIENTRESOPT_NOCDFLAG
259  * disables the CD flag on queries, DNS_CLIENTRESOPT_TCP switches to
260  * the TCP (vs. UDP) transport.
261  *
262  * dns_client_resolve() provides a synchronous service.  This function starts
263  * name resolution internally and blocks until it completes.  On success,
264  * 'namelist' will contain a list of answer names, each of which has
265  * corresponding RRsets.  The caller must provide a valid empty list, and
266  * is responsible for freeing the list content via dns_client_freeresanswer().
267  * If the name resolution fails due to an error in DNSSEC validation,
268  * dns_client_resolve() returns the result code indicating the validation
269  * error. Otherwise, it returns the result code of the entire resolution
270  * process, either success or failure.
271  *
272  * It is expected that the client object passed to dns_client_resolve() was
273  * created via dns_client_create() and has external managers and contexts.
274  *
275  * dns_client_startresolve() is an asynchronous version of dns_client_resolve()
276  * and does not block.  When name resolution is completed, 'action' will be
277  * called with the argument of a 'dns_clientresevent_t' object, which contains
278  * the resulting list of answer names (on success).  On return, '*transp' is
279  * set to an opaque transaction ID so that the caller can cancel this
280  * resolution process.
281  *
282  * Requires:
283  *
284  *\li	'client' is a valid client.
285  *
286  *\li	'addrs' != NULL.
287  *
288  *\li	'name' is a valid name.
289  *
290  *\li	'namelist' != NULL and is not empty.
291  *
292  *\li	'task' is a valid task.
293  *
294  *\li	'transp' != NULL && *transp == NULL;
295  *
296  * Returns:
297  *
298  *\li	#ISC_R_SUCCESS				On success.
299  *
300  *\li	Anything else				Failure.
301  */
302 
303 void
304 dns_client_cancelresolve(dns_clientrestrans_t *trans);
305 /*%<
306  * Cancel an ongoing resolution procedure started via
307  * dns_client_startresolve().
308  *
309  * Notes:
310  *
311  *\li	If the resolution procedure has not completed, post its CLIENTRESDONE
312  *	event with a result code of #ISC_R_CANCELED.
313  *
314  * Requires:
315  *
316  *\li	'trans' is a valid transaction ID.
317  */
318 
319 void
320 dns_client_destroyrestrans(dns_clientrestrans_t **transp);
321 /*%<
322  * Destroy name resolution transaction state identified by '*transp'.
323  *
324  * Requires:
325  *
326  *\li	'*transp' is a valid transaction ID.
327  *
328  *\li	The caller has received the CLIENTRESDONE event (either because the
329  *	resolution completed or because dns_client_cancelresolve() was called).
330  *
331  * Ensures:
332  *
333  *\li	*transp == NULL.
334  */
335 
336 void
337 dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist);
338 /*%<
339  * Free resources allocated for the content of 'namelist'.
340  *
341  * Requires:
342  *
343  *\li	'client' is a valid client.
344  *
345  *\li	'namelist' != NULL.
346  */
347 
348 isc_result_t
349 dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
350 			 dns_rdatatype_t rdtype, const dns_name_t *keyname,
351 			 isc_buffer_t *keydatabuf);
352 /*%<
353  * Add a DNSSEC trusted key for the 'rdclass' class.  A view for the 'rdclass'
354  * class must be created beforehand.  'rdtype' is the type of the RR data
355  * for the key, either DNSKEY or DS.  'keyname' is the DNS name of the key,
356  * and 'keydatabuf' stores the RR data.
357  *
358  * Requires:
359  *
360  *\li	'client' is a valid client.
361  *
362  *\li	'keyname' is a valid name.
363  *
364  *\li	'keydatabuf' is a valid buffer.
365  *
366  * Returns:
367  *
368  *\li	#ISC_R_SUCCESS				On success.
369  *
370  *\li	Anything else				Failure.
371  */
372 
373 isc_result_t
374 dns_client_request(dns_client_t *client, dns_message_t *qmessage,
375 		   dns_message_t *rmessage, const isc_sockaddr_t *server,
376 		   unsigned int options, unsigned int parseoptions,
377 		   dns_tsec_t *tsec, unsigned int timeout,
378 		   unsigned int udptimeout, unsigned int udpretries);
379 
380 isc_result_t
381 dns_client_startrequest(dns_client_t *client, dns_message_t *qmessage,
382 			dns_message_t *rmessage, const isc_sockaddr_t *server,
383 			unsigned int options, unsigned int parseoptions,
384 			dns_tsec_t *tsec, unsigned int timeout,
385 			unsigned int udptimeout, unsigned int udpretries,
386 			isc_task_t *task, isc_taskaction_t action, void *arg,
387 			dns_clientreqtrans_t **transp);
388 
389 /*%<
390  * Send a DNS request containing a query message 'query' to 'server'.
391  *
392  * 'parseoptions' will be used when the response packet is parsed, and will be
393  * passed to dns_message_parse() via dns_request_getresponse().  See
394  * dns_message_parse() for more details.
395  *
396  * 'tsec' is a transaction security object containing, e.g. a TSIG key for
397  * authenticating the request/response transaction.  This is optional and can
398  * be NULL, in which case this library performs the transaction  without any
399  * transaction authentication.
400  *
401  * 'timeout', 'udptimeout', and 'udpretries' are passed to
402  * dns_request_createvia3().  See dns_request_createvia3() for more details.
403  *
404  * dns_client_request() provides a synchronous service.  This function sends
405  * the request and blocks until a response is received.  On success,
406  * 'rmessage' will contain the response message.  The caller must provide a
407  * valid initialized message.
408  *
409  * It is expected that the client object passed to dns_client_request() was
410  * created via dns_client_create() and has external managers and contexts.
411  *
412  * dns_client_startrequest() is an asynchronous version of dns_client_request()
413  * and does not block.  When the transaction is completed, 'action' will be
414  * called with the argument of a 'dns_clientreqevent_t' object, which contains
415  * the response message (on success).  On return, '*transp' is set to an opaque
416  * transaction ID so that the caller can cancel this request.
417  *
418  * DNS_CLIENTREQOPT_TCP switches to the TCP (vs. UDP) transport.
419  *
420  * Requires:
421  *
422  *\li	'client' is a valid client.
423  *
424  *\li	'qmessage' and 'rmessage' are valid initialized message.
425  *
426  *\li	'server' is a valid socket address structure.
427  *
428  *\li	'task' is a valid task.
429  *
430  *\li	'transp' != NULL && *transp == NULL;
431  *
432  * Returns:
433  *
434  *\li	#ISC_R_SUCCESS				On success.
435  *
436  *\li	Anything else				Failure.
437  *
438  *\li	Any result that dns_message_parse() can return.
439  */
440 
441 void
442 dns_client_cancelrequest(dns_clientreqtrans_t *transp);
443 /*%<
444  * Cancel an ongoing DNS request procedure started via
445  * dns_client_startrequest().
446  *
447  * Notes:
448  *
449  *\li	If the request procedure has not completed, post its CLIENTREQDONE
450  *	event with a result code of #ISC_R_CANCELED.
451  *
452  * Requires:
453  *
454  *\li	'trans' is a valid transaction ID.
455  */
456 
457 void
458 dns_client_destroyreqtrans(dns_clientreqtrans_t **transp);
459 /*%
460  * Destroy DNS request transaction state identified by '*transp'.
461  *
462  * Requires:
463  *
464  *\li	'*transp' is a valid transaction ID.
465  *
466  *\li	The caller has received the CLIENTREQDONE event (either because the
467  *	request completed or because dns_client_cancelrequest() was called).
468  *
469  * Ensures:
470  *
471  *\li	*transp == NULL.
472  */
473 
474 ISC_LANG_ENDDECLS
475 
476 #endif /* DNS_CLIENT_H */
477