Asterisk - The Open Source Telephony Project GIT-master-4c84066
Loading...
Searching...
No Matches
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 ast_debug(2, "Calling %s resolver for name: %s class: %d type: %d", active->query->resolver->name,
262 name, rr_class, rr_type);
263 if (active->query->resolver->resolve(active->query)) {
264 ast_log(LOG_ERROR, "Resolver '%s' returned an error when resolving '%s' of class '%d' and type '%d'\n",
265 active->query->resolver->name, name, rr_class, rr_type);
266 ao2_ref(active, -1);
267 return NULL;
268 }
269
270 return active;
271}
272
274{
275 return active->query->resolver->cancel(active->query);
276}
277
278/*! \brief Structure used for signaling back for synchronous resolution completion */
280 /*! \brief Lock used for signaling */
282 /*! \brief Condition used for signaling */
284 /*! \brief Whether the query has completed */
285 unsigned int completed;
286 /*! \brief The result from the query */
288};
289
290/*! \brief Destructor for synchronous resolution structure */
291static void dns_synchronous_resolve_destroy(void *data)
292{
293 struct dns_synchronous_resolve *synchronous = data;
294
295 ast_mutex_destroy(&synchronous->lock);
296 ast_cond_destroy(&synchronous->cond);
297
298 /* This purposely does not unref result as it has been passed to the caller */
299}
300
301/*! \brief Callback used to implement synchronous resolution */
302static void dns_synchronous_resolve_callback(const struct ast_dns_query *query)
303{
304 struct dns_synchronous_resolve *synchronous = ast_dns_query_get_data(query);
305
306 synchronous->result = query->result;
307 ((struct ast_dns_query *)query)->result = NULL;
308
309 ast_mutex_lock(&synchronous->lock);
310 synchronous->completed = 1;
311 ast_cond_signal(&synchronous->cond);
312 ast_mutex_unlock(&synchronous->lock);
313}
314
315int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
316{
317 struct dns_synchronous_resolve *synchronous;
318 struct ast_dns_query_active *active;
319
320 if (ast_strlen_zero(name)) {
321 ast_log(LOG_WARNING, "Could not perform synchronous resolution, no name provided\n");
322 return -1;
323 } else if (rr_type > 65536) {
324 ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', resource record type '%d' exceeds maximum\n",
325 name, rr_type);
326 return -1;
327 } else if (rr_type < 0) {
328 ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', invalid resource record type '%d'\n",
329 name, rr_type);
330 return -1;
331 } else if (rr_class > 65536) {
332 ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', resource record class '%d' exceeds maximum\n",
333 name, rr_class);
334 return -1;
335 } else if (rr_class < 0) {
336 ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', invalid resource class '%d'\n",
337 name, rr_class);
338 return -1;
339 } else if (!result) {
340 ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', no result pointer provided for storing results\n",
341 name);
342 return -1;
343 }
344
346 if (!synchronous) {
347 return -1;
348 }
349
350 ast_mutex_init(&synchronous->lock);
351 ast_cond_init(&synchronous->cond, NULL);
352
353 active = ast_dns_resolve_async(name, rr_type, rr_class, dns_synchronous_resolve_callback, synchronous);
354 if (active) {
355 /* Wait for resolution to complete */
356 ast_mutex_lock(&synchronous->lock);
357 while (!synchronous->completed) {
358 ast_cond_wait(&synchronous->cond, &synchronous->lock);
359 }
360 ast_mutex_unlock(&synchronous->lock);
361 ao2_ref(active, -1);
362 }
363
364 *result = synchronous->result;
365 ao2_ref(synchronous, -1);
366
367 return *result ? 0 : -1;
368}
369
370int ast_dns_resolve_ipv6_and_ipv4(struct ast_sockaddr *address, const char *host, const char *port)
371{
373 int i;
374 int rc;
375
376 if (!queries) {
377 ast_log(LOG_ERROR, "Couldn't allocate DNS query structure\n");
378 return -1;
379 }
380 rc = ast_dns_query_set_add(queries, host, ns_t_aaaa, ns_c_in);
381 if (rc != 0) {
382 ast_log(LOG_ERROR, "Couldn't add 'AAAA' DNS query for '%s'\n", host);
383 return -1;
384 }
385 rc = ast_dns_query_set_add(queries, host, ns_t_a, ns_c_in);
386 if (rc != 0) {
387 ast_log(LOG_ERROR, "Couldn't add 'A' DNS query for '%s'\n", host);
388 return -1;
389 }
391 if (rc != 0) {
392 ast_log(LOG_ERROR, "Query set resolve failure for '%s'\n", host);
393 return -1;
394 }
395 for (i = 0; i < ast_dns_query_set_num_queries(queries); ++i) {
396 struct ast_dns_query *query = ast_dns_query_set_get(queries, i);
398 const struct ast_dns_record *record;
399 in_port_t in_port = 0;
400
401 if (!ast_strlen_zero(port)) {
402 in_port = htons(atoi(port));
403 }
404
405 for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) {
406 size_t data_size = ast_dns_record_get_data_size(record);
407 const unsigned char *data = (unsigned char *)ast_dns_record_get_data(record);
409
410 if (rr_type == ns_t_aaaa && data_size == 16) {
411 struct sockaddr_in6 sin6 = { 0, };
412
413 sin6.sin6_port = in_port;
414 memcpy(&sin6.sin6_addr, data, data_size);
415 sin6.sin6_family = AF_INET6;
416 memcpy(&address->ss, &sin6, sizeof(sin6));
417 address->len = sizeof(sin6);
418
419 return 0;
420 } else if (rr_type == ns_t_a && data_size == 4) {
421 struct sockaddr_in sin4 = { 0, };
422
423 sin4.sin_port = in_port;
424 memcpy(&sin4.sin_addr, data, data_size);
425 sin4.sin_family = AF_INET;
426 memcpy(&address->ss, &sin4, sizeof(sin4));
427 address->len = sizeof(sin4);
428
429 return 0;
430 } else {
431 ast_debug(3, "Unrecognized rr_type '%u' or data_size '%zu' from DNS query for host '%s'\n",
432 rr_type, data_size, host);
433 continue;
434 }
435 }
436 }
437
438 return -1;
439}
440
441int ast_dns_resolver_set_data(struct ast_dns_query *query, void *data)
442{
443 if (query->resolver_data) {
444 return -1;
445 }
446
447 query->resolver_data = ao2_bump(data);
448
449 return 0;
450}
451
452void *ast_dns_resolver_get_data(const struct ast_dns_query *query)
453{
454 return query->resolver_data;
455}
456
457int ast_dns_resolver_set_result(struct ast_dns_query *query, unsigned int secure, unsigned int bogus,
458 unsigned int rcode, const char *canonical, const char *answer, size_t answer_size)
459{
460 char *buf_ptr;
461
462 if (secure && bogus) {
463 ast_debug(2, "Query '%p': Could not set result information, it can not be both secure and bogus\n",
464 query);
465 return -1;
466 }
467
468 if (ast_strlen_zero(canonical)) {
469 ast_debug(2, "Query '%p': Could not set result information since no canonical name was provided\n",
470 query);
471 return -1;
472 }
473
474 if (!answer) {
475 answer = "";
476 answer_size = 0;
477 ast_debug(2, "Query '%p': Assuming zero-sized answer on NULL input\n", query);
478 }
479
481
482 query->result = ast_calloc(1, sizeof(*query->result) + strlen(canonical) + 1 + answer_size);
483 if (!query->result) {
484 return -1;
485 }
486
487 query->result->secure = secure;
488 query->result->bogus = bogus;
489 query->result->rcode = rcode;
490
491 buf_ptr = query->result->buf;
492 strcpy(buf_ptr, canonical); /* SAFE */
493 query->result->canonical = buf_ptr;
494
495 buf_ptr += strlen(canonical) + 1;
496 memcpy(buf_ptr, answer, answer_size); /* SAFE */
497 query->result->answer = buf_ptr;
498 query->result->answer_size = answer_size;
499
500 return 0;
501}
502
503static struct ast_dns_record *generic_record_alloc(struct ast_dns_query *query, const char *data, const size_t size)
504{
505 struct ast_dns_record *record;
506
507 record = ast_calloc(1, sizeof(*record) + size);
508 if (!record) {
509 return NULL;
510 }
511
512 record->data_ptr = record->data;
513
514 return record;
515}
516
517typedef struct ast_dns_record *(*dns_alloc_fn)(struct ast_dns_query *query, const char *data, const size_t size);
518
520 [T_TXT] = dns_txt_alloc,
521 [T_NAPTR] = dns_naptr_alloc,
522 [T_SRV] = dns_srv_alloc,
523};
524
525static struct ast_dns_record *allocate_dns_record(unsigned int rr_type, struct ast_dns_query *query, const char *data, const size_t size)
526{
528
530 allocator = dns_alloc_table[rr_type];
531 }
532
533 return allocator(query, data, size);
534}
535
536int 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)
537{
538 struct ast_dns_record *record;
539
540 if (rr_type < 0) {
541 ast_debug(2, "Query '%p': Could not add record, invalid resource record type '%d'\n",
542 query, rr_type);
543 return -1;
544 } else if (rr_type > 65536) {
545 ast_debug(2, "Query '%p': Could not add record, resource record type '%d' exceeds maximum\n",
546 query, rr_type);
547 return -1;
548 } else if (rr_class < 0) {
549 ast_debug(2, "Query '%p': Could not add record, invalid resource record class '%d'\n",
550 query, rr_class);
551 return -1;
552 } else if (rr_class > 65536) {
553 ast_debug(2, "Query '%p': Could not add record, resource record class '%d' exceeds maximum\n",
554 query, rr_class);
555 return -1;
556 } else if (ttl < 0) {
557 ast_debug(2, "Query '%p': Could not add record, invalid TTL '%d'\n",
558 query, ttl);
559 return -1;
560 } else if (!data || !size) {
561 ast_debug(2, "Query '%p': Could not add record, no data specified\n",
562 query);
563 return -1;
564 } else if (!query->result) {
565 ast_debug(2, "Query '%p': No result was set on the query, thus records can not be added\n",
566 query);
567 return -1;
568 }
569
570 record = allocate_dns_record(rr_type, query, data, size);
571 if (!record) {
572 return -1;
573 }
574
575 record->rr_type = rr_type;
576 record->rr_class = rr_class;
577 record->ttl = ttl;
578 record->data_len = size;
579 memcpy(record->data_ptr, data, size);
580
581 AST_LIST_INSERT_TAIL(&query->result->records, record, list);
582
583 return 0;
584}
585
586typedef void (*dns_sort_fn)(struct ast_dns_result *result);
587
589 [T_NAPTR] = dns_naptr_sort,
590 [T_SRV] = dns_srv_sort,
591};
592
593static void sort_result(int rr_type, struct ast_dns_result *result)
594{
595 if (dns_sort_table[rr_type]) {
596 dns_sort_table[rr_type](result);
597 }
598}
599
601{
602 if (query->result) {
604 }
605
606 query->callback(query);
607}
608
609static void dns_shutdown(void)
610{
611 if (sched) {
613 sched = NULL;
614 }
615}
616
618{
620 if (!sched) {
621 return -1;
622 }
623
625 return -1;
626 }
627
629
630 return 0;
631}
632
634{
635 struct ast_dns_resolver *iter;
636 int inserted = 0;
637
638 if (!resolver) {
639 return -1;
640 } else if (ast_strlen_zero(resolver->name)) {
641 ast_log(LOG_ERROR, "Registration of DNS resolver failed as it does not have a name\n");
642 return -1;
643 } else if (!resolver->resolve) {
644 ast_log(LOG_ERROR, "DNS resolver '%s' does not implement the resolve callback which is required\n",
645 resolver->name);
646 return -1;
647 } else if (!resolver->cancel) {
648 ast_log(LOG_ERROR, "DNS resolver '%s' does not implement the cancel callback which is required\n",
649 resolver->name);
650 return -1;
651 }
652
654
655 AST_LIST_TRAVERSE(&resolvers, iter, next) {
656 if (!strcmp(iter->name, resolver->name)) {
657 ast_log(LOG_ERROR, "A DNS resolver with the name '%s' is already registered\n", resolver->name);
659 return -1;
660 }
661 }
662
664 if (iter->priority > resolver->priority) {
665 AST_RWLIST_INSERT_BEFORE_CURRENT(resolver, next);
666 inserted = 1;
667 break;
668 }
669 }
671
672 if (!inserted) {
673 AST_RWLIST_INSERT_TAIL(&resolvers, resolver, next);
674 }
675
677
678 ast_verb(5, "Registered DNS resolver '%s' with priority '%d'\n", resolver->name, resolver->priority);
679
680 return 0;
681}
682
684{
685 struct ast_dns_resolver *iter;
686
687 if (!resolver) {
688 return;
689 }
690
693 if (resolver == iter) {
695 break;
696 }
697 }
700
701 ast_verb(5, "Unregistered DNS resolver '%s'\n", resolver->name);
702}
703
704char *dns_find_record(const char *record, size_t record_size, const char *response, size_t response_size)
705{
706 size_t remaining_size = response_size;
707 const char *search_base = response;
708 char *record_offset;
709
710 while (1) {
711 record_offset = memchr((void *)search_base, record[0], remaining_size);
712
713 ast_assert(record_offset != NULL);
714 ast_assert(search_base + remaining_size - record_offset >= record_size);
715
716 if (!memcmp(record_offset, record, record_size)) {
717 return record_offset;
718 }
719
720 remaining_size -= record_offset - search_base;
721 search_base = record_offset + 1;
722 }
723}
724
725int dns_parse_short(unsigned char *cur, uint16_t *val)
726{
727 /* This assignment takes a big-endian 16-bit value and stores it in the
728 * machine's native byte order. Using this method allows us to avoid potential
729 * alignment issues in case the order is not on a short-addressable boundary.
730 * See http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html for
731 * more information
732 */
733 *val = (cur[1] << 0) | (cur[0] << 8);
734 return sizeof(*val);
735}
736
737int dns_parse_string(char *cur, uint8_t *size, char **val)
738{
739 *size = *cur++;
740 *val = cur;
741 return *size + 1;
742}
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:687
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int rdlock)
int ast_dns_resolver_set_data(struct ast_dns_query *query, void *data)
Set resolver specific data on a query.
Definition dns_core.c:441
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:302
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:704
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:517
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:457
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:600
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:273
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:370
static struct ast_dns_record * generic_record_alloc(struct ast_dns_query *query, const char *data, const size_t size)
Definition dns_core.c:503
void(* dns_sort_fn)(struct ast_dns_result *result)
Definition dns_core.c:586
static dns_sort_fn dns_sort_table[]
Definition dns_core.c:588
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:452
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
Definition dns_core.c:633
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:525
static void dns_synchronous_resolve_destroy(void *data)
Destructor for synchronous resolution structure.
Definition dns_core.c:291
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:725
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:737
int dns_core_init(void)
Definition dns_core.c:617
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:315
static void dns_shutdown(void)
Definition dns_core.c:609
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:519
static void sort_result(int rr_type, struct ast_dns_result *result)
Definition dns_core.c:593
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:536
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:683
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.
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
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition linkedlists.h:78
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#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.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_RWLIST_FIRST
#define AST_RWLIST_TRAVERSE_SAFE_END
#define AST_RWLIST_INSERT_TAIL
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_RWLIST_INSERT_BEFORE_CURRENT
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
#define ast_cond_destroy(cond)
Definition lock.h:209
#define ast_cond_wait(cond, mutex)
Definition lock.h:212
#define ast_cond_init(cond, attr)
Definition lock.h:208
#define ast_mutex_init(pmutex)
Definition lock.h:193
#define ast_mutex_unlock(a)
Definition lock.h:197
pthread_cond_t ast_cond_t
Definition lock.h:185
#define ast_mutex_destroy(a)
Definition lock.h:195
#define ast_mutex_lock(a)
Definition lock.h:196
#define ast_cond_signal(cond)
Definition lock.h:210
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.
struct ast_dns_query * query
The underlying DNS query.
A set of DNS queries.
A DNS query.
void * user_data
User-specific data.
void * resolver_data
Resolver-specific data.
ast_dns_resolve_callback callback
Callback to invoke upon completion.
struct ast_dns_resolver * resolver
The resolver in use for this query.
struct ast_dns_result * result
Result of the DNS query.
int rr_class
Resource record class.
int rr_type
Resource record type.
char name[0]
The name of what is being resolved.
For AST_LIST.
int ttl
Time-to-live of the record.
char data[0]
The raw DNS record.
int rr_class
Resource record class.
int rr_type
Resource record type.
size_t data_len
The size of the raw DNS record.
struct ast_dns_record::@224 list
Linked list information.
char * data_ptr
pointer to record-specific data.
DNS resolver implementation.
unsigned int priority
Priority for this resolver if multiple exist, lower being higher priority.
int(* cancel)(struct ast_dns_query *query)
Cancel resolution of a DNS query.
const char * name
The name of the resolver implementation.
int(* resolve)(struct ast_dns_query *query)
Perform resolution of a DNS query.
The result of a DNS query.
char buf[0]
Buffer for dynamic data.
struct ast_dns_result::dns_records records
const char * canonical
The canonical name.
size_t answer_size
The size of the raw DNS answer.
unsigned int bogus
Whether the result is bogus.
unsigned int secure
Whether the result is secure.
const char * answer
The raw DNS answer.
unsigned int rcode
Optional rcode, set if an error occurred.
Structure for mutex and tracking information.
Definition lock.h:142
Socket address structure.
Definition netsock2.h:97
Structure used for signaling back for synchronous resolution completion.
Definition dns_core.c:279
ast_cond_t cond
Condition used for signaling.
Definition dns_core.c:283
struct ast_dns_result * result
The result from the query.
Definition dns_core.c:287
ast_mutex_t lock
Lock used for signaling.
Definition dns_core.c:281
unsigned int completed
Whether the query has completed.
Definition dns_core.c:285
Definition sched.c:76
#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:981
#define ast_assert(a)
Definition utils.h:779
#define ARRAY_LEN(a)
Definition utils.h:706