]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- ACL per interface: refactor, complete testing and a bugfix for
authorGeorge Thessalonikefs <george@nlnetlabs.nl>
Sun, 11 Sep 2022 18:57:41 +0000 (20:57 +0200)
committerGeorge Thessalonikefs <george@nlnetlabs.nl>
Sun, 11 Sep 2022 18:57:41 +0000 (20:57 +0200)
  interface names.

14 files changed:
Makefile.in
daemon/acl_list.c
daemon/acl_list.h
daemon/daemon.c
services/listen_dnsport.c
services/listen_dnsport.h
testcode/fake_event.c
testdata/acl_interface.tdir/acl_interface.conf
testdata/acl_interface.tdir/acl_interface.pre
testdata/acl_interface.tdir/acl_interface.test.scenario
testdata/acl_interface.tdir/acl_interface.testns
util/fptr_wlist.c
util/storage/dnstree.c
util/storage/dnstree.h

index bf78a694d5693a5b888aa06eaf1e9a8329b7dce3..3189731ad52fae6eb5ac6fe4b959ff3b1f9b4b70 100644 (file)
@@ -139,7 +139,7 @@ validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \
 edns-subnet/edns-subnet.c edns-subnet/subnetmod.c \
 edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c \
 $(CACHEDB_SRC) respip/respip.c $(CHECKLOCK_SRC) \
-$(DNSTAP_SRC) $(DNSCRYPT_SRC) $(IPSECMOD_SRC) $(IPSET_SRC) daemon/acl_list.c
+$(DNSTAP_SRC) $(DNSCRYPT_SRC) $(IPSECMOD_SRC) $(IPSET_SRC)
 COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
 as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
 iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
@@ -154,7 +154,7 @@ val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo $(CACHEDB_OBJ) authzone.lo
 $(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
 $(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo
 COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
-outside_network.lo acl_list.lo
+outside_network.lo
 COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
 # set to $COMMON_OBJ or to "" if --enableallsymbols
 COMMON_OBJ_ALL_SYMBOLS=@COMMON_OBJ_ALL_SYMBOLS@
@@ -186,9 +186,9 @@ readhex.lo testpkts.lo unitldns.lo unitecs.lo unitauth.lo unitzonemd.lo \
 unittcpreuse.lo
 UNITTEST_OBJ_LINK=$(UNITTEST_OBJ) worker_cb.lo $(COMMON_OBJ) $(SLDNS_OBJ) \
 $(COMPAT_OBJ)
-DAEMON_SRC=daemon/cachedump.c daemon/daemon.c \
+DAEMON_SRC=daemon/acl_list.c daemon/cachedump.c daemon/daemon.c \
 daemon/remote.c daemon/stats.c daemon/unbound.c daemon/worker.c @WIN_DAEMON_SRC@
-DAEMON_OBJ=cachedump.lo daemon.lo \
+DAEMON_OBJ=acl_list.lo cachedump.lo daemon.lo \
 shm_main.lo remote.lo stats.lo unbound.lo \
 worker.lo @WIN_DAEMON_OBJ@
 DAEMON_OBJ_LINK=$(DAEMON_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \
index 5ec4122a4573ee86a9aad1772fdaffa418472060..05b720bd538b93b34c9c2fa74b2fcb80d266b051 100644 (file)
@@ -142,8 +142,8 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
 
 /** find or create node (NULL on parse or error) */
 static struct acl_addr*
-acl_find_or_create(struct acl_list* acl, const char* str, int is_interface,
-       int port)
+acl_find_or_create_str2addr(struct acl_list* acl, const char* str,
+       int is_interface, int port)
 {
        struct acl_addr* node;
        struct sockaddr_storage addr;
@@ -174,6 +174,27 @@ acl_find_or_create(struct acl_list* acl, const char* str, int is_interface,
        return node;
 }
 
+/** find or create node (NULL on error) */
+static struct acl_addr*
+acl_find_or_create(struct acl_list* acl, struct sockaddr_storage* addr,
+       socklen_t addrlen, enum acl_access control)
+{
+       struct acl_addr* node;
+       int net = (addr_is_ip6(addr, addrlen)?128:32);
+       /* find or create node */
+       if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, addr,
+               addrlen, net))) {
+               /* create node;
+                * can override with specific access-control: cfg */
+               if(!(node=(struct acl_addr*)acl_list_insert(acl, addr,
+                       addrlen, net, control, 1))) {
+                       log_err("out of memory");
+                       return NULL;
+               }
+       }
+       return node;
+}
+
 /** apply acl_interface string */
 static int
 acl_interface_str_cfg(struct acl_list* acl_interface, const char* interface,
@@ -184,7 +205,7 @@ acl_interface_str_cfg(struct acl_list* acl_interface, const char* interface,
        if(!parse_acl_access(s2, &control)) {
                return 0;
        }
-       if(!(node=acl_find_or_create(acl_interface, interface, 1, port))) {
+       if(!(node=acl_find_or_create_str2addr(acl_interface, interface, 1, port))) {
                log_err("cannot update ACL on non-configured interface: %s %d",
                        interface, port);
                return 0;
@@ -194,25 +215,11 @@ acl_interface_str_cfg(struct acl_list* acl_interface, const char* interface,
 }
 
 struct acl_addr*
-acl_interface_insert(struct acl_list* acl_interface, const char* interface,
-       const char* s2, int port)
+acl_interface_insert(struct acl_list* acl_interface,
+       struct sockaddr_storage* addr, socklen_t addrlen,
+       enum acl_access control)
 {
-       struct acl_addr* node;
-       struct sockaddr_storage addr;
-       socklen_t addrlen;
-       enum acl_access control;
-       int net = (str_is_ip6(interface)?128:32);
-       if(!parse_acl_access(s2, &control)) {
-               return NULL;
-       }
-       if((node=acl_find_or_create(acl_interface, interface, 1, port))) {
-               return node;
-       }
-       if(!extstrtoaddr(interface, &addr, &addrlen, port)) {
-               log_err("cannot parse access control: %s %s", interface, s2);
-               return NULL;
-       }
-       return acl_list_insert(acl_interface, &addr, addrlen, net, control, 1);
+       return acl_find_or_create(acl_interface, addr, addrlen, control);
 }
 
 /** apply acl_tag string */
@@ -221,7 +228,7 @@ acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap,
        size_t bitmaplen, int is_interface, int port)
 {
        struct acl_addr* node;
-       if(!(node=acl_find_or_create(acl, str, is_interface, port))) {
+       if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
                if(is_interface)
                        log_err("non-configured interface: %s", str);
                return 0;
@@ -241,7 +248,7 @@ acl_list_view_cfg(struct acl_list* acl, const char* str, const char* str2,
        struct views* vs, int is_interface, int port)
 {
        struct acl_addr* node;
-       if(!(node=acl_find_or_create(acl, str, is_interface, port))) {
+       if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
                if(is_interface)
                        log_err("non-configured interface: %s", str);
                return 0;
@@ -264,7 +271,7 @@ acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg,
        struct acl_addr* node;
        int tagid;
        enum localzone_type t;
-       if(!(node=acl_find_or_create(acl, str, is_interface, port))) {
+       if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
                if(is_interface)
                        log_err("non-configured interface: %s", str);
                return 0;
@@ -357,7 +364,7 @@ acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg,
        struct acl_addr* node;
        int tagid;
        char* dupdata;
-       if(!(node=acl_find_or_create(acl, str, is_interface, port))) {
+       if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
                if(is_interface)
                        log_err("non-configured interface: %s", str);
                return 0;
@@ -557,10 +564,12 @@ void
 acl_interface_init(struct acl_list* acl_interface)
 {
        regional_free_all(acl_interface->region);
-       /* We want comparison in the tree to include both IP and port.
-        * Initialise with the given compare fucntion but keep treating it as
-        * an addr_tree. */
-       rbtree_init(&acl_interface->tree, &acl_interface_compare);
+       /* We want comparison in the tree to include only address and port.
+        * We don't care about comparing node->net. All addresses in the
+        * acl_interface->tree should have either 32 (ipv4) or 128 (ipv6).
+        * Initialise with the appropriate compare fucntion but keep treating
+        * it as an addr_tree. */
+       addr_tree_addrport_init(&acl_interface->tree);
 }
 
 static int
@@ -604,7 +613,7 @@ read_acl_interface_view(struct acl_list* acl_interface,
                        return 0;
                }
                for(i = 0; i<num_resif; i++) {
-                       if(!acl_list_view_cfg(acl_interface, p->str, p->str2,
+                       if(!acl_list_view_cfg(acl_interface, resif[i], p->str2,
                                v, 1, port)) {
                                config_del_strarray(resif, num_resif);
                                config_deldblstrlist(p);
@@ -639,7 +648,7 @@ read_acl_interface_tags(struct acl_list* acl_interface,
                        return 0;
                }
                for(i = 0; i<num_resif; i++) {
-                       if(!acl_list_tags_cfg(acl_interface, p->str, p->str2,
+                       if(!acl_list_tags_cfg(acl_interface, resif[i], p->str2,
                                p->str2len, 1, port)) {
                                config_del_strbytelist(p);
                                config_del_strarray(resif, num_resif);
@@ -676,8 +685,8 @@ read_acl_interface_tag_actions(struct acl_list* acl_interface,
                        return 0;
                }
                for(i = 0; i<num_resif; i++) {
-                       if(!acl_list_tag_action_cfg(acl_interface, cfg, p->str,
-                               p->str2, p->str3, 1, port)) {
+                       if(!acl_list_tag_action_cfg(acl_interface, cfg,
+                               resif[i], p->str2, p->str3, 1, port)) {
                                config_deltrplstrlist(p);
                                config_del_strarray(resif, num_resif);
                                return 0;
@@ -714,8 +723,8 @@ read_acl_interface_tag_datas(struct acl_list* acl_interface,
                        return 0;
                }
                for(i = 0; i<num_resif; i++) {
-                       if(!acl_list_tag_data_cfg(acl_interface, cfg, p->str,
-                               p->str2, p->str3, 1, port)) {
+                       if(!acl_list_tag_data_cfg(acl_interface, cfg,
+                               resif[i], p->str2, p->str3, 1, port)) {
                                config_deltrplstrlist(p);
                                config_del_strarray(resif, num_resif);
                                return 0;
index 6617ec8c433e18d3e7bcc03543d2e1f4dd7baced..930f978d3726ab3ef6795cdccfa3935c01e8522f 100644 (file)
@@ -123,14 +123,15 @@ void acl_list_delete(struct acl_list* acl);
  * Insert interface in the alc_list. This should happen when the listening
  * interface is setup.
  * @param acl_interface: acl_list to insert to.
- * @param interface: interface (IP) in string format.
- * @param s2: acl_access in string format.
- * @param port: default port.
+ * @param addr: interface IP.
+ * @param addrlen: length of the interface IP.
+ * @param control: acl_access.
  * @return new structure or NULL on error.
  */
 struct acl_addr*
-acl_interface_insert(struct acl_list* acl_interface, const char* interface,
-       const char* s2, int port);
+acl_interface_insert(struct acl_list* acl_interface,
+       struct sockaddr_storage* addr, socklen_t addrlen,
+       enum acl_access control);
 
 /**
  * Process access control config.
index 28a06175d231f857032923426c1fc7c02cfe72d1..71091133a48787f1be06ff68da84f49a6a6f3547 100644 (file)
@@ -96,6 +96,9 @@
 #ifdef HAVE_SYSTEMD
 #include <systemd/sd-daemon.h>
 #endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
 
 /** How many quit requests happened. */
 static int sig_record_quit = 0;
@@ -314,6 +317,29 @@ daemon_init(void)
        return daemon;  
 }
 
+static int setup_acl_for_ports(struct acl_list* list,
+       struct listen_port* port_list)
+{
+       struct acl_addr* acl_node;
+       struct addrinfo* addr;
+       for(; port_list; port_list=port_list->next) {
+               if(!port_list->socket) {
+                       /* This is mainly for testbound where port_list is
+                        * empty. */
+                       continue;
+               }
+               addr = port_list->socket->addr;
+               if(!(acl_node = acl_interface_insert(list,
+                       (struct sockaddr_storage*)addr->ai_addr,
+                       (socklen_t)addr->ai_addrlen,
+                       acl_refuse))) {
+                       return 0;
+               }
+               port_list->socket->acl = acl_node;
+       }
+       return 1;
+}
+
 int 
 daemon_open_shared_ports(struct daemon* daemon)
 {
@@ -342,8 +368,8 @@ daemon_open_shared_ports(struct daemon* daemon)
                        daemon->reuseport = 1;
 #endif
                /* try to use reuseport */
-               p0 = listening_ports_open(daemon->cfg, daemon->acl_interface,
-                       resif, num_resif, &daemon->reuseport);
+               p0 = listening_ports_open(daemon->cfg, resif, num_resif,
+                       &daemon->reuseport);
                if(!p0) {
                        listening_ports_free(p0);
                        config_del_strarray(resif, num_resif);
@@ -364,12 +390,17 @@ daemon_open_shared_ports(struct daemon* daemon)
                        return 0;
                }
                daemon->ports[0] = p0;
+               if(!setup_acl_for_ports(daemon->acl_interface,
+                   daemon->ports[0])) {
+                       listening_ports_free(p0);
+                       config_del_strarray(resif, num_resif);
+                       return 0;
+               }
                if(daemon->reuseport) {
                        /* continue to use reuseport */
                        for(i=1; i<daemon->num_ports; i++) {
                                if(!(daemon->ports[i]=
                                        listening_ports_open(daemon->cfg,
-                                               daemon->acl_interface,
                                                resif, num_resif,
                                                &daemon->reuseport))
                                        || !daemon->reuseport ) {
@@ -380,6 +411,15 @@ daemon_open_shared_ports(struct daemon* daemon)
                                        config_del_strarray(resif, num_resif);
                                        return 0;
                                }
+                               if(!setup_acl_for_ports(daemon->acl_interface,
+                                       daemon->ports[i])) {
+                                       for(i=0; i<daemon->num_ports; i++)
+                                               listening_ports_free(daemon->ports[i]);
+                                       free(daemon->ports);
+                                       daemon->ports = NULL;
+                                       config_del_strarray(resif, num_resif);
+                                       return 0;
+                               }
                        }
                }
                config_del_strarray(resif, num_resif);
index fb2c53ba2e0be304b34e7e03596ce83d5104cc97..e823b3c12dcff7b3011bc7bbc53cc4ee7dca0ec3 100644 (file)
@@ -1196,7 +1196,6 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
  * @param hints: for getaddrinfo. family and flags have to be set by caller.
  * @param port: Port number to use (as string).
  * @param list: list of open ports, appended to, changed to point to list head.
- * @param acl_interface: acl list with options for the interface.
  * @param rcv: receive buffer size for UDP
  * @param snd: send buffer size for UDP
  * @param ssl_port: ssl service port number
@@ -1216,7 +1215,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
 static int
 ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
        struct addrinfo *hints, const char* port, struct listen_port** list,
-       struct acl_list* acl_interface, size_t rcv, size_t snd, int ssl_port,
+       size_t rcv, size_t snd, int ssl_port,
        struct config_strlist* tls_additional_port, int https_port,
        int* reuseport, int transparent, int tcp_mss, int freebind,
        int http2_nodelay, int use_systemd, int dnscrypt_port, int dscp)
@@ -1225,7 +1224,6 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
        int is_https = if_is_https(ifname, port, https_port);
        int nodelay = is_https && http2_nodelay;
        struct unbound_socket* ub_sock;
-       struct acl_addr* acl_node;
 #ifdef USE_DNSCRYPT
        int is_dnscrypt = ((strchr(ifname, '@') &&
                        atoi(strchr(ifname, '@')+1) == dnscrypt_port) ||
@@ -1240,7 +1238,6 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
 
        if(do_auto) {
                ub_sock = calloc(1, sizeof(struct unbound_socket));
-               acl_node = NULL;
                if(!ub_sock)
                        return 0;
                if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
@@ -1269,17 +1266,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
                        free(ub_sock);
                        return 0;
                }
-               if(!(acl_node = acl_interface_insert(acl_interface, ifname,
-                       "refuse", ntohs(((struct sockaddr_in*)ub_sock->addr->ai_addr)->sin_port)))) {
-                       sock_close(s);
-                       freeaddrinfo(ub_sock->addr);
-                       free(ub_sock);
-                       return 0;
-               }
-               ub_sock->acl = acl_node;
        } else if(do_udp) {
                ub_sock = calloc(1, sizeof(struct unbound_socket));
-               acl_node = NULL;
                if(!ub_sock)
                        return 0;
                /* regular udp socket */
@@ -1301,21 +1289,12 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
                        free(ub_sock);
                        return 0;
                }
-               if(!(acl_node = acl_interface_insert(acl_interface, ifname,
-                       "refuse", ntohs(((struct sockaddr_in*)ub_sock->addr->ai_addr)->sin_port)))) {
-                       sock_close(s);
-                       freeaddrinfo(ub_sock->addr);
-                       free(ub_sock);
-                       return 0;
-               }
-               ub_sock->acl = acl_node;
        }
        if(do_tcp) {
                int is_ssl = if_is_ssl(ifname, port, ssl_port,
                        tls_additional_port);
                enum listen_type port_type;
                ub_sock = calloc(1, sizeof(struct unbound_socket));
-               acl_node = NULL;
                if(!ub_sock)
                        return 0;
                if(is_ssl)
@@ -1345,14 +1324,6 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
                        free(ub_sock);
                        return 0;
                }
-               if(!(acl_node = acl_interface_insert(acl_interface, ifname,
-                       "refuse", ntohs(((struct sockaddr_in*)ub_sock->addr->ai_addr)->sin_port)))) {
-                       sock_close(s);
-                       freeaddrinfo(ub_sock->addr);
-                       free(ub_sock);
-                       return 0;
-               }
-               ub_sock->acl = acl_node;
        }
        return 1;
 }
@@ -1750,8 +1721,8 @@ int resolve_interface_names(char** ifs, int num_ifs,
 }
 
 struct listen_port*
-listening_ports_open(struct config_file* cfg, struct acl_list* acl_interface,
-       char** ifs, int num_ifs, int* reuseport)
+listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
+       int* reuseport)
 {
        struct listen_port* list = NULL;
        struct addrinfo hints;
@@ -1842,7 +1813,7 @@ listening_ports_open(struct config_file* cfg, struct acl_list* acl_interface,
                        hints.ai_family = AF_INET6;
                        if(!ports_create_if(do_auto?"::0":"::1",
                                do_auto, cfg->do_udp, do_tcp,
-                               &hints, portbuf, &list, acl_interface,
+                               &hints, portbuf, &list,
                                cfg->so_rcvbuf, cfg->so_sndbuf,
                                cfg->ssl_port, cfg->tls_additional_port,
                                cfg->https_port, reuseport, cfg->ip_transparent,
@@ -1857,7 +1828,7 @@ listening_ports_open(struct config_file* cfg, struct acl_list* acl_interface,
                        hints.ai_family = AF_INET;
                        if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
                                do_auto, cfg->do_udp, do_tcp,
-                               &hints, portbuf, &list, acl_interface,
+                               &hints, portbuf, &list,
                                cfg->so_rcvbuf, cfg->so_sndbuf,
                                cfg->ssl_port, cfg->tls_additional_port,
                                cfg->https_port, reuseport, cfg->ip_transparent,
@@ -1874,7 +1845,7 @@ listening_ports_open(struct config_file* cfg, struct acl_list* acl_interface,
                                continue;
                        hints.ai_family = AF_INET6;
                        if(!ports_create_if(ifs[i], 0, cfg->do_udp,
-                               do_tcp, &hints, portbuf, &list, acl_interface,
+                               do_tcp, &hints, portbuf, &list,
                                cfg->so_rcvbuf, cfg->so_sndbuf,
                                cfg->ssl_port, cfg->tls_additional_port,
                                cfg->https_port, reuseport, cfg->ip_transparent,
@@ -1889,7 +1860,7 @@ listening_ports_open(struct config_file* cfg, struct acl_list* acl_interface,
                                continue;
                        hints.ai_family = AF_INET;
                        if(!ports_create_if(ifs[i], 0, cfg->do_udp,
-                               do_tcp, &hints, portbuf, &list, acl_interface,
+                               do_tcp, &hints, portbuf, &list,
                                cfg->so_rcvbuf, cfg->so_sndbuf,
                                cfg->ssl_port, cfg->tls_additional_port,
                                cfg->https_port, reuseport, cfg->ip_transparent,
index 70b3da0f0468c9fba4f06a822df5728c086e2bb2..f27fa597bca08ab883e4179da040f43c6d9bbd43 100644 (file)
@@ -138,7 +138,6 @@ struct listen_port {
  * interfaces for IP4 and/or IP6, for UDP and/or TCP.
  * On the given port number. It creates the sockets.
  * @param cfg: settings on what ports to open.
- * @param acl_interface: acl list for interface options.
  * @param ifs: interfaces to open, array of IP addresses, "ip[@port]".
  * @param num_ifs: length of ifs.
  * @param reuseport: set to true if you want reuseport, or NULL to not have it,
@@ -147,7 +146,6 @@ struct listen_port {
  * @return: linked list of ports or NULL on error.
  */
 struct listen_port* listening_ports_open(struct config_file* cfg,
-       struct acl_list* acl_interface,
        char** ifs, int num_ifs, int* reuseport);
 
 /**
index a50e2f3b19a26e03356456c3cee9749f1fee03b8..03e1c04f3dc8a4dd60e82655518c2aaf6a1f7ad4 100644 (file)
@@ -1341,11 +1341,10 @@ int resolve_interface_names(char** ATTR_UNUSED(ifs), int ATTR_UNUSED(num_ifs),
 }
 
 struct listen_port* listening_ports_open(struct config_file* ATTR_UNUSED(cfg),
-       struct acl_list* ATTR_UNUSED(acl_interface),
        char** ATTR_UNUSED(ifs), int ATTR_UNUSED(num_ifs),
        int* ATTR_UNUSED(reuseport))
 {
-       return calloc(1, 1);
+       return calloc(1, sizeof(struct listen_port));
 }
 
 void listening_ports_free(struct listen_port* list)
index 0c2314770a4c3fbbd491caa821bebbe9a69ed2fe..157a2d7b76bfd640a3088c306352bfab17e0b42f 100644 (file)
@@ -6,22 +6,39 @@ server:
        chroot: ""
        username: ""
        do-not-query-localhost: no
-       use-caps-for-id: yes
+       use-caps-for-id: no
+       define-tag: "one two refuse"
 
 # Interface configuration for IPv4
        interface: @IPV4_ADDR@@@PORT_ALLOW@
        interface: @IPV4_ADDR@@@PORT_DENY@
        interface: @IPV4_ADDR@@@PORT_REFUSE@
+       interface: @IPV4_ADDR@@@PORT_TAG_1@
+       interface: @IPV4_ADDR@@@PORT_TAG_2@
+       interface: @IPV4_ADDR@@@PORT_TAG_3@
        interface: @IPV4_ADDR@@@PORT_VIEW_INT@
        interface: @IPV4_ADDR@@@PORT_VIEW_EXT@
        interface: @IPV4_ADDR@@@PORT_VIEW_INTEXT@
 
        interface-action: @IPV4_ADDR@@@PORT_ALLOW@ allow
        interface-action: @IPV4_ADDR@@@PORT_DENY@ deny
+       # interface-action: @IPV4_ADDR@@@PORT_REFUSE@ refuse  # This is the default action
+       interface-action: @IPV4_ADDR@@@PORT_TAG_1@ allow
+       interface-action: @IPV4_ADDR@@@PORT_TAG_2@ allow
+       interface-action: @IPV4_ADDR@@@PORT_TAG_3@ allow
        interface-action: @IPV4_ADDR@@@PORT_VIEW_INT@ allow
        interface-action: @IPV4_ADDR@@@PORT_VIEW_EXT@ allow
        interface-action: @IPV4_ADDR@@@PORT_VIEW_INTEXT@ allow
 
+       interface-tag: @IPV4_ADDR@@@PORT_TAG_1@ "one"
+       interface-tag: @IPV4_ADDR@@@PORT_TAG_2@ "two"
+       interface-tag: @IPV4_ADDR@@@PORT_TAG_3@ "refuse"
+       interface-tag-action: @IPV4_ADDR@@@PORT_TAG_1@ one redirect
+       interface-tag-data: @IPV4_ADDR@@@PORT_TAG_1@ one "A 1.1.1.1"
+       interface-tag-action: @IPV4_ADDR@@@PORT_TAG_2@ two redirect
+       interface-tag-data: @IPV4_ADDR@@@PORT_TAG_2@ two "A 2.2.2.2"
+       interface-tag-action: @IPV4_ADDR@@@PORT_TAG_3@ refuse always_refuse
+
        interface-view: @IPV4_ADDR@@@PORT_VIEW_INT@ "int"
        interface-view: @IPV4_ADDR@@@PORT_VIEW_EXT@ "ext"
        interface-view: @IPV4_ADDR@@@PORT_VIEW_INTEXT@ "intext"
@@ -30,20 +47,75 @@ server:
        interface: @IPV6_ADDR@@@PORT_ALLOW@
        interface: @IPV6_ADDR@@@PORT_DENY@
        interface: @IPV6_ADDR@@@PORT_REFUSE@
+       interface: @IPV6_ADDR@@@PORT_TAG_1@
+       interface: @IPV6_ADDR@@@PORT_TAG_2@
+       interface: @IPV6_ADDR@@@PORT_TAG_3@
        interface: @IPV6_ADDR@@@PORT_VIEW_INT@
        interface: @IPV6_ADDR@@@PORT_VIEW_EXT@
        interface: @IPV6_ADDR@@@PORT_VIEW_INTEXT@
 
        interface-action: @IPV6_ADDR@@@PORT_ALLOW@ allow
        interface-action: @IPV6_ADDR@@@PORT_DENY@ deny
+       # interface-action: @IPV6_ADDR@@@PORT_REFUSE@ refuse  # This is the default action
+       interface-action: @IPV6_ADDR@@@PORT_TAG_1@ allow
+       interface-action: @IPV6_ADDR@@@PORT_TAG_2@ allow
+       interface-action: @IPV6_ADDR@@@PORT_TAG_3@ allow
        interface-action: @IPV6_ADDR@@@PORT_VIEW_INT@ allow
        interface-action: @IPV6_ADDR@@@PORT_VIEW_EXT@ allow
        interface-action: @IPV6_ADDR@@@PORT_VIEW_INTEXT@ allow
 
+       interface-tag: @IPV6_ADDR@@@PORT_TAG_1@ "one"
+       interface-tag: @IPV6_ADDR@@@PORT_TAG_2@ "two"
+       interface-tag: @IPV6_ADDR@@@PORT_TAG_3@ "refuse"
+       interface-tag-action: @IPV6_ADDR@@@PORT_TAG_1@ one redirect
+       interface-tag-data: @IPV6_ADDR@@@PORT_TAG_1@ one "A 1.1.1.1"
+       interface-tag-action: @IPV6_ADDR@@@PORT_TAG_2@ two redirect
+       interface-tag-data: @IPV6_ADDR@@@PORT_TAG_2@ two "A 2.2.2.2"
+       interface-tag-action: @IPV6_ADDR@@@PORT_TAG_3@ refuse always_refuse
+
        interface-view: @IPV6_ADDR@@@PORT_VIEW_INT@ "int"
        interface-view: @IPV6_ADDR@@@PORT_VIEW_EXT@ "ext"
        interface-view: @IPV6_ADDR@@@PORT_VIEW_INTEXT@ "intext"
 
+# Mirrored interface configuration for interface name
+       interface: @INTERFACE@@@PORT_ALLOW@
+       interface: @INTERFACE@@@PORT_DENY@
+       interface: @INTERFACE@@@PORT_REFUSE@
+       interface: @INTERFACE@@@PORT_TAG_1@
+       interface: @INTERFACE@@@PORT_TAG_2@
+       interface: @INTERFACE@@@PORT_TAG_3@
+       interface: @INTERFACE@@@PORT_VIEW_INT@
+       interface: @INTERFACE@@@PORT_VIEW_EXT@
+       interface: @INTERFACE@@@PORT_VIEW_INTEXT@
+
+       interface-action: @INTERFACE@@@PORT_ALLOW@ allow
+       interface-action: @INTERFACE@@@PORT_DENY@ deny
+       # interface-action: @INTERFACE@@@PORT_REFUSE@ refuse  # This is the default action
+       interface-action: @INTERFACE@@@PORT_TAG_1@ allow
+       interface-action: @INTERFACE@@@PORT_TAG_2@ allow
+       interface-action: @INTERFACE@@@PORT_TAG_3@ allow
+       interface-action: @INTERFACE@@@PORT_VIEW_INT@ allow
+       interface-action: @INTERFACE@@@PORT_VIEW_EXT@ allow
+       interface-action: @INTERFACE@@@PORT_VIEW_INTEXT@ allow
+
+       interface-tag: @INTERFACE@@@PORT_TAG_1@ "one"
+       interface-tag: @INTERFACE@@@PORT_TAG_2@ "two"
+       interface-tag: @INTERFACE@@@PORT_TAG_3@ "refuse"
+       interface-tag-action: @INTERFACE@@@PORT_TAG_1@ one redirect
+       interface-tag-data: @INTERFACE@@@PORT_TAG_1@ one "A 1.1.1.1"
+       interface-tag-action: @INTERFACE@@@PORT_TAG_2@ two redirect
+       interface-tag-data: @INTERFACE@@@PORT_TAG_2@ two "A 2.2.2.2"
+       interface-tag-action: @INTERFACE@@@PORT_TAG_3@ refuse always_refuse
+
+       interface-view: @INTERFACE@@@PORT_VIEW_INT@ "int"
+       interface-view: @INTERFACE@@@PORT_VIEW_EXT@ "ext"
+       interface-view: @INTERFACE@@@PORT_VIEW_INTEXT@ "intext"
+
+# Local zones configuration
+       local-zone: local. transparent
+       local-data: "local. A 0.0.0.0"
+       local-zone-tag: local. "one two refuse"
+
 # Views configuration
 view:
        name: "int"
index 14f2fb599819c003a1778dada16452e51aa046e2..ce5358c1b2d903a0dfca7f6e7715b9e37843c263 100644 (file)
@@ -7,25 +7,37 @@ if test ! -x "`which unshare 2>&1`"; then
        skip_test "no unshare (from util-linux package) available, skip test"
 fi
 
-get_random_port 8
+get_random_port 11
 
 PORT_ALLOW=$RND_PORT
 PORT_DENY=$(($RND_PORT + 1))
 PORT_REFUSE=$(($RND_PORT + 2))
-PORT_VIEW_INT=$(($RND_PORT + 3))
-PORT_VIEW_EXT=$(($RND_PORT + 4))
-PORT_VIEW_INTEXT=$(($RND_PORT + 5))
-FORWARD_PORT=$(($RND_PORT + 6))
-STUB_PORT=$(($RND_PORT + 7))
+PORT_TAG_1=$(($RND_PORT + 3))
+PORT_TAG_2=$(($RND_PORT + 4))
+PORT_TAG_3=$(($RND_PORT + 5))
+PORT_VIEW_INT=$(($RND_PORT + 6))
+PORT_VIEW_EXT=$(($RND_PORT + 7))
+PORT_VIEW_INTEXT=$(($RND_PORT + 8))
+FORWARD_PORT=$(($RND_PORT + 9))
+STUB_PORT=$(($RND_PORT + 10))
 
 IPV4_ADDR=192.168.1.1
 IPV6_ADDR=2001:db8::1
 
+INTERFACE=eth24
+INTERFACE_ADDR_1=10.0.0.1
+INTERFACE_ADDR_2=10.0.0.2
+INTERFACE_ADDR_3=10.0.0.3
+INTERFACE_ADDR_4=10.0.0.4
+
 # make config file
 sed \
        -e 's/@PORT_ALLOW\@/'$PORT_ALLOW'/' \
        -e 's/@PORT_DENY\@/'$PORT_DENY'/' \
        -e 's/@PORT_REFUSE\@/'$PORT_REFUSE'/' \
+       -e 's/@PORT_TAG_1\@/'$PORT_TAG_1'/' \
+       -e 's/@PORT_TAG_2\@/'$PORT_TAG_2'/' \
+       -e 's/@PORT_TAG_3\@/'$PORT_TAG_3'/' \
        -e 's/@PORT_VIEW_INT\@/'$PORT_VIEW_INT'/' \
        -e 's/@PORT_VIEW_EXT\@/'$PORT_VIEW_EXT'/' \
        -e 's/@PORT_VIEW_INTEXT\@/'$PORT_VIEW_INTEXT'/' \
@@ -33,6 +45,7 @@ sed \
        -e 's/@STUB_PORT\@/'$STUB_PORT'/' \
        -e 's/@IPV4_ADDR\@/'$IPV4_ADDR'/' \
        -e 's/@IPV6_ADDR\@/'$IPV6_ADDR'/' \
+       -e 's/@INTERFACE\@/'$INTERFACE'/' \
        < acl_interface.conf > ub.conf
 
 if test -x "`which bash`"; then
@@ -44,6 +57,9 @@ fi
 echo "PORT_ALLOW=$PORT_ALLOW" >> .tpkg.var.test
 echo "PORT_DENY=$PORT_DENY" >> .tpkg.var.test
 echo "PORT_REFUSE=$PORT_REFUSE" >> .tpkg.var.test
+echo "PORT_TAG_1=$PORT_TAG_1" >> .tpkg.var.test
+echo "PORT_TAG_2=$PORT_TAG_2" >> .tpkg.var.test
+echo "PORT_TAG_3=$PORT_TAG_3" >> .tpkg.var.test
 echo "PORT_VIEW_INT=$PORT_VIEW_INT" >> .tpkg.var.test
 echo "PORT_VIEW_EXT=$PORT_VIEW_EXT" >> .tpkg.var.test
 echo "PORT_VIEW_INTEXT=$PORT_VIEW_INTEXT" >> .tpkg.var.test
@@ -51,4 +67,9 @@ echo "FORWARD_PORT=$FORWARD_PORT" >> .tpkg.var.test
 echo "STUB_PORT=$STUB_PORT" >> .tpkg.var.test
 echo "IPV4_ADDR=$IPV4_ADDR" >> .tpkg.var.test
 echo "IPV6_ADDR=$IPV6_ADDR" >> .tpkg.var.test
+echo "INTERFACE=$INTERFACE" >> .tpkg.var.test
+echo "INTERFACE_ADDR_1=$INTERFACE_ADDR_1" >> .tpkg.var.test
+echo "INTERFACE_ADDR_2=$INTERFACE_ADDR_2" >> .tpkg.var.test
+echo "INTERFACE_ADDR_3=$INTERFACE_ADDR_3" >> .tpkg.var.test
+echo "INTERFACE_ADDR_4=$INTERFACE_ADDR_4" >> .tpkg.var.test
 echo "shell=$shell" >> .tpkg.var.test
index d30c64d3fdbbd3b67e80f7c17fd8fcc04476d323..00b2b059f94203de6839699bd9f640dc3d4be4d2 100644 (file)
@@ -10,6 +10,13 @@ ip addr add $IPV4_ADDR dev lo
 ip addr add $IPV6_ADDR dev lo
 ip link set lo up
 
+ip link add $INTERFACE type dummy
+ip addr add $INTERFACE_ADDR_1 dev $INTERFACE
+ip addr add $INTERFACE_ADDR_2 dev $INTERFACE
+ip addr add $INTERFACE_ADDR_3 dev $INTERFACE
+ip addr add $INTERFACE_ADDR_4 dev $INTERFACE
+ip link set $INTERFACE up
+
 # start the forwarder in the background
 get_ldns_testns
 $LDNS_TESTNS -p $FORWARD_PORT acl_interface.testns >fwd.log 2>&1 &
@@ -31,6 +38,14 @@ wait_ldns_testns_up fwd.log
 wait_ldns_testns_up fwd2.log
 wait_unbound_up unbound.log
 
+end () {
+       echo "> cat logfiles"
+       cat fwd.log
+       cat fwd2.log
+       cat unbound.log
+       exit $1
+}
+
 # Query for the given domain to the given port
 # $1: address family [4, 6]
 # $2: port
@@ -44,13 +59,22 @@ query () {
        dig @"$addr" -p $2 $3 | tee outfile
 }
 
+# Query for the given domain to the given port
+# $1: address
+# $2: port
+# $3: dname
+query_addr () {
+       echo "> dig @$1 -p $2 $3"
+       dig @"$1" -p $2 $3 | tee outfile
+}
+
 expect_refused () {
        echo "> check answer for REFUSED"
        if grep "REFUSED" outfile; then
                echo "OK"
        else
                echo "Not OK"
-               exit 1
+               end 1
        fi
 }
 
@@ -60,7 +84,7 @@ expect_external_answer () {
                echo "OK"
        else
                echo "Not OK"
-               exit 1
+               end 1
        fi
 }
 
@@ -70,10 +94,29 @@ expect_internal_answer () {
                echo "OK"
        else
                echo "Not OK"
-               exit 1
+               end 1
+       fi
+}
+
+expect_tag_one_answer () {
+       echo "> check tag 'one' answer"
+       if grep "1.1.1.1" outfile; then
+               echo "OK"
+       else
+               echo "Not OK"
+               end 1
        fi
 }
 
+expect_tag_two_answer () {
+       echo "> check tag 'two' answer"
+       if grep "2.2.2.2" outfile; then
+               echo "OK"
+       else
+               echo "Not OK"
+               end 1
+       fi
+}
 
 # do the test
 
@@ -90,6 +133,15 @@ for i in 4 6; do
        query $i $PORT_ALLOW "www.internal"
        expect_internal_answer
 
+       query $i $PORT_TAG_1 "local"
+       expect_tag_one_answer
+
+       query $i $PORT_TAG_2 "local"
+       expect_tag_two_answer
+
+       query $i $PORT_TAG_3 "local"
+       expect_refused
+
        query $i $PORT_VIEW_INT "www.internal"
        expect_internal_answer
 
@@ -109,8 +161,45 @@ for i in 4 6; do
        expect_external_answer
 done
 
-echo "> cat logfiles"
-cat fwd.log
-cat fwd2.log
-cat unbound.log
-exit 0
+for addr in $INTERFACE_ADDR_1 $INTERFACE_ADDR_2 $INTERFACE_ADDR_3 $INTERFACE_ADDR_4; do
+       query_addr $addr $PORT_REFUSE "www.external"
+       expect_refused
+
+       query_addr $addr $PORT_REFUSE "www.internal"
+       expect_refused
+
+       query_addr $addr $PORT_ALLOW "www.external"
+       expect_external_answer
+
+       query_addr $addr $PORT_ALLOW "www.internal"
+       expect_internal_answer
+
+       query_addr $addr $PORT_TAG_1 "local"
+       expect_tag_one_answer
+
+       query_addr $addr $PORT_TAG_2 "local"
+       expect_tag_two_answer
+
+       query_addr $addr $PORT_TAG_3 "local"
+       expect_refused
+
+       query_addr $addr $PORT_VIEW_INT "www.internal"
+       expect_internal_answer
+
+       query_addr $addr $PORT_VIEW_INT "www.external"
+       expect_refused
+
+       query_addr $addr $PORT_VIEW_EXT "www.internal"
+       expect_refused
+
+       query_addr $addr $PORT_VIEW_EXT "www.external"
+       expect_external_answer
+
+       query_addr $addr $PORT_VIEW_INTEXT "www.internal"
+       expect_internal_answer
+
+       query_addr $addr $PORT_VIEW_INTEXT "www.external"
+       expect_external_answer
+done
+
+end 0
index 62abf69288482728189d82e65da77c8d2cab032c..d8c871b1c6023ef15c4ed2e4bcfd8ddb6810439b 100644 (file)
@@ -11,3 +11,16 @@ www  IN      A
 SECTION ANSWER
 www    IN      A       1.2.3.4
 ENTRY_END
+
+$ORIGIN local.
+$TTL 3600
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+REPLY QR AA NOERROR
+ADJUST copy_id
+SECTION QUESTION
+@      IN      A
+SECTION ANSWER
+@      IN      A       127.0.0.1
+ENTRY_END
index 750f45b50e8461c7bb17cc4a998d5f9af4f6086c..dc8ab66938763a6448051fe0c616916d9118fc0c 100644 (file)
@@ -44,7 +44,6 @@
  * boundaries in the program.
  */
 #include "config.h"
-#include "daemon/acl_list.h"
 #include "util/fptr_wlist.h"
 #include "util/mini_event.h"
 #include "services/outside_network.h"
@@ -222,6 +221,7 @@ fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *))
        if(fptr == &mesh_state_compare) return 1;
        else if(fptr == &mesh_state_ref_compare) return 1;
        else if(fptr == &addr_tree_compare) return 1;
+       else if(fptr == &addr_tree_addrport_compare) return 1;
        else if(fptr == &local_zone_cmp) return 1;
        else if(fptr == &local_data_cmp) return 1;
        else if(fptr == &fwd_cmp) return 1;
@@ -245,7 +245,6 @@ fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *))
        else if(fptr == &auth_zone_cmp) return 1;
        else if(fptr == &auth_data_cmp) return 1;
        else if(fptr == &auth_xfer_cmp) return 1;
-       else if(fptr == &acl_interface_compare) return 1;
        return 0;
 }
 
index f883044afa4b0cbc2ba69c78dbc36814c91397da..eef393f91b69175a188bdeb395c2556263039210 100644 (file)
@@ -71,6 +71,14 @@ int addr_tree_compare(const void* k1, const void* k2)
         return 0;
 }
 
+int addr_tree_addrport_compare(const void* k1, const void* k2)
+{
+       struct addr_tree_node* n1 = (struct addr_tree_node*)k1;
+       struct addr_tree_node* n2 = (struct addr_tree_node*)k2;
+       return sockaddr_cmp(&n1->addr, n1->addrlen, &n2->addr,
+               n2->addrlen);
+}
+
 void name_tree_init(rbtree_type* tree)
 {
        rbtree_init(tree, &name_tree_compare);
@@ -81,6 +89,11 @@ void addr_tree_init(rbtree_type* tree)
        rbtree_init(tree, &addr_tree_compare);
 }
 
+void addr_tree_addrport_init(rbtree_type* tree)
+{
+       rbtree_init(tree, &addr_tree_addrport_compare);
+}
+
 int name_tree_insert(rbtree_type* tree, struct name_tree_node* node, 
         uint8_t* name, size_t len, int labs, uint16_t dclass)
 {
index d54602fd7ddfe426934fb4459b6adab75ab1e1c4..8aaa94098bc78bc908f2f96d721246e2f093aa6c 100644 (file)
@@ -153,6 +153,13 @@ int name_tree_next_root(rbtree_type* tree, uint16_t* dclass);
  */
 void addr_tree_init(rbtree_type* tree);
 
+/**
+ * Init addr tree to be empty.
+ * The comparison function to be used is addr_tree_addrport_compare.
+ * @param tree: to init.
+ */
+void addr_tree_addrport_init(rbtree_type* tree);
+
 /**
  * insert element into addr tree.
  * @param tree: addr tree
@@ -207,4 +214,7 @@ int name_tree_compare(const void* k1, const void* k2);
 /** compare addr tree nodes */
 int addr_tree_compare(const void* k1, const void* k2);
 
+/** compare addr tree nodes (address and port only) */
+int addr_tree_addrport_compare(const void* k1, const void* k2);
+
 #endif /* UTIL_STORAGE_DNSTREE_H */