28#include <arpa/nameser.h>
135 .category =
"general",
141 .
filename =
"resolver_unbound.conf",
166 ub_ctx_delete(resolver->
context);
182 resolver->
context = ub_ctx_create();
189 ub_ctx_async(resolver->
context, 1);
199 ast_debug(1,
"Starting processing for unbound resolver\n");
209 ast_debug(1,
"Terminating processing for unbound resolver\n");
225 ast_debug(1,
"Starting thread for unbound resolver\n");
229 ast_debug(1,
"Could not start thread for unbound resolver\n");
245 ast_debug(1,
"Stopping processing thread for unbound resolver\n");
249 pthread_kill(
thread, SIGURG);
252 ast_debug(1,
"Stopped processing thread for unbound resolver\n");
273 for (i = 0; (result_data = ub_result->data[i]); i++) {
275 result_data, ub_result->len[i])) {
283 ub_resolve_free(ub_result);
302 ast_log(
LOG_ERROR,
"Failed to allocate resolver data for resolution of '%s'\n",
367 if (
state->resolver) {
406 ast_log(
LOG_ERROR,
"Could not allocate unbound resolver state structure\n");
425 ast_log(
LOG_ERROR,
"Failed to set hosts file to '%s' in unbound resolver: %s\n",
439 ast_log(
LOG_ERROR,
"Failed to add nameserver '%s' to unbound resolver: %s\n",
440 nameserver, ub_strerror(res));
457 ast_log(
LOG_ERROR,
"Failed to set resolv.conf file to '%s' in unbound resolver: %s\n",
466 ast_log(
LOG_ERROR,
"Failed to set trusted anchor file to '%s' in unbound resolver: %s\n",
486 ast_log(
LOG_ERROR,
"Could not create default configuration for unbound resolver\n");
497 ast_verb(1,
"Starting unbound resolver using default configuration\n");
519 const char *as_string;
531 const size_t bufsize;
553typedef int (*resolve_fn)(
struct ast_test *
test,
const char *domain,
int rr_type,
554 int rr_class,
struct dns_record *
records,
size_t num_records);
559static int nominal_sync_run(
struct ast_test *
test,
const char *domain,
int rr_type,
560 int rr_class,
struct dns_record *
records,
size_t num_records)
567 for (i = 0; i < num_records; ++i) {
587 for (i = 0; i < num_records; ++i) {
625 struct async_data *adata = obj;
633 struct async_data *adata;
643 adata->num_records = num_records;
673 for (i = 0; i < adata->num_records; ++i) {
679 adata->records[i].visited = 1;
703static int nominal_async_run(
struct ast_test *
test,
const char *domain,
int rr_type,
717 for (i = 0; i < num_records; ++i) {
730 while (!adata->complete) {
738 return adata->failed;
756 static const size_t V4_SIZE =
sizeof(
struct in_addr);
757 static const size_t V6_SIZE =
sizeof(
struct in6_addr);
759 static const char *DOMAIN1 =
"goose.feathers";
760 static const char *DOMAIN2 =
"duck.feathers";
762 static const char *ADDR1 =
"127.0.0.2";
763 static const char *ADDR2 =
"127.0.0.3";
764 static const char *ADDR3 =
"::1";
765 static const char *ADDR4 =
"127.0.0.4";
767 char addr1_buf[V4_SIZE];
768 char addr2_buf[V4_SIZE];
769 char addr3_buf[V6_SIZE];
770 char addr4_buf[V4_SIZE];
772 struct dns_record
records [] = {
773 {
"goose.feathers 12345 IN A 127.0.0.2", DOMAIN1, ns_t_a, ns_c_in, 12345, addr1_buf, V4_SIZE, 0 },
774 {
"goose.feathers 12345 IN A 127.0.0.3", DOMAIN1, ns_t_a, ns_c_in, 12345, addr2_buf, V4_SIZE, 0 },
775 {
"goose.feathers 12345 IN AAAA ::1", DOMAIN1, ns_t_aaaa, ns_c_in, 12345, addr3_buf, V6_SIZE, 0 },
776 {
"duck.feathers 12345 IN A 127.0.0.4", DOMAIN2, ns_t_a, ns_c_in, 12345, addr4_buf, V4_SIZE, 0 },
785 { DOMAIN1, ns_t_a, ns_c_in, { 1, 1, 0, 0 } },
786 { DOMAIN1, ns_t_aaaa, ns_c_in, { 0, 0, 1, 0 } },
787 { DOMAIN2, ns_t_a, ns_c_in, { 0, 0, 0, 1 } },
793 inet_pton(AF_INET, ADDR1, addr1_buf);
794 inet_pton(AF_INET, ADDR2, addr2_buf);
795 inet_pton(AF_INET6, ADDR3, addr3_buf);
796 inet_pton(AF_INET, ADDR4, addr4_buf);
799 resolver =
ao2_bump(cfg->global->state->resolver);
801 ub_ctx_zone_add(resolver->context, DOMAIN1,
"static");
802 ub_ctx_zone_add(resolver->context, DOMAIN2,
"static");
805 ub_ctx_data_add(resolver->context,
records[i].as_string);
817 if (
records[j].visited != runs[i].visited[j]) {
827 ub_ctx_data_remove(resolver->context,
records[i].as_string);
829 ub_ctx_zone_remove(resolver->context, DOMAIN1);
830 ub_ctx_zone_remove(resolver->context, DOMAIN2);
840 info->name =
"resolve_sync";
841 info->category =
"/res/res_resolver_unbound/";
842 info->summary =
"Test nominal synchronous resolution using libunbound";
843 info->description =
"This test performs the following:\n"
844 "\t* Set two static A records and one static AAAA record on one domain\n"
845 "\t* Set an A record for a second domain\n"
846 "\t* Perform an A record lookup on the first domain\n"
847 "\t* Ensure that both A records are returned and no AAAA record is returned\n"
848 "\t* Perform an AAAA record lookup on the first domain\n"
849 "\t* Ensure that the AAAA record is returned and no A record is returned\n"
850 "\t* Perform an A record lookup on the second domain\n"
851 "\t* Ensure that the A record from the second domain is returned";
864 info->name =
"resolve_async";
865 info->category =
"/res/res_resolver_unbound/";
866 info->summary =
"Test nominal asynchronous resolution using libunbound";
867 info->description =
"This test performs the following:\n"
868 "\t* Set two static A records and one static AAAA record on one domain\n"
869 "\t* Set an A record for a second domain\n"
870 "\t* Perform an A record lookup on the first domain\n"
871 "\t* Ensure that both A records are returned and no AAAA record is returned\n"
872 "\t* Perform an AAAA record lookup on the first domain\n"
873 "\t* Ensure that the AAAA record is returned and no A record is returned\n"
874 "\t* Perform an A record lookup on the second domain\n"
875 "\t* Ensure that the A record from the second domain is returned";
884typedef int (*off_nominal_resolve_fn)(
struct ast_test *
test,
const char *domain,
int rr_type,
885 int rr_class,
int expected_rcode);
887static int off_nominal_sync_run(
struct ast_test *
test,
const char *domain,
int rr_type,
888 int rr_class,
int expected_rcode)
921struct off_nominal_async_data {
932static void off_nominal_async_data_destructor(
void *obj)
934 struct off_nominal_async_data *adata = obj;
940static struct off_nominal_async_data *off_nominal_async_data_alloc(
int expected_rcode)
942 struct off_nominal_async_data *adata;
944 adata =
ao2_alloc(
sizeof(*adata), off_nominal_async_data_destructor);
952 adata->expected_rcode = expected_rcode;
967static void off_nominal_async_callback(
const struct ast_dns_query *query)
992static int off_nominal_async_run(
struct ast_test *
test,
const char *domain,
int rr_type,
993 int rr_class,
int expected_rcode)
998 adata = off_nominal_async_data_alloc(expected_rcode);
1013 while (!adata->complete) {
1018 if (adata->failed) {
1021 return adata->failed;
1025 off_nominal_resolve_fn runner)
1030 static const size_t V4_SIZE =
sizeof(
struct in_addr);
1032 static const char *DOMAIN1 =
"goose.feathers";
1033 static const char *DOMAIN2 =
"duck.feathers";
1034 static const char *BADFORMAT1 =
".1";
1035 static const char *BADFORMAT2 =
".www";
1037 static const char *ADDR1 =
"127.0.0.2";
1039 char addr1_buf[V4_SIZE];
1041 struct dns_record
records [] = {
1042 {
"goose.feathers 12345 IN A 127.0.0.2", DOMAIN1, ns_t_a, ns_c_in, 12345, addr1_buf, V4_SIZE, 0, },
1054 { DOMAIN2, ns_t_a, ns_c_in, ns_r_nxdomain },
1055 { DOMAIN1, ns_t_aaaa, ns_c_in, ns_r_noerror },
1056 { DOMAIN1, ns_t_a, ns_c_chaos, ns_r_refused },
1057 { BADFORMAT1, ns_t_a, ns_c_in, ns_r_formerr },
1058 { BADFORMAT2, ns_t_a, ns_c_in, ns_r_formerr },
1059 { BADFORMAT1, ns_t_ptr, ns_c_in, ns_r_formerr },
1060 { BADFORMAT2, ns_t_ptr, ns_c_in, ns_r_formerr },
1063 inet_pton(AF_INET, ADDR1, addr1_buf);
1066 resolver =
ao2_bump(cfg->global->state->resolver);
1068 ub_ctx_zone_add(resolver->context, DOMAIN1,
"static");
1069 ub_ctx_zone_add(resolver->context, DOMAIN2,
"static");
1072 ub_ctx_data_add(resolver->context,
records[i].as_string);
1076 if (runner(
test, runs[i].domain, runs[i].rr_type, runs[i].rr_class, runs[i].rcode)) {
1088 info->name =
"resolve_sync_off_nominal";
1089 info->category =
"/res/res_resolver_unbound/";
1090 info->summary =
"Test off-nominal synchronous resolution using libunbound";
1091 info->description =
"This test performs the following:\n"
1092 "\t* Attempt a lookup of a non-existent domain\n"
1093 "\t* Attempt a lookup of a AAAA record on a domain that contains only A records\n"
1094 "\t* Attempt a lookup of an A record on Chaos-net";
1107 info->name =
"resolve_async_off_nominal";
1108 info->category =
"/res/res_resolver_unbound/";
1109 info->summary =
"Test off-nominal synchronous resolution using libunbound";
1110 info->description =
"This test performs the following:\n"
1111 "\t* Attempt a lookup of a non-existent domain\n"
1112 "\t* Attempt a lookup of a AAAA record on a domain that contains only A records\n"
1113 "\t* Attempt a lookup of an A record on Chaos-net";
1125struct async_minimal_data {
1131static void async_minimal_data_destructor(
void *obj)
1133 struct async_minimal_data *adata = obj;
1139static struct async_minimal_data *async_minimal_data_alloc(
void)
1141 struct async_minimal_data *adata;
1143 adata =
ao2_alloc(
sizeof(*adata), async_minimal_data_destructor);
1159static void minimal_callback(
const struct ast_dns_query *query)
1164 adata->complete = 1;
1176 info->name =
"resolve_cancel_off_nominal";
1177 info->category =
"/res/res_resolver_unbound/";
1178 info->summary =
"Off nominal cancellation test using libunbound";
1179 info->description =
"This test does the following:\n"
1180 "\t* Perform an asynchronous query\n"
1181 "\t* Once the query has completed, attempt to cancel it";
1187 adata = async_minimal_data_alloc();
1201 while (!adata->complete) {
1222 static char * DOMAIN1 =
"goose.feathers";
1227 const char *zone_entry;
1236 {
"goose.feathers 12345 IN NAPTR 100 100 A SIP+D2U \"\" goose.down", 100, 100,
"A",
"SIP+D2U",
"",
"goose.down", 0},
1237 {
"goose.feathers 12345 IN NAPTR 100 200 A SIP+D2T \"\" duck.down", 100, 200,
"A",
"SIP+D2T",
"",
"duck.down", 0},
1238 {
"goose.feathers 12345 IN NAPTR 200 100 A SIPS+D2U \"\" pheasant.down", 200, 100,
"A",
"SIPS+D2U",
"",
"pheasant.down", 0},
1239 {
"goose.feathers 12345 IN NAPTR 200 200 A SIPS+D2T \"\" platypus.fur", 200, 200,
"A",
"SIPS+D2T",
"",
"platypus.fur", 0},
1244 info->name =
"resolve_naptr";
1245 info->category =
"/res/res_resolver_unbound/";
1246 info->summary =
"Attempt resolution of NAPTR record";
1247 info->description =
"This test performs a NAPTR lookup and ensures that\n"
1248 "the returned record has the appropriate values set";
1255 resolver =
ao2_bump(cfg->global->state->resolver);
1257 ub_ctx_zone_add(resolver->context, DOMAIN1,
"static");
1260 ub_ctx_data_add(resolver->context,
records[i].zone_entry);
1337 static const char *DOMAIN1 =
"taco.bananas";
1338 static const char *DOMAIN1_SRV =
"taco.bananas 12345 IN SRV 10 20 5060 sip.taco.bananas";
1343 info->name =
"resolve_srv";
1344 info->category =
"/res/res_resolver_unbound/";
1345 info->summary =
"Test synchronous SRV resolution using libunbound";
1346 info->description =
"This test performs the following:\n"
1347 "\t* Set one SRV record on one domain\n"
1348 "\t* Perform an SRV lookup on the domain\n"
1349 "\t* Ensure that the SRV record returned matches the expected value";
1356 resolver =
ao2_bump(cfg->global->state->resolver);
1358 ub_ctx_zone_add(resolver->context, DOMAIN1,
"static");
1359 ub_ctx_data_add(resolver->context, DOMAIN1_SRV);
1393 ub_ctx_data_remove(resolver->context, DOMAIN1_SRV);
1394 ub_ctx_zone_remove(resolver->context, DOMAIN1);
1428 if (!
global->nameservers) {
1430 if (!
global->nameservers) {
Asterisk main include file. File version handling, generic pbx functions.
#define ao2_iterator_next(iter)
@ AO2_ALLOC_OPT_LOCK_NOLOCK
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_alloc_options(data_size, destructor_fn, options)
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_alloc(data_size, destructor_fn)
static struct console_pvt globals
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Configuration option-handling.
int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
Set all default options of obj.
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
@ ACO_PROCESS_ERROR
Their was an error and no changes were applied.
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
void * aco_pending_config(struct aco_info *info)
Get pending config changes.
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
int ast_dns_query_get_rr_type(const struct ast_dns_query *query)
Get the record resource type of a DNS query.
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_ttl(const struct ast_dns_record *record)
Get the TTL of a DNS record.
const struct ast_dns_record * ast_dns_record_get_next(const struct ast_dns_record *record)
Get the next DNS record.
struct ast_dns_query_active * ast_dns_resolve_async(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
Asynchronously resolve a DNS query.
int ast_dns_resolve_cancel(struct ast_dns_query_active *active)
Cancel an asynchronous DNS resolution.
int ast_dns_query_get_rr_class(const struct ast_dns_query *query)
Get the record resource class of a DNS query.
unsigned int ast_dns_result_get_rcode(const struct ast_dns_result *result)
Get the error rcode of a DN result.
const char * ast_dns_record_get_data(const struct ast_dns_record *record)
Retrieve the raw DNS record.
const struct ast_dns_record * ast_dns_result_get_records(const struct ast_dns_result *result)
Get the first record of a DNS Result.
void * ast_dns_query_get_data(const struct ast_dns_query *query)
Get the user specific data of a DNS query.
void ast_dns_result_free(struct ast_dns_result *result)
Free the DNS result information.
struct ast_dns_result * ast_dns_query_get_result(const struct ast_dns_query *query)
Get the result information for a DNS query.
int ast_dns_record_get_rr_type(const struct ast_dns_record *record)
Get the resource record type of a DNS record.
int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
Synchronously resolve a DNS query.
const char * ast_dns_query_get_name(const struct ast_dns_query *query)
Get the name queried in a DNS query.
DNS NAPTR Record Parsing API.
const char * ast_dns_naptr_get_replacement(const struct ast_dns_record *record)
Get the replacement value from a NAPTR record.
unsigned short ast_dns_naptr_get_preference(const struct ast_dns_record *record)
Get the preference from a NAPTR record.
const char * ast_dns_naptr_get_flags(const struct ast_dns_record *record)
Get the flags from a NAPTR record.
const char * ast_dns_naptr_get_service(const struct ast_dns_record *record)
Get the service from a NAPTR record.
const char * ast_dns_naptr_get_regexp(const struct ast_dns_record *record)
Get the regular expression from a NAPTR record.
unsigned short ast_dns_naptr_get_order(const struct ast_dns_record *record)
Get the order from a NAPTR record.
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_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_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.
DNS SRV Record Parsing API.
const char * ast_dns_srv_get_host(const struct ast_dns_record *record)
Get the hostname from an SRV record.
unsigned short ast_dns_srv_get_priority(const struct ast_dns_record *record)
Get the priority from an SRV record.
unsigned short ast_dns_srv_get_weight(const struct ast_dns_record *record)
Get the weight from an SRV record.
unsigned short ast_dns_srv_get_port(const struct ast_dns_record *record)
Get the port from an SRV record.
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
A set of macros to manage forward-linked lists.
#define ast_cond_destroy(cond)
#define ast_cond_wait(cond, mutex)
#define AST_PTHREADT_NULL
#define ast_cond_init(cond, attr)
#define ast_mutex_init(pmutex)
#define AST_PTHREADT_STOP
#define ast_mutex_unlock(a)
pthread_cond_t ast_cond_t
#define ast_mutex_destroy(a)
#define ast_mutex_lock(a)
#define ast_cond_signal(cond)
Asterisk module definitions.
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_CHANNEL_DEPEND
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_RELOAD_ERROR
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
static void * cleanup(void *unused)
static struct aco_type * global_options[]
static struct unbound_resolver * unbound_resolver_alloc(void)
Allocator for unbound resolver.
static void unbound_resolver_callback(void *data, int err, struct ub_result *ub_result)
Callback invoked when resolution completes on a query.
static int unbound_resolver_cancel(struct ast_dns_query *query)
static void unbound_resolver_destroy(void *obj)
Destructor for unbound resolver.
static void * unbound_resolver_thread(void *data)
Resolver thread which waits and handles results.
static void * unbound_config_alloc(void)
Allocate a unbound_config to hold a snapshot of the complete results of parsing a config.
static AO2_GLOBAL_OBJ_STATIC(globals)
A global object container that will contain the global_config that gets swapped out on reloads.
static struct aco_file resolver_unbound_conf
static int reload_module(void)
static int unbound_config_preapply(struct unbound_config *cfg)
static int unbound_config_preapply_callback(void)
Finish initializing new configuration.
static int unbound_config_apply_default(void)
static void unbound_config_destructor(void *obj)
static void unbound_resolver_data_dtor(void *vdoomed)
static int custom_nameserver_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static void unbound_global_config_destructor(void *obj)
static int unbound_resolver_start(struct unbound_resolver *resolver)
Start function for the unbound resolver.
static int load_module(void)
static void unbound_resolver_stop(struct unbound_resolver *resolver)
Stop function for the unbound resolver.
static int unload_module(void)
CONFIG_INFO_STANDARD(cfg_info, globals, unbound_config_alloc,.files=ACO_FILES(&resolver_unbound_conf),.pre_apply_config=unbound_config_preapply_callback,)
Register information about the configs being processed by this module.
static struct aco_type global_option
An aco_type structure to link the "general" category to the unbound_global_config type.
static int unbound_resolver_resolve(struct ast_dns_query *query)
static void unbound_config_state_destructor(void *obj)
static int debug
Global debug status.
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
#define AST_STRING_FIELD(name)
Declare a string field.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
struct ao2_container * ast_str_container_alloc_options(enum ao2_alloc_opts opts, int buckets)
Allocates a hash container for bare strings.
int ast_str_container_add(struct ao2_container *str_container, const char *add)
Adds a string to a string container allocated by ast_str_container_alloc.
The representation of a single configuration file to be processed.
Type information about a category-level configurable object.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
int rr_class
Resource record class.
int rr_type
Resource record type.
DNS resolver implementation.
The result of a DNS query.
Structure used to handle boolean flags.
Structure for mutex and tracking information.
Structure for variables, used for configurations and for channel variables.
struct ast_dns_test_string services
struct ast_dns_test_string flags
struct ast_dns_test_string regexp
Unbound configuration state information.
struct unbound_resolver * resolver
The configured resolver.
A container for config related information.
struct unbound_global_config * global
A structure to hold global configuration-related options.
struct unbound_config_state * state
State information.
const ast_string_field resolv
unsigned int debug
Debug level for the resolver.
struct ao2_container * nameservers
List of nameservers (in order) to use for queries.
const ast_string_field hosts
const ast_string_field ta_file
Structure for query resolver data.
int id
ID for the specific query.
struct unbound_resolver * resolver
The resolver in use for the query.
Structure for an unbound resolver.
pthread_t thread
Thread handling the resolver.
struct ub_ctx * context
Resolver context itself.
#define AST_TEST_REGISTER(cb)
#define ast_test_status_update(a, b, c...)
#define AST_TEST_UNREGISTER(cb)
#define AST_TEST_DEFINE(hdr)
static struct aco_type global
static struct async_resolution_data * async_data_alloc(void)
Allocation/initialization for async_resolution_data.
static void async_data_destructor(void *obj)
Destructor for async_resolution_data.
static void async_callback(const struct ast_dns_query *query)
Async DNS callback.
static enum ast_test_result_state off_nominal_test(struct ast_test *test, struct naptr_record *records, int num_records)
static enum ast_test_result_state nominal_test(struct ast_test *test, struct srv_record *records, int *srv_record_order, int num_records)
int error(const char *format,...)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_pthread_create(a, b, c, d)
int ast_wait_for_input(int fd, int ms)