summaryrefslogtreecommitdiff
path: root/src/libknot/dname.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libknot/dname.h')
-rw-r--r--src/libknot/dname.h428
1 files changed, 428 insertions, 0 deletions
diff --git a/src/libknot/dname.h b/src/libknot/dname.h
new file mode 100644
index 0000000..c0e3f35
--- /dev/null
+++ b/src/libknot/dname.h
@@ -0,0 +1,428 @@
+/*!
+ * \file dname.h
+ *
+ * \author Lubos Slovak <lubos.slovak@nic.cz>
+ *
+ * \brief Domain name structure and API for manipulating it.
+ *
+ * \addtogroup libknot
+ * @{
+ */
+/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _KNOT_DNAME_H_
+#define _KNOT_DNAME_H_
+
+#include <stdint.h>
+#include <string.h>
+#include "common/ref.h"
+
+struct knot_node;
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief Structure for representing a domain name.
+ *
+ * Stores the domain name in wire format.
+ *
+ * \todo Consider restricting to FQDN only (see knot_dname_new_from_str()).
+ */
+struct knot_dname {
+ ref_t ref; /*!< Reference counting. */
+ uint8_t *name; /*!< Wire format of the domain name. */
+ /*!
+ * \brief Size of the domain name in octets.
+ * \todo Is this needed? Every dname should end with \0 or pointer.
+ */
+ unsigned int size;
+ uint8_t *labels;
+ unsigned short label_count;
+ struct knot_node *node; /*!< Zone node the domain name belongs to. */
+ unsigned int id; /*!< ID of domain name used in zone dumping. */
+};
+
+typedef struct knot_dname knot_dname_t;
+
+/*----------------------------------------------------------------------------*/
+
+/*!
+ * \brief Creates empty dname structure (no name, no owner node).
+ *
+ * \note Newly created dname is referenced, caller is responsible for releasing
+ * it after use.
+ *
+ * \return Newly allocated and initialized dname structure.
+ *
+ * \todo Possibly useless.
+ */
+knot_dname_t *knot_dname_new();
+
+/*!
+ * \brief Creates a dname structure from domain name given in presentation
+ * format.
+ *
+ * The resulting domain name is stored in wire format, but it may not end with
+ * root label (0).
+ *
+ * \note Newly created dname is referenced, caller is responsible for releasing
+ * it after use.
+ *
+ * \param name Domain name in presentation format (labels separated by dots).
+ * \param size Size of the domain name (count of characters with all dots).
+ * \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.
+ */
+knot_dname_t *knot_dname_new_from_str(const char *name, unsigned int size,
+ struct knot_node *node);
+
+/*!
+ * \brief Creates a dname structure from domain name given in wire format.
+ *
+ * \note The name is copied into the structure.
+ * \note If the given name is not a FQDN, the result will be neither.
+ * \note Newly created dname is referenced, caller is responsible for releasing
+ * it after use.
+ *
+ * \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.
+ *
+ * \todo This function does not check if the given data is in correct wire
+ * format at all. It thus creates a invalid domain name, which if passed
+ * e.g. to knot_dname_to_str() may result in crash. Decide whether it
+ * is OK to retain this and check the data in other functions before
+ * calling this one, or if it should verify the given data.
+ */
+knot_dname_t *knot_dname_new_from_wire(const uint8_t *name,
+ unsigned int size,
+ struct knot_node *node);
+
+knot_dname_t *knot_dname_parse_from_wire(const uint8_t *wire,
+ size_t *pos, size_t size,
+ struct knot_node *node);
+
+/*!
+ * \brief Initializes domain name by the name given in wire format.
+ *
+ * \note The name is copied into the structure.
+ * \note If there is any name in the structure, it will be replaced.
+ * \note If the given name is not a FQDN, the result will be neither.
+ *
+ * \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.
+ * \param target Domain name structure to initialize.
+ *
+ * \retval KNOT_EOK on success.
+ * \retval KNOT_ENOMEM if allocation of labels info failed.
+ * \retval KNOT_EBADARG if name or target is null.
+ *
+ * \todo This function does not check if the given data is in correct wire
+ * format at all. It thus creates a invalid domain name, which if passed
+ * e.g. to knot_dname_to_str() may result in crash. Decide whether it
+ * is OK to retain this and check the data in other functions before
+ * calling this one, or if it should verify the given data.
+ */
+int knot_dname_from_wire(const uint8_t *name, unsigned int size,
+ struct knot_node *node, knot_dname_t *target);
+
+/*!
+ * \brief Duplicates the given domain name.
+ *
+ * \note Copied dname referense count is reset to 1, caller is responsible
+ * for releasing it after use.
+ *
+ * \param dname Domain name to be copied.
+ *
+ * \return New domain name which is an exact copy of \a dname.
+ */
+knot_dname_t *knot_dname_deep_copy(const knot_dname_t *dname);
+
+/*!
+ * \brief Converts the given domain name to string representation.
+ *
+ * \note Allocates new memory, remember to free it.
+ *
+ * \param dname Domain name to be converted.
+ *
+ * \return 0-terminated string representing the given domain name in
+ * presentation format.
+ */
+char *knot_dname_to_str(const knot_dname_t *dname);
+
+int knot_dname_to_lower(knot_dname_t *dname);
+
+int knot_dname_to_lower_copy(const knot_dname_t *dname, char *name,
+ size_t size);
+
+/*!
+ * \brief Returns the domain name in wire format.
+ *
+ * \param dname Domain name.
+ *
+ * \return Wire format of the domain name.
+ */
+const uint8_t *knot_dname_name(const knot_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.
+ */
+unsigned int knot_dname_size(const knot_dname_t *dname);
+
+unsigned int knot_dname_id(const knot_dname_t *dname);
+
+/*!
+ * \brief Returns size of a part of domain name.
+ *
+ * \param dname Domain name.
+ * \param labels Count of labels to get the size of (counted from left).
+ *
+ * \return Size of first \a labels labels of \a dname, counted from left.
+ */
+uint8_t knot_dname_size_part(const knot_dname_t *dname, int labels);
+
+/*!
+ * \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 knot_node *knot_dname_node(const knot_dname_t *dname,
+ int check_version);
+
+struct knot_node *knot_dname_get_node(knot_dname_t *dname,
+ int check_version);
+
+void knot_dname_set_node(knot_dname_t *dname, struct knot_node *node);
+
+void knot_dname_update_node(knot_dname_t *dname);
+
+void knot_dname_set_node(knot_dname_t *dname, struct knot_node *node);
+
+/*!
+ * \brief Checks if the given domain name is a fully-qualified domain name.
+ *
+ * \param dname Domain name to check.
+ *
+ * \retval <> 0 if \a dname is a FQDN.
+ * \retval 0 otherwise.
+ */
+int knot_dname_is_fqdn(const knot_dname_t *dname);
+
+/*!
+ * \brief Creates new domain name by removing leftmost label from \a dname.
+ *
+ * \note Newly created dname reference count is set to 1, caller is responsible
+ * for releasing it after use.
+ *
+ * \param dname Domain name to remove the first label from.
+ *
+ * \return New domain name with the same labels as \a dname, except for the
+ * leftmost label, which is removed.
+ */
+knot_dname_t *knot_dname_left_chop(const knot_dname_t *dname);
+
+/*!
+ * \brief Removes leftmost label from \a dname.
+ *
+ * \param dname Domain name to remove the first label from.
+ */
+void knot_dname_left_chop_no_copy(knot_dname_t *dname);
+
+/*!
+ * \brief Checks if one domain name is a subdomain of other.
+ *
+ * \param sub Domain name to be the possible subdomain.
+ * \param domain Domain name to be the possible parent domain.
+ *
+ * \retval <> 0 if \a sub is a subdomain of \a domain.
+ * \retval 0 otherwise.
+ */
+int knot_dname_is_subdomain(const knot_dname_t *sub,
+ const knot_dname_t *domain);
+
+/*!
+ * \brief Checks if the domain name is a wildcard.
+ *
+ * \param dname Domain name to check.
+ *
+ * \retval <> 0 if \a dname is a wildcard domain name.
+ * \retval 0 otherwise.
+ */
+int knot_dname_is_wildcard(const knot_dname_t *dname);
+
+/*!
+ * \brief Returns the number of labels common for the two domain names (counted
+ * from the rightmost label.
+ *
+ * \param dname1 First domain name.
+ * \param dname2 Second domain name.
+ *
+ * \return Number of labels common for the two domain names.
+ */
+int knot_dname_matched_labels(const knot_dname_t *dname1,
+ const knot_dname_t *dname2);
+
+/*!
+ * \brief Returns the number of labels in the domain name.
+ *
+ * \param dname Domain name to get the label count of.
+ *
+ * \return Number of labels in \a dname.
+ *
+ * \todo Find out if this counts the root label also.
+ */
+int knot_dname_label_count(const knot_dname_t *dname);
+
+/*!
+ * \brief Returns the size of the requested label in the domain name.
+ *
+ * \param dname Domain name to get the label size from.
+ * \param i Index of the label (0 is the leftmost label).
+ *
+ * \return Size of \a i-th label in \a dname (counted from left).
+ */
+uint8_t knot_dname_label_size(const knot_dname_t *dname, int i);
+
+/*!
+ * \brief Replaces the suffix of given size in one domain name with other domain
+ * name.
+ *
+ * \param dname Domain name where to replace the suffix.
+ * \param size Size of the suffix to be replaced.
+ * \param suffix New suffix to be used as a replacement.
+ *
+ * \return New domain name created by replacing suffix of \a dname of size
+ * \a size with \a suffix.
+ */
+knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *dname,
+ int size,
+ const knot_dname_t *suffix);
+
+/*!
+ * \brief Destroys the given domain name.
+ *
+ * Frees also the data within the struct. This is somewhat different behaviour
+ * than that of RDATA and RRSet structures which do not deallocate their
+ * contents.
+ *
+ * Sets the given pointer to NULL.
+ *
+ * \param dname Domain name to be destroyed.
+ */
+void knot_dname_free(knot_dname_t **dname);
+
+/*!
+ * \brief Compares two domain names (case insensitive).
+ *
+ * \param d1 First domain name.
+ * \param d2 Second domain name.
+ *
+ * \retval < 0 if \a d1 goes before \a d2 in canonical order.
+ * \retval > 0 if \a d1 goes after \a d2 in canonical order.
+ * \retval 0 if the domain names are identical.
+ */
+int knot_dname_compare(const knot_dname_t *d1, const knot_dname_t *d2);
+
+/*!
+ * \brief Compares two domain names (case sensitive).
+ *
+ * \param d1 First domain name.
+ * \param d2 Second domain name.
+ *
+ * \retval < 0 if \a d1 goes before \a d2 in canonical order.
+ * \retval > 0 if \a d1 goes after \a d2 in canonical order.
+ * \retval 0 if the domain names are identical.
+ */
+int knot_dname_compare_cs(const knot_dname_t *d1, const knot_dname_t *d2);
+
+/*!
+ * \brief Concatenates two domain names.
+ *
+ * \note Member \a node is ignored, i.e. preserved.
+ *
+ * \param d1 First domain name (will be modified).
+ * \param d2 Second domain name (will not be modified).
+ *
+ * \return The concatenated domain name (i.e. modified \a d1) or NULL if
+ * the operation is not valid (e.g. \a d1 is a FQDN).
+ */
+knot_dname_t *knot_dname_cat(knot_dname_t *d1, const knot_dname_t *d2);
+
+void knot_dname_set_id(knot_dname_t *dname, unsigned int id);
+
+unsigned int knot_dname_get_id(const knot_dname_t *dname);
+
+/*!
+ * \brief Increment reference counter for dname.
+ *
+ * Function makes shallow copy (reference).
+ *
+ * \param dname Referenced dname.
+ */
+static inline void knot_dname_retain(knot_dname_t *dname) {
+ if (dname) {
+ ref_retain(&dname->ref);
+// char *name = knot_dname_to_str(dname);
+// printf("retain: %s %p %d\n", name, dname, dname->ref.count);
+// free(name);
+
+ }
+}
+
+/*#define knot_dname_retain(d) \
+ knot_dname_retain_((d));\
+ if ((d))\
+ printf("dname_retain: %s() at %s:%d, %p refcount=%zu\n",\
+ __func__, __FILE__, __LINE__, d, (d)->ref.count) */
+
+/*!
+ * \brief Decrement reference counter for dname.
+ *
+ * \param dname Referenced dname.
+ */
+static inline void knot_dname_release(knot_dname_t *dname) {
+ if (dname) {
+// char *name = knot_dname_to_str(dname);
+// printf("releasing: %p %s %d\n", dname, name, dname->ref.count - 1);
+// free(name);
+ ref_release(&dname->ref);
+ }
+}
+
+/*#define knot_dname_release(d) \
+ if ((d))\
+ printf("dname_release: %s() at %s:%d, %p refcount=%zu\n",\
+ __func__, __FILE__, __LINE__, d, (d)->ref.count-1);\
+ knot_dname_release_((d)) */
+
+#endif /* _KNOT_DNAME_H_ */
+
+/*! @} */