summaryrefslogtreecommitdiffstats
path: root/debian/patches/75_08-Logging-fix-initial-listening-on-log-line.patch
blob: 4af2972aecce71c7595d9a0681a55395f7d187f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
From e5be948a65fe601024e5d4256f64efbfed3dd72e Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Mon, 18 Mar 2019 00:31:43 +0000
Subject: [PATCH 4/5] Logging: fix initial listening-on log line

(cherry picked from commit 254f38d1c5ada5e4df0bccb385dc466549620c71)
---
 doc/ChangeLog |  4 +++
 src/daemon.c      | 73 +++++++++++++++++++++++++++----------------
 src/host.c        |  1 +
 src/structs.h     |  1 +
 test/confs/0282       |  2 +-
 test/log/0282         |  2 +-
 6 files changed, 54 insertions(+), 29 deletions(-)

diff --git a/doc/ChangeLog b/doc/ChangeLog
index 0f8d05b2..3c0ffbf0 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -23,10 +23,14 @@ JB/01 Bug 2375: fix expansions of 822 addresses having comments in local-part
 
 JH/08 Add hardening against SRV & TLSA lookups the hit CNAMEs (a nonvalid
       configuration).  If a CNAME target was not a wellformed name pattern, a
       crash could result.
 
+JH/09 Logging: Fix initial listening-on line for multiple ports for an IP when
+      the OS reports them interleaved with other addresses.
+
+
 
 Exim version 4.92
 -----------------
 
 JH/01 Remove code calling the customisable local_scan function, unless a new
diff --git a/src/daemon.c b/src/daemon.c
index a852192e..01da3936 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -1625,12 +1625,12 @@ if (f.inetd_wait_mode)
 else if (f.daemon_listen)
   {
   int i, j;
   int smtp_ports = 0;
   int smtps_ports = 0;
-  ip_address_item * ipa, * i2;
-  uschar * p = big_buffer;
+  ip_address_item * ipa;
+  uschar * p;
   uschar * qinfo = queue_interval > 0
     ? string_sprintf("-q%s", readconf_printtime(queue_interval))
     : US"no queue runs";
 
   /* Build a list of listening addresses in big_buffer, but limit it to 10
@@ -1638,73 +1638,92 @@ else if (f.daemon_listen)
 
   It is now possible to have some ports listening for SMTPS (the old,
   deprecated protocol that starts TLS without using STARTTLS), and others
   listening for standard SMTP. Keep their listings separate. */
 
-  for (j = 0; j < 2; j++)
+  for (int j = 0, i; j < 2; j++)
     {
     for (i = 0, ipa = addresses; i < 10 && ipa; i++, ipa = ipa->next)
       {
       /* First time round, look for SMTP ports; second time round, look for
-      SMTPS ports. For the first one of each, insert leading text. */
+      SMTPS ports. Build IP+port strings. */
 
       if (host_is_tls_on_connect_port(ipa->port) == (j > 0))
 	{
 	if (j == 0)
-	  {
-	  if (smtp_ports++ == 0)
-	    {
-	    memcpy(p, "SMTP on", 8);
-	    p += 7;
-	    }
-	  }
+	  smtp_ports++;
 	else
-	  if (smtps_ports++ == 0)
-	    p += sprintf(CS p, "%sSMTPS on",
-	      smtp_ports == 0 ? "" : " and for ");
+	  smtps_ports++;
 
 	/* Now the information about the port (and sometimes interface) */
 
 	if (ipa->address[0] == ':' && ipa->address[1] == 0)
 	  {						/* v6 wildcard */
 	  if (ipa->next && ipa->next->address[0] == 0 &&
 	      ipa->next->port == ipa->port)
 	    {
-	    p += sprintf(CS p, " port %d (IPv6 and IPv4)", ipa->port);
-	    ipa = ipa->next;
+	    ipa->log = string_sprintf(" port %d (IPv6 and IPv4)", ipa->port);
+	    (ipa = ipa->next)->log = NULL;
 	    }
 	  else if (ipa->v6_include_v4)
-	    p += sprintf(CS p, " port %d (IPv6 with IPv4)", ipa->port);
+	    ipa->log = string_sprintf(" port %d (IPv6 with IPv4)", ipa->port);
 	  else
-	    p += sprintf(CS p, " port %d (IPv6)", ipa->port);
+	    ipa->log = string_sprintf(" port %d (IPv6)", ipa->port);
 	  }
 	else if (ipa->address[0] == 0)			/* v4 wildcard */
-	  p += sprintf(CS p, " port %d (IPv4)", ipa->port);
+	  ipa->log = string_sprintf(" port %d (IPv4)", ipa->port);
 	else				/* check for previously-seen IP */
 	  {
+	  ip_address_item * i2;
 	  for (i2 = addresses; i2 != ipa; i2 = i2->next)
 	    if (  host_is_tls_on_connect_port(i2->port) == (j > 0)
 	       && Ustrcmp(ipa->address, i2->address) == 0
 	       )
 	      {				/* found; append port to list */
-	      if (p[-1] == '}') p--;
-	      while (isdigit(*--p)) ;
-	      p +=  1 + sprintf(CS p+1, "%s%d,%d}", *p == ',' ? "" : "{",
-		i2->port, ipa->port);
+	      for (p = i2->log; *p; ) p++;	/* end of existing string */
+	      if (*--p == '}') *p = '\0';	/* drop EOL */
+	      while (isdigit(*--p)) ;		/* char before port */
+
+	      i2->log = *p == ':'		/* no list yet? */
+		? string_sprintf("%.*s{%s,%d}",
+		  (int)(p - i2->log + 1), i2->log, p+1, ipa->port)
+		: string_sprintf("%s,%d}", i2->log, ipa->port);
+	      ipa->log = NULL;
 	      break;
 	      }
 	  if (i2 == ipa)		/* first-time IP */
-	    p += sprintf(CS p, " [%s]:%d", ipa->address, ipa->port);
+	    ipa->log = string_sprintf(" [%s]:%d", ipa->address, ipa->port);
 	  }
 	}
       }
+    }
 
-    if (ipa)
+  p = big_buffer;
+  for (int j = 0, i; j < 2; j++)
+    {
+    /* First time round, look for SMTP ports; second time round, look for
+    SMTPS ports. For the first one of each, insert leading text. */
+
+    if (j == 0)
       {
-      memcpy(p, " ...", 5);
-      p += 4;
+      if (smtp_ports > 0)
+	p += sprintf(CS p, "SMTP on");
       }
+    else
+      if (smtps_ports > 0)
+	p += sprintf(CS p, "%sSMTPS on",
+	  smtp_ports == 0 ? "" : " and for ");
+
+    /* Now the information about the port (and sometimes interface) */
+
+    for (i = 0, ipa = addresses; i < 10 && ipa; i++, ipa = ipa->next)
+      if (host_is_tls_on_connect_port(ipa->port) == (j > 0))
+	if (ipa->log)
+	  p += sprintf(CS p, "%s",  ipa->log);
+
+    if (ipa)
+      p += sprintf(CS p, " ...");
     }
 
   log_write(0, LOG_MAIN,
     "exim %s daemon started: pid=%d, %s, listening for %s",
     version_string, getpid(), qinfo, big_buffer);
diff --git a/src/host.c b/src/host.c
index 29c977fe..a3b0977b 100644
--- a/src/host.c
+++ b/src/host.c
@@ -757,10 +757,11 @@ while ((s = string_nextinlist(&list, &sep, NULL, 0)))
   next = store_get(sizeof(ip_address_item));
   next->next = NULL;
   Ustrcpy(next->address, s);
   next->port = port;
   next->v6_include_v4 = FALSE;
+  next->log = NULL;
 
   if (!yield)
     yield = last = next;
   else
     {
diff --git a/src/structs.h b/src/structs.h
index 20db0e5f..1e63d752 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -442,10 +442,11 @@ hold an IPv6 address. */
 typedef struct ip_address_item {
   struct ip_address_item *next;
   int    port;
   BOOL   v6_include_v4;            /* Used in the daemon */
   uschar address[46];
+  uschar * log;			   /* portion of "listening on" log line */
 } ip_address_item;
 
 /* Structure for chaining together arbitrary strings. */
 
 typedef struct string_item {
-- 
2.20.1