Update copyright year to 2018
[exim.git] / src / src / dns.c
index fc0ffb2baa59e2b1e09582b2c24943da5cd0d82a..83de7c26684ea3a6ad640089899c59e986dcb453 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2016 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions for interfacing with the DNS. */
@@ -271,10 +271,7 @@ else
     {
     int j;
     for (j = 0; j < 32; j += 4)
-      {
-      sprintf(CS pp, "%x.", (v6[i] >> j) & 15);
-      pp += 2;
-      }
+      pp += sprintf(CS pp, "%x.", (v6[i] >> j) & 15);
     }
   Ustrcpy(pp, "ip6.arpa.");
 
@@ -326,7 +323,7 @@ The result is in static storage which must be copied if it is to be preserved.
 Arguments:
   dnsa      pointer to dns answer block
   dnss      pointer to dns scan block
-  reset     option specifing what portion to scan, as described above
+  reset     option specifying what portion to scan, as described above
 
 Returns:    next dns record, or NULL when no more
 */
@@ -349,8 +346,8 @@ trace = trace;
 
 if (reset != RESET_NEXT)
   {
-  TRACE debug_printf("%s: reset\n", __FUNCTION__);
   dnss->rrcount = ntohs(h->qdcount);
+  TRACE debug_printf("%s: reset (Q rrcount %d)\n", __FUNCTION__, dnss->rrcount);
   dnss->aptr = dnsa->answer + sizeof(HEADER);
 
   /* Skip over questions; failure to expand the name just gives up */
@@ -369,6 +366,7 @@ if (reset != RESET_NEXT)
   /* Get the number of answer records. */
 
   dnss->rrcount = ntohs(h->ancount);
+  TRACE debug_printf("%s: reset (A rrcount %d)\n", __FUNCTION__, dnss->rrcount);
 
   /* Skip over answers if we want to look at the authority section. Also skip
   the NS records (i.e. authority section) if wanting to look at the additional
@@ -378,6 +376,7 @@ if (reset != RESET_NEXT)
     {
     TRACE debug_printf("%s: additional\n", __FUNCTION__);
     dnss->rrcount += ntohs(h->nscount);
+    TRACE debug_printf("%s: reset (NS rrcount %d)\n", __FUNCTION__, dnss->rrcount);
     }
 
   if (reset == RESET_AUTHORITY || reset == RESET_ADDITIONAL)
@@ -400,6 +399,8 @@ if (reset != RESET_NEXT)
       }
     dnss->rrcount = reset == RESET_AUTHORITY
       ? ntohs(h->nscount) : ntohs(h->arcount);
+    TRACE debug_printf("%s: reset (%s rrcount %d)\n", __FUNCTION__,
+      reset == RESET_AUTHORITY ? "NS" : "AR", dnss->rrcount);
     }
   TRACE debug_printf("%s: %d RRs to read\n", __FUNCTION__, dnss->rrcount);
   }
@@ -443,17 +444,17 @@ for convenience so that the scans can use nice-looking for loops. */
 return &dnss->srr;
 
 null_return:
-  TRACE debug_printf("%s: terminate (%d RRs left). Last op: %s\n",
-    __FUNCTION__, dnss->rrcount, trace);
+  TRACE debug_printf("%s: terminate (%d RRs left). Last op: %s; errno %d %s\n",
+    __FUNCTION__, dnss->rrcount, trace, errno, strerror(errno));
   dnss->rrcount = 0;
   return NULL;
 }
 
 
 /* Extract the AUTHORITY information from the answer. If the answer isn't
-authoritive (AA not set), we do not extract anything.
+authoritative (AA not set), we do not extract anything.
 
-The AUTHORITIVE section contains NS records if the name in question was found,
+The AUTHORITY section contains NS records if the name in question was found,
 it contains a SOA record otherwise. (This is just from experience and some
 tests, is there some spec?)
 
@@ -486,7 +487,7 @@ return NULL;
 
 /* We do not perform DNSSEC work ourselves; if the administrator has installed
 a verifying resolver which sets AD as appropriate, though, we'll use that.
-(AD = Authentic Data, AA = Authoritive Answer)
+(AD = Authentic Data, AA = Authoritative Answer)
 
 Argument:   pointer to dns answer block
 Returns:    bool indicating presence of AD bit
@@ -506,7 +507,7 @@ const uschar * trusted;
 
 if (h->ad) return TRUE;
 
-/* If the resolver we ask is authoritive for the domain in question, it
+/* 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.
@@ -542,7 +543,7 @@ h->aa = h->ad = 0;
 /************************************************
  *     Check whether the AA bit is set         *
  *     We need this to warn if we requested AD *
- *     from an authoritive server              *
+ *     from an authoritative server            *
  ************************************************/
 
 BOOL
@@ -595,6 +596,15 @@ switch(t)
 *        Cache a failed DNS lookup result        *
 *************************************************/
 
+static void
+dns_fail_tag(uschar * buf, const uschar * name, int dns_type)
+{
+res_state resp = os_get_dns_resolver_res();
+sprintf(CS buf, "%.255s-%s-%lx", name, dns_text_type(dns_type),
+  (unsigned long) resp->options);
+}
+
+
 /* We cache failed lookup results so as not to experience timeouts many
 times for the same domain. We need to retain the resolver options because they
 may change. For successful lookups, we rely on resolver and/or name server
@@ -611,10 +621,8 @@ Returns:     the return code
 static int
 dns_return(const uschar * name, int type, int rc)
 {
-res_state resp = os_get_dns_resolver_res();
 tree_node *node = store_get_perm(sizeof(tree_node) + 290);
-sprintf(CS node->name, "%.255s-%s-%lx", name, dns_text_type(type),
-  (unsigned long) resp->options);
+dns_fail_tag(node->name, name, type);
 node->data.val = rc;
 (void)tree_insertnode(&tree_dns_fails, node);
 return rc;
@@ -626,7 +634,7 @@ return rc;
 
 /* Call the resolver to look up the given domain name, using the given type,
 and check the result. The error code TRY_AGAIN is documented as meaning "non-
-Authoritive Host not found, or SERVERFAIL". Sometimes there are badly set
+Authoritative Host not found, or SERVERFAIL". Sometimes there are badly set
 up nameservers that produce this error continually, so there is the option of
 providing a list of domains for which this is treated as a non-existent
 host.
@@ -652,7 +660,6 @@ dns_basic_lookup(dns_answer *dnsa, const uschar *name, int type)
 int rc = -1;
 const uschar *save_domain;
 #endif
-res_state resp = os_get_dns_resolver_res();
 
 tree_node *previous;
 uschar node_name[290];
@@ -662,8 +669,7 @@ a timeout on one domain doesn't happen time and time again for messages that
 have many addresses in the same domain. We rely on the resolver and name server
 caching for successful lookups. */
 
-sprintf(CS node_name, "%.255s-%s-%lx", name, dns_text_type(type),
-  (unsigned long) resp->options);
+dns_fail_tag(node_name, name, type);
 if ((previous = tree_search(tree_dns_fails, node_name)))
   {
   DEBUG(D_dns) debug_printf("DNS lookup of %.255s-%s: using cached value %s\n",
@@ -694,7 +700,7 @@ if ((previous = tree_search(tree_dns_fails, node_name)))
   }
 #endif
 
-/* If configured, check the hygene of the name passed to lookup. Otherwise,
+/* If configured, check the hygiene of the name passed to lookup. Otherwise,
 although DNS lookups may give REFUSED at the lower level, some resolvers
 turn this into TRY_AGAIN, which is silly. Give a NOMATCH return, since such
 domains cannot be in the DNS. The check is now done by a regular expression;
@@ -727,7 +733,7 @@ if (check_dns_names_pattern[0] != 0 && type != T_PTR && type != T_TXT)
     }
 
   if (pcre_exec(regex_check_dns_names, NULL, CCS checkname, Ustrlen(checkname),
-      0, PCRE_EOPT, ovector, sizeof(ovector)/sizeof(int)) < 0)
+      0, PCRE_EOPT, ovector, nelem(ovector)) < 0)
     {
     DEBUG(D_dns)
       debug_printf("DNS name syntax check failed: %s (%s)\n", name,
@@ -756,14 +762,15 @@ if ((type == T_A || type == T_AAAA) && string_is_ip_address(name, NULL) != 0)
 domains, and interfaces to a fake nameserver for certain special zones. */
 
 dnsa->answerlen = running_in_test_harness
-  ? fakens_search(name, type, dnsa->answer, MAXPACKET)
-  : res_search(CCS name, C_IN, type, dnsa->answer, MAXPACKET);
+  ? fakens_search(name, type, dnsa->answer, sizeof(dnsa->answer))
+  : res_search(CCS name, C_IN, type, dnsa->answer, sizeof(dnsa->answer));
 
-if (dnsa->answerlen > MAXPACKET)
+if (dnsa->answerlen > (int) sizeof(dnsa->answer))
   {
-  DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) resulted in overlong packet (size %d), truncating to %d.\n",
-    name, dns_text_type(type), dnsa->answerlen, MAXPACKET);
-  dnsa->answerlen = MAXPACKET;
+  DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) resulted in overlong packet"
+    " (size %d), truncating to %u.\n",
+    name, dns_text_type(type), dnsa->answerlen, (unsigned int) sizeof(dnsa->answer));
+  dnsa->answerlen = sizeof(dnsa->answer);
   }
 
 if (dnsa->answerlen < 0) switch (h_errno)
@@ -1014,7 +1021,7 @@ switch (type)
   assertion field. */
   case T_CSA:
     {
-    uschar *srvname, *namesuff, *tld, *p;
+    uschar *srvname, *namesuff, *tld;
     int priority, weight, port;
     int limit, rc, i;
     BOOL ipv6;