Blame SOURCES/dnsmasq-2.79-rh1728698-4.patch

85f98a
From 11ab42e63f9089c4c14a391f30175d4c2d071e99 Mon Sep 17 00:00:00 2001
85f98a
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
85f98a
Date: Mon, 15 Jul 2019 17:13:12 +0200
85f98a
Subject: [PATCH 4/5] Handle listening on duplicate addresses
85f98a
85f98a
Save listening address into listener. Use it to find existing listeners
85f98a
before creating new one. If it exist, increase just used counter.
85f98a
Release only listeners not already used.
85f98a
85f98a
Duplicates family in listener.
85f98a
---
85f98a
 src/dnsmasq.h |   3 +-
85f98a
 src/network.c | 115 ++++++++++++++++++++++++++++++++++++--------------
85f98a
 2 files changed, 85 insertions(+), 33 deletions(-)
85f98a
85f98a
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
85f98a
index 89d138a..3b3f6ef 100644
85f98a
--- a/src/dnsmasq.h
85f98a
+++ b/src/dnsmasq.h
85f98a
@@ -552,7 +552,8 @@ struct irec {
85f98a
 };
85f98a
 
85f98a
 struct listener {
85f98a
-  int fd, tcpfd, tftpfd, family;
85f98a
+  int fd, tcpfd, tftpfd, family, used;
85f98a
+  union mysockaddr addr;
85f98a
   struct irec *iface; /* only sometimes valid for non-wildcard */
85f98a
   struct listener *next;
85f98a
 };
85f98a
diff --git a/src/network.c b/src/network.c
85f98a
index d6d4b01..4bbd810 100644
85f98a
--- a/src/network.c
85f98a
+++ b/src/network.c
85f98a
@@ -577,6 +577,56 @@ static void clean_interfaces()
85f98a
   }
85f98a
 }
85f98a
 
85f98a
+/** Release listener if no other interface needs it.
85f98a
+ *
85f98a
+ * @return 1 if released, 0 if still required
85f98a
+ */
85f98a
+static int release_listener(struct listener *l)
85f98a
+{
85f98a
+  if (l->used > 1)
85f98a
+    {
85f98a
+      struct irec *iface;
85f98a
+      for (iface = daemon->interfaces; iface; iface = iface->next)
85f98a
+	if (iface->done && sockaddr_isequal(&l->addr, &iface->addr))
85f98a
+	  {
85f98a
+	    if (iface->found)
85f98a
+	      {
85f98a
+		/* update listener to point to active interface instead */
85f98a
+		if (!l->iface->found)
85f98a
+		  l->iface = iface;
85f98a
+	      }
85f98a
+	    else
85f98a
+	      {
85f98a
+		l->used--;
85f98a
+		iface->done = 0;
85f98a
+	      }
85f98a
+	  }
85f98a
+
85f98a
+      /* Someone is still using this listener, skip its deletion */
85f98a
+      if (l->used > 0)
85f98a
+	return 0;
85f98a
+    }
85f98a
+
85f98a
+  if (l->iface->done)
85f98a
+    {
85f98a
+      (void)prettyprint_addr(&l->iface->addr, daemon->addrbuff);
85f98a
+      my_syslog(LOG_DEBUG, _("stopped listening on %s(#%d): %s"),
85f98a
+		l->iface->name, l->iface->index, daemon->addrbuff);
85f98a
+      /* In case it ever returns */
85f98a
+      l->iface->done = 0;
85f98a
+    }
85f98a
+
85f98a
+  if (l->fd != -1)
85f98a
+    close(l->fd);
85f98a
+  if (l->tcpfd != -1)
85f98a
+    close(l->tcpfd);
85f98a
+  if (l->tftpfd != -1)
85f98a
+    close(l->tftpfd);
85f98a
+
85f98a
+  free(l);
85f98a
+  return 1;
85f98a
+}
85f98a
+
85f98a
 int enumerate_interfaces(int reset)
85f98a
 {
85f98a
   static struct addrlist *spare = NULL;
85f98a
@@ -684,29 +734,10 @@ int enumerate_interfaces(int reset)
85f98a
 	  
85f98a
 	  if (!l->iface || l->iface->found)
85f98a
 	    up = &l->next;
85f98a
-	  else
85f98a
+	  else if (release_listener(l))
85f98a
 	    {
85f98a
-	      *up = l->next;
85f98a
-	      if (l->iface->done)
85f98a
-	        {
85f98a
-	          iface = l->iface;
85f98a
-	          (void)prettyprint_addr(&iface->addr, daemon->addrbuff);
85f98a
-	          my_syslog(LOG_DEBUG, _("stopped listening on %s(#%d): %s"),
85f98a
-	                    iface->name, iface->index, daemon->addrbuff);
85f98a
-	        }
85f98a
-	      
85f98a
-	      /* In case it ever returns */
85f98a
-	      l->iface->done = 0;
85f98a
-	      
85f98a
-	      if (l->fd != -1)
85f98a
-		close(l->fd);
85f98a
-	      if (l->tcpfd != -1)
85f98a
-		close(l->tcpfd);
85f98a
-	      if (l->tftpfd != -1)
85f98a
-		close(l->tftpfd);
85f98a
-	      
85f98a
-	      free(l);
85f98a
-	      freed = 1;
85f98a
+	      *up = tmp;
85f98a
+		freed = 1;
85f98a
 	    }
85f98a
 	}
85f98a
 
85f98a
@@ -959,7 +990,9 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
85f98a
       l->family = addr->sa.sa_family;
85f98a
       l->fd = fd;
85f98a
       l->tcpfd = tcpfd;
85f98a
-      l->tftpfd = tftpfd;	
85f98a
+      l->tftpfd = tftpfd;
85f98a
+      l->addr = *addr;
85f98a
+      l->used = 1;
85f98a
       l->iface = NULL;
85f98a
     }
85f98a
 
85f98a
@@ -1000,23 +1033,41 @@ void create_wildcard_listeners(void)
85f98a
   daemon->listeners = l;
85f98a
 }
85f98a
 
85f98a
+static struct listener *find_listener(union mysockaddr *addr)
85f98a
+{
85f98a
+  struct listener *l;
85f98a
+  for (l = daemon->listeners; l; l = l->next)
85f98a
+    if (sockaddr_isequal(&l->addr, addr))
85f98a
+      return l;
85f98a
+  return NULL;
85f98a
+}
85f98a
+
85f98a
 void create_bound_listeners(int dienow)
85f98a
 {
85f98a
   struct listener *new;
85f98a
   struct irec *iface;
85f98a
   struct iname *if_tmp;
85f98a
+  struct listener *existing;
85f98a
 
85f98a
   for (iface = daemon->interfaces; iface; iface = iface->next)
85f98a
-    if (!iface->done && !iface->dad && iface->found &&
85f98a
-	(new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
85f98a
+    if (!iface->done && !iface->dad && iface->found)
85f98a
       {
85f98a
-	new->iface = iface;
85f98a
-	new->next = daemon->listeners;
85f98a
-	daemon->listeners = new;
85f98a
-	iface->done = 1;
85f98a
-	(void)prettyprint_addr(&iface->addr, daemon->addrbuff);
85f98a
-	my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s"),
85f98a
-	          iface->name, iface->index, daemon->addrbuff);
85f98a
+	existing = find_listener(&iface->addr);
85f98a
+	if (existing)
85f98a
+	  {
85f98a
+	    iface->done = 1;
85f98a
+	    existing->used++; /* increase usage counter */
85f98a
+	  }
85f98a
+	else if ((new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
85f98a
+	  {
85f98a
+	    new->iface = iface;
85f98a
+	    new->next = daemon->listeners;
85f98a
+	    daemon->listeners = new;
85f98a
+	    iface->done = 1;
85f98a
+	    (void)prettyprint_addr(&iface->addr, daemon->addrbuff);
85f98a
+	    my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s"),
85f98a
+		      iface->name, iface->index, daemon->addrbuff);
85f98a
+	  }
85f98a
       }
85f98a
 
85f98a
   /* Check for --listen-address options that haven't been used because there's
85f98a
-- 
85f98a
2.20.1
85f98a