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