Skip to content
Snippets Groups Projects
Commit 56b2003e authored by Lubos Slovak's avatar Lubos Slovak
Browse files

Changes to RDATA.

RDATA items changed to be more space efficient. Distinguishes
  several content types and stores the rest as binary array with
  its length stored in th first byte.

Changed RDATA constructor to not allocate space for items.

Functions for comparing RDATAs:
  dnslib_rdata_compare() - just a first draft though.
  dnslib_rdata_compare_binary() - compares two binary RDATA items
    (needs testing)

refs #119
parent b4063358
Branches
Tags
No related merge requests found
......@@ -4,12 +4,14 @@
#include <string.h>
#include "common.h"
#include "rdata.h"
#include "descriptor.h"
#include "dname.h"
/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
dnslib_rdata_t *dnslib_rdata_new( uint count )
dnslib_rdata_t *dnslib_rdata_new()
{
dnslib_rdata_t *rdata = (dnslib_rdata_t *)malloc(sizeof(dnslib_rdata_t));
if (rdata == NULL) {
......@@ -18,15 +20,7 @@ dnslib_rdata_t *dnslib_rdata_new( uint count )
}
rdata->items = NULL;
if (count > 0 && (rdata->items = (dnslib_rdata_item_t *)calloc(
count, sizeof(dnslib_rdata_item_t))) == NULL) {
ERR_ALLOC_FAILED;
free(rdata);
return NULL;
}
rdata->count = count;
rdata->count = 0;
return rdata;
}
......@@ -52,14 +46,14 @@ int dnslib_rdata_set_items( dnslib_rdata_t *rdata,
return 1;
}
if (rdata->count == 0) { // empty so far, allocate new space
assert(rdata->items == NULL);
if ((rdata->items = (dnslib_rdata_item_t *)malloc(
count * sizeof(dnslib_rdata_item_t))) == NULL) {
ERR_ALLOC_FAILED;
return -1;
}
} else if (rdata->count != count) {
if (rdata->items != NULL) { // not empty
return -1;
}
assert(rdata->count == 0);
if ((rdata->items = (dnslib_rdata_item_t *)malloc(
count * sizeof(dnslib_rdata_item_t))) == NULL) {
ERR_ALLOC_FAILED;
return -2;
}
......@@ -92,3 +86,105 @@ void dnslib_rdata_free( dnslib_rdata_t **rdata )
free(*rdata);
*rdata = NULL;
}
/*----------------------------------------------------------------------------*/
static int dnslib_rdata_compare_binary( const uint8_t *d1, const uint8_t *d2,
int count1, int count2 )
{
int i1 = 0, i2 = 0;
// length stored in the first octet
if (count1 < 0) {
// take count from the first byte
count1 = (int)d1[0];
// and start from the second byte
i1 = 1;
}
if (count2 < 0) { // dtto
count2 = (int)d2[0];
i2 = 1;
}
while (i1 < count1 && i2 < count2 && d1[i1] == d2[i2]) {
++i1;
++i2;
}
if (i1 == count1 && i2 == count2) {
return 0;
}
if (i1 == count1 && i2 < count2) {
return -1;
} else if (i2 == count2 && i1 < count1) {
return 1;
} else {
assert(i1 < count1 && i2 < count2);
return (d1[i1] < d2[i2]) ? -1 : 1;
}
}
/*----------------------------------------------------------------------------*/
int dnslib_rdata_compare( const dnslib_rdata_t *r1, const dnslib_rdata_t *r2,
const uint8_t *format )
{
uint count = (r1->count < r2->count) ? r1->count : r2->count;
int cmp = 0;
for (int i = 0; i < count; ++i) {
dnslib_rdata_item_t *item1 = &r2->items[i];
dnslib_rdata_item_t *item2 = &r2->items[i];
switch (format[i]) {
case DNSLIB_RDATA_WF_COMPRESSED_DNAME:
case DNSLIB_RDATA_WF_UNCOMPRESSED_DNAME:
case DNSLIB_RDATA_WF_LITERAL_DNAME:
// maybe also compare with dnslib_rdata_compare_binary()
cmp = dnslib_dname_compare(item1->dname, item2->dname);
break;
case DNSLIB_RDATA_WF_BYTE:
cmp = (item1->int8 == item2->int8) ? 0 : (
(r1->items[i].int8 < item2->int8) ? -1 : 1);
break;
case DNSLIB_RDATA_WF_SHORT:
cmp = (item1->int16 == item2->int16) ? 0 : (
(item1->int16 < item2->int16) ? -1 : 1);
break;
case DNSLIB_RDATA_WF_LONG:
cmp = (item1->int32 == item2->int32) ? 0 : (
(item1->int32 < item2->int32) ? -1 : 1);
break;
case DNSLIB_RDATA_WF_A:
cmp = dnslib_rdata_compare_binary(item1->a, item2->a, 4, 4);
break;
case DNSLIB_RDATA_WF_AAAA:
cmp = dnslib_rdata_compare_binary(item1->raw_data, item2->raw_data,
16, 16);
break;
case DNSLIB_RDATA_WF_TEXT:
case DNSLIB_RDATA_WF_BINARYWITHLENGTH:
cmp = dnslib_rdata_compare_binary(&item1->raw_data[1],
&item2->raw_data[1], (int)item1->raw_data[0],
(int)item2->raw_data[0]);
break;
case DNSLIB_RDATA_WF_BINARY:
case DNSLIB_RDATA_WF_APL: // saved as binary
case DNSLIB_RDATA_WF_IPSECGATEWAY: // saved as binary
cmp = dnslib_rdata_compare_binary(item1->a, item2->a, -1, -1);
break;
default:
assert(0);
}
if (cmp != 0) {
return cmp;
}
}
assert(cmp == 0);
return 0;
}
......@@ -26,12 +26,19 @@
* require special treatment within some RDATA (e.g. compressing in packets).
*/
union dnslib_rdata_item {
dnslib_dname_t *dname; /*!< RDATA item represented as a domain name. */
uint8_t int8; /*!< 8bit unsigned integer */
uint16_t int16; /*!< 16bit unsigned integer */
uint32_t int32; /*!< 32bit unsigned integer */
uint8_t a[4]; /*!< A address - four 8bit integers */
/*!
* \brief RDATA item represented as raw array of octets.
* \note Will this be convenient enough? What about parsing? (in runtime?)
*
* In most cases the first octet will be the length of the array. The only
* now known exception will be when storing AAAA address which has known
* length (sixteen 8bit integers), so there is no need to store the lenght.
*/
uint8_t *raw_data;
dnslib_dname_t *dname; /*!< RDATA item represented as a domain name. */
};
typedef union dnslib_rdata_item dnslib_rdata_item_t;
......@@ -43,11 +50,19 @@ typedef union dnslib_rdata_item dnslib_rdata_item_t;
* Each RDATA may be logically divided into items, each of possible different
* type (see dnslib_rdata_item). This structure stores an array of such items.
* It is not dynamic, so any RDATA structure may hold either 0 or one specified
* number of items which cannot be changed later.
* number of items which cannot be changed later. However, the number of items
* may be different for each RDATA structure. The number of items should be
* given by descriptors for each RR type. Some types may have variable number
* of items. In such cases, the last item in the array will be set tu NULL
* to distinguish the actual count of items.
*
* \todo Find out whether NULL is appropriate value. If it is a possible
* value for some of the items, we must find some other way to deal with
* this.
*
* This structure does not hold information about the RDATA items, such as
* what type is which item or how long are they. This information should be
* stored elsewhere (probably globally) as it is RR-specific and given for each
* stored elsewhere (in descriptors) as it is RR-specific and given for each
* RR type.
*/
struct dnslib_rdata {
......@@ -60,15 +75,11 @@ typedef struct dnslib_rdata dnslib_rdata_t;
/*----------------------------------------------------------------------------*/
/*!
* \brief Creates an empty RDATA structure and possibly reserves space for data.
*
* \param count Number of RDATA items to be later stored in this structure.
*
* If \a count > 0, all RDATA items are initialized to 0.
* \brief Creates an empty RDATA structure.
*
* \return Pointer to the new RDATA structure or NULL if an error occured.
*/
dnslib_rdata_t *dnslib_rdata_new( uint count );
dnslib_rdata_t *dnslib_rdata_new();
/*!
* \brief Sets the RDATA item on position \a pos.
......@@ -136,6 +147,12 @@ const dnslib_rdata_item_t *dnslib_rdata_get_item( const dnslib_rdata_t *rdata,
*/
void dnslib_rdata_free( dnslib_rdata_t **rdata );
/*!
*
*/
int dnslib_rdata_compare( const dnslib_rdata_t *r1, const dnslib_rdata_t *r2,
const uint8_t *format );
#endif /* _CUTEDNS_RDATA_H */
/*! @} */
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