mirror of
https://github.com/isc-projects/bind9.git
synced 2026-02-24 10:21:10 -05:00
convert rndc and control channel to use netmgr
- updated libisccc to use netmgr events - updated rndc to use isc_nm_tcpconnect() to establish connections - updated control channel to use isc_nm_listentcp() open issues: - the control channel timeout was previously 60 seconds, but it is now overridden by the TCP idle timeout setting, which defaults to 30 seconds. we should add a function that sets the timeout value for a specific listener socket, instead of always using the global value set in the netmgr. (for the moment, since 30 seconds is a reasonable timeout for the control channel, I'm not prioritizing this.) - the netmgr currently has no support for UNIX-domain sockets; until this is addressed, it will not be possible to configure rndc to use them. we will need to either fix this or document the change in behavior.
This commit is contained in:
parent
002c328437
commit
3551d3ffd2
5 changed files with 430 additions and 522 deletions
|
|
@ -21,12 +21,12 @@
|
|||
#include <isc/mem.h>
|
||||
#include <isc/net.h>
|
||||
#include <isc/netaddr.h>
|
||||
#include <isc/netmgr.h>
|
||||
#include <isc/nonce.h>
|
||||
#include <isc/random.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/stdtime.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/timer.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/result.h>
|
||||
|
|
@ -49,12 +49,6 @@
|
|||
#include <named/log.h>
|
||||
#include <named/server.h>
|
||||
|
||||
/*
|
||||
* Note: Listeners and connections are not locked. All event handlers are
|
||||
* executed by the server task, and all callers of exported routines must
|
||||
* be running under the server task.
|
||||
*/
|
||||
|
||||
typedef struct controlkey controlkey_t;
|
||||
typedef ISC_LIST(controlkey_t) controlkeylist_t;
|
||||
|
||||
|
|
@ -72,11 +66,10 @@ struct controlkey {
|
|||
};
|
||||
|
||||
struct controlconnection {
|
||||
isc_socket_t *sock;
|
||||
isc_nmhandle_t *handle;
|
||||
isccc_ccmsg_t ccmsg;
|
||||
bool ccmsg_valid;
|
||||
bool sending;
|
||||
isc_timer_t *timer;
|
||||
isc_buffer_t *buffer;
|
||||
controllistener_t *listener;
|
||||
uint32_t nonce;
|
||||
|
|
@ -86,15 +79,14 @@ struct controlconnection {
|
|||
struct controllistener {
|
||||
named_controls_t *controls;
|
||||
isc_mem_t *mctx;
|
||||
isc_task_t *task;
|
||||
isc_sockaddr_t address;
|
||||
isc_socket_t *sock;
|
||||
isc_nmsocket_t *sock;
|
||||
dns_acl_t *acl;
|
||||
bool listening;
|
||||
bool exiting;
|
||||
controlkeylist_t keys;
|
||||
controlconnectionlist_t connections;
|
||||
isc_sockettype_t type;
|
||||
isc_socktype_t type;
|
||||
uint32_t perm;
|
||||
uint32_t owner;
|
||||
uint32_t group;
|
||||
|
|
@ -109,10 +101,10 @@ struct named_controls {
|
|||
isccc_symtab_t *symtab;
|
||||
};
|
||||
|
||||
static isc_result_t
|
||||
control_newconn(isc_nmhandle_t *handle, isc_result_t result, void *arg);
|
||||
static void
|
||||
control_newconn(isc_task_t *task, isc_event_t *event);
|
||||
static void
|
||||
control_recvmessage(isc_task_t *task, isc_event_t *event);
|
||||
control_recvmessage(isc_nmhandle_t *handle, isc_result_t result, void *arg);
|
||||
|
||||
#define CLOCKSKEW 300
|
||||
|
||||
|
|
@ -143,7 +135,7 @@ free_listener(controllistener_t *listener) {
|
|||
INSIST(ISC_LIST_EMPTY(listener->connections));
|
||||
|
||||
if (listener->sock != NULL) {
|
||||
isc_socket_detach(&listener->sock);
|
||||
isc_nmsocket_close(&listener->sock);
|
||||
}
|
||||
|
||||
free_controlkeylist(&listener->keys, listener->mctx);
|
||||
|
|
@ -164,43 +156,8 @@ maybe_free_listener(controllistener_t *listener) {
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_free_connection(controlconnection_t *conn) {
|
||||
controllistener_t *listener = conn->listener;
|
||||
|
||||
if (conn->buffer != NULL) {
|
||||
isc_buffer_free(&conn->buffer);
|
||||
}
|
||||
|
||||
if (conn->timer != NULL) {
|
||||
isc_timer_detach(&conn->timer);
|
||||
}
|
||||
|
||||
if (conn->ccmsg_valid) {
|
||||
isccc_ccmsg_cancelread(&conn->ccmsg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (conn->sending) {
|
||||
isc_socket_cancel(conn->sock, listener->task,
|
||||
ISC_SOCKCANCEL_SEND);
|
||||
return;
|
||||
}
|
||||
|
||||
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 */
|
||||
isc_mem_put(listener->mctx, conn, sizeof(*conn));
|
||||
}
|
||||
|
||||
static void
|
||||
shutdown_listener(controllistener_t *listener) {
|
||||
controlconnection_t *conn = NULL;
|
||||
controlconnection_t *next = NULL;
|
||||
|
||||
if (!listener->exiting) {
|
||||
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
||||
|
||||
|
|
@ -211,117 +168,77 @@ shutdown_listener(controllistener_t *listener) {
|
|||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
|
||||
"stopping command channel on %s", socktext);
|
||||
if (listener->type == isc_sockettype_unix) {
|
||||
#if 0
|
||||
/* XXX: no unix domain socket support */
|
||||
if (listener->type == isc_socktype_unix) {
|
||||
isc_socket_cleanunix(&listener->address, true);
|
||||
}
|
||||
#endif
|
||||
listener->exiting = true;
|
||||
listener->listening = false;
|
||||
}
|
||||
|
||||
for (conn = ISC_LIST_HEAD(listener->connections); conn != NULL;
|
||||
conn = next) {
|
||||
next = ISC_LIST_NEXT(conn, link);
|
||||
maybe_free_connection(conn);
|
||||
}
|
||||
|
||||
if (listener->listening) {
|
||||
isc_socket_cancel(listener->sock, listener->task,
|
||||
ISC_SOCKCANCEL_ACCEPT);
|
||||
return;
|
||||
}
|
||||
|
||||
isc_nm_stoplistening(listener->sock);
|
||||
maybe_free_listener(listener);
|
||||
}
|
||||
|
||||
static bool
|
||||
address_ok(isc_sockaddr_t *sockaddr, dns_acl_t *acl) {
|
||||
address_ok(isc_sockaddr_t *sockaddr, controllistener_t *listener) {
|
||||
dns_aclenv_t *env =
|
||||
ns_interfacemgr_getaclenv(named_g_server->interfacemgr);
|
||||
isc_netaddr_t netaddr;
|
||||
isc_result_t result;
|
||||
int match;
|
||||
|
||||
/* ACL doesn't apply to unix domain sockets */
|
||||
if (listener->type != isc_socktype_tcp) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
isc_netaddr_fromsockaddr(&netaddr, sockaddr);
|
||||
|
||||
result = dns_acl_match(&netaddr, NULL, acl, env, &match, NULL);
|
||||
result = dns_acl_match(&netaddr, NULL, listener->acl, env, &match,
|
||||
NULL);
|
||||
return (result == ISC_R_SUCCESS && match > 0);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
control_accept(controllistener_t *listener) {
|
||||
isc_result_t result;
|
||||
result = isc_socket_accept(listener->sock, listener->task,
|
||||
control_newconn, listener);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"isc_socket_accept() failed: %s",
|
||||
isc_result_totext(result));
|
||||
} else {
|
||||
listener->listening = true;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
control_listen(controllistener_t *listener) {
|
||||
isc_result_t result;
|
||||
|
||||
result = isc_socket_listen(listener->sock, 0);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"isc_socket_listen() failed: %s",
|
||||
isc_result_totext(result));
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
control_next(controllistener_t *listener) {
|
||||
(void)control_accept(listener);
|
||||
}
|
||||
|
||||
static void
|
||||
control_senddone(isc_task_t *task, isc_event_t *event) {
|
||||
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
|
||||
controlconnection_t *conn = event->ev_arg;
|
||||
control_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
controlconnection_t *conn = (controlconnection_t *)arg;
|
||||
controllistener_t *listener = conn->listener;
|
||||
isc_socket_t *sock = (isc_socket_t *)sevent->ev_sender;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(conn->sending);
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
conn->sending = false;
|
||||
|
||||
if (sevent->result != ISC_R_SUCCESS && sevent->result != ISC_R_CANCELED)
|
||||
{
|
||||
if (result == ISC_R_CANCELED) {
|
||||
return;
|
||||
} else if (result != ISC_R_SUCCESS) {
|
||||
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
||||
isc_sockaddr_t peeraddr;
|
||||
isc_sockaddr_t peeraddr = isc_nmhandle_peeraddr(handle);
|
||||
|
||||
(void)isc_socket_getpeername(sock, &peeraddr);
|
||||
isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
|
||||
"error sending command response to %s: %s",
|
||||
socktext, isc_result_totext(sevent->result));
|
||||
socktext, isc_result_totext(result));
|
||||
return;
|
||||
}
|
||||
isc_event_free(&event);
|
||||
|
||||
result = isccc_ccmsg_readmessage(&conn->ccmsg, listener->task,
|
||||
control_recvmessage, conn);
|
||||
result = isccc_ccmsg_readmessage(&conn->ccmsg, control_recvmessage,
|
||||
conn);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_socket_detach(&conn->sock);
|
||||
maybe_free_connection(conn);
|
||||
maybe_free_listener(listener);
|
||||
}
|
||||
|
||||
listener->listening = true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
log_invalid(isccc_ccmsg_t *ccmsg, isc_result_t result) {
|
||||
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
||||
isc_sockaddr_t peeraddr;
|
||||
isc_sockaddr_t peeraddr = isc_nmhandle_peeraddr(ccmsg->handle);
|
||||
|
||||
(void)isc_socket_getpeername(ccmsg->sock, &peeraddr);
|
||||
isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_CONTROL, ISC_LOG_ERROR,
|
||||
|
|
@ -330,8 +247,8 @@ log_invalid(isccc_ccmsg_t *ccmsg, isc_result_t result) {
|
|||
}
|
||||
|
||||
static void
|
||||
control_recvmessage(isc_task_t *task, isc_event_t *event) {
|
||||
controlconnection_t *conn = NULL;
|
||||
control_recvmessage(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
controlconnection_t *conn = (controlconnection_t *)arg;
|
||||
controllistener_t *listener = NULL;
|
||||
controlkey_t *key = NULL;
|
||||
isccc_sexpr_t *request = NULL;
|
||||
|
|
@ -342,7 +259,6 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
|
|||
isc_buffer_t b;
|
||||
isc_region_t r;
|
||||
isc_buffer_t *text = NULL;
|
||||
isc_result_t result;
|
||||
isc_result_t eresult;
|
||||
isccc_sexpr_t *_ctrl = NULL;
|
||||
isccc_time_t sent;
|
||||
|
|
@ -350,9 +266,6 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
|
|||
uint32_t nonce;
|
||||
isccc_sexpr_t *data = NULL;
|
||||
|
||||
REQUIRE(event->ev_type == ISCCC_EVENT_CCMSG);
|
||||
|
||||
conn = event->ev_arg;
|
||||
listener = conn->listener;
|
||||
algorithm = DST_ALG_UNKNOWN;
|
||||
secret.rstart = NULL;
|
||||
|
|
@ -363,23 +276,21 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
if (conn->ccmsg.result != ISC_R_SUCCESS) {
|
||||
if (conn->ccmsg.result != ISC_R_CANCELED &&
|
||||
conn->ccmsg.result != ISC_R_EOF) {
|
||||
log_invalid(&conn->ccmsg, conn->ccmsg.result);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (result != ISC_R_CANCELED && result != ISC_R_EOF) {
|
||||
log_invalid(&conn->ccmsg, result);
|
||||
}
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
request = NULL;
|
||||
|
||||
for (key = ISC_LIST_HEAD(listener->keys); key != NULL;
|
||||
key = ISC_LIST_NEXT(key, link))
|
||||
{
|
||||
isccc_region_t ccregion;
|
||||
|
||||
ccregion.rstart = isc_buffer_base(&conn->ccmsg.buffer);
|
||||
ccregion.rend = isc_buffer_used(&conn->ccmsg.buffer);
|
||||
ccregion.rstart = isc_buffer_base(conn->ccmsg.buffer);
|
||||
ccregion.rend = isc_buffer_used(conn->ccmsg.buffer);
|
||||
secret.rstart = isc_mem_get(listener->mctx, key->secret.length);
|
||||
memmove(secret.rstart, key->secret.base, key->secret.length);
|
||||
secret.rend = secret.rstart + key->secret.length;
|
||||
|
|
@ -529,7 +440,7 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) {
|
|||
r.base = conn->buffer->base;
|
||||
r.length = conn->buffer->used;
|
||||
|
||||
result = isc_socket_send(conn->sock, &r, task, control_senddone, conn);
|
||||
result = isc_nm_send(handle, &r, control_senddone, conn);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_response;
|
||||
}
|
||||
|
|
@ -552,57 +463,78 @@ cleanup_request:
|
|||
}
|
||||
|
||||
cleanup:
|
||||
isc_socket_detach(&conn->sock);
|
||||
isccc_ccmsg_invalidate(&conn->ccmsg);
|
||||
conn->ccmsg_valid = false;
|
||||
maybe_free_connection(conn);
|
||||
maybe_free_listener(listener);
|
||||
}
|
||||
|
||||
static void
|
||||
control_timeout(isc_task_t *task, isc_event_t *event) {
|
||||
controlconnection_t *conn = event->ev_arg;
|
||||
conn_reset(void *arg) {
|
||||
controlconnection_t *conn = (controlconnection_t *)arg;
|
||||
controllistener_t *listener = conn->listener;
|
||||
|
||||
UNUSED(task);
|
||||
if (conn->buffer != NULL) {
|
||||
isc_buffer_free(&conn->buffer);
|
||||
}
|
||||
|
||||
isc_timer_detach(&conn->timer);
|
||||
maybe_free_connection(conn);
|
||||
if (conn->ccmsg_valid) {
|
||||
isccc_ccmsg_cancelread(&conn->ccmsg);
|
||||
return;
|
||||
}
|
||||
|
||||
isc_event_free(&event);
|
||||
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 */
|
||||
|
||||
isccc_ccmsg_invalidate(&conn->ccmsg);
|
||||
}
|
||||
|
||||
static void
|
||||
conn_put(void *arg) {
|
||||
controlconnection_t *conn = (controlconnection_t *)arg;
|
||||
controllistener_t *listener = conn->listener;
|
||||
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_CONTROL, ISC_LOG_DEBUG(3),
|
||||
"freeing control connection");
|
||||
|
||||
maybe_free_listener(listener);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
newconnection(controllistener_t *listener, isc_socket_t *sock) {
|
||||
newconnection(controllistener_t *listener, isc_nmhandle_t *handle) {
|
||||
controlconnection_t *conn = NULL;
|
||||
isc_interval_t interval;
|
||||
isc_result_t result;
|
||||
|
||||
conn = isc_mem_get(listener->mctx, sizeof(*conn));
|
||||
conn = isc_nmhandle_getdata(handle);
|
||||
if (conn == NULL) {
|
||||
conn = isc_nmhandle_getextra(handle);
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_CONTROL, ISC_LOG_DEBUG(3),
|
||||
"allocate new control connection");
|
||||
*conn = (controlconnection_t){ .handle = NULL };
|
||||
}
|
||||
|
||||
conn->sock = sock;
|
||||
isccc_ccmsg_init(listener->mctx, sock, &conn->ccmsg);
|
||||
if (conn->handle == NULL) {
|
||||
isc_nmhandle_setdata(handle, conn, conn_reset, conn_put);
|
||||
} else {
|
||||
INSIST(conn->handle == handle);
|
||||
}
|
||||
|
||||
*conn = (controlconnection_t){ .handle = handle,
|
||||
.listener = listener,
|
||||
.ccmsg_valid = true };
|
||||
|
||||
isccc_ccmsg_init(listener->mctx, handle, &conn->ccmsg);
|
||||
|
||||
/* Set a 32 KiB upper limit on incoming message. */
|
||||
isccc_ccmsg_setmaxsize(&conn->ccmsg, 32768);
|
||||
|
||||
conn->ccmsg_valid = true;
|
||||
conn->sending = false;
|
||||
conn->buffer = NULL;
|
||||
conn->timer = NULL;
|
||||
isc_interval_set(&interval, 60, 0);
|
||||
result = isc_timer_create(named_g_timermgr, isc_timertype_once, NULL,
|
||||
&interval, listener->task, control_timeout,
|
||||
conn, &conn->timer);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
conn->listener = listener;
|
||||
conn->nonce = 0;
|
||||
ISC_LINK_INIT(conn, link);
|
||||
|
||||
result = isccc_ccmsg_readmessage(&conn->ccmsg, listener->task,
|
||||
control_recvmessage, conn);
|
||||
result = isccc_ccmsg_readmessage(&conn->ccmsg, control_recvmessage,
|
||||
conn);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
@ -614,10 +546,9 @@ cleanup:
|
|||
if (conn->buffer != NULL) {
|
||||
isc_buffer_free(&conn->buffer);
|
||||
}
|
||||
|
||||
isccc_ccmsg_invalidate(&conn->ccmsg);
|
||||
if (conn->timer != NULL) {
|
||||
isc_timer_detach(&conn->timer);
|
||||
}
|
||||
|
||||
isc_mem_put(listener->mctx, conn, sizeof(*conn));
|
||||
#ifdef ENABLE_AFL
|
||||
if (named_g_fuzz_type == isc_fuzz_rndc) {
|
||||
|
|
@ -627,53 +558,32 @@ cleanup:
|
|||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
control_newconn(isc_task_t *task, isc_event_t *event) {
|
||||
isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
|
||||
controllistener_t *listener = event->ev_arg;
|
||||
isc_socket_t *sock = NULL;
|
||||
static isc_result_t
|
||||
control_newconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
controllistener_t *listener = arg;
|
||||
isc_sockaddr_t peeraddr;
|
||||
isc_result_t result;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
REQUIRE(listener->listening);
|
||||
|
||||
listener->listening = false;
|
||||
|
||||
if (nevent->result != ISC_R_SUCCESS) {
|
||||
if (nevent->result == ISC_R_CANCELED) {
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (result == ISC_R_CANCELED) {
|
||||
shutdown_listener(listener);
|
||||
goto cleanup;
|
||||
}
|
||||
goto restart;
|
||||
return (result);
|
||||
}
|
||||
|
||||
sock = nevent->newsocket;
|
||||
|
||||
/* Is the server shutting down? */
|
||||
if (listener->controls->shuttingdown) {
|
||||
isc_socket_detach(&sock);
|
||||
shutdown_listener(listener);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
isc_socket_setname(sock, "control", NULL);
|
||||
(void)isc_socket_getpeername(sock, &peeraddr);
|
||||
if (listener->type == isc_sockettype_tcp &&
|
||||
!address_ok(&peeraddr, listener->acl))
|
||||
{
|
||||
peeraddr = isc_nmhandle_peeraddr(handle);
|
||||
if (!address_ok(&peeraddr, listener)) {
|
||||
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
||||
isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
|
||||
"rejected command channel message from %s",
|
||||
socktext);
|
||||
isc_socket_detach(&sock);
|
||||
goto restart;
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
result = newconnection(listener, sock);
|
||||
result = newconnection(listener, handle);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
||||
isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
|
||||
|
|
@ -681,14 +591,10 @@ control_newconn(isc_task_t *task, isc_event_t *event) {
|
|||
NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
|
||||
"dropped command channel from %s: %s", socktext,
|
||||
isc_result_totext(result));
|
||||
isc_socket_detach(&sock);
|
||||
goto restart;
|
||||
return (result);
|
||||
}
|
||||
|
||||
restart:
|
||||
control_next(listener);
|
||||
cleanup:
|
||||
isc_event_free(&event);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -968,7 +874,7 @@ static void
|
|||
update_listener(named_controls_t *cp, controllistener_t **listenerp,
|
||||
const cfg_obj_t *control, const cfg_obj_t *config,
|
||||
isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
|
||||
const char *socktext, isc_sockettype_t type) {
|
||||
const char *socktext, isc_socktype_t type) {
|
||||
controllistener_t *listener = NULL;
|
||||
const cfg_obj_t *allow = NULL;
|
||||
const cfg_obj_t *global_keylist = NULL;
|
||||
|
|
@ -1053,7 +959,7 @@ update_listener(named_controls_t *cp, controllistener_t **listenerp,
|
|||
/*
|
||||
* Now, keep the old access list unless a new one can be made.
|
||||
*/
|
||||
if (control != NULL && type == isc_sockettype_tcp) {
|
||||
if (control != NULL && type == isc_socktype_tcp) {
|
||||
allow = cfg_tuple_get(control, "allow");
|
||||
result = cfg_acl_fromconfig(allow, config, named_g_lctx,
|
||||
aclconfctx, listener->mctx, 0,
|
||||
|
|
@ -1089,7 +995,7 @@ update_listener(named_controls_t *cp, controllistener_t **listenerp,
|
|||
socktext, isc_result_totext(result));
|
||||
}
|
||||
|
||||
if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) {
|
||||
if (result == ISC_R_SUCCESS && type == isc_socktype_unix) {
|
||||
uint32_t perm, owner, group;
|
||||
perm = cfg_obj_asuint32(cfg_tuple_get(control, "perm"));
|
||||
owner = cfg_obj_asuint32(cfg_tuple_get(control, "owner"));
|
||||
|
|
@ -1120,7 +1026,7 @@ static void
|
|||
add_listener(named_controls_t *cp, controllistener_t **listenerp,
|
||||
const cfg_obj_t *control, const cfg_obj_t *config,
|
||||
isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
|
||||
const char *socktext, isc_sockettype_t type) {
|
||||
const char *socktext, isc_socktype_t type) {
|
||||
isc_mem_t *mctx = cp->server->mctx;
|
||||
controllistener_t *listener = NULL;
|
||||
const cfg_obj_t *allow = NULL;
|
||||
|
|
@ -1128,10 +1034,10 @@ add_listener(named_controls_t *cp, controllistener_t **listenerp,
|
|||
const cfg_obj_t *control_keylist = NULL;
|
||||
dns_acl_t *new_acl = NULL;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
int pf;
|
||||
|
||||
listener = isc_mem_get(mctx, sizeof(*listener));
|
||||
*listener = (controllistener_t){ .controls = cp,
|
||||
.task = cp->server->task,
|
||||
.address = *addr,
|
||||
.type = type };
|
||||
isc_mem_attach(mctx, &listener->mctx);
|
||||
|
|
@ -1142,41 +1048,36 @@ add_listener(named_controls_t *cp, controllistener_t **listenerp,
|
|||
/*
|
||||
* Make the ACL.
|
||||
*/
|
||||
if (control != NULL && type == isc_sockettype_tcp) {
|
||||
allow = cfg_tuple_get(control, "allow");
|
||||
result = cfg_acl_fromconfig(allow, config, named_g_lctx,
|
||||
aclconfctx, mctx, 0, &new_acl);
|
||||
} else {
|
||||
result = dns_acl_any(mctx, &new_acl);
|
||||
}
|
||||
|
||||
if (result == ISC_R_SUCCESS && control != NULL) {
|
||||
if (control != NULL && type == isc_socktype_tcp) {
|
||||
const cfg_obj_t *readonly = NULL;
|
||||
|
||||
allow = cfg_tuple_get(control, "allow");
|
||||
CHECK(cfg_acl_fromconfig(allow, config, named_g_lctx,
|
||||
aclconfctx, mctx, 0, &new_acl));
|
||||
|
||||
readonly = cfg_tuple_get(control, "read-only");
|
||||
if (!cfg_obj_isvoid(readonly)) {
|
||||
listener->readonly = cfg_obj_asboolean(readonly);
|
||||
}
|
||||
} else {
|
||||
CHECK(dns_acl_any(mctx, &new_acl));
|
||||
}
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
dns_acl_attach(new_acl, &listener->acl);
|
||||
dns_acl_detach(&new_acl);
|
||||
dns_acl_attach(new_acl, &listener->acl);
|
||||
dns_acl_detach(&new_acl);
|
||||
|
||||
if (config != NULL) {
|
||||
get_key_info(config, control, &global_keylist,
|
||||
&control_keylist);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
if (config != NULL) {
|
||||
get_key_info(config, control, &global_keylist,
|
||||
&control_keylist);
|
||||
}
|
||||
|
||||
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);
|
||||
if (result != ISC_R_SUCCESS && control != NULL) {
|
||||
cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING,
|
||||
"couldn't install keys for "
|
||||
|
|
@ -1185,43 +1086,31 @@ add_listener(named_controls_t *cp, controllistener_t **listenerp,
|
|||
}
|
||||
}
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
int pf = isc_sockaddr_pf(&listener->address);
|
||||
if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
|
||||
pf = isc_sockaddr_pf(&listener->address);
|
||||
if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
|
||||
#ifndef _WIN32
|
||||
(pf == AF_UNIX && isc_net_probeunix() != ISC_R_SUCCESS) ||
|
||||
#endif
|
||||
(pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
|
||||
{
|
||||
result = ISC_R_FAMILYNOSUPPORT;
|
||||
}
|
||||
(pf == AF_UNIX && isc_net_probeunix() != ISC_R_SUCCESS) ||
|
||||
#endif /* ifdef _WIN32 */
|
||||
(pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
|
||||
{
|
||||
CHECK(ISC_R_FAMILYNOSUPPORT);
|
||||
}
|
||||
|
||||
if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) {
|
||||
#if 0
|
||||
/* XXX: no unix socket support yet */
|
||||
if (type == isc_socktype_unix) {
|
||||
isc_socket_cleanunix(&listener->address, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
result = isc_socket_create(named_g_socketmgr,
|
||||
isc_sockaddr_pf(&listener->address),
|
||||
type, &listener->sock);
|
||||
}
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
isc_socket_setname(listener->sock, "control", NULL);
|
||||
}
|
||||
|
||||
#ifndef ISC_ALLOW_MAPPED
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
isc_socket_ipv6only(listener->sock, true);
|
||||
}
|
||||
#endif /* ifndef ISC_ALLOW_MAPPED */
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
result = isc_socket_bind(listener->sock, &listener->address,
|
||||
ISC_SOCKET_REUSEADDRESS);
|
||||
}
|
||||
|
||||
if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) {
|
||||
CHECK(isc_nm_listentcp(named_g_nm, (isc_nmiface_t *)&listener->address,
|
||||
control_newconn, listener,
|
||||
sizeof(controlconnection_t), 5, NULL,
|
||||
&listener->sock));
|
||||
listener->listening = true;
|
||||
#if 0
|
||||
/* XXX: no unix socket support yet */
|
||||
if (type == isc_socktype_unix) {
|
||||
listener->perm =
|
||||
cfg_obj_asuint32(cfg_tuple_get(control, "perm"));
|
||||
listener->owner =
|
||||
|
|
@ -1231,38 +1120,33 @@ add_listener(named_controls_t *cp, controllistener_t **listenerp,
|
|||
result = isc_socket_permunix(&listener->address, listener->perm,
|
||||
listener->owner, listener->group);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
result = control_listen(listener);
|
||||
}
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
|
||||
"command channel listening on %s", socktext);
|
||||
*listenerp = listener;
|
||||
return;
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
result = control_accept(listener);
|
||||
}
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
|
||||
"command channel listening on %s", socktext);
|
||||
*listenerp = listener;
|
||||
} else {
|
||||
cleanup:
|
||||
if (listener != NULL) {
|
||||
listener->exiting = true;
|
||||
free_listener(listener);
|
||||
|
||||
if (control != NULL) {
|
||||
cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING,
|
||||
"couldn't add command channel %s: %s",
|
||||
socktext, isc_result_totext(result));
|
||||
} else {
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
|
||||
"couldn't add command channel %s: %s",
|
||||
socktext, isc_result_totext(result));
|
||||
}
|
||||
|
||||
*listenerp = NULL;
|
||||
}
|
||||
|
||||
if (control != NULL) {
|
||||
cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING,
|
||||
"couldn't add command channel %s: %s", socktext,
|
||||
isc_result_totext(result));
|
||||
} else {
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
|
||||
"couldn't add command channel %s: %s", socktext,
|
||||
isc_result_totext(result));
|
||||
}
|
||||
|
||||
*listenerp = NULL;
|
||||
|
||||
/* XXXDCL return error results? fail hard? */
|
||||
}
|
||||
|
||||
|
|
@ -1337,7 +1221,7 @@ named_controls_configure(named_controls_t *cp, const cfg_obj_t *config,
|
|||
|
||||
update_listener(cp, &listener, control, config,
|
||||
&addr, aclconfctx, socktext,
|
||||
isc_sockettype_tcp);
|
||||
isc_socktype_tcp);
|
||||
|
||||
if (listener != NULL) {
|
||||
/*
|
||||
|
|
@ -1353,7 +1237,7 @@ named_controls_configure(named_controls_t *cp, const cfg_obj_t *config,
|
|||
add_listener(cp, &listener, control,
|
||||
config, &addr, aclconfctx,
|
||||
socktext,
|
||||
isc_sockettype_tcp);
|
||||
isc_socktype_tcp);
|
||||
}
|
||||
|
||||
if (listener != NULL) {
|
||||
|
|
@ -1374,6 +1258,12 @@ named_controls_configure(named_controls_t *cp, const cfg_obj_t *config,
|
|||
continue;
|
||||
}
|
||||
|
||||
cfg_obj_log(controls, named_g_lctx, ISC_LOG_ERROR,
|
||||
"UNIX domain sockets not yet supported");
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
#if 0
|
||||
/* XXX: no unix domain socket support in netmgr */
|
||||
for (element2 = cfg_list_first(unixcontrols);
|
||||
element2 != NULL;
|
||||
element2 = cfg_list_next(element2))
|
||||
|
|
@ -1415,7 +1305,7 @@ named_controls_configure(named_controls_t *cp, const cfg_obj_t *config,
|
|||
update_listener(cp, &listener, control, config,
|
||||
&addr, aclconfctx,
|
||||
cfg_obj_asstring(path),
|
||||
isc_sockettype_unix);
|
||||
isc_socktype_unix);
|
||||
|
||||
if (listener != NULL) {
|
||||
/*
|
||||
|
|
@ -1431,7 +1321,7 @@ named_controls_configure(named_controls_t *cp, const cfg_obj_t *config,
|
|||
add_listener(cp, &listener, control,
|
||||
config, &addr, aclconfctx,
|
||||
cfg_obj_asstring(path),
|
||||
isc_sockettype_unix);
|
||||
isc_socktype_unix);
|
||||
}
|
||||
|
||||
if (listener != NULL) {
|
||||
|
|
@ -1439,6 +1329,7 @@ named_controls_configure(named_controls_t *cp, const cfg_obj_t *config,
|
|||
link);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
int i;
|
||||
|
|
@ -1466,7 +1357,7 @@ named_controls_configure(named_controls_t *cp, const cfg_obj_t *config,
|
|||
isc_sockaddr_format(&addr, socktext, sizeof(socktext));
|
||||
|
||||
update_listener(cp, &listener, NULL, NULL, &addr, NULL,
|
||||
socktext, isc_sockettype_tcp);
|
||||
socktext, isc_socktype_tcp);
|
||||
|
||||
if (listener != NULL) {
|
||||
/*
|
||||
|
|
@ -1479,8 +1370,7 @@ named_controls_configure(named_controls_t *cp, const cfg_obj_t *config,
|
|||
* This is a new listener.
|
||||
*/
|
||||
add_listener(cp, &listener, NULL, NULL, &addr,
|
||||
NULL, socktext,
|
||||
isc_sockettype_tcp);
|
||||
NULL, socktext, isc_socktype_tcp);
|
||||
}
|
||||
|
||||
if (listener != NULL) {
|
||||
|
|
|
|||
230
bin/rndc/rndc.c
230
bin/rndc/rndc.c
|
|
@ -58,6 +58,9 @@
|
|||
const char *progname = NULL;
|
||||
bool verbose;
|
||||
|
||||
static isc_taskmgr_t *taskmgr = NULL;
|
||||
static isc_task_t *rndc_task = NULL;
|
||||
|
||||
static const char *admin_conffile = NULL;
|
||||
static const char *admin_keyfile = NULL;
|
||||
static const char *version = PACKAGE_VERSION;
|
||||
|
|
@ -68,9 +71,9 @@ static bool local4set = false, local6set = false;
|
|||
static int nserveraddrs;
|
||||
static int currentaddr = 0;
|
||||
static unsigned int remoteport = 0;
|
||||
static isc_socketmgr_t *socketmgr = NULL;
|
||||
static isc_nm_t *netmgr = NULL;
|
||||
static isc_buffer_t *databuf = NULL;
|
||||
static isccc_ccmsg_t ccmsg;
|
||||
static isccc_ccmsg_t rndc_ccmsg;
|
||||
static uint32_t algorithm;
|
||||
static isccc_region_t secret;
|
||||
static bool failed = false;
|
||||
|
|
@ -82,13 +85,13 @@ static atomic_uint_fast32_t connects = ATOMIC_VAR_INIT(0);
|
|||
static char *command = NULL;
|
||||
static char *args = NULL;
|
||||
static char program[256];
|
||||
static isc_socket_t *sock = NULL;
|
||||
static uint32_t serial;
|
||||
static bool quiet = false;
|
||||
static bool showresult = false;
|
||||
static bool shuttingdown = false;
|
||||
|
||||
static void
|
||||
rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task);
|
||||
rndc_startconnect(isc_sockaddr_t *addr);
|
||||
|
||||
ISC_NORETURN static void
|
||||
usage(int status);
|
||||
|
|
@ -278,51 +281,54 @@ get_addresses(const char *host, in_port_t port) {
|
|||
}
|
||||
|
||||
static void
|
||||
rndc_senddone(isc_task_t *task, isc_event_t *event) {
|
||||
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
|
||||
rndc_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
UNUSED(arg);
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
if (sevent->result != ISC_R_SUCCESS) {
|
||||
fatal("send failed: %s", isc_result_totext(sevent->result));
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("send failed: %s", isc_result_totext(result));
|
||||
}
|
||||
isc_event_free(&event);
|
||||
|
||||
if (atomic_fetch_sub_release(&sends, 1) == 1 &&
|
||||
atomic_load_acquire(&recvs) == 0)
|
||||
{
|
||||
isc_socket_detach(&sock);
|
||||
isc_task_shutdown(task);
|
||||
shuttingdown = true;
|
||||
isc_task_shutdown(rndc_task);
|
||||
isc_app_shutdown();
|
||||
isc_nmhandle_unref(handle);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rndc_recvdone(isc_task_t *task, isc_event_t *event) {
|
||||
rndc_recvdone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
isccc_ccmsg_t *ccmsg = (isccc_ccmsg_t *)arg;
|
||||
isccc_sexpr_t *response = NULL;
|
||||
isccc_sexpr_t *data;
|
||||
isccc_region_t source;
|
||||
char *errormsg = NULL;
|
||||
char *textmsg = NULL;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(ccmsg != NULL);
|
||||
|
||||
atomic_fetch_sub_release(&recvs, 1);
|
||||
|
||||
if (ccmsg.result == ISC_R_EOF) {
|
||||
fatal("connection to remote host closed\n"
|
||||
"This may indicate that\n"
|
||||
"* the remote server is using an older version of"
|
||||
" the command protocol,\n"
|
||||
if (shuttingdown && (result == ISC_R_EOF || result == ISC_R_CANCELED)) {
|
||||
isc_nmhandle_unref(handle);
|
||||
return;
|
||||
} else if (result == ISC_R_EOF) {
|
||||
fatal("connection to remote host closed.\n"
|
||||
"* This may indicate that the\n"
|
||||
"* remote server is using an older\n"
|
||||
"* version of the command protocol,\n"
|
||||
"* this host is not authorized to connect,\n"
|
||||
"* the clocks are not synchronized, or\n"
|
||||
"* the key is invalid.");
|
||||
"* the clocks are not synchronized,\n"
|
||||
"* the key signing algorithm is incorrect,\n"
|
||||
"* or the key is invalid.");
|
||||
} else if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
|
||||
fatal("recv failed: %s", isc_result_totext(result));
|
||||
}
|
||||
|
||||
if (ccmsg.result != ISC_R_SUCCESS) {
|
||||
fatal("recv failed: %s", isc_result_totext(ccmsg.result));
|
||||
}
|
||||
|
||||
source.rstart = isc_buffer_base(&ccmsg.buffer);
|
||||
source.rend = isc_buffer_used(&ccmsg.buffer);
|
||||
source.rstart = isc_buffer_base(ccmsg->buffer);
|
||||
source.rend = isc_buffer_used(ccmsg->buffer);
|
||||
|
||||
DO("parse message",
|
||||
isccc_cc_fromwire(&source, &response, algorithm, &secret));
|
||||
|
|
@ -362,22 +368,23 @@ rndc_recvdone(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
}
|
||||
|
||||
isc_event_free(&event);
|
||||
isccc_sexpr_free(&response);
|
||||
|
||||
if (atomic_load_acquire(&sends) == 0 &&
|
||||
atomic_load_acquire(&recvs) == 0) {
|
||||
isc_socket_detach(&sock);
|
||||
isc_task_shutdown(task);
|
||||
shuttingdown = true;
|
||||
isc_task_shutdown(rndc_task);
|
||||
isc_app_shutdown();
|
||||
isc_nmhandle_unref(handle);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rndc_recvnonce(isc_task_t *task, isc_event_t *event) {
|
||||
rndc_recvnonce(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
isccc_ccmsg_t *ccmsg = (isccc_ccmsg_t *)arg;
|
||||
isccc_sexpr_t *response = NULL;
|
||||
isccc_sexpr_t *_ctrl;
|
||||
isccc_region_t source;
|
||||
isc_result_t result;
|
||||
uint32_t nonce;
|
||||
isccc_sexpr_t *request = NULL;
|
||||
isccc_time_t now;
|
||||
|
|
@ -385,25 +392,28 @@ rndc_recvnonce(isc_task_t *task, isc_event_t *event) {
|
|||
isccc_sexpr_t *data;
|
||||
isc_buffer_t b;
|
||||
|
||||
REQUIRE(ccmsg != NULL);
|
||||
|
||||
atomic_fetch_sub_release(&recvs, 1);
|
||||
|
||||
if (ccmsg.result == ISC_R_EOF) {
|
||||
fatal("connection to remote host closed\n"
|
||||
"This may indicate that\n"
|
||||
"* the remote server is using an older version of"
|
||||
" the command protocol,\n"
|
||||
if (shuttingdown && result == ISC_R_EOF) {
|
||||
isc_nmhandle_unref(handle);
|
||||
return;
|
||||
} else if (result == ISC_R_EOF) {
|
||||
fatal("connection to remote host closed.\n"
|
||||
"* This may indicate that the\n"
|
||||
"* remote server is using an older\n"
|
||||
"* version of the command protocol,\n"
|
||||
"* this host is not authorized to connect,\n"
|
||||
"* the clocks are not synchronized,\n"
|
||||
"* the key signing algorithm is incorrect, or\n"
|
||||
"* the key is invalid.");
|
||||
"* the key signing algorithm is incorrect\n"
|
||||
"* or the key is invalid.");
|
||||
} else if (result != ISC_R_SUCCESS) {
|
||||
fatal("recv failed: %s", isc_result_totext(result));
|
||||
}
|
||||
|
||||
if (ccmsg.result != ISC_R_SUCCESS) {
|
||||
fatal("recv failed: %s", isc_result_totext(ccmsg.result));
|
||||
}
|
||||
|
||||
source.rstart = isc_buffer_base(&ccmsg.buffer);
|
||||
source.rend = isc_buffer_used(&ccmsg.buffer);
|
||||
source.rstart = isc_buffer_base(ccmsg->buffer);
|
||||
source.rend = isc_buffer_used(ccmsg->buffer);
|
||||
|
||||
DO("parse message",
|
||||
isccc_cc_fromwire(&source, &response, algorithm, &secret));
|
||||
|
|
@ -451,48 +461,44 @@ rndc_recvnonce(isc_task_t *task, isc_event_t *event) {
|
|||
r.base = databuf->base;
|
||||
r.length = databuf->used;
|
||||
|
||||
isccc_ccmsg_cancelread(&ccmsg);
|
||||
DO("schedule recv",
|
||||
isccc_ccmsg_readmessage(&ccmsg, task, rndc_recvdone, NULL));
|
||||
isccc_ccmsg_readmessage(ccmsg, rndc_recvdone, ccmsg));
|
||||
atomic_fetch_add_relaxed(&recvs, 1);
|
||||
DO("send message",
|
||||
isc_socket_send(sock, &r, task, rndc_senddone, NULL));
|
||||
|
||||
DO("send message", isc_nm_send(handle, &r, rndc_senddone, NULL));
|
||||
atomic_fetch_add_relaxed(&sends, 1);
|
||||
|
||||
isc_event_free(&event);
|
||||
isccc_sexpr_free(&response);
|
||||
isccc_sexpr_free(&request);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
rndc_connected(isc_task_t *task, isc_event_t *event) {
|
||||
rndc_connected(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
isccc_ccmsg_t *ccmsg = (isccc_ccmsg_t *)arg;
|
||||
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
||||
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
|
||||
isccc_sexpr_t *request = NULL;
|
||||
isccc_sexpr_t *data;
|
||||
isccc_time_t now;
|
||||
isc_region_t r;
|
||||
isc_buffer_t b;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(ccmsg != NULL);
|
||||
|
||||
atomic_fetch_sub_release(&connects, 1);
|
||||
|
||||
if (sevent->result != ISC_R_SUCCESS) {
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_sockaddr_format(&serveraddrs[currentaddr], socktext,
|
||||
sizeof(socktext));
|
||||
if (sevent->result != ISC_R_CANCELED &&
|
||||
++currentaddr < nserveraddrs) {
|
||||
if (++currentaddr < nserveraddrs) {
|
||||
notify("connection failed: %s: %s", socktext,
|
||||
isc_result_totext(sevent->result));
|
||||
isc_socket_detach(&sock);
|
||||
isc_event_free(&event);
|
||||
rndc_startconnect(&serveraddrs[currentaddr], task);
|
||||
isc_result_totext(result));
|
||||
rndc_startconnect(&serveraddrs[currentaddr]);
|
||||
return;
|
||||
} else {
|
||||
fatal("connect failed: %s: %s", socktext,
|
||||
isc_result_totext(sevent->result));
|
||||
}
|
||||
|
||||
fatal("connect failed: %s: %s", socktext,
|
||||
isc_result_totext(result));
|
||||
}
|
||||
|
||||
isc_stdtime_get(&now);
|
||||
|
|
@ -519,50 +525,52 @@ rndc_connected(isc_task_t *task, isc_event_t *event) {
|
|||
r.base = databuf->base;
|
||||
r.length = databuf->used;
|
||||
|
||||
isccc_ccmsg_init(rndc_mctx, sock, &ccmsg);
|
||||
isccc_ccmsg_setmaxsize(&ccmsg, 1024 * 1024);
|
||||
isccc_ccmsg_init(rndc_mctx, handle, ccmsg);
|
||||
isccc_ccmsg_setmaxsize(ccmsg, 1024 * 1024);
|
||||
|
||||
isc_nmhandle_ref(handle);
|
||||
|
||||
DO("schedule recv",
|
||||
isccc_ccmsg_readmessage(&ccmsg, task, rndc_recvnonce, NULL));
|
||||
isccc_ccmsg_readmessage(ccmsg, rndc_recvnonce, ccmsg));
|
||||
atomic_fetch_add_relaxed(&recvs, 1);
|
||||
DO("send message",
|
||||
isc_socket_send(sock, &r, task, rndc_senddone, NULL));
|
||||
|
||||
DO("send message", isc_nm_send(handle, &r, rndc_senddone, NULL));
|
||||
atomic_fetch_add_relaxed(&sends, 1);
|
||||
isc_event_free(&event);
|
||||
|
||||
isccc_sexpr_free(&request);
|
||||
}
|
||||
|
||||
static void
|
||||
rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task) {
|
||||
rndc_startconnect(isc_sockaddr_t *addr) {
|
||||
isc_result_t result;
|
||||
int pf;
|
||||
isc_sockettype_t type;
|
||||
|
||||
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
||||
isc_sockaddr_t *local = NULL;
|
||||
|
||||
isc_sockaddr_format(addr, socktext, sizeof(socktext));
|
||||
|
||||
notify("using server %s (%s)", servername, socktext);
|
||||
|
||||
pf = isc_sockaddr_pf(addr);
|
||||
if (pf == AF_INET || pf == AF_INET6) {
|
||||
type = isc_sockettype_tcp;
|
||||
} else {
|
||||
type = isc_sockettype_unix;
|
||||
}
|
||||
DO("create socket", isc_socket_create(socketmgr, pf, type, &sock));
|
||||
switch (isc_sockaddr_pf(addr)) {
|
||||
case AF_INET:
|
||||
DO("bind socket", isc_socket_bind(sock, &local4, 0));
|
||||
local = &local4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
DO("bind socket", isc_socket_bind(sock, &local6, 0));
|
||||
local = &local6;
|
||||
break;
|
||||
case AF_UNIX:
|
||||
/*
|
||||
* TODO: support UNIX domain sockets in netgmr.
|
||||
*/
|
||||
fatal("UNIX domain sockets not currently supported");
|
||||
default:
|
||||
break;
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
}
|
||||
DO("connect",
|
||||
isc_socket_connect(sock, addr, task, rndc_connected, NULL));
|
||||
|
||||
DO("create connection",
|
||||
isc_nm_tcpconnect(netmgr, (isc_nmiface_t *)local,
|
||||
(isc_nmiface_t *)addr, rndc_connected, &rndc_ccmsg,
|
||||
0));
|
||||
atomic_fetch_add_relaxed(&connects, 1);
|
||||
}
|
||||
|
||||
|
|
@ -570,8 +578,10 @@ static void
|
|||
rndc_start(isc_task_t *task, isc_event_t *event) {
|
||||
isc_event_free(&event);
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
currentaddr = 0;
|
||||
rndc_startconnect(&serveraddrs[currentaddr], task);
|
||||
rndc_startconnect(&serveraddrs[currentaddr]);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -853,8 +863,6 @@ int
|
|||
main(int argc, char **argv) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
bool show_final_mem = false;
|
||||
isc_taskmgr_t *taskmgr = NULL;
|
||||
isc_task_t *task = NULL;
|
||||
isc_log_t *log = NULL;
|
||||
isc_logconfig_t *logconfig = NULL;
|
||||
isc_logdestination_t logdest;
|
||||
|
|
@ -980,18 +988,23 @@ main(int argc, char **argv) {
|
|||
argc -= isc_commandline_index;
|
||||
argv += isc_commandline_index;
|
||||
|
||||
if (argc < 1) {
|
||||
if (argv[0] == NULL) {
|
||||
usage(1);
|
||||
} else {
|
||||
command = argv[0];
|
||||
if (strcmp(command, "restart") == 0) {
|
||||
fatal("'%s' is not implemented", command);
|
||||
}
|
||||
notify("%s", command);
|
||||
}
|
||||
|
||||
serial = isc_random32();
|
||||
|
||||
isc_mem_create(&rndc_mctx);
|
||||
DO("create socket manager",
|
||||
isc_socketmgr_create(rndc_mctx, &socketmgr));
|
||||
netmgr = isc_nm_start(rndc_mctx, 1);
|
||||
DO("create task manager",
|
||||
isc_taskmgr_create(rndc_mctx, 1, 0, NULL, &taskmgr));
|
||||
DO("create task", isc_task_create(taskmgr, 0, &task));
|
||||
DO("create task", isc_task_create(taskmgr, 0, &rndc_task));
|
||||
isc_log_create(rndc_mctx, &log, &logconfig);
|
||||
isc_log_setcontext(log);
|
||||
isc_log_settag(logconfig, progname);
|
||||
|
|
@ -1009,8 +1022,6 @@ main(int argc, char **argv) {
|
|||
|
||||
isccc_result_register();
|
||||
|
||||
command = *argv;
|
||||
|
||||
isc_buffer_allocate(rndc_mctx, &databuf, 2048);
|
||||
|
||||
/*
|
||||
|
|
@ -1037,32 +1048,30 @@ main(int argc, char **argv) {
|
|||
*p++ = '\0';
|
||||
INSIST(p == args + argslen);
|
||||
|
||||
notify("%s", command);
|
||||
|
||||
if (strcmp(command, "restart") == 0) {
|
||||
fatal("'%s' is not implemented", command);
|
||||
}
|
||||
|
||||
if (nserveraddrs == 0 && servername != NULL) {
|
||||
get_addresses(servername, (in_port_t)remoteport);
|
||||
}
|
||||
|
||||
DO("post event", isc_app_onrun(rndc_mctx, task, rndc_start, NULL));
|
||||
DO("post event", isc_app_onrun(rndc_mctx, rndc_task, rndc_start, NULL));
|
||||
|
||||
result = isc_app_run();
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("isc_app_run() failed: %s", isc_result_totext(result));
|
||||
}
|
||||
|
||||
if (atomic_load_acquire(&connects) > 0 ||
|
||||
atomic_load_acquire(&sends) > 0 || atomic_load_acquire(&recvs) > 0)
|
||||
{
|
||||
isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL);
|
||||
}
|
||||
|
||||
isc_task_detach(&task);
|
||||
isc_task_detach(&rndc_task);
|
||||
isc_taskmgr_destroy(&taskmgr);
|
||||
isc_socketmgr_destroy(&socketmgr);
|
||||
|
||||
isc_nm_destroy(&netmgr);
|
||||
|
||||
/*
|
||||
* Note: when TCP connections are shut down, there will be a final
|
||||
* call to the isccc callback routine with &rndc_ccmsg as its
|
||||
* argument. We therefore need to delay invalidating it until
|
||||
* after the netmgr is destroyed.
|
||||
*/
|
||||
isccc_ccmsg_invalidate(&rndc_ccmsg);
|
||||
|
||||
isc_log_destroy(&log);
|
||||
isc_log_setcontext(NULL);
|
||||
|
||||
|
|
@ -1070,7 +1079,6 @@ main(int argc, char **argv) {
|
|||
cfg_parser_destroy(&pctx);
|
||||
|
||||
isc_mem_put(rndc_mctx, args, argslen);
|
||||
isccc_ccmsg_invalidate(&ccmsg);
|
||||
|
||||
isc_buffer_free(&databuf);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.sp
|
||||
\fBdnssec\-importkey\fP reads a public DNSKEY record and generates a pair
|
||||
of .key/.private files. The DNSKEY record may be read from an existing
|
||||
.key file, in which case a corresponding .private file is
|
||||
\&.key file, in which case a corresponding .private file is
|
||||
generated, or it may be read from any other file or from the standard
|
||||
input, in which case both .key and .private files are generated.
|
||||
.sp
|
||||
|
|
|
|||
|
|
@ -28,8 +28,9 @@
|
|||
#include <inttypes.h>
|
||||
|
||||
#include <isc/mem.h>
|
||||
#include <isc/netmgr.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/task.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <isccc/ccmsg.h>
|
||||
|
|
@ -39,109 +40,140 @@
|
|||
#define VALID_CCMSG(foo) ISC_MAGIC_VALID(foo, CCMSG_MAGIC)
|
||||
|
||||
static void
|
||||
recv_length(isc_task_t *, isc_event_t *);
|
||||
static void
|
||||
recv_message(isc_task_t *, isc_event_t *);
|
||||
recv_message(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
||||
void *arg);
|
||||
|
||||
static void
|
||||
recv_length(isc_task_t *task, isc_event_t *ev_in) {
|
||||
isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
|
||||
isc_event_t *dev = NULL;
|
||||
isccc_ccmsg_t *ccmsg = ev_in->ev_arg;
|
||||
isc_region_t region;
|
||||
recv_nonce(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
||||
void *arg) {
|
||||
isccc_ccmsg_t *ccmsg = arg;
|
||||
isc_result_t result;
|
||||
|
||||
if (eresult == ISC_R_CANCELED || eresult == ISC_R_EOF) {
|
||||
ccmsg->result = eresult;
|
||||
goto done;
|
||||
}
|
||||
|
||||
INSIST(VALID_CCMSG(ccmsg));
|
||||
|
||||
dev = &ccmsg->event;
|
||||
|
||||
if (ev->result != ISC_R_SUCCESS) {
|
||||
ccmsg->result = ev->result;
|
||||
goto send_and_free;
|
||||
if (region == NULL && eresult == ISC_R_SUCCESS) {
|
||||
ccmsg->result = ISC_R_EOF;
|
||||
goto done;
|
||||
} else if (eresult != ISC_R_SUCCESS) {
|
||||
ccmsg->result = eresult;
|
||||
goto done;
|
||||
} else {
|
||||
ccmsg->result = eresult;
|
||||
}
|
||||
|
||||
/*
|
||||
* Success.
|
||||
*/
|
||||
ccmsg->size = ntohl(ccmsg->size);
|
||||
if (region->length < sizeof(uint32_t)) {
|
||||
ccmsg->result = ISC_R_UNEXPECTEDEND;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ccmsg->size = ntohl(*(uint32_t *)region->base);
|
||||
if (ccmsg->size == 0) {
|
||||
ccmsg->result = ISC_R_UNEXPECTEDEND;
|
||||
goto send_and_free;
|
||||
goto done;
|
||||
}
|
||||
if (ccmsg->size > ccmsg->maxsize) {
|
||||
ccmsg->result = ISC_R_RANGE;
|
||||
goto send_and_free;
|
||||
goto done;
|
||||
}
|
||||
|
||||
region.base = isc_mem_get(ccmsg->mctx, ccmsg->size);
|
||||
region.length = ccmsg->size;
|
||||
if (region.base == NULL) {
|
||||
ccmsg->result = ISC_R_NOMEMORY;
|
||||
goto send_and_free;
|
||||
isc_region_consume(region, sizeof(uint32_t));
|
||||
isc_buffer_allocate(ccmsg->mctx, &ccmsg->buffer, ccmsg->size);
|
||||
|
||||
/*
|
||||
* If there's more of the message waiting, pass it to
|
||||
* recv_message() directly.
|
||||
*/
|
||||
if (region->length != 0) {
|
||||
recv_message(handle, ISC_R_SUCCESS, region, ccmsg);
|
||||
return;
|
||||
}
|
||||
|
||||
isc_buffer_init(&ccmsg->buffer, region.base, region.length);
|
||||
result = isc_socket_recv(ccmsg->sock, ®ion, 0, task, recv_message,
|
||||
ccmsg);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ccmsg->result = result;
|
||||
goto send_and_free;
|
||||
/*
|
||||
* Otherwise, continue reading and handle it in
|
||||
* recv_message().
|
||||
*/
|
||||
result = isc_nm_read(handle, recv_message, ccmsg);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
isc_event_free(&ev_in);
|
||||
return;
|
||||
ccmsg->result = result;
|
||||
|
||||
send_and_free:
|
||||
isc_task_send(ccmsg->task, &dev);
|
||||
ccmsg->task = NULL;
|
||||
isc_event_free(&ev_in);
|
||||
return;
|
||||
done:
|
||||
ccmsg->cb(handle, ccmsg->result, ccmsg->cbarg);
|
||||
isc_nmhandle_unref(handle);
|
||||
}
|
||||
|
||||
static void
|
||||
recv_message(isc_task_t *task, isc_event_t *ev_in) {
|
||||
isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
|
||||
isc_event_t *dev = NULL;
|
||||
isccc_ccmsg_t *ccmsg = ev_in->ev_arg;
|
||||
recv_message(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
||||
void *arg) {
|
||||
isc_result_t result;
|
||||
isccc_ccmsg_t *ccmsg = arg;
|
||||
size_t size;
|
||||
|
||||
UNUSED(task);
|
||||
if (eresult == ISC_R_CANCELED || eresult == ISC_R_EOF) {
|
||||
ccmsg->result = eresult;
|
||||
goto done;
|
||||
}
|
||||
|
||||
INSIST(VALID_CCMSG(ccmsg));
|
||||
|
||||
dev = &ccmsg->event;
|
||||
|
||||
if (ev->result != ISC_R_SUCCESS) {
|
||||
ccmsg->result = ev->result;
|
||||
goto send_and_free;
|
||||
if (region == NULL && eresult == ISC_R_SUCCESS) {
|
||||
ccmsg->result = ISC_R_EOF;
|
||||
goto done;
|
||||
} else if (eresult != ISC_R_SUCCESS) {
|
||||
ccmsg->result = eresult;
|
||||
goto done;
|
||||
} else {
|
||||
ccmsg->result = eresult;
|
||||
}
|
||||
|
||||
ccmsg->result = ISC_R_SUCCESS;
|
||||
isc_buffer_add(&ccmsg->buffer, ev->n);
|
||||
ccmsg->address = ev->address;
|
||||
if (region->length == 0) {
|
||||
ccmsg->result = ISC_R_UNEXPECTEDEND;
|
||||
goto done;
|
||||
}
|
||||
|
||||
send_and_free:
|
||||
isc_task_send(ccmsg->task, &dev);
|
||||
ccmsg->task = NULL;
|
||||
isc_event_free(&ev_in);
|
||||
size = ISC_MIN(isc_buffer_availablelength(ccmsg->buffer),
|
||||
region->length);
|
||||
isc_buffer_putmem(ccmsg->buffer, region->base, size);
|
||||
isc_region_consume(region, size);
|
||||
|
||||
if (isc_buffer_usedlength(ccmsg->buffer) == ccmsg->size) {
|
||||
ccmsg->result = ISC_R_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = isc_nm_read(handle, recv_message, ccmsg);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
ccmsg->result = result;
|
||||
|
||||
done:
|
||||
ccmsg->cb(handle, ccmsg->result, ccmsg->cbarg);
|
||||
isc_nmhandle_unref(handle);
|
||||
}
|
||||
|
||||
void
|
||||
isccc_ccmsg_init(isc_mem_t *mctx, isc_socket_t *sock, isccc_ccmsg_t *ccmsg) {
|
||||
isccc_ccmsg_init(isc_mem_t *mctx, isc_nmhandle_t *handle,
|
||||
isccc_ccmsg_t *ccmsg) {
|
||||
REQUIRE(mctx != NULL);
|
||||
REQUIRE(sock != NULL);
|
||||
REQUIRE(handle != NULL);
|
||||
REQUIRE(ccmsg != NULL);
|
||||
|
||||
*ccmsg = (isccc_ccmsg_t){
|
||||
.magic = CCMSG_MAGIC,
|
||||
.maxsize = 0xffffffffU, /* Largest message possible. */
|
||||
.mctx = mctx,
|
||||
.sock = sock,
|
||||
.handle = handle,
|
||||
.result = ISC_R_UNEXPECTED /* None yet. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Should probably initialize the event here, but it can wait.
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -152,37 +184,23 @@ isccc_ccmsg_setmaxsize(isccc_ccmsg_t *ccmsg, unsigned int maxsize) {
|
|||
}
|
||||
|
||||
isc_result_t
|
||||
isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg, isc_task_t *task,
|
||||
isc_taskaction_t action, void *arg) {
|
||||
isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg, isc_nm_cb_t cb, void *cbarg) {
|
||||
isc_result_t result;
|
||||
isc_region_t region;
|
||||
|
||||
REQUIRE(VALID_CCMSG(ccmsg));
|
||||
REQUIRE(task != NULL);
|
||||
REQUIRE(ccmsg->task == NULL); /* not currently in use */
|
||||
|
||||
if (ccmsg->buffer.base != NULL) {
|
||||
isc_mem_put(ccmsg->mctx, ccmsg->buffer.base,
|
||||
ccmsg->buffer.length);
|
||||
ccmsg->buffer.base = NULL;
|
||||
ccmsg->buffer.length = 0;
|
||||
if (ccmsg->buffer != NULL) {
|
||||
isc_buffer_free(&ccmsg->buffer);
|
||||
}
|
||||
|
||||
ccmsg->task = task;
|
||||
ccmsg->action = action;
|
||||
ccmsg->arg = arg;
|
||||
ccmsg->cb = cb;
|
||||
ccmsg->cbarg = cbarg;
|
||||
ccmsg->result = ISC_R_UNEXPECTED; /* unknown right now */
|
||||
|
||||
ISC_EVENT_INIT(&ccmsg->event, sizeof(isc_event_t), 0, 0,
|
||||
ISCCC_EVENT_CCMSG, action, arg, ccmsg, NULL, NULL);
|
||||
|
||||
region.base = (unsigned char *)&ccmsg->size;
|
||||
region.length = 4; /* uint32_t */
|
||||
result = isc_socket_recv(ccmsg->sock, ®ion, 0, ccmsg->task,
|
||||
recv_length, ccmsg);
|
||||
|
||||
isc_nmhandle_ref(ccmsg->handle);
|
||||
result = isc_nm_read(ccmsg->handle, recv_nonce, ccmsg);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ccmsg->task = NULL;
|
||||
isc_nmhandle_unref(ccmsg->handle);
|
||||
}
|
||||
|
||||
return (result);
|
||||
|
|
@ -192,7 +210,7 @@ void
|
|||
isccc_ccmsg_cancelread(isccc_ccmsg_t *ccmsg) {
|
||||
REQUIRE(VALID_CCMSG(ccmsg));
|
||||
|
||||
isc_socket_cancel(ccmsg->sock, NULL, ISC_SOCKCANCEL_RECV);
|
||||
isc_nm_cancelread(ccmsg->handle);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -201,10 +219,7 @@ isccc_ccmsg_invalidate(isccc_ccmsg_t *ccmsg) {
|
|||
|
||||
ccmsg->magic = 0;
|
||||
|
||||
if (ccmsg->buffer.base != NULL) {
|
||||
isc_mem_put(ccmsg->mctx, ccmsg->buffer.base,
|
||||
ccmsg->buffer.length);
|
||||
ccmsg->buffer.base = NULL;
|
||||
ccmsg->buffer.length = 0;
|
||||
if (ccmsg->buffer != NULL) {
|
||||
isc_buffer_free(&ccmsg->buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,39 +32,37 @@
|
|||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/lang.h>
|
||||
#include <isc/socket.h>
|
||||
#include <isc/netmgr.h>
|
||||
#include <isc/sockaddr.h>
|
||||
|
||||
/*% ISCCC Message Structure */
|
||||
typedef struct isccc_ccmsg {
|
||||
/* private (don't touch!) */
|
||||
unsigned int magic;
|
||||
uint32_t size;
|
||||
isc_buffer_t buffer;
|
||||
unsigned int maxsize;
|
||||
isc_mem_t * mctx;
|
||||
isc_socket_t * sock;
|
||||
isc_task_t * task;
|
||||
isc_taskaction_t action;
|
||||
void * arg;
|
||||
isc_event_t event;
|
||||
unsigned int magic;
|
||||
uint32_t size;
|
||||
isc_buffer_t * buffer;
|
||||
unsigned int maxsize;
|
||||
isc_mem_t * mctx;
|
||||
isc_nmhandle_t *handle;
|
||||
isc_nm_cb_t cb;
|
||||
void * cbarg;
|
||||
/* public (read-only) */
|
||||
isc_result_t result;
|
||||
isc_sockaddr_t address;
|
||||
isc_result_t result;
|
||||
} isccc_ccmsg_t;
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
void
|
||||
isccc_ccmsg_init(isc_mem_t *mctx, isc_socket_t *sock, isccc_ccmsg_t *ccmsg);
|
||||
isccc_ccmsg_init(isc_mem_t *mctx, isc_nmhandle_t *handle, isccc_ccmsg_t *ccmsg);
|
||||
/*%
|
||||
* Associate a cc message state with a given memory context and
|
||||
* TCP socket.
|
||||
* netmgr handle.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li "mctx" and "sock" be non-NULL and valid types.
|
||||
*\li "mctx" be a valid memory context.
|
||||
*
|
||||
*\li "sock" be a read/write TCP socket.
|
||||
*\li "handle" be a netmgr handle for a stream socket.
|
||||
*
|
||||
*\li "ccmsg" be non-NULL and an uninitialized or invalidated structure.
|
||||
*
|
||||
|
|
@ -86,8 +84,7 @@ isccc_ccmsg_setmaxsize(isccc_ccmsg_t *ccmsg, unsigned int maxsize);
|
|||
*/
|
||||
|
||||
isc_result_t
|
||||
isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg, isc_task_t *task,
|
||||
isc_taskaction_t action, void *arg);
|
||||
isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg, isc_nm_cb_t cb, void *cbarg);
|
||||
/*%
|
||||
* Schedule an event to be delivered when a command channel message is
|
||||
* readable, or when an error occurs on the socket.
|
||||
|
|
@ -96,12 +93,10 @@ isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg, isc_task_t *task,
|
|||
*
|
||||
*\li "ccmsg" be valid.
|
||||
*
|
||||
*\li "task", "taskaction", and "arg" be valid.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
*\li #ISC_R_SUCCESS -- no error
|
||||
*\li Anything that the isc_socket_recv() call can return. XXXMLG
|
||||
*\li Anything that the isc_nm_read() call can return.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in a new issue