Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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"
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"
43#include "asterisk/netsock2.h"
44
45#include <netinet/in.h>
46#include <arpa/nameser.h>
47
49
50static struct ast_sched_context *sched;
51
53{
54 return sched;
55}
56
57const char *ast_dns_query_get_name(const struct ast_dns_query *query)
58{
59 return query->name;
60}
61
63{
64 return query->rr_type;
65}
66
68{
69 return query->rr_class;
70}
71
72void *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
83{
84 return result->secure;
85}
86
88{
89 return result->bogus;
90}
91
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
143}
144
146{
147 return record->rr_type;
148}
149
151{
152 return record->rr_class;
153}
154
155int ast_dns_record_get_ttl(const struct ast_dns_record *record)
156{
157 return record->ttl;
158}
159
160const char *ast_dns_record_get_data(const struct ast_dns_record *record)
161{
162 return record->data_ptr;
163}
164
166{
167 return record->data_len;
168}
169
170const 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 */
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 */
184static void dns_query_destroy(void *data)
185{
186 struct ast_dns_query *query = data;
187
188 ao2_cleanup(query->user_data);
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",
240 ao2_ref(query, -1);
241 return NULL;
242 }
243
244 return query;
245}
246
247struct 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 */
290static 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 */
301static 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
314int 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
369int 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);
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
440int 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
451void *ast_dns_resolver_get_data(const struct ast_dns_query *query)
452{
453 return query->resolver_data;
454}
455
456int 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
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
502static 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
516typedef 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
524static 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
529 allocator = dns_alloc_table[rr_type];
530 }
531
532 return allocator(query, data, size);
533}
534
535int 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
585typedef void (*dns_sort_fn)(struct ast_dns_result *result);
586
588 [T_NAPTR] = dns_naptr_sort,
589 [T_SRV] = dns_srv_sort,
590};
591
592static 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
606static void dns_shutdown(void)
607{
608 if (sched) {
610 sched = NULL;
611 }
612}
613
615{
617 if (!sched) {
618 return -1;
619 }
620
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(5, "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(5, "Unregistered DNS resolver '%s'\n", resolver->name);
699}
700
701char *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
722int 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
734int dns_parse_string(char *cur, uint8_t *size, char **val)
735{
736 *size = *cur++;
737 *val = cur;
738 return *size + 1;
739}
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_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static PGresult * result
Definition: cel_pgsql.c:84
static int answer(void *data)
Definition: chan_pjsip.c:683
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
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
static void dns_synchronous_resolve_callback(const struct ast_dns_query *query)
Callback used to implement synchronous resolution.
Definition: dns_core.c:301
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
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
struct ast_dns_record *(* dns_alloc_fn)(struct ast_dns_query *query, const char *data, const size_t size)
Definition: dns_core.c:516
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 ast_dns_record_get_ttl(const struct ast_dns_record *record)
Get the TTL of a DNS record.
Definition: dns_core.c:155
static struct ast_sched_context * sched
Definition: dns_core.c:50
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
void ast_dns_resolver_completed(struct ast_dns_query *query)
Mark a DNS query as having been completed.
Definition: dns_core.c:599
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_dns_resolve_cancel(struct ast_dns_query_active *active)
Cancel an asynchronous DNS resolution.
Definition: dns_core.c:272
struct ast_sched_context * ast_dns_get_sched(void)
Retrieve the DNS scheduler context.
Definition: dns_core.c:52
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
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
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
void(* dns_sort_fn)(struct ast_dns_result *result)
Definition: dns_core.c:585
static dns_sort_fn dns_sort_table[]
Definition: dns_core.c:587
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
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
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_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
const char * ast_dns_record_get_data(const struct ast_dns_record *record)
Retrieve the raw DNS record.
Definition: dns_core.c:160
void * ast_dns_resolver_get_data(const struct ast_dns_query *query)
Retrieve resolver specific data.
Definition: dns_core.c:451
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
Definition: dns_core.c:630
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
static void dns_synchronous_resolve_destroy(void *data)
Destructor for synchronous resolution structure.
Definition: dns_core.c:290
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_dns_query_get_data(const struct ast_dns_query *query)
Get the user specific data of a DNS query.
Definition: dns_core.c:72
void ast_dns_result_free(struct ast_dns_result *result)
Free the DNS result information.
Definition: dns_core.c:130
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
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 dns_parse_string(char *cur, uint8_t *size, char **val)
Parse a DNS string from a DNS record.
Definition: dns_core.c:734
int dns_core_init(void)
Definition: dns_core.c:614
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
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
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
static void dns_shutdown(void)
Definition: dns_core.c:606
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
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
static dns_alloc_fn dns_alloc_table[]
Definition: dns_core.c:518
static void sort_result(int rr_type, struct ast_dns_result *result)
Definition: dns_core.c:592
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
static void dns_query_active_destroy(void *data)
Destructor for an active DNS query.
Definition: dns_core.c:176
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
void ast_dns_resolver_unregister(struct ast_dns_resolver *resolver)
Unregister a DNS resolver.
Definition: dns_core.c:680
static void dns_query_destroy(void *data)
Destructor for a DNS query.
Definition: dns_core.c:184
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
Core DNS API.
void(* ast_dns_resolve_callback)(const struct ast_dns_query *query)
Callback invoked when a query completes.
Definition: dns_core.h:171
Internal DNS structure definitions.
void dns_naptr_sort(struct ast_dns_result *result)
Sort the NAPTR records on a result.
Definition: dns_naptr.c:551
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
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 dns_srv_sort(struct ast_dns_result *result)
Sort the SRV records on a result.
Definition: dns_srv.c:113
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
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.
struct ast_dns_query_set * ast_dns_query_set_create(void)
Create a query set to hold queries.
Definition: dns_query_set.c:60
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.
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.
int ast_query_set_resolve(struct ast_dns_query_set *query_set)
Synchronously resolve queries in a query set.
DNS Recurring Resolution API.
DNS Resolver API.
DNS SRV Record Parsing API.
DNS TLSA Record Parsing API.
char * address
Definition: f2c.h:59
static const char name[]
Definition: format_mp3.c:68
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_WARNING
A set of macros to manage forward-linked lists.
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#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:333
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_RWLIST_FIRST
Definition: linkedlists.h:423
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:610
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
#define ast_cond_destroy(cond)
Definition: lock.h:202
#define ast_cond_wait(cond, mutex)
Definition: lock.h:205
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_init(pmutex)
Definition: lock.h:186
#define ast_mutex_unlock(a)
Definition: lock.h:190
pthread_cond_t ast_cond_t
Definition: lock.h:178
#define ast_mutex_destroy(a)
Definition: lock.h:188
#define ast_mutex_lock(a)
Definition: lock.h:189
#define ast_cond_signal(cond)
Definition: lock.h:203
Network socket handling.
#define NULL
Definition: resample.c:96
Scheduler Routines (derived from cheops)
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:271
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Definition: sched.c:197
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:238
String manipulation functions.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
An active DNS query.
Definition: dns_internal.h:201
struct ast_dns_query * query
The underlying DNS query.
Definition: dns_internal.h:203
A set of DNS queries.
Definition: dns_internal.h:185
A DNS query.
Definition: dns_internal.h:137
void * user_data
User-specific data.
Definition: dns_internal.h:141
void * resolver_data
Resolver-specific data.
Definition: dns_internal.h:145
ast_dns_resolve_callback callback
Callback to invoke upon completion.
Definition: dns_internal.h:139
struct ast_dns_resolver * resolver
The resolver in use for this query.
Definition: dns_internal.h:143
struct ast_dns_result * result
Result of the DNS query.
Definition: dns_internal.h:147
int rr_class
Resource record class.
Definition: dns_internal.h:151
int rr_type
Resource record type.
Definition: dns_internal.h:149
char name[0]
The name of what is being resolved.
Definition: dns_internal.h:153
For AST_LIST.
Definition: dns_internal.h:39
int ttl
Time-to-live of the record.
Definition: dns_internal.h:45
char data[0]
The raw DNS record.
Definition: dns_internal.h:60
struct ast_dns_record::@215 list
Linked list information.
int rr_class
Resource record class.
Definition: dns_internal.h:43
int rr_type
Resource record type.
Definition: dns_internal.h:41
size_t data_len
The size of the raw DNS record.
Definition: dns_internal.h:47
char * data_ptr
pointer to record-specific data.
Definition: dns_internal.h:58
DNS resolver implementation.
Definition: dns_resolver.h:32
unsigned int priority
Priority for this resolver if multiple exist, lower being higher priority.
Definition: dns_resolver.h:37
int(* cancel)(struct ast_dns_query *query)
Cancel resolution of a DNS query.
Definition: dns_resolver.h:48
const char * name
The name of the resolver implementation.
Definition: dns_resolver.h:34
int(* resolve)(struct ast_dns_query *query)
Perform resolution of a DNS query.
Definition: dns_resolver.h:45
The result of a DNS query.
Definition: dns_internal.h:117
char buf[0]
Buffer for dynamic data.
Definition: dns_internal.h:133
struct ast_dns_result::dns_records records
const char * canonical
The canonical name.
Definition: dns_internal.h:127
size_t answer_size
The size of the raw DNS answer.
Definition: dns_internal.h:131
unsigned int bogus
Whether the result is bogus.
Definition: dns_internal.h:121
unsigned int secure
Whether the result is secure.
Definition: dns_internal.h:119
const char * answer
The raw DNS answer.
Definition: dns_internal.h:129
unsigned int rcode
Optional rcode, set if an error occurred.
Definition: dns_internal.h:123
Structure for mutex and tracking information.
Definition: lock.h:135
Socket address structure.
Definition: netsock2.h:97
Structure used for signaling back for synchronous resolution completion.
Definition: dns_core.c:278
ast_cond_t cond
Condition used for signaling.
Definition: dns_core.c:282
struct ast_dns_result * result
The result from the query.
Definition: dns_core.c:286
ast_mutex_t lock
Lock used for signaling.
Definition: dns_core.c:280
unsigned int completed
Whether the query has completed.
Definition: dns_core.c:284
Definition: sched.c:76
Definition: ast_expr2.c:325
#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:941
#define ast_assert(a)
Definition: utils.h:739
#define ARRAY_LEN(a)
Definition: utils.h:666