dns_core.c File Reference

Core DNS Functionality. More...

#include "asterisk.h"
#include "asterisk/linkedlists.h"
#include "asterisk/vector.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 <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 void __fini_resolvers (void)
static void __init_resolvers (void)
static struct ast_dns_recordallocate_dns_record (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.
void * ast_dns_query_get_data (const struct ast_dns_query *query)
 Get the user specific data of a DNS query.
const char * ast_dns_query_get_name (const struct ast_dns_query *query)
 Get the name queried in a DNS query.
struct ast_dns_resultast_dns_query_get_result (const struct ast_dns_query *query)
 Get the result information for a DNS query.
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_query_get_rr_type (const struct ast_dns_query *query)
 Get the record resource type of a DNS query.
const char * ast_dns_record_get_data (const struct ast_dns_record *record)
 Retrieve the raw DNS record.
struct ast_dns_recordast_dns_record_get_next (const struct ast_dns_record *record)
 Get the next DNS record.
int ast_dns_record_get_rr_class (const struct ast_dns_record *record)
 Get the resource record class of 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.
int ast_dns_record_get_ttl (const struct ast_dns_record *record)
 Get the TTL of a DNS record.
int ast_dns_resolve (const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
 Synchronously resolve a DNS query.
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.
int ast_dns_resolve_cancel (struct ast_dns_query_active *active)
 Cancel an asynchronous DNS resolution.
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.
void ast_dns_resolver_completed (struct ast_dns_query *query)
 Mark a DNS query as having been completed.
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.
int ast_dns_resolver_set_data (struct ast_dns_query *query, void *data)
 Set resolver specific data on a query.
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.
void ast_dns_resolver_unregister (struct ast_dns_resolver *resolver)
 Unregister a DNS resolver.
void ast_dns_result_free (struct ast_dns_result *result)
 Free the DNS result information.
const char * ast_dns_result_get_answer (const struct ast_dns_result *result)
 Get the raw DNS answer from a DNS result.
unsigned int ast_dns_result_get_bogus (const struct ast_dns_result *result)
 Get whether the result is bogus or not.
const char * ast_dns_result_get_canonical (const struct ast_dns_result *result)
 Get the canonical name of the result.
int ast_dns_result_get_lowest_ttl (const struct ast_dns_result *result)
 Retrieve the lowest TTL from a 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_recordast_dns_result_get_records (const struct ast_dns_result *result)
 Get the first record of a DNS Result.
unsigned int ast_dns_result_get_secure (const struct ast_dns_result *result)
 Get whether the result is secure or not.
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 dns_parse_short (unsigned char *cur, uint16_t *val)
 Parse a 16-bit unsigned value from a DNS record.
int dns_parse_string (char *cur, uint8_t *size, char **val)
 Parse a DNS string from a DNS record.
static void dns_query_active_destroy (void *data)
 Destructor for an active DNS query.
static void dns_query_destroy (void *data)
 Destructor for a DNS query.
static void dns_shutdown (void)
static void dns_synchronous_resolve_callback (const struct ast_dns_query *query)
 Callback used to implement synchronous resolution.
static void dns_synchronous_resolve_destroy (void *data)
 Destructor for synchronous resolution structure.
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 []
static struct ast_sched_contextsched


Detailed Description

Core DNS Functionality.

Author:
Joshua Colp <jcolp@digium.com>

Definition in file dns_core.c.


Typedef Documentation

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

Definition at line 429 of file dns_core.c.

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

Definition at line 493 of file dns_core.c.


Function Documentation

static void __fini_resolvers ( void   )  [static]

Definition at line 49 of file dns_core.c.

00054 {

static void __init_resolvers ( void   )  [static]

Definition at line 49 of file dns_core.c.

00054 {

static struct ast_dns_record* allocate_dns_record ( int  rr_type,
struct ast_dns_query query,
const char *  data,
const size_t  size 
) [static, read]

Definition at line 436 of file dns_core.c.

References generic_record_alloc().

Referenced by ast_dns_resolver_add_record().

00437 {
00438    dns_alloc_fn allocator = dns_alloc_table[rr_type] ?: generic_record_alloc;
00439 
00440    return allocator(query, data, size);
00441 }

struct ast_sched_context* ast_dns_get_sched ( void   )  [read]

Retrieve the DNS scheduler context.

Returns:
scheduler context

Definition at line 53 of file dns_core.c.

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

00054 {
00055    return sched;
00056 }

void* ast_dns_query_get_data ( const struct ast_dns_query query  ) 

Get the user specific data of a DNS query.

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

Definition at line 73 of file dns_core.c.

References ast_dns_query::user_data.

Referenced by async_callback(), dns_query_recurring_resolution_callback(), dns_synchronous_resolve_callback(), recurring_cancel(), recurring_resolve(), and resolution_thread().

00074 {
00075    return query->user_data;
00076 }

const char* ast_dns_query_get_name ( const struct ast_dns_query query  ) 

Get the name queried in a DNS query.

Parameters:
query The DNS query
Returns:
the name queried

Definition at line 58 of file dns_core.c.

References ast_dns_query::name.

Referenced by unbound_resolver_callback(), and unbound_resolver_resolve().

00059 {
00060    return query->name;
00061 }

struct ast_dns_result* ast_dns_query_get_result ( const struct ast_dns_query query  )  [read]

Get the result information for a DNS query.

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

Definition at line 78 of file dns_core.c.

References ast_dns_query::result.

Referenced by AST_TEST_DEFINE(), dns_query_recurring_resolution_callback(), and test_results().

00079 {
00080    return query->result;
00081 }

int ast_dns_query_get_rr_class ( const struct ast_dns_query query  ) 

Get the record resource class of a DNS query.

Parameters:
query The DNS query
Returns:
the record resource class

Definition at line 68 of file dns_core.c.

References ast_dns_query::rr_class.

Referenced by unbound_resolver_resolve().

00069 {
00070    return query->rr_class;
00071 }

int ast_dns_query_get_rr_type ( const struct ast_dns_query query  ) 

Get the record resource type of a DNS query.

Parameters:
query The DNS query
Returns:
the record resource type

Definition at line 63 of file dns_core.c.

References ast_dns_query::rr_type.

Referenced by ast_dns_resolver_completed(), and unbound_resolver_resolve().

00064 {
00065    return query->rr_type;
00066 }

const char* ast_dns_record_get_data ( const struct ast_dns_record record  ) 

Retrieve the raw DNS record.

Parameters:
record The DNS record
Returns:
the raw DNS record

Definition at line 161 of file dns_core.c.

References ast_dns_record::data_ptr.

Referenced by test_record().

00162 {
00163    return record->data_ptr;
00164 }

struct ast_dns_record* ast_dns_record_get_next ( const struct ast_dns_record record  )  [read]

Get the next DNS record.

Parameters:
record The current DNS record
Returns:
the next DNS record

Definition at line 166 of file dns_core.c.

References AST_LIST_NEXT.

Referenced by ast_dns_result_get_lowest_ttl(), AST_TEST_DEFINE(), and nominal_test().

00167 {
00168    return AST_LIST_NEXT(record, list);
00169 }

int ast_dns_record_get_rr_class ( const struct ast_dns_record record  ) 

Get the resource record class of a DNS record.

Parameters:
record The DNS record
Returns:
the resource record class

Definition at line 151 of file dns_core.c.

References ast_dns_record::rr_class.

Referenced by test_record().

00152 {
00153    return record->rr_class;
00154 }

int ast_dns_record_get_rr_type ( const struct ast_dns_record record  ) 

Get the resource record type of a DNS record.

Parameters:
record The DNS record
Returns:
the resource record type

Definition at line 146 of file dns_core.c.

References ast_dns_record::rr_type.

Referenced by ast_dns_naptr_get_flags(), ast_dns_naptr_get_order(), ast_dns_naptr_get_preference(), ast_dns_naptr_get_regexp(), ast_dns_naptr_get_replacement(), ast_dns_naptr_get_service(), ast_dns_srv_get_host(), ast_dns_srv_get_port(), ast_dns_srv_get_priority(), ast_dns_srv_get_weight(), AST_TEST_DEFINE(), and test_record().

00147 {
00148    return record->rr_type;
00149 }

int ast_dns_record_get_ttl ( const struct ast_dns_record record  ) 

Get the TTL of a DNS record.

Parameters:
record The DNS record
Returns:
the TTL

Definition at line 156 of file dns_core.c.

References ast_dns_record::ttl.

Referenced by ast_dns_result_get_lowest_ttl(), and test_record().

00157 {
00158    return record->ttl;
00159 }

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

Synchronously resolve a DNS query.

Parameters:
name The name of what to resolve
rr_type Resource record type
rr_class Resource record class
result A pointer to hold the DNS result
Return values:
0 success - query was completed and result is available
-1 failure

Definition at line 298 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_test(), and off_nominal_test().

00299 {
00300    struct dns_synchronous_resolve *synchronous;
00301    struct ast_dns_query_active *active;
00302 
00303    if (ast_strlen_zero(name)) {
00304       ast_log(LOG_WARNING, "Could not perform synchronous resolution, no name provided\n");
00305       return -1;
00306    } else if (rr_type > ns_t_max) {
00307       ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', resource record type '%d' exceeds maximum\n",
00308          name, rr_type);
00309       return -1;
00310    } else if (rr_type < 0) {
00311       ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', invalid resource record type '%d'\n",
00312          name, rr_type);
00313       return -1;
00314    } else if (rr_class > ns_c_max) {
00315       ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', resource record class '%d' exceeds maximum\n",
00316          name, rr_class);
00317       return -1;
00318    } else if (rr_class < 0) {
00319       ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', invalid resource class '%d'\n",
00320          name, rr_class);
00321       return -1;
00322    } else if (!result) {
00323       ast_log(LOG_WARNING, "Could not perform synchronous resolution of '%s', no result pointer provided for storing results\n",
00324          name);
00325       return -1;
00326    }
00327 
00328    synchronous = ao2_alloc_options(sizeof(*synchronous), dns_synchronous_resolve_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
00329    if (!synchronous) {
00330       return -1;
00331    }
00332 
00333    ast_mutex_init(&synchronous->lock);
00334    ast_cond_init(&synchronous->cond, NULL);
00335 
00336    active = ast_dns_resolve_async(name, rr_type, rr_class, dns_synchronous_resolve_callback, synchronous);
00337    if (active) {
00338       /* Wait for resolution to complete */
00339       ast_mutex_lock(&synchronous->lock);
00340       while (!synchronous->completed) {
00341          ast_cond_wait(&synchronous->cond, &synchronous->lock);
00342       }
00343       ast_mutex_unlock(&synchronous->lock);
00344       ao2_ref(active, -1);
00345    }
00346 
00347    *result = synchronous->result;
00348    ao2_ref(synchronous, -1);
00349 
00350    return *result ? 0 : -1;
00351 }

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 
) [read]

Asynchronously resolve a DNS query.

Parameters:
name The name of what to resolve
rr_type Resource record type
rr_class Resource record class
callback The callback to invoke upon completion
data User data to make available on the query
Return values:
non-NULL success - query has been sent for resolution
NULL failure
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 189 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_active_destroy(), dns_query_destroy(), LOG_ERROR, LOG_WARNING, ast_dns_resolver::name, ast_dns_query::name, NULL, ast_dns_query_active::query, ast_dns_resolver::resolve, ast_dns_query::resolver, ast_dns_query::rr_class, ast_dns_query::rr_type, and ast_dns_query::user_data.

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

00190 {
00191    struct ast_dns_query_active *active;
00192 
00193    if (ast_strlen_zero(name)) {
00194       ast_log(LOG_WARNING, "Could not perform asynchronous resolution, no name provided\n");
00195       return NULL;
00196    } else if (rr_type > ns_t_max) {
00197       ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', resource record type '%d' exceeds maximum\n",
00198          name, rr_type);
00199       return NULL;
00200    } else if (rr_type < 0) {
00201       ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', invalid resource record type '%d'\n",
00202          name, rr_type);
00203       return NULL;
00204    } else if (rr_class > ns_c_max) {
00205       ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', resource record class '%d' exceeds maximum\n",
00206          name, rr_class);
00207       return NULL;
00208    } else if (rr_class < 0) {
00209       ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', invalid resource class '%d'\n",
00210          name, rr_class);
00211       return NULL;
00212    } else if (!callback) {
00213       ast_log(LOG_WARNING, "Could not perform asynchronous resolution of '%s', no callback provided\n",
00214          name);
00215       return NULL;
00216    }
00217 
00218    active = ao2_alloc_options(sizeof(*active), dns_query_active_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
00219    if (!active) {
00220       return NULL;
00221    }
00222 
00223    active->query = ao2_alloc_options(sizeof(*active->query) + strlen(name) + 1, dns_query_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
00224    if (!active->query) {
00225       ao2_ref(active, -1);
00226       return NULL;
00227    }
00228 
00229    active->query->callback = callback;
00230    active->query->user_data = ao2_bump(data);
00231    active->query->rr_type = rr_type;
00232    active->query->rr_class = rr_class;
00233    strcpy(active->query->name, name); /* SAFE */
00234 
00235    AST_RWLIST_RDLOCK(&resolvers);
00236    active->query->resolver = AST_RWLIST_FIRST(&resolvers);
00237    AST_RWLIST_UNLOCK(&resolvers);
00238 
00239    if (!active->query->resolver) {
00240       ast_log(LOG_ERROR, "Attempted to do a DNS query for '%s' of class '%d' and type '%d' but no resolver is available\n",
00241          name, rr_class, rr_type);
00242       ao2_ref(active, -1);
00243       return NULL;
00244    }
00245 
00246    if (active->query->resolver->resolve(active->query)) {
00247       ast_log(LOG_ERROR, "Resolver '%s' returned an error when resolving '%s' of class '%d' and type '%d'\n",
00248          active->query->resolver->name, name, rr_class, rr_type);
00249       ao2_ref(active, -1);
00250       return NULL;
00251    }
00252 
00253    return active;
00254 }

int ast_dns_resolve_cancel ( struct ast_dns_query_active active  ) 

Cancel an asynchronous DNS resolution.

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

Definition at line 256 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().

00257 {
00258    return active->query->resolver->cancel(active->query);
00259 }

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:
query The DNS query
rr_type Resource record type
rr_class Resource record class
ttl TTL of the record
data The raw DNS record
size The size of the raw DNS record
Return values:
0 success
-1 failure

Definition at line 443 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_query::result, ast_dns_record::rr_class, ast_dns_record::rr_type, and ast_dns_record::ttl.

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

00444 {
00445    struct ast_dns_record *record;
00446 
00447    if (rr_type < 0) {
00448       ast_debug(2, "Query '%p': Could not add record, invalid resource record type '%d'\n",
00449          query, rr_type);
00450       return -1;
00451    } else if (rr_type > ns_t_max) {
00452       ast_debug(2, "Query '%p': Could not add record, resource record type '%d' exceeds maximum\n",
00453          query, rr_type);
00454       return -1;
00455    } else if (rr_class < 0) {
00456       ast_debug(2, "Query '%p': Could not add record, invalid resource record class '%d'\n",
00457          query, rr_class);
00458       return -1;
00459    } else if (rr_class > ns_c_max) {
00460       ast_debug(2, "Query '%p': Could not add record, resource record class '%d' exceeds maximum\n",
00461          query, rr_class);
00462       return -1;
00463    } else if (ttl < 0) {
00464       ast_debug(2, "Query '%p': Could not add record, invalid TTL '%d'\n",
00465          query, ttl);
00466       return -1;
00467    } else if (!data || !size) {
00468       ast_debug(2, "Query '%p': Could not add record, no data specified\n",
00469          query);
00470       return -1;
00471    } else if (!query->result) {
00472       ast_debug(2, "Query '%p': No result was set on the query, thus records can not be added\n",
00473          query);
00474       return -1;
00475    }
00476 
00477    record = allocate_dns_record(rr_type, query, data, size);
00478    if (!record) {
00479       return -1;
00480    }
00481 
00482    record->rr_type = rr_type;
00483    record->rr_class = rr_class;
00484    record->ttl = ttl;
00485    record->data_len = size;
00486    memcpy(record->data_ptr, data, size);
00487 
00488    AST_LIST_INSERT_TAIL(&query->result->records, record, list);
00489 
00490    return 0;
00491 }

void ast_dns_resolver_completed ( struct ast_dns_query query  ) 

Mark a DNS query as having been completed.

Parameters:
query The DNS query

Definition at line 507 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 naptr_thread(), resolution_thread(), srv_thread(), and unbound_resolver_callback().

00508 {
00509    sort_result(ast_dns_query_get_rr_type(query), query->result);
00510 
00511    query->callback(query);
00512 }

void* ast_dns_resolver_get_data ( const struct ast_dns_query query  ) 

Retrieve resolver specific data.

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

Definition at line 364 of file dns_core.c.

References ast_dns_query::resolver_data.

Referenced by AST_TEST_DEFINE(), and unbound_resolver_cancel().

00365 {
00366    return query->resolver_data;
00367 }

int ast_dns_resolver_register ( struct ast_dns_resolver resolver  ) 

Register a DNS resolver.

Parameters:
resolver A DNS resolver implementation
Return values:
0 success
-1 failure

Definition at line 522 of file dns_core.c.

References AST_LIST_EMPTY, AST_LIST_TRAVERSE, ast_log, ast_register_cleanup(), 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_sched_context_create(), ast_sched_start_thread(), ast_strlen_zero, ast_verb, ast_dns_resolver::cancel, dns_shutdown(), LOG_ERROR, ast_dns_resolver::name, ast_dns_resolver::priority, and ast_dns_resolver::resolve.

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

00523 {
00524    struct ast_dns_resolver *iter;
00525    int inserted = 0;
00526 
00527    if (!resolver) {
00528       return -1;
00529    } else if (ast_strlen_zero(resolver->name)) {
00530       ast_log(LOG_ERROR, "Registration of DNS resolver failed as it does not have a name\n");
00531       return -1;
00532    } else if (!resolver->resolve) {
00533       ast_log(LOG_ERROR, "DNS resolver '%s' does not implement the resolve callback which is required\n",
00534          resolver->name);
00535       return -1;
00536    } else if (!resolver->cancel) {
00537       ast_log(LOG_ERROR, "DNS resolver '%s' does not implement the cancel callback which is required\n",
00538          resolver->name);
00539       return -1;
00540    }
00541 
00542    AST_RWLIST_WRLOCK(&resolvers);
00543 
00544    /* On the first registration of a resolver start a scheduler for recurring queries */
00545    if (AST_LIST_EMPTY(&resolvers) && !sched) {
00546       sched = ast_sched_context_create();
00547       if (!sched) {
00548          ast_log(LOG_ERROR, "DNS resolver '%s' could not be registered: Failed to create scheduler for recurring DNS queries\n",
00549             resolver->name);
00550          AST_RWLIST_UNLOCK(&resolvers);
00551          return -1;
00552       }
00553 
00554       if (ast_sched_start_thread(sched)) {
00555          ast_log(LOG_ERROR, "DNS resolver '%s' could not be registered: Failed to start thread for recurring DNS queries\n",
00556             resolver->name);
00557          dns_shutdown();
00558          AST_RWLIST_UNLOCK(&resolvers);
00559          return -1;
00560       }
00561 
00562       ast_register_cleanup(dns_shutdown);
00563    }
00564 
00565    AST_LIST_TRAVERSE(&resolvers, iter, next) {
00566       if (!strcmp(iter->name, resolver->name)) {
00567          ast_log(LOG_ERROR, "A DNS resolver with the name '%s' is already registered\n", resolver->name);
00568          AST_RWLIST_UNLOCK(&resolvers);
00569          return -1;
00570       }
00571    }
00572 
00573    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&resolvers, iter, next) {
00574       if (iter->priority > resolver->priority) {
00575          AST_RWLIST_INSERT_BEFORE_CURRENT(resolver, next);
00576          inserted = 1;
00577          break;
00578       }
00579    }
00580    AST_RWLIST_TRAVERSE_SAFE_END;
00581 
00582    if (!inserted) {
00583       AST_RWLIST_INSERT_TAIL(&resolvers, resolver, next);
00584    }
00585 
00586    AST_RWLIST_UNLOCK(&resolvers);
00587 
00588    ast_verb(2, "Registered DNS resolver '%s' with priority '%d'\n", resolver->name, resolver->priority);
00589 
00590    return 0;
00591 }

int ast_dns_resolver_set_data ( struct ast_dns_query query,
void *  data 
)

Set resolver specific data on a query.

Parameters:
query The DNS query
data The 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:
0 success
-1 failure, resolver data is already set

Definition at line 353 of file dns_core.c.

References ao2_bump, and ast_dns_query::resolver_data.

Referenced by AST_TEST_DEFINE(), and unbound_resolver_resolve().

00354 {
00355    if (query->resolver_data) {
00356       return -1;
00357    }
00358 
00359    query->resolver_data = ao2_bump(data);
00360 
00361    return 0;
00362 }

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:
query The DNS query
result Whether the result is secured or not
bogus Whether the result is bogus or not
rcode Optional response code
canonical The canonical name
answer The raw DNS answer
answer_size The size of the raw DNS answer
Return values:
0 success
-1 failure

Definition at line 369 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(), naptr_thread(), resolution_thread(), srv_thread(), and unbound_resolver_callback().

00371 {
00372    char *buf_ptr;
00373 
00374    if (secure && bogus) {
00375       ast_debug(2, "Query '%p': Could not set result information, it can not be both secure and bogus\n",
00376          query);
00377       return -1;
00378    }
00379 
00380    if (ast_strlen_zero(canonical)) {
00381       ast_debug(2, "Query '%p': Could not set result information since no canonical name was provided\n",
00382          query);
00383       return -1;
00384    }
00385 
00386    if (!answer || answer_size == 0) {
00387       ast_debug(2, "Query '%p': Could not set result information since no DNS answer was provided\n",
00388          query);
00389       return -1;
00390    }
00391 
00392    ast_dns_result_free(query->result);
00393 
00394    query->result = ast_calloc(1, sizeof(*query->result) + strlen(canonical) + 1 + answer_size);
00395    if (!query->result) {
00396       return -1;
00397    }
00398 
00399    query->result->secure = secure;
00400    query->result->bogus = bogus;
00401    query->result->rcode = rcode;
00402 
00403    buf_ptr = query->result->buf;
00404    strcpy(buf_ptr, canonical); /* SAFE */
00405    query->result->canonical = buf_ptr;
00406 
00407    buf_ptr += strlen(canonical) + 1;
00408    memcpy(buf_ptr, answer, answer_size); /* SAFE */
00409    query->result->answer = buf_ptr;
00410    query->result->answer_size = answer_size;
00411 
00412    return 0;
00413 }

void ast_dns_resolver_unregister ( struct ast_dns_resolver resolver  ) 

Unregister a DNS resolver.

Parameters:
resolver A DNS resolver implementation

Definition at line 593 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(), invalid_record_test(), nominal_test(), and off_nominal_test().

00594 {
00595    struct ast_dns_resolver *iter;
00596 
00597    if (!resolver) {
00598       return;
00599    }
00600 
00601    AST_RWLIST_WRLOCK(&resolvers);
00602    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&resolvers, iter, next) {
00603       if (resolver == iter) {
00604          AST_RWLIST_REMOVE_CURRENT(next);
00605          break;
00606       }
00607    }
00608    AST_RWLIST_TRAVERSE_SAFE_END;
00609    AST_RWLIST_UNLOCK(&resolvers);
00610 
00611    ast_verb(2, "Unregistered DNS resolver '%s'\n", resolver->name);
00612 }

void ast_dns_result_free ( struct ast_dns_result result  ) 

Free the DNS result information.

Parameters:
result The DNS result

Definition at line 131 of file dns_core.c.

References ast_free, and AST_LIST_REMOVE_HEAD.

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

00132 {
00133    struct ast_dns_record *record;
00134 
00135    if (!result) {
00136       return;
00137    }
00138 
00139    while ((record = AST_LIST_REMOVE_HEAD(&result->records, list))) {
00140       ast_free(record);
00141    }
00142 
00143    ast_free(result);
00144 }

const char* ast_dns_result_get_answer ( const struct ast_dns_result result  ) 

Get the raw DNS answer from a DNS result.

Parameters:
result The DNS result
Returns:
The DNS result

Definition at line 108 of file dns_core.c.

References ast_dns_result::answer.

Referenced by test_results().

00109 {
00110    return result->answer;
00111 }

unsigned int ast_dns_result_get_bogus ( const struct ast_dns_result result  ) 

Get whether the result is bogus or not.

Parameters:
result The DNS result
Returns:
whether the result is bogus or not

Definition at line 88 of file dns_core.c.

References ast_dns_result::bogus.

Referenced by test_results().

00089 {
00090    return result->bogus;
00091 }

const char* ast_dns_result_get_canonical ( const struct ast_dns_result result  ) 

Get the canonical name of the result.

Parameters:
result The DNS result
Returns:
the canonical name

Definition at line 98 of file dns_core.c.

References ast_dns_result::canonical.

Referenced by test_results().

00099 {
00100    return result->canonical;
00101 }

int ast_dns_result_get_lowest_ttl ( const struct ast_dns_result result  ) 

Retrieve the lowest TTL from a result.

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

Definition at line 113 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().

00114 {
00115    int ttl = 0;
00116    const struct ast_dns_record *record;
00117 
00118    if (ast_dns_result_get_rcode(result) == ns_r_nxdomain) {
00119       return 0;
00120    }
00121 
00122    for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) {
00123       if (!ttl || (ast_dns_record_get_ttl(record) && (ast_dns_record_get_ttl(record) < ttl))) {
00124          ttl = ast_dns_record_get_ttl(record);
00125       }
00126    }
00127 
00128    return ttl;
00129 }

unsigned int ast_dns_result_get_rcode ( const struct ast_dns_result result  ) 

Get the error rcode of a DN result.

Parameters:
query The DNS result
Returns:
the DNS rcode

Definition at line 93 of file dns_core.c.

References ast_dns_result::rcode.

Referenced by ast_dns_result_get_lowest_ttl(), and test_results().

00094 {
00095    return result->rcode;
00096 }

struct ast_dns_record* ast_dns_result_get_records ( const struct ast_dns_result result  )  [read]

Get the first record of a DNS Result.

Parameters:
result The DNS result
Returns:
first DNS record

Definition at line 103 of file dns_core.c.

References AST_LIST_FIRST.

Referenced by ast_dns_result_get_lowest_ttl(), AST_TEST_DEFINE(), invalid_record_test(), nominal_test(), and off_nominal_test().

00104 {
00105    return AST_LIST_FIRST(&result->records);
00106 }

unsigned int ast_dns_result_get_secure ( const struct ast_dns_result result  ) 

Get whether the result is secure or not.

Parameters:
result The DNS result
Returns:
whether the result is secure or not

Definition at line 83 of file dns_core.c.

References ast_dns_result::secure.

Referenced by test_results().

00084 {
00085    return result->secure;
00086 }

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:
record The DNS record returned by a resolver implementation
record_size The size of the DNS record in bytes
response The complete DNS answer
response_size The size of the complete DNS response

Definition at line 614 of file dns_core.c.

References ast_assert, and NULL.

Referenced by dns_naptr_alloc(), and dns_srv_alloc().

00615 {
00616    size_t remaining_size = response_size;
00617    const char *search_base = response;
00618    char *record_offset;
00619 
00620    while (1) {
00621       record_offset = memchr(search_base, record[0], remaining_size);
00622 
00623       ast_assert(record_offset != NULL);
00624       ast_assert(search_base + remaining_size - record_offset >= record_size);
00625 
00626       if (!memcmp(record_offset, record, record_size)) {
00627          return record_offset;
00628       }
00629 
00630       remaining_size -= record_offset - search_base;
00631       search_base = record_offset + 1;
00632    }
00633 }

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

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

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

Definition at line 635 of file dns_core.c.

Referenced by dns_naptr_alloc(), and dns_srv_alloc().

00636 {
00637    /* This assignment takes a big-endian 16-bit value and stores it in the
00638     * machine's native byte order. Using this method allows us to avoid potential
00639     * alignment issues in case the order is not on a short-addressable boundary.
00640     * See http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html for
00641     * more information
00642     */
00643    *val = (cur[1] << 0) | (cur[0] << 8);
00644    return sizeof(*val);
00645 }

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:
cur Pointer to the location of the DNS string
[out] size The parsed size of the DNS string
[out] val The contained string (not NULL-terminated)
Returns:
The number of bytes consumed while parsing

Definition at line 647 of file dns_core.c.

Referenced by dns_naptr_alloc().

00648 {
00649    *size = *cur++;
00650    *val = cur;
00651    return *size + 1;
00652 }

static void dns_query_active_destroy ( void *  data  )  [static]

Destructor for an active DNS query.

Definition at line 172 of file dns_core.c.

References ao2_cleanup, and ast_dns_query_active::query.

Referenced by ast_dns_resolve_async().

00173 {
00174    struct ast_dns_query_active *active = data;
00175 
00176    ao2_cleanup(active->query);
00177 }

static void dns_query_destroy ( void *  data  )  [static]

Destructor for a DNS query.

Definition at line 180 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 ast_dns_resolve_async().

00181 {
00182    struct ast_dns_query *query = data;
00183 
00184    ao2_cleanup(query->user_data);
00185    ao2_cleanup(query->resolver_data);
00186    ast_dns_result_free(query->result);
00187 }

static void dns_shutdown ( void   )  [static]

Definition at line 514 of file dns_core.c.

References ast_sched_context_destroy(), and NULL.

Referenced by ast_dns_resolver_register().

00515 {
00516    if (sched) {
00517       ast_sched_context_destroy(sched);
00518       sched = NULL;
00519    }
00520 }

static void dns_synchronous_resolve_callback ( const struct ast_dns_query query  )  [static]

Callback used to implement synchronous resolution.

Definition at line 285 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().

00286 {
00287    struct dns_synchronous_resolve *synchronous = ast_dns_query_get_data(query);
00288 
00289    synchronous->result = query->result;
00290    ((struct ast_dns_query *)query)->result = NULL;
00291 
00292    ast_mutex_lock(&synchronous->lock);
00293    synchronous->completed = 1;
00294    ast_cond_signal(&synchronous->cond);
00295    ast_mutex_unlock(&synchronous->lock);
00296 }

static void dns_synchronous_resolve_destroy ( void *  data  )  [static]

Destructor for synchronous resolution structure.

Definition at line 274 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().

00275 {
00276    struct dns_synchronous_resolve *synchronous = data;
00277 
00278    ast_mutex_destroy(&synchronous->lock);
00279    ast_cond_destroy(&synchronous->cond);
00280 
00281    /* This purposely does not unref result as it has been passed to the caller */
00282 }

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

Definition at line 415 of file dns_core.c.

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

Referenced by allocate_dns_record().

00416 {
00417    struct ast_dns_record *record;
00418 
00419    record = ast_calloc(1, sizeof(*record) + size);
00420    if (!record) {
00421       return NULL;
00422    }
00423 
00424    record->data_ptr = record->data;
00425 
00426    return record;
00427 }

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

Definition at line 500 of file dns_core.c.

Referenced by ast_dns_resolver_completed().

00501 {
00502    if (dns_sort_table[rr_type]) {
00503       dns_sort_table[rr_type](result);
00504    }
00505 }


Variable Documentation

Initial value:

 {
   [ns_t_naptr] = dns_naptr_alloc,
   [ns_t_srv] = dns_srv_alloc,
}

Definition at line 431 of file dns_core.c.

Initial value:

 {
   [ns_t_naptr] = dns_naptr_sort,
   [ns_t_srv] = dns_srv_sort,
}

Definition at line 495 of file dns_core.c.

struct ast_sched_context* sched [static]

Definition at line 51 of file dns_core.c.


Generated on Thu Apr 16 06:30:42 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6