Update copyright year in (most) files (those that my script finds).
[exim.git] / src / src / transports / smtp.c
index c16e620b31e44e7e84afea32cf258e7b6f95f9df..bb8c6e01821902575690c7b9da94cd6ec31c149c 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/transports/smtp.c,v 1.16 2005/08/08 15:02:48 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/smtp.c,v 1.20 2006/02/07 11:19:03 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) University of Cambridge 1995 - 2006 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 #include "../exim.h"
@@ -329,8 +329,8 @@ this particular type of timeout.
 Returns:       nothing
 */
 
-static
-void set_errno(address_item *addrlist, int errno_value, uschar *msg, int rc,
+static void
+set_errno(address_item *addrlist, int errno_value, uschar *msg, int rc,
   BOOL pass_message)
 {
 address_item *addr;
@@ -462,11 +462,12 @@ if (buffer[0] != 0)
   }
 
 /* No data was read. If there is no errno, this must be the EOF (i.e.
-connection closed) case, which causes deferral. Otherwise, put the host's
-identity in the message, leaving the errno value to be interpreted as well. In
-all cases, we have to assume the connection is now dead. */
+connection closed) case, which causes deferral. An explicit connection reset
+error has the same effect. Otherwise, put the host's identity in the message,
+leaving the errno value to be interpreted as well. In all cases, we have to
+assume the connection is now dead. */
 
-if (*errno_value == 0)
+if (*errno_value == 0 || *errno_value == ECONNRESET)
   {
   *errno_value = ERRNO_SMTPCLOSED;
   *message = US string_sprintf("Remote host %s [%s] closed connection "
@@ -505,14 +506,14 @@ if (addr->message != NULL)
   }
 else
   {
-  log_write(0, LOG_MAIN, "%s [%s]: %s",
-    host->name,
-    host->address,
-    strerror(addr->basic_errno));
-  deliver_msglog("%s %s [%s]: %s\n",
-    tod_stamp(tod_log),
-    host->name,
-    host->address,
+  uschar *msg =
+    ((log_extra_selector & LX_outgoing_port) != 0)?
+    string_sprintf("%s [%s]:%d", host->name, host->address,
+      (host->port == PORT_NONE)? 25 : host->port)
+    :
+    string_sprintf("%s [%s]", host->name, host->address);
+  log_write(0, LOG_MAIN, "%s %s", msg, strerror(addr->basic_errno));
+  deliver_msglog("%s %s %s\n", tod_stamp(tod_log), msg,
     strerror(addr->basic_errno));
   }
 }
@@ -2206,14 +2207,6 @@ for (cutoff_retry = 0; expired &&
     uschar *retry_message_key = NULL;
     uschar *serialize_key = NULL;
 
-    /* Set up a string for adding to the retry key if the port number is not
-    the standard SMTP port. A host may have its own port setting that overrides
-    the default. */
-
-    pistring = string_sprintf(":%d", (host->port == PORT_NONE)?
-      port : host->port);
-    if (Ustrcmp(pistring, ":25") == 0) pistring = US"";
-
     /* Default next host is next host. :-) But this can vary if the
     hosts_max_try limit is hit (see below). It may also be reset if a host
     address is looked up here (in case the host was multihomed). */
@@ -2243,6 +2236,8 @@ for (cutoff_retry = 0; expired &&
 
     if (host->address == NULL)
       {
+      int new_port;
+      host_item *hh;
       uschar *canonical_name;
 
       if (host->status >= hstatus_unusable)
@@ -2254,12 +2249,19 @@ for (cutoff_retry = 0; expired &&
 
       DEBUG(D_transport) debug_printf("getting address for %s\n", host->name);
 
+      /* The host name is permitted to have an attached port. Find it, and
+      strip it from the name. Just remember it for now. */
+
+      new_port = host_item_get_port(host);
+
+      /* Count hosts looked up */
+
       hosts_looked_up++;
 
       /* Find by name if so configured, or if it's an IP address. We don't
       just copy the IP address, because we need the test-for-local to happen. */
 
-      if (ob->gethostbyname || string_is_ip_address(host->name, NULL) > 0)
+      if (ob->gethostbyname || string_is_ip_address(host->name, NULL) != 0)
         rc = host_find_byname(host, NULL, &canonical_name, TRUE);
       else
         {
@@ -2270,6 +2272,11 @@ for (cutoff_retry = 0; expired &&
           &canonical_name, NULL);
         }
 
+      /* Update the host (and any additional blocks, resulting from
+      multihoming) with a host-specific port, if any. */
+
+      for (hh = host; hh != nexthost; hh = hh->next) hh->port = new_port;
+
       /* Failure to find the host at this time (usually DNS temporary failure)
       is really a kind of routing failure rather than a transport failure.
       Therefore we add a retry item of the routing kind, not to stop us trying
@@ -2363,6 +2370,14 @@ for (cutoff_retry = 0; expired &&
     deliver_host = host->name;
     deliver_host_address = host->address;
 
+    /* Set up a string for adding to the retry key if the port number is not
+    the standard SMTP port. A host may have its own port setting that overrides
+    the default. */
+
+    pistring = string_sprintf(":%d", (host->port == PORT_NONE)?
+      port : host->port);
+    if (Ustrcmp(pistring, ":25") == 0) pistring = US"";
+
     /* Select IPv4 or IPv6, and choose an outgoing interface. If the interface
     string changes upon expansion, we must add it to the key that is used for
     retries, because connections to the same host from a different interface