Added a "connect=<time>" option to callouts, for a separate timeout
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Thu, 4 Nov 2004 12:19:48 +0000 (12:19 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Thu, 4 Nov 2004 12:19:48 +0000 (12:19 +0000)
for making the connection. As part of this, the debug output for a
failed connection now shows the error, and, if it's a timeout, the
timeout value.

doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/src/acl.c
src/src/exim.c
src/src/functions.h
src/src/routers/rf_get_errors_address.c
src/src/smtp_in.c
src/src/smtp_out.c
src/src/verify.c

index a57b077a174380c808b6542c2baac18bdc41f9c1..01bfcf8f17dd288ab54e881c74f7166c9a5195d6 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.14 2004/11/04 10:42:11 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.15 2004/11/04 12:19:48 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -56,6 +56,9 @@ Exim version 4.44
 
 14. Added forbid_sieve_filter and forbid_exim_filter to the redirect router.
 
 
 14. Added forbid_sieve_filter and forbid_exim_filter to the redirect router.
 
+15. Added a new option "connect=<time>" to callout options, to set a different
+    connection timeout.
+
 
 Exim version 4.43
 -----------------
 
 Exim version 4.43
 -----------------
index b8cf61cc9396013ad002feba21e930fccc5bdf25..79e3476981f1fd4b8d7af0c24a092c4b7f625254 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/NewStuff,v 1.5 2004/11/04 10:42:11 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/NewStuff,v 1.6 2004/11/04 12:19:48 ph10 Exp $
 
 New Features in Exim
 --------------------
 
 New Features in Exim
 --------------------
@@ -33,6 +33,14 @@ Version 4.44
     options control which type(s) of filtering are permitted. By default, both
     Exim and Sieve filters are allowed.
 
     options control which type(s) of filtering are permitted. By default, both
     Exim and Sieve filters are allowed.
 
+ 6. A new option for callouts makes it possible to set a different (usually
+    smaller) timeout for making the SMTP connection. The keyword is "connect".
+    For example:
+
+       verify = sender/callout=5s,connect=1s
+
+    If not specified, it defaults to the general timeout value.
+
 
 Version 4.43
 ------------
 
 Version 4.43
 ------------
index 1812e0be254879ca9afad7d1ce6d63e97ac93e9c..92ebc18ec7d3e785d0339b9f975e65a63eb64d37 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/acl.c,v 1.4 2004/10/19 13:40:39 ph10 Exp $ */
+/* $Cambridge: exim/src/src/acl.c,v 1.5 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -689,6 +689,7 @@ acl_verify(int where, address_item *addr, uschar *arg,
 int sep = '/';
 int callout = -1;
 int callout_overall = -1;
 int sep = '/';
 int callout = -1;
 int callout_overall = -1;
+int callout_connect = -1;
 int verify_options = 0;
 int rc;
 BOOL verify_header_sender = FALSE;
 int verify_options = 0;
 int rc;
 BOOL verify_header_sender = FALSE;
@@ -835,6 +836,11 @@ while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))
         uschar *opt;
         uschar buffer[256];
         while (isspace(*ss)) ss++;
         uschar *opt;
         uschar buffer[256];
         while (isspace(*ss)) ss++;
+        
+        /* This callout option handling code has become a mess as new options 
+        have been added in an ad hoc manner. It should be tidied up into some 
+        kind of table-driven thing. */
         while ((opt = string_nextinlist(&ss, &optsep, buffer, sizeof(buffer)))
               != NULL)
           {
         while ((opt = string_nextinlist(&ss, &optsep, buffer, sizeof(buffer)))
               != NULL)
           {
@@ -903,6 +909,25 @@ while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))
               return ERROR;
               }
             }
               return ERROR;
               }
             }
+          else if (strncmpic(opt, US"connect", 7) == 0)
+            {
+            opt += 7;
+            while (isspace(*opt)) opt++;
+            if (*opt++ != '=')
+              {
+              *log_msgptr = string_sprintf("'=' expected after "
+                "\"callout_overaall\" in ACL condition \"%s\"", arg);
+              return ERROR;
+              }
+            while (isspace(*opt)) opt++;
+            callout_connect = readconf_readtime(opt, 0, FALSE);
+            if (callout_connect < 0)
+              {
+              *log_msgptr = string_sprintf("bad time value in ACL condition "
+                "\"verify %s\"", arg);
+              return ERROR;
+              }
+            }
           else    /* Plain time is callout connect/command timeout */
             {
             callout = readconf_readtime(opt, 0, FALSE);
           else    /* Plain time is callout connect/command timeout */
             {
             callout = readconf_readtime(opt, 0, FALSE);
@@ -948,7 +973,7 @@ message if giving out verification details. */
 if (verify_header_sender)
   {
   rc = verify_check_header_address(user_msgptr, log_msgptr, callout,
 if (verify_header_sender)
   {
   rc = verify_check_header_address(user_msgptr, log_msgptr, callout,
-    callout_overall, se_mailfrom, pm_mailfrom, verify_options);
+    callout_overall, callout_connect, se_mailfrom, pm_mailfrom, verify_options);
   if (smtp_return_error_details)
     {
     if (*user_msgptr == NULL && *log_msgptr != NULL)
   if (smtp_return_error_details)
     {
     if (*user_msgptr == NULL && *log_msgptr != NULL)
@@ -1031,7 +1056,7 @@ else if (verify_sender_address != NULL)
       verify_options. */
 
       rc = verify_address(sender_vaddr, NULL, verify_options, callout,
       verify_options. */
 
       rc = verify_address(sender_vaddr, NULL, verify_options, callout,
-        callout_overall, se_mailfrom, pm_mailfrom, &routed);
+        callout_overall, callout_connect, se_mailfrom, pm_mailfrom, &routed);
 
       HDEBUG(D_acl) debug_printf("----------- end verify ------------\n");
 
 
       HDEBUG(D_acl) debug_printf("----------- end verify ------------\n");
 
@@ -1083,7 +1108,7 @@ else
 
   addr2 = *addr;
   rc = verify_address(&addr2, NULL, verify_options|vopt_is_recipient, callout,
 
   addr2 = *addr;
   rc = verify_address(&addr2, NULL, verify_options|vopt_is_recipient, callout,
-    callout_overall, se_mailfrom, pm_mailfrom, NULL);
+    callout_overall, callout_connect, se_mailfrom, pm_mailfrom, NULL);
   HDEBUG(D_acl) debug_printf("----------- end verify ------------\n");
   *log_msgptr = addr2.message;
   *user_msgptr = addr2.user_message;
   HDEBUG(D_acl) debug_printf("----------- end verify ------------\n");
   *log_msgptr = addr2.message;
   *user_msgptr = addr2.user_message;
index 8f51e66fa01da5acedf50d3243d0d1ef39bd942a..e22fd23089f4f2be908244f6bd156a7a03a69980 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/exim.c,v 1.6 2004/10/19 11:40:52 ph10 Exp $ */
+/* $Cambridge: exim/src/src/exim.c,v 1.7 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -640,7 +640,7 @@ if (address == NULL)
 else
   {
   int rc = verify_address(deliver_make_addr(address,TRUE), stdout, flags, -1,
 else
   {
   int rc = verify_address(deliver_make_addr(address,TRUE), stdout, flags, -1,
-    -1, NULL, NULL, NULL);
+    -1, -1, NULL, NULL, NULL);
   if (rc == FAIL) *exit_value = 2;
     else if (rc == DEFER && *exit_value == 0) *exit_value = 1;
   }
   if (rc == FAIL) *exit_value = 2;
     else if (rc == DEFER && *exit_value == 0) *exit_value = 1;
   }
index dbdf798e5d83ca6cf9f904523000e7f466a4ba35..017ec87206942ca584f043acfb0881643d8bcaa9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/functions.h,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/functions.h,v 1.2 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -292,10 +292,10 @@ extern int     tree_insertnode(tree_node **, tree_node *);
 extern tree_node *tree_search(tree_node *, uschar *);
 extern void    tree_write(tree_node *, FILE *);
 
 extern tree_node *tree_search(tree_node *, uschar *);
 extern void    tree_write(tree_node *, FILE *);
 
-extern int     verify_address(address_item *, FILE *, int, int, int, uschar *,
-                 uschar *, BOOL *);
+extern int     verify_address(address_item *, FILE *, int, int, int, int,
+                 uschar *, uschar *, BOOL *);
 extern int     verify_check_dnsbl(uschar **);
 extern int     verify_check_dnsbl(uschar **);
-extern int     verify_check_header_address(uschar **, uschar **, int, int,
+extern int     verify_check_header_address(uschar **, uschar **, int, int, int,
                  uschar *, uschar *, int);
 extern int     verify_check_headers(uschar **);
 extern int     verify_check_host(uschar **);
                  uschar *, uschar *, int);
 extern int     verify_check_headers(uschar **);
 extern int     verify_check_host(uschar **);
index e2e75424ce84113ad49c4a9505f4bea5866561f3..e0c3bc1cd6587836a6b15dd465748bf2c9dace19 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/routers/rf_get_errors_address.c,v 1.1 2004/10/07 13:10:02 ph10 Exp $ */
+/* $Cambridge: exim/src/src/routers/rf_get_errors_address.c,v 1.2 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -102,7 +102,7 @@ else
 
   DEBUG(D_route|D_verify)
     debug_printf("------ Verifying errors address %s ------\n", s);
 
   DEBUG(D_route|D_verify)
     debug_printf("------ Verifying errors address %s ------\n", s);
-  if (verify_address(snew, NULL, vopt_is_recipient | vopt_qualify, -1, -1,
+  if (verify_address(snew, NULL, vopt_is_recipient | vopt_qualify, -1, -1, -1,
     NULL, NULL, NULL) == OK) *errors_to = snew->address;
   DEBUG(D_route|D_verify)
     debug_printf("------ End verifying errors address %s ------\n", s);
     NULL, NULL, NULL) == OK) *errors_to = snew->address;
   DEBUG(D_route|D_verify)
     debug_printf("------ End verifying errors address %s ------\n", s);
index 9189c67ee36cf1d7b506cc8dc86c44e2b90e803f..e3b4dcecec60992e8b46c89188f94011cda5256e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/smtp_in.c,v 1.3 2004/10/19 11:29:25 ph10 Exp $ */
+/* $Cambridge: exim/src/src/smtp_in.c,v 1.4 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -3078,7 +3078,7 @@ while (done <= 0)
         {
         address_item *addr = deliver_make_addr(address, FALSE);
         switch(verify_address(addr, NULL, vopt_is_recipient | vopt_qualify, -1,
         {
         address_item *addr = deliver_make_addr(address, FALSE);
         switch(verify_address(addr, NULL, vopt_is_recipient | vopt_qualify, -1,
-               -1, NULL, NULL, NULL))
+               -1, -1, NULL, NULL, NULL))
           {
           case OK:
           s = string_sprintf("250 <%s> is deliverable", address);
           {
           case OK:
           s = string_sprintf("250 <%s> is deliverable", address);
@@ -3115,7 +3115,8 @@ while (done <= 0)
       BOOL save_log_testing_mode = log_testing_mode;
       address_test_mode = log_testing_mode = TRUE;
       (void) verify_address(deliver_make_addr(smtp_data, FALSE), smtp_out,
       BOOL save_log_testing_mode = log_testing_mode;
       address_test_mode = log_testing_mode = TRUE;
       (void) verify_address(deliver_make_addr(smtp_data, FALSE), smtp_out,
-        vopt_is_recipient | vopt_qualify | vopt_expn, -1, -1, NULL, NULL, NULL);
+        vopt_is_recipient | vopt_qualify | vopt_expn, -1, -1, -1, NULL, NULL, 
+        NULL);
       address_test_mode = FALSE;
       log_testing_mode = save_log_testing_mode;    /* true for -bh */
       }
       address_test_mode = FALSE;
       log_testing_mode = save_log_testing_mode;    /* true for -bh */
       }
index fc90c251166acdc3defa42d2736b2d398b91f16e..449b52438b3295d9ae9334d3eb9e431ff6de93c1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/smtp_out.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/smtp_out.c,v 1.2 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -223,7 +223,13 @@ else if (ip_connect(sock, host_af, host->address, port, timeout) < 0)
 
 if (save_errno != 0)
   {
 
 if (save_errno != 0)
   {
-  HDEBUG(D_transport|D_acl|D_v) debug_printf("failed\n");
+  HDEBUG(D_transport|D_acl|D_v) 
+    {
+    debug_printf("failed: %s", CUstrerror(save_errno));
+    if (save_errno == ETIMEDOUT) 
+      debug_printf(" (timeout=%s)", readconf_printtime(timeout));
+    debug_printf("\n");   
+    } 
   close(sock);
   errno = save_errno;
   return -1;
   close(sock);
   errno = save_errno;
   return -1;
index bae410e6722c52464e16d6ab7110f8530027147b..8b24fb48a0b532f235d1744686844dd88597046f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/verify.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/verify.c,v 1.2 2004/11/04 12:19:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -123,7 +123,8 @@ Arguments:
   portstring        "port" option from transport, or NULL
   protocolstring    "protocol" option from transport, or NULL
   callout           the per-command callout timeout
   portstring        "port" option from transport, or NULL
   protocolstring    "protocol" option from transport, or NULL
   callout           the per-command callout timeout
-  callout_overall   the overall callout timeout (if < 0; use 4*callout)
+  callout_overall   the overall callout timeout (if < 0 use 4*callout)
+  callout_connect   the callout connection timeout (if < 0 use callout)
   options           the verification options - these bits are used:
                       vopt_is_recipient => this is a recipient address
                       vopt_callout_no_cache => don't use callout cache
   options           the verification options - these bits are used:
                       vopt_is_recipient => this is a recipient address
                       vopt_callout_no_cache => don't use callout cache
@@ -138,8 +139,8 @@ Returns:            OK/FAIL/DEFER
 
 static int
 do_callout(address_item *addr, host_item *host_list, transport_feedback *tf,
 
 static int
 do_callout(address_item *addr, host_item *host_list, transport_feedback *tf,
-  int callout, int callout_overall, int options, uschar *se_mailfrom,
-  uschar *pm_mailfrom)
+  int callout, int callout_overall, int callout_connect, int options, 
+  uschar *se_mailfrom, uschar *pm_mailfrom)
 {
 BOOL is_recipient = (options & vopt_is_recipient) != 0;
 BOOL callout_no_cache = (options & vopt_callout_no_cache) != 0;
 {
 BOOL is_recipient = (options & vopt_is_recipient) != 0;
 BOOL callout_no_cache = (options & vopt_callout_no_cache) != 0;
@@ -355,10 +356,11 @@ if (callout_random && callout_random_local_part != NULL)
       "callout_random_local_part: %s", expand_string_message);
   }
 
       "callout_random_local_part: %s", expand_string_message);
   }
 
-/* Default the overall callout timeout if not set, and record the time we are
-starting so that we can enforce it. */
+/* Default the connect and overall callout timeouts if not set, and record the
+time we are starting so that we can enforce it. */
 
 if (callout_overall < 0) callout_overall = 4 * callout;
 
 if (callout_overall < 0) callout_overall = 4 * callout;
+if (callout_connect < 0) callout_connect = callout;
 callout_start_time = time(NULL);
 
 /* Now make connections to the hosts and do real callouts. The list of hosts
 callout_start_time = time(NULL);
 
 /* Now make connections to the hosts and do real callouts. The list of hosts
@@ -435,10 +437,10 @@ for (host = host_list; host != NULL && !done; host = host->next)
   outblock.authenticating = FALSE;
 
   /* Connect to the host; on failure, just loop for the next one, but we
   outblock.authenticating = FALSE;
 
   /* Connect to the host; on failure, just loop for the next one, but we
-  set the error for the last one. */
+  set the error for the last one. Use the callout_connect timeout. */
 
   inblock.sock = outblock.sock =
 
   inblock.sock = outblock.sock =
-    smtp_connect(host, host_af, port, interface, callout, TRUE);
+    smtp_connect(host, host_af, port, interface, callout_connect, TRUE);
   if (inblock.sock < 0)
     {
     addr->message = string_sprintf("could not connect to %s [%s]: %s",
   if (inblock.sock < 0)
     {
     addr->message = string_sprintf("could not connect to %s [%s]: %s",
@@ -782,9 +784,10 @@ Arguments:
                      vopt_callout_recippmaster => use postmaster for recipient
 
   callout          if > 0, specifies that callout is required, and gives timeout
                      vopt_callout_recippmaster => use postmaster for recipient
 
   callout          if > 0, specifies that callout is required, and gives timeout
-                     for individual connections and commands
+                     for individual commands
   callout_overall  if > 0, gives overall timeout for the callout function;
                    if < 0, a default is used (see do_callout())
   callout_overall  if > 0, gives overall timeout for the callout function;
                    if < 0, a default is used (see do_callout())
+  callout_connect  the connection timeout for callouts                  
   se_mailfrom      when callout is requested to verify a sender, use this
                      in MAIL FROM; NULL => ""
   pm_mailfrom      when callout is requested, if non-NULL, do the postmaster
   se_mailfrom      when callout is requested to verify a sender, use this
                      in MAIL FROM; NULL => ""
   pm_mailfrom      when callout is requested, if non-NULL, do the postmaster
@@ -800,7 +803,8 @@ Returns:           OK      address verified
 
 int
 verify_address(address_item *vaddr, FILE *f, int options, int callout,
 
 int
 verify_address(address_item *vaddr, FILE *f, int options, int callout,
-  int callout_overall, uschar *se_mailfrom, uschar *pm_mailfrom, BOOL *routed)
+  int callout_overall, int callout_connect, uschar *se_mailfrom, 
+  uschar *pm_mailfrom, BOOL *routed)
 {
 BOOL allok = TRUE;
 BOOL full_info = (f == NULL)? FALSE : (debug_selector != 0);
 {
 BOOL allok = TRUE;
 BOOL full_info = (f == NULL)? FALSE : (debug_selector != 0);
@@ -1054,7 +1058,7 @@ while (addr_new != NULL)
         else
           {
           rc = do_callout(addr, host_list, &tf, callout, callout_overall,
         else
           {
           rc = do_callout(addr, host_list, &tf, callout, callout_overall,
-            options, se_mailfrom, pm_mailfrom);
+            callout_connect, options, se_mailfrom, pm_mailfrom);
           }
         }
       else
           }
         }
       else
@@ -1426,6 +1430,7 @@ Arguments:
   log_msgptr       points to where to put a log error message
   callout          timeout for callout check (passed to verify_address())
   callout_overall  overall callout timeout (ditto)
   log_msgptr       points to where to put a log error message
   callout          timeout for callout check (passed to verify_address())
   callout_overall  overall callout timeout (ditto)
+  callout_connect  connect callout timeout (ditto) 
   se_mailfrom      mailfrom for verify; NULL => ""
   pm_mailfrom      sender for pm callout check (passed to verify_address())
   options          callout options (passed to verify_address())
   se_mailfrom      mailfrom for verify; NULL => ""
   pm_mailfrom      sender for pm callout check (passed to verify_address())
   options          callout options (passed to verify_address())
@@ -1439,8 +1444,8 @@ Returns:           result of the verification attempt: OK, FAIL, or DEFER;
 
 int
 verify_check_header_address(uschar **user_msgptr, uschar **log_msgptr,
 
 int
 verify_check_header_address(uschar **user_msgptr, uschar **log_msgptr,
-  int callout, int callout_overall, uschar *se_mailfrom, uschar *pm_mailfrom,
-  int options)
+  int callout, int callout_overall, int callout_connect, uschar *se_mailfrom, 
+  uschar *pm_mailfrom, int options)
 {
 static int header_types[] = { htype_sender, htype_reply_to, htype_from };
 int yield = FAIL;
 {
 static int header_types[] = { htype_sender, htype_reply_to, htype_from };
 int yield = FAIL;
@@ -1529,7 +1534,8 @@ for (i = 0; i < 3; i++)
           {
           vaddr = deliver_make_addr(address, FALSE);
           new_ok = verify_address(vaddr, NULL, options | vopt_fake_sender,
           {
           vaddr = deliver_make_addr(address, FALSE);
           new_ok = verify_address(vaddr, NULL, options | vopt_fake_sender,
-            callout, callout_overall, se_mailfrom, pm_mailfrom, NULL);
+            callout, callout_overall, callout_connect, se_mailfrom, 
+            pm_mailfrom, NULL);
           }
         }
 
           }
         }