Asterisk - The Open Source Telephony Project  GIT-master-a1fa8df
dns_core.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  * Joshua Colp <jcolp@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 Core DNS Functionality
22  *
23  * \author Joshua Colp <jcolp@digium.com>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 #include "asterisk/_private.h"
33 #include "asterisk/linkedlists.h"
34 #include "asterisk/astobj2.h"
35 #include "asterisk/strings.h"
36 #include "asterisk/sched.h"
37 #include "asterisk/dns_core.h"
38 #include "asterisk/dns_srv.h"
39 #include "asterisk/dns_tlsa.h"
40 #include "asterisk/dns_recurring.h"
41 #include "asterisk/dns_resolver.h"
42 #include "asterisk/dns_internal.h"
43 #include "asterisk/netsock2.h"
44 
45 #include <netinet/in.h>
46 #include <arpa/nameser.h>
47 
49 
50 static struct ast_sched_context *sched;
51 
53 {
54  return sched;
55 }
56 
57 const char *ast_dns_query_get_name(const struct ast_dns_query *query)
58 {
59  return query->name;
60 }
61 
62 int ast_dns_query_get_rr_type(const struct ast_dns_query *query)
63 {
64  return query->rr_type;
65 }
66 
67 int ast_dns_query_get_rr_class(const struct ast_dns_query *query)
68 {
69  return query->rr_class;
70 }
71 
72 void *ast_dns_query_get_data(const struct ast_dns_query *query)
73 {
74  return query->user_data;
75 }
76 
78 {
79  return query->result;
80 }
81 
82 unsigned int ast_dns_result_get_secure(const struct ast_dns_result *result)
83 {
84  return result->secure;
85 }
86 
87 unsigned int ast_dns_result_get_bogus(const struct ast_dns_result *result)
88 {
89  return result->bogus;
90 }
91 
92 unsigned int ast_dns_result_get_rcode(const struct ast_dns_result *result)
93 {
94  return result->rcode;
95 }
96 
98 {
99  return result->canonical;
100 }
101 
103 {
104  return AST_LIST_FIRST(&result->records);
105 }
106 
108 {
109  return result->answer;
110 }
111 
113 {
114  int ttl = 0;
115  const struct ast_dns_record *record;
116 
117  if (ast_dns_result_get_rcode(result) == NXDOMAIN) {
118  return 0;
119  }
120 
121  for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) {
122  if (!ttl || (ast_dns_record_get_ttl(record) && (ast_dns_record_get_ttl(record) < ttl))) {
123  ttl = ast_dns_record_get_ttl(record);
124  }
125  }
126 
127  return ttl;
128 }
129 
131 {
132  struct ast_dns_record *record;
133 
134  if (!result) {
135  return;
136  }
137 
138  while ((record = AST_LIST_REMOVE_HEAD(&result->records, list))) {
139  ast_free(record);
140  }
141 
142  ast_free(result);
143 }
144 
146 {
147  return record->rr_type;
148 }
149 
151 {
152  return record->rr_class;
153 }
154 
155 int ast_dns_record_get_ttl(const struct ast_dns_record *record)
156 {
157  return record->ttl;
158 }
159 
160 const char *ast_dns_record_get_data(const struct ast_dns_record *record)
161 {
162  return record->data_ptr;
163 }
164 
165 size_t ast_dns_record_get_data_size(const struct ast_dns_record *record)
166 {
167  return record->data_len;
168 }
169 
170 const struct ast_dns_record *ast_dns_record_get_next(const struct ast_dns_record *record)
171 {
172  return AST_LIST_NEXT(record, list);
173 }
174 
175 /*! \brief Destructor for an active DNS query */
176 static void dns_query_active_destroy(void *data)
177 {
178  struct ast_dns_query_active *active = data;
179 
180  ao2_cleanup(active->query);
181 }
182 
183 /*! \brief \brief Destructor for a DNS query */
184 static void dns_query_destroy(void *data)
185 {
186  struct ast_dns_query *query = data;
187 
188  ao2_cleanup(query->user_data);
189  ao2_cleanup(query->resolver_data);
190  ast_dns_result_free(query->result);
191 }
192 
194 {
195  struct ast_dns_query *query;
196 
197  if (ast_strlen_zero(name)) {
198  ast_log(LOG_WARNING, "Could not perform asynchronous resolution, no name provided\n");
199  return NULL;
200  } else if (rr_type > 65536) {
201  ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', resource record type '%d' exceeds maximum\n",
202  name, rr_type);
203  return NULL;
204  } else if (rr_type < 0) {
205  ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', invalid resource record type '%d'\n",
206  name, rr_type);
207  return NULL;
208  } else if (rr_class > 65536) {
209  ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', resource record class '%d' exceeds maximum\n",
210  name, rr_class);
211  return NULL;
212  } else if (rr_class < 0) {
213  ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', invalid resource class '%d'\n",
214  name, rr_class);
215  return NULL;
216  } else if (!callback) {
217  ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', no callback provided\n",
218  name);
219  return NULL;
220  }
221 
222  query = ao2_alloc_options(sizeof(*query) + strlen(name) + 1, dns_query_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
223  if (!query) {
224  return NULL;
225  }
226 
227  query->callback = callback;
228  query->user_data = ao2_bump(data);
229  query->rr_type = rr_type;
230  query->rr_class = rr_class;
231  strcpy(query->name, name); /* SAFE */
232 
236 
237  if (!query->resolver) {
238  ast_log(LOG_ERROR, "Attempted to do a DNS query for '%s' of class '%d' and type '%d' but no resolver is available\n",
239  name, rr_class, rr_type);
240  ao2_ref(query, -1);
241  return NULL;
242  }
243 
244  return query;
245 }
246 
247 struct ast_dns_query_active *ast_dns_resolve_async(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
248 {
249  struct ast_dns_query_active *active;
250 
252  if (!active) {
253  return NULL;
254  }
255 
256  active->query = dns_query_alloc(name, rr_type, rr_class, callback, data);
257  if (!active->query) {
258  ao2_ref(active, -1);
259  return NULL;
260  }
261 
262  if (active->query->resolver->resolve(active->query)) {
263  ast_log(LOG_ERROR, "Resolver '%s' returned an error when resolving '%s' of class '%d' and type '%d'\n",
264  active->query->resolver->name, name, rr_class, rr_type);
265  ao2_ref(active, -1);
266  return NULL;
267  }
268 
269  return active;
270 }
271 
273 {
274  return active->query->resolver->cancel(active->query);
275 }
276 
277 /*! \brief Structure used for signaling back for synchronous resolution completion */
279  /*! \brief Lock used for signaling */
281  /*! \brief Condition used for signaling */
283  /*! \brief Whether the query has completed */
284  unsigned int completed;
285  /*! \brief The result from the query */
287 };
288 
289 /*! \brief Destructor for synchronous resolution structure */
290 static void dns_synchronous_resolve_destroy(void *data)
291 {
292  struct dns_synchronous_resolve *synchronous = data;
293 
294  ast_mutex_destroy(&synchronous->lock);
295  ast_cond_destroy(&synchronous->cond);
296 
297  /* This purposely does not unref result as it has been passed to the caller */
298 }
299 
300 /*! \brief Callback used to implement synchronous resolution */
301 static void dns_synchronous_resolve_callback(const struct ast_dns_query *query)
302 {
303  struct dns_synchronous_resolve *synchronous = ast_dns_query_get_data(query);
304 
305  synchronous->result = query->result;
306  ((struct ast_dns_query *)query)->result = NULL;
307 
308  ast_mutex_lock(&synchronous->lock);
309  synchronous->completed = 1;
310  ast_cond_signal(&synchronous->cond);
311  ast_mutex_unlock(&synchronous->lock);
312 }
313 
314 int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
315 {
316  struct dns_synchronous_resolve *synchronous;
317  struct ast_dns_query_active *active;
318 
319  if (ast_strlen_zero(name)) {
320  ast_log(LOG_WARNING, "Could not perform synchronous resolution, no name provided\n");
321  return -1;
322  } else if (rr_type > 65536) {
323  ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', resource record type '%d' exceeds maximum\n",
324  name, rr_type);
325  return -1;
326  } else if (rr_type < 0) {
327  ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', invalid resource record type '%d'\n",
328  name, rr_type);
329  return -1;
330  } else if (rr_class > 65536) {
331  ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', resource record class '%d' exceeds maximum\n",
332  name, rr_class);
333  return -1;
334  } else if (rr_class < 0) {
335  ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', invalid resource class '%d'\n",
336  name, rr_class);
337  return -1;
338  } else if (!result) {
339  ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', no result pointer provided for storing results\n",
340  name);
341  return -1;
342  }
343 
345  if (!synchronous) {
346  return -1;
347  }
348 
349  ast_mutex_init(&synchronous->lock);
350  ast_cond_init(&synchronous->cond, NULL);
351 
352  active = ast_dns_resolve_async(name, rr_type, rr_class, dns_synchronous_resolve_callback, synchronous);
353  if (active) {
354  /* Wait for resolution to complete */
355  ast_mutex_lock(&synchronous->lock);
356  while (!synchronous->completed) {
357  ast_cond_wait(&synchronous->cond, &synchronous->lock);
358  }
359  ast_mutex_unlock(&synchronous->lock);
360  ao2_ref(active, -1);
361  }
362 
363  *result = synchronous->result;
364  ao2_ref(synchronous, -1);
365 
366  return *result ? 0 : -1;
367 }
368 
369 int ast_dns_resolve_ipv6_and_ipv4(struct ast_sockaddr *address, const char *host, const char *port)
370 {
372  int i;
373  int rc;
374 
375  if (!queries) {
376  ast_log(LOG_ERROR, "Couldn't allocate DNS query structure\n");
377  return -1;
378  }
379  rc = ast_dns_query_set_add(queries, host, ns_t_aaaa, ns_c_in);
380  if (rc != 0) {
381  ast_log(LOG_ERROR, "Couldn't add 'AAAA' DNS query for '%s'\n", host);
382  return -1;
383  }
384  rc = ast_dns_query_set_add(queries, host, ns_t_a, ns_c_in);
385  if (rc != 0) {
386  ast_log(LOG_ERROR, "Couldn't add 'A' DNS query for '%s'\n", host);
387  return -1;
388  }
390  if (rc != 0) {
391  ast_log(LOG_ERROR, "Query set resolve failure for '%s'\n", host);
392  return -1;
393  }
394  for (i = 0; i < ast_dns_query_set_num_queries(queries); ++i) {
395  struct ast_dns_query *query = ast_dns_query_set_get(queries, i);
397  const struct ast_dns_record *record;
398  in_port_t in_port = 0;
399 
400  if (!ast_strlen_zero(port)) {
401  in_port = htons(atoi(port));
402  }
403 
404  for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) {
405  size_t data_size = ast_dns_record_get_data_size(record);
406  const unsigned char *data = (unsigned char *)ast_dns_record_get_data(record);
407  int rr_type = ast_dns_record_get_rr_type(record);
408 
409  if (rr_type == ns_t_aaaa && data_size == 16) {
410  struct sockaddr_in6 sin6 = { 0, };
411 
412  sin6.sin6_port = in_port;
413  memcpy(&sin6.sin6_addr, data, data_size);
414  sin6.sin6_family = AF_INET6;
415  memcpy(&address->ss, &sin6, sizeof(sin6));
416  address->len = sizeof(sin6);
417 
418  return 0;
419  } else if (rr_type == ns_t_a && data_size == 4) {
420  struct sockaddr_in sin4 = { 0, };
421 
422  sin4.sin_port = in_port;
423  memcpy(&sin4.sin_addr, data, data_size);
424  sin4.sin_family = AF_INET;
425  memcpy(&address->ss, &sin4, sizeof(sin4));
426  address->len = sizeof(sin4);
427 
428  return 0;
429  } else {
430  ast_debug(3, "Unrecognized rr_type '%u' or data_size '%zu' from DNS query for host '%s'\n",
431  rr_type, data_size, host);
432  continue;
433  }
434  }
435  }
436 
437  return -1;
438 }
439 
440 int ast_dns_resolver_set_data(struct ast_dns_query *query, void *data)
441 {
442  if (query->resolver_data) {
443  return -1;
444  }
445 
446  query->resolver_data = ao2_bump(data);
447 
448  return 0;
449 }
450 
451 void *ast_dns_resolver_get_data(const struct ast_dns_query *query)
452 {
453  return query->resolver_data;
454 }
455 
456 int ast_dns_resolver_set_result(struct ast_dns_query *query, unsigned int secure, unsigned int bogus,
457  unsigned int rcode, const char *canonical, const char *answer, size_t answer_size)
458 {
459  char *buf_ptr;
460 
461  if (secure && bogus) {
462  ast_debug(2, "Query '%p': Could not set result information, it can not be both secure and bogus\n",
463  query);
464  return -1;
465  }
466 
467  if (ast_strlen_zero(canonical)) {
468  ast_debug(2, "Query '%p': Could not set result information since no canonical name was provided\n",
469  query);
470  return -1;
471  }
472 
473  if (!answer) {
474  answer = "";
475  answer_size = 0;
476  ast_debug(2, "Query '%p': Assuming zero-sized answer on NULL input\n", query);
477  }
478 
479  ast_dns_result_free(query->result);
480 
481  query->result = ast_calloc(1, sizeof(*query->result) + strlen(canonical) + 1 + answer_size);
482  if (!query->result) {
483  return -1;
484  }
485 
486  query->result->secure = secure;
487  query->result->bogus = bogus;
488  query->result->rcode = rcode;
489 
490  buf_ptr = query->result->buf;
491  strcpy(buf_ptr, canonical); /* SAFE */
492  query->result->canonical = buf_ptr;
493 
494  buf_ptr += strlen(canonical) + 1;
495  memcpy(buf_ptr, answer, answer_size); /* SAFE */
496  query->result->answer = buf_ptr;
497  query->result->answer_size = answer_size;
498 
499  return 0;
500 }
501 
502 static struct ast_dns_record *generic_record_alloc(struct ast_dns_query *query, const char *data, const size_t size)
503 {
504  struct ast_dns_record *record;
505 
506  record = ast_calloc(1, sizeof(*record) + size);
507  if (!record) {
508  return NULL;
509  }
510 
511  record->data_ptr = record->data;
512 
513  return record;
514 }
515 
516 typedef struct ast_dns_record *(*dns_alloc_fn)(struct ast_dns_query *query, const char *data, const size_t size);
517 
519  [T_TXT] = dns_txt_alloc,
520  [T_NAPTR] = dns_naptr_alloc,
521  [T_SRV] = dns_srv_alloc,
522 };
523 
524 static struct ast_dns_record *allocate_dns_record(unsigned int rr_type, struct ast_dns_query *query, const char *data, const size_t size)
525 {
527 
528  if (rr_type < ARRAY_LEN(dns_alloc_table) && dns_alloc_table[rr_type]) {
529  allocator = dns_alloc_table[rr_type];
530  }
531 
532  return allocator(query, data, size);
533 }
534 
535 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)
536 {
537  struct ast_dns_record *record;
538 
539  if (rr_type < 0) {
540  ast_debug(2, "Query '%p': Could not add record, invalid resource record type '%d'\n",
541  query, rr_type);
542  return -1;
543  } else if (rr_type > 65536) {
544  ast_debug(2, "Query '%p': Could not add record, resource record type '%d' exceeds maximum\n",
545  query, rr_type);
546  return -1;
547  } else if (rr_class < 0) {
548  ast_debug(2, "Query '%p': Could not add record, invalid resource record class '%d'\n",
549  query, rr_class);
550  return -1;
551  } else if (rr_class > 65536) {
552  ast_debug(2, "Query '%p': Could not add record, resource record class '%d' exceeds maximum\n",
553  query, rr_class);
554  return -1;
555  } else if (ttl < 0) {
556  ast_debug(2, "Query '%p': Could not add record, invalid TTL '%d'\n",
557  query, ttl);
558  return -1;
559  } else if (!data || !size) {
560  ast_debug(2, "Query '%p': Could not add record, no data specified\n",
561  query);
562  return -1;
563  } else if (!query->result) {
564  ast_debug(2, "Query '%p': No result was set on the query, thus records can not be added\n",
565  query);
566  return -1;
567  }
568 
569  record = allocate_dns_record(rr_type, query, data, size);
570  if (!record) {
571  return -1;
572  }
573 
574  record->rr_type = rr_type;
575  record->rr_class = rr_class;
576  record->ttl = ttl;
577  record->data_len = size;
578  memcpy(record->data_ptr, data, size);
579 
580  AST_LIST_INSERT_TAIL(&query->result->records, record, list);
581 
582  return 0;
583 }
584 
585 typedef void (*dns_sort_fn)(struct ast_dns_result *result);
586 
588  [T_NAPTR] = dns_naptr_sort,
589  [T_SRV] = dns_srv_sort,
590 };
591 
592 static void sort_result(int rr_type, struct ast_dns_result *result)
593 {
594  if (dns_sort_table[rr_type]) {
595  dns_sort_table[rr_type](result);
596  }
597 }
598 
600 {
602 
603  query->callback(query);
604 }
605 
606 static void dns_shutdown(void)
607 {
608  if (sched) {
610  sched = NULL;
611  }
612 }
613 
614 int dns_core_init(void)
615 {
616  sched = ast_sched_context_create();
617  if (!sched) {
618  return -1;
619  }
620 
621  if (ast_sched_start_thread(sched)) {
622  return -1;
623  }
624 
626 
627  return 0;
628 }
629 
631 {
632  struct ast_dns_resolver *iter;
633  int inserted = 0;
634 
635  if (!resolver) {
636  return -1;
637  } else if (ast_strlen_zero(resolver->name)) {
638  ast_log(LOG_ERROR, "Registration of DNS resolver failed as it does not have a name\n");
639  return -1;
640  } else if (!resolver->resolve) {
641  ast_log(LOG_ERROR, "DNS resolver '%s' does not implement the resolve callback which is required\n",
642  resolver->name);
643  return -1;
644  } else if (!resolver->cancel) {
645  ast_log(LOG_ERROR, "DNS resolver '%s' does not implement the cancel callback which is required\n",
646  resolver->name);
647  return -1;
648  }
649 
651 
652  AST_LIST_TRAVERSE(&resolvers, iter, next) {
653  if (!strcmp(iter->name, resolver->name)) {
654  ast_log(LOG_ERROR, "A DNS resolver with the name '%s' is already registered\n", resolver->name);
656  return -1;
657  }
658  }
659 
661  if (iter->priority > resolver->priority) {
662  AST_RWLIST_INSERT_BEFORE_CURRENT(resolver, next);
663  inserted = 1;
664  break;
665  }
666  }
668 
669  if (!inserted) {
670  AST_RWLIST_INSERT_TAIL(&resolvers, resolver, next);
671  }
672 
674 
675  ast_verb(2, "Registered DNS resolver '%s' with priority '%d'\n", resolver->name, resolver->priority);
676 
677  return 0;
678 }
679 
681 {
682  struct ast_dns_resolver *iter;
683 
684  if (!resolver) {
685  return;
686  }
687 
690  if (resolver == iter) {
692  break;
693  }
694  }
697 
698  ast_verb(2, "Unregistered DNS resolver '%s'\n", resolver->name);
699 }
700 
701 char *dns_find_record(const char *record, size_t record_size, const char *response, size_t response_size)
702 {
703  size_t remaining_size = response_size;
704  const char *search_base = response;
705  char *record_offset;
706 
707  while (1) {
708  record_offset = memchr(search_base, record[0], remaining_size);
709 
710  ast_assert(record_offset != NULL);
711  ast_assert(search_base + remaining_size - record_offset >= record_size);
712 
713  if (!memcmp(record_offset, record, record_size)) {
714  return record_offset;
715  }
716 
717  remaining_size -= record_offset - search_base;
718  search_base = record_offset + 1;
719  }
720 }
721 
722 int dns_parse_short(unsigned char *cur, uint16_t *val)
723 {
724  /* This assignment takes a big-endian 16-bit value and stores it in the
725  * machine's native byte order. Using this method allows us to avoid potential
726  * alignment issues in case the order is not on a short-addressable boundary.
727  * See http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html for
728  * more information
729  */
730  *val = (cur[1] << 0) | (cur[0] << 8);
731  return sizeof(*val);
732 }
733 
734 int dns_parse_string(char *cur, uint8_t *size, char **val)
735 {
736  *size = *cur++;
737  *val = cur;
738  return *size + 1;
739 }
void(* dns_sort_fn)(struct ast_dns_result *result)
Definition: dns_core.c:585
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Definition: sched.c:195
const char * ast_dns_result_get_canonical(const struct ast_dns_result *result)
Get the canonical name of the result.
Definition: dns_core.c:97
const char * ast_dns_record_get_data(const struct ast_dns_record *record)
Retrieve the raw DNS record.
Definition: dns_core.c:160
struct sockaddr_storage ss
Definition: netsock2.h:98
static const char name[]
Definition: format_mp3.c:68
struct ast_dns_query * query
The underlying DNS query.
Definition: dns_internal.h:203
int ast_dns_resolver_set_data(struct ast_dns_query *query, void *data)
Set resolver specific data on a query.
Definition: dns_core.c:440
Asterisk main include file. File version handling, generic pbx functions.
void ast_dns_resolver_completed(struct ast_dns_query *query)
Mark a DNS query as having been completed.
Definition: dns_core.c:599
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
int dns_core_init(void)
Definition: dns_core.c:614
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: linkedlists.h:332
int ast_query_set_resolve(struct ast_dns_query_set *query_set)
Synchronously resolve queries in a query set.
String manipulation functions.
static void dns_synchronous_resolve_callback(const struct ast_dns_query *query)
Callback used to implement synchronous resolution.
Definition: dns_core.c:301
Definition: ast_expr2.c:325
void dns_srv_sort(struct ast_dns_result *result)
Sort the SRV records on a result.
Definition: dns_srv.c:113
static void dns_shutdown(void)
Definition: dns_core.c:606
void dns_naptr_sort(struct ast_dns_result *result)
Sort the NAPTR records on a result.
Definition: dns_naptr.c:551
void(* ast_dns_resolve_callback)(const struct ast_dns_query *query)
Callback invoked when a query completes.
Definition: dns_core.h:171
char * address
Definition: f2c.h:59
char * data_ptr
pointer to record-specific data.
Definition: dns_internal.h:58
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
unsigned int rcode
Optional rcode, set if an error occurred.
Definition: dns_internal.h:123
Structure used for signaling back for synchronous resolution completion.
Definition: dns_core.c:278
int rr_type
Resource record type.
Definition: dns_internal.h:149
#define LOG_WARNING
Definition: logger.h:274
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
unsigned int secure
Whether the result is secure.
Definition: dns_internal.h:119
For AST_LIST.
Definition: dns_internal.h:39
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
socklen_t len
Definition: netsock2.h:99
size_t ast_dns_record_get_data_size(const struct ast_dns_record *record)
Retrieve the size of the raw DNS record.
Definition: dns_core.c:165
void ast_dns_resolver_unregister(struct ast_dns_resolver *resolver)
Unregister a DNS resolver.
Definition: dns_core.c:680
int dns_parse_short(unsigned char *cur, uint16_t *val)
Parse a 16-bit unsigned value from a DNS record.
Definition: dns_core.c:722
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
int rr_class
Resource record class.
Definition: dns_internal.h:151
struct ast_dns_query_set * ast_dns_query_set_create(void)
Create a query set to hold queries.
Definition: dns_query_set.c:60
const char * ast_dns_result_get_answer(const struct ast_dns_result *result)
Get the raw DNS answer from a DNS result.
Definition: dns_core.c:107
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_cond_init(cond, attr)
Definition: lock.h:199
struct ast_dns_query * dns_query_alloc(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
Allocate a DNS query (but do not start resolution)
Definition: dns_core.c:193
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ast_assert(a)
Definition: utils.h:710
#define ast_mutex_lock(a)
Definition: lock.h:187
char name[0]
The name of what is being resolved.
Definition: dns_internal.h:153
int ast_dns_resolve_ipv6_and_ipv4(struct ast_sockaddr *address, const char *host, const char *port)
Synchronously resolves host to an AAAA or A record.
Definition: dns_core.c:369
int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
Synchronously resolve a DNS query.
Definition: dns_core.c:314
#define NULL
Definition: resample.c:96
ast_cond_t cond
Condition used for signaling.
Definition: dns_core.c:282
struct ast_dns_record * dns_srv_alloc(struct ast_dns_query *query, const char *data, const size_t size)
Allocate and parse a DNS SRV record.
Definition: dns_srv.c:42
void * ast_dns_query_get_data(const struct ast_dns_query *query)
Get the user specific data of a DNS query.
Definition: dns_core.c:72
static dns_alloc_fn dns_alloc_table[]
Definition: dns_core.c:518
Socket address structure.
Definition: netsock2.h:97
const char * canonical
The canonical name.
Definition: dns_internal.h:127
#define ast_cond_signal(cond)
Definition: lock.h:201
const char * name
The name of the resolver implementation.
Definition: dns_resolver.h:34
#define ast_verb(level,...)
Definition: logger.h:455
struct ast_dns_record * dns_txt_alloc(struct ast_dns_query *query, const char *data, const size_t size)
Allocate and parse a DNS TXT record.
Definition: dns_txt.c:38
pthread_cond_t ast_cond_t
Definition: lock.h:176
#define ao2_bump(obj)
Definition: astobj2.h:491
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
DNS TLSA Record Parsing API.
struct ast_dns_query_active * ast_dns_resolve_async(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
Asynchronously resolve a DNS query.
Definition: dns_core.c:247
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
Definition: dns_core.c:630
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
struct ast_dns_result * result
The result from the query.
Definition: dns_core.c:286
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
const struct ast_dns_record * ast_dns_record_get_next(const struct ast_dns_record *record)
Get the next DNS record.
Definition: dns_core.c:170
struct ast_dns_query * ast_dns_query_set_get(const struct ast_dns_query_set *query_set, unsigned int index)
Retrieve a query from a query set.
unsigned int ast_dns_result_get_bogus(const struct ast_dns_result *result)
Get whether the result is bogus or not.
Definition: dns_core.c:87
Scheduler Routines (derived from cheops)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_dns_record_get_rr_class(const struct ast_dns_record *record)
Get the resource record class of a DNS record.
Definition: dns_core.c:150
void ast_dns_result_free(struct ast_dns_result *result)
Free the DNS result information.
Definition: dns_core.c:130
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
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
int ast_dns_record_get_rr_type(const struct ast_dns_record *record)
Get the resource record type of a DNS record.
Definition: dns_core.c:145
A set of macros to manage forward-linked lists.
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
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:609
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
static int answer(void *data)
Definition: chan_pjsip.c:682
void * ast_dns_resolver_get_data(const struct ast_dns_query *query)
Retrieve resolver specific data.
Definition: dns_core.c:451
#define ARRAY_LEN(a)
Definition: utils.h:639
Network socket handling.
static struct ast_dns_record * allocate_dns_record(unsigned int rr_type, struct ast_dns_query *query, const char *data, const size_t size)
Definition: dns_core.c:524
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
char data[0]
The raw DNS record.
Definition: dns_internal.h:60
The result of a DNS query.
Definition: dns_internal.h:117
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:236
static void dns_query_destroy(void *data)
Destructor for a DNS query.
Definition: dns_core.c:184
void * user_data
User-specific data.
Definition: dns_internal.h:141
unsigned int completed
Whether the query has completed.
Definition: dns_core.c:284
int ast_dns_resolve_cancel(struct ast_dns_query_active *active)
Cancel an asynchronous DNS resolution.
Definition: dns_core.c:272
static void dns_synchronous_resolve_destroy(void *data)
Destructor for synchronous resolution structure.
Definition: dns_core.c:290
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
int dns_parse_string(char *cur, uint8_t *size, char **val)
Parse a DNS string from a DNS record.
Definition: dns_core.c:734
An active DNS query.
Definition: dns_internal.h:201
size_t data_len
The size of the raw DNS record.
Definition: dns_internal.h:47
int ast_dns_record_get_ttl(const struct ast_dns_record *record)
Get the TTL of a DNS record.
Definition: dns_core.c:155
struct ast_dns_result * result
Result of the DNS query.
Definition: dns_internal.h:147
char buf[0]
Buffer for dynamic data.
Definition: dns_internal.h:133
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
int(* resolve)(struct ast_dns_query *query)
Perform resolution of a DNS query.
Definition: dns_resolver.h:45
#define ast_cond_destroy(cond)
Definition: lock.h:200
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
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
DNS resolver implementation.
Definition: dns_resolver.h:32
Internal DNS structure definitions.
ast_dns_resolve_callback callback
Callback to invoke upon completion.
Definition: dns_internal.h:139
#define ast_free(a)
Definition: astmm.h:182
A DNS query.
Definition: dns_internal.h:137
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
unsigned int bogus
Whether the result is bogus.
Definition: dns_internal.h:121
Prototypes for public functions only of internal interest,.
struct ast_sched_context * ast_dns_get_sched(void)
Retrieve the DNS scheduler context.
Definition: dns_core.c:52
unsigned int priority
Priority for this resolver if multiple exist, lower being higher priority.
Definition: dns_resolver.h:37
unsigned int ast_dns_result_get_rcode(const struct ast_dns_result *result)
Get the error rcode of a DN result.
Definition: dns_core.c:92
struct ast_dns_resolver * resolver
The resolver in use for this query.
Definition: dns_internal.h:143
static struct ast_sched_context * sched
Definition: dns_core.c:50
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
struct ast_dns_record * dns_naptr_alloc(struct ast_dns_query *query, const char *data, const size_t size)
Allocate and parse a DNS NAPTR record.
Definition: dns_naptr.c:380
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
unsigned int ast_dns_result_get_secure(const struct ast_dns_result *result)
Get whether the result is secure or not.
Definition: dns_core.c:82
int ast_dns_query_set_add(struct ast_dns_query_set *query_set, const char *name, int rr_type, int rr_class)
Add a query to a query set.
static void dns_query_active_destroy(void *data)
Destructor for an active DNS query.
Definition: dns_core.c:176
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
struct ast_dns_record *(* dns_alloc_fn)(struct ast_dns_query *query, const char *data, const size_t size)
Definition: dns_core.c:516
static PGresult * result
Definition: cel_pgsql.c:88
struct ast_dns_record::@240 list
Linked list information.
int ast_dns_result_get_lowest_ttl(const struct ast_dns_result *result)
Retrieve the lowest TTL from a result.
Definition: dns_core.c:112
void * resolver_data
Resolver-specific data.
Definition: dns_internal.h:145
char * dns_find_record(const char *record, size_t record_size, const char *response, size_t response_size)
Find the location of a DNS record within the entire DNS answer.
Definition: dns_core.c:701
static dns_sort_fn dns_sort_table[]
Definition: dns_core.c:587
size_t answer_size
The size of the raw DNS answer.
Definition: dns_internal.h:131
DNS SRV Record Parsing API.
static void sort_result(int rr_type, struct ast_dns_result *result)
Definition: dns_core.c:592
ast_mutex_t lock
Lock used for signaling.
Definition: dns_core.c:280
#define ast_mutex_init(pmutex)
Definition: lock.h:184
int ttl
Time-to-live of the record.
Definition: dns_internal.h:45
size_t ast_dns_query_set_num_queries(const struct ast_dns_query_set *query_set)
Retrieve the number of queries in a query set.
#define AST_RWLIST_FIRST
Definition: linkedlists.h:422
#define ast_mutex_destroy(a)
Definition: lock.h:186
const char * answer
The raw DNS answer.
Definition: dns_internal.h:129
static struct ast_dns_record * generic_record_alloc(struct ast_dns_query *query, const char *data, const size_t size)
Definition: dns_core.c:502
struct ast_dns_result::dns_records records
int rr_type
Resource record type.
Definition: dns_internal.h:41
A set of DNS queries.
Definition: dns_internal.h:185
DNS Resolver API.
const struct ast_dns_record * ast_dns_result_get_records(const struct ast_dns_result *result)
Get the first record of a DNS Result.
Definition: dns_core.c:102
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:269
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616
Structure for mutex and tracking information.
Definition: lock.h:135
Core DNS API.
DNS Recurring Resolution API.
#define ast_mutex_unlock(a)
Definition: lock.h:188
int(* cancel)(struct ast_dns_query *query)
Cancel resolution of a DNS query.
Definition: dns_resolver.h:48
int rr_class
Resource record class.
Definition: dns_internal.h:43