xref: /netbsd-src/external/mpl/bind/dist/lib/isc/include/isc/netmgr.h (revision bcda20f65a8566e103791ec395f7f499ef322704)
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