(1) Typo in redirect router; (2) Update version number; (3) Update
[exim.git] / src / src / host.c
index 0acafd8a83f97c262f9bfefc84bedc9237979a0d..91ba467d30f9e92f558572c7a69b9bd1bb684033 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/host.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/host.c,v 1.5 2005/01/04 10:00:42 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2004 */
+/* Copyright (c) University of Cambridge 1995 - 2005 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions for finding hosts, either by gethostbyname(), gethostbyaddr(), or
@@ -90,6 +90,48 @@ return (unsigned int)(random_seed >> 16) % limit;
 
 
 
+/*************************************************
+*         Sort addresses when testing            *
+*************************************************/
+
+/* This function is called only when running in the test harness. It sorts a
+number of multihomed host IP addresses into the order, so as to get
+repeatability. This doesn't have to be efficient. But don't interchange IPv4
+and IPv6 addresses!
+
+Arguments:
+  host        -> the first host item
+  last        -> the last host item
+  
+Returns:      nothing
+*/  
+
+static void
+sort_addresses(host_item *host, host_item *last)
+{
+BOOL done = FALSE;
+while (!done)
+  {
+  host_item *h;
+  done = TRUE;
+  for (h = host; h != last; h = h->next)
+    {
+    if ((Ustrchr(h->address, ':') == NULL) !=
+        (Ustrchr(h->next->address, ':') == NULL))
+      continue;
+    if (Ustrcmp(h->address, h->next->address) > 0)
+      {
+      uschar *temp = h->address;
+      h->address = h->next->address;
+      h->next->address = temp;
+      done = FALSE;
+      }
+    }
+  }
+}
+
+
+
 /*************************************************
 *       Build chain of host items from list      *
 *************************************************/
@@ -712,12 +754,18 @@ if (Ustrchr(address, ':') != NULL)
 
   if (*p == ':') p++;
 
-  /* Split the address into components separated by colons. */
+  /* Split the address into components separated by colons. The input address 
+  is supposed to be checked for syntax. There was a case where this was 
+  overlooked; to guard against that happening again, check here and crash if 
+  there is a violation. */
 
   while (*p != 0)
     {
     int len = Ustrcspn(p, ":");
     if (len == 0) nulloffset = ci;
+    if (ci > 7) log_write(0, LOG_MAIN|LOG_PANIC_DIE, 
+      "Internal error: invalid IPv6 address \"%s\" passed to host_aton()",
+      address);  
     component[ci++] = p;
     p += len;
     if (*p == ':') p++;
@@ -814,22 +862,24 @@ for (i = 0; i < count; i++)
 /* We can't use host_ntoa() because it assumes the binary values are in network
 byte order, and these are the result of host_aton(), which puts them in ints in
 host byte order. Also, we really want IPv6 addresses to be in a canonical
-format, so we output them with no abbreviation. However, we can't use the
-normal colon separator in them because it terminates keys in lsearch files, so
-use dot instead.
+format, so we output them with no abbreviation. In a number of cases we can't
+use the normal colon separator in them because it terminates keys in lsearch
+files, so we want to use dot instead. There's an argument that specifies what 
+to use for IPv6 addresses.
 
 Arguments:
   count       1 or 4 (number of ints)
   binary      points to the ints
   mask        mask value; if < 0 don't add to result
   buffer      big enough to hold the result
+  sep         component separator character for IPv6 addresses 
 
 Returns:      the number of characters placed in buffer, not counting
               the final nul.
 */
 
 int
-host_nmtoa(int count, int *binary, int mask, uschar *buffer)
+host_nmtoa(int count, int *binary, int mask, uschar *buffer, int sep)
 {
 int i, j;
 uschar *tt = buffer;
@@ -848,12 +898,12 @@ else
   for (i = 0; i < 4; i++)
     {
     j = binary[i];
-    sprintf(CS tt, "%04x.%04x.", (j >> 16) & 0xffff, j & 0xffff);
+    sprintf(CS tt, "%04x%c%04x%c", (j >> 16) & 0xffff, sep, j & 0xffff, sep);
     while (*tt) tt++;
     }
   }
 
-tt--;   /* lose final . */
+tt--;   /* lose final separator */
 
 if (mask < 0)
   *tt = 0;
@@ -1791,31 +1841,9 @@ yield = local_host_check?
   host_scan_for_local_hosts(host, &last, NULL) : HOST_FOUND;
 
 /* When running in the test harness, sort into the order of addresses so as to
-get repeatability. This doesn't have to be efficient. But don't interchange
-IPv4 and IPv6 addresses! */
+get repeatability. */
 
-if (running_in_test_harness)
-  {
-  BOOL done = FALSE;
-  while (!done)
-    {
-    host_item *h;
-    done = TRUE;
-    for (h = host; h != last; h = h->next)
-      {
-      if ((Ustrchr(h->address, ':') == NULL) !=
-          (Ustrchr(h->next->address, ':') == NULL))
-        continue;
-      if (Ustrcmp(h->address, h->next->address) > 0)
-        {
-        uschar *temp = h->address;
-        h->address = h->next->address;
-        h->next->address = temp;
-        done = FALSE;
-        }
-      }
-    }
-  }
+if (running_in_test_harness) sort_addresses(host, last);
 
 HDEBUG(D_host_lookup)
   {
@@ -1954,7 +1982,7 @@ for (; i >= 0; i--)
   fails or times out, but not if another one succeeds. (In the early
   IPv6 days there are name servers that always fail on AAAA, but are happy
   to give out an A record. We want to proceed with that A record.) */
-
+  
   if (rc != DNS_SUCCEED)
     {
     if (i == 0)  /* Just tried for an A record, i.e. end of loop */
@@ -2242,6 +2270,11 @@ if (rc != DNS_SUCCEED)
   else
     if (rc == HOST_IGNORED) rc = HOST_FIND_FAILED;  /* No special action */
 
+  /* When running in the test harness, sort into the order of addresses so as
+  to get repeatability. */
+  
+  if (running_in_test_harness) sort_addresses(host, last);
+
   DEBUG(D_host_lookup)
     {
     host_item *h;