Ian Kent 36ee82
diff --git a/include/defaults.h b/include/defaults.h
Ian Kent 36ee82
index 0984b1c..46393d9 100644
Ian Kent 36ee82
--- a/include/defaults.h
Ian Kent 36ee82
+++ b/include/defaults.h
Ian Kent 36ee82
@@ -26,7 +26,8 @@
Ian Kent 36ee82
 #define DEFAULT_BROWSE_MODE	1
Ian Kent 36ee82
 #define DEFAULT_LOGGING		0
Ian Kent 36ee82
 
Ian Kent 36ee82
-#define DEFAULT_LDAP_SERVER		NULL
Ian Kent 36ee82
+#define DEFAULT_LDAP_TIMEOUT		-1
Ian Kent 36ee82
+#define DEFAULT_LDAP_NETWORK_TIMEOUT	8
Ian Kent 36ee82
 
Ian Kent 36ee82
 #define DEFAULT_MAP_OBJ_CLASS		"nisMap"
Ian Kent 36ee82
 #define DEFAULT_ENTRY_OBJ_CLASS		"nisObject"
Ian Kent 36ee82
@@ -46,6 +47,10 @@ unsigned int defaults_get_timeout(void);
Ian Kent 36ee82
 unsigned int defaults_get_browse_mode(void);
Ian Kent 36ee82
 unsigned int defaults_get_logging(void);
Ian Kent 36ee82
 const char *defaults_get_ldap_server(void);
Ian Kent 36ee82
+unsigned int defaults_get_ldap_timeout(void);
Ian Kent 36ee82
+unsigned int defaults_get_ldap_network_timeout(void);
Ian Kent 36ee82
+struct list_head *defaults_get_uris(void);
Ian Kent 36ee82
+void defaults_free_uris(struct list_head *);
Ian Kent 36ee82
 struct ldap_schema *defaults_get_default_schema(void);
Ian Kent 36ee82
 struct ldap_schema *defaults_get_schema(void);
Ian Kent 36ee82
 struct ldap_searchdn *defaults_get_searchdns(void);
Ian Kent 36ee82
diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h
Ian Kent 36ee82
index 1a924be..ca8d658 100644
Ian Kent 36ee82
--- a/include/lookup_ldap.h
Ian Kent 36ee82
+++ b/include/lookup_ldap.h
Ian Kent 36ee82
@@ -18,6 +18,11 @@ struct ldap_schema {
Ian Kent 36ee82
 	char *value_attr;
Ian Kent 36ee82
 };
Ian Kent 36ee82
 
Ian Kent 36ee82
+struct ldap_uri {
Ian Kent 36ee82
+	char *uri;
Ian Kent 36ee82
+	struct list_head list;
Ian Kent 36ee82
+};
Ian Kent 36ee82
+
Ian Kent 36ee82
 struct ldap_searchdn {
Ian Kent 36ee82
 	char *basedn;
Ian Kent 36ee82
 	struct ldap_searchdn *next;
Ian Kent 36ee82
@@ -30,6 +35,8 @@ struct lookup_context {
Ian Kent 36ee82
 	int port;
Ian Kent 36ee82
 	char *base;
Ian Kent 36ee82
 	char *qdn;
Ian Kent 36ee82
+	unsigned int timeout;
Ian Kent 36ee82
+	unsigned int network_timeout;
Ian Kent 36ee82
 
Ian Kent 36ee82
 	/* LDAP version 2 or 3 */
Ian Kent 36ee82
 	int version;
Ian Kent 36ee82
@@ -37,7 +44,17 @@ struct lookup_context {
Ian Kent 36ee82
 	/* LDAP lookup configuration */
Ian Kent 36ee82
 	struct ldap_schema *schema;
Ian Kent 36ee82
 
Ian Kent 36ee82
-	/* List of base dns for searching */
Ian Kent 36ee82
+	/*
Ian Kent 36ee82
+ 	 * List of servers and base dns for searching.
Ian Kent 36ee82
+ 	 * uri is the list of servers to attempt connection to and is
Ian Kent 36ee82
+ 	 * used only if server, above, is NULL. The head of the list
Ian Kent 36ee82
+ 	 * is the server which we are currently connected to.
Ian Kent 36ee82
+ 	 * cur_host tracks chnages to connected server, triggering
Ian Kent 36ee82
+ 	 * a scan of basedns when it changes.
Ian Kent 36ee82
+ 	 * sdns is the list of basdns to check, done in the order
Ian Kent 36ee82
+ 	 * given in configuration.
Ian Kent 36ee82
+ 	 */
Ian Kent 36ee82
+	struct list_head *uri;
Ian Kent 36ee82
 	char *cur_host;
Ian Kent 36ee82
 	struct ldap_searchdn *sdns;
Ian Kent 36ee82
 
Ian Kent 36ee82
@@ -77,7 +94,7 @@ struct lookup_context {
Ian Kent 36ee82
 #define LDAP_AUTH_AUTODETECT	0x0004
Ian Kent 36ee82
 
Ian Kent 36ee82
 /* lookup_ldap.c */
Ian Kent 36ee82
-LDAP *init_ldap_connection(struct lookup_context *ctxt);
Ian Kent 36ee82
+LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt);
Ian Kent 36ee82
 int unbind_ldap_connection(LDAP *ldap, struct lookup_context *ctxt);
Ian Kent 36ee82
 int authtype_requires_creds(const char *authtype);
Ian Kent 36ee82
 
Ian Kent 36ee82
diff --git a/lib/defaults.c b/lib/defaults.c
Ian Kent 36ee82
index 7da4631..bf1ceed 100644
Ian Kent 36ee82
--- a/lib/defaults.c
Ian Kent 36ee82
+++ b/lib/defaults.c
Ian Kent 36ee82
@@ -17,6 +17,7 @@
Ian Kent 36ee82
 #include <ctype.h>
Ian Kent 36ee82
 #include <string.h>
Ian Kent 36ee82
 
Ian Kent 36ee82
+#include "list.h"
Ian Kent 36ee82
 #include "defaults.h"
Ian Kent 36ee82
 #include "lookup_ldap.h"
Ian Kent 36ee82
 #include "log.h"
Ian Kent 36ee82
@@ -30,7 +31,9 @@
Ian Kent 36ee82
 #define ENV_NAME_BROWSE_MODE		"BROWSE_MODE"
Ian Kent 36ee82
 #define ENV_NAME_LOGGING		"LOGGING"
Ian Kent 36ee82
 
Ian Kent 36ee82
-#define ENV_LDAP_SERVER			"LDAP_SERVER"
Ian Kent 36ee82
+#define LDAP_URI			"LDAP_URI"
Ian Kent 36ee82
+#define ENV_LDAP_TIMEOUT		"LDAP_TIMEOUT"
Ian Kent 36ee82
+#define ENV_LDAP_NETWORK_TIMEOUT	"LDAP_NETWORK_TIMEOUT"
Ian Kent 36ee82
 
Ian Kent 36ee82
 #define SEARCH_BASE			"SEARCH_BASE"
Ian Kent 36ee82
 
Ian Kent 36ee82
@@ -44,7 +47,6 @@
Ian Kent 36ee82
 #define ENV_AUTH_CONF_FILE		"AUTH_CONF_FILE"
Ian Kent 36ee82
 
Ian Kent 36ee82
 static const char *default_master_map_name = DEFAULT_MASTER_MAP_NAME;
Ian Kent 36ee82
-static const char *default_ldap_server	   = DEFAULT_LDAP_SERVER;
Ian Kent 36ee82
 static const char *default_auth_conf_file  = DEFAULT_AUTH_CONF_FILE;
Ian Kent 36ee82
 
Ian Kent 36ee82
 static char *get_env_string(const char *name)
Ian Kent 36ee82
@@ -178,6 +180,99 @@ static int parse_line(char *line, char **res, char **value)
Ian Kent 36ee82
 	return 1;
Ian Kent 36ee82
 }
Ian Kent 36ee82
 
Ian Kent 36ee82
+void defaults_free_uris(struct list_head *list)
Ian Kent 36ee82
+{
Ian Kent 36ee82
+	struct list_head *next;
Ian Kent 36ee82
+	struct ldap_uri *uri;
Ian Kent 36ee82
+
Ian Kent 36ee82
+	if (list_empty(list)) {
Ian Kent 36ee82
+		free(list);
Ian Kent 36ee82
+		return;
Ian Kent 36ee82
+	}
Ian Kent 36ee82
+
Ian Kent 36ee82
+	next = list->next;
Ian Kent 36ee82
+	while (next != list) {
Ian Kent 36ee82
+		uri = list_entry(next, struct ldap_uri, list);
Ian Kent 36ee82
+		next = next->next;
Ian Kent 36ee82
+		list_del(&uri->list);
Ian Kent 36ee82
+		free(uri->uri);
Ian Kent 36ee82
+		free(uri);
Ian Kent 36ee82
+	}
Ian Kent 36ee82
+	free(list);
Ian Kent 36ee82
+
Ian Kent 36ee82
+	return;
Ian Kent 36ee82
+}
Ian Kent 36ee82
+
Ian Kent 36ee82
+static unsigned int add_uris(char *value, struct list_head *list)
Ian Kent 36ee82
+{
Ian Kent 36ee82
+	char *str, *tok, *ptr = NULL;
Ian Kent 36ee82
+	size_t len = strlen(value);
Ian Kent 36ee82
+
Ian Kent 36ee82
+	str = alloca(len);
Ian Kent 36ee82
+	if (!str)
Ian Kent 36ee82
+		return 0;
Ian Kent 36ee82
+	strcpy(str, value);
Ian Kent 36ee82
+
Ian Kent 36ee82
+	tok = strtok_r(str, " ", &ptr);
Ian Kent 36ee82
+	while (tok) {
Ian Kent 36ee82
+		struct ldap_uri *new;
Ian Kent 36ee82
+		char *uri;
Ian Kent 36ee82
+
Ian Kent 36ee82
+		new = malloc(sizeof(struct ldap_uri));
Ian Kent 36ee82
+		if (!new)
Ian Kent 36ee82
+			continue;
Ian Kent 36ee82
+
Ian Kent 36ee82
+		uri = strdup(tok);
Ian Kent 36ee82
+		if (!uri)
Ian Kent 36ee82
+			free(new);
Ian Kent 36ee82
+		else {
Ian Kent 36ee82
+			new->uri = uri;
Ian Kent 36ee82
+			list_add_tail(&new->list, list);
Ian Kent 36ee82
+		}
Ian Kent 36ee82
+
Ian Kent 36ee82
+		tok = strtok_r(NULL, " ", &ptr);
Ian Kent 36ee82
+	}
Ian Kent 36ee82
+
Ian Kent 36ee82
+	return 1;
Ian Kent 36ee82
+}
Ian Kent 36ee82
+
Ian Kent 36ee82
+struct list_head *defaults_get_uris(void)
Ian Kent 36ee82
+{
Ian Kent 36ee82
+	FILE *f;
Ian Kent 36ee82
+	char buf[MAX_LINE_LEN];
Ian Kent 36ee82
+	char *res;
Ian Kent 36ee82
+	struct list_head *list;
Ian Kent 36ee82
+
Ian Kent 36ee82
+	f = fopen(DEFAULTS_CONFIG_FILE, "r");
Ian Kent 36ee82
+	if (!f)
Ian Kent 36ee82
+		return NULL;
Ian Kent 36ee82
+
Ian Kent 36ee82
+	list = malloc(sizeof(struct list_head));
Ian Kent 36ee82
+	if (!list) {
Ian Kent 36ee82
+		fclose(f);
Ian Kent 36ee82
+		return NULL;
Ian Kent 36ee82
+	}
Ian Kent 36ee82
+	INIT_LIST_HEAD(list);
Ian Kent 36ee82
+
Ian Kent 36ee82
+	while ((res = fgets(buf, MAX_LINE_LEN, f))) {
Ian Kent 36ee82
+		char *key, *value;
Ian Kent 36ee82
+
Ian Kent 36ee82
+		if (!parse_line(res, &key, &value))
Ian Kent 36ee82
+			continue;
Ian Kent 36ee82
+
Ian Kent 36ee82
+		if (!strcasecmp(res, LDAP_URI))
Ian Kent 36ee82
+			add_uris(value, list);
Ian Kent 36ee82
+	}
Ian Kent 36ee82
+
Ian Kent 36ee82
+	if (list_empty(list)) {
Ian Kent 36ee82
+		free(list);
Ian Kent 36ee82
+		list = NULL;
Ian Kent 36ee82
+	}
Ian Kent 36ee82
+
Ian Kent 36ee82
+	fclose(f);
Ian Kent 36ee82
+	return list;
Ian Kent 36ee82
+}
Ian Kent 36ee82
+
Ian Kent 36ee82
 /*
Ian Kent 36ee82
  * Read config env variables and check they have been set.
Ian Kent 36ee82
  *
Ian Kent 36ee82
@@ -205,7 +300,8 @@ unsigned int defaults_read_config(void)
Ian Kent 36ee82
 		    check_set_config_value(key, ENV_NAME_TIMEOUT, value) ||
Ian Kent 36ee82
 		    check_set_config_value(key, ENV_NAME_BROWSE_MODE, value) ||
Ian Kent 36ee82
 		    check_set_config_value(key, ENV_NAME_LOGGING, value) ||
Ian Kent 36ee82
-		    check_set_config_value(key, ENV_LDAP_SERVER, value) ||
Ian Kent 36ee82
+		    check_set_config_value(key, ENV_LDAP_TIMEOUT, value) ||
Ian Kent 36ee82
+		    check_set_config_value(key, ENV_LDAP_NETWORK_TIMEOUT, value) ||
Ian Kent 36ee82
 		    check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value) ||
Ian Kent 36ee82
 		    check_set_config_value(key, ENV_NAME_ENTRY_OBJ_CLASS, value) ||
Ian Kent 36ee82
 		    check_set_config_value(key, ENV_NAME_MAP_ATTR, value) ||
Ian Kent 36ee82
@@ -284,15 +380,26 @@ unsigned int defaults_get_logging(void)
Ian Kent 36ee82
 	return logging;
Ian Kent 36ee82
 }
Ian Kent 36ee82
 
Ian Kent 36ee82
-const char *defaults_get_ldap_server(void)
Ian Kent 36ee82
+unsigned int defaults_get_ldap_timeout(void)
Ian Kent 36ee82
 {
Ian Kent 36ee82
-	char *server;
Ian Kent 36ee82
+	int res;
Ian Kent 36ee82
 
Ian Kent 36ee82
-	server = get_env_string(ENV_LDAP_SERVER);
Ian Kent 36ee82
-	if (!server)
Ian Kent 36ee82
-		return default_ldap_server;
Ian Kent 36ee82
+	res = get_env_number(ENV_LDAP_TIMEOUT);
Ian Kent 36ee82
+	if (res < 0)
Ian Kent 36ee82
+		res = DEFAULT_LDAP_TIMEOUT;
Ian Kent 36ee82
 
Ian Kent 36ee82
-	return (const char *) server;
Ian Kent 36ee82
+	return res;
Ian Kent 36ee82
+}
Ian Kent 36ee82
+
Ian Kent 36ee82
+unsigned int defaults_get_ldap_network_timeout(void)
Ian Kent 36ee82
+{
Ian Kent 36ee82
+	int res;
Ian Kent 36ee82
+
Ian Kent 36ee82
+	res = get_env_number(ENV_LDAP_NETWORK_TIMEOUT);
Ian Kent 36ee82
+	if (res < 0)
Ian Kent 36ee82
+		res = DEFAULT_LDAP_NETWORK_TIMEOUT;
Ian Kent 36ee82
+
Ian Kent 36ee82
+	return res;
Ian Kent 36ee82
 }
Ian Kent 36ee82
 
Ian Kent 36ee82
 struct ldap_schema *defaults_get_default_schema(void)
Ian Kent 36ee82
diff --git a/man/auto.master.5.in b/man/auto.master.5.in
Ian Kent 36ee82
index 0cb2f07..68447e0 100644
Ian Kent 36ee82
--- a/man/auto.master.5.in
Ian Kent 36ee82
+++ b/man/auto.master.5.in
Ian Kent 36ee82
@@ -230,10 +230,27 @@ values must be set, any partial schema specification will be ignored.
Ian Kent 36ee82
 .P
Ian Kent 36ee82
 The configuration settings available are:
Ian Kent 36ee82
 .TP
Ian Kent 36ee82
+.B LDAP_TIMEOUT
Ian Kent 36ee82
+Set the network response timeout (default 8).
Ian Kent 36ee82
+Set timeout value for the synchronous API  calls. The default is the LDAP
Ian Kent 36ee82
+library default of an infinite timeout.
Ian Kent 36ee82
+.TP
Ian Kent 36ee82
+.B LDAP_NETWORK_TIMEOUT
Ian Kent 36ee82
+Set the network response timeout (default 8).
Ian Kent 36ee82
+.TP
Ian Kent 36ee82
+.B LDAP_URI
Ian Kent 36ee82
+A space seperated list of server uris of the form <proto>://<server>[/]
Ian Kent 36ee82
+where <proto> can be ldap or ldaps. The option can be given multiple times.
Ian Kent 36ee82
+Map entries that include a server name override this option and it is then
Ian Kent 36ee82
+not used. Default is an empty list in which case either the server given
Ian Kent 36ee82
+in a map entry or the LDAP configured default is used. This uri list is read at
Ian Kent 36ee82
+startup and whenever the daemon receives a HUP signal.
Ian Kent 36ee82
+.TP
Ian Kent 36ee82
 .B SEARCH_BASE
Ian Kent 36ee82
 The base dn to use when searching for amap base dn. This entry may be
Ian Kent 36ee82
 given multiple times and each will be checked for a map base dn in
Ian Kent 36ee82
-the order they occur in the configuration.
Ian Kent 36ee82
+the order they occur in the configuration. The search base list is read
Ian Kent 36ee82
+at startup and whenever the daemon recieves a HUP signal.
Ian Kent 36ee82
 .TP
Ian Kent 36ee82
 .B MAP_OBJECT_CLASS
Ian Kent 36ee82
 The map object class. In the \fBnisMap\fP schema this corresponds to the class
Ian Kent 36ee82
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
Ian Kent 36ee82
index 2baf8b8..4068561 100644
Ian Kent 36ee82
--- a/modules/lookup_ldap.c
Ian Kent 36ee82
+++ b/modules/lookup_ldap.c
Ian Kent 36ee82
@@ -49,6 +49,8 @@ static struct ldap_schema common_schema[] = {
Ian Kent 36ee82
 };
Ian Kent 36ee82
 static unsigned int common_schema_count = sizeof(common_schema)/sizeof(struct ldap_schema);
Ian Kent 36ee82
 
Ian Kent 36ee82
+static LDAP *auth_init(const char *, struct lookup_context *);
Ian Kent 36ee82
+
Ian Kent 36ee82
 int bind_ldap_anonymous(LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 36ee82
 {
Ian Kent 36ee82
 	int rv;
Ian Kent 36ee82
@@ -59,10 +61,18 @@ int bind_ldap_anonymous(LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 36ee82
 		rv = ldap_simple_bind_s(ldap, NULL, NULL);
Ian Kent 36ee82
 
Ian Kent 36ee82
 	if (rv != LDAP_SUCCESS) {
Ian Kent 36ee82
-		crit(LOGOPT_ANY,
Ian Kent 36ee82
-		     MODPREFIX "Unable to bind to the LDAP server: "
Ian Kent 36ee82
-		     "%s, error %s", ctxt->server ? "" : "(default)",
Ian Kent 36ee82
-		     ldap_err2string(rv));
Ian Kent 36ee82
+		if (!ctxt->uri) {
Ian Kent 36ee82
+			crit(LOGOPT_ANY,
Ian Kent 36ee82
+			     MODPREFIX "Unable to bind to the LDAP server: "
Ian Kent 36ee82
+			     "%s, error %s", ctxt->server ? "" : "(default)",
Ian Kent 36ee82
+			     ldap_err2string(rv));
Ian Kent 36ee82
+		} else {
Ian Kent 36ee82
+			struct ldap_uri *uri;
Ian Kent 36ee82
+			uri = list_entry(ctxt->uri->next, struct ldap_uri, list);
Ian Kent 36ee82
+			warn(LOGOPT_ANY,
Ian Kent 36ee82
+			     MODPREFIX "Unable to bind to the LDAP server: "
Ian Kent 36ee82
+			     "%s, error %s", uri->uri, ldap_err2string(rv));
Ian Kent 36ee82
+		}
Ian Kent 36ee82
 		return -1;
Ian Kent 36ee82
 	}
Ian Kent 36ee82
 
Ian Kent 36ee82
@@ -98,20 +108,21 @@ int unbind_ldap_connection(LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 36ee82
 	return rv;
Ian Kent 36ee82
 }
Ian Kent 36ee82
 
Ian Kent 36ee82
-LDAP *init_ldap_connection(struct lookup_context *ctxt)
Ian Kent 36ee82
+LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt)
Ian Kent 36ee82
 {
Ian Kent 36ee82
 	LDAP *ldap = NULL;
Ian Kent 36ee82
-	int timeout = 8;
Ian Kent 36ee82
+	struct timeval timeout     = { ctxt->timeout, 0 };
Ian Kent 36ee82
+	struct timeval net_timeout = { ctxt->network_timeout, 0 };
Ian Kent 36ee82
 	int rv;
Ian Kent 36ee82
 
Ian Kent 36ee82
 	ctxt->version = 3;
Ian Kent 36ee82
 
Ian Kent 36ee82
 	/* Initialize the LDAP context. */
Ian Kent 36ee82
-	rv = ldap_initialize(&ldap, ctxt->server);
Ian Kent 36ee82
+	rv = ldap_initialize(&ldap, uri);
Ian Kent 36ee82
 	if (rv != LDAP_OPT_SUCCESS) {
Ian Kent 36ee82
 		crit(LOGOPT_ANY,
Ian Kent 36ee82
 		     MODPREFIX "couldn't initialize LDAP connection to %s",
Ian Kent 36ee82
-		     ctxt->server ? ctxt->server : "default server");
Ian Kent 36ee82
+		     uri ? uri : "default server");
Ian Kent 36ee82
 		return NULL;
Ian Kent 36ee82
 	}
Ian Kent 36ee82
 
Ian Kent 36ee82
@@ -120,7 +131,7 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt)
Ian Kent 36ee82
 	if (rv != LDAP_OPT_SUCCESS) {
Ian Kent 36ee82
 		/* fall back to LDAPv2 */
Ian Kent 36ee82
 		ldap_unbind_ext(ldap, NULL, NULL);
Ian Kent 36ee82
-		rv = ldap_initialize(&ldap, ctxt->server);
Ian Kent 36ee82
+		rv = ldap_initialize(&ldap, uri);
Ian Kent 36ee82
 		if (rv != LDAP_OPT_SUCCESS) {
Ian Kent 36ee82
 			crit(LOGOPT_ANY, MODPREFIX "couldn't initialize LDAP");
Ian Kent 36ee82
 			return NULL;
Ian Kent 36ee82
@@ -128,12 +139,22 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt)
Ian Kent 36ee82
 		ctxt->version = 2;
Ian Kent 36ee82
 	}
Ian Kent 36ee82
 
Ian Kent 36ee82
-	/* Sane network connection timeout */
Ian Kent 36ee82
-	rv = ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout);
Ian Kent 36ee82
+
Ian Kent 36ee82
+	if (ctxt->timeout != -1) {
Ian Kent 36ee82
+		/* Set synchronous call timeout */
Ian Kent 36ee82
+		rv = ldap_set_option(ldap, LDAP_OPT_TIMEOUT, &timeout);
Ian Kent 36ee82
+		if (rv != LDAP_OPT_SUCCESS)
Ian Kent 36ee82
+			info(LOGOPT_ANY, MODPREFIX
Ian Kent 36ee82
+			     "failed to set synchronous call timeout to %d",
Ian Kent 36ee82
+			     timeout.tv_sec);
Ian Kent 36ee82
+	}
Ian Kent 36ee82
+
Ian Kent 36ee82
+	/* Sane network timeout */
Ian Kent 36ee82
+	rv = ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &net_timeout);
Ian Kent 36ee82
 	if (rv != LDAP_OPT_SUCCESS)
Ian Kent 36ee82
 		info(LOGOPT_ANY,
Ian Kent 36ee82
 		     MODPREFIX "failed to set connection timeout to %d",
Ian Kent 36ee82
-		     timeout);
Ian Kent 36ee82
+		     net_timeout.tv_sec);
Ian Kent 36ee82
 
Ian Kent 36ee82
 #ifdef WITH_SASL
Ian Kent 36ee82
 	if (ctxt->use_tls) {
Ian Kent 36ee82
@@ -159,7 +180,7 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt)
Ian Kent 36ee82
 				return NULL;
Ian Kent 36ee82
 			}
Ian Kent 36ee82
 			ctxt->use_tls = LDAP_TLS_DONT_USE;
Ian Kent 36ee82
-			ldap = init_ldap_connection(ctxt);
Ian Kent 36ee82
+			ldap = init_ldap_connection(uri, ctxt);
Ian Kent 36ee82
 			if (ldap)
Ian Kent 36ee82
 				ctxt->use_tls = LDAP_TLS_INIT;
Ian Kent 36ee82
 			return ldap;
Ian Kent 36ee82
@@ -271,7 +292,7 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla
Ian Kent 36ee82
 	e = ldap_first_entry(ldap, result);
Ian Kent 36ee82
 	if (e) {
Ian Kent 36ee82
 		dn = ldap_get_dn(ldap, e);
Ian Kent 36ee82
-		debug(LOGOPT_NONE, MODPREFIX "query dn %s", dn);
Ian Kent 36ee82
+		debug(LOGOPT_NONE, MODPREFIX "found query dn %s", dn);
Ian Kent 36ee82
 	} else {
Ian Kent 36ee82
 		debug(LOGOPT_NONE,
Ian Kent 36ee82
 		      MODPREFIX "query succeeded, no matches for %s",
Ian Kent 36ee82
@@ -378,16 +399,11 @@ static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 36ee82
 	return 0;
Ian Kent 36ee82
 }
Ian Kent 36ee82
 
Ian Kent 36ee82
-static LDAP *do_connect(struct lookup_context *ctxt)
Ian Kent 36ee82
+static int do_bind(LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 36ee82
 {
Ian Kent 36ee82
-	LDAP *ldap;
Ian Kent 36ee82
 	char *host = NULL, *nhost;
Ian Kent 36ee82
 	int rv, need_base = 1;
Ian Kent 36ee82
 
Ian Kent 36ee82
-	ldap = init_ldap_connection(ctxt);
Ian Kent 36ee82
-	if (!ldap)
Ian Kent 36ee82
-		return NULL;
Ian Kent 36ee82
-
Ian Kent 36ee82
 #ifdef WITH_SASL
Ian Kent 36ee82
 	debug(LOGOPT_NONE, "auth_required: %d, sasl_mech %s",
Ian Kent 36ee82
 	      ctxt->auth_required, ctxt->sasl_mech);
Ian Kent 36ee82
@@ -407,23 +423,19 @@ static LDAP *do_connect(struct lookup_context *ctxt)
Ian Kent 36ee82
 	debug(LOGOPT_NONE, MODPREFIX "ldap anonymous bind returned %d", rv);
Ian Kent 36ee82
 #endif
Ian Kent 36ee82
 
Ian Kent 36ee82
-	if (rv != 0) {
Ian Kent 36ee82
-		unbind_ldap_connection(ldap, ctxt);
Ian Kent 36ee82
-		return NULL;
Ian Kent 36ee82
-	}
Ian Kent 36ee82
+	if (rv != 0)
Ian Kent 36ee82
+		return 0;
Ian Kent 36ee82
 
Ian Kent 36ee82
 	rv = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host);
Ian Kent 36ee82
         if (rv != LDAP_SUCCESS || !host) {
Ian Kent 36ee82
-		unbind_ldap_connection(ldap, ctxt);
Ian Kent 36ee82
 		debug(LOGOPT_ANY, "failed to get hostname for connection");
Ian Kent 36ee82
-		return NULL;
Ian Kent 36ee82
+		return 0;
Ian Kent 36ee82
 	}
Ian Kent 36ee82
 
Ian Kent 36ee82
 	nhost = strdup(host);
Ian Kent 36ee82
 	if (!nhost) {
Ian Kent 36ee82
-		unbind_ldap_connection(ldap, ctxt);
Ian Kent 36ee82
 		debug(LOGOPT_ANY, "failed to alloc context for hostname");
Ian Kent 36ee82
-		return NULL;
Ian Kent 36ee82
+		return 0;
Ian Kent 36ee82
 	}
Ian Kent 36ee82
 	ldap_memfree(host);
Ian Kent 36ee82
 
Ian Kent 36ee82
@@ -443,7 +455,7 @@ static LDAP *do_connect(struct lookup_context *ctxt)
Ian Kent 36ee82
 	}
Ian Kent 36ee82
 
Ian Kent 36ee82
 	if (!need_base)
Ian Kent 36ee82
-		return ldap;
Ian Kent 36ee82
+		return 1;
Ian Kent 36ee82
 
Ian Kent 36ee82
 	/*
Ian Kent 36ee82
 	 * If the schema isn't defined in the configuration then check for
Ian Kent 36ee82
@@ -452,20 +464,134 @@ static LDAP *do_connect(struct lookup_context *ctxt)
Ian Kent 36ee82
 	 */
Ian Kent 36ee82
 	if (!ctxt->schema) {
Ian Kent 36ee82
 		if (!find_query_dn(ldap, ctxt)) {
Ian Kent 36ee82
-			unbind_ldap_connection(ldap, ctxt);
Ian Kent 36ee82
 			error(LOGOPT_ANY,
Ian Kent 36ee82
 		      	      MODPREFIX "failed to find valid query dn");
Ian Kent 36ee82
-			return NULL;
Ian Kent 36ee82
+			return 0;
Ian Kent 36ee82
 		}
Ian Kent 36ee82
 	} else {
Ian Kent 36ee82
 		const char *class = ctxt->schema->map_class;
Ian Kent 36ee82
 		const char *key = ctxt->schema->map_attr;
Ian Kent 36ee82
 		if (!get_query_dn(ldap, ctxt, class, key)) {
Ian Kent 36ee82
-			unbind_ldap_connection(ldap, ctxt);
Ian Kent 36ee82
 			error(LOGOPT_ANY, MODPREFIX "failed to get query dn");
Ian Kent 36ee82
+			return 0;
Ian Kent 36ee82
+		}
Ian Kent 36ee82
+	}
Ian Kent 36ee82
+
Ian Kent 36ee82
+	return 1;
Ian Kent 36ee82
+}
Ian Kent 36ee82
+
Ian Kent 36ee82
+static LDAP *do_connect(const char *uri, struct lookup_context *ctxt)
Ian Kent 36ee82
+{
Ian Kent 36ee82
+	LDAP *ldap;
Ian Kent 36ee82
+
Ian Kent 36ee82
+	ldap = init_ldap_connection(uri, ctxt);
Ian Kent 36ee82
+	if (!ldap)
Ian Kent 36ee82
+		return NULL;
Ian Kent 36ee82
+
Ian Kent 36ee82
+	if (!do_bind(ldap, ctxt)) {
Ian Kent 36ee82
+		unbind_ldap_connection(ldap, ctxt);
Ian Kent 36ee82
+		return NULL;
Ian Kent 36ee82
+	}
Ian Kent 36ee82
+
Ian Kent 36ee82
+	return ldap;
Ian Kent 36ee82
+}
Ian Kent 36ee82
+
Ian Kent 36ee82
+static LDAP *connect_to_server(const char *uri, struct lookup_context *ctxt)
Ian Kent 36ee82
+{
Ian Kent 36ee82
+	LDAP *ldap;
Ian Kent 36ee82
+
Ian Kent 36ee82
+#ifdef WITH_SASL
Ian Kent 36ee82
+	/*
Ian Kent 36ee82
+	 * Determine which authentication mechanism to use if we require
Ian Kent 36ee82
+	 * authentication.
Ian Kent 36ee82
+	 */
Ian Kent 36ee82
+	if (ctxt->auth_required & LDAP_AUTH_REQUIRED) {
Ian Kent 36ee82
+		ldap = auth_init(uri, ctxt);
Ian Kent 36ee82
+		if (!ldap && ctxt->auth_required & LDAP_AUTH_AUTODETECT)
Ian Kent 36ee82
+			warn(LOGOPT_NONE,
Ian Kent 36ee82
+			     "no authentication mechanisms auto detected.");
Ian Kent 36ee82
+		if (!ldap) {
Ian Kent 36ee82
+			error(LOGOPT_ANY, MODPREFIX
Ian Kent 36ee82
+			      "cannot initialize authentication setup");
Ian Kent 36ee82
 			return NULL;
Ian Kent 36ee82
 		}
Ian Kent 36ee82
+
Ian Kent 36ee82
+		if (!do_bind(ldap, ctxt)) {
Ian Kent 36ee82
+			unbind_ldap_connection(ldap, ctxt);
Ian Kent 36ee82
+			error(LOGOPT_ANY, MODPREFIX "cannot bind to server");
Ian Kent 36ee82
+			return NULL;
Ian Kent 36ee82
+		}
Ian Kent 36ee82
+
Ian Kent 36ee82
+		return ldap;
Ian Kent 36ee82
+	}
Ian Kent 36ee82
+#endif
Ian Kent 36ee82
+
Ian Kent 36ee82
+	ldap = do_connect(uri, ctxt);
Ian Kent 36ee82
+	if (!ldap) {
Ian Kent 36ee82
+		error(LOGOPT_ANY, MODPREFIX "cannot connect to server");
Ian Kent 36ee82
+		return NULL;
Ian Kent 36ee82
+	}
Ian Kent 36ee82
+
Ian Kent 36ee82
+	return ldap;
Ian Kent 36ee82
+}
Ian Kent 36ee82
+
Ian Kent 36ee82
+static LDAP *find_server(struct lookup_context *ctxt)
Ian Kent 36ee82
+{
Ian Kent 36ee82
+	LDAP *ldap = NULL;
Ian Kent 36ee82
+	struct ldap_uri *this;
Ian Kent 36ee82
+	struct list_head *p;
Ian Kent 36ee82
+	LIST_HEAD(tmp);
Ian Kent 36ee82
+
Ian Kent 36ee82
+	/* Try each uri in list, add connect fails to tmp list */
Ian Kent 36ee82
+	p = ctxt->uri->next;
Ian Kent 36ee82
+	while(p != ctxt->uri) {
Ian Kent 36ee82
+		this = list_entry(p, struct ldap_uri, list);
Ian Kent 36ee82
+		p = p->next;
Ian Kent 36ee82
+		debug(LOGOPT_ANY, "check uri %s", this->uri);
Ian Kent 36ee82
+		ldap = connect_to_server(this->uri, ctxt);
Ian Kent 36ee82
+		if (ldap) {
Ian Kent 36ee82
+			debug(LOGOPT_ANY, "connexted to uri %s", this->uri);
Ian Kent 36ee82
+			break;
Ian Kent 36ee82
+		}
Ian Kent 36ee82
+		list_del_init(&this->list);
Ian Kent 36ee82
+		list_add_tail(&this->list, &tmp);
Ian Kent 36ee82
 	}
Ian Kent 36ee82
+	/*
Ian Kent 36ee82
+	 * Successfuly connected uri (head of list) and untried uris are
Ian Kent 36ee82
+	 * in ctxt->uri list. Make list of remainder and failed uris with
Ian Kent 36ee82
+	 * failed uris at end and assign back to ctxt-uri.
Ian Kent 36ee82
+	 */
Ian Kent 36ee82
+	list_splice(ctxt->uri, &tmp);
Ian Kent 36ee82
+	INIT_LIST_HEAD(ctxt->uri);
Ian Kent 36ee82
+	list_splice(&tmp, ctxt->uri);
Ian Kent 36ee82
+
Ian Kent 36ee82
+	return ldap;
Ian Kent 36ee82
+}
Ian Kent 36ee82
+
Ian Kent 36ee82
+static LDAP *do_reconnect(struct lookup_context *ctxt)
Ian Kent 36ee82
+{
Ian Kent 36ee82
+	LDAP *ldap;
Ian Kent 36ee82
+
Ian Kent 36ee82
+	if (ctxt->server || !ctxt->uri) {
Ian Kent 36ee82
+		ldap = do_connect(ctxt->server, ctxt);
Ian Kent 36ee82
+		return ldap;
Ian Kent 36ee82
+	} else {
Ian Kent 36ee82
+		struct ldap_uri *this;
Ian Kent 36ee82
+		this = list_entry(ctxt->uri->next, struct ldap_uri, list);
Ian Kent 36ee82
+		ldap = do_connect(this->uri, ctxt);
Ian Kent 36ee82
+		if (ldap)
Ian Kent 36ee82
+			return ldap;
Ian Kent 36ee82
+		/* Failed to connect, put at end of list */
Ian Kent 36ee82
+		list_del_init(&this->list);
Ian Kent 36ee82
+		list_add_tail(&this->list, ctxt->uri);
Ian Kent 36ee82
+	}
Ian Kent 36ee82
+
Ian Kent 36ee82
+	autofs_sasl_done(ctxt);
Ian Kent 36ee82
+
Ian Kent 36ee82
+	/* Current server failed connect, try the rest */
Ian Kent 36ee82
+	ldap = find_server(ctxt);
Ian Kent 36ee82
+	if (!ldap)
Ian Kent 36ee82
+		error(LOGOPT_ANY, MODPREFIX "failed to find available server");
Ian Kent 36ee82
 
Ian Kent 36ee82
 	return ldap;
Ian Kent 36ee82
 }
Ian Kent 36ee82
@@ -760,10 +886,10 @@ out:
Ian Kent 36ee82
  *  information.  If there is no configuration file, then we fall back to
Ian Kent 36ee82
  *  trying all supported authentication mechanisms until one works.
Ian Kent 36ee82
  *
Ian Kent 36ee82
- *  Returns 0 on success, with authtype, user and secret filled in as
Ian Kent 36ee82
- *  appropriate.  Returns -1 on failre.
Ian Kent 36ee82
+ *  Returns ldap connection on success, with authtype, user and secret
Ian Kent 36ee82
+ *  filled in as appropriate.  Returns NULL on failre.
Ian Kent 36ee82
  */
Ian Kent 36ee82
-int auth_init(struct lookup_context *ctxt)
Ian Kent 36ee82
+static LDAP *auth_init(const char *uri, struct lookup_context *ctxt)
Ian Kent 36ee82
 {
Ian Kent 36ee82
 	int ret;
Ian Kent 36ee82
 	LDAP *ldap;
Ian Kent 36ee82
@@ -776,14 +902,11 @@ int auth_init(struct lookup_context *ctxt)
Ian Kent 36ee82
 	 */
Ian Kent 36ee82
 	ret = parse_ldap_config(ctxt);
Ian Kent 36ee82
 	if (ret)
Ian Kent 36ee82
-		return -1;
Ian Kent 36ee82
-
Ian Kent 36ee82
-	if (ctxt->auth_required & LDAP_AUTH_NOTREQUIRED)
Ian Kent 36ee82
-		return 0;
Ian Kent 36ee82
+		return NULL;
Ian Kent 36ee82
 
Ian Kent 36ee82
-	ldap = init_ldap_connection(ctxt);
Ian Kent 36ee82
+	ldap = init_ldap_connection(uri, ctxt);
Ian Kent 36ee82
 	if (!ldap)
Ian Kent 36ee82
-		return -1;
Ian Kent 36ee82
+		return NULL;
Ian Kent 36ee82
 
Ian Kent 36ee82
 	/*
Ian Kent 36ee82
 	 *  Initialize the sasl library.  It is okay if user and secret
Ian Kent 36ee82
@@ -794,18 +917,12 @@ int auth_init(struct lookup_context *ctxt)
Ian Kent 36ee82
 	 *  the credential cache and the client and service principals.
Ian Kent 36ee82
 	 */
Ian Kent 36ee82
 	ret = autofs_sasl_init(ldap, ctxt);
Ian Kent 36ee82
-	unbind_ldap_connection(ldap, ctxt);
Ian Kent 36ee82
 	if (ret) {
Ian Kent 36ee82
 		ctxt->sasl_mech = NULL;
Ian Kent 36ee82
-		if (ctxt->auth_required & LDAP_AUTH_AUTODETECT) {
Ian Kent 36ee82
-			warn(LOGOPT_NONE,
Ian Kent 36ee82
-			     "no authentication mechanisms auto detected.");
Ian Kent 36ee82
-			return 0;
Ian Kent 36ee82
-		}
Ian Kent 36ee82
-		return -1;
Ian Kent 36ee82
+		return NULL;
Ian Kent 36ee82
 	}
Ian Kent 36ee82
 
Ian Kent 36ee82
-	return 0;
Ian Kent 36ee82
+	return ldap;
Ian Kent 36ee82
 }
Ian Kent 36ee82
 #endif
Ian Kent 36ee82
 
Ian Kent 36ee82
@@ -1036,6 +1153,8 @@ static void free_context(struct lookup_context *ctxt)
Ian Kent 36ee82
 		free(ctxt->cur_host);
Ian Kent 36ee82
 	if (ctxt->base)
Ian Kent 36ee82
 		free(ctxt->base);
Ian Kent 36ee82
+	if (ctxt->uri)
Ian Kent 36ee82
+		defaults_free_uris(ctxt->uri);
Ian Kent 36ee82
 	if (ctxt->sdns)
Ian Kent 36ee82
 		defaults_free_searchdns(ctxt->sdns);
Ian Kent 36ee82
 	free(ctxt);
Ian Kent 36ee82
@@ -1043,6 +1162,30 @@ static void free_context(struct lookup_context *ctxt)
Ian Kent 36ee82
 	return;
Ian Kent 36ee82
 }
Ian Kent 36ee82
 
Ian Kent 36ee82
+static void validate_uris(struct list_head *list)
Ian Kent 36ee82
+{
Ian Kent 36ee82
+	struct list_head *next;
Ian Kent 36ee82
+
Ian Kent 36ee82
+	next = list->next;
Ian Kent 36ee82
+	while (next != list) {
Ian Kent 36ee82
+		struct ldap_uri *this;
Ian Kent 36ee82
+
Ian Kent 36ee82
+		this = list_entry(next, struct ldap_uri, list);
Ian Kent 36ee82
+		next = next->next;
Ian Kent 36ee82
+
Ian Kent 36ee82
+		/* At least we get some basic validation */
Ian Kent 36ee82
+		if (!ldap_is_ldap_url(this->uri)) {
Ian Kent 36ee82
+			warn(LOGOPT_ANY,
Ian Kent 36ee82
+			     "removed invalid uri from list, %s", this->uri);
Ian Kent 36ee82
+			list_del(&this->list);
Ian Kent 36ee82
+			free(this->uri);
Ian Kent 36ee82
+			free(this);
Ian Kent 36ee82
+		}
Ian Kent 36ee82
+	}
Ian Kent 36ee82
+
Ian Kent 36ee82
+	return;			
Ian Kent 36ee82
+}
Ian Kent 36ee82
+
Ian Kent 36ee82
 /*
Ian Kent 36ee82
  * This initializes a context (persistent non-global data) for queries to
Ian Kent 36ee82
  * this module.  Return zero if we succeed.
Ian Kent 36ee82
@@ -1051,7 +1194,6 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
Ian Kent 36ee82
 {
Ian Kent 36ee82
 	struct lookup_context *ctxt;
Ian Kent 36ee82
 	char buf[MAX_ERR_BUF];
Ian Kent 36ee82
-	int ret;
Ian Kent 36ee82
 	LDAP *ldap = NULL;
Ian Kent 36ee82
 
Ian Kent 36ee82
 	*context = NULL;
Ian Kent 36ee82
@@ -1079,33 +1221,42 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
Ian Kent 36ee82
 		return 1;
Ian Kent 36ee82
 	}
Ian Kent 36ee82
 
Ian Kent 36ee82
-#ifdef WITH_SASL
Ian Kent 36ee82
-	/*
Ian Kent 36ee82
-	 * Determine which authentication mechanism to use.  We sanity-
Ian Kent 36ee82
-	 * check by binding to the server temporarily.
Ian Kent 36ee82
-	 */
Ian Kent 36ee82
-	ret = auth_init(ctxt);
Ian Kent 36ee82
-	if (ret && (ctxt->auth_required & LDAP_AUTH_REQUIRED)) {
Ian Kent 36ee82
-		error(LOGOPT_ANY, MODPREFIX
Ian Kent 36ee82
-		      "cannot initialize authentication setup");
Ian Kent 36ee82
-		free_context(ctxt);
Ian Kent 36ee82
-		return 1;
Ian Kent 36ee82
+	ctxt->timeout = defaults_get_ldap_timeout();
Ian Kent 36ee82
+	ctxt->network_timeout = defaults_get_ldap_network_timeout();
Ian Kent 36ee82
+
Ian Kent 36ee82
+	if (!ctxt->server) {
Ian Kent 36ee82
+		struct list_head *uris = defaults_get_uris();
Ian Kent 36ee82
+		if (uris) {
Ian Kent 36ee82
+			validate_uris(uris);
Ian Kent 36ee82
+			if (!list_empty(uris))
Ian Kent 36ee82
+				ctxt->uri = uris;
Ian Kent 36ee82
+			else 
Ian Kent 36ee82
+				free(uris);
Ian Kent 36ee82
+		}
Ian Kent 36ee82
 	}
Ian Kent 36ee82
-#endif
Ian Kent 36ee82
 
Ian Kent 36ee82
-	ldap = do_connect(ctxt);
Ian Kent 36ee82
-	if (!ldap) {
Ian Kent 36ee82
-		error(LOGOPT_ANY, MODPREFIX "cannot connect to server");
Ian Kent 36ee82
-		free_context(ctxt);
Ian Kent 36ee82
-		return 1;
Ian Kent 36ee82
+	if (ctxt->server || !ctxt->uri) {
Ian Kent 36ee82
+		ldap = connect_to_server(ctxt->server, ctxt);
Ian Kent 36ee82
+		if (!ldap) {
Ian Kent 36ee82
+			free_context(ctxt);
Ian Kent 36ee82
+			return 1;
Ian Kent 36ee82
+		}
Ian Kent 36ee82
+	} else {
Ian Kent 36ee82
+		ldap = find_server(ctxt);
Ian Kent 36ee82
+		if (!ldap) {
Ian Kent 36ee82
+			free_context(ctxt);
Ian Kent 36ee82
+			error(LOGOPT_ANY, MODPREFIX
Ian Kent 36ee82
+			     "failed to find available server");
Ian Kent 36ee82
+			return 1;
Ian Kent 36ee82
+		}
Ian Kent 36ee82
 	}
Ian Kent 36ee82
 	unbind_ldap_connection(ldap, ctxt);
Ian Kent 36ee82
 
Ian Kent 36ee82
 	/* Open the parser, if we can. */
Ian Kent 36ee82
 	ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
Ian Kent 36ee82
 	if (!ctxt->parse) {
Ian Kent 36ee82
-		crit(LOGOPT_ANY, MODPREFIX "failed to open parse context");
Ian Kent 36ee82
 		free_context(ctxt);
Ian Kent 36ee82
+		crit(LOGOPT_ANY, MODPREFIX "failed to open parse context");
Ian Kent 36ee82
 		return 1;
Ian Kent 36ee82
 	}
Ian Kent 36ee82
 	*context = ctxt;
Ian Kent 36ee82
@@ -1153,7 +1304,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
Ian Kent 36ee82
 	query[l] = '\0';
Ian Kent 36ee82
 
Ian Kent 36ee82
 	/* Initialize the LDAP context. */
Ian Kent 36ee82
-	ldap = do_connect(ctxt);
Ian Kent 36ee82
+	ldap = do_reconnect(ctxt);
Ian Kent 36ee82
 	if (!ldap)
Ian Kent 36ee82
 		return NSS_STATUS_UNAVAIL;
Ian Kent 36ee82
 
Ian Kent 36ee82
@@ -1305,7 +1456,7 @@ static int read_one_map(struct autofs_point *ap,
Ian Kent 36ee82
 	query[l] = '\0';
Ian Kent 36ee82
 
Ian Kent 36ee82
 	/* Initialize the LDAP context. */
Ian Kent 36ee82
-	ldap = do_connect(ctxt);
Ian Kent 36ee82
+	ldap = do_reconnect(ctxt);
Ian Kent 36ee82
 	if (!ldap)
Ian Kent 36ee82
 		return NSS_STATUS_UNAVAIL;
Ian Kent 36ee82
 
Ian Kent 36ee82
@@ -1536,6 +1687,9 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
Ian Kent 36ee82
 	if (ret != NSS_STATUS_SUCCESS) {
Ian Kent 36ee82
 		switch (rv) {
Ian Kent 36ee82
 		case LDAP_SIZELIMIT_EXCEEDED:
Ian Kent 36ee82
+			crit(ap->logopt, MODPREFIX
Ian Kent 36ee82
+			     "Unable to download entire LDAP map for: %s",
Ian Kent 36ee82
+			     ap->path);
Ian Kent 36ee82
 		case LDAP_UNWILLING_TO_PERFORM:
Ian Kent 36ee82
 			pthread_setcancelstate(cur_state, NULL);
Ian Kent 36ee82
 			return NSS_STATUS_UNAVAIL;
Ian Kent 36ee82
@@ -1612,7 +1766,7 @@ static int lookup_one(struct autofs_point *ap,
Ian Kent 36ee82
 	query[ql] = '\0';
Ian Kent 36ee82
 
Ian Kent 36ee82
 	/* Initialize the LDAP context. */
Ian Kent 36ee82
-	ldap = do_connect(ctxt);
Ian Kent 36ee82
+	ldap = do_reconnect(ctxt);
Ian Kent 36ee82
 	if (!ldap)
Ian Kent 36ee82
 		return CHE_FAIL;
Ian Kent 36ee82
 
Ian Kent 36ee82
diff --git a/redhat/autofs.sysconfig.in b/redhat/autofs.sysconfig.in
Ian Kent 36ee82
index 2b1e20a..f01ee5f 100644
Ian Kent 36ee82
--- a/redhat/autofs.sysconfig.in
Ian Kent 36ee82
+++ b/redhat/autofs.sysconfig.in
Ian Kent 36ee82
@@ -23,6 +23,25 @@ BROWSE_MODE="no"
Ian Kent 36ee82
 #
Ian Kent 36ee82
 # Define base dn for map dn lookup.
Ian Kent 36ee82
 #
Ian Kent 36ee82
+# Define server URIs
Ian Kent 36ee82
+#
Ian Kent 36ee82
+# LDAP_URI - space seperated list of server uris of the form
Ian Kent 36ee82
+# 	     <proto>://<server>[/] where <proto> can be ldap
Ian Kent 36ee82
+# 	     or ldaps. The option can be given multiple times.
Ian Kent 36ee82
+# 	     Map entries that include a server name override
Ian Kent 36ee82
+# 	     this option.
Ian Kent 36ee82
+#
Ian Kent 36ee82
+#LDAP_URI=""
Ian Kent 36ee82
+#
Ian Kent 36ee82
+# LDAP__TIMEOUT - timeout value for the synchronous API  calls
Ian Kent 36ee82
+#		  (default is LDAP library default).
Ian Kent 36ee82
+#
Ian Kent 36ee82
+#LDAP_TIMEOUT=-1
Ian Kent 36ee82
+#
Ian Kent 36ee82
+# LDAP_NETWORK_TIMEOUT - set the network response timeout (default 8).
Ian Kent 36ee82
+#
Ian Kent 36ee82
+#LDAP_NETWORK_TIMEOUT=8
Ian Kent 36ee82
+#
Ian Kent 36ee82
 # SEARCH_BASE - base dn to use for searching for map search dn.
Ian Kent 36ee82
 # 		Multiple entries can be given and they are checked
Ian Kent 36ee82
 # 		in the order they occur here.
Ian Kent 36ee82
diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in
Ian Kent 36ee82
index 2b1e20a..028341c 100644
Ian Kent 36ee82
--- a/samples/autofs.conf.default.in
Ian Kent 36ee82
+++ b/samples/autofs.conf.default.in
Ian Kent 36ee82
@@ -21,6 +21,25 @@ BROWSE_MODE="no"
Ian Kent 36ee82
 #
Ian Kent 36ee82
 #LOGGING="none"
Ian Kent 36ee82
 #
Ian Kent 36ee82
+# Define server URIs
Ian Kent 36ee82
+#
Ian Kent 36ee82
+# LDAP_URI - space seperated list of server uris of the form
Ian Kent 36ee82
+# 	     <proto>://<server>[/] where <proto> can be ldap
Ian Kent 36ee82
+# 	     or ldaps. The option can be given multiple times.
Ian Kent 36ee82
+# 	     Map entries that include a server name override
Ian Kent 36ee82
+# 	     this option.
Ian Kent 36ee82
+#
Ian Kent 36ee82
+#LDAP_URI=""
Ian Kent 36ee82
+#
Ian Kent 36ee82
+# LDAP__TIMEOUT - timeout value for the synchronous API  calls
Ian Kent 36ee82
+#		  (default is LDAP library default).
Ian Kent 36ee82
+#
Ian Kent 36ee82
+#LDAP_TIMEOUT=-1
Ian Kent 36ee82
+#
Ian Kent 36ee82
+# LDAP_NETWORK_TIMEOUT - set the network response timeout (default 8).
Ian Kent 36ee82
+#
Ian Kent 36ee82
+#LDAP_NETWORK_TIMEOUT=8
Ian Kent 36ee82
+#
Ian Kent 36ee82
 # Define base dn for map dn lookup.
Ian Kent 36ee82
 #
Ian Kent 36ee82
 # SEARCH_BASE - base dn to use for searching for map search dn.