Home | History | Annotate | Line # | Download | only in dns
      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