mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-12 10:54:48 +08:00
ITS#7027 actually implement RFC 2782 shuffle
This commit is contained in:
parent
31995b535e
commit
eef1ca007f
@ -176,41 +176,77 @@ int ldap_domain2dn(
|
|||||||
|
|
||||||
#ifdef HAVE_RES_QUERY
|
#ifdef HAVE_RES_QUERY
|
||||||
#define DNSBUFSIZ (64*1024)
|
#define DNSBUFSIZ (64*1024)
|
||||||
|
#define MAXHOST 254 /* RFC 1034, max length is 253 chars */
|
||||||
typedef struct srv_record {
|
typedef struct srv_record {
|
||||||
u_short priority;
|
u_short priority;
|
||||||
u_short weight;
|
u_short weight;
|
||||||
u_short port;
|
u_short port;
|
||||||
char hostname[DNSBUFSIZ];
|
char hostname[MAXHOST];
|
||||||
} srv_record;
|
} srv_record;
|
||||||
|
|
||||||
|
/* Linear Congruential Generator - we don't need
|
||||||
|
* high quality randomness, and we don't want to
|
||||||
|
* interfere with anyone else's use of srand().
|
||||||
|
*
|
||||||
|
* The PRNG here cycles thru 941,955 numbers.
|
||||||
|
*/
|
||||||
|
static float srv_seed;
|
||||||
|
|
||||||
|
static void srv_srand(int seed) {
|
||||||
|
srv_seed = (float)seed / (float)RAND_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float srv_rand() {
|
||||||
|
float val = 9821.0 * srv_seed + .211327;
|
||||||
|
srv_seed = val - (int)val;
|
||||||
|
return srv_seed;
|
||||||
|
}
|
||||||
|
|
||||||
static int srv_cmp(const void *aa, const void *bb){
|
static int srv_cmp(const void *aa, const void *bb){
|
||||||
srv_record *a=(srv_record *)aa;
|
srv_record *a=(srv_record *)aa;
|
||||||
srv_record *b=(srv_record *)bb;
|
srv_record *b=(srv_record *)bb;
|
||||||
u_long total;
|
int i = a->priority - b->priority;
|
||||||
|
if (i) return i;
|
||||||
|
return b->weight - a->weight;
|
||||||
|
}
|
||||||
|
|
||||||
if(a->priority < b->priority) {
|
static void srv_shuffle(srv_record *a, int n) {
|
||||||
return -1;
|
int i, j, total = 0, r, p;
|
||||||
}
|
|
||||||
if(a->priority > b->priority) {
|
for (i=0; i<n; i++)
|
||||||
return 1;
|
total += a[i].weight;
|
||||||
}
|
|
||||||
if(a->priority == b->priority){
|
/* all weights are zero, do a straight Fisher-Yates shuffle */
|
||||||
/* targets with same priority are in psudeo random order */
|
if (!total) {
|
||||||
if (a->weight == 0 && b->weight == 0) {
|
while (n) {
|
||||||
if (rand() % 2) {
|
srv_record t;
|
||||||
return -1;
|
i = srv_rand() * n--;
|
||||||
} else {
|
t = a[n];
|
||||||
return 1;
|
a[n] = a[i];
|
||||||
}
|
a[i] = t;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
total = a->weight + b->weight;
|
|
||||||
if (rand() % total < a->weight) {
|
/* Do a shuffle per RFC2782 Page 4 */
|
||||||
return -1;
|
p = n;
|
||||||
} else {
|
for (i=0; i<n-1; i++) {
|
||||||
return 1;
|
r = srv_rand() * total;
|
||||||
|
for (j=0; j<p; j++) {
|
||||||
|
r -= a[j].weight;
|
||||||
|
if (r <= 0) {
|
||||||
|
if (j) {
|
||||||
|
srv_record t = a[0];
|
||||||
|
a[0] = a[j];
|
||||||
|
a[j] = t;
|
||||||
|
}
|
||||||
|
total -= a[0].weight;
|
||||||
|
a++;
|
||||||
|
p--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* HAVE_RES_QUERY */
|
#endif /* HAVE_RES_QUERY */
|
||||||
|
|
||||||
@ -226,7 +262,7 @@ int ldap_domain2hostlist(
|
|||||||
char *request;
|
char *request;
|
||||||
char *hostlist = NULL;
|
char *hostlist = NULL;
|
||||||
srv_record *hostent_head=NULL;
|
srv_record *hostent_head=NULL;
|
||||||
int i;
|
int i, j;
|
||||||
int rc, len, cur = 0;
|
int rc, len, cur = 0;
|
||||||
unsigned char reply[DNSBUFSIZ];
|
unsigned char reply[DNSBUFSIZ];
|
||||||
int hostent_count=0;
|
int hostent_count=0;
|
||||||
@ -325,15 +361,31 @@ int ldap_domain2hostlist(
|
|||||||
hostent_head[hostent_count].priority=priority;
|
hostent_head[hostent_count].priority=priority;
|
||||||
hostent_head[hostent_count].weight=weight;
|
hostent_head[hostent_count].weight=weight;
|
||||||
hostent_head[hostent_count].port=port;
|
hostent_head[hostent_count].port=port;
|
||||||
strncpy(hostent_head[hostent_count].hostname, host,255);
|
strncpy(hostent_head[hostent_count].hostname, host, MAXHOST);
|
||||||
hostent_count=hostent_count+1;
|
hostent_count++;
|
||||||
}
|
}
|
||||||
add_size:;
|
add_size:;
|
||||||
p += size;
|
p += size;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
qsort(hostent_head, hostent_count, sizeof(srv_record), srv_cmp);
|
qsort(hostent_head, hostent_count, sizeof(srv_record), srv_cmp);
|
||||||
|
|
||||||
|
if (!srv_seed)
|
||||||
|
srv_srand(time(0L));
|
||||||
|
|
||||||
|
/* shuffle records of same priority */
|
||||||
|
j = 0;
|
||||||
|
priority = hostent_head[0].priority;
|
||||||
|
for (i=1; i<hostent_count; i++) {
|
||||||
|
if (hostent_head[i].priority != priority) {
|
||||||
|
priority = hostent_head[i].priority;
|
||||||
|
if (i-j > 1)
|
||||||
|
srv_shuffle(hostent_head+j, i-j);
|
||||||
|
j = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i-j > 1)
|
||||||
|
srv_shuffle(hostent_head+j, i-j);
|
||||||
|
|
||||||
for(i=0; i<hostent_count; i++){
|
for(i=0; i<hostent_count; i++){
|
||||||
int buflen;
|
int buflen;
|
||||||
buflen = strlen(hostent_head[i].hostname) + STRLENOF(":65535 ");
|
buflen = strlen(hostent_head[i].hostname) + STRLENOF(":65535 ");
|
||||||
@ -347,6 +399,7 @@ add_size:;
|
|||||||
}
|
}
|
||||||
cur += sprintf(&hostlist[cur], "%s:%hd", hostent_head[i].hostname, hostent_head[i].port);
|
cur += sprintf(&hostlist[cur], "%s:%hd", hostent_head[i].hostname, hostent_head[i].port);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (hostlist == NULL) {
|
if (hostlist == NULL) {
|
||||||
/* No LDAP servers found in DNS. */
|
/* No LDAP servers found in DNS. */
|
||||||
|
Loading…
Reference in New Issue
Block a user