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