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; }
/*----------------------------------------------------------------------------*/ _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); }
static bool check_ttl(knot_rdata_t *rdata, uint8_t ext_rcode, uint8_t ver, uint16_t flags, char *msg, int *done) { /* TTL should be stored in machine byte order. We need network byte order to compare its parts. */ uint8_t ttl_wire[4] = { 0, 0, 0, 0 }; wire_write_u32(ttl_wire, knot_rdata_ttl(rdata)); /* Convert Flags from EDNS parameters to wire format for comparison. */ uint8_t flags_wire[2] = { 0, 0 }; wire_write_u16(flags_wire, flags); bool success = true; /* TTL = Ext RCODE + Version + Flags */ bool check = (ttl_wire[OFFSET_ERCODE] == ext_rcode); ok(check, "%s: extended RCODE", msg); success &= check; (*done)++; check = (ttl_wire[OFFSET_VER] == ver); ok(check, "%s: version", msg); success &= check; (*done)++; check = (memcmp(flags_wire, ttl_wire + OFFSET_FLAGS, 2) == 0); ok(check, "%s: flags", msg); success &= check; (*done)++; return success; }
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; }
_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; }
_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; }
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_ uint32_t knot_rdataset_ttl(const knot_rdataset_t *rrs) { return knot_rdata_ttl(knot_rdataset_at(rrs, 0)); }