dovecot-1.1: If login process crashes, log the IP address that (...

dovecot at dovecot.org dovecot at dovecot.org
Wed Jan 14 22:14:14 EET 2009


details:   http://hg.dovecot.org/dovecot-1.1/rev/2146e1963b79
changeset: 8098:2146e1963b79
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Jan 14 15:14:11 2009 -0500
description:
If login process crashes, log the IP address that (maybe) caused it.

diffstat:

9 files changed, 67 insertions(+), 12 deletions(-)
src/lib/failures.c         |   11 +++++++++++
src/lib/failures.h         |    7 ++++++-
src/login-common/main.c    |    2 ++
src/master/auth-process.c  |    4 ++--
src/master/child-process.c |   29 +++++++++++++++++++++++------
src/master/child-process.h |    4 +++-
src/master/log.c           |   15 +++++++++++++++
src/master/login-process.c |    5 ++++-
src/master/ssl-init.c      |    2 +-

diffs (223 lines):

diff -r c612f0fa6bfb -r 2146e1963b79 src/lib/failures.c
--- a/src/lib/failures.c	Wed Jan 14 14:06:46 2009 -0500
+++ b/src/lib/failures.c	Wed Jan 14 15:14:11 2009 -0500
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "ioloop.h"
 #include "str.h"
+#include "network.h"
 #include "backtrace-string.h"
 #include "printf-format-fix.h"
 #include "write-full.h"
@@ -459,6 +460,16 @@ void i_set_failure_timestamp_format(cons
         log_stamp_format = i_strdup(fmt);
 }
 
+void i_set_failure_ip(const struct ip_addr *ip)
+{
+	const char *str;
+
+	if (error_handler == i_internal_error_handler) {
+		str = t_strdup_printf("\x01Oip=%s\n", net_ip2addr(ip));
+		(void)write_full(2, str, strlen(str));
+	}
+}
+
 void i_set_failure_exit_callback(void (*callback)(int *status))
 {
 	failure_exit_callback = callback;
diff -r c612f0fa6bfb -r 2146e1963b79 src/lib/failures.h
--- a/src/lib/failures.h	Wed Jan 14 14:06:46 2009 -0500
+++ b/src/lib/failures.h	Wed Jan 14 15:14:11 2009 -0500
@@ -1,5 +1,7 @@
 #ifndef FAILURES_H
 #define FAILURES_H
+
+struct ip_addr;
 
 /* Default exit status codes that we could use. */
 enum fatal_exit_status {
@@ -78,9 +80,12 @@ void i_set_info_file(const char *path);
 
 /* Set the failure prefix. This is used only when logging to a file. */
 void i_set_failure_prefix(const char *prefix);
-
 /* Prefix failures with a timestamp. fmt is in strftime() format. */
 void i_set_failure_timestamp_format(const char *fmt);
+/* When logging with internal error protocol, update the process's current
+   IP address. This is mainly used by the master process to log some IP
+   address if the process crash. */
+void i_set_failure_ip(const struct ip_addr *ip);
 
 /* Call the callback before exit()ing. The callback may update the status. */
 void i_set_failure_exit_callback(void (*callback)(int *status));
diff -r c612f0fa6bfb -r 2146e1963b79 src/login-common/main.c
--- a/src/login-common/main.c	Wed Jan 14 14:06:46 2009 -0500
+++ b/src/login-common/main.c	Wed Jan 14 15:14:11 2009 -0500
@@ -89,6 +89,7 @@ static void login_accept(void *context)
 			i_error("accept() failed: %m");
 		return;
 	}
+	i_set_failure_ip(&remote_ip);
 
 	if (net_getsockname(fd, &local_ip, &local_port) < 0) {
 		memset(&local_ip, 0, sizeof(local_ip));
@@ -120,6 +121,7 @@ static void login_accept_ssl(void *conte
 			i_error("accept() failed: %m");
 		return;
 	}
+	i_set_failure_ip(&remote_ip);
 
 	if (net_getsockname(fd, &local_ip, &local_port) < 0) {
 		memset(&local_ip, 0, sizeof(local_ip));
diff -r c612f0fa6bfb -r 2146e1963b79 src/master/auth-process.c
--- a/src/master/auth-process.c	Wed Jan 14 14:06:46 2009 -0500
+++ b/src/master/auth-process.c	Wed Jan 14 15:14:11 2009 -0500
@@ -60,9 +60,9 @@ bool have_initialized_auth_processes = F
 bool have_initialized_auth_processes = FALSE;
 
 static struct child_process auth_child_process =
-	{ PROCESS_TYPE_AUTH, 0 };
+	{ MEMBER(type) PROCESS_TYPE_AUTH };
 static struct child_process auth_worker_child_process =
-	{ PROCESS_TYPE_AUTH_WORKER, 0 };
+	{ MEMBER(type) PROCESS_TYPE_AUTH_WORKER };
 
 static struct timeout *to;
 static unsigned int auth_tag;
diff -r c612f0fa6bfb -r 2146e1963b79 src/master/child-process.c
--- a/src/master/child-process.c	Wed Jan 14 14:06:46 2009 -0500
+++ b/src/master/child-process.c	Wed Jan 14 15:14:11 2009 -0500
@@ -3,6 +3,7 @@
 #include "common.h"
 #include "lib-signals.h"
 #include "hash.h"
+#include "str.h"
 #include "env-util.h"
 #include "syslog-util.h"
 #include "child-process.h"
@@ -132,12 +133,15 @@ static void sigchld_handler(int signo AT
 	struct child_process *process;
 	const char *process_type_name, *msg;
 	enum process_type process_type;
+	string_t *str;
 	pid_t pid;
 	int status;
 	bool abnormal_exit;
 
+	str = t_str_new(128);
 	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
 		/* get the type and remove from hash */
+		str_truncate(str, 0);
 		process = child_process_lookup(pid);
 		if (process == NULL)
 			process_type = PROCESS_TYPE_UNKNOWN;
@@ -168,14 +172,27 @@ static void sigchld_handler(int signo AT
 							      process_type);
 				msg = msg == NULL ? "" :
 					t_strconcat(" (", msg, ")", NULL);
-				i_error("child %s (%s) returned error %d%s",
-					dec2str(pid), process_type_name,
-					status, msg);
+				str_printfa(str,
+					    "child %s (%s) returned error %d%s",
+					    dec2str(pid), process_type_name,
+					    status, msg);
 			}
 		} else if (WIFSIGNALED(status)) {
-			i_error("child %s (%s) killed with signal %d",
-				dec2str(pid), process_type_name,
-				WTERMSIG(status));
+			str_printfa(str, "child %s (%s) killed with signal %d",
+				    dec2str(pid), process_type_name,
+				    WTERMSIG(status));
+		}
+
+		if (str_len(str) > 0) {
+			if (process != NULL && process->ip.family != 0) {
+				if (!process->ip_changed)
+					str_append(str, " (ip=");
+				else
+					str_append(str, " (latest ip=");
+				str_printfa(str, "%s)",
+					    net_ip2addr(&process->ip));
+			}
+			i_error("%s", str_c(str));
 		}
 
 		if (destroy_callbacks[process_type] != NULL) {
diff -r c612f0fa6bfb -r 2146e1963b79 src/master/child-process.h
--- a/src/master/child-process.h	Wed Jan 14 14:06:46 2009 -0500
+++ b/src/master/child-process.h	Wed Jan 14 15:14:11 2009 -0500
@@ -16,8 +16,10 @@ enum process_type {
 
 struct child_process {
 	enum process_type type;
-
+	struct ip_addr ip;
+	unsigned int allow_change_ip:1;
 	unsigned int seen_fatal:1;
+	unsigned int ip_changed:1;
 };
 
 typedef void child_process_destroy_callback_t(struct child_process *process,
diff -r c612f0fa6bfb -r 2146e1963b79 src/master/log.c
--- a/src/master/log.c	Wed Jan 14 14:06:46 2009 -0500
+++ b/src/master/log.c	Wed Jan 14 15:14:11 2009 -0500
@@ -17,6 +17,7 @@ struct log_io {
 	struct io *io;
 	struct istream *stream;
 	pid_t pid;
+	struct ip_addr ip;
 
 	time_t log_stamp;
 	unsigned int log_counter;
@@ -129,6 +130,20 @@ static int log_it(struct log_io *log_io,
 		if (process != NULL)
 			process->seen_fatal = TRUE;
 		break;
+	case 'O':
+		/* logging option. ignore unknown ones. */
+		if (strncmp(line, "ip=", 3) == 0) {
+			process = child_process_lookup(log_io->pid);
+			if (process != NULL &&
+			    (process->allow_change_ip ||
+			     process->ip.family == 0)) {
+				if (process->ip.family != 0)
+					process->ip_changed = TRUE;
+				net_addr2ip(line + 3, &process->ip);
+			}
+		}
+		log_io->next_log_type = '\0';
+		return 1;
 	default:
 		log_type = LOG_TYPE_ERROR;
 		break;
diff -r c612f0fa6bfb -r 2146e1963b79 src/master/login-process.c
--- a/src/master/login-process.c	Wed Jan 14 14:06:46 2009 -0500
+++ b/src/master/login-process.c	Wed Jan 14 15:14:11 2009 -0500
@@ -450,8 +450,11 @@ login_process_new(struct login_group *gr
 	p->io = io_add(fd, IO_READ, login_process_input, p);
 	p->output = o_stream_create_fd(fd, sizeof(struct master_login_reply)*10,
 				       FALSE);
-	if (!inetd_child)
+	if (!inetd_child) {
+		if (!group->set->login_process_per_connection)
+			p->process.allow_change_ip = TRUE;
 		child_process_add(pid, &p->process);
+	}
 
 	p->state = LOGIN_STATE_LISTENING;
 
diff -r c612f0fa6bfb -r 2146e1963b79 src/master/ssl-init.c
--- a/src/master/ssl-init.c	Wed Jan 14 14:06:46 2009 -0500
+++ b/src/master/ssl-init.c	Wed Jan 14 15:14:11 2009 -0500
@@ -18,7 +18,7 @@
 #include <sys/stat.h>
 
 static struct child_process ssl_param_child_process =
-	{ PROCESS_TYPE_SSL_PARAM, 0 };
+	{ MEMBER(type) PROCESS_TYPE_SSL_PARAM };
 
 static struct timeout *to;
 static char *generating_path = NULL;


More information about the dovecot-cvs mailing list