]> git.pld-linux.org Git - packages/exim.git/blame - exim-git.patch
- rel 2; include git patch (contains fix for exim crash while handling hashed queue)
[packages/exim.git] / exim-git.patch
CommitLineData
4022a9ec
AM
1commit aa7751be078fe9a20efa2cf2a8856fadb98f4178
2Author: Jeremy Harris <jgh146exb@wizmail.org>
3Date: Sun Jun 28 15:14:02 2015 +0100
4
5 Compiler quietening
6
7diff --git a/src/src/dns.c b/src/src/dns.c
8index 64958d9..a239bec 100644
9--- a/src/src/dns.c
10+++ b/src/src/dns.c
11@@ -40,7 +40,6 @@ fakens_search(const uschar *domain, int type, uschar *answerptr, int size)
12 {
13 int len = Ustrlen(domain);
14 int asize = size; /* Locally modified */
15-uschar *endname;
16 uschar name[256];
17 uschar utilname[256];
18 uschar *aptr = answerptr; /* Locally modified */
19@@ -51,7 +50,6 @@ struct stat statbuf;
20 if (domain[len - 1] == '.') len--;
21 Ustrncpy(name, domain, len);
22 name[len] = 0;
23-endname = name + len;
24
25 /* Look for the fakens utility, and if it exists, call it. */
26
27@@ -86,7 +84,7 @@ if (stat(CS utilname, &statbuf) >= 0)
28 asize -= rc; /* may need to be passed on to res_search(). */
29 }
30
31- /* If we ran out of output buffer before exhasting the return,
32+ /* If we ran out of output buffer before exhausting the return,
33 carry on reading and counting it. */
34
35 if (asize == 0)
36diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
37index cf0a5d6..711ee86 100644
38--- a/src/src/smtp_in.c
39+++ b/src/src/smtp_in.c
40@@ -3293,7 +3293,7 @@ while (done <= 0)
41 pid_t pid;
42 int start, end, sender_domain, recipient_domain;
43 int ptr, size, rc;
44- int c, i;
45+ int c;
46 auth_instance *au;
47 uschar *orcpt = NULL;
48 int flags;
49diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
50index e1dcd77..d8377fd 100644
51--- a/src/src/tls-openssl.c
52+++ b/src/src/tls-openssl.c
53@@ -708,7 +708,7 @@ if ( (nid = OBJ_sn2nid (CCS exp_curve)) == NID_undef
54
55 if (!(ecdh = EC_KEY_new_by_curve_name(nid)))
56 {
57- tls_error("Unable to create ec curve", host, NULL);
58+ tls_error(US"Unable to create ec curve", host, NULL);
59 return FALSE;
60 }
61
62diff --git a/src/src/utf8.c b/src/src/utf8.c
63index a0ec003..8a7cf38 100644
64--- a/src/src/utf8.c
65+++ b/src/src/utf8.c
66@@ -127,7 +127,7 @@ if ((rc = punycode_decode(p_len, CCS alabel+4, &p_len, p, NULL)) != PUNYCODE_SUC
67 return NULL;
68 }
69
70-s = stringprep_ucs4_to_utf8(p, p_len, NULL, &p_len);
71+s = US stringprep_ucs4_to_utf8(p, p_len, NULL, &p_len);
72 res = string_copyn(s, p_len);
73 free(s);
74 return res;
75
76commit 5b881b5a8e0d7bc540f4b63cc9559d2cb1775965
77Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
78Date: Thu Jul 30 09:43:51 2015 +0200
79
80 Docs: Add a note about the maximum spam bar length
81
82diff --git a/src/src/spam.h b/src/src/spam.h
83index 05ab655..2fe7380 100644
84--- a/src/src/spam.h
85+++ b/src/src/spam.h
86@@ -12,7 +12,8 @@
87 /* timeout for reading and writing spamd */
88 #define SPAMD_TIMEOUT 120
89
90-/* maximum length of the spam bar */
91+/* maximum length of the spam bar, please update the
92+ * spec, the max length is mentioned there */
93 #define MAX_SPAM_BAR_CHARS 50
94
95 /* SHUT_WR seems to be undefined on Unixware ? */
96
97commit 98716abe2b636d275e866f3ad6374cb70bf6e504
98Author: Jeremy Harris <jgh146exb@wizmail.org>
99Date: Sun Aug 2 13:44:31 2015 +0100
100
101 Testsuite: Add testcase for OCSP-nonaware client, to supporting server. Bug 1664
102
103 The logfile here is for (I hope) the passing case, though the fixed GnuTLS library
104 is not yet available. Also due to the bug, client-gnutls is not usable for the
105 test; client-openssl must be used - meaning that a GnuTLS-only system cannot run
106 the testcase:
107
108 OCSP-GnuTLS/5650 OCSP stapling, server
109 ** Command 15 ("client-ssl", starting at line 98)
110 ** Return code 127 (expected 0)
111
112diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
113index 61ed0e8..e2ac17c 100644
114--- a/src/src/tls-gnu.c
115+++ b/src/src/tls-gnu.c
116@@ -842,7 +842,7 @@ if ( !host /* server */
117 gnutls_certificate_set_ocsp_status_request_function(state->x509_cred,
118 server_ocsp_stapling_cb, state->exp_tls_ocsp_file);
119
120- DEBUG(D_tls) debug_printf("Set OCSP response file %s\n", &state->exp_tls_ocsp_file);
121+ DEBUG(D_tls) debug_printf("OCSP response file = %s\n", state->exp_tls_ocsp_file);
122 }
123 #endif
124
125
126commit 9196d5bf543d75a81ae0825a352920d27241c325
127Author: Jeremy Harris <jgh146exb@wizmail.org>
128Date: Sun Aug 2 13:53:15 2015 +0100
129
130 GnuTLS: avoid using OCSP on buggy library versions. Bug 1664
131
132diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
133index e2ac17c..8aabc5c 100644
134--- a/src/src/tls-gnu.c
135+++ b/src/src/tls-gnu.c
136@@ -176,6 +176,8 @@ static const char * const exim_default_gnutls_priority = "NORMAL";
137
138 static BOOL exim_gnutls_base_init_done = FALSE;
139
140+static BOOL gnutls_buggy_ocsp = FALSE;
141+
142
143 /* ------------------------------------------------------------------------ */
144 /* macros */
145@@ -831,18 +833,25 @@ if ( !host /* server */
146 && tls_ocsp_file
147 )
148 {
149- if (!expand_check(tls_ocsp_file, US"tls_ocsp_file",
150- &state->exp_tls_ocsp_file))
151- return DEFER;
152+ if (gnutls_buggy_ocsp)
153+ {
154+ DEBUG(D_tls) debug_printf("GnuTLS library is buggy for OCSP; avoiding\n");
155+ }
156+ else
157+ {
158+ if (!expand_check(tls_ocsp_file, US"tls_ocsp_file",
159+ &state->exp_tls_ocsp_file))
160+ return DEFER;
161
162- /* Use the full callback method for stapling just to get observability.
163- More efficient would be to read the file once only, if it never changed
164- (due to SNI). Would need restart on file update, or watch datestamp. */
165+ /* Use the full callback method for stapling just to get observability.
166+ More efficient would be to read the file once only, if it never changed
167+ (due to SNI). Would need restart on file update, or watch datestamp. */
168
169- gnutls_certificate_set_ocsp_status_request_function(state->x509_cred,
170- server_ocsp_stapling_cb, state->exp_tls_ocsp_file);
171+ gnutls_certificate_set_ocsp_status_request_function(state->x509_cred,
172+ server_ocsp_stapling_cb, state->exp_tls_ocsp_file);
173
174- DEBUG(D_tls) debug_printf("OCSP response file = %s\n", state->exp_tls_ocsp_file);
175+ DEBUG(D_tls) debug_printf("OCSP response file = %s\n", state->exp_tls_ocsp_file);
176+ }
177 }
178 #endif
179
180@@ -1011,6 +1020,35 @@ return OK;
181 * Initialize for GnuTLS *
182 *************************************************/
183
184+
185+static BOOL
186+tls_is_buggy_ocsp(void)
187+{
188+const uschar * s;
189+uschar maj, mid, mic;
190+
191+s = CUS gnutls_check_version(NULL);
192+maj = atoi(CCS s);
193+if (maj == 3)
194+ {
195+ while (*s && *s != '.') s++;
196+ mid = atoi(CCS ++s);
197+ if (mid <= 2)
198+ return TRUE;
199+ else if (mid >= 5)
200+ return FALSE;
201+ else
202+ {
203+ while (*s && *s != '.') s++;
204+ mic = atoi(CCS ++s);
205+ return mic <= (mid == 3 ? 16 : 3);
206+ }
207+ }
208+return FALSE;
209+}
210+
211+
212+
213 /* Called from both server and client code. In the case of a server, errors
214 before actual TLS negotiation return DEFER.
215
216@@ -1074,6 +1112,9 @@ if (!exim_gnutls_base_init_done)
217 }
218 #endif
219
220+ if ((gnutls_buggy_ocsp = tls_is_buggy_ocsp()))
221+ log_write(0, LOG_MAIN, "OCSP unusable with this GnuTLS library version");
222+
223 exim_gnutls_base_init_done = TRUE;
224 }
225
226
227commit 63f0dbe0ca0aba7be3bc8807f45c8703a1cfafe1
228Author: Jeremy Harris <jgh146exb@wizmail.org>
229Date: Thu Aug 6 21:38:33 2015 +0100
230
231 OpenSSL: fix complile on pre-EC-capable library versions
232
233diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
234index d8377fd..b1dccb8 100644
235--- a/src/src/tls-openssl.c
236+++ b/src/src/tls-openssl.c
237@@ -659,15 +659,15 @@ Returns: TRUE if OK (nothing to set up, or setup worked)
238 static BOOL
239 init_ecdh(SSL_CTX * sctx, host_item * host)
240 {
241+#ifdef OPENSSL_NO_ECDH
242+return TRUE;
243+#else
244+
245 EC_KEY * ecdh;
246 uschar * exp_curve;
247 int nid;
248 BOOL rv;
249
250-#ifdef OPENSSL_NO_ECDH
251-return TRUE;
252-#else
253-
254 if (host) /* No ECDH setup for clients, only for servers */
255 return TRUE;
256
257
258commit 755762fd4c420cabbcba4a9c79947e926fa82219
259Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
260Date: Sun Aug 9 23:29:44 2015 +0200
261
262 Compiler quietening
263
264diff --git a/src/src/malware.c b/src/src/malware.c
265index 141c6ea..96af1e8 100644
266--- a/src/src/malware.c
267+++ b/src/src/malware.c
268@@ -886,7 +886,7 @@ if (!malware_ok)
269 string_sprintf("unable to read result (%s)", strerror(errno)),
270 sock);
271
272- for (p[bread] = '\0'; q = Ustrchr(p, '\n'); p = q+1)
273+ for (p[bread] = '\0'; (q = Ustrchr(p, '\n')); p = q+1)
274 {
275 *q = '\0';
276
277@@ -1880,6 +1880,9 @@ if (!malware_ok)
278
279 /* here for any unexpected response from the scanner */
280 goto endloop;
281+
282+ case AVA_DONE: log_write(0, LOG_PANIC, "%s:%d:%s: should not happen",
283+ __FILE__, __LINE__, __FUNCTION__);
284 }
285 }
286 }
287diff --git a/src/src/spam.c b/src/src/spam.c
288index ca8d207..457aa3a 100644
289--- a/src/src/spam.c
290+++ b/src/src/spam.c
291@@ -297,7 +297,7 @@ start = time(NULL);
292 sd = (spamd_address_container *)store_get(sizeof(spamd_address_container));
293
294 for (sublist = address, args = 0, spamd_param_init(sd);
295- s = string_nextinlist(&sublist, &sublist_sep, NULL, 0);
296+ (s = string_nextinlist(&sublist, &sublist_sep, NULL, 0));
297 args++
298 )
299 {
300diff --git a/src/src/tlscert-openssl.c b/src/src/tlscert-openssl.c
301index 72808a7..19db040 100644
302--- a/src/src/tlscert-openssl.c
303+++ b/src/src/tlscert-openssl.c
304@@ -127,7 +127,7 @@ else
305 {
306 struct tm tm;
307 struct tm * tm_p = &tm;
308- BOOL mod_tz;
309+ BOOL mod_tz = TRUE;
310 uschar * tz = to_tz(US"GMT0"); /* need to call strptime with baseline TZ */
311
312 /* Parse OpenSSL ASN1_TIME_print output. A shame there seems to
313@@ -164,7 +164,7 @@ else
314 }
315 }
316
317- if (mod_tz);
318+ if (mod_tz)
319 restore_tz(tz);
320 }
321 BIO_free(bp);
322
323commit 4bd6107db73131e1b48f1902833fd7c637c08bda
324Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
325Date: Mon Aug 10 00:39:36 2015 +0200
326
327 Really re-select() when interrupted.
328
329diff --git a/src/src/ip.c b/src/src/ip.c
330index ead7299..cb54f16 100644
331--- a/src/src/ip.c
332+++ b/src/src/ip.c
333@@ -499,7 +499,7 @@ do
334
335 /* If the socket is ready, break out of the loop. */
336 }
337-while (!FD_ISSET(fd, &select_inset));
338+while (rc < 0 || !FD_ISSET(fd, &select_inset));
339 return TRUE;
340 }
341
342
343commit 505d976aa23de4294751162dee6466e335c96fbf
344Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
345Date: Tue Aug 11 09:13:11 2015 +0200
346
347 Build: Make test_{os,parse,dbfn,string} work
348
349diff --git a/src/OS/Makefile-Base b/src/OS/Makefile-Base
350index 1d5a5f6..95110e6 100644
351--- a/src/OS/Makefile-Base
352+++ b/src/OS/Makefile-Base
353@@ -743,11 +743,11 @@ sa-os.o: $(HDRS) os.c
354 # These are the test targets themselves
355
356 test_dbfn: config.h dbfn.c dummies.o sa-globals.o sa-os.o store.o \
357- string.o tod.o version.o
358+ string.o tod.o version.o utf8.o
359 $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE dbfn.c
360 $(LNCC) -o test_dbfn $(LFLAGS) dbfn.o \
361 dummies.o sa-globals.o sa-os.o store.o string.o \
362- tod.o version.o $(LIBS) $(DBMLIB)
363+ tod.o version.o utf8.o $(LIBS) $(DBMLIB) $(LDFLAGS)
364 rm -f dbfn.o
365
366 test_host: config.h child.c host.c dns.c dummies.c sa-globals.o os.o \
367@@ -761,23 +761,24 @@ test_host: config.h child.c host.c dns.c dummies.c sa-globals.o os.o \
368 tod.o tree.o $(LIBS) $(LIBRESOLV)
369 rm -f child.o dummies.o host.o dns.o
370
371-test_os: os.h os.c dummies.o sa-globals.o store.o string.o tod.o
372+test_os: os.h os.c dummies.o sa-globals.o store.o string.o tod.o utf8.o
373 $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE os.c
374 $(LNCC) -o test_os $(LFLAGS) os.o dummies.o \
375- sa-globals.o store.o string.o tod.o $(LIBS)
376+ sa-globals.o store.o string.o tod.o utf8.o $(LIBS) $(LDFLAGS)
377 rm -f os.o
378
379 test_parse: config.h parse.c dummies.o sa-globals.o \
380- store.o string.o tod.o version.o
381+ store.o string.o tod.o version.o utf8.o
382 $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE parse.c
383 $(LNCC) -o test_parse $(LFLAGS) parse.o \
384- dummies.o sa-globals.o store.o string.o tod.o version.o
385+ dummies.o sa-globals.o store.o string.o tod.o version.o \
386+ utf8.o $(LDFLAGS)
387 rm -f parse.o
388
389-test_string: config.h string.c dummies.o sa-globals.o store.o tod.o
390+test_string: config.h string.c dummies.o sa-globals.o store.o tod.o utf8.o
391 $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE string.c
392 $(LNCC) -o test_string $(LFLAGS) -DSTAND_ALONE string.o \
393- dummies.o sa-globals.o store.o tod.o $(LIBS)
394+ dummies.o sa-globals.o store.o tod.o utf8.o $(LIBS) $(LDFLAGS)
395 rm -f string.o
396
397 # End
398diff --git a/src/src/host.c b/src/src/host.c
399index 94126d4..31c2bbf 100644
400--- a/src/src/host.c
401+++ b/src/src/host.c
402@@ -3212,7 +3212,7 @@ while (Ufgets(buffer, 256, stdin) != NULL)
403 else
404 {
405 int flags = whichrrs;
406- dnssec d;
407+ dnssec_domains d;
408
409 h.name = buffer;
410 h.next = NULL;
411
412commit 2ef7ed082481b2dccd3c2e0eae849b24bf0b172a
413Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
414Date: Tue Aug 11 17:36:29 2015 +0200
415
416 Fix ESMTP MAIL command option processing
417
418 If the address containes spaces, the option processing
419 was confused.
420
421diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
422index 711ee86..effc636 100644
423--- a/src/src/smtp_in.c
424+++ b/src/src/smtp_in.c
425@@ -9,6 +9,7 @@
426
427
428 #include "exim.h"
429+#include <assert.h>
430
431
432 /* Initialize for TCP wrappers if so configured. It appears that the macro
433@@ -232,6 +233,7 @@ static uschar *protocols[] = {
434
435 /* Sanity check and validate optional args to MAIL FROM: envelope */
436 enum {
437+ ENV_MAIL_OPT_NULL,
438 ENV_MAIL_OPT_SIZE, ENV_MAIL_OPT_BODY, ENV_MAIL_OPT_AUTH,
439 #ifndef DISABLE_PRDR
440 ENV_MAIL_OPT_PRDR,
441@@ -240,7 +242,6 @@ enum {
442 #ifdef EXPERIMENTAL_INTERNATIONAL
443 ENV_MAIL_OPT_UTF8,
444 #endif
445- ENV_MAIL_OPT_NULL
446 };
447 typedef struct {
448 uschar * name; /* option requested during MAIL cmd */
449@@ -260,7 +261,8 @@ static env_mail_type_t env_mail_type_list[] = {
450 #ifdef EXPERIMENTAL_INTERNATIONAL
451 { US"SMTPUTF8",ENV_MAIL_OPT_UTF8, FALSE }, /* rfc6531 */
452 #endif
453- { US"NULL", ENV_MAIL_OPT_NULL, FALSE }
454+ /* keep this the last entry */
455+ { US"NULL", ENV_MAIL_OPT_NULL, FALSE },
456 };
457
458 /* When reading SMTP from a remote host, we have to use our own versions of the
459@@ -3887,7 +3889,7 @@ while (done <= 0)
460 if (!extract_option(&name, &value)) break;
461
462 for (mail_args = env_mail_type_list;
463- (char *)mail_args < (char *)env_mail_type_list + sizeof(env_mail_type_list);
464+ mail_args->value != ENV_MAIL_OPT_NULL;
465 mail_args++
466 )
467 if (strcmpic(name, mail_args->name) == 0)
468@@ -4066,15 +4068,17 @@ while (done <= 0)
469 }
470 break;
471 #endif
472- /* Unknown option. Stick back the terminator characters and break
473+ /* No valid option. Stick back the terminator characters and break
474 the loop. Do the name-terminator second as extract_option sets
475- value==name when it found no equal-sign.
476- An error for a malformed address will occur. */
477- default:
478+ value==name when it found no equal-sign.
479+ An error for a malformed address will occur. */
480+ case ENV_MAIL_OPT_NULL:
481 value[-1] = '=';
482 name[-1] = ' ';
483 arg_error = TRUE;
484 break;
485+
486+ default: assert(0);
487 }
488 /* Break out of for loop if switch() had bad argument or
489 when start of the email address is reached */
490
491commit 4fb7df6d044a39151e72346ac0d67ac09686f704
492Author: Jeremy Harris <jgh146exb@wizmail.org>
493Date: Tue Aug 11 22:54:53 2015 +0100
494
495 GnuTLS: avoid whining about OCSP when not requested by config
496
497diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
498index 8aabc5c..fe18094 100644
499--- a/src/src/tls-gnu.c
500+++ b/src/src/tls-gnu.c
501@@ -176,7 +176,9 @@ static const char * const exim_default_gnutls_priority = "NORMAL";
502
503 static BOOL exim_gnutls_base_init_done = FALSE;
504
505+#ifndef DISABLE_OCSP
506 static BOOL gnutls_buggy_ocsp = FALSE;
507+#endif
508
509
510 /* ------------------------------------------------------------------------ */
511@@ -1021,6 +1023,8 @@ return OK;
512 *************************************************/
513
514
515+#ifndef DISABLE_OCSP
516+
517 static BOOL
518 tls_is_buggy_ocsp(void)
519 {
520@@ -1047,6 +1051,7 @@ if (maj == 3)
521 return FALSE;
522 }
523
524+#endif
525
526
527 /* Called from both server and client code. In the case of a server, errors
528@@ -1112,8 +1117,10 @@ if (!exim_gnutls_base_init_done)
529 }
530 #endif
531
532- if ((gnutls_buggy_ocsp = tls_is_buggy_ocsp()))
533+#ifndef DISABLE_OCSP
534+ if (tls_ocsp_file && (gnutls_buggy_ocsp = tls_is_buggy_ocsp()))
535 log_write(0, LOG_MAIN, "OCSP unusable with this GnuTLS library version");
536+#endif
537
538 exim_gnutls_base_init_done = TRUE;
539 }
540
541commit c528cec4dbfdb6e367a6ac0ed72e2e768a9c4392
542Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
543Date: Wed Aug 12 23:45:44 2015 +0200
544
545 Adjust the timeout after interrupted select()
546
547diff --git a/src/src/ip.c b/src/src/ip.c
548index cb54f16..7991a58 100644
549--- a/src/src/ip.c
550+++ b/src/src/ip.c
551@@ -451,8 +451,8 @@ BOOL
552 fd_ready(int fd, int timeout)
553 {
554 fd_set select_inset;
555-struct timeval tv;
556 time_t start_recv = time(NULL);
557+int time_left = timeout;
558 int rc;
559
560 if (timeout <= 0)
561@@ -464,10 +464,9 @@ if (timeout <= 0)
562
563 do
564 {
565+ struct timeval tv = { time_left, 0 };
566 FD_ZERO (&select_inset);
567 FD_SET (fd, &select_inset);
568- tv.tv_sec = timeout;
569- tv.tv_usec = 0;
570
571 /*DEBUG(D_transport) debug_printf("waiting for data on fd\n");*/
572 rc = select(fd + 1, (SELECT_ARG2_TYPE *)&select_inset, NULL, NULL, &tv);
573@@ -479,25 +478,24 @@ do
574 Aug 2004: Somebody set up a cron job that ran exiwhat every 2 minutes, making
575 the interrupt not at all rare. Since the timeout is typically more than 2
576 minutes, the effect was to block the timeout completely. To prevent this
577- happening again, we do an explicit time test. */
578+ happening again, we do an explicit time test and adjust the timeout
579+ accordingly */
580
581 if (rc < 0 && errno == EINTR)
582 {
583 DEBUG(D_transport) debug_printf("EINTR while waiting for socket data\n");
584- if (time(NULL) - start_recv < timeout) continue;
585- DEBUG(D_transport) debug_printf("total wait time exceeds timeout\n");
586+ /* Watch out, 'continue' jumps to the condition, not to the loops top */
587+ if (time_left = timeout - (time(NULL) - start_recv)) continue;
588 }
589
590- /* Handle a timeout, and treat any other select error as a timeout, including
591- an EINTR when we have been in this loop for longer than timeout. */
592-
593 if (rc <= 0)
594 {
595 errno = ETIMEDOUT;
596 return FALSE;
597 }
598
599- /* If the socket is ready, break out of the loop. */
600+ /* Checking the FD_ISSET is not enough, if we're interrupted, the
601+ select_inset may still contain the 'input'. */
602 }
603 while (rc < 0 || !FD_ISSET(fd, &select_inset));
604 return TRUE;
605
606commit 85ff3cf9f3ab78c4dfa9f9ff34d27e6fe8f73c39
607Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
608Date: Thu Aug 13 00:20:12 2015 +0200
609
610 Fix timeout adjustment in c528cec4
611
612diff --git a/src/src/ip.c b/src/src/ip.c
613index 7991a58..2d71705 100644
614--- a/src/src/ip.c
615+++ b/src/src/ip.c
616@@ -455,7 +455,7 @@ time_t start_recv = time(NULL);
617 int time_left = timeout;
618 int rc;
619
620-if (timeout <= 0)
621+if (time_left <= 0)
622 {
623 errno = ETIMEDOUT;
624 return FALSE;
625@@ -484,8 +484,10 @@ do
626 if (rc < 0 && errno == EINTR)
627 {
628 DEBUG(D_transport) debug_printf("EINTR while waiting for socket data\n");
629+
630 /* Watch out, 'continue' jumps to the condition, not to the loops top */
631- if (time_left = timeout - (time(NULL) - start_recv)) continue;
632+ time_left = timeout - (time(NULL) - start_recv);
633+ if (time_left > 0) continue;
634 }
635
636 if (rc <= 0)
637
638commit 6c6d6e483411af2c087ff258f4041d38eb65e775
639Author: Tony Finch <dot@dotat.at>
640Date: Thu Aug 13 15:16:48 2015 +0100
641
642 Overhaul the debug_selector and log_selector machinery to support variable-length bit vectors. No functional change.
643
644diff --git a/src/src/acl.c b/src/src/acl.c
645index 91ee571..f2e0ef2 100644
646--- a/src/src/acl.c
647+++ b/src/src/acl.c
648@@ -4287,7 +4287,7 @@ while (acl != NULL)
649 case ACL_WARN:
650 if (cond == OK)
651 acl_warn(where, *user_msgptr, *log_msgptr);
652- else if (cond == DEFER && (log_extra_selector & LX_acl_warn_skipped) != 0)
653+ else if (cond == DEFER && LOGGING(acl_warn_skipped))
654 log_write(0, LOG_MAIN, "%s Warning: ACL \"warn\" statement skipped: "
655 "condition test deferred%s%s", host_and_ident(TRUE),
656 (*log_msgptr == NULL)? US"" : US": ",
657diff --git a/src/src/daemon.c b/src/src/daemon.c
658index 894a96f..2d10387 100644
659--- a/src/src/daemon.c
660+++ b/src/src/daemon.c
661@@ -145,7 +145,7 @@ int dup_accept_socket = -1;
662 int max_for_this_host = 0;
663 int wfsize = 0;
664 int wfptr = 0;
665-int use_log_write_selector = log_write_selector;
666+int save_log_selector = *log_selector;
667 uschar *whofrom = NULL;
668
669 void *reset_point = store_get(0);
670@@ -206,11 +206,11 @@ memory is reclaimed. */
671
672 whofrom = string_append(whofrom, &wfsize, &wfptr, 3, "[", sender_host_address, "]");
673
674-if ((log_extra_selector & LX_incoming_port) != 0)
675+if (LOGGING(incoming_port))
676 whofrom = string_append(whofrom, &wfsize, &wfptr, 2, ":", string_sprintf("%d",
677 sender_host_port));
678
679-if ((log_extra_selector & LX_incoming_interface) != 0)
680+if (LOGGING(incoming_interface))
681 whofrom = string_append(whofrom, &wfsize, &wfptr, 4, " I=[",
682 interface_address, "]:", string_sprintf("%d", interface_port));
683
684@@ -338,11 +338,11 @@ the generalized logging code each time when the selector is false. If the
685 selector is set, check whether the host is on the list for logging. If not,
686 arrange to unset the selector in the subprocess. */
687
688-if ((log_write_selector & L_smtp_connection) != 0)
689+if (LOGGING(smtp_connection))
690 {
691 uschar *list = hosts_connection_nolog;
692 if (list != NULL && verify_check_host(&list) == OK)
693- use_log_write_selector &= ~L_smtp_connection;
694+ save_log_selector &= ~L_smtp_connection;
695 else
696 log_write(L_smtp_connection, LOG_MAIN, "SMTP connection from %s "
697 "(TCP/IP connection count = %d)", whofrom, smtp_accept_count + 1);
698@@ -372,7 +372,7 @@ if (pid == 0)
699
700 /* May have been modified for the subprocess */
701
702- log_write_selector = use_log_write_selector;
703+ *log_selector = save_log_selector;
704
705 /* Get the local interface address into permanent store */
706
707diff --git a/src/src/deliver.c b/src/src/deliver.c
708index 78f8f4b..c796de0 100644
709--- a/src/src/deliver.c
710+++ b/src/src/deliver.c
711@@ -682,7 +682,7 @@ d_hostlog(uschar * s, int * sizep, int * ptrp, address_item * addr)
712 {
713 s = string_append(s, sizep, ptrp, 5, US" H=", addr->host_used->name,
714 US" [", addr->host_used->address, US"]");
715- if ((log_extra_selector & LX_outgoing_port) != 0)
716+ if (LOGGING(outgoing_port))
717 s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d",
718 addr->host_used->port));
719 return s;
720@@ -692,10 +692,9 @@ d_hostlog(uschar * s, int * sizep, int * ptrp, address_item * addr)
721 static uschar *
722 d_tlslog(uschar * s, int * sizep, int * ptrp, address_item * addr)
723 {
724- if ((log_extra_selector & LX_tls_cipher) != 0 && addr->cipher != NULL)
725+ if (LOGGING(tls_cipher) && addr->cipher != NULL)
726 s = string_append(s, sizep, ptrp, 2, US" X=", addr->cipher);
727- if ((log_extra_selector & LX_tls_certificate_verified) != 0 &&
728- addr->cipher != NULL)
729+ if (LOGGING(tls_certificate_verified) && addr->cipher != NULL)
730 s = string_append(s, sizep, ptrp, 2, US" CV=",
731 testflag(addr, af_cert_verified)
732 ?
733@@ -706,7 +705,7 @@ d_tlslog(uschar * s, int * sizep, int * ptrp, address_item * addr)
734 #endif
735 "yes"
736 : "no");
737- if ((log_extra_selector & LX_tls_peerdn) != 0 && addr->peerdn != NULL)
738+ if (LOGGING(tls_peerdn) && addr->peerdn != NULL)
739 s = string_append(s, sizep, ptrp, 3, US" DN=\"",
740 string_printing(addr->peerdn), US"\"");
741 return s;
742@@ -808,7 +807,7 @@ pointer to a single host item in their host list, for use by the transport. */
743
744 s = reset_point = store_get(size);
745
746-log_address = string_log_address(addr, (log_write_selector & L_all_parents) != 0, TRUE);
747+log_address = string_log_address(addr, LOGGING(all_parents), TRUE);
748 if (msg)
749 s = string_append(s, &size, &ptr, 3, host_and_ident(TRUE), US" ", log_address);
750 else
751@@ -817,11 +816,11 @@ else
752 s = string_append(s, &size, &ptr, 2, US"> ", log_address);
753 }
754
755-if (log_extra_selector & LX_incoming_interface && sending_ip_address)
756+if (LOGGING(incoming_interface) && sending_ip_address)
757 s = string_append(s, &size, &ptr, 3, US" I=[", sending_ip_address, US"]");
758 /* for the port: string_sprintf("%d", sending_port) */
759
760-if ((log_extra_selector & LX_sender_on_delivery) != 0 || msg)
761+if (LOGGING(sender_on_delivery) || msg)
762 s = string_append(s, &size, &ptr, 3, US" F=<",
763 #ifdef EXPERIMENTAL_INTERNATIONAL
764 testflag(addr, af_utf8_downcvt)
765@@ -841,8 +840,7 @@ delivery; indeed, I did for some time, until this statement crashed. The case
766 when it is not set is for a delivery to /dev/null which is optimised by not
767 being run at all. */
768
769-if (used_return_path != NULL &&
770- (log_extra_selector & LX_return_path_on_delivery) != 0)
771+if (used_return_path != NULL && LOGGING(return_path_on_delivery))
772 s = string_append(s, &size, &ptr, 3, US" P=<", used_return_path, US">");
773
774 if (msg)
775@@ -854,7 +852,7 @@ if (addr->router != NULL)
776
777 s = string_append(s, &size, &ptr, 2, US" T=", addr->transport->name);
778
779-if ((log_extra_selector & LX_delivery_size) != 0)
780+if (LOGGING(delivery_size))
781 s = string_append(s, &size, &ptr, 2, US" S=",
782 string_sprintf("%d", transport_count));
783
784@@ -901,7 +899,7 @@ else
785 if (addr->auth_id)
786 {
787 s = string_append(s, &size, &ptr, 2, US":", addr->auth_id);
788- if (log_extra_selector & LX_smtp_mailauth && addr->auth_sndr)
789+ if (LOGGING(smtp_mailauth) && addr->auth_sndr)
790 s = string_append(s, &size, &ptr, 2, US":", addr->auth_sndr);
791 }
792 }
793@@ -914,8 +912,7 @@ else
794
795 /* confirmation message (SMTP (host_used) and LMTP (driver_name)) */
796
797-if (log_extra_selector & LX_smtp_confirmation &&
798- addr->message &&
799+if (LOGGING(smtp_confirmation) && addr->message &&
800 (addr->host_used || Ustrcmp(addr->transport->driver_name, "lmtp") == 0))
801 {
802 unsigned i;
803@@ -935,11 +932,11 @@ if (log_extra_selector & LX_smtp_confirmation &&
804
805 /* Time on queue and actual time taken to deliver */
806
807-if ((log_extra_selector & LX_queue_time) != 0)
808+if (LOGGING(queue_time))
809 s = string_append(s, &size, &ptr, 2, US" QT=",
810 readconf_printtime( (int) ((long)time(NULL) - (long)received_time)) );
811
812-if ((log_extra_selector & LX_deliver_time) != 0)
813+if (LOGGING(deliver_time))
814 s = string_append(s, &size, &ptr, 2, US" DT=",
815 readconf_printtime(addr->more_errno));
816
817@@ -1230,8 +1227,7 @@ else if (result == DEFER || result == PANIC)
818 /* Create the address string for logging. Must not do this earlier, because
819 an OK result may be changed to FAIL when a pipe returns text. */
820
821- log_address = string_log_address(addr,
822- (log_write_selector & L_all_parents) != 0, result == OK);
823+ log_address = string_log_address(addr, LOGGING(all_parents), result == OK);
824
825 s = string_cat(s, &size, &ptr, log_address, Ustrlen(log_address));
826
827@@ -1342,18 +1338,16 @@ else
828 /* Create the address string for logging. Must not do this earlier, because
829 an OK result may be changed to FAIL when a pipe returns text. */
830
831- log_address = string_log_address(addr,
832- (log_write_selector & L_all_parents) != 0, result == OK);
833+ log_address = string_log_address(addr, LOGGING(all_parents), result == OK);
834
835 s = string_cat(s, &size, &ptr, log_address, Ustrlen(log_address));
836
837- if ((log_extra_selector & LX_sender_on_delivery) != 0)
838+ if (LOGGING(sender_on_delivery))
839 s = string_append(s, &size, &ptr, 3, US" F=<", sender_address, US">");
840
841 /* Return path may not be set if no delivery actually happened */
842
843- if (used_return_path != NULL &&
844- (log_extra_selector & LX_return_path_on_delivery) != 0)
845+ if (used_return_path != NULL && LOGGING(return_path_on_delivery))
846 s = string_append(s, &size, &ptr, 3, US" P=<", used_return_path, US">");
847
848 if (addr->router != NULL)
849@@ -4449,7 +4443,7 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++)
850 }
851
852 /* Local interface address/port */
853- if (log_extra_selector & LX_incoming_interface && sending_ip_address)
854+ if (LOGGING(incoming_interface) && sending_ip_address)
855 {
856 uschar * ptr = big_buffer;
857 sprintf(CS ptr, "%.128s", sending_ip_address);
858@@ -7365,7 +7359,7 @@ if (addr_defer == NULL)
859
860 /* Log the end of this message, with queue time if requested. */
861
862- if ((log_extra_selector & LX_queue_time_overall) != 0)
863+ if (LOGGING(queue_time_overall))
864 log_write(0, LOG_MAIN, "Completed QT=%s",
865 readconf_printtime( (int) ((long)time(NULL) - (long)received_time)) );
866 else
867diff --git a/src/src/exim.c b/src/src/exim.c
868index f9d57ab..d7cb5d8 100644
869--- a/src/src/exim.c
870+++ b/src/src/exim.c
871@@ -1639,6 +1639,10 @@ if (log_buffer == NULL)
872 exit(EXIT_FAILURE);
873 }
874
875+/* Initialize the default log options. */
876+
877+bits_set(log_selector, log_selector_size, log_default);
878+
879 /* Set log_stderr to stderr, provided that stderr exists. This gets reset to
880 NULL when the daemon is run and the file is closed. We have to use this
881 indirection, because some systems don't allow writing to the variable "stderr".
882@@ -2451,8 +2455,8 @@ for (i = 1; i < argc; i++)
883 argrest++;
884 }
885 if (*argrest != 0)
886- decode_bits(&selector, NULL, D_memory, 0, argrest, debug_options,
887- debug_options_count, US"debug", 0);
888+ decode_bits(&selector, 1, debug_notall, argrest,
889+ debug_options, debug_options_count, US"debug", 0);
890 debug_selector = selector;
891 }
892 break;
893@@ -3787,14 +3791,17 @@ else
894
895 /* Handle the decoding of logging options. */
896
897-decode_bits(&log_write_selector, &log_extra_selector, 0, 0,
898+decode_bits(log_selector, log_selector_size, log_notall,
899 log_selector_string, log_options, log_options_count, US"log", 0);
900
901 DEBUG(D_any)
902 {
903+ int i;
904 debug_printf("configuration file is %s\n", config_main_filename);
905- debug_printf("log selectors = %08x %08x\n", log_write_selector,
906- log_extra_selector);
907+ debug_printf("log selectors =");
908+ for (i = 0; i < log_selector_size; i++)
909+ debug_printf(" %08x", log_selector[i]);
910+ debug_printf("\n");
911 }
912
913 /* If domain literals are not allowed, check the sender address that was
914@@ -4001,7 +4008,7 @@ a debugging feature for finding out what arguments certain MUAs actually use.
915 Don't attempt it if logging is disabled, or if listing variables or if
916 verifying/testing addresses or expansions. */
917
918-if (((debug_selector & D_any) != 0 || (log_extra_selector & LX_arguments) != 0)
919+if (((debug_selector & D_any) != 0 || LOGGING(arguments))
920 && really_exim && !list_options && !checking)
921 {
922 int i;
923@@ -4036,7 +4043,7 @@ if (((debug_selector & D_any) != 0 || (log_extra_selector & LX_arguments) != 0)
924 while (*p) p++;
925 }
926
927- if ((log_extra_selector & LX_arguments) != 0)
928+ if (LOGGING(arguments))
929 log_write(0, LOG_MAIN, "%s", big_buffer);
930 else
931 debug_printf("%s\n", big_buffer);
932@@ -5021,7 +5028,7 @@ if (host_checking)
933 sender_host_address);
934
935 if (verify_check_host(&hosts_connection_nolog) == OK)
936- log_write_selector &= ~L_smtp_connection;
937+ BIT_CLEAR(log_selector, log_selector_size, Li_smtp_connection);
938 log_write(L_smtp_connection, LOG_MAIN, "%s", smtp_get_connection_info());
939
940 /* NOTE: We do *not* call smtp_log_no_mail() if smtp_start_session() fails,
941@@ -5195,7 +5202,7 @@ if (smtp_input)
942 smtp_in = stdin;
943 smtp_out = stdout;
944 if (verify_check_host(&hosts_connection_nolog) == OK)
945- log_write_selector &= ~L_smtp_connection;
946+ BIT_CLEAR(log_selector, log_selector_size, Li_smtp_connection);
947 log_write(L_smtp_connection, LOG_MAIN, "%s", smtp_get_connection_info());
948 if (!smtp_start_session())
949 {
950diff --git a/src/src/functions.h b/src/src/functions.h
951index 0257904..4af0017 100644
952--- a/src/src/functions.h
953+++ b/src/src/functions.h
954@@ -99,6 +99,9 @@ extern int auth_get_no64_data(uschar **, uschar *);
955 extern uschar *auth_xtextencode(uschar *, int);
956 extern int auth_xtextdecode(uschar *, uschar **);
957
958+extern void bits_clear(unsigned int *, size_t, int *);
959+extern void bits_set(unsigned int *, size_t, int *);
960+
961 extern void cancel_cutthrough_connection(const char *);
962 extern int check_host(void *, const uschar *, const uschar **, uschar **);
963 extern uschar **child_exec_exim(int, BOOL, int *, BOOL, int, ...);
964@@ -123,8 +126,8 @@ extern void debug_print_ids(uschar *);
965 extern void debug_print_string(uschar *);
966 extern void debug_print_tree(tree_node *);
967 extern void debug_vprintf(const char *, va_list);
968-extern void decode_bits(unsigned int *, unsigned int *,
969- int, int, uschar *, bit_table *, int, uschar *, int);
970+extern void decode_bits(unsigned int *, size_t, int *,
971+ uschar *, bit_table *, int, uschar *, int);
972 extern address_item *deliver_make_addr(uschar *, BOOL);
973 extern void deliver_init(void);
974 extern void delivery_log(int, address_item *, int, uschar *);
975diff --git a/src/src/globals.c b/src/src/globals.c
976index 66baffe..1344b5a 100644
977--- a/src/src/globals.c
978+++ b/src/src/globals.c
979@@ -536,40 +536,45 @@ uschar *dccifd_options = US"header";
980 BOOL debug_daemon = FALSE;
981 int debug_fd = -1;
982 FILE *debug_file = NULL;
983-bit_table debug_options[] = {
984- { US"acl", D_acl },
985- { US"all", D_all },
986- { US"auth", D_auth },
987- { US"deliver", D_deliver },
988- { US"dns", D_dns },
989- { US"dnsbl", D_dnsbl },
990- { US"exec", D_exec },
991- { US"expand", D_expand },
992- { US"filter", D_filter },
993- { US"hints_lookup", D_hints_lookup },
994- { US"host_lookup", D_host_lookup },
995- { US"ident", D_ident },
996- { US"interface", D_interface },
997- { US"lists", D_lists },
998- { US"load", D_load },
999- { US"local_scan", D_local_scan },
1000- { US"lookup", D_lookup },
1001- { US"memory", D_memory },
1002- { US"pid", D_pid },
1003- { US"process_info", D_process_info },
1004- { US"queue_run", D_queue_run },
1005- { US"receive", D_receive },
1006- { US"resolver", D_resolver },
1007- { US"retry", D_retry },
1008- { US"rewrite", D_rewrite },
1009- { US"route", D_route },
1010- { US"timestamp", D_timestamp },
1011- { US"tls", D_tls },
1012- { US"transport", D_transport },
1013- { US"uid", D_uid },
1014- { US"verify", D_verify }
1015+int debug_notall[] = {
1016+ Di_memory,
1017+ -1
1018 };
1019-int debug_options_count = sizeof(debug_options)/sizeof(bit_table);
1020+bit_table debug_options[] = { /* must be in alphabetical order */
1021+ BIT_TABLE(D, acl),
1022+ BIT_TABLE(D, all),
1023+ BIT_TABLE(D, auth),
1024+ BIT_TABLE(D, deliver),
1025+ BIT_TABLE(D, dns),
1026+ BIT_TABLE(D, dnsbl),
1027+ BIT_TABLE(D, exec),
1028+ BIT_TABLE(D, expand),
1029+ BIT_TABLE(D, filter),
1030+ BIT_TABLE(D, hints_lookup),
1031+ BIT_TABLE(D, host_lookup),
1032+ BIT_TABLE(D, ident),
1033+ BIT_TABLE(D, interface),
1034+ BIT_TABLE(D, lists),
1035+ BIT_TABLE(D, load),
1036+ BIT_TABLE(D, local_scan),
1037+ BIT_TABLE(D, lookup),
1038+ BIT_TABLE(D, memory),
1039+ BIT_TABLE(D, pid),
1040+ BIT_TABLE(D, process_info),
1041+ BIT_TABLE(D, queue_run),
1042+ BIT_TABLE(D, receive),
1043+ BIT_TABLE(D, resolver),
1044+ BIT_TABLE(D, retry),
1045+ BIT_TABLE(D, rewrite),
1046+ BIT_TABLE(D, route),
1047+ BIT_TABLE(D, timestamp),
1048+ BIT_TABLE(D, tls),
1049+ BIT_TABLE(D, transport),
1050+ BIT_TABLE(D, uid),
1051+ BIT_TABLE(D, verify),
1052+};
1053+int debug_options_count = nelem(debug_options);
1054+
1055 unsigned int debug_selector = 0;
1056 int delay_warning[DELAY_WARNING_SIZE] = { DELAY_WARNING_SIZE, 1, 24*60*60 };
1057 uschar *delay_warning_condition=
1058@@ -813,78 +818,91 @@ uid_t local_user_uid = (uid_t)(-1);
1059 tree_node *localpartlist_anchor= NULL;
1060 int localpartlist_count = 0;
1061 uschar *log_buffer = NULL;
1062-unsigned int log_extra_selector = LX_default;
1063+
1064+int log_default[] = { /* for initializing log_selector */
1065+ Li_acl_warn_skipped,
1066+ Li_connection_reject,
1067+ Li_delay_delivery,
1068+ Li_dnslist_defer,
1069+ Li_etrn,
1070+ Li_host_lookup_failed,
1071+ Li_lost_incoming_connection,
1072+ Li_queue_run,
1073+ Li_rejected_header,
1074+ Li_retry_defer,
1075+ Li_sender_verify_fail,
1076+ Li_size_reject,
1077+ Li_skip_delivery,
1078+ Li_smtp_confirmation,
1079+ Li_tls_certificate_verified,
1080+ Li_tls_cipher,
1081+ -1
1082+};
1083+
1084 uschar *log_file_path = US LOG_FILE_PATH
1085 "\0<--------------Space to patch log_file_path->";
1086
1087-/* Those log options with L_xxx identifiers have values less than 0x800000 and
1088-are the ones that get put into log_write_selector. They can be used in calls to
1089-log_write() to test for the bit. The options with LX_xxx identifiers have
1090-values greater than 0x80000000 and are put into log_extra_selector (without the
1091-top bit). They are never used in calls to log_write(), but are tested
1092-independently. This separation became necessary when the number of log
1093-selectors was getting close to filling a 32-bit word. */
1094-
1095-/* Note that this list must be in alphabetical order. */
1096-
1097-bit_table log_options[] = {
1098- { US"8bitmime", LX_8bitmime },
1099- { US"acl_warn_skipped", LX_acl_warn_skipped },
1100- { US"address_rewrite", L_address_rewrite },
1101- { US"all", L_all },
1102- { US"all_parents", L_all_parents },
1103- { US"arguments", LX_arguments },
1104- { US"connection_reject", L_connection_reject },
1105- { US"delay_delivery", L_delay_delivery },
1106- { US"deliver_time", LX_deliver_time },
1107- { US"delivery_size", LX_delivery_size },
1108- { US"dnslist_defer", L_dnslist_defer },
1109- { US"etrn", L_etrn },
1110- { US"host_lookup_failed", L_host_lookup_failed },
1111- { US"ident_timeout", LX_ident_timeout },
1112- { US"incoming_interface", LX_incoming_interface },
1113- { US"incoming_port", LX_incoming_port },
1114- { US"lost_incoming_connection", L_lost_incoming_connection },
1115- { US"outgoing_port", LX_outgoing_port },
1116- { US"pid", LX_pid },
1117+int log_notall[] = {
1118+ -1
1119+};
1120+bit_table log_options[] = { /* must be in alphabetical order */
1121+ BIT_TABLE(L, 8bitmime),
1122+ BIT_TABLE(L, acl_warn_skipped),
1123+ BIT_TABLE(L, address_rewrite),
1124+ BIT_TABLE(L, all),
1125+ BIT_TABLE(L, all_parents),
1126+ BIT_TABLE(L, arguments),
1127+ BIT_TABLE(L, connection_reject),
1128+ BIT_TABLE(L, delay_delivery),
1129+ BIT_TABLE(L, deliver_time),
1130+ BIT_TABLE(L, delivery_size),
1131+ BIT_TABLE(L, dnslist_defer),
1132+ BIT_TABLE(L, etrn),
1133+ BIT_TABLE(L, host_lookup_failed),
1134+ BIT_TABLE(L, ident_timeout),
1135+ BIT_TABLE(L, incoming_interface),
1136+ BIT_TABLE(L, incoming_port),
1137+ BIT_TABLE(L, lost_incoming_connection),
1138+ BIT_TABLE(L, outgoing_port),
1139+ BIT_TABLE(L, pid),
1140 #ifdef EXPERIMENTAL_PROXY
1141- { US"proxy", LX_proxy },
1142+ BIT_TABLE(L, proxy),
1143 #endif
1144- { US"queue_run", L_queue_run },
1145- { US"queue_time", LX_queue_time },
1146- { US"queue_time_overall", LX_queue_time_overall },
1147- { US"received_recipients", LX_received_recipients },
1148- { US"received_sender", LX_received_sender },
1149- { US"rejected_header", LX_rejected_header },
1150- { US"rejected_headers", LX_rejected_header },
1151- { US"retry_defer", L_retry_defer },
1152- { US"return_path_on_delivery", LX_return_path_on_delivery },
1153- { US"sender_on_delivery", LX_sender_on_delivery },
1154- { US"sender_verify_fail", LX_sender_verify_fail },
1155- { US"size_reject", L_size_reject },
1156- { US"skip_delivery", L_skip_delivery },
1157- { US"smtp_confirmation", LX_smtp_confirmation },
1158- { US"smtp_connection", L_smtp_connection },
1159- { US"smtp_incomplete_transaction", L_smtp_incomplete_transaction },
1160- { US"smtp_mailauth", LX_smtp_mailauth },
1161- { US"smtp_no_mail", LX_smtp_no_mail },
1162- { US"smtp_protocol_error", L_smtp_protocol_error },
1163- { US"smtp_syntax_error", L_smtp_syntax_error },
1164- { US"subject", LX_subject },
1165- { US"tls_certificate_verified", LX_tls_certificate_verified },
1166- { US"tls_cipher", LX_tls_cipher },
1167- { US"tls_peerdn", LX_tls_peerdn },
1168- { US"tls_sni", LX_tls_sni },
1169- { US"unknown_in_list", LX_unknown_in_list }
1170+ BIT_TABLE(L, queue_run),
1171+ BIT_TABLE(L, queue_time),
1172+ BIT_TABLE(L, queue_time_overall),
1173+ BIT_TABLE(L, received_recipients),
1174+ BIT_TABLE(L, received_sender),
1175+ BIT_TABLE(L, rejected_header),
1176+ { US"rejected_headers", Li_rejected_header },
1177+ BIT_TABLE(L, retry_defer),
1178+ BIT_TABLE(L, return_path_on_delivery),
1179+ BIT_TABLE(L, sender_on_delivery),
1180+ BIT_TABLE(L, sender_verify_fail),
1181+ BIT_TABLE(L, size_reject),
1182+ BIT_TABLE(L, skip_delivery),
1183+ BIT_TABLE(L, smtp_confirmation),
1184+ BIT_TABLE(L, smtp_connection),
1185+ BIT_TABLE(L, smtp_incomplete_transaction),
1186+ BIT_TABLE(L, smtp_mailauth),
1187+ BIT_TABLE(L, smtp_no_mail),
1188+ BIT_TABLE(L, smtp_protocol_error),
1189+ BIT_TABLE(L, smtp_syntax_error),
1190+ BIT_TABLE(L, subject),
1191+ BIT_TABLE(L, tls_certificate_verified),
1192+ BIT_TABLE(L, tls_cipher),
1193+ BIT_TABLE(L, tls_peerdn),
1194+ BIT_TABLE(L, tls_sni),
1195+ BIT_TABLE(L, unknown_in_list),
1196 };
1197+int log_options_count = nelem(log_options);
1198
1199-int log_options_count = sizeof(log_options)/sizeof(bit_table);
1200 int log_reject_target = 0;
1201+unsigned int log_selector[log_selector_size]; /* initialized in main() */
1202 uschar *log_selector_string = NULL;
1203 FILE *log_stderr = NULL;
1204 BOOL log_testing_mode = FALSE;
1205 BOOL log_timezone = FALSE;
1206-unsigned int log_write_selector= L_default;
1207 uschar *login_sender_address = NULL;
1208 uschar *lookup_dnssec_authenticated = NULL;
1209 int lookup_open_max = 25;
1210diff --git a/src/src/globals.h b/src/src/globals.h
1211index ab03302..978a4cc 100644
1212--- a/src/src/globals.h
1213+++ b/src/src/globals.h
1214@@ -319,6 +319,7 @@ extern uschar *dccifd_options; /* options for the dccifd daemon */
1215 extern BOOL debug_daemon; /* Debug the daemon process only */
1216 extern int debug_fd; /* The fd for debug_file */
1217 extern FILE *debug_file; /* Where to write debugging info */
1218+extern int debug_notall[]; /* Debug options excluded from +all */
1219 extern bit_table debug_options[]; /* Table of debug options */
1220 extern int debug_options_count; /* Size of table */
1221 extern int delay_warning[]; /* Times between warnings */
1222@@ -531,16 +532,17 @@ extern uid_t local_user_uid; /* As it says; may be set in routers */
1223 extern tree_node *localpartlist_anchor;/* Tree of defined localpart lists */
1224 extern int localpartlist_count; /* Number defined */
1225 extern uschar *log_buffer; /* For constructing log entries */
1226-extern unsigned int log_extra_selector;/* Bit map of logging options other than used by log_write() */
1227+extern int log_default[]; /* Initialization list for log_selector */
1228 extern uschar *log_file_path; /* If unset, use default */
1229+extern int log_notall[]; /* Log options excluded from +all */
1230 extern bit_table log_options[]; /* Table of options */
1231 extern int log_options_count; /* Size of table */
1232 extern int log_reject_target; /* Target log for ACL rejections */
1233+extern unsigned int log_selector[]; /* Bit map of logging options */
1234 extern uschar *log_selector_string; /* As supplied in the config */
1235 extern FILE *log_stderr; /* Copy of stderr for log use, or NULL */
1236 extern BOOL log_testing_mode; /* TRUE in various testing modes */
1237 extern BOOL log_timezone; /* TRUE to include the timezone in log lines */
1238-extern unsigned int log_write_selector;/* Bit map of logging options for log_write() */
1239 extern uschar *login_sender_address; /* The actual sender address */
1240 extern lookup_info **lookup_list; /* Array of pointers to available lookups */
1241 extern int lookup_list_count; /* Number of entries in the list */
1242diff --git a/src/src/host.c b/src/src/host.c
1243index 31c2bbf..5c69c7f 100644
1244--- a/src/src/host.c
1245+++ b/src/src/host.c
1246@@ -544,7 +544,7 @@ use this directly as the first item for Received: because it ain't an RFC 2822
1247 domain. Sigh. */
1248
1249 address = string_sprintf("[%s]:%d", sender_host_address, sender_host_port);
1250-if ((log_extra_selector & LX_incoming_port) == 0 || sender_host_port <= 0)
1251+if (!LOGGING(incoming_port) || sender_host_port <= 0)
1252 *(Ustrrchr(address, ':')) = 0;
1253
1254 /* If there's no EHLO/HELO data, we can't show it. */
1255@@ -695,8 +695,7 @@ else
1256 {
1257 uschar *flag = useflag? US"H=" : US"";
1258 uschar *iface = US"";
1259- if ((log_extra_selector & LX_incoming_interface) != 0 &&
1260- interface_address != NULL)
1261+ if (LOGGING(incoming_interface) && interface_address != NULL)
1262 iface = string_sprintf(" I=[%s]:%d", interface_address, interface_port);
1263 if (sender_ident == NULL)
1264 (void)string_format(big_buffer, big_buffer_size, "%s%s%s",
1265diff --git a/src/src/log.c b/src/src/log.c
1266index 11b3edf..b2d1fcf 100644
1267--- a/src/src/log.c
1268+++ b/src/src/log.c
1269@@ -613,7 +613,7 @@ If a message_id exists, we include it after the timestamp.
1270
1271 Arguments:
1272 selector write to main log or LOG_INFO only if this value is zero, or if
1273- its bit is set in log_write_selector
1274+ its bit is set in log_selector[0]
1275 flags each bit indicates some independent action:
1276 LOG_SENDER add raw sender to the message
1277 LOG_RECIPIENTS add raw recipients list to message
1278@@ -749,15 +749,12 @@ DEBUG(D_any|D_v)
1279 Ustrcpy(ptr, "LOG:");
1280 ptr += 4;
1281
1282- /* Show the options that were passed into the call. These are those whose
1283- flag values do not have the 0x80000000 bit in them. Note that this
1284- automatically exclude the "all" setting. */
1285+ /* Show the selector that was passed into the call. */
1286
1287 for (i = 0; i < log_options_count; i++)
1288 {
1289 unsigned int bit = log_options[i].bit;
1290- if ((bit & 0x80000000) != 0) continue;
1291- if ((selector & bit) != 0)
1292+ if (bit < BITWORDSIZE && selector == BIT(bit))
1293 {
1294 *ptr++ = ' ';
1295 Ustrcpy(ptr, log_options[i].name);
1296@@ -809,7 +806,7 @@ ptr = log_buffer;
1297 sprintf(CS ptr, "%s ", tod_stamp(tod_log));
1298 while(*ptr) ptr++;
1299
1300-if ((log_extra_selector & LX_pid) != 0)
1301+if (LOGGING(pid))
1302 {
1303 sprintf(CS ptr, "[%d] ", (int)getpid());
1304 while (*ptr) ptr++;
1305@@ -869,7 +866,7 @@ or unless there is no log_stderr (expn called from daemon, for example). */
1306 if (!really_exim || log_testing_mode)
1307 {
1308 if (debug_selector == 0 && log_stderr != NULL &&
1309- (selector == 0 || (selector & log_write_selector) != 0))
1310+ (selector == 0 || (selector & log_selector[0]) != 0))
1311 {
1312 if (host_checking)
1313 fprintf(log_stderr, "LOG: %s", CS(log_buffer + 20)); /* no timestamp */
1314@@ -887,7 +884,7 @@ has been renamed. Therefore, do a stat() and see if the inode has changed, and
1315 if so, re-open. */
1316
1317 if ((flags & LOG_MAIN) != 0 &&
1318- (selector == 0 || (selector & log_write_selector) != 0))
1319+ (selector == 0 || (selector & log_selector[0]) != 0))
1320 {
1321 if ((logging_mode & LOG_MODE_SYSLOG) != 0 &&
1322 (syslog_duplication || (flags & (LOG_REJECT|LOG_PANIC)) == 0))
1323@@ -956,7 +953,7 @@ if ((flags & LOG_REJECT) != 0)
1324 {
1325 header_line *h;
1326
1327- if (header_list != NULL && (log_extra_selector & LX_rejected_header) != 0)
1328+ if (header_list != NULL && LOGGING(rejected_header))
1329 {
1330 if (recipients_count > 0)
1331 {
1332@@ -1142,6 +1139,35 @@ syslog_open = FALSE;
1333
1334
1335 /*************************************************
1336+* Multi-bit set or clear *
1337+*************************************************/
1338+
1339+/* These functions take a list of bit indexes (terminated by -1) and
1340+clear or set the corresponding bits in the selector.
1341+
1342+Arguments:
1343+ selector address of the bit string
1344+ selsize number of words in the bit string
1345+ bits list of bits to set
1346+*/
1347+
1348+void
1349+bits_clear(unsigned int *selector, size_t selsize, int *bits)
1350+{
1351+for(; *bits != -1; ++bits)
1352+ BIT_CLEAR(selector, selsize, *bits);
1353+}
1354+
1355+void
1356+bits_set(unsigned int *selector, size_t selsize, int *bits)
1357+{
1358+for(; *bits != -1; ++bits)
1359+ BIT_SET(selector, selsize, *bits);
1360+}
1361+
1362+
1363+
1364+/*************************************************
1365 * Decode bit settings for log/debug *
1366 *************************************************/
1367
1368@@ -1151,13 +1177,9 @@ also recognizes a numeric setting of the form =<number>, but this is not
1369 intended for user use. It's an easy way for Exim to pass the debug settings
1370 when it is re-exec'ed.
1371
1372-The log options are held in two unsigned ints (because there became too many
1373-for one). The top bit in the table means "put in 2nd selector". This does not
1374-yet apply to debug options, so the "=" facility sets only the first selector.
1375-
1376-The "all" selector, which must be equal to 0xffffffff, is recognized specially.
1377-It sets all the bits in both selectors. However, there is a facility for then
1378-unsetting certain bits, because we want to turn off "memory" in the debug case.
1379+The option table is a list of names and bit indexes. The index -1
1380+means "set all bits, except for those listed in notall". The notall
1381+list is terminated by -1.
1382
1383 The action taken for bad values varies depending upon why we're here.
1384 For log messages, or if the debugging is triggered from config, then we write
1385@@ -1165,10 +1187,9 @@ to the log on the way out. For debug setting triggered from the command-line,
1386 we treat it as an unknown option: error message to stderr and die.
1387
1388 Arguments:
1389- selector1 address of the first bit string
1390- selector2 address of the second bit string, or NULL
1391- notall1 bits to exclude from "all" for selector1
1392- notall2 bits to exclude from "all" for selector2
1393+ selector address of the bit string
1394+ selsize number of words in the bit string
1395+ notall list of bits to exclude from "all"
1396 string the configured string
1397 options the table of option names
1398 count size of table
1399@@ -1179,9 +1200,8 @@ Returns: nothing on success - bomb out on failure
1400 */
1401
1402 void
1403-decode_bits(unsigned int *selector1, unsigned int *selector2, int notall1,
1404- int notall2, uschar *string, bit_table *options, int count, uschar *which,
1405- int flags)
1406+decode_bits(unsigned int *selector, size_t selsize, int *notall,
1407+ uschar *string, bit_table *options, int count, uschar *which, int flags)
1408 {
1409 uschar *errmsg;
1410 if (string == NULL) return;
1411@@ -1189,7 +1209,8 @@ if (string == NULL) return;
1412 if (*string == '=')
1413 {
1414 char *end; /* Not uschar */
1415- *selector1 = strtoul(CS string+1, &end, 0);
1416+ memset(selector, 0, sizeof(*selector)*selsize);
1417+ *selector = strtoul(CS string+1, &end, 0);
1418 if (*end == 0) return;
1419 errmsg = string_sprintf("malformed numeric %s_selector setting: %s", which,
1420 string);
1421@@ -1232,40 +1253,22 @@ else for(;;)
1422 if (middle->name[len] != 0) c = -1; else
1423 {
1424 unsigned int bit = middle->bit;
1425- unsigned int *selector;
1426-
1427- /* The value with all bits set means "force all bits in both selectors"
1428- in the case where two are being handled. However, the top bit in the
1429- second selector is never set. When setting, some bits can be excluded.
1430- */
1431-
1432- if (bit == 0xffffffff)
1433- {
1434- if (adding)
1435- {
1436- *selector1 = 0xffffffff ^ notall1;
1437- if (selector2 != NULL) *selector2 = 0x7fffffff ^ notall2;
1438- }
1439- else
1440- {
1441- *selector1 = 0;
1442- if (selector2 != NULL) *selector2 = 0;
1443- }
1444- }
1445-
1446- /* Otherwise, the 0x80000000 bit means "this value, without the top
1447- bit, belongs in the second selector". */
1448
1449- else
1450- {
1451- if ((bit & 0x80000000) != 0)
1452- {
1453- selector = selector2;
1454- bit &= 0x7fffffff;
1455- }
1456- else selector = selector1;
1457- if (adding) *selector |= bit; else *selector &= ~bit;
1458- }
1459+ if (bit == -1)
1460+ {
1461+ if (adding)
1462+ {
1463+ memset(selector, -1, sizeof(*selector)*selsize);
1464+ bits_clear(selector, selsize, notall);
1465+ }
1466+ else
1467+ memset(selector, 0, sizeof(*selector)*selsize);
1468+ }
1469+ else if (adding)
1470+ BIT_SET(selector, selsize, bit);
1471+ else
1472+ BIT_CLEAR(selector, selsize, bit);
1473+
1474 break; /* Out of loop to match selector name */
1475 }
1476 }
1477@@ -1335,10 +1338,8 @@ if (tag_name != NULL && (Ustrchr(tag_name, '/') != NULL))
1478
1479 debug_selector = D_default;
1480 if (opts)
1481- {
1482- decode_bits(&debug_selector, NULL, D_memory, 0, opts,
1483+ decode_bits(&debug_selector, 1, debug_notall, opts,
1484 debug_options, debug_options_count, US"debug", DEBUG_FROM_CONFIG);
1485- }
1486
1487 /* When activating from a transport process we may never have logged at all
1488 resulting in certain setup not having been done. Hack this for now so we
1489diff --git a/src/src/macros.h b/src/src/macros.h
1490index 61f9ca6..d63025e 100644
1491--- a/src/src/macros.h
1492+++ b/src/src/macros.h
1493@@ -321,46 +321,84 @@ for having to swallow the rest of an SMTP message is whether the value is
1494 #define END_SIZE 4 /* Reading ended because message too big */
1495 #define END_WERROR 5 /* Write error while reading the message */
1496
1497-/* Options bits for debugging; D_v and D_local_scan are also in local_scan.h */
1498-
1499-#define D_v 0x00000001
1500-#define D_local_scan 0x00000002
1501-
1502-#define D_acl 0x00000004
1503-#define D_auth 0x00000008
1504-#define D_deliver 0x00000010
1505-#define D_dns 0x00000020
1506-#define D_dnsbl 0x00000040
1507-#define D_exec 0x00000080
1508-#define D_expand 0x00000100
1509-#define D_filter 0x00000200
1510-#define D_hints_lookup 0x00000400
1511-#define D_host_lookup 0x00000800
1512-#define D_ident 0x00001000
1513-#define D_interface 0x00002000
1514-#define D_lists 0x00004000
1515-#define D_load 0x00008000
1516-#define D_lookup 0x00010000
1517-#define D_memory 0x00020000
1518-#define D_pid 0x00040000
1519-#define D_process_info 0x00080000
1520-#define D_queue_run 0x00100000
1521-#define D_receive 0x00200000
1522-#define D_resolver 0x00400000
1523-#define D_retry 0x00800000
1524-#define D_rewrite 0x01000000
1525-#define D_route 0x02000000
1526-#define D_timestamp 0x04000000
1527-#define D_tls 0x08000000
1528-#define D_transport 0x10000000
1529-#define D_uid 0x20000000
1530-#define D_verify 0x40000000
1531-
1532-/* The D_all value must always have all bits set, as it is recognized specially
1533-by the function that decodes debug and log selectors. This is to enable it to
1534-set all the bits in a multi-word selector. Debug doesn't use this yet, but we
1535-are getting close. In fact, we want to omit "memory" for -d+all, but can't
1536-handle this here. It is fudged externally. */
1537+/* Bit masks for debug and log selectors */
1538+
1539+/* Assume words are 32 bits wide. Tiny waste of space on 64 bit
1540+platforms, but this ensures bit vectors always work the same way. */
1541+#define BITWORDSIZE 32
1542+
1543+/* This macro is for single-word bit vectors: the debug selector,
1544+and the first word of the log selector. */
1545+#define BIT(n) (1 << (n))
1546+
1547+/* And these are for multi-word vectors. */
1548+#define BITWORD(n) ( (n) / BITWORDSIZE)
1549+#define BITMASK(n) (1 << (n) % BITWORDSIZE)
1550+
1551+#define BIT_CLEAR(s,z,n) ((s)[BITWORD(n)] &= ~BITMASK(n))
1552+#define BIT_SET(s,z,n) ((s)[BITWORD(n)] |= BITMASK(n))
1553+#define BIT_TEST(s,z,n) (((s)[BITWORD(n)] & BITMASK(n)) != 0)
1554+
1555+/* Used in globals.c for initializing bit_table structures. T will be either
1556+D or L correspondong to the debug and log selector bits declared below. */
1557+
1558+#define BIT_TABLE(T,name) { US #name, T##i_##name }
1559+
1560+/* IOTA allows us to keep an implicit sequential count, like a simple enum,
1561+but we can have sequentially numbered identifiers which are not declared
1562+sequentially. We use this for more compact declarations of bit indexes and
1563+masks, alternating between sequential bit index and corresponding mask. */
1564+
1565+#define IOTA(iota) (__LINE__ - iota)
1566+#define IOTA_INIT(zero) (__LINE__ - zero + 1)
1567+
1568+/* Options bits for debugging. DEBUG_BIT() declares both a bit index and the
1569+corresponding mask. Di_all is a special value recognized by decode_bits().
1570+
1571+Exim's code assumes in a number of places that the debug_selector is one
1572+word, and this is exposed in the local_scan ABI. The D_v and D_local_scan bit
1573+masks are part of the local_scan API so are #defined in local_scan.h */
1574+
1575+#define DEBUG_BIT(name) Di_##name = IOTA(Di_iota), D_##name = BIT(Di_##name)
1576+
1577+enum {
1578+ Di_all = -1,
1579+ Di_v = 0,
1580+ Di_local_scan = 1,
1581+
1582+ Di_iota = IOTA_INIT(2),
1583+ DEBUG_BIT(acl),
1584+ DEBUG_BIT(auth),
1585+ DEBUG_BIT(deliver),
1586+ DEBUG_BIT(dns),
1587+ DEBUG_BIT(dnsbl),
1588+ DEBUG_BIT(exec),
1589+ DEBUG_BIT(expand),
1590+ DEBUG_BIT(filter),
1591+ DEBUG_BIT(hints_lookup),
1592+ DEBUG_BIT(host_lookup),
1593+ DEBUG_BIT(ident),
1594+ DEBUG_BIT(interface),
1595+ DEBUG_BIT(lists),
1596+ DEBUG_BIT(load),
1597+ DEBUG_BIT(lookup),
1598+ DEBUG_BIT(memory),
1599+ DEBUG_BIT(pid),
1600+ DEBUG_BIT(process_info),
1601+ DEBUG_BIT(queue_run),
1602+ DEBUG_BIT(receive),
1603+ DEBUG_BIT(resolver),
1604+ DEBUG_BIT(retry),
1605+ DEBUG_BIT(rewrite),
1606+ DEBUG_BIT(route),
1607+ DEBUG_BIT(timestamp),
1608+ DEBUG_BIT(tls),
1609+ DEBUG_BIT(transport),
1610+ DEBUG_BIT(uid),
1611+ DEBUG_BIT(verify),
1612+};
1613+
1614+/* Multi-bit debug masks */
1615
1616 #define D_all 0xffffffff
1617
1618@@ -380,81 +418,67 @@ handle this here. It is fudged externally. */
1619 D_timestamp | \
1620 D_resolver))
1621
1622-/* Options bits for logging. Those that will end up in log_write_selector have
1623-values < 0x80000000. They can be used in calls to log_write(). The others have
1624-values > 0x80000000 and are put into log_extra_selector (without the top bit).
1625-These are only ever tested independently. "All" is a magic value that is used
1626-only in the name table to set all options in both bit maps. */
1627-
1628-/* The L_all value must always have all bits set, as it is recognized specially
1629-by the function that decodes debug and log selectors. This is to enable it to
1630-set all the bits in a multi-word selector. */
1631-
1632-#define L_all 0xffffffff
1633-
1634-#define L_address_rewrite 0x00000001
1635-#define L_all_parents 0x00000002
1636-#define L_connection_reject 0x00000004
1637-#define L_delay_delivery 0x00000008
1638-#define L_dnslist_defer 0x00000010
1639-#define L_etrn 0x00000020
1640-#define L_host_lookup_failed 0x00000040
1641-#define L_lost_incoming_connection 0x00000080
1642-#define L_queue_run 0x00000100
1643-#define L_retry_defer 0x00000200
1644-#define L_size_reject 0x00000400
1645-#define L_skip_delivery 0x00000800
1646-#define L_smtp_connection 0x00001000
1647-#define L_smtp_incomplete_transaction 0x00002000
1648-#define L_smtp_protocol_error 0x00004000
1649-#define L_smtp_syntax_error 0x00008000
1650-
1651-#define LX_acl_warn_skipped 0x80000001
1652-#define LX_arguments 0x80000002
1653-#define LX_deliver_time 0x80000004
1654-#define LX_delivery_size 0x80000008
1655-#define LX_ident_timeout 0x80000010
1656-#define LX_incoming_interface 0x80000020
1657-#define LX_incoming_port 0x80000040
1658-#define LX_outgoing_port 0x80000080
1659-#define LX_pid 0x80000100
1660-#define LX_queue_time 0x80000200
1661-#define LX_queue_time_overall 0x80000400
1662-#define LX_received_sender 0x80000800
1663-#define LX_received_recipients 0x80001000
1664-#define LX_rejected_header 0x80002000
1665-#define LX_return_path_on_delivery 0x80004000
1666-#define LX_sender_on_delivery 0x80008000
1667-#define LX_sender_verify_fail 0x80010000
1668-#define LX_smtp_confirmation 0x80020000
1669-#define LX_smtp_no_mail 0x80040000
1670-#define LX_subject 0x80080000
1671-#define LX_tls_certificate_verified 0x80100000
1672-#define LX_tls_cipher 0x80200000
1673-#define LX_tls_peerdn 0x80400000
1674-#define LX_tls_sni 0x80800000
1675-#define LX_unknown_in_list 0x81000000
1676-#define LX_8bitmime 0x82000000
1677-#define LX_smtp_mailauth 0x84000000
1678-#define LX_proxy 0x88000000
1679-
1680-#define L_default (L_connection_reject | \
1681- L_delay_delivery | \
1682- L_dnslist_defer | \
1683- L_etrn | \
1684- L_host_lookup_failed | \
1685- L_lost_incoming_connection | \
1686- L_queue_run | \
1687- L_retry_defer | \
1688- L_size_reject | \
1689- L_skip_delivery)
1690-
1691-#define LX_default ((LX_acl_warn_skipped | \
1692- LX_rejected_header | \
1693- LX_sender_verify_fail | \
1694- LX_smtp_confirmation | \
1695- LX_tls_certificate_verified| \
1696- LX_tls_cipher) & 0x7fffffff)
1697+/* Options bits for logging. Those that have values < BITWORDSIZE can be used
1698+in calls to log_write(). The others are put into later words in log_selector
1699+and are only ever tested independently, so they do not need bit mask
1700+declarations. The Li_all value is recognized specially by decode_bits(). */
1701+
1702+#define LOG_BIT(name) Li_##name = IOTA(Li_iota), L_##name = BIT(Li_##name)
1703+
1704+enum {
1705+ Li_all = -1,
1706+
1707+ Li_iota = IOTA_INIT(0),
1708+ LOG_BIT(address_rewrite),
1709+ LOG_BIT(all_parents),
1710+ LOG_BIT(connection_reject),
1711+ LOG_BIT(delay_delivery),
1712+ LOG_BIT(dnslist_defer),
1713+ LOG_BIT(etrn),
1714+ LOG_BIT(host_lookup_failed),
1715+ LOG_BIT(lost_incoming_connection),
1716+ LOG_BIT(queue_run),
1717+ LOG_BIT(retry_defer),
1718+ LOG_BIT(size_reject),
1719+ LOG_BIT(skip_delivery),
1720+ LOG_BIT(smtp_connection),
1721+ LOG_BIT(smtp_incomplete_transaction),
1722+ LOG_BIT(smtp_protocol_error),
1723+ LOG_BIT(smtp_syntax_error),
1724+
1725+ Li_acl_warn_skipped = BITWORDSIZE,
1726+ Li_arguments,
1727+ Li_deliver_time,
1728+ Li_delivery_size,
1729+ Li_ident_timeout,
1730+ Li_incoming_interface,
1731+ Li_incoming_port,
1732+ Li_outgoing_port,
1733+ Li_pid,
1734+ Li_queue_time,
1735+ Li_queue_time_overall,
1736+ Li_received_sender,
1737+ Li_received_recipients,
1738+ Li_rejected_header,
1739+ Li_return_path_on_delivery,
1740+ Li_sender_on_delivery,
1741+ Li_sender_verify_fail,
1742+ Li_smtp_confirmation,
1743+ Li_smtp_no_mail,
1744+ Li_subject,
1745+ Li_tls_certificate_verified,
1746+ Li_tls_cipher,
1747+ Li_tls_peerdn,
1748+ Li_tls_sni,
1749+ Li_unknown_in_list,
1750+ Li_8bitmime,
1751+ Li_smtp_mailauth,
1752+ Li_proxy,
1753+
1754+ log_selector_size = BITWORD(Li_proxy) + 1
1755+};
1756+
1757+#define LOGGING(opt) BIT_TEST(log_selector, log_selector_size, Li_##opt)
1758
1759 /* Private error numbers for delivery failures, set negative so as not
1760 to conflict with system errno values. */
1761diff --git a/src/src/match.c b/src/src/match.c
1762index 9e47110..fa42187 100644
1763--- a/src/src/match.c
1764+++ b/src/src/match.c
1765@@ -771,7 +771,7 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
1766 include_unknown? "yes":"no", error);
1767 if (!include_unknown)
1768 {
1769- if ((log_extra_selector & LX_unknown_in_list) != 0)
1770+ if (LOGGING(unknown_in_list))
1771 log_write(0, LOG_MAIN, "list matching forced to fail: %s", error);
1772 return FAIL;
1773 }
1774@@ -880,7 +880,7 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
1775 (void)fclose(f);
1776 if (!include_unknown)
1777 {
1778- if ((log_extra_selector & LX_unknown_in_list) != 0)
1779+ if (LOGGING(unknown_in_list))
1780 log_write(0, LOG_MAIN, "list matching forced to fail: %s", error);
1781 return FAIL;
1782 }
1783diff --git a/src/src/rda.c b/src/src/rda.c
1784index 7596466..2afd6dc 100644
1785--- a/src/src/rda.c
1786+++ b/src/src/rda.c
1787@@ -635,7 +635,7 @@ if ((pid = fork()) == 0)
1788 {
1789 DEBUG(D_rewrite) debug_printf("turned off address rewrite logging (not "
1790 "root or exim in this process)\n");
1791- log_write_selector &= ~L_address_rewrite;
1792+ BIT_CLEAR(log_selector, log_selector_size, Li_address_rewrite);
1793 }
1794
1795 /* Now do the business */
1796diff --git a/src/src/receive.c b/src/src/receive.c
1797index 64cf1ae..b430ee2 100644
1798--- a/src/src/receive.c
1799+++ b/src/src/receive.c
1800@@ -1118,8 +1118,7 @@ add_host_info_for_log(uschar *s, int *sizeptr, int *ptrptr)
1801 if (sender_fullhost != NULL)
1802 {
1803 s = string_append(s, sizeptr, ptrptr, 2, US" H=", sender_fullhost);
1804- if ((log_extra_selector & LX_incoming_interface) != 0 &&
1805- interface_address != NULL)
1806+ if (LOGGING(incoming_interface) && interface_address != NULL)
1807 {
1808 uschar *ss = string_sprintf(" I=[%s]:%d", interface_address,
1809 interface_port);
1810@@ -2529,7 +2528,7 @@ if (msgid_header == NULL &&
1811 rewriting. Must copy the count, because later ACLs and the local_scan()
1812 function may mess with the real recipients. */
1813
1814-if ((log_extra_selector & LX_received_recipients) != 0)
1815+if (LOGGING(received_recipients))
1816 {
1817 raw_recipients = store_get(recipients_count * sizeof(uschar *));
1818 for (i = 0; i < recipients_count; i++)
1819@@ -3573,7 +3572,7 @@ else
1820 goto TEMPREJECT;
1821
1822 case LOCAL_SCAN_REJECT_NOLOGHDR:
1823- log_extra_selector &= ~LX_rejected_header;
1824+ BIT_CLEAR(log_selector, log_selector_size, Li_rejected_header);
1825 /* Fall through */
1826
1827 case LOCAL_SCAN_REJECT:
1828@@ -3582,7 +3581,7 @@ else
1829 break;
1830
1831 case LOCAL_SCAN_TEMPREJECT_NOLOGHDR:
1832- log_extra_selector &= ~LX_rejected_header;
1833+ BIT_CLEAR(log_selector, log_selector_size, Li_rejected_header);
1834 /* Fall through */
1835
1836 case LOCAL_SCAN_TEMPREJECT:
1837@@ -3747,15 +3746,15 @@ if (message_reference != NULL)
1838 s = add_host_info_for_log(s, &size, &sptr);
1839
1840 #ifdef SUPPORT_TLS
1841-if (log_extra_selector & LX_tls_cipher && tls_in.cipher)
1842+if (LOGGING(tls_cipher) && tls_in.cipher)
1843 s = string_append(s, &size, &sptr, 2, US" X=", tls_in.cipher);
1844-if (log_extra_selector & LX_tls_certificate_verified && tls_in.cipher)
1845+if (LOGGING(tls_certificate_verified) && tls_in.cipher)
1846 s = string_append(s, &size, &sptr, 2, US" CV=",
1847 tls_in.certificate_verified? "yes":"no");
1848-if (log_extra_selector & LX_tls_peerdn && tls_in.peerdn)
1849+if (LOGGING(tls_peerdn) && tls_in.peerdn)
1850 s = string_append(s, &size, &sptr, 3, US" DN=\"",
1851 string_printing(tls_in.peerdn), US"\"");
1852-if (log_extra_selector & LX_tls_sni && tls_in.sni)
1853+if (LOGGING(tls_sni) && tls_in.sni)
1854 s = string_append(s, &size, &sptr, 3, US" SNI=\"",
1855 string_printing(tls_in.sni), US"\"");
1856 #endif
1857@@ -3766,7 +3765,7 @@ if (sender_host_authenticated)
1858 if (authenticated_id != NULL)
1859 {
1860 s = string_append(s, &size, &sptr, 2, US":", authenticated_id);
1861- if (log_extra_selector & LX_smtp_mailauth && authenticated_sender != NULL)
1862+ if (LOGGING(smtp_mailauth) && authenticated_sender != NULL)
1863 s = string_append(s, &size, &sptr, 2, US":", authenticated_sender);
1864 }
1865 }
1866@@ -3777,7 +3776,7 @@ if (prdr_requested)
1867 #endif
1868
1869 #ifdef EXPERIMENTAL_PROXY
1870-if (proxy_session && log_extra_selector & LX_proxy)
1871+if (proxy_session && LOGGING(proxy))
1872 s = string_append(s, &size, &sptr, 2, US" PRX=", proxy_host_address);
1873 #endif
1874
1875@@ -3788,7 +3787,7 @@ s = string_append(s, &size, &sptr, 2, US" S=", big_buffer);
1876 0 ... no BODY= used
1877 7 ... 7BIT
1878 8 ... 8BITMIME */
1879-if (log_extra_selector & LX_8bitmime)
1880+if (LOGGING(8bitmime))
1881 {
1882 sprintf(CS big_buffer, "%d", body_8bitmime);
1883 s = string_append(s, &size, &sptr, 2, US" M8S=", big_buffer);
1884@@ -3814,7 +3813,7 @@ if (msgid_header != NULL)
1885 /* If subject logging is turned on, create suitable printing-character
1886 text. By expanding $h_subject: we make use of the MIME decoding. */
1887
1888-if ((log_extra_selector & LX_subject) != 0 && subject_header != NULL)
1889+if (LOGGING(subject) && subject_header != NULL)
1890 {
1891 int i;
1892 uschar *p = big_buffer;
1893@@ -4003,8 +4002,8 @@ if(!smtp_reply)
1894 #endif
1895 {
1896 log_write(0, LOG_MAIN |
1897- (((log_extra_selector & LX_received_recipients) != 0)? LOG_RECIPIENTS : 0) |
1898- (((log_extra_selector & LX_received_sender) != 0)? LOG_SENDER : 0),
1899+ (LOGGING(received_recipients)? LOG_RECIPIENTS : 0) |
1900+ (LOGGING(received_sender)? LOG_SENDER : 0),
1901 "%s", s);
1902
1903 /* Log any control actions taken by an ACL or local_scan(). */
1904diff --git a/src/src/rewrite.c b/src/src/rewrite.c
1905index 296fe8c..ca7fb6a 100644
1906--- a/src/src/rewrite.c
1907+++ b/src/src/rewrite.c
1908@@ -247,8 +247,7 @@ for (rule = rewrite_rules;
1909
1910 /* We have a validly rewritten address */
1911
1912- if ((log_write_selector & L_address_rewrite) != 0 ||
1913- (debug_selector & D_rewrite) != 0)
1914+ if (LOGGING(address_rewrite) || (debug_selector & D_rewrite) != 0)
1915 {
1916 int i;
1917 const uschar *where = CUS"?";
1918diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
1919index effc636..9982451 100644
1920--- a/src/src/smtp_in.c
1921+++ b/src/src/smtp_in.c
1922@@ -1234,8 +1234,7 @@ if (sender_host_unknown || sender_host_notsocket)
1923 if (is_inetd)
1924 return string_sprintf("SMTP connection from %s (via inetd)", hostname);
1925
1926-if ((log_extra_selector & LX_incoming_interface) != 0 &&
1927- interface_address != NULL)
1928+if (LOGGING(incoming_interface) && interface_address != NULL)
1929 return string_sprintf("SMTP connection from %s I=[%s]:%d", hostname,
1930 interface_address, interface_port);
1931
1932@@ -1260,16 +1259,15 @@ s_tlslog(uschar * s, int * sizep, int * ptrp)
1933 int size = sizep ? *sizep : 0;
1934 int ptr = ptrp ? *ptrp : 0;
1935
1936- if ((log_extra_selector & LX_tls_cipher) != 0 && tls_in.cipher != NULL)
1937+ if (LOGGING(tls_cipher) && tls_in.cipher != NULL)
1938 s = string_append(s, &size, &ptr, 2, US" X=", tls_in.cipher);
1939- if ((log_extra_selector & LX_tls_certificate_verified) != 0 &&
1940- tls_in.cipher != NULL)
1941+ if (LOGGING(tls_certificate_verified) && tls_in.cipher != NULL)
1942 s = string_append(s, &size, &ptr, 2, US" CV=",
1943 tls_in.certificate_verified? "yes":"no");
1944- if ((log_extra_selector & LX_tls_peerdn) != 0 && tls_in.peerdn != NULL)
1945+ if (LOGGING(tls_peerdn) && tls_in.peerdn != NULL)
1946 s = string_append(s, &size, &ptr, 3, US" DN=\"",
1947 string_printing(tls_in.peerdn), US"\"");
1948- if ((log_extra_selector & LX_tls_sni) != 0 && tls_in.sni != NULL)
1949+ if (LOGGING(tls_sni) && tls_in.sni != NULL)
1950 s = string_append(s, &size, &ptr, 3, US" SNI=\"",
1951 string_printing(tls_in.sni), US"\"");
1952
1953@@ -1301,7 +1299,7 @@ smtp_log_no_mail(void)
1954 int size, ptr, i;
1955 uschar *s, *sep;
1956
1957-if (smtp_mailcmd_count > 0 || (log_extra_selector & LX_smtp_no_mail) == 0)
1958+if (smtp_mailcmd_count > 0 || !LOGGING(smtp_no_mail))
1959 return;
1960
1961 s = NULL;
1962@@ -2510,8 +2508,8 @@ static void
1963 incomplete_transaction_log(uschar *what)
1964 {
1965 if (sender_address == NULL || /* No transaction in progress */
1966- (log_write_selector & L_smtp_incomplete_transaction) == 0 /* Not logging */
1967- ) return;
1968+ !LOGGING(smtp_incomplete_transaction))
1969+ return;
1970
1971 /* Build list of recipients for logging */
1972
1973@@ -2762,7 +2760,7 @@ if (sender_verified_failed != NULL &&
1974
1975 setflag(sender_verified_failed, af_sverify_told);
1976
1977- if (rc != FAIL || (log_extra_selector & LX_sender_verify_fail) != 0)
1978+ if (rc != FAIL || LOGGING(sender_verify_fail))
1979 log_write(0, LOG_MAIN|LOG_REJECT, "%s sender verify %s for <%s>%s",
1980 host_and_ident(TRUE),
1981 ((sender_verified_failed->special_action & 255) == DEFER)? "defer":"fail",
1982diff --git a/src/src/structs.h b/src/src/structs.h
1983index 6f143d6..438b521 100644
1984--- a/src/src/structs.h
1985+++ b/src/src/structs.h
1986@@ -38,7 +38,7 @@ typedef struct macro_item {
1987
1988 typedef struct bit_table {
1989 uschar *name;
1990- unsigned int bit;
1991+ int bit;
1992 } bit_table;
1993
1994 /* Block for holding a uid and gid, possibly unset, and an initgroups flag. */
1995diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
1996index b1dccb8..73ac807 100644
1997--- a/src/src/tls-openssl.c
1998+++ b/src/src/tls-openssl.c
1999@@ -1111,8 +1111,7 @@ len = SSL_get_tlsext_status_ocsp_resp(s, &p);
2000 if(!p)
2001 {
2002 /* Expect this when we requested ocsp but got none */
2003- if ( cbinfo->u_ocsp.client.verify_required
2004- && log_extra_selector & LX_tls_cipher)
2005+ if (cbinfo->u_ocsp.client.verify_required && LOGGING(tls_cipher))
2006 log_write(0, LOG_MAIN, "Received TLS status callback, null content");
2007 else
2008 DEBUG(D_tls) debug_printf(" null\n");
2009@@ -1122,7 +1121,7 @@ if(!p)
2010 if(!(rsp = d2i_OCSP_RESPONSE(NULL, &p, len)))
2011 {
2012 tls_out.ocsp = OCSP_FAILED;
2013- if (log_extra_selector & LX_tls_cipher)
2014+ if (LOGGING(tls_cipher))
2015 log_write(0, LOG_MAIN, "Received TLS cert status response, parse error");
2016 else
2017 DEBUG(D_tls) debug_printf(" parse error\n");
2018@@ -1132,7 +1131,7 @@ if(!(rsp = d2i_OCSP_RESPONSE(NULL, &p, len)))
2019 if(!(bs = OCSP_response_get1_basic(rsp)))
2020 {
2021 tls_out.ocsp = OCSP_FAILED;
2022- if (log_extra_selector & LX_tls_cipher)
2023+ if (LOGGING(tls_cipher))
2024 log_write(0, LOG_MAIN, "Received TLS cert status response, error parsing response");
2025 else
2026 DEBUG(D_tls) debug_printf(" error parsing response\n");
2027@@ -1163,7 +1162,7 @@ if(!(bs = OCSP_response_get1_basic(rsp)))
2028 cbinfo->u_ocsp.client.verify_store, 0)) <= 0)
2029 {
2030 tls_out.ocsp = OCSP_FAILED;
2031- if (log_extra_selector & LX_tls_cipher)
2032+ if (LOGGING(tls_cipher))
2033 log_write(0, LOG_MAIN, "Received TLS cert status response, itself unverifiable");
2034 BIO_printf(bp, "OCSP response verify failure\n");
2035 ERR_print_errors(bp);
2036diff --git a/src/src/transports/lmtp.c b/src/src/transports/lmtp.c
2037index 0cd89af..1f4d7a6 100644
2038--- a/src/src/transports/lmtp.c
2039+++ b/src/src/transports/lmtp.c
2040@@ -654,7 +654,7 @@ if (send_data)
2041 if (lmtp_read_response(out, buffer, sizeof(buffer), '2', timeout))
2042 {
2043 addr->transport_return = OK;
2044- if ((log_extra_selector & LX_smtp_confirmation) != 0)
2045+ if (LOGGING(smtp_confirmation))
2046 {
2047 const uschar *s = string_printing(buffer);
2048 /* de-const safe here as string_printing known to have alloc'n'copied */
2049diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
2050index a952413..609dba3 100644
2051--- a/src/src/transports/smtp.c
2052+++ b/src/src/transports/smtp.c
2053@@ -638,7 +638,7 @@ if (addr->message)
2054 }
2055 else
2056 {
2057- if (log_extra_selector & LX_outgoing_port)
2058+ if (LOGGING(outgoing_port))
2059 message = string_sprintf("%s:%d", message,
2060 host->port == PORT_NONE ? 25 : host->port);
2061 log_write(0, LOG_MAIN, "%s %s", message, strerror(addr->basic_errno));
2062@@ -2380,7 +2380,7 @@ if (!ok) ok = TRUE; else
2063
2064 if (
2065 #ifndef EXPERIMENTAL_EVENT
2066- (log_extra_selector & LX_smtp_confirmation) != 0 &&
2067+ LOGGING(smtp_confirmation) &&
2068 #endif
2069 !lmtp
2070 )
2071@@ -2435,7 +2435,7 @@ if (!ok) ok = TRUE; else
2072 continue;
2073 }
2074 completed_address = TRUE; /* NOW we can set this flag */
2075- if ((log_extra_selector & LX_smtp_confirmation) != 0)
2076+ if (LOGGING(smtp_confirmation))
2077 {
2078 const uschar *s = string_printing(buffer);
2079 /* deconst cast ok here as string_printing was checked to have alloc'n'copied */
2080diff --git a/src/src/verify.c b/src/src/verify.c
2081index e00e7b9..7992d58 100644
2082--- a/src/src/verify.c
2083+++ b/src/src/verify.c
2084@@ -2916,7 +2916,7 @@ if (ip_bind(sock, host_af, interface_address, 0) < 0)
2085 if (ip_connect(sock, host_af, sender_host_address, port, rfc1413_query_timeout)
2086 < 0)
2087 {
2088- if (errno == ETIMEDOUT && (log_extra_selector & LX_ident_timeout) != 0)
2089+ if (errno == ETIMEDOUT && LOGGING(ident_timeout))
2090 {
2091 log_write(0, LOG_MAIN, "ident connection to %s timed out",
2092 sender_host_address);
2093
2094commit ac881e2749754fbe167b5f38784dd85b088571cf
2095Author: Tony Finch <dot@dotat.at>
2096Date: Thu Aug 13 15:16:51 2015 +0100
2097
2098 Improve the consistency of logging incoming and outgoing interfaces.
2099
2100 The I= interface field on outgoing lines is now after the H= remote
2101 host field, same as incoming lines. There is a separate outgoing_interface
2102 log selector which allows you to disable the outgoing I= field.
2103
2104 (slight massaging by JH)
2105
2106diff --git a/src/src/deliver.c b/src/src/deliver.c
2107index c796de0..0e7cea3 100644
2108--- a/src/src/deliver.c
2109+++ b/src/src/deliver.c
2110@@ -676,39 +676,78 @@ while (addr->parent != NULL)
2111
2112
2113
2114+/*************************************************
2115+* Delivery logging support functions *
2116+*************************************************/
2117+
2118+/* The LOGGING() checks in d_log_interface() are complicated for backwards
2119+compatibility. When outgoing interface logging was originally added, it was
2120+conditional on just incoming_interface (which is off by default). The
2121+outgoing_interface option is on by default to preserve this behaviour, but
2122+you can enable incoming_interface and disable outgoing_interface to get I=
2123+fields on incoming lines only.
2124+
2125+Arguments:
2126+ s The log line buffer
2127+ sizep Pointer to the buffer size
2128+ ptrp Pointer to current index into buffer
2129+ addr The address to be logged
2130+
2131+Returns: New value for s
2132+*/
2133
2134 static uschar *
2135-d_hostlog(uschar * s, int * sizep, int * ptrp, address_item * addr)
2136+d_log_interface(uschar *s, int *sizep, int *ptrp)
2137 {
2138- s = string_append(s, sizep, ptrp, 5, US" H=", addr->host_used->name,
2139- US" [", addr->host_used->address, US"]");
2140+if (LOGGING(incoming_interface) && LOGGING(outgoing_interface)
2141+ && sending_ip_address != NULL)
2142+ {
2143+ s = string_append(s, sizep, ptrp, 2, US" I=[", sending_ip_address);
2144 if (LOGGING(outgoing_port))
2145- s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d",
2146- addr->host_used->port));
2147- return s;
2148+ s = string_append(s, sizep, ptrp, 2, US"]:",
2149+ string_sprintf("%d", sending_port));
2150+ else
2151+ s = string_cat(s, sizep, ptrp, "]", 1);
2152+ }
2153+return s;
2154 }
2155
2156+
2157+
2158+static uschar *
2159+d_hostlog(uschar *s, int *sizep, int *ptrp, address_item *addr)
2160+{
2161+s = string_append(s, sizep, ptrp, 5, US" H=", addr->host_used->name,
2162+ US" [", addr->host_used->address, US"]");
2163+if (LOGGING(outgoing_port))
2164+ s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d",
2165+ addr->host_used->port));
2166+return d_log_interface(s, sizep, ptrp);
2167+}
2168+
2169+
2170+
2171 #ifdef SUPPORT_TLS
2172 static uschar *
2173 d_tlslog(uschar * s, int * sizep, int * ptrp, address_item * addr)
2174 {
2175- if (LOGGING(tls_cipher) && addr->cipher != NULL)
2176- s = string_append(s, sizep, ptrp, 2, US" X=", addr->cipher);
2177- if (LOGGING(tls_certificate_verified) && addr->cipher != NULL)
2178- s = string_append(s, sizep, ptrp, 2, US" CV=",
2179- testflag(addr, af_cert_verified)
2180- ?
2181+if (LOGGING(tls_cipher) && addr->cipher != NULL)
2182+ s = string_append(s, sizep, ptrp, 2, US" X=", addr->cipher);
2183+if (LOGGING(tls_certificate_verified) && addr->cipher != NULL)
2184+ s = string_append(s, sizep, ptrp, 2, US" CV=",
2185+ testflag(addr, af_cert_verified)
2186+ ?
2187 #ifdef EXPERIMENTAL_DANE
2188- testflag(addr, af_dane_verified)
2189- ? "dane"
2190- :
2191+ testflag(addr, af_dane_verified)
2192+ ? "dane"
2193+ :
2194 #endif
2195- "yes"
2196- : "no");
2197- if (LOGGING(tls_peerdn) && addr->peerdn != NULL)
2198- s = string_append(s, sizep, ptrp, 3, US" DN=\"",
2199- string_printing(addr->peerdn), US"\"");
2200- return s;
2201+ "yes"
2202+ : "no");
2203+if (LOGGING(tls_peerdn) && addr->peerdn != NULL)
2204+ s = string_append(s, sizep, ptrp, 3, US" DN=\"",
2205+ string_printing(addr->peerdn), US"\"");
2206+return s;
2207 }
2208 #endif
2209
2210@@ -816,10 +855,6 @@ else
2211 s = string_append(s, &size, &ptr, 2, US"> ", log_address);
2212 }
2213
2214-if (LOGGING(incoming_interface) && sending_ip_address)
2215- s = string_append(s, &size, &ptr, 3, US" I=[", sending_ip_address, US"]");
2216- /* for the port: string_sprintf("%d", sending_port) */
2217-
2218 if (LOGGING(sender_on_delivery) || msg)
2219 s = string_append(s, &size, &ptr, 3, US" F=<",
2220 #ifdef EXPERIMENTAL_INTERNATIONAL
2221@@ -862,6 +897,7 @@ if (addr->transport->info->local)
2222 {
2223 if (addr->host_list)
2224 s = string_append(s, &size, &ptr, 2, US" H=", addr->host_list->name);
2225+ s = d_log_interface(s, &size, &ptr);
2226 if (addr->shadow_message != NULL)
2227 s = string_cat(s, &size, &ptr, addr->shadow_message,
2228 Ustrlen(addr->shadow_message));
2229diff --git a/src/src/globals.c b/src/src/globals.c
2230index 1344b5a..4188b4d 100644
2231--- a/src/src/globals.c
2232+++ b/src/src/globals.c
2233@@ -827,6 +827,7 @@ int log_default[] = { /* for initializing log_selector */
2234 Li_etrn,
2235 Li_host_lookup_failed,
2236 Li_lost_incoming_connection,
2237+ Li_outgoing_interface, /* see d_log_interface in deliver.c */
2238 Li_queue_run,
2239 Li_rejected_header,
2240 Li_retry_defer,
2241@@ -863,6 +864,7 @@ bit_table log_options[] = { /* must be in alphabetical order */
2242 BIT_TABLE(L, incoming_interface),
2243 BIT_TABLE(L, incoming_port),
2244 BIT_TABLE(L, lost_incoming_connection),
2245+ BIT_TABLE(L, outgoing_interface),
2246 BIT_TABLE(L, outgoing_port),
2247 BIT_TABLE(L, pid),
2248 #ifdef EXPERIMENTAL_PROXY
2249diff --git a/src/src/log.c b/src/src/log.c
2250index b2d1fcf..558c000 100644
2251--- a/src/src/log.c
2252+++ b/src/src/log.c
2253@@ -753,8 +753,8 @@ DEBUG(D_any|D_v)
2254
2255 for (i = 0; i < log_options_count; i++)
2256 {
2257- unsigned int bit = log_options[i].bit;
2258- if (bit < BITWORDSIZE && selector == BIT(bit))
2259+ unsigned int bitnum = log_options[i].bit;
2260+ if (bitnum < BITWORDSIZE && selector == BIT(bitnum))
2261 {
2262 *ptr++ = ' ';
2263 Ustrcpy(ptr, log_options[i].name);
2264diff --git a/src/src/macros.h b/src/src/macros.h
2265index d63025e..0ce24f8 100644
2266--- a/src/src/macros.h
2267+++ b/src/src/macros.h
2268@@ -474,8 +474,9 @@ enum {
2269 Li_8bitmime,
2270 Li_smtp_mailauth,
2271 Li_proxy,
2272+ Li_outgoing_interface,
2273
2274- log_selector_size = BITWORD(Li_proxy) + 1
2275+ log_selector_size = BITWORD(Li_outgoing_interface) + 1
2276 };
2277
2278 #define LOGGING(opt) BIT_TEST(log_selector, log_selector_size, Li_##opt)
2279
2280commit 6b51df8340eacc95e3def9a4376506610e91996c
2281Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
2282Date: Wed Aug 19 15:22:41 2015 +0200
2283
2284 Fix post-transport-crash.
2285
2286 The crash probably was introduced in a39bd74d3e94 and
2287 needs 'split_spool_directory=yes' to expose.
2288
2289 Thanks to Wolfgang Breyha, who found the same fix.
2290
2291diff --git a/src/src/transport.c b/src/src/transport.c
2292index fa6f869..a6ad3ed 100644
2293--- a/src/src/transport.c
2294+++ b/src/src/transport.c
2295@@ -1752,7 +1752,7 @@ while (1)
2296 {
2297 if (split_spool_directory)
2298 sprintf(CS spool_file, "%s%c/%s-D",
2299- spool_dir, new_message_id[5], msgq[i].message_id);
2300+ spool_dir, msgq[i].message_id[5], msgq[i].message_id);
2301 else
2302 sprintf(CS spool_file, "%s%s-D", spool_dir, msgq[i].message_id);
2303
2304
2305commit b20b82a0b4169cb23380a373ed2a898b0cb337d2
2306Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
2307Date: Fri Aug 21 12:26:50 2015 +0200
2308
2309 Add a .ctags file to src
2310
2311diff --git a/src/.ctags b/src/.ctags
2312new file mode 100644
2313index 0000000..c764086
2314--- /dev/null
2315+++ b/src/.ctags
2316@@ -0,0 +1,2 @@
2317+--recurse
2318+--exclude=build-*
2319
2320commit dadff1d47e54962b0fdf98e8ce5cef42b6cb7fb5
2321Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
2322Date: Thu Aug 20 13:58:06 2015 +0200
2323
2324 Fix post-transport-crash: safeguard for missing spool BUG 1671
2325
2326 Based on a proposal from Wolfgang Breyha.
2327
2328diff --git a/src/src/deliver.c b/src/src/deliver.c
2329index 0e7cea3..b5aa9b9 100644
2330--- a/src/src/deliver.c
2331+++ b/src/src/deliver.c
2332@@ -9,6 +9,7 @@
2333
2334
2335 #include "exim.h"
2336+#include <assert.h>
2337
2338
2339 /* Data block for keeping track of subprocesses for parallel remote
2340@@ -7934,17 +7935,36 @@ if (!regex_IGNOREQUOTA) regex_IGNOREQUOTA =
2341 uschar *
2342 deliver_get_sender_address (uschar * id)
2343 {
2344+int rc;
2345+uschar * new_sender_address,
2346+ * save_sender_address;
2347+
2348 if (!spool_open_datafile(id))
2349 return NULL;
2350
2351+/* Save and restore the global sender_address. I'm not sure if we should
2352+not save/restore all the other global variables too, because
2353+spool_read_header() may change all of them. But OTOH, when this
2354+deliver_get_sender_address() gets called, the current message is done
2355+already and nobody needs the globals anymore. (HS12, 2015-08-21) */
2356+
2357 sprintf(CS spoolname, "%s-H", id);
2358-if (spool_read_header(spoolname, TRUE, TRUE) != spool_read_OK)
2359+save_sender_address = sender_address;
2360+
2361+rc = spool_read_header(spoolname, TRUE, TRUE);
2362+
2363+new_sender_address = sender_address;
2364+sender_address = save_sender_address;
2365+
2366+if (rc != spool_read_OK)
2367 return NULL;
2368
2369+assert(new_sender_address);
2370+
2371 (void)close(deliver_datafile);
2372 deliver_datafile = -1;
2373
2374-return sender_address;
2375+return new_sender_address;
2376 }
2377
2378 /* vi: aw ai sw=2
2379diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
2380index 609dba3..c93f2ef 100644
2381--- a/src/src/transports/smtp.c
2382+++ b/src/src/transports/smtp.c
2383@@ -1274,14 +1274,19 @@ we will veto this new message. */
2384 static BOOL
2385 smtp_are_same_identities(uschar * message_id, smtp_compare_t * s_compare)
2386 {
2387-uschar * save_sender_address = sender_address;
2388-uschar * current_local_identity =
2389+
2390+uschar * message_local_identity,
2391+ * current_local_identity,
2392+ * new_sender_address;
2393+
2394+current_local_identity =
2395 smtp_local_identity(s_compare->current_sender_address, s_compare->tblock);
2396-uschar * new_sender_address = deliver_get_sender_address(message_id);
2397-uschar * message_local_identity =
2398- smtp_local_identity(new_sender_address, s_compare->tblock);
2399
2400-sender_address = save_sender_address;
2401+if (!(new_sender_address = deliver_get_sender_address(message_id)))
2402+ return 0;
2403+
2404+message_local_identity =
2405+ smtp_local_identity(new_sender_address, s_compare->tblock);
2406
2407 return Ustrcmp(current_local_identity, message_local_identity) == 0;
2408 }
2409
2410commit 3703d8187af01d13ca71f7918c7ef78529bb784d
2411Author: Jeremy Harris <jgh146exb@wizmail.org>
2412Date: Fri Aug 21 18:08:39 2015 +0100
2413
2414 Remember the fail reason for verify=headers_syntax. Bug 264
2415
2416diff --git a/src/src/acl.c b/src/src/acl.c
2417index f2e0ef2..064ee6c 100644
2418--- a/src/src/acl.c
2419+++ b/src/src/acl.c
2420@@ -1803,27 +1803,27 @@ switch(vp->value)
2421 test whether it was successful or not. (This is for optional verification; for
2422 mandatory verification, the connection doesn't last this long.) */
2423
2424- if (tls_in.certificate_verified) return OK;
2425- *user_msgptr = US"no verified certificate";
2426- return FAIL;
2427+ if (tls_in.certificate_verified) return OK;
2428+ *user_msgptr = US"no verified certificate";
2429+ return FAIL;
2430
2431 case VERIFY_HELO:
2432 /* We can test the result of optional HELO verification that might have
2433 occurred earlier. If not, we can attempt the verification now. */
2434
2435- if (!helo_verified && !helo_verify_failed) smtp_verify_helo();
2436- return helo_verified? OK : FAIL;
2437+ if (!helo_verified && !helo_verify_failed) smtp_verify_helo();
2438+ return helo_verified? OK : FAIL;
2439
2440 case VERIFY_CSA:
2441 /* Do Client SMTP Authorization checks in a separate function, and turn the
2442 result code into user-friendly strings. */
2443
2444- rc = acl_verify_csa(list);
2445- *log_msgptr = *user_msgptr = string_sprintf("client SMTP authorization %s",
2446+ rc = acl_verify_csa(list);
2447+ *log_msgptr = *user_msgptr = string_sprintf("client SMTP authorization %s",
2448 csa_reason_string[rc]);
2449- csa_status = csa_status_string[rc];
2450- DEBUG(D_acl) debug_printf("CSA result %s\n", csa_status);
2451- return csa_return_code[rc];
2452+ csa_status = csa_status_string[rc];
2453+ DEBUG(D_acl) debug_printf("CSA result %s\n", csa_status);
2454+ return csa_return_code[rc];
2455
2456 case VERIFY_HDR_SYNTAX:
2457 /* Check that all relevant header lines have the correct syntax. If there is
2458@@ -1832,8 +1832,11 @@ switch(vp->value)
2459 always). */
2460
2461 rc = verify_check_headers(log_msgptr);
2462- if (rc != OK && smtp_return_error_details && *log_msgptr != NULL)
2463- *user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr);
2464+ if (rc != OK && *log_msgptr)
2465+ if (smtp_return_error_details)
2466+ *user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr);
2467+ else
2468+ acl_verify_message = *log_msgptr;
2469 return rc;
2470
2471 case VERIFY_HDR_NAMES_ASCII:
2472@@ -3788,7 +3791,8 @@ for (; cb != NULL; cb = cb->next)
2473
2474 case ACLC_VERIFY:
2475 rc = acl_verify(where, addr, arg, user_msgptr, log_msgptr, basic_errno);
2476- acl_verify_message = *user_msgptr;
2477+ if (*user_msgptr)
2478+ acl_verify_message = *user_msgptr;
2479 if (verb == ACL_WARN) *user_msgptr = NULL;
2480 break;
2481
2482
2483commit c8899c20aa08c9ae6a4c291aad23ba90512bebe4
2484Author: Jeremy Harris <jgh146exb@wizmail.org>
2485Date: Tue Aug 25 10:36:27 2015 +0100
2486
2487 Close logs after daemon-process exceptional write. Bug 728
2488
2489diff --git a/src/src/daemon.c b/src/src/daemon.c
2490index 2d10387..e1ff9a1 100644
2491--- a/src/src/daemon.c
2492+++ b/src/src/daemon.c
2493@@ -735,6 +735,7 @@ else (void)close(dup_accept_socket);
2494 /* Release any store used in this process, including the store used for holding
2495 the incoming host address and an expanded active_hostname. */
2496
2497+log_close_all();
2498 store_reset(reset_point);
2499 sender_host_address = NULL;
2500 }
2501
2502commit f38917cc94ab337c15ff70c254dd564ee2dcafe7
2503Author: Jeremy Harris <jgh146exb@wizmail.org>
2504Date: Tue Sep 8 23:05:20 2015 +0100
2505
2506 Capture substrings in ACL regex= . Bug 425.
2507
2508diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
2509index c33e098..596e651 100644
2510--- a/src/src/config.h.defaults
2511+++ b/src/src/config.h.defaults
2512@@ -116,6 +116,8 @@ it's a default value. */
2513 #define RADIUS_CONFIG_FILE
2514 #define RADIUS_LIB_TYPE
2515
2516+#define REGEX_VARS 9
2517+
2518 #define ROUTER_ACCEPT
2519 #define ROUTER_DNSLOOKUP
2520 #define ROUTER_IPLITERAL
2521diff --git a/src/src/exim.c b/src/src/exim.c
2522index d7cb5d8..999b94c 100644
2523--- a/src/src/exim.c
2524+++ b/src/src/exim.c
2525@@ -1753,6 +1753,8 @@ regex_whitelisted_macro =
2526 regex_must_compile(US"^[A-Za-z0-9_/.-]*$", FALSE, TRUE);
2527 #endif
2528
2529+for (i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL;
2530+
2531
2532 /* If the program is called as "mailq" treat it as equivalent to "exim -bp";
2533 this seems to be a generally accepted convention, since one finds symbolic
2534diff --git a/src/src/expand.c b/src/src/expand.c
2535index 89e0ac7..1bff521 100644
2536--- a/src/src/expand.c
2537+++ b/src/src/expand.c
2538@@ -1726,7 +1726,14 @@ if (Ustrncmp(name, "auth", 4) == 0)
2539 uschar *endptr;
2540 int n = Ustrtoul(name + 4, &endptr, 10);
2541 if (*endptr == 0 && n != 0 && n <= AUTH_VARS)
2542- return (auth_vars[n-1] == NULL)? US"" : auth_vars[n-1];
2543+ return !auth_vars[n-1] ? US"" : auth_vars[n-1];
2544+ }
2545+else if (Ustrncmp(name, "regex", 5) == 0)
2546+ {
2547+ uschar *endptr;
2548+ int n = Ustrtoul(name + 5, &endptr, 10);
2549+ if (*endptr == 0 && n != 0 && n <= REGEX_VARS)
2550+ return !regex_vars[n-1] ? US"" : regex_vars[n-1];
2551 }
2552
2553 /* For all other variables, search the table */
2554diff --git a/src/src/globals.c b/src/src/globals.c
2555index 4188b4d..8445f00 100644
2556--- a/src/src/globals.c
2557+++ b/src/src/globals.c
2558@@ -1090,8 +1090,9 @@ const pcre *regex_From = NULL;
2559 const pcre *regex_IGNOREQUOTA = NULL;
2560 const pcre *regex_PIPELINING = NULL;
2561 const pcre *regex_SIZE = NULL;
2562-const pcre *regex_smtp_code = NULL;
2563 const pcre *regex_ismsgid = NULL;
2564+const pcre *regex_smtp_code = NULL;
2565+uschar *regex_vars[REGEX_VARS];
2566 #ifdef WHITELIST_D_MACROS
2567 const pcre *regex_whitelisted_macro = NULL;
2568 #endif
2569diff --git a/src/src/globals.h b/src/src/globals.h
2570index 978a4cc..3c69e43 100644
2571--- a/src/src/globals.h
2572+++ b/src/src/globals.h
2573@@ -717,8 +717,9 @@ extern const pcre *regex_From; /* For recognizing "From_" lines */
2574 extern const pcre *regex_IGNOREQUOTA; /* For recognizing IGNOREQUOTA (LMTP) */
2575 extern const pcre *regex_PIPELINING; /* For recognizing PIPELINING */
2576 extern const pcre *regex_SIZE; /* For recognizing SIZE settings */
2577-extern const pcre *regex_smtp_code; /* For recognizing SMTP codes */
2578 extern const pcre *regex_ismsgid; /* Compiled r.e. for message it */
2579+extern const pcre *regex_smtp_code; /* For recognizing SMTP codes */
2580+extern uschar *regex_vars[]; /* $regexN variables */
2581 #ifdef WHITELIST_D_MACROS
2582 extern const pcre *regex_whitelisted_macro; /* For -D macro values */
2583 #endif
2584diff --git a/src/src/regex.c b/src/src/regex.c
2585index ed73b6e..93422fa 100644
2586--- a/src/src/regex.c
2587+++ b/src/src/regex.c
2588@@ -25,109 +25,120 @@ uschar regex_match_string_buffer[1024];
2589 extern FILE *mime_stream;
2590 extern uschar *mime_current_boundary;
2591
2592-int
2593-regex(const uschar **listptr)
2594+static pcre_list *
2595+compile(const uschar * list)
2596 {
2597 int sep = 0;
2598- const uschar *list = *listptr;
2599 uschar *regex_string;
2600 uschar regex_string_buffer[1024];
2601- unsigned long mbox_size;
2602- FILE *mbox_file;
2603- pcre *re;
2604- pcre_list *re_list_head = NULL;
2605- pcre_list *re_list_item;
2606 const char *pcre_error;
2607 int pcre_erroffset;
2608+ pcre_list *re_list_head = NULL;
2609+ pcre_list *ri;
2610+
2611+ /* precompile our regexes */
2612+ while ((regex_string = string_nextinlist(&list, &sep,
2613+ regex_string_buffer,
2614+ sizeof(regex_string_buffer))) != NULL) {
2615+ pcre *re;
2616+
2617+ /* parse option */
2618+ if ( (strcmpic(regex_string,US"false") == 0) ||
2619+ (Ustrcmp(regex_string,"0") == 0) )
2620+ continue; /* explicitly no matching */
2621+
2622+ /* compile our regular expression */
2623+ if (!(re = pcre_compile( CS regex_string,
2624+ 0, &pcre_error, &pcre_erroffset, NULL ))) {
2625+ log_write(0, LOG_MAIN,
2626+ "regex acl condition warning - error in regex '%s': %s at offset %d, skipped.",
2627+ regex_string, pcre_error, pcre_erroffset);
2628+ continue;
2629+ }
2630+
2631+ ri = store_get(sizeof(pcre_list));
2632+ ri->re = re;
2633+ ri->pcre_text = string_copy(regex_string);
2634+ ri->next = re_list_head;
2635+ re_list_head = ri;
2636+ }
2637+ return re_list_head;
2638+}
2639+
2640+static int
2641+matcher(pcre_list * re_list_head, uschar * linebuffer, int len)
2642+{
2643+ pcre_list * ri;
2644+
2645+ for(ri = re_list_head; ri; ri = ri->next)
2646+ {
2647+ int ovec[3*(REGEX_VARS+1)];
2648+ int n, nn;
2649+
2650+ /* try matcher on the line */
2651+ n = pcre_exec(ri->re, NULL,
2652+ CS linebuffer, len, 0, 0,
2653+ ovec, nelem(ovec));
2654+ if (n > 0)
2655+ {
2656+ Ustrncpy(regex_match_string_buffer, ri->pcre_text, 1023);
2657+ regex_match_string = regex_match_string_buffer;
2658+
2659+ for (nn = 1; nn < n; nn++)
2660+ regex_vars[nn-1] =
2661+ string_copyn(linebuffer + ovec[nn*2], ovec[nn*2+1] - ovec[nn*2]);
2662+
2663+ return OK;
2664+ }
2665+ }
2666+ return FAIL;
2667+}
2668+
2669+int
2670+regex(const uschar **listptr)
2671+{
2672+ unsigned long mbox_size;
2673+ FILE *mbox_file;
2674+ pcre_list *re_list_head;
2675 uschar *linebuffer;
2676 long f_pos = 0;
2677+ int ret = FAIL;
2678
2679 /* reset expansion variable */
2680 regex_match_string = NULL;
2681
2682- if (mime_stream == NULL) {
2683- /* We are in the DATA ACL */
2684+ if (mime_stream == NULL) { /* We are in the DATA ACL */
2685 mbox_file = spool_mbox(&mbox_size, NULL);
2686- if (mbox_file == NULL) {
2687- /* error while spooling */
2688+ if (mbox_file == NULL) { /* error while spooling */
2689 log_write(0, LOG_MAIN|LOG_PANIC,
2690 "regex acl condition: error while creating mbox spool file");
2691 return DEFER;
2692- };
2693+ }
2694 }
2695 else {
2696 f_pos = ftell(mime_stream);
2697 mbox_file = mime_stream;
2698- };
2699+ }
2700
2701 /* precompile our regexes */
2702- while ((regex_string = string_nextinlist(&list, &sep,
2703- regex_string_buffer,
2704- sizeof(regex_string_buffer))) != NULL) {
2705-
2706- /* parse option */
2707- if ( (strcmpic(regex_string,US"false") == 0) ||
2708- (Ustrcmp(regex_string,"0") == 0) ) {
2709- /* explicitly no matching */
2710- continue;
2711- };
2712-
2713- /* compile our regular expression */
2714- re = pcre_compile( CS regex_string,
2715- 0,
2716- &pcre_error,
2717- &pcre_erroffset,
2718- NULL );
2719-
2720- if (re == NULL) {
2721- log_write(0, LOG_MAIN,
2722- "regex acl condition warning - error in regex '%s': %s at offset %d, skipped.", regex_string, pcre_error, pcre_erroffset);
2723- continue;
2724- }
2725- else {
2726- re_list_item = store_get(sizeof(pcre_list));
2727- re_list_item->re = re;
2728- re_list_item->pcre_text = string_copy(regex_string);
2729- re_list_item->next = re_list_head;
2730- re_list_head = re_list_item;
2731- };
2732- };
2733-
2734- /* no regexes -> nothing to do */
2735- if (re_list_head == NULL) {
2736- return FAIL;
2737- };
2738+ if (!(re_list_head = compile(*listptr)))
2739+ return FAIL; /* no regexes -> nothing to do */
2740
2741 /* match each line against all regexes */
2742 linebuffer = store_get(32767);
2743 while (fgets(CS linebuffer, 32767, mbox_file) != NULL) {
2744- if ( (mime_stream != NULL) && (mime_current_boundary != NULL) ) {
2745- /* check boundary */
2746- if (Ustrncmp(linebuffer,"--",2) == 0) {
2747- if (Ustrncmp((linebuffer+2),mime_current_boundary,Ustrlen(mime_current_boundary)) == 0)
2748- /* found boundary */
2749- break;
2750- };
2751- };
2752- re_list_item = re_list_head;
2753- do {
2754- /* try matcher on the line */
2755- if (pcre_exec(re_list_item->re, NULL, CS linebuffer,
2756- (int)Ustrlen(linebuffer), 0, 0, NULL, 0) >= 0) {
2757- Ustrncpy(regex_match_string_buffer, re_list_item->pcre_text, 1023);
2758- regex_match_string = regex_match_string_buffer;
2759- if (mime_stream == NULL)
2760- (void)fclose(mbox_file);
2761- else {
2762- clearerr(mime_stream);
2763- fseek(mime_stream,f_pos,SEEK_SET);
2764- };
2765- return OK;
2766- };
2767- re_list_item = re_list_item->next;
2768- } while (re_list_item != NULL);
2769- };
2770
2771+ if ( mime_stream && mime_current_boundary /* check boundary */
2772+ && Ustrncmp(linebuffer,"--",2) == 0
2773+ && Ustrncmp((linebuffer+2),mime_current_boundary,Ustrlen(mime_current_boundary)) == 0)
2774+ break; /* found boundary */
2775+
2776+ if ((ret = matcher(re_list_head, linebuffer, (int)Ustrlen(linebuffer))) == OK)
2777+ goto done;
2778+ }
2779+ /* no matches ... */
2780+
2781+done:
2782 if (mime_stream == NULL)
2783 (void)fclose(mbox_file);
2784 else {
2785@@ -135,67 +146,25 @@ regex(const uschar **listptr)
2786 fseek(mime_stream,f_pos,SEEK_SET);
2787 };
2788
2789- /* no matches ... */
2790- return FAIL;
2791+ return ret;
2792 }
2793
2794
2795 int
2796 mime_regex(const uschar **listptr)
2797 {
2798- int sep = 0;
2799- const uschar *list = *listptr;
2800- uschar *regex_string;
2801- uschar regex_string_buffer[1024];
2802- pcre *re;
2803 pcre_list *re_list_head = NULL;
2804- pcre_list *re_list_item;
2805- const char *pcre_error;
2806- int pcre_erroffset;
2807 FILE *f;
2808 uschar *mime_subject = NULL;
2809 int mime_subject_len = 0;
2810+ int ret;
2811
2812 /* reset expansion variable */
2813 regex_match_string = NULL;
2814
2815 /* precompile our regexes */
2816- while ((regex_string = string_nextinlist(&list, &sep,
2817- regex_string_buffer,
2818- sizeof(regex_string_buffer))) != NULL) {
2819-
2820- /* parse option */
2821- if ( (strcmpic(regex_string,US"false") == 0) ||
2822- (Ustrcmp(regex_string,"0") == 0) ) {
2823- /* explicitly no matching */
2824- continue;
2825- };
2826-
2827- /* compile our regular expression */
2828- re = pcre_compile( CS regex_string,
2829- 0,
2830- &pcre_error,
2831- &pcre_erroffset,
2832- NULL );
2833-
2834- if (re == NULL) {
2835- log_write(0, LOG_MAIN,
2836- "regex acl condition warning - error in regex '%s': %s at offset %d, skipped.", regex_string, pcre_error, pcre_erroffset);
2837- continue;
2838- }
2839- else {
2840- re_list_item = store_get(sizeof(pcre_list));
2841- re_list_item->re = re;
2842- re_list_item->pcre_text = string_copy(regex_string);
2843- re_list_item->next = re_list_head;
2844- re_list_head = re_list_item;
2845- };
2846- };
2847-
2848- /* no regexes -> nothing to do */
2849- if (re_list_head == NULL) {
2850- return FAIL;
2851- };
2852+ if (!(re_list_head = compile(*listptr)))
2853+ return FAIL; /* no regexes -> nothing to do */
2854
2855 /* check if the file is already decoded */
2856 if (mime_decoded_filename == NULL) {
2857@@ -207,43 +176,25 @@ mime_regex(const uschar **listptr)
2858 log_write(0, LOG_MAIN,
2859 "mime_regex acl condition warning - could not decode MIME part to file.");
2860 return DEFER;
2861- };
2862- };
2863-
2864+ }
2865+ }
2866
2867 /* open file */
2868- f = fopen(CS mime_decoded_filename, "rb");
2869- if (f == NULL) {
2870- /* open failed */
2871+ if (!(f = fopen(CS mime_decoded_filename, "rb"))) {
2872 log_write(0, LOG_MAIN,
2873- "mime_regex acl condition warning - can't open '%s' for reading.", mime_decoded_filename);
2874+ "mime_regex acl condition warning - can't open '%s' for reading.",
2875+ mime_decoded_filename);
2876 return DEFER;
2877- };
2878+ }
2879
2880 /* get 32k memory */
2881 mime_subject = (uschar *)store_get(32767);
2882
2883- /* read max 32k chars from file */
2884 mime_subject_len = fread(mime_subject, 1, 32766, f);
2885
2886- re_list_item = re_list_head;
2887- do {
2888- /* try matcher on the mmapped file */
2889- debug_printf("Matching '%s'\n", re_list_item->pcre_text);
2890- if (pcre_exec(re_list_item->re, NULL, CS mime_subject,
2891- mime_subject_len, 0, 0, NULL, 0) >= 0) {
2892- Ustrncpy(regex_match_string_buffer, re_list_item->pcre_text, 1023);
2893- regex_match_string = regex_match_string_buffer;
2894- (void)fclose(f);
2895- return OK;
2896- };
2897- re_list_item = re_list_item->next;
2898- } while (re_list_item != NULL);
2899-
2900+ ret = matcher(re_list_head, mime_subject, mime_subject_len);
2901 (void)fclose(f);
2902-
2903- /* no matches ... */
2904- return FAIL;
2905+ return ret;
2906 }
2907
2908 #endif /* WITH_CONTENT_SCAN */
2909
2910commit 895fbaf26d3450d4eeacbad8fe04c328a77645f0
2911Author: Jeremy Harris <jgh146exb@wizmail.org>
2912Date: Wed Sep 9 16:03:38 2015 +0100
2913
2914 DSN: Under EXPERIMENTAL_DSN_INFO add extras to bounce messages. Bug 1686
2915
2916diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
2917index 596e651..6af3b4d 100644
2918--- a/src/src/config.h.defaults
2919+++ b/src/src/config.h.defaults
2920@@ -172,6 +172,7 @@ it's a default value. */
2921 #define EXPERIMENTAL_BRIGHTMAIL
2922 #define EXPERIMENTAL_DANE
2923 #define EXPERIMENTAL_DCC
2924+#define EXPERIMENTAL_DSN_INFO
2925 #define EXPERIMENTAL_DMARC
2926 #define EXPERIMENTAL_EVENT
2927 #define EXPERIMENTAL_INTERNATIONAL
2928diff --git a/src/src/deliver.c b/src/src/deliver.c
2929index b5aa9b9..3f22dc9 100644
2930--- a/src/src/deliver.c
2931+++ b/src/src/deliver.c
2932@@ -3223,41 +3223,56 @@ while (!done)
2933 break;
2934 }
2935
2936- addr->transport_return = *ptr++;
2937- addr->special_action = *ptr++;
2938- memcpy(&(addr->basic_errno), ptr, sizeof(addr->basic_errno));
2939- ptr += sizeof(addr->basic_errno);
2940- memcpy(&(addr->more_errno), ptr, sizeof(addr->more_errno));
2941- ptr += sizeof(addr->more_errno);
2942- memcpy(&(addr->flags), ptr, sizeof(addr->flags));
2943- ptr += sizeof(addr->flags);
2944- addr->message = (*ptr)? string_copy(ptr) : NULL;
2945- while(*ptr++);
2946- addr->user_message = (*ptr)? string_copy(ptr) : NULL;
2947- while(*ptr++);
2948-
2949- /* Always two strings for host information, followed by the port number and DNSSEC mark */
2950-
2951- if (*ptr != 0)
2952+ switch (subid)
2953 {
2954- h = store_get(sizeof(host_item));
2955- h->name = string_copy(ptr);
2956- while (*ptr++);
2957- h->address = string_copy(ptr);
2958- while(*ptr++);
2959- memcpy(&(h->port), ptr, sizeof(h->port));
2960- ptr += sizeof(h->port);
2961- h->dnssec = *ptr == '2' ? DS_YES
2962- : *ptr == '1' ? DS_NO
2963- : DS_UNK;
2964- ptr++;
2965- addr->host_used = h;
2966- }
2967- else ptr++;
2968+#ifdef EXPERIMENTAL_DSN_INFO
2969+ case '1': /* must arrive before A0, and applies to that addr */
2970+ /* Two strings: smtp_greeting and helo_response */
2971+ addr->smtp_greeting = string_copy(ptr);
2972+ while(*ptr++);
2973+ addr->helo_response = string_copy(ptr);
2974+ while(*ptr++);
2975+ break;
2976+#endif
2977
2978- /* Finished with this address */
2979+ case '0':
2980+ addr->transport_return = *ptr++;
2981+ addr->special_action = *ptr++;
2982+ memcpy(&(addr->basic_errno), ptr, sizeof(addr->basic_errno));
2983+ ptr += sizeof(addr->basic_errno);
2984+ memcpy(&(addr->more_errno), ptr, sizeof(addr->more_errno));
2985+ ptr += sizeof(addr->more_errno);
2986+ memcpy(&(addr->flags), ptr, sizeof(addr->flags));
2987+ ptr += sizeof(addr->flags);
2988+ addr->message = (*ptr)? string_copy(ptr) : NULL;
2989+ while(*ptr++);
2990+ addr->user_message = (*ptr)? string_copy(ptr) : NULL;
2991+ while(*ptr++);
2992
2993- addr = addr->next;
2994+ /* Always two strings for host information, followed by the port number and DNSSEC mark */
2995+
2996+ if (*ptr != 0)
2997+ {
2998+ h = store_get(sizeof(host_item));
2999+ h->name = string_copy(ptr);
3000+ while (*ptr++);
3001+ h->address = string_copy(ptr);
3002+ while(*ptr++);
3003+ memcpy(&(h->port), ptr, sizeof(h->port));
3004+ ptr += sizeof(h->port);
3005+ h->dnssec = *ptr == '2' ? DS_YES
3006+ : *ptr == '1' ? DS_NO
3007+ : DS_UNK;
3008+ ptr++;
3009+ addr->host_used = h;
3010+ }
3011+ else ptr++;
3012+
3013+ /* Finished with this address */
3014+
3015+ addr = addr->next;
3016+ break;
3017+ }
3018 break;
3019
3020 /* Local interface address/port */
3021@@ -4423,7 +4438,6 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++)
3022
3023 for (r = addr->retries; r != NULL; r = r->next)
3024 {
3025- uschar *ptr;
3026 sprintf(CS big_buffer, "%c%.500s", r->flags, r->key);
3027 ptr = big_buffer + Ustrlen(big_buffer+2) + 3;
3028 memcpy(ptr, &(r->basic_errno), sizeof(r->basic_errno));
3029@@ -4438,11 +4452,31 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++)
3030 rmt_dlv_checked_write(fd, 'R', '0', big_buffer, ptr - big_buffer);
3031 }
3032
3033- /* The rest of the information goes in an 'A' item. */
3034+#ifdef EXPERIMENTAL_DSN_INFO
3035+/*um, are they really per-addr? Other per-conn stuff is not (auth, tls). But host_used is! */
3036+ if (addr->smtp_greeting)
3037+ {
3038+ ptr = big_buffer;
3039+ DEBUG(D_deliver) debug_printf("smtp_greeting '%s'\n", addr->smtp_greeting);
3040+ sprintf(CS ptr, "%.128s", addr->smtp_greeting);
3041+ while(*ptr++);
3042+ if (addr->helo_response)
3043+ {
3044+ DEBUG(D_deliver) debug_printf("helo_response '%s'\n", addr->helo_response);
3045+ sprintf(CS ptr, "%.128s", addr->helo_response);
3046+ while(*ptr++);
3047+ }
3048+ else
3049+ *ptr++ = '\0';
3050+ rmt_dlv_checked_write(fd, 'A', '1', big_buffer, ptr - big_buffer);
3051+ }
3052+#endif
3053+
3054+ /* The rest of the information goes in an 'A0' item. */
3055
3056- ptr = big_buffer + 2;
3057 sprintf(CS big_buffer, "%c%c", addr->transport_return,
3058 addr->special_action);
3059+ ptr = big_buffer + 2;
3060 memcpy(ptr, &(addr->basic_errno), sizeof(addr->basic_errno));
3061 ptr += sizeof(addr->basic_errno);
3062 memcpy(ptr, &(addr->more_errno), sizeof(addr->more_errno));
3063@@ -4480,7 +4514,11 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++)
3064 }
3065
3066 /* Local interface address/port */
3067+#ifdef EXPERIMENTAL_DSN_INFO
3068+ if (sending_ip_address)
3069+#else
3070 if (LOGGING(incoming_interface) && sending_ip_address)
3071+#endif
3072 {
3073 uschar * ptr = big_buffer;
3074 sprintf(CS ptr, "%.128s", sending_ip_address);
3075@@ -7209,16 +7247,32 @@ wording. */
3076
3077 for (addr = handled_addr; addr; addr = addr->next)
3078 {
3079+ host_item * hu;
3080 fprintf(f, "Action: failed\n"
3081 "Final-Recipient: rfc822;%s\n"
3082 "Status: 5.0.0\n",
3083 addr->address);
3084- if (addr->host_used && addr->host_used->name)
3085- {
3086- fprintf(f, "Remote-MTA: dns; %s\n",
3087- addr->host_used->name);
3088- print_dsn_diagnostic_code(addr, f);
3089- }
3090+ if ((hu = addr->host_used) && hu->name)
3091+ {
3092+ const uschar * s;
3093+ fprintf(f, "Remote-MTA: dns; %s\n",
3094+ hu->name);
3095+#ifdef EXPERIMENTAL_DSN_INFO
3096+ if (hu->address)
3097+ {
3098+ uschar * p = hu->port == 25
3099+ ? US"" : string_sprintf(":%d", hu->port);
3100+ fprintf(f, "Remote-MTA: X-ip; [%s]%s\n", hu->address, p);
3101+ }
3102+ if ((s = addr->smtp_greeting) && *s)
3103+ fprintf(f, "X-Remote-MTA-smtp-greeting: X-str; %s\n", s);
3104+ if ((s = addr->helo_response) && *s)
3105+ fprintf(f, "X-Remote-MTA-helo-response: X-str; %s\n", s);
3106+ if ((s = addr->message) && *s)
3107+ fprintf(f, "X-Exim-Diagnostic: X-str; %s\n", s);
3108+#endif
3109+ print_dsn_diagnostic_code(addr, f);
3110+ }
3111 fputc('\n', f);
3112 }
3113
3114diff --git a/src/src/exim.c b/src/src/exim.c
3115index 999b94c..084d649 100644
3116--- a/src/src/exim.c
3117+++ b/src/src/exim.c
3118@@ -847,6 +847,12 @@ fprintf(f, "Support for:");
3119 #ifdef EXPERIMENTAL_DMARC
3120 fprintf(f, " Experimental_DMARC");
3121 #endif
3122+#ifdef EXPERIMENTAL_DSN_INFO
3123+ fprintf(f, " Experimental_DSN_info");
3124+#endif
3125+#ifdef EXPERIMENTAL_INTERNATIONAL
3126+ fprintf(f, " Experimental_International");
3127+#endif
3128 #ifdef EXPERIMENTAL_PROXY
3129 fprintf(f, " Experimental_Proxy");
3130 #endif
3131@@ -859,9 +865,6 @@ fprintf(f, "Support for:");
3132 #ifdef EXPERIMENTAL_SOCKS
3133 fprintf(f, " Experimental_SOCKS");
3134 #endif
3135-#ifdef EXPERIMENTAL_INTERNATIONAL
3136- fprintf(f, " Experimental_International");
3137-#endif
3138 fprintf(f, "\n");
3139
3140 fprintf(f, "Lookups (built-in):");
3141diff --git a/src/src/globals.c b/src/src/globals.c
3142index 8445f00..f3b6791 100644
3143--- a/src/src/globals.c
3144+++ b/src/src/globals.c
3145@@ -354,13 +354,17 @@ address_item address_defaults = {
3146 NULL, /* return_filename */
3147 NULL, /* self_hostname */
3148 NULL, /* shadow_message */
3149- #ifdef SUPPORT_TLS
3150+#ifdef SUPPORT_TLS
3151 NULL, /* cipher */
3152 NULL, /* ourcert */
3153 NULL, /* peercert */
3154 NULL, /* peerdn */
3155 OCSP_NOT_REQ, /* ocsp */
3156- #endif
3157+#endif
3158+#ifdef EXPERIMENTAL_DSN_INFO
3159+ NULL, /* smtp_greeting */
3160+ NULL, /* helo_response */
3161+#endif
3162 NULL, /* authenticator */
3163 NULL, /* auth_id */
3164 NULL, /* auth_sndr */
3165diff --git a/src/src/structs.h b/src/src/structs.h
3166index 438b521..db9e843 100644
3167--- a/src/src/structs.h
3168+++ b/src/src/structs.h
3169@@ -561,13 +561,18 @@ typedef struct address_item {
3170 uschar *self_hostname; /* after self=pass */
3171 uschar *shadow_message; /* info about shadow transporting */
3172
3173- #ifdef SUPPORT_TLS
3174+#ifdef SUPPORT_TLS
3175 uschar *cipher; /* Cipher used for transport */
3176 void *ourcert; /* Certificate offered to peer, binary */
3177 void *peercert; /* Certificate from peer, binary */
3178 uschar *peerdn; /* DN of server's certificate */
3179 int ocsp; /* OCSP status of peer cert */
3180- #endif
3181+#endif
3182+
3183+#ifdef EXPERIMENTAL_DSN_INFO
3184+ const uschar *smtp_greeting; /* peer self-identification */
3185+ const uschar *helo_response; /* peer message */
3186+#endif
3187
3188 uschar *authenticator; /* auth driver name used by transport */
3189 uschar *auth_id; /* auth "login" name used by transport */
3190diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
3191index c93f2ef..ac40460 100644
3192--- a/src/src/transports/smtp.c
3193+++ b/src/src/transports/smtp.c
3194@@ -440,6 +440,8 @@ Arguments:
3195 rc to put in each address's transport_return field
3196 pass_message if TRUE, set the "pass message" flag in the address
3197 host if set, mark addrs as having used this host
3198+ smtp_greeting from peer
3199+ helo_response from peer
3200
3201 If errno_value has the special value ERRNO_CONNECTTIMEOUT, ETIMEDOUT is put in
3202 the errno field, and RTEF_CTOUT is ORed into the more_errno field, to indicate
3203@@ -450,7 +452,11 @@ Returns: nothing
3204
3205 static void
3206 set_errno(address_item *addrlist, int errno_value, uschar *msg, int rc,
3207- BOOL pass_message, host_item * host)
3208+ BOOL pass_message, host_item * host
3209+#ifdef EXPERIMENTAL_DSN_INFO
3210+ , const uschar * smtp_greeting, const uschar * helo_response
3211+#endif
3212+ )
3213 {
3214 address_item *addr;
3215 int orvalue = 0;
3216@@ -459,7 +465,7 @@ if (errno_value == ERRNO_CONNECTTIMEOUT)
3217 errno_value = ETIMEDOUT;
3218 orvalue = RTEF_CTOUT;
3219 }
3220-for (addr = addrlist; addr != NULL; addr = addr->next)
3221+for (addr = addrlist; addr; addr = addr->next)
3222 if (addr->transport_return >= PENDING)
3223 {
3224 addr->basic_errno = errno_value;
3225@@ -471,10 +477,31 @@ for (addr = addrlist; addr != NULL; addr = addr->next)
3226 }
3227 addr->transport_return = rc;
3228 if (host)
3229+ {
3230 addr->host_used = host;
3231+#ifdef EXPERIMENTAL_DSN_INFO
3232+ if (smtp_greeting)
3233+ {uschar * s = Ustrchr(smtp_greeting, '\n'); if (s) *s = '\0';}
3234+ addr->smtp_greeting = smtp_greeting;
3235+
3236+ if (helo_response)
3237+ {uschar * s = Ustrchr(helo_response, '\n'); if (s) *s = '\0';}
3238+ addr->helo_response = helo_response;
3239+#endif
3240+ }
3241 }
3242 }
3243
3244+static void
3245+set_errno_nohost(address_item *addrlist, int errno_value, uschar *msg, int rc,
3246+ BOOL pass_message)
3247+{
3248+set_errno(addrlist, errno_value, msg, rc, pass_message, NULL
3249+#ifdef EXPERIMENTAL_DSN_INFO
3250+ , NULL, NULL
3251+#endif
3252+ );
3253+}
3254
3255
3256 /*************************************************
3257@@ -847,7 +874,7 @@ while (count-- > 0)
3258 {
3259 uschar *message = string_sprintf("SMTP timeout after RCPT TO:<%s>",
3260 transport_rcpt_address(addr, include_affixes));
3261- set_errno(addrlist, ETIMEDOUT, message, DEFER, FALSE, NULL);
3262+ set_errno_nohost(addrlist, ETIMEDOUT, message, DEFER, FALSE);
3263 retry_add_item(addr, addr->address_retry_key, 0);
3264 update_waiting = FALSE;
3265 return -1;
3266@@ -1096,8 +1123,8 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1))
3267 /* Internal problem, message in buffer. */
3268
3269 case ERROR:
3270- set_errno(addrlist, ERRNO_AUTHPROB, string_copy(buffer),
3271- DEFER, FALSE, NULL);
3272+ set_errno_nohost(addrlist, ERRNO_AUTHPROB, string_copy(buffer),
3273+ DEFER, FALSE);
3274 return ERROR;
3275 }
3276
3277@@ -1111,9 +1138,9 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1))
3278
3279 if (require_auth == OK && !smtp_authenticated)
3280 {
3281- set_errno(addrlist, ERRNO_AUTHFAIL,
3282+ set_errno_nohost(addrlist, ERRNO_AUTHFAIL,
3283 string_sprintf("authentication required but %s", fail_reason), DEFER,
3284- FALSE, NULL);
3285+ FALSE);
3286 return DEFER;
3287 }
3288
3289@@ -1152,7 +1179,7 @@ if (ob->authenticated_sender != NULL)
3290 {
3291 uschar *message = string_sprintf("failed to expand "
3292 "authenticated_sender: %s", expand_string_message);
3293- set_errno(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE, NULL);
3294+ set_errno_nohost(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE);
3295 return TRUE;
3296 }
3297 }
3298@@ -1381,6 +1408,10 @@ smtp_outblock outblock;
3299 int max_rcpt = tblock->max_addresses;
3300 uschar *igquotstr = US"";
3301
3302+#ifdef EXPERIMENTAL_DSN_INFO
3303+uschar *smtp_greeting = NULL;
3304+uschar *helo_response = NULL;
3305+#endif
3306 uschar *helo_data = NULL;
3307
3308 uschar *message = NULL;
3309@@ -1432,8 +1463,8 @@ tls_modify_variables(&tls_out);
3310 #ifndef SUPPORT_TLS
3311 if (smtps)
3312 {
3313- set_errno(addrlist, ERRNO_TLSFAILURE, US"TLS support not available",
3314- DEFER, FALSE, NULL);
3315+ set_errno_nohost(addrlist, ERRNO_TLSFAILURE, US"TLS support not available",
3316+ DEFER, FALSE);
3317 return ERROR;
3318 }
3319 #endif
3320@@ -1450,8 +1481,8 @@ if (continue_hostname == NULL)
3321
3322 if (inblock.sock < 0)
3323 {
3324- set_errno(addrlist, (errno == ETIMEDOUT)? ERRNO_CONNECTTIMEOUT : errno,
3325- NULL, DEFER, FALSE, NULL);
3326+ set_errno_nohost(addrlist, (errno == ETIMEDOUT)? ERRNO_CONNECTTIMEOUT : errno,
3327+ NULL, DEFER, FALSE);
3328 return DEFER;
3329 }
3330
3331@@ -1469,18 +1500,18 @@ if (continue_hostname == NULL)
3332 && dane_required /* do not error on only dane-requested */
3333 )
3334 {
3335- set_errno(addrlist, ERRNO_DNSDEFER,
3336+ set_errno_nohost(addrlist, ERRNO_DNSDEFER,
3337 string_sprintf("DANE error: tlsa lookup %s",
3338 rc == DEFER ? "DEFER" : "FAIL"),
3339- rc, FALSE, NULL);
3340+ rc, FALSE);
3341 return rc;
3342 }
3343 }
3344 else if (dane_required)
3345 {
3346- set_errno(addrlist, ERRNO_DNSDEFER,
3347+ set_errno_nohost(addrlist, ERRNO_DNSDEFER,
3348 string_sprintf("DANE error: %s lookup not DNSSEC", host->name),
3349- FAIL, FALSE, NULL);
3350+ FAIL, FALSE);
3351 return FAIL;
3352 }
3353
3354@@ -1501,7 +1532,7 @@ if (continue_hostname == NULL)
3355 if ((helo_data = string_domain_utf8_to_alabel(helo_data, &errstr)), errstr)
3356 {
3357 errstr = string_sprintf("failed to expand helo_data: %s", errstr);
3358- set_errno(addrlist, ERRNO_EXPANDFAIL, errstr, DEFER, FALSE, NULL);
3359+ set_errno_nohost(addrlist, ERRNO_EXPANDFAIL, errstr, DEFER, FALSE);
3360 yield = DEFER;
3361 goto SEND_QUIT;
3362 }
3363@@ -1514,8 +1545,12 @@ if (continue_hostname == NULL)
3364
3365 if (!smtps)
3366 {
3367- if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2',
3368- ob->command_timeout)) goto RESPONSE_FAILED;
3369+ BOOL good_response = smtp_read_response(&inblock, buffer, sizeof(buffer),
3370+ '2', ob->command_timeout);
3371+#ifdef EXPERIMENTAL_DSN_INFO
3372+ smtp_greeting = string_copy(buffer);
3373+#endif
3374+ if (!good_response) goto RESPONSE_FAILED;
3375
3376 #ifdef EXPERIMENTAL_EVENT
3377 {
3378@@ -1525,9 +1560,9 @@ if (continue_hostname == NULL)
3379 s = event_raise(tblock->event_action, US"smtp:connect", buffer);
3380 if (s)
3381 {
3382- set_errno(addrlist, ERRNO_EXPANDFAIL,
3383+ set_errno_nohost(addrlist, ERRNO_EXPANDFAIL,
3384 string_sprintf("deferred by smtp:connect event expansion: %s", s),
3385- DEFER, FALSE, NULL);
3386+ DEFER, FALSE);
3387 yield = DEFER;
3388 goto SEND_QUIT;
3389 }
3390@@ -1541,7 +1576,7 @@ if (continue_hostname == NULL)
3391 {
3392 uschar *message = string_sprintf("failed to expand helo_data: %s",
3393 expand_string_message);
3394- set_errno(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE, NULL);
3395+ set_errno_nohost(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE);
3396 yield = DEFER;
3397 goto SEND_QUIT;
3398 }
3399@@ -1606,9 +1641,18 @@ goto SEND_QUIT;
3400 if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2',
3401 ob->command_timeout))
3402 {
3403- if (errno != 0 || buffer[0] == 0 || lmtp) goto RESPONSE_FAILED;
3404+ if (errno != 0 || buffer[0] == 0 || lmtp)
3405+ {
3406+#ifdef EXPERIMENTAL_DSN_INFO
3407+ helo_response = string_copy(buffer);
3408+#endif
3409+ goto RESPONSE_FAILED;
3410+ }
3411 esmtp = FALSE;
3412 }
3413+#ifdef EXPERIMENTAL_DSN_INFO
3414+ helo_response = string_copy(buffer);
3415+#endif
3416 }
3417 else
3418 {
3419@@ -1618,10 +1662,16 @@ goto SEND_QUIT;
3420
3421 if (!esmtp)
3422 {
3423+ BOOL good_response;
3424+
3425 if (smtp_write_command(&outblock, FALSE, "HELO %s\r\n", helo_data) < 0)
3426 goto SEND_FAILED;
3427- if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2',
3428- ob->command_timeout)) goto RESPONSE_FAILED;
3429+ good_response = smtp_read_response(&inblock, buffer, sizeof(buffer),
3430+ '2', ob->command_timeout);
3431+#ifdef EXPERIMENTAL_DSN_INFO
3432+ helo_response = string_copy(buffer);
3433+#endif
3434+ if (!good_response) goto RESPONSE_FAILED;
3435 }
3436
3437 /* Set IGNOREQUOTA if the response to LHLO specifies support and the
3438@@ -1671,6 +1721,11 @@ error messages. Note that smtp_use_size and smtp_use_pipelining will have been
3439 set from the command line if they were set in the process that passed the
3440 connection on. */
3441
3442+/*XXX continue case needs to propagate DSN_INFO, prob. in deliver.c
3443+as the contine goes via transport_pass_socket() and doublefork and exec.
3444+It does not wait. Unclear how we keep separate host's responses
3445+separate - we could match up by host ip+port as a bodge. */
3446+
3447 else
3448 {
3449 inblock.sock = outblock.sock = fileno(stdin);
3450@@ -1749,7 +1804,7 @@ if ( tls_offered
3451
3452 /* TLS session is set up */
3453
3454- for (addr = addrlist; addr != NULL; addr = addr->next)
3455+ for (addr = addrlist; addr; addr = addr->next)
3456 if (addr->transport_return == PENDING_DEFER)
3457 {
3458 addr->cipher = tls_out.cipher;
3459@@ -1774,6 +1829,8 @@ start of the Exim process (in exim.c). */
3460 if (tls_out.active >= 0)
3461 {
3462 char *greeting_cmd;
3463+ BOOL good_response;
3464+
3465 if (helo_data == NULL)
3466 {
3467 helo_data = expand_string(ob->helo_data);
3468@@ -1781,7 +1838,7 @@ if (tls_out.active >= 0)
3469 {
3470 uschar *message = string_sprintf("failed to expand helo_data: %s",
3471 expand_string_message);
3472- set_errno(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE, NULL);
3473+ set_errno_nohost(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE);
3474 yield = DEFER;
3475 goto SEND_QUIT;
3476 }
3477@@ -1790,8 +1847,12 @@ if (tls_out.active >= 0)
3478 /* For SMTPS we need to wait for the initial OK response. */
3479 if (smtps)
3480 {
3481- if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2',
3482- ob->command_timeout)) goto RESPONSE_FAILED;
3483+ good_response = smtp_read_response(&inblock, buffer, sizeof(buffer),
3484+ '2', ob->command_timeout);
3485+#ifdef EXPERIMENTAL_DSN_INFO
3486+ smtp_greeting = string_copy(buffer);
3487+#endif
3488+ if (!good_response) goto RESPONSE_FAILED;
3489 }
3490
3491 if (esmtp)
3492@@ -1806,9 +1867,12 @@ if (tls_out.active >= 0)
3493 if (smtp_write_command(&outblock, FALSE, "%s %s\r\n",
3494 lmtp? "LHLO" : greeting_cmd, helo_data) < 0)
3495 goto SEND_FAILED;
3496- if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2',
3497- ob->command_timeout))
3498- goto RESPONSE_FAILED;
3499+ good_response = smtp_read_response(&inblock, buffer, sizeof(buffer),
3500+ '2', ob->command_timeout);
3501+#ifdef EXPERIMENTAL_DSN_INFO
3502+ helo_response = string_copy(buffer);
3503+#endif
3504+ if (!good_response) goto RESPONSE_FAILED;
3505 }
3506
3507 /* If the host is required to use a secure channel, ensure that we
3508@@ -1935,8 +1999,8 @@ if (tblock->filter_command != NULL)
3509
3510 if (!rc)
3511 {
3512- set_errno(addrlist->next, addrlist->basic_errno, addrlist->message, DEFER,
3513- FALSE, NULL);
3514+ set_errno_nohost(addrlist->next, addrlist->basic_errno, addrlist->message, DEFER,
3515+ FALSE);
3516 yield = ERROR;
3517 goto SEND_QUIT;
3518 }
3519@@ -2065,7 +2129,7 @@ pending_MAIL = TRUE; /* The block starts with MAIL */
3520 {
3521 if (s = string_address_utf8_to_alabel(return_path, &errstr), errstr)
3522 {
3523- set_errno(addrlist, ERRNO_EXPANDFAIL, errstr, DEFER, FALSE, NULL);
3524+ set_errno_nohost(addrlist, ERRNO_EXPANDFAIL, errstr, DEFER, FALSE);
3525 yield = ERROR;
3526 goto SEND_QUIT;
3527 }
3528@@ -2217,8 +2281,8 @@ if (mua_wrapper)
3529 if (badaddr->transport_return != PENDING_OK)
3530 {
3531 /*XXX could we find a better errno than 0 here? */
3532- set_errno(addrlist, 0, badaddr->message, FAIL,
3533- testflag(badaddr, af_pass_message), NULL);
3534+ set_errno_nohost(addrlist, 0, badaddr->message, FAIL,
3535+ testflag(badaddr, af_pass_message));
3536 ok = FALSE;
3537 break;
3538 }
3539@@ -2475,7 +2539,7 @@ if (!ok) ok = TRUE; else
3540 else
3541 sprintf(CS buffer, "%.500s\n", addr->unique);
3542
3543- DEBUG(D_deliver) debug_printf("journalling %s", buffer);
3544+ DEBUG(D_deliver) debug_printf("journalling %s\n", buffer);
3545 len = Ustrlen(CS buffer);
3546 if (write(journal_fd, buffer, len) != len)
3547 log_write(0, LOG_MAIN|LOG_PANIC, "failed to write journal for "
3548@@ -2512,7 +2576,7 @@ if (!ok) ok = TRUE; else
3549 else
3550 sprintf(CS buffer, "%.500s\n", addr->unique);
3551
3552- DEBUG(D_deliver) debug_printf("journalling(PRDR) %s", buffer);
3553+ DEBUG(D_deliver) debug_printf("journalling(PRDR) %s\n", buffer);
3554 len = Ustrlen(CS buffer);
3555 if (write(journal_fd, buffer, len) != len)
3556 log_write(0, LOG_MAIN|LOG_PANIC, "failed to write journal for "
3557@@ -2542,22 +2606,27 @@ the problem is not related to this specific message. */
3558
3559 if (!ok)
3560 {
3561- int code;
3562+ int code, set_rc;
3563+ uschar * set_message;
3564
3565 RESPONSE_FAILED:
3566- save_errno = errno;
3567- message = NULL;
3568- send_quit = check_response(host, &save_errno, addrlist->more_errno,
3569- buffer, &code, &message, &pass_message);
3570- goto FAILED;
3571+ {
3572+ save_errno = errno;
3573+ message = NULL;
3574+ send_quit = check_response(host, &save_errno, addrlist->more_errno,
3575+ buffer, &code, &message, &pass_message);
3576+ goto FAILED;
3577+ }
3578
3579 SEND_FAILED:
3580- save_errno = errno;
3581- code = '4';
3582- message = US string_sprintf("send() to %s [%s] failed: %s",
3583- host->name, host->address, strerror(save_errno));
3584- send_quit = FALSE;
3585- goto FAILED;
3586+ {
3587+ save_errno = errno;
3588+ code = '4';
3589+ message = US string_sprintf("send() to %s [%s] failed: %s",
3590+ host->name, host->address, strerror(save_errno));
3591+ send_quit = FALSE;
3592+ goto FAILED;
3593+ }
3594
3595 /* This label is jumped to directly when a TLS negotiation has failed,
3596 or was not done for a host for which it is required. Values will be set
3597@@ -2578,16 +2647,14 @@ if (!ok)
3598
3599 FAILED:
3600 ok = FALSE; /* For when reached by GOTO */
3601+ set_message = message;
3602
3603 if (setting_up)
3604 {
3605 if (code == '5')
3606- set_errno(addrlist, save_errno, message, FAIL, pass_message, host);
3607+ set_rc = FAIL;
3608 else
3609- {
3610- set_errno(addrlist, save_errno, message, DEFER, pass_message, host);
3611- yield = DEFER;
3612- }
3613+ yield = set_rc = DEFER;
3614 }
3615
3616 /* We want to handle timeouts after MAIL or "." and loss of connection after
3617@@ -2646,14 +2713,15 @@ if (!ok)
3618 if (message_error)
3619 {
3620 if (mua_wrapper) code = '5'; /* Force hard failure in wrapper mode */
3621- set_errno(addrlist, save_errno, message, (code == '5')? FAIL : DEFER,
3622- pass_message, host);
3623
3624 /* If there's an errno, the message contains just the identity of
3625 the host. */
3626
3627- if (code != '5') /* Anything other than 5 is treated as temporary */
3628+ if (code == '5')
3629+ set_rc = FAIL;
3630+ else /* Anything other than 5 is treated as temporary */
3631 {
3632+ set_rc = DEFER;
3633 if (save_errno > 0)
3634 message = US string_sprintf("%s: %s", message, strerror(save_errno));
3635 if (host->next != NULL) log_write(0, LOG_MAIN, "%s", message);
3636@@ -2670,11 +2738,17 @@ if (!ok)
3637
3638 else
3639 {
3640+ set_rc = DEFER;
3641 yield = (save_errno == ERRNO_CHHEADER_FAIL ||
3642 save_errno == ERRNO_FILTER_FAIL)? ERROR : DEFER;
3643- set_errno(addrlist, save_errno, message, DEFER, pass_message, host);
3644 }
3645 }
3646+
3647+ set_errno(addrlist, save_errno, set_message, set_rc, pass_message, host
3648+#ifdef EXPERIMENTAL_DSN_INFO
3649+ , smtp_greeting, helo_response
3650+#endif
3651+ );
3652 }
3653
3654
3655@@ -2787,6 +2861,9 @@ if (completed_address && ok && send_quit)
3656 /* If the socket is successfully passed, we musn't send QUIT (or
3657 indeed anything!) from here. */
3658
3659+/*XXX DSN_INFO: assume likely to do new HELO; but for greet we'll want to
3660+propagate it from the initial
3661+*/
3662 if (ok && transport_pass_socket(tblock->name, host->name, host->address,
3663 new_message_id, inblock.sock))
3664 {
3665@@ -2796,7 +2873,11 @@ if (completed_address && ok && send_quit)
3666
3667 /* If RSET failed and there are addresses left, they get deferred. */
3668
3669- else set_errno(first_addr, errno, msg, DEFER, FALSE, host);
3670+ else set_errno(first_addr, errno, msg, DEFER, FALSE, host
3671+#ifdef EXPERIMENTAL_DSN_INFO
3672+ , smtp_greeting, helo_response
3673+#endif
3674+ );
3675 }
3676 }
3677
3678@@ -2938,6 +3019,10 @@ for (addr = addrlist; addr != NULL; addr = addr->next)
3679 addr->peerdn = NULL;
3680 addr->ocsp = OCSP_NOT_REQ;
3681 #endif
3682+#ifdef EXPERIMENTAL_DSN_INFO
3683+ addr->smtp_greeting = NULL;
3684+ addr->helo_response = NULL;
3685+#endif
3686 }
3687 return first_addr;
3688 }
3689@@ -3479,7 +3564,7 @@ for (cutoff_retry = 0; expired &&
3690 if (dont_deliver)
3691 {
3692 host_item *host2;
3693- set_errno(addrlist, 0, NULL, OK, FALSE, NULL);
3694+ set_errno_nohost(addrlist, 0, NULL, OK, FALSE);
3695 for (addr = addrlist; addr != NULL; addr = addr->next)
3696 {
3697 addr->host_used = host;
This page took 2.824411 seconds and 4 git commands to generate.