Example #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;
}
Example #2
0
File: edns.c Project: idtek/knot
static bool check_header(knot_rrset_t *opt_rr, uint16_t payload, uint8_t ver,
                         uint16_t flags, uint8_t ext_rcode, char *msg,
                         int *done)
{
	assert(opt_rr != NULL);
	assert(done != NULL);
	bool check;
	bool success = true;

	/* Check values in OPT RR by hand. */
	/* CLASS == Max UDP payload */
	check = (opt_rr->rclass == payload);
	ok(check, "%s: max payload", msg);
	success &= check;
	(*done)++;

	/* The OPT RR should have exactly one RDATA. */
	check = (opt_rr->rrs.rr_count == 1);
	ok(check, "%s: RR count == 1", msg);
	success &= check;
	(*done)++;

	knot_rdata_t *rdata = knot_rdataset_at(&opt_rr->rrs, 0);
	check = (rdata != NULL);
	ok(check, "%s: RDATA exists", msg);
	success &= check;
	(*done)++;

	success &= check_ttl(rdata, ext_rcode, ver, flags, msg, done);

	return success;
}
Example #3
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;
}
Example #4
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);
}
Example #5
0
_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;
}
Example #6
0
static bool rr_exists(const knot_rrset_t *in, const knot_rrset_t *ref,
                      size_t ref_pos)
{
	knot_rdata_t *to_check = knot_rdataset_at(&ref->rrs, ref_pos);
	const bool compare_ttls = true;
	return knot_rdataset_member(&in->rrs, to_check, compare_ttls);
}
Example #7
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;
}
Example #8
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;
}
Example #9
0
_public_
void knot_rdataset_set_ttl(knot_rdataset_t *rrs, uint32_t ttl)
{
	for (uint16_t i = 0; i < rrs->rr_count; ++i) {
		knot_rdata_t *rrset_rr = knot_rdataset_at(rrs, i);
		knot_rdata_set_ttl(rrset_rr, ttl);
	}
}
Example #10
0
_public_
bool knot_rdataset_eq(const knot_rdataset_t *rrs1, const knot_rdataset_t *rrs2)
{
	if (rrs1->rr_count != rrs2->rr_count) {
		return false;
	}

	for (uint16_t i = 0; i < rrs1->rr_count; ++i) {
		const knot_rdata_t *rr1 = knot_rdataset_at(rrs1, i);
		const knot_rdata_t *rr2 = knot_rdataset_at(rrs2, i);
		if (knot_rdata_cmp(rr1, rr2) != 0) {
			return false;
		}
	}

	return true;
}
Example #11
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;
    }
}
Example #12
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);
}
Example #13
0
/*----------------------------------------------------------------------------*/
_public_
void knot_edns_set_do(knot_rrset_t *opt_rr)
{
	assert(opt_rr != NULL);

	// Read the TTL
	uint32_t ttl = knot_rrset_ttl(opt_rr);
	// Set the DO bit
	ttl |= EDNS_DO_MASK;
	// Store the TTL to the RDATA
	knot_rdata_set_ttl(knot_rdataset_at(&opt_rr->rrs, 0), ttl);
}
Example #14
0
static int find_rr_pos(const knot_rdataset_t *search_in,
                       const knot_rdata_t *rr)
{
	for (uint16_t i = 0; i < search_in->rr_count; ++i) {
		const knot_rdata_t *search_rr = knot_rdataset_at(search_in, i);
		if (knot_rdata_cmp(rr, search_rr) == 0) {
			return i;
		}
	}

	return KNOT_ENOENT;
}
Example #15
0
/*----------------------------------------------------------------------------*/
_public_
bool knot_edns_has_option(const knot_rrset_t *opt_rr, uint16_t code)
{
	assert(opt_rr != NULL);

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

	uint8_t *pos = find_option(rdata, code);

	return pos != NULL;
}
Example #16
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;
}
Example #17
0
static void set_value_to_ttl(knot_rrset_t *opt_rr, size_t offset, uint8_t value)
{
	uint32_t ttl = 0;
	uint8_t *ttl_ptr = (uint8_t *)&ttl;

	// TTL is stored in machine byte order. Convert it to wire order first.
	wire_write_u32(ttl_ptr, knot_rrset_ttl(opt_rr));
	// Set the Extended RCODE in the converted TTL
	memcpy(ttl_ptr + offset, &value, sizeof(uint8_t));
	// Convert it back to machine byte order
	uint32_t ttl_local = wire_read_u32(ttl_ptr);
	// Store the TTL to the RDATA
	knot_rdata_set_ttl(knot_rdataset_at(&opt_rr->rrs, 0), ttl_local);
}
Example #18
0
/*!
 * \brief Create and zero SIG(0) RDATA field.
 *
 * \param rrset  SIG(0) RR set.
 * \param key    Signing key.
 *
 * \return SIG(0) RDATA.
 */
static uint8_t *sig0_create_rdata(knot_rrset_t *rrset, knot_dnssec_key_t *key)
{
	assert(rrset);
	assert(key);

	size_t rdata_size = knot_rrsig_rdata_size(key);
	const uint32_t ttl = 0;
	uint8_t rdata[rdata_size];
	sig0_write_rdata(rdata, key);
	if (knot_rrset_add_rdata(rrset, rdata, rdata_size, ttl, NULL) != KNOT_EOK) {
		return NULL;
	}

	const knot_rdata_t *rr = knot_rdataset_at(&rrset->rrs, 0);
	return knot_rdata_data(rr);
}
Example #19
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;
}
Example #20
0
_public_
int knot_rdataset_merge(knot_rdataset_t *rrs1, const knot_rdataset_t *rrs2, knot_mm_t *mm)
{
	if (rrs1 == NULL || rrs2 == NULL) {
		return KNOT_EINVAL;
	}

	for (uint16_t i = 0; i < rrs2->rr_count; ++i) {
		const knot_rdata_t *rr = knot_rdataset_at(rrs2, i);
		int ret = knot_rdataset_add(rrs1, rr, mm);
		if (ret != KNOT_EOK) {
			return ret;
		}
	}

	return KNOT_EOK;
}
Example #21
0
int kr_check_signature(const knot_rrset_t *rrsigs, size_t pos,
                       const dnssec_key_t *key, const knot_rrset_t *covered,
                       int trim_labels)
{
	if (!rrsigs || !key || !dnssec_key_can_verify(key)) {
		return kr_error(EINVAL);
	}

	int ret = 0;
	dnssec_sign_ctx_t *sign_ctx = NULL;
	dnssec_binary_t signature = {0, };

	knot_rrsig_signature(&rrsigs->rrs, pos, &signature.data, &signature.size);
	if (!signature.data || !signature.size) {
		ret = kr_error(EINVAL);
		goto fail;
	}

	if (dnssec_sign_new(&sign_ctx, key) != 0) {
		ret = kr_error(ENOMEM);
		goto fail;
	}

	uint32_t orig_ttl = knot_rrsig_original_ttl(&rrsigs->rrs, pos);
	const knot_rdata_t *rr_data = knot_rdataset_at(&rrsigs->rrs, pos);
	uint8_t *rdata = knot_rdata_data(rr_data);

	if (sign_ctx_add_data(sign_ctx, rdata, covered, orig_ttl, trim_labels) != 0) {
		ret = kr_error(ENOMEM);
		goto fail;
	}

	if (dnssec_sign_verify(sign_ctx, &signature) != 0) {
		ret = kr_error(EBADMSG);
		goto fail;
	}

	ret = kr_ok();

fail:
	dnssec_sign_free(sign_ctx);
	return ret;
}
Example #22
0
static int knot_zone_diff_rdata_return_changes(const knot_rrset_t *rrset1,
                                               const knot_rrset_t *rrset2,
                                               knot_rrset_t *changes)
{
	if (rrset1 == NULL || rrset2 == NULL) {
		dbg_zonediff("zone_diff: diff_rdata: NULL arguments. (%p) (%p).\n",
		             rrset1, rrset2);
		return KNOT_EINVAL;
	}

	/*
	* Take one rdata from first list and search through the second list
	* looking for an exact match. If no match occurs, it means that this
	* particular RR has changed.
	* After the list has been traversed, we have a list of
	* changed/removed rdatas. This has awful computation time.
	*/

	/* Create fake RRSet, it will be easier to handle. */
	knot_rrset_init(changes, rrset1->owner, rrset1->type, rrset1->rclass);

	const knot_rdata_descriptor_t *desc = knot_get_rdata_descriptor(rrset1->type);
	assert(desc);

	uint16_t rr1_count = rrset1->rrs.rr_count;
	for (uint16_t i = 0; i < rr1_count; ++i) {
		if (!rr_exists(rrset2, rrset1, i)) {
			/*
			 * No such RR is present in 'rrset2'. We'll copy
			 * index 'i' into 'changes' RRSet.
			 */
			knot_rdata_t *add_rr = knot_rdataset_at(&rrset1->rrs, i);
			int ret = knot_rdataset_add(&changes->rrs, add_rr, NULL);
			if (ret != KNOT_EOK) {
				knot_rdataset_clear(&changes->rrs, NULL);
				return ret;
			}
		}
	}

	return KNOT_EOK;
}
Example #23
0
_public_
int knot_rdataset_subtract(knot_rdataset_t *from, const knot_rdataset_t *what,
			   knot_mm_t *mm)
{
	if (from == NULL || what == NULL || from->data == what->data) {
		return KNOT_EINVAL;
	}

	for (uint16_t i = 0; i < what->rr_count; ++i) {
		const knot_rdata_t *to_remove = knot_rdataset_at(what, i);
		int pos_to_remove = find_rr_pos(from, to_remove);
		if (pos_to_remove >= 0) {
			int ret = remove_rr_at(from, pos_to_remove, mm);
			if (ret != KNOT_EOK) {
				return ret;
			}
		}
	}

	return KNOT_EOK;
}
Example #24
0
_public_
int knot_rdataset_add(knot_rdataset_t *rrs, const knot_rdata_t *rr, knot_mm_t *mm)
{
	if (rrs == NULL || rr == NULL) {
		return KNOT_EINVAL;
	}

	for (uint16_t i = 0; i < rrs->rr_count; ++i) {
		const knot_rdata_t *rrset_rr = knot_rdataset_at(rrs, i);
		int cmp = knot_rdata_cmp(rrset_rr, rr);
		if (cmp == 0) {
			// Duplication - no need to add this RR
			return KNOT_EOK;
		} else if (cmp > 0) {
			// Found position to insert
			return add_rr_at(rrs, rr, i, mm);
		}
	}

	// If flow gets here, it means that we should insert at the last position
	return add_rr_at(rrs, rr, rrs->rr_count, mm);
}
Example #25
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);
}
Example #26
0
_public_
bool knot_rdataset_member(const knot_rdataset_t *rrs, const knot_rdata_t *rr,
			  bool cmp_ttl)
{
	for (uint16_t i = 0; i < rrs->rr_count; ++i) {
		const knot_rdata_t *cmp_rr = knot_rdataset_at(rrs, i);
		if (cmp_ttl) {
			if (knot_rdata_ttl(rr) != knot_rdata_ttl(cmp_rr)) {
				continue;
			}
		}
		int cmp = knot_rdata_cmp(cmp_rr, rr);
		if (cmp == 0) {
			// Match.
			return true;
		}
		if (cmp > 0) {
			// 'Greater' RR present, no need to continue.
			return false;
		}
	}
	return false;
}
Example #27
0
_public_
int knot_rdataset_intersect(const knot_rdataset_t *a, const knot_rdataset_t *b,
                       knot_rdataset_t *out, knot_mm_t *mm)
{
	if (a == NULL || b == NULL || out == NULL) {
		return KNOT_EINVAL;
	}

	knot_rdataset_init(out);
	const bool compare_ttls = false;
	for (uint16_t i = 0; i < a->rr_count; ++i) {
		const knot_rdata_t *rr = knot_rdataset_at(a, i);
		if (knot_rdataset_member(b, rr, compare_ttls)) {
			// Add RR into output intersection RRSet.
			int ret = knot_rdataset_add(out, rr, mm);
			if (ret != KNOT_EOK) {
				knot_rdataset_clear(out, mm);
				return ret;
			}
		}
	}

	return KNOT_EOK;
}
Example #28
0
_public_
uint32_t knot_rdataset_ttl(const knot_rdataset_t *rrs)
{
	return knot_rdata_ttl(knot_rdataset_at(rrs, 0));
}
Example #29
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);
}
Example #30
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;
}