Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 130701790bf2d95e902edf16031ff596 > files > 221

autofs-5.0.1-0.rc2.164.el5_8.src.rpm

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