From: W.C.A. Wijngaards Date: Wed, 27 May 2026 11:20:35 +0000 (+0200) Subject: - Fix to decrement the per-netblock tcp connection limits, so X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=047df73887f947f8421c17ee2691244ea47d74c6;p=thirdparty%2Funbound.git - Fix to decrement the per-netblock tcp connection limits, so it keeps usable. Thanks to Qifan Zhang, Palo Alto Networks, for the report. --- diff --git a/doc/Changelog b/doc/Changelog index 1622426c2..11ee7a0b5 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -13,6 +13,9 @@ - Fix to reset the tcp-timeout before applying a load based reduction. Thanks to Qifan Zhang, Palo Alto Networks, for the report. + - Fix to decrement the per-netblock tcp connection limits, so + it keeps usable. Thanks to Qifan Zhang, Palo Alto Networks, + for the report. 26 May 2026: Wouter - Fix for mesh new client and mesh new callback to rollback the diff --git a/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.conf b/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.conf new file mode 100644 index 000000000..bac2ebcf9 --- /dev/null +++ b/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.conf @@ -0,0 +1,25 @@ +server: + verbosity: 4 + num-threads: 1 + interface: 127.0.0.1 + port: @PORT@ + use-syslog: no + directory: . + pidfile: "unbound.pid" + chroot: "" + username: "" + do-not-query-localhost: no + incoming-num-tcp: 20 + tcp-connection-limit: 0.0.0.0/0 3 + local-data: "www1.example.net. A 10.20.30.41" + local-data: "www2.example.net. A 10.20.30.42" + local-data: "www3.example.net. A 10.20.30.43" + local-data: "www4.example.net. A 10.20.30.44" + local-data: "www5.example.net. A 10.20.30.45" + local-data: "www6.example.net. A 10.20.30.46" + local-data: "www7.example.net. A 10.20.30.47" + local-data: "www8.example.net. A 10.20.30.48" + +forward-zone: + name: "." + forward-addr: "127.0.0.1@@TOPORT@" diff --git a/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.dsc b/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.dsc new file mode 100644 index 000000000..d3a7483c4 --- /dev/null +++ b/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.dsc @@ -0,0 +1,16 @@ +BaseName: tcp_conn_limit_dec +Version: 1.0 +Description: Test tcp-connection-limit setting decrement. +CreationData: Fri May 1 10:10:00 CEST 2026 +Maintainer: dr. W.C.A. Wijngaards +Category: +Component: +CmdDepends: +Depends: +Help: +Pre: tcp_conn_limit_dec.pre +Post: tcp_conn_limit_dec.post +Test: tcp_conn_limit_dec.test +AuxFiles: +Passed: +Failure: diff --git a/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.post b/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.post new file mode 100644 index 000000000..767ec91dd --- /dev/null +++ b/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.post @@ -0,0 +1,12 @@ +# #-- tcp_conn_limit_dec.post --# +# source the master var file when it's there +[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master +# source the test var file when it's there +[ -f .tpkg.var.test ] && source .tpkg.var.test +# +# do your teardown here +. ../common.sh +kill_pid $FWD_PID +kill_pid $UNBOUND_PID +cat fwd.log +cat unbound.log diff --git a/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.pre b/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.pre new file mode 100644 index 000000000..795d56e5a --- /dev/null +++ b/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.pre @@ -0,0 +1,30 @@ +# #-- tcp_conn_limit_dec.pre--# +# source the master var file when it's there +[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master +# use .tpkg.var.test for in test variable passing +[ -f .tpkg.var.test ] && source .tpkg.var.test + +. ../common.sh +get_random_port 2 +UNBOUND_PORT=$RND_PORT +FWD_PORT=$(($RND_PORT + 1)) +echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test +echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test + +# start forwarder +get_ldns_testns +$LDNS_TESTNS -p $FWD_PORT tcp_conn_limit_dec.testns >fwd.log 2>&1 & +FWD_PID=$! +echo "FWD_PID=$FWD_PID" >> .tpkg.var.test + +# make config file +sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' < tcp_conn_limit_dec.conf > ub.conf +# start unbound in the background +PRE="../.." +$PRE/unbound -d -c ub.conf >unbound.log 2>&1 & +UNBOUND_PID=$! +echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test + +cat .tpkg.var.test +wait_ldns_testns_up fwd.log +wait_unbound_up unbound.log diff --git a/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.test b/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.test new file mode 100644 index 000000000..973559df6 --- /dev/null +++ b/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.test @@ -0,0 +1,42 @@ +# #-- tcp_conn_limit_dec.test --# +# source the master var file when it's there +[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master +# use .tpkg.var.test for in test variable passing +[ -f .tpkg.var.test ] && source .tpkg.var.test + + +# Set unbound to limit all IPv4 addresses to 0 connections. +# Make sure TCP connection fails. + + +if uname | grep MINGW >/dev/null; then + echo "no job control in shell on windows. end test" + exit 0 +fi + +PRE="../.." +. ../common.sh +get_make +(cd $PRE; $MAKE streamtcp) + +# after first three queries, the counter must decrement to answer the others. +for i in 1 2 3 4 5 6 7 8; do + echo + echo "> query www$i.example.net." + $PRE/streamtcp -f 127.0.0.1@$UNBOUND_PORT www$i.example.net. A IN 2>&1 | tee outfile + if test "$?" -ne 0; then + echo "exit status not OK" + echo "Not OK" + exit 1 + else + echo "exit status OK" + fi + if grep "10.20.30.4$i" outfile; then + echo "OK" + else + echo "not OK" + exit 1 + fi +done + +exit 0 diff --git a/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.testns b/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.testns new file mode 100644 index 000000000..2f8afd878 --- /dev/null +++ b/testdata/tcp_conn_limit_dec.tdir/tcp_conn_limit_dec.testns @@ -0,0 +1,41 @@ +; nameserver test file +$ORIGIN example.com. +$TTL 3600 + +ENTRY_BEGIN +MATCH UDP opcode qtype qname +REPLY QR AA NOERROR TC +ADJUST copy_id +SECTION QUESTION +www IN A +ENTRY_END + +ENTRY_BEGIN +MATCH TCP opcode qtype qname +REPLY QR AA NOERROR +ADJUST copy_id sleep=2 +SECTION QUESTION +www IN A +SECTION ANSWER +www IN A 10.20.30.40 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +REPLY QR AA NOERROR +ADJUST copy_id +SECTION QUESTION +www2 IN A +SECTION ANSWER +www2 IN A 10.20.30.42 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +REPLY QR AA NOERROR +ADJUST copy_id +SECTION QUESTION +www3 IN A +SECTION ANSWER +www3 IN A 10.20.30.43 +ENTRY_END diff --git a/util/netevent.c b/util/netevent.c index cd74a8dbc..8e4228edc 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -3280,6 +3280,10 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg) #endif return; } + /* move per-netblock TCP-connection-limit handle to the handler so that + * comm_point_close() on the handler decrements the count on close */ + c_hdl->tcl_addr = c->tcl_addr; + c->tcl_addr = NULL; /* Copy remote_address to client_address. * Simplest way/time for streams to do that. */ c_hdl->repinfo.client_addrlen = c_hdl->repinfo.remote_addrlen; @@ -6594,7 +6598,10 @@ comm_point_close(struct comm_point* c) c->event_added = 0; } } - tcl_close_connection(c->tcl_addr); + if(c->tcl_addr) { + tcl_close_connection(c->tcl_addr); + c->tcl_addr = NULL; + } if(c->tcp_req_info) tcp_req_info_clear(c->tcp_req_info); if(c->h2_session)