Пример #1
0
int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
	size_t nmlen, int ATTR_UNUSED(nmlabs))
{
	/* deep links into the iterator module */
	struct delegpt* dp;
	struct dns_msg* msg;
	struct regional* region = worker->scratchpad;
	char b[260];
	struct query_info qinfo;
	struct iter_hints_stub* stub;
	regional_free_all(region);
	qinfo.qname = nm;
	qinfo.qname_len = nmlen;
	qinfo.qtype = LDNS_RR_TYPE_A;
	qinfo.qclass = LDNS_RR_CLASS_IN;
	qinfo.local_alias = NULL;

	dname_str(nm, b);
	if(!ssl_printf(ssl, "The following name servers are used for lookup "
		"of %s\n", b)) 
		return 0;
	
	dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass);
	if(dp) {
		if(!ssl_printf(ssl, "forwarding request:\n"))
			return 0;
		print_dp_main(ssl, dp, NULL);
		print_dp_details(ssl, worker, dp);
		return 1;
	}
	
	while(1) {
		dp = dns_cache_find_delegation(&worker->env, nm, nmlen, 
			qinfo.qtype, qinfo.qclass, region, &msg, 
			*worker->env.now);
		if(!dp) {
			return ssl_printf(ssl, "no delegation from "
				"cache; goes to configured roots\n");
		}
		/* go up? */
		if(iter_dp_is_useless(&qinfo, BIT_RD, dp)) {
			print_dp_main(ssl, dp, msg);
			print_dp_details(ssl, worker, dp);
			if(!ssl_printf(ssl, "cache delegation was "
				"useless (no IP addresses)\n"))
				return 0;
			if(dname_is_root(nm)) {
				/* goes to root config */
				return ssl_printf(ssl, "no delegation from "
					"cache; goes to configured roots\n");
			} else {
				/* useless, goes up */
				nm = dp->name;
				nmlen = dp->namelen;
				dname_remove_label(&nm, &nmlen);
				dname_str(nm, b);
				if(!ssl_printf(ssl, "going up, lookup %s\n", b))
					return 0;
				continue;
			}
		} 
		stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass,
			dp);
		if(stub) {
			if(stub->noprime) {
				if(!ssl_printf(ssl, "The noprime stub servers "
					"are used:\n"))
					return 0;
			} else {
				if(!ssl_printf(ssl, "The stub is primed "
						"with servers:\n"))
					return 0;
			}
			print_dp_main(ssl, stub->dp, NULL);
			print_dp_details(ssl, worker, stub->dp);
		} else {
			print_dp_main(ssl, dp, msg);
			print_dp_details(ssl, worker, dp);
		}
		break;
	}

	return 1;
}
Пример #2
0
/** answer nonrecursive query from the cache */
static int
answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
	uint16_t id, uint16_t flags, struct comm_reply* repinfo, 
	struct edns_data* edns)
{
	/* for a nonrecursive query return either:
	 * 	o an error (servfail; we try to avoid this)
	 * 	o a delegation (closest we have; this routine tries that)
	 * 	o the answer (checked by answer_from_cache) 
	 *
	 * So, grab a delegation from the rrset cache. 
	 * Then check if it needs validation, if so, this routine fails,
	 * so that iterator can prime and validator can verify rrsets.
	 */
	uint16_t udpsize = edns->udp_size;
	int secure = 0;
	time_t timenow = *worker->env.now;
	int must_validate = (!(flags&BIT_CD) || worker->env.cfg->ignore_cd)
		&& worker->env.need_to_validate;
	struct dns_msg *msg = NULL;
	struct delegpt *dp;

	dp = dns_cache_find_delegation(&worker->env, qinfo->qname, 
		qinfo->qname_len, qinfo->qtype, qinfo->qclass,
		worker->scratchpad, &msg, timenow);
	if(!dp) { /* no delegation, need to reprime */
		return 0;
	}
	if(must_validate) {
		switch(check_delegation_secure(msg->rep)) {
		case sec_status_unchecked:
			/* some rrsets have not been verified yet, go and 
			 * let validator do that */
			return 0;
		case sec_status_bogus:
			/* some rrsets are bogus, reply servfail */
			edns->edns_version = EDNS_ADVERTISED_VERSION;
			edns->udp_size = EDNS_ADVERTISED_SIZE;
			edns->ext_rcode = 0;
			edns->bits &= EDNS_DO;
			if(!edns_opt_inplace_reply(edns, worker->scratchpad))
				return 0;
			error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, 
				&msg->qinfo, id, flags, edns);
			if(worker->stats.extended) {
				worker->stats.ans_bogus++;
				worker->stats.ans_rcode[LDNS_RCODE_SERVFAIL]++;
			}
			return 1;
		case sec_status_secure:
			/* all rrsets are secure */
			/* remove non-secure rrsets from the add. section*/
			if(worker->env.cfg->val_clean_additional)
				deleg_remove_nonsecure_additional(msg->rep);
			secure = 1;
			break;
		case sec_status_indeterminate:
		case sec_status_insecure:
		default:
			/* not secure */
			secure = 0;
			break;
		}
	}
	/* return this delegation from the cache */
	edns->edns_version = EDNS_ADVERTISED_VERSION;
	edns->udp_size = EDNS_ADVERTISED_SIZE;
	edns->ext_rcode = 0;
	edns->bits &= EDNS_DO;
	if(!edns_opt_inplace_reply(edns, worker->scratchpad))
		return 0;
	msg->rep->flags |= BIT_QR|BIT_RA;
	if(!reply_info_answer_encode(&msg->qinfo, msg->rep, id, flags, 
		repinfo->c->buffer, 0, 1, worker->scratchpad,
		udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
		error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, 
			&msg->qinfo, id, flags, edns);
	}
	if(worker->stats.extended) {
		if(secure) worker->stats.ans_secure++;
		server_stats_insrcode(&worker->stats, repinfo->c->buffer);
	}
	return 1;
}