コード例 #1
0
ファイル: rdataset.c プロジェクト: idtek/knot
_public_
int knot_rdataset_sort_at(knot_rdataset_t *rrs, size_t pos, knot_mm_t *mm)
{
	if (rrs == NULL || rrs->rr_count == 0) {
		return KNOT_EINVAL;
	}

	knot_rdata_t *rr = knot_rdataset_at(rrs, pos);
	assert(rr);

	knot_rdata_t *earlier_rr = NULL;
	for (uint16_t i = 0; i < rrs->rr_count; ++i) {
		if (i == pos) {
			// It already is at the position
			return KNOT_EOK;
		}
		earlier_rr = knot_rdataset_at(rrs, i);
		int cmp = knot_rdata_cmp(earlier_rr, rr);
		if (cmp == 0) {
			// Duplication - we need to remove this RR
			return remove_rr_at(rrs, pos, mm);
		} else if (cmp > 0) {
			// Found position to move
			break;
		}
	}

	// RDATA have to be rearanged.
	knot_rdata_t *last_rr = knot_rdataset_at(rrs, pos - 1);
	assert(last_rr);
	assert(earlier_rr);

	// Save the RR to be moved
	const uint16_t size = knot_rdata_rdlen(rr);
	const uint32_t ttl = knot_rdata_ttl(rr);
	const uint8_t *rdata = knot_rdata_data(rr);

	knot_rdata_t tmp_rr[knot_rdata_array_size(size)];
	knot_rdata_init(tmp_rr, size, rdata, ttl);

	// Move the array or just part of it
	knot_rdata_t *earlier_rr_moved = earlier_rr + knot_rdata_array_size(size);
	size_t last_rr_size = knot_rdata_array_size(knot_rdata_rdlen(last_rr));
	memmove(earlier_rr_moved, earlier_rr, (last_rr + last_rr_size) - earlier_rr);

	// Set new RR
	knot_rdata_init(earlier_rr, size, knot_rdata_data(tmp_rr), ttl);

	return KNOT_EOK;
}
コード例 #2
0
ファイル: rdataset.c プロジェクト: idtek/knot
_public_
int knot_rdataset_reserve(knot_rdataset_t *rrs, size_t size, knot_mm_t *mm)
{
	if (rrs == NULL || size > MAX_RDLENGTH) {
		return KNOT_EINVAL;
	}

	size_t total_size = knot_rdataset_size(rrs);
	size_t new_size = total_size + knot_rdata_array_size(size);

	uint8_t *tmp = mm_realloc(mm, rrs->data, new_size, total_size);
	if (tmp == NULL) {
		return KNOT_ENOMEM;
	}

	rrs->data = tmp;
	rrs->rr_count++;

	// We have to initialise the 'size' field in the reserved space.
	knot_rdata_t *rr = knot_rdataset_at(rrs, rrs->rr_count - 1);
	assert(rr);
	knot_rdata_set_rdlen(rr, size);

	return KNOT_EOK;
}
コード例 #3
0
ファイル: rdataset.c プロジェクト: idtek/knot
static int add_rr_at(knot_rdataset_t *rrs, const knot_rdata_t *rr, size_t pos,
                     knot_mm_t *mm)
{
	if (rrs == NULL || pos > rrs->rr_count) {
		return KNOT_EINVAL;
	}
	const uint16_t size = knot_rdata_rdlen(rr);
	const uint32_t ttl = knot_rdata_ttl(rr);
	const uint8_t *rdata = knot_rdata_data(rr);

	size_t total_size = knot_rdataset_size(rrs);

	// Realloc data.
	void *tmp = mm_realloc(mm, rrs->data,
	                       total_size + knot_rdata_array_size(size),
	                       total_size);
	if (tmp) {
		rrs->data = tmp;
	} else {
		return KNOT_ENOMEM;
	}

	if (rrs->rr_count == 0 || pos == rrs->rr_count) {
		// No need to rearange RDATA
		rrs->rr_count++;
		knot_rdata_t *new_rr = knot_rdataset_at(rrs, pos);
		knot_rdata_init(new_rr, size, rdata, ttl);
		return KNOT_EOK;
	}

	// RDATA have to be rearanged.
	knot_rdata_t *last_rr = knot_rdataset_at(rrs, rrs->rr_count - 1);
	knot_rdata_t *old_rr = knot_rdataset_at(rrs, pos);
	assert(last_rr);
	assert(old_rr);

	// Make space for new data by moving the array
	memmove(old_rr + knot_rdata_array_size(size), old_rr,
	        (last_rr + knot_rdata_array_size(knot_rdata_rdlen(last_rr))) - old_rr);

	// Set new RR
	knot_rdata_init(old_rr, size, rdata, ttl);

	rrs->rr_count++;
	return KNOT_EOK;
}
コード例 #4
0
ファイル: rdata.c プロジェクト: gitter-badger/knot
int main(int argc, char *argv[])
{
	plan(9);

	// Test array size
	size_t array_size = knot_rdata_array_size(16);
	ok(array_size == sizeof(struct rr_offsets) + 16, "rdata: array size.");

	// Test init
	knot_rdata_t rdata[array_size];
	uint8_t payload[16] = "abcdefghijklmnop";
	knot_rdata_init(rdata, 16, payload, 3600);
	const bool set_ok = knot_rdata_rdlen(rdata) == 16 &&
	                    knot_rdata_ttl(rdata) == 3600 &&
	                    memcmp(knot_rdata_data(rdata), payload, 16) == 0;
	ok(set_ok, "rdata: init.");

	// Test setters
	knot_rdata_set_ttl(rdata, 1234);
	ok(knot_rdata_ttl(rdata) == 1234, "rdata: set TTL.");
	knot_rdata_set_rdlen(rdata, 1);
	ok(knot_rdata_rdlen(rdata) == 1, "rdata: set RDLEN.");

	// Test compare
	knot_rdata_set_rdlen(rdata, 16);
	ok(knot_rdata_cmp(rdata, rdata) == 0, "rdata: cmp eq.");

	knot_rdata_t *lower = rdata;
	knot_rdata_t greater[knot_rdata_array_size(16)];
	knot_rdata_init(greater, 16, (uint8_t *)"qrstuvwxyz123456", 1234);
	ok(knot_rdata_cmp(lower, greater) < 0, "rdata: cmp lower.");
	ok(knot_rdata_cmp(greater, lower) > 0, "rdata: cmp greater.");

	// Payloads will be the same.
	memcpy(knot_rdata_data(greater), knot_rdata_data(lower), 16);
	assert(knot_rdata_cmp(lower, greater) == 0);

	knot_rdata_set_rdlen(lower, 15);
	ok(knot_rdata_cmp(lower, greater) < 0, "rdata: cmp lower size.");
	ok(knot_rdata_cmp(greater, lower) > 0, "rdata: cmp greater size.");

	return 0;
}
コード例 #5
0
ファイル: rdataset.c プロジェクト: idtek/knot
static int remove_rr_at(knot_rdataset_t *rrs, size_t pos, knot_mm_t *mm)
{
	if (rrs == NULL || pos >= rrs->rr_count) {
		return KNOT_EINVAL;
	}

	knot_rdata_t *old_rr = knot_rdataset_at(rrs, pos);
	knot_rdata_t *last_rr = knot_rdataset_at(rrs, rrs->rr_count - 1);
	assert(old_rr);
	assert(last_rr);

	size_t total_size = knot_rdataset_size(rrs);
	uint16_t old_size = knot_rdata_rdlen(old_rr);

	uint8_t *old_threshold = old_rr + knot_rdata_array_size(old_size);
	uint8_t *last_threshold = last_rr + knot_rdata_array_size(knot_rdata_rdlen(last_rr));
	// Move RDATA
	memmove(old_rr, old_threshold,
	        last_threshold - old_threshold);

	if (rrs->rr_count > 1) {
		// Realloc RDATA
		void *tmp = mm_realloc(mm, rrs->data,
		                       total_size - (knot_rdata_array_size(old_size)),
		                       total_size);
		if (tmp == NULL) {
			return KNOT_ENOMEM;
		} else {
			rrs->data = tmp;
		}
	} else {
		// Free RDATA
		mm_free(mm, rrs->data);
		rrs->data = NULL;
	}
	rrs->rr_count--;

	return KNOT_EOK;
}
コード例 #6
0
ファイル: rdataset.c プロジェクト: idtek/knot
static knot_rdata_t *rr_seek(knot_rdata_t *d, size_t pos)
{
	if (d == NULL) {
		return NULL;
	}

	size_t offset = 0;
	for (size_t i = 0; i < pos; i++) {
		knot_rdata_t *rr = d + offset;
		offset += knot_rdata_array_size(knot_rdata_rdlen(rr));
	}

	return d + offset;
}
コード例 #7
0
ファイル: rdataset.c プロジェクト: idtek/knot
_public_
size_t knot_rdataset_size(const knot_rdataset_t *rrs)
{
	if (rrs == NULL) {
		return 0;
	}

	size_t total_size = 0;
	for (size_t i = 0; i < rrs->rr_count; ++i) {
		const knot_rdata_t *rr = knot_rdataset_at(rrs, i);
		assert(rr);
		total_size += knot_rdata_array_size(knot_rdata_rdlen(rr));
	}

	return total_size;
}
コード例 #8
0
ファイル: hints.c プロジェクト: gitter-badger/knot-resolver
static int add_pair(struct kr_zonecut *hints, const char *name, const char *addr)
{
	/* Build key */
	knot_dname_t key[KNOT_DNAME_MAXLEN];
	if (!knot_dname_from_str(key, name, sizeof(key))) {
		return kr_error(EINVAL);
	}

	/* Parse address string */
	struct sockaddr_storage ss;
	if (parse_addr_str(&ss, addr) != 0) {
		return kr_error(EINVAL);
	}

	/* Build rdata */
	size_t addr_len = 0;
	uint8_t *raw_addr = sockaddr_raw(&ss, &addr_len);
	knot_rdata_t rdata[knot_rdata_array_size(addr_len)];
	knot_rdata_init(rdata, addr_len, raw_addr, 0);

	return kr_zonecut_add(hints, key, rdata);
}
コード例 #9
0
ファイル: rosedb_tool.c プロジェクト: idtek/knot
static int parse_rdata(struct entry *entry, const char *owner, const char *rrtype, const char *rdata,
		       int ttl, knot_mm_t *mm)
{
	knot_rdataset_init(&entry->data.rrs);
	int ret = knot_rrtype_from_string(rrtype, &entry->data.type);
	if (ret != KNOT_EOK) {
		return ret;
	}

	/* Synthetize RR line */
	char *rr_line = sprintf_alloc("%s %u IN %s %s\n", owner, ttl, rrtype, rdata);
	if (zs_set_input_string(g_scanner, rr_line, strlen(rr_line)) != 0 ||
	    zs_parse_all(g_scanner) != 0) {
		free(rr_line);
		return KNOT_EPARSEFAIL;
	}
	free(rr_line);

	/* Write parsed RDATA. */
	knot_rdata_t rr[knot_rdata_array_size(g_scanner->r_data_length)];
	knot_rdata_init(rr, g_scanner->r_data_length, g_scanner->r_data, ttl);
	return knot_rdataset_add(&entry->data.rrs, rr, mm);
}
コード例 #10
0
ファイル: rosedb_tool.c プロジェクト: gitter-badger/knot
static int parse_rdata(struct entry *entry, const char *owner, const char *rrtype, const char *rdata,
		       int ttl, mm_ctx_t *mm)
{
	knot_rdataset_init(&entry->data.rrs);
	int ret = knot_rrtype_from_string(rrtype, &entry->data.type);
	if (ret != KNOT_EOK) {
		return ret;
	}

	/* Synthetize RR line */
	char *rr_line = sprintf_alloc("%s %u IN %s %s\n", owner, ttl, rrtype, rdata);
	ret = zs_scanner_parse(g_scanner, rr_line, rr_line + strlen(rr_line), true);
	free(rr_line);

	/* Write parsed RDATA. */
	if (ret == KNOT_EOK) {
		knot_rdata_t rr[knot_rdata_array_size(g_scanner->r_data_length)];
		knot_rdata_init(rr, g_scanner->r_data_length, g_scanner->r_data, ttl);
		ret = knot_rdataset_add(&entry->data.rrs, rr, mm);
	}

	return ret;
}
コード例 #11
0
ファイル: rdataset.c プロジェクト: gitter-badger/knot
int main(int argc, char *argv[])
{
	plan(34);

	// Test init
	knot_rdataset_t rdataset;
	knot_rdataset_init(&rdataset);
	ok(rdataset.data == NULL && rdataset.rr_count == 0, "rdataset: init.");

	// Test rdata addition
	knot_rdata_t rdata_gt[knot_rdata_array_size(4)];
	knot_rdata_init(rdata_gt, 4, (uint8_t *)"wxyz", 3600);

	int ret = knot_rdataset_add(NULL, NULL, NULL);
	ok(ret == KNOT_EINVAL, "rdataset: add NULL.");
	ret = knot_rdataset_add(&rdataset, rdata_gt, NULL);
	bool add_ok = ret == KNOT_EOK && rdataset.rr_count == 1 &&
	              knot_rdata_cmp(rdata_gt, rdataset.data) == 0;
	ok(add_ok, "rdataset: add.");

	knot_rdata_t rdata_lo[knot_rdata_array_size(4)];
	knot_rdata_init(rdata_lo, 4, (uint8_t *)"abcd", 3600);
	ret = knot_rdataset_add(&rdataset, rdata_lo, NULL);
	add_ok = ret == KNOT_EOK && rdataset.rr_count == 2 &&
	         knot_rdata_cmp(rdata_lo, rdataset.data) == 0;
	ok(add_ok, "rdataset: add lower.");

	// Test getters
	ok(knot_rdata_cmp(knot_rdataset_at(&rdataset, 0), rdata_lo) == 0 &&
	   knot_rdata_cmp(knot_rdataset_at(&rdataset, 1), rdata_gt) == 0,
	   "rdataset: at.");

	ok(knot_rdataset_size(&rdataset) == knot_rdata_array_size(4) * 2,
	   "rdataset: size.");

	// Test copy
	ok(knot_rdataset_copy(NULL, NULL, NULL) == KNOT_EINVAL,
	   "rdataset: copy NULL.");
	knot_rdataset_t copy;
	ret = knot_rdataset_copy(&copy, &rdataset, NULL);
	const bool copy_ok = ret == KNOT_EOK && copy.rr_count == rdataset.rr_count &&
	                     knot_rdataset_size(&copy) == knot_rdataset_size(&rdataset) &&
	                     memcmp(rdataset.data, copy.data,
	                            knot_rdataset_size(&rdataset)) == 0;
	ok(copy_ok, "rdataset: copy");

	// Test eq
	ok(knot_rdataset_eq(&rdataset, &copy), "rdataset: equal");

	// Test clear
	knot_rdataset_clear(&copy, NULL);
	ok(copy.rr_count == 0 && copy.data == NULL, "rdataset: clear.");

	// Test not equal (different count)
	ok(!knot_rdataset_eq(&rdataset, &copy), "rdataset: not equal - count");

	// Test member
	knot_rdata_t not_a_member[knot_rdata_array_size(1)];
	knot_rdata_init(not_a_member, 1, (uint8_t *)"?", 3600);
	ok(knot_rdataset_member(&rdataset, rdata_gt, true), "rdataset: is member.");
	ok(!knot_rdataset_member(&rdataset, not_a_member, true), "rdataset: is not member.");

	knot_rdata_set_ttl(rdata_gt, 1234);
	ok(knot_rdataset_member(&rdataset, rdata_gt, false), "rdataset: is member TTL.");
	ok(!knot_rdataset_member(&rdataset, rdata_gt, true), "rdataset: is not member TTL.");

	// Test merge
	ok(knot_rdataset_merge(NULL, NULL, NULL) == KNOT_EINVAL,
	   "rdataset: merge NULL.");
	knot_rdataset_t empty;
	knot_rdataset_init(&empty);
	ret = knot_rdataset_merge(&empty, &rdataset, NULL);
	bool merge_ok = ret == KNOT_EOK && knot_rdataset_eq(&empty, &rdataset);
	ok(merge_ok, "rdataset: merge empty.");
	knot_rdata_t *data_before = rdataset.data;
	ret = knot_rdataset_merge(&rdataset, &rdataset, NULL);
	merge_ok = ret == KNOT_EOK && rdataset.rr_count == 2 &&
	           data_before == rdataset.data;
	ok(merge_ok, "rdataset: merge self.");

	knot_rdataset_clear(&empty, NULL);

	// Init structs for merge sort testing
	knot_rdataset_t rdataset_lo; // "Lower" rdataset
	knot_rdataset_init(&rdataset_lo);
	RDATASET_INIT_WITH(rdataset_lo, rdata_lo);
	knot_rdataset_t rdataset_gt; // "Greater" rdataset
	knot_rdataset_init(&rdataset_gt);
	RDATASET_INIT_WITH(rdataset_gt, rdata_gt);

	// Test not equal - different data
	ok(!knot_rdataset_eq(&rdataset_gt, &rdataset_lo), "rdataset: data not equal.");

	// Test that merge keeps the sorted order
	ret = knot_rdataset_merge(&rdataset_lo, &rdataset_gt, NULL);
	merge_ok = ret == KNOT_EOK && knot_rdataset_eq(&rdataset_lo, &rdataset);
	ok(merge_ok, "rdataset: merge into lower.");

	RDATASET_INIT_WITH(rdataset_lo, rdata_lo);
	RDATASET_INIT_WITH(rdataset_gt, rdata_gt);
	ret = knot_rdataset_merge(&rdataset_gt, &rdataset_lo, NULL);
	merge_ok = ret == KNOT_EOK && knot_rdataset_eq(&rdataset_gt, &rdataset);
	ok(merge_ok, "rdataset: merge into greater.");

	// Test intersect
	ok(knot_rdataset_intersect(NULL, NULL, NULL, NULL) == KNOT_EINVAL,
	   "rdataset: intersect NULL.");

	knot_rdataset_t intersection;
	ret = knot_rdataset_intersect(&rdataset, &rdataset, &intersection, NULL);
	bool intersect_ok = ret == KNOT_EOK && knot_rdataset_eq(&rdataset, &intersection);
	ok(intersect_ok, "rdataset: intersect self.");
	knot_rdataset_clear(&intersection, NULL);

	RDATASET_INIT_WITH(rdataset_lo, rdata_lo);
	RDATASET_INIT_WITH(rdataset_gt, rdata_gt);
	ret = knot_rdataset_intersect(&rdataset_lo, &rdataset_gt, &intersection, NULL);
	intersect_ok = ret == KNOT_EOK && intersection.rr_count == 0;
	ok(intersect_ok, "rdataset: intersect no common.");

	ret = knot_rdataset_intersect(&rdataset, &rdataset_lo, &intersection, NULL);
	intersect_ok = ret == KNOT_EOK && knot_rdataset_eq(&intersection, &rdataset_lo);
	ok(intersect_ok, "rdataset: intersect normal.");
	knot_rdataset_clear(&intersection, NULL);

	// Test subtract
	ok(knot_rdataset_subtract(NULL, NULL, NULL) == KNOT_EINVAL,
	   "rdataset: subtract NULL.");
	ok(knot_rdataset_subtract(&rdataset, &rdataset, NULL) == KNOT_EINVAL,
	   "rdataset: subtract self.");

	ret = knot_rdataset_copy(&copy, &rdataset, NULL);
	assert(ret == KNOT_EOK);
	ret = knot_rdataset_subtract(&copy, &rdataset, NULL);
	bool subtract_ok = ret == KNOT_EOK && copy.rr_count == 0;
	ok(subtract_ok, "rdataset: subtract identical.");

	RDATASET_INIT_WITH(rdataset_lo, rdata_lo);
	RDATASET_INIT_WITH(rdataset_gt, rdata_gt);
	data_before = rdataset_lo.data;
	ret = knot_rdataset_subtract(&rdataset_lo, &rdataset_gt, NULL);
	subtract_ok = ret == KNOT_EOK && rdataset_lo.rr_count == 1 &&
	              rdataset_lo.data == data_before;
	ok(subtract_ok, "rdataset: subtract no common.");

	ret = knot_rdataset_subtract(&rdataset, &rdataset_gt, NULL);
	subtract_ok = ret == KNOT_EOK && knot_rdataset_eq(&rdataset, &rdataset_lo);
	ok(subtract_ok, "rdataset: subtract normal.");

	ret = knot_rdataset_subtract(&rdataset, &rdataset_lo, NULL);
	subtract_ok = ret == KNOT_EOK && rdataset.rr_count == 0 &&
	              rdataset.data == NULL;
	ok(subtract_ok, "rdataset: subtract last.");

	ret = knot_rdataset_reserve(&rdataset, 65536, NULL);
	ok(ret == KNOT_EINVAL, "rdataset: reserve too much");

	RDATASET_INIT_WITH(rdataset, rdata_gt);

	size_t old_rrs_size = knot_rdataset_size(&rdataset);
	size_t rr_size = knot_rdata_rdlen(rdata_lo);
	ret = knot_rdataset_reserve(&rdataset, rr_size, NULL);
	size_t new_rrs_size = knot_rdataset_size(&rdataset);
	bool reserve_ok = ret == KNOT_EOK && new_rrs_size == (old_rrs_size + knot_rdata_array_size(rr_size));
	ok(reserve_ok, "rdataset: reserve normal");

	RDATASET_INIT_WITH(copy, rdata_lo);
	knot_rdataset_add(&copy, rdata_gt, NULL);

	knot_rdata_init(knot_rdataset_at(&rdataset, 1), 4, (uint8_t *)"abcd", 3600);

	ret = knot_rdataset_sort_at(&rdataset, 1, NULL);
	bool sort_ok = ret == KNOT_EOK && knot_rdataset_eq(&rdataset, &copy);
	ok(sort_ok, "rdataset: sort reserved space");

	knot_rdataset_clear(&copy, NULL);
	knot_rdataset_clear(&rdataset, NULL);
	knot_rdataset_clear(&rdataset_lo, NULL);
	knot_rdataset_clear(&rdataset_gt, NULL);

	return EXIT_SUCCESS;
}