Asterisk - The Open Source Telephony Project  GIT-master-a24979a
dns_system_resolver.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2015, Digium, Inc.
5  *
6  * Ashley Sanders <asanders@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief The default DNS resolver for Asterisk.
22  *
23  * \arg See also \ref res_resolver_unbound.c
24  *
25  * \author Ashley Sanders <asanders@digium.com>
26  */
27 
28 #include "asterisk.h"
29 
30 #include "asterisk/_private.h"
31 #include "asterisk/astobj2.h"
32 #include "asterisk/dns.h"
33 #include "asterisk/dns_core.h"
34 #include "asterisk/dns_resolver.h"
35 #include "asterisk/linkedlists.h"
36 #include "asterisk/taskprocessor.h"
37 #include "asterisk/utils.h"
38 
39 /*! \brief The consideration priority for this resolver implementation. */
40 #define DNS_SYSTEM_RESOLVER_PRIORITY INT_MAX
41 
42 /*! \brief Resolver return code upon success. */
43 #define DNS_SYSTEM_RESOLVER_SUCCESS 0
44 
45 /*! \brief Resolver return code upon failure. */
46 #define DNS_SYSTEM_RESOLVER_FAILURE -1
47 
48 
49 static int dns_system_resolver_add_record(void *context, unsigned char *record, int record_len, int ttl);
50 static int dns_system_resolver_cancel(struct ast_dns_query *query);
51 static void dns_system_resolver_destroy(void);
52 static int dns_system_resolver_process_query(void *data);
53 static int dns_system_resolver_resolve(struct ast_dns_query *query);
54 static int dns_system_resolver_set_response(void *context, unsigned char *dns_response, int dns_response_len, int rcode);
55 
56 
57 /*! \brief The task processor to use for making DNS searches asynchronous. */
59 
60 /*! \brief The base definition for the dns_system_resolver */
62  .name = "system",
63  .priority = DNS_SYSTEM_RESOLVER_PRIORITY,
64  .resolve = dns_system_resolver_resolve,
66 };
67 
68 /*!
69  * \brief Callback to handle processing resource records.
70  *
71  * \details Adds an individual resource record discovered with ast_search_dns_ex to the
72  * ast_dns_query currently being resolved.
73  *
74  * \internal
75  *
76  * \param context A void pointer to the ast_dns_query being processed.
77  * \param record An individual resource record discovered during the DNS search.
78  * \param record_len The length of the resource record.
79  * \param ttl The resource record's expiration time limit (time to live).
80  *
81  * \retval 0 on success
82  * \retval -1 on failure
83  */
84 static int dns_system_resolver_add_record(void *context, unsigned char *record, int record_len, int ttl)
85 {
86  struct ast_dns_query *query = context;
87 
88  /* Add the record to the query.*/
89  return ast_dns_resolver_add_record(query,
92  ttl,
93  (const char*) record,
94  record_len);
95 }
96 
97 /*!
98  * \brief Cancels processing resolution for a given query.
99  *
100  * \note The system API calls block so there is no way to cancel them. Therefore, this function always
101  * returns failure when invoked.
102  *
103  * \internal
104  *
105  * \param query The ast_dns_query to cancel.
106  *
107  * \retval 0 on success
108  * \retval -1 on failure
109  */
110 static int dns_system_resolver_cancel(struct ast_dns_query *query)
111 {
113 }
114 
115 /*!
116  * \brief Destructor.
117  *
118  * \internal
119  */
121 {
122  /* Unreference the task processor */
124 
125  /* Unregister the base resolver */
127 }
128 
129 /*!
130  * \brief Callback to handle processing the query from the ast_taskprocessor instance.
131  *
132  * \internal
133  *
134  * \param data A void pointer to the ast_dns_query being processed.
135  *
136  * \retval -1 on search failure
137  * \retval 0 on no records found
138  * \retval 1 on success
139  */
140 static int dns_system_resolver_process_query(void *data)
141 {
142  struct ast_dns_query *query = data;
143 
144  /* Perform the DNS search */
145  enum ast_dns_search_result res = ast_search_dns_ex(query,
146  ast_dns_query_get_name(query),
151 
152  /* Handle the possible return values from the DNS search */
153  if (res == AST_DNS_SEARCH_FAILURE) {
154  ast_debug(1, "DNS search failed for query: '%s'\n",
155  ast_dns_query_get_name(query));
156  } else if (res == AST_DNS_SEARCH_NO_RECORDS) {
157  ast_debug(1, "DNS search failed to yield any results for query: '%s'\n",
158  ast_dns_query_get_name(query));
159  }
160 
161  /* Mark the query as complete */
163 
164  /* Reduce the reference count on the query object */
165  ao2_ref(query, -1);
166 
167  return res;
168 }
169 
170 /*!
171  * \brief Resolves a DNS query.
172  *
173  * \internal
174  *
175  * \param query The ast_dns_query to resolve.
176  *
177  * \retval 0 on successful load of query handler to the ast_taskprocessor instance
178  * \retval -1 on failure to load the query handler to the ast_taskprocessor instance
179  */
181 {
182  /* Add query processing handler to the task processor */
185  ao2_bump(query));
186 
187  /* The query processing handler was not added to the task processor */
188  if (res < 0) {
189  ast_log(LOG_ERROR, "Failed to perform async DNS resolution of '%s'\n",
190  ast_dns_query_get_name(query));
191  ao2_ref(query, -1);
192  }
193 
194  /* Return the result of adding the query processing handler to the task processor */
195  return res;
196 }
197 
198 /*!
199  * \brief Callback to handle initializing the results field.
200  *
201  * \internal
202  *
203  * \param context A void pointer to the ast_dns_query being processed.
204  * \param dns_response The full DNS response.
205  * \param dns_response_len The length of the full DNS response.
206  * \param rcode The DNS response code.
207  *
208  * \retval 0 on success
209  * \retval -1 on failure
210  */
211 static int dns_system_resolver_set_response(void *context, unsigned char *dns_response, int dns_response_len, int rcode)
212 {
213  struct ast_dns_query *query = context;
214  int res;
215 
216  /* Instantiate the query's result field (if necessary). */
217  if (!ast_dns_query_get_result(query)) {
218  res = ast_dns_resolver_set_result(query,
219  0,
220  0,
221  rcode,
222  ast_dns_query_get_name(query),
223  (const char*) dns_response,
224  dns_response_len);
225 
226  if (res) {
227  /* There was a problem instantiating the results field. */
228  ast_log(LOG_ERROR, "Could not instantiate the results field for query: '%s'\n",
229  ast_dns_query_get_name(query));
230  }
231  } else {
233  }
234 
235  return res;
236 }
237 
238 /*!
239  * \brief Initializes the resolver.
240  *
241  * \retval 0 on success
242  * \retval -1 on failure
243  */
245 {
246  /* Register the base resolver */
248 
249  if (res) {
251  }
252 
253  /* Instantiate the task processor */
254  dns_system_resolver_tp = ast_taskprocessor_get("dns_system_resolver_tp",
256 
257  /* Return error if the task processor failed to instantiate */
258  if (!dns_system_resolver_tp) {
260  }
261 
262  /* Register the cleanup function */
264 
266 }
Prototypes for public functions only of internal interest,.
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:120
DNS support for Asterisk.
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))
Extended version of the DNS search function.
Definition: dns.c:536
ast_dns_search_result
DNS search return values.
Definition: dns.h:28
@ AST_DNS_SEARCH_FAILURE
Definition: dns.h:29
@ AST_DNS_SEARCH_NO_RECORDS
Definition: dns.h:30
Core DNS API.
int ast_dns_query_get_rr_type(const struct ast_dns_query *query)
Get the record resource type of a DNS query.
Definition: dns_core.c:62
const char * ast_dns_query_get_name(const struct ast_dns_query *query)
Get the name queried in a DNS query.
Definition: dns_core.c:57
struct ast_dns_result * ast_dns_query_get_result(const struct ast_dns_query *query)
Get the result information for a DNS query.
Definition: dns_core.c:77
int ast_dns_query_get_rr_class(const struct ast_dns_query *query)
Get the record resource class of a DNS query.
Definition: dns_core.c:67
DNS Resolver API.
int ast_dns_resolver_set_result(struct ast_dns_query *query, unsigned int secure, unsigned int bogus, unsigned int rcode, const char *canonical, const char *answer, size_t answer_size)
Set result information for a DNS query.
Definition: dns_core.c:456
void ast_dns_resolver_completed(struct ast_dns_query *query)
Mark a DNS query as having been completed.
Definition: dns_core.c:599
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
Definition: dns_core.c:630
int ast_dns_resolver_add_record(struct ast_dns_query *query, int rr_type, int rr_class, int ttl, const char *data, const size_t size)
Add a DNS record to the result of a DNS query.
Definition: dns_core.c:535
void ast_dns_resolver_unregister(struct ast_dns_resolver *resolver)
Unregister a DNS resolver.
Definition: dns_core.c:680
static struct ast_taskprocessor * dns_system_resolver_tp
The task processor to use for making DNS searches asynchronous.
static int dns_system_resolver_process_query(void *data)
Callback to handle processing the query from the ast_taskprocessor instance.
#define DNS_SYSTEM_RESOLVER_FAILURE
Resolver return code upon failure.
static int dns_system_resolver_add_record(void *context, unsigned char *record, int record_len, int ttl)
Callback to handle processing resource records.
static void dns_system_resolver_destroy(void)
Destructor.
static int dns_system_resolver_set_response(void *context, unsigned char *dns_response, int dns_response_len, int rcode)
Callback to handle initializing the results field.
static int dns_system_resolver_resolve(struct ast_dns_query *query)
Resolves a DNS query.
#define DNS_SYSTEM_RESOLVER_PRIORITY
The consideration priority for this resolver implementation.
#define DNS_SYSTEM_RESOLVER_SUCCESS
Resolver return code upon success.
int ast_dns_system_resolver_init(void)
Initializes the resolver.
struct ast_dns_resolver dns_system_resolver_base
The base definition for the dns_system_resolver.
static int dns_system_resolver_cancel(struct ast_dns_query *query)
Cancels processing resolution for a given query.
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
A set of macros to manage forward-linked lists.
A DNS query.
Definition: dns_internal.h:137
DNS resolver implementation.
Definition: dns_resolver.h:32
const char * name
The name of the resolver implementation.
Definition: dns_resolver.h:34
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:69
An API for managing task processing threads that can be shared across modules.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
@ TPS_REF_DEFAULT
return a reference to a taskprocessor, create one if it does not exist
Definition: taskprocessor.h:76
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary.
Utility functions.