From 65a01b71bb433c9466e4c78a73a8d8ed218ed4e8 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 31 Dec 2018 23:56:33 +0000
Subject: [PATCH 19/32] Tidy address-union handling: move class into explicit
 argument.

This moves the class argument to cache-insert into an argument,
rather then overloading a union in the address argument. Note that
tha class is NOT stored in the cache other than for DS/DNSKEY entries,
so must always be C_IN except for these. The data-extraction code
ensures this as it only attempts to cache C_IN class records.

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
 src/cache.c   | 57 ++++++++++++++++++++++-----------------------------
 src/dnsmasq.h |  2 +-
 src/dnssec.c  | 13 +++---------
 src/rfc1035.c | 12 +++++------
 4 files changed, 34 insertions(+), 50 deletions(-)

--- a/src/cache.c
+++ b/src/cache.c
@@ -26,7 +26,7 @@ static union bigname *big_free = NULL;
 static int bignames_left, hash_size;
 
 static void make_non_terminals(struct crec *source);
-static struct crec *really_insert(char *name, struct all_addr *addr, 
+static struct crec *really_insert(char *name, struct all_addr *addr, unsigned short class,
 				  time_t now,  unsigned long ttl, unsigned short flags);
 
 /* type->string mapping: this is also used by the name-hash function as a mixing table. */
@@ -330,8 +330,8 @@ static int is_expired(time_t now, struct
   return 1;
 }
 
-static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags,
-				    struct crec **target_crec, unsigned int *target_uid)
+static struct crec *cache_scan_free(char *name, struct all_addr *addr, unsigned short class, time_t now,
+				    unsigned short flags, struct crec **target_crec, unsigned int *target_uid)
 {
   /* Scan and remove old entries.
      If (flags & F_FORWARD) then remove any forward entries for name and any expired
@@ -350,6 +350,8 @@ static struct crec *cache_scan_free(char
      This entry will get re-used with the same name, to preserve CNAMEs. */
  
   struct crec *crecp, **up;
+
+  (void)class;
   
   if (flags & F_FORWARD)
     {
@@ -381,7 +383,7 @@ static struct crec *cache_scan_free(char
 	      
 #ifdef HAVE_DNSSEC
 	      /* Deletion has to be class-sensitive for DS and DNSKEY */
-	      if ((flags & crecp->flags & (F_DNSKEY | F_DS)) && crecp->uid == addr->addr.dnssec.class)
+	      if ((flags & crecp->flags & (F_DNSKEY | F_DS)) && crecp->uid == class)
 		{
 		  if (crecp->flags & F_CONFIG)
 		    return crecp;
@@ -464,7 +466,7 @@ void cache_start_insert(void)
   insert_error = 0;
 }
 
-struct crec *cache_insert(char *name, struct all_addr *addr, 
+struct crec *cache_insert(char *name, struct all_addr *addr, unsigned short class,
 			  time_t now,  unsigned long ttl, unsigned short flags)
 {
   /* Don't log DNSSEC records here, done elsewhere */
@@ -478,11 +480,11 @@ struct crec *cache_insert(char *name, st
 	ttl = daemon->min_cache_ttl;
     }
   
-  return really_insert(name, addr, now, ttl, flags);
+  return really_insert(name, addr, class, now, ttl, flags);
 }
 
 
-static struct crec *really_insert(char *name, struct all_addr *addr, 
+static struct crec *really_insert(char *name, struct all_addr *addr, unsigned short class,
 				  time_t now,  unsigned long ttl, unsigned short flags)
 {
   struct crec *new, *target_crec = NULL;
@@ -497,7 +499,7 @@ static struct crec *really_insert(char *
   
   /* First remove any expired entries and entries for the name/address we
      are currently inserting. */
-  if ((new = cache_scan_free(name, addr, now, flags, &target_crec, &target_uid)))
+  if ((new = cache_scan_free(name, addr, class, now, flags, &target_crec, &target_uid)))
     {
       /* We're trying to insert a record over one from 
 	 /etc/hosts or DHCP, or other config. If the 
@@ -553,21 +555,14 @@ static struct crec *really_insert(char *
       
       if (freed_all)
 	{
-	  struct all_addr free_addr = new->addr.addr;;
-	  
-#ifdef HAVE_DNSSEC
-	  /* For DNSSEC records, addr holds class. */
-	  if (new->flags & (F_DS | F_DNSKEY))
-	    free_addr.addr.dnssec.class = new->uid;
-#endif
-	  
+	  /* For DNSSEC records, uid holds class. */
 	  free_avail = 1; /* Must be free space now. */
-	  cache_scan_free(cache_get_name(new), &free_addr, now, new->flags, NULL, NULL);
+	  cache_scan_free(cache_get_name(new), &new->addr.addr, new->uid, now, new->flags, NULL, NULL);
 	  daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]++;
 	}
       else
 	{
-	  cache_scan_free(NULL, NULL, now, 0, NULL, NULL);
+	  cache_scan_free(NULL, NULL, class, now, 0, NULL, NULL);
 	  freed_all = 1;
 	}
     }
@@ -615,15 +610,13 @@ static struct crec *really_insert(char *
   else
     *cache_get_name(new) = 0;
 
-  if (addr)
-    {
 #ifdef HAVE_DNSSEC
-      if (flags & (F_DS | F_DNSKEY))
-	new->uid = addr->addr.dnssec.class;
-      else
+  if (flags & (F_DS | F_DNSKEY))
+    new->uid = class;
 #endif
-	new->addr.addr = *addr;	
-    }
+
+  if (addr)
+    new->addr.addr = *addr;	
 
   new->ttd = now + (time_t)ttl;
   new->next = new_chain;
@@ -747,11 +740,11 @@ int cache_recv_insert(time_t now, int fd
 	{
 	  if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
 	    return 0;
-	  crecp = really_insert(daemon->namebuff, &addr, now, ttl, flags);
+	  crecp = really_insert(daemon->namebuff, &addr, C_IN, now, ttl, flags);
 	}
       else if (flags & F_CNAME)
 	{
-	  struct crec *newc = really_insert(daemon->namebuff, NULL, now, ttl, flags);
+	  struct crec *newc = really_insert(daemon->namebuff, NULL, C_IN, now, ttl, flags);
 	  /* This relies on the fact the the target of a CNAME immediately preceeds
 	     it because of the order of extraction in extract_addresses, and
 	     the order reversal on the new_chain. */
@@ -780,10 +773,8 @@ int cache_recv_insert(time_t now, int fd
 	  
 	  if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1))
 	    return 0;
-	  /* Cache needs to known class for DNSSEC stuff */
-	  addr.addr.dnssec.class = class;
-
-	  crecp = really_insert(daemon->namebuff, &addr, now, ttl, flags);
+	 
+	  crecp = really_insert(daemon->namebuff, NULL, class, now, ttl, flags);
 	    
 	  if (flags & F_DNSKEY)
 	    {
@@ -1463,7 +1454,7 @@ void cache_add_dhcp_entry(char *host_nam
 	}
       else if (!(crec->flags & F_DHCP))
 	{
-	  cache_scan_free(host_name, NULL, 0, crec->flags & (flags | F_CNAME | F_FORWARD), NULL, NULL);
+	  cache_scan_free(host_name, NULL, C_IN, 0, crec->flags & (flags | F_CNAME | F_FORWARD), NULL, NULL);
 	  /* scan_free deletes all addresses associated with name */
 	  break;
 	}
@@ -1490,7 +1481,7 @@ void cache_add_dhcp_entry(char *host_nam
       if (crec->flags & F_NEG)
 	{
 	  flags |= F_REVERSE;
-	  cache_scan_free(NULL, (struct all_addr *)host_address, 0, flags, NULL, NULL);
+	  cache_scan_free(NULL, (struct all_addr *)host_address, C_IN, 0, flags, NULL, NULL);
 	}
     }
   else
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1144,7 +1144,7 @@ struct crec *cache_find_by_name(struct c
 void cache_end_insert(void);
 void cache_start_insert(void);
 int cache_recv_insert(time_t now, int fd);
-struct crec *cache_insert(char *name, struct all_addr *addr,
+struct crec *cache_insert(char *name, struct all_addr *addr, unsigned short class, 
 			  time_t now, unsigned long ttl, unsigned short flags);
 void cache_reload(void);
 void cache_add_dhcp_entry(char *host_name, int prot, struct all_addr *host_address, time_t ttd);
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -798,12 +798,9 @@ int dnssec_validate_by_ds(time_t now, st
 		  algo = *p++;
 		  keytag = dnskey_keytag(algo, flags, p, rdlen - 4);
 		  
-		  /* Cache needs to known class for DNSSEC stuff */
-		  a.addr.dnssec.class = class;
-		  
 		  if ((key = blockdata_alloc((char*)p, rdlen - 4)))
 		    {
-		      if (!(recp1 = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DNSSECOK)))
+		      if (!(recp1 = cache_insert(name, &a, class, now, ttl, F_FORWARD | F_DNSKEY | F_DNSSECOK)))
 			{
 			  blockdata_free(key);
 			  return STAT_BOGUS;
@@ -927,12 +924,9 @@ int dnssec_validate_ds(time_t now, struc
 	      algo = *p++;
 	      digest = *p++;
 	      
-	      /* Cache needs to known class for DNSSEC stuff */
-	      a.addr.dnssec.class = class;
-	      
 	      if ((key = blockdata_alloc((char*)p, rdlen - 4)))
 		{
-		  if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
+		  if (!(crecp = cache_insert(name, NULL, class, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
 		    {
 		      blockdata_free(key);
 		      return STAT_BOGUS;
@@ -1021,8 +1015,7 @@ int dnssec_validate_ds(time_t now, struc
 	{
 	  cache_start_insert();
 	  
-	  a.addr.dnssec.class = class;
-	  if (!cache_insert(name, &a, now, ttl, flags))
+	  if (!cache_insert(name, NULL, class, now, ttl, flags))
 	    return STAT_BOGUS;
 	  
 	  cache_end_insert();  
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -701,7 +701,7 @@ int extract_addresses(struct dns_header
 			  goto cname_loop;
 			}
 		      
-		      cache_insert(name, &addr, now, cttl, name_encoding | secflag | F_REVERSE);
+		      cache_insert(name, &addr, C_IN, now, cttl, name_encoding | secflag | F_REVERSE);
 		      found = 1; 
 		    }
 		  
@@ -719,7 +719,7 @@ int extract_addresses(struct dns_header
 		  ttl = find_soa(header, qlen, NULL, doctored);
 		}
 	      if (ttl)
-		cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | (secure ?  F_DNSSECOK : 0));	
+		cache_insert(NULL, &addr, C_IN, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | (secure ?  F_DNSSECOK : 0));	
 	    }
 	}
       else
@@ -773,7 +773,7 @@ int extract_addresses(struct dns_header
 		    {
 		      if (!cname_count--)
 			return 0; /* looped CNAMES */
-		      newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD | secflag);
+		      newc = cache_insert(name, NULL, C_IN, now, attl, F_CNAME | F_FORWARD | secflag);
 		      if (newc)
 			{
 			  newc->addr.cname.target.cache = NULL;
@@ -833,7 +833,7 @@ int extract_addresses(struct dns_header
 			}
 #endif
 		      
-		      newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD | secflag);
+		      newc = cache_insert(name, &addr, C_IN, now, attl, flags | F_FORWARD | secflag);
 		      if (newc && cpp)
 			{
 			  next_uid(newc);
@@ -860,7 +860,7 @@ int extract_addresses(struct dns_header
 		 pointing at this, inherit its TTL */
 	      if (ttl || cpp)
 		{
-		  newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));	
+		  newc = cache_insert(name, NULL, C_IN, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));	
 		  if (newc && cpp)
 		    {
 		      next_uid(newc);
@@ -1054,7 +1054,7 @@ int check_for_bogus_wildcard(struct dns_
 		/* Found a bogus address. Insert that info here, since there no SOA record
 		   to get the ttl from in the normal processing */
 		cache_start_insert();
-		cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN);
+		cache_insert(name, NULL, C_IN, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN);
 		cache_end_insert();
 		
 		return 1;
