]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
convert rndc and control channel to use netmgr
authorEvan Hunt <each@isc.org>
Thu, 16 Apr 2020 20:06:42 +0000 (13:06 -0700)
committerEvan Hunt <each@isc.org>
Mon, 13 Jul 2020 20:16:53 +0000 (13:16 -0700)
- 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.

bin/named/controlconf.c
bin/rndc/rndc.c
doc/man/dnssec-importkey.1in
lib/isccc/ccmsg.c
lib/isccc/include/isccc/ccmsg.h

index 5e3fe4f36e2867fa13ba0d58b6085ccecf14d522..37a19b57b6c0aebea7e5b741ec011286cc632220 100644 (file)
 #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;
 
@@ -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;
 
-       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,
@@ -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;
-       }
-
-       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));
@@ -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);
+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? */
 }
 
@@ -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) {
index 58e9a43d8e347bab16583fa6471c6494041c95ea..7753f7f463e884d7360658de79894b7b80048bbd 100644 (file)
@@ -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;
-
-       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));
@@ -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.");
-       }
-
-       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));
@@ -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);
 
index 619e5edadea50e134603f9fa9620bbd89803aca9..174c25c2a3ab6eca10e0857f70a0679133856833 100644 (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
index b3ce556efb914676bda969f6ba4bf69a7a2b33d4..5b79e6148db7a73687ccddbb9a3ff1d8ddf0590a 100644 (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>
 #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, &region, 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
@@ -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, &region, 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);
        }
 }
index 082abb2eef0fa3619296c5764e9b6dd91e551aa6..3451007bf91440764ea6e75e7eac0a47953faffa 100644 (file)
 
 #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:
  *