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_DISPATCH_H
15 #define DNS_DISPATCH_H 1
16 
17 /*****
18 ***** Module Info
19 *****/
20 
21 /*! \file dns/dispatch.h
22  * \brief
23  * DNS Dispatch Management
24  * 	Shared UDP and single-use TCP dispatches for queries and responses.
25  *
26  * MP:
27  *
28  *\li     	All locking is performed internally to each dispatch.
29  * 	Restrictions apply to dns_dispatch_removeresponse().
30  *
31  * Reliability:
32  *
33  * Resources:
34  *
35  * Security:
36  *
37  *\li	Depends on the isc_socket_t and dns_message_t for prevention of
38  *	buffer overruns.
39  *
40  * Standards:
41  *
42  *\li	None.
43  */
44 
45 /***
46  *** Imports
47  ***/
48 
49 #include <inttypes.h>
50 #include <stdbool.h>
51 
52 #include <isc/buffer.h>
53 #include <isc/lang.h>
54 #include <isc/mutex.h>
55 #include <isc/socket.h>
56 #include <isc/types.h>
57 
58 #include <dns/types.h>
59 
60 ISC_LANG_BEGINDECLS
61 
62 /*%
63  * This event is sent to a task when a response comes in.
64  * No part of this structure should ever be modified by the caller,
65  * other than parts of the buffer.  The holy parts of the buffer are
66  * the base and size of the buffer.  All other parts of the buffer may
67  * be used.  On event delivery the used region contains the packet.
68  *
69  * "id" is the received message id,
70  *
71  * "addr" is the host that sent it to us,
72  *
73  * "buffer" holds state on the received data.
74  *
75  * The "free" routine for this event will clean up itself as well as
76  * any buffer space allocated from common pools.
77  */
78 
79 struct dns_dispatchevent {
80 	ISC_EVENT_COMMON(dns_dispatchevent_t); /*%< standard event common */
81 	isc_result_t	   result;	       /*%< result code */
82 	int32_t		   id;		       /*%< message id */
83 	isc_sockaddr_t	   addr;	       /*%< address recv'd from */
84 	struct in6_pktinfo pktinfo;	       /*%< reply info for v6 */
85 	isc_buffer_t	   buffer;	       /*%< data buffer */
86 	uint32_t	   attributes;	       /*%< mirrored from socket.h */
87 };
88 
89 /*%
90  * This is a set of one or more dispatches which can be retrieved
91  * round-robin fashion.
92  */
93 struct dns_dispatchset {
94 	isc_mem_t	  *mctx;
95 	dns_dispatch_t **dispatches;
96 	int		 ndisp;
97 	int		 cur;
98 	isc_mutex_t	 lock;
99 };
100 
101 /*@{*/
102 /*%
103  * Attributes for added dispatchers.
104  *
105  * Values with the mask 0xffff0000 are application defined.
106  * Values with the mask 0x0000ffff are library defined.
107  *
108  * Insane values (like setting both TCP and UDP) are not caught.  Don't
109  * do that.
110  *
111  * _PRIVATE
112  *	The dispatcher cannot be shared.
113  *
114  * _TCP, _UDP
115  *	The dispatcher is a TCP or UDP socket.
116  *
117  * _IPV4, _IPV6
118  *	The dispatcher uses an IPv4 or IPv6 socket.
119  *
120  * _NOLISTEN
121  *	The dispatcher should not listen on the socket.
122  *
123  * _MAKEQUERY
124  *	The dispatcher can be used to issue queries to other servers, and
125  *	accept replies from them.
126  *
127  * _RANDOMPORT
128  *	Previously used to indicate that the port of a dispatch UDP must be
129  *	chosen randomly.  This behavior now always applies and the attribute
130  *	is obsoleted.
131  *
132  * _EXCLUSIVE
133  *	A separate socket will be used on-demand for each transaction.
134  */
135 #define DNS_DISPATCHATTR_PRIVATE   0x00000001U
136 #define DNS_DISPATCHATTR_TCP	   0x00000002U
137 #define DNS_DISPATCHATTR_UDP	   0x00000004U
138 #define DNS_DISPATCHATTR_IPV4	   0x00000008U
139 #define DNS_DISPATCHATTR_IPV6	   0x00000010U
140 #define DNS_DISPATCHATTR_NOLISTEN  0x00000020U
141 #define DNS_DISPATCHATTR_MAKEQUERY 0x00000040U
142 #define DNS_DISPATCHATTR_CONNECTED 0x00000080U
143 #define DNS_DISPATCHATTR_FIXEDID   0x00000100U
144 #define DNS_DISPATCHATTR_EXCLUSIVE 0x00000200U
145 #define DNS_DISPATCHATTR_CANREUSE  0x00000400U
146 /*@}*/
147 
148 /*
149  */
150 #define DNS_DISPATCHOPT_FIXEDID 0x00000001U
151 
152 isc_result_t
153 dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp);
154 /*%<
155  * Creates a new dispatchmgr object.
156  *
157  * Requires:
158  *\li	"mctx" be a valid memory context.
159  *
160  *\li	mgrp != NULL && *mgrp == NULL
161  *
162  * Returns:
163  *\li	ISC_R_SUCCESS	-- all ok
164  *
165  *\li	anything else	-- failure
166  */
167 
168 void
169 dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp);
170 /*%<
171  * Destroys the dispatchmgr when it becomes empty.  This could be
172  * immediately.
173  *
174  * Requires:
175  *\li	mgrp != NULL && *mgrp is a valid dispatchmgr.
176  */
177 
178 void
179 dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole);
180 /*%<
181  * Sets the dispatcher's "blackhole list," a list of addresses that will
182  * be ignored by all dispatchers created by the dispatchmgr.
183  *
184  * Requires:
185  * \li	mgrp is a valid dispatchmgr
186  * \li	blackhole is a valid acl
187  */
188 
189 dns_acl_t *
190 dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr);
191 /*%<
192  * Gets a pointer to the dispatcher's current blackhole list,
193  * without incrementing its reference count.
194  *
195  * Requires:
196  *\li 	mgr is a valid dispatchmgr
197  * Returns:
198  *\li	A pointer to the current blackhole list, or NULL.
199  */
200 
201 void
202 dns_dispatchmgr_setblackportlist(dns_dispatchmgr_t *mgr,
203 				 dns_portlist_t	*portlist);
204 /*%<
205  * This function is deprecated.  Use dns_dispatchmgr_setavailports() instead.
206  *
207  * Requires:
208  *\li	mgr is a valid dispatchmgr
209  */
210 
211 dns_portlist_t *
212 dns_dispatchmgr_getblackportlist(dns_dispatchmgr_t *mgr);
213 /*%<
214  * This function is deprecated and always returns NULL.
215  *
216  * Requires:
217  *\li	mgr is a valid dispatchmgr
218  */
219 
220 isc_result_t
221 dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
222 			      isc_portset_t *v6portset);
223 /*%<
224  * Sets a list of UDP ports that can be used for outgoing UDP messages.
225  *
226  * Requires:
227  *\li	mgr is a valid dispatchmgr
228  *\li	v4portset is NULL or a valid port set
229  *\li	v6portset is NULL or a valid port set
230  */
231 
232 void
233 dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats);
234 /*%<
235  * Sets statistics counter for the dispatchmgr.  This function is expected to
236  * be called only on zone creation (when necessary).
237  * Once installed, it cannot be removed or replaced.  Also, there is no
238  * interface to get the installed stats from the zone; the caller must keep the
239  * stats to reference (e.g. dump) it later.
240  *
241  * Requires:
242  *\li	mgr is a valid dispatchmgr with no managed dispatch.
243  *\li	stats is a valid statistics supporting resolver statistics counters
244  *	(see dns/stats.h).
245  */
246 
247 isc_result_t
248 dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
249 		    isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
250 		    unsigned int buffersize, unsigned int maxbuffers,
251 		    unsigned int maxrequests, unsigned int buckets,
252 		    unsigned int increment, unsigned int attributes,
253 		    unsigned int mask, dns_dispatch_t **dispp);
254 
255 isc_result_t
256 dns_dispatch_getudp_dup(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
257 			isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
258 			unsigned int buffersize, unsigned int maxbuffers,
259 			unsigned int maxrequests, unsigned int buckets,
260 			unsigned int increment, unsigned int attributes,
261 			unsigned int mask, dns_dispatch_t **dispp,
262 			dns_dispatch_t *dup);
263 /*%<
264  * Attach to existing dns_dispatch_t if one is found with dns_dispatchmgr_find,
265  * otherwise create a new UDP dispatch.
266  *
267  * Requires:
268  *\li	All pointer parameters be valid for their respective types.
269  *
270  *\li	dispp != NULL && *disp == NULL
271  *
272  *\li	512 <= buffersize <= 64k
273  *
274  *\li	maxbuffers > 0
275  *
276  *\li	buckets < 2097169
277  *
278  *\li	increment > buckets
279  *
280  *\li	(attributes & DNS_DISPATCHATTR_TCP) == 0
281  *
282  * Returns:
283  *\li	ISC_R_SUCCESS	-- success.
284  *
285  *\li	Anything else	-- failure.
286  */
287 
288 isc_result_t
289 dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
290 		       isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr,
291 		       const isc_sockaddr_t *destaddr, unsigned int buffersize,
292 		       unsigned int maxbuffers, unsigned int maxrequests,
293 		       unsigned int buckets, unsigned int increment,
294 		       unsigned int attributes, dns_dispatch_t **dispp);
295 /*%<
296  * Create a new dns_dispatch and attach it to the provided isc_socket_t.
297  *
298  * For all dispatches, "buffersize" is the maximum packet size we will
299  * accept.
300  *
301  * "maxbuffers" and "maxrequests" control the number of buffers in the
302  * overall system and the number of buffers which can be allocated to
303  * requests.
304  *
305  * "buckets" is the number of buckets to use, and should be prime.
306  *
307  * "increment" is used in a collision avoidance function, and needs to be
308  * a prime > buckets, and not 2.
309  *
310  * Requires:
311  *
312  *\li	mgr is a valid dispatch manager.
313  *
314  *\li	sock is a valid.
315  *
316  *\li	task is a valid task that can be used internally to this dispatcher.
317  *
318  * \li	512 <= buffersize <= 64k
319  *
320  *\li	maxbuffers > 0.
321  *
322  *\li	maxrequests <= maxbuffers.
323  *
324  *\li	buckets < 2097169 (the next prime after 65536 * 32)
325  *
326  *\li	increment > buckets (and prime).
327  *
328  *\li	attributes includes #DNS_DISPATCHATTR_TCP and does not include
329  *	#DNS_DISPATCHATTR_UDP.
330  *
331  * Returns:
332  *\li	ISC_R_SUCCESS	-- success.
333  *
334  *\li	Anything else	-- failure.
335  */
336 
337 void
338 dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp);
339 /*%<
340  * Attach to a dispatch handle.
341  *
342  * Requires:
343  *\li	disp is valid.
344  *
345  *\li	dispp != NULL && *dispp == NULL
346  */
347 
348 void
349 dns_dispatch_detach(dns_dispatch_t **dispp);
350 /*%<
351  * Detaches from the dispatch.
352  *
353  * Requires:
354  *\li	dispp != NULL and *dispp be a valid dispatch.
355  */
356 
357 void
358 dns_dispatch_starttcp(dns_dispatch_t *disp);
359 /*%<
360  * Start processing of a TCP dispatch once the socket connects.
361  *
362  * Requires:
363  *\li	'disp' is valid.
364  */
365 
366 isc_result_t
367 dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr,
368 		    const isc_sockaddr_t *localaddr, bool *connected,
369 		    dns_dispatch_t **dispp);
370 /*
371  * Attempt to connect to a existing TCP connection (connection completed
372  * if connected == NULL).
373  */
374 
375 isc_result_t
376 dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
377 			 const isc_sockaddr_t *dest, isc_task_t *task,
378 			 isc_taskaction_t action, void *arg, uint16_t *idp,
379 			 dns_dispentry_t **resp, isc_socketmgr_t *sockmgr);
380 /*%<
381  * Add a response entry for this dispatch.
382  *
383  * "*idp" is filled in with the assigned message ID, and *resp is filled in
384  * to contain the magic token used to request event flow stop.
385  *
386  * Arranges for the given task to get a callback for response packets.  When
387  * the event is delivered, it must be returned using dns_dispatch_freeevent()
388  * or through dns_dispatch_removeresponse() for another to be delivered.
389  *
390  * Requires:
391  *\li	"idp" be non-NULL.
392  *
393  *\li	"task" "action" and "arg" be set as appropriate.
394  *
395  *\li	"dest" be non-NULL and valid.
396  *
397  *\li	"resp" be non-NULL and *resp be NULL
398  *
399  *\li	"sockmgr" be NULL or a valid socket manager.  If 'disp' has
400  *	the DNS_DISPATCHATTR_EXCLUSIVE attribute, this must not be NULL,
401  *	which also means dns_dispatch_addresponse() cannot be used.
402  *
403  * Ensures:
404  *
405  *\li	&lt;id, dest> is a unique tuple.  That means incoming messages
406  *	are identifiable.
407  *
408  * Returns:
409  *
410  *\li	ISC_R_SUCCESS		-- all is well.
411  *\li	ISC_R_NOMEMORY		-- memory could not be allocated.
412  *\li	ISC_R_NOMORE		-- no more message ids can be allocated
413  *				   for this destination.
414  */
415 
416 void
417 dns_dispatch_removeresponse(dns_dispentry_t	    **resp,
418 			    dns_dispatchevent_t **sockevent);
419 /*%<
420  * Stops the flow of responses for the provided id and destination.
421  * If "sockevent" is non-NULL, the dispatch event and associated buffer is
422  * also returned to the system.
423  *
424  * Requires:
425  *\li	"resp" != NULL and "*resp" contain a value previously allocated
426  *	by dns_dispatch_addresponse();
427  *
428  *\li	May only be called from within the task given as the 'task'
429  * 	argument to dns_dispatch_addresponse() when allocating '*resp'.
430  */
431 
432 isc_socket_t *
433 dns_dispatch_getentrysocket(dns_dispentry_t *resp);
434 
435 isc_socket_t *
436 dns_dispatch_getsocket(dns_dispatch_t *disp);
437 /*%<
438  * Return the socket associated with this dispatcher.
439  *
440  * Requires:
441  *\li	disp is valid.
442  *
443  * Returns:
444  *\li	The socket the dispatcher is using.
445  */
446 
447 isc_result_t
448 dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp);
449 /*%<
450  * Return the local address for this dispatch.
451  * This currently only works for dispatches using UDP sockets.
452  *
453  * Requires:
454  *\li	disp is valid.
455  *\li	addrp to be non null.
456  *
457  * Returns:
458  *\li	ISC_R_SUCCESS
459  *\li	ISC_R_NOTIMPLEMENTED
460  */
461 
462 void
463 dns_dispatch_cancel(dns_dispatch_t *disp);
464 /*%<
465  * cancel outstanding clients
466  *
467  * Requires:
468  *\li	disp is valid.
469  */
470 
471 unsigned int
472 dns_dispatch_getattributes(dns_dispatch_t *disp);
473 /*%<
474  * Return the attributes (DNS_DISPATCHATTR_xxx) of this dispatch.  Only the
475  * non-changeable attributes are expected to be referenced by the caller.
476  *
477  * Requires:
478  *\li	disp is valid.
479  */
480 
481 void
482 dns_dispatch_changeattributes(dns_dispatch_t *disp, unsigned int attributes,
483 			      unsigned int mask);
484 /*%<
485  * Set the bits described by "mask" to the corresponding values in
486  * "attributes".
487  *
488  * That is:
489  *
490  * \code
491  *	new = (old & ~mask) | (attributes & mask)
492  * \endcode
493  *
494  * This function has a side effect when #DNS_DISPATCHATTR_NOLISTEN changes.
495  * When the flag becomes off, the dispatch will start receiving on the
496  * corresponding socket.  When the flag becomes on, receive events on the
497  * corresponding socket will be canceled.
498  *
499  * Requires:
500  *\li	disp is valid.
501  *
502  *\li	attributes are reasonable for the dispatch.  That is, setting the UDP
503  *	attribute on a TCP socket isn't reasonable.
504  */
505 
506 void
507 dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event);
508 /*%<
509  * Inform the dispatcher of a socket receive.  This is used for sockets
510  * shared between dispatchers and clients.  If the dispatcher fails to copy
511  * or send the event, nothing happens.
512  *
513  * If the attribute DNS_DISPATCHATTR_NOLISTEN is not set, then
514  * the dispatch is already handling a recv; return immediately.
515  *
516  * Requires:
517  *\li 	disp is valid, and the attribute DNS_DISPATCHATTR_NOLISTEN is set.
518  * 	event != NULL
519  */
520 
521 dns_dispatch_t *
522 dns_dispatchset_get(dns_dispatchset_t *dset);
523 /*%<
524  * Retrieve the next dispatch from dispatch set 'dset', and increment
525  * the round-robin counter.
526  *
527  * Requires:
528  *\li 	dset != NULL
529  */
530 
531 isc_result_t
532 dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr,
533 		       isc_taskmgr_t *taskmgr, dns_dispatch_t *source,
534 		       dns_dispatchset_t **dsetp, int n);
535 /*%<
536  * Given a valid dispatch 'source', create a dispatch set containing
537  * 'n' UDP dispatches, with the remainder filled out by clones of the
538  * source.
539  *
540  * Requires:
541  *\li 	source is a valid UDP dispatcher
542  *\li 	dsetp != NULL, *dsetp == NULL
543  */
544 
545 void
546 dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task);
547 /*%<
548  * Cancel socket operations for the dispatches in 'dset'.
549  */
550 
551 void
552 dns_dispatchset_destroy(dns_dispatchset_t **dsetp);
553 /*%<
554  * Dereference all the dispatches in '*dsetp', free the dispatchset
555  * memory, and set *dsetp to NULL.
556  *
557  * Requires:
558  *\li 	dset is valid
559  */
560 
561 void
562 dns_dispatch_setdscp(dns_dispatch_t *disp, isc_dscp_t dscp);
563 isc_dscp_t
564 dns_dispatch_getdscp(dns_dispatch_t *disp);
565 /*%<
566  * Set/get the DSCP value to be used when sending responses to clients,
567  * as defined in the "listen-on" or "listen-on-v6" statements.
568  *
569  * Requires:
570  *\li	disp is valid.
571  */
572 
573 isc_result_t
574 dns_dispatch_getnext(dns_dispentry_t *resp, dns_dispatchevent_t **sockevent);
575 /*%<
576  * Free the sockevent and trigger the sending of the next item off the
577  * dispatch queue if present.
578  *
579  * Requires:
580  *\li	resp is valid
581  *\li	*sockevent to be valid
582  */
583 
584 ISC_LANG_ENDDECLS
585 
586 #endif /* DNS_DISPATCH_H */
587