Hi,

a year ago I added support for our pf tables to the unbound ipset module. Upstream does not seem eager to merge it:
https://github.com/NLnetLabs/unbound/pull/144

Implementing pf tables support was pretty straightforward. It has been more work to adjust module's privilege management to allow the modules to open privileget files like /dev/pf and keep them open across reloads.
This is also what upstream was unsure about.

So below you find the diff against our base unbound.

Should this go in? Continue to wait for upstream?
Suggestions for improvement?


Christopher



Index: Makefile.bsd-wrapper
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/Makefile.bsd-wrapper,v
retrieving revision 1.20
diff -u -p -r1.20 Makefile.bsd-wrapper
--- Makefile.bsd-wrapper        24 Aug 2020 15:33:33 -0000      1.20
+++ Makefile.bsd-wrapper        7 Feb 2021 16:02:51 -0000
@@ -17,6 +17,7 @@ CONFIGURE_OPTS_UNBOUND=       --enable-allsymb
                        --with-rootkey-file=/var/unbound/db/root.key \
                        --with-conf-file=${CHROOTDIR}/etc/unbound.conf \
                        --with-username=_unbound \
+                       --enable-ipset \
                        --disable-shared \
                        --disable-explicit-port-randomisation
Index: config.h.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/config.h.in,v
retrieving revision 1.21
diff -u -p -r1.21 config.h.in
--- config.h.in 28 Oct 2020 11:31:06 -0000      1.21
+++ config.h.in 7 Feb 2021 16:02:51 -0000
@@ -381,6 +381,9 @@
 /* Define to 1 if you have the <nettle/eddsa.h> header file. */
 #undef HAVE_NETTLE_EDDSA_H
+/* Define to 1 if you have the <net/pfvar.h> header file. */
+#undef HAVE_NET_PFVAR_H
+
 /* Define to 1 if you have the <net/if.h> header file. */
 #undef HAVE_NET_IF_H
Index: configure
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/configure,v
retrieving revision 1.41
diff -u -p -r1.41 configure
--- configure   10 Dec 2020 21:44:57 -0000      1.41
+++ configure   7 Feb 2021 16:02:52 -0000
@@ -21520,7 +21520,22 @@ $as_echo "#define USE_IPSET 1" >>confdef
                IPSET_OBJ="ipset.lo"
- # mnl
+               # BSD's pf
+               for ac_header in net/pfvar.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "net/pfvar.h" "ac_cv_header_net_pfvar_h" 
"
+                 #include <netinet/in.h>
+                 #include <net/if.h>
+
+"
+if test "x$ac_cv_header_net_pfvar_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_PFVAR_H 1
+_ACEOF
+
+else
+
+                 # mnl
# Check whether --with-libmnl was given.
 if test "${with_libmnl+set}" = set; then :
@@ -21529,28 +21544,34 @@ else
    withval="yes"
 fi
- found_libmnl="no"
-               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmnl" 
>&5
+                 found_libmnl="no"
+                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmnl" 
>&5
 $as_echo_n "checking for libmnl... " >&6; }
-               if test x_$withval = x_ -o x_$withval = x_yes; then
-                       withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw 
/usr"
-               fi
-               for dir in $withval ; do
-                       if test -f "$dir/include/libmnl/libmnl.h"; then
-                               found_libmnl="yes"
-                                                               if test "$dir" != 
"/usr"; then
-                                       CPPFLAGS="$CPPFLAGS -I$dir/include"
-                                       LDFLAGS="$LDFLAGS -L$dir/lib"
-                               fi
-                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in 
$dir" >&5
+                 if test x_$withval = x_ -o x_$withval = x_yes; then
+                         withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw 
/usr"
+                 fi
+                 for dir in $withval ; do
+                         if test -f "$dir/include/libmnl/libmnl.h"; then
+                                 found_libmnl="yes"
+                                                                 if test "$dir" != 
"/usr"; then
+                                         CPPFLAGS="$CPPFLAGS -I$dir/include"
+                                         LDFLAGS="$LDFLAGS -L$dir/lib"
+                                 fi
+                                 { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in 
$dir" >&5
 $as_echo "found in $dir" >&6; }
-                               LIBS="$LIBS -lmnl"
-                               break;
-                       fi
-               done
-               if test x_$found_libmnl != x_yes; then
-                       as_fn_error $? "Could not find libmnl, libmnl.h" 
"$LINENO" 5
-               fi
+                                 LIBS="$LIBS -lmnl"
+                                 break;
+                         fi
+                 done
+                 if test x_$found_libmnl != x_yes
+                 then
+                         as_fn_error $? "Could not find libmnl, libmnl.h" 
"$LINENO" 5
+                 fi
+
+fi
+
+done
+
                ;;
     no|*)
        # nothing
Index: configure.ac
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/configure.ac,v
retrieving revision 1.41
diff -u -p -r1.41 configure.ac
--- configure.ac        10 Dec 2020 21:44:57 -0000      1.41
+++ configure.ac        7 Feb 2021 16:02:52 -0000
@@ -1830,31 +1830,37 @@ case "$enable_ipset" in
                IPSET_OBJ="ipset.lo"
                AC_SUBST(IPSET_OBJ)
- # mnl
-               AC_ARG_WITH(libmnl, AC_HELP_STRING([--with-libmnl=path],
-                       [specify explicit path for libmnl.]),
-                       [ ],[ withval="yes" ])
-               found_libmnl="no"
-               AC_MSG_CHECKING(for libmnl)
-               if test x_$withval = x_ -o x_$withval = x_yes; then
-                       withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw 
/usr"
-               fi
-               for dir in $withval ; do
-                       if test -f "$dir/include/libmnl/libmnl.h"; then
-                               found_libmnl="yes"
-                               dnl assume /usr is in default path.
-                               if test "$dir" != "/usr"; then
-                                       CPPFLAGS="$CPPFLAGS -I$dir/include"
-                                       LDFLAGS="$LDFLAGS -L$dir/lib"
-                               fi
-                               AC_MSG_RESULT(found in $dir)
-                               LIBS="$LIBS -lmnl"
-                               break;
-                       fi
-               done
-               if test x_$found_libmnl != x_yes; then
-                       AC_ERROR([Could not find libmnl, libmnl.h])
-               fi
+               # BSD's pf
+               AC_CHECK_HEADERS([net/pfvar.h], [], [
+                 # mnl
+                 AC_ARG_WITH(libmnl, AC_HELP_STRING([--with-libmnl=path],
+                         [specify explicit path for libmnl.]),
+                         [ ],[ withval="yes" ])
+                 found_libmnl="no"
+                 AC_MSG_CHECKING(for libmnl)
+                 if test x_$withval = x_ -o x_$withval = x_yes; then
+                         withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw 
/usr"
+                 fi
+                 for dir in $withval ; do
+                         if test -f "$dir/include/libmnl/libmnl.h"; then
+                                 found_libmnl="yes"
+                                 dnl assume /usr is in default path.
+                                 if test "$dir" != "/usr"; then
+                                         CPPFLAGS="$CPPFLAGS -I$dir/include"
+                                         LDFLAGS="$LDFLAGS -L$dir/lib"
+                                 fi
+                                 AC_MSG_RESULT(found in $dir)
+                                 LIBS="$LIBS -lmnl"
+                                 break;
+                         fi
+                 done
+                 if test x_$found_libmnl != x_yes; then
+                         AC_ERROR([Could not find libmnl, libmnl.h])
+                 fi
+               ], [
+                 #include <netinet/in.h>
+                 #include <net/if.h>
+               ])
                ;;
     no|*)
        # nothing
Index: cachedb/cachedb.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/cachedb/cachedb.c,v
retrieving revision 1.12
diff -u -p -r1.12 cachedb.c
--- cachedb/cachedb.c   24 Aug 2020 09:41:52 -0000      1.12
+++ cachedb/cachedb.c   7 Feb 2021 16:02:52 -0000
@@ -229,7 +229,7 @@ cachedb_apply_cfg(struct cachedb_env* ca
 }
int -cachedb_init(struct module_env* env, int id)
+cachedb_setup(struct module_env* env, int id)
 {
        struct cachedb_env* cachedb_env = (struct cachedb_env*)calloc(1,
                sizeof(struct cachedb_env));
@@ -268,7 +268,7 @@ cachedb_init(struct module_env* env, int
 }
void -cachedb_deinit(struct module_env* env, int id)
+cachedb_desetup(struct module_env* env, int id)
 {
        struct cachedb_env* cachedb_env;
        if(!env || !env->modinfo[id])
@@ -846,7 +846,7 @@ cachedb_get_mem(struct module_env* env, */
 static struct module_func_block cachedb_block = {
        "cachedb",
-       &cachedb_init, &cachedb_deinit, &cachedb_operate,
+       &module_dummy_init, &module_dummy_init, &cachedb_setup, &cachedb_desetup, 
&cachedb_operate,
        &cachedb_inform_super, &cachedb_clear, &cachedb_get_mem
 };
Index: cachedb/cachedb.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/cachedb/cachedb.h,v
retrieving revision 1.3
diff -u -p -r1.3 cachedb.h
--- cachedb/cachedb.h   24 Aug 2020 09:41:52 -0000      1.3
+++ cachedb/cachedb.h   7 Feb 2021 16:02:52 -0000
@@ -90,9 +90,9 @@ struct cachedb_backend {
 #define CACHEDB_HASHSIZE 256 /* bit hash */
/** Init the cachedb module */
-int cachedb_init(struct module_env* env, int id);
+int cachedb_setup(struct module_env* env, int id);
 /** Deinit the cachedb module */
-void cachedb_deinit(struct module_env* env, int id);
+void cachedb_desetup(struct module_env* env, int id);
 /** Operate on an event on a query (in qstate). */
 void cachedb_operate(struct module_qstate* qstate, enum module_ev event,
        int id, struct outbound_entry* outbound);
Index: daemon/daemon.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/daemon.c,v
retrieving revision 1.18
diff -u -p -r1.18 daemon.c
--- daemon/daemon.c     10 Dec 2020 21:44:58 -0000      1.18
+++ daemon/daemon.c     7 Feb 2021 16:02:52 -0000
@@ -252,7 +252,7 @@ daemon_init(void)
        tzset();
 #endif
        daemon->need_to_exit = 0;
-       modstack_init(&daemon->mods);
+       memset(&daemon->mods, 0, sizeof(daemon->mods));
if(!(daemon->env = (struct module_env*)calloc(1, sizeof(*daemon->env)))) {
                free(daemon);
@@ -303,7 +303,7 @@ daemon_init(void)
        return daemon;  
 }
-int +int
 daemon_open_shared_ports(struct daemon* daemon)
 {
        log_assert(daemon);
@@ -380,6 +380,22 @@ daemon_open_shared_ports(struct daemon* if(!(daemon->rc_ports=daemon_remote_open_ports(daemon->cfg)))
                        return 0;
                daemon->rc_port = daemon->cfg->control_port;
+       }
+       return 1;
+}
+
+int
+daemon_privileged(struct daemon* daemon)
+{
+       if(!daemon_open_shared_ports(daemon))
+               fatal_exit("could not open ports");
+
+       daemon->env->cfg = daemon->cfg;
+       daemon->env->alloc = &daemon->superalloc;
+       daemon->env->worker = NULL;
+       if(!modstack_init(&daemon->mods, daemon->cfg->module_conf,
+               daemon->env)) {
+               fatal_exit("failed to init modules");
        }
        return 1;
 }
Index: daemon/daemon.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/daemon.h,v
retrieving revision 1.6
diff -u -p -r1.6 daemon.h
--- daemon/daemon.h     19 Mar 2020 17:48:07 -0000      1.6
+++ daemon/daemon.h     7 Feb 2021 16:02:52 -0000
@@ -147,12 +147,13 @@ struct daemon {
 struct daemon* daemon_init(void);
/**
- * Open shared listening ports (if needed).
+ * Do daemon setup that needs privileges
+ * like opening privileged ports or opening device files.
  * The cfg member pointer must have been set for the daemon.
  * @param daemon: the daemon.
  * @return: false on error.
  */
-int daemon_open_shared_ports(struct daemon* daemon);
+int daemon_privileged(struct daemon* daemon);
/**
  * Fork workers and start service.
Index: daemon/unbound.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/unbound.c,v
retrieving revision 1.29
diff -u -p -r1.29 unbound.c
--- daemon/unbound.c    10 Dec 2020 21:44:58 -0000      1.29
+++ daemon/unbound.c    7 Feb 2021 16:02:52 -0000
@@ -693,9 +693,9 @@ run_daemon(const char* cfgfile, int cmdl
                        config_lookup_uid(cfg);
        
                /* prepare */
-               if(!daemon_open_shared_ports(daemon))
-                       fatal_exit("could not open ports");
if(!done_setup) { + if(!daemon_privileged(daemon))
+                               fatal_exit("could not do privileged setup");
                        perform_setup(daemon, cfg, debug_mode, &cfgfile, 
need_pidfile);
done_setup = 1; } else {
Index: dns64/dns64.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/dns64/dns64.c,v
retrieving revision 1.15
diff -u -p -r1.15 dns64.c
--- dns64/dns64.c       24 Aug 2020 09:41:52 -0000      1.15
+++ dns64/dns64.c       7 Feb 2021 16:02:52 -0000
@@ -394,7 +394,7 @@ dns64_apply_cfg(struct dns64_env* dns64_
  * \param id  This instance's ID number.
  */
 int
-dns64_init(struct module_env* env, int id)
+dns64_setup(struct module_env* env, int id)
 {
     struct dns64_env* dns64_env =
         (struct dns64_env*)calloc(1, sizeof(struct dns64_env));
@@ -428,7 +428,7 @@ free_ignore_aaaa_node(rbnode_type* node,
  * \param id  This instance's ID number.
  */
 void
-dns64_deinit(struct module_env* env, int id)
+dns64_desetup(struct module_env* env, int id)
 {
     struct dns64_env* dns64_env;
     if (!env)
@@ -1019,8 +1019,8 @@ dns64_get_mem(struct module_env* env, in
  */
 static struct module_func_block dns64_block = {
        "dns64",
-       &dns64_init, &dns64_deinit, &dns64_operate, &dns64_inform_super,
-       &dns64_clear, &dns64_get_mem
+       &module_dummy_init, &module_dummy_init, &dns64_setup, &dns64_desetup,
+       &dns64_operate, &dns64_inform_super, &dns64_clear, &dns64_get_mem
 };
/**
Index: dns64/dns64.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/dns64/dns64.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 dns64.h
--- dns64/dns64.h       20 Nov 2014 00:00:32 -0000      1.1.1.1
+++ dns64/dns64.h       7 Feb 2021 16:02:52 -0000
@@ -50,10 +50,10 @@
 struct module_func_block *dns64_get_funcblock(void);
/** dns64 init */
-int dns64_init(struct module_env* env, int id);
+int dns64_setup(struct module_env* env, int id);
/** dns64 deinit */
-void dns64_deinit(struct module_env* env, int id);
+void dns64_desetup(struct module_env* env, int id);
/** dns64 operate on a query */
 void dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
Index: edns-subnet/subnetmod.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/edns-subnet/subnetmod.c,v
retrieving revision 1.8
diff -u -p -r1.8 subnetmod.c
--- edns-subnet/subnetmod.c     24 Aug 2020 09:41:52 -0000      1.8
+++ edns-subnet/subnetmod.c     7 Feb 2021 16:02:52 -0000
@@ -188,7 +188,7 @@ subnet_markdel(void* key)
 }
int
-subnetmod_init(struct module_env *env, int id)
+subnetmod_setup(struct module_env *env, int id)
 {
        struct subnet_env *sn_env = (struct subnet_env*)calloc(1,
                sizeof(struct subnet_env));
@@ -246,7 +246,7 @@ subnetmod_init(struct module_env *env, i
 }
void
-subnetmod_deinit(struct module_env *env, int id)
+subnetmod_desetup(struct module_env *env, int id)
 {
        struct subnet_env *sn_env;
        if(!env || !env->modinfo[id])
@@ -861,8 +861,10 @@ subnetmod_get_mem(struct module_env *env
* The module function block */
 static struct module_func_block subnetmod_block = {
-       "subnet", &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
-       &subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem
+       "subnet",
+       &module_dummy_init, &module_dummy_init, &subnetmod_setup,
+       &subnetmod_desetup, &subnetmod_operate, &subnetmod_inform_super,
+       &subnetmod_clear, &subnetmod_get_mem
 };
struct module_func_block*
Index: edns-subnet/subnetmod.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/edns-subnet/subnetmod.h,v
retrieving revision 1.5
diff -u -p -r1.5 subnetmod.h
--- edns-subnet/subnetmod.h     24 Aug 2020 09:41:52 -0000      1.5
+++ edns-subnet/subnetmod.h     7 Feb 2021 16:02:52 -0000
@@ -104,10 +104,10 @@ size_t msg_cache_sizefunc(void* k, void*
 struct module_func_block* subnetmod_get_funcblock(void);
/** subnet module init */
-int subnetmod_init(struct module_env* env, int id);
+int subnetmod_setup(struct module_env* env, int id);
/** subnet module deinit */
-void subnetmod_deinit(struct module_env* env, int id);
+void subnetmod_desetup(struct module_env* env, int id);
/** subnet module operate on a query */
 void subnetmod_operate(struct module_qstate* qstate, enum module_ev event,
Index: ipsecmod/ipsecmod.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/ipsecmod/ipsecmod.c,v
retrieving revision 1.3
diff -u -p -r1.3 ipsecmod.c
--- ipsecmod/ipsecmod.c 18 Dec 2019 11:04:13 -0000      1.3
+++ ipsecmod/ipsecmod.c 7 Feb 2021 16:02:52 -0000
@@ -67,7 +67,7 @@ ipsecmod_apply_cfg(struct ipsecmod_env* } int
-ipsecmod_init(struct module_env* env, int id)
+ipsecmod_setup(struct module_env* env, int id)
 {
        struct ipsecmod_env* ipsecmod_env = (struct ipsecmod_env*)calloc(1,
                sizeof(struct ipsecmod_env));
@@ -85,7 +85,7 @@ ipsecmod_init(struct module_env* env, in
 }
void
-ipsecmod_deinit(struct module_env* env, int id)
+ipsecmod_desetup(struct module_env* env, int id)
 {
        struct ipsecmod_env* ipsecmod_env;
        if(!env || !env->modinfo[id])
@@ -598,8 +598,9 @@ ipsecmod_get_mem(struct module_env* env,
  */
 static struct module_func_block ipsecmod_block = {
        "ipsecmod",
-       &ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate,
-       &ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem
+       &module_dummy_init, &module_dummy_init, &ipsecmod_setup,
+       &ipsecmod_desetup, &ipsecmod_operate, &ipsecmod_inform_super,
+       &ipsecmod_clear, &ipsecmod_get_mem
 };
struct module_func_block*
Index: ipsecmod/ipsecmod.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/ipsecmod/ipsecmod.h,v
retrieving revision 1.1
diff -u -p -r1.1 ipsecmod.h
--- ipsecmod/ipsecmod.h 12 Aug 2017 11:22:46 -0000      1.1
+++ ipsecmod/ipsecmod.h 7 Feb 2021 16:02:52 -0000
@@ -74,9 +74,9 @@ struct ipsecmod_qstate {
 };
/** Init the ipsecmod module */
-int ipsecmod_init(struct module_env* env, int id);
+int ipsecmod_setup(struct module_env* env, int id);
 /** Deinit the ipsecmod module */
-void ipsecmod_deinit(struct module_env* env, int id);
+void ipsecmod_desetup(struct module_env* env, int id);
 /** Operate on an event on a query (in qstate). */
 void ipsecmod_operate(struct module_qstate* qstate, enum module_ev event,
        int id, struct outbound_entry* outbound);
Index: ipset/ipset.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/ipset/ipset.c,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 ipset.c
--- ipset/ipset.c       18 Dec 2019 11:02:59 -0000      1.1.1.2
+++ ipset/ipset.c       7 Feb 2021 16:02:52 -0000
@@ -17,9 +17,21 @@
 #include "sldns/wire2str.h"
 #include "sldns/parseutil.h"
+#include <stdint.h>
+
+#ifdef HAVE_NET_PFVAR_H
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <net/pfvar.h>
+typedef intptr_t filter_dev;
+#else
 #include <libmnl/libmnl.h>
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/ipset/ip_set.h>
+typedef struct mnl_socket * filter_dev;
+#endif
#define BUFF_LEN 256 @@ -41,24 +53,95 @@ static int error_response(struct module_
        return 0;
 }
-static struct mnl_socket * open_mnl_socket() {
-       struct mnl_socket *mnl;
+#ifdef HAVE_NET_PFVAR_H
+static void * open_filter() {
+       filter_dev dev;
+
+       dev = open("/dev/pf", O_RDWR);
+       if (dev == -1) {
+               log_err("open(\"/dev/pf\") failed");
+               return NULL;
+       }
+       else
+               return (void *)dev;
+}
+#else
+static void * open_filter() {
+       filter_dev dev;
- mnl = mnl_socket_open(NETLINK_NETFILTER);
-       if (!mnl) {
+       dev = mnl_socket_open(NETLINK_NETFILTER);
+       if (!dev) {
                log_err("ipset: could not open netfilter.");
                return NULL;
        }
- if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) {
-               mnl_socket_close(mnl);
+       if (mnl_socket_bind(dev, 0, MNL_SOCKET_AUTOPID) < 0) {
+               mnl_socket_close(dev);
                log_err("ipset: could not bind netfilter.");
                return NULL;
        }
-       return mnl;
+       return dev;
 }
+#endif
-static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void *ipaddr, int af) {
+#ifdef HAVE_NET_PFVAR_H
+static int add_to_ipset(filter_dev dev, const char *setname, const void 
*ipaddr, int af) {
+       struct pfioc_table io;
+       struct pfr_addr addr;
+       const char *p;
+       int i;
+
+       bzero(&io, sizeof(io));
+       bzero(&addr, sizeof(addr));
+
+       p = strrchr(setname, '/');
+       if (p) {
+               i = p - setname;
+               if (i >= PATH_MAX) {
+                       errno = ENAMETOOLONG;
+                       return -1;
+               }
+               memcpy(io.pfrio_table.pfrt_anchor, setname, i);
+               if (i < PATH_MAX)
+                       io.pfrio_table.pfrt_anchor[i] = '\0';
+               p++;
+       }
+       else
+               p = setname;
+
+       if (strlen(p) >= PF_TABLE_NAME_SIZE) {
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+       strlcpy(io.pfrio_table.pfrt_name, p, PF_TABLE_NAME_SIZE);
+
+       io.pfrio_buffer = &addr;
+       io.pfrio_size = 1;
+       io.pfrio_esize = sizeof(addr);
+
+       switch (af) {
+               case AF_INET:
+                       addr.pfra_ip4addr = *(struct in_addr *)ipaddr;
+                       addr.pfra_net = 32;
+                       break;
+               case AF_INET6:
+                       addr.pfra_ip6addr = *(struct in6_addr *)ipaddr;
+                       addr.pfra_net = 128;
+                       break;
+               default:
+               errno = EAFNOSUPPORT;
+               return -1;
+       }
+       addr.pfra_af = af;
+
+       if (ioctl(dev, DIOCRADDADDRS, &io) == -1) {
+               log_err("ioctl failed: %s", strerror(errno));
+               return -1;
+       }
+       return 0;
+}
+#else
+static int add_to_ipset(filter_dev dev, const char *setname, const void 
*ipaddr, int af) {
        struct nlmsghdr *nlh;
        struct nfgenmsg *nfg;
        struct nlattr *nested[2];
@@ -91,14 +174,15 @@ static int add_to_ipset(struct mnl_socke
        mnl_attr_nest_end(nlh, nested[1]);
        mnl_attr_nest_end(nlh, nested[0]);
- if (mnl_socket_sendto(mnl, nlh, nlh->nlmsg_len) < 0) {
+       if (mnl_socket_sendto(dev, nlh, nlh->nlmsg_len) < 0) {
                return -1;
        }
        return 0;
 }
+#endif
static void
-ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
+ipset_add_rrset_data(struct ipset_env *ie,
        struct packed_rrset_data *d, const char* setname, int af,
        const char* dname)
 {
@@ -123,12 +207,16 @@ ipset_add_rrset_data(struct ipset_env *i
                                        snprintf(ip, sizeof(ip), 
"(inet_ntop_error)");
                                verbose(VERB_QUERY, "ipset: add %s to %s for 
%s", ip, setname, dname);
                        }
-                       ret = add_to_ipset(mnl, setname, rr_data + 2, af);
+                       ret = add_to_ipset((filter_dev)ie->dev, setname, 
rr_data + 2, af);
                        if (ret < 0) {
                                log_err("ipset: could not add %s into %s", 
dname, setname);
- mnl_socket_close(mnl);
-                               ie->mnl = NULL;
+#if HAVE_NET_PFVAR_H
+                               /* don't close as we might not be able to open 
again due to dropped privs */
+#else
+                               mnl_socket_close((filter_dev)ie->dev);
+                               ie->dev = NULL;
+#endif
                                break;
                        }
                }
@@ -137,7 +225,7 @@ ipset_add_rrset_data(struct ipset_env *i
static int
 ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
-       struct mnl_socket *mnl, struct ub_packed_rrset_key *rrset,
+       struct ub_packed_rrset_key *rrset,
        const char *setname, int af)
 {
        static char dname[BUFF_LEN];
@@ -158,13 +246,16 @@ ipset_check_zones_for_rrset(struct modul
for (p = env->cfg->local_zones_ipset; p; p = p->next) {
                plen = strlen(p->str);
+               if (p->str[plen - 1] == '.') {
+                       plen--;
+               }
if (dlen >= plen) {
                        s = dname + (dlen - plen);
if (strncasecmp(p->str, s, plen) == 0) {
                                d = (struct 
packed_rrset_data*)rrset->entry.data;
-                               ipset_add_rrset_data(ie, mnl, d, setname,
+                               ipset_add_rrset_data(ie, d, setname,
                                        af, dname);
                                break;
                        }
@@ -174,8 +265,6 @@ ipset_check_zones_for_rrset(struct modul
 }
static int ipset_update(struct module_env *env, struct dns_msg *return_msg, struct ipset_env *ie) {
-       struct mnl_socket *mnl;
-
        size_t i;
const char *setname;
@@ -184,17 +273,17 @@ static int ipset_update(struct module_en
int af; -
-       mnl = (struct mnl_socket *)ie->mnl;
-       if (!mnl) {
+#ifdef HAVE_NET_PFVAR_H
+#else
+       if (!ie->dev) {
                // retry to create mnl socket
-               mnl = open_mnl_socket();
-               if (!mnl) {
+               ie->dev = open_filter();
+               if (!ie->dev) {
+                       log_warn("ipset open_filter failed");
                        return -1;
                }
-
-               ie->mnl = mnl;
        }
+#endif
for (i = 0; i < return_msg->rep->rrset_count; ++i) {
                setname = NULL;
@@ -203,18 +292,18 @@ static int ipset_update(struct module_en
if (rrset->rk.type == htons(LDNS_RR_TYPE_A)) {
                        af = AF_INET;
-                       if ((ie->v4_enabled == 1)) {
+                       if (ie->v4_enabled == 1) {
                                setname = ie->name_v4;
                        }
                } else {
                        af = AF_INET6;
-                       if ((ie->v6_enabled == 1)) {
+                       if (ie->v6_enabled == 1) {
                                setname = ie->name_v6;
                        }
                }
if (setname) {
-                       if(ipset_check_zones_for_rrset(env, ie, mnl, rrset,
+                       if(ipset_check_zones_for_rrset(env, ie, rrset,
                                setname, af) == -1)
                                return -1;
                }
@@ -226,7 +315,7 @@ static int ipset_update(struct module_en
 int ipset_init(struct module_env* env, int id) {
        struct ipset_env *ipset_env;
- ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env));
+       ipset_env = (struct ipset_env *)malloc(sizeof(struct ipset_env));
        if (!ipset_env) {
                log_err("malloc failure");
                return 0;
@@ -234,7 +323,28 @@ int ipset_init(struct module_env* env, i
env->modinfo[id] = (void *)ipset_env; - ipset_env->mnl = NULL;
+#ifdef HAVE_NET_PFVAR_H
+       ipset_env->dev = open_filter();
+       if (!ipset_env->dev) {
+               log_err("ipset open_filter failed");
+               return 0;
+       }
+#else
+       ipset_env->dev = NULL;
+#endif
+       return 1;
+}
+
+int ipset_deinit(struct module_env* env, int id) {
+       struct ipset_env *ipset_env = env->modinfo[id];
+       close((filter_dev)ipset_env->dev);
+       free(ipset_env);
+       env->modinfo[id] = NULL;
+       return 1;
+}
+
+int ipset_setup(struct module_env* env, int id) {
+       struct ipset_env *ipset_env = env->modinfo[id];
ipset_env->name_v4 = env->cfg->ipset_name_v4;
        ipset_env->name_v6 = env->cfg->ipset_name_v6;
@@ -250,8 +360,8 @@ int ipset_init(struct module_env* env, i
        return 1;
 }
-void ipset_deinit(struct module_env *env, int id) {
-       struct mnl_socket *mnl;
+void ipset_desetup(struct module_env *env, int id) {
+       filter_dev dev;
        struct ipset_env *ipset_env;
if (!env || !env->modinfo[id]) {
@@ -260,10 +370,14 @@ void ipset_deinit(struct module_env *env
ipset_env = (struct ipset_env *)env->modinfo[id]; - mnl = (struct mnl_socket *)ipset_env->mnl;
-       if (mnl) {
-               mnl_socket_close(mnl);
-               ipset_env->mnl = NULL;
+       dev = (filter_dev)ipset_env->dev;
+       if (dev) {
+#if HAVE_NET_PFVAR_H
+               close(dev);
+#else
+               mnl_socket_close(dev);
+#endif
+               ipset_env->dev = NULL;
        }
free(ipset_env);
@@ -373,8 +487,8 @@ size_t ipset_get_mem(struct module_env *
  */
 static struct module_func_block ipset_block = {
        "ipset",
-       &ipset_init, &ipset_deinit, &ipset_operate,
-       &ipset_inform_super, &ipset_clear, &ipset_get_mem
+       &ipset_init, &ipset_deinit, &ipset_setup, &ipset_desetup,
+       &ipset_operate, &ipset_inform_super, &ipset_clear, &ipset_get_mem
 };
struct module_func_block * ipset_get_funcblock(void) {
Index: ipset/ipset.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/ipset/ipset.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 ipset.h
--- ipset/ipset.h       11 Sep 2019 14:11:38 -0000      1.1.1.1
+++ ipset/ipset.h       7 Feb 2021 16:02:52 -0000
@@ -37,7 +37,7 @@ extern "C" {
 #endif
struct ipset_env {
-    void* mnl;
+       void* dev;
int v4_enabled;
        int v6_enabled;
@@ -53,7 +53,11 @@ struct ipset_qstate {
 /** Init the ipset module */
 int ipset_init(struct module_env* env, int id);
 /** Deinit the ipset module */
-void ipset_deinit(struct module_env* env, int id);
+int ipset_deinit(struct module_env* env, int id);
+/** Setup the ipset module */
+int ipset_setup(struct module_env* env, int id);
+/** Desetup the ipset module */
+void ipset_desetup(struct module_env* env, int id);
 /** Operate on an event on a query (in qstate). */
 void ipset_operate(struct module_qstate* qstate, enum module_ev event,
        int id, struct outbound_entry* outbound);
Index: iterator/iterator.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/iterator/iterator.c,v
retrieving revision 1.27
diff -u -p -r1.27 iterator.c
--- iterator/iterator.c 28 Oct 2020 11:31:07 -0000      1.27
+++ iterator/iterator.c 7 Feb 2021 16:02:52 -0000
@@ -75,7 +75,7 @@ int UNKNOWN_SERVER_NICENESS = 376;
 static void target_count_increase_nx(struct iter_qstate* iq, int num);
int -iter_init(struct module_env* env, int id)
+iter_setup(struct module_env* env, int id)
 {
        struct iter_env* iter_env = (struct iter_env*)calloc(1,
                sizeof(struct iter_env));
@@ -109,7 +109,7 @@ caps_free(struct rbnode_type* n, void* A
 }
void -iter_deinit(struct module_env* env, int id)
+iter_desetup(struct module_env* env, int id)
 {
        struct iter_env* iter_env;
        if(!env || !env->modinfo[id])
@@ -3940,8 +3940,8 @@ iter_get_mem(struct module_env* env, int
  */
 static struct module_func_block iter_block = {
        "iterator",
- &iter_init, &iter_deinit, &iter_operate, &iter_inform_super, - &iter_clear, &iter_get_mem
+       &module_dummy_init, &module_dummy_init, &iter_setup, &iter_desetup,
+       &iter_operate, &iter_inform_super, &iter_clear, &iter_get_mem
 };
struct module_func_block* Index: iterator/iterator.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/iterator/iterator.h,v
retrieving revision 1.15
diff -u -p -r1.15 iterator.h
--- iterator/iterator.h 24 Aug 2020 09:41:52 -0000      1.15
+++ iterator/iterator.h 7 Feb 2021 16:02:52 -0000
@@ -439,10 +439,10 @@ const char* iter_state_to_string(enum it
 int iter_state_is_responsestate(enum iter_state s);
/** iterator init */
-int iter_init(struct module_env* env, int id);
+int iter_setup(struct module_env* env, int id);
/** iterator deinit */
-void iter_deinit(struct module_env* env, int id);
+void iter_desetup(struct module_env* env, int id);
/** iterator operate on a query */
 void iter_operate(struct module_qstate* qstate, enum module_ev event, int id,
Index: libunbound/context.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/libunbound/context.c,v
retrieving revision 1.10
diff -u -p -r1.10 context.c
--- libunbound/context.c        10 Dec 2020 21:44:58 -0000      1.10
+++ libunbound/context.c        7 Feb 2021 16:02:52 -0000
@@ -70,6 +70,8 @@ context_finalize(struct ub_ctx* ctx)
                log_init(cfg->logfile, cfg->use_syslog, NULL);
        }
        config_apply(cfg);
+       if(!modstack_init(&ctx->mods, cfg->module_conf, ctx->env))
+               return UB_INITFAIL;
        if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env))
                return UB_INITFAIL;
        log_edns_known_options(VERB_ALGO, ctx->env);
Index: libunbound/libunbound.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/libunbound/libunbound.c,v
retrieving revision 1.17
diff -u -p -r1.17 libunbound.c
--- libunbound/libunbound.c     10 Dec 2020 21:44:58 -0000      1.17
+++ libunbound/libunbound.c     7 Feb 2021 16:02:52 -0000
@@ -169,7 +169,7 @@ static struct ub_ctx* ub_ctx_create_nopi
        ctx->env->alloc = &ctx->superalloc;
        ctx->env->worker = NULL;
        ctx->env->need_to_validate = 0;
-       modstack_init(&ctx->mods);
+       memset(&ctx->mods, 0, sizeof(ctx->mods));
        rbtree_init(&ctx->queries, &context_query_cmp);
        return ctx;
 }
@@ -185,6 +185,7 @@ ub_ctx_create(void)
                ub_randfree(ctx->seed_rnd);
                config_delete(ctx->env->cfg);
                modstack_desetup(&ctx->mods, ctx->env);
+               modstack_deinit(&ctx->mods, ctx->env);
                edns_known_options_delete(ctx->env);
                edns_strings_delete(ctx->env->edns_strings);
                free(ctx->env);
@@ -198,6 +199,7 @@ ub_ctx_create(void)
                ub_randfree(ctx->seed_rnd);
                config_delete(ctx->env->cfg);
                modstack_desetup(&ctx->mods, ctx->env);
+               modstack_deinit(&ctx->mods, ctx->env);
                edns_known_options_delete(ctx->env);
                edns_strings_delete(ctx->env->edns_strings);
                free(ctx->env);
@@ -318,6 +320,7 @@ ub_ctx_delete(struct ub_ctx* ctx)
        libworker_delete_event(ctx->event_worker);
modstack_desetup(&ctx->mods, ctx->env);
+       modstack_deinit(&ctx->mods, ctx->env);
        a = ctx->alloc_list;
        while(a) {
                na = a->super;
Index: respip/respip.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/respip/respip.c,v
retrieving revision 1.10
diff -u -p -r1.10 respip.c
--- respip/respip.c     10 Dec 2020 21:44:58 -0000      1.10
+++ respip/respip.c     7 Feb 2021 16:02:52 -0000
@@ -547,7 +547,7 @@ copy_rrset(const struct ub_packed_rrset_
 }
int
-respip_init(struct module_env* env, int id)
+respip_setup(struct module_env* env, int id)
 {
        (void)env;
        (void)id;
@@ -555,7 +555,7 @@ respip_init(struct module_env* env, int } void
-respip_deinit(struct module_env* env, int id)
+respip_desetup(struct module_env* env, int id)
 {
        (void)env;
        (void)id;
@@ -1273,8 +1273,8 @@ respip_get_mem(struct module_env* env, i
  */
 static struct module_func_block respip_block = {
        "respip",
-       &respip_init, &respip_deinit, &respip_operate, &respip_inform_super,
-       &respip_clear, &respip_get_mem
+       &module_dummy_init, &module_dummy_init, &respip_setup, &respip_desetup, 
&respip_operate,
+       &respip_inform_super, &respip_clear, &respip_get_mem
 };
struct module_func_block*
Index: respip/respip.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/respip/respip.h,v
retrieving revision 1.2
diff -u -p -r1.2 respip.h
--- respip/respip.h     19 Mar 2020 17:48:07 -0000      1.2
+++ respip/respip.h     7 Feb 2021 16:02:52 -0000
@@ -192,10 +192,10 @@ int respip_rewrite_reply(const struct qu
 struct module_func_block* respip_get_funcblock(void);
/** response-ip init */
-int respip_init(struct module_env* env, int id);
+int respip_setup(struct module_env* env, int id);
/** response-ip deinit */
-void respip_deinit(struct module_env* env, int id);
+void respip_desetup(struct module_env* env, int id);
/** response-ip operate on a query */
 void respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
Index: services/modstack.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/modstack.c,v
retrieving revision 1.6
diff -u -p -r1.6 modstack.c
--- services/modstack.c 24 Aug 2020 09:41:53 -0000      1.6
+++ services/modstack.c 7 Feb 2021 16:02:52 -0000
@@ -88,14 +88,7 @@ count_modules(const char* s)
         return num;
 }
-void -modstack_init(struct module_stack* stack)
-{
-       stack->num = 0;
-       stack->mod = NULL;
-}
-
-int +int
 modstack_config(struct module_stack* stack, const char* module_conf)
 {
         int i;
@@ -219,18 +212,17 @@ module_func_block* module_factory(const return NULL;
 }
-int -modstack_setup(struct module_stack* stack, const char* module_conf,
+int
+modstack_init(struct module_stack* stack, const char* module_conf,
        struct module_env* env)
 {
-        int i;
-        if(stack->num != 0)
-                modstack_desetup(stack, env);
+       int i;
+       if (stack->num != 0)
+               fatal_exit("unexpected already initialised modules");
         /* fixed setup of the modules */
         if(!modstack_config(stack, module_conf)) {
                return 0;
         }
-        env->need_to_validate = 0; /* set by module init below */
         for(i=0; i<stack->num; i++) {
                 verbose(VERB_OPS, "init module %d: %s",
                         i, stack->mod[i]->name);
@@ -244,11 +236,48 @@ modstack_setup(struct module_stack* stac
        return 1;
 }
-void +int
+modstack_setup(struct module_stack* stack, const char* module_conf,
+       struct module_env* env)
+{
+        int i;
+        env->need_to_validate = 0; /* set by module setup below */
+        for(i=0; i<stack->num; i++) {
+               while(*module_conf && isspace(*module_conf))
+                       module_conf++;
+                if(strncmp(stack->mod[i]->name, module_conf,
+                       strlen(stack->mod[i]->name))) {
+                       log_err("changed module ordering during reload not 
supported");
+                       return 0;
+               }
+               module_conf += strlen(stack->mod[i]->name);
+                verbose(VERB_OPS, "setup module %d: %s",
+                        i, stack->mod[i]->name);
+                fptr_ok(fptr_whitelist_mod_setup(stack->mod[i]->setup));
+                if(!(*stack->mod[i]->setup)(env, i)) {
+                        log_err("module setup for module %s failed",
+                                stack->mod[i]->name);
+                       return 0;
+                }
+        }
+       return 1;
+}
+
+void
 modstack_desetup(struct module_stack* stack, struct module_env* env)
 {
         int i;
         for(i=0; i<stack->num; i++) {
+                fptr_ok(fptr_whitelist_mod_desetup(stack->mod[i]->desetup));
+                (*stack->mod[i]->desetup)(env, i);
+        }
+}
+
+void
+modstack_deinit(struct module_stack* stack, struct module_env* env)
+{
+        int i;
+        for(i=0; i<stack->num; i++) {
                 fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit));
                 (*stack->mod[i]->deinit)(env, i);
         }
@@ -257,7 +286,7 @@ modstack_desetup(struct module_stack* st
         stack->mod = NULL;
 }
-int +int
 modstack_find(struct module_stack* stack, const char* name)
 {
        int i;
Index: services/modstack.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/modstack.h,v
retrieving revision 1.2
diff -u -p -r1.2 modstack.h
--- services/modstack.h 12 Aug 2017 11:22:46 -0000      1.2
+++ services/modstack.h 7 Feb 2021 16:02:52 -0000
@@ -55,10 +55,16 @@ struct module_stack {
 };
/**
- * Init a stack of modules
- * @param stack: initialised as empty.
+ * Initialises modules and assignes ids.
+ * @param stack: Expected empty, filled according to module_conf
+ * @param module_conf: string what modules to initialize
+ * @param env: module environment which is inited by the modules.
+ *     environment should have a superalloc, cfg,
+ *     env.need_to_validate is set by the modules.
+ * @return on false a module init failed.
  */
-void modstack_init(struct module_stack* stack);
+int modstack_init(struct module_stack* stack, const char* module_conf,
+       struct module_env* env);
/**
  * Read config file module settings and set up the modfunc block
@@ -83,10 +89,10 @@ struct module_func_block* module_factory
 const char** module_list_avail(void);
/**
- * Setup modules. Assigns ids and calls module_init.
- * @param stack: if not empty beforehand, it will be desetup()ed.
- *     It is then modstack_configged().
- * @param module_conf: string what modules to insert.
+ * Setup modules. Calls module_setup().
+ * @param stack: It is modstack_setupped().
+ * @param module_conf: module ordering to check against the ordering in stack.
+ * fails on changed ordering.
  * @param env: module environment which is inited by the modules.
  *     environment should have a superalloc, cfg,
  *     env.need_to_validate is set by the modules.
@@ -96,11 +102,18 @@ int modstack_setup(struct module_stack* struct module_env* env); /**
- * Desetup the modules, deinit, delete.
+ * Desetup the modules
  * @param stack: made empty.
  * @param env: module env for module deinit() calls.
  */
 void modstack_desetup(struct module_stack* stack, struct module_env* env);
+
+/**
+ * Deinit the modules, deinit, delete.
+ * @param stack: made empty.
+ * @param env: module env for module deinit() calls.
+ */
+void modstack_deinit(struct module_stack* stack, struct module_env* env);
/**
  * Find index of module by name.
Index: smallapp/unbound-checkconf.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/smallapp/unbound-checkconf.c,v
retrieving revision 1.16
diff -u -p -r1.16 unbound-checkconf.c
--- smallapp/unbound-checkconf.c        28 Oct 2020 11:31:07 -0000      1.16
+++ smallapp/unbound-checkconf.c        7 Feb 2021 16:02:52 -0000
@@ -138,9 +138,11 @@ check_mod(struct config_file* cfg, struc
                fatal_exit("out of memory");
        if(!edns_known_options_init(&env))
                fatal_exit("out of memory");
-       if(!(*fb->init)(&env, 0)) {
+       if(!(*fb->setup)(&env, 0))
                fatal_exit("bad config for %s module", fb->name);
-       }
+       if(!(*fb->setup)(&env, 0))
+               fatal_exit("bad config for %s module", fb->name);
+       (*fb->desetup)(&env, 0);
        (*fb->deinit)(&env, 0);
        sldns_buffer_free(env.scratch_buffer);
        regional_destroy(env.scratch);
Index: util/fptr_wlist.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/fptr_wlist.c,v
retrieving revision 1.20
diff -u -p -r1.20 fptr_wlist.c
--- util/fptr_wlist.c   10 Dec 2020 21:44:58 -0000      1.20
+++ util/fptr_wlist.c   7 Feb 2021 16:02:52 -0000
@@ -390,58 +390,78 @@ fptr_whitelist_modenv_detect_cycle(int (
        return 0;
 }
-int +int
 fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id))
 {
-       if(fptr == &iter_init) return 1;
-       else if(fptr == &val_init) return 1;
-       else if(fptr == &dns64_init) return 1;
-       else if(fptr == &respip_init) return 1;
+       if(fptr == &module_dummy_init) return 1;
+#ifdef USE_IPSET
+       else if(fptr == &ipset_init) return 1;
+#endif
+       return 0;
+}
+
+int
+fptr_whitelist_mod_deinit(int (*fptr)(struct module_env* env, int id))
+{
+       if(fptr == &module_dummy_init) return 1;
+#ifdef USE_IPSET
+       else if(fptr == &ipset_deinit) return 1;
+#endif
+       return 0;
+}
+
+int
+fptr_whitelist_mod_setup(int (*fptr)(struct module_env* env, int id))
+{
+       if(fptr == &iter_setup) return 1;
+       else if(fptr == &val_setup) return 1;
+       else if(fptr == &dns64_setup) return 1;
+       else if(fptr == &respip_setup) return 1;
 #ifdef WITH_PYTHONMODULE
-       else if(fptr == &pythonmod_init) return 1;
+       else if(fptr == &pythonmod_setup) return 1;
 #endif
 #ifdef WITH_DYNLIBMODULE
        else if(fptr == &dynlibmod_init) return 1;
 #endif
 #ifdef USE_CACHEDB
-       else if(fptr == &cachedb_init) return 1;
+       else if(fptr == &cachedb_setup) return 1;
 #endif
 #ifdef USE_IPSECMOD
-       else if(fptr == &ipsecmod_init) return 1;
+       else if(fptr == &ipsecmod_setup) return 1;
 #endif
 #ifdef CLIENT_SUBNET
-       else if(fptr == &subnetmod_init) return 1;
+       else if(fptr == &subnetmod_setup) return 1;
 #endif
 #ifdef USE_IPSET
-       else if(fptr == &ipset_init) return 1;
+       else if(fptr == &ipset_setup) return 1;
 #endif
        return 0;
 }
int -fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id))
+fptr_whitelist_mod_desetup(void (*fptr)(struct module_env* env, int id))
 {
-       if(fptr == &iter_deinit) return 1;
-       else if(fptr == &val_deinit) return 1;
-       else if(fptr == &dns64_deinit) return 1;
-       else if(fptr == &respip_deinit) return 1;
+       if(fptr == &iter_desetup) return 1;
+       else if(fptr == &val_desetup) return 1;
+       else if(fptr == &dns64_desetup) return 1;
+       else if(fptr == &respip_desetup) return 1;
 #ifdef WITH_PYTHONMODULE
-       else if(fptr == &pythonmod_deinit) return 1;
+       else if(fptr == &pythonmod_desetup) return 1;
 #endif
 #ifdef WITH_DYNLIBMODULE
        else if(fptr == &dynlibmod_deinit) return 1;
 #endif
 #ifdef USE_CACHEDB
-       else if(fptr == &cachedb_deinit) return 1;
+       else if(fptr == &cachedb_desetup) return 1;
 #endif
 #ifdef USE_IPSECMOD
-       else if(fptr == &ipsecmod_deinit) return 1;
+       else if(fptr == &ipsecmod_desetup) return 1;
 #endif
 #ifdef CLIENT_SUBNET
-       else if(fptr == &subnetmod_deinit) return 1;
+       else if(fptr == &subnetmod_desetup) return 1;
 #endif
 #ifdef USE_IPSET
-       else if(fptr == &ipset_deinit) return 1;
+       else if(fptr == &ipset_desetup) return 1;
 #endif
        return 0;
 }
Index: util/fptr_wlist.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/fptr_wlist.h,v
retrieving revision 1.10
diff -u -p -r1.10 fptr_wlist.h
--- util/fptr_wlist.h   19 Mar 2020 17:48:08 -0000      1.10
+++ util/fptr_wlist.h   7 Feb 2021 16:02:52 -0000
@@ -270,12 +270,20 @@ int fptr_whitelist_modenv_detect_cycle(i
 int fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id));
/**
- * Check function pointer whitelist for module deinit call values.
+ * Check function pointer whitelist for module setup call values.
  *
  * @param fptr: function pointer to check.
  * @return false if not in whitelist.
  */
-int fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id));
+int fptr_whitelist_mod_setup(int (*fptr)(struct module_env* env, int id));
+
+/**
+ * Check function pointer whitelist for module desetup call values.
+ *
+ * @param fptr: function pointer to check.
+ * @return false if not in whitelist.
+ */
+int fptr_whitelist_mod_desetup(void (*fptr)(struct module_env* env, int id));
/**
  * Check function pointer whitelist for module operate call values.
Index: util/module.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/module.c,v
retrieving revision 1.6
diff -u -p -r1.6 module.c
--- util/module.c       20 Sep 2018 23:15:40 -0000      1.6
+++ util/module.c       7 Feb 2021 16:02:52 -0000
@@ -246,3 +246,8 @@ copy_state_to_super(struct module_qstate
                super->was_ratelimited = qstate->was_ratelimited;
        }
 }
+
+int module_dummy_init(struct module_env* env, int id)
+{
+       return 1;
+}
Index: util/module.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/module.h,v
retrieving revision 1.11
diff -u -p -r1.11 module.h
--- util/module.h       10 Dec 2020 21:44:58 -0000      1.11
+++ util/module.h       7 Feb 2021 16:02:52 -0000
@@ -674,21 +674,40 @@ struct module_func_block {
        /** text string name of module */
        const char* name;
- /** - * init the module. Called once for the global state.
+       /**
+        * initialise the module. This is called only once at startup.
+        * Privileged operations like opening device files may be done here.
+        * @param id: module id number.
+        * return: 0 on error
+        */
+       int (*init)(struct module_env* env, int id);
+
+       /**
+        * deinitialise the module. This is called only once before shutdown to
+        * free resources allocated during init().
+        * Closing privileged ports or files must be done here.
+        * @param id: module id number.
+        * return: 0 on error
+        */
+       int (*deinit)(struct module_env* env, int id);
+
+       /**
+        * setup the module. Called when restarting or reloading the
+        * daemon.
         * This is the place to apply settings from the config file.
         * @param env: module environment.
         * @param id: module id number.
         * return: 0 on error
         */
-       int (*init)(struct module_env* env, int id);
+       int (*setup)(struct module_env* env, int id);
/**
-        * de-init, delete, the module. Called once for the global state.
+        * de-setup, undo stuff done during setup().
+        * Called before reloading the daemon.
         * @param env: module environment.
         * @param id: module id number.
         */
-       void (*deinit)(struct module_env* env, int id);
+       void (*desetup)(struct module_env* env, int id);
/**
         * accept a new query, or work further on existing query.
@@ -859,5 +878,7 @@ void log_edns_known_options(enum verbosi
  */
 void copy_state_to_super(struct module_qstate* qstate, int id,
        struct module_qstate* super);
+
+int module_dummy_init(struct module_env* env, int id);
#endif /* UTIL_MODULE_H */
Index: validator/validator.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/validator/validator.c,v
retrieving revision 1.15
diff -u -p -r1.15 validator.c
--- validator/validator.c       28 Oct 2020 11:31:08 -0000      1.15
+++ validator/validator.c       7 Feb 2021 16:02:52 -0000
@@ -165,7 +165,7 @@ val_apply_cfg(struct module_env* env, st
 void ecdsa_evp_workaround_init(void);
 #endif
 int
-val_init(struct module_env* env, int id)
+val_setup(struct module_env* env, int id)
 {
        struct val_env* val_env = (struct val_env*)calloc(1,
                sizeof(struct val_env));
@@ -190,7 +190,7 @@ val_init(struct module_env* env, int id)
 }
void
-val_deinit(struct module_env* env, int id)
+val_desetup(struct module_env* env, int id)
 {
        struct val_env* val_env;
        if(!env || !env->modinfo[id])
@@ -2895,8 +2895,8 @@ val_get_mem(struct module_env* env, int */
 static struct module_func_block val_block = {
        "validator",
-       &val_init, &val_deinit, &val_operate, &val_inform_super, &val_clear,
-       &val_get_mem
+       &module_dummy_init, &module_dummy_init, &val_setup, &val_desetup,
+       &val_operate, &val_inform_super, &val_clear, &val_get_mem
 };
struct module_func_block* Index: validator/validator.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/validator/validator.h,v
retrieving revision 1.5
diff -u -p -r1.5 validator.h
--- validator/validator.h       28 Oct 2020 11:31:08 -0000      1.5
+++ validator/validator.h       7 Feb 2021 16:02:52 -0000
@@ -231,10 +231,10 @@ struct module_func_block* val_get_funcbl
 const char* val_state_to_string(enum val_state state);
/** validator init */
-int val_init(struct module_env* env, int id);
+int val_setup(struct module_env* env, int id);
/** validator deinit */
-void val_deinit(struct module_env* env, int id);
+void val_desetup(struct module_env* env, int id);
/** validator operate on a query */
 void val_operate(struct module_qstate* qstate, enum module_ev event, int id,

Reply via email to