rpms/autofs/F-11 autofs-5.0.4-fix-double-free-in-do_sasl_bind.patch, NONE, 1.1 autofs-5.0.4-fix-incorrect-dclist-free.patch, NONE, 1.1 autofs-5.0.4-fix-map-type-info-parse-error.patch, NONE, 1.1 autofs-5.0.4-fix-notify-mount-message-path.patch, NONE, 1.1 autofs-5.0.4-library-reload-fix-update-fix-2.patch, NONE, 1.1 autofs-5.0.4-manual-umount-recovery-fixes.patch, NONE, 1.1 autofs-5.0.4-remount-we-created-mount-point-fix.patch, NONE, 1.1 autofs-5.0.4-srv-lookup-handle-endian.patch, NONE, 1.1 autofs-5.0.4-use-srv-query-for-domain-dn.patch, NONE, 1.1 autofs.spec, 1.283, 1.284

Ian Kent iankent at fedoraproject.org
Fri Jun 12 09:19:00 UTC 2009


Author: iankent

Update of /cvs/pkgs/rpms/autofs/F-11
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv13595

Modified Files:
	autofs.spec 
Added Files:
	autofs-5.0.4-fix-double-free-in-do_sasl_bind.patch 
	autofs-5.0.4-fix-incorrect-dclist-free.patch 
	autofs-5.0.4-fix-map-type-info-parse-error.patch 
	autofs-5.0.4-fix-notify-mount-message-path.patch 
	autofs-5.0.4-library-reload-fix-update-fix-2.patch 
	autofs-5.0.4-manual-umount-recovery-fixes.patch 
	autofs-5.0.4-remount-we-created-mount-point-fix.patch 
	autofs-5.0.4-srv-lookup-handle-endian.patch 
	autofs-5.0.4-use-srv-query-for-domain-dn.patch 
Log Message:
* Fri Jun 12 2009 Ian Kent <ikent at redhat.com> - 1:5.0.4-31
- add support for LDAP_URI="ldap:///<domain db>" SRV RR lookup.
- fix incorrect dclist free.
- srv lookup handle endianness.
- fix bug introduced by library reload changes which causes autofs to
  not release mount thread resources when using submounts.
- fix notify mount message path.
- try harder to work out if we created mount point at remount.
- fix double free in do_sasl_bind().
- manual umount recovery fixes.
- fix map type info parse error.


autofs-5.0.4-fix-double-free-in-do_sasl_bind.patch:

--- NEW FILE autofs-5.0.4-fix-double-free-in-do_sasl_bind.patch ---
autofs-5.0.4 - fix double free in do_sasl_bind()

From: Ian Kent <raven at themaw.net>

In do_sasl_bind() the connection negotiation loop can exit with the
local variable server_cred non-null after it has been freed, leading
to a double free.
---

 CHANGELOG            |    1 +
 modules/cyrus-sasl.c |    4 +++-
 2 files changed, 4 insertions(+), 1 deletions(-)


diff --git a/CHANGELOG b/CHANGELOG
index e138ca3..f0d0e58 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -53,6 +53,7 @@
 - fix not releasing resources when using submounts.
 - fix notify mount message path.
 - remount we created mount point fix.
+- fix double free in sasl_bind().
 
 4/11/2008 autofs-5.0.4
 -----------------------
diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c
index ec2ab0c..04001d0 100644
--- a/modules/cyrus-sasl.c
+++ b/modules/cyrus-sasl.c
@@ -348,8 +348,10 @@ do_sasl_bind(unsigned logopt, LDAP *ld, sasl_conn_t *conn, const char **clientou
 			}
 		}
 
-		if (server_cred && server_cred->bv_len > 0)
+		if (server_cred && server_cred->bv_len > 0) {
 			ber_bvfree(server_cred);
+			server_cred = NULL;
+		}
 
 	} while ((bind_result == LDAP_SASL_BIND_IN_PROGRESS) ||
 		 (sasl_result == SASL_CONTINUE));

autofs-5.0.4-fix-incorrect-dclist-free.patch:

--- NEW FILE autofs-5.0.4-fix-incorrect-dclist-free.patch ---
autofs-5.0.4 - fix incorrect dclist free

From: Ian Kent <raven at themaw.net>

We incorrectly try to free dclist in modules/lookup_ldap.c:find_server().
---

 modules/lookup_ldap.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)


diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index f6b3f42..8f352d6 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -688,6 +688,10 @@ static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt)
 			}
 		}
 		if (!uri) {
+			if (dclist) {
+				free_dclist(dclist);
+				dclist = NULL;
+			}
 			p = p->next;
 			continue;
 		}
@@ -700,8 +704,10 @@ static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt)
 		}
 		free(uri);
 		uri = NULL;
-		free_dclist(dclist);
-		dclist = NULL;
+		if (dclist) {
+			free_dclist(dclist);
+			dclist = NULL;
+		}
 		p = p->next;
 	}
 

autofs-5.0.4-fix-map-type-info-parse-error.patch:

--- NEW FILE autofs-5.0.4-fix-map-type-info-parse-error.patch ---
autofs-5.0.4 - fix map type info parse error

From: Ian Kent <raven at themaw.net>

Fix a mistake in map type info parsing introduced by the IPv6 parse
changes.
---

 CHANGELOG        |    1 +
 lib/parse_subs.c |    4 +++-
 2 files changed, 4 insertions(+), 1 deletions(-)


diff --git a/CHANGELOG b/CHANGELOG
index 05e0206..3fd97d3 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -55,6 +55,7 @@
 - remount we created mount point fix.
 - fix double free in sasl_bind().
 - mannual umount recovery fixes.
+- fix map type info parse error.
 
 4/11/2008 autofs-5.0.4
 -----------------------
diff --git a/lib/parse_subs.c b/lib/parse_subs.c
index 0cba95a..0608cb7 100644
--- a/lib/parse_subs.c
+++ b/lib/parse_subs.c
@@ -315,6 +315,7 @@ struct map_type_info *parse_map_type_info(const char *str)
 {
 	struct map_type_info *info;
 	char *buf, *type, *fmt, *map, *tmp;
+	int seen_colon = 0;
 
 	buf = strdup(str);
 	if (!buf)
@@ -335,11 +336,12 @@ struct map_type_info *parse_map_type_info(const char *str)
 		if (*tmp == ' ') {
 			*tmp = '\0';
 			break;
-		} else if (*tmp == ',') {
+		} else if (!seen_colon && *tmp == ',') {
 			type = buf;
 			*tmp++ = '\0';
 			fmt = tmp;
 		} else if (*tmp == ':') {
+			seen_colon = 1;
 			if (!fmt)
 				type = buf;
 			*tmp++ = '\0';

autofs-5.0.4-fix-notify-mount-message-path.patch:

--- NEW FILE autofs-5.0.4-fix-notify-mount-message-path.patch ---
autofs-5.0.4 - fix notify mount message path

From: Ian Kent <raven at themaw.net>

If logging is set to verbose we want to log the actual path rather
than the false root. Hoevever, when logging is set to debug we do
need to show the false root to give us the true picture in relation
to accompanying log messages.
---

 CHANGELOG         |    1 +
 daemon/direct.c   |    5 ++++-
 daemon/indirect.c |    5 ++++-
 3 files changed, 9 insertions(+), 2 deletions(-)


diff --git a/CHANGELOG b/CHANGELOG
index d1cc113..0a0519f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -51,6 +51,7 @@
 - always read file maps key lookup fixes.
 - use srv query for domain dn.
 - fix not releasing resources when using submounts.
+- fix notify mount message path.
 
 4/11/2008 autofs-5.0.4
 -----------------------
diff --git a/daemon/direct.c b/daemon/direct.c
index 1ed2b15..74a9acc 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -767,8 +767,11 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *
 	}
 
 	ops->timeout(ap->logopt, ioctlfd, &timeout);
-	notify_mount_result(ap, mountpoint, str_offset);
 	cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
+	if (ap->logopt & LOGOPT_DEBUG)
+		notify_mount_result(ap, mountpoint, str_offset);
+	else
+		notify_mount_result(ap, me->key, str_offset);
 	ops->close(ap->logopt, ioctlfd);
 
 	debug(ap->logopt, "mounted trigger %s at %s", me->key, mountpoint);
diff --git a/daemon/indirect.c b/daemon/indirect.c
index bc39e63..463b39c 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -174,7 +174,10 @@ static int do_mount_autofs_indirect(struct autofs_point *ap, const char *root)
 	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
 
 	ops->timeout(ap->logopt, ap->ioctlfd, &timeout);
-	notify_mount_result(ap, root, str_indirect);
+	if (ap->logopt & LOGOPT_DEBUG)
+		notify_mount_result(ap, root, str_indirect);
+	else
+		notify_mount_result(ap, ap->path, str_indirect);
 
 	return 0;
 

autofs-5.0.4-library-reload-fix-update-fix-2.patch:

--- NEW FILE autofs-5.0.4-library-reload-fix-update-fix-2.patch ---
autofs-5.0.4 - library reload fix update fix 2

From: Ian Kent <raven at themaw.net>

The library reload fixes introduced a bug which causes autofs to
not release mount thread resources when using submounts.
---

 CHANGELOG          |    1 +
 daemon/automount.c |   11 +++++++++--
 2 files changed, 10 insertions(+), 2 deletions(-)


diff --git a/CHANGELOG b/CHANGELOG
index f49784a..d1cc113 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -50,6 +50,7 @@
 - always read file maps multi map fix.
 - always read file maps key lookup fixes.
 - use srv query for domain dn.
+- fix not releasing resources when using submounts.
 
 4/11/2008 autofs-5.0.4
 -----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 3a0fe0b..44dcdd6 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -1460,14 +1460,21 @@ static void handle_mounts_cleanup(void *arg)
 	master_remove_mapent(ap->entry);
 	master_source_unlock(ap->entry);
 
+	destroy_logpri_fifo(ap);
+
+	/*
+	 * Submounts are detached threads and don't belong to the
+	 * master map entry list so we need to free their resources
+	 * here.
+	 */
 	if (submount) {
 		mounts_mutex_unlock(ap->parent);
 		master_source_unlock(ap->parent->entry);
+		master_free_mapent_sources(ap->entry, 1);
+		master_free_mapent(ap->entry);
 	}
 	master_mutex_unlock();
 
-	destroy_logpri_fifo(ap);
-
 	if (clean) {
 		if (rmdir(path) == -1) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);

autofs-5.0.4-manual-umount-recovery-fixes.patch:

--- NEW FILE autofs-5.0.4-manual-umount-recovery-fixes.patch ---
autofs-5.0.4 - mannual umount recovery fixes

From: Ian Kent <raven at themaw.net>

Check for the absence of a mount before doing the manual umount
checks and check ioctlfd is valid seperately. Take a write lock
on the map entry mutex to ensure any mount request is complete
before checking.
---

 CHANGELOG         |    1 +
 daemon/direct.c   |    4 ++--
 daemon/indirect.c |   37 +++++++++++++++++++++++--------------
 3 files changed, 26 insertions(+), 16 deletions(-)


diff --git a/CHANGELOG b/CHANGELOG
index f0d0e58..05e0206 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -54,6 +54,7 @@
 - fix notify mount message path.
 - remount we created mount point fix.
 - fix double free in sasl_bind().
+- mannual umount recovery fixes.
 
 4/11/2008 autofs-5.0.4
 -----------------------
diff --git a/daemon/direct.c b/daemon/direct.c
index 74a9acc..7b02c7a 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -889,9 +889,9 @@ void *expire_proc_direct(void *arg)
 			/* Check for manual umount */
 			cache_writelock(me->mc);
 			if (me->ioctlfd != -1 && 
-			    fstat(ioctlfd, &st) != -1 &&
+			    fstat(me->ioctlfd, &st) != -1 &&
 			    !count_mounts(ap->logopt, next->path, st.st_dev)) {
-				ops->close(ap->logopt, ioctlfd);
+				ops->close(ap->logopt, me->ioctlfd);
 				me->ioctlfd = -1;
 				cache_unlock(me->mc);
 				pthread_setcancelstate(cur_state, NULL);
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 463b39c..8025ee4 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -437,7 +437,19 @@ void *expire_proc_indirect(void *arg)
 				struct mapent *me = NULL;
 				struct stat st;
 
-				master_source_readlock(ap->entry);
+				/* It's got a mount, deal with in the outer loop */
+				if (is_mounted(_PATH_MOUNTED, next->path, MNTS_REAL)) {
+					pthread_setcancelstate(cur_state, NULL);
+					continue;
+				}
+
+				/* Don't touch submounts */
+				if (master_find_submount(ap, next->path)) {
+					pthread_setcancelstate(cur_state, NULL);
+					continue;
+				}
+
+				master_source_writelock(ap->entry);
 
 				map = ap->entry->maps;
 				while (map) {
@@ -456,20 +468,17 @@ void *expire_proc_indirect(void *arg)
 					continue;
 				}
 
+				if (me->ioctlfd == -1) {
+					cache_unlock(mc);
+					master_source_unlock(ap->entry);
+					pthread_setcancelstate(cur_state, NULL);
+					continue;
+				}
+
 				/* Check for manual umount */
-				if (me->ioctlfd != -1 &&
-				    (fstat(me->ioctlfd, &st) == -1 ||
-				     !count_mounts(ap->logopt, me->key, st.st_dev))) {
-					if (is_mounted(_PROC_MOUNTS, me->key, MNTS_REAL)) {
-						error(ap->logopt,
-						      "error: possible mtab mismatch %s",
-						      me->key);
-						cache_unlock(mc);
-						master_source_unlock(ap->entry);
-						pthread_setcancelstate(cur_state, NULL);
-						continue;
-					}
-					close(me->ioctlfd);
+				if (fstat(me->ioctlfd, &st) == -1 ||
+				    !count_mounts(ap->logopt, me->key, st.st_dev)) {
+					ops->close(ap->logopt, me->ioctlfd);
 					me->ioctlfd = -1;
 				}
 

autofs-5.0.4-remount-we-created-mount-point-fix.patch:

--- NEW FILE autofs-5.0.4-remount-we-created-mount-point-fix.patch ---
autofs-5.0.4 - remount we created mount point fix

From: Ian Kent <raven at themaw.net>

During remount determine if autofs created the mount point directory,
as best we can.
---

 CHANGELOG    |    1 +
 lib/mounts.c |   15 +++++++--------
 2 files changed, 8 insertions(+), 8 deletions(-)


diff --git a/CHANGELOG b/CHANGELOG
index 0a0519f..e138ca3 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -52,6 +52,7 @@
 - use srv query for domain dn.
 - fix not releasing resources when using submounts.
 - fix notify mount message path.
+- remount we created mount point fix.
 
 4/11/2008 autofs-5.0.4
 -----------------------
diff --git a/lib/mounts.c b/lib/mounts.c
index 4787bb6..4c44982 100644
--- a/lib/mounts.c
+++ b/lib/mounts.c
@@ -1359,18 +1359,17 @@ int try_remount(struct autofs_point *ap, struct mapent *me, unsigned int type)
 	/*
 	 * The directory must exist since we found a device
 	 * number for the mount but we can't know if we created
-	 * it or not. However, if we're mounted on an autofs fs
-	 * then we need to cleanup the path anyway.
+	 * it or not. However, if this is an indirect mount with
+	 * the nobrowse option we need to remove the mount point
+	 * directory at umount anyway.
 	 */
 	if (type == t_indirect) {
-		ap->flags &= ~MOUNT_FLAG_DIR_CREATED;
-		if (ret == DEV_IOCTL_IS_AUTOFS)
+		if (ap->flags & MOUNT_FLAG_GHOST)
+			ap->flags &= ~MOUNT_FLAG_DIR_CREATED;
+		else
 			ap->flags |= MOUNT_FLAG_DIR_CREATED;
-	} else {
+	} else
 		me->flags &= ~MOUNT_FLAG_DIR_CREATED;
-		if (ret == DEV_IOCTL_IS_AUTOFS)
-			me->flags |= MOUNT_FLAG_DIR_CREATED;
-	}
 
 	/*
 	 * Either we opened the mount or we're re-reading the map.

autofs-5.0.4-srv-lookup-handle-endian.patch:

--- NEW FILE autofs-5.0.4-srv-lookup-handle-endian.patch ---
autofs-5.0.4 - srv lookup handle endianness

From: Ian Kent <raven at themaw.net>


---

 modules/dclist.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)


diff --git a/modules/dclist.c b/modules/dclist.c
index 5b0e577..967581c 100644
--- a/modules/dclist.c
+++ b/modules/dclist.c
@@ -34,6 +34,7 @@
 #include <ldap.h>
 #include <sys/param.h>
 #include <errno.h>
+#include <endian.h>
 
 #include "automount.h"
 #include "dclist.h"
@@ -72,8 +73,13 @@
 #define SVAL(buf, pos) (*(const uint16_t *)((const char *)(buf) + (pos)))
 #define IVAL(buf, pos) (*(const uint32_t *)((const char *)(buf) + (pos)))
 
+#if __BYTE_ORDER == __LITTLE_ENDIAN
 #define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
 #define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
+#else
+#define SREV(x) (x)
+#define IREV(x) (x)
+#endif
 
 #define RSVAL(buf, pos) SREV(SVAL(buf, pos))
 #define RIVAL(buf, pos) IREV(IVAL(buf, pos))

autofs-5.0.4-use-srv-query-for-domain-dn.patch:

--- NEW FILE autofs-5.0.4-use-srv-query-for-domain-dn.patch ---
autofs-5.0.4 - use srv query for domain dn

From: Ian Kent <raven at themaw.net>

Add the ability to use a domain dn in the LDAP_URI configuration
entry. If a domain dn is encountered in the LDAP_URI the list of
servers will be queried and used for the LDAP connection. The list
won't be queried again until the minimum ttl found in the SRV RR
records is reached or, if ttl isn't given in any SRV RR records,
after 1 hour.
---

 CHANGELOG                      |    1 
 include/dclist.h               |   14 +
 include/lookup_ldap.h          |    3 
 man/auto.master.5.in           |    8 
 modules/Makefile               |    5 
 modules/dclist.c               |  785 ++++++++++++++++++++++++++++++++++++++++
 modules/lookup_ldap.c          |   86 ++++
 redhat/autofs.sysconfig.in     |   11 +
 samples/autofs.conf.default.in |   11 +
 9 files changed, 911 insertions(+), 13 deletions(-)
 create mode 100644 include/dclist.h
 create mode 100644 modules/dclist.c


diff --git a/CHANGELOG b/CHANGELOG
index 5000f0c..f49784a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -49,6 +49,7 @@
 - dont fail on ipv6 address when adding host.
 - always read file maps multi map fix.
 - always read file maps key lookup fixes.
+- use srv query for domain dn.
 
 4/11/2008 autofs-5.0.4
 -----------------------
diff --git a/include/dclist.h b/include/dclist.h
new file mode 100644
index 0000000..ed89f97
--- /dev/null
+++ b/include/dclist.h
@@ -0,0 +1,14 @@
+#ifndef __DCLIST_H
+#define __DCLIST_H
+
+#include <sys/types.h>
+
+struct dclist {
+	time_t expire;
+	const char *uri;
+};
+
+struct dclist *get_dc_list(unsigned int logopt, const char *uri);
+void free_dclist(struct dclist *dclist);
+
+#endif
diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h
index b47bf5d..dcae220 100644
--- a/include/lookup_ldap.h
+++ b/include/lookup_ldap.h
@@ -10,6 +10,8 @@
 #include <krb5.h>
 #endif
 
+#include "dclist.h"
+
 struct ldap_schema {
 	char *map_class;
 	char *map_attr;
@@ -57,6 +59,7 @@ struct lookup_context {
 	pthread_mutex_t uris_mutex;
 	struct list_head *uris;
 	struct ldap_uri *uri;
+	struct dclist *dclist;
 	char *cur_host;
 	struct ldap_searchdn *sdns;
 
diff --git a/man/auto.master.5.in b/man/auto.master.5.in
index 7b7004f..71c4402 100644
--- a/man/auto.master.5.in
+++ b/man/auto.master.5.in
@@ -271,6 +271,14 @@ 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.
+.P
+This configuration option can also be used to request autofs lookup SRV RRs
+for a domain of the form <proto>:///[<domain dn>]. Note that a trailing
+"/" is not allowed when using this form. If the domain dn is not specified
+the dns domain name (if any) is used to construct the domain dn for the
+SRV RR lookup. The server list returned from an SRV RR lookup is refreshed
+according to the minimum ttl found in the SRV RR records or after one hour,
+whichever is less.
 .TP
 .B SEARCH_BASE
 The base dn to use when searching for amap base dn. This entry may be
diff --git a/modules/Makefile b/modules/Makefile
index 0d12f01..13b3bd8 100644
--- a/modules/Makefile
+++ b/modules/Makefile
@@ -86,9 +86,10 @@ lookup_hesiod.so: lookup_hesiod.c
 cyrus-sasl.o: cyrus-sasl.c
 	$(CC) $(CFLAGS) $(LDAP_FLAGS) -c $<
 
-lookup_ldap.so: lookup_ldap.c $(SASL_OBJ)
+lookup_ldap.so: lookup_ldap.c dclist.o $(SASL_OBJ)
 	$(CC) $(SOLDFLAGS) $(CFLAGS) $(LDAP_FLAGS) -o lookup_ldap.so \
-		lookup_ldap.c $(SASL_OBJ) $(AUTOFS_LIB) $(LIBLDAP)
+		lookup_ldap.c dclist.o $(SASL_OBJ) \
+		$(AUTOFS_LIB) $(LIBLDAP) $(LIBRESOLV)
 	$(STRIP) lookup_ldap.so
 
 mount_nfs.so: mount_nfs.c replicated.o
diff --git a/modules/dclist.c b/modules/dclist.c
new file mode 100644
index 0000000..5b0e577
--- /dev/null
+++ b/modules/dclist.c
@@ -0,0 +1,785 @@
+/*
+ * Copyright 2009 Ian Kent <raven at themaw.net>
+ * Copyright 2009 Red Hat, Inc.
+ *
+ * This module was apapted from code contained in the Samba distribution
+ * file source/libads/dns.c which contained the following copyright
+ * information:
+ *
+ * Unix SMB/CIFS implementation.
+ * DNS utility library
+ * Copyright (C) Gerald (Jerry) Carter           2006.
+ * Copyright (C) Jeremy Allison                  2007.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <stdlib.h>
+#include <string.h>
+#include <resolv.h>
+#include <netdb.h>
+#include <ldap.h>
+#include <sys/param.h>
+#include <errno.h>
+
+#include "automount.h"
+#include "dclist.h"
+
+#define	MAX_DNS_PACKET_SIZE	0xffff
+#define	MAX_DNS_NAME_LENGTH	MAXHOSTNAMELEN
+/* The longest time we will cache dns srv records */
+#define MAX_TTL			(60*60*1) /* 1 hours */
+
+#ifdef NS_HFIXEDSZ	/* Bind 8/9 interface */
+#if !defined(C_IN)	/* AIX 5.3 already defines C_IN */
+#  define C_IN		ns_c_in
+#endif
+#if !defined(T_A)	/* AIX 5.3 already defines T_A */
+#  define T_A   	ns_t_a
+#endif
+
+#  define T_SRV 	ns_t_srv
+#if !defined(T_NS)	/* AIX 5.3 already defines T_NS */
+#  define T_NS 		ns_t_ns
+#endif
+#else
+#  ifdef HFIXEDSZ
+#    define NS_HFIXEDSZ HFIXEDSZ
+#  else
+#    define NS_HFIXEDSZ sizeof(HEADER)
+#  endif	/* HFIXEDSZ */
+#  ifdef PACKETSZ
+#    define NS_PACKETSZ	PACKETSZ
+#  else	/* 512 is usually the default */
+#    define NS_PACKETSZ	512
+#  endif	/* PACKETSZ */
+#  define T_SRV 	33
+#endif
+
+#define SVAL(buf, pos) (*(const uint16_t *)((const char *)(buf) + (pos)))
+#define IVAL(buf, pos) (*(const uint32_t *)((const char *)(buf) + (pos)))
+
+#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
+#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
+
+#define RSVAL(buf, pos) SREV(SVAL(buf, pos))
+#define RIVAL(buf, pos) IREV(IVAL(buf, pos))
+
+#define QSORT_CAST	(int (*)(const void *, const void *))
+
+/* DNS query section in replies */
+
+struct dns_query {
+	const char *hostname;
+	uint16_t type;
+	uint16_t in_class;
+};
+
+/* DNS RR record in reply */
+
+struct dns_rr {
+	const char *hostname;
+	uint16_t type;
+	uint16_t in_class;
+	uint32_t ttl;
+	uint16_t rdatalen;
+	uint8_t *rdata;
+};
+
+/* SRV records */
+
+struct dns_rr_srv {
+	const char *hostname;
+	uint16_t priority;
+	uint16_t weight;
+	uint16_t port;
+	uint32_t ttl;
+};
+
+static pthread_mutex_t dclist_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void dclist_mutex_lock(void)
+{
+	int status = pthread_mutex_lock(&dclist_mutex);
+	if (status)
+		fatal(status);
+	return;
+}
+
+static void dclist_mutex_unlock(void)
+{
+	int status = pthread_mutex_unlock(&dclist_mutex);
+	if (status)
+		fatal(status);
+	return;
+}
+
+static int dns_parse_query(unsigned int logopt,
+			   uint8_t *start, uint8_t *end,
+			   uint8_t **ptr, struct dns_query *q)
+{
+	uint8_t *p = *ptr;
+	char hostname[MAX_DNS_NAME_LENGTH];
+	char buf[MAX_ERR_BUF];
+	int namelen;
+
+	if (!start || !end || !q || !*ptr)
+		return 0;
+
+	memset(q, 0, sizeof(*q));
+
+	/* See RFC 1035 for details. If this fails, then return. */
+
+	namelen = dn_expand(start, end, p, hostname, sizeof(hostname));
+	if (namelen < 0) {
+		error(logopt, "failed to expand query hostname");
+		return 0;
+	}
+
+	p += namelen;
+	q->hostname = strdup(hostname);
+	if (!q) {
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		error(logopt, "strdup: %s", estr);
+		return 0;
+	}
+
+	/* check that we have space remaining */
+
+	if (p + 4 > end) {
+		error(logopt, "insufficient buffer space for result");
+		free((void *) q->hostname);
+		return 0;
+	}
+
+	q->type     = RSVAL(p, 0);
+	q->in_class = RSVAL(p, 2);
+	p += 4;
+
+	*ptr = p;
+
+	return 1;
+}
+
+static int dns_parse_rr(unsigned int logopt,
+			uint8_t *start, uint8_t *end,
+			uint8_t **ptr, struct dns_rr *rr)
+{
+	uint8_t *p = *ptr;
+	char hostname[MAX_DNS_NAME_LENGTH];
+	char buf[MAX_ERR_BUF];
+	int namelen;
+
+	if (!start || !end || !rr || !*ptr)
+		return 0;
+
+	memset(rr, 0, sizeof(*rr));
+
+	/* pull the name from the answer */
+
+	namelen = dn_expand(start, end, p, hostname, sizeof(hostname));
+	if (namelen < 0) {
+		error(logopt, "failed to expand query hostname");
+		return 0;
+	}
+	p += namelen;
+	rr->hostname = strdup(hostname);
+	if (!rr->hostname) {
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		error(logopt, "strdup: %s", estr);
+		return 0;
+	}
+
+	/* check that we have space remaining */
+
+	if (p + 10 > end) {
+		error(logopt, "insufficient buffer space for result");
+		free((void *) rr->hostname);
+		return 0;
+	}
+
+	/* pull some values and then skip onto the string */
+
+	rr->type     = RSVAL(p, 0);
+	rr->in_class = RSVAL(p, 2);
+	rr->ttl      = RIVAL(p, 4);
+	rr->rdatalen = RSVAL(p, 8);
+
+	p += 10;
+
+	/* sanity check the available space */
+
+	if (p + rr->rdatalen > end) {
+		error(logopt, "insufficient buffer space for data");
+		free((void *) rr->hostname);
+		return 0;
+	}
+
+	/* save a point to the rdata for this section */
+
+	rr->rdata = p;
+	p += rr->rdatalen;
+
+	*ptr = p;
+
+	return 1;
+}
+
+static int dns_parse_rr_srv(unsigned int logopt,
+			    uint8_t *start, uint8_t *end,
+			    uint8_t **ptr, struct dns_rr_srv *srv)
+{
+	struct dns_rr rr;
+	uint8_t *p;
+	char dcname[MAX_DNS_NAME_LENGTH];
+	char buf[MAX_ERR_BUF];
+	int namelen;
+
+	if (!start || !end || !srv || !*ptr)
+		return 0;
+
+	/* Parse the RR entry.  Coming out of the this, ptr is at the beginning
+	   of the next record */
+
+	if (!dns_parse_rr(logopt, start, end, ptr, &rr)) {
+		error(logopt, "Failed to parse RR record");
+		return 0;
+	}
+
+	if (rr.type != T_SRV) {
+		error(logopt, "Bad answer type (%d)", rr.type);
+		return 0;
+	}
+
+	p = rr.rdata;
+
+	srv->priority = RSVAL(p, 0);
+	srv->weight   = RSVAL(p, 2);
+	srv->port     = RSVAL(p, 4);
+	srv->ttl      = rr.ttl;
+
+	p += 6;
+
+	namelen = dn_expand(start, end, p, dcname, sizeof(dcname));
+	if (namelen < 0) {
+		error(logopt, "Failed to expand dcname");
+		return 0;
+	}
+
+	srv->hostname = strdup(dcname);
+	if (!srv->hostname) {
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		error(logopt, "strdup: %s", estr);
+		return 0;
+	}
+
+	debug(logopt, "Parsed %s [%u, %u, %u]",
+	      srv->hostname, srv->priority, srv->weight, srv->port);
+
+	return 1;
+}
+
+/*********************************************************************
+ Sort SRV record list based on weight and priority.  See RFC 2782.
+*********************************************************************/
+
+static int dnssrvcmp(struct dns_rr_srv *a, struct dns_rr_srv *b)
+{
+	if (a->priority == b->priority) {
+		/* randomize entries with an equal weight and priority */
+		if (a->weight == b->weight)
+			return 0;
+
+		/* higher weights should be sorted lower */
+		if (a->weight > b->weight)
+			return -1;
+		else
+			return 1;
+	}
+
+	if (a->priority < b->priority)
+		return -1;
+
+	return 1;
+}
+
+#define DNS_FAILED_WAITTIME          30
+
+static int dns_send_req(unsigned int logopt,
+			const char *name, int q_type, uint8_t **rbuf,
+			int *resp_length)
+{
+	uint8_t *buffer = NULL;
+	size_t buf_len = 0;
+	int resp_len = NS_PACKETSZ;
+	static time_t last_dns_check = 0;
+	static unsigned int last_dns_status = 0;
+	time_t now = time(NULL);
+	char buf[MAX_ERR_BUF];
+
+	/* Try to prevent bursts of DNS lookups if the server is down */
+
+	/* Protect against large clock changes */
+
+	if (last_dns_check > now)
+		last_dns_check = 0;
+
+	/* IF we had a DNS timeout or a bad server and we are still
+	   in the 30 second cache window, just return the previous
+	   status and save the network timeout. */
+
+	if ((last_dns_status == ETIMEDOUT ||
+	     last_dns_status == ECONNREFUSED) &&
+	     ((last_dns_check + DNS_FAILED_WAITTIME) > now)) {
+		char *estr = strerror_r(last_dns_status, buf, MAX_ERR_BUF);
+		debug(logopt, "Returning cached status (%s)", estr);
+		return last_dns_status;
+	}
+
+	/* Send the Query */
+	do {
+		if (buffer)
+			free(buffer);
+
+		buf_len = resp_len * sizeof(uint8_t);
+
+		if (buf_len) {
+			buffer = malloc(buf_len);
+			if (!buffer) {
+				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+				error(logopt, "malloc: %s", estr);
+				last_dns_status = ENOMEM;
+				last_dns_check = time(NULL);
+				return last_dns_status;
+			}
+		}
+
+		resp_len = res_query(name, C_IN, q_type, buffer, buf_len);
+		if (resp_len < 0) {
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			error(logopt, "Failed to resolve %s (%s)", name, estr);
+			free(buffer);
+			last_dns_status = ENOENT;
+			last_dns_check = time(NULL);
+			return last_dns_status;
+		}
+
+		/* On AIX, Solaris, and possibly some older glibc systems (e.g. SLES8)
+		   truncated replies never give back a resp_len > buflen
+		   which ends up causing DNS resolve failures on large tcp DNS replies */
+
+		if (buf_len == resp_len) {
+			if (resp_len == MAX_DNS_PACKET_SIZE) {
+				error(logopt,
+				      "DNS reply too large when resolving %s",
+				      name);
+				free(buffer);
+				last_dns_status = EMSGSIZE;
+				last_dns_check = time(NULL);
+				return last_dns_status;
+			}
+
+			resp_len = MIN(resp_len * 2, MAX_DNS_PACKET_SIZE);
+		}
+	} while (buf_len < resp_len && resp_len <= MAX_DNS_PACKET_SIZE);
+
+	*rbuf = buffer;
+	*resp_length = resp_len;
+
+	last_dns_check = time(NULL);
+	last_dns_status = 0;
+
+	return 0;
+}
+
+static int dns_lookup_srv(unsigned int logopt, const char *name,
+			  struct dns_rr_srv **dclist, int *numdcs)
+{
+	uint8_t *buffer = NULL;
+	int resp_len = 0;
+	struct dns_rr_srv *dcs = NULL;
+	int query_count, answer_count;
+	uint8_t *p = buffer;
+	int rrnum;
+	int idx = 0;
+	char buf[MAX_ERR_BUF];
+	int ret;
+
+	if (!name || !dclist)
+		return -EINVAL;
+
+	/* Send the request.  May have to loop several times in case
+	   of large replies */
+
+	ret = dns_send_req(logopt, name, T_SRV, &buffer, &resp_len);
+	if (ret) {
+		error(logopt, "Failed to send DNS query");
+		return ret;
+	}
+	p = buffer;
+
+	/* For some insane reason, the ns_initparse() et. al. routines are only
+	   available in libresolv.a, and not the shared lib.  Who knows why....
+	   So we have to parse the DNS reply ourselves */
+
+	/* Pull the answer RR's count from the header.
+	 * Use the NMB ordering macros */
+
+	query_count      = RSVAL(p, 4);
+	answer_count     = RSVAL(p, 6);
+
+	debug(logopt,
+	      "%d records returned in the answer section.",
+	       answer_count);
+
+	if (answer_count) {
+		dcs = malloc(sizeof(struct dns_rr_srv) * answer_count);
+		if (!dcs) {
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			error(logopt, "malloc: %s", estr);
+			free(buffer);
+			return ENOMEM;
+		}
+	}
+
+	/* now skip the header */
+
+	p += NS_HFIXEDSZ;
+
+	/* parse the query section */
+
+	for (rrnum = 0; rrnum < query_count; rrnum++) {
+		struct dns_query q;
+
+		ret = dns_parse_query(logopt, buffer, buffer+resp_len, &p, &q);
+		if (!ret) {
+			error(logopt,
+			      "Failed to parse query record [%d]", rrnum);
+			free(buffer);
+			free(dcs);
+			return EBADMSG;
+		}
+	}
+
+	/* now we are at the answer section */
+
+	for (rrnum = 0; rrnum < answer_count; rrnum++) {
+		ret = dns_parse_rr_srv(logopt,
+				       buffer, buffer+resp_len,
+				       &p, &dcs[rrnum]);
+		if (!ret) {
+			error(logopt,
+			      "Failed to parse answer record [%d]", rrnum);
+			free(buffer);
+			free(dcs);
+			return EBADMSG;
+		}
+	}
+	idx = rrnum;
+
+	qsort(dcs, idx, sizeof(struct dns_rr_srv), QSORT_CAST dnssrvcmp);
+
+	*dclist = dcs;
+	*numdcs = idx;
+
+	return 0;
+}
+
+static char *escape_dn_commas(const char *uri)
+{
+	size_t len = strlen(uri);
+	char *new, *tmp, *ptr;
+
+	ptr = (char *) uri;
+	while (*ptr) {
+		if (*ptr == '\\')
+			ptr += 2;
+		if (*ptr == ',')
+			len += 2;
+		ptr++;
+	}
+
+	new = malloc(len + 1);
+	if (!new)
+		return NULL;
+	memset(new, 0, len + 1);
+
+	ptr = (char *) uri;
+	tmp = new;
+	while (*ptr) {
+		if (*ptr == '\\') {
+			ptr++;
+			*tmp++ = *ptr++;
+			continue;
+		}
+		if (*ptr == ',') {
+			strcpy(tmp, "%2c");
+			ptr++;
+			tmp += 3;
+			continue;
+		}
+		*tmp++ = *ptr++;
+	}
+
+	return new;
+}
+
+void free_dclist(struct dclist *dclist)
+{
+	if (dclist->uri)
+		free((void *) dclist->uri);
+	free(dclist);
+}
+
+static char *getdnsdomainname(unsigned int logopt)
+{
+	struct addrinfo hints, *ni;
+	char name[MAX_DNS_NAME_LENGTH + 1];
+	char buf[MAX_ERR_BUF];
+	char *dnsdomain = NULL;
+	char *ptr;
+	int ret;
+
+	memset(name, 0, sizeof(name));
+	if (gethostname(name, MAX_DNS_NAME_LENGTH) == -1) {
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		error(logopt, "gethostname: %s", estr);
+		return NULL;
+	}
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_flags = AI_CANONNAME;
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_DGRAM;
+
+	ret = getaddrinfo(name, NULL, &hints, &ni);
+	if (ret) {
+		error(logopt, "hostname lookup failed: %s", gai_strerror(ret));
+		return NULL;
+	}
+
+	ptr = ni->ai_canonname;
+	while (*ptr && *ptr != '.')
+		ptr++;
+
+	if (*++ptr)
+		dnsdomain = strdup(ptr);
+
+	freeaddrinfo(ni);
+
+	return dnsdomain;
+}
+
+struct dclist *get_dc_list(unsigned int logopt, const char *uri)
+{
+	LDAPURLDesc *ludlist = NULL;
+	LDAPURLDesc **ludp;
+	struct dns_rr_srv *dcs;
+	unsigned int min_ttl = MAX_TTL;
+	struct dclist *dclist = NULL;;
+	char buf[MAX_ERR_BUF];
+	char *dn_uri, *esc_uri;
+	char *domain;
+	char *list;
+	int numdcs;
+	int ret;
+
+	if (strcmp(uri, "ldap:///") && strcmp(uri, "ldaps:///")) {
+		dn_uri = strdup(uri);
+		if (!dn_uri) {
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			error(logopt, "strdup: %s", estr);
+			return NULL;
+		}
+	} else {
+		char *dnsdomain;
+		char *hdn;
+
+		dnsdomain = getdnsdomainname(logopt);
+		if (!dnsdomain) {
+			error(logopt, "failed to get dns domainname");
+			return NULL;
+		}
+
+		if (ldap_domain2dn(dnsdomain, &hdn) || hdn == NULL) {
+			error(logopt,
+			      "Could not turn domain \"%s\" into a dn\n",
+			      dnsdomain);
+			free(dnsdomain);
+			return NULL;
+		}
+		free(dnsdomain);
+
+		dn_uri = malloc(strlen(uri) + strlen(hdn) + 1);
+		if (!dn_uri) {
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			error(logopt, "malloc: %s", estr);
+			ber_memfree(hdn);
+			return NULL;
+		}
+
+		strcpy(dn_uri, uri);
+		strcat(dn_uri, hdn);
+		ber_memfree(hdn);
+	}
+
+	esc_uri = escape_dn_commas(dn_uri);
+	if (!esc_uri) {
+		error(logopt, "Could not escape commas in uri %s", dn_uri);
+		free(dn_uri);
+		return NULL;
+	}
+
+	ret = ldap_url_parse(esc_uri, &ludlist);
+	if (ret != LDAP_URL_SUCCESS) {
+		error(logopt, "Could not parse uri %s (%d)", dn_uri, ret);
+		free(esc_uri);
+		free(dn_uri);
+		return NULL;
+	}
+
+	free(esc_uri);
+
+	if (!ludlist) {
+		error(logopt, "No dn found in uri %s", dn_uri);
+		free(dn_uri);
+		return NULL;
+	}
+
+	free(dn_uri);
+
+	dclist = malloc(sizeof(struct dclist));
+	if (!dclist) {
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		error(logopt, "malloc: %s", estr);
+		ldap_free_urldesc(ludlist);
+		return NULL;
+	}
+	memset(dclist, 0, sizeof(struct dclist));
+
+	list = NULL;
+	for (ludp = &ludlist; *ludp != NULL;) {
+		LDAPURLDesc *lud = *ludp;
+		size_t req_len, len;
+		char *request = NULL;
+		char *tmp;
+		int i;
+
+		if (!lud->lud_dn && !lud->lud_dn[0] &&
+		   (!lud->lud_host || !lud->lud_host[0])) {
+			*ludp = lud->lud_next;
+			continue;
+		}
+
+		domain = NULL;
+		if (ldap_dn2domain(lud->lud_dn, &domain) || domain == NULL) {
+			error(logopt,
+			      "Could not turn dn \"%s\" into a domain",
+			      lud->lud_dn);
+			*ludp = lud->lud_next;
+			continue;
+		}
+
+		debug(logopt, "doing lookup of SRV RRs for domain %s", domain);
+
+		req_len = sizeof("_ldap._tcp.") + strlen(domain);
+		request = malloc(req_len);
+		if (!request) {
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			error(logopt, "malloc: %s", estr);
+			goto out_error;
+		}
+
+		ret = snprintf(request, req_len, "_ldap._tcp.%s", domain);
+		if (ret >= req_len) {
+			free(request);
+			goto out_error;
+		}
+
+		dclist_mutex_lock();
+		if (dns_lookup_srv(logopt, request, &dcs, &numdcs)) {
+			error(logopt,
+			      "DNS SRV query failed for domain %s", domain);
+			dclist_mutex_unlock();
+			free(request);
+			goto out_error;
+		}
+		dclist_mutex_unlock();
+		free(request);
+
+		len = strlen(lud->lud_scheme);
+		len += sizeof("://");
+		len *= numdcs;
+
+		for (i = 0; i < numdcs; i++) {
+			if (dcs[i].ttl > 0 && dcs[i].ttl < min_ttl)
+				min_ttl = dcs[i].ttl;
+			len += strlen(dcs[i].hostname);
+			if (dcs[i].port > 0)
+				len += sizeof(":65535");
+		}
+
+		tmp = realloc(list, len);
+		if (!tmp) {
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			error(logopt, "realloc: %s", estr);
+			goto out_error;
+		}
+
+		if (!list)
+			memset(tmp, 0, len);
+		else
+			strcat(tmp, " ");
+
+		for (i = 0; i < numdcs; i++) {
+			if (i > 0)
+				strcat(tmp, " ");
+			strcat(tmp, lud->lud_scheme);
+			strcat(tmp, "://");
+			strcat(tmp, dcs[i].hostname);
+			if (dcs[i].port > 0) {
+				char port[7];
+				ret = snprintf(port, 7, ":%d", dcs[i].port);
+				if (ret > 6) {
+					error(logopt,
+					      "invalid port: %u", dcs[i].port);
+					goto out_error;
+				}
+				strcat(tmp, port);
+			}
+		}
+		list = tmp;
+
+		*ludp = lud->lud_next;
+		ber_memfree(domain);
+	}
+
+	ldap_free_urldesc(ludlist);
+
+	dclist->expire = time(NULL) + min_ttl;
+	dclist->uri = list;
+
+	return dclist;
+
+out_error:
+	if (list)
+		free(list);
+	if (domain)
+		ber_memfree(domain);
+	ldap_free_urldesc(ludlist);
+	free_dclist(dclist);
+	return NULL;
+}
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index a847622..f6b3f42 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -643,14 +643,26 @@ static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt)
 	LDAP *ldap = NULL;
 	struct ldap_uri *this;
 	struct list_head *p, *first;
+	struct dclist *dclist = NULL;
+	char *uri = NULL;
 
-	/* Try each uri in list, add connect fails to tmp list */
 	uris_mutex_lock(ctxt);
+	if (ctxt->dclist) {
+		dclist = ctxt->dclist;
+		if (ctxt->dclist->expire < time(NULL)) {
+			free_dclist(ctxt->dclist);
+			ctxt->dclist = NULL;
+			dclist = NULL;
+		}
+	}
 	if (!ctxt->uri)
 		first = ctxt->uris;
 	else
 		first = &ctxt->uri->list;
 	uris_mutex_unlock(ctxt);
+
+
+	/* Try each uri, save point in server list upon success */
 	p = first->next;
 	while(p != first) {
 		/* Skip list head */
@@ -659,25 +671,62 @@ static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt)
 			continue;
 		}
 		this = list_entry(p, struct ldap_uri, list);
-		debug(logopt, "trying server %s", this->uri);
-		ldap = connect_to_server(logopt, this->uri, ctxt);
+		if (!strstr(this->uri, ":///"))
+			uri = strdup(this->uri);
+		else {
+			if (dclist)
+				uri = strdup(dclist->uri);
+			else {
+				struct dclist *tmp;
+				tmp = get_dc_list(logopt, this->uri);
+				if (!tmp) {
+					p = p->next;
+					continue;
+				}
+				dclist = tmp;
+				uri = strdup(dclist->uri);
+			}
+		}
+		if (!uri) {
+			p = p->next;
+			continue;
+		}
+		debug(logopt, "trying server uri %s", uri);
+		ldap = connect_to_server(logopt, uri, ctxt);
 		if (ldap) {
-			info(logopt, "connected to uri %s", this->uri);
-			uris_mutex_lock(ctxt);
-			ctxt->uri = this;
-			uris_mutex_unlock(ctxt);
+			info(logopt, "connected to uri %s", uri);
+			free(uri);
 			break;
 		}
+		free(uri);
+		uri = NULL;
+		free_dclist(dclist);
+		dclist = NULL;
 		p = p->next;
 	}
 
+	uris_mutex_lock(ctxt);
+	if (ldap)
+		ctxt->uri = this;
+	if (dclist) {
+		if (!ctxt->dclist)
+			ctxt->dclist = dclist;
+		else {
+			if (ctxt->dclist != dclist) {
+				free_dclist(ctxt->dclist);
+				ctxt->dclist = dclist;
+			}
+		}
+	}
+	uris_mutex_unlock(ctxt);
+
 	return ldap;
 }
 
 static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt)
 {
-	struct ldap_uri *this;
 	LDAP *ldap;
+	char *uri;
 
 	if (ctxt->server || !ctxt->uris) {
 		ldap = do_connect(logopt, ctxt->server, ctxt);
@@ -692,9 +741,20 @@ static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt)
 	}
 
 	uris_mutex_lock(ctxt);
-	this = ctxt->uri;
+	if (ctxt->dclist)
+		uri = strdup(ctxt->dclist->uri);
+	else
+		uri = strdup(ctxt->uri->uri);
 	uris_mutex_unlock(ctxt);
-	ldap = do_connect(logopt, this->uri, ctxt);
+
+	if (!uri) {
+		char buf[MAX_ERR_BUF];
+		char *estr = strerror_r(errno, buf, sizeof(buf));
+		crit(logopt, MODPREFIX "strdup: %s", estr);
+		return NULL;
+	}
+
+	ldap = do_connect(logopt, uri, ctxt);
 #ifdef WITH_SASL
 	/*
 	 * Dispose of the sasl authentication connection and try the
@@ -702,9 +762,11 @@ static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt)
 	 */
 	if (!ldap) {
 		autofs_sasl_dispose(ctxt);
-		ldap = connect_to_server(logopt, this->uri, ctxt);
+		ldap = connect_to_server(logopt, uri, ctxt);
 	}
 #endif
+	free(uri);
+
 	if (ldap)
 		return ldap;
 
@@ -1296,6 +1358,8 @@ static void free_context(struct lookup_context *ctxt)
 		fatal(ret);
 	if (ctxt->sdns)
 		defaults_free_searchdns(ctxt->sdns);
+	if (ctxt->dclist)
+		free_dclist(ctxt->dclist);
 	free(ctxt);
 
 	return;
diff --git a/redhat/autofs.sysconfig.in b/redhat/autofs.sysconfig.in
index 97e20fe..37448ea 100644
--- a/redhat/autofs.sysconfig.in
+++ b/redhat/autofs.sysconfig.in
@@ -50,6 +50,17 @@ BROWSE_MODE="no"
 # 	     Map entries that include a server name override
 # 	     this option.
 #
+#	     This configuration option can also be used to
+#	     request autofs lookup SRV RRs for a domain of
+#	     the form <proto>:///[<domain dn>]. Note that a
+#	     trailing "/" is not allowed when using this form.
+#	     If the domain dn is not specified the dns domain
+#	     name (if any) is used to construct the domain dn
+#	     for the SRV RR lookup. The server list returned
+#	     from an SRV RR lookup is refreshed according to
+#	     the minimum ttl found in the SRV RR records or
+#	     after one hour, whichever is less.
+#
 #LDAP_URI=""
 #
 # LDAP__TIMEOUT - timeout value for the synchronous API  calls
diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in
index 62084c2..7dee5fd 100644
--- a/samples/autofs.conf.default.in
+++ b/samples/autofs.conf.default.in
@@ -48,6 +48,17 @@ BROWSE_MODE="no"
 # 	     Map entries that include a server name override
 # 	     this option.
 #
+#	     This configuration option can also be used to
+#	     request autofs lookup SRV RRs for a domain of
+#	     the form <proto>:///[<domain dn>]. Note that a
+#	     trailing "/" is not allowed when using this form.
+#	     If the domain dn is not specified the dns domain
+#	     name (if any) is used to construct the domain dn
+#	     for the SRV RR lookup. The server list returned
+#	     from an SRV RR lookup is refreshed according to
+#	     the minimum ttl found in the SRV RR records or
+#	     after one hour, whichever is less.
+#
 #LDAP_URI=""
 #
 # LDAP__TIMEOUT - timeout value for the synchronous API  calls


Index: autofs.spec
===================================================================
RCS file: /cvs/pkgs/rpms/autofs/F-11/autofs.spec,v
retrieving revision 1.283
retrieving revision 1.284
diff -u -p -r1.283 -r1.284
--- autofs.spec	18 May 2009 02:59:14 -0000	1.283
+++ autofs.spec	12 Jun 2009 09:18:59 -0000	1.284
@@ -4,7 +4,7 @@
 Summary: A tool for automatically mounting and unmounting filesystems
 Name: autofs
 Version: 5.0.4
-Release: 29
+Release: 31
 Epoch: 1
 License: GPLv2+
 Group: System Environment/Daemons
@@ -59,6 +59,15 @@ Patch46: autofs-5.0.4-improve-manual-umo
 Patch47: autofs-5.0.4-dont-fail-on-ipv6-address-adding-host.patch
 Patch48: autofs-5.0.4-always-read-file-maps-multi-map-fix.patch
 Patch49: autofs-5.0.4-always-read-file-maps-key-lookup-fixes.patch
+Patch50: autofs-5.0.4-use-srv-query-for-domain-dn.patch
+Patch51: autofs-5.0.4-fix-incorrect-dclist-free.patch
+Patch52: autofs-5.0.4-srv-lookup-handle-endian.patch
+Patch53: autofs-5.0.4-library-reload-fix-update-fix-2.patch
+Patch54: autofs-5.0.4-fix-notify-mount-message-path.patch
+Patch55: autofs-5.0.4-remount-we-created-mount-point-fix.patch
+Patch56: autofs-5.0.4-fix-double-free-in-do_sasl_bind.patch
+Patch57: autofs-5.0.4-manual-umount-recovery-fixes.patch
+Patch58: autofs-5.0.4-fix-map-type-info-parse-error.patch
 Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires: autoconf, hesiod-devel, openldap-devel, bison, flex, libxml2-devel, cyrus-sasl-devel, openssl-devel module-init-tools util-linux nfs-utils e2fsprogs libtirpc-devel
 Requires: kernel >= 2.6.17
@@ -149,6 +158,15 @@ echo %{version}-%{release} > .version
 %patch47 -p1
 %patch48 -p1
 %patch49 -p1
+%patch50 -p1
+%patch51 -p1
+%patch52 -p1
+%patch53 -p1
+%patch54 -p1
+%patch55 -p1
+%patch56 -p1
+%patch57 -p1
+%patch58 -p1
 
 %build
 #CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr --libdir=%{_libdir}
@@ -201,6 +219,18 @@ fi
 %{_libdir}/autofs/
 
 %changelog
+* Fri Jun 12 2009 Ian Kent <ikent at redhat.com> - 1:5.0.4-31
+- add support for LDAP_URI="ldap:///<domain db>" SRV RR lookup.
+- fix incorrect dclist free.
+- srv lookup handle endianness.
+- fix bug introduced by library reload changes which causes autofs to
+  not release mount thread resources when using submounts.
+- fix notify mount message path.
+- try harder to work out if we created mount point at remount.
+- fix double free in do_sasl_bind().
+- manual umount recovery fixes.
+- fix map type info parse error.
+
 * Mon May 18 2009 Ian Kent <ikent at redhat.com> - 1:5.0.4-29
 - use intr option as hosts mount default.
 - sync kernel includes with upstream kernel.




More information about the fedora-extras-commits mailing list