45#include <netinet/in.h>
46#include <arpa/nameser.h>
198 ast_log(
LOG_WARNING,
"Could not perform asynchronous resolution, no name provided\n");
201 ast_log(
LOG_WARNING,
"Could not perform asynchronous resolution of '%s', resource record type '%d' exceeds maximum\n",
205 ast_log(
LOG_WARNING,
"Could not perform asynchronous resolution of '%s', invalid resource record type '%d'\n",
209 ast_log(
LOG_WARNING,
"Could not perform asynchronous resolution of '%s', resource record class '%d' exceeds maximum\n",
213 ast_log(
LOG_WARNING,
"Could not perform asynchronous resolution of '%s', invalid resource class '%d'\n",
217 ast_log(
LOG_WARNING,
"Could not perform asynchronous resolution of '%s', no callback provided\n",
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",
257 if (!active->
query) {
263 ast_log(
LOG_ERROR,
"Resolver '%s' returned an error when resolving '%s' of class '%d' and type '%d'\n",
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",
326 }
else if (rr_type < 0) {
327 ast_log(
LOG_WARNING,
"Could not perform synchronous resolution of '%s', invalid resource record type '%d'\n",
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",
334 }
else if (rr_class < 0) {
335 ast_log(
LOG_WARNING,
"Could not perform synchronous resolution of '%s', invalid resource class '%d'\n",
339 ast_log(
LOG_WARNING,
"Could not perform synchronous resolution of '%s', no result pointer provided for storing results\n",
398 in_port_t in_port = 0;
401 in_port = htons(atoi(port));
409 if (
rr_type == ns_t_aaaa && data_size == 16) {
410 struct sockaddr_in6 sin6 = { 0, };
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));
419 }
else if (rr_type == ns_t_a && data_size == 4) {
420 struct sockaddr_in sin4 = { 0, };
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));
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);
457 unsigned int rcode,
const char *canonical,
const char *
answer,
size_t answer_size)
461 if (secure && bogus) {
462 ast_debug(2,
"Query '%p': Could not set result information, it can not be both secure and bogus\n",
468 ast_debug(2,
"Query '%p': Could not set result information since no canonical name was provided\n",
476 ast_debug(2,
"Query '%p': Assuming zero-sized answer on NULL input\n", query);
491 strcpy(buf_ptr, canonical);
494 buf_ptr += strlen(canonical) + 1;
495 memcpy(buf_ptr,
answer, answer_size);
506 record =
ast_calloc(1,
sizeof(*record) + size);
532 return allocator(query,
data, size);
540 ast_debug(2,
"Query '%p': Could not add record, invalid resource record type '%d'\n",
544 ast_debug(2,
"Query '%p': Could not add record, resource record type '%d' exceeds maximum\n",
548 ast_debug(2,
"Query '%p': Could not add record, invalid resource record class '%d'\n",
552 ast_debug(2,
"Query '%p': Could not add record, resource record class '%d' exceeds maximum\n",
555 }
else if (
ttl < 0) {
556 ast_debug(2,
"Query '%p': Could not add record, invalid TTL '%d'\n",
559 }
else if (!
data || !size) {
560 ast_debug(2,
"Query '%p': Could not add record, no data specified\n",
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",
640 ast_log(
LOG_ERROR,
"Registration of DNS resolver failed as it does not have a name\n");
642 }
else if (!resolver->
resolve) {
643 ast_log(
LOG_ERROR,
"DNS resolver '%s' does not implement the resolve callback which is required\n",
646 }
else if (!resolver->
cancel) {
647 ast_log(
LOG_ERROR,
"DNS resolver '%s' does not implement the cancel callback which is required\n",
655 if (!strcmp(iter->
name, resolver->
name)) {
656 ast_log(
LOG_ERROR,
"A DNS resolver with the name '%s' is already registered\n", resolver->
name);
677 ast_verb(5,
"Registered DNS resolver '%s' with priority '%d'\n", resolver->
name, resolver->
priority);
692 if (resolver == iter) {
700 ast_verb(5,
"Unregistered DNS resolver '%s'\n", resolver->
name);
703char *
dns_find_record(
const char *record,
size_t record_size,
const char *response,
size_t response_size)
705 size_t remaining_size = response_size;
706 const char *search_base = response;
710 record_offset = memchr(search_base, record[0], remaining_size);
713 ast_assert(search_base + remaining_size - record_offset >= record_size);
715 if (!memcmp(record_offset, record, record_size)) {
716 return record_offset;
719 remaining_size -= record_offset - search_base;
720 search_base = record_offset + 1;
732 *
val = (cur[1] << 0) | (cur[0] << 8);
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.
#define ast_calloc(num, len)
A wrapper for calloc()
@ AO2_ALLOC_OPT_LOCK_NOLOCK
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_alloc_options(data_size, destructor_fn, options)
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
static int answer(void *data)
int ast_dns_resolver_set_data(struct ast_dns_query *query, void *data)
Set resolver specific data on a query.
int ast_dns_query_get_rr_type(const struct ast_dns_query *query)
Get the record resource type of a DNS query.
static void dns_synchronous_resolve_callback(const struct ast_dns_query *query)
Callback used to implement synchronous resolution.
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.
int ast_dns_record_get_rr_class(const struct ast_dns_record *record)
Get the resource record class of a DNS record.
struct ast_dns_record *(* dns_alloc_fn)(struct ast_dns_query *query, const char *data, const size_t size)
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.
int ast_dns_record_get_ttl(const struct ast_dns_record *record)
Get the TTL of a DNS record.
static struct ast_sched_context * sched
const struct ast_dns_record * ast_dns_record_get_next(const struct ast_dns_record *record)
Get the next DNS record.
void ast_dns_resolver_completed(struct ast_dns_query *query)
Mark a DNS query as having been completed.
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.
int ast_dns_resolve_cancel(struct ast_dns_query_active *active)
Cancel an asynchronous DNS resolution.
struct ast_sched_context * ast_dns_get_sched(void)
Retrieve the DNS scheduler context.
int ast_dns_query_get_rr_class(const struct ast_dns_query *query)
Get the record resource class of a DNS query.
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.
static struct ast_dns_record * generic_record_alloc(struct ast_dns_query *query, const char *data, const size_t size)
void(* dns_sort_fn)(struct ast_dns_result *result)
static dns_sort_fn dns_sort_table[]
int ast_dns_result_get_lowest_ttl(const struct ast_dns_result *result)
Retrieve the lowest TTL from a result.
const char * ast_dns_result_get_canonical(const struct ast_dns_result *result)
Get the canonical name of the result.
unsigned int ast_dns_result_get_rcode(const struct ast_dns_result *result)
Get the error rcode of a DN result.
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)
const char * ast_dns_record_get_data(const struct ast_dns_record *record)
Retrieve the raw DNS record.
void * ast_dns_resolver_get_data(const struct ast_dns_query *query)
Retrieve resolver specific data.
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
static struct ast_dns_record * allocate_dns_record(unsigned int rr_type, struct ast_dns_query *query, const char *data, const size_t size)
static void dns_synchronous_resolve_destroy(void *data)
Destructor for synchronous resolution structure.
const struct ast_dns_record * ast_dns_result_get_records(const struct ast_dns_result *result)
Get the first record of a DNS Result.
void * ast_dns_query_get_data(const struct ast_dns_query *query)
Get the user specific data of a DNS query.
void ast_dns_result_free(struct ast_dns_result *result)
Free the DNS result information.
int dns_parse_short(unsigned char *cur, uint16_t *val)
Parse a 16-bit unsigned value from a DNS record.
struct ast_dns_result * ast_dns_query_get_result(const struct ast_dns_query *query)
Get the result information for a DNS query.
int dns_parse_string(char *cur, uint8_t *size, char **val)
Parse a DNS string from a DNS record.
int ast_dns_record_get_rr_type(const struct ast_dns_record *record)
Get the resource record type of a DNS record.
unsigned int ast_dns_result_get_bogus(const struct ast_dns_result *result)
Get whether the result is bogus or not.
int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
Synchronously resolve a DNS query.
static void dns_shutdown(void)
unsigned int ast_dns_result_get_secure(const struct ast_dns_result *result)
Get whether the result is secure or not.
const char * ast_dns_query_get_name(const struct ast_dns_query *query)
Get the name queried in a DNS query.
static dns_alloc_fn dns_alloc_table[]
static void sort_result(int rr_type, struct ast_dns_result *result)
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.
static void dns_query_active_destroy(void *data)
Destructor for an active DNS query.
const char * ast_dns_result_get_answer(const struct ast_dns_result *result)
Get the raw DNS answer from a DNS result.
void ast_dns_resolver_unregister(struct ast_dns_resolver *resolver)
Unregister a DNS resolver.
static void dns_query_destroy(void *data)
Destructor for a DNS query.
size_t ast_dns_record_get_data_size(const struct ast_dns_record *record)
Retrieve the size of the raw DNS record.
void(* ast_dns_resolve_callback)(const struct ast_dns_query *query)
Callback invoked when a query completes.
Internal DNS structure definitions.
void dns_naptr_sort(struct ast_dns_result *result)
Sort the NAPTR records on a result.
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.
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.
void dns_srv_sort(struct ast_dns_result *result)
Sort the SRV records on a result.
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.
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 SRV Record Parsing API.
DNS TLSA Record Parsing API.
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
A set of macros to manage forward-linked lists.
#define AST_RWLIST_REMOVE_CURRENT
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
#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_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)
#define ast_cond_wait(cond, mutex)
#define ast_cond_init(cond, attr)
#define ast_mutex_init(pmutex)
#define ast_mutex_unlock(a)
pthread_cond_t ast_cond_t
#define ast_mutex_destroy(a)
#define ast_mutex_lock(a)
#define ast_cond_signal(cond)
Scheduler Routines (derived from cheops)
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
String manipulation functions.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
struct ast_dns_query * query
The underlying 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.
int ttl
Time-to-live of the record.
char data[0]
The raw DNS record.
struct ast_dns_record::@215 list
Linked list information.
int rr_class
Resource record class.
int rr_type
Resource record type.
size_t data_len
The size of the raw DNS record.
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.
Socket address structure.
Structure used for signaling back for synchronous resolution completion.
ast_cond_t cond
Condition used for signaling.
struct ast_dns_result * result
The result from the query.
ast_mutex_t lock
Lock used for signaling.
unsigned int completed
Whether the query has completed.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.