1 /* $NetBSD: netmgr.h,v 1.12 2026/04/08 00:16:16 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 #include <sys/socket.h> 19 #include <sys/types.h> 20 #include <unistd.h> 21 22 #include <isc/mem.h> 23 #include <isc/refcount.h> 24 #include <isc/region.h> 25 #include <isc/result.h> 26 #include <isc/sockaddr.h> 27 #include <isc/tls.h> 28 #include <isc/types.h> 29 30 /* Add -DISC_NETMGR_TRACE=1 to CFLAGS for detailed reference tracing */ 31 32 #if defined(SO_REUSEPORT_LB) || (defined(SO_REUSEPORT) && defined(__linux__)) 33 #define HAVE_SO_REUSEPORT_LB 1 34 #endif 35 36 /* 37 * Convenience macros to specify on how many threads should socket listen 38 */ 39 #define ISC_NM_LISTEN_ALL 0 40 #define ISC_NM_LISTEN_ONE 1 41 42 /* 43 * Replacement for isc_sockettype_t provided by socket.h. 44 */ 45 typedef enum { 46 isc_socktype_tcp = 1, 47 isc_socktype_udp = 2, 48 isc_socktype_unix = 3, 49 isc_socktype_raw = 4 50 } isc_socktype_t; 51 52 typedef void (*isc_nm_recv_cb_t)(isc_nmhandle_t *handle, isc_result_t eresult, 53 isc_region_t *region, void *cbarg); 54 /*%< 55 * Callback function to be used when receiving a packet. 56 * 57 * 'handle' the handle that can be used to send back the answer. 58 * 'eresult' the result of the event. 59 * 'region' contains the received data, if any. It will be freed 60 * after return by caller. 61 * 'cbarg' the callback argument passed to isc_nm_listenudp(), 62 * isc_nm_listenstreamdns(), or isc_nm_read(). 63 */ 64 typedef isc_result_t (*isc_nm_accept_cb_t)(isc_nmhandle_t *handle, 65 isc_result_t result, void *cbarg); 66 /*%< 67 * Callback function to be used when accepting a connection. (This differs 68 * from isc_nm_cb_t below in that it returns a result code.) 69 * 70 * 'handle' the handle that can be used to send back the answer. 71 * 'eresult' the result of the event. 72 * 'cbarg' the callback argument passed to isc_nm_listentcp() or 73 * isc_nm_listenstreamdns(). 74 */ 75 76 typedef void (*isc_nm_cb_t)(isc_nmhandle_t *handle, isc_result_t result, 77 void *cbarg); 78 /*%< 79 * Callback function for other network completion events (send, connect). 80 * 81 * 'handle' the handle on which the event took place. 82 * 'eresult' the result of the event. 83 * 'cbarg' the callback argument passed to isc_nm_send(), 84 * isc_nm_tcp_connect(), or isc_nm_listentcp() 85 */ 86 87 typedef void (*isc_nm_opaquecb_t)(void *arg); 88 /*%< 89 * Opaque callback function, used for isc_nmhandle 'reset' and 'free' 90 * callbacks. 91 */ 92 93 typedef struct isc_nm_proxyheader_info { 94 bool complete; 95 union { 96 isc_region_t complete_header; /* complete header data */ 97 struct { 98 isc_sockaddr_t src_addr; 99 isc_sockaddr_t dst_addr; 100 isc_region_t tlv_data; 101 } proxy_info; /* information to put into the new header */ 102 }; 103 } isc_nm_proxyheader_info_t; 104 /*%< 105 * Information to put into the PROXYv2 header when establishing a connection. 106 */ 107 108 typedef enum isc_nm_proxy_type { 109 ISC_NM_PROXY_NONE = 0, 110 ISC_NM_PROXY_PLAIN = 1, 111 ISC_NM_PROXY_ENCRYPTED = 2 112 } isc_nm_proxy_type_t; 113 /*%< 114 * PROXYv2 support type: 115 * 116 * - ISC_NM_PROXY_NONE - no PROXY headers are expected; 117 * - ISC_NM_PROXY_PLAIN - PROXY headers are sent ahead of any encryption, right 118 * after TCP connection establishment; 119 * - ISC_NM_PROXY_ENCRYPTED - PROXY headers are sent after TLS handshakes. 120 */ 121 122 void 123 isc_netmgr_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr, isc_nm_t **netgmrp); 124 /*%< 125 * Creates a new network manager and starts it running when loopmgr is started. 126 */ 127 128 void 129 isc_netmgr_destroy(isc_nm_t **netmgrp); 130 /*%< 131 * Similar to isc_nm_detach(), but requires all other references to be gone. 132 */ 133 134 void 135 isc_nm_attach(isc_nm_t *mgr, isc_nm_t **dst); 136 void 137 isc_nm_detach(isc_nm_t **mgr0); 138 /*%< 139 * Attach/detach a network manager. When all references have been 140 * released, the network manager is shut down, freeing all resources. 141 */ 142 143 void 144 isc_nmsocket_close(isc_nmsocket_t **sockp); 145 /*%< 146 * isc_nmsocket_close() detaches a listening socket that was 147 * created by isc_nm_listenudp(), isc_nm_listentcp(), or 148 * isc_nm_listentcpdns(). Once there are no remaining child 149 * sockets with active handles, the socket will be closed. 150 */ 151 152 void 153 isc_nmsocket_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx); 154 /*%< 155 * Asynchronously replace the TLS context within the listener socket object. 156 * The function is intended to be used during reconfiguration. 157 * 158 * Requires: 159 * \li 'listener' is a pointer to a valid network manager listener socket 160 object with TLS support; 161 * \li 'tlsctx' is a valid pointer to a TLS context object. 162 */ 163 164 void 165 isc_nmsocket_set_max_streams(isc_nmsocket_t *listener, 166 const uint32_t max_streams); 167 /*%< 168 * Set the maximum allowed number of concurrent streams for accepted 169 * client connections. The implementation might be asynchronous 170 * depending on the listener socket type. 171 * 172 * The call is a no-op for any listener socket type that does not 173 * support concept of multiple sessions per a client 174 * connection. Currently, it works only for HTTP/2 listeners. 175 * 176 * Setting 'max_streams' to '0' instructs the listener that there is 177 * no limit for concurrent streams. 178 * 179 * Requires: 180 * \li 'listener' is a pointer to a valid network manager listener socket. 181 */ 182 183 #if ISC_NETMGR_TRACE 184 #define isc_nmhandle_ref(ptr) \ 185 isc_nmhandle__ref(ptr, __func__, __FILE__, __LINE__) 186 #define isc_nmhandle_unref(ptr) \ 187 isc_nmhandle__unref(ptr, __func__, __FILE__, __LINE__) 188 #define isc_nmhandle_attach(ptr, ptrp) \ 189 isc_nmhandle__attach(ptr, ptrp, __func__, __FILE__, __LINE__) 190 #define isc_nmhandle_detach(ptrp) \ 191 isc_nmhandle__detach(ptrp, __func__, __FILE__, __LINE__) 192 ISC_REFCOUNT_TRACE_DECL(isc_nmhandle); 193 #else 194 ISC_REFCOUNT_DECL(isc_nmhandle); 195 #endif 196 /*%< 197 * Increment/decrement the reference counter in a netmgr handle. 198 * 199 * When the detach function is called on a thread other than the one that 200 * created the handle, it is scheduled to asynchronously by the handle's 201 * event loop. When references go to zero, the associated socket will be 202 * closed and deleted. 203 */ 204 205 int 206 isc_nmhandle_getfd(isc_nmhandle_t *handle); 207 208 void * 209 isc_nmhandle_getdata(isc_nmhandle_t *handle); 210 211 bool 212 isc_nmhandle_is_stream(isc_nmhandle_t *handle); 213 214 void 215 isc_nmhandle_setdata(isc_nmhandle_t *handle, void *arg, 216 isc_nm_opaquecb_t doreset, isc_nm_opaquecb_t dofree); 217 /*%< 218 * isc_nmhandle_t has a void* opaque field (for example, ns_client_t). 219 * We reuse handle and `opaque` can also be reused between calls. 220 * This function sets this field and two callbacks: 221 * - doreset resets the `opaque` to initial state 222 * - dofree frees everything associated with `opaque` 223 */ 224 225 void 226 isc_nmhandle_settimeout(isc_nmhandle_t *handle, uint32_t timeout); 227 void 228 isc_nmhandle_cleartimeout(isc_nmhandle_t *handle); 229 /*%< 230 * Set/clear the read/recv timeout for the socket connected to 'handle' 231 * to 'timeout' (in milliseconds), and reset the timer. 232 * 233 * When this is called on a 'wrapper' socket handle (for example, 234 * a TCPDNS socket wrapping a TCP connection), the timer is set for 235 * both socket layers. 236 */ 237 bool 238 isc_nmhandle_timer_running(isc_nmhandle_t *handle); 239 /*%< 240 * Return true if the timer for the socket connected to 'handle' 241 * is running. 242 */ 243 244 void 245 isc_nmhandle_keepalive(isc_nmhandle_t *handle, bool value); 246 /*%< 247 * Enable/disable keepalive on this connection by setting it to 'value'. 248 * 249 * When keepalive is active, we switch to using the keepalive timeout 250 * to determine when to close a connection, rather than the idle timeout. 251 * 252 * This applies only to TCP-based DNS connections (i.e., TCPDNS or 253 * TLSDNS). On other types of connection it has no effect. 254 */ 255 256 isc_sockaddr_t 257 isc_nmhandle_peeraddr(isc_nmhandle_t *handle); 258 /*%< 259 * Return the peer address for the given handle. 260 */ 261 isc_sockaddr_t 262 isc_nmhandle_localaddr(isc_nmhandle_t *handle); 263 /*%< 264 * Return the local address for the given handle. 265 */ 266 267 isc_sockaddr_t 268 isc_nmhandle_real_peeraddr(isc_nmhandle_t *handle); 269 /*%< 270 * Return the real (as seen by the OS) peer address for the given 271 * handle even when PROXY protocol is used. 272 * 273 * NOTE: This function is intended mostly for a) implementing PROXYv2 274 * access control facilities and b) logging. Using it for anything 275 * else WILL break PROXYv2 support. Please consider using 276 * 'isc_nmhandle_peeraddr()' instead. 277 */ 278 isc_sockaddr_t 279 isc_nmhandle_real_localaddr(isc_nmhandle_t *handle); 280 /*%< 281 * Return the real (as seen by the OS) local address for the given 282 * handle even when PROXY protocol is used. 283 * 284 * NOTE: This function is intended mostly for a) implementing PROXYv2 285 * access control facilities and b) logging. Using it for anything 286 * else WILL break PROXYv2 support. Please consider using 287 * 'isc_nmhandle_localaddr()' instead. 288 */ 289 290 isc_nm_t * 291 isc_nmhandle_netmgr(isc_nmhandle_t *handle); 292 /*%< 293 * Return a pointer to the netmgr object for the given handle. 294 */ 295 296 isc_result_t 297 isc_nm_listenudp(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface, 298 isc_nm_recv_cb_t cb, void *cbarg, isc_nmsocket_t **sockp); 299 /*%< 300 * Start listening for UDP packets on interface 'iface' using net manager 301 * 'mgr'. 302 * 303 * On success, 'sockp' will be updated to contain a new listening UDP socket. 304 * 305 * When a packet is received on the socket, 'cb' will be called with 'cbarg' 306 * as its argument. 307 */ 308 309 void 310 isc_nm_udpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, 311 isc_nm_cb_t cb, void *cbarg, unsigned int timeout); 312 /*%< 313 * Open a UDP socket, bind to 'local' and connect to 'peer', and 314 * immediately call 'cb' with a handle so that the caller can begin 315 * sending packets over UDP. 316 * 317 * 'timeout' specifies the timeout interval in milliseconds. 318 * 319 * The connected socket can only be accessed via the handle passed to 320 * 'cb'. 321 */ 322 323 isc_result_t 324 isc_nm_routeconnect(isc_nm_t *mgr, isc_nm_cb_t cb, void *cbarg); 325 /*%< 326 * Open a route/netlink socket and call 'cb', so the caller can be 327 * begin listening for interface changes. This behaves similarly to 328 * isc_nm_udpconnect(). 329 * 330 * Returns ISC_R_NOTIMPLEMENTED on systems where route/netlink sockets 331 * are not supported. 332 */ 333 334 isc_result_t 335 isc_nm_listenproxyudp(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface, 336 isc_nm_recv_cb_t cb, void *cbarg, isc_nmsocket_t **sockp); 337 /*%< 338 * The same as `isc_nm_listenudp()`, but PROXYv2 headers are 339 * expected at the beginning of the received datagrams. 340 */ 341 342 void 343 isc_nm_proxyudpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, 344 isc_sockaddr_t *peer, isc_nm_cb_t cb, void *cbarg, 345 unsigned int timeout, 346 isc_nm_proxyheader_info_t *proxy_info); 347 /*%< 348 * The same as `isc_nm_udpconnect()`, but PROXYv2 headers are added 349 * at the beginning of each sent datagram. The PROXYv2 headers are 350 * created using the data from the `proxy_info` object. If the 351 * object is omitted, then LOCAL PROXYv2 headers are used. 352 */ 353 354 void 355 isc_nm_stoplistening(isc_nmsocket_t *sock); 356 /*%< 357 * Stop listening on socket 'sock'. 358 */ 359 360 void 361 isc_nm_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg); 362 /* 363 * Begin (or continue) reading on the socket associated with 'handle', and 364 * update its recv callback to 'cb', which will be called as soon as there 365 * is data to process. 366 */ 367 368 void 369 isc_nm_read_stop(isc_nmhandle_t *handle); 370 /*%< 371 * Stop reading on this handle's socket. 372 * 373 * Requires: 374 * \li 'handle' is a valid netmgr handle. 375 */ 376 377 void 378 isc_nm_cancelread(isc_nmhandle_t *handle); 379 /*%< 380 * Cancel reading on a connected socket. Calls the read/recv callback on 381 * active handles with a result code of ISC_R_CANCELED. 382 * 383 * Requires: 384 * \li 'handle' is a valid netmgr handle 385 * \li ...for which a read/recv callback has been defined. 386 */ 387 388 void 389 isc_nmhandle_close(isc_nmhandle_t *handle); 390 /*%< 391 * Close the active handle - no further read callbacks will happen. 392 * 393 * Requires: 394 * 'li 'handle' is a valid netmgr handle 395 */ 396 397 void 398 isc_nm_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb, 399 void *cbarg); 400 /*%< 401 * Send the data in 'region' via 'handle'. Afterward, the callback 'cb' is 402 * called with the argument 'cbarg'. 403 * 404 * 'region' is not copied; it has to be allocated beforehand and freed 405 * in 'cb'. 406 */ 407 408 isc_result_t 409 isc_nm_listentcp(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface, 410 isc_nm_accept_cb_t accept_cb, void *accept_cbarg, int backlog, 411 isc_quota_t *quota, isc_nmsocket_t **sockp); 412 /*%< 413 * Start listening for raw messages over the TCP interface 'iface', using 414 * net manager 'mgr'. 415 * 416 * On success, 'sockp' will be updated to contain a new listening TCP 417 * socket. 418 * 419 * When connection is accepted on the socket, 'accept_cb' will be called with 420 * 'accept_cbarg' as its argument. The callback is expected to start a read. 421 * 422 * If 'quota' is not NULL, then the socket is attached to the specified 423 * quota. This allows us to enforce TCP client quota limits. 424 * 425 */ 426 427 void 428 isc_nm_tcpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, 429 isc_nm_cb_t connect_cb, void *connect_cbarg, 430 unsigned int timeout); 431 /*%< 432 * Create a socket using netmgr 'mgr', bind it to the address 'local', 433 * and connect it to the address 'peer'. 434 * 435 * When the connection is complete or has timed out, call 'cb' with 436 * argument 'cbarg'. 437 * 438 * 'timeout' specifies the timeout interval in milliseconds. 439 * 440 * The connected socket can only be accessed via the handle passed to 441 * 'cb'. 442 */ 443 444 isc_result_t 445 isc_nm_listenstreamdns(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface, 446 isc_nm_recv_cb_t recv_cb, void *recv_cbarg, 447 isc_nm_accept_cb_t accept_cb, void *accept_cbarg, 448 int backlog, isc_quota_t *quota, isc_tlsctx_t *tlsctx, 449 isc_nm_proxy_type_t proxy_type, isc_nmsocket_t **sockp); 450 /*%< 451 * Start listening for DNS messages over the TCP interface 'iface', using 452 * net manager 'mgr'. 453 * 454 * On success, 'sockp' will be updated to contain a new listening TCPDNS 455 * socket. This is a wrapper around a raw TCP socket, which sends and 456 * receives DNS messages via that socket. It handles message buffering 457 * and pipelining, and automatically prepends messages with a two-byte 458 * length field. 459 * 460 * When a complete DNS message is received on the socket, 'cb' will be 461 * called with 'cbarg' as its argument. 462 * 463 * When a new connection is accepted, 'accept_cb' will be called with 464 * 'accept_cbarg' as its argument. 465 * 466 * Passing a non-NULL value as 'tlsctx' instructs the underlying code 467 * to create a DNS over TLS listener. 468 * 469 * Passing 'proxy == true' instruct the code that a PROXY header is 470 * sent before any data after the connection is accepted. 471 * 472 * 'quota' is passed to isc_nm_listentcp() when opening the raw TCP socket. 473 */ 474 475 isc_result_t 476 isc_nm_listenproxystream(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface, 477 isc_nm_accept_cb_t accept_cb, void *accept_cbarg, 478 int backlog, isc_quota_t *quota, isc_tlsctx_t *tlsctx, 479 isc_nmsocket_t **sockp); 480 /*%< 481 * Start listening for data preceded by a PROXYv2 header over the 482 * TCP or TLS on interface 'iface', using net manager 'mgr'. 483 * 484 * On success, 'sockp' will be updated to contain a new listening TCP 485 * socket. 486 * 487 * When connection is accepted on the socket, 'accept_cb' will be called with 488 * 'accept_cbarg' as its argument. The callback is expected to start a read. 489 * 490 * If 'quota' is not NULL, then the socket is attached to the specified 491 * quota. This allows us to enforce TCP client quota limits. 492 * 493 * If 'tlsctx' is not NULL, then listen for TLS connections. In that 494 * case PROXYv2 headers are expected to be sent encrypted right after 495 * the TLS handshake. 496 */ 497 498 void 499 isc_nm_proxystreamconnect(isc_nm_t *mgr, isc_sockaddr_t *local, 500 isc_sockaddr_t *peer, isc_nm_cb_t cb, void *cbarg, 501 unsigned int timeout, isc_tlsctx_t *tlsctx, 502 const char *sni_hostname, 503 isc_tlsctx_client_session_cache_t *client_sess_cache, 504 isc_nm_proxyheader_info_t *proxy_info); 505 /*%< 506 * Create a TCP socket using netmgr 'mgr', bind it to the address 507 * 'local', and connect it to the address 'peer'. Right after the 508 * connection has been established, send PROXYv2 header using the 509 * information provided via the 'proxy_info' to the remote peer. Then 510 * the connection is considered established. 511 * 512 * If 'proxy_info' is omitted, then a LOCAL PROXYv2 header is sent. 513 * 514 * When the connection is established or has timed out, call 'cb' with 515 * argument 'cbarg'. 516 * 517 * 'timeout' specifies the timeout interval in milliseconds. 518 * 519 * The connected socket can only be accessed via the handle passed to 520 * 'cb'. 521 */ 522 523 void 524 isc_nm_proxyheader_info_init(isc_nm_proxyheader_info_t *restrict info, 525 isc_sockaddr_t *restrict src_addr, 526 isc_sockaddr_t *restrict dst_addr, 527 isc_region_t *restrict tlv_data); 528 /*%< 529 * Initialize a 'isc_nm_proxyheader_info_t' object with user 530 * provided addresses and a TLVs blob, that can be omitted (the rest 531 * of the data is REQUIRE()d). 532 */ 533 534 void 535 isc_nm_proxyheader_info_init_complete(isc_nm_proxyheader_info_t *restrict info, 536 isc_region_t *restrict header_data); 537 /*%< 538 * Initialize a 'isc_nm_proxyheader_info_t' with user provided data 539 * blob (e.g. a pre-rendered PROXYv2 header for forwarding or 540 * testing). 541 */ 542 543 void 544 isc_nm_settimeouts(isc_nm_t *mgr, uint32_t init, uint32_t idle, 545 uint32_t keepalive, uint32_t advertised); 546 /*%< 547 * Sets the initial, idle, and keepalive timeout values (in milliseconds) to use 548 * for TCP connections, and the timeout value to advertise in responses using 549 * the EDNS TCP Keepalive option (which should ordinarily be the same 550 * as 'keepalive'), in milliseconds. 551 * 552 * Requires: 553 * \li 'mgr' is a valid netmgr. 554 */ 555 556 void 557 isc_nm_setnetbuffers(isc_nm_t *mgr, int32_t recv_tcp, int32_t send_tcp, 558 int32_t recv_udp, int32_t send_udp); 559 /*%< 560 * If not 0, sets the SO_RCVBUF and SO_SNDBUF socket options for TCP and UDP 561 * respectively. 562 * 563 * Requires: 564 * \li 'mgr' is a valid netmgr. 565 */ 566 567 bool 568 isc_nm_getloadbalancesockets(isc_nm_t *mgr); 569 void 570 isc_nm_setloadbalancesockets(isc_nm_t *mgr, bool enabled); 571 /*%< 572 * Get and set value of load balancing of the sockets. 573 * 574 * Requires: 575 * \li 'mgr' is a valid netmgr. 576 */ 577 578 void 579 isc_nm_gettimeouts(isc_nm_t *mgr, uint32_t *initial, uint32_t *idle, 580 uint32_t *keepalive, uint32_t *advertised); 581 /*%< 582 * Gets the initial, idle, keepalive, or advertised timeout values, 583 * in milliseconds. 584 * 585 * Any integer pointer parameter not set to NULL will be updated to 586 * contain the corresponding timeout value. 587 * 588 * Requires: 589 * \li 'mgr' is a valid netmgr. 590 */ 591 592 void 593 isc_nm_maxudp(isc_nm_t *mgr, uint32_t maxudp); 594 /*%< 595 * Simulate a broken firewall that blocks UDP messages larger than a given 596 * size. 597 */ 598 599 void 600 isc_nm_setstats(isc_nm_t *mgr, isc_stats_t *stats); 601 /*%< 602 * Set a socket statistics counter set 'stats' for 'mgr'. 603 * 604 * Requires: 605 *\li 'mgr' is valid and doesn't have stats already set. 606 * 607 *\li stats is a valid set of statistics counters supporting the 608 * full range of socket-related stats counter numbers. 609 */ 610 611 isc_result_t 612 isc_nm_checkaddr(const isc_sockaddr_t *addr, isc_socktype_t type); 613 /*%< 614 * Check whether the specified address is available on the local system 615 * by opening a socket and immediately closing it. 616 * 617 * Requires: 618 *\li 'addr' is not NULL. 619 */ 620 621 void 622 isc_nm_streamdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, 623 isc_sockaddr_t *peer, isc_nm_cb_t cb, void *cbarg, 624 unsigned int timeout, isc_tlsctx_t *tlsctx, 625 const char *sni_hostname, 626 isc_tlsctx_client_session_cache_t *client_sess_cache, 627 isc_nm_proxy_type_t proxy_type, 628 isc_nm_proxyheader_info_t *proxy_info); 629 /*%< 630 * Establish a DNS client connection via a TCP or TLS connection, bound to 631 * the address 'local' and connected to the address 'peer'. 632 * 633 * When the connection is complete or has timed out, call 'cb' with 634 * argument 'cbarg'. 635 * 636 * 'timeout' specifies the timeout interval in milliseconds. 637 * 638 * The connected socket can only be accessed via the handle passed to 639 * 'cb'. 640 */ 641 642 /*%< 643 * Returns 'true' iff 'handle' is associated with a socket of type 644 * 'isc_nm_tlsdnssocket'. 645 */ 646 647 bool 648 isc_nm_is_http_handle(isc_nmhandle_t *handle); 649 /*%< 650 * Returns 'true' iff 'handle' is associated with a socket of type 651 * 'isc_nm_httpsocket'. 652 */ 653 654 bool 655 isc_nm_is_proxy_unspec(isc_nmhandle_t *handle); 656 /*%< 657 * Returns 'true' iff 'handle' is associated with a peer who send 658 * a PROXYv2 header with unsupported address type. 659 */ 660 661 bool 662 isc_nm_is_proxy_handle(isc_nmhandle_t *handle); 663 /*%< Returns 'true' iff 'handle' is associated is with a PROXYv2 664 * connection. 665 */ 666 667 isc_result_t 668 isc_nm_listentls(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface, 669 isc_nm_accept_cb_t accept_cb, void *accept_cbarg, int backlog, 670 isc_quota_t *quota, isc_tlsctx_t *sslctx, bool proxy, 671 isc_nmsocket_t **sockp); 672 673 void 674 isc_nm_tlsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, 675 isc_nm_cb_t connect_cb, void *connect_cbarg, 676 isc_tlsctx_t *ctx, const char *sni_hostname, 677 isc_tlsctx_client_session_cache_t *client_sess_cache, 678 unsigned int timeout, bool proxy, 679 isc_nm_proxyheader_info_t *proxy_info); 680 681 #if HAVE_LIBNGHTTP2 682 683 #define ISC_NM_HTTP_DEFAULT_PATH "/dns-query" 684 685 void 686 isc_nm_httpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, 687 const char *uri, bool POST, isc_nm_cb_t cb, void *cbarg, 688 isc_tlsctx_t *ctx, const char *sni_hostname, 689 isc_tlsctx_client_session_cache_t *client_sess_cache, 690 unsigned int timeout, isc_nm_proxy_type_t proxy_type, 691 isc_nm_proxyheader_info_t *proxy_info); 692 693 isc_result_t 694 isc_nm_listenhttp(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface, 695 int backlog, isc_quota_t *quota, isc_tlsctx_t *ctx, 696 isc_nm_http_endpoints_t *eps, uint32_t max_concurrent_streams, 697 isc_nm_proxy_type_t proxy_type, isc_nmsocket_t **sockp); 698 699 isc_nm_http_endpoints_t * 700 isc_nm_http_endpoints_new(isc_mem_t *mctx); 701 /*%< 702 * Create a new, empty HTTP endpoints set object. 703 * 704 * Requires: 705 * \li 'mctx' a valid memory context object. 706 */ 707 708 isc_result_t 709 isc_nm_http_endpoints_add(isc_nm_http_endpoints_t *restrict eps, 710 const char *uri, const isc_nm_recv_cb_t cb, 711 void *cbarg); 712 /*%< Adds a new endpoint to the given HTTP endpoints set object. 713 * 714 * NOTE: adding an endpoint is allowed only if the endpoint object has 715 * not been passed to isc_nm_listenhttp() yet. 716 * 717 * Requires: 718 * \li 'eps' is a valid pointer to a valid isc_nm_http_endpoints_t 719 * object; 720 * \li 'uri' is a valid pointer to a string of length > 0; 721 * \li 'cb' is a valid pointer to a read callback function. 722 */ 723 724 void 725 isc_nm_http_endpoints_attach(isc_nm_http_endpoints_t *source, 726 isc_nm_http_endpoints_t **targetp); 727 /*%< 728 * Attaches to an HTTP endpoints set object. 729 * 730 * Requires: 731 * \li 'source' is a non-NULL pointer to a valid 732 * isc_nm_http_endpoints_t object; 733 * \li 'target' is a pointer to a pointer, containing NULL. 734 */ 735 736 void 737 isc_nm_http_endpoints_detach(isc_nm_http_endpoints_t **restrict epsp); 738 /*%< 739 * Detaches from an HTTP endpoints set object. When reference count 740 * reaches 0, the object get deleted. 741 * 742 * Requires: 743 * \li 'epsp' is a pointer to a pointer to a valid 744 * isc_nm_http_endpoints_t object. 745 */ 746 747 bool 748 isc_nm_http_path_isvalid(const char *path); 749 /*%< 750 * Returns 'true' if 'path' matches the format requirements for 751 * the path component of a URI as defined in RFC 3986 section 3.3. 752 */ 753 754 void 755 isc_nm_http_makeuri(const bool https, const isc_sockaddr_t *sa, 756 const char *hostname, const uint16_t http_port, 757 const char *abs_path, char *outbuf, 758 const size_t outbuf_len); 759 /*%< 760 * Makes a URI connection string out of na isc_sockaddr_t object 'sa' 761 * or the specified 'hostname' and 'http_port'. 762 * 763 * Requires: 764 * \li 'abs_path' is a valid absolute HTTP path string; 765 * \li 'outbuf' is a valid pointer to a buffer which will get the result; 766 * \li 'outbuf_len' is a size of the result buffer and is greater than zero. 767 */ 768 769 void 770 isc_nm_http_set_endpoints(isc_nmsocket_t *listener, 771 isc_nm_http_endpoints_t *eps); 772 /*%< 773 * Asynchronously replace the set of HTTP endpoints (paths) within 774 * the listener socket object. The function is intended to be used 775 * during reconfiguration. 776 * 777 * Requires: 778 * \li 'listener' is a pointer to a valid network manager HTTP listener socket; 779 * \li 'eps' is a valid pointer to an HTTP endpoints set. 780 */ 781 782 #endif /* HAVE_LIBNGHTTP2 */ 783 784 void 785 isc_nm_bad_request(isc_nmhandle_t *handle); 786 /*%< 787 * Perform a transport protocol specific action on the handle in case of a 788 * bad/malformed incoming DNS message. 789 * 790 * NOTE: The function currently is no-op for any protocol except HTTP/2. 791 * 792 * Requires: 793 * \li 'handle' is a valid netmgr handle object. 794 */ 795 796 isc_result_t 797 isc_nm_xfr_checkperm(isc_nmhandle_t *handle); 798 /*%< 799 * Check if it is permitted to do a zone transfer over the given handle. 800 * 801 * Returns: 802 * \li #ISC_R_SUCCESS Success, permission check passed successfully 803 * \li #ISC_R_DOTALPNERROR No permission because of ALPN tag mismatch 804 * \li #ISC_R_NOPERM No permission because of other restrictions 805 * \li any other result indicates failure (i.e. no permission) 806 * 807 * Requires: 808 * \li 'handle' is a valid connection handle. 809 */ 810 811 void 812 isc_nm_set_maxage(isc_nmhandle_t *handle, const uint32_t ttl); 813 /*%< 814 * Set the minimal time to live from the server's response Answer 815 * section as a hint to the underlying transport. 816 * 817 * NOTE: The function currently is no-op for any protocol except HTTP/2. 818 * 819 * Requires: 820 * 821 * \li 'handle' is a valid netmgr handle object associated with an accepted 822 * connection. 823 */ 824 825 isc_nmsocket_type 826 isc_nm_socket_type(const isc_nmhandle_t *handle); 827 /*%< 828 * Returns the handle's underlying socket type. 829 * 830 * Requires: 831 * \li 'handle' is a valid netmgr handle object. 832 */ 833 834 bool 835 isc_nm_has_encryption(const isc_nmhandle_t *handle); 836 /*%< 837 * Returns 'true' iff the handle's underlying transport does encryption. 838 * 839 * Requires: 840 * \li 'handle' is a valid netmgr handle object. 841 */ 842 843 const char * 844 isc_nm_verify_tls_peer_result_string(const isc_nmhandle_t *handle); 845 /*%< 846 * Returns user-readable message describing TLS peer's certificate 847 * validation result. Returns 'NULL' for the transport handles for 848 * which peer verification was not performed. 849 * 850 * Requires: 851 * \li 'handle' is a valid netmgr handle object. 852 */ 853 854 void 855 isc__nm_force_tid(int tid); 856 /*%< 857 * Force the thread ID to 'tid'. This is STRICTLY for use in unit 858 * tests and should not be used in any production code. 859 */ 860 861 void 862 isc_nmhandle_setwritetimeout(isc_nmhandle_t *handle, uint64_t write_timeout); 863 864 /* 865 * Timer related functions 866 */ 867 868 typedef struct isc_nm_timer isc_nm_timer_t; 869 870 typedef void (*isc_nm_timer_cb)(void *, isc_result_t); 871 872 void 873 isc_nm_timer_create(isc_nmhandle_t *, isc_nm_timer_cb, void *, 874 isc_nm_timer_t **); 875 876 void 877 isc_nm_timer_attach(isc_nm_timer_t *, isc_nm_timer_t **); 878 879 void 880 isc_nm_timer_detach(isc_nm_timer_t **); 881 882 void 883 isc_nm_timer_start(isc_nm_timer_t *, uint64_t); 884 885 void 886 isc_nm_timer_stop(isc_nm_timer_t *); 887 888 isc_result_t 889 isc_nmhandle_set_tcp_nodelay(isc_nmhandle_t *handle, const bool value); 890 /*%< 891 * Disables/Enables Nagle's algorithm on a TCP socket for a 892 * transport backed by TCP (sets TCP_NODELAY if 'value' equals 'true' 893 * or vice versa). 894 * 895 * Requires: 896 * 897 * \li 'handle' is a valid netmgr handle object. 898 */ 899 900 isc_sockaddr_t 901 isc_nmsocket_getaddr(isc_nmsocket_t *sock); 902 /*%< 903 * Return the local address of 'sock'. 904 */ 905 906 void 907 isc_netmgr_portrange(isc_nm_t *netmgr, sa_family_t af, in_port_t low, 908 in_port_t high); 909 /*%< 910 * Set the ephemeral port range <low, high> for 'af' family. 911 */ 912