1 /* $NetBSD: netmgr.h,v 1.10 2025/01/26 16:25:41 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 isc_tlsctx_client_session_cache_t *client_sess_cache, 503 isc_nm_proxyheader_info_t *proxy_info); 504 /*%< 505 * Create a TCP socket using netmgr 'mgr', bind it to the address 506 * 'local', and connect it to the address 'peer'. Right after the 507 * connection has been established, send PROXYv2 header using the 508 * information provided via the 'proxy_info' to the remote peer. Then 509 * the connection is considered established. 510 * 511 * If 'proxy_info' is omitted, then a LOCAL PROXYv2 header is sent. 512 * 513 * When the connection is established or has timed out, call 'cb' with 514 * argument 'cbarg'. 515 * 516 * 'timeout' specifies the timeout interval in milliseconds. 517 * 518 * The connected socket can only be accessed via the handle passed to 519 * 'cb'. 520 */ 521 522 void 523 isc_nm_proxyheader_info_init(isc_nm_proxyheader_info_t *restrict info, 524 isc_sockaddr_t *restrict src_addr, 525 isc_sockaddr_t *restrict dst_addr, 526 isc_region_t *restrict tlv_data); 527 /*%< 528 * Initialize a 'isc_nm_proxyheader_info_t' object with user 529 * provided addresses and a TLVs blob, that can be omitted (the rest 530 * of the data is REQUIRE()d). 531 */ 532 533 void 534 isc_nm_proxyheader_info_init_complete(isc_nm_proxyheader_info_t *restrict info, 535 isc_region_t *restrict header_data); 536 /*%< 537 * Initialize a 'isc_nm_proxyheader_info_t' with user provided data 538 * blob (e.g. a pre-rendered PROXYv2 header for forwarding or 539 * testing). 540 */ 541 542 void 543 isc_nm_settimeouts(isc_nm_t *mgr, uint32_t init, uint32_t idle, 544 uint32_t keepalive, uint32_t advertised); 545 /*%< 546 * Sets the initial, idle, and keepalive timeout values (in milliseconds) to use 547 * for TCP connections, and the timeout value to advertise in responses using 548 * the EDNS TCP Keepalive option (which should ordinarily be the same 549 * as 'keepalive'), in milliseconds. 550 * 551 * Requires: 552 * \li 'mgr' is a valid netmgr. 553 */ 554 555 void 556 isc_nm_setnetbuffers(isc_nm_t *mgr, int32_t recv_tcp, int32_t send_tcp, 557 int32_t recv_udp, int32_t send_udp); 558 /*%< 559 * If not 0, sets the SO_RCVBUF and SO_SNDBUF socket options for TCP and UDP 560 * respectively. 561 * 562 * Requires: 563 * \li 'mgr' is a valid netmgr. 564 */ 565 566 bool 567 isc_nm_getloadbalancesockets(isc_nm_t *mgr); 568 void 569 isc_nm_setloadbalancesockets(isc_nm_t *mgr, bool enabled); 570 /*%< 571 * Get and set value of load balancing of the sockets. 572 * 573 * Requires: 574 * \li 'mgr' is a valid netmgr. 575 */ 576 577 void 578 isc_nm_gettimeouts(isc_nm_t *mgr, uint32_t *initial, uint32_t *idle, 579 uint32_t *keepalive, uint32_t *advertised); 580 /*%< 581 * Gets the initial, idle, keepalive, or advertised timeout values, 582 * in milliseconds. 583 * 584 * Any integer pointer parameter not set to NULL will be updated to 585 * contain the corresponding timeout value. 586 * 587 * Requires: 588 * \li 'mgr' is a valid netmgr. 589 */ 590 591 void 592 isc_nm_maxudp(isc_nm_t *mgr, uint32_t maxudp); 593 /*%< 594 * Simulate a broken firewall that blocks UDP messages larger than a given 595 * size. 596 */ 597 598 void 599 isc_nm_setstats(isc_nm_t *mgr, isc_stats_t *stats); 600 /*%< 601 * Set a socket statistics counter set 'stats' for 'mgr'. 602 * 603 * Requires: 604 *\li 'mgr' is valid and doesn't have stats already set. 605 * 606 *\li stats is a valid set of statistics counters supporting the 607 * full range of socket-related stats counter numbers. 608 */ 609 610 isc_result_t 611 isc_nm_checkaddr(const isc_sockaddr_t *addr, isc_socktype_t type); 612 /*%< 613 * Check whether the specified address is available on the local system 614 * by opening a socket and immediately closing it. 615 * 616 * Requires: 617 *\li 'addr' is not NULL. 618 */ 619 620 void 621 isc_nm_streamdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, 622 isc_sockaddr_t *peer, isc_nm_cb_t cb, void *cbarg, 623 unsigned int timeout, isc_tlsctx_t *tlsctx, 624 isc_tlsctx_client_session_cache_t *client_sess_cache, 625 isc_nm_proxy_type_t proxy_type, 626 isc_nm_proxyheader_info_t *proxy_info); 627 /*%< 628 * Establish a DNS client connection via a TCP or TLS connection, bound to 629 * the address 'local' and connected to the address 'peer'. 630 * 631 * When the connection is complete or has timed out, call 'cb' with 632 * argument 'cbarg'. 633 * 634 * 'timeout' specifies the timeout interval in milliseconds. 635 * 636 * The connected socket can only be accessed via the handle passed to 637 * 'cb'. 638 */ 639 640 /*%< 641 * Returns 'true' iff 'handle' is associated with a socket of type 642 * 'isc_nm_tlsdnssocket'. 643 */ 644 645 bool 646 isc_nm_is_http_handle(isc_nmhandle_t *handle); 647 /*%< 648 * Returns 'true' iff 'handle' is associated with a socket of type 649 * 'isc_nm_httpsocket'. 650 */ 651 652 bool 653 isc_nm_is_proxy_unspec(isc_nmhandle_t *handle); 654 /*%< 655 * Returns 'true' iff 'handle' is associated with a peer who send 656 * a PROXYv2 header with unsupported address type. 657 */ 658 659 bool 660 isc_nm_is_proxy_handle(isc_nmhandle_t *handle); 661 /*%< Returns 'true' iff 'handle' is associated is with a PROXYv2 662 * connection. 663 */ 664 665 isc_result_t 666 isc_nm_listentls(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface, 667 isc_nm_accept_cb_t accept_cb, void *accept_cbarg, int backlog, 668 isc_quota_t *quota, isc_tlsctx_t *sslctx, bool proxy, 669 isc_nmsocket_t **sockp); 670 671 void 672 isc_nm_tlsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, 673 isc_nm_cb_t connect_cb, void *connect_cbarg, 674 isc_tlsctx_t *ctx, 675 isc_tlsctx_client_session_cache_t *client_sess_cache, 676 unsigned int timeout, bool proxy, 677 isc_nm_proxyheader_info_t *proxy_info); 678 679 #if HAVE_LIBNGHTTP2 680 681 #define ISC_NM_HTTP_DEFAULT_PATH "/dns-query" 682 683 void 684 isc_nm_httpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, 685 const char *uri, bool POST, isc_nm_cb_t cb, void *cbarg, 686 isc_tlsctx_t *ctx, 687 isc_tlsctx_client_session_cache_t *client_sess_cache, 688 unsigned int timeout, isc_nm_proxy_type_t proxy_type, 689 isc_nm_proxyheader_info_t *proxy_info); 690 691 isc_result_t 692 isc_nm_listenhttp(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface, 693 int backlog, isc_quota_t *quota, isc_tlsctx_t *ctx, 694 isc_nm_http_endpoints_t *eps, uint32_t max_concurrent_streams, 695 isc_nm_proxy_type_t proxy_type, isc_nmsocket_t **sockp); 696 697 isc_nm_http_endpoints_t * 698 isc_nm_http_endpoints_new(isc_mem_t *mctx); 699 /*%< 700 * Create a new, empty HTTP endpoints set object. 701 * 702 * Requires: 703 * \li 'mctx' a valid memory context object. 704 */ 705 706 isc_result_t 707 isc_nm_http_endpoints_add(isc_nm_http_endpoints_t *restrict eps, 708 const char *uri, const isc_nm_recv_cb_t cb, 709 void *cbarg); 710 /*%< Adds a new endpoint to the given HTTP endpoints set object. 711 * 712 * NOTE: adding an endpoint is allowed only if the endpoint object has 713 * not been passed to isc_nm_listenhttp() yet. 714 * 715 * Requires: 716 * \li 'eps' is a valid pointer to a valid isc_nm_http_endpoints_t 717 * object; 718 * \li 'uri' is a valid pointer to a string of length > 0; 719 * \li 'cb' is a valid pointer to a read callback function. 720 */ 721 722 void 723 isc_nm_http_endpoints_attach(isc_nm_http_endpoints_t *source, 724 isc_nm_http_endpoints_t **targetp); 725 /*%< 726 * Attaches to an HTTP endpoints set object. 727 * 728 * Requires: 729 * \li 'source' is a non-NULL pointer to a valid 730 * isc_nm_http_endpoints_t object; 731 * \li 'target' is a pointer to a pointer, containing NULL. 732 */ 733 734 void 735 isc_nm_http_endpoints_detach(isc_nm_http_endpoints_t **restrict epsp); 736 /*%< 737 * Detaches from an HTTP endpoints set object. When reference count 738 * reaches 0, the object get deleted. 739 * 740 * Requires: 741 * \li 'epsp' is a pointer to a pointer to a valid 742 * isc_nm_http_endpoints_t object. 743 */ 744 745 bool 746 isc_nm_http_path_isvalid(const char *path); 747 /*%< 748 * Returns 'true' if 'path' matches the format requirements for 749 * the path component of a URI as defined in RFC 3986 section 3.3. 750 */ 751 752 void 753 isc_nm_http_makeuri(const bool https, const isc_sockaddr_t *sa, 754 const char *hostname, const uint16_t http_port, 755 const char *abs_path, char *outbuf, 756 const size_t outbuf_len); 757 /*%< 758 * Makes a URI connection string out of na isc_sockaddr_t object 'sa' 759 * or the specified 'hostname' and 'http_port'. 760 * 761 * Requires: 762 * \li 'abs_path' is a valid absolute HTTP path string; 763 * \li 'outbuf' is a valid pointer to a buffer which will get the result; 764 * \li 'outbuf_len' is a size of the result buffer and is greater than zero. 765 */ 766 767 void 768 isc_nm_http_set_endpoints(isc_nmsocket_t *listener, 769 isc_nm_http_endpoints_t *eps); 770 /*%< 771 * Asynchronously replace the set of HTTP endpoints (paths) within 772 * the listener socket object. The function is intended to be used 773 * during reconfiguration. 774 * 775 * Requires: 776 * \li 'listener' is a pointer to a valid network manager HTTP listener socket; 777 * \li 'eps' is a valid pointer to an HTTP endpoints set. 778 */ 779 780 #endif /* HAVE_LIBNGHTTP2 */ 781 782 void 783 isc_nm_bad_request(isc_nmhandle_t *handle); 784 /*%< 785 * Perform a transport protocol specific action on the handle in case of a 786 * bad/malformed incoming DNS message. 787 * 788 * NOTE: The function currently is no-op for any protocol except HTTP/2. 789 * 790 * Requires: 791 * \li 'handle' is a valid netmgr handle object. 792 */ 793 794 isc_result_t 795 isc_nm_xfr_checkperm(isc_nmhandle_t *handle); 796 /*%< 797 * Check if it is permitted to do a zone transfer over the given handle. 798 * 799 * Returns: 800 * \li #ISC_R_SUCCESS Success, permission check passed successfully 801 * \li #ISC_R_DOTALPNERROR No permission because of ALPN tag mismatch 802 * \li #ISC_R_NOPERM No permission because of other restrictions 803 * \li any other result indicates failure (i.e. no permission) 804 * 805 * Requires: 806 * \li 'handle' is a valid connection handle. 807 */ 808 809 void 810 isc_nm_set_maxage(isc_nmhandle_t *handle, const uint32_t ttl); 811 /*%< 812 * Set the minimal time to live from the server's response Answer 813 * section as a hint to the underlying transport. 814 * 815 * NOTE: The function currently is no-op for any protocol except HTTP/2. 816 * 817 * Requires: 818 * 819 * \li 'handle' is a valid netmgr handle object associated with an accepted 820 * connection. 821 */ 822 823 isc_nmsocket_type 824 isc_nm_socket_type(const isc_nmhandle_t *handle); 825 /*%< 826 * Returns the handle's underlying socket type. 827 * 828 * Requires: 829 * \li 'handle' is a valid netmgr handle object. 830 */ 831 832 bool 833 isc_nm_has_encryption(const isc_nmhandle_t *handle); 834 /*%< 835 * Returns 'true' iff the handle's underlying transport does encryption. 836 * 837 * Requires: 838 * \li 'handle' is a valid netmgr handle object. 839 */ 840 841 const char * 842 isc_nm_verify_tls_peer_result_string(const isc_nmhandle_t *handle); 843 /*%< 844 * Returns user-readable message describing TLS peer's certificate 845 * validation result. Returns 'NULL' for the transport handles for 846 * which peer verification was not performed. 847 * 848 * Requires: 849 * \li 'handle' is a valid netmgr handle object. 850 */ 851 852 void 853 isc__nm_force_tid(int tid); 854 /*%< 855 * Force the thread ID to 'tid'. This is STRICTLY for use in unit 856 * tests and should not be used in any production code. 857 */ 858 859 void 860 isc_nmhandle_setwritetimeout(isc_nmhandle_t *handle, uint64_t write_timeout); 861 862 /* 863 * Timer related functions 864 */ 865 866 typedef struct isc_nm_timer isc_nm_timer_t; 867 868 typedef void (*isc_nm_timer_cb)(void *, isc_result_t); 869 870 void 871 isc_nm_timer_create(isc_nmhandle_t *, isc_nm_timer_cb, void *, 872 isc_nm_timer_t **); 873 874 void 875 isc_nm_timer_attach(isc_nm_timer_t *, isc_nm_timer_t **); 876 877 void 878 isc_nm_timer_detach(isc_nm_timer_t **); 879 880 void 881 isc_nm_timer_start(isc_nm_timer_t *, uint64_t); 882 883 void 884 isc_nm_timer_stop(isc_nm_timer_t *); 885 886 isc_result_t 887 isc_nmhandle_set_tcp_nodelay(isc_nmhandle_t *handle, const bool value); 888 /*%< 889 * Disables/Enables Nagle's algorithm on a TCP socket for a 890 * transport backed by TCP (sets TCP_NODELAY if 'value' equals 'true' 891 * or vice versa). 892 * 893 * Requires: 894 * 895 * \li 'handle' is a valid netmgr handle object. 896 */ 897 898 isc_sockaddr_t 899 isc_nmsocket_getaddr(isc_nmsocket_t *sock); 900 /*%< 901 * Return the local address of 'sock'. 902 */ 903