-/*\r
- * Asterisk -- An open source telephony toolkit.\r
- *\r
- * Copyright (C) 2015, Digium, Inc.\r
- *\r
- * Ashley Sanders <asanders@digium.com>\r
- *\r
- * See http://www.asterisk.org for more information about\r
- * the Asterisk project. Please do not directly contact\r
- * any of the maintainers of this project for assistance;\r
- * the project provides a web site, mailing lists and IRC\r
- * channels for your use.\r
- *\r
- * This program is free software, distributed under the terms of\r
- * the GNU General Public License Version 2. See the LICENSE file\r
- * at the top of the source tree.\r
- */\r
-\r
-/*! \file\r
- *\r
- * \brief The default DNS resolver for Asterisk.\r
- *\r
- * \arg See also \ref res_resolver_unbound\r
- *\r
- * \author Ashley Sanders <asanders@digium.com>\r
- */\r
-\r
-#include "asterisk.h"\r
-\r
-ASTERISK_REGISTER_FILE()\r
-\r
-#include "asterisk/_private.h"\r
-#include "asterisk/astobj2.h"\r
-#include "asterisk/dns.h"\r
-#include "asterisk/dns_core.h"\r
-#include "asterisk/dns_resolver.h"\r
-#include "asterisk/linkedlists.h"\r
-#include "asterisk/taskprocessor.h"\r
-\r
-/*! \brief The consideration priority for this resolver implementation. */\r
-#define DNS_SYSTEM_RESOLVER_PRIORITY INT_MAX\r
-\r
-/*! \brief Resolver return code upon success. */\r
-#define DNS_SYSTEM_RESOLVER_SUCCESS 0\r
-\r
-/*! \brief Resolver return code upon failure. */\r
-#define DNS_SYSTEM_RESOLVER_FAILURE -1\r
-\r
-\r
-static int dns_system_resolver_add_record(void *context, unsigned char *record, int record_len, int ttl);\r
-static int dns_system_resolver_cancel(struct ast_dns_query *query);\r
-static void dns_system_resolver_destroy(void);\r
-static int dns_system_resolver_process_query(void *data);\r
-static int dns_system_resolver_resolve(struct ast_dns_query *query);\r
-static int dns_system_resolver_set_response(void *context, unsigned char *dns_response, int dns_response_len, int rcode);\r
-\r
-\r
-/*! \brief The task processor to use for making DNS searches asynchronous. */\r
-static struct ast_taskprocessor *dns_system_resolver_tp;\r
-\r
-/*! \brief The base definition for the dns_system_resolver */\r
-struct ast_dns_resolver dns_system_resolver_base = {\r
- .name = "system",\r
- .priority = DNS_SYSTEM_RESOLVER_PRIORITY,\r
- .resolve = dns_system_resolver_resolve,\r
- .cancel = dns_system_resolver_cancel,\r
-};\r
-\r
-/*!\r
- * \brief Callback to handle processing resource records.\r
- *\r
- * \details Adds an individual resource record discovered with ast_search_dns_ex to the\r
- * ast_dns_query currently being resolved.\r
- *\r
- * \internal\r
- *\r
- * \param context A void pointer to the ast_dns_query being processed.\r
- * \param record An individual resource record discovered during the DNS search.\r
- * \param record_len The length of the resource record.\r
- * \param ttl The resource record's expiration time limit (time to live).\r
- *\r
- * \retval 0 on success\r
- * \retval -1 on failure\r
- */\r
-static int dns_system_resolver_add_record(void *context, unsigned char *record, int record_len, int ttl)\r
-{\r
- struct ast_dns_query *query = context;\r
-\r
- /* Add the record to the query.*/\r
- return ast_dns_resolver_add_record(query,\r
- ast_dns_query_get_rr_type(query),\r
- ast_dns_query_get_rr_class(query),\r
- ttl,\r
- (const char*) record,\r
- record_len);\r
-}\r
-\r
-/*!\r
- * \brief Cancels processing resolution for a given query.\r
- *\r
- * \note The system API calls block so there is no way to cancel them. Therefore, this function always\r
- * returns failure when invoked.\r
- *\r
- * \internal\r
- *\r
- * \param query The ast_dns_query to cancel.\r
- *\r
- * \retval 0 on success\r
- * \retval -1 on failure\r
- */\r
-static int dns_system_resolver_cancel(struct ast_dns_query *query)\r
-{\r
- return DNS_SYSTEM_RESOLVER_FAILURE;\r
-}\r
-\r
-/*!\r
- * \brief Destructor.\r
- *\r
- * \internal\r
- */\r
-static void dns_system_resolver_destroy(void)\r
-{\r
- /* Unreference the task processor */\r
- dns_system_resolver_tp = ast_taskprocessor_unreference(dns_system_resolver_tp);\r
-\r
- /* Unregister the base resolver */\r
- ast_dns_resolver_unregister(&dns_system_resolver_base);\r
-}\r
-\r
-/*!\r
- * \brief Callback to handle processing the query from the ast_taskprocessor instance.\r
- *\r
- * \internal\r
- *\r
- * \param data A void pointer to the ast_dns_query being processed.\r
- *\r
- * \retval -1 on search failure\r
- * \retval 0 on no records found\r
- * \retval 1 on success\r
- */\r
-static int dns_system_resolver_process_query(void *data)\r
-{\r
- struct ast_dns_query *query = data;\r
-\r
- /* Perform the DNS search */\r
- enum ast_dns_search_result res = ast_search_dns_ex(query,\r
- ast_dns_query_get_name(query),\r
- ast_dns_query_get_rr_class(query),\r
- ast_dns_query_get_rr_type(query),\r
- dns_system_resolver_set_response,\r
- dns_system_resolver_add_record);\r
-\r
- /* Handle the possible return values from the DNS search */\r
- if (res == AST_DNS_SEARCH_FAILURE) {\r
- ast_log(LOG_ERROR, "DNS search failed for query: '%s'\n",\r
- ast_dns_query_get_name(query));\r
- } else if (res == AST_DNS_SEARCH_NO_RECORDS) {\r
- ast_log(LOG_WARNING, "DNS search failed to yield any results for query: '%s'\n",\r
- ast_dns_query_get_name(query));\r
- }\r
-\r
- /* Mark the query as complete */\r
- ast_dns_resolver_completed(query);\r
-\r
- /* Reduce the reference count on the query object */\r
- ao2_ref(query, -1);\r
-\r
- return res;\r
-}\r
-\r
-/*!\r
- * \brief Resolves a DNS query.\r
- *\r
- * \internal\r
- *\r
- * \param query The ast_dns_query to resolve.\r
- *\r
- * \retval 0 on successful load of query handler to the ast_taskprocessor instance\r
- * \retval -1 on failure to load the query handler to the ast_taskprocessor instance\r
- */\r
-static int dns_system_resolver_resolve(struct ast_dns_query *query)\r
-{\r
- /* Add query processing handler to the task processor */\r
- int res = ast_taskprocessor_push(dns_system_resolver_tp,\r
- dns_system_resolver_process_query,\r
- ao2_bump(query));\r
-\r
- /* The query processing handler was not added to the task processor */\r
- if (res < 0) {\r
- ast_log(LOG_ERROR, "Failed to perform async DNS resolution of '%s'\n",\r
- ast_dns_query_get_name(query));\r
- ao2_ref(query, -1);\r
- }\r
-\r
- /* Return the result of adding the query processing handler to the task processor */\r
- return res;\r
-}\r
-\r
-/*!\r
- * \brief Callback to handle initializing the results field.\r
- *\r
- * \internal\r
- *\r
- * \param dns_response The full DNS response.\r
- * \param dns_response The length of the full DNS response.\r
- * \param rcode The DNS response code.\r
- *\r
- * \retval 0 on success\r
- * \retval -1 on failure\r
- */\r
-static int dns_system_resolver_set_response(void *context, unsigned char *dns_response, int dns_response_len, int rcode)\r
-{\r
- struct ast_dns_query *query = context;\r
- int res;\r
-\r
- /* Instantiate the query's result field (if necessary). */\r
- if (!ast_dns_query_get_result(query)) {\r
- res = ast_dns_resolver_set_result(query,\r
- 0,\r
- 0,\r
- rcode,\r
- ast_dns_query_get_name(query),\r
- (const char*) dns_response,\r
- dns_response_len);\r
-\r
- if (res) {\r
- /* There was a problem instantiating the results field. */\r
- ast_log(LOG_ERROR, "Could not instantiate the results field for query: '%s'\n",\r
- ast_dns_query_get_name(query));\r
- }\r
- } else {\r
- res = DNS_SYSTEM_RESOLVER_SUCCESS;\r
- }\r
-\r
- return res;\r
-}\r
-\r
-/*!\r
- * \brief Initializes the resolver.\r
- *\r
- * \retval 0 on success\r
- * \retval -1 on failure\r
- */\r
-int ast_dns_system_resolver_init(void)\r
-{\r
- /* Register the base resolver */\r
- int res = ast_dns_resolver_register(&dns_system_resolver_base);\r
-\r
- if (res) {\r
- return DNS_SYSTEM_RESOLVER_FAILURE;\r
- }\r
-\r
- /* Instantiate the task processor */\r
- dns_system_resolver_tp = ast_taskprocessor_get("dns_system_resolver_tp",\r
- TPS_REF_DEFAULT);\r
-\r
- /* Return error if the task processor failed to instantiate */\r
- if (!dns_system_resolver_tp) {\r
- dns_system_resolver_destroy();\r
- return DNS_SYSTEM_RESOLVER_FAILURE;\r
- }\r
-\r
- /* Register the cleanup function */\r
- ast_register_cleanup(dns_system_resolver_destroy);\r
-\r
- return DNS_SYSTEM_RESOLVER_SUCCESS;\r
-}\r
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2015, Digium, Inc.
+ *
+ * Ashley Sanders <asanders@digium.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 The default DNS resolver for Asterisk.
+ *
+ * \arg See also \ref res_resolver_unbound
+ *
+ * \author Ashley Sanders <asanders@digium.com>
+ */
+
+#include "asterisk.h"
+
+ASTERISK_REGISTER_FILE()
+
+#include "asterisk/_private.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/dns.h"
+#include "asterisk/dns_core.h"
+#include "asterisk/dns_resolver.h"
+#include "asterisk/linkedlists.h"
+#include "asterisk/taskprocessor.h"
+#include "asterisk/utils.h"
+
+/*! \brief The consideration priority for this resolver implementation. */
+#define DNS_SYSTEM_RESOLVER_PRIORITY INT_MAX
+
+/*! \brief Resolver return code upon success. */
+#define DNS_SYSTEM_RESOLVER_SUCCESS 0
+
+/*! \brief Resolver return code upon failure. */
+#define DNS_SYSTEM_RESOLVER_FAILURE -1
+
+
+static int dns_system_resolver_add_record(void *context, unsigned char *record, int record_len, int ttl);
+static int dns_system_resolver_cancel(struct ast_dns_query *query);
+static void dns_system_resolver_destroy(void);
+static int dns_system_resolver_process_query(void *data);
+static int dns_system_resolver_resolve(struct ast_dns_query *query);
+static int dns_system_resolver_set_response(void *context, unsigned char *dns_response, int dns_response_len, int rcode);
+
+
+/*! \brief The task processor to use for making DNS searches asynchronous. */
+static struct ast_taskprocessor *dns_system_resolver_tp;
+
+/*! \brief The base definition for the dns_system_resolver */
+struct ast_dns_resolver dns_system_resolver_base = {
+ .name = "system",
+ .priority = DNS_SYSTEM_RESOLVER_PRIORITY,
+ .resolve = dns_system_resolver_resolve,
+ .cancel = dns_system_resolver_cancel,
+};
+
+/*!
+ * \brief Callback to handle processing resource records.
+ *
+ * \details Adds an individual resource record discovered with ast_search_dns_ex to the
+ * ast_dns_query currently being resolved.
+ *
+ * \internal
+ *
+ * \param context A void pointer to the ast_dns_query being processed.
+ * \param record An individual resource record discovered during the DNS search.
+ * \param record_len The length of the resource record.
+ * \param ttl The resource record's expiration time limit (time to live).
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
+ */
+static int dns_system_resolver_add_record(void *context, unsigned char *record, int record_len, int ttl)
+{
+ struct ast_dns_query *query = context;
+
+ /* Add the record to the query.*/
+ return ast_dns_resolver_add_record(query,
+ ast_dns_query_get_rr_type(query),
+ ast_dns_query_get_rr_class(query),
+ ttl,
+ (const char*) record,
+ record_len);
+}
+
+/*!
+ * \brief Cancels processing resolution for a given query.
+ *
+ * \note The system API calls block so there is no way to cancel them. Therefore, this function always
+ * returns failure when invoked.
+ *
+ * \internal
+ *
+ * \param query The ast_dns_query to cancel.
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
+ */
+static int dns_system_resolver_cancel(struct ast_dns_query *query)
+{
+ return DNS_SYSTEM_RESOLVER_FAILURE;
+}
+
+/*!
+ * \brief Destructor.
+ *
+ * \internal
+ */
+static void dns_system_resolver_destroy(void)
+{
+ /* Unreference the task processor */
+ dns_system_resolver_tp = ast_taskprocessor_unreference(dns_system_resolver_tp);
+
+ /* Unregister the base resolver */
+ ast_dns_resolver_unregister(&dns_system_resolver_base);
+}
+
+/*!
+ * \brief Callback to handle processing the query from the ast_taskprocessor instance.
+ *
+ * \internal
+ *
+ * \param data A void pointer to the ast_dns_query being processed.
+ *
+ * \retval -1 on search failure
+ * \retval 0 on no records found
+ * \retval 1 on success
+ */
+static int dns_system_resolver_process_query(void *data)
+{
+ struct ast_dns_query *query = data;
+
+ /* Perform the DNS search */
+ enum ast_dns_search_result res = ast_search_dns_ex(query,
+ ast_dns_query_get_name(query),
+ ast_dns_query_get_rr_class(query),
+ ast_dns_query_get_rr_type(query),
+ dns_system_resolver_set_response,
+ dns_system_resolver_add_record);
+
+ /* Handle the possible return values from the DNS search */
+ if (res == AST_DNS_SEARCH_FAILURE) {
+ ast_debug(1, "DNS search failed for query: '%s'\n",
+ ast_dns_query_get_name(query));
+ } else if (res == AST_DNS_SEARCH_NO_RECORDS) {
+ ast_debug(1, "DNS search failed to yield any results for query: '%s'\n",
+ ast_dns_query_get_name(query));
+ }
+
+ /* Mark the query as complete */
+ ast_dns_resolver_completed(query);
+
+ /* Reduce the reference count on the query object */
+ ao2_ref(query, -1);
+
+ return res;
+}
+
+/*!
+ * \brief Resolves a DNS query.
+ *
+ * \internal
+ *
+ * \param query The ast_dns_query to resolve.
+ *
+ * \retval 0 on successful load of query handler to the ast_taskprocessor instance
+ * \retval -1 on failure to load the query handler to the ast_taskprocessor instance
+ */
+static int dns_system_resolver_resolve(struct ast_dns_query *query)
+{
+ /* Add query processing handler to the task processor */
+ int res = ast_taskprocessor_push(dns_system_resolver_tp,
+ dns_system_resolver_process_query,
+ ao2_bump(query));
+
+ /* The query processing handler was not added to the task processor */
+ if (res < 0) {
+ ast_log(LOG_ERROR, "Failed to perform async DNS resolution of '%s'\n",
+ ast_dns_query_get_name(query));
+ ao2_ref(query, -1);
+ }
+
+ /* Return the result of adding the query processing handler to the task processor */
+ return res;
+}
+
+/*!
+ * \brief Callback to handle initializing the results field.
+ *
+ * \internal
+ *
+ * \param dns_response The full DNS response.
+ * \param dns_response The length of the full DNS response.
+ * \param rcode The DNS response code.
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
+ */
+static int dns_system_resolver_set_response(void *context, unsigned char *dns_response, int dns_response_len, int rcode)
+{
+ struct ast_dns_query *query = context;
+ int res;
+
+ /* Instantiate the query's result field (if necessary). */
+ if (!ast_dns_query_get_result(query)) {
+ res = ast_dns_resolver_set_result(query,
+ 0,
+ 0,
+ rcode,
+ ast_dns_query_get_name(query),
+ (const char*) dns_response,
+ dns_response_len);
+
+ if (res) {
+ /* There was a problem instantiating the results field. */
+ ast_log(LOG_ERROR, "Could not instantiate the results field for query: '%s'\n",
+ ast_dns_query_get_name(query));
+ }
+ } else {
+ res = DNS_SYSTEM_RESOLVER_SUCCESS;
+ }
+
+ return res;
+}
+
+/*!
+ * \brief Initializes the resolver.
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
+ */
+int ast_dns_system_resolver_init(void)
+{
+ /* Register the base resolver */
+ int res = ast_dns_resolver_register(&dns_system_resolver_base);
+
+ if (res) {
+ return DNS_SYSTEM_RESOLVER_FAILURE;
+ }
+
+ /* Instantiate the task processor */
+ dns_system_resolver_tp = ast_taskprocessor_get("dns_system_resolver_tp",
+ TPS_REF_DEFAULT);
+
+ /* Return error if the task processor failed to instantiate */
+ if (!dns_system_resolver_tp) {
+ dns_system_resolver_destroy();
+ return DNS_SYSTEM_RESOLVER_FAILURE;
+ }
+
+ /* Register the cleanup function */
+ ast_register_cleanup(dns_system_resolver_destroy);
+
+ return DNS_SYSTEM_RESOLVER_SUCCESS;
+}