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