summaryrefslogtreecommitdiff
path: root/usr.sbin/nsd/dname.h
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/nsd/dname.h')
-rw-r--r--usr.sbin/nsd/dname.h377
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_ */