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