From e5be948a65fe601024e5d4256f64efbfed3dd72e Mon Sep 17 00:00:00 2001 From: Jeremy Harris 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