int dnsmgr_init(void); /*!< Provided by dnsmgr.c */
void dnsmgr_start_refresh(void); /*!< Provided by dnsmgr.c */
int dnsmgr_reload(void); /*!< Provided by dnsmgr.c */
+int ast_dns_system_resolver_init(void); /*!< Provided by dns_system_resolver.c */
void threadstorage_init(void); /*!< Provided by threadstorage.c */
int ast_device_state_engine_init(void); /*!< Provided by devicestate.c */
int astobj2_init(void); /*!< Provided by astobj2.c */
#ifndef _ASTERISK_DNS_H
#define _ASTERISK_DNS_H
-/*! \brief Perform DNS lookup (used by DNS, enum and SRV lookups)
- \param context
- \param dname Domain name to lookup (host, SRV domain, TXT record name)
- \param class Record Class (see "man res_search")
- \param type Record type (see "man res_search")
- \param callback Callback function for handling DNS result
- \note Asterisk DNS is synchronus at this time. This means that if your DNS
- services does not work, Asterisk may lock while waiting for response.
-*/
+/*! \brief DNS search return values */
+enum ast_dns_search_result {
+ AST_DNS_SEARCH_FAILURE = -1, /*!< DNS search resulted in failure */
+ AST_DNS_SEARCH_NO_RECORDS = 0, /*!< DNS search yielded no results */
+ AST_DNS_SEARCH_SUCCESS = 1 /*!< DNS search yielded at least one discovered record */
+};
+
+/*!
+ * \brief Perform DNS lookup (used by DNS, enum and SRV lookups)
+ *
+ * \param context Void pointer containing data to use in the callback function.
+ * \param dname Domain name to lookup (host, SRV domain, TXT record name).
+ * \param class Record Class (see "man res_search").
+ * \param type Record type (see "man res_search").
+ * \param answer The full DNS response.
+ * \param len The length of the full DNS response.
+ * \param callback Callback function for handling the discovered resource records from
+ * the DNS search.
+ *
+ * \retval -1 on search failure
+ * \retval 0 on no records found
+ * \retval 1 on success
+ *
+ * \note Asterisk DNS is synchronus at this time. This means that if your DNS
+ * service does not work, Asterisk may lock while waiting for a response.
+ */
int ast_search_dns(void *context, const char *dname, int class, int type,
- int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer));
+ int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer));
+
+/*!
+ * \brief Extended version of the DNS search function.
+ *
+ * \details Performs a DNS lookup, (used by DNS, enum and SRV lookups), parses the
+ * results and notifies the observer with the response and discovered records
+ * via invoking the provided callbacks (used by ast_dns_system_resolver).
+ *
+ * \param context Void pointer containing data to use in the handler functions.
+ * \param dname Domain name to lookup (host, SRV domain, TXT record name).
+ * \param rr_class Record Class (see "man res_search").
+ * \param rr_type Record type (see "man res_search").
+ * \param response_handler Callback function for handling the DNS response. Invoked upon
+ * completion of the DNS search.
+ * \param record_handler Callback function for handling the discovered resource
+ * records from the DNS search. Invoked n times, where n is the
+ * number of records discovered while parsing the DNS
+ * response.
+ *
+ * \retval AST_DNS_SEARCH_FAILURE on search failure
+ * \retval AST_DNS_SEARCH_NO_RECORDS on no records found
+ * \retval AST_DNS_SEARCH_SUCCESS on success
+ *
+ * \note Asterisk DNS is synchronus at this time. This means that if your DNS
+ * service does not work, Asterisk may lock while waiting for a response.
+ */
+enum ast_dns_search_result ast_search_dns_ex(void *context, const char *dname, int rr_class, int rr_type,
+ int (*response_handler)(void *context, unsigned char *dns_response, int dns_response_len, int rcode),
+ int (*record_handler)(void *context, unsigned char *record, int record_len, int ttl));
/*! \brief Retrieve the configured nameservers of the system */
struct ao2_container *ast_dns_get_nameservers(void);
exit(1);
}
+ if (ast_dns_system_resolver_init()) { /* Initialize the default DNS resolver */
+ printf("Failed: ast_dns_system_resolver_init\n%s", term_quit());
+ exit(1);
+ }
+
if ((moduleresult = load_modules(1))) { /* Load modules, pre-load only */
printf("Failed: load_modules\n%s", term_quit());
exit(moduleresult == -2 ? 2 : 1);
#include "asterisk/dns.h"
#include "asterisk/endian.h"
+/*! \brief The maximum size permitted for the answer from the DNS server */
#define MAX_SIZE 4096
#ifdef __PDP_ENDIAN
#define DETERMINED_BYTE_ORDER __LITTLE_ENDIAN
#endif
+#ifndef HAVE_RES_NINIT
+AST_MUTEX_DEFINE_STATIC(res_lock);
+#endif
+
/* The dns_HEADER structure definition below originated
in the arpa/nameser.h header file distributed with ISC
BIND, which contains the following copyright and license
} dns_HEADER;
struct dn_answer {
- unsigned short rtype;
- unsigned short class;
- unsigned int ttl;
- unsigned short size;
+ unsigned short rtype; /*!< The resource record type. */
+ unsigned short class; /*!< The resource record class. */
+ unsigned int ttl; /*!< The resource record time to live. */
+ unsigned short size; /*!< The resource record size. */
} __attribute__((__packed__));
+/*!
+ * \brief Tries to find the position of the next field in the DNS response.
+ *
+ * \internal
+ *
+ * \param s A char pointer to the current frame in the DNS response.
+ * \param len The remaining available length of the DNS response.
+ *
+ * \retval The position of the next field
+ * \retval -1 if there are no remaining fields
+ */
static int skip_name(unsigned char *s, int len)
{
int x = 0;
x++;
break;
}
+
if ((*s & 0xc0) == 0xc0) {
s += 2;
x += 2;
break;
}
+
x += *s + 1;
s += *s + 1;
}
- if (x >= len)
- return -1;
+
+ /* If we are out of room to search, return failure. */
+ if (x >= len) {
+ return AST_DNS_SEARCH_FAILURE;
+ }
+
+ /* Return the value for the current position in the DNS response. This is the start
+ position of the next field. */
return x;
}
-/*! \brief Parse DNS lookup result, call callback */
+/*!
+ * \brief Advances the position of the DNS response pointer by the size of the current field.
+ *
+ * \internal
+ *
+ * \param dns_response A pointer to a char pointer to the current field in the DNS response.
+ * \param remaining_len The remaining available length in the DNS response to search.
+ * \param field_size A positive value representing the size of the current field
+ pointed to by the dns_response parameter.
+ *
+ * \retval The remaining length in the DNS response
+ * \retval -1 there are no frames remaining in the DNS response
+ */
+static int dns_advance_field(unsigned char **dns_response, int remaining_len, int field_size)
+{
+ if (dns_response == NULL || field_size < 0 || remaining_len < field_size) {
+ return AST_DNS_SEARCH_FAILURE;
+ }
+
+ *dns_response += field_size;
+ remaining_len -= field_size;
+
+ return remaining_len;
+}
+
+#ifndef HAVE_RES_NINIT
+/*!
+ * \brief Handles the DNS search if the system has RES_INIT.
+ *
+ * \internal
+ *
+ * \param dname Domain name to lookup (host, SRV domain, TXT record name).
+ * \param rr_class Record Class (see "man res_search").
+ * \param rr_type Record type (see "man res_search").
+ * \param dns_response The full DNS response.
+ * \param dns_response_len The length of the full DNS response.
+ *
+ * \retval The length of the DNS response
+ * \retval -1 on search failure
+ */
+static int dns_search_res(const char *dname, int rr_class, int rr_type,
+ unsigned char *dns_response, int dns_response_len)
+{
+
+ int ret = AST_DNS_SEARCH_FAILURE;
+ struct __res_state dns_state;
+
+ ast_mutex_lock(&res_lock);
+ res_init();
+ ret = res_search(&dns_state,
+ dname,
+ rr_class,
+ rr_type,
+ dns_response,
+ dns_response_len);
+
+#ifdef HAVE_RES_CLOSE
+ res_close();
+#endif
+
+ ast_mutex_unlock(&res_lock);
+
+ return ret;
+}
+#else
+/*!
+ * \brief Handles the DNS search if the system has RES_NINIT.
+ *
+ * \internal
+ *
+ * \param dname Domain name to lookup (host, SRV domain, TXT record name).
+ * \param rr_class Record Class (see "man res_search").
+ * \param rr_type Record type (see "man res_search").
+ * \param dns_response The full DNS response.
+ * \param dns_response_len The length of the full DNS response.
+ *
+ * \retval The length of the DNS response
+ * \retval -1 on search failure
+ */
+static int dns_search_res(const char *dname, int rr_class, int rr_type,
+ unsigned char *dns_response, int dns_response_len)
+{
+
+ int ret = AST_DNS_SEARCH_FAILURE;
+ struct __res_state dns_state;
+
+ memset(&dns_state, 0, sizeof(dns_state));
+ res_ninit(&dns_state);
+ ret = res_nsearch(&dns_state,
+ dname,
+ rr_class,
+ rr_type,
+ dns_response,
+ dns_response_len);
+
+#ifdef HAVE_RES_NDESTROY
+ res_ndestroy(&dns_state);
+#else
+ res_nclose(&dns_state);
+#endif
+
+ return ret;
+}
+#endif
+
+/*!
+ * \brief Parse DNS lookup result, call callback
+ *
+ * \internal
+ *
+ * \param context Void pointer containing data to use in the callback functions.
+ * \param dname Domain name to lookup (host, SRV domain, TXT record name).
+ * \param class Record Class (see "man res_search").
+ * \param type Record type (see "man res_search").
+ * \param answer The full DNS response.
+ * \param len The length of the full DNS response.
+ * \param callback Callback function for handling the discovered resource records from the DNS search.
+ *
+ * \retval -1 on search failure
+ * \retval 0 on no records found
+ * \retval 1 on success
+ */
static int dns_parse_answer(void *context,
int class, int type, unsigned char *answer, int len,
int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
return ret;
}
-#ifndef HAVE_RES_NINIT
-AST_MUTEX_DEFINE_STATIC(res_lock);
-#endif
+/*!
+ * \brief Extended version of the DNS Parsing function.
+ *
+ * \details Parses the DNS lookup result and notifies the observer of each discovered
+ * resource record with the provided callback.
+ *
+ * \internal
+ *
+ * \param context Void pointer containing data to use in the callback functions.
+ * \param dname Domain name to lookup (host, SRV domain, TXT record name).
+ * \param rr_class Record Class (see "man res_search").
+ * \param rr_type Record type (see "man res_search").
+ * \param answer The full DNS response.
+ * \param answer_len The length of the full DNS response.
+ * \param response_handler Callback function for handling the DNS response.
+ * \param record_handler Callback function for handling the discovered resource records from the DNS search.
+ *
+ * \retval -1 on search failure
+ * \retval 0 on no records found
+ * \retval 1 on success
+ */
+static int dns_parse_answer_ex(void *context, int rr_class, int rr_type, unsigned char *answer, int answer_len,
+ int (*response_handler)(void *context, unsigned char *dns_response, int dns_response_len, int rcode),
+ int (*record_handler)(void *context, unsigned char *record, int record_len, int ttl))
+{
+ unsigned char *dns_response = answer;
+ dns_HEADER *dns_header = (dns_HEADER *)answer;
+
+ struct dn_answer *ans;
+ int res, x, pos, dns_response_len, ret;
+
+ dns_response_len = answer_len;
+ ret = AST_DNS_SEARCH_NO_RECORDS;
+
+ /* Invoke the response_handler callback to notify the observer of the raw DNS response */
+ response_handler(context, dns_response, dns_response_len, ntohs(dns_header->rcode));
+
+ /* Verify there is something to parse */
+ if (answer_len == 0) {
+ return ret;
+ }
+
+ /* Try advancing the cursor for the dns header */
+ if ((pos = dns_advance_field(&answer, answer_len, sizeof(dns_HEADER))) < 0) {
+ ast_log(LOG_WARNING, "Length of DNS answer exceeds available search frames\n");
+ return AST_DNS_SEARCH_FAILURE;
+ }
+
+ /* Skip domain name and QCODE / QCLASS */
+ for (x = 0; x < ntohs(dns_header->qdcount); x++) {
+ if ((res = skip_name(answer, pos)) < 0) {
+ ast_log(LOG_WARNING, "Failed skipping name\n");
+ return AST_DNS_SEARCH_FAILURE;
+ }
+
+ /* Try advancing the cursor for the name and QCODE / QCLASS fields */
+ if ((pos = dns_advance_field(&answer, pos, res + 4)) < 0) {
+ return AST_DNS_SEARCH_FAILURE;
+ }
+ }
-/*! \brief Lookup record in DNS
-\note Asterisk DNS is synchronus at this time. This means that if your DNS does
-not work properly, Asterisk might not start properly or a channel may lock.
+ /* Extract the individual records */
+ for (x = 0; x < ntohs(dns_header->ancount); x++) {
+ if ((res = skip_name(answer, pos)) < 0) {
+ ast_log(LOG_WARNING, "Failed skipping name\n");
+ return AST_DNS_SEARCH_FAILURE;
+ }
+
+ /* Try advancing the cursor to the current record */
+ if ((pos = dns_advance_field(&answer, pos, res)) < 0) {
+ ast_log(LOG_WARNING, "Length of DNS answer exceeds available search frames\n");
+ return AST_DNS_SEARCH_FAILURE;
+ }
+
+ /* Cast the current value for the answer pointer as a dn_answer struct */
+ ans = (struct dn_answer *) answer;
+
+ /* Try advancing the cursor to the end of the current record */
+ if ((pos = dns_advance_field(&answer, pos, sizeof(struct dn_answer))) < 0) {
+ ast_log(LOG_WARNING, "Length of DNS answer exceeds available search frames\n");
+ return AST_DNS_SEARCH_FAILURE;
+ }
+
+ /* Skip over the records that do not have the same resource record class and type we care about */
+ if (ntohs(ans->class) == rr_class && ntohs(ans->rtype) == rr_type) {
+ /* Invoke the record handler callback to deliver the discovered record */
+ record_handler(context, answer, ntohs(ans->size), ans->ttl);
+ /*At least one record was found */
+ ret = AST_DNS_SEARCH_SUCCESS;
+ }
+
+ /* Try and update the field to the next record, but ignore any errors that come
+ * back because this may be the end of the line. */
+ pos = dns_advance_field(&answer, pos, res + ntohs(ans->size));
+ }
+
+ return ret;
+}
+
+/*!
+ * \brief Lookup record in DNS
+ *
+ * \note Asterisk DNS is synchronus at this time. This means that if your DNS does not
+ * work properly, Asterisk might not start properly or a channel may lock.
*/
int ast_search_dns(void *context,
const char *dname, int class, int type,
return ret;
}
+enum ast_dns_search_result ast_search_dns_ex(void *context, const char *dname, int rr_class, int rr_type,
+ int (*response_handler)(void *context, unsigned char *dns_response, int dns_response_len, int rcode),
+ int (*record_handler)(void *context, unsigned char *record, int record_len, int ttl))
+{
+ int ret, dns_response_len;
+ unsigned char dns_response[MAX_SIZE];
+
+ /* Assert that the callbacks are not NULL */
+ ast_assert(response_handler != NULL);
+ ast_assert(record_handler != NULL);
+
+ /* Try the DNS search. */
+ dns_response_len = dns_search_res(dname,
+ rr_class,
+ rr_type,
+ dns_response,
+ sizeof(dns_response));
+
+ if (dns_response_len < 0) {
+ ast_log(LOG_ERROR, "DNS search failed for %s\n", dname);
+ return AST_DNS_SEARCH_FAILURE;
+ }
+
+ /* Parse records from DNS response */
+ ret = dns_parse_answer_ex(context,
+ rr_class,
+ rr_type,
+ dns_response,
+ dns_response_len,
+ response_handler,
+ record_handler);
+
+ /* Handle the return code from parsing the DNS response */
+ if (ret == AST_DNS_SEARCH_FAILURE) {
+ /* Parsing Error */
+ ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname);
+ } else if (ret == AST_DNS_SEARCH_NO_RECORDS) {
+ /* No results found */
+ ast_debug(1, "DNS search yielded no results for %s\n", dname);
+ }
+
+ return ret;
+}
+
struct ao2_container *ast_dns_get_nameservers(void)
{
#ifdef HAVE_RES_NINIT
--- /dev/null
+/*\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