xref: /netbsd-src/external/mpl/bind/dist/lib/ns/include/ns/client.h (revision f8cf1a9151c7af1cb0bd8b09c13c66bca599c027)
1 /*	$NetBSD: client.h,v 1.17 2024/09/22 00:14:10 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 #pragma once
17 
18 /*****
19 ***** Module Info
20 *****/
21 
22 /*! \file
23  * \brief
24  * This module defines two objects, ns_client_t and ns_clientmgr_t.
25  *
26  * An ns_client_t object handles incoming DNS requests from clients
27  * on a given network interface.
28  *
29  * Each ns_client_t object can handle only one TCP connection or UDP
30  * request at a time.  Therefore, several ns_client_t objects are
31  * typically created to serve each network interface, e.g., one
32  * for handling TCP requests and a few (one per CPU) for handling
33  * UDP requests.
34  *
35  * Incoming requests are classified as queries, zone transfer
36  * requests, update requests, notify requests, etc, and handed off
37  * to the appropriate request handler.  When the request has been
38  * fully handled (which can be much later), the ns_client_t must be
39  * notified of this by calling one of the following functions
40  * exactly once in the context of its task:
41  * \code
42  *   ns_client_send()	 (sending a non-error response)
43  *   ns_client_sendraw() (sending a raw response)
44  *   ns_client_error()	 (sending an error response)
45  *   ns_client_drop() (sending no response, logging the reason)
46  *\endcode
47  * This will release any resources used by the request and
48  * and allow the ns_client_t to listen for the next request.
49  *
50  * A ns_clientmgr_t manages a number of ns_client_t objects.
51  * New ns_client_t objects are created by calling
52  * ns_clientmgr_createclients(). They are destroyed by
53  * destroying their manager.
54  */
55 
56 /***
57  *** Imports
58  ***/
59 
60 #include <inttypes.h>
61 #include <stdbool.h>
62 
63 #include <isc/atomic.h>
64 #include <isc/buffer.h>
65 #include <isc/magic.h>
66 #include <isc/netmgr.h>
67 #include <isc/quota.h>
68 #include <isc/stdtime.h>
69 
70 #include <dns/db.h>
71 #include <dns/ecs.h>
72 #include <dns/fixedname.h>
73 #include <dns/name.h>
74 #include <dns/rdataclass.h>
75 #include <dns/rdatatype.h>
76 #include <dns/types.h>
77 
78 #include <ns/query.h>
79 #include <ns/types.h>
80 
81 /***
82  *** Types
83  ***/
84 
85 #define NS_CLIENT_TCP_BUFFER_SIZE  65535
86 #define NS_CLIENT_SEND_BUFFER_SIZE 4096
87 
88 /*!
89  * Client object states.  Ordering is significant: higher-numbered
90  * states are generally "more active", meaning that the client can
91  * have more dynamically allocated data, outstanding events, etc.
92  * In the list below, any such properties listed for state N
93  * also apply to any state > N.
94  */
95 
96 typedef enum {
97 	NS_CLIENTSTATE_FREED = 0,
98 	/*%<
99 	 * The client object no longer exists.
100 	 */
101 
102 	NS_CLIENTSTATE_INACTIVE = 1,
103 	/*%<
104 	 * The client object exists and has a task and timer.
105 	 * Its "query" struct and sendbuf are initialized.
106 	 * It has a message and OPT, both in the reset state.
107 	 */
108 
109 	NS_CLIENTSTATE_READY = 2,
110 	/*%<
111 	 * The client object is either a TCP or a UDP one, and
112 	 * it is associated with a network interface.  It is on the
113 	 * client manager's list of active clients.
114 	 *
115 	 * If it is a TCP client object, it has a TCP listener socket
116 	 * and an outstanding TCP listen request.
117 	 *
118 	 * If it is a UDP client object, it has a UDP listener socket
119 	 * and an outstanding UDP receive request.
120 	 */
121 
122 	NS_CLIENTSTATE_WORKING = 3,
123 	/*%<
124 	 * The client object has received a request and is working
125 	 * on it.  It has a view, and it may have any of a non-reset OPT,
126 	 * recursion quota, and an outstanding write request.
127 	 */
128 
129 	NS_CLIENTSTATE_RECURSING = 4,
130 	/*%<
131 	 * The client object is recursing.  It will be on the
132 	 * 'recursing' list.
133 	 */
134 
135 	NS_CLIENTSTATE_MAX = 5
136 	/*%<
137 	 * Sentinel value used to indicate "no state".
138 	 */
139 } ns_clientstate_t;
140 
141 typedef ISC_LIST(ns_client_t) client_list_t;
142 
143 /*% nameserver client manager structure */
144 struct ns_clientmgr {
145 	/* Unlocked. */
146 	unsigned int magic;
147 
148 	isc_mem_t      *mctx;
149 	ns_server_t    *sctx;
150 	isc_taskmgr_t  *taskmgr;
151 	isc_timermgr_t *timermgr;
152 	isc_refcount_t	references;
153 	int		tid;
154 
155 	/* Attached by clients, needed for e.g. recursion */
156 	isc_task_t *task;
157 
158 	dns_aclenv_t *aclenv;
159 
160 	/* Lock covers the recursing list */
161 	isc_mutex_t   reclock;
162 	client_list_t recursing; /*%< Recursing clients */
163 
164 	uint8_t tcp_buffer[NS_CLIENT_TCP_BUFFER_SIZE];
165 };
166 
167 /*% nameserver client structure */
168 struct ns_client {
169 	unsigned int	 magic;
170 	isc_mem_t	*mctx;
171 	int		 tid;
172 	bool		 allocated; /* Do we need to free it? */
173 	ns_server_t	*sctx;
174 	ns_clientmgr_t	*manager;
175 	ns_clientstate_t state;
176 	int		 nupdates;
177 	bool		 nodetach;
178 	bool		 shuttingdown;
179 	unsigned int	 attributes;
180 	isc_task_t	*task;
181 	dns_view_t	*view;
182 	dns_dispatch_t	*dispatch;
183 	isc_nmhandle_t	*handle;	/* Permanent pointer to handle */
184 	isc_nmhandle_t	*sendhandle;	/* Waiting for send callback */
185 	isc_nmhandle_t	*reqhandle;	/* Waiting for request callback
186 					   (query, update, notify) */
187 	isc_nmhandle_t *fetchhandle;	/* Waiting for recursive fetch */
188 	isc_nmhandle_t *prefetchhandle; /* Waiting for prefetch / rpzfetch */
189 	isc_nmhandle_t *updatehandle;	/* Waiting for update callback */
190 	unsigned char  *tcpbuf;
191 	size_t		tcpbuf_size;
192 	dns_message_t  *message;
193 	dns_rdataset_t *opt;
194 	dns_ednsopt_t  *ede;
195 	uint16_t	udpsize;
196 	uint16_t	extflags;
197 	int16_t		ednsversion; /* -1 noedns */
198 	uint16_t	additionaldepth;
199 	void (*cleanup)(ns_client_t *);
200 	ns_query_t    query;
201 	isc_time_t    requesttime;
202 	isc_stdtime_t now;
203 	isc_time_t    tnow;
204 	dns_name_t    signername; /*%< [T]SIG key name */
205 	dns_name_t   *signer;	  /*%< NULL if not valid sig */
206 	bool	      mortal;	  /*%< Die after handling request */
207 	isc_quota_t  *recursionquota;
208 
209 	isc_sockaddr_t peeraddr;
210 	bool	       peeraddr_valid;
211 	isc_netaddr_t  destaddr;
212 	isc_sockaddr_t destsockaddr;
213 
214 	dns_ecs_t ecs; /*%< EDNS client subnet sent by client */
215 
216 	struct in6_pktinfo pktinfo;
217 	/*%
218 	 * Information about recent FORMERR response(s), for
219 	 * FORMERR loop avoidance.  This is separate for each
220 	 * client object rather than global only to avoid
221 	 * the need for locking.
222 	 */
223 	struct {
224 		isc_sockaddr_t	addr;
225 		isc_stdtime_t	time;
226 		dns_messageid_t id;
227 	} formerrcache;
228 
229 	/*% Callback function to send a response when unit testing */
230 	void (*sendcb)(isc_buffer_t *buf);
231 
232 	ISC_LINK(ns_client_t) rlink;
233 	unsigned char  cookie[8];
234 	uint32_t       expire;
235 	unsigned char *keytag;
236 	uint16_t       keytag_len;
237 
238 	/*%
239 	 * Used to override the DNS response code in ns_client_error().
240 	 * If set to -1, the rcode is determined from the result code,
241 	 * but if set to any other value, the least significant 12
242 	 * bits will be used as the rcode in the response message.
243 	 */
244 	int32_t rcode_override;
245 
246 	uint8_t sendbuf[NS_CLIENT_SEND_BUFFER_SIZE];
247 };
248 
249 #define NS_CLIENT_MAGIC	   ISC_MAGIC('N', 'S', 'C', 'c')
250 #define NS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, NS_CLIENT_MAGIC)
251 
252 #define NS_CLIENTATTR_TCP	 0x00001
253 #define NS_CLIENTATTR_RA	 0x00002 /*%< Client gets recursive service */
254 #define NS_CLIENTATTR_PKTINFO	 0x00004 /*%< pktinfo is valid */
255 #define NS_CLIENTATTR_MULTICAST	 0x00008 /*%< recv'd from multicast */
256 #define NS_CLIENTATTR_WANTDNSSEC 0x00010 /*%< include dnssec records */
257 #define NS_CLIENTATTR_WANTNSID	 0x00020 /*%< include nameserver ID */
258 /* Obsolete: NS_CLIENTATTR_FILTER_AAAA	0x00040 */
259 /* Obsolete: NS_CLIENTATTR_FILTER_AAAA_RC 0x00080 */
260 #define NS_CLIENTATTR_WANTAD	   0x00100 /*%< want AD in response if possible */
261 #define NS_CLIENTATTR_WANTCOOKIE   0x00200 /*%< return a COOKIE */
262 #define NS_CLIENTATTR_HAVECOOKIE   0x00400 /*%< has a valid COOKIE */
263 #define NS_CLIENTATTR_WANTEXPIRE   0x00800 /*%< return seconds to expire */
264 #define NS_CLIENTATTR_HAVEEXPIRE   0x01000 /*%< return seconds to expire */
265 #define NS_CLIENTATTR_WANTOPT	   0x02000 /*%< add opt to reply */
266 #define NS_CLIENTATTR_HAVEECS	   0x04000 /*%< received an ECS option */
267 #define NS_CLIENTATTR_WANTPAD	   0x08000 /*%< pad reply */
268 #define NS_CLIENTATTR_USEKEEPALIVE 0x10000 /*%< use TCP keepalive */
269 
270 #define NS_CLIENTATTR_NOSETFC 0x20000 /*%< don't set servfail cache */
271 
272 /*
273  * Flag to use with the SERVFAIL cache to indicate
274  * that a query had the CD bit set.
275  */
276 #define NS_FAILCACHE_CD 0x01
277 
278 #ifdef _LP64
279 extern atomic_uint_fast64_t ns_client_requests;
280 #else
281 extern atomic_uint_fast32_t ns_client_requests;
282 #endif
283 
284 /***
285  *** Functions
286  ***/
287 
288 /*
289  * Note!  These ns_client_ routines MUST be called ONLY from the client's
290  * task in order to ensure synchronization.
291  */
292 
293 void
294 ns_client_send(ns_client_t *client);
295 /*%<
296  * Finish processing the current client request and
297  * send client->message as a response.
298  * \brief
299  * Note!  These ns_client_ routines MUST be called ONLY from the client's
300  * task in order to ensure synchronization.
301  */
302 
303 void
304 ns_client_sendraw(ns_client_t *client, dns_message_t *msg);
305 /*%<
306  * Finish processing the current client request and
307  * send msg as a response using client->message->id for the id.
308  */
309 
310 void
311 ns_client_error(ns_client_t *client, isc_result_t result);
312 /*%<
313  * Finish processing the current client request and return
314  * an error response to the client.  The error response
315  * will have an RCODE determined by 'result'.
316  */
317 
318 void
319 ns_client_extendederror(ns_client_t *client, uint16_t code, const char *text);
320 /*%<
321  * Set extended error with INFO-CODE <code> and EXTRA-TEXT <text>.
322  */
323 
324 void
325 ns_client_drop(ns_client_t *client, isc_result_t result);
326 /*%<
327  * Log the reason the current client request has failed; no response
328  * will be sent.
329  */
330 
331 bool
332 ns_client_shuttingdown(ns_client_t *client);
333 /*%<
334  * Return true iff the client is currently shutting down.
335  */
336 
337 isc_result_t
338 ns_client_replace(ns_client_t *client);
339 /*%<
340  * Try to replace the current client with a new one, so that the
341  * current one can go off and do some lengthy work without
342  * leaving the dispatch/socket without service.
343  */
344 
345 void
346 ns_client_settimeout(ns_client_t *client, unsigned int seconds);
347 /*%<
348  * Set a timer in the client to go off in the specified amount of time.
349  */
350 
351 isc_result_t
352 ns_clientmgr_create(ns_server_t *sctx, isc_taskmgr_t *taskmgr,
353 		    isc_timermgr_t *timermgr, dns_aclenv_t *aclenv, int tid,
354 		    ns_clientmgr_t **managerp);
355 /*%<
356  * Create a client manager.
357  */
358 
359 void
360 ns_clientmgr_shutdown(ns_clientmgr_t *manager);
361 /*%<
362  * Shutdown a client manager and all ns_client_t objects
363  * managed by it
364  */
365 
366 void
367 ns_clientmgr_detach(ns_clientmgr_t **managerp);
368 /*%<
369  * Detach from a client manager.
370  */
371 
372 isc_sockaddr_t *
373 ns_client_getsockaddr(ns_client_t *client);
374 /*%<
375  * Get the socket address of the client whose request is
376  * currently being processed.
377  */
378 
379 isc_sockaddr_t *
380 ns_client_getdestaddr(ns_client_t *client);
381 /*%<
382  * Get the destination address (server) for the request that is
383  * currently being processed.
384  */
385 
386 isc_result_t
387 ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
388 			 dns_acl_t *acl, bool default_allow);
389 
390 /*%<
391  * Convenience function for client request ACL checking.
392  *
393  * Check the current client request against 'acl'.  If 'acl'
394  * is NULL, allow the request iff 'default_allow' is true.
395  * If netaddr is NULL, check the ACL against client->peeraddr;
396  * otherwise check it against netaddr.
397  *
398  * Notes:
399  *\li	This is appropriate for checking allow-update,
400  * 	allow-query, allow-transfer, etc.  It is not appropriate
401  * 	for checking the blackhole list because we treat positive
402  * 	matches as "allow" and negative matches as "deny"; in
403  *	the case of the blackhole list this would be backwards.
404  *
405  * Requires:
406  *\li	'client' points to a valid client.
407  *\li	'netaddr' points to a valid address, or is NULL.
408  *\li	'acl' points to a valid ACL, or is NULL.
409  *
410  * Returns:
411  *\li	ISC_R_SUCCESS	if the request should be allowed
412  * \li	DNS_R_REFUSED	if the request should be denied
413  *\li	No other return values are possible.
414  */
415 
416 isc_result_t
417 ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
418 		   const char *opname, dns_acl_t *acl, bool default_allow,
419 		   int log_level);
420 /*%<
421  * Like ns_client_checkaclsilent, except the outcome of the check is
422  * logged at log level 'log_level' if denied, and at debug 3 if approved.
423  * Log messages will refer to the request as an 'opname' request.
424  *
425  * Requires:
426  *\li	'client' points to a valid client.
427  *\li	'sockaddr' points to a valid address, or is NULL.
428  *\li	'acl' points to a valid ACL, or is NULL.
429  *\li	'opname' points to a null-terminated string.
430  */
431 
432 void
433 ns_client_log(ns_client_t *client, isc_logcategory_t *category,
434 	      isc_logmodule_t *module, int level, const char *fmt, ...)
435 	ISC_FORMAT_PRINTF(5, 6);
436 
437 void
438 ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
439 	       isc_logmodule_t *module, int level, const char *fmt, va_list ap)
440 	ISC_FORMAT_PRINTF(5, 0);
441 
442 void
443 ns_client_aclmsg(const char *msg, const dns_name_t *name, dns_rdatatype_t type,
444 		 dns_rdataclass_t rdclass, char *buf, size_t len);
445 
446 #define NS_CLIENT_ACLMSGSIZE(x)                           \
447 	(DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE + \
448 	 DNS_RDATACLASS_FORMATSIZE + sizeof(x) + sizeof("'/'"))
449 
450 void
451 ns_client_recursing(ns_client_t *client);
452 /*%<
453  * Add client to end of th recursing list.
454  */
455 
456 void
457 ns_client_killoldestquery(ns_client_t *client);
458 /*%<
459  * Kill the oldest recursive query (recursing list head).
460  */
461 
462 void
463 ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager);
464 /*%<
465  * Dump the outstanding recursive queries to 'f'.
466  */
467 
468 void
469 ns_client_qnamereplace(ns_client_t *client, dns_name_t *name);
470 /*%<
471  * Replace the qname.
472  */
473 
474 isc_result_t
475 ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp);
476 
477 isc_result_t
478 ns_client_addopt(ns_client_t *client, dns_message_t *message,
479 		 dns_rdataset_t **opt);
480 
481 /*%<
482  * Get a client object from the inactive queue, or create one, as needed.
483  * (Not intended for use outside this module and associated tests.)
484  */
485 
486 void
487 ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
488 		   isc_region_t *region, void *arg);
489 
490 /*%<
491  * Handle client requests.
492  * (Not intended for use outside this module and associated tests.)
493  */
494 
495 isc_result_t
496 ns__client_tcpconn(isc_nmhandle_t *handle, isc_result_t result, void *arg);
497 
498 /*%<
499  * Called every time a TCP connection is establish.  This is used for
500  * updating TCP statistics.
501  */
502 
503 dns_rdataset_t *
504 ns_client_newrdataset(ns_client_t *client);
505 
506 void
507 ns_client_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp);
508 /*%<
509  * Get and release temporary rdatasets in the client message;
510  * used in query.c and in plugins.
511  */
512 
513 isc_result_t
514 ns_client_newnamebuf(ns_client_t *client);
515 /*%<
516  * Allocate a name buffer for the client message.
517  */
518 
519 dns_name_t *
520 ns_client_newname(ns_client_t *client, isc_buffer_t *dbuf, isc_buffer_t *nbuf);
521 /*%<
522  * Get a temporary name for the client message.
523  */
524 
525 isc_buffer_t *
526 ns_client_getnamebuf(ns_client_t *client);
527 /*%<
528  * Get a name buffer from the pool, or allocate a new one if needed.
529  */
530 
531 void
532 ns_client_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf);
533 /*%<
534  * Adjust buffer 'dbuf' to reflect that 'name' is using space in it,
535  * and set client attributes appropriately.
536  */
537 
538 void
539 ns_client_releasename(ns_client_t *client, dns_name_t **namep);
540 /*%<
541  * Release 'name' back to the pool of temporary names for the client
542  * message. If it is using a name buffer, relinquish its exclusive
543  * rights on the buffer.
544  */
545 
546 isc_result_t
547 ns_client_newdbversion(ns_client_t *client, unsigned int n);
548 /*%<
549  * Allocate 'n' new database versions for use by client queries.
550  */
551 
552 ns_dbversion_t *
553 ns_client_getdbversion(ns_client_t *client);
554 /*%<
555  * Get a free database version for use by a client query, allocating
556  * a new one if necessary.
557  */
558 
559 ns_dbversion_t *
560 ns_client_findversion(ns_client_t *client, dns_db_t *db);
561 /*%<
562  * Find the correct database version to use with a client query.
563  * If we have already done a query related to the database 'db',
564  * make sure subsequent queries are from the same version;
565  * otherwise, take a database version from the list of dbversions
566  * allocated by ns_client_newdbversion().
567  */
568 
569 isc_result_t
570 ns__client_setup(ns_client_t *client, ns_clientmgr_t *manager, bool new);
571 /*%<
572  * Perform initial setup of an allocated client.
573  */
574 
575 void
576 ns__client_reset_cb(void *client0);
577 /*%<
578  * Reset the client object so that it can be reused.
579  */
580 
581 void
582 ns__client_put_cb(void *client0);
583 /*%<
584  * Free all resources allocated to this client object, so that
585  * it can be freed.
586  */
587