Exemple #1
0
ldns_status
ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n)
{
	ldns_rdf **nameservers;
	size_t ns_count;
	size_t *rtt;

	if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A &&
			ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) {
		return LDNS_STATUS_ERR;
	}

	ns_count = ldns_resolver_nameserver_count(r);
	nameservers = ldns_resolver_nameservers(r);
	rtt = ldns_resolver_rtt(r);

	/* make room for the next one */
	nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1));
	/* don't forget the rtt */
	rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1));
	
	/* set the new value in the resolver */
	ldns_resolver_set_nameservers(r, nameservers);

	/* slide n in its slot. */
	/* we clone it here, because then we can free the original
	 * rr's where it stood */
	nameservers[ns_count] = ldns_rdf_clone(n);
	rtt[ns_count] = LDNS_RESOLV_RTT_MIN;
	ldns_resolver_incr_nameserver_count(r);
	ldns_resolver_set_rtt(r, rtt);
	return LDNS_STATUS_OK;
}
Exemple #2
0
ldns_rdf *
ldns_resolver_pop_nameserver(ldns_resolver *r)
{
	ldns_rdf **nameservers;
	ldns_rdf *pop;
	size_t ns_count;
	size_t *rtt;

	assert(r != NULL);

	ns_count = ldns_resolver_nameserver_count(r);
	nameservers = ldns_resolver_nameservers(r);
	rtt = ldns_resolver_rtt(r);
	if (ns_count == 0 || !nameservers) {
		return NULL;
	}
	
	pop = nameservers[ns_count - 1];

	nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count - 1));
	rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1));

	ldns_resolver_set_nameservers(r, nameservers);
	ldns_resolver_set_rtt(r, rtt);
	/* decr the count */
	ldns_resolver_dec_nameserver_count(r);
	return pop;
}
Exemple #3
0
void
ldns_resolver_incr_nameserver_count(ldns_resolver *r)
{
	size_t c;

	c = ldns_resolver_nameserver_count(r);
	ldns_resolver_set_nameserver_count(r, ++c);
}
/* random isn't really that good */
void
ldns_resolver_nameservers_randomize(ldns_resolver *r)
{
    uint16_t i, j;
    ldns_rdf **ns, *tmp;

    /* should I check for ldns_resolver_random?? */
    assert(r != NULL);

    ns = ldns_resolver_nameservers(r);
    for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
        j = ldns_get_random() % ldns_resolver_nameserver_count(r);
        tmp = ns[i];
        ns[i] = ns[j];
        ns[j] = tmp;
    }
    ldns_resolver_set_nameservers(r, ns);
}
Exemple #5
0
void
ldns_resolver_dec_nameserver_count(ldns_resolver *r)
{
	size_t c;

	c = ldns_resolver_nameserver_count(r);
	if (c == 0) {
		return;
	} else {
		ldns_resolver_set_nameserver_count(r, --c);
	}
}
Exemple #6
0
void
ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value)
{
	size_t *rtt;

	assert(r != NULL);

	rtt = ldns_resolver_rtt(r);
	
	if (pos >= ldns_resolver_nameserver_count(r)) {
		/* error ?*/
	} else {
		rtt[pos] = value;
	}

}
Exemple #7
0
size_t
ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos)
{
	size_t *rtt;

	assert(r != NULL);
	
	rtt = ldns_resolver_rtt(r);
	
	if (pos >= ldns_resolver_nameserver_count(r)) {
		/* error ?*/
		return 0;
	} else {
		return rtt[pos];
	}

}
Exemple #8
0
ldns_status
ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, 
		ldns_rr_type type, ldns_rr_class c, uint16_t flags)
{
	ldns_pkt *query_pkt;
	ldns_pkt *answer_pkt;
	ldns_status status;

	assert(r != NULL);
	assert(name != NULL);

	answer_pkt = NULL;
	
	/* do all the preprocessing here, then fire of an query to 
	 * the network */

	if (0 == type) {
		type = LDNS_RR_TYPE_A;
	}
	if (0 == c) {
		c = LDNS_RR_CLASS_IN;
	}
	if (0 == ldns_resolver_nameserver_count(r)) {
		return LDNS_STATUS_RES_NO_NS;
	}
	if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
		return LDNS_STATUS_RES_QUERY;
	}

	status = ldns_resolver_prepare_query_pkt(&query_pkt,
	                                         r,
	                                         name,
	                                         type,
	                                         c,
	                                         flags);
	if (status != LDNS_STATUS_OK) {
		return status;
	}

	/* if tsig values are set, tsign it */
	/* TODO: make last 3 arguments optional too? maybe make complete
	         rr instead of seperate values in resolver (and packet)
	  Jelte
	  should this go in pkt_prepare?
	*/
#ifdef HAVE_SSL
	if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
		status = ldns_pkt_tsig_sign(query_pkt,
		                            ldns_resolver_tsig_keyname(r),
		                            ldns_resolver_tsig_keydata(r),
		                            300, ldns_resolver_tsig_algorithm(r), NULL);
		if (status != LDNS_STATUS_OK) {
			return LDNS_STATUS_CRYPTO_TSIG_ERR;
		}
	}
#endif /* HAVE_SSL */
	status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
	ldns_pkt_free(query_pkt);
	
	/* allows answer to be NULL when not interested in return value */
	if (answer) {
		*answer = answer_pkt;
	}
	return status;
}
Exemple #9
0
ldns_status
ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac)
{
	uint8_t i;

	struct sockaddr_storage *src = NULL;
	size_t src_len;
	struct sockaddr_storage *ns;
	size_t ns_len;
	struct timeval tv_s;
	struct timeval tv_e;

	ldns_rdf **ns_array;
	size_t *rtt;
	ldns_pkt *reply;
	bool all_servers_rtt_inf;
	uint8_t retries;

	uint8_t *reply_bytes = NULL;
	size_t reply_size = 0;
	ldns_status status, send_status;

	assert(r != NULL);

	status = LDNS_STATUS_OK;
	rtt = ldns_resolver_rtt(r);
	ns_array = ldns_resolver_nameservers(r);
	reply = NULL; 
	ns_len = 0;

	all_servers_rtt_inf = true;

	if (ldns_resolver_random(r)) {
		ldns_resolver_nameservers_randomize(r);
	}

	if(ldns_resolver_source(r)) {
		src = ldns_rdf2native_sockaddr_storage_port(
				ldns_resolver_source(r), 0, &src_len);
	}

	/* loop through all defined nameservers */
	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
		if (rtt[i] == LDNS_RESOLV_RTT_INF) {
			/* not reachable nameserver! */
			continue;
		}

		/* maybe verbosity setting?
		printf("Sending to ");
		ldns_rdf_print(stdout, ns_array[i]);
		printf("\n");
		*/
		ns = ldns_rdf2native_sockaddr_storage(ns_array[i],
				ldns_resolver_port(r), &ns_len);


#ifndef S_SPLINT_S
		if ((ns->ss_family == AF_INET) &&
				(ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) {
			/* not reachable */
			LDNS_FREE(ns);
			continue;
		}

		if ((ns->ss_family == AF_INET6) &&
				 (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) {
			/* not reachable */
			LDNS_FREE(ns);
			continue;
		}
#endif

		all_servers_rtt_inf = false;

		gettimeofday(&tv_s, NULL);

		send_status = LDNS_STATUS_ERR;

		/* reply_bytes implicitly handles our error */
		if (ldns_resolver_usevc(r)) {
			for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
				send_status = 
					ldns_tcp_send_from(&reply_bytes, qb, 
						ns, (socklen_t)ns_len,
						src, (socklen_t)src_len,
						ldns_resolver_timeout(r),
						&reply_size);
				if (send_status == LDNS_STATUS_OK) {
					break;
				}
			}
		} else {
			for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
				/* ldns_rdf_print(stdout, ns_array[i]); */
				send_status = 
					ldns_udp_send_from(&reply_bytes, qb,
						ns,  (socklen_t)ns_len,
						src, (socklen_t)src_len,
						ldns_resolver_timeout(r),
						&reply_size);
				if (send_status == LDNS_STATUS_OK) {
					break;
				}
			}
		}

		if (send_status != LDNS_STATUS_OK) {
			ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF);
			status = send_status;
		}
		
		/* obey the fail directive */
		if (!reply_bytes) {
			/* the current nameserver seems to have a problem, blacklist it */
			if (ldns_resolver_fail(r)) {
				LDNS_FREE(ns);
				return LDNS_STATUS_ERR;
			} else {
				LDNS_FREE(ns);
				continue;
			}
		} 
		
		status = ldns_wire2pkt(&reply, reply_bytes, reply_size);
		if (status != LDNS_STATUS_OK) {
			LDNS_FREE(reply_bytes);
			LDNS_FREE(ns);
			return status;
		}
		
		LDNS_FREE(ns);
		gettimeofday(&tv_e, NULL);

		if (reply) {
			ldns_pkt_set_querytime(reply, (uint32_t)
				((tv_e.tv_sec - tv_s.tv_sec) * 1000) +
				(tv_e.tv_usec - tv_s.tv_usec) / 1000);
			ldns_pkt_set_answerfrom(reply,
					ldns_rdf_clone(ns_array[i]));
			ldns_pkt_set_timestamp(reply, tv_s);
			ldns_pkt_set_size(reply, reply_size);
			break;
		} else {
			if (ldns_resolver_fail(r)) {
				/* if fail is set bail out, after the first
				 * one */
				break;
			}
		}

		/* wait retrans seconds... */
		sleep((unsigned int) ldns_resolver_retrans(r));
	}

	if(src) {
		LDNS_FREE(src);
	}
	if (all_servers_rtt_inf) {
		LDNS_FREE(reply_bytes);
		return LDNS_STATUS_RES_NO_NS;
	}
#ifdef HAVE_SSL
	if (tsig_mac && reply && reply_bytes) {
		if (!ldns_pkt_tsig_verify(reply,
		                          reply_bytes,
					  reply_size,
		                          ldns_resolver_tsig_keyname(r),
		                          ldns_resolver_tsig_keydata(r), tsig_mac)) {
			status = LDNS_STATUS_CRYPTO_TSIG_BOGUS;
		}
	}
#else
	(void)tsig_mac;
#endif /* HAVE_SSL */

	LDNS_FREE(reply_bytes);
	if (result) {
		*result = reply;
	}

	return status;
}