SPDX: Mass-update to GPL-2.0-or-later
[exim.git] / src / src / dns.c
index b309207cfd43dd6cf90781a71eb2ccaf6ba4b425..4e01d8661271948ad1b75b2378d7eb9554a28598 100644 (file)
@@ -2,15 +2,16 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
+/* Copyright (c) The Exim Maintainers 2020 - 2022 */
 /* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
 /* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 /* Functions for interfacing with the DNS. */
 
 #include "exim.h"
 
 
 
 /* Functions for interfacing with the DNS. */
 
 #include "exim.h"
 
 
-
 /*************************************************
 *               Fake DNS resolver                *
 *************************************************/
 /*************************************************
 *               Fake DNS resolver                *
 *************************************************/
@@ -61,7 +62,8 @@ if (stat(CS utilname, &statbuf) >= 0)
   int infd, outfd, rc;
   uschar *argv[5];
 
   int infd, outfd, rc;
   uschar *argv[5];
 
-  DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) using fakens\n", name, dns_text_type(type));
+  DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) using fakens\n",
+               name, dns_text_type(type));
 
   argv[0] = utilname;
   argv[1] = config_main_directory;
 
   argv[0] = utilname;
   argv[1] = config_main_directory;
@@ -69,7 +71,7 @@ if (stat(CS utilname, &statbuf) >= 0)
   argv[3] = dns_text_type(type);
   argv[4] = NULL;
 
   argv[3] = dns_text_type(type);
   argv[4] = NULL;
 
-  pid = child_open(argv, NULL, 0000, &infd, &outfd, FALSE);
+  pid = child_open(argv, NULL, 0000, &infd, &outfd, FALSE, US"fakens-search");
   if (pid < 0)
     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to run fakens: %s",
       strerror(errno));
   if (pid < 0)
     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to run fakens: %s",
       strerror(errno));
@@ -222,16 +224,15 @@ a name that can be used to look up PTR records.
 
 Arguments:
   string     the IP address as a string
 
 Arguments:
   string     the IP address as a string
-  buffer     a suitable buffer, long enough to hold the result
 
 
-Returns:     nothing
+Returns:     an allocated string
 */
 
 */
 
-void
-dns_build_reverse(const uschar *string, uschar *buffer)
+uschar *
+dns_build_reverse(const uschar * string)
 {
 {
-const uschar *p = string + Ustrlen(string);
-uschar *pp = buffer;
+const uschar * p = string + Ustrlen(string);
+gstring * g = NULL;
 
 /* Handle IPv4 address */
 
 
 /* Handle IPv4 address */
 
@@ -241,14 +242,13 @@ if (Ustrchr(string, ':') == NULL)
   {
   for (int i = 0; i < 4; i++)
     {
   {
   for (int i = 0; i < 4; i++)
     {
-    const uschar *ppp = p;
+    const uschar * ppp = p;
     while (ppp > string && ppp[-1] != '.') ppp--;
     while (ppp > string && ppp[-1] != '.') ppp--;
-    Ustrncpy(pp, ppp, p - ppp);
-    pp += p - ppp;
-    *pp++ = '.';
+    g = string_catn(g, ppp, p - ppp);
+    g = string_catn(g, US".", 1);
     p = ppp - 1;
     }
     p = ppp - 1;
     }
-  Ustrcpy(pp, US"in-addr.arpa");
+  g = string_catn(g, US"in-addr.arpa", 12);
   }
 
 /* Handle IPv6 address; convert to binary so as to fill out any
   }
 
 /* Handle IPv6 address; convert to binary so as to fill out any
@@ -258,6 +258,8 @@ abbreviation in the textual form. */
 else
   {
   int v6[4];
 else
   {
   int v6[4];
+
+  g = string_get_tainted(32, string);
   (void)host_aton(string, v6);
 
   /* The original specification for IPv6 reverse lookup was to invert each
   (void)host_aton(string, v6);
 
   /* The original specification for IPv6 reverse lookup was to invert each
@@ -266,8 +268,8 @@ else
 
   for (int i = 3; i >= 0; i--)
     for (int j = 0; j < 32; j += 4)
 
   for (int i = 3; i >= 0; i--)
     for (int j = 0; j < 32; j += 4)
-      pp += sprintf(CS pp, "%x.", (v6[i] >> j) & 15);
-  Ustrcpy(pp, US"ip6.arpa.");
+      g = string_fmt_append(g, "%x.", (v6[i] >> j) & 15);
+  g = string_catn(g, US"ip6.arpa.", 9);
 
   /* Another way of doing IPv6 reverse lookups was proposed in conjunction
   with A6 records. However, it fell out of favour when they did. The
 
   /* Another way of doing IPv6 reverse lookups was proposed in conjunction
   with A6 records. However, it fell out of favour when they did. The
@@ -291,6 +293,7 @@ else
 
   }
 #endif
 
   }
 #endif
+return string_from_gstring(g);
 }
 
 
 }
 
 
@@ -332,7 +335,6 @@ char * trace = NULL;
 #ifdef rr_trace
 # define TRACE DEBUG(D_dns)
 #else
 #ifdef rr_trace
 # define TRACE DEBUG(D_dns)
 #else
-trace = trace;
 # define TRACE if (FALSE)
 #endif
 
 # define TRACE if (FALSE)
 #endif
 
@@ -499,20 +501,22 @@ const HEADER * h = (const HEADER *) dnsa->answer;
 const uschar * auth_name;
 const uschar * trusted;
 
 const uschar * auth_name;
 const uschar * trusted;
 
+if (dnsa->answerlen < 0) return FALSE;
+/* Beware that newer versions of glibc on Linux will filter out the ad bit
+unless their shiny new RES_TRUSTAD bit is set for the resolver.  */
 if (h->ad) return TRUE;
 
 if (h->ad) return TRUE;
 
-/* If the resolver we ask is authoritative for the domain in question, it
-* may not set the AD but the AA bit. If we explicitly trust
-* the resolver for that domain (via a domainlist in dns_trust_aa),
-* we return TRUE to indicate a secure answer.
-*/
+/* If the resolver we ask is authoritative for the domain in question, it may
+not set the AD but the AA bit. If we explicitly trust the resolver for that
+domain (via a domainlist in dns_trust_aa), we return TRUE to indicate a secure
+answer.  */
 
 if (  !h->aa
    || !dns_trust_aa
    || !(trusted = expand_string(dns_trust_aa))
    || !*trusted
    || !(auth_name = dns_extract_auth_name(dnsa))
 
 if (  !h->aa
    || !dns_trust_aa
    || !(trusted = expand_string(dns_trust_aa))
    || !*trusted
    || !(auth_name = dns_extract_auth_name(dnsa))
-   || OK != match_isinlist(auth_name, &trusted, 0, NULL, NULL,
+   || OK != match_isinlist(auth_name, &trusted, 0, &domainlist_anchor, NULL,
                            MCL_DOMAIN, TRUE, NULL)
    )
   return FALSE;
                            MCL_DOMAIN, TRUE, NULL)
    )
   return FALSE;
@@ -541,12 +545,12 @@ h->aa = h->ad = 0;
  ************************************************/
 
 BOOL
  ************************************************/
 
 BOOL
-dns_is_aa(const dns_answer *dnsa)
+dns_is_aa(const dns_answer * dnsa)
 {
 #ifdef DISABLE_DNSSEC
 return FALSE;
 #else
 {
 #ifdef DISABLE_DNSSEC
 return FALSE;
 #else
-return ((const HEADER*)dnsa->answer)->aa;
+return dnsa->answerlen >= 0 && ((const HEADER *)dnsa->answer)->aa;
 #endif
 }
 
 #endif
 }
 
@@ -617,8 +621,10 @@ Arguments:
 Returns:     the return code
 */
 
 Returns:     the return code
 */
 
-/*XXX the derivation of this value needs explaining */
+/* we need:  255 +1 + (max(typetext) == 5) +1 + max(chars_for_long-max) +1 */
 #define DNS_FAILTAG_MAX 290
 #define DNS_FAILTAG_MAX 290
+#define DNS_FAILNODE_SIZE \
+  (sizeof(expiring_data) + sizeof(tree_node) + DNS_FAILTAG_MAX)
 
 static int
 dns_fail_return(const uschar * name, int type, time_t expiry, int rc)
 
 static int
 dns_fail_return(const uschar * name, int type, time_t expiry, int rc)
@@ -632,11 +638,9 @@ if ((previous = tree_search(tree_dns_fails, node_name)))
   e = previous->data.ptr;
 else
   {
   e = previous->data.ptr;
 else
   {
-  new = store_get_perm(
-    sizeof(tree_node) + DNS_FAILTAG_MAX + sizeof(expiring_data), is_tainted(name));
-
+  e = store_get_perm(DNS_FAILNODE_SIZE, name);
+  new = (void *)(e+1);
   dns_fail_tag(new->name, name, type);
   dns_fail_tag(new->name, name, type);
-  e = (expiring_data *)((char *)new + sizeof(tree_node) + DNS_FAILTAG_MAX);
   new->data.ptr = e;
   (void)tree_insertnode(&tree_dns_fails, new);
   }
   new->data.ptr = e;
   (void)tree_insertnode(&tree_dns_fails, new);
   }
@@ -668,13 +672,10 @@ e = previous->data.ptr;
 val = e->data.val;
 rc = e->expiry && e->expiry <= time(NULL) ? -1 : val;
 
 val = e->data.val;
 rc = e->expiry && e->expiry <= time(NULL) ? -1 : val;
 
-DEBUG(D_dns) debug_printf("DNS lookup of %.255s-%s: %scached value %s%s\n",
+DEBUG(D_dns) debug_printf("DNS lookup of %.255s (%s): %scached value %s%s\n",
   name, dns_text_type(type),
   rc == -1 ? "" : "using ",
   name, dns_text_type(type),
   rc == -1 ? "" : "using ",
-    val == DNS_NOMATCH ? "DNS_NOMATCH" :
-    val == DNS_NODATA ? "DNS_NODATA" :
-    val == DNS_AGAIN ? "DNS_AGAIN" :
-    val == DNS_FAIL ? "DNS_FAIL" : "??",
+  dns_rc_names[val],
   rc == -1 ? " past valid time" : "");
 
 return rc;
   rc == -1 ? " past valid time" : "");
 
 return rc;
@@ -682,17 +683,6 @@ return rc;
 
 
 
 
 
 
-/* Return the TTL suitable for an NXDOMAIN result, which is given
-in the SOA.  We hope that one was returned in the lookup, and do not
-bother doing a separate lookup; if not found return a forever TTL.
-*/
-
-static time_t
-dns_expire_from_soa(dns_answer * dnsa)
-{
-const HEADER * h = (const HEADER *)dnsa->answer;
-dns_scan dnss;
-
 /* This is really gross. The successful return value from res_search() is
 the packet length, which is stored in dnsa->answerlen. If we get a
 negative DNS reply then res_search() returns -1, which causes the bounds
 /* This is really gross. The successful return value from res_search() is
 the packet length, which is stored in dnsa->answerlen. If we get a
 negative DNS reply then res_search() returns -1, which causes the bounds
@@ -702,44 +692,76 @@ packet length has been lost inside libresolv, so we have to guess a
 replacement value. (The only way to fix this properly would be to
 re-implement res_search() and res_query() so that they don't muddle their
 success and packet length return values.) For added safety we only reset
 replacement value. (The only way to fix this properly would be to
 re-implement res_search() and res_query() so that they don't muddle their
 success and packet length return values.) For added safety we only reset
-the packet length if the packet header looks plausible. */
+the packet length if the packet header looks plausible.
+
+Return TRUE iff it seemed ok */
+
+static BOOL
+fake_dnsa_len_for_fail(dns_answer * dnsa, int type)
+{
+const HEADER * h = (const HEADER *)dnsa->answer;
 
 
-if (  h->qr == 1 && h->opcode == QUERY && h->tc == 0
+if (  h->qr == 1                               /* a response */
+   && h->opcode == QUERY
+   && h->tc == 0                               /* nmessage not truncated */
    && (h->rcode == NOERROR || h->rcode == NXDOMAIN)
    && (h->rcode == NOERROR || h->rcode == NXDOMAIN)
-   && (ntohs(h->qdcount) == 1 || f.running_in_test_harness)
-   && ntohs(h->ancount) == 0
-   && ntohs(h->nscount) >= 1)
-      dnsa->answerlen = sizeof(dnsa->answer);
-
-for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_AUTHORITY);
-     rr; rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)
-    ) if (rr->type == T_SOA)
+   && (  ntohs(h->qdcount) == 1                        /* one question record */
+      || f.running_in_test_harness)
+   && ntohs(h->ancount) == 0                   /* no answer records */
+   && ntohs(h->nscount) >= 1)                  /* authority records */
   {
   {
-  const uschar * p = rr->data;
-  uschar discard_buf[256];
-  int len;
-  unsigned long ttl;
-
-  /* Skip the mname & rname strings */
-
-  if ((len = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
-      p, (DN_EXPAND_ARG4_TYPE)discard_buf, 256)) < 0)
-    break;
-  p += len;
-  if ((len = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
-      p, (DN_EXPAND_ARG4_TYPE)discard_buf, 256)) < 0)
-    break;
-  p += len;
-
-  /* Skip the SOA serial, refresh, retry & expire.  Grab the TTL */
-
-  if (p > dnsa->answer + dnsa->answerlen - 5 * NS_INT32SZ)
-    break;
-  p += 4 * NS_INT32SZ;
-  GETLONG(ttl, p);
-
-  return time(NULL) + ttl;
+  DEBUG(D_dns) debug_printf("faking res_search(%s) response length as %d\n",
+    dns_text_type(type), (int)sizeof(dnsa->answer));
+  dnsa->answerlen = sizeof(dnsa->answer);
+  return TRUE;
   }
   }
+DEBUG(D_dns) debug_printf("DNS: couldn't fake dnsa len\n");
+/* Maybe we should just do a second lookup for an SOA? */
+return FALSE;
+}
+
+
+/* Return the TTL suitable for an NXDOMAIN result, which is given
+in the SOA.  We hope that one was returned in the lookup, and do not
+bother doing a separate lookup; if not found return a forever TTL.
+*/
+
+time_t
+dns_expire_from_soa(dns_answer * dnsa, int type)
+{
+dns_scan dnss;
+
+if (fake_dnsa_len_for_fail(dnsa, type))
+  for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_AUTHORITY);
+       rr; rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)
+      ) if (rr->type == T_SOA)
+    {
+    const uschar * p = rr->data;
+    uschar discard_buf[256];
+    int len;
+    unsigned long ttl;
+
+    /* Skip the mname & rname strings */
+
+    if ((len = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
+       p, (DN_EXPAND_ARG4_TYPE)discard_buf, 256)) < 0)
+      break;
+    p += len;
+    if ((len = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
+       p, (DN_EXPAND_ARG4_TYPE)discard_buf, 256)) < 0)
+      break;
+    p += len;
+
+    /* Skip the SOA serial, refresh, retry & expire.  Grab the TTL */
+
+    if (p > dnsa->answer + dnsa->answerlen - 5 * INT32SZ)
+      break;
+    p += 4 * INT32SZ;
+    GETLONG(ttl, p);
+
+    return time(NULL) + ttl;
+    }
+
 DEBUG(D_dns) debug_printf("DNS: no SOA record found for neg-TTL\n");
 return 0;
 }
 DEBUG(D_dns) debug_printf("DNS: no SOA record found for neg-TTL\n");
 return 0;
 }
@@ -789,7 +811,10 @@ caching for successful lookups.
 */
 
 if ((rc = dns_fail_cache_hit(name, type)) > 0)
 */
 
 if ((rc = dns_fail_cache_hit(name, type)) > 0)
+  {
+  dnsa->answerlen = -1;
   return rc;
   return rc;
+  }
 
 #ifdef SUPPORT_I18N
 /* Convert all names to a-label form before doing lookup */
 
 #ifdef SUPPORT_I18N
 /* Convert all names to a-label form before doing lookup */
@@ -819,35 +844,15 @@ regex has substrings that are used - the default uses a conditional.
 
 This test is omitted for PTR records. These occur only in calls from the dnsdb
 lookup, which constructs the names itself, so they should be OK. Besides,
 
 This test is omitted for PTR records. These occur only in calls from the dnsdb
 lookup, which constructs the names itself, so they should be OK. Besides,
-bitstring labels don't conform to normal name syntax. (But the aren't used any
-more.)
-
-For SRV records, we omit the initial _smtp._tcp. components at the start.
-The check has been seen to bite on the destination of a SRV lookup that
-initiall hit a CNAME, for which the next name had only two components.
-RFC2782 makes no mention of the possibiility of CNAMES, but the Wikipedia
-article on SRV says they are not a valid configuration. */
+bitstring labels don't conform to normal name syntax. (But they aren't used any
+more.) */
 
 #ifndef STAND_ALONE   /* Omit this for stand-alone tests */
 
 if (check_dns_names_pattern[0] != 0 && type != T_PTR && type != T_TXT)
   {
 
 #ifndef STAND_ALONE   /* Omit this for stand-alone tests */
 
 if (check_dns_names_pattern[0] != 0 && type != T_PTR && type != T_TXT)
   {
-  const uschar *checkname = name;
-  int ovector[3*(EXPAND_MAXN+1)];
-
   dns_pattern_init();
   dns_pattern_init();
-
-  /* For an SRV lookup, skip over the first two components (the service and
-  protocol names, which both start with an underscore). */
-
-  if (type == T_SRV || type == T_TLSA)
-    {
-    while (*checkname && *checkname++ != '.') ;
-    while (*checkname && *checkname++ != '.') ;
-    }
-
-  if (pcre_exec(regex_check_dns_names, NULL, CCS checkname, Ustrlen(checkname),
-      0, PCRE_EOPT, ovector, nelem(ovector)) < 0)
+  if (!regex_match(regex_check_dns_names, name, -1, NULL))
     {
     DEBUG(D_dns)
       debug_printf("DNS name syntax check failed: %s (%s)\n", name,
     {
     DEBUG(D_dns)
       debug_printf("DNS name syntax check failed: %s (%s)\n", name,
@@ -875,6 +880,7 @@ if ((type == T_A || type == T_AAAA) && string_is_ip_address(name, NULL) != 0)
 (res_search), we call fakens_search(), which recognizes certain special
 domains, and interfaces to a fake nameserver for certain special zones. */
 
 (res_search), we call fakens_search(), which recognizes certain special
 domains, and interfaces to a fake nameserver for certain special zones. */
 
+h_errno = 0;
 dnsa->answerlen = f.running_in_test_harness
   ? fakens_search(name, type, dnsa->answer, sizeof(dnsa->answer))
   : res_search(CCS name, C_IN, type, dnsa->answer, sizeof(dnsa->answer));
 dnsa->answerlen = f.running_in_test_harness
   ? fakens_search(name, type, dnsa->answer, sizeof(dnsa->answer))
   : res_search(CCS name, C_IN, type, dnsa->answer, sizeof(dnsa->answer));
@@ -892,7 +898,7 @@ if (dnsa->answerlen < 0) switch (h_errno)
   case HOST_NOT_FOUND:
     DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave HOST_NOT_FOUND\n"
       "returning DNS_NOMATCH\n", name, dns_text_type(type));
   case HOST_NOT_FOUND:
     DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave HOST_NOT_FOUND\n"
       "returning DNS_NOMATCH\n", name, dns_text_type(type));
-    return dns_fail_return(name, type, dns_expire_from_soa(dnsa), DNS_NOMATCH);
+    return dns_fail_return(name, type, dns_expire_from_soa(dnsa, type), DNS_NOMATCH);
 
   case TRY_AGAIN:
     DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave TRY_AGAIN\n",
 
   case TRY_AGAIN:
     DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave TRY_AGAIN\n",
@@ -902,8 +908,8 @@ if (dnsa->answerlen < 0) switch (h_errno)
 #ifndef STAND_ALONE
     save_domain = deliver_domain;
     deliver_domain = string_copy(name);  /* set $domain */
 #ifndef STAND_ALONE
     save_domain = deliver_domain;
     deliver_domain = string_copy(name);  /* set $domain */
-    rc = match_isinlist(name, (const uschar **)&dns_again_means_nonexist, 0, NULL, NULL,
-      MCL_DOMAIN, TRUE, NULL);
+    rc = match_isinlist(name, CUSS &dns_again_means_nonexist, 0,
+      &domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL);
     deliver_domain = save_domain;
     if (rc != OK)
       {
     deliver_domain = save_domain;
     if (rc != OK)
       {
@@ -912,7 +918,7 @@ if (dnsa->answerlen < 0) switch (h_errno)
       }
     DEBUG(D_dns) debug_printf("%s is in dns_again_means_nonexist: returning "
       "DNS_NOMATCH\n", name);
       }
     DEBUG(D_dns) debug_printf("%s is in dns_again_means_nonexist: returning "
       "DNS_NOMATCH\n", name);
-    return dns_fail_return(name, type, dns_expire_from_soa(dnsa), DNS_NOMATCH);
+    return dns_fail_return(name, type, dns_expire_from_soa(dnsa, type), DNS_NOMATCH);
 
 #else   /* For stand-alone tests */
     return dns_fail_return(name, type, 0, DNS_AGAIN);
 
 #else   /* For stand-alone tests */
     return dns_fail_return(name, type, 0, DNS_AGAIN);
@@ -926,7 +932,7 @@ if (dnsa->answerlen < 0) switch (h_errno)
   case NO_DATA:
     DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave NO_DATA\n"
       "returning DNS_NODATA\n", name, dns_text_type(type));
   case NO_DATA:
     DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave NO_DATA\n"
       "returning DNS_NODATA\n", name, dns_text_type(type));
-    return dns_fail_return(name, type, dns_expire_from_soa(dnsa), DNS_NODATA);
+    return dns_fail_return(name, type, dns_expire_from_soa(dnsa, type), DNS_NODATA);
 
   default:
     DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave unknown DNS error %d\n"
 
   default:
     DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave unknown DNS error %d\n"
@@ -1060,7 +1066,7 @@ for (int i = 0; i <= dns_cname_loops; i++)
     return DNS_FAIL;
 
   /* DNS data comes from the outside, hence tainted */
     return DNS_FAIL;
 
   /* DNS data comes from the outside, hence tainted */
-  data = store_get(256, TRUE);
+  data = store_get(256, GET_TAINTED);
   if (dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
       cname_rr.data, (DN_EXPAND_ARG4_TYPE)data, 256) < 0)
     return DNS_FAIL;
   if (dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
       cname_rr.data, (DN_EXPAND_ARG4_TYPE)data, 256) < 0)
     return DNS_FAIL;
@@ -1143,7 +1149,7 @@ switch (type)
   case T_CSA:
     {
     uschar *srvname, *namesuff, *tld;
   case T_CSA:
     {
     uschar *srvname, *namesuff, *tld;
-    int priority, weight, port;
+    int priority, dummy_weight, port;
     int limit, rc, i;
     BOOL ipv6;
     dns_record *rr;
     int limit, rc, i;
     BOOL ipv6;
     dns_record *rr;
@@ -1197,34 +1203,7 @@ switch (type)
     If the TLD and the 2LD exist but the explicit CSA record lookup failed, then
     the AUTHORITY SOA will be the 2LD's or a subdomain thereof. */
 
     If the TLD and the 2LD exist but the explicit CSA record lookup failed, then
     the AUTHORITY SOA will be the 2LD's or a subdomain thereof. */
 
-    if (rc == DNS_NOMATCH)
-      {
-      /* This is really gross. The successful return value from res_search() is
-      the packet length, which is stored in dnsa->answerlen. If we get a
-      negative DNS reply then res_search() returns -1, which causes the bounds
-      checks for name decompression to fail when it is treated as a packet
-      length, which in turn causes the authority search to fail. The correct
-      packet length has been lost inside libresolv, so we have to guess a
-      replacement value. (The only way to fix this properly would be to
-      re-implement res_search() and res_query() so that they don't muddle their
-      success and packet length return values.) For added safety we only reset
-      the packet length if the packet header looks plausible. */
-
-      const HEADER * h = (const HEADER *)dnsa->answer;
-      if (h->qr == 1 && h->opcode == QUERY && h->tc == 0
-         && (h->rcode == NOERROR || h->rcode == NXDOMAIN)
-         && ntohs(h->qdcount) == 1 && ntohs(h->ancount) == 0
-         && ntohs(h->nscount) >= 1)
-           dnsa->answerlen = sizeof(dnsa->answer);
-
-      for (rr = dns_next_rr(dnsa, &dnss, RESET_AUTHORITY);
-          rr; rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)
-         )
-       if (rr->type != T_SOA) continue;
-       else if (strcmpic(rr->name, US"") == 0 ||
-                strcmpic(rr->name, tld) == 0) return DNS_NOMATCH;
-       else break;
-      }
+    if (rc == DNS_NOMATCH) return DNS_NOMATCH;
 
     for (i = 0; i < limit; i++)
       {
 
     for (i = 0; i < limit; i++)
       {
@@ -1259,7 +1238,7 @@ switch (type)
 
        /* Extract the numerical SRV fields (p is incremented) */
        GETSHORT(priority, p);
 
        /* Extract the numerical SRV fields (p is incremented) */
        GETSHORT(priority, p);
-       GETSHORT(weight, p);    weight = weight; /* compiler quietening */
+       GETSHORT(dummy_weight, p);
        GETSHORT(port, p);
 
        /* Check the CSA version number */
        GETSHORT(port, p);
 
        /* Check the CSA version number */
@@ -1315,7 +1294,7 @@ if (rr->type == T_A)
   if (p + 4 <= dnsa_lim)
     {
     /* the IP is not regarded as tainted */
   if (p + 4 <= dnsa_lim)
     {
     /* the IP is not regarded as tainted */
-    yield = store_get(sizeof(dns_address) + 20, FALSE);
+    yield = store_get(sizeof(dns_address) + 20, GET_UNTAINTED);
     (void)sprintf(CS yield->address, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
     yield->next = NULL;
     }
     (void)sprintf(CS yield->address, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
     yield->next = NULL;
     }
@@ -1329,7 +1308,7 @@ else
     {
     struct in6_addr in6;
     for (int i = 0; i < 16; i++) in6.s6_addr[i] = rr->data[i];
     {
     struct in6_addr in6;
     for (int i = 0; i < 16; i++) in6.s6_addr[i] = rr->data[i];
-    yield = store_get(sizeof(dns_address) + 50, FALSE);
+    yield = store_get(sizeof(dns_address) + 50, GET_UNTAINTED);
     inet_ntop(AF_INET6, &in6, CS yield->address, 50);
     yield->next = NULL;
     }
     inet_ntop(AF_INET6, &in6, CS yield->address, 50);
     yield->next = NULL;
     }
@@ -1346,7 +1325,7 @@ dns_pattern_init(void)
 {
 if (check_dns_names_pattern[0] != 0 && !regex_check_dns_names)
   regex_check_dns_names =
 {
 if (check_dns_names_pattern[0] != 0 && !regex_check_dns_names)
   regex_check_dns_names =
-    regex_must_compile(check_dns_names_pattern, FALSE, TRUE);
+    regex_must_compile(check_dns_names_pattern, MCS_NOFLAGS, TRUE);
 }
 
 /* vi: aw ai sw=2
 }
 
 /* vi: aw ai sw=2