45 #include <netinet/in.h> 46 #include <arpa/nameser.h> 198 ast_log(
LOG_WARNING,
"Could not perform asynchronous resolution, no name provided\n");
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",
204 }
else if (rr_type < 0) {
205 ast_log(
LOG_WARNING,
"Could not perform asynchronous resolution of '%s', invalid resource record type '%d'\n",
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",
212 }
else if (rr_class < 0) {
213 ast_log(
LOG_WARNING,
"Could not perform asynchronous resolution of '%s', invalid resource class '%d'\n",
216 }
else if (!callback) {
217 ast_log(
LOG_WARNING,
"Could not perform asynchronous resolution of '%s', no callback provided\n",
231 strcpy(query->
name, name);
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);
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",
338 }
else if (!result) {
339 ast_log(
LOG_WARNING,
"Could not perform synchronous resolution of '%s', no result pointer provided for storing results\n",
363 *result = synchronous->
result;
366 return *result ? 0 : -1;
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));
416 address->
len =
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));
426 address->
len =
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",
543 }
else if (rr_type > 65536) {
544 ast_debug(2,
"Query '%p': Could not add record, resource record type '%d' exceeds maximum\n",
547 }
else if (rr_class < 0) {
548 ast_debug(2,
"Query '%p': Could not add record, invalid resource record class '%d'\n",
551 }
else if (rr_class > 65536) {
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",
578 memcpy(record->
data_ptr, data, size);
638 ast_log(
LOG_ERROR,
"Registration of DNS resolver failed as it does not have a name\n");
640 }
else if (!resolver->
resolve) {
641 ast_log(
LOG_ERROR,
"DNS resolver '%s' does not implement the resolve callback which is required\n",
644 }
else if (!resolver->
cancel) {
645 ast_log(
LOG_ERROR,
"DNS resolver '%s' does not implement the cancel callback which is required\n",
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);
675 ast_verb(2,
"Registered DNS resolver '%s' with priority '%d'\n", resolver->
name, resolver->
priority);
690 if (resolver == iter) {
698 ast_verb(2,
"Unregistered DNS resolver '%s'\n", resolver->
name);
701 char *
dns_find_record(
const char *record,
size_t record_size,
const char *response,
size_t response_size)
703 size_t remaining_size = response_size;
704 const char *search_base = response;
708 record_offset = memchr(search_base, record[0], remaining_size);
711 ast_assert(search_base + remaining_size - record_offset >= record_size);
713 if (!memcmp(record_offset, record, record_size)) {
714 return record_offset;
717 remaining_size -= record_offset - search_base;
718 search_base = record_offset + 1;
730 *val = (cur[1] << 0) | (cur[0] << 8);
void(* dns_sort_fn)(struct ast_dns_result *result)
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
const char * ast_dns_result_get_canonical(const struct ast_dns_result *result)
Get the canonical name of the result.
const char * ast_dns_record_get_data(const struct ast_dns_record *record)
Retrieve the raw DNS record.
struct sockaddr_storage ss
struct ast_dns_query * query
The underlying DNS query.
int ast_dns_resolver_set_data(struct ast_dns_query *query, void *data)
Set resolver specific data on a query.
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.
#define AST_LIST_FIRST(head)
Returns the first entry contained 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...
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.
void dns_srv_sort(struct ast_dns_result *result)
Sort the SRV records on a result.
static void dns_shutdown(void)
void dns_naptr_sort(struct ast_dns_result *result)
Sort the NAPTR records on a result.
void(* ast_dns_resolve_callback)(const struct ast_dns_query *query)
Callback invoked when a query completes.
char * data_ptr
pointer to record-specific data.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
unsigned int rcode
Optional rcode, set if an error occurred.
Structure used for signaling back for synchronous resolution completion.
int rr_type
Resource record type.
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.
unsigned int secure
Whether the result is secure.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
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_resolver_unregister(struct ast_dns_resolver *resolver)
Unregister a DNS resolver.
int dns_parse_short(unsigned char *cur, uint16_t *val)
Parse a 16-bit unsigned value from a DNS record.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
int rr_class
Resource record class.
struct ast_dns_query_set * ast_dns_query_set_create(void)
Create a query set to hold queries.
const char * ast_dns_result_get_answer(const struct ast_dns_result *result)
Get the raw DNS answer from a DNS result.
#define ast_cond_wait(cond, mutex)
#define ast_cond_init(cond, attr)
struct ast_dns_record::@253 list
Linked list information.
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)
#define ao2_alloc_options(data_size, destructor_fn, options)
#define ast_mutex_lock(a)
char name[0]
The name of what is being resolved.
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.
int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
Synchronously resolve a DNS query.
ast_cond_t cond
Condition used for signaling.
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 * ast_dns_query_get_data(const struct ast_dns_query *query)
Get the user specific data of a DNS query.
static dns_alloc_fn dns_alloc_table[]
Socket address structure.
const char * canonical
The canonical name.
#define ast_cond_signal(cond)
const char * name
The name of the resolver implementation.
#define ast_verb(level,...)
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.
pthread_cond_t ast_cond_t
#define ast_strlen_zero(foo)
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define ast_debug(level,...)
Log a DEBUG message.
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.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
struct ast_dns_result * result
The result from the query.
const struct ast_dns_record * ast_dns_record_get_next(const struct ast_dns_record *record)
Get the next DNS 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.
unsigned int ast_dns_result_get_bogus(const struct ast_dns_result *result)
Get whether the result is bogus or not.
Scheduler Routines (derived from cheops)
#define ao2_ref(o, delta)
int ast_dns_record_get_rr_class(const struct ast_dns_record *record)
Get the resource record class of a DNS record.
void ast_dns_result_free(struct ast_dns_result *result)
Free the DNS result information.
#define AST_RWLIST_REMOVE_CURRENT
const char * ast_dns_query_get_name(const struct ast_dns_query *query)
Get the name queried in a DNS query.
int ast_dns_record_get_rr_type(const struct ast_dns_record *record)
Get the resource record type of a DNS record.
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.
#define AST_RWLIST_INSERT_BEFORE_CURRENT
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
static int answer(void *data)
void * ast_dns_resolver_get_data(const struct ast_dns_query *query)
Retrieve resolver specific data.
static struct ast_dns_record * allocate_dns_record(unsigned int rr_type, struct ast_dns_query *query, const char *data, const size_t size)
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
char data[0]
The raw DNS record.
The result of a DNS query.
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
static void dns_query_destroy(void *data)
Destructor for a DNS query.
void * user_data
User-specific data.
unsigned int completed
Whether the query has completed.
int ast_dns_resolve_cancel(struct ast_dns_query_active *active)
Cancel an asynchronous DNS resolution.
static void dns_synchronous_resolve_destroy(void *data)
Destructor for synchronous resolution structure.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
int dns_parse_string(char *cur, uint8_t *size, char **val)
Parse a DNS string from a DNS record.
size_t data_len
The size of the raw DNS record.
int ast_dns_record_get_ttl(const struct ast_dns_record *record)
Get the TTL of a DNS record.
struct ast_dns_result * result
Result of the DNS query.
char buf[0]
Buffer for dynamic data.
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(* resolve)(struct ast_dns_query *query)
Perform resolution of a DNS query.
#define ast_cond_destroy(cond)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
struct ast_dns_result * ast_dns_query_get_result(const struct ast_dns_query *query)
Get the result information for a DNS query.
DNS resolver implementation.
Internal DNS structure definitions.
ast_dns_resolve_callback callback
Callback to invoke upon completion.
#define ast_calloc(num, len)
A wrapper for calloc()
unsigned int bogus
Whether the result is bogus.
Prototypes for public functions only of internal interest,.
struct ast_sched_context * ast_dns_get_sched(void)
Retrieve the DNS scheduler context.
unsigned int priority
Priority for this resolver if multiple exist, lower being higher priority.
unsigned int ast_dns_result_get_rcode(const struct ast_dns_result *result)
Get the error rcode of a DN result.
struct ast_dns_resolver * resolver
The resolver in use for this query.
static struct ast_sched_context * sched
#define AST_RWLIST_INSERT_TAIL
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.
unsigned int ast_dns_result_get_secure(const struct ast_dns_result *result)
Get whether the result is secure or not.
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.
int ast_dns_query_get_rr_type(const struct ast_dns_query *query)
Get the record resource type of a DNS query.
struct ast_dns_record *(* dns_alloc_fn)(struct ast_dns_query *query, const char *data, const size_t size)
int ast_dns_result_get_lowest_ttl(const struct ast_dns_result *result)
Retrieve the lowest TTL from a result.
void * resolver_data
Resolver-specific data.
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.
static dns_sort_fn dns_sort_table[]
size_t answer_size
The size of the raw DNS answer.
DNS SRV Record Parsing API.
static void sort_result(int rr_type, struct ast_dns_result *result)
ast_mutex_t lock
Lock used for signaling.
#define ast_mutex_init(pmutex)
int ttl
Time-to-live of the record.
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_mutex_destroy(a)
const char * answer
The raw DNS answer.
static struct ast_dns_record * generic_record_alloc(struct ast_dns_query *query, const char *data, const size_t size)
struct ast_dns_result::dns_records records
int rr_type
Resource record type.
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_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
#define AST_RWLIST_TRAVERSE_SAFE_END
Structure for mutex and tracking information.
DNS Recurring Resolution API.
#define ast_mutex_unlock(a)
int(* cancel)(struct ast_dns_query *query)
Cancel resolution of a DNS query.
int rr_class
Resource record class.