[openldap] new feature: honor priority/weight with ldap_domain2hostlist

jvcelak jvcelak at fedoraproject.org
Wed Aug 24 17:36:23 UTC 2011


commit a551ec94d31e38e4d3cfac7f631234c2f50f1566
Author: Jan Vcelak <jvcelak at redhat.com>
Date:   Wed Aug 24 19:16:35 2011 +0200

    new feature: honor priority/weight with ldap_domain2hostlist
    
    Resolves: #733078

 openldap-dns-priority.patch |  192 +++++++++++++++++++++++++++++++++++++++++++
 openldap.spec               |    3 +
 2 files changed, 195 insertions(+), 0 deletions(-)
---
diff --git a/openldap-dns-priority.patch b/openldap-dns-priority.patch
new file mode 100644
index 0000000..13d9dcf
--- /dev/null
+++ b/openldap-dns-priority.patch
@@ -0,0 +1,192 @@
+Implement priority/weight for DNS SRV records
+
+From RFC 2782:
+
+  A client MUST attempt to contact the target host with the
+  lowest-numbered priority it can reach.
+
+This patch sorts the DNS SRV records by their priority, and
+additionally gives records with a larger weight a higher probability
+of appearing earlier. This way, the DNS SRV records are tried in the
+order of their priority.
+
+Author: James M Leddy <james.leddy at redhat.com>
+Upstream ITS: #7027
+Resolves: #733078
+
+---
+ libraries/libldap/dnssrv.c |  106 ++++++++++++++++++++++++++++++++++----------
+ 1 files changed, 83 insertions(+), 23 deletions(-)
+
+diff --git a/libraries/libldap/dnssrv.c b/libraries/libldap/dnssrv.c
+index 16b1544..40f93b4 100644
+--- a/libraries/libldap/dnssrv.c
++++ b/libraries/libldap/dnssrv.c
+@@ -174,6 +174,46 @@ int ldap_domain2dn(
+ 	return LDAP_SUCCESS;
+ }
+ 
++#ifdef HAVE_RES_QUERY
++#define DNSBUFSIZ (64*1024)
++typedef struct srv_record {
++    u_short priority;
++    u_short weight;
++    u_short port;
++    char hostname[DNSBUFSIZ];
++} srv_record;
++
++
++static int srv_cmp(const void *aa, const void *bb){
++    srv_record *a=(srv_record *)aa;
++    srv_record *b=(srv_record *)bb;
++    u_long total;
++    
++    if(a->priority < b->priority) {
++	return -1;
++    }
++    if(a->priority > b->priority) {
++	return 1;
++    }
++    if(a->priority == b->priority){
++	/* targets with same priority are in psudeo random order */
++	if (a->weight == 0 && b->weight == 0) {
++	    if (rand() % 2) {
++		return -1;
++	    } else {
++		return 1;
++	    }
++	}
++	total = a->weight + b->weight;
++	if (rand() % total < a->weight) {
++	    return -1;
++	} else {
++	    return 1;
++	}
++    }
++}
++#endif /* HAVE_RES_QUERY */
++
+ /*
+  * Lookup and return LDAP servers for domain (using the DNS
+  * SRV record _ldap._tcp.domain).
+@@ -183,15 +223,16 @@ int ldap_domain2hostlist(
+ 	char **list )
+ {
+ #ifdef HAVE_RES_QUERY
+-#define DNSBUFSIZ (64*1024)
+-    char *request;
+-    char *hostlist = NULL;
++    char *request; 
++   char *hostlist = NULL;
++    srv_record *hostent_head=NULL;
++    int i;
+     int rc, len, cur = 0;
+     unsigned char reply[DNSBUFSIZ];
++    int hostent_count=0;
+ 
+ 	assert( domain != NULL );
+ 	assert( list != NULL );
+-
+ 	if( *domain == '\0' ) {
+ 		return LDAP_PARAM_ERROR;
+ 	}
+@@ -223,8 +264,7 @@ int ldap_domain2hostlist(
+ 	unsigned char *p;
+ 	char host[DNSBUFSIZ];
+ 	int status;
+-	u_short port;
+-	/* int priority, weight; */
++	u_short port, priority, weight; 
+ 
+ 	/* Parse out query */
+ 	p = reply;
+@@ -263,40 +303,56 @@ int ldap_domain2hostlist(
+ 	    size = (p[0] << 8) | p[1];
+ 	    p += 2;
+ 	    if (type == T_SRV) {
+-		int buflen;
+ 		status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
+ 		if (status < 0) {
+ 		    goto out;
+ 		}
+-		/* ignore priority and weight for now */
+-		/* priority = (p[0] << 8) | p[1]; */
+-		/* weight = (p[2] << 8) | p[3]; */
++		
++		/* Get priority weight and port */
++		priority = (p[0] << 8) | p[1];
++		weight = (p[2] << 8) | p[3]; 
+ 		port = (p[4] << 8) | p[5];
+ 
+ 		if ( port == 0 || host[ 0 ] == '\0' ) {
+ 		    goto add_size;
+ 		}
+ 
+-		buflen = strlen(host) + STRLENOF(":65355 ");
+-		hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen + 1);
+-		if (hostlist == NULL) {
+-		    rc = LDAP_NO_MEMORY;
+-		    goto out;
++		hostent_head = (srv_record *) LDAP_REALLOC(hostent_head, (hostent_count+1)*(sizeof(srv_record)));
++		if(hostent_head==NULL){
++		  rc=LDAP_NO_MEMORY;
++		  goto out;
++		  
+ 		}
+-		if (cur > 0) {
+-		    /* not first time around */
+-		    hostlist[cur++] = ' ';
+-		}
+-		cur += sprintf(&hostlist[cur], "%s:%hu", host, port);
++		hostent_head[hostent_count].priority=priority;
++		hostent_head[hostent_count].weight=priority;
++		hostent_head[hostent_count].port=port;
++		strncpy(hostent_head[hostent_count].hostname, host,255);
++		hostent_count=hostent_count+1;
+ 	    }
+ add_size:;
+ 	    p += size;
+ 	}
+     }
++    qsort(hostent_head, hostent_count, sizeof(srv_record), srv_cmp);
++
++    for(i=0; i<hostent_count; i++){
++	int buflen;
++        buflen = strlen(hostent_head[i].hostname) + STRLENOF(":65355" );
++        hostlist = (char *) LDAP_REALLOC(hostlist, cur+buflen+1);
++        if (hostlist == NULL) {
++            rc = LDAP_NO_MEMORY;
++            goto out;
++        }
++        if(cur>0){
++            hostlist[cur++]=' ';
++        }
++        cur += sprintf(&hostlist[cur], "%s:%hd", hostent_head[i].hostname, hostent_head[i].port);
++    }
++
+     if (hostlist == NULL) {
+-	/* No LDAP servers found in DNS. */
+-	rc = LDAP_UNAVAILABLE;
+-	goto out;
++         /* No LDAP servers found in DNS. */
++         rc = LDAP_UNAVAILABLE;
++         goto out;
+     }
+ 
+     rc = LDAP_SUCCESS;
+@@ -308,8 +364,12 @@ add_size:;
+     if (request != NULL) {
+ 	LDAP_FREE(request);
+     }
++    if (hostent_head != NULL) {
++	LDAP_FREE(hostent_head);
++    }
+     if (rc != LDAP_SUCCESS && hostlist != NULL) {
+ 	LDAP_FREE(hostlist);
++	
+     }
+     return rc;
+ #else
+-- 
+1.7.6
+
diff --git a/openldap.spec b/openldap.spec
index dd1d3f3..2411455 100644
--- a/openldap.spec
+++ b/openldap.spec
@@ -38,6 +38,7 @@ Patch12: openldap-constraint-overlay-config.patch
 Patch13: openldap-dds-overlay-tolerance.patch
 Patch14: openldap-man-slapo-unique.patch
 Patch15: openldap-nss-wildcards.patch
+Patch16: openldap-dns-priority.patch
 
 # patches for the evolution library (see README.evolution)
 Patch200: openldap-evolution-ntlm.patch
@@ -146,6 +147,7 @@ pushd openldap-%{version}
 %patch13 -p1 -b .dds-overlay-tolerance
 %patch14 -p1 -b .man-slapo-unique
 %patch15 -p1 -b .nss-wildcards
+%patch16 -p1 -b .dns-priority
 
 cp %{_datadir}/libtool/config/config.{sub,guess} build/
 
@@ -678,6 +680,7 @@ exit 0
 - fix: DDS overlay tolerance parametr doesn't function and breakes default TTL (#733069)
 - manpage fix: errors in manual page slapo-unique (#733070)
 - fix: matching wildcard hostnames in certificate Subject field does not work (#733073)
+- new feature: honor priority/weight with ldap_domain2hostlist (#733078)
 
 * Sun Aug 14 2011 Rex Dieter <rdieter at fedoraproject.org> - 2.4.26-1.1
 - Rebuilt for rpm (#728707)


More information about the scm-commits mailing list