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

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