]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
dns_txt: Add TXT record parsing support
authorSean Bright <sean.bright@gmail.com>
Tue, 10 Mar 2020 00:07:10 +0000 (20:07 -0400)
committerGeorge Joseph <gjoseph@digium.com>
Fri, 13 Mar 2020 15:00:31 +0000 (10:00 -0500)
Change-Id: Ie0eca23b8e6f4c7d9846b6013d79099314d90ef5

include/asterisk/dns_internal.h
include/asterisk/dns_txt.h [new file with mode: 0644]
main/dns_core.c
main/dns_txt.c [new file with mode: 0644]

index 7ce0c28f1fa1fb278ce094229e84aeee8ee0c348..3d2d0df7a7c56f823dd96fd29e9b3272133a6279 100644 (file)
@@ -26,6 +26,9 @@
 #ifndef _ASTERISK_DNS_INTERNAL_H
 #define _ASTERISK_DNS_INTERNAL_H
 
+/*! \brief For AST_LIST */
+#include "asterisk/linkedlists.h"
+
 /*! \brief For AST_VECTOR */
 #include "asterisk/vector.h"
 
@@ -57,6 +60,16 @@ struct ast_dns_record {
        char data[0];
 };
 
+/*! \brief A TXT record */
+struct ast_dns_txt_record {
+       /*! \brief Generic DNS record information */
+       struct ast_dns_record generic;
+       /*! \brief The number of character strings in the TXT record */
+       size_t count;
+       /*! \brief The raw DNS record */
+       char data[0];
+};
+
 /*! \brief An SRV record */
 struct ast_dns_srv_record {
        /*! \brief Generic DNS record information */
@@ -199,6 +212,19 @@ struct ast_sched_context;
  */
 struct ast_sched_context *ast_dns_get_sched(void);
 
+/*!
+ * \brief Allocate and parse a DNS TXT record
+ * \since 16.10.0, 17.4.0
+ *
+ * \param query The DNS query
+ * \param data This specific TXT record
+ * \param size The size of the TXT record
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ */
+struct ast_dns_record *dns_txt_alloc(struct ast_dns_query *query, const char *data, const size_t size);
+
 /*!
  * \brief Allocate and parse a DNS NAPTR record
  *
diff --git a/include/asterisk/dns_txt.h b/include/asterisk/dns_txt.h
new file mode 100644 (file)
index 0000000..368a861
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2020, Sean Bright
+ *
+ * Sean Bright <sean.bright@gmail.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ * \brief DNS TXT Record Parsing API
+ * \author Sean Bright <sean.bright@gmail.com>
+ */
+
+#ifndef ASTERISK_DNS_TXT_H
+#define ASTERISK_DNS_TXT_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/*!
+ * \brief Get the number of character strings in a TXT record
+ * \since 16.10.0, 17.4.0
+ *
+ * \param record The DNS record
+ *
+ * \return the number of character strings in this TXT record
+ */
+size_t ast_dns_txt_get_count(const struct ast_dns_record *record);
+
+/*!
+ * \brief Get the character strings from this TXT record
+ * \since 16.10.0, 17.4.0
+ *
+ * \param record The DNS record
+ *
+ * \retval NULL Unable to allocate memory
+ * \return Vector of strings. Free with ast_dns_txt_free_strings
+ */
+struct ast_vector_string *ast_dns_txt_get_strings(const struct ast_dns_record *record);
+
+/*!
+ * \brief Free strings returned by ast_dns_txt_get_strings
+ * \since 16.10.0, 17.4.0
+ *
+ * \param strings The vector to free
+ */
+void ast_dns_txt_free_strings(struct ast_vector_string *strings);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* ASTERISK_DNS_TXT_H */
index f262d7deba33df85b555e6c6c1e85d3d895e3d4c..0fb0731e92a3a0fbd7dcec5f383b1f5f29424777 100644 (file)
@@ -516,8 +516,9 @@ static struct ast_dns_record *generic_record_alloc(struct ast_dns_query *query,
 typedef struct ast_dns_record *(*dns_alloc_fn)(struct ast_dns_query *query, const char *data, const size_t size);
 
 static dns_alloc_fn dns_alloc_table [] = {
+       [T_TXT]   = dns_txt_alloc,
        [T_NAPTR] = dns_naptr_alloc,
-       [T_SRV] = dns_srv_alloc,
+       [T_SRV]   = dns_srv_alloc,
 };
 
 static struct ast_dns_record *allocate_dns_record(unsigned int rr_type, struct ast_dns_query *query, const char *data, const size_t size)
diff --git a/main/dns_txt.c b/main/dns_txt.c
new file mode 100644 (file)
index 0000000..5c1c581
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2020, Sean Bright
+ *
+ * Sean Bright <sean.bright@gmail.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ * \brief DNS TXT Record Parsing API
+ * \author Sean Bright <sean.bright@gmail.com>
+ */
+
+/*** MODULEINFO
+       <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+#include <resolv.h>
+
+#include "asterisk/dns_core.h"
+#include "asterisk/dns_txt.h"
+#include "asterisk/dns_internal.h"
+#include "asterisk/utils.h"
+
+struct ast_dns_record *dns_txt_alloc(struct ast_dns_query *query, const char *data, const size_t size)
+{
+       struct ast_dns_txt_record *txt;
+       const char *end_of_record = data + size;
+       size_t count = 0;
+
+       /* Because we can't allocate additional memory, the best we can do here is just
+        * validate that this conforms to a TXT record. */
+       while (data < end_of_record) {
+               uint8_t byte_count = (uint8_t) *data;
+               count++;
+               data += byte_count + 1;
+       }
+
+       if (data != end_of_record) {
+               /* This is not a valid TXT record, so we can bail out */
+               return NULL;
+       }
+
+       txt = ast_calloc(1, sizeof(*txt) + size);
+       if (!txt) {
+               return NULL;
+       }
+
+       txt->count = count;
+       txt->generic.data_ptr = txt->data;
+
+       return (struct ast_dns_record *) txt;
+}
+
+size_t ast_dns_txt_get_count(const struct ast_dns_record *record)
+{
+       struct ast_dns_txt_record *txt = (struct ast_dns_txt_record *) record;
+       ast_assert(ast_dns_record_get_rr_type(record) == T_TXT);
+       return txt->count;
+}
+
+struct ast_vector_string *ast_dns_txt_get_strings(const struct ast_dns_record *record)
+{
+       struct ast_vector_string *strings;
+
+       const size_t size = ast_dns_record_get_data_size(record);
+       const char *data = ast_dns_record_get_data(record);
+       const char *end_of_record = data + size;
+
+       ast_assert(ast_dns_record_get_rr_type(record) == T_TXT);
+
+       strings = ast_malloc(sizeof(struct ast_vector_const_string));
+       if (!strings) {
+               return NULL;
+       }
+
+       if (AST_VECTOR_INIT(strings, ast_dns_txt_get_count(record))) {
+               ast_free(strings);
+               return NULL;
+       }
+
+       while (data < end_of_record) {
+               char *s;
+               uint8_t bytes = (uint8_t) *data;
+
+               s = ast_malloc(bytes + 1);
+               if (!s) {
+                       ast_dns_txt_free_strings(strings);
+                       return NULL;
+               }
+
+               memcpy(s, &data[1], bytes);
+               s[bytes] = 0;
+
+               /* We know the size in advance so this can't fail */
+               AST_VECTOR_APPEND(strings, s);
+
+               data += bytes + 1;
+       }
+
+       /* Sanity check */
+       if (data != end_of_record) {
+               ast_dns_txt_free_strings(strings);
+               return NULL;
+       }
+
+       return strings;
+}
+
+void ast_dns_txt_free_strings(struct ast_vector_string *strings)
+{
+       AST_VECTOR_CALLBACK_VOID(strings, ast_free);
+       AST_VECTOR_PTR_FREE(strings);
+}