#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>
#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;
};
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;
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;
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
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);
}
}
-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];
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;
- isc_netaddr_fromsockaddr(&netaddr, sockaddr);
-
- result = dns_acl_match(&netaddr, NULL, 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;
+ /* ACL doesn't apply to unix domain sockets */
+ if (listener->type != isc_socktype_tcp) {
+ return (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);
-}
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
-static void
-control_next(controllistener_t *listener) {
- (void)control_accept(listener);
+ result = dns_acl_match(&netaddr, NULL, listener->acl, env, &match,
+ NULL);
+ return (result == ISC_R_SUCCESS && match > 0);
}
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,
}
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;
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;
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;
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;
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;
}
}
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;
}
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) {
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;
- }
-
- sock = nevent->newsocket;
-
- /* Is the server shutting down? */
- if (listener->controls->shuttingdown) {
- isc_socket_detach(&sock);
- shutdown_listener(listener);
- goto cleanup;
+ return (result);
}
- 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));
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
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;
/*
* 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,
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"));
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;
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);
/*
* 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 "
}
}
- 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 =
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);
+cleanup:
+ if (listener != NULL) {
+ listener->exiting = true;
+ free_listener(listener);
}
- if (result == ISC_R_SUCCESS) {
+ 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,
- "command channel listening on %s", socktext);
- *listenerp = listener;
- } else {
- 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;
+ "couldn't add command channel %s: %s", socktext,
+ isc_result_totext(result));
}
+ *listenerp = NULL;
+
/* XXXDCL return error results? fail hard? */
}
update_listener(cp, &listener, control, config,
&addr, aclconfctx, socktext,
- isc_sockettype_tcp);
+ isc_socktype_tcp);
if (listener != NULL) {
/*
add_listener(cp, &listener, control,
config, &addr, aclconfctx,
socktext,
- isc_sockettype_tcp);
+ isc_socktype_tcp);
}
if (listener != NULL) {
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))
update_listener(cp, &listener, control, config,
&addr, aclconfctx,
cfg_obj_asstring(path),
- isc_sockettype_unix);
+ isc_socktype_unix);
if (listener != NULL) {
/*
add_listener(cp, &listener, control,
config, &addr, aclconfctx,
cfg_obj_asstring(path),
- isc_sockettype_unix);
+ isc_socktype_unix);
}
if (listener != NULL) {
link);
}
}
+#endif
}
} else {
int i;
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) {
/*
* 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) {
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;
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;
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);
}
static void
-rndc_senddone(isc_task_t *task, isc_event_t *event) {
- isc_socketevent_t *sevent = (isc_socketevent_t *)event;
-
- UNUSED(task);
+rndc_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
+ UNUSED(arg);
- 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.");
- }
-
- if (ccmsg.result != ISC_R_SUCCESS) {
- fatal("recv failed: %s", isc_result_totext(ccmsg.result));
+ "* 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));
}
- 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));
}
}
- 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;
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.");
- }
-
- if (ccmsg.result != ISC_R_SUCCESS) {
- fatal("recv failed: %s", isc_result_totext(ccmsg.result));
+ "* 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));
}
- 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));
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);
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);
}
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
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;
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);
isccc_result_register();
- command = *argv;
-
isc_buffer_allocate(rndc_mctx, &databuf, 2048);
/*
*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);
cfg_parser_destroy(&pctx);
isc_mem_put(rndc_mctx, args, argslen);
- isccc_ccmsg_invalidate(&ccmsg);
isc_buffer_free(&databuf);
#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>
#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 (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 (region->length < sizeof(uint32_t)) {
+ ccmsg->result = ISC_R_UNEXPECTEDEND;
+ goto done;
}
- /*
- * Success.
- */
- ccmsg->size = ntohl(ccmsg->size);
+ 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 (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 (region->length == 0) {
+ ccmsg->result = ISC_R_UNEXPECTEDEND;
+ goto done;
+ }
+
+ 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;
+ }
- if (ev->result != ISC_R_SUCCESS) {
- ccmsg->result = ev->result;
- goto send_and_free;
+ result = isc_nm_read(handle, recv_message, ccmsg);
+ if (result == ISC_R_SUCCESS) {
+ return;
}
- ccmsg->result = ISC_R_SUCCESS;
- isc_buffer_add(&ccmsg->buffer, ev->n);
- ccmsg->address = ev->address;
+ ccmsg->result = result;
-send_and_free:
- isc_task_send(ccmsg->task, &dev);
- ccmsg->task = NULL;
- isc_event_free(&ev_in);
+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
}
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);
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
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);
}
}