void dnsparse::srvrec_randomize (srvrec *base, srvrec *last) { qsort (base, last - base, sizeof (*base), &srvrec_cmp); #if 0 for (srvrec *x = base; x < last; x++) warn ("DBG: %3d %3d %5d %s\n", x->prio, x->weight, x->port, x->name); #endif while (base < last) { srvrec *lastprio = base; u_int totweight; /* It's not clear from RFC 2782 if we need to randomize multiple * records with weight 0 at the same priority. We do it anyway * just because it might be helpful. */ if (base->weight == 0) { totweight = 1; while (++lastprio < last && lastprio->prio == base->prio) totweight++; while (base + 1 < lastprio) { u_int which = arandom () % totweight; if (which) { srvrec tmp = base[which]; base[which] = *base; *base = tmp; } base++; totweight--; } } else { totweight = lastprio->weight; while (++lastprio < last && lastprio->weight && lastprio->prio == base->prio) totweight += lastprio->weight; while (base + 1 < lastprio) { u_int32_t rndweight = arandom () % totweight + 1; srvrec *nextrec; for (nextrec = base; nextrec->weight < rndweight; nextrec++) rndweight -= nextrec->weight; srvrec tmp = *base; *base = *nextrec; *nextrec = tmp; totweight -= base++->weight; } assert (totweight == base->weight); } base++; } }
u_int16_t resolver::genid () { u_int16_t id; int i = 0; do { id = arandom () % 0xffff; } while (reqtab[id] && ++i < 8); return id; }