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