Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 15 May 2021 09:24:27 GMT
From:      Matthias Andree <mandree@FreeBSD.org>
To:        ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org
Subject:   git: 505d608290a2 - main - dns/dnsmasq: cherry-pick upstream-fixes
Message-ID:  <202105150924.14F9OR2S072976@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by mandree:

URL: https://cgit.FreeBSD.org/ports/commit/?id=505d608290a2efa7d064c4d4f7ca75b17c675405

commit 505d608290a2efa7d064c4d4f7ca75b17c675405
Author:     Matthias Andree <mandree@FreeBSD.org>
AuthorDate: 2021-05-15 09:22:50 +0000
Commit:     Matthias Andree <mandree@FreeBSD.org>
CommitDate: 2021-05-15 09:24:25 +0000

    dns/dnsmasq: cherry-pick upstream-fixes
    
     *  Handle DHCPREBIND requests in the DHCPv6 server.
     *  Fix bug in TCP process handling.
---
 dns/dnsmasq/Makefile              |   3 +-
 dns/dnsmasq/files/patch-ad90eb075 | 135 ++++++++++++++++++++++++++++++++++++++
 dns/dnsmasq/files/patch-d55e2d08  | 123 ++++++++++++++++++++++++++++++++++
 3 files changed, 260 insertions(+), 1 deletion(-)

diff --git a/dns/dnsmasq/Makefile b/dns/dnsmasq/Makefile
index 6beea43b327b..fe4d5d7a73fb 100644
--- a/dns/dnsmasq/Makefile
+++ b/dns/dnsmasq/Makefile
@@ -3,11 +3,12 @@
 PORTNAME=	dnsmasq
 DISTVERSION=	2.85
 # Leave the PORTREVISION in even if 0 to avoid accidental PORTEPOCH bumps:
-PORTREVISION=	0
+PORTREVISION=	1
 PORTEPOCH=	1
 CATEGORIES=	dns
 MASTER_SITES=	https://www.thekelleys.org.uk/dnsmasq/ \
 		LOCAL/mandree/
+PATCH_STRIP=	-p1
 
 MAINTAINER=	mandree@FreeBSD.org
 COMMENT=	Lightweight DNS forwarder, DHCP, and TFTP server
diff --git a/dns/dnsmasq/files/patch-ad90eb075 b/dns/dnsmasq/files/patch-ad90eb075
new file mode 100644
index 000000000000..72ae3b74dd58
--- /dev/null
+++ b/dns/dnsmasq/files/patch-ad90eb075
@@ -0,0 +1,135 @@
+commit ad90eb075dfeeb1936e8bc0f323fcc23f89364d4
+Author: Simon Kelley <simon@thekelleys.org.uk>
+Date:   Fri Apr 9 16:08:05 2021 +0100
+
+    Fix bug in TCP process handling.
+    
+    Fix bug which caused dnsmasq to lose track of processes forked
+    to handle TCP DNS connections under heavy load. The code
+    checked that at least one free process table slot was
+    available before listening on TCP sockets, but didn't take
+    into account that more than one TCP connection could
+    arrive, so that check was not sufficient to ensure that
+    there would be slots for all new processes. It compounded
+    this error by silently failing to store the process when
+    it did run out of slots. Even when this bug is triggered,
+    all the right things happen, and answers are still returned.
+    Only under very exceptional circumstances, does the bug
+    manifest itself: see
+    https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2021q2/014976.html
+    
+    Thanks to Tijs Van Buggenhout for finding the conditions under
+    which the bug manifests itself, and then working out
+    exactly what was going on.
+
+diff --git a/CHANGELOG b/CHANGELOG
+index ab4aa42..87adaf7 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -3,6 +3,24 @@ version 2.86
+ 	Thanks to Aichun Li for spotting this ommision, and the initial
+ 	patch.
+ 
++	Fix bug which caused dnsmasq to lose track of processes forked
++	to handle TCP DNS connections under heavy load. The code
++	checked that at least one free process table slot was
++	available before listening on TCP sockets, but didn't take
++	into account that more than one TCP connection could
++	arrive, so that check was not sufficient to ensure that
++	there would be slots for all new processes. It compounded
++	this error by silently failing to store the process when
++	it did run out of slots. Even when this bug is triggered,
++	all the right things happen, and answers are still returned.
++	Only under very exceptional circumstances, does the bug
++	manifest itself: see
++	https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2021q2/014976.html
++	Thanks to Tijs Van Buggenhout for finding the conditions under
++	which the bug manifests itself, and then working out
++	exactly what was going on.
++
++	
+ 	
+ version 2.85
+         Fix problem with DNS retries in 2.83/2.84.
+diff --git a/src/dnsmasq.c b/src/dnsmasq.c
+index 256d2bc..bf031a1 100644
+--- a/src/dnsmasq.c
++++ b/src/dnsmasq.c
+@@ -1716,22 +1716,24 @@ static int set_dns_listeners(time_t now)
+   for (rfl = daemon->rfl_poll; rfl; rfl = rfl->next)
+     poll_listen(rfl->rfd->fd, POLLIN);
+   
++  /* check to see if we have free tcp process slots. */
++  for (i = MAX_PROCS - 1; i >= 0; i--)
++    if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
++      break;
++
+   for (listener = daemon->listeners; listener; listener = listener->next)
+     {
+       /* only listen for queries if we have resources */
+       if (listener->fd != -1 && wait == 0)
+ 	poll_listen(listener->fd, POLLIN);
+ 	
+-      /* death of a child goes through the select loop, so
+-	 we don't need to explicitly arrange to wake up here */
+-      if  (listener->tcpfd != -1)
+-	for (i = 0; i < MAX_PROCS; i++)
+-	  if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
+-	    {
+-	      poll_listen(listener->tcpfd, POLLIN);
+-	      break;
+-	    }
+-
++      /* Only listen for TCP connections when a process slot
++	 is available. Death of a child goes through the select loop, so
++	 we don't need to explicitly arrange to wake up here,
++	 we'll be called again when a slot becomes available. */
++      if  (listener->tcpfd != -1 && i >= 0)
++	poll_listen(listener->tcpfd, POLLIN);
++      
+ #ifdef HAVE_TFTP
+       /* tftp == 0 in single-port mode. */
+       if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
+@@ -1797,7 +1799,16 @@ static void check_dns_listeners(time_t now)
+ 	tftp_request(listener, now);
+ #endif
+ 
+-      if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
++      /* check to see if we have a free tcp process slot.
++	 Note that we can't assume that because we had
++	 at least one a poll() time, that we still do.
++	 There may be more waiting connections after
++	 poll() returns then free process slots. */
++      for (i = MAX_PROCS - 1; i >= 0; i--)
++	if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
++	  break;
++
++      if (listener->tcpfd != -1 && i >= 0 && poll_check(listener->tcpfd, POLLIN))
+ 	{
+ 	  int confd, client_ok = 1;
+ 	  struct irec *iface = NULL;
+@@ -1887,7 +1898,6 @@ static void check_dns_listeners(time_t now)
+ 		close(pipefd[0]);
+ 	      else
+ 		{
+-		  int i;
+ #ifdef HAVE_LINUX_NETWORK
+ 		  /* The child process inherits the netlink socket, 
+ 		     which it never uses, but when the parent (us) 
+@@ -1907,13 +1917,9 @@ static void check_dns_listeners(time_t now)
+ 		  read_write(pipefd[0], &a, 1, 1);
+ #endif
+ 
+-		  for (i = 0; i < MAX_PROCS; i++)
+-		    if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
+-		      {
+-			daemon->tcp_pids[i] = p;
+-			daemon->tcp_pipes[i] = pipefd[0];
+-			break;
+-		      }
++		  /* i holds index of free slot */
++		  daemon->tcp_pids[i] = p;
++		  daemon->tcp_pipes[i] = pipefd[0];
+ 		}
+ 	      close(confd);
+ 
diff --git a/dns/dnsmasq/files/patch-d55e2d08 b/dns/dnsmasq/files/patch-d55e2d08
new file mode 100644
index 000000000000..137dd0cbe8e9
--- /dev/null
+++ b/dns/dnsmasq/files/patch-d55e2d08
@@ -0,0 +1,123 @@
+commit d55e2d086d1ff30c427fa5e0ecc79746de8a81b7
+Author: Simon Kelley <simon@thekelleys.org.uk>
+Date:   Fri Apr 9 15:19:28 2021 +0100
+
+    Handle DHCPREBIND requests in the DHCPv6 server.
+    
+    Patch by srk, based on submitted patch from liaichun@huawei.com
+
+diff --git a/CHANGELOG b/CHANGELOG
+index ca555ed..ab4aa42 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -1,3 +1,9 @@
++version 2.86
++	Handle DHCPREBIND requests in the DHCPv6 server code.
++	Thanks to Aichun Li for spotting this ommision, and the initial
++	patch.
++
++	
+ version 2.85
+         Fix problem with DNS retries in 2.83/2.84.
+         The new logic in 2.83/2.84 which merges distinct requests
+diff --git a/src/rfc3315.c b/src/rfc3315.c
+index 982c68a..5c2ff97 100644
+--- a/src/rfc3315.c
++++ b/src/rfc3315.c
+@@ -919,11 +919,14 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
+       
+   
+     case DHCP6RENEW:
++    case DHCP6REBIND:
+       {
++	int address_assigned = 0;
++
+ 	/* set reply message type */
+ 	*outmsgtypep = DHCP6REPLY;
+ 	
+-	log6_quiet(state, "DHCPRENEW", NULL, NULL);
++	log6_quiet(state, msg_type == DHCP6RENEW ? "DHCPRENEW" : "DHCPREBIND", NULL, NULL);
+ 
+ 	for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
+ 	  {
+@@ -952,24 +955,35 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
+ 					  state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, 
+ 					  state->iaid, &req_addr)))
+ 		  {
+-		    /* If the server cannot find a client entry for the IA the server
+-		       returns the IA containing no addresses with a Status Code option set
+-		       to NoBinding in the Reply message. */
+-		    save_counter(iacntr);
+-		    t1cntr = 0;
+-		    
+-		    log6_packet(state, "DHCPREPLY", &req_addr, _("lease not found"));
+-		    
+-		    o1 = new_opt6(OPTION6_STATUS_CODE);
+-		    put_opt6_short(DHCP6NOBINDING);
+-		    put_opt6_string(_("no binding found"));
+-		    end_opt6(o1);
+-
+-		    preferred_time = valid_time = 0;
+-		    break;
++		    if (msg_type == DHCP6REBIND)
++		      {
++			/* When rebinding, we can create a lease if it doesn't exist. */
++			lease = lease6_allocate(&req_addr, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA);
++			if (lease)
++			  lease_set_iaid(lease, state->iaid);
++			else
++			  break;
++		      }
++		    else
++		      {
++			/* If the server cannot find a client entry for the IA the server
++			   returns the IA containing no addresses with a Status Code option set
++			   to NoBinding in the Reply message. */
++			save_counter(iacntr);
++			t1cntr = 0;
++			
++			log6_packet(state, "DHCPREPLY", &req_addr, _("lease not found"));
++			
++			o1 = new_opt6(OPTION6_STATUS_CODE);
++			put_opt6_short(DHCP6NOBINDING);
++			put_opt6_string(_("no binding found"));
++			end_opt6(o1);
++			
++			preferred_time = valid_time = 0;
++			break;
++		      }
+ 		  }
+ 		
+-		
+ 		if ((this_context = address6_available(state->context, &req_addr, tagif, 1)) ||
+ 		    (this_context = address6_valid(state->context, &req_addr, tagif, 1)))
+ 		  {
+@@ -1000,6 +1014,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
+ 		    
+ 		    if (preferred_time == 0)
+ 		      message = _("deprecated");
++
++		    address_assigned = 1;
+ 		  }
+ 		else
+ 		  {
+@@ -1022,10 +1038,18 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
+ 	    end_ia(t1cntr, min_time, 1);
+ 	    end_opt6(o);
+ 	  }
++
++	if (!address_assigned && msg_type == DHCP6REBIND)
++	  { 
++	    /* can't create lease for any address, return error */
++	    o1 = new_opt6(OPTION6_STATUS_CODE);
++	    put_opt6_short(DHCP6NOADDRS);
++	    put_opt6_string(_("no addresses available"));
++	    end_opt6(o1);
++	  }
+ 	
+ 	tagif = add_options(state, 0);
+ 	break;
+-	
+       }
+       
+     case DHCP6CONFIRM:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202105150924.14F9OR2S072976>