Hi!

After reading those changes a bit, it seems there are too many variables used in a complex mess. It is very easy to get lost in them, especially when sdetails just points somewhere to local function other variables.

I made attempt to reduce the complexity and amount of local variables. Instead I moved contents of variables directly into server_details structure and added function to just add server from its pointer. Tried reducing repetitions by moving similar parts to shared functions.

But I admit I haven't tested the result stays unchanged. It should not change any behaviour, just cleanups the code. I think I should finally fix more serious runnable tests, which would ensure the functionality stayed the same.

What do you think?

Cheers,
Petr

On 11/17/22 20:59, Simon Kelley wrote:
Thanks for testing these builds. That's a genuine problem.

Fixed in 2.88rc3, in git now.

Cheers,

Simon.


On 17/11/2022 18:26, Johnny S. Lee via Dnsmasq-discuss wrote:
"local=//" means "Do not forward unqualified names to any upstream
servers", right?
It has not generated any kind of error until I updated to v2.88rc2.
The last build I've been using was built against
d3c21c596ef96027429b11216fcdbf65c9434afa

_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss


_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss

--
Petr Menšík
Software Engineer, RHEL
Red Hat, https://www.redhat.com/
PGP: DFCF908DB7C87E8E529925BC4931CA5B6C9FC5CB
From 1a6eba5f3972efe31f1a03d33ed64e239ed47079 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemen...@redhat.com>
Date: Fri, 25 Nov 2022 15:02:37 +0100
Subject: [PATCH 3/3] Reuse similar dbus message parsing

Move almost same codes into single function, use map_address parameter
to make difference between them.
---
 src/dbus.c | 91 +++++++++++++++++++++++++-----------------------------
 1 file changed, 42 insertions(+), 49 deletions(-)

diff --git a/src/dbus.c b/src/dbus.c
index 6370b41..3e9b9a8 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -260,11 +260,46 @@ static DBusMessage *dbus_reply_server_loop(DBusMessage *message)
 }
 #endif
 
+/* Parse one entry from dbus. */
+static DBusMessage *dbus_parse_servers(DBusMessage *message,
+				       struct server_details *sdetails,
+				       char *str_addr, const char *str,
+				       int map_address)
+{
+  const char *addr_err;
+  DBusMessage *error = NULL;
+
+  if ((addr_err = parse_server(str_addr, sdetails)))
+    return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
+					 "Invalid IP address '%s': %s",
+					 str, addr_err);
+
+  while (parse_server_next(sdetails))
+    {
+      if ((addr_err = parse_server_addr(sdetails)))
+	return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
+					     "Invalid IP address '%s': %s",
+					     str, addr_err);
+
+      if (map_address)
+	{
+	  /* 0.0.0.0 for server address == NULL, for Dbus */
+	  if (sdetails->addr.in.sin_family == AF_INET &&
+	      sdetails->addr.in.sin_addr.s_addr == 0)
+	    sdetails->flags |= SERV_LITERAL_ADDRESS;
+	  else
+	    sdetails->flags &= ~SERV_LITERAL_ADDRESS;
+	}
+
+	add_update_server_details(sdetails, str, NULL);
+    }
+  return error;
+}
+
 static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
 {
   DBusMessageIter iter, array_iter, string_iter;
   DBusMessage *error = NULL;
-  const char *addr_err;
   char *dup = NULL;
   
   if (!dbus_message_iter_init(message, &iter))
@@ -392,26 +427,9 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
 	       }
 	     else
 	       {
-		 if ((addr_err = parse_server(str_addr, &sdetails)))
-		   {
-		     error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
-							   "Invalid IP address '%s': %s",
-							   str, addr_err);
-		     break;
-		   }
-		 
-		 while (parse_server_next(&sdetails))
-		   {
-		     if ((addr_err = parse_server_addr(&sdetails)))
-		       {
-			 error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
-							       "Invalid IP address '%s': %s",
-							       str, addr_err);
-			 break;
-		       }
-		     
-	             add_update_server_details(&sdetails, str_domain, NULL);
-		   }
+		 error = dbus_parse_servers(message, &sdetails, str_addr, str, 0);
+		 if (error)
+		   break;
 	       }
 	  } while ((str_domain = p));
 	}
@@ -427,34 +445,9 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
 	      dbus_message_iter_get_basic(&string_iter, &str);
 	    dbus_message_iter_next (&string_iter);
 
-	    if ((addr_err = parse_server(str_addr, &sdetails)))
-	      {
-		error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
-						      "Invalid IP address '%s': %s",
-						      str, addr_err);
-		break;
-	      }
-	    
-	    while (parse_server_next(&sdetails))
-	      {
-		if ((addr_err = parse_server_addr(&sdetails)))
-		  {
-		    error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
-							  "Invalid IP address '%s': %s",
-							  str, addr_err);
-		    break;
-		  }
-		
-		/* 0.0.0.0 for server address == NULL, for Dbus */
-		if (sdetails.addr.in.sin_family == AF_INET &&
-		    sdetails.addr.in.sin_addr.s_addr == 0)
-		  sdetails.flags |= SERV_LITERAL_ADDRESS;
-		else
-		  sdetails.flags &= ~SERV_LITERAL_ADDRESS;
-		
-	        add_update_server_details(&sdetails, str, NULL);
-	      }
-	  } while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);
+	    error = dbus_parse_servers(message, &sdetails, str_addr, str, 1);
+	  } while (!error &&
+		   dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);
 	}
       
       if (sdetails.orig_hostinfo)
-- 
2.38.1

From 4fce0e3f40ed1ad41c428ae2d20096b486c199be Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemen...@redhat.com>
Date: Tue, 22 Nov 2022 01:51:23 +0100
Subject: [PATCH 2/3] Reuse some common parts of server details parsing

Use server_details direct member, instead of using multiple local
variables linked from by pointers. Move some common parts to shared
function.
---
 src/dbus.c         |  26 +++---
 src/dnsmasq.h      |  10 +-
 src/domain-match.c |   8 ++
 src/option.c       | 225 +++++++++++++++++++--------------------------
 4 files changed, 122 insertions(+), 147 deletions(-)

diff --git a/src/dbus.c b/src/dbus.c
index 2067ed9..6370b41 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -288,15 +288,8 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
   while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID)
     {
       const char *str = NULL;
-      union  mysockaddr addr, source_addr;
-      u16 flags = 0;
-      char interface[IF_NAMESIZE];
       char *str_addr, *str_domain = NULL;
-      struct server_details sdetails = { 0 };
-      sdetails.addr = &addr;
-      sdetails.source_addr = &source_addr;
-      sdetails.interface = interface;
-      sdetails.flags = &flags;
+      struct server_details sdetails = { .flags = SERV_FROM_DBUS, };
 
       if (strings)
 	{
@@ -393,7 +386,10 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
 	      p = NULL;
 	    
 	     if (strings && strlen(str_addr) == 0)
-	       add_update_server(SERV_LITERAL_ADDRESS | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain, NULL);
+	       {
+		 sdetails.flags |= SERV_LITERAL_ADDRESS;
+	         add_update_server_details(&sdetails, str_domain, NULL);
+	       }
 	     else
 	       {
 		 if ((addr_err = parse_server(str_addr, &sdetails)))
@@ -414,7 +410,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
 			 break;
 		       }
 		     
-		     add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain, NULL);
+	             add_update_server_details(&sdetails, str_domain, NULL);
 		   }
 	       }
 	  } while ((str_domain = p));
@@ -450,13 +446,13 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
 		  }
 		
 		/* 0.0.0.0 for server address == NULL, for Dbus */
-		if (addr.in.sin_family == AF_INET &&
-		    addr.in.sin_addr.s_addr == 0)
-		  flags |= SERV_LITERAL_ADDRESS;
+		if (sdetails.addr.in.sin_family == AF_INET &&
+		    sdetails.addr.in.sin_addr.s_addr == 0)
+		  sdetails.flags |= SERV_LITERAL_ADDRESS;
 		else
-		  flags &= ~SERV_LITERAL_ADDRESS;
+		  sdetails.flags &= ~SERV_LITERAL_ADDRESS;
 		
-		add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str, NULL);
+	        add_update_server_details(&sdetails, str, NULL);
 	      }
 	  } while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);
 	}
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 90dc986..68fc01f 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1294,11 +1294,12 @@ extern struct daemon {
 } *daemon;
 
 struct server_details {
-  union mysockaddr *addr, *source_addr;
+  union mysockaddr addr, source_addr;
+  char interface[IF_NAMESIZE+1];
   struct addrinfo *hostinfo, *orig_hostinfo;
-  char *interface, *source, *scope_id, *interface_opt;
+  char *source, *scope_id, *interface_opt;
   int serv_port, source_port, addr_type, scope_index, valid;
-  u16 *flags;
+  u16 flags;
 };
 
 /* cache.c */
@@ -1860,3 +1861,6 @@ int add_update_server(int flags,
 		      const char *interface,
 		      const char *domain,
 		      union all_addr *local_addr); 
+int add_update_server_details(struct server_details *sdetails,
+		      const char *domain,
+		      union all_addr *local_addr);
diff --git a/src/domain-match.c b/src/domain-match.c
index bef460a..e66efbc 100644
--- a/src/domain-match.c
+++ b/src/domain-match.c
@@ -745,3 +745,11 @@ int add_update_server(int flags,
   return 1;
 }
 
+int add_update_server_details(struct server_details *sdetails,
+		      const char *domain,
+		      union all_addr *local_addr)
+{
+  char *interface = (sdetails->interface[0]) ? sdetails->interface : NULL;
+  return add_update_server(sdetails->flags, &sdetails->addr, &sdetails->source_addr,
+			   interface, domain, local_addr);
+}
diff --git a/src/option.c b/src/option.c
index efd5f49..4ffc64d 100644
--- a/src/option.c
+++ b/src/option.c
@@ -857,11 +857,12 @@ static char *parse_mysockaddr(char *arg, union mysockaddr *addr)
 
 char *parse_server(char *arg, struct server_details *sdetails)
 {
-  sdetails->serv_port = NAMESERVER_PORT;
   char *portno;
   int ecode = 0;
   struct addrinfo hints;
 
+  memset(sdetails, 0, sizeof(struct server_details));
+  sdetails->serv_port = NAMESERVER_PORT;
   memset(&hints, 0, sizeof(struct addrinfo));
   
   *sdetails->interface = 0;
@@ -869,8 +870,7 @@ char *parse_server(char *arg, struct server_details *sdetails)
      
   if (strcmp(arg, "#") == 0)
     {
-      if (sdetails->flags)
-	*sdetails->flags |= SERV_USE_RESOLV;
+      sdetails->flags |= SERV_USE_RESOLV;
       sdetails->addr_type = AF_LOCAL;
       sdetails->valid = 1;
       return NULL;
@@ -901,9 +901,9 @@ char *parse_server(char *arg, struct server_details *sdetails)
       }
   }
 
-  if (inet_pton(AF_INET, arg, &sdetails->addr->in.sin_addr) > 0)
+  if (inet_pton(AF_INET, arg, &sdetails->addr.in.sin_addr) > 0)
       sdetails->addr_type = AF_INET;
-  else if (inet_pton(AF_INET6, arg, &sdetails->addr->in6.sin6_addr) > 0)
+  else if (inet_pton(AF_INET6, arg, &sdetails->addr.in6.sin6_addr) > 0)
       sdetails->addr_type = AF_INET6;
   else 
     {
@@ -966,24 +966,23 @@ char *parse_server_addr(struct server_details *sdetails)
 {
   if (sdetails->addr_type == AF_INET)
     {
-      sdetails->addr->in.sin_port = htons(sdetails->serv_port);
-      sdetails->addr->sa.sa_family = sdetails->source_addr->sa.sa_family = AF_INET;
+      sdetails->addr.in.sin_port = htons(sdetails->serv_port);
+      sdetails->addr.sa.sa_family = sdetails->source_addr.sa.sa_family = AF_INET;
 #ifdef HAVE_SOCKADDR_SA_LEN
-      sdetails->source_addr->in.sin_len = sdetails->addr->in.sin_len = sizeof(struct sockaddr_in);
+      sdetails->source_addr.in.sin_len = sdetails->addr->in.sin_len = sizeof(struct sockaddr_in);
 #endif
-      sdetails->source_addr->in.sin_addr.s_addr = INADDR_ANY;
-      sdetails->source_addr->in.sin_port = htons(daemon->query_port);
+      sdetails->source_addr.in.sin_addr.s_addr = INADDR_ANY;
+      sdetails->source_addr.in.sin_port = htons(daemon->query_port);
       
       if (sdetails->source)
 	{
-	  if (sdetails->flags)
-	    *sdetails->flags |= SERV_HAS_SOURCE;
-	  sdetails->source_addr->in.sin_port = htons(sdetails->source_port);
-	  if (inet_pton(AF_INET, sdetails->source, &sdetails->source_addr->in.sin_addr) == 0)
+	  sdetails->flags |= SERV_HAS_SOURCE;
+	  sdetails->source_addr.in.sin_port = htons(sdetails->source_port);
+	  if (inet_pton(AF_INET, sdetails->source, &sdetails->source_addr.in.sin_addr) == 0)
 	    {
-	      if (inet_pton(AF_INET6, sdetails->source, &sdetails->source_addr->in6.sin6_addr) == 1)
+	      if (inet_pton(AF_INET6, sdetails->source, &sdetails->source_addr.in6.sin6_addr) == 1)
 		{
-		  sdetails->source_addr->sa.sa_family = AF_INET6;
+		  sdetails->source_addr.sa.sa_family = AF_INET6;
 		  /* When resolving a server IP by hostname, we can simply skip mismatching
 		     server / source IP pairs. Otherwise, when an IP address is given directly,
 		     this is a fatal error. */
@@ -996,7 +995,7 @@ char *parse_server_addr(struct server_details *sdetails)
 		  if (sdetails->interface_opt)
 		    return _("interface can only be specified once");
 
-		  sdetails->source_addr->in.sin_addr.s_addr = INADDR_ANY;
+		  sdetails->source_addr.in.sin_addr.s_addr = INADDR_ANY;
 		  safe_strncpy(sdetails->interface, sdetails->source, IF_NAMESIZE);
 #else
 		  return _("interface binding not supported");
@@ -1010,26 +1009,25 @@ char *parse_server_addr(struct server_details *sdetails)
       if (sdetails->scope_id && (sdetails->scope_index = if_nametoindex(sdetails->scope_id)) == 0)
 	return _("bad interface name");
 
-      sdetails->addr->in6.sin6_port = htons(sdetails->serv_port);
-      sdetails->addr->in6.sin6_scope_id = sdetails->scope_index;
-      sdetails->source_addr->in6.sin6_addr = in6addr_any;
-      sdetails->source_addr->in6.sin6_port = htons(daemon->query_port);
-      sdetails->source_addr->in6.sin6_scope_id = 0;
-      sdetails->addr->sa.sa_family = sdetails->source_addr->sa.sa_family = AF_INET6;
-      sdetails->addr->in6.sin6_flowinfo = sdetails->source_addr->in6.sin6_flowinfo = 0;
+      sdetails->addr.in6.sin6_port = htons(sdetails->serv_port);
+      sdetails->addr.in6.sin6_scope_id = sdetails->scope_index;
+      sdetails->source_addr.in6.sin6_addr = in6addr_any;
+      sdetails->source_addr.in6.sin6_port = htons(daemon->query_port);
+      sdetails->source_addr.in6.sin6_scope_id = 0;
+      sdetails->addr.sa.sa_family = sdetails->source_addr.sa.sa_family = AF_INET6;
+      sdetails->addr.in6.sin6_flowinfo = sdetails->source_addr.in6.sin6_flowinfo = 0;
 #ifdef HAVE_SOCKADDR_SA_LEN
-      sdetails->addr->in6.sin6_len = sdetails->source_addr->in6.sin6_len = sizeof(sdetails->addr->in6);
+      sdetails->addr.in6.sin6_len = sdetails->source_addr.in6.sin6_len = sizeof(sdetails->addr->in6);
 #endif
       if (sdetails->source)
 	{
-	  if (sdetails->flags)
-	    *sdetails->flags |= SERV_HAS_SOURCE;
-	  sdetails->source_addr->in6.sin6_port = htons(sdetails->source_port);
-	  if (inet_pton(AF_INET6, sdetails->source, &sdetails->source_addr->in6.sin6_addr) == 0)
+	  sdetails->flags |= SERV_HAS_SOURCE;
+	  sdetails->source_addr.in6.sin6_port = htons(sdetails->source_port);
+	  if (inet_pton(AF_INET6, sdetails->source, &sdetails->source_addr.in6.sin6_addr) == 0)
 	    {
-	      if (inet_pton(AF_INET, sdetails->source, &sdetails->source_addr->in.sin_addr) == 1)
+	      if (inet_pton(AF_INET, sdetails->source, &sdetails->source_addr.in.sin_addr) == 1)
 		{
-		  sdetails->source_addr->sa.sa_family = AF_INET;
+		  sdetails->source_addr.sa.sa_family = AF_INET;
 		  /* When resolving a server IP by hostname, we can simply skip mismatching
 		     server / source IP pairs. Otherwise, when an IP address is given directly,
 		     this is a fatal error. */
@@ -1042,7 +1040,7 @@ char *parse_server_addr(struct server_details *sdetails)
 		  if (sdetails->interface_opt)
 		  return _("interface can only be specified once");
 
-		  sdetails->source_addr->in6.sin6_addr = in6addr_any;
+		  sdetails->source_addr.in6.sin6_addr = in6addr_any;
 		  safe_strncpy(sdetails->interface, sdetails->source, IF_NAMESIZE);
 #else
 		  return _("interface binding not supported");
@@ -1067,13 +1065,13 @@ int parse_server_next(struct server_details *sdetails)
 
       /* Get address */
       if (sdetails->addr_type == AF_INET)
-	memcpy(&sdetails->addr->in.sin_addr,
+	memcpy(&sdetails->addr.in.sin_addr,
 		&((struct sockaddr_in *) sdetails->hostinfo->ai_addr)->sin_addr,
-		sizeof(sdetails->addr->in.sin_addr));
+		sizeof(sdetails->addr.in.sin_addr));
       else if (sdetails->addr_type == AF_INET6)
-	memcpy(&sdetails->addr->in6.sin6_addr,
+	memcpy(&sdetails->addr.in6.sin6_addr,
 		&((struct sockaddr_in6 *) sdetails->hostinfo->ai_addr)->sin6_addr,
-		sizeof(sdetails->addr->in6.sin6_addr));
+		sizeof(sdetails->addr.in6.sin6_addr));
 
       /* Iterate to the next available address */
       sdetails->valid = sdetails->hostinfo->ai_next != NULL;
@@ -1090,31 +1088,63 @@ int parse_server_next(struct server_details *sdetails)
   return 0;
 }
 
+static char *add_server_rev(struct server_details *sdetails,
+		      const char *domain,
+		      union all_addr *local_addr)
+{
+  if (sdetails->flags & SERV_LITERAL_ADDRESS)
+    {
+      if (!add_update_server_details(sdetails, domain, local_addr))
+	return  _("error");
+    }
+  else
+    {
+      char *string;
+
+      while (parse_server_next(sdetails))
+	{
+	  if ((string = parse_server_addr(sdetails)))
+	    return string;
+	      
+	  if (!add_update_server_details(sdetails, domain, local_addr))
+	    return  _("error");
+	}
+
+      if (sdetails->orig_hostinfo)
+	{
+	  freeaddrinfo(sdetails->orig_hostinfo);
+	  sdetails->orig_hostinfo = NULL;
+	}
+    }
+  return NULL;
+}
+
+static char *parse_server_rev(int from_file, char *server, struct server_details *sdetails)
+{
+  char *string;
+
+  if (!server)
+    sdetails->flags = SERV_LITERAL_ADDRESS;
+  else if ((string = parse_server(server, sdetails)))
+    return string;
+  
+  if (from_file)
+    sdetails->flags |= SERV_FROM_FILE;
+
+  return NULL;
+}
+
 static char *domain_rev4(int from_file, char *server, struct in_addr *addr4, int size)
 {
   int i, j;
-  char *string;
+  char *string, *ret = NULL;
   int msize;
-  u16 flags = 0;
   char domain[29]; /* strlen("xxx.yyy.zzz.ttt.in-addr.arpa")+1 */
-  union mysockaddr serv_addr, source_addr;
-  char interface[IF_NAMESIZE+1];
   int count = 1, rem, addrbytes, addrbits;
   struct server_details sdetails;
 
-  memset(&sdetails, 0, sizeof(struct server_details));
-  sdetails.addr = &serv_addr;
-  sdetails.source_addr = &source_addr;
-  sdetails.interface = interface;
-  sdetails.flags = &flags;
-    
-  if (!server)
-    flags = SERV_LITERAL_ADDRESS;
-  else if ((string = parse_server(server, &sdetails)))
-    return string;
-  
-  if (from_file)
-    flags |= SERV_FROM_FILE;
+  if ((ret = parse_server_rev(from_file, server, &sdetails)))
+    return ret;
  
   rem = size & 0x7;
   addrbytes = (32 - size) >> 3;
@@ -1131,7 +1161,7 @@ static char *domain_rev4(int from_file, char *server, struct in_addr *addr4, int
   if (rem != 0)
     count = 1 << (8 - rem);
   
-  for (i = 0; i < count; i++)
+  for (i = 0; !ret && i < count; i++)
     {
       *domain = 0;
       string = domain;
@@ -1149,59 +1179,24 @@ static char *domain_rev4(int from_file, char *server, struct in_addr *addr4, int
       
       sprintf(string, "in-addr.arpa");
 
-      if (flags & SERV_LITERAL_ADDRESS)
-	{
-	  if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, NULL))
-	    return  _("error");
-	}
-      else
-	{
-	  while (parse_server_next(&sdetails))
-	    {
-	      if ((string = parse_server_addr(&sdetails)))
-		return string;
-	      
-	      if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, NULL))
-		return  _("error");
-	    }
-
-	  if (sdetails.orig_hostinfo)
-	    {
-	      freeaddrinfo(sdetails.orig_hostinfo);
-	      sdetails.orig_hostinfo = NULL;
-	    }
-	}
+      ret = add_server_rev(&sdetails, domain, NULL);
     }
   
-  return NULL;
+  return ret;
 }
 
 static char *domain_rev6(int from_file, char *server, struct in6_addr *addr6, int size)
 {
   int i, j;
-  char *string;
+  char *string, *ret = NULL;
   int msize;
-  u16 flags = 0;
   char domain[73]; /* strlen("32*<n.>ip6.arpa")+1 */
-  union mysockaddr serv_addr, source_addr;
-  char interface[IF_NAMESIZE+1];
   int count = 1, rem, addrbytes, addrbits;
   struct server_details sdetails;
   
-  memset(&sdetails, 0, sizeof(struct server_details));
-  sdetails.addr = &serv_addr;
-  sdetails.source_addr = &source_addr;
-  sdetails.interface = interface;
-  sdetails.flags = &flags;
-   
-  if (!server)
-    flags = SERV_LITERAL_ADDRESS;
-  else if ((string = parse_server(server, &sdetails)))
-    return string;
+  if ((ret = parse_server_rev(from_file, server, &sdetails)))
+    return ret;
 
-  if (from_file)
-    flags |= SERV_FROM_FILE;
-  
   rem = size & 0x3;
   addrbytes = (128 - size) >> 3;
   addrbits = (128 - size) & 7;
@@ -1217,7 +1212,7 @@ static char *domain_rev6(int from_file, char *server, struct in6_addr *addr6, in
   if (rem != 0)
     count = 1 << (4 - rem);
       
-  for (i = 0; i < count; i++)
+  for (i = 0; !ret && i < count; i++)
     {
       *domain = 0;
       string = domain;
@@ -1237,31 +1232,10 @@ static char *domain_rev6(int from_file, char *server, struct in6_addr *addr6, in
       
       sprintf(string, "ip6.arpa");
 
-      if (flags & SERV_LITERAL_ADDRESS)
-	{
-	  if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, NULL))
-	    return  _("error");
-	}
-      else
-	{
-	  while (parse_server_next(&sdetails))
-	    {
-	      if ((string = parse_server_addr(&sdetails)))
-		return string;
-	      
-	      if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, NULL))
-		return  _("error");
-	    }
-
-	  if (sdetails.orig_hostinfo)
-	    {
-	      freeaddrinfo(sdetails.orig_hostinfo);
-	      sdetails.orig_hostinfo = NULL;
-	    }
-	}
+      ret = add_server_rev(&sdetails, domain, NULL);
     }
   
-  return NULL;
+  return ret;
 }
 
 #ifdef HAVE_DHCP
@@ -2975,16 +2949,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
 	u16 flags = 0;
 	char *err;
 	union all_addr addr;
-	union mysockaddr serv_addr, source_addr;
-	char interface[IF_NAMESIZE+1];
 	struct server_details sdetails;
 
-	memset(&sdetails, 0, sizeof(struct server_details));
-	sdetails.addr = &serv_addr;
-	sdetails.source_addr = &source_addr;
-	sdetails.interface = interface;
-	sdetails.flags = &flags;
-			
 	unhide_metas(arg);
 	
 	/* split the domain args, if any and skip to the end of them. */
@@ -3033,7 +2999,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
 	      ret_err(err);
 
 	    /* When source is set only use DNS records of the same type and skip all others */
-	    if (flags & SERV_HAS_SOURCE && sdetails.addr_type != sdetails.source_addr->sa.sa_family)
+	    if (flags & SERV_HAS_SOURCE && sdetails.addr_type != sdetails.source_addr.sa.sa_family)
 	      continue;
 
 	    while (1)
@@ -3050,8 +3016,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
 		    if (option == 'A' && cur_domain[0] == '#' && cur_domain[1] == 0)
 		      cur_domain[0] = 0;
 		  }
-		
-		if (!add_update_server(flags, sdetails.addr, sdetails.source_addr, sdetails.interface, cur_domain, &addr))
+
+		sdetails.flags = flags;
+		if (!add_update_server_details(&sdetails, cur_domain, &addr))
 		  ret_err(gen_err);
 		
 		if (!lastdomain || cur_domain == lastdomain)
-- 
2.38.1

From a9cbe6d9e75680202e9df269b214da6c5a53250d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemen...@redhat.com>
Date: Fri, 25 Nov 2022 15:39:19 +0100
Subject: [PATCH 1/3] Ensure pointer is always invalidated after freeaddrinfo

freeaddrinfo is called conditionally. Ensure when the pointer is
invalidated, it no longer points to non-NULL memory and free again
cannot happen on the same structure.
---
 src/dbus.c   |  5 ++++-
 src/option.c | 15 ++++++++++++---
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/src/dbus.c b/src/dbus.c
index fd5d1ca..2067ed9 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -462,7 +462,10 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
 	}
       
       if (sdetails.orig_hostinfo)
-	freeaddrinfo(sdetails.orig_hostinfo);
+	{
+	  freeaddrinfo(sdetails.orig_hostinfo);
+	  sdetails.orig_hostinfo = NULL;
+	}
       
       /* jump to next element in outer array */
       dbus_message_iter_next(&array_iter);
diff --git a/src/option.c b/src/option.c
index 6a63268..efd5f49 100644
--- a/src/option.c
+++ b/src/option.c
@@ -1166,7 +1166,10 @@ static char *domain_rev4(int from_file, char *server, struct in_addr *addr4, int
 	    }
 
 	  if (sdetails.orig_hostinfo)
-	    freeaddrinfo(sdetails.orig_hostinfo);
+	    {
+	      freeaddrinfo(sdetails.orig_hostinfo);
+	      sdetails.orig_hostinfo = NULL;
+	    }
 	}
     }
   
@@ -1251,7 +1254,10 @@ static char *domain_rev6(int from_file, char *server, struct in6_addr *addr6, in
 	    }
 
 	  if (sdetails.orig_hostinfo)
-	    freeaddrinfo(sdetails.orig_hostinfo);
+	    {
+	      freeaddrinfo(sdetails.orig_hostinfo);
+	      sdetails.orig_hostinfo = NULL;
+	    }
 	}
     }
   
@@ -3059,7 +3065,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
 	  }
 
 	if (sdetails.orig_hostinfo)
-	  freeaddrinfo(sdetails.orig_hostinfo);
+	  {
+	    freeaddrinfo(sdetails.orig_hostinfo);
+	    sdetails.orig_hostinfo = NULL;
+	  }
 	
      	break;
       }
-- 
2.38.1

_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss

Reply via email to