From 2aebcef93d77244fc8a6418c3986d1bad615eff7 Mon Sep 17 00:00:00 2001 From: Lubos Slovak <lubos.slovak@nic.cz> Date: Tue, 9 Nov 2010 18:05:11 +0100 Subject: [PATCH] First RDATA API functions and their implementation - creating RDATA structure (empty, possibly with reserving space) - setting and getting particular items - setting all items (only if empty) - deallocating refs #5, #88 --- src/dnslib/rdata.c | 89 ++++++++++++++++++++++++++++++++++++ src/dnslib/rdata.h | 111 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 194 insertions(+), 6 deletions(-) diff --git a/src/dnslib/rdata.c b/src/dnslib/rdata.c index e69de29bb..85d6788bc 100644 --- a/src/dnslib/rdata.c +++ b/src/dnslib/rdata.c @@ -0,0 +1,89 @@ +#include <stdint.h> +#include <stdlib.h> +#include <assert.h> +#include <string.h> +#include "common.h" +#include "rdata.h" + +/*----------------------------------------------------------------------------*/ +/* API functions */ +/*----------------------------------------------------------------------------*/ + +dnslib_rdata_t *dnslib_rdata_new( uint count ) +{ + dnslib_rdata_t *rdata = (dnslib_rdata_t *)malloc(sizeof(dnslib_rdata_t)); + if (rdata == NULL) { + ERR_ALLOC_FAILED; + return NULL; + } + + 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; + + return rdata; +} + +/*----------------------------------------------------------------------------*/ + +int dnslib_rdata_set_item( dnslib_rdata *rdata, uint pos, + dnslib_rdata_item_t item ) +{ + if (pos >= rdata->count) { + return -1; + } + rdata->items[pos] = item; // this should copy the union; or use memcpy? + return 0; +} + +/*----------------------------------------------------------------------------*/ + +int dnslib_rdata_set_items( dnslib_rdata *rdata, + const dnslib_rdata_item_t *items, uint count ) +{ + if (count == 0) { + 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) { + return -2; + } + + memcpy(rdata->items, items, count * sizeof(dnslib_rdata_item_t)); + rdata->count = count; + + return 0; +} + +/*----------------------------------------------------------------------------*/ + +const dnslib_rdata_item_t *dnslib_rdata_get_item( dnslib_rdata_t *rdata, + uint pos ) +{ + if (pos >= rdata->count) { + return NULL; + } + else return &rdata->items[pos]; +} + +/*----------------------------------------------------------------------------*/ + +void dnslib_rdata_free( dnslib_rdata_t *rdata ) +{ + free(rdata->items); + free(rdata); +} diff --git a/src/dnslib/rdata.h b/src/dnslib/rdata.h index 86c4d92d3..d99f3b87c 100644 --- a/src/dnslib/rdata.h +++ b/src/dnslib/rdata.h @@ -5,21 +5,120 @@ #include "dname.h" #include "common.h" +/*----------------------------------------------------------------------------*/ +/*! + * \brief RDATA item structure. + * + * Each RDATA may be logically divided into items, each of possible different + * type. This structure distinguishes between general data (\a raw_data) + * represented as an array of octets, and domain name (\a dname) as domain names + * require special treatment within some RDATA (e.g. compressing in packets). + */ union dnslib_rdata_item { - uint8_t *raw_data; // will this be convenient enough? what about parsing? - dnslib_dname_t *dname; + /*! + * \brief RDATA item represented as raw array of octets. + * \note Will this be convenient enough? What about parsing? (in runtime?) + */ + uint8_t *raw_data; + dnslib_dname_t *dname; /*!< RDATA item represented as a domain name. */ }; typedef union dnslib_rdata_item dnslib_rdata_item_t; /*----------------------------------------------------------------------------*/ - +/*! + * \brief RDATA structure. + * + * 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. + * + * 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 + * RR type. + */ struct dnslib_rdata { - dnslib_rdata_item_t *items; - uint *item_lengths; - uint item_count; + dnslib_rdata_item_t *items; /*!< RDATA items comprising this RDATA. */ + uint count; /*! < Count of RDATA items in this RDATA. */ }; 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. + * + * \return Pointer to the new RDATA structure or NULL if an error occured. + */ +dnslib_rdata_t *dnslib_rdata_new( uint count ); + +/*! + * \brief Sets the RDATA item on position \a pos. + * + * \param rdata RDATA structure in which the item should be set. + * \param pos Position of the RDATA item to be set. + * \param item RDATA item value to be set. + * + * \retval 0 if successful. + * \retval < 0 on error. (-1 if the allocation was not successful). + * + * \todo Use the union or a pointer to it as parameter? IMHO there is always + * only one pointer that is copied, so it doesn't matter. + */ +int dnslib_rdata_set_item( dnslib_rdata *rdata, uint pos, + dnslib_rdata_item_t item ); + +/*! + * \brief Sets all RDATA items within the given RDATA structure. + * + * \param rdata RDATA structure to store the items in. + * \param items An array of RDATA items to be stored in this RDATA structure. + * \param count Count of RDATA items to be stored. + * + * If \a rdata has been empty so far (\a rdata->count == 0), the necessary space + * is allocated. Otherwise \a rdata->count must be equal to \a count. If it is + * not, this function does not alter the stored items and returns an error. + * + * This function copies the array of RDATA items from \a items to \a rdata. + * + * \retval 0 if successful. + * \retval 1 if the \a count is 0, i.e. nothing was done. + * \retval -1 if allocation of necessary space was not successful. + * \retval -2 if \a rdata->count != \a count. + */ +int dnslib_rdata_set_items( dnslib_rdata *rdata, + const dnslib_rdata_item_t *items, uint count ); + +/*! + * \brief Returns the RDATA item on position \a pos. + * + * \param rdata RDATA structure to get the item from. + * \param pos Position of the item to retrieve. + * + * \return The RDATA item on position \a pos, or NULL if such position does not + * exist within the given RDATA structure. + * + * \note Although returning union would be OK (no overhead), we need to be able + * to distinguish errors (in this case by returning NULL). + */ +const dnslib_rdata_item_t *dnslib_rdata_get_item( dnslib_rdata_t *rdata, + uint pos ); + +/*! + * \brief Destroys the RDATA structure. + * + * \param rdata RDATA structure to be destroyed. + * + * Contents of RDATA items are not deallocated, as it is not clear whether the + * particular item is a domain name (which cannot be deallocated here) or raw + * data (which could have been). + */ +void dnslib_rdata_free( dnslib_rdata_t *rdata ); + #endif /* _CUTEDNS_RDATA_H */ -- GitLab