/** filter out unsuitable targets * @param iter_env: iterator environment with ipv6-support flag. * @param env: module environment with infra cache. * @param name: zone name * @param namelen: length of name * @param qtype: query type (host order). * @param now: current time * @param a: address in delegation point we are examining. * @return an integer that signals the target suitability. * as follows: * -1: The address should be omitted from the list. * Because: * o The address is bogus (DNSSEC validation failure). * o Listed as donotquery * o is ipv6 but no ipv6 support (in operating system). * o is ipv4 but no ipv4 support (in operating system). * o is lame * Otherwise, an rtt in milliseconds. * 0 .. USEFUL_SERVER_TOP_TIMEOUT-1 * The roundtrip time timeout estimate. less than 2 minutes. * Note that util/rtt.c has a MIN_TIMEOUT of 50 msec, thus * values 0 .. 49 are not used, unless that is changed. * USEFUL_SERVER_TOP_TIMEOUT * This value exactly is given for unresponsive blacklisted. * USEFUL_SERVER_TOP_TIMEOUT+1 * For non-blacklisted servers: huge timeout, but has traffic. * USEFUL_SERVER_TOP_TIMEOUT*1 .. * parent-side lame servers get this penalty. A dispreferential * server. (lame in delegpt). * USEFUL_SERVER_TOP_TIMEOUT*2 .. * dnsseclame servers get penalty * USEFUL_SERVER_TOP_TIMEOUT*3 .. * recursion lame servers get penalty * UNKNOWN_SERVER_NICENESS * If no information is known about the server, this is * returned. 376 msec or so. * +BLACKLIST_PENALTY (of USEFUL_TOP_TIMEOUT*4) for dnssec failed IPs. * * When a final value is chosen that is dnsseclame ; dnsseclameness checking * is turned off (so we do not discard the reply). * When a final value is chosen that is recursionlame; RD bit is set on query. * Because of the numbers this means recursionlame also have dnssec lameness * checking turned off. */ static int iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env, uint8_t* name, size_t namelen, uint16_t qtype, time_t now, struct delegpt_addr* a) { int rtt, lame, reclame, dnsseclame; if(a->bogus) return -1; /* address of server is bogus */ if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) { log_addr(VERB_ALGO, "skip addr on the donotquery list", &a->addr, a->addrlen); return -1; /* server is on the donotquery list */ } if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) { return -1; /* there is no ip6 available */ } if(!iter_env->supports_ipv4 && !addr_is_ip6(&a->addr, a->addrlen)) { return -1; /* there is no ip4 available */ } /* check lameness - need zone , class info */ if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen, name, namelen, qtype, &lame, &dnsseclame, &reclame, &rtt, now)) { log_addr(VERB_ALGO, "servselect", &a->addr, a->addrlen); verbose(VERB_ALGO, " rtt=%d%s%s%s%s", rtt, lame?" LAME":"", dnsseclame?" DNSSEC_LAME":"", reclame?" REC_LAME":"", a->lame?" ADDR_LAME":""); if(lame) return -1; /* server is lame */ else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT) /* server is unresponsive, * we used to return TOP_TIMEOUT, but fairly useless, * because if == TOP_TIMEOUT is dropped because * blacklisted later, instead, remove it here, so * other choices (that are not blacklisted) can be * tried */ return -1; /* select remainder from worst to best */ else if(reclame) return rtt+USEFUL_SERVER_TOP_TIMEOUT*3; /* nonpref */ else if(dnsseclame || a->dnsseclame) return rtt+USEFUL_SERVER_TOP_TIMEOUT*2; /* nonpref */ else if(a->lame) return rtt+USEFUL_SERVER_TOP_TIMEOUT+1; /* nonpref */ else return rtt; } /* no server information present */ if(a->dnsseclame) return UNKNOWN_SERVER_NICENESS+USEFUL_SERVER_TOP_TIMEOUT*2; /* nonpref */ else if(a->lame) return USEFUL_SERVER_TOP_TIMEOUT+1+UNKNOWN_SERVER_NICENESS; /* nonpref */ return UNKNOWN_SERVER_NICENESS; }
/** print details on a delegation point */ static void print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp) { char buf[257]; struct delegpt_addr* a; int lame, dlame, rlame, rto, edns_vs, to, delay, tA = 0, tAAAA = 0, tother = 0; long long entry_ttl; struct rtt_info ri; uint8_t edns_lame_known; for(a = dp->target_list; a; a = a->next_target) { addr_to_str(&a->addr, a->addrlen, buf, sizeof(buf)); if(!ssl_printf(ssl, "%-16s\t", buf)) return; if(a->bogus) { if(!ssl_printf(ssl, "Address is BOGUS. ")) return; } /* lookup in infra cache */ delay=0; entry_ttl = infra_get_host_rto(worker->env.infra_cache, &a->addr, a->addrlen, dp->name, dp->namelen, &ri, &delay, *worker->env.now, &tA, &tAAAA, &tother); if(entry_ttl == -2 && ri.rto >= USEFUL_SERVER_TOP_TIMEOUT) { if(!ssl_printf(ssl, "expired, rto %d msec, tA %d " "tAAAA %d tother %d.\n", ri.rto, tA, tAAAA, tother)) return; continue; } if(entry_ttl == -1 || entry_ttl == -2) { if(!ssl_printf(ssl, "not in infra cache.\n")) return; continue; /* skip stuff not in infra cache */ } /* uses type_A because most often looked up, but other * lameness won't be reported then */ if(!infra_get_lame_rtt(worker->env.infra_cache, &a->addr, a->addrlen, dp->name, dp->namelen, LDNS_RR_TYPE_A, &lame, &dlame, &rlame, &rto, *worker->env.now)) { if(!ssl_printf(ssl, "not in infra cache.\n")) return; continue; /* skip stuff not in infra cache */ } if(!ssl_printf(ssl, "%s%s%s%srto %d msec, ttl " ARG_LL "d, " "ping %d var %d rtt %d, tA %d, tAAAA %d, tother %d", lame?"LAME ":"", dlame?"NoDNSSEC ":"", a->lame?"AddrWasParentSide ":"", rlame?"NoAuthButRecursive ":"", rto, entry_ttl, ri.srtt, ri.rttvar, rtt_notimeout(&ri), tA, tAAAA, tother)) return; if(delay) if(!ssl_printf(ssl, ", probedelay %d", delay)) return; if(infra_host(worker->env.infra_cache, &a->addr, a->addrlen, dp->name, dp->namelen, *worker->env.now, &edns_vs, &edns_lame_known, &to)) { if(edns_vs == -1) { if(!ssl_printf(ssl, ", noEDNS%s.", edns_lame_known?" probed":" assumed")) return; } else { if(!ssl_printf(ssl, ", EDNS %d%s.", edns_vs, edns_lame_known?" probed":" assumed")) return; } } if(!ssl_printf(ssl, "\n")) return; } }