From 76c3923a9f832dcd0a1952633c2a5a6eecd4646d Mon Sep 17 00:00:00 2001 From: Lubos Slovak <lubos.slovak@nic.cz> Date: Wed, 4 May 2011 14:50:14 +0200 Subject: [PATCH] Dname parsing from wire format implemented. - Added functions for checking and getting dname pointer. refs #816 @0:45 --- src/dnslib/dname.c | 71 ++++++++++++++++++++++++++++++++++++++++++++-- src/dnslib/wire.h | 15 ++++++++++ 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/src/dnslib/dname.c b/src/dnslib/dname.c index 622633e2fd..8dcb9c31ba 100644 --- a/src/dnslib/dname.c +++ b/src/dnslib/dname.c @@ -12,6 +12,7 @@ #include "dnslib/tolower.h" #include "dnslib/debug.h" #include "dnslib/utils.h" +#include "dnslib/wire.h" /* * Memory cache. @@ -432,10 +433,74 @@ dnslib_dname_t *dnslib_dname_new_from_wire(const uint8_t *name, uint size, dnslib_dname_t *dnslib_dname_parse_from_wire(const uint8_t *wire, size_t *pos, size_t size, - struct dnslib_node *node) + dnslib_node_t *node) { - /*! @todo Implement! */ - return NULL; + uint8_t name[DNSLIB_MAX_DNAME_LENGTH]; + uint8_t labels[DNSLIB_MAX_DNAME_LABELS]; + + short l = 0; + size_t i = 0, p = *pos; + int pointer_used = 0; + + while (p < size && wire[p] != 0) { + labels[l] = i; + + if (dnslib_wire_is_pointer(wire + p)) { + // pointer. + p = dnslib_wire_get_pointer(wire + p); + *pos += 2; + pointer_used = 1; + if (p >= size) { + return NULL; + } + } else { + // label; first byte is label length + uint8_t length = *(wire + p); + memcpy(name + i, wire + p, length + 1); + p += length + 1; + i += length + 1; + if (!pointer_used) { + *pos += length + 1; + } + ++l; + } + } + if (p >= size) { + return NULL; + } + + name[i] = 0; + + dnslib_dname_t *dname = dnslib_dname_alloc(); + + if (dname == NULL) { + ERR_ALLOC_FAILED; + return NULL; + } + + dname->name = (uint8_t *)malloc((i + 1) * sizeof(uint8_t)); + if (dname->name == NULL) { + ERR_ALLOC_FAILED; + dnslib_dname_free(&dname); + return NULL; + } + + memcpy(dname->name, name, i + 1); + dname->size = i + 1; + + dname->labels = (uint8_t *)malloc(l * sizeof(uint8_t)); + if (dname->labels == NULL) { + ERR_ALLOC_FAILED; + dnslib_dname_free(&dname); + return NULL; + } + memcpy(dname->labels, labels, l); + + dname->label_count = l - 1; + + dname->node = node; + + return dname; } /*----------------------------------------------------------------------------*/ diff --git a/src/dnslib/wire.h b/src/dnslib/wire.h index 6affd7c352..3e0eff04bd 100644 --- a/src/dnslib/wire.h +++ b/src/dnslib/wire.h @@ -890,6 +890,21 @@ static inline void dnslib_wire_put_pointer(uint8_t *pos, size_t ptr) pos[0] |= DNSLIB_WIRE_PTR; } +static inline int dnslib_wire_is_pointer(const uint8_t *pos) +{ + return ((pos[0] & DNSLIB_WIRE_PTR) != 0); +} + +static inline size_t dnslib_wire_get_pointer(const uint8_t *pos) +{ + uint16_t p = 0; + memcpy(&p, pos, 2); + p &= ~DNSLIB_WIRE_PTR; + + uint16_t p2 = dnslib_wire_read_u16(&p); + return p2; +} + #endif /* _KNOT_DNSLIB_WIRE_H_ */ /*! @} */ -- GitLab