Пример #1
0
static unsigned eval_addr_set(pack_t *addr_set, kr_nsrep_lru_t *rttcache, unsigned score, uint8_t *addr[], uint32_t opts)
{
	/* Name server is better candidate if it has address record. */
	uint8_t *it = pack_head(*addr_set);
	while (it != pack_tail(*addr_set)) {
		void *val = pack_obj_val(it);
		size_t len = pack_obj_len(it);
		unsigned favour = 0;
		bool is_valid = false;
		/* Check if the address isn't disabled. */
		if (len == sizeof(struct in6_addr)) {
			is_valid = !(opts & QUERY_NO_IPV6);
			favour = FAVOUR_IPV6;
		} else {
			is_valid = !(opts & QUERY_NO_IPV4);
		}
		/* Get RTT for this address (if known) */
		if (is_valid) {
			unsigned *cached = rttcache ? lru_get(rttcache, val, len) : NULL;
			unsigned addr_score = (cached) ? *cached : KR_NS_GLUED;
			if (addr_score < score + favour) {
				/* Shake down previous contenders */
				for (size_t i = KR_NSREP_MAXADDR - 1; i > 0; --i)
					addr[i] = addr[i - 1];
				addr[0] = it;
				score = addr_score;
			}
		}
		it = pack_obj_next(it);
	}
	return score;
}
Пример #2
0
/** @internal Pack address list into JSON array. */
static JsonNode *pack_addrs(pack_t *pack)
{
	char buf[SOCKADDR_STRLEN];
	JsonNode *root = json_mkarray();
	uint8_t *addr = pack_head(*pack);
	while (addr != pack_tail(*pack)) {
		size_t len = pack_obj_len(addr);
		int family = len == sizeof(struct in_addr) ? AF_INET : AF_INET6;
		if (!inet_ntop(family, pack_obj_val(addr), buf, sizeof(buf))) {
			break;
		}
		json_append_element(root, json_mkstring(buf));
		addr = pack_obj_next(addr);
	}
	return root;
}
Пример #3
0
static int answer_query(knot_pkt_t *pkt, pack_t *addr_set, struct kr_query *qry)
{
	uint16_t rrtype = qry->stype;
	uint16_t rrclass = qry->sclass;
	if (rrtype != KNOT_RRTYPE_A && rrtype != KNOT_RRTYPE_AAAA) {
		return kr_error(ENOENT);
	}

	knot_dname_t *qname = knot_dname_copy(qry->sname, &pkt->mm);
	knot_rrset_t rr;
	knot_rrset_init(&rr, qname, rrtype, rrclass);
	int family_len = sizeof(struct in_addr);
	if (rr.type == KNOT_RRTYPE_AAAA) {
		family_len = sizeof(struct in6_addr);
	}

	/* Append address records from hints */
	uint8_t *addr = pack_head(*addr_set);
	while (addr != pack_tail(*addr_set)) {
		size_t len = pack_obj_len(addr);
		void *addr_val = pack_obj_val(addr);
		if (len == family_len) {
			knot_rrset_add_rdata(&rr, addr_val, len, 0, &pkt->mm);
		}
		addr = pack_obj_next(addr);
	}

	int ret = kr_error(ENOENT);
	if (!knot_rrset_empty(&rr)) {
		/* Update packet question */
		if (!knot_dname_is_equal(knot_pkt_qname(pkt), qname)) {
			KR_PKT_RECYCLE(pkt);
			knot_pkt_put_question(pkt, qname, rrclass, rrtype);
		}
		/* Append to packet */
		ret = knot_pkt_put(pkt, KNOT_COMPR_HINT_QNAME, &rr, KNOT_PF_FREE);
	}
	/* Clear RR if failed */
	if (ret != 0) {
		knot_rrset_clear(&rr, &pkt->mm);
	}
	return ret;
}
Пример #4
0
static void test_pack_std(void **state)
{
	int ret = 0;
	pack_t pack;
	pack_init(pack);
	assert_int_equal(pack.len, 0);

	/* Push/delete without reservation. */
	assert_int_not_equal(pack_obj_push(&pack, U8(""), 1), 0);
	assert_int_not_equal(pack_obj_del(&pack, U8(""), 1), 0);

	/* Reserve capacity and fill. */
	assert_true(pack_reserve(pack, 10, 10 * 2) >= 0);
	for (unsigned i = 0; i < 10; ++i) {
		ret = pack_obj_push(&pack, U8("de"), 2);
		assert_true(ret >= 0);
	}

	/* Iterate */
	uint8_t *it = pack_head(pack);
	assert_non_null(it);
	unsigned count = 0;
	while (it != pack_tail(pack)) {
		assert_int_equal(pack_obj_len(it), 2);
		assert_true(memcmp(pack_obj_val(it), "de", 2) == 0);
		it = pack_obj_next(it);
		count += 1;
	}

	/* Find */
	it = pack_obj_find(&pack, U8("de"), 2);
	assert_non_null(it);
	it = pack_obj_find(&pack, U8("ed"), 2);
	assert_null(it);

	/* Delete */
	assert_int_not_equal(pack_obj_del(&pack, U8("be"), 2), 0);
	assert_int_equal(pack_obj_del(&pack, U8("de"), 2), 0);
	assert_int_equal(pack.len, 9*(2+2)); /* 9 objects, length=2 */

	pack_clear(pack);
}
Пример #5
0
static unsigned eval_addr_set(pack_t *addr_set, kr_nsrep_lru_t *rttcache, unsigned score, uint8_t **addr)
{
	/* Name server is better candidate if it has address record. */
	uint8_t *it = pack_head(*addr_set);
	while (it != pack_tail(*addr_set)) {
		void *val = pack_obj_val(it);
		size_t len = pack_obj_len(it);
		/* Get RTT for this address (if known) */
		unsigned *cached = rttcache ? lru_get(rttcache, val, len) : NULL;
		unsigned addr_score = (cached) ? *cached : KR_NS_GLUED;
		/* Give v6 a head start */
		unsigned favour = (len == sizeof(struct in6_addr)) ? FAVOUR_IPV6 : 0;
		if (addr_score < score + favour) {
			*addr = it;
			score = addr_score;
		}
		it = pack_obj_next(it);
	}
	return score;
}