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