2001-04-10 21:52:17 +00:00
|
|
|
/*
|
2017-09-08 13:39:09 -07:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2001-04-10 21:52:17 +00:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
2021-06-03 08:37:05 +02:00
|
|
|
*
|
2001-04-10 21:52:17 +00:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
2001-04-10 21:52:17 +00:00
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
2001-05-31 10:36:05 +00:00
|
|
|
* information regarding copyright ownership.
|
2001-04-10 21:52:17 +00:00
|
|
|
*/
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*! \file */
|
2001-04-10 21:52:17 +00:00
|
|
|
|
2018-03-28 14:19:37 +02:00
|
|
|
#include <inttypes.h>
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
2018-03-28 14:19:37 +02:00
|
|
|
|
2022-10-29 03:33:05 -07:00
|
|
|
#include <isc/async.h>
|
2001-03-27 00:45:13 +00:00
|
|
|
#include <isc/base64.h>
|
|
|
|
#include <isc/buffer.h>
|
2014-02-27 17:55:04 -08:00
|
|
|
#include <isc/file.h>
|
2001-03-27 00:45:13 +00:00
|
|
|
#include <isc/mem.h>
|
2020-09-08 12:11:06 +10:00
|
|
|
#include <isc/mutex.h>
|
2001-10-31 19:35:19 +00:00
|
|
|
#include <isc/net.h>
|
2001-05-31 10:36:05 +00:00
|
|
|
#include <isc/netaddr.h>
|
2020-04-16 13:06:42 -07:00
|
|
|
#include <isc/netmgr.h>
|
2018-05-28 15:22:23 +02:00
|
|
|
#include <isc/nonce.h>
|
2003-07-17 06:24:44 +00:00
|
|
|
#include <isc/random.h>
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
#include <isc/refcount.h>
|
2001-03-27 00:45:13 +00:00
|
|
|
#include <isc/result.h>
|
|
|
|
#include <isc/stdtime.h>
|
|
|
|
#include <isc/string.h>
|
2024-11-29 10:02:13 +01:00
|
|
|
#include <isc/symtab.h>
|
2001-03-27 00:45:13 +00:00
|
|
|
#include <isc/util.h>
|
|
|
|
|
|
|
|
#include <isccc/alist.h>
|
|
|
|
#include <isccc/cc.h>
|
|
|
|
#include <isccc/ccmsg.h>
|
|
|
|
#include <isccc/sexpr.h>
|
|
|
|
#include <isccc/util.h>
|
2020-03-09 16:17:26 +01:00
|
|
|
|
2022-12-16 10:39:15 +00:00
|
|
|
#include <isccfg/check.h>
|
2020-03-09 16:17:26 +01:00
|
|
|
#include <isccfg/namedconf.h>
|
|
|
|
|
2001-08-03 18:12:08 +00:00
|
|
|
#include <named/config.h>
|
2001-03-27 00:45:13 +00:00
|
|
|
#include <named/control.h>
|
|
|
|
#include <named/log.h>
|
2022-07-26 13:03:45 +02:00
|
|
|
#include <named/main.h>
|
2001-03-27 00:45:13 +00:00
|
|
|
#include <named/server.h>
|
|
|
|
|
2023-10-13 10:08:26 +02:00
|
|
|
/* Add -DNAMED_CONTROLCONF_TRACE=1 to CFLAGS for detailed reference tracing */
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
|
2001-03-27 00:45:13 +00:00
|
|
|
typedef struct controlkey controlkey_t;
|
|
|
|
typedef ISC_LIST(controlkey_t) controlkeylist_t;
|
|
|
|
|
|
|
|
typedef struct controlconnection controlconnection_t;
|
|
|
|
typedef ISC_LIST(controlconnection_t) controlconnectionlist_t;
|
|
|
|
|
|
|
|
typedef struct controllistener controllistener_t;
|
|
|
|
typedef ISC_LIST(controllistener_t) controllistenerlist_t;
|
|
|
|
|
|
|
|
struct controlkey {
|
|
|
|
char *keyname;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t algorithm;
|
2001-03-27 00:45:13 +00:00
|
|
|
isc_region_t secret;
|
|
|
|
ISC_LINK(controlkey_t) link;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct controlconnection {
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
isc_refcount_t references;
|
2001-03-27 00:45:13 +00:00
|
|
|
isccc_ccmsg_t ccmsg;
|
|
|
|
controllistener_t *listener;
|
2020-05-14 14:03:37 -07:00
|
|
|
isccc_sexpr_t *ctrl;
|
|
|
|
isc_buffer_t *buffer;
|
|
|
|
isc_buffer_t *text;
|
|
|
|
isccc_sexpr_t *request;
|
|
|
|
isccc_sexpr_t *response;
|
|
|
|
uint32_t alg;
|
|
|
|
isccc_region_t secret;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t nonce;
|
2020-05-14 14:03:37 -07:00
|
|
|
isc_stdtime_t now;
|
|
|
|
isc_result_t result;
|
2001-03-27 00:45:13 +00:00
|
|
|
ISC_LINK(controlconnection_t) link;
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
bool shuttingdown;
|
2001-03-27 00:45:13 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct controllistener {
|
2017-09-08 13:39:09 -07:00
|
|
|
named_controls_t *controls;
|
2001-03-27 00:45:13 +00:00
|
|
|
isc_mem_t *mctx;
|
|
|
|
isc_sockaddr_t address;
|
2020-04-16 13:06:42 -07:00
|
|
|
isc_nmsocket_t *sock;
|
2001-03-27 00:45:13 +00:00
|
|
|
dns_acl_t *acl;
|
2023-11-06 20:19:20 +01:00
|
|
|
bool shuttingdown;
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
isc_refcount_t references;
|
2001-03-27 00:45:13 +00:00
|
|
|
controlkeylist_t keys;
|
|
|
|
controlconnectionlist_t connections;
|
2020-04-16 13:06:42 -07:00
|
|
|
isc_socktype_t type;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t perm;
|
|
|
|
uint32_t owner;
|
|
|
|
uint32_t group;
|
2018-04-17 08:29:14 -07:00
|
|
|
bool readonly;
|
2001-03-27 00:45:13 +00:00
|
|
|
ISC_LINK(controllistener_t) link;
|
|
|
|
};
|
|
|
|
|
2017-09-08 13:39:09 -07:00
|
|
|
struct named_controls {
|
|
|
|
named_server_t *server;
|
2001-05-08 03:42:34 +00:00
|
|
|
controllistenerlist_t listeners;
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
bool shuttingdown;
|
2020-09-08 12:11:06 +10:00
|
|
|
isc_mutex_t symtab_lock;
|
2024-11-29 10:02:13 +01:00
|
|
|
isc_symtab_t *symtab;
|
2001-05-08 03:42:34 +00:00
|
|
|
};
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
static isc_result_t
|
|
|
|
control_newconn(isc_nmhandle_t *handle, isc_result_t result, void *arg);
|
2001-03-27 00:45:13 +00:00
|
|
|
static void
|
2020-04-16 13:06:42 -07:00
|
|
|
control_recvmessage(isc_nmhandle_t *handle, isc_result_t result, void *arg);
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
static void
|
|
|
|
conn_cleanup(controlconnection_t *conn);
|
|
|
|
static void
|
|
|
|
conn_free(controlconnection_t *conn);
|
2023-11-06 20:19:20 +01:00
|
|
|
static void
|
|
|
|
conn_shutdown(controlconnection_t *conn);
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
|
|
|
|
#if NAMED_CONTROLCONF_TRACE
|
|
|
|
#define controllistener_ref(ptr) \
|
|
|
|
controllistener__ref(ptr, __func__, __FILE__, __LINE__)
|
|
|
|
#define controllistener_unref(ptr) \
|
|
|
|
controllistener__unref(ptr, __func__, __FILE__, __LINE__)
|
|
|
|
#define controllistener_attach(ptr, ptrp) \
|
|
|
|
controllistener__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
|
|
|
|
#define controllistener_detach(ptrp) \
|
|
|
|
controllistener__detach(ptrp, __func__, __FILE__, __LINE__)
|
|
|
|
ISC_REFCOUNT_TRACE_DECL(controllistener);
|
|
|
|
|
|
|
|
#define controlconnection_ref(ptr) \
|
|
|
|
controlconnection__ref(ptr, __func__, __FILE__, __LINE__)
|
|
|
|
#define controlconnection_unref(ptr) \
|
|
|
|
controlconnection__unref(ptr, __func__, __FILE__, __LINE__)
|
|
|
|
#define controlconnection_attach(ptr, ptrp) \
|
|
|
|
controlconnection__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
|
|
|
|
#define controlconnection_detach(ptrp) \
|
|
|
|
controlconnection__detach(ptrp, __func__, __FILE__, __LINE__)
|
|
|
|
ISC_REFCOUNT_TRACE_DECL(controlconnection);
|
|
|
|
#else
|
|
|
|
ISC_REFCOUNT_DECL(controllistener);
|
|
|
|
ISC_REFCOUNT_DECL(controlconnection);
|
|
|
|
#endif
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2003-07-17 06:24:44 +00:00
|
|
|
#define CLOCKSKEW 300
|
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
#define CHECK(x) \
|
|
|
|
{ \
|
|
|
|
result = (x); \
|
|
|
|
if (result != ISC_R_SUCCESS) { \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
2001-03-27 00:45:13 +00:00
|
|
|
static void
|
|
|
|
free_controlkey(controlkey_t *key, isc_mem_t *mctx) {
|
|
|
|
if (key->keyname != NULL) {
|
|
|
|
isc_mem_free(mctx, key->keyname);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 00:45:13 +00:00
|
|
|
if (key->secret.base != NULL) {
|
|
|
|
isc_mem_put(mctx, key->secret.base, key->secret.length);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 00:45:13 +00:00
|
|
|
isc_mem_put(mctx, key, sizeof(*key));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
free_controlkeylist(controlkeylist_t *keylist, isc_mem_t *mctx) {
|
2025-05-23 13:02:22 -07:00
|
|
|
ISC_LIST_FOREACH (*keylist, key, link) {
|
2001-03-27 00:45:13 +00:00
|
|
|
ISC_LIST_UNLINK(*keylist, key, link);
|
|
|
|
free_controlkey(key, mctx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
free_listener(controllistener_t *listener) {
|
2023-11-06 20:19:20 +01:00
|
|
|
REQUIRE(listener->shuttingdown);
|
2023-10-26 10:47:03 +02:00
|
|
|
REQUIRE(ISC_LIST_EMPTY(listener->connections));
|
2022-07-26 13:03:45 +02:00
|
|
|
REQUIRE(listener->sock == NULL);
|
2001-03-27 00:45:13 +00:00
|
|
|
|
|
|
|
free_controlkeylist(&listener->keys, listener->mctx);
|
|
|
|
|
|
|
|
if (listener->acl != NULL) {
|
|
|
|
dns_acl_detach(&listener->acl);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2013-03-08 14:38:03 +11:00
|
|
|
isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener));
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
#if NAMED_CONTROLCONF_TRACE
|
|
|
|
ISC_REFCOUNT_TRACE_IMPL(controllistener, free_listener);
|
|
|
|
ISC_REFCOUNT_TRACE_IMPL(controlconnection, conn_free);
|
|
|
|
#else
|
|
|
|
ISC_REFCOUNT_IMPL(controllistener, free_listener);
|
|
|
|
ISC_REFCOUNT_IMPL(controlconnection, conn_free);
|
|
|
|
#endif
|
2001-03-27 00:45:13 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
shutdown_listener(controllistener_t *listener) {
|
2023-11-06 20:19:20 +01:00
|
|
|
/* Don't shutdown the same listener twice */
|
|
|
|
if (listener->shuttingdown) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
listener->shuttingdown = true;
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
|
2025-05-23 13:02:22 -07:00
|
|
|
ISC_LIST_FOREACH (listener->connections, conn, link) {
|
2023-11-06 20:19:20 +01:00
|
|
|
conn_shutdown(conn);
|
|
|
|
}
|
2001-10-19 21:00:12 +00:00
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
ISC_LIST_UNLINK(listener->controls->listeners, listener, link);
|
2023-09-12 08:39:12 +02:00
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
|
|
|
isc_sockaddr_format(&listener->address, socktext, sizeof(socktext));
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_CONTROL,
|
|
|
|
ISC_LOG_NOTICE, "stopping command channel on %s",
|
|
|
|
socktext);
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
isc_nm_stoplistening(listener->sock);
|
2022-07-26 13:03:45 +02:00
|
|
|
isc_nmsocket_close(&listener->sock);
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
controllistener_detach(&listener);
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
static bool
|
2020-04-16 13:06:42 -07:00
|
|
|
address_ok(isc_sockaddr_t *sockaddr, controllistener_t *listener) {
|
2017-09-08 13:39:09 -07:00
|
|
|
dns_aclenv_t *env =
|
|
|
|
ns_interfacemgr_getaclenv(named_g_server->interfacemgr);
|
2001-03-27 00:45:13 +00:00
|
|
|
isc_netaddr_t netaddr;
|
|
|
|
isc_result_t result;
|
|
|
|
int match;
|
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
isc_netaddr_fromsockaddr(&netaddr, sockaddr);
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
result = dns_acl_match(&netaddr, NULL, listener->acl, env, &match,
|
|
|
|
NULL);
|
|
|
|
return result == ISC_R_SUCCESS && match > 0;
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-04-16 13:06:42 -07:00
|
|
|
control_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|
|
|
controlconnection_t *conn = (controlconnection_t *)arg;
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
if (conn->shuttingdown) {
|
|
|
|
/* The connection is shuttingdown */
|
|
|
|
result = ISC_R_SHUTTINGDOWN;
|
2020-10-22 12:32:18 +02:00
|
|
|
}
|
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
/* Everything is peachy, continue reading from the socket */
|
|
|
|
isccc_ccmsg_readmessage(&conn->ccmsg, control_recvmessage,
|
|
|
|
conn);
|
2024-02-08 12:31:09 +01:00
|
|
|
/* Detach the sending reference */
|
|
|
|
controlconnection_detach(&conn);
|
|
|
|
return;
|
2023-11-06 20:19:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (result != ISC_R_SHUTTINGDOWN) {
|
2001-03-27 00:45:13 +00:00
|
|
|
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
2023-11-06 20:19:20 +01:00
|
|
|
isc_sockaddr_t peeraddr = isc_nmhandle_peeraddr(handle);
|
2001-03-27 00:45:13 +00:00
|
|
|
|
|
|
|
isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(NAMED_LOGCATEGORY_GENERAL,
|
2017-09-08 13:39:09 -07:00
|
|
|
NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
|
2001-03-27 00:45:13 +00:00
|
|
|
"error sending command response to %s: %s",
|
2020-04-16 13:06:42 -07:00
|
|
|
socktext, isc_result_totext(result));
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
2001-03-31 01:24:25 +00:00
|
|
|
|
2024-02-08 12:31:09 +01:00
|
|
|
/* Shutdown the reading */
|
2023-11-06 20:19:20 +01:00
|
|
|
conn_shutdown(conn);
|
2020-09-03 13:31:27 -07:00
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
/* Detach the sending reference */
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
controlconnection_detach(&conn);
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 13:43:12 +02:00
|
|
|
static void
|
2001-03-27 00:45:13 +00:00
|
|
|
log_invalid(isccc_ccmsg_t *ccmsg, isc_result_t result) {
|
|
|
|
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
2020-04-16 13:06:42 -07:00
|
|
|
isc_sockaddr_t peeraddr = isc_nmhandle_peeraddr(ccmsg->handle);
|
2001-03-27 00:45:13 +00:00
|
|
|
|
|
|
|
isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_CONTROL,
|
|
|
|
ISC_LOG_ERROR, "invalid command from %s: %s", socktext,
|
2001-03-27 00:45:13 +00:00
|
|
|
isc_result_totext(result));
|
|
|
|
}
|
|
|
|
|
2020-09-03 13:31:27 -07:00
|
|
|
static void
|
|
|
|
conn_cleanup(controlconnection_t *conn) {
|
|
|
|
controllistener_t *listener = conn->listener;
|
|
|
|
|
|
|
|
if (conn->response != NULL) {
|
|
|
|
isccc_sexpr_free(&conn->response);
|
|
|
|
}
|
|
|
|
if (conn->request != NULL) {
|
|
|
|
isccc_sexpr_free(&conn->request);
|
|
|
|
}
|
|
|
|
if (conn->secret.rstart != NULL) {
|
|
|
|
isc_mem_put(listener->mctx, conn->secret.rstart,
|
|
|
|
REGION_SIZE(conn->secret));
|
|
|
|
}
|
|
|
|
if (conn->text != NULL) {
|
|
|
|
isc_buffer_free(&conn->text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-27 00:45:13 +00:00
|
|
|
static void
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
control_respond(controlconnection_t *conn) {
|
2020-05-14 14:03:37 -07:00
|
|
|
controllistener_t *listener = conn->listener;
|
|
|
|
isccc_sexpr_t *data = NULL;
|
2001-03-27 00:45:13 +00:00
|
|
|
isc_buffer_t b;
|
|
|
|
isc_region_t r;
|
2020-10-22 12:32:18 +02:00
|
|
|
isc_result_t result;
|
2020-05-14 14:03:37 -07:00
|
|
|
|
|
|
|
result = isccc_cc_createresponse(conn->request, conn->now,
|
|
|
|
conn->now + 60, &conn->response);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2020-10-22 12:32:18 +02:00
|
|
|
if (conn->result == ISC_R_SHUTTINGDOWN) {
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
} else {
|
|
|
|
result = conn->result;
|
|
|
|
}
|
|
|
|
|
2020-05-14 14:03:37 -07:00
|
|
|
data = isccc_alist_lookup(conn->response, "_data");
|
|
|
|
if (data != NULL) {
|
2020-10-22 12:32:18 +02:00
|
|
|
if (isccc_cc_defineuint32(data, "result", result) == NULL) {
|
2020-05-14 14:03:37 -07:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-22 12:32:18 +02:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2020-05-14 14:03:37 -07:00
|
|
|
if (data != NULL) {
|
2020-10-22 12:32:18 +02:00
|
|
|
const char *estr = isc_result_totext(result);
|
2020-05-14 14:03:37 -07:00
|
|
|
if (isccc_cc_definestring(data, "err", estr) == NULL) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isc_buffer_usedlength(conn->text) > 0) {
|
|
|
|
if (data != NULL) {
|
|
|
|
char *str = (char *)isc_buffer_base(conn->text);
|
|
|
|
if (isccc_cc_definestring(data, "text", str) == NULL) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
conn->ctrl = isccc_alist_lookup(conn->response, "_ctrl");
|
|
|
|
if (conn->ctrl == NULL ||
|
|
|
|
isccc_cc_defineuint32(conn->ctrl, "_nonce", conn->nonce) == NULL)
|
|
|
|
{
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (conn->buffer == NULL) {
|
|
|
|
isc_buffer_allocate(listener->mctx, &conn->buffer, 2 * 2048);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_buffer_clear(conn->buffer);
|
|
|
|
/* Skip the length field (4 bytes) */
|
|
|
|
isc_buffer_add(conn->buffer, 4);
|
|
|
|
|
|
|
|
result = isccc_cc_towire(conn->response, &conn->buffer, conn->alg,
|
|
|
|
&conn->secret);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
return;
|
2020-05-14 14:03:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_buffer_init(&b, conn->buffer->base, 4);
|
|
|
|
isc_buffer_putuint32(&b, conn->buffer->used - 4);
|
|
|
|
|
|
|
|
r.base = conn->buffer->base;
|
|
|
|
r.length = conn->buffer->used;
|
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
/* Attach the sending reference */
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
controlconnection_ref(conn);
|
|
|
|
isccc_ccmsg_sendmessage(&conn->ccmsg, &r, control_senddone, conn);
|
2020-09-17 15:52:19 +10:00
|
|
|
|
2020-05-14 14:03:37 -07:00
|
|
|
cleanup:
|
2020-09-03 13:31:27 -07:00
|
|
|
conn_cleanup(conn);
|
2020-05-14 14:03:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-10-29 03:33:05 -07:00
|
|
|
control_command(void *arg) {
|
|
|
|
controlconnection_t *conn = (controlconnection_t *)arg;
|
2020-05-14 14:03:37 -07:00
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
/* Don't run the command if we already started the shutdown */
|
|
|
|
if (!conn->shuttingdown) {
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
conn->result = named_control_docommand(
|
2023-11-06 20:19:20 +01:00
|
|
|
conn->request, conn->listener->readonly, &conn->text);
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
control_respond(conn);
|
2020-09-03 13:31:27 -07:00
|
|
|
}
|
2023-10-26 10:47:03 +02:00
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
/* Detach the control command reference */
|
|
|
|
controlconnection_detach(&conn);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
conn_shutdown(controlconnection_t *conn) {
|
|
|
|
/* Don't shutdown the same controlconnection twice */
|
|
|
|
if (conn->shuttingdown) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
conn->shuttingdown = true;
|
|
|
|
|
|
|
|
/*
|
Defer control channel message invalidation
The conn_shutdown() function is called whenever a control channel
connection is supposed to be closed, e.g. after a response to the client
is sent or when named is being shut down. That function calls
isccc_ccmsg_invalidate(), which resets the magic number in the structure
holding the messages exchanged over a given control channel connection
(isccc_ccmsg_t). The expectation here is that all operations related to
the given control channel connection will have been completed by the
time the connection needs to be shut down.
However, if named shutdown is initiated while a control channel message
is still in flight, some netmgr callbacks might still be pending when
conn_shutdown() is called and isccc_ccmsg_t invalidated. This causes
the REQUIRE assertion checking the magic number in ccmsg_senddone() to
fail when the latter function is eventually called, resulting in a
crash.
Fix by splitting up isccc_ccmsg_invalidate() into two separate
functions:
- isccc_ccmsg_disconnect(), which initiates TCP connection shutdown,
- isccc_ccmsg_invalidate(), which cleans up magic number and buffer,
and then:
- replacing all existing uses of isccc_ccmsg_invalidate() with calls
to isccc_ccmsg_disconnect(),
- only calling isccc_ccmsg_invalidate() when all netmgr callbacks are
guaranteed to have been run.
Adjust function comments accordingly.
2024-01-10 14:35:36 +11:00
|
|
|
* Close the TCP connection to make sure that no read callback will be
|
|
|
|
* called for it ever again.
|
2023-11-06 20:19:20 +01:00
|
|
|
*/
|
Defer control channel message invalidation
The conn_shutdown() function is called whenever a control channel
connection is supposed to be closed, e.g. after a response to the client
is sent or when named is being shut down. That function calls
isccc_ccmsg_invalidate(), which resets the magic number in the structure
holding the messages exchanged over a given control channel connection
(isccc_ccmsg_t). The expectation here is that all operations related to
the given control channel connection will have been completed by the
time the connection needs to be shut down.
However, if named shutdown is initiated while a control channel message
is still in flight, some netmgr callbacks might still be pending when
conn_shutdown() is called and isccc_ccmsg_t invalidated. This causes
the REQUIRE assertion checking the magic number in ccmsg_senddone() to
fail when the latter function is eventually called, resulting in a
crash.
Fix by splitting up isccc_ccmsg_invalidate() into two separate
functions:
- isccc_ccmsg_disconnect(), which initiates TCP connection shutdown,
- isccc_ccmsg_invalidate(), which cleans up magic number and buffer,
and then:
- replacing all existing uses of isccc_ccmsg_invalidate() with calls
to isccc_ccmsg_disconnect(),
- only calling isccc_ccmsg_invalidate() when all netmgr callbacks are
guaranteed to have been run.
Adjust function comments accordingly.
2024-01-10 14:35:36 +11:00
|
|
|
isccc_ccmsg_disconnect(&conn->ccmsg);
|
2023-11-06 20:19:20 +01:00
|
|
|
|
|
|
|
/* Detach the reading reference */
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
controlconnection_detach(&conn);
|
2020-05-14 14:03:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
control_recvmessage(isc_nmhandle_t *handle ISC_ATTR_UNUSED, isc_result_t result,
|
|
|
|
void *arg) {
|
2020-05-14 14:03:37 -07:00
|
|
|
controlconnection_t *conn = (controlconnection_t *)arg;
|
|
|
|
controllistener_t *listener = conn->listener;
|
2025-03-20 22:25:56 -07:00
|
|
|
bool match = false;
|
2003-07-17 06:24:44 +00:00
|
|
|
isccc_time_t sent;
|
|
|
|
isccc_time_t exp;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t nonce;
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
goto cleanup;
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2025-03-20 22:25:56 -07:00
|
|
|
ISC_LIST_FOREACH (listener->keys, key, link) {
|
2014-11-14 15:58:54 -08:00
|
|
|
isccc_region_t ccregion;
|
|
|
|
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
isccc_ccmsg_toregion(&conn->ccmsg, &ccregion);
|
2020-05-14 14:03:37 -07:00
|
|
|
conn->secret.rstart = isc_mem_get(listener->mctx,
|
|
|
|
key->secret.length);
|
|
|
|
memmove(conn->secret.rstart, key->secret.base,
|
|
|
|
key->secret.length);
|
|
|
|
conn->secret.rend = conn->secret.rstart + key->secret.length;
|
|
|
|
conn->alg = key->algorithm;
|
|
|
|
result = isccc_cc_fromwire(&ccregion, &conn->request, conn->alg,
|
|
|
|
&conn->secret);
|
2001-07-04 03:54:55 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2025-03-20 22:25:56 -07:00
|
|
|
match = true;
|
2001-07-04 03:54:55 +00:00
|
|
|
break;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-05-14 14:03:37 -07:00
|
|
|
isc_mem_put(listener->mctx, conn->secret.rstart,
|
|
|
|
REGION_SIZE(conn->secret));
|
2001-07-04 03:54:55 +00:00
|
|
|
}
|
|
|
|
|
2025-03-20 22:25:56 -07:00
|
|
|
if (!match) {
|
2023-11-06 20:19:20 +01:00
|
|
|
result = ISCCC_R_BADAUTH;
|
2001-03-27 00:45:13 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We shouldn't be getting a reply. */
|
2020-05-14 14:03:37 -07:00
|
|
|
if (isccc_cc_isreply(conn->request)) {
|
2023-11-06 20:19:20 +01:00
|
|
|
result = ISC_R_FAILURE;
|
2020-05-14 14:03:37 -07:00
|
|
|
goto cleanup;
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2023-03-30 21:13:41 +02:00
|
|
|
conn->now = isc_stdtime_now();
|
2003-07-17 06:24:44 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Limit exposure to replay attacks.
|
|
|
|
*/
|
2020-05-14 14:03:37 -07:00
|
|
|
conn->ctrl = isccc_alist_lookup(conn->request, "_ctrl");
|
|
|
|
if (!isccc_alist_alistp(conn->ctrl)) {
|
2023-11-06 20:19:20 +01:00
|
|
|
result = ISC_R_FAILURE;
|
2020-05-14 14:03:37 -07:00
|
|
|
goto cleanup;
|
2003-07-17 06:24:44 +00:00
|
|
|
}
|
|
|
|
|
2020-05-14 14:03:37 -07:00
|
|
|
if (isccc_cc_lookupuint32(conn->ctrl, "_tim", &sent) == ISC_R_SUCCESS) {
|
|
|
|
if ((sent + CLOCKSKEW) < conn->now ||
|
2022-11-02 19:33:14 +01:00
|
|
|
(sent - CLOCKSKEW) > conn->now)
|
|
|
|
{
|
2025-01-08 20:13:34 -08:00
|
|
|
result = DNS_R_CLOCKSKEW;
|
2020-05-14 14:03:37 -07:00
|
|
|
goto cleanup;
|
2003-07-17 06:24:44 +00:00
|
|
|
}
|
|
|
|
} else {
|
2023-11-06 20:19:20 +01:00
|
|
|
result = ISC_R_FAILURE;
|
2020-05-14 14:03:37 -07:00
|
|
|
goto cleanup;
|
2003-07-17 06:24:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Expire messages that are too old.
|
|
|
|
*/
|
2020-05-14 14:03:37 -07:00
|
|
|
if (isccc_cc_lookupuint32(conn->ctrl, "_exp", &exp) == ISC_R_SUCCESS &&
|
|
|
|
conn->now > exp)
|
|
|
|
{
|
2025-01-08 20:13:34 -08:00
|
|
|
result = DNS_R_EXPIRED;
|
2020-05-14 14:03:37 -07:00
|
|
|
goto cleanup;
|
2003-07-17 06:24:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Duplicate suppression (required for UDP).
|
|
|
|
*/
|
2020-09-08 12:11:06 +10:00
|
|
|
LOCK(&listener->controls->symtab_lock);
|
2020-05-14 14:03:37 -07:00
|
|
|
isccc_cc_cleansymtab(listener->controls->symtab, conn->now);
|
|
|
|
result = isccc_cc_checkdup(listener->controls->symtab, conn->request,
|
|
|
|
conn->now);
|
2020-09-08 12:11:06 +10:00
|
|
|
UNLOCK(&listener->controls->symtab_lock);
|
2003-07-17 06:24:44 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
if (result == ISC_R_EXISTS) {
|
2008-01-18 23:46:58 +00:00
|
|
|
result = ISCCC_R_DUPLICATE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-05-14 14:03:37 -07:00
|
|
|
goto cleanup;
|
2003-07-17 06:24:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (conn->nonce != 0 &&
|
2020-05-14 14:03:37 -07:00
|
|
|
(isccc_cc_lookupuint32(conn->ctrl, "_nonce", &nonce) !=
|
|
|
|
ISC_R_SUCCESS ||
|
2003-07-17 06:24:44 +00:00
|
|
|
conn->nonce != nonce))
|
|
|
|
{
|
2023-11-06 20:19:20 +01:00
|
|
|
result = ISCCC_R_BADAUTH;
|
2020-05-14 14:03:37 -07:00
|
|
|
goto cleanup;
|
2003-07-17 06:24:44 +00:00
|
|
|
}
|
|
|
|
|
2020-05-14 14:03:37 -07:00
|
|
|
isc_buffer_allocate(listener->mctx, &conn->text, 2 * 2048);
|
|
|
|
|
2013-03-07 15:14:07 -08:00
|
|
|
if (conn->nonce == 0) {
|
2020-05-14 14:03:37 -07:00
|
|
|
/*
|
|
|
|
* Establish nonce.
|
|
|
|
*/
|
2017-09-28 10:09:22 -07:00
|
|
|
while (conn->nonce == 0) {
|
2018-05-28 15:22:23 +02:00
|
|
|
isc_nonce_buf(&conn->nonce, sizeof(conn->nonce));
|
2017-09-28 10:09:22 -07:00
|
|
|
}
|
2020-05-14 14:03:37 -07:00
|
|
|
conn->result = ISC_R_SUCCESS;
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
control_respond(conn);
|
2020-05-14 14:03:37 -07:00
|
|
|
return;
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
/* Attach the command reference */
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
controlconnection_ref(conn);
|
2023-11-06 20:19:20 +01:00
|
|
|
|
|
|
|
/* Trigger the command asynchronously. */
|
2022-10-29 03:33:05 -07:00
|
|
|
isc_async_run(named_g_mainloop, control_command, conn);
|
2020-09-03 13:31:27 -07:00
|
|
|
|
2020-05-14 14:03:37 -07:00
|
|
|
return;
|
2001-05-08 04:09:41 +00:00
|
|
|
|
2020-05-14 14:03:37 -07:00
|
|
|
cleanup:
|
2023-11-06 20:19:20 +01:00
|
|
|
switch (result) {
|
|
|
|
case ISC_R_SHUTTINGDOWN:
|
|
|
|
case ISC_R_EOF:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
log_invalid(&conn->ccmsg, result);
|
|
|
|
}
|
2023-10-26 10:47:03 +02:00
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
conn_shutdown(conn);
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
conn_free(controlconnection_t *conn) {
|
2023-11-06 20:19:20 +01:00
|
|
|
/* Make sure that the connection was shutdown first */
|
|
|
|
REQUIRE(conn->shuttingdown);
|
2023-10-26 10:47:03 +02:00
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
controllistener_t *listener = conn->listener;
|
2001-03-27 00:45:13 +00:00
|
|
|
|
Defer control channel message invalidation
The conn_shutdown() function is called whenever a control channel
connection is supposed to be closed, e.g. after a response to the client
is sent or when named is being shut down. That function calls
isccc_ccmsg_invalidate(), which resets the magic number in the structure
holding the messages exchanged over a given control channel connection
(isccc_ccmsg_t). The expectation here is that all operations related to
the given control channel connection will have been completed by the
time the connection needs to be shut down.
However, if named shutdown is initiated while a control channel message
is still in flight, some netmgr callbacks might still be pending when
conn_shutdown() is called and isccc_ccmsg_t invalidated. This causes
the REQUIRE assertion checking the magic number in ccmsg_senddone() to
fail when the latter function is eventually called, resulting in a
crash.
Fix by splitting up isccc_ccmsg_invalidate() into two separate
functions:
- isccc_ccmsg_disconnect(), which initiates TCP connection shutdown,
- isccc_ccmsg_invalidate(), which cleans up magic number and buffer,
and then:
- replacing all existing uses of isccc_ccmsg_invalidate() with calls
to isccc_ccmsg_disconnect(),
- only calling isccc_ccmsg_invalidate() when all netmgr callbacks are
guaranteed to have been run.
Adjust function comments accordingly.
2024-01-10 14:35:36 +11:00
|
|
|
isccc_ccmsg_invalidate(&conn->ccmsg);
|
|
|
|
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
conn_cleanup(conn);
|
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
if (conn->buffer != NULL) {
|
|
|
|
isc_buffer_free(&conn->buffer);
|
|
|
|
}
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
ISC_LIST_UNLINK(listener->connections, conn, link);
|
|
|
|
#ifdef ENABLE_AFL
|
|
|
|
if (named_g_fuzz_type == isc_fuzz_rndc) {
|
|
|
|
named_fuzz_notify();
|
|
|
|
}
|
|
|
|
#endif /* ifdef ENABLE_AFL */
|
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_CONTROL,
|
|
|
|
ISC_LOG_DEBUG(3), "freeing control connection");
|
2022-03-23 13:57:15 +01:00
|
|
|
|
|
|
|
isc_mem_put(listener->mctx, conn, sizeof(*conn));
|
|
|
|
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
controllistener_detach(&listener);
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2020-10-21 12:52:09 +02:00
|
|
|
static void
|
2020-04-16 13:06:42 -07:00
|
|
|
newconnection(controllistener_t *listener, isc_nmhandle_t *handle) {
|
2023-11-06 20:19:20 +01:00
|
|
|
/* Don't create new connection if we are shutting down */
|
|
|
|
if (listener->shuttingdown) {
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(NAMED_LOGCATEGORY_GENERAL,
|
2023-11-06 20:19:20 +01:00
|
|
|
NAMED_LOGMODULE_CONTROL, ISC_LOG_DEBUG(3),
|
|
|
|
"rejected new control connection: %s",
|
|
|
|
isc_result_totext(ISC_R_SHUTTINGDOWN));
|
|
|
|
return;
|
|
|
|
}
|
2023-10-26 10:47:03 +02:00
|
|
|
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
controlconnection_t *conn = isc_mem_get(listener->mctx, sizeof(*conn));
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_CONTROL,
|
|
|
|
ISC_LOG_DEBUG(3), "allocate new control connection");
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
*conn = (controlconnection_t){
|
|
|
|
.alg = DST_ALG_UNKNOWN,
|
|
|
|
.references = ISC_REFCOUNT_INITIALIZER(1),
|
|
|
|
.listener = controllistener_ref(listener),
|
|
|
|
.link = ISC_LINK_INITIALIZER,
|
|
|
|
};
|
2020-04-16 13:06:42 -07:00
|
|
|
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
/* isccc_ccmsg_init() attaches to the handle */
|
2020-04-16 13:06:42 -07:00
|
|
|
isccc_ccmsg_init(listener->mctx, handle, &conn->ccmsg);
|
2015-11-11 09:55:25 +05:30
|
|
|
|
|
|
|
/* Set a 32 KiB upper limit on incoming message. */
|
|
|
|
isccc_ccmsg_setmaxsize(&conn->ccmsg, 32768);
|
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
ISC_LIST_APPEND(listener->connections, conn, link);
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
/* The reading reference has been initialized in the initializer */
|
2020-10-21 12:52:09 +02:00
|
|
|
isccc_ccmsg_readmessage(&conn->ccmsg, control_recvmessage, conn);
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
static isc_result_t
|
|
|
|
control_newconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|
|
|
controllistener_t *listener = arg;
|
2001-03-27 00:45:13 +00:00
|
|
|
isc_sockaddr_t peeraddr;
|
2020-06-23 13:02:21 +02:00
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2022-01-11 14:27:28 +01:00
|
|
|
if (result == ISC_R_SHUTTINGDOWN) {
|
2001-03-27 00:45:13 +00:00
|
|
|
shutdown_listener(listener);
|
|
|
|
}
|
2020-04-16 13:06:42 -07:00
|
|
|
return result;
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
peeraddr = isc_nmhandle_peeraddr(handle);
|
|
|
|
if (!address_ok(&peeraddr, listener)) {
|
2001-03-27 00:45:13 +00:00
|
|
|
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
|
|
|
isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(NAMED_LOGCATEGORY_GENERAL,
|
2017-09-08 13:39:09 -07:00
|
|
|
NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
|
2001-03-27 00:45:13 +00:00
|
|
|
"rejected command channel message from %s",
|
|
|
|
socktext);
|
2020-04-16 13:06:42 -07:00
|
|
|
return ISC_R_FAILURE;
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2020-10-21 12:52:09 +02:00
|
|
|
newconnection(listener, handle);
|
2020-04-16 13:06:42 -07:00
|
|
|
return ISC_R_SUCCESS;
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2001-09-21 03:04:14 +00:00
|
|
|
static void
|
2017-09-08 13:39:09 -07:00
|
|
|
controls_shutdown(named_controls_t *controls) {
|
2025-05-23 13:02:22 -07:00
|
|
|
ISC_LIST_FOREACH (controls->listeners, listener, link) {
|
2001-03-27 00:45:13 +00:00
|
|
|
/*
|
2023-11-06 20:19:20 +01:00
|
|
|
* As listeners shut down, they will call their callbacks.
|
2001-03-27 00:45:13 +00:00
|
|
|
*/
|
|
|
|
shutdown_listener(listener);
|
|
|
|
}
|
2001-09-21 03:04:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-09-08 13:39:09 -07:00
|
|
|
named_controls_shutdown(named_controls_t *controls) {
|
2023-11-06 20:19:20 +01:00
|
|
|
/*
|
|
|
|
* Don't ever shutdown the controls twice.
|
|
|
|
*
|
|
|
|
* NOTE: This functions is called when the server is shutting down, but
|
|
|
|
* controls_shutdown() can and will be called multiple times - on each
|
|
|
|
* reconfiguration, the listeners will be torn down and recreated again,
|
|
|
|
* see named_controls_configure() for details.
|
|
|
|
*/
|
|
|
|
if (controls->shuttingdown) {
|
|
|
|
return;
|
|
|
|
}
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
controls->shuttingdown = true;
|
2023-11-06 20:19:20 +01:00
|
|
|
|
|
|
|
controls_shutdown(controls);
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
cfgkeylist_find(const cfg_obj_t *keylist, const char *keyname,
|
2008-01-18 23:46:58 +00:00
|
|
|
const cfg_obj_t **objp) {
|
2019-12-15 16:45:17 -08:00
|
|
|
const char *str = NULL;
|
|
|
|
const cfg_obj_t *obj = NULL;
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2025-03-26 18:54:05 -07:00
|
|
|
CFG_LIST_FOREACH (keylist, element) {
|
2001-03-27 00:45:13 +00:00
|
|
|
obj = cfg_listelt_value(element);
|
|
|
|
str = cfg_obj_asstring(cfg_map_getname(obj));
|
|
|
|
if (strcasecmp(str, keyname) == 0) {
|
2025-03-26 18:54:05 -07:00
|
|
|
*objp = obj;
|
|
|
|
return ISC_R_SUCCESS;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
2025-03-26 18:54:05 -07:00
|
|
|
|
|
|
|
return ISC_R_NOTFOUND;
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2019-07-23 14:56:24 -04:00
|
|
|
static void
|
2006-02-28 02:39:52 +00:00
|
|
|
controlkeylist_fromcfg(const cfg_obj_t *keylist, isc_mem_t *mctx,
|
2001-05-31 10:36:05 +00:00
|
|
|
controlkeylist_t *keyids) {
|
2001-03-27 00:45:13 +00:00
|
|
|
char *newstr = NULL;
|
2019-12-15 16:45:17 -08:00
|
|
|
const char *str = NULL;
|
|
|
|
const cfg_obj_t *obj = NULL;
|
|
|
|
controlkey_t *key = NULL;
|
2020-02-12 13:59:18 +01:00
|
|
|
|
2025-03-26 18:54:05 -07:00
|
|
|
CFG_LIST_FOREACH (keylist, element) {
|
2001-03-27 00:45:13 +00:00
|
|
|
obj = cfg_listelt_value(element);
|
|
|
|
str = cfg_obj_asstring(obj);
|
|
|
|
newstr = isc_mem_strdup(mctx, str);
|
|
|
|
key = isc_mem_get(mctx, sizeof(*key));
|
|
|
|
key->keyname = newstr;
|
2013-03-13 17:53:11 -07:00
|
|
|
key->algorithm = DST_ALG_UNKNOWN;
|
2001-03-27 00:45:13 +00:00
|
|
|
key->secret.base = NULL;
|
|
|
|
key->secret.length = 0;
|
|
|
|
ISC_LINK_INIT(key, link);
|
|
|
|
ISC_LIST_APPEND(*keyids, key, link);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-02-28 02:39:52 +00:00
|
|
|
register_keys(const cfg_obj_t *control, const cfg_obj_t *keylist,
|
2001-08-03 05:56:22 +00:00
|
|
|
controlkeylist_t *keyids, isc_mem_t *mctx, const char *socktext) {
|
2019-12-15 16:45:17 -08:00
|
|
|
const cfg_obj_t *keydef = NULL;
|
2001-03-27 00:45:13 +00:00
|
|
|
char secret[1024];
|
|
|
|
isc_buffer_t b;
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find the keys corresponding to the keyids used by this listener.
|
|
|
|
*/
|
2025-05-23 13:02:22 -07:00
|
|
|
ISC_LIST_FOREACH (*keyids, keyid, link) {
|
2001-03-27 00:45:13 +00:00
|
|
|
result = cfgkeylist_find(keylist, keyid->keyname, &keydef);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2024-08-13 18:20:26 +02:00
|
|
|
cfg_obj_log(control, ISC_LOG_WARNING,
|
2001-05-07 21:57:25 +00:00
|
|
|
"couldn't find key '%s' for use with "
|
2001-03-27 00:45:13 +00:00
|
|
|
"command channel %s",
|
|
|
|
keyid->keyname, socktext);
|
|
|
|
ISC_LIST_UNLINK(*keyids, keyid, link);
|
|
|
|
free_controlkey(keyid, mctx);
|
|
|
|
} else {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *algobj = NULL;
|
|
|
|
const cfg_obj_t *secretobj = NULL;
|
2005-08-23 02:36:11 +00:00
|
|
|
const char *algstr = NULL;
|
|
|
|
const char *secretstr = NULL;
|
2013-03-13 17:53:11 -07:00
|
|
|
unsigned int algtype;
|
2001-03-27 00:45:13 +00:00
|
|
|
|
|
|
|
(void)cfg_map_get(keydef, "algorithm", &algobj);
|
|
|
|
(void)cfg_map_get(keydef, "secret", &secretobj);
|
|
|
|
INSIST(algobj != NULL && secretobj != NULL);
|
|
|
|
|
|
|
|
algstr = cfg_obj_asstring(algobj);
|
|
|
|
secretstr = cfg_obj_asstring(secretobj);
|
|
|
|
|
2023-04-11 19:01:31 -07:00
|
|
|
result = named_config_getkeyalgorithm(algstr, &algtype,
|
|
|
|
NULL);
|
2019-12-15 16:45:17 -08:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2024-08-13 18:20:26 +02:00
|
|
|
cfg_obj_log(control, ISC_LOG_WARNING,
|
2001-03-27 00:45:13 +00:00
|
|
|
"unsupported algorithm '%s' in "
|
|
|
|
"key '%s' for use with command "
|
|
|
|
"channel %s",
|
|
|
|
algstr, keyid->keyname, socktext);
|
|
|
|
ISC_LIST_UNLINK(*keyids, keyid, link);
|
|
|
|
free_controlkey(keyid, mctx);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-03-13 17:53:11 -07:00
|
|
|
keyid->algorithm = algtype;
|
2001-03-27 00:45:13 +00:00
|
|
|
isc_buffer_init(&b, secret, sizeof(secret));
|
|
|
|
result = isc_base64_decodestring(secretstr, &b);
|
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2024-08-13 18:20:26 +02:00
|
|
|
cfg_obj_log(keydef, ISC_LOG_WARNING,
|
2001-03-27 00:45:13 +00:00
|
|
|
"secret for key '%s' on "
|
|
|
|
"command channel %s: %s",
|
|
|
|
keyid->keyname, socktext,
|
|
|
|
isc_result_totext(result));
|
|
|
|
ISC_LIST_UNLINK(*keyids, keyid, link);
|
|
|
|
free_controlkey(keyid, mctx);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
keyid->secret.length = isc_buffer_usedlength(&b);
|
|
|
|
keyid->secret.base = isc_mem_get(mctx,
|
|
|
|
keyid->secret.length);
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(keyid->secret.base, isc_buffer_base(&b),
|
|
|
|
keyid->secret.length);
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-05-31 10:36:05 +00:00
|
|
|
static isc_result_t
|
2001-08-03 05:56:22 +00:00
|
|
|
get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) {
|
2001-05-31 10:36:05 +00:00
|
|
|
isc_result_t result;
|
2001-08-03 05:56:22 +00:00
|
|
|
cfg_parser_t *pctx = NULL;
|
|
|
|
cfg_obj_t *config = NULL;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *key = NULL;
|
|
|
|
const cfg_obj_t *algobj = NULL;
|
|
|
|
const cfg_obj_t *secretobj = NULL;
|
2005-08-23 02:36:11 +00:00
|
|
|
const char *algstr = NULL;
|
|
|
|
const char *secretstr = NULL;
|
2001-08-03 05:56:22 +00:00
|
|
|
controlkey_t *keyid = NULL;
|
|
|
|
char secret[1024];
|
2013-03-13 17:53:11 -07:00
|
|
|
unsigned int algtype;
|
2001-08-03 05:56:22 +00:00
|
|
|
isc_buffer_t b;
|
2001-05-31 10:36:05 +00:00
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_CONTROL,
|
|
|
|
ISC_LOG_INFO, "configuring command channel from '%s'",
|
|
|
|
named_g_keyfile);
|
2017-09-08 13:39:09 -07:00
|
|
|
if (!isc_file_exists(named_g_keyfile)) {
|
2014-02-27 17:55:04 -08:00
|
|
|
return ISC_R_FILENOTFOUND;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-02-27 17:55:04 -08:00
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
CHECK(cfg_parser_create(mctx, &pctx));
|
2017-09-08 13:39:09 -07:00
|
|
|
CHECK(cfg_parse_file(pctx, named_g_keyfile, &cfg_type_rndckey,
|
|
|
|
&config));
|
2001-08-03 05:56:22 +00:00
|
|
|
CHECK(cfg_map_get(config, "key", &key));
|
|
|
|
|
|
|
|
keyid = isc_mem_get(mctx, sizeof(*keyid));
|
2025-01-07 19:03:07 -08:00
|
|
|
*keyid = (controlkey_t){
|
|
|
|
.algorithm = DST_ALG_UNKNOWN,
|
|
|
|
.link = ISC_LINK_INITIALIZER,
|
|
|
|
};
|
2001-08-03 05:56:22 +00:00
|
|
|
keyid->keyname = isc_mem_strdup(mctx,
|
|
|
|
cfg_obj_asstring(cfg_map_getname(key)));
|
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
CHECK(isccfg_check_key(key));
|
2001-08-03 17:24:11 +00:00
|
|
|
|
2001-08-03 05:56:22 +00:00
|
|
|
(void)cfg_map_get(key, "algorithm", &algobj);
|
|
|
|
(void)cfg_map_get(key, "secret", &secretobj);
|
|
|
|
INSIST(algobj != NULL && secretobj != NULL);
|
|
|
|
|
|
|
|
algstr = cfg_obj_asstring(algobj);
|
|
|
|
secretstr = cfg_obj_asstring(secretobj);
|
|
|
|
|
2023-04-11 19:01:31 -07:00
|
|
|
result = named_config_getkeyalgorithm(algstr, &algtype, NULL);
|
2019-12-15 16:45:17 -08:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2024-08-13 18:20:26 +02:00
|
|
|
cfg_obj_log(key, ISC_LOG_WARNING,
|
2001-08-03 05:56:22 +00:00
|
|
|
"unsupported algorithm '%s' in "
|
|
|
|
"key '%s' for use with command "
|
|
|
|
"channel",
|
|
|
|
algstr, keyid->keyname);
|
|
|
|
goto cleanup;
|
2001-05-31 10:36:05 +00:00
|
|
|
}
|
|
|
|
|
2013-03-13 17:53:11 -07:00
|
|
|
keyid->algorithm = algtype;
|
2001-08-03 05:56:22 +00:00
|
|
|
isc_buffer_init(&b, secret, sizeof(secret));
|
|
|
|
result = isc_base64_decodestring(secretstr, &b);
|
2001-05-31 10:36:05 +00:00
|
|
|
|
2001-08-03 05:56:22 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2024-08-13 18:20:26 +02:00
|
|
|
cfg_obj_log(key, ISC_LOG_WARNING,
|
2001-08-03 05:56:22 +00:00
|
|
|
"secret for key '%s' on command channel: %s",
|
|
|
|
keyid->keyname, isc_result_totext(result));
|
2011-03-11 06:11:27 +00:00
|
|
|
goto cleanup;
|
2001-05-31 10:36:05 +00:00
|
|
|
}
|
|
|
|
|
2001-08-03 05:56:22 +00:00
|
|
|
keyid->secret.length = isc_buffer_usedlength(&b);
|
2019-07-16 15:52:14 +02:00
|
|
|
keyid->secret.base = isc_mem_get(mctx, keyid->secret.length);
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(keyid->secret.base, isc_buffer_base(&b), keyid->secret.length);
|
2001-08-03 05:56:22 +00:00
|
|
|
ISC_LIST_APPEND(*keyids, keyid, link);
|
|
|
|
keyid = NULL;
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (keyid != NULL) {
|
|
|
|
free_controlkey(keyid, mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-03 05:56:22 +00:00
|
|
|
if (config != NULL) {
|
|
|
|
cfg_obj_destroy(pctx, &config);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-03 05:56:22 +00:00
|
|
|
if (pctx != NULL) {
|
|
|
|
cfg_parser_destroy(&pctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-05-31 10:36:05 +00:00
|
|
|
return result;
|
|
|
|
}
|
2008-01-18 23:46:58 +00:00
|
|
|
|
2001-08-04 07:38:06 +00:00
|
|
|
/*
|
|
|
|
* Ensures that both '*global_keylistp' and '*control_keylistp' are
|
|
|
|
* valid or both are NULL.
|
|
|
|
*/
|
2001-05-31 10:36:05 +00:00
|
|
|
static void
|
2006-02-28 02:39:52 +00:00
|
|
|
get_key_info(const cfg_obj_t *config, const cfg_obj_t *control,
|
|
|
|
const cfg_obj_t **global_keylistp,
|
|
|
|
const cfg_obj_t **control_keylistp) {
|
2001-08-04 07:38:06 +00:00
|
|
|
isc_result_t result;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *control_keylist = NULL;
|
|
|
|
const cfg_obj_t *global_keylist = NULL;
|
2001-05-31 10:36:05 +00:00
|
|
|
|
|
|
|
REQUIRE(global_keylistp != NULL && *global_keylistp == NULL);
|
|
|
|
REQUIRE(control_keylistp != NULL && *control_keylistp == NULL);
|
|
|
|
|
|
|
|
control_keylist = cfg_tuple_get(control, "keys");
|
|
|
|
|
2001-08-03 05:56:22 +00:00
|
|
|
if (!cfg_obj_isvoid(control_keylist) &&
|
2022-11-02 19:33:14 +01:00
|
|
|
cfg_list_first(control_keylist) != NULL)
|
|
|
|
{
|
2001-08-04 07:38:06 +00:00
|
|
|
result = cfg_map_get(config, "key", &global_keylist);
|
2001-05-31 10:36:05 +00:00
|
|
|
|
2001-08-04 07:38:06 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
*global_keylistp = global_keylist;
|
|
|
|
*control_keylistp = control_keylist;
|
|
|
|
}
|
|
|
|
}
|
2001-05-31 10:36:05 +00:00
|
|
|
}
|
|
|
|
|
2001-03-27 00:45:13 +00:00
|
|
|
static void
|
2017-09-08 13:39:09 -07:00
|
|
|
update_listener(named_controls_t *cp, controllistener_t **listenerp,
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *control, const cfg_obj_t *config,
|
|
|
|
isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
|
2020-04-16 13:06:42 -07:00
|
|
|
const char *socktext, isc_socktype_t type) {
|
2019-12-15 16:45:17 -08:00
|
|
|
controllistener_t *listener = NULL;
|
|
|
|
const cfg_obj_t *allow = NULL;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *global_keylist = NULL;
|
|
|
|
const cfg_obj_t *control_keylist = NULL;
|
2001-03-27 00:45:13 +00:00
|
|
|
dns_acl_t *new_acl = NULL;
|
|
|
|
controlkeylist_t keys;
|
2001-05-31 10:36:05 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2020-02-12 13:59:18 +01:00
|
|
|
|
2025-03-20 22:25:56 -07:00
|
|
|
ISC_LIST_FOREACH (cp->listeners, l, link) {
|
|
|
|
if (isc_sockaddr_equal(addr, &l->address)) {
|
|
|
|
listener = l;
|
2001-03-27 00:45:13 +00:00
|
|
|
break;
|
2020-02-13 18:16:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-27 00:45:13 +00:00
|
|
|
if (listener == NULL) {
|
|
|
|
*listenerp = NULL;
|
|
|
|
return;
|
|
|
|
}
|
2008-01-18 23:46:58 +00:00
|
|
|
|
2001-03-27 00:45:13 +00:00
|
|
|
/*
|
|
|
|
* There is already a listener for this sockaddr.
|
|
|
|
* Update the access list and key information.
|
|
|
|
*
|
2001-05-31 10:36:05 +00:00
|
|
|
* First try to deal with the key situation. There are a few
|
|
|
|
* possibilities:
|
|
|
|
* (a) It had an explicit keylist and still has an explicit keylist.
|
|
|
|
* (b) It had an automagic key and now has an explicit keylist.
|
|
|
|
* (c) It had an explicit keylist and now needs an automagic key.
|
|
|
|
* (d) It has an automagic key and still needs the automagic key.
|
|
|
|
*
|
|
|
|
* (c) and (d) are the annoying ones. The caller needs to know
|
|
|
|
* that it should use the automagic configuration for key information
|
|
|
|
* in place of the named.conf configuration.
|
|
|
|
*
|
|
|
|
* XXXDCL There is one other hazard that has not been dealt with,
|
|
|
|
* the problem that if a key change is being caused by a control
|
|
|
|
* channel reload, then the response will be with the new key
|
2001-08-03 18:03:02 +00:00
|
|
|
* and not able to be decrypted by the client.
|
2001-05-31 10:36:05 +00:00
|
|
|
*/
|
2001-08-04 07:49:38 +00:00
|
|
|
if (control != NULL) {
|
|
|
|
get_key_info(config, control, &global_keylist,
|
|
|
|
&control_keylist);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-05-31 10:36:05 +00:00
|
|
|
|
|
|
|
if (control_keylist != NULL) {
|
|
|
|
INSIST(global_keylist != NULL);
|
|
|
|
|
|
|
|
ISC_LIST_INIT(keys);
|
2019-07-23 14:56:24 -04:00
|
|
|
controlkeylist_fromcfg(control_keylist, listener->mctx, &keys);
|
|
|
|
free_controlkeylist(&listener->keys, listener->mctx);
|
|
|
|
listener->keys = keys;
|
|
|
|
register_keys(control, global_keylist, &listener->keys,
|
|
|
|
listener->mctx, socktext);
|
2001-08-03 05:56:22 +00:00
|
|
|
} else {
|
2001-05-31 10:36:05 +00:00
|
|
|
free_controlkeylist(&listener->keys, listener->mctx);
|
2001-08-03 05:56:22 +00:00
|
|
|
result = get_rndckey(listener->mctx, &listener->keys);
|
|
|
|
}
|
2001-05-31 10:36:05 +00:00
|
|
|
|
2005-11-30 03:36:45 +00:00
|
|
|
if (result != ISC_R_SUCCESS && global_keylist != NULL) {
|
2001-05-31 10:36:05 +00:00
|
|
|
/*
|
|
|
|
* This message might be a little misleading since the
|
|
|
|
* "new keys" might in fact be identical to the old ones,
|
|
|
|
* but tracking whether they are identical just for the
|
|
|
|
* sake of avoiding this message would be too much trouble.
|
|
|
|
*/
|
2005-11-30 03:33:49 +00:00
|
|
|
if (control != NULL) {
|
2024-08-13 18:20:26 +02:00
|
|
|
cfg_obj_log(control, ISC_LOG_WARNING,
|
2005-11-30 03:33:49 +00:00
|
|
|
"couldn't install new keys for "
|
|
|
|
"command channel %s: %s",
|
|
|
|
socktext, isc_result_totext(result));
|
|
|
|
} else {
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(NAMED_LOGCATEGORY_GENERAL,
|
2017-09-08 13:39:09 -07:00
|
|
|
NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
|
2005-11-30 03:33:49 +00:00
|
|
|
"couldn't install new keys for "
|
|
|
|
"command channel %s: %s",
|
|
|
|
socktext, isc_result_totext(result));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-11-30 03:36:45 +00:00
|
|
|
}
|
2001-05-31 10:36:05 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Now, keep the old access list unless a new one can be made.
|
2001-03-27 00:45:13 +00:00
|
|
|
*/
|
2020-04-16 13:06:42 -07:00
|
|
|
if (control != NULL && type == isc_socktype_tcp) {
|
2001-08-03 05:56:22 +00:00
|
|
|
allow = cfg_tuple_get(control, "allow");
|
2024-08-13 18:20:26 +02:00
|
|
|
result = cfg_acl_fromconfig(allow, config, aclconfctx,
|
|
|
|
listener->mctx, 0, &new_acl);
|
2001-08-03 05:56:22 +00:00
|
|
|
} else {
|
2001-08-03 18:28:48 +00:00
|
|
|
result = dns_acl_any(listener->mctx, &new_acl);
|
2001-08-03 05:56:22 +00:00
|
|
|
}
|
|
|
|
|
2015-11-11 13:29:38 +05:30
|
|
|
if (control != NULL) {
|
2019-12-15 16:45:17 -08:00
|
|
|
const cfg_obj_t *readonly = NULL;
|
2015-11-11 13:29:38 +05:30
|
|
|
|
|
|
|
readonly = cfg_tuple_get(control, "read-only");
|
|
|
|
if (!cfg_obj_isvoid(readonly)) {
|
|
|
|
listener->readonly = cfg_obj_asboolean(readonly);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2015-11-11 13:29:38 +05:30
|
|
|
}
|
|
|
|
|
2001-03-27 00:45:13 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
dns_acl_detach(&listener->acl);
|
|
|
|
dns_acl_attach(new_acl, &listener->acl);
|
|
|
|
dns_acl_detach(&new_acl);
|
|
|
|
/* XXXDCL say the old acl is still used? */
|
2005-11-30 03:33:49 +00:00
|
|
|
} else if (control != NULL) {
|
2024-08-13 18:20:26 +02:00
|
|
|
cfg_obj_log(control, ISC_LOG_WARNING,
|
2001-03-27 00:45:13 +00:00
|
|
|
"couldn't install new acl for "
|
|
|
|
"command channel %s: %s",
|
|
|
|
socktext, isc_result_totext(result));
|
2005-11-30 03:33:49 +00:00
|
|
|
} else {
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(NAMED_LOGCATEGORY_GENERAL,
|
2017-09-08 13:39:09 -07:00
|
|
|
NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
|
2005-11-30 03:33:49 +00:00
|
|
|
"couldn't install new acl for "
|
|
|
|
"command channel %s: %s",
|
|
|
|
socktext, isc_result_totext(result));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 00:45:13 +00:00
|
|
|
|
|
|
|
*listenerp = listener;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-09-08 13:39:09 -07:00
|
|
|
add_listener(named_controls_t *cp, controllistener_t **listenerp,
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *control, const cfg_obj_t *config,
|
|
|
|
isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
|
2020-04-16 13:06:42 -07:00
|
|
|
const char *socktext, isc_socktype_t type) {
|
2001-05-08 03:42:34 +00:00
|
|
|
isc_mem_t *mctx = cp->server->mctx;
|
2019-12-15 16:45:17 -08:00
|
|
|
controllistener_t *listener = NULL;
|
|
|
|
const cfg_obj_t *allow = NULL;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *global_keylist = NULL;
|
|
|
|
const cfg_obj_t *control_keylist = NULL;
|
2001-03-27 00:45:13 +00:00
|
|
|
dns_acl_t *new_acl = NULL;
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2020-04-16 13:06:42 -07:00
|
|
|
int pf;
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
/* Don't create new listener if we are shutting down */
|
|
|
|
if (cp->shuttingdown) {
|
|
|
|
result = ISC_R_SHUTTINGDOWN;
|
|
|
|
goto shuttingdown;
|
|
|
|
}
|
|
|
|
|
2001-03-27 00:45:13 +00:00
|
|
|
listener = isc_mem_get(mctx, sizeof(*listener));
|
2019-12-15 16:45:17 -08:00
|
|
|
*listener = (controllistener_t){ .controls = cp,
|
|
|
|
.address = *addr,
|
|
|
|
.type = type };
|
2020-06-23 13:02:21 +02:00
|
|
|
isc_mem_attach(mctx, &listener->mctx);
|
|
|
|
ISC_LINK_INIT(listener, link);
|
|
|
|
ISC_LIST_INIT(listener->keys);
|
|
|
|
ISC_LIST_INIT(listener->connections);
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
isc_refcount_init(&listener->references, 1);
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2020-06-23 13:02:21 +02:00
|
|
|
/*
|
2019-12-15 16:45:17 -08:00
|
|
|
* Make the ACL.
|
2020-06-23 13:02:21 +02:00
|
|
|
*/
|
2020-04-16 13:06:42 -07:00
|
|
|
if (control != NULL && type == isc_socktype_tcp) {
|
2019-12-15 16:45:17 -08:00
|
|
|
const cfg_obj_t *readonly = NULL;
|
2015-11-11 13:29:38 +05:30
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
allow = cfg_tuple_get(control, "allow");
|
2024-08-13 18:20:26 +02:00
|
|
|
CHECK(cfg_acl_fromconfig(allow, config, aclconfctx, mctx, 0,
|
|
|
|
&new_acl));
|
2020-04-16 13:06:42 -07:00
|
|
|
|
2015-11-11 13:29:38 +05:30
|
|
|
readonly = cfg_tuple_get(control, "read-only");
|
|
|
|
if (!cfg_obj_isvoid(readonly)) {
|
|
|
|
listener->readonly = cfg_obj_asboolean(readonly);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-04-16 13:06:42 -07:00
|
|
|
} else {
|
|
|
|
CHECK(dns_acl_any(mctx, &new_acl));
|
2015-11-11 13:29:38 +05:30
|
|
|
}
|
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
dns_acl_attach(new_acl, &listener->acl);
|
|
|
|
dns_acl_detach(&new_acl);
|
2001-05-31 10:36:05 +00:00
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
if (config != NULL) {
|
|
|
|
get_key_info(config, control, &global_keylist,
|
|
|
|
&control_keylist);
|
|
|
|
}
|
2001-08-03 05:56:22 +00:00
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
if (control_keylist != NULL) {
|
|
|
|
controlkeylist_fromcfg(control_keylist, listener->mctx,
|
|
|
|
&listener->keys);
|
|
|
|
register_keys(control, global_keylist, &listener->keys,
|
|
|
|
listener->mctx, socktext);
|
|
|
|
} else {
|
|
|
|
result = get_rndckey(mctx, &listener->keys);
|
2001-08-03 05:56:22 +00:00
|
|
|
if (result != ISC_R_SUCCESS && control != NULL) {
|
2024-08-13 18:20:26 +02:00
|
|
|
cfg_obj_log(control, ISC_LOG_WARNING,
|
2001-05-31 10:36:05 +00:00
|
|
|
"couldn't install keys for "
|
2001-03-27 00:45:13 +00:00
|
|
|
"command channel %s: %s",
|
|
|
|
socktext, isc_result_totext(result));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
pf = isc_sockaddr_pf(&listener->address);
|
|
|
|
if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
|
|
|
|
(pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
|
|
|
|
{
|
|
|
|
CHECK(ISC_R_FAMILYNOSUPPORT);
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2022-03-25 16:44:21 +01:00
|
|
|
CHECK(isc_nm_listentcp(named_g_netmgr, ISC_NM_LISTEN_ONE,
|
|
|
|
&listener->address, control_newconn, listener, 5,
|
|
|
|
NULL, &listener->sock));
|
2019-12-15 16:45:17 -08:00
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_CONTROL,
|
|
|
|
ISC_LOG_NOTICE, "command channel listening on %s",
|
|
|
|
socktext);
|
2020-04-16 13:06:42 -07:00
|
|
|
*listenerp = listener;
|
|
|
|
return;
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
cleanup:
|
Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra. Fix the
logic in the way:
1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
the handle, the read callback will be called with ISC_R_CANCELED to
cancel active reading from the socket/handle.
2. When isc_nm_read() has been called and isc_nm_read_stop() has been
called on the on the handle, the read callback will be called with
ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
is being shut down.
3. The .reading and .recv_read flags are little bit tricky. The
.reading flag indicates if the outer layer is reading the data (that
would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
the .recv_read flag indicates whether somebody is interested in the
data read from the socket.
Usually, you would expect that the .reading should be false when
.recv_read is false, but it gets even more tricky with TLSStream as
the TLS protocol might need to read from the socket even when sending
data.
Fix the usage of the .recv_read and .reading flags in the TLSStream
to their true meaning - which mostly consist of using .recv_read
everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
with the .reading flag.
4. The TLS failed read helper has been modified to resemble the TCP code
as much as possible, clearing and re-setting the .recv_read flag in
the TCP timeout code has been fixed and .recv_read is now cleared
when isc_nm_read_stop() has been called on the streaming socket.
5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
isc_httpd units have been greatly simplified due to the improved design.
6. More unit tests for TCP and TLS testing the shutdown conditions have
been added.
Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-13 17:27:50 +02:00
|
|
|
isc_refcount_decrement(&listener->references);
|
2023-11-06 20:19:20 +01:00
|
|
|
listener->shuttingdown = true;
|
2021-02-16 16:05:56 +11:00
|
|
|
free_listener(listener);
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
shuttingdown:
|
2020-04-16 13:06:42 -07:00
|
|
|
if (control != NULL) {
|
2024-08-13 18:20:26 +02:00
|
|
|
cfg_obj_log(control, ISC_LOG_WARNING,
|
2020-04-16 13:06:42 -07:00
|
|
|
"couldn't add command channel %s: %s", socktext,
|
|
|
|
isc_result_totext(result));
|
|
|
|
} else {
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(NAMED_LOGCATEGORY_GENERAL,
|
2017-09-08 13:39:09 -07:00
|
|
|
NAMED_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
|
2020-04-16 13:06:42 -07:00
|
|
|
"couldn't add command channel %s: %s", socktext,
|
|
|
|
isc_result_totext(result));
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2020-04-16 13:06:42 -07:00
|
|
|
*listenerp = NULL;
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2017-09-08 13:39:09 -07:00
|
|
|
named_controls_configure(named_controls_t *cp, const cfg_obj_t *config,
|
|
|
|
cfg_aclconfctx_t *aclconfctx) {
|
2019-12-15 16:45:17 -08:00
|
|
|
controllistener_t *listener = NULL;
|
2001-03-27 00:45:13 +00:00
|
|
|
controllistenerlist_t new_listeners;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *controlslist = NULL;
|
2001-03-27 00:45:13 +00:00
|
|
|
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
|
|
|
|
|
|
|
ISC_LIST_INIT(new_listeners);
|
|
|
|
|
|
|
|
/*
|
2001-05-07 21:57:25 +00:00
|
|
|
* Get the list of named.conf 'controls' statements.
|
2001-03-27 00:45:13 +00:00
|
|
|
*/
|
|
|
|
(void)cfg_map_get(config, "controls", &controlslist);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Run through the new control channel list, noting sockets that
|
|
|
|
* are already being listened on and moving them to the new list.
|
|
|
|
*
|
2001-05-07 21:57:25 +00:00
|
|
|
* Identifying duplicate addr/port combinations is left to either
|
2001-03-27 00:45:13 +00:00
|
|
|
* the underlying config code, or to the bind attempt getting an
|
|
|
|
* address-in-use error.
|
|
|
|
*/
|
|
|
|
if (controlslist != NULL) {
|
2025-03-26 18:54:05 -07:00
|
|
|
CFG_LIST_FOREACH (controlslist, element) {
|
2019-12-15 16:45:17 -08:00
|
|
|
const cfg_obj_t *controls = NULL;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *inetcontrols = NULL;
|
2023-09-12 08:39:12 +02:00
|
|
|
const cfg_obj_t *unixcontrols = NULL;
|
2001-03-27 00:45:13 +00:00
|
|
|
|
|
|
|
controls = cfg_listelt_value(element);
|
2023-09-12 08:39:12 +02:00
|
|
|
|
|
|
|
(void)cfg_map_get(controls, "unix", &unixcontrols);
|
|
|
|
if (unixcontrols != NULL) {
|
2024-08-13 18:20:26 +02:00
|
|
|
cfg_obj_log(controls, ISC_LOG_ERROR,
|
2023-09-12 08:39:12 +02:00
|
|
|
"UNIX domain sockets are not "
|
|
|
|
"supported");
|
|
|
|
return ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
2001-03-27 00:45:13 +00:00
|
|
|
(void)cfg_map_get(controls, "inet", &inetcontrols);
|
|
|
|
if (inetcontrols == NULL) {
|
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2025-03-26 18:54:05 -07:00
|
|
|
CFG_LIST_FOREACH (inetcontrols, element2) {
|
2019-12-15 16:45:17 -08:00
|
|
|
const cfg_obj_t *control = NULL;
|
|
|
|
const cfg_obj_t *obj = NULL;
|
2006-02-28 02:39:52 +00:00
|
|
|
isc_sockaddr_t addr;
|
2001-03-27 00:45:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The parser handles BIND 8 configuration file
|
2023-09-12 08:39:12 +02:00
|
|
|
* syntax, so it allows inet phrases with no
|
|
|
|
* keys{} clause.
|
2001-03-27 00:45:13 +00:00
|
|
|
*/
|
|
|
|
control = cfg_listelt_value(element2);
|
|
|
|
|
|
|
|
obj = cfg_tuple_get(control, "address");
|
2006-02-28 02:39:52 +00:00
|
|
|
addr = *cfg_obj_assockaddr(obj);
|
|
|
|
if (isc_sockaddr_getport(&addr) == 0) {
|
|
|
|
isc_sockaddr_setport(
|
2017-09-08 13:39:09 -07:00
|
|
|
&addr, NAMED_CONTROL_PORT);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2006-02-28 02:39:52 +00:00
|
|
|
isc_sockaddr_format(&addr, socktext,
|
2001-03-27 00:45:13 +00:00
|
|
|
sizeof(socktext));
|
|
|
|
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(NAMED_LOGCATEGORY_GENERAL,
|
2017-09-08 13:39:09 -07:00
|
|
|
NAMED_LOGMODULE_CONTROL,
|
2001-03-27 00:45:13 +00:00
|
|
|
ISC_LOG_DEBUG(9),
|
|
|
|
"processing control channel %s",
|
|
|
|
socktext);
|
|
|
|
|
2001-05-08 03:42:34 +00:00
|
|
|
update_listener(cp, &listener, control, config,
|
2006-02-28 02:39:52 +00:00
|
|
|
&addr, aclconfctx, socktext,
|
2020-04-16 13:06:42 -07:00
|
|
|
isc_socktype_tcp);
|
2001-03-27 00:45:13 +00:00
|
|
|
|
|
|
|
if (listener != NULL) {
|
|
|
|
/*
|
|
|
|
* Remove the listener from the old
|
|
|
|
* list, so it won't be shut down.
|
|
|
|
*/
|
2001-05-31 21:49:11 +00:00
|
|
|
ISC_LIST_UNLINK(cp->listeners, listener,
|
|
|
|
link);
|
2001-03-27 00:45:13 +00:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* This is a new listener.
|
|
|
|
*/
|
2001-05-31 10:36:05 +00:00
|
|
|
add_listener(cp, &listener, control,
|
2006-02-28 02:39:52 +00:00
|
|
|
config, &addr, aclconfctx,
|
2005-02-23 01:09:23 +00:00
|
|
|
socktext,
|
2020-04-16 13:06:42 -07:00
|
|
|
isc_socktype_tcp);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-23 01:09:23 +00:00
|
|
|
|
|
|
|
if (listener != NULL) {
|
|
|
|
ISC_LIST_APPEND(new_listeners, listener,
|
|
|
|
link);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-23 01:09:23 +00:00
|
|
|
}
|
|
|
|
}
|
2001-05-31 10:36:05 +00:00
|
|
|
} else {
|
2001-08-03 05:56:22 +00:00
|
|
|
int i;
|
|
|
|
|
2001-08-06 11:28:21 +00:00
|
|
|
for (i = 0; i < 2; i++) {
|
2001-08-03 05:56:22 +00:00
|
|
|
isc_sockaddr_t addr;
|
|
|
|
|
2001-08-06 01:03:53 +00:00
|
|
|
if (i == 0) {
|
2001-10-31 19:35:19 +00:00
|
|
|
struct in_addr localhost;
|
|
|
|
|
2001-08-03 05:56:22 +00:00
|
|
|
if (isc_net_probeipv4() != ISC_R_SUCCESS) {
|
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-10-31 19:35:19 +00:00
|
|
|
localhost.s_addr = htonl(INADDR_LOOPBACK);
|
|
|
|
isc_sockaddr_fromin(&addr, &localhost, 0);
|
2001-08-03 05:56:22 +00:00
|
|
|
} else {
|
|
|
|
if (isc_net_probeipv6() != ISC_R_SUCCESS) {
|
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-10-31 19:35:19 +00:00
|
|
|
isc_sockaddr_fromin6(&addr, &in6addr_loopback,
|
|
|
|
0);
|
2001-08-03 05:56:22 +00:00
|
|
|
}
|
2017-09-08 13:39:09 -07:00
|
|
|
isc_sockaddr_setport(&addr, NAMED_CONTROL_PORT);
|
2001-05-31 10:36:05 +00:00
|
|
|
|
2001-08-03 05:56:22 +00:00
|
|
|
isc_sockaddr_format(&addr, socktext, sizeof(socktext));
|
2008-01-18 23:46:58 +00:00
|
|
|
|
2001-08-03 05:56:22 +00:00
|
|
|
update_listener(cp, &listener, NULL, NULL, &addr, NULL,
|
2020-04-16 13:06:42 -07:00
|
|
|
socktext, isc_socktype_tcp);
|
2001-05-31 10:36:05 +00:00
|
|
|
|
2001-08-03 05:56:22 +00:00
|
|
|
if (listener != NULL) {
|
|
|
|
/*
|
|
|
|
* Remove the listener from the old
|
|
|
|
* list, so it won't be shut down.
|
|
|
|
*/
|
|
|
|
ISC_LIST_UNLINK(cp->listeners, listener, link);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* This is a new listener.
|
|
|
|
*/
|
|
|
|
add_listener(cp, &listener, NULL, NULL, &addr,
|
2020-04-16 13:06:42 -07:00
|
|
|
NULL, socktext, isc_socktype_tcp);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-03 05:56:22 +00:00
|
|
|
|
|
|
|
if (listener != NULL) {
|
|
|
|
ISC_LIST_APPEND(new_listeners, listener, link);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-03 05:56:22 +00:00
|
|
|
}
|
2001-03-27 00:45:13 +00:00
|
|
|
}
|
|
|
|
|
2001-08-03 05:56:22 +00:00
|
|
|
/*
|
2017-09-08 13:39:09 -07:00
|
|
|
* named_control_shutdown() will stop whatever is on the global
|
2001-08-03 05:56:22 +00:00
|
|
|
* listeners list, which currently only has whatever sockaddrs
|
|
|
|
* were in the previous configuration (if any) that do not
|
|
|
|
* remain in the current configuration.
|
|
|
|
*/
|
2001-09-21 03:04:14 +00:00
|
|
|
controls_shutdown(cp);
|
2001-08-03 05:56:22 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Put all of the valid listeners on the listeners list.
|
|
|
|
* Anything already on listeners in the process of shutting
|
|
|
|
* down will be taken care of by listen_done().
|
|
|
|
*/
|
|
|
|
ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link);
|
2001-05-08 03:42:34 +00:00
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
2001-03-27 00:45:13 +00:00
|
|
|
|
2001-05-08 03:42:34 +00:00
|
|
|
isc_result_t
|
2017-09-08 13:39:09 -07:00
|
|
|
named_controls_create(named_server_t *server, named_controls_t **ctrlsp) {
|
2001-05-08 03:42:34 +00:00
|
|
|
isc_mem_t *mctx = server->mctx;
|
2017-09-08 13:39:09 -07:00
|
|
|
named_controls_t *controls = isc_mem_get(mctx, sizeof(*controls));
|
2003-07-17 06:24:44 +00:00
|
|
|
|
2020-09-08 12:11:06 +10:00
|
|
|
*controls = (named_controls_t){
|
|
|
|
.server = server,
|
|
|
|
};
|
|
|
|
|
2001-05-08 03:42:34 +00:00
|
|
|
ISC_LIST_INIT(controls->listeners);
|
2020-09-08 12:11:06 +10:00
|
|
|
|
|
|
|
isc_mutex_init(&controls->symtab_lock);
|
|
|
|
LOCK(&controls->symtab_lock);
|
2024-11-29 10:02:13 +01:00
|
|
|
isccc_cc_createsymtab(mctx, &controls->symtab);
|
2020-09-08 12:11:06 +10:00
|
|
|
UNLOCK(&controls->symtab_lock);
|
|
|
|
|
2001-05-08 03:42:34 +00:00
|
|
|
*ctrlsp = controls;
|
2001-03-27 00:45:13 +00:00
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
2001-05-08 03:42:34 +00:00
|
|
|
|
|
|
|
void
|
2017-09-08 13:39:09 -07:00
|
|
|
named_controls_destroy(named_controls_t **ctrlsp) {
|
|
|
|
named_controls_t *controls = *ctrlsp;
|
2020-02-08 04:37:54 -08:00
|
|
|
*ctrlsp = NULL;
|
2001-05-08 03:42:34 +00:00
|
|
|
|
2023-11-06 20:19:20 +01:00
|
|
|
REQUIRE(controls->shuttingdown);
|
2001-05-08 03:42:34 +00:00
|
|
|
REQUIRE(ISC_LIST_EMPTY(controls->listeners));
|
|
|
|
|
2020-09-08 12:11:06 +10:00
|
|
|
LOCK(&controls->symtab_lock);
|
2024-11-29 10:02:13 +01:00
|
|
|
isc_symtab_destroy(&controls->symtab);
|
2020-09-08 12:11:06 +10:00
|
|
|
UNLOCK(&controls->symtab_lock);
|
|
|
|
isc_mutex_destroy(&controls->symtab_lock);
|
2001-05-08 03:42:34 +00:00
|
|
|
isc_mem_put(controls->server->mctx, controls, sizeof(*controls));
|
|
|
|
}
|