From cfe80a2c4f8fb21f2af011a15b4b1923643be2b1 Mon Sep 17 00:00:00 2001 From: Lubos Slovak <lubos.slovak@nic.cz> Date: Fri, 5 Nov 2010 16:54:40 +0100 Subject: [PATCH] Fixed dname API, added 3 functions, fixed impl. dname and node were referencing each other. Used forward-declaration of node in dname. Added API getter functions (with implementation): - dnslib_dname_name() - dnslib_dname_size() - dnslib_dname_node() Fixed dname implementation: - str_to_wire() was replacing chars by label lengths - new_from_str() bad assert - new_from_wire() was not allocating space for the name - to_str() was de facto copying the wire format Added some debug output to dname refs #5, #88 --- src/dnslib/dname.c | 109 ++++++++++++++++++++++++++++++++++++++------- src/dnslib/dname.h | 45 ++++++++++++++++--- 2 files changed, 131 insertions(+), 23 deletions(-) diff --git a/src/dnslib/dname.c b/src/dnslib/dname.c index 3eab23b3e5..5fcdc87ec0 100644 --- a/src/dnslib/dname.c +++ b/src/dnslib/dname.c @@ -1,4 +1,7 @@ #include <stdint.h> +#include <stdlib.h> +#include <assert.h> +#include <string.h> #include "common.h" #include "consts.h" #include "dname.h" @@ -6,48 +9,84 @@ /*----------------------------------------------------------------------------*/ /* Non-API functions */ /*----------------------------------------------------------------------------*/ +/*! + * \brief Returns the size of the wire format of domain name which has + * \a str_size characters in presentation format. + */ +static inline uint dnslib_dname_wire_size( uint str_size ) +{ + return str_size + 1; +} +/*----------------------------------------------------------------------------*/ /*! + * \brief Converts domain name from string representation to wire format. + * + * \param name Domain name in string representation (presentation format). + * \param size Size of the given domain name in characters (not counting the + * terminating 0 character. + * \param wire [in/out] Pointer to position where the wire format of the domain + * name will be stored. + * + * This function also allocates the space for the wire format. + * + * \return Size of the wire format of the domain name in octets. If 0, no + * space has been allocated. + * * \todo handle \X and \DDD (RFC 1035 5.1) or it can be handled by the parser? */ -int dnslib_dname_str_to_wire( const char *name, uint size, uint8_t **wire ) +static uint dnslib_dname_str_to_wire( const char *name, uint size, + uint8_t **wire ) { if (size > DNSLIB_MAX_DNAME_LENGTH) { return 0; } + uint wire_size = dnslib_dname_wire_size(size); + // signed / unsigned issues?? - *wire = (uint8_t *)malloc((size + 1) * sizeof(uint8_t)); + *wire = (uint8_t *)malloc(wire_size * sizeof(uint8_t)); if (*wire == NULL) { return 0; } + debug_dnslib_dname("Allocated space for wire format of dname: %p\n", + *wire); + const uint8_t *ch = (const uint8_t *)name; uint8_t *label_start = *wire; - uint8_t *w = *wire; + uint8_t *w = *wire + 1; uint8_t label_length = 0; - while (ch - name < size) { - assert(w - *wire < size); - assert(w - *wire == ch - name); + while (ch - (const uint8_t *)name < size) { + assert(w - *wire < wire_size); + assert(w - *wire - 1 == ch - (const uint8_t *)name); if (*ch == '.' ) { + debug_dnslib_dname("Position %u (%p): label length: %u\n", + label_start - *wire, label_start, label_length); *label_start = label_length; label_start = w; + label_length = 0; } else { + debug_dnslib_dname("Position %u (%p): character: %c\n", + w - *wire, w, *ch); *w = *ch; + ++label_length; } ++w; ++ch; - assert(ch >= name); + assert(ch >= (const uint8_t *)name); } // put 0 for root label regardless whether the name ended with . + --w; + debug_dnslib_dname("Position %u (%p): character: (null)\n", w - *wire, w); *w = 0; //memcpy(*wire, name, size); - return size; + return wire_size; } /*----------------------------------------------------------------------------*/ @@ -57,7 +96,7 @@ int dnslib_dname_str_to_wire( const char *name, uint size, uint8_t **wire ) dnslib_dname_t *dnslib_dname_new() { dnslib_dname_t *dname = (dnslib_dname_t *)malloc(sizeof(dnslib_dname_t)); - if (name == NULL) { + if (dname == NULL) { ERR_ALLOC_FAILED; return NULL; } @@ -72,7 +111,7 @@ dnslib_dname_t *dnslib_dname_new() /*----------------------------------------------------------------------------*/ dnslib_dname_t *dnslib_dname_new_from_str( char *name, uint size, - dnslib_node_t *node ) + struct dnslib_node *node ) { if (name == NULL || size == 0) { return NULL; @@ -89,6 +128,8 @@ dnslib_dname_t *dnslib_dname_new_from_str( char *name, uint size, log_warning("Could not parse domain name from string: '%.*s'\n", size, name); } + assert(dname->name != NULL); + dname->node = node; return dname; @@ -97,14 +138,26 @@ dnslib_dname_t *dnslib_dname_new_from_str( char *name, uint size, /*----------------------------------------------------------------------------*/ dnslib_dname_t *dnslib_dname_new_from_wire( uint8_t *name, uint size, - dnslib_node_t *node ) + struct dnslib_node *node ) { + if (name == NULL && size != 0) { + printf("No name given!\n"); + return NULL; + } + dnslib_dname_t *dname = (dnslib_dname_t *)malloc(sizeof(dnslib_dname_t)); - if (name == NULL) { + if (dname == NULL) { ERR_ALLOC_FAILED; return NULL; } + dname->name = (uint8_t *)malloc(size * sizeof(uint8_t)); + if (dname->name == NULL) { + ERR_ALLOC_FAILED; + free(dname); + return NULL; + } + memcpy(dname->name, name, size); dname->size = size; dname->node = node; @@ -114,7 +167,7 @@ dnslib_dname_t *dnslib_dname_new_from_wire( uint8_t *name, uint size, /*----------------------------------------------------------------------------*/ -char *dnslib_dname_to_str( dnslib_dname_t *dname ) +char *dnslib_dname_to_str( const dnslib_dname_t *dname ) { char *name = (char *)malloc(dname->size * sizeof(char)); @@ -122,22 +175,46 @@ char *dnslib_dname_to_str( dnslib_dname_t *dname ) char *ch = name; while (*w != 0) { - // skip label length uint8_t *next = w + *w + 1; + // skip label length + ++w; while (w != next) { *(ch++) = *(w++); } + // insert . at the end of label + *(ch++) = '.'; } *ch = 0; - assert(ch - name == dname->size); + assert(ch - name == dname->size - 1); return name; } /*----------------------------------------------------------------------------*/ -void dnslib_dname_free( dnslib_dname *dname ) +const uint8_t *dnslib_dname_name( const dnslib_dname_t *dname ) +{ + return dname->name; +} + +/*----------------------------------------------------------------------------*/ + +uint dnslib_dname_size( const dnslib_dname_t *dname ) +{ + return dname->size; +} + +/*----------------------------------------------------------------------------*/ + +const struct dnslib_node *dnslib_dname_node( const dnslib_dname_t *dname ) +{ + return dname->node; +} + +/*----------------------------------------------------------------------------*/ + +void dnslib_dname_free( dnslib_dname_t *dname ) { free(dname->name); free(dname); diff --git a/src/dnslib/dname.h b/src/dnslib/dname.h index 0902dc766b..6081f4f36f 100644 --- a/src/dnslib/dname.h +++ b/src/dnslib/dname.h @@ -3,7 +3,8 @@ #include <stdint.h> #include "common.h" -#include "node.h" + +struct dnslib_node; /*----------------------------------------------------------------------------*/ /*! @@ -20,10 +21,10 @@ struct dnslib_dname { * \todo Is this needed? Every dname should end with \0 or pointer. */ uint size; - dnslib_node_t *node; /*!< Zone node the domain name belongs to. */ + struct dnslib_node *node; /*!< Zone node the domain name belongs to. */ }; -typedef struct dname dnslib_dname_t; +typedef struct dnslib_dname dnslib_dname_t; /*----------------------------------------------------------------------------*/ @@ -53,13 +54,15 @@ dnslib_dname_t *dnslib_dname_new(); * \todo Check if the FQDN issue is OK. */ dnslib_dname_t *dnslib_dname_new_from_str( char *name, uint size, - dnslib_node_t *node ); + struct dnslib_node *node ); /*! * \brief Creates a dname structure from domain name given in wire format. * * \param name Domain name in wire format. * \param size Size of the domain name in octets. + * \param node Zone node the domain name belongs to. Set to NULL if not + * applicable. * * \return Newly allocated and initialized dname structure representing the * given domain name. @@ -69,7 +72,8 @@ dnslib_dname_t *dnslib_dname_new_from_str( char *name, uint size, * does not correspond to the behaviour of dnslib_dname_new_from_str(). * \todo Address the FQDN issue. */ -dnslib_dname_t *dnslib_dname_new_from_wire( uint8_t *name, uint size ); +dnslib_dname_t *dnslib_dname_new_from_wire( uint8_t *name, uint size, + struct dnslib_node *node ); /*! * \brief Converts the given domain name to string representation. @@ -80,7 +84,34 @@ dnslib_dname_t *dnslib_dname_new_from_wire( uint8_t *name, uint size ); * presentation format. * \note Allocates new memory, remember to free it. */ -char *dnslib_dname_to_str( dnslib_dname_t *dname ); +char *dnslib_dname_to_str( const dnslib_dname_t *dname ); + +/*! + * \brief Returns the domain name in wire format. + * + * \param dname Domain name. + * + * \return Wire format of the domain name. + */ +const uint8_t *dnslib_dname_name( const dnslib_dname_t *dname ); + +/*! + * \brief Returns size of the given domain name. + * + * \param dname Domain name to get the size of. + * + * \return Size of the domain name in wire format in octets. + */ +uint dnslib_dname_size( const dnslib_dname_t *dname ); + +/*! + * \brief Returns the zone node the domain name belongs to. + * + * \param dname Domain name to get the zone node of. + * + * \return Zone node the domain name belongs to or NULL if none. + */ +const struct dnslib_node *dnslib_dname_node( const dnslib_dname_t *dname ); /*! * \brief Destroys the given domain name. @@ -89,6 +120,6 @@ char *dnslib_dname_to_str( dnslib_dname_t *dname ); * * \note Frees also the data within the struct. */ -void dnslib_dname_free( dnslib_dname *dname ); +void dnslib_dname_free( dnslib_dname_t *dname ); #endif /* _CUTEDNS_DNAME_H */ -- GitLab