Merge branch 'each-rndc-netmgr-pt2' into 'main'

RNDC using netmgr

See merge request isc-projects/bind9!3724
This commit is contained in:
Evan Hunt 2020-07-13 20:39:49 +00:00
commit d97710acdc
13 changed files with 753 additions and 837 deletions

12
CHANGES
View file

@ -1,3 +1,15 @@
5467. [func] The control channel and the rndc utility have been
updated to use the new network manager. To support
this, the network manager was updated to enable
wthe initiation of client TCP connections. Its
internal reference counting has been refactored.
Note: As side effects of this change, rndc cannot
currently be used with UNIX-domain sockets, and its
default timeout has changed from 60 seconds to 30.
These will be addressed in a future release.
[GL #1759]
5466. [bug] Addressed an error in recursive clients stats reporting.
[GL #1719]

File diff suppressed because it is too large Load diff

View file

@ -38,6 +38,7 @@
#define NAMED_EVENTCLASS ISC_EVENTCLASS(0x4E43)
#define NAMED_EVENT_RELOAD (NAMED_EVENTCLASS + 0)
#define NAMED_EVENT_DELZONE (NAMED_EVENTCLASS + 1)
#define NAMED_EVENT_COMMAND (NAMED_EVENTCLASS + 2)
/*%
* Name server state. Better here than in lots of separate global variables.
@ -80,8 +81,6 @@ struct named_server {
uint32_t interface_interval;
uint32_t heartbeat_interval;
isc_mutex_t reload_event_lock;
isc_event_t * reload_event;
named_reload_t reload_status;
bool flushonshutdown;

View file

@ -9936,14 +9936,6 @@ named_server_create(isc_mem_t *mctx, named_server_t **serverp) {
&server->in_roothints),
"setting up root hints");
isc_mutex_init(&server->reload_event_lock);
server->reload_event = isc_event_allocate(
named_g_mctx, server, NAMED_EVENT_RELOAD, named_server_reload,
server, sizeof(isc_event_t));
CHECKFATAL(server->reload_event == NULL ? ISC_R_NOMEMORY
: ISC_R_SUCCESS,
"allocating reload event");
server->reload_status = NAMED_RELOAD_IN_PROGRESS;
/*
@ -10113,9 +10105,6 @@ named_server_destroy(named_server_t **serverp) {
dst_lib_destroy();
isc_event_free(&server->reload_event);
isc_mutex_destroy(&server->reload_event_lock);
INSIST(ISC_LIST_EMPTY(server->kasplist));
INSIST(ISC_LIST_EMPTY(server->viewlist));
INSIST(ISC_LIST_EMPTY(server->cachelist));
@ -10293,7 +10282,7 @@ cleanup:
*/
static void
named_server_reload(isc_task_t *task, isc_event_t *event) {
named_server_t *server = (named_server_t *)event->ev_arg;
named_server_t *server = (named_server_t *)event->ev_sender;
INSIST(task == server->task);
UNUSED(task);
@ -10303,19 +10292,15 @@ named_server_reload(isc_task_t *task, isc_event_t *event) {
"received SIGHUP signal to reload zones");
(void)reload(server);
LOCK(&server->reload_event_lock);
INSIST(server->reload_event == NULL);
server->reload_event = event;
UNLOCK(&server->reload_event_lock);
isc_event_free(&event);
}
void
named_server_reloadwanted(named_server_t *server) {
LOCK(&server->reload_event_lock);
if (server->reload_event != NULL) {
isc_task_send(server->task, &server->reload_event);
}
UNLOCK(&server->reload_event_lock);
isc_event_t *event = isc_event_allocate(
named_g_mctx, server, NAMED_EVENT_RELOAD, named_server_reload,
NULL, sizeof(isc_event_t));
isc_task_send(server->task, &event);
}
void
@ -12086,12 +12071,10 @@ cleanup:
isc_result_t
named_server_tsiglist(named_server_t *server, isc_buffer_t **text) {
isc_result_t result;
isc_result_t result = ISC_R_SUCCESS;
dns_view_t *view;
unsigned int foundkeys = 0;
result = isc_task_beginexclusive(server->task);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
view = ISC_LIST_NEXT(view, link))
{
@ -12100,7 +12083,6 @@ named_server_tsiglist(named_server_t *server, isc_buffer_t **text) {
&foundkeys);
RWUNLOCK(&view->statickeys->lock, isc_rwlocktype_read);
if (result != ISC_R_SUCCESS) {
isc_task_endexclusive(server->task);
return (result);
}
RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
@ -12108,11 +12090,9 @@ named_server_tsiglist(named_server_t *server, isc_buffer_t **text) {
&foundkeys);
RWUNLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
if (result != ISC_R_SUCCESS) {
isc_task_endexclusive(server->task);
return (result);
}
}
isc_task_endexclusive(server->task);
if (foundkeys == 0) {
CHECK(putstr(text, "no tsig keys found."));
@ -14161,7 +14141,6 @@ named_server_showzone(named_server_t *server, isc_lex_t *lex,
dns_view_t *view = NULL;
dns_zone_t *zone = NULL;
ns_cfgctx_t *cfg = NULL;
bool exclusive = false;
#ifdef HAVE_LMDB
cfg_obj_t *nzconfig = NULL;
#endif /* HAVE_LMDB */
@ -14186,10 +14165,6 @@ named_server_showzone(named_server_t *server, isc_lex_t *lex,
goto cleanup;
}
result = isc_task_beginexclusive(server->task);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
exclusive = true;
if (!added) {
/* Find the view statement */
vconfig = find_name_in_list_from_map(cfg->config, "view",
@ -14248,9 +14223,6 @@ cleanup:
if (isc_buffer_usedlength(*text) > 0) {
(void)putnull(text);
}
if (exclusive) {
isc_task_endexclusive(server->task);
}
return (result);
}

View file

@ -55,11 +55,14 @@
#define SERVERADDRS 10
const char *progname;
const char *progname = NULL;
bool verbose;
static const char *admin_conffile;
static const char *admin_keyfile;
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;
static const char *servername = NULL;
static isc_sockaddr_t serveraddrs[SERVERADDRS];
@ -68,27 +71,27 @@ 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_buffer_t *databuf;
static isccc_ccmsg_t ccmsg;
static isc_nm_t *netmgr = NULL;
static isc_buffer_t *databuf = NULL;
static isccc_ccmsg_t rndc_ccmsg;
static uint32_t algorithm;
static isccc_region_t secret;
static bool failed = false;
static bool c_flag = false;
static isc_mem_t *rndc_mctx;
static isc_mem_t *rndc_mctx = NULL;
static atomic_uint_fast32_t sends = ATOMIC_VAR_INIT(0);
static atomic_uint_fast32_t recvs = ATOMIC_VAR_INIT(0);
static atomic_uint_fast32_t connects = ATOMIC_VAR_INIT(0);
static char *command;
static char *args;
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);
@ -114,7 +117,7 @@ command is one of the following:\n\
Close, rename and re-open the DNSTAP output file(s).\n\
dumpdb [-all|-cache|-zones|-adb|-bad|-fail] [view ...]\n\
Dump cache(s) to the dump file (named_dump.db).\n\
flush Flushes all of the server's caches.\n\
flush Flushes all of the server's caches.\n\
flush [view] Flushes the server's cache for a view.\n\
flushname name [view]\n\
Flush the given name from the server's cache(s)\n\
@ -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_nmhandle_unref(handle);
isc_task_shutdown(rndc_task);
isc_app_shutdown();
}
}
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
@ -652,7 +662,7 @@ parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname,
if (servers != NULL) {
for (elt = cfg_list_first(servers); elt != NULL;
elt = cfg_list_next(elt)) {
const char *name;
const char *name = NULL;
server = cfg_listelt_value(elt);
name = cfg_obj_asstring(
cfg_map_getname(server));
@ -689,9 +699,11 @@ parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname,
DO("get config key list", cfg_map_get(config, "key", &keys));
for (elt = cfg_list_first(keys); elt != NULL;
elt = cfg_list_next(elt)) {
const char *name = NULL;
key = cfg_listelt_value(elt);
if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key)),
keyname) == 0) {
name = cfg_obj_asstring(cfg_map_getname(key));
if (strcasecmp(name, keyname) == 0) {
break;
}
}
@ -851,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;
@ -978,19 +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);
@ -1008,8 +1022,6 @@ main(int argc, char **argv) {
isccc_result_register();
command = *argv;
isc_buffer_allocate(rndc_mctx, &databuf, 2048);
/*
@ -1036,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);
@ -1069,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);

View file

@ -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

View file

@ -24,7 +24,14 @@ Known Issues
New Features
~~~~~~~~~~~~
- None.
- ``rndc`` has been updated to use the new BIND network manager API.
This change had the side effect of altering the TCP timeout for RNDC
connections from 60 seconds to the ``tcp-idle-timeout`` value, which
defaults to 30 seconds. Also, because the network manager currently
has no support for UNIX-domain sockets, those cannot now be used
with ``rndc``. This will be addressed in a future release, either by
restoring UNIX-domain socket support or by formally declaring them
to be obsolete in the control channel. [GL #1759]
Feature Changes
~~~~~~~~~~~~~~~

View file

@ -204,9 +204,12 @@ isc_result_t
isc_nm_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
isc_result_t
isc_nm_pauseread(isc_nmsocket_t *sock);
isc_nm_pauseread(isc_nmhandle_t *handle);
/*%<
* Pause reading on this socket, while still remembering the callback.
* Pause reading on this handle's socket, but remember the callback.
*
* Requires:
* \li 'handle' is a valid netmgr handle.
*/
void
@ -221,13 +224,13 @@ isc_nm_cancelread(isc_nmhandle_t *handle);
*/
isc_result_t
isc_nm_resumeread(isc_nmsocket_t *sock);
isc_nm_resumeread(isc_nmhandle_t *handle);
/*%<
* Resume reading from socket.
* Resume reading on the handle's socket.
*
* Requires:
* \li 'sock' is a valid netmgr socket
* \li ...for which a read/recv callback has been defined.
* \li 'handle' is a valid netmgr handle.
* \li ...for a socket with a defined read/recv callback.
*/
isc_result_t

View file

@ -1379,8 +1379,10 @@ isc_nm_cancelread(isc_nmhandle_t *handle) {
}
isc_result_t
isc_nm_pauseread(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
isc_nm_pauseread(isc_nmhandle_t *handle) {
REQUIRE(VALID_NMHANDLE(handle));
isc_nmsocket_t *sock = handle->sock;
switch (sock->type) {
case isc_nm_tcpsocket:
@ -1392,8 +1394,10 @@ isc_nm_pauseread(isc_nmsocket_t *sock) {
}
isc_result_t
isc_nm_resumeread(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
isc_nm_resumeread(isc_nmhandle_t *handle) {
REQUIRE(VALID_NMHANDLE(handle));
isc_nmsocket_t *sock = handle->sock;
switch (sock->type) {
case isc_nm_tcpsocket:

View file

@ -283,7 +283,7 @@ dnslisten_readcb(isc_nmhandle_t *handle, isc_result_t eresult,
* one packet, so we're done until the next read
* completes.
*/
isc_nm_pauseread(dnssock->outerhandle->sock);
isc_nm_pauseread(dnssock->outerhandle);
done = true;
} else {
/*
@ -295,7 +295,7 @@ dnslisten_readcb(isc_nmhandle_t *handle, isc_result_t eresult,
*/
if (atomic_load(&dnssock->ah) >=
TCPDNS_CLIENTS_PER_CONN) {
isc_nm_pauseread(dnssock->outerhandle->sock);
isc_nm_pauseread(dnssock->outerhandle);
done = true;
}
}
@ -376,7 +376,7 @@ isc_nm_tcpdns_sequential(isc_nmhandle_t *handle) {
* closehandle_cb callback, called whenever a handle
* is released.
*/
isc_nm_pauseread(handle->sock->outerhandle->sock);
isc_nm_pauseread(handle->sock->outerhandle);
atomic_store(&handle->sock->sequential, true);
}
@ -431,7 +431,7 @@ resume_processing(void *arg) {
}
isc_nmhandle_unref(handle);
} else if (sock->outerhandle != NULL) {
result = isc_nm_resumeread(sock->outerhandle->sock);
result = isc_nm_resumeread(sock->outerhandle);
if (result != ISC_R_SUCCESS) {
isc_nmhandle_unref(sock->outerhandle);
sock->outerhandle = NULL;
@ -454,7 +454,7 @@ resume_processing(void *arg) {
* Nothing in the buffer; resume reading.
*/
if (sock->outerhandle != NULL) {
isc_nm_resumeread(sock->outerhandle->sock);
isc_nm_resumeread(sock->outerhandle);
}
break;

View file

@ -457,7 +457,9 @@ isc_nm_listentcpdns
isc_nm_listentcp
isc_nm_listenudp
isc_nm_maxudp
isc_nm_pauseread
isc_nm_read
isc_nm_resumeread
isc_nm_send
isc_nm_setstats
isc_nm_start

View file

@ -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,111 +40,91 @@
#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 *);
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;
isccc_ccmsg_t *ccmsg = ev_in->ev_arg;
isc_region_t region;
isc_result_t result;
recv_data(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
void *arg) {
isccc_ccmsg_t *ccmsg = arg;
size_t size;
INSIST(VALID_CCMSG(ccmsg));
dev = &ccmsg->event;
if (eresult == ISC_R_CANCELED || eresult == ISC_R_EOF) {
ccmsg->result = eresult;
goto done;
} else 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;
}
if (ev->result != ISC_R_SUCCESS) {
ccmsg->result = ev->result;
goto send_and_free;
if (!ccmsg->length_received) {
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 done;
}
if (ccmsg->size > ccmsg->maxsize) {
ccmsg->result = ISC_R_RANGE;
goto done;
}
isc_region_consume(region, sizeof(uint32_t));
isc_buffer_allocate(ccmsg->mctx, &ccmsg->buffer, ccmsg->size);
ccmsg->length_received = true;
}
/*
* Success.
* If there's no more data, wait for more
*/
ccmsg->size = ntohl(ccmsg->size);
if (ccmsg->size == 0) {
ccmsg->result = ISC_R_UNEXPECTEDEND;
goto send_and_free;
}
if (ccmsg->size > ccmsg->maxsize) {
ccmsg->result = ISC_R_RANGE;
goto send_and_free;
if (region->length == 0) {
return;
}
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;
/* We have some data in the buffer, read it */
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;
}
isc_buffer_init(&ccmsg->buffer, region.base, region.length);
result = isc_socket_recv(ccmsg->sock, &region, 0, task, recv_message,
ccmsg);
if (result != ISC_R_SUCCESS) {
ccmsg->result = result;
goto send_and_free;
}
isc_event_free(&ev_in);
/* Wait for more data to come */
return;
send_and_free:
isc_task_send(ccmsg->task, &dev);
ccmsg->task = NULL;
isc_event_free(&ev_in);
return;
}
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;
isccc_ccmsg_t *ccmsg = ev_in->ev_arg;
(void)task;
INSIST(VALID_CCMSG(ccmsg));
dev = &ccmsg->event;
if (ev->result != ISC_R_SUCCESS) {
ccmsg->result = ev->result;
goto send_and_free;
}
ccmsg->result = ISC_R_SUCCESS;
isc_buffer_add(&ccmsg->buffer, ev->n);
ccmsg->address = ev->address;
send_and_free:
isc_task_send(ccmsg->task, &dev);
ccmsg->task = NULL;
isc_event_free(&ev_in);
done:
isc_nm_pauseread(handle);
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->magic = CCMSG_MAGIC;
ccmsg->size = 0;
ccmsg->buffer.base = NULL;
ccmsg->buffer.length = 0;
ccmsg->maxsize = 4294967295U; /* Largest message possible. */
ccmsg->mctx = mctx;
ccmsg->sock = sock;
ccmsg->task = NULL; /* None yet. */
ccmsg->result = ISC_R_UNEXPECTED; /* None yet. */
/*
* Should probably initialize the
*event here, but it can wait.
*/
*ccmsg = (isccc_ccmsg_t){
.magic = CCMSG_MAGIC,
.maxsize = 0xffffffffU, /* Largest message possible. */
.mctx = mctx,
.handle = handle,
.result = ISC_R_UNEXPECTED /* None yet. */
};
}
void
@ -154,37 +135,32 @@ 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 */
ccmsg->length_received = false;
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, &region, 0, ccmsg->task,
recv_length, ccmsg);
if (result != ISC_R_SUCCESS) {
ccmsg->task = NULL;
isc_nmhandle_ref(ccmsg->handle);
if (ccmsg->reading) {
result = isc_nm_resumeread(ccmsg->handle);
} else {
result = isc_nm_read(ccmsg->handle, recv_data, ccmsg);
ccmsg->reading = true;
}
if (result == ISC_R_CANCELED) {
ccmsg->reading = false;
} else if (result != ISC_R_SUCCESS) {
ccmsg->reading = false;
isc_nmhandle_unref(ccmsg->handle);
}
return (result);
@ -194,23 +170,10 @@ void
isccc_ccmsg_cancelread(isccc_ccmsg_t *ccmsg) {
REQUIRE(VALID_CCMSG(ccmsg));
isc_socket_cancel(ccmsg->sock, NULL, ISC_SOCKCANCEL_RECV);
}
#if 0
void
isccc_ccmsg_freebuffer(isccc_ccmsg_t*ccmsg) {
REQUIRE(VALID_CCMSG(ccmsg));
if (ccmsg->buffer.base == NULL) {
return;
if (ccmsg->reading) {
isc_nm_cancelread(ccmsg->handle);
}
isc_mem_put(ccmsg->mctx,ccmsg->buffer.base,ccmsg->buffer.length);
ccmsg->buffer.base = NULL;
ccmsg->buffer.length = 0;
}
#endif /* if 0 */
void
isccc_ccmsg_invalidate(isccc_ccmsg_t *ccmsg) {
@ -218,10 +181,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);
}
}

View file

@ -32,39 +32,39 @@
#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;
bool length_received;
isc_buffer_t * buffer;
unsigned int maxsize;
isc_mem_t * mctx;
isc_nmhandle_t *handle;
isc_nm_cb_t cb;
void * cbarg;
bool reading;
/* 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 +86,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 +95,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:
*