Imported Upstream version 2.88
[platform/upstream/dnsmasq.git] / src / rrfilter.c
index 58c6d8f..42d9c21 100644 (file)
@@ -1,4 +1,4 @@
-/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -156,10 +156,10 @@ static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, i
 }
        
 
-/* mode is 0 to remove EDNS0, 1 to filter DNSSEC RRs */
+/* mode may be remove EDNS0 or DNSSEC RRs or remove A or AAAA from answer section. */
 size_t rrfilter(struct dns_header *header, size_t plen, int mode)
 {
-  static unsigned char **rrs;
+  static unsigned char **rrs = NULL;
   static int rr_sz = 0;
 
   unsigned char *p = (unsigned char *)(header+1);
@@ -192,20 +192,37 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode)
       if (!ADD_RDLEN(header, p, plen, rdlen))
        return plen;
 
-      /* Don't remove the answer. */
-      if (i < ntohs(header->ancount) && type == qtype && class == qclass)
-       continue;
-      
-      if (mode == 0) /* EDNS */
+      if (mode == RRFILTER_EDNS0) /* EDNS */
        {
          /* EDNS mode, remove T_OPT from additional section only */
          if (i < (ntohs(header->nscount) + ntohs(header->ancount)) || type != T_OPT)
            continue;
        }
-      else if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
-       /* DNSSEC mode, remove SIGs and NSECs from all three sections. */
-       continue;
-      
+      else if (mode == RRFILTER_DNSSEC)
+       {
+         if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
+           /* DNSSEC mode, remove SIGs and NSECs from all three sections. */
+           continue;
+
+         /* Don't remove the answer. */
+         if (i < ntohs(header->ancount) && type == qtype && class == qclass)
+           continue;
+       }
+      else
+       {
+         /* Only looking at answer section now. */
+         if (i >= ntohs(header->ancount))
+           break;
+
+         if (class != C_IN)
+           continue;
+         
+         if (mode == RRFILTER_A && type != T_A)
+           continue;
+
+         if (mode == RRFILTER_AAAA && type != T_AAAA)
+           continue;
+       }
       
       if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
        return plen; 
@@ -322,15 +339,11 @@ int expand_workspace(unsigned char ***wkspc, int *szp, int new)
     return 0;
 
   new += 5;
-  
-  if (!(p = whine_malloc(new * sizeof(unsigned char *))))
-    return 0;  
-  
-  if (old != 0 && *wkspc)
-    {
-      memcpy(p, *wkspc, old * sizeof(unsigned char *));
-      free(*wkspc);
-    }
+
+  if (!(p = whine_realloc(*wkspc, new * sizeof(unsigned char *))))
+    return 0;
+
+  memset(p+old, 0, new-old);
   
   *wkspc = p;
   *szp = new;