123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- /*
- * 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.c
- *
- * \author Ashley Sanders <asanders@digium.com>
- */
- #include "asterisk.h"
- #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 context A void pointer to the ast_dns_query being processed.
- * \param dns_response The full DNS response.
- * \param dns_response_len 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) {
- return DNS_SYSTEM_RESOLVER_FAILURE;
- }
- /* Register the cleanup function */
- ast_register_cleanup(dns_system_resolver_destroy);
- return DNS_SYSTEM_RESOLVER_SUCCESS;
- }
|