From: W.C.A. Wijngaards Date: Wed, 16 Oct 2024 13:56:33 +0000 (+0200) Subject: - Fix #1154: Tag Incorrectly Applying for Other Interfaces X-Git-Tag: release-1.23.0rc1~117 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9a63db344eb859d32d04dcabcf0cd74fe00be76f;p=thirdparty%2Funbound.git - Fix #1154: Tag Incorrectly Applying for Other Interfaces Using the Same IP. This fix is not for 1.22.0. --- diff --git a/daemon/acl_list.c b/daemon/acl_list.c index 83cfd7ddf..605851e4f 100644 --- a/daemon/acl_list.c +++ b/daemon/acl_list.c @@ -551,17 +551,6 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg, return 1; } -int -acl_interface_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); - /* We don't care about comparing node->net. All addresses in the - * acl_interface tree have either 32 (ipv4) or 128 (ipv6). */ -} - void acl_interface_init(struct acl_list* acl_interface) { diff --git a/daemon/acl_list.h b/daemon/acl_list.h index 9da43bef3..ee679eb6e 100644 --- a/daemon/acl_list.h +++ b/daemon/acl_list.h @@ -147,9 +147,6 @@ acl_interface_insert(struct acl_list* acl_interface, int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg, struct views* v); -/** compare ACL interface "addr_tree" nodes (+port) */ -int acl_interface_compare(const void* k1, const void* k2); - /** * Initialise (also clean) the acl_interface struct. * @param acl_interface: where to store. diff --git a/doc/Changelog b/doc/Changelog index fde05db51..2acc4b380 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -4,6 +4,8 @@ 16 October 2024: Wouter - Fix for dnstap with dnscrypt and dnstap without dnsoverquic. + - Fix #1154: Tag Incorrectly Applying for Other Interfaces + Using the Same IP. This fix is not for 1.22.0. 14 October 2024: Wouter - Fix to display warning if quic-port is set but dnsoverquic is not diff --git a/testdata/acl_interface.tdir/acl_interface.conf b/testdata/acl_interface.tdir/acl_interface.conf index 1d9f8c9aa..b1d948573 100644 --- a/testdata/acl_interface.tdir/acl_interface.conf +++ b/testdata/acl_interface.tdir/acl_interface.conf @@ -139,6 +139,20 @@ server: interface-view: @INTERFACE@@@PORT_VIEW_EXT@ "ext" interface-view: @INTERFACE@@@PORT_VIEW_INTEXT@ "intext" +# Interface with scope_id + interface: @INTERFACE@vlan50@@PORT_ALLOW@ + interface: @INTERFACE@vlan51@@PORT_ALLOW@ + interface-tag: @INTERFACE@vlan50@@PORT_ALLOW@ "one" + interface-tag: @INTERFACE@vlan51@@PORT_ALLOW@ "two" + interface-action: @INTERFACE@vlan50@@PORT_ALLOW@ allow + interface-action: @INTERFACE@vlan51@@PORT_ALLOW@ allow + local-zone: one.vtest. static + local-data: "one.vtest. A 1.1.1.1" + local-zone-tag: one.vtest. "one" + local-zone: two.vtest. static + local-data: "two.vtest. A 2.2.2.2" + local-zone-tag: two.vtest. "two" + # Local zones configuration local-zone: local. transparent local-data: "local. A 0.0.0.0" diff --git a/testdata/acl_interface.tdir/acl_interface.test.scenario b/testdata/acl_interface.tdir/acl_interface.test.scenario index 4ae0a42f0..6348d2ef4 100644 --- a/testdata/acl_interface.tdir/acl_interface.test.scenario +++ b/testdata/acl_interface.tdir/acl_interface.test.scenario @@ -17,6 +17,15 @@ ip addr add $INTERFACE_ADDR_3 dev $INTERFACE ip addr add $INTERFACE_ADDR_4 dev $INTERFACE ip link set $INTERFACE up +ip link add ${INTERFACE}vlan50 type dummy +ip addr add fe80::2/64 dev ${INTERFACE}vlan50 +ip link add ${INTERFACE}vlan51 type dummy +ip addr add fe80::2/64 dev ${INTERFACE}vlan51 +ip link set ${INTERFACE}vlan50 up +ip link set ${INTERFACE}vlan51 up + +ip addr show + # start the forwarder in the background get_ldns_testns $LDNS_TESTNS -p $FORWARD_PORT acl_interface.testns >fwd.log 2>&1 & @@ -250,4 +259,10 @@ for addr in $INTERFACE_ADDR_1 $INTERFACE_ADDR_2 $INTERFACE_ADDR_3 $INTERFACE_ADD expect_external_answer done +query_addr fe80::2%${INTERFACE}vlan50 $PORT_ALLOW "one.vtest." +expect_tag_one_answer + +query_addr fe80::2%${INTERFACE}vlan51 $PORT_ALLOW "two.vtest." +expect_tag_two_answer + end 0 diff --git a/util/net_help.c b/util/net_help.c index 5cf702ef9..96b2b19a0 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -727,6 +727,52 @@ sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, } } +int +sockaddr_cmp_scopeid(struct sockaddr_storage* addr1, socklen_t len1, + struct sockaddr_storage* addr2, socklen_t len2) +{ + struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; + struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; + struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; + struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; + if(len1 < len2) + return -1; + if(len1 > len2) + return 1; + log_assert(len1 == len2); + if( p1_in->sin_family < p2_in->sin_family) + return -1; + if( p1_in->sin_family > p2_in->sin_family) + return 1; + log_assert( p1_in->sin_family == p2_in->sin_family ); + /* compare ip4 */ + if( p1_in->sin_family == AF_INET ) { + /* just order it, ntohs not required */ + if(p1_in->sin_port < p2_in->sin_port) + return -1; + if(p1_in->sin_port > p2_in->sin_port) + return 1; + log_assert(p1_in->sin_port == p2_in->sin_port); + return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); + } else if (p1_in6->sin6_family == AF_INET6) { + /* just order it, ntohs not required */ + if(p1_in6->sin6_port < p2_in6->sin6_port) + return -1; + if(p1_in6->sin6_port > p2_in6->sin6_port) + return 1; + if(p1_in6->sin6_scope_id < p2_in6->sin6_scope_id) + return -1; + if(p1_in6->sin6_scope_id > p2_in6->sin6_scope_id) + return 1; + log_assert(p1_in6->sin6_port == p2_in6->sin6_port); + return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, + INET6_SIZE); + } else { + /* eek unknown type, perform this comparison for sanity. */ + return memcmp(addr1, addr2, len1); + } +} + int addr_is_ip6(struct sockaddr_storage* addr, socklen_t len) { diff --git a/util/net_help.h b/util/net_help.h index 28245ea0c..eba38cee0 100644 --- a/util/net_help.h +++ b/util/net_help.h @@ -289,6 +289,18 @@ int sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1, int sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, struct sockaddr_storage* addr2, socklen_t len2); +/** + * Compare two sockaddrs. Imposes an ordering on the addresses. + * Compares address and port. It also compares scope_id for ip6. + * @param addr1: address 1. + * @param len1: lengths of addr1. + * @param addr2: address 2. + * @param len2: lengths of addr2. + * @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger. + */ +int sockaddr_cmp_scopeid(struct sockaddr_storage* addr1, socklen_t len1, + struct sockaddr_storage* addr2, socklen_t len2); + /** * Checkout address family. * @param addr: the sockaddr to examine. diff --git a/util/storage/dnstree.c b/util/storage/dnstree.c index eef393f91..93a0cc4c3 100644 --- a/util/storage/dnstree.c +++ b/util/storage/dnstree.c @@ -75,7 +75,7 @@ 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, + return sockaddr_cmp_scopeid(&n1->addr, n1->addrlen, &n2->addr, n2->addrlen); }