Blame SOURCES/openldap-dns-priority.patch

767ab2
Implement priority/weight for DNS SRV records
767ab2
767ab2
From RFC 2782:
767ab2
767ab2
  A client MUST attempt to contact the target host with the
767ab2
  lowest-numbered priority it can reach.
767ab2
767ab2
This patch sorts the DNS SRV records by their priority, and
767ab2
additionally gives records with a larger weight a higher probability
767ab2
of appearing earlier. This way, the DNS SRV records are tried in the
767ab2
order of their priority.
767ab2
767ab2
Author: James M Leddy <james.leddy@redhat.com>
767ab2
Upstream ITS: #7027
767ab2
Resolves: #733078
767ab2
767ab2
---
767ab2
 libraries/libldap/dnssrv.c |  106 ++++++++++++++++++++++++++++++++++----------
767ab2
 1 files changed, 83 insertions(+), 23 deletions(-)
767ab2
767ab2
diff --git a/libraries/libldap/dnssrv.c b/libraries/libldap/dnssrv.c
767ab2
index 16b1544..40f93b4 100644
767ab2
--- a/libraries/libldap/dnssrv.c
767ab2
+++ b/libraries/libldap/dnssrv.c
767ab2
@@ -174,6 +174,46 @@ int ldap_domain2dn(
767ab2
 	return LDAP_SUCCESS;
767ab2
 }
767ab2
 
767ab2
+#ifdef HAVE_RES_QUERY
767ab2
+#define DNSBUFSIZ (64*1024)
767ab2
+typedef struct srv_record {
767ab2
+    u_short priority;
767ab2
+    u_short weight;
767ab2
+    u_short port;
767ab2
+    char hostname[DNSBUFSIZ];
767ab2
+} srv_record;
767ab2
+
767ab2
+
767ab2
+static int srv_cmp(const void *aa, const void *bb){
767ab2
+    srv_record *a=(srv_record *)aa;
767ab2
+    srv_record *b=(srv_record *)bb;
767ab2
+    u_long total;
767ab2
+    
767ab2
+    if(a->priority < b->priority) {
767ab2
+	return -1;
767ab2
+    }
767ab2
+    if(a->priority > b->priority) {
767ab2
+	return 1;
767ab2
+    }
767ab2
+    if(a->priority == b->priority){
767ab2
+	/* targets with same priority are in psudeo random order */
767ab2
+	if (a->weight == 0 && b->weight == 0) {
767ab2
+	    if (rand() % 2) {
767ab2
+		return -1;
767ab2
+	    } else {
767ab2
+		return 1;
767ab2
+	    }
767ab2
+	}
767ab2
+	total = a->weight + b->weight;
767ab2
+	if (rand() % total < a->weight) {
767ab2
+	    return -1;
767ab2
+	} else {
767ab2
+	    return 1;
767ab2
+	}
767ab2
+    }
767ab2
+}
767ab2
+#endif /* HAVE_RES_QUERY */
767ab2
+
767ab2
 /*
767ab2
  * Lookup and return LDAP servers for domain (using the DNS
767ab2
  * SRV record _ldap._tcp.domain).
767ab2
@@ -183,15 +223,16 @@ int ldap_domain2hostlist(
767ab2
 	char **list )
767ab2
 {
767ab2
 #ifdef HAVE_RES_QUERY
767ab2
-#define DNSBUFSIZ (64*1024)
767ab2
-    char *request;
767ab2
-    char *hostlist = NULL;
767ab2
+    char *request; 
767ab2
+   char *hostlist = NULL;
767ab2
+    srv_record *hostent_head=NULL;
767ab2
+    int i;
767ab2
     int rc, len, cur = 0;
767ab2
     unsigned char reply[DNSBUFSIZ];
767ab2
+    int hostent_count=0;
767ab2
 
767ab2
 	assert( domain != NULL );
767ab2
 	assert( list != NULL );
767ab2
-
767ab2
 	if( *domain == '\0' ) {
767ab2
 		return LDAP_PARAM_ERROR;
767ab2
 	}
767ab2
@@ -223,8 +264,7 @@ int ldap_domain2hostlist(
767ab2
 	unsigned char *p;
767ab2
 	char host[DNSBUFSIZ];
767ab2
 	int status;
767ab2
-	u_short port;
767ab2
-	/* int priority, weight; */
767ab2
+	u_short port, priority, weight; 
767ab2
 
767ab2
 	/* Parse out query */
767ab2
 	p = reply;
767ab2
@@ -263,40 +303,56 @@ int ldap_domain2hostlist(
767ab2
 	    size = (p[0] << 8) | p[1];
767ab2
 	    p += 2;
767ab2
 	    if (type == T_SRV) {
767ab2
-		int buflen;
767ab2
 		status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
767ab2
 		if (status < 0) {
767ab2
 		    goto out;
767ab2
 		}
767ab2
-		/* ignore priority and weight for now */
767ab2
-		/* priority = (p[0] << 8) | p[1]; */
767ab2
-		/* weight = (p[2] << 8) | p[3]; */
767ab2
+		
767ab2
+		/* Get priority weight and port */
767ab2
+		priority = (p[0] << 8) | p[1];
767ab2
+		weight = (p[2] << 8) | p[3]; 
767ab2
 		port = (p[4] << 8) | p[5];
767ab2
 
767ab2
 		if ( port == 0 || host[ 0 ] == '\0' ) {
767ab2
 		    goto add_size;
767ab2
 		}
767ab2
 
767ab2
-		buflen = strlen(host) + STRLENOF(":65355 ");
767ab2
-		hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen + 1);
767ab2
-		if (hostlist == NULL) {
767ab2
-		    rc = LDAP_NO_MEMORY;
767ab2
-		    goto out;
767ab2
+		hostent_head = (srv_record *) LDAP_REALLOC(hostent_head, (hostent_count+1)*(sizeof(srv_record)));
767ab2
+		if(hostent_head==NULL){
767ab2
+		  rc=LDAP_NO_MEMORY;
767ab2
+		  goto out;
767ab2
+		  
767ab2
 		}
767ab2
-		if (cur > 0) {
767ab2
-		    /* not first time around */
767ab2
-		    hostlist[cur++] = ' ';
767ab2
-		}
767ab2
-		cur += sprintf(&hostlist[cur], "%s:%hu", host, port);
767ab2
+		hostent_head[hostent_count].priority=priority;
767ab2
+		hostent_head[hostent_count].weight=weight;
767ab2
+		hostent_head[hostent_count].port=port;
767ab2
+		strncpy(hostent_head[hostent_count].hostname, host,255);
767ab2
+		hostent_count=hostent_count+1;
767ab2
 	    }
767ab2
 add_size:;
767ab2
 	    p += size;
767ab2
 	}
767ab2
     }
767ab2
+    qsort(hostent_head, hostent_count, sizeof(srv_record), srv_cmp);
767ab2
+
767ab2
+    for(i=0; i
767ab2
+	int buflen;
767ab2
+        buflen = strlen(hostent_head[i].hostname) + STRLENOF(":65355" );
767ab2
+        hostlist = (char *) LDAP_REALLOC(hostlist, cur+buflen+1);
767ab2
+        if (hostlist == NULL) {
767ab2
+            rc = LDAP_NO_MEMORY;
767ab2
+            goto out;
767ab2
+        }
767ab2
+        if(cur>0){
767ab2
+            hostlist[cur++]=' ';
767ab2
+        }
767ab2
+        cur += sprintf(&hostlist[cur], "%s:%hd", hostent_head[i].hostname, hostent_head[i].port);
767ab2
+    }
767ab2
+
767ab2
     if (hostlist == NULL) {
767ab2
-	/* No LDAP servers found in DNS. */
767ab2
-	rc = LDAP_UNAVAILABLE;
767ab2
-	goto out;
767ab2
+         /* No LDAP servers found in DNS. */
767ab2
+         rc = LDAP_UNAVAILABLE;
767ab2
+         goto out;
767ab2
     }
767ab2
 
767ab2
     rc = LDAP_SUCCESS;
767ab2
@@ -308,8 +364,12 @@ add_size:;
767ab2
     if (request != NULL) {
767ab2
 	LDAP_FREE(request);
767ab2
     }
767ab2
+    if (hostent_head != NULL) {
767ab2
+	LDAP_FREE(hostent_head);
767ab2
+    }
767ab2
     if (rc != LDAP_SUCCESS && hostlist != NULL) {
767ab2
 	LDAP_FREE(hostlist);
767ab2
+	
767ab2
     }
767ab2
     return rc;
767ab2
 #else
767ab2
-- 
767ab2
1.7.6
767ab2