Exemple #1
0
_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;
}
Exemple #2
0
/*----------------------------------------------------------------------------*/
_public_
int knot_edns_add_option(knot_rrset_t *opt_rr, uint16_t code,
                         uint16_t length, const uint8_t *data, mm_ctx_t *mm)
{
	if (opt_rr == NULL || (length != 0 && data == NULL)) {
		return KNOT_EINVAL;
	}

	/* We need to replace the RDATA currently in the OPT RR */

	/* 1) create new RDATA by appending the new option after the current
	 *    RDATA.
	 */
	assert(opt_rr->rrs.rr_count == 1);
	knot_rdata_t *old_rdata = knot_rdataset_at(&opt_rr->rrs, 0);

	uint8_t *old_data = knot_rdata_data(old_rdata);
	uint16_t old_data_len = knot_rdata_rdlen(old_rdata);
	uint16_t new_data_len = old_data_len + KNOT_EDNS_OPTION_HDRLEN + length;

	uint8_t new_data[new_data_len];

	memcpy(new_data, old_data, old_data_len);
	// write length and code in wireformat (convert endian)
	wire_write_u16(new_data + old_data_len, code);
	wire_write_u16(new_data + old_data_len + sizeof(uint16_t), length);
	// write the option data
	memcpy(new_data + old_data_len + KNOT_EDNS_OPTION_HDRLEN, data, length);

	/* 2) Replace the RDATA in the RRSet. */
	uint32_t old_ttl = knot_rdata_ttl(old_rdata);
	knot_rdataset_clear(&opt_rr->rrs, mm);
	return knot_rrset_add_rdata(opt_rr, new_data, new_data_len,
	                            old_ttl, mm);
}
Exemple #3
0
static int rosedb_get(struct cache *cache, MDB_txn *txn, int argc, char *argv[])
{
	knot_dname_t key[KNOT_DNAME_MAXLEN] = { '\0' };
	knot_dname_from_str(key, argv[0], sizeof(key));
	knot_dname_to_lower(key);

	char type_str[16] = { '\0' };

	struct iter it;
	int ret = cache_query_fetch(txn, cache->dbi, &it, key);
	while (ret == 0) {
		struct entry entry;
		cache_iter_val(&it, &entry);
		knot_rdata_t *rd = knot_rdataset_at(&entry.data.rrs, 0);
		knot_rrtype_to_string(entry.data.type, type_str, sizeof(type_str));
		printf("%s\t%s\tTTL=%u\tRDLEN=%u\t%s\t%s\n", argv[0], type_str,
		       knot_rdata_ttl(rd), knot_rdata_rdlen(rd), entry.threat_code, entry.syslog_ip);
		if (cache_iter_next(&it) != 0) {
			break;
		}
	}

	cache_iter_free(&it);

	return ret;
}
Exemple #4
0
/*----------------------------------------------------------------------------*/
_public_
bool knot_edns_check_record(knot_rrset_t *opt_rr)
{
	if (opt_rr->rrs.rr_count != 1) {
		return false;
	}

	knot_rdata_t *rdata = knot_rdataset_at(&opt_rr->rrs, 0);
	if (rdata == NULL) {
		return false;
	}

	uint8_t *data = knot_rdata_data(rdata);
	uint16_t rdlength = knot_rdata_rdlen(rdata);
	uint32_t pos = 0;

	/* RFC2671 4.4: {uint16_t code, uint16_t len, data} */
	while (pos + KNOT_EDNS_OPTION_HDRLEN <= rdlength) {
		uint16_t opt_len = wire_read_u16(data + pos
		                                      + sizeof(uint16_t));
		pos += KNOT_EDNS_OPTION_HDRLEN + opt_len;
	}

	/* If not at the end of the RDATA, there are either some redundant data
	 * (pos < rdlength) or the last OPTION is too long (pos > rdlength).
	 */
	return pos == rdlength;
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
static void print_section_opt(const knot_rrset_t *rr, const uint8_t rcode)
{
    uint8_t        ercode = knot_edns_get_ext_rcode(rr);
    uint16_t       ext_rcode_id = knot_edns_whole_rcode(ercode, rcode);
    const char     *ext_rcode_str = "Unused";
    lookup_table_t *ext_rcode;

    if (ercode > 0) {
        ext_rcode = lookup_by_id(knot_rcode_names, ext_rcode_id);
        if (ext_rcode != NULL) {
            ext_rcode_str = ext_rcode->name;
        } else {
            ext_rcode_str = "Unknown";
        }
    }

    printf("Version: %u; flags: %s; UDP size: %u B; ext-rcode: %s\n",
           knot_edns_get_version(rr),
           (knot_edns_do(rr) != 0) ? "do" : "",
           knot_edns_get_payload(rr),
           ext_rcode_str);

    knot_rdata_t *rdata = knot_rdataset_at(&rr->rrs, 0);
    assert(rdata != NULL);

    uint16_t data_len = knot_rdata_rdlen(rdata);
    uint8_t *data = knot_rdata_data(rdata);
    int pos = 0;

    while (pos < data_len - KNOT_EDNS_OPTION_HDRLEN) {
        uint16_t opt_code = wire_read_u16(data + pos);
        uint16_t opt_len = wire_read_u16(data + pos + 2);
        uint8_t *opt_data = data + pos + 4;

        switch (opt_code) {
        case KNOT_EDNS_OPTION_NSID:
            printf(";; NSID: ");
            short_hex_print(opt_data, opt_len);
            if (opt_len > 0) {
                printf(";;     :  ");
                txt_print(opt_data, opt_len);
            }
            break;
        case KNOT_EDNS_OPTION_CLIENT_SUBNET:
            printf(";; CLIENT-SUBNET: ");
            print_edns_client_subnet(opt_data, opt_len);
            break;
        default:
            printf(";; Option (%u): ", opt_code);
            short_hex_print(opt_data, opt_len);
        }

        pos += 4 + opt_len;
    }
}
Exemple #8
0
/*----------------------------------------------------------------------------*/
_public_
size_t knot_edns_wire_size(knot_rrset_t *opt_rr)
{
	if (opt_rr == NULL) {
		return 0;
	}

	knot_rdata_t *rdata = knot_rdataset_at(&opt_rr->rrs, 0);
	assert(rdata != NULL);

	return KNOT_EDNS_MIN_SIZE + knot_rdata_rdlen(rdata);
}
Exemple #9
0
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;
}
Exemple #10
0
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;
}
Exemple #11
0
static bool check_option(knot_rdata_t *rdata, uint16_t opt_code,
                         uint16_t opt_len, uint8_t *opt_data, char *msg,
                         int *done)
{
	assert(rdata != NULL);
	bool success = true;

	uint8_t *data = knot_rdata_data(rdata);
	uint16_t data_len = knot_rdata_rdlen(rdata);

	/* Check RDLENGTH according to given data length. */
	bool check = (data_len >= 4 + opt_len);
	ok(check, "%s: RDLENGTH (%u)", msg, data_len);
	success &= check;
	(*done)++;

	/* Find the desired option. */
	bool found = false;
	int pos = 0;
	while (pos <= data_len - 4) {
		uint16_t code = wire_read_u16(data + pos + OFFSET_OPT_CODE);
		if (code == opt_code) {
			found = true;
			break;
		}
		uint16_t len = wire_read_u16(data + pos + OFFSET_OPT_SIZE);
		pos += 4 + len;
	}

	/* Check that the option is present. */
	ok(found, "%s: find OPTION %u in OPT RR", msg, opt_code);
	success &= found;
	(*done)++;

	/* Check that the first OPTION's size si the size of the option data. */
	uint16_t opt_size = wire_read_u16(data + pos + OFFSET_OPT_SIZE);
	check = (opt_size == opt_len);
	ok(check, "%s: OPTION data size", msg);
	success &= check;
	(*done)++;

	/* Check the actual NSID data. */
	check = (memcmp(data + pos + OFFSET_OPT_DATA, opt_data, opt_len)) == 0;
	ok(check, "%s: OPTION data", msg);
	success &= check;
	(*done)++;

	return success;
}
Exemple #12
0
_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;
}
Exemple #13
0
int kr_dnskeys_trusted(const knot_pkt_t *pkt, knot_section_t section_id, const knot_rrset_t *keys,
                       const knot_rrset_t *ta, const knot_dname_t *zone_name, uint32_t timestamp,
                       bool has_nsec3)
{
	if (!pkt || !keys || !ta) {
		return kr_error(EINVAL);
	}

	/* RFC4035 5.2, bullet 1
	 * The supplied DS record has been authenticated.
	 * It has been validated or is part of a configured trust anchor.
	 */
	for (uint16_t i = 0; i < keys->rrs.rr_count; ++i) {
		/* RFC4035 5.3.1, bullet 8 */ /* ZSK */
		const knot_rdata_t *krr = knot_rdataset_at(&keys->rrs, i);
		const uint8_t *key_data = knot_rdata_data(krr);
		if (!kr_dnssec_key_zsk(key_data) || kr_dnssec_key_revoked(key_data)) {
			continue;
		}
		
		struct dseckey *key;
		if (kr_dnssec_key_from_rdata(&key, keys->owner, key_data, knot_rdata_rdlen(krr)) != 0) {
			continue;
		}
		if (kr_authenticate_referral(ta, (dnssec_key_t *) key) != 0) {
			kr_dnssec_key_free(&key);
			continue;
		}
		if (kr_rrset_validate_with_key(pkt, section_id, keys, keys, i, key, zone_name, timestamp, has_nsec3) != 0) {
			kr_dnssec_key_free(&key);
			continue;
		}
		kr_dnssec_key_free(&key);
		return kr_ok();
	}
	/* No useable key found */
	return kr_error(ENOENT);
}
Exemple #14
0
/*!
 * \brief Find OPTION with the given code in the OPT RDATA.
 *
 * \param rdata     RDATA to search in.
 * \param opt_code  Code of the OPTION to find.
 * \param[out] pos  Position of the OPTION or NULL if not found.
 */
static uint8_t *find_option(knot_rdata_t *rdata, uint16_t opt_code)
{
	assert(rdata != NULL);

	uint8_t *data = knot_rdata_data(rdata);
	uint16_t rdlength = knot_rdata_rdlen(rdata);

	uint8_t *pos = NULL;

	int i = 0;
	while (i + KNOT_EDNS_OPTION_HDRLEN <= rdlength) {
		uint16_t code = wire_read_u16(data + i);
		if (opt_code == code) {
			pos = data + i;
			break;
		}
		uint16_t opt_len = wire_read_u16(data + i
		                                      + sizeof(uint16_t));
		i += (KNOT_EDNS_OPTION_HDRLEN + opt_len);
	}

	return pos;
}
Exemple #15
0
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;
}
Exemple #16
0
int kr_rrset_validate_with_key(const knot_pkt_t *pkt, knot_section_t section_id,
                               const knot_rrset_t *covered, const knot_rrset_t *keys,
                               size_t key_pos, const struct dseckey *key,
                               const knot_dname_t *zone_name, uint32_t timestamp,
                               bool has_nsec3)
{
	struct dseckey *created_key = NULL;
	if (key == NULL) {
		const knot_rdata_t *krr = knot_rdataset_at(&keys->rrs, key_pos);
		int ret = kr_dnssec_key_from_rdata(&created_key, keys->owner,
			                       knot_rdata_data(krr), knot_rdata_rdlen(krr));
		if (ret != 0) {
			return ret;
		}
		key = created_key;
	}
	uint16_t keytag = dnssec_key_get_keytag((dnssec_key_t *)key);
	int covered_labels = knot_dname_labels(covered->owner, NULL);
	if (knot_dname_is_wildcard(covered->owner)) {
		/* The asterisk does not count, RFC4034 3.1.3, paragraph 3. */
		--covered_labels;
	}

	const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
	for (unsigned i = 0; i < sec->count; ++i) {
		/* Consider every RRSIG that matches owner and covers the class/type. */
		const knot_rrset_t *rrsig = knot_pkt_rr(sec, i);
		if (rrsig->type != KNOT_RRTYPE_RRSIG) {
			continue;
		}
		if ((covered->rclass != rrsig->rclass) || !knot_dname_is_equal(covered->owner, rrsig->owner)) {
			continue;
		}
		for (uint16_t j = 0; j < rrsig->rrs.rr_count; ++j) {
			int val_flgs = 0;
			int trim_labels = 0;
			if (knot_rrsig_type_covered(&rrsig->rrs, j) != covered->type) {
				continue;
			}
			if (validate_rrsig_rr(&val_flgs, covered_labels, rrsig, j,
			                      keys, key_pos, keytag,
			                      zone_name, timestamp) != 0) {
				continue;
			}
			if (val_flgs & FLG_WILDCARD_EXPANSION) {
				trim_labels = wildcard_radix_len_diff(covered->owner, rrsig, j);
				if (trim_labels < 0) {
					break;
				}
			}
			if (kr_check_signature(rrsig, j, (dnssec_key_t *) key, covered, trim_labels) != 0) {
				continue;
			}
			if (val_flgs & FLG_WILDCARD_EXPANSION) {
				int ret = 0;
				if (!has_nsec3) {
					ret = kr_nsec_wildcard_answer_response_check(pkt, KNOT_AUTHORITY, covered->owner);
				} else {
					ret = kr_nsec3_wildcard_answer_response_check(pkt, KNOT_AUTHORITY, covered->owner, trim_labels - 1);
				}
				if (ret != 0) {
					continue;
				}
			}
			/* Validated with current key, OK */
			kr_dnssec_key_free(&created_key);
			return kr_ok();
		}
	}
	/* No applicable key found, cannot be validated. */
	kr_dnssec_key_free(&created_key);
	return kr_error(ENOENT);
}