Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Typedefs | Functions | Variables
dns_core.c File Reference

Core DNS Functionality. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/linkedlists.h"
#include "asterisk/astobj2.h"
#include "asterisk/strings.h"
#include "asterisk/sched.h"
#include "asterisk/dns_core.h"
#include "asterisk/dns_srv.h"
#include "asterisk/dns_tlsa.h"
#include "asterisk/dns_recurring.h"
#include "asterisk/dns_resolver.h"
#include "asterisk/dns_internal.h"
#include "asterisk/netsock2.h"
#include <netinet/in.h>
#include <arpa/nameser.h>
Include dependency graph for dns_core.c:

Go to the source code of this file.

Data Structures

struct  dns_synchronous_resolve
 Structure used for signaling back for synchronous resolution completion. More...
 
struct  resolvers
 

Typedefs

typedef struct ast_dns_record *(* dns_alloc_fn) (struct ast_dns_query *query, const char *data, const size_t size)
 
typedef void(* dns_sort_fn) (struct ast_dns_result *result)
 

Functions

static struct ast_dns_recordallocate_dns_record (unsigned int rr_type, struct ast_dns_query *query, const char *data, const size_t size)
 
struct ast_sched_contextast_dns_get_sched (void)
 Retrieve the DNS scheduler context. More...
 
void * ast_dns_query_get_data (const struct ast_dns_query *query)
 Get the user specific data of a DNS query. More...
 
const char * ast_dns_query_get_name (const struct ast_dns_query *query)
 Get the name queried in a DNS query. More...
 
struct ast_dns_resultast_dns_query_get_result (const struct ast_dns_query *query)
 Get the result information for a DNS query. More...
 
int ast_dns_query_get_rr_class (const struct ast_dns_query *query)
 Get the record resource class of a DNS query. More...
 
int ast_dns_query_get_rr_type (const struct ast_dns_query *query)
 Get the record resource type of a DNS query. More...
 
const char * ast_dns_record_get_data (const struct ast_dns_record *record)
 Retrieve the raw DNS record. More...
 
size_t ast_dns_record_get_data_size (const struct ast_dns_record *record)
 Retrieve the size of the raw DNS record. More...
 
const struct ast_dns_recordast_dns_record_get_next (const struct ast_dns_record *record)
 Get the next DNS record. More...
 
int ast_dns_record_get_rr_class (const struct ast_dns_record *record)
 Get the resource record class of a DNS record. More...
 
int ast_dns_record_get_rr_type (const struct ast_dns_record *record)
 Get the resource record type of a DNS record. More...
 
int ast_dns_record_get_ttl (const struct ast_dns_record *record)
 Get the TTL of a DNS record. More...
 
int ast_dns_resolve (const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
 Synchronously resolve a DNS query. More...
 
struct ast_dns_query_activeast_dns_resolve_async (const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
 Asynchronously resolve a DNS query. More...
 
int ast_dns_resolve_cancel (struct ast_dns_query_active *active)
 Cancel an asynchronous DNS resolution. More...
 
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. More...
 
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. More...
 
void ast_dns_resolver_completed (struct ast_dns_query *query)
 Mark a DNS query as having been completed. More...
 
void * ast_dns_resolver_get_data (const struct ast_dns_query *query)
 Retrieve resolver specific data. More...
 
int ast_dns_resolver_register (struct ast_dns_resolver *resolver)
 Register a DNS resolver. More...
 
int ast_dns_resolver_set_data (struct ast_dns_query *query, void *data)
 Set resolver specific data on a query. More...
 
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. More...
 
void ast_dns_resolver_unregister (struct ast_dns_resolver *resolver)
 Unregister a DNS resolver. More...
 
void ast_dns_result_free (struct ast_dns_result *result)
 Free the DNS result information. More...
 
const char * ast_dns_result_get_answer (const struct ast_dns_result *result)
 Get the raw DNS answer from a DNS result. More...
 
unsigned int ast_dns_result_get_bogus (const struct ast_dns_result *result)
 Get whether the result is bogus or not. More...
 
const char * ast_dns_result_get_canonical (const struct ast_dns_result *result)
 Get the canonical name of the result. More...
 
int ast_dns_result_get_lowest_ttl (const struct ast_dns_result *result)
 Retrieve the lowest TTL from a result. More...
 
unsigned int ast_dns_result_get_rcode (const struct ast_dns_result *result)
 Get the error rcode of a DN result. More...
 
const struct ast_dns_recordast_dns_result_get_records (const struct ast_dns_result *result)
 Get the first record of a DNS Result. More...
 
unsigned int ast_dns_result_get_secure (const struct ast_dns_result *result)
 Get whether the result is secure or not. More...
 
int dns_core_init (void)
 
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. More...
 
int dns_parse_short (unsigned char *cur, uint16_t *val)
 Parse a 16-bit unsigned value from a DNS record. More...
 
int dns_parse_string (char *cur, uint8_t *size, char **val)
 Parse a DNS string from a DNS record. More...
 
static void dns_query_active_destroy (void *data)
 Destructor for an active DNS query. More...
 
struct ast_dns_querydns_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) More...
 
static void dns_query_destroy (void *data)
 Destructor for a DNS query. More...
 
static void dns_shutdown (void)
 
static void dns_synchronous_resolve_callback (const struct ast_dns_query *query)
 Callback used to implement synchronous resolution. More...
 
static void dns_synchronous_resolve_destroy (void *data)
 Destructor for synchronous resolution structure. More...
 
static struct ast_dns_recordgeneric_record_alloc (struct ast_dns_query *query, const char *data, const size_t size)
 
static void sort_result (int rr_type, struct ast_dns_result *result)
 

Variables

static dns_alloc_fn dns_alloc_table []
 
static dns_sort_fn dns_sort_table []
 
struct resolvers resolvers = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static struct ast_sched_contextsched
 

Detailed Description

Core DNS Functionality.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file dns_core.c.

Typedef Documentation

◆ dns_alloc_fn

typedef struct ast_dns_record*(* dns_alloc_fn) (struct ast_dns_query *query, const char *data, const size_t size)

Definition at line 516 of file dns_core.c.

◆ dns_sort_fn

typedef void(* dns_sort_fn) (struct ast_dns_result *result)

Definition at line 585 of file dns_core.c.

Function Documentation

◆ allocate_dns_record()

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

Definition at line 524 of file dns_core.c.

References ARRAY_LEN, dns_alloc_table, generic_record_alloc(), and ast_dns_record::rr_type.

Referenced by ast_dns_resolver_add_record().

525 {
527 
528  if (rr_type < ARRAY_LEN(dns_alloc_table) && dns_alloc_table[rr_type]) {
529  allocator = dns_alloc_table[rr_type];
530  }
531 
532  return allocator(query, data, size);
533 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static dns_alloc_fn dns_alloc_table[]
Definition: dns_core.c:518
struct ast_dns_record *(* dns_alloc_fn)(struct ast_dns_query *query, const char *data, const size_t size)
Definition: dns_core.c:516
static struct ast_dns_record * generic_record_alloc(struct ast_dns_query *query, const char *data, const size_t size)
Definition: dns_core.c:502

◆ ast_dns_get_sched()

struct ast_sched_context* ast_dns_get_sched ( void  )

Retrieve the DNS scheduler context.

Returns
scheduler context

Definition at line 52 of file dns_core.c.

References sched.

Referenced by ast_dns_resolve_recurring(), ast_dns_resolve_recurring_cancel(), and dns_query_recurring_resolution_callback().

53 {
54  return sched;
55 }
static struct ast_sched_context * sched
Definition: dns_core.c:50

◆ ast_dns_query_get_data()

void* ast_dns_query_get_data ( const struct ast_dns_query query)

Get the user specific data of a DNS query.

Parameters
queryThe DNS query
Returns
the user specific data
Note
The reference count of the data is NOT incremented on return

Definition at line 72 of file dns_core.c.

References ast_dns_query::user_data.

Referenced by async_callback(), dns_query_recurring_resolution_callback(), dns_query_set_callback(), dns_synchronous_resolve_callback(), minimal_callback(), off_nominal_async_callback(), query_set_cancel(), query_set_resolve(), recurring_cancel(), recurring_resolve(), and resolution_thread().

73 {
74  return query->user_data;
75 }
void * user_data
User-specific data.
Definition: dns_internal.h:141

◆ ast_dns_query_get_name()

const char* ast_dns_query_get_name ( const struct ast_dns_query query)

Get the name queried in a DNS query.

Parameters
queryThe DNS query
Returns
the name queried

Definition at line 57 of file dns_core.c.

References ast_dns_query::name.

Referenced by dns_system_resolver_process_query(), dns_system_resolver_resolve(), dns_system_resolver_set_response(), query_set_test(), sip_resolve_callback(), unbound_resolver_callback(), and unbound_resolver_resolve().

58 {
59  return query->name;
60 }
char name[0]
The name of what is being resolved.
Definition: dns_internal.h:153

◆ ast_dns_query_get_result()

struct ast_dns_result* ast_dns_query_get_result ( const struct ast_dns_query query)

Get the result information for a DNS query.

Parameters
queryThe DNS query
Returns
the DNS result information
Note
The result is NOT ao2 allocated

Definition at line 77 of file dns_core.c.

References ast_dns_query::result.

Referenced by ast_dns_resolve_ipv6_and_ipv4(), AST_TEST_DEFINE(), async_callback(), dns_query_recurring_resolution_callback(), dns_system_resolver_set_response(), off_nominal_async_callback(), sip_resolve_callback(), and test_results().

78 {
79  return query->result;
80 }
struct ast_dns_result * result
Result of the DNS query.
Definition: dns_internal.h:147

◆ ast_dns_query_get_rr_class()

int ast_dns_query_get_rr_class ( const struct ast_dns_query query)

Get the record resource class of a DNS query.

Parameters
queryThe DNS query
Returns
the record resource class

Definition at line 67 of file dns_core.c.

References ast_dns_query::rr_class.

Referenced by dns_system_resolver_add_record(), dns_system_resolver_process_query(), query_set_test(), and unbound_resolver_resolve().

68 {
69  return query->rr_class;
70 }
int rr_class
Resource record class.
Definition: dns_internal.h:151

◆ ast_dns_query_get_rr_type()

int ast_dns_query_get_rr_type ( const struct ast_dns_query query)

Get the record resource type of a DNS query.

Parameters
queryThe DNS query
Returns
the record resource type

Definition at line 62 of file dns_core.c.

References ast_dns_query::rr_type.

Referenced by ast_dns_resolver_completed(), dns_system_resolver_add_record(), dns_system_resolver_process_query(), query_set_test(), sip_resolve_callback(), and unbound_resolver_resolve().

63 {
64  return query->rr_type;
65 }
int rr_type
Resource record type.
Definition: dns_internal.h:149

◆ ast_dns_record_get_data()

const char* ast_dns_record_get_data ( const struct ast_dns_record record)

Retrieve the raw DNS record.

Parameters
recordThe DNS record
Returns
the raw DNS record

Definition at line 160 of file dns_core.c.

References ast_dns_record::data_ptr.

Referenced by ast_dns_resolve_ipv6_and_ipv4(), ast_dns_txt_get_strings(), async_callback(), nominal_sync_run(), sip_resolve_callback(), and test_record().

161 {
162  return record->data_ptr;
163 }
char * data_ptr
pointer to record-specific data.
Definition: dns_internal.h:58

◆ ast_dns_record_get_data_size()

size_t ast_dns_record_get_data_size ( const struct ast_dns_record record)

Retrieve the size of the raw DNS record.

Parameters
recordThe DNS record
Returns
the size of the raw DNS record

Definition at line 165 of file dns_core.c.

References ast_dns_record::data_len.

Referenced by ast_dns_resolve_ipv6_and_ipv4(), ast_dns_txt_get_strings(), and sip_resolve_callback().

166 {
167  return record->data_len;
168 }
size_t data_len
The size of the raw DNS record.
Definition: dns_internal.h:47

◆ ast_dns_record_get_next()

const struct ast_dns_record* ast_dns_record_get_next ( const struct ast_dns_record record)

Get the next DNS record.

Parameters
recordThe current DNS record
Returns
the next DNS record

Definition at line 170 of file dns_core.c.

References AST_LIST_NEXT, and ast_dns_record::list.

Referenced by ast_dns_resolve_ipv6_and_ipv4(), ast_dns_result_get_lowest_ttl(), AST_TEST_DEFINE(), async_callback(), nominal_sync_run(), nominal_test(), and sip_resolve_callback().

171 {
172  return AST_LIST_NEXT(record, list);
173 }
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438

◆ ast_dns_record_get_rr_class()

int ast_dns_record_get_rr_class ( const struct ast_dns_record record)

Get the resource record class of a DNS record.

Parameters
recordThe DNS record
Returns
the resource record class

Definition at line 150 of file dns_core.c.

References ast_dns_record::rr_class.

Referenced by async_callback(), nominal_sync_run(), and test_record().

151 {
152  return record->rr_class;
153 }
int rr_class
Resource record class.
Definition: dns_internal.h:43

◆ ast_dns_record_get_rr_type()

int ast_dns_record_get_rr_type ( const struct ast_dns_record record)

◆ ast_dns_record_get_ttl()

int ast_dns_record_get_ttl ( const struct ast_dns_record record)

Get the TTL of a DNS record.

Parameters
recordThe DNS record
Returns
the TTL

Definition at line 155 of file dns_core.c.

References ast_dns_record::ttl.

Referenced by ast_dns_result_get_lowest_ttl(), async_callback(), nominal_sync_run(), and test_record().

156 {
157  return record->ttl;
158 }
int ttl
Time-to-live of the record.
Definition: dns_internal.h:45

◆ ast_dns_resolve()

int ast_dns_resolve ( const char *  name,
int  rr_type,
int  rr_class,
struct ast_dns_result **  result 
)

Synchronously resolve a DNS query.

Parameters
nameThe name of what to resolve
rr_typeResource record type
rr_classResource record class
resultA pointer to hold the DNS result
Return values
0success - query was completed and result is available
-1failure

Definition at line 314 of file dns_core.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, ast_cond_init, ast_cond_wait, ast_dns_resolve_async(), ast_log, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero, dns_synchronous_resolve::completed, dns_synchronous_resolve::cond, dns_synchronous_resolve_callback(), dns_synchronous_resolve_destroy(), dns_synchronous_resolve::lock, LOG_WARNING, NULL, and dns_synchronous_resolve::result.

Referenced by AST_TEST_DEFINE(), invalid_record_test(), nominal_sync_run(), nominal_test(), off_nominal_sync_run(), and off_nominal_test().

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 }
static void dns_synchronous_resolve_callback(const struct ast_dns_query *query)
Callback used to implement synchronous resolution.
Definition: dns_core.c:301
Structure used for signaling back for synchronous resolution completion.
Definition: dns_core.c:278
#define LOG_WARNING
Definition: logger.h:274
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
ast_cond_t cond
Condition used for signaling.
Definition: dns_core.c:282
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
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
struct ast_dns_result * result
The result from the query.
Definition: dns_core.c:286
#define ao2_ref(o, delta)
Definition: astobj2.h:464
unsigned int completed
Whether the query has completed.
Definition: dns_core.c:284
static void dns_synchronous_resolve_destroy(void *data)
Destructor for synchronous resolution structure.
Definition: dns_core.c:290
An active DNS query.
Definition: dns_internal.h:201
static const char name[]
Definition: cdr_mysql.c:74
ast_mutex_t lock
Lock used for signaling.
Definition: dns_core.c:280
#define ast_mutex_init(pmutex)
Definition: lock.h:184
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ ast_dns_resolve_async()

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.

Parameters
nameThe name of what to resolve
rr_typeResource record type
rr_classResource record class
callbackThe callback to invoke upon completion
dataUser data to make available on the query
Return values
non-NULLsuccess - query has been sent for resolution
NULLfailure
Note
The result passed to the callback does not need to be freed
The user data MUST be an ao2 object
This function increments the reference count of the user data, it does NOT steal
The active query must be released upon completion or cancellation using ao2_ref

Definition at line 247 of file dns_core.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, ast_log, dns_query_active_destroy(), dns_query_alloc(), LOG_ERROR, ast_dns_resolver::name, NULL, ast_dns_query_active::query, ast_dns_resolver::resolve, and ast_dns_query::resolver.

Referenced by ast_dns_resolve(), ast_dns_resolve_recurring(), AST_TEST_DEFINE(), dns_query_recurring_scheduled_callback(), nominal_async_run(), and off_nominal_async_run().

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 }
struct ast_dns_query * query
The underlying DNS query.
Definition: dns_internal.h:203
struct ast_dns_query * dns_query_alloc(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
Allocate a DNS query (but do not start resolution)
Definition: dns_core.c:193
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
const char * name
The name of the resolver implementation.
Definition: dns_resolver.h:34
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define LOG_ERROR
Definition: logger.h:285
An active DNS query.
Definition: dns_internal.h:201
int(* resolve)(struct ast_dns_query *query)
Perform resolution of a DNS query.
Definition: dns_resolver.h:45
static const char name[]
Definition: cdr_mysql.c:74
struct ast_dns_resolver * resolver
The resolver in use for this query.
Definition: dns_internal.h:143
static void dns_query_active_destroy(void *data)
Destructor for an active DNS query.
Definition: dns_core.c:176

◆ ast_dns_resolve_cancel()

int ast_dns_resolve_cancel ( struct ast_dns_query_active active)

Cancel an asynchronous DNS resolution.

Parameters
activeThe active DNS query returned from ast_dns_resolve_async
Return values
0success
-1failure
Note
If successfully cancelled the callback will not be invoked

Definition at line 272 of file dns_core.c.

References ast_dns_resolver::cancel, ast_dns_query_active::query, and ast_dns_query::resolver.

Referenced by ast_dns_resolve_recurring_cancel(), and AST_TEST_DEFINE().

273 {
274  return active->query->resolver->cancel(active->query);
275 }
struct ast_dns_query * query
The underlying DNS query.
Definition: dns_internal.h:203
struct ast_dns_resolver * resolver
The resolver in use for this query.
Definition: dns_internal.h:143
int(* cancel)(struct ast_dns_query *query)
Cancel resolution of a DNS query.
Definition: dns_resolver.h:48

◆ ast_dns_resolve_ipv6_and_ipv4()

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.

Since
16.6.0
Parameters
addressA pointer to an ast_sockaddr structure to receive the IPv6 or IPv4 address
hostThe hostname to resolve
port(optional) A port to parse into the final ast_sockaddr structure
Return values
0success - query was completed and result is available
-1failure
Note
This function makes parallel queries for both AAAA and A records for the host. The first returned AAAA record (if any) is used and if not found, the first A record is used.
Warning
This function is synchronous and will block until records are returned or an error occurrs.

Definition at line 369 of file dns_core.c.

References ao2_cleanup, ast_debug, ast_dns_query_get_result(), ast_dns_query_set_add(), ast_dns_query_set_create(), ast_dns_query_set_get(), ast_dns_query_set_num_queries(), ast_dns_record_get_data(), ast_dns_record_get_data_size(), ast_dns_record_get_next(), ast_dns_record_get_rr_type(), ast_dns_result_get_records(), ast_log, ast_query_set_resolve(), ast_strlen_zero, ast_dns_record::data, ast_sockaddr::len, LOG_ERROR, RAII_VAR, dns_synchronous_resolve::result, ast_dns_record::rr_type, and ast_sockaddr::ss.

Referenced by unicast_rtp_request().

370 {
372  int i;
373  int rc;
374 
375  if (!queries) {
376  ast_log(LOG_ERROR, "Couldn't allocate DNS query structure\n");
377  return -1;
378  }
379  rc = ast_dns_query_set_add(queries, host, ns_t_aaaa, ns_c_in);
380  if (rc != 0) {
381  ast_log(LOG_ERROR, "Couldn't add 'AAAA' DNS query for '%s'\n", host);
382  return -1;
383  }
384  rc = ast_dns_query_set_add(queries, host, ns_t_a, ns_c_in);
385  if (rc != 0) {
386  ast_log(LOG_ERROR, "Couldn't add 'A' DNS query for '%s'\n", host);
387  return -1;
388  }
390  if (rc != 0) {
391  ast_log(LOG_ERROR, "Query set resolve failure for '%s'\n", host);
392  return -1;
393  }
394  for (i = 0; i < ast_dns_query_set_num_queries(queries); ++i) {
395  struct ast_dns_query *query = ast_dns_query_set_get(queries, i);
397  const struct ast_dns_record *record;
398  in_port_t in_port = 0;
399 
400  if (!ast_strlen_zero(port)) {
401  in_port = htons(atoi(port));
402  }
403 
404  for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) {
405  size_t data_size = ast_dns_record_get_data_size(record);
406  const unsigned char *data = (unsigned char *)ast_dns_record_get_data(record);
407  int rr_type = ast_dns_record_get_rr_type(record);
408 
409  if (rr_type == ns_t_aaaa && data_size == 16) {
410  struct sockaddr_in6 sin6 = { 0, };
411 
412  sin6.sin6_port = in_port;
413  memcpy(&sin6.sin6_addr, data, data_size);
414  sin6.sin6_family = AF_INET6;
415  memcpy(&address->ss, &sin6, sizeof(sin6));
416  address->len = sizeof(sin6);
417 
418  return 0;
419  } else if (rr_type == ns_t_a && data_size == 4) {
420  struct sockaddr_in sin4 = { 0, };
421 
422  sin4.sin_port = in_port;
423  memcpy(&sin4.sin_addr, data, data_size);
424  sin4.sin_family = AF_INET;
425  memcpy(&address->ss, &sin4, sizeof(sin4));
426  address->len = sizeof(sin4);
427 
428  return 0;
429  } else {
430  ast_debug(3, "Unrecognized rr_type '%u' or data_size '%zu' from DNS query for host '%s'\n",
431  rr_type, data_size, host);
432  continue;
433  }
434  }
435  }
436 
437  return -1;
438 }
const char * ast_dns_record_get_data(const struct ast_dns_record *record)
Retrieve the raw DNS record.
Definition: dns_core.c:160
struct sockaddr_storage ss
Definition: netsock2.h:98
int ast_query_set_resolve(struct ast_dns_query_set *query_set)
Synchronously resolve queries in a query set.
For AST_LIST.
Definition: dns_internal.h:39
socklen_t len
Definition: netsock2.h:99
size_t ast_dns_record_get_data_size(const struct ast_dns_record *record)
Retrieve the size of the raw DNS record.
Definition: dns_core.c:165
struct ast_dns_query_set * ast_dns_query_set_create(void)
Create a query set to hold queries.
Definition: dns_query_set.c:60
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static char host[256]
Definition: muted.c:77
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
const struct ast_dns_record * ast_dns_record_get_next(const struct ast_dns_record *record)
Get the next DNS record.
Definition: dns_core.c:170
struct ast_dns_query * ast_dns_query_set_get(const struct ast_dns_query_set *query_set, unsigned int index)
Retrieve a query from a query set.
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
char data[0]
The raw DNS record.
Definition: dns_internal.h:60
The result of a DNS query.
Definition: dns_internal.h:117
#define LOG_ERROR
Definition: logger.h:285
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
A DNS query.
Definition: dns_internal.h:137
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
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 PGresult * result
Definition: cel_pgsql.c:88
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 rr_type
Resource record type.
Definition: dns_internal.h:41
A set of DNS queries.
Definition: dns_internal.h:185
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

◆ ast_dns_resolver_add_record()

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.

Parameters
queryThe DNS query
rr_typeResource record type
rr_classResource record class
ttlTTL of the record
dataThe raw DNS record
sizeThe size of the raw DNS record
Return values
0success
-1failure

Definition at line 535 of file dns_core.c.

References allocate_dns_record(), ast_debug, AST_LIST_INSERT_TAIL, ast_dns_record::data_len, ast_dns_record::data_ptr, ast_dns_record::list, ast_dns_result::records, ast_dns_query::result, ast_dns_record::rr_class, ast_dns_record::rr_type, and ast_dns_record::ttl.

Referenced by AST_TEST_DEFINE(), dns_system_resolver_add_record(), naptr_thread(), resolution_thread(), srv_thread(), and unbound_resolver_callback().

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 }
char * data_ptr
pointer to record-specific data.
Definition: dns_internal.h:58
For AST_LIST.
Definition: dns_internal.h:39
struct ast_dns_record::@253 list
Linked list information.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
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
char data[0]
The raw DNS record.
Definition: dns_internal.h:60
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
size_t data_len
The size of the raw DNS record.
Definition: dns_internal.h:47
struct ast_dns_result * result
Result of the DNS query.
Definition: dns_internal.h:147
int ttl
Time-to-live of the record.
Definition: dns_internal.h:45
struct ast_dns_result::dns_records records
int rr_type
Resource record type.
Definition: dns_internal.h:41
int rr_class
Resource record class.
Definition: dns_internal.h:43

◆ ast_dns_resolver_completed()

void ast_dns_resolver_completed ( struct ast_dns_query query)

Mark a DNS query as having been completed.

Parameters
queryThe DNS query

Definition at line 599 of file dns_core.c.

References ast_dns_query_get_rr_type(), ast_dns_query::callback, ast_dns_query::result, and sort_result().

Referenced by dns_system_resolver_process_query(), naptr_thread(), resolution_thread(), srv_thread(), and unbound_resolver_callback().

600 {
602 
603  query->callback(query);
604 }
struct ast_dns_result * result
Result of the DNS query.
Definition: dns_internal.h:147
ast_dns_resolve_callback callback
Callback to invoke upon completion.
Definition: dns_internal.h:139
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 sort_result(int rr_type, struct ast_dns_result *result)
Definition: dns_core.c:592

◆ ast_dns_resolver_get_data()

void* ast_dns_resolver_get_data ( const struct ast_dns_query query)

Retrieve resolver specific data.

Parameters
queryThe DNS query
Returns
the resolver specific data
Note
The reference count of the resolver data is NOT incremented on return

Definition at line 451 of file dns_core.c.

References ast_dns_query::resolver_data.

Referenced by AST_TEST_DEFINE(), and unbound_resolver_cancel().

452 {
453  return query->resolver_data;
454 }
void * resolver_data
Resolver-specific data.
Definition: dns_internal.h:145

◆ ast_dns_resolver_register()

int ast_dns_resolver_register ( struct ast_dns_resolver resolver)

Register a DNS resolver.

Parameters
resolverA DNS resolver implementation
Return values
0success
-1failure

Definition at line 630 of file dns_core.c.

References AST_LIST_TRAVERSE, ast_log, AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero, ast_verb, ast_dns_resolver::cancel, LOG_ERROR, ast_dns_resolver::name, ast_dns_resolver::priority, and ast_dns_resolver::resolve.

Referenced by ast_dns_system_resolver_init(), AST_TEST_DEFINE(), invalid_record_test(), load_module(), nominal_test(), off_nominal_test(), and query_set_test().

631 {
632  struct ast_dns_resolver *iter;
633  int inserted = 0;
634 
635  if (!resolver) {
636  return -1;
637  } else if (ast_strlen_zero(resolver->name)) {
638  ast_log(LOG_ERROR, "Registration of DNS resolver failed as it does not have a name\n");
639  return -1;
640  } else if (!resolver->resolve) {
641  ast_log(LOG_ERROR, "DNS resolver '%s' does not implement the resolve callback which is required\n",
642  resolver->name);
643  return -1;
644  } else if (!resolver->cancel) {
645  ast_log(LOG_ERROR, "DNS resolver '%s' does not implement the cancel callback which is required\n",
646  resolver->name);
647  return -1;
648  }
649 
651 
652  AST_LIST_TRAVERSE(&resolvers, iter, next) {
653  if (!strcmp(iter->name, resolver->name)) {
654  ast_log(LOG_ERROR, "A DNS resolver with the name '%s' is already registered\n", resolver->name);
656  return -1;
657  }
658  }
659 
661  if (iter->priority > resolver->priority) {
662  AST_RWLIST_INSERT_BEFORE_CURRENT(resolver, next);
663  inserted = 1;
664  break;
665  }
666  }
668 
669  if (!inserted) {
670  AST_RWLIST_INSERT_TAIL(&resolvers, resolver, next);
671  }
672 
674 
675  ast_verb(2, "Registered DNS resolver '%s' with priority '%d'\n", resolver->name, resolver->priority);
676 
677  return 0;
678 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
const char * name
The name of the resolver implementation.
Definition: dns_resolver.h:34
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:609
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
#define LOG_ERROR
Definition: logger.h:285
int(* resolve)(struct ast_dns_query *query)
Perform resolution of a DNS query.
Definition: dns_resolver.h:45
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
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
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616
int(* cancel)(struct ast_dns_query *query)
Cancel resolution of a DNS query.
Definition: dns_resolver.h:48

◆ ast_dns_resolver_set_data()

int ast_dns_resolver_set_data ( struct ast_dns_query query,
void *  data 
)

Set resolver specific data on a query.

Parameters
queryThe DNS query
dataThe resolver specific data
Note
The resolver data MUST be an ao2 object
This function increments the reference count of the resolver data, it does NOT steal
Once resolver specific data has been set it can not be changed
Return values
0success
-1failure, resolver data is already set

Definition at line 440 of file dns_core.c.

References ao2_bump, and ast_dns_query::resolver_data.

Referenced by AST_TEST_DEFINE(), and unbound_resolver_resolve().

441 {
442  if (query->resolver_data) {
443  return -1;
444  }
445 
446  query->resolver_data = ao2_bump(data);
447 
448  return 0;
449 }
#define ao2_bump(obj)
Definition: astobj2.h:491
void * resolver_data
Resolver-specific data.
Definition: dns_internal.h:145

◆ ast_dns_resolver_set_result()

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.

Parameters
queryThe DNS query
resultWhether the result is secured or not
bogusWhether the result is bogus or not
rcodeOptional response code
canonicalThe canonical name
answerThe raw DNS answer
answer_sizeThe size of the raw DNS answer

Zero-sized and NULL answers are permitted by this function. This may be necessary if the query fails at an early stage and no actual DNS response has been received from a DNS server.

Return values
0success
-1failure

Definition at line 456 of file dns_core.c.

References ast_dns_result::answer, ast_dns_result::answer_size, ast_calloc, ast_debug, ast_dns_result_free(), ast_strlen_zero, ast_dns_result::bogus, ast_dns_result::buf, ast_dns_result::canonical, ast_dns_result::rcode, ast_dns_query::result, and ast_dns_result::secure.

Referenced by AST_TEST_DEFINE(), dns_system_resolver_set_response(), naptr_thread(), resolution_thread(), srv_thread(), and unbound_resolver_callback().

458 {
459  char *buf_ptr;
460 
461  if (secure && bogus) {
462  ast_debug(2, "Query '%p': Could not set result information, it can not be both secure and bogus\n",
463  query);
464  return -1;
465  }
466 
467  if (ast_strlen_zero(canonical)) {
468  ast_debug(2, "Query '%p': Could not set result information since no canonical name was provided\n",
469  query);
470  return -1;
471  }
472 
473  if (!answer) {
474  answer = "";
475  answer_size = 0;
476  ast_debug(2, "Query '%p': Assuming zero-sized answer on NULL input\n", query);
477  }
478 
479  ast_dns_result_free(query->result);
480 
481  query->result = ast_calloc(1, sizeof(*query->result) + strlen(canonical) + 1 + answer_size);
482  if (!query->result) {
483  return -1;
484  }
485 
486  query->result->secure = secure;
487  query->result->bogus = bogus;
488  query->result->rcode = rcode;
489 
490  buf_ptr = query->result->buf;
491  strcpy(buf_ptr, canonical); /* SAFE */
492  query->result->canonical = buf_ptr;
493 
494  buf_ptr += strlen(canonical) + 1;
495  memcpy(buf_ptr, answer, answer_size); /* SAFE */
496  query->result->answer = buf_ptr;
497  query->result->answer_size = answer_size;
498 
499  return 0;
500 }
unsigned int rcode
Optional rcode, set if an error occurred.
Definition: dns_internal.h:123
unsigned int secure
Whether the result is secure.
Definition: dns_internal.h:119
const char * canonical
The canonical name.
Definition: dns_internal.h:127
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
void ast_dns_result_free(struct ast_dns_result *result)
Free the DNS result information.
Definition: dns_core.c:130
static int answer(void *data)
Definition: chan_pjsip.c:682
struct ast_dns_result * result
Result of the DNS query.
Definition: dns_internal.h:147
char buf[0]
Buffer for dynamic data.
Definition: dns_internal.h:133
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
unsigned int bogus
Whether the result is bogus.
Definition: dns_internal.h:121
size_t answer_size
The size of the raw DNS answer.
Definition: dns_internal.h:131
const char * answer
The raw DNS answer.
Definition: dns_internal.h:129

◆ ast_dns_resolver_unregister()

void ast_dns_resolver_unregister ( struct ast_dns_resolver resolver)

Unregister a DNS resolver.

Parameters
resolverA DNS resolver implementation

Definition at line 680 of file dns_core.c.

References AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, and ast_dns_resolver::name.

Referenced by AST_TEST_DEFINE(), dns_system_resolver_destroy(), invalid_record_test(), nominal_test(), off_nominal_test(), and query_set_test().

681 {
682  struct ast_dns_resolver *iter;
683 
684  if (!resolver) {
685  return;
686  }
687 
690  if (resolver == iter) {
692  break;
693  }
694  }
697 
698  ast_verb(2, "Unregistered DNS resolver '%s'\n", resolver->name);
699 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
const char * name
The name of the resolver implementation.
Definition: dns_resolver.h:34
#define ast_verb(level,...)
Definition: logger.h:463
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
DNS resolver implementation.
Definition: dns_resolver.h:32
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ ast_dns_result_free()

void ast_dns_result_free ( struct ast_dns_result result)

Free the DNS result information.

Parameters
resultThe DNS result

Definition at line 130 of file dns_core.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_dns_record::list, and ast_dns_result::records.

Referenced by ast_dns_resolver_set_result(), AST_TEST_DEFINE(), dns_query_destroy(), invalid_record_test(), nominal_sync_run(), nominal_test(), off_nominal_sync_run(), and off_nominal_test().

131 {
132  struct ast_dns_record *record;
133 
134  if (!result) {
135  return;
136  }
137 
138  while ((record = AST_LIST_REMOVE_HEAD(&result->records, list))) {
139  ast_free(record);
140  }
141 
142  ast_free(result);
143 }
For AST_LIST.
Definition: dns_internal.h:39
struct ast_dns_record::@253 list
Linked list information.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
#define ast_free(a)
Definition: astmm.h:182
struct ast_dns_result::dns_records records

◆ ast_dns_result_get_answer()

const char* ast_dns_result_get_answer ( const struct ast_dns_result result)

Get the raw DNS answer from a DNS result.

Parameters
resultThe DNS result
Returns
The DNS result

Definition at line 107 of file dns_core.c.

References ast_dns_result::answer.

Referenced by test_results().

108 {
109  return result->answer;
110 }
const char * answer
The raw DNS answer.
Definition: dns_internal.h:129

◆ ast_dns_result_get_bogus()

unsigned int ast_dns_result_get_bogus ( const struct ast_dns_result result)

Get whether the result is bogus or not.

Parameters
resultThe DNS result
Returns
whether the result is bogus or not

Definition at line 87 of file dns_core.c.

References ast_dns_result::bogus.

Referenced by test_results().

88 {
89  return result->bogus;
90 }
unsigned int bogus
Whether the result is bogus.
Definition: dns_internal.h:121

◆ ast_dns_result_get_canonical()

const char* ast_dns_result_get_canonical ( const struct ast_dns_result result)

Get the canonical name of the result.

Parameters
resultThe DNS result
Returns
the canonical name

Definition at line 97 of file dns_core.c.

References ast_dns_result::canonical.

Referenced by test_results().

98 {
99  return result->canonical;
100 }
const char * canonical
The canonical name.
Definition: dns_internal.h:127

◆ ast_dns_result_get_lowest_ttl()

int ast_dns_result_get_lowest_ttl ( const struct ast_dns_result result)

Retrieve the lowest TTL from a result.

Parameters
resultThe DNS result
Returns
the lowest TTL
Note
If no records exist this function will return a TTL of 0

Definition at line 112 of file dns_core.c.

References ast_dns_record_get_next(), ast_dns_record_get_ttl(), ast_dns_result_get_rcode(), ast_dns_result_get_records(), and ast_dns_record::ttl.

Referenced by dns_query_recurring_resolution_callback().

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 }
For AST_LIST.
Definition: dns_internal.h:39
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
int ast_dns_record_get_ttl(const struct ast_dns_record *record)
Get the TTL of a DNS record.
Definition: dns_core.c:155
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
int ttl
Time-to-live of the record.
Definition: dns_internal.h:45
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

◆ ast_dns_result_get_rcode()

unsigned int ast_dns_result_get_rcode ( const struct ast_dns_result result)

Get the error rcode of a DN result.

Parameters
queryThe DNS result
Returns
the DNS rcode

Definition at line 92 of file dns_core.c.

References ast_dns_result::rcode.

Referenced by ast_dns_result_get_lowest_ttl(), off_nominal_async_callback(), off_nominal_sync_run(), and test_results().

93 {
94  return result->rcode;
95 }
unsigned int rcode
Optional rcode, set if an error occurred.
Definition: dns_internal.h:123

◆ ast_dns_result_get_records()

const struct ast_dns_record* ast_dns_result_get_records ( const struct ast_dns_result result)

Get the first record of a DNS Result.

Parameters
resultThe DNS result
Returns
first DNS record

Definition at line 102 of file dns_core.c.

References AST_LIST_FIRST, and ast_dns_result::records.

Referenced by ast_dns_resolve_ipv6_and_ipv4(), ast_dns_result_get_lowest_ttl(), AST_TEST_DEFINE(), async_callback(), invalid_record_test(), nominal_sync_run(), nominal_test(), off_nominal_async_callback(), off_nominal_sync_run(), off_nominal_test(), and sip_resolve_callback().

103 {
104  return AST_LIST_FIRST(&result->records);
105 }
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
struct ast_dns_result::dns_records records

◆ ast_dns_result_get_secure()

unsigned int ast_dns_result_get_secure ( const struct ast_dns_result result)

Get whether the result is secure or not.

Parameters
resultThe DNS result
Returns
whether the result is secure or not

Definition at line 82 of file dns_core.c.

References ast_dns_result::secure.

Referenced by test_results().

83 {
84  return result->secure;
85 }
unsigned int secure
Whether the result is secure.
Definition: dns_internal.h:119

◆ dns_core_init()

int dns_core_init ( void  )

Provided by dns_core.c

Definition at line 614 of file dns_core.c.

References ast_register_cleanup(), ast_sched_context_create(), ast_sched_start_thread(), and dns_shutdown().

Referenced by asterisk_daemon().

615 {
617  if (!sched) {
618  return -1;
619  }
620 
622  return -1;
623  }
624 
626 
627  return 0;
628 }
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Definition: sched.c:195
static void dns_shutdown(void)
Definition: dns_core.c:606
Definition: sched.c:76
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:236

◆ dns_find_record()

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.

The DNS record that has been returned by the resolver may be a copy of the record that was found in the complete DNS response. If so, then some DNS record types (specifically those that parse domains) will need to locate the DNS record within the complete DNS response. This is so that if the domain contains pointers to other sections of the DNS response, then the referenced domains may be located.

Parameters
recordThe DNS record returned by a resolver implementation
record_sizeThe size of the DNS record in bytes
responseThe complete DNS answer
response_sizeThe size of the complete DNS response

Definition at line 701 of file dns_core.c.

References ast_assert, and NULL.

Referenced by dns_naptr_alloc(), and dns_srv_alloc().

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 }
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96

◆ dns_parse_short()

int dns_parse_short ( unsigned char *  cur,
uint16_t *  val 
)

Parse a 16-bit unsigned value from a DNS record.

Parameters
curPointer to the location of the 16-bit value in the DNS record
[out]valThe parsed 16-bit unsigned integer
Returns
The number of bytes consumed while parsing

Definition at line 722 of file dns_core.c.

Referenced by dns_naptr_alloc(), and dns_srv_alloc().

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 }
Definition: ast_expr2.c:325

◆ dns_parse_string()

int dns_parse_string ( char *  cur,
uint8_t *  size,
char **  val 
)

Parse a DNS string from a DNS record.

A DNS string consists of an 8-bit size, followed by the string value (not NULL-terminated).

Parameters
curPointer to the location of the DNS string
[out]sizeThe parsed size of the DNS string
[out]valThe contained string (not NULL-terminated)
Returns
The number of bytes consumed while parsing

Definition at line 734 of file dns_core.c.

Referenced by dns_naptr_alloc().

735 {
736  *size = *cur++;
737  *val = cur;
738  return *size + 1;
739 }
Definition: ast_expr2.c:325

◆ dns_query_active_destroy()

static void dns_query_active_destroy ( void *  data)
static

Destructor for an active DNS query.

Definition at line 176 of file dns_core.c.

References ao2_cleanup, and ast_dns_query_active::query.

Referenced by ast_dns_resolve_async().

177 {
178  struct ast_dns_query_active *active = data;
179 
180  ao2_cleanup(active->query);
181 }
struct ast_dns_query * query
The underlying DNS query.
Definition: dns_internal.h:203
An active DNS query.
Definition: dns_internal.h:201
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ dns_query_alloc()

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)

Parameters
nameThe name of what to resolve
rr_typeResource record type
rr_classResource record class
callbackThe callback to invoke upon completion
dataUser data to make available on the query
Return values
non-NULLsuccess
NULLfailure
Note
The result passed to the callback does not need to be freed
The user data MUST be an ao2 object
This function increments the reference count of the user data, it does NOT steal
The query must be released upon completion or cancellation using ao2_ref

Definition at line 193 of file dns_core.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_bump, ao2_ref, ast_log, AST_RWLIST_FIRST, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_strlen_zero, ast_dns_query::callback, dns_query_destroy(), LOG_ERROR, LOG_WARNING, ast_dns_query::name, NULL, ast_dns_query::resolver, ast_dns_query::rr_class, ast_dns_query::rr_type, and ast_dns_query::user_data.

Referenced by ast_dns_query_set_add(), ast_dns_resolve_async(), and dns_query_recurring_resolution_callback().

194 {
195  struct ast_dns_query *query;
196 
197  if (ast_strlen_zero(name)) {
198  ast_log(LOG_WARNING, "Could not perform asynchronous resolution, no name provided\n");
199  return NULL;
200  } else if (rr_type > 65536) {
201  ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', resource record type '%d' exceeds maximum\n",
202  name, rr_type);
203  return NULL;
204  } else if (rr_type < 0) {
205  ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', invalid resource record type '%d'\n",
206  name, rr_type);
207  return NULL;
208  } else if (rr_class > 65536) {
209  ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', resource record class '%d' exceeds maximum\n",
210  name, rr_class);
211  return NULL;
212  } else if (rr_class < 0) {
213  ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', invalid resource class '%d'\n",
214  name, rr_class);
215  return NULL;
216  } else if (!callback) {
217  ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', no callback provided\n",
218  name);
219  return NULL;
220  }
221 
222  query = ao2_alloc_options(sizeof(*query) + strlen(name) + 1, dns_query_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
223  if (!query) {
224  return NULL;
225  }
226 
227  query->callback = callback;
228  query->user_data = ao2_bump(data);
229  query->rr_type = rr_type;
230  query->rr_class = rr_class;
231  strcpy(query->name, name); /* SAFE */
232 
236 
237  if (!query->resolver) {
238  ast_log(LOG_ERROR, "Attempted to do a DNS query for '%s' of class '%d' and type '%d' but no resolver is available\n",
239  name, rr_class, rr_type);
240  ao2_ref(query, -1);
241  return NULL;
242  }
243 
244  return query;
245 }
int rr_type
Resource record type.
Definition: dns_internal.h:149
#define LOG_WARNING
Definition: logger.h:274
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
int rr_class
Resource record class.
Definition: dns_internal.h:151
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
char name[0]
The name of what is being resolved.
Definition: dns_internal.h:153
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_bump(obj)
Definition: astobj2.h:491
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void * user_data
User-specific data.
Definition: dns_internal.h:141
static void dns_query_destroy(void *data)
Destructor for a DNS query.
Definition: dns_core.c:184
#define LOG_ERROR
Definition: logger.h:285
ast_dns_resolve_callback callback
Callback to invoke upon completion.
Definition: dns_internal.h:139
static const char name[]
Definition: cdr_mysql.c:74
A DNS query.
Definition: dns_internal.h:137
struct ast_dns_resolver * resolver
The resolver in use for this query.
Definition: dns_internal.h:143
#define AST_RWLIST_FIRST
Definition: linkedlists.h:422

◆ dns_query_destroy()

static void dns_query_destroy ( void *  data)
static

Destructor for a DNS query.

Definition at line 184 of file dns_core.c.

References ao2_cleanup, ast_dns_result_free(), ast_dns_query::resolver_data, ast_dns_query::result, and ast_dns_query::user_data.

Referenced by dns_query_alloc().

185 {
186  struct ast_dns_query *query = data;
187 
188  ao2_cleanup(query->user_data);
189  ao2_cleanup(query->resolver_data);
190  ast_dns_result_free(query->result);
191 }
void ast_dns_result_free(struct ast_dns_result *result)
Free the DNS result information.
Definition: dns_core.c:130
void * user_data
User-specific data.
Definition: dns_internal.h:141
struct ast_dns_result * result
Result of the DNS query.
Definition: dns_internal.h:147
A DNS query.
Definition: dns_internal.h:137
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void * resolver_data
Resolver-specific data.
Definition: dns_internal.h:145

◆ dns_shutdown()

static void dns_shutdown ( void  )
static

Definition at line 606 of file dns_core.c.

References ast_sched_context_destroy(), and NULL.

Referenced by dns_core_init().

607 {
608  if (sched) {
610  sched = NULL;
611  }
612 }
Definition: sched.c:76
#define NULL
Definition: resample.c:96
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:269

◆ dns_synchronous_resolve_callback()

static void dns_synchronous_resolve_callback ( const struct ast_dns_query query)
static

Callback used to implement synchronous resolution.

Definition at line 301 of file dns_core.c.

References ast_cond_signal, ast_dns_query_get_data(), ast_mutex_lock, ast_mutex_unlock, dns_synchronous_resolve::completed, dns_synchronous_resolve::cond, dns_synchronous_resolve::lock, NULL, ast_dns_query::result, and dns_synchronous_resolve::result.

Referenced by ast_dns_resolve().

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 }
Structure used for signaling back for synchronous resolution completion.
Definition: dns_core.c:278
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
ast_cond_t cond
Condition used for signaling.
Definition: dns_core.c:282
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
#define ast_cond_signal(cond)
Definition: lock.h:201
struct ast_dns_result * result
The result from the query.
Definition: dns_core.c:286
unsigned int completed
Whether the query has completed.
Definition: dns_core.c:284
struct ast_dns_result * result
Result of the DNS query.
Definition: dns_internal.h:147
A DNS query.
Definition: dns_internal.h:137
ast_mutex_t lock
Lock used for signaling.
Definition: dns_core.c:280
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ dns_synchronous_resolve_destroy()

static void dns_synchronous_resolve_destroy ( void *  data)
static

Destructor for synchronous resolution structure.

Definition at line 290 of file dns_core.c.

References ast_cond_destroy, ast_mutex_destroy, dns_synchronous_resolve::cond, and dns_synchronous_resolve::lock.

Referenced by ast_dns_resolve().

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 }
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
#define ast_cond_destroy(cond)
Definition: lock.h:200
ast_mutex_t lock
Lock used for signaling.
Definition: dns_core.c:280
#define ast_mutex_destroy(a)
Definition: lock.h:186

◆ generic_record_alloc()

static struct ast_dns_record* generic_record_alloc ( struct ast_dns_query query,
const char *  data,
const size_t  size 
)
static

Definition at line 502 of file dns_core.c.

References ast_calloc, ast_dns_record::data, ast_dns_record::data_ptr, and NULL.

Referenced by allocate_dns_record().

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 }
char * data_ptr
pointer to record-specific data.
Definition: dns_internal.h:58
For AST_LIST.
Definition: dns_internal.h:39
#define NULL
Definition: resample.c:96
char data[0]
The raw DNS record.
Definition: dns_internal.h:60
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204

◆ sort_result()

static void sort_result ( int  rr_type,
struct ast_dns_result result 
)
static

Definition at line 592 of file dns_core.c.

References dns_sort_table, and dns_synchronous_resolve::result.

Referenced by ast_dns_resolver_completed().

593 {
594  if (dns_sort_table[rr_type]) {
596  }
597 }
static PGresult * result
Definition: cel_pgsql.c:88
static dns_sort_fn dns_sort_table[]
Definition: dns_core.c:587
int rr_type
Resource record type.
Definition: dns_internal.h:41

Variable Documentation

◆ dns_alloc_table

dns_alloc_fn dns_alloc_table[]
static
Initial value:
= {
[T_TXT] = dns_txt_alloc,
[T_NAPTR] = dns_naptr_alloc,
[T_SRV] = dns_srv_alloc,
}
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
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_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

Definition at line 518 of file dns_core.c.

Referenced by allocate_dns_record().

◆ dns_sort_table

dns_sort_fn dns_sort_table[]
static
Initial value:
= {
[T_NAPTR] = dns_naptr_sort,
[T_SRV] = dns_srv_sort,
}
void dns_srv_sort(struct ast_dns_result *result)
Sort the SRV records on a result.
Definition: dns_srv.c:113
void dns_naptr_sort(struct ast_dns_result *result)
Sort the NAPTR records on a result.
Definition: dns_naptr.c:551

Definition at line 587 of file dns_core.c.

Referenced by sort_result().

◆ resolvers

struct resolvers resolvers = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }

◆ sched

struct ast_sched_context* sched
static

Definition at line 50 of file dns_core.c.

Referenced by ast_dns_get_sched().