Fix incorrect scaling of weight 0 SRV records

Loosely based on patch by Nico.
This commit is contained in:
Viktor Dukhovni
2016-12-12 17:51:08 -05:00
parent a7f8732d79
commit 32f8564296

View File

@@ -659,12 +659,15 @@ rk_dns_srv_order(struct rk_dns_reply *r)
headp = &r->head; headp = &r->head;
for(ss = srvs; ss < srvs + num_srv; ) { for (ss = srvs; ss < srvs + num_srv; ) {
int sum, zeros, rnd, count; int sum, zeros, rnd, count; /* zeros -> weight scaling */
struct rk_resource_record **ee, **tt; struct rk_resource_record **ee, **tt;
/* find the last record with the same priority and count the
sum of all weights */ /*
for(sum = 0, zeros = 0, tt = ss; tt < srvs + num_srv; tt++) { * find the last record with the same priority and count the sum of all
* weights
*/
for (sum = 0, zeros = 0, tt = ss; tt < srvs + num_srv; tt++) {
assert(*tt != NULL); assert(*tt != NULL);
if((*tt)->u.srv->priority != (*ss)->u.srv->priority) if((*tt)->u.srv->priority != (*ss)->u.srv->priority)
break; break;
@@ -672,36 +675,43 @@ rk_dns_srv_order(struct rk_dns_reply *r)
if ((*tt)->u.srv->weight == 0) if ((*tt)->u.srv->weight == 0)
zeros++; zeros++;
} }
/* With no zeros, add 0 and scale * 1 */ /* make sure scale (`zeros') is > 0 then scale out */
sum += zeros ? zeros : zeros++; sum += zeros ? 1 : zeros++;
sum *= zeros; sum *= zeros;
ee = tt; ee = tt;
/* ss is now the first record of this priority and ee is the
first of the next */ /*
while(ss < ee) { * ss is now the first record of this priority and ee is the first of
* the next or the first past the end of srvs
*/
while (ss < ee) {
rnd = rk_random() % sum + 1; rnd = rk_random() % sum + 1;
for(count = 0, tt = ss; ; tt++) { for (count = 0, tt = ss; tt < ee; tt++) {
if(*tt == NULL) if (*tt == NULL)
continue; continue; /* this one's already been picked */
count += (*tt)->u.srv->weight * zeros;
if ((*tt)->u.srv->weight == 0) if ((*tt)->u.srv->weight == 0)
count++; count++;
if(count >= rnd) else
count += (*tt)->u.srv->weight * zeros;
if (count >= rnd)
break; break;
} }
assert(tt < ee); assert(tt < ee);
/* insert the selected record at the tail (of the head) of /* push the selected record */
the list */
(*tt)->next = *headp; (*tt)->next = *headp;
*headp = *tt; *headp = *tt;
headp = &(*tt)->next; headp = &(*tt)->next;
sum -= (*tt)->u.srv->weight * zeros; /*
* reduce the sum so the next iteration is sure to reach the random
* total after examining all the remaining records.
*/
if ((*tt)->u.srv->weight == 0) if ((*tt)->u.srv->weight == 0)
sum--; sum--;
else
sum -= (*tt)->u.srv->weight * zeros;
*tt = NULL; *tt = NULL;
while(ss < ee && *ss == NULL) while (ss < ee && *ss == NULL)
ss++; ss++;
} }
} }