From a82af293fc7bebbb95a62a7cb707c761ba70a170 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Mon, 21 Jul 2014 22:05:25 -0700 Subject: [PATCH] ITS#7027 actually implement RFC 2782 shuffle --- libraries/libldap/dnssrv.c | 109 +++++++++++++++++++++++++++---------- 1 file changed, 81 insertions(+), 28 deletions(-) diff --git a/libraries/libldap/dnssrv.c b/libraries/libldap/dnssrv.c index de849e30d5..51a711ac67 100644 --- a/libraries/libldap/dnssrv.c +++ b/libraries/libldap/dnssrv.c @@ -176,41 +176,77 @@ int ldap_domain2dn( #ifdef HAVE_RES_QUERY #define DNSBUFSIZ (64*1024) +#define MAXHOST 254 /* RFC 1034, max length is 253 chars */ typedef struct srv_record { u_short priority; u_short weight; u_short port; - char hostname[DNSBUFSIZ]; + char hostname[MAXHOST]; } 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){ - srv_record *a=(srv_record *)aa; - srv_record *b=(srv_record *)bb; - u_long total; + srv_record *a=(srv_record *)aa; + srv_record *b=(srv_record *)bb; + int i = a->priority - b->priority; + if (i) return i; + return b->weight - a->weight; +} - 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; - } +static void srv_shuffle(srv_record *a, int n) { + int i, j, total = 0, r, p; + + for (i=0; iweight + b->weight; - if (rand() % total < a->weight) { - return -1; - } else { - return 1; + + /* Do a shuffle per RFC2782 Page 4 */ + p = n; + for (i=0; i 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