Commit fc26cda0 authored by Daniel Salzman's avatar Daniel Salzman

libknot/rdata: make it public structure

parent e4416793
......@@ -359,7 +359,6 @@ src/libknot/packet/rrset-wire.c
src/libknot/packet/rrset-wire.h
src/libknot/packet/wire.c
src/libknot/packet/wire.h
src/libknot/rdata.c
src/libknot/rdata.h
src/libknot/rdataset.c
src/libknot/rdataset.h
......
......@@ -160,7 +160,6 @@ libknot_la_SOURCES = \
libknot/packet/pkt.c \
libknot/packet/rrset-wire.c \
libknot/packet/wire.c \
libknot/rdata.c \
libknot/rdataset.c \
libknot/rrset-dump.c \
libknot/rrset.c \
......
......@@ -43,7 +43,7 @@ static bool pkt_contains(const knot_pkt_t *packet, const knot_rrset_t *rrset)
for (int i = 0; i < packet->rrset_count; ++i) {
const uint16_t type = packet->rr[i].type;
const uint8_t *data = packet->rr[i].rrs.data;
const knot_rdata_t *data = packet->rr[i].rrs.data;
if (type == rrset->type && data == rrset->rrs.data) {
return true;
}
......
......@@ -689,7 +689,7 @@ static int parse_rdata(const uint8_t *pkt_wire, size_t *pos, size_t pkt_size,
return buffer_size;
}
if (buffer_size > MAX_RDLENGTH) {
if (buffer_size > KNOT_RDATA_MAXLEN) {
/* DNAME compression caused RDATA overflow. */
return KNOT_EMALF;
}
......
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "libknot/attribute.h"
#include "libknot/rdata.h"
#include "contrib/macros.h"
#ifndef STRICT_ALIGNMENT
#pragma pack(push, 1)
#endif
/*!< \brief Helper structure - offsets in RR array. */
struct rr_offsets {
uint16_t size;
uint8_t rdata[];
};
#ifndef STRICT_ALIGNMENT
#pragma pack(pop)
#endif
_public_
void knot_rdata_init(knot_rdata_t *rdata, uint16_t rdlen, const uint8_t *data)
{
knot_rdata_set_rdlen(rdata, rdlen);
memcpy(knot_rdata_data(rdata), data, rdlen);
}
_public_
uint16_t knot_rdata_rdlen(const knot_rdata_t *rr)
{
return ((struct rr_offsets *)rr)->size;
}
_public_
void knot_rdata_set_rdlen(knot_rdata_t *rr, uint16_t size)
{
((struct rr_offsets *)rr)->size = size;
}
_public_
uint8_t *knot_rdata_data(const knot_rdata_t *rr)
{
return ((struct rr_offsets *)rr)->rdata;
}
_public_
size_t knot_rdata_array_size(uint16_t size)
{
return size + sizeof(struct rr_offsets);
}
_public_
int knot_rdata_cmp(const knot_rdata_t *rr1, const knot_rdata_t *rr2)
{
assert(rr1 && rr2);
const uint8_t *r1 = knot_rdata_data(rr1);
const uint8_t *r2 = knot_rdata_data(rr2);
uint16_t l1 = knot_rdata_rdlen(rr1);
uint16_t l2 = knot_rdata_rdlen(rr2);
int cmp = memcmp(r1, r2, MIN(l1, l2));
if (cmp == 0 && l1 != l2) {
cmp = l1 < l2 ? -1 : 1;
}
return cmp;
}
......@@ -16,7 +16,7 @@
/*!
* \file
*
* \brief API for manipulating RRs.
* \brief API for manipulating rdata.
*
* \addtogroup libknot
* @{
......@@ -24,69 +24,107 @@
#pragma once
#include <stdlib.h>
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
/* ---------------------------- Single RR ----------------------------------- */
/*!< \brief Maximum rdata data size. */
#define MAX_RDLENGTH 65535
/*!< \brief Maximum rdata length. */
#define KNOT_RDATA_MAXLEN 65535
/*!
* \brief knot_rdata_t Array holding single RR payload, i.e. TTL, RDLENGTH and RDATA.
* \brief Structure holding single rdata payload.
*/
typedef uint8_t knot_rdata_t;
/* ------------------------------- Init ------------------------------------- */
typedef struct {
uint16_t len;
uint8_t data[];
} knot_rdata_t;
/*!
* \brief Inits knot_rdata_t structure - the structure has to be created using
* knot_rdata_array_size.
* \brief Inits rdata structure.
*
* \param buf Rdata structure to be initialized. At least knot_rdata_size bytes
* must fit into it!
* \param len Rdata length.
* \param data Rdata itself.
*/
void knot_rdata_init(knot_rdata_t *rdata, uint16_t rdlen, const uint8_t *data);
/* ------------------------- RR getters/setters ----------------------------- */
inline static void knot_rdata_init(knot_rdata_t *rdata, uint16_t len, const uint8_t *data)
{
assert(rdata);
rdata->len = len;
memcpy(rdata->data, data, len);
}
/*!
* \brief Returns RDATA size of single RR.
*
* \param rr RR whose size we want.
* \return RR size.
* \return RR size.
*/
uint16_t knot_rdata_rdlen(const knot_rdata_t *rr);
inline static uint16_t knot_rdata_rdlen(const knot_rdata_t *rr)
{
assert(rr);
return rr->len;
}
/*!
* \brief Sets size for given RR.
* \param rr RR whose size we want to set.
* \param size Size to be set.
*
* \param rr RR whose size we want to set.
* \param len Size to be set.
*/
void knot_rdata_set_rdlen(knot_rdata_t *rr, uint16_t size);
inline static void knot_rdata_set_rdlen(knot_rdata_t *rr, uint16_t len)
{
assert(rr);
rr->len = len;
}
/*!
* \brief Returns pointer to RR data.
*
* \param rr RR whose data we want.
* \return RR data pointer.
*/
uint8_t *knot_rdata_data(const knot_rdata_t *rr);
/* ----------------------------- RR misc ------------------------------------ */
inline static uint8_t *knot_rdata_data(const knot_rdata_t *rr)
{
assert(rr);
return (uint8_t *)rr->data;
}
/*!
* \brief Returns actual size of RR structure for given RDATA size.
* \param size RDATA size.
* \brief Returns actual size of the rdata structure for given rdata length.
*
* \param len Rdata length.
*
* \return Actual structure size.
*/
size_t knot_rdata_array_size(uint16_t size);
inline static size_t knot_rdata_size(uint16_t len)
{
return sizeof(uint16_t) + len + (len & 1);
}
/*!
* \brief Canonical comparison of two RRs. Both RRs *must* exist.
* TTLs are *not* compared.
* \param rr1 First RR to compare.
* \param rr2 Second RR to compare.
* \retval 0 if rr1 == rr2.
* \retval < 0 if rr1 < rr2.
* \retval > 0 if rr1 > rr2.
* \brief Canonical comparison of two rdata structures.
*
* \param rdata1 First rdata to compare.
* \param rdata2 Second rdata to compare.
*
* \retval = 0 if rdata1 == rdata2.
* \retval < 0 if rdata1 < rdata2.
* \retval > 0 if rdata1 > rdata2.
*/
int knot_rdata_cmp(const knot_rdata_t *rr1, const knot_rdata_t *rr2);
inline static int knot_rdata_cmp(const knot_rdata_t *rdata1, const knot_rdata_t *rdata2)
{
assert(rdata1);
assert(rdata2);
size_t common_len = (rdata1->len <= rdata2->len) ? rdata1->len : rdata2->len;
int cmp = memcmp(rdata1->data, rdata2->data, common_len);
if (cmp == 0 && rdata1->len != rdata2->len) {
cmp = rdata1->len < rdata2->len ? -1 : 1;
}
return cmp;
}
/*! @} */
......@@ -25,19 +25,18 @@
#include "contrib/macros.h"
#include "contrib/mempattern.h"
static knot_rdata_t *rr_seek(knot_rdata_t *d, size_t pos)
static knot_rdata_t *rr_seek(knot_rdata_t *rr, size_t pos)
{
if (d == NULL) {
if (rr == NULL) {
return NULL;
}
size_t offset = 0;
uint8_t *raw = (uint8_t *)rr;
for (size_t i = 0; i < pos; i++) {
knot_rdata_t *rr = d + offset;
offset += knot_rdata_array_size(knot_rdata_rdlen(rr));
raw += knot_rdata_size(knot_rdata_rdlen((knot_rdata_t *)raw));
}
return d + offset;
return (knot_rdata_t *)raw;
}
static int find_rr_pos(const knot_rdataset_t *search_in,
......@@ -66,7 +65,7 @@ static int add_rr_at(knot_rdataset_t *rrs, const knot_rdata_t *rr, size_t pos,
// Realloc data.
void *tmp = mm_realloc(mm, rrs->data,
total_size + knot_rdata_array_size(size),
total_size + knot_rdata_size(size),
total_size);
if (tmp) {
rrs->data = tmp;
......@@ -83,14 +82,16 @@ static int add_rr_at(knot_rdataset_t *rrs, const knot_rdata_t *rr, size_t pos,
}
// 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);
knot_rdata_t *last_rr = knot_rdataset_at(rrs, rrs->rr_count - 1);
assert(old_rr);
assert(last_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);
uint8_t *dst = (uint8_t *)old_rr + knot_rdata_size(size);
size_t len = ((uint8_t *)last_rr + knot_rdata_size(knot_rdata_rdlen(last_rr))) - (uint8_t *)old_rr;
memmove(dst, old_rr, len);
// Set new RR
knot_rdata_init(old_rr, size, rdata);
......@@ -113,16 +114,15 @@ static int remove_rr_at(knot_rdataset_t *rrs, size_t pos, knot_mm_t *mm)
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);
uint8_t *old_threshold = (uint8_t *)old_rr + knot_rdata_size(old_size);
uint8_t *last_threshold = (uint8_t *)last_rr + knot_rdata_size(knot_rdata_rdlen(last_rr));
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 - knot_rdata_size(old_size),
total_size);
if (tmp == NULL) {
return KNOT_ENOMEM;
......@@ -188,12 +188,12 @@ knot_rdata_t *knot_rdataset_at(const knot_rdataset_t *rrs, size_t pos)
_public_
size_t knot_rdataset_size(const knot_rdataset_t *rrs)
{
if (rrs == NULL) {
if (rrs == NULL || rrs->rr_count == 0) {
return 0;
}
const knot_rdata_t *rr_end = rr_seek(rrs->data, rrs->rr_count);
return rr_end - rrs->data;
return (uint8_t *)rr_end - (uint8_t *)rrs->data;
}
_public_
......@@ -229,7 +229,7 @@ int knot_rdataset_gather(knot_rdataset_t *dst, knot_rdata_t **src, uint16_t coun
size_t size = 0;
for (int i = 0; i < count; ++i) {
size += knot_rdata_array_size(knot_rdata_rdlen(src[i]));
size += knot_rdata_size(knot_rdata_rdlen(src[i]));
}
knot_rdata_t *data = mm_alloc(mm, size);
......@@ -242,7 +242,7 @@ int knot_rdataset_gather(knot_rdataset_t *dst, knot_rdata_t **src, uint16_t coun
dst->data = data;
for (int i = 0; i < count; ++i) {
size_t len = knot_rdata_array_size(knot_rdata_rdlen(src[i]));
size_t len = knot_rdata_size(knot_rdata_rdlen(src[i]));
memcpy(data, src[i], len);
data += len;
}
......@@ -253,19 +253,19 @@ int knot_rdataset_gather(knot_rdataset_t *dst, knot_rdata_t **src, uint16_t coun
_public_
int knot_rdataset_reserve(knot_rdataset_t *rrs, size_t size, knot_mm_t *mm)
{
if (rrs == NULL || size > MAX_RDLENGTH || rrs->rr_count == UINT16_MAX) {
if (rrs == NULL || size > KNOT_RDATA_MAXLEN || rrs->rr_count == UINT16_MAX) {
return KNOT_EINVAL;
}
size_t total_size = knot_rdataset_size(rrs);
size_t new_size = total_size + knot_rdata_array_size(size);
size_t new_size = total_size + knot_rdata_size(size);
uint8_t *tmp = mm_realloc(mm, rrs->data, new_size, total_size);
if (tmp == NULL) {
return KNOT_ENOMEM;
}
rrs->data = tmp;
rrs->data = (knot_rdata_t *)tmp;
rrs->rr_count++;
// We have to initialise the 'size' field in the reserved space.
......@@ -424,12 +424,13 @@ int knot_rdataset_sort_at(knot_rdataset_t *rrs, size_t pos, knot_mm_t *mm)
const uint16_t size = knot_rdata_rdlen(rr);
const uint8_t *rdata = knot_rdata_data(rr);
knot_rdata_t tmp_rr[knot_rdata_array_size(size)];
uint8_t buf[knot_rdata_size(size)];
knot_rdata_t *tmp_rr = (knot_rdata_t *)buf;
knot_rdata_init(tmp_rr, size, rdata);
// 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));
uint8_t *earlier_rr_moved = (uint8_t *)earlier_rr + knot_rdata_size(size);
size_t last_rr_size = knot_rdata_size(knot_rdata_rdlen(last_rr));
memmove(earlier_rr_moved, earlier_rr, (last_rr + last_rr_size) - earlier_rr);
// Set new RR
......
......@@ -111,17 +111,18 @@ void knot_rrset_clear(knot_rrset_t *rrset, knot_mm_t *mm)
}
_public_
int knot_rrset_add_rdata(knot_rrset_t *rrset, const uint8_t *rdata,
const uint16_t size, knot_mm_t *mm)
int knot_rrset_add_rdata(knot_rrset_t *rrset, const uint8_t *data, uint16_t len,
knot_mm_t *mm)
{
if (rrset == NULL || (rdata == NULL && size > 0)) {
if (rrset == NULL || (data == NULL && len > 0)) {
return KNOT_EINVAL;
}
knot_rdata_t rr[knot_rdata_array_size(size)];
knot_rdata_init(rr, size, rdata);
uint8_t buf[knot_rdata_size(len)];
knot_rdata_t *rdata = (knot_rdata_t *)buf;
knot_rdata_init(rdata, len, data);
return knot_rdataset_add(&rrset->rrs, rr, mm);
return knot_rdataset_add(&rrset->rrs, rdata, mm);
}
_public_
......
......@@ -129,14 +129,14 @@ void knot_rrset_clear(knot_rrset_t *rrset, knot_mm_t *mm);
* \brief Adds the given RDATA to the RRSet.
*
* \param rrset RRSet to add the RDATA to.
* \param rdata RDATA to add to the RRSet.
* \param size Size of RDATA.
* \param data RDATA to add to the RRSet.
* \param len Length of RDATA.
* \param mm Memory context.
*
* \return KNOT_E*
*/
int knot_rrset_add_rdata(knot_rrset_t *rrset, const uint8_t *rdata,
const uint16_t size, knot_mm_t *mm);
int knot_rrset_add_rdata(knot_rrset_t *rrset, const uint8_t *data, uint16_t len,
knot_mm_t *mm);
/* ------------------ Equality / emptines bool checks ----------------------- */
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -102,8 +102,8 @@ static void rrset_memsize(zone_estim_t *est, const zs_scanner_t *scanner)
}
assert(dummy_node);
// Add RDATA + size + TTL
size_t rdlen = knot_rdata_array_size(scanner->r_data_length);
// Add RDATA + size
size_t rdlen = knot_rdata_size(scanner->r_data_length);
est->rdata_size += add_overhead(rdlen);
est->record_count++;
......
......@@ -14,26 +14,27 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdbool.h>
#include <tap/basic.h>
#include "libknot/rdata.h"
#include "libknot/rdata.c"
int main(int argc, char *argv[])
{
plan_lazy();
// Test array size
size_t array_size = knot_rdata_array_size(16);
ok(array_size == sizeof(struct rr_offsets) + 16, "rdata: array size.");
ok(knot_rdata_size(1) == 2 + 1 + 1, "rdata: array size odd.");
ok(knot_rdata_size(2) == 2 + 2, "rdata: array size even.");
// Test init
knot_rdata_t rdata[array_size];
uint8_t payload[16] = "abcdefghijklmnop";
knot_rdata_init(rdata, 16, payload);
const bool set_ok = knot_rdata_rdlen(rdata) == 16 &&
memcmp(knot_rdata_data(rdata), payload, 16) == 0;
const size_t data_size = 16;
uint8_t buf1[knot_rdata_size(data_size)];
knot_rdata_t *rdata = (knot_rdata_t *)buf1;
uint8_t payload[] = "abcdefghijklmnop";
knot_rdata_init(rdata, data_size, payload);
const bool set_ok = knot_rdata_rdlen(rdata) == data_size &&
memcmp(knot_rdata_data(rdata), payload, data_size) == 0;
ok(set_ok, "rdata: init.");
// Test setters
......@@ -41,20 +42,21 @@ int main(int argc, char *argv[])
ok(knot_rdata_rdlen(rdata) == 1, "rdata: set RDLEN.");
// Test compare
knot_rdata_set_rdlen(rdata, 16);
knot_rdata_set_rdlen(rdata, data_size);
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");
uint8_t buf2[knot_rdata_size(data_size)];
knot_rdata_t *greater = (knot_rdata_t *)buf2;
knot_rdata_init(greater, data_size, (uint8_t *)"qrstuvwxyz123456");
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);
memcpy(knot_rdata_data(greater), knot_rdata_data(lower), data_size);
assert(knot_rdata_cmp(lower, greater) == 0);
knot_rdata_set_rdlen(lower, 15);
knot_rdata_set_rdlen(lower, data_size - 1);
ok(knot_rdata_cmp(lower, greater) < 0, "rdata: cmp lower size.");
ok(knot_rdata_cmp(greater, lower) > 0, "rdata: cmp greater size.");
......
......@@ -37,7 +37,8 @@ int main(int argc, char *argv[])
ok(rdataset.data == NULL && rdataset.rr_count == 0, "rdataset: init.");
// Test rdata addition
knot_rdata_t rdata_gt[knot_rdata_array_size(4)];
uint8_t buf_gt[knot_rdata_size(4)];
knot_rdata_t *rdata_gt = (knot_rdata_t *)buf_gt;
knot_rdata_init(rdata_gt, 4, (uint8_t *)"wxyz");
int ret = knot_rdataset_add(NULL, NULL, NULL);
......@@ -47,7 +48,8 @@ int main(int argc, char *argv[])
knot_rdata_cmp(rdata_gt, rdataset.data) == 0;
ok(add_ok, "rdataset: add.");
knot_rdata_t rdata_lo[knot_rdata_array_size(4)];
uint8_t buf_lo[knot_rdata_size(4)];
knot_rdata_t *rdata_lo = (knot_rdata_t *)buf_lo;
knot_rdata_init(rdata_lo, 4, (uint8_t *)"abcd");
ret = knot_rdataset_add(&rdataset, rdata_lo, NULL);
add_ok = ret == KNOT_EOK && rdataset.rr_count == 2 &&
......@@ -59,7 +61,7 @@ int main(int argc, char *argv[])
knot_rdata_cmp(knot_rdataset_at(&rdataset, 1), rdata_gt) == 0,
"rdataset: at.");
ok(knot_rdataset_size(&rdataset) == knot_rdata_array_size(4) * 2,
ok(knot_rdataset_size(&rdataset) == knot_rdata_size(4) * 2,
"rdataset: size.");
// Test copy
......@@ -84,7 +86,8 @@ int main(int argc, char *argv[])
ok(!knot_rdataset_eq(&rdataset, &copy), "rdataset: not equal - count");
// Test member
knot_rdata_t not_a_member[knot_rdata_array_size(1)];
uint8_t buf_not[knot_rdata_size(1)];
knot_rdata_t *not_a_member = (knot_rdata_t *)buf_not;
knot_rdata_init(not_a_member, 1, (uint8_t *)"?");
ok(knot_rdataset_member(&rdataset, rdata_gt), "rdataset: is member.");
ok(!knot_rdataset_member(&rdataset, not_a_member), "rdataset: is not member.");
......@@ -188,7 +191,7 @@ int main(int argc, char *argv[])
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));
bool reserve_ok = ret == KNOT_EOK && new_rrs_size == (old_rrs_size + knot_rdata_size(rr_size));
ok(reserve_ok, "rdataset: reserve normal");
RDATASET_INIT_WITH(copy, rdata_lo);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment