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