int iter_ns_probability(struct ub_randstate* rnd, int n, int m) { int sel; if(n == m) /* 100% chance */ return 1; /* we do not need secure random numbers here, but * we do need it to be threadsafe, so we use this */ sel = ub_random_max(rnd, m); return (sel < n); }
/** * Obtain allowed port numbers, concatenate the list, and shuffle them * (ready to be handed out to threads). * @param daemon: the daemon. Uses rand and cfg. * @param shufport: the portlist output. * @return number of ports available. */ static int daemon_get_shufport(struct daemon* daemon, int* shufport) { int i, n, k, temp; int avail = 0; for(i=0; i<65536; i++) { if(daemon->cfg->outgoing_avail_ports[i]) { shufport[avail++] = daemon->cfg-> outgoing_avail_ports[i]; } } if(avail == 0) fatal_exit("no ports are permitted for UDP, add " "with outgoing-port-permit"); /* Knuth shuffle */ n = avail; while(--n > 0) { k = ub_random_max(daemon->rand, n+1); /* 0<= k<= n */ temp = shufport[k]; shufport[k] = shufport[n]; shufport[n] = temp; } return avail; }
struct delegpt_addr* iter_server_selection(struct iter_env* iter_env, struct module_env* env, struct delegpt* dp, uint8_t* name, size_t namelen, uint16_t qtype, int* dnssec_lame, int* chase_to_rd, int open_target, struct sock_list* blacklist) { int sel; int selrtt; struct delegpt_addr* a, *prev; int num = iter_filter_order(iter_env, env, name, namelen, qtype, *env->now, dp, &selrtt, open_target, blacklist); if(num == 0) return NULL; verbose(VERB_ALGO, "selrtt %d", selrtt); if(selrtt > BLACKLIST_PENALTY) { if(selrtt-BLACKLIST_PENALTY > USEFUL_SERVER_TOP_TIMEOUT*3) { verbose(VERB_ALGO, "chase to " "blacklisted recursion lame server"); *chase_to_rd = 1; } if(selrtt-BLACKLIST_PENALTY > USEFUL_SERVER_TOP_TIMEOUT*2) { verbose(VERB_ALGO, "chase to " "blacklisted dnssec lame server"); *dnssec_lame = 1; } } else { if(selrtt > USEFUL_SERVER_TOP_TIMEOUT*3) { verbose(VERB_ALGO, "chase to recursion lame server"); *chase_to_rd = 1; } if(selrtt > USEFUL_SERVER_TOP_TIMEOUT*2) { verbose(VERB_ALGO, "chase to dnssec lame server"); *dnssec_lame = 1; } if(selrtt == USEFUL_SERVER_TOP_TIMEOUT) { verbose(VERB_ALGO, "chase to blacklisted lame server"); return NULL; } } if(num == 1) { a = dp->result_list; if(++a->attempts < OUTBOUND_MSG_RETRY) return a; dp->result_list = a->next_result; return a; } /* randomly select a target from the list */ log_assert(num > 1); /* grab secure random number, to pick unexpected server. * also we need it to be threadsafe. */ sel = ub_random_max(env->rnd, num); a = dp->result_list; prev = NULL; while(sel > 0 && a) { prev = a; a = a->next_result; sel--; } if(!a) /* robustness */ return NULL; if(++a->attempts < OUTBOUND_MSG_RETRY) return a; /* remove it from the delegation point result list */ if(prev) prev->next_result = a->next_result; else dp->result_list = a->next_result; return a; }