_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; }
static int pack_entry(MDB_val *data, struct entry *entry) { char *stream = data->mv_data; char *bptr = stream; pack_bin(&stream, &entry->data.type, sizeof(entry->data.type)); knot_rdataset_t *rrs = &entry->data.rrs; pack_bin(&stream, &rrs->rr_count, sizeof(rrs->rr_count)); pack_bin(&stream, rrs->data, knot_rdataset_size(rrs)); pack_str(&stream, entry->threat_code); pack_str(&stream, entry->syslog_ip); data->mv_size = (stream - bptr); return KNOT_EOK; }
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; }
_public_ int knot_rdataset_copy(knot_rdataset_t *dst, const knot_rdataset_t *src, knot_mm_t *mm) { if (dst == NULL || src == NULL) { return KNOT_EINVAL; } dst->rr_count = src->rr_count; size_t src_size = knot_rdataset_size(src); dst->data = mm_alloc(mm, src_size); if (dst->data == NULL) { return KNOT_ENOMEM; } memcpy(dst->data, src->data, src_size); return KNOT_EOK; }
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; }
static int rosedb_list(struct cache *cache, MDB_txn *txn, int argc, char *argv[]) { MDB_cursor *cursor = cursor_acquire(txn, cache->dbi); MDB_val key, data; char dname_str[KNOT_DNAME_MAXLEN] = {'\0'}; char type_str[16] = { '\0' }; int ret = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); while (ret == 0) { struct entry entry; unpack_entry(&data, &entry); knot_dname_to_str(dname_str, key.mv_data, sizeof(dname_str)); knot_rrtype_to_string(entry.data.type, type_str, sizeof(type_str)); printf("%s\t%s RDATA=%zuB\t%s\t%s\n", dname_str, type_str, knot_rdataset_size(&entry.data.rrs), entry.threat_code, entry.syslog_ip); ret = mdb_cursor_get(cursor, &key, &data, MDB_NEXT); } cursor_release(cursor); return KNOT_EOK; }
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(©, &rdataset, NULL); const bool copy_ok = ret == KNOT_EOK && copy.rr_count == rdataset.rr_count && knot_rdataset_size(©) == 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, ©), "rdataset: equal"); // Test clear knot_rdataset_clear(©, NULL); ok(copy.rr_count == 0 && copy.data == NULL, "rdataset: clear."); // Test not equal (different count) ok(!knot_rdataset_eq(&rdataset, ©), "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(©, &rdataset, NULL); assert(ret == KNOT_EOK); ret = knot_rdataset_subtract(©, &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(©, 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, ©); ok(sort_ok, "rdataset: sort reserved space"); knot_rdataset_clear(©, NULL); knot_rdataset_clear(&rdataset, NULL); knot_rdataset_clear(&rdataset_lo, NULL); knot_rdataset_clear(&rdataset_gt, NULL); return EXIT_SUCCESS; }