]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- fast-reload, communication sockets for information transfer.
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Fri, 3 Nov 2023 16:12:44 +0000 (17:12 +0100)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Fri, 3 Nov 2023 16:12:44 +0000 (17:12 +0100)
Makefile.in
daemon/daemon.c
daemon/remote.c
daemon/remote.h
libunbound/libworker.c
smallapp/worker_cb.c
testcode/fake_event.c
util/fptr_wlist.c

index a1d98a97180e072858e59fb585a335dd747838ab..2ed4d1199e82a31535d0d7678158e162ad462918 100644 (file)
@@ -962,7 +962,7 @@ fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/
  $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h \
  $(srcdir)/validator/val_neg.h $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h \
  $(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound-event.h \
- $(srcdir)/libunbound/worker.h
+ $(srcdir)/libunbound/worker.h $(srcdir)/daemon/remote.h
 locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
 log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/sldns/sbuffer.h
 mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
@@ -1296,7 +1296,7 @@ remote.lo remote.o: $(srcdir)/daemon/remote.c config.h $(srcdir)/daemon/remote.h
  $(srcdir)/validator/val_anchor.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \
  $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/iterator/iter_delegpt.h \
  $(srcdir)/services/outside_network.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/parseutil.h \
- $(srcdir)/sldns/wire2str.h $(srcdir)/util/locks.h
+ $(srcdir)/sldns/wire2str.h $(srcdir)/util/locks.h $(srcdir)/util/ub_event.h
 stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
  $(srcdir)/libunbound/unbound.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
index 186ae42f2ed5acd60a653a3256fdeef9a6a20396..b7d7b631b25f1e57af7984e547c0bec93847edc9 100644 (file)
@@ -842,6 +842,8 @@ daemon_cleanup(struct daemon* daemon)
                auth_zones_cleanup(daemon->env->auth_zones);
        /* key cache is cleared by module desetup during next daemon_fork() */
        daemon_remote_clear(daemon->rc);
+       if(daemon->fast_reload_thread)
+               fast_reload_thread_stop(daemon->fast_reload_thread);
        for(i=0; i<daemon->num; i++)
                worker_delete(daemon->workers[i]);
        free(daemon->workers);
@@ -861,8 +863,6 @@ daemon_cleanup(struct daemon* daemon)
        dnsc_delete(daemon->dnscenv);
        daemon->dnscenv = NULL;
 #endif
-       if(daemon->fast_reload_thread)
-               fast_reload_thread_stop(daemon->fast_reload_thread);
        daemon->cfg = NULL;
 }
 
index bdc4dd4f87dcf76fcd1abdf6fba85e089b367e8a..fdb8e164138fbc71a78fa78540d099137c27080c 100644 (file)
@@ -63,6 +63,7 @@
 #include "util/config_file.h"
 #include "util/net_help.h"
 #include "util/module.h"
+#include "util/ub_event.h"
 #include "services/listen_dnsport.h"
 #include "services/cache/rrset.h"
 #include "services/cache/infra.h"
@@ -504,6 +505,11 @@ state_list_remove_elem(struct rc_state** list, struct comm_point* c)
 static void
 clean_point(struct daemon_remote* rc, struct rc_state* s)
 {
+       if(!s->rc) {
+               /* the state has been picked up and moved away */
+               free(s);
+               return;
+       }
        state_list_remove_elem(&rc->busy_list, s->c);
        rc->active --;
        if(s->ssl) {
@@ -654,11 +660,11 @@ do_reload(RES* ssl, struct worker* worker, int reuse_cache)
 
 /** do the fast_reload command */
 static void
-do_fast_reload(RES* ssl, struct worker* worker)
+do_fast_reload(RES* ssl, struct worker* worker, struct rc_state* s)
 {
        if(!ssl_printf(ssl, "start fast_reload\n"))
                return;
-       fast_reload_thread_start(ssl, worker);
+       fast_reload_thread_start(ssl, worker, s);
 }
 
 /** do the verbosity command */
@@ -3015,7 +3021,7 @@ cmdcmp(char* p, const char* cmd, size_t len)
 
 /** execute a remote control command */
 static void
-execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
+execute_cmd(struct daemon_remote* rc, struct rc_state* s, RES* ssl, char* cmd,
        struct worker* worker)
 {
        char* p = skipwhite(cmd);
@@ -3030,7 +3036,7 @@ execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
                do_reload(ssl, worker, 0);
                return;
        } else if(cmdcmp(p, "fast_reload", 11)) {
-               do_fast_reload(ssl, worker);
+               do_fast_reload(ssl, worker, s);
                return;
        } else if(cmdcmp(p, "stats_noreset", 13)) {
                do_stats(ssl, worker, 0);
@@ -3213,7 +3219,7 @@ daemon_remote_exec(struct worker* worker)
                return;
        }
        verbose(VERB_ALGO, "remote exec distributed: %s", (char*)msg);
-       execute_cmd(NULL, NULL, (char*)msg, worker);
+       execute_cmd(NULL, NULL, NULL, (char*)msg, worker);
        free(msg);
 }
 
@@ -3277,7 +3283,7 @@ handle_req(struct daemon_remote* rc, struct rc_state* s, RES* res)
        verbose(VERB_DETAIL, "control cmd: %s", buf);
 
        /* figure out what to do */
-       execute_cmd(rc, res, buf, rc->worker);
+       execute_cmd(rc, s, res, buf, rc->worker);
 }
 
 /** handle SSL_do_handshake changes to the file descriptor to wait for later */
@@ -3374,8 +3380,8 @@ int remote_control_callback(struct comm_point* c, void* arg, int err,
 /** fast reload thread. the thread main function */
 static void* fast_reload_thread_main(void* arg)
 {
-       struct fast_reload_thread* frio = (struct fast_reload_thread*)arg;
-       log_thread_set(&frio->threadnum);
+       struct fast_reload_thread* fast_reload_thread = (struct fast_reload_thread*)arg;
+       log_thread_set(&fast_reload_thread->threadnum);
 
        verbose(VERB_ALGO, "start fast reload thread");
 
@@ -3384,6 +3390,204 @@ static void* fast_reload_thread_main(void* arg)
 }
 #endif /* !THREADS_DISABLED */
 
+/** create a socketpair for bidirectional communication, false on failure */
+static int
+create_socketpair(int* pair, struct ub_randstate* rand)
+{
+#ifndef USE_WINSOCK
+       if(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
+               log_err("socketpair: %s", strerror(errno));
+               return 0;
+       }
+       (void)rand;
+#else
+       struct sockaddr_in addr, baddr, accaddr, connaddr;
+       socklen_t baddrlen, accaddrlen, connaddrlen;
+       uint8_t localhost[] = {127, 0, 0, 1};
+       uint8_t nonce[16], recvnonce[16];
+       size_t i;
+       int lst;
+       ssize_t ret;
+       pair[0] = -1;
+       pair[1] = -1;
+       for(i=0; i<sizeof(nonce); i++) {
+               nonce[i] = ub_random_max(rand, 256);
+       }
+       lst = socket(AF_INET, SOCK_STREAM, 0);
+       if(lst == -1) {
+               log_err("create_socketpair: socket: %s", sock_strerror(errno));
+               return 0;
+       }
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_port = 0;
+       memcpy(&addr.sin_addr, localhost, 4);
+       if(bind(lst, (struct sockaddr*)&addr, (socklen_t)sizeof(addr))
+               == -1) {
+               log_err("create socketpair: bind: %s", sock_strerror(errno));
+               sock_close(lst);
+               return 0;
+       }
+       if(listen(lst, 12) == -1) {
+               log_err("create socketpair: listen: %s", sock_strerror(errno));
+               sock_close(lst);
+               return 0;
+       }
+
+       pair[1] = socket(AF_INET, SOCK_STREAM, 0);
+       if(pair[1] == -1) {
+               log_err("create socketpair: socket: %s", sock_strerror(errno));
+               sock_close(lst);
+               return 0;
+       }
+       baddrlen = (socklen_t)sizeof(baddr);
+       if(getsockname(lst, (struct sockaddr*)&baddr, &baddrlen) == -1) {
+               log_err("create socketpair: getsockname: %s",
+                       sock_strerror(errno));
+               sock_close(lst);
+               sock_close(pair[1]);
+               pair[1] = -1;
+               return 0;
+       }
+       if(baddrlen > (socklen_t)sizeof(baddr)) {
+               log_err("create socketpair: getsockname returned addr too big");
+               sock_close(lst);
+               sock_close(pair[1]);
+               pair[1] = -1;
+               return 0;
+       }
+       /* the socket is blocking */
+       if(connect(pair[1], (struct sockaddr*)&baddr, baddrlen) == -1) {
+               log_err("create socketpair: connect: %s",
+                       sock_strerror(errno));
+               sock_close(lst);
+               sock_close(pair[1]);
+               pair[1] = -1;
+               return 0;
+       }
+       accaddrlen = (socklen_t)sizeof(accaddr);
+       pair[0] = accept(lst, &accaddr, &accaddrlen);
+       if(pair[0] == -1) {
+               log_err("create socketpair: accept: %s", sock_strerror(errno));
+               sock_close(lst);
+               sock_close(pair[1]);
+               pair[1] = -1;
+               return 0;
+       }
+       if(accaddrlen > (socklen_t)sizeof(accaddr)) {
+               log_err("create socketpair: accept returned addr too big");
+               sock_close(lst);
+               sock_close(pair[0]);
+               sock_close(pair[1]);
+               pair[0] = -1;
+               pair[1] = -1;
+               return 0;
+       }
+       if(accaddr.sin_family != AF_INET ||
+          memcmp(localhost, &accaddr.sin_addr, 4) != 0) {
+               log_err("create socketpair: accept from wrong address");
+               sock_close(lst);
+               sock_close(pair[0]);
+               sock_close(pair[1]);
+               pair[0] = -1;
+               pair[1] = -1;
+               return 0;
+       }
+       connaddrlen = (socklen_t)sizeof(connaddr);
+       if(getsockname(pair[1], (struct sockaddr*)&connaddr, &connaddrlen)
+               == -1) {
+               log_err("create socketpair: getsockname connectedaddr: %s",
+                       sock_strerror(errno));
+               sock_close(lst);
+               sock_close(pair[0]);
+               sock_close(pair[1]);
+               pair[0] = -1;
+               pair[1] = -1;
+               return 0;
+       }
+       if(connaddrlen > (socklen_t)sizeof(connaddr)) {
+               log_err("create socketpair: getsockname connectedaddr returned addr too big");
+               sock_close(lst);
+               sock_close(pair[0]);
+               sock_close(pair[1]);
+               pair[0] = -1;
+               pair[1] = -1;
+               return 0;
+       }
+       if(connaddr.sin_family != AF_INET ||
+          memcmp(localhost, &connaddr.sin_addr, 4) != 0) {
+               log_err("create socketpair: getsockname connectedadd returned wrong address");
+               sock_close(lst);
+               sock_close(pair[0]);
+               sock_close(pair[1]);
+               pair[0] = -1;
+               pair[1] = -1;
+               return 0;
+       }
+       if(accaddr.sin_port != connaddr.sin_port) {
+               log_err("create socketpair: accept from wrong port");
+               sock_close(lst);
+               sock_close(pair[0]);
+               sock_close(pair[1]);
+               pair[0] = -1;
+               pair[1] = -1;
+               return 0;
+       }
+       sock_close(lst);
+
+       ret = send(pair[1], nonce, sizeof(nonce), 0);
+       if(ret == -1) {
+               log_err("create socketpair: send: %s", sock_strerror(errno));
+               sock_close(pair[0]);
+               sock_close(pair[1]);
+               pair[0] = -1;
+               pair[1] = -1;
+               return 0;
+       } else if(ret != sizeof(nonce)) {
+               log_err("create socketpair: send was truncated");
+               sock_close(pair[0]);
+               sock_close(pair[1]);
+               pair[0] = -1;
+               pair[1] = -1;
+               return 0;
+       }
+
+       ret = recv(pair[0], recvnonce, sizeof(nonce), 0);
+       if(ret == -1) {
+               log_err("create socketpair: recv: %s", sock_strerror(errno));
+               sock_close(pair[0]);
+               sock_close(pair[1]);
+               pair[0] = -1;
+               pair[1] = -1;
+               return 0;
+       } else if(ret == 0) {
+               log_err("create socketpair: stream closed");
+               sock_close(pair[0]);
+               sock_close(pair[1]);
+               pair[0] = -1;
+               pair[1] = -1;
+               return 0;
+       }
+       if(ret != sizeof(nonce)) {
+               log_err("create socketpair: recv did not read all nonce bytes");
+               sock_close(pair[0]);
+               sock_close(pair[1]);
+               pair[0] = -1;
+               pair[1] = -1;
+               return 0;
+       }
+       if(memcmp(nonce, recvnonce, sizeof(nonce)) != 0) {
+               log_err("create socketpair: recv wrong nonce");
+               sock_close(pair[0]);
+               sock_close(pair[1]);
+               pair[0] = -1;
+               pair[1] = -1;
+               return 0;
+       }
+#endif
+       return 1;
+}
+
 /** fast reload thread. setup the thread info */
 static int
 fast_reload_thread_setup(struct worker* worker)
@@ -3396,6 +3600,14 @@ fast_reload_thread_setup(struct worker* worker)
        /* The thread id printed in logs, numworker+1 is the dnstap thread.
         * This is numworkers+2. */
        worker->daemon->fast_reload_thread->threadnum = numworkers+2;
+       worker->daemon->fast_reload_thread->commpair[0] = -1;
+       worker->daemon->fast_reload_thread->commpair[1] = -1;
+       if(!create_socketpair(worker->daemon->fast_reload_thread->commpair,
+               worker->daemon->rand)) {
+               free(worker->daemon->fast_reload_thread);
+               return 0;
+       }
+       worker->daemon->fast_reload_thread->worker = worker;
        return 1;
 }
 
@@ -3405,11 +3617,44 @@ fast_reload_thread_desetup(struct fast_reload_thread* fast_reload_thread)
 {
        if(!fast_reload_thread)
                return;
+       if(fast_reload_thread->service_event &&
+               fast_reload_thread->service_event_is_added) {
+               ub_event_del(fast_reload_thread->service_event);
+               fast_reload_thread->service_event_is_added = 0;
+       }
+       if(fast_reload_thread->service_event)
+               ub_event_free(fast_reload_thread->service_event);
+       sock_close(fast_reload_thread->commpair[0]);
+       sock_close(fast_reload_thread->commpair[1]);
+       if(fast_reload_thread->remote.ssl) {
+               SSL_shutdown(fast_reload_thread->remote.ssl);
+               SSL_free(fast_reload_thread->remote.ssl);
+       }
+       comm_point_delete(fast_reload_thread->client_cp);
        free(fast_reload_thread);
 }
 
+void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits),
+       void* arg)
+{
+       struct fast_reload_thread* fast_reload_thread =
+               (struct fast_reload_thread*)arg;
+       (void)fast_reload_thread;
+}
+
+int fast_reload_client_callback(struct comm_point* c, void* arg, int err,
+       struct comm_reply* ATTR_UNUSED(rep))
+{
+       struct fast_reload_thread* fast_reload_thread =
+               (struct fast_reload_thread*)arg;
+       (void)c;
+       (void)err;
+       (void)fast_reload_thread;
+       return 0;
+}
+
 void
-fast_reload_thread_start(RES* ssl, struct worker* worker)
+fast_reload_thread_start(RES* ssl, struct worker* worker, struct rc_state* s)
 {
        if(worker->daemon->fast_reload_thread) {
                log_err("fast reload thread already running");
@@ -3420,8 +3665,43 @@ fast_reload_thread_start(RES* ssl, struct worker* worker)
                        return;
                return;
        }
+       worker->daemon->fast_reload_thread->remote = *ssl;
        worker->daemon->fast_reload_thread->started = 1;
+
 #ifndef THREADS_DISABLED
+       /* Setup command listener in remote servicing thread */
+       worker->daemon->fast_reload_thread->service_event = ub_event_new(
+               comm_base_internal(worker->base),
+               worker->daemon->fast_reload_thread->commpair[0],
+               UB_EV_READ | UB_EV_PERSIST, fast_reload_service_cb,
+               worker->daemon->fast_reload_thread);
+       if(!worker->daemon->fast_reload_thread->service_event) {
+               if(!ssl_printf(ssl, "error out of memory\n"))
+                       return;
+               return;
+       }
+       if(ub_event_add(worker->daemon->fast_reload_thread->service_event,
+               NULL) != 0) {
+               if(!ssl_printf(ssl, "error out of memory adding service event\n"))
+                       return;
+               return;
+       }
+       worker->daemon->fast_reload_thread->service_event_is_added = 1;
+
+       /* Setup the comm point to the remote control client as an event
+        * on the remote servicing thread, which it already is.
+        * It needs a new callback to service it. */
+       log_assert(s);
+       state_list_remove_elem(&s->rc->busy_list, s->c);
+       s->rc->active --;
+       worker->daemon->fast_reload_thread->client_cp = s->c;
+       worker->daemon->fast_reload_thread->client_cp->callback =
+               fast_reload_client_callback;
+       worker->daemon->fast_reload_thread->client_cp->cb_arg =
+               worker->daemon->fast_reload_thread;
+       s->rc = NULL; /* move away the rc state */
+
+       /* Start fast reload thread */
        ub_thread_create(&worker->daemon->fast_reload_thread->tid,
                fast_reload_thread_main, worker->daemon->fast_reload_thread);
 #else
index cb80d4e84942b32133f3515b912b8ab1ed1a5f5c..c257916a3c4f4b51cc0c8c3679780c855a65ea3c 100644 (file)
@@ -126,12 +126,26 @@ struct fast_reload_thread {
        /** the thread number for the dtio thread,
         * must be first to cast thread arg to int* in checklock code. */
        int threadnum;
-       /** event base, for event handling */
-       void* event_base;
+       /** communication socket pair, that sends commands */
+       int commpair[2];
        /** thread id, of the io thread */
        ub_thread_type tid;
        /** if the io processing has started */
        int started;
+
+       /** the event that listens on the remote service worker to the
+        * commpair, it receives content from the fast reload thread. */
+       void* service_event;
+       /** if the event that listens on the remote service worker has
+        * been added to the comm base. */
+       int service_event_is_added;
+       /** the remote control connection to print output to. */
+       struct remote_stream remote;
+       /** the worker that the service_event is added in */
+       struct worker* worker;
+       /** the comm point for the client connection, the remote control
+        * client. */
+       struct comm_point* client_cp;
 };
 
 /**
@@ -223,8 +237,12 @@ int ssl_read_line(RES* ssl, char* buf, size_t max);
  * Start fast reload thread
  * @param ssl: the RES connection to print to.
  * @param worker: the remote servicing worker.
+ * @param s: the rc_state that is servicing the remote control connection to
+ *     the remote control client. It needs to be moved away to stay connected
+ *     while the fast reload is running.
  */
-void fast_reload_thread_start(RES* ssl, struct worker* worker);
+void fast_reload_thread_start(RES* ssl, struct worker* worker,
+       struct rc_state* s);
 
 /**
  * Stop fast reload thread
@@ -232,4 +250,11 @@ void fast_reload_thread_start(RES* ssl, struct worker* worker);
  */
 void fast_reload_thread_stop(struct fast_reload_thread* fast_reload_thread);
 
+/** fast reload thread commands to remote service thread event callback */
+void fast_reload_service_cb(int fd, short bits, void* arg);
+
+/** fast reload callback for the remote control client connection */
+int fast_reload_client_callback(struct comm_point* c, void* arg, int err,
+       struct comm_reply* rep);
+
 #endif /* DAEMON_REMOTE_H */
index 0e1c403937636da4f134cb0431058d6466be642a..412293f9a7c6b5da2618018c5df8677df8da1a6f 100644 (file)
@@ -1072,3 +1072,17 @@ void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
        log_assert(0);
 }
 #endif
+
+void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
+       void* ATTR_UNUSED(arg))
+{
+       log_assert(0);
+}
+
+int fast_reload_client_callback(struct comm_point* ATTR_UNUSED(c),
+       void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
+        struct comm_reply* ATTR_UNUSED(repinfo))
+{
+       log_assert(0);
+       return 0;
+}
index c68981735cb76e947e053d2b2481b64ad510b122..5987e76220e753237f9c4fff1268c1fc61c1755f 100644 (file)
@@ -255,3 +255,17 @@ void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
        log_assert(0);
 }
 #endif
+
+void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
+       void* ATTR_UNUSED(arg))
+{
+       log_assert(0);
+}
+
+int fast_reload_client_callback(struct comm_point* ATTR_UNUSED(c),
+       void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
+        struct comm_reply* ATTR_UNUSED(repinfo))
+{
+       log_assert(0);
+       return 0;
+}
index 13970c37726a789a8a298b6eb01acc01befe195d..45911fe2914ebc4f470d658af3e57f8a07d0c3dc 100644 (file)
@@ -1906,4 +1906,24 @@ void http2_stream_add_meshstate(struct http2_stream* ATTR_UNUSED(h2_stream),
 {
 }
 
+void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
+       void* ATTR_UNUSED(arg))
+{
+       log_assert(0);
+}
+
+void fast_reload_thread_stop(
+       struct fast_reload_thread* ATTR_UNUSED(fast_reload_thread))
+{
+       /* nothing */
+}
+
+int fast_reload_client_callback(struct comm_point* ATTR_UNUSED(c),
+       void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
+        struct comm_reply* ATTR_UNUSED(repinfo))
+{
+       log_assert(0);
+       return 0;
+}
+
 /*********** End of Dummy routines ***********/
index 43d38dc3797ddd7316ea90bebc35a7aa9ba70ee1..2a2b89dba6106db618b06120a923b70987756af8 100644 (file)
@@ -73,6 +73,7 @@
 #include "libunbound/worker.h"
 #include "util/tube.h"
 #include "util/config_file.h"
+#include "daemon/remote.h"
 #ifdef UB_ON_WINDOWS
 #include "winrc/win_svc.h"
 #endif
@@ -120,6 +121,7 @@ fptr_whitelist_comm_point_raw(comm_point_callback_type *fptr)
        else if(fptr == &tube_handle_write) return 1;
        else if(fptr == &remote_accept_callback) return 1;
        else if(fptr == &remote_control_callback) return 1;
+       else if(fptr == &fast_reload_client_callback) return 1;
        return 0;
 }
 
@@ -180,6 +182,7 @@ fptr_whitelist_event(void (*fptr)(int, short, void *))
        else if(fptr == &tube_handle_signal) return 1;
        else if(fptr == &comm_base_handle_slow_accept) return 1;
        else if(fptr == &comm_point_http_handle_callback) return 1;
+       else if(fptr == &fast_reload_service_cb) return 1;
 #ifdef USE_DNSTAP
        else if(fptr == &dtio_output_cb) return 1;
        else if(fptr == &dtio_cmd_cb) return 1;