DANE: Fix 2 messages from queue case
[exim.git] / src / src / transport.c
index 3eb1c8097e04b3657b9e9f072b84d00d1dea7a70..fd8da0f08c74386941dc2c51dc9ef885effb12a5 100644 (file)
@@ -3,6 +3,7 @@
 *************************************************/
 
 /* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* General functions concerned with transportation, and generic options for all
@@ -265,6 +266,7 @@ for (int i = 0; i < 100; i++)
       }
     else                               /* Timeout wanted. */
       {
+      sigalrm_seen = FALSE;
       ALARM(local_timeout);
        rc = tpt_write(fd, block, len, more, tctx->options);
        save_errno = errno;
@@ -1188,7 +1190,8 @@ transport_write_message(transport_ctx * tctx, int size_limit)
 {
 BOOL last_filter_was_NL = TRUE;
 BOOL save_spool_file_wireformat = f.spool_file_wireformat;
-int rc, len, yield, fd_read, fd_write, save_errno;
+BOOL yield;
+int rc, len, fd_read, fd_write, save_errno;
 int pfd[2] = {-1, -1};
 pid_t filter_pid, write_pid;
 
@@ -1232,10 +1235,10 @@ write_pid = (pid_t)(-1);
 
   {
   int bits = fcntl(tctx->u.fd, F_GETFD);
-  (void)fcntl(tctx->u.fd, F_SETFD, bits | FD_CLOEXEC);
+  (void) fcntl(tctx->u.fd, F_SETFD, bits | FD_CLOEXEC);
   filter_pid = child_open(USS transport_filter_argv, NULL, 077,
-   &fd_write, &fd_read, FALSE);
-  (void)fcntl(tctx->u.fd, F_SETFD, bits & ~FD_CLOEXEC);
+                         &fd_write, &fd_read, FALSE, US"transport-filter");
+  (void) fcntl(tctx->u.fd, F_SETFD, bits & ~FD_CLOEXEC);
   }
 if (filter_pid < 0) goto TIDY_UP;      /* errno set */
 
@@ -1248,7 +1251,7 @@ via a(nother) pipe. While writing to the filter, we do not do the CRLF,
 smtp dots, or check string processing. */
 
 if (pipe(pfd) != 0) goto TIDY_UP;      /* errno set */
-if ((write_pid = fork()) == 0)
+if ((write_pid = exim_fork(US"tpt-filter-writer")) == 0)
   {
   BOOL rc;
   (void)close(fd_read);
@@ -1272,7 +1275,7 @@ if ((write_pid = fork()) == 0)
         != sizeof(struct timeval)
      )
     rc = FALSE;        /* compiler quietening */
-  exim_underbar_exit(0, US"tpt-filter");
+  exim_underbar_exit(EXIT_SUCCESS);
   }
 save_errno = errno;
 
@@ -1320,6 +1323,7 @@ for (;;)
   ALARM_CLR(0);
   if (sigalrm_seen)
     {
+    DEBUG(D_transport) debug_printf("timed out reading from filter\n");
     errno = ETIMEDOUT;
     f.transport_filter_timed_out = TRUE;
     goto TIDY_UP;
@@ -1396,7 +1400,6 @@ if (write_pid > 0)
        int dummy = read(pfd[pipe_read], (void *)&save_errno, sizeof(int));
         dummy = read(pfd[pipe_read], (void *)&tctx->addr->more_errno, sizeof(int));
         dummy = read(pfd[pipe_read], (void *)&tctx->addr->delivery_time, sizeof(struct timeval));
-       dummy = dummy;          /* compiler quietening */
         yield = FALSE;
         }
       }
@@ -1438,7 +1441,7 @@ DEBUG(D_transport)
   {
   debug_printf("end of filtering transport writing: yield=%d\n", yield);
   if (!yield)
-    debug_printf("errno=%d more_errno=%d\n", errno, tctx->addr->more_errno);
+    debug_printf(" errno=%d more_errno=%d\n", errno, tctx->addr->more_errno);
   }
 
 return yield;
@@ -1567,7 +1570,7 @@ for (host_item * host = hostlist; host; host = host->next)
     {
     sprintf(CS buffer, "%.200s:%d", host->name, host_record->sequence);
     dbfn_write(dbm_file, buffer, host_record, sizeof(dbdata_wait) + host_length);
-#ifdef EXPERIMENTAL_QUEUE_RAMP
+#ifndef DISABLE_QUEUE_RAMP
     if (f.queue_2stage && queue_fast_ramp && !queue_run_in_order)
       queue_notify_daemon(message_id);
 #endif
@@ -1624,7 +1627,6 @@ Arguments:
   local_message_max  maximum number of messages down one connection
                        as set by the caller transport
   new_message_id     set to the message id of a waiting message
-  more               set TRUE if there are yet more messages waiting
   oicf_func          function to call to validate if it is ok to send
                      to this message_id from the current instance.
   oicf_data          opaque data for oicf_func
@@ -1640,7 +1642,7 @@ typedef struct msgq_s
 
 BOOL
 transport_check_waiting(const uschar *transport_name, const uschar *hostname,
-  int local_message_max, uschar *new_message_id, BOOL *more, oicf oicf_func, void *oicf_data)
+  int local_message_max, uschar *new_message_id, oicf oicf_func, void *oicf_data)
 {
 dbdata_wait *host_record;
 int host_length;
@@ -1650,13 +1652,12 @@ open_db *dbm_file;
 int         i;
 struct stat statbuf;
 
-*more = FALSE;
-
 DEBUG(D_transport)
   {
   debug_printf("transport_check_waiting entered\n");
   debug_printf("  sequence=%d local_max=%d global_max=%d\n",
     continue_sequence, local_message_max, connection_max_messages);
+  acl_level++;
   }
 
 /* Do nothing if we have hit the maximum number that can be send down one
@@ -1666,23 +1667,23 @@ if (connection_max_messages >= 0) local_message_max = connection_max_messages;
 if (local_message_max > 0 && continue_sequence >= local_message_max)
   {
   DEBUG(D_transport)
-    debug_printf("max messages for one connection reached: returning\n");
-  return FALSE;
+    debug_printf_indent("max messages for one connection reached: returning\n");
+  goto retfalse;
   }
 
 /* Open the waiting information database. */
 
 if (!(dbm_file = dbfn_open(string_sprintf("wait-%.200s", transport_name),
                          O_RDWR, &dbblock, TRUE, TRUE)))
-  return FALSE;
+  goto retfalse;
 
 /* See if there is a record for this host; if not, there's nothing to do. */
 
 if (!(host_record = dbfn_read(dbm_file, hostname)))
   {
   dbfn_close(dbm_file);
-  DEBUG(D_transport) debug_printf("no messages waiting for %s\n", hostname);
-  return FALSE;
+  DEBUG(D_transport) debug_printf_indent("no messages waiting for %s\n", hostname);
+  goto retfalse;
   }
 
 /* If the data in the record looks corrupt, just log something and
@@ -1693,7 +1694,7 @@ if (host_record->count > WAIT_NAME_MAX)
   dbfn_close(dbm_file);
   log_write(0, LOG_MAIN|LOG_PANIC, "smtp-wait database entry for %s has bad "
     "count=%d (max=%d)", hostname, host_record->count, WAIT_NAME_MAX);
-  return FALSE;
+  goto retfalse;
   }
 
 /* Scan the message ids in the record from the end towards the beginning,
@@ -1731,6 +1732,7 @@ while (1)
     }
 
   /* first thing remove current message id if it exists */
+  /*XXX but what if it has un-sent addrs? */
 
   for (i = 0; i < msgq_count; ++i)
     if (Ustrcmp(msgq[i].message_id, message_id) == 0)
@@ -1830,8 +1832,8 @@ while (1)
   if (host_length <= 0)
     {
     dbfn_close(dbm_file);
-    DEBUG(D_transport) debug_printf("waiting messages already delivered\n");
-    return FALSE;
+    DEBUG(D_transport) debug_printf_indent("waiting messages already delivered\n");
+    goto retfalse;
     }
 
   /* we were not able to find an acceptable message, nor was there a
@@ -1842,7 +1844,7 @@ while (1)
     {
     Ustrcpy(new_message_id, message_id);
     dbfn_close(dbm_file);
-    return FALSE;
+    goto retfalse;
     }
   }            /* we need to process a continuation record */
 
@@ -1854,13 +1856,16 @@ record if required, close the database, and return TRUE. */
 if (host_length > 0)
   {
   host_record->count = host_length/MESSAGE_ID_LENGTH;
-
   dbfn_write(dbm_file, hostname, host_record, (int)sizeof(dbdata_wait) + host_length);
-  *more = TRUE;
   }
 
 dbfn_close(dbm_file);
+DEBUG(D_transport) {acl_level--; debug_printf("transport_check_waiting: TRUE\n"); }
 return TRUE;
+
+retfalse:
+DEBUG(D_transport) {acl_level--; debug_printf("transport_check_waiting: FALSE\n"); }
+return FALSE;
 }
 
 /*************************************************
@@ -1872,7 +1877,7 @@ void
 transport_do_pass_socket(const uschar *transport_name, const uschar *hostname,
   const uschar *hostaddress, uschar *id, int socket_fd)
 {
-int i = 20;
+int i = 22;
 const uschar **argv;
 
 /* Set up the calling arguments; use the standard function for the basics,
@@ -1893,6 +1898,12 @@ if (smtp_peer_options & OPTION_TLS)
     argv[i++] = sending_ip_address;
     argv[i++] = string_sprintf("%d", sending_port);
     argv[i++] = tls_out.active.sock >= 0 ? tls_out.cipher : continue_proxy_cipher;
+
+    if (tls_out.sni)
+      {
+      argv[i++] = tls_out.dane_verified ? US"-MCr" : US"-MCs";
+      argv[i++] = tls_out.sni;
+      }
     }
   else
     argv[i++] = US"-MCT";
@@ -1954,18 +1965,15 @@ int status;
 
 DEBUG(D_transport) debug_printf("transport_pass_socket entered\n");
 
-if ((pid = fork()) == 0)
+if ((pid = exim_fork(US"continued-transport-interproc")) == 0)
   {
   /* Disconnect entirely from the parent process. If we are running in the
   test harness, wait for a bit to allow the previous process time to finish,
   write the log, etc., so that the output is always in the same order for
   automatic comparison. */
 
-  if ((pid = fork()) != 0)
-    {
-    DEBUG(D_transport) debug_printf("transport_pass_socket succeeded (final-pid %d)\n", pid);
+  if ((pid = exim_fork(US"continued-transport")) != 0)
     _exit(EXIT_SUCCESS);
-    }
   testharness_pause_ms(1000);
 
   transport_do_pass_socket(transport_name, hostname, hostaddress,
@@ -1980,7 +1988,6 @@ if (pid > 0)
   {
   int rc;
   while ((rc = wait(&status)) != pid && (rc >= 0 || errno != ECHILD));
-  DEBUG(D_transport) debug_printf("transport_pass_socket succeeded (inter-pid %d)\n", pid);
   return TRUE;
   }
 else