diff options
Diffstat (limited to 'usr.sbin/nsd/dname.h')
-rw-r--r-- | usr.sbin/nsd/dname.h | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/usr.sbin/nsd/dname.h b/usr.sbin/nsd/dname.h new file mode 100644 index 00000000000..b68bc0dfe40 --- /dev/null +++ b/usr.sbin/nsd/dname.h @@ -0,0 +1,377 @@ +/* + * dname.h -- Domain name handling. + * + * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. + * + */ + +#ifndef _DNAME_H_ +#define _DNAME_H_ + +#include <assert.h> +#include <stdio.h> + +#include "buffer.h" +#include "region-allocator.h" + +#if defined(NAMEDB_UPPERCASE) || defined(USE_NAMEDB_UPPERCASE) +#define DNAME_NORMALIZE toupper +#else +#define DNAME_NORMALIZE tolower +#endif + + +/* + * Domain names stored in memory add some additional information to be + * able to quickly index and compare by label. + */ +typedef struct dname dname_type; +struct dname +{ + /* + * The size (in bytes) of the domain name in wire format. + */ + uint8_t name_size; + + /* + * The number of labels in this domain name (including the + * root label). + */ + uint8_t label_count; + + /* + uint8_t label_offsets[label_count]; + uint8_t name[name_size]; + */ +}; + + +/* + * Construct a new domain name based on NAME in wire format. NAME + * cannot contain compression pointers. + * + * Pre: NAME != NULL. + */ +const dname_type *dname_make(region_type *region, const uint8_t *name, + int normalize); + +/* + * Construct a new domain name based on wire format dname stored at + * PACKET's current position. Compression pointers are followed. The + * PACKET's current position is changed to the end of the wire format + * dname or set to just after the first compression pointer. + */ +const dname_type *dname_make_from_packet(region_type *region, + buffer_type *packet, + int allow_pointers, + int normalize); + +/* + * parse wireformat from packet (following pointers) into the + * given buffer. Returns length in buffer or 0 on error. + * buffer must be MAXDOMAINLEN+1 long. + */ +int dname_make_wire_from_packet(uint8_t *buf, + buffer_type *packet, + int allow_pointers); + +/* + * Construct a new domain name based on the ASCII representation NAME. + * If ORIGIN is not NULL and NAME is not terminated by a "." the + * ORIGIN is appended to the result. NAME can contain escape + * sequences. + * + * Returns NULL on failure. Otherwise a newly allocated domain name + * is returned. + * + * Pre: name != NULL. + */ +const dname_type *dname_parse(region_type *region, const char *name); + +/* + * parse ascii string to wireformat domain name (without compression ptrs) + * returns 0 on failure, the length of the wireformat on success. + * the result is stored in the wirefmt which must be at least MAXDOMAINLEN + * in size. On failure, the wirefmt can be altered. + */ +int dname_parse_wire(uint8_t* wirefmt, const char* name); + +/* + * Return NULL if DNAME is NULL or a copy of DNAME otherwise. + */ +const dname_type *dname_copy(region_type *region, const dname_type *dname); + + +/* + * Copy the most significant LABEL_COUNT labels from dname. + */ +const dname_type *dname_partial_copy(region_type *region, + const dname_type *dname, + uint8_t label_count); + + +/* + * The origin of DNAME. + */ +const dname_type *dname_origin(region_type *region, const dname_type *dname); + +/* + * Return true if LEFT is a subdomain of RIGHT. + */ +int dname_is_subdomain(const dname_type *left, const dname_type *right); + + +/* + * Offsets into NAME for each label starting with the most + * significant label (the root label, followed by the TLD, + * etc). + */ +static inline const uint8_t * +dname_label_offsets(const dname_type *dname) +{ + return (const uint8_t *) ((const char *) dname + sizeof(dname_type)); +} + + +/* + * The actual name in wire format (a sequence of label, each + * prefixed by a length byte, terminated by a zero length + * label). + */ +static inline const uint8_t * +dname_name(const dname_type *dname) +{ + return (const uint8_t *) ((const char *) dname + + sizeof(dname_type) + + dname->label_count * sizeof(uint8_t)); +} + + +/* + * Return the label for DNAME specified by LABEL_INDEX. The first + * label (LABEL_INDEX == 0) is the root label, the next label is the + * TLD, etc. + * + * Pre: dname != NULL && label_index < dname->label_count. + */ +static inline const uint8_t * +dname_label(const dname_type *dname, uint8_t label) +{ + uint8_t label_index; + + assert(dname != NULL); + assert(label < dname->label_count); + + label_index = dname_label_offsets(dname)[label]; + assert(label_index < dname->name_size); + + return dname_name(dname) + label_index; +} + + +/* + * Compare two domain names. The comparison defines a lexographical + * ordering based on the domain name's labels, starting with the most + * significant label. + * + * Return < 0 if LEFT < RIGHT, 0 if LEFT == RIGHT, and > 0 if LEFT > + * RIGHT. The comparison is case sensitive. + * + * Pre: left != NULL && right != NULL + */ +int dname_compare(const dname_type *left, const dname_type *right); + + +/* + * Compare two labels. The comparison defines a lexographical + * ordering based on the characters in the labels. + * + * Return < 0 if LEFT < RIGHT, 0 if LEFT == RIGHT, and > 0 if LEFT > + * RIGHT. The comparison is case sensitive. + * + * Pre: left != NULL && right != NULL + * label_is_normal(left) && label_is_normal(right) + */ +int label_compare(const uint8_t *left, const uint8_t *right); + + +/* + * Returns the number of labels that match in LEFT and RIGHT, starting + * with the most significant label. Because the root label always + * matches, the result will always be >= 1. + * + * Pre: left != NULL && right != NULL + */ +uint8_t dname_label_match_count(const dname_type *left, + const dname_type *right); + + +/* + * The total size (in bytes) allocated to store DNAME. + * + * Pre: dname != NULL + */ +static inline size_t +dname_total_size(const dname_type *dname) +{ + return (sizeof(dname_type) + + ((dname->label_count + dname->name_size) + * sizeof(uint8_t))); +} + + +/* + * Is LABEL a normal LABEL (not a pointer or reserved)? + * + * Pre: label != NULL; + */ +static inline int +label_is_normal(const uint8_t *label) +{ + assert(label); + return (label[0] & 0xc0) == 0; +} + + +/* + * Is LABEL a pointer? + * + * Pre: label != NULL; + */ +static inline int +label_is_pointer(const uint8_t *label) +{ + assert(label); + return (label[0] & 0xc0) == 0xc0; +} + + +/* + * LABEL's pointer location. + * + * Pre: label != NULL && label_is_pointer(label) + */ +static inline uint16_t +label_pointer_location(const uint8_t *label) +{ + assert(label); + assert(label_is_pointer(label)); + return ((uint16_t) (label[0] & ~0xc0) << 8) | (uint16_t) label[1]; +} + + +/* + * Length of LABEL. + * + * Pre: label != NULL && label_is_normal(label) + */ +static inline uint8_t +label_length(const uint8_t *label) +{ + assert(label); + assert(label_is_normal(label)); + return label[0]; +} + + +/* + * The data of LABEL. + * + * Pre: label != NULL && label_is_normal(label) + */ +static inline const uint8_t * +label_data(const uint8_t *label) +{ + assert(label); + assert(label_is_normal(label)); + return label + 1; +} + + +/* + * Is LABEL the root label? + * + * Pre: label != NULL + */ +static inline int +label_is_root(const uint8_t *label) +{ + assert(label); + return label[0] == 0; +} + + +/* + * Is LABEL the wildcard label? + * + * Pre: label != NULL + */ +static inline int +label_is_wildcard(const uint8_t *label) +{ + assert(label); + return label[0] == 1 && label[1] == '*'; +} + + +/* + * The next label of LABEL. + * + * Pre: label != NULL + * label_is_normal(label) + * !label_is_root(label) + */ +static inline const uint8_t * +label_next(const uint8_t *label) +{ + assert(label); + assert(label_is_normal(label)); + assert(!label_is_root(label)); + return label + label_length(label) + 1; +} + + +/* + * Convert DNAME to its string representation. The result points to a + * static buffer that is overwritten the next time this function is + * invoked. + * + * If ORIGIN is provided and DNAME is a subdomain of ORIGIN the dname + * will be represented relative to ORIGIN. + * + * Pre: dname != NULL + */ +const char *dname_to_string(const dname_type *dname, + const dname_type *origin); + + +/* + * Create a dname containing the single label specified by STR + * followed by the root label. + */ +const dname_type *dname_make_from_label(region_type *region, + const uint8_t *label, + const size_t length); + + +/* + * Concatenate two dnames. + */ +const dname_type *dname_concatenate(region_type *region, + const dname_type *left, + const dname_type *right); + + +/* + * Perform DNAME substitution on a name, replace src with dest. + * Name must be a subdomain of src. The returned name is a subdomain of dest. + * Returns NULL if the result domain name is too long. + */ +const dname_type *dname_replace(region_type* region, + const dname_type* name, + const dname_type* src, + const dname_type* dest); + +#endif /* _DNAME_H_ */ |