diff -r 90d7364b8c9d src/login-common/login-proxy.c
--- a/src/login-common/login-proxy.c	Thu Apr 19 18:59:33 2012 +0300
+++ b/src/login-common/login-proxy.c	Thu Apr 19 19:22:16 2012 +0300
@@ -25,6 +25,9 @@
 #define KILLED_BY_ADMIN_REASON "Killed by admin"
 #define PROXY_IMMEDIATE_FAILURE_SECS 30
 
+#define PROXY_DEFAULT_TIMEOUT 5000
+#define PROXY_DEFAULT_RETRIES 10
+
 struct login_proxy {
 	struct login_proxy *prev, *next;
 
@@ -49,6 +52,8 @@
 
 	proxy_callback_t *callback;
 
+	unsigned int retries_left;
+
 	unsigned int destroying:1;
 	unsigned int disconnecting:1;
 };
@@ -59,6 +64,7 @@
 static struct ipc_server *login_proxy_ipc_server;
 
 static void login_proxy_ipc_cmd(struct ipc_cmd *cmd, const char *line);
+static bool login_proxy_try_reconnect(struct login_proxy *proxy);
 
 static void
 login_proxy_free_reason(struct login_proxy **_proxy, const char *reason);
@@ -196,16 +202,25 @@
 
 static void proxy_wait_connect(struct login_proxy *proxy)
 {
+	const char *errstr;
 	int err;
 
 	err = net_geterror(proxy->server_fd);
 	if (err != 0) {
-		i_error("proxy(%s): connect(%s, %u) failed: %s (after %u secs)",
+		errstr = t_strdup_printf(
+			"proxy(%s): connect(%s, %u) failed: %s "
+			"(after %u secs, %u retries left)",
 			proxy->client->virtual_user,
 			proxy->host, proxy->port, strerror(err),
-			(unsigned int)(ioloop_time - proxy->created.tv_sec));
+			(unsigned int)(ioloop_time - proxy->created.tv_sec),
+			proxy->retries_left);
+		if (proxy->retries_left > 0)
+			i_warning("%s", errstr);
+		else
+			i_error("%s", errstr);
 		proxy_fail_connect(proxy);
-                login_proxy_free(&proxy);
+		if (!login_proxy_try_reconnect(proxy))
+			login_proxy_free(&proxy);
 		return;
 	}
 	proxy->state_rec->last_success = ioloop_timeval;
@@ -229,10 +244,20 @@
 
 static void proxy_connect_timeout(struct login_proxy *proxy)
 {
-	i_error("proxy(%s): connect(%s, %u) timed out",
-		proxy->client->virtual_user, proxy->host, proxy->port);
+	const char *errstr;
+
+	errstr = t_strdup_printf(
+		"proxy(%s): connect(%s, %u) timed out (%u retries left)",
+		proxy->client->virtual_user, proxy->host, proxy->port,
+		proxy->retries_left);
+	if (proxy->retries_left > 0)
+		i_warning("%s", errstr);
+	else
+		i_error("%s", errstr);
+
 	proxy_fail_connect(proxy);
-	login_proxy_free(&proxy);
+	if (!login_proxy_try_reconnect(proxy))
+		login_proxy_free(&proxy);
 }
 
 static int login_proxy_connect(struct login_proxy *proxy)
@@ -259,6 +284,8 @@
 	}
 	proxy->server_io = io_add(proxy->server_fd, IO_WRITE,
 				  proxy_wait_connect, proxy);
+	if (proxy->connect_timeout_msecs == 0)
+		proxy->connect_timeout_msecs = PROXY_DEFAULT_TIMEOUT;
 	if (proxy->connect_timeout_msecs != 0) {
 		proxy->to = timeout_add(proxy->connect_timeout_msecs,
 					proxy_connect_timeout, proxy);
@@ -313,6 +340,7 @@
 	proxy->connect_timeout_msecs = set->connect_timeout_msecs;
 	proxy->notify_refresh_secs = set->notify_refresh_secs;
 	proxy->ssl_flags = set->ssl_flags;
+	proxy->retries_left = PROXY_DEFAULT_RETRIES;
 	client_ref(client);
 
 	memset(&dns_lookup_set, 0, sizeof(dns_lookup_set));
@@ -335,19 +363,8 @@
 	return 0;
 }
 
-static void
-login_proxy_free_reason(struct login_proxy **_proxy, const char *reason)
+static void login_proxy_disconnect(struct login_proxy *proxy)
 {
-	struct login_proxy *proxy = *_proxy;
-	struct client *client = proxy->client;
-	const char *ipstr;
-
-	*_proxy = NULL;
-
-	if (proxy->destroying)
-		return;
-	proxy->destroying = TRUE;
-
 	if (proxy->to != NULL)
 		timeout_remove(&proxy->to);
 	if (proxy->to_notify != NULL)
@@ -365,8 +382,54 @@
 	if (proxy->server_output != NULL)
 		o_stream_destroy(&proxy->server_output);
 
+	if (proxy->ssl_server_proxy != NULL)
+		ssl_proxy_free(&proxy->ssl_server_proxy);
+	if (proxy->server_fd != -1) {
+		net_disconnect(proxy->server_fd);
+		proxy->server_fd = -1;
+	}
+
 	if (proxy->client_fd != -1) {
 		/* detached proxy */
+		if (proxy->client_io != NULL)
+			io_remove(&proxy->client_io);
+		if (proxy->client_output != NULL)
+			o_stream_destroy(&proxy->client_output);
+		net_disconnect(proxy->client_fd);
+		proxy->client_fd = -1;
+	}
+}
+
+static bool login_proxy_try_reconnect(struct login_proxy *proxy)
+{
+	i_assert(proxy->client_fd == -1);
+
+	if (proxy->retries_left == 0)
+		return FALSE;
+	proxy->retries_left--;
+
+	login_proxy_disconnect(proxy);
+	return login_proxy_connect(proxy) == 0;
+}
+
+static void
+login_proxy_free_reason(struct login_proxy **_proxy, const char *reason)
+{
+	struct login_proxy *proxy = *_proxy;
+	struct client *client = proxy->client;
+	const char *ipstr;
+	bool detached = proxy->client_fd != -1;
+
+	*_proxy = NULL;
+
+	if (proxy->destroying)
+		return;
+	proxy->destroying = TRUE;
+
+	login_proxy_disconnect(proxy);
+
+	if (detached) {
+		/* detached proxy */
 		DLLIST_REMOVE(&login_proxies, proxy);
 
 		ipstr = net_ip2addr(&proxy->client->ip);
@@ -375,12 +438,6 @@
 			proxy->client->virtual_user,
 			ipstr != NULL ? ipstr : "",
 			reason == NULL ? "" : t_strdup_printf(" (%s)", reason)));
-
-		if (proxy->client_io != NULL)
-			io_remove(&proxy->client_io);
-		if (proxy->client_output != NULL)
-			o_stream_destroy(&proxy->client_output);
-		net_disconnect(proxy->client_fd);
 	} else {
 		i_assert(proxy->client_io == NULL);
 		i_assert(proxy->client_output == NULL);
@@ -391,11 +448,6 @@
 			proxy->callback(proxy->client);
 	}
 
-	if (proxy->server_fd != -1)
-		net_disconnect(proxy->server_fd);
-
-	if (proxy->ssl_server_proxy != NULL)
-		ssl_proxy_free(&proxy->ssl_server_proxy);
 	i_free(proxy->host);
 	i_free(proxy);
 
