From a551ec94d31e38e4d3cfac7f631234c2f50f1566 Mon Sep 17 00:00:00 2001 From: Jan Vcelak Date: Wed, 24 Aug 2011 19:16:35 +0200 Subject: [PATCH] new feature: honor priority/weight with ldap_domain2hostlist Resolves: #733078 --- openldap-dns-priority.patch | 192 ++++++++++++++++++++++++++++++++++++ openldap.spec | 3 + 2 files changed, 195 insertions(+) create mode 100644 openldap-dns-priority.patch 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 +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; i0){ ++ 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 - 2.4.26-1.1 - Rebuilt for rpm (#728707)