28#include <arpa/nameser.h>
153 .category =
"general",
159 .
filename =
"resolver_unbound.conf",
184 ub_ctx_delete(resolver->
context);
200 resolver->
context = ub_ctx_create();
207 ub_ctx_async(resolver->
context, 1);
217 ast_debug(1,
"Starting processing for unbound resolver\n");
227 ast_debug(1,
"Terminating processing for unbound resolver\n");
243 ast_debug(1,
"Starting thread for unbound resolver\n");
247 ast_debug(1,
"Could not start thread for unbound resolver\n");
263 ast_debug(1,
"Stopping processing thread for unbound resolver\n");
267 pthread_kill(
thread, SIGURG);
270 ast_debug(1,
"Stopped processing thread for unbound resolver\n");
291 for (i = 0; (result_data = ub_result->data[i]); i++) {
293 result_data, ub_result->len[i])) {
301 ub_resolve_free(ub_result);
320 ast_log(
LOG_ERROR,
"Failed to allocate resolver data for resolution of '%s'\n",
385 if (
state->resolver) {
424 ast_log(
LOG_ERROR,
"Could not allocate unbound resolver state structure\n");
443 ast_log(
LOG_ERROR,
"Failed to set hosts file to '%s' in unbound resolver: %s\n",
457 ast_log(
LOG_ERROR,
"Failed to add nameserver '%s' to unbound resolver: %s\n",
458 nameserver, ub_strerror(res));
475 ast_log(
LOG_ERROR,
"Failed to set resolv.conf file to '%s' in unbound resolver: %s\n",
484 ast_log(
LOG_ERROR,
"Failed to set trusted anchor file to '%s' in unbound resolver: %s\n",
504 ast_log(
LOG_ERROR,
"Could not create default configuration for unbound resolver\n");
515 ast_verb(1,
"Starting unbound resolver using default configuration\n");
537 const char *as_string;
549 const size_t bufsize;
571typedef int (*resolve_fn)(
struct ast_test *
test,
const char *domain,
int rr_type,
572 int rr_class,
struct dns_record *
records,
size_t num_records);
577static int nominal_sync_run(
struct ast_test *
test,
const char *domain,
int rr_type,
578 int rr_class,
struct dns_record *
records,
size_t num_records)
585 for (i = 0; i < num_records; ++i) {
605 for (i = 0; i < num_records; ++i) {
643 struct async_data *adata = obj;
651 struct async_data *adata;
661 adata->num_records = num_records;
691 for (i = 0; i < adata->num_records; ++i) {
697 adata->records[i].visited = 1;
721static int nominal_async_run(
struct ast_test *
test,
const char *domain,
int rr_type,
735 for (i = 0; i < num_records; ++i) {
748 while (!adata->complete) {
756 return adata->failed;
774 static const size_t V4_SIZE =
sizeof(
struct in_addr);
775 static const size_t V6_SIZE =
sizeof(
struct in6_addr);
777 static const char *DOMAIN1 =
"goose.feathers";
778 static const char *DOMAIN2 =
"duck.feathers";
780 static const char *ADDR1 =
"127.0.0.2";
781 static const char *ADDR2 =
"127.0.0.3";
782 static const char *ADDR3 =
"::1";
783 static const char *ADDR4 =
"127.0.0.4";
785 char addr1_buf[V4_SIZE];
786 char addr2_buf[V4_SIZE];
787 char addr3_buf[V6_SIZE];
788 char addr4_buf[V4_SIZE];
790 struct dns_record
records [] = {
791 {
"goose.feathers 12345 IN A 127.0.0.2", DOMAIN1, ns_t_a, ns_c_in, 12345, addr1_buf, V4_SIZE, 0 },
792 {
"goose.feathers 12345 IN A 127.0.0.3", DOMAIN1, ns_t_a, ns_c_in, 12345, addr2_buf, V4_SIZE, 0 },
793 {
"goose.feathers 12345 IN AAAA ::1", DOMAIN1, ns_t_aaaa, ns_c_in, 12345, addr3_buf, V6_SIZE, 0 },
794 {
"duck.feathers 12345 IN A 127.0.0.4", DOMAIN2, ns_t_a, ns_c_in, 12345, addr4_buf, V4_SIZE, 0 },
803 { DOMAIN1, ns_t_a, ns_c_in, { 1, 1, 0, 0 } },
804 { DOMAIN1, ns_t_aaaa, ns_c_in, { 0, 0, 1, 0 } },
805 { DOMAIN2, ns_t_a, ns_c_in, { 0, 0, 0, 1 } },
811 inet_pton(AF_INET, ADDR1, addr1_buf);
812 inet_pton(AF_INET, ADDR2, addr2_buf);
813 inet_pton(AF_INET6, ADDR3, addr3_buf);
814 inet_pton(AF_INET, ADDR4, addr4_buf);
817 resolver =
ao2_bump(cfg->global->state->resolver);
819 ub_ctx_zone_add(resolver->context, DOMAIN1,
"static");
820 ub_ctx_zone_add(resolver->context, DOMAIN2,
"static");
823 ub_ctx_data_add(resolver->context,
records[i].as_string);
835 if (
records[j].visited != runs[i].visited[j]) {
845 ub_ctx_data_remove(resolver->context,
records[i].as_string);
847 ub_ctx_zone_remove(resolver->context, DOMAIN1);
848 ub_ctx_zone_remove(resolver->context, DOMAIN2);
858 info->name =
"resolve_sync";
859 info->category =
"/res/res_resolver_unbound/";
860 info->summary =
"Test nominal synchronous resolution using libunbound";
861 info->description =
"This test performs the following:\n"
862 "\t* Set two static A records and one static AAAA record on one domain\n"
863 "\t* Set an A record for a second domain\n"
864 "\t* Perform an A record lookup on the first domain\n"
865 "\t* Ensure that both A records are returned and no AAAA record is returned\n"
866 "\t* Perform an AAAA record lookup on the first domain\n"
867 "\t* Ensure that the AAAA record is returned and no A record is returned\n"
868 "\t* Perform an A record lookup on the second domain\n"
869 "\t* Ensure that the A record from the second domain is returned";
882 info->name =
"resolve_async";
883 info->category =
"/res/res_resolver_unbound/";
884 info->summary =
"Test nominal asynchronous resolution using libunbound";
885 info->description =
"This test performs the following:\n"
886 "\t* Set two static A records and one static AAAA record on one domain\n"
887 "\t* Set an A record for a second domain\n"
888 "\t* Perform an A record lookup on the first domain\n"
889 "\t* Ensure that both A records are returned and no AAAA record is returned\n"
890 "\t* Perform an AAAA record lookup on the first domain\n"
891 "\t* Ensure that the AAAA record is returned and no A record is returned\n"
892 "\t* Perform an A record lookup on the second domain\n"
893 "\t* Ensure that the A record from the second domain is returned";
902typedef int (*off_nominal_resolve_fn)(
struct ast_test *
test,
const char *domain,
int rr_type,
903 int rr_class,
int expected_rcode);
905static int off_nominal_sync_run(
struct ast_test *
test,
const char *domain,
int rr_type,
906 int rr_class,
int expected_rcode)
939struct off_nominal_async_data {
950static void off_nominal_async_data_destructor(
void *obj)
952 struct off_nominal_async_data *adata = obj;
958static struct off_nominal_async_data *off_nominal_async_data_alloc(
int expected_rcode)
960 struct off_nominal_async_data *adata;
962 adata =
ao2_alloc(
sizeof(*adata), off_nominal_async_data_destructor);
970 adata->expected_rcode = expected_rcode;
985static void off_nominal_async_callback(
const struct ast_dns_query *query)
1005 adata->complete = 1;
1010static int off_nominal_async_run(
struct ast_test *
test,
const char *domain,
int rr_type,
1011 int rr_class,
int expected_rcode)
1016 adata = off_nominal_async_data_alloc(expected_rcode);
1031 while (!adata->complete) {
1036 if (adata->failed) {
1039 return adata->failed;
1043 off_nominal_resolve_fn runner)
1048 static const size_t V4_SIZE =
sizeof(
struct in_addr);
1050 static const char *DOMAIN1 =
"goose.feathers";
1051 static const char *DOMAIN2 =
"duck.feathers";
1052 static const char *BADFORMAT1 =
".1";
1053 static const char *BADFORMAT2 =
".www";
1055 static const char *ADDR1 =
"127.0.0.2";
1057 char addr1_buf[V4_SIZE];
1059 struct dns_record
records [] = {
1060 {
"goose.feathers 12345 IN A 127.0.0.2", DOMAIN1, ns_t_a, ns_c_in, 12345, addr1_buf, V4_SIZE, 0, },
1072 { DOMAIN2, ns_t_a, ns_c_in, ns_r_nxdomain },
1073 { DOMAIN1, ns_t_aaaa, ns_c_in, ns_r_noerror },
1074 { DOMAIN1, ns_t_a, ns_c_chaos, ns_r_refused },
1075 { BADFORMAT1, ns_t_a, ns_c_in, ns_r_formerr },
1076 { BADFORMAT2, ns_t_a, ns_c_in, ns_r_formerr },
1077 { BADFORMAT1, ns_t_ptr, ns_c_in, ns_r_formerr },
1078 { BADFORMAT2, ns_t_ptr, ns_c_in, ns_r_formerr },
1081 inet_pton(AF_INET, ADDR1, addr1_buf);
1084 resolver =
ao2_bump(cfg->global->state->resolver);
1086 ub_ctx_zone_add(resolver->context, DOMAIN1,
"static");
1087 ub_ctx_zone_add(resolver->context, DOMAIN2,
"static");
1090 ub_ctx_data_add(resolver->context,
records[i].as_string);
1094 if (runner(
test, runs[i].domain, runs[i].rr_type, runs[i].rr_class, runs[i].rcode)) {
1106 info->name =
"resolve_sync_off_nominal";
1107 info->category =
"/res/res_resolver_unbound/";
1108 info->summary =
"Test off-nominal synchronous resolution using libunbound";
1109 info->description =
"This test performs the following:\n"
1110 "\t* Attempt a lookup of a non-existent domain\n"
1111 "\t* Attempt a lookup of a AAAA record on a domain that contains only A records\n"
1112 "\t* Attempt a lookup of an A record on Chaos-net";
1125 info->name =
"resolve_async_off_nominal";
1126 info->category =
"/res/res_resolver_unbound/";
1127 info->summary =
"Test off-nominal synchronous resolution using libunbound";
1128 info->description =
"This test performs the following:\n"
1129 "\t* Attempt a lookup of a non-existent domain\n"
1130 "\t* Attempt a lookup of a AAAA record on a domain that contains only A records\n"
1131 "\t* Attempt a lookup of an A record on Chaos-net";
1143struct async_minimal_data {
1149static void async_minimal_data_destructor(
void *obj)
1151 struct async_minimal_data *adata = obj;
1157static struct async_minimal_data *async_minimal_data_alloc(
void)
1159 struct async_minimal_data *adata;
1161 adata =
ao2_alloc(
sizeof(*adata), async_minimal_data_destructor);
1177static void minimal_callback(
const struct ast_dns_query *query)
1182 adata->complete = 1;
1194 info->name =
"resolve_cancel_off_nominal";
1195 info->category =
"/res/res_resolver_unbound/";
1196 info->summary =
"Off nominal cancellation test using libunbound";
1197 info->description =
"This test does the following:\n"
1198 "\t* Perform an asynchronous query\n"
1199 "\t* Once the query has completed, attempt to cancel it";
1205 adata = async_minimal_data_alloc();
1219 while (!adata->complete) {
1240 static char * DOMAIN1 =
"goose.feathers";
1245 const char *zone_entry;
1254 {
"goose.feathers 12345 IN NAPTR 100 100 A SIP+D2U \"\" goose.down", 100, 100,
"A",
"SIP+D2U",
"",
"goose.down", 0},
1255 {
"goose.feathers 12345 IN NAPTR 100 200 A SIP+D2T \"\" duck.down", 100, 200,
"A",
"SIP+D2T",
"",
"duck.down", 0},
1256 {
"goose.feathers 12345 IN NAPTR 200 100 A SIPS+D2U \"\" pheasant.down", 200, 100,
"A",
"SIPS+D2U",
"",
"pheasant.down", 0},
1257 {
"goose.feathers 12345 IN NAPTR 200 200 A SIPS+D2T \"\" platypus.fur", 200, 200,
"A",
"SIPS+D2T",
"",
"platypus.fur", 0},
1262 info->name =
"resolve_naptr";
1263 info->category =
"/res/res_resolver_unbound/";
1264 info->summary =
"Attempt resolution of NAPTR record";
1265 info->description =
"This test performs a NAPTR lookup and ensures that\n"
1266 "the returned record has the appropriate values set";
1273 resolver =
ao2_bump(cfg->global->state->resolver);
1275 ub_ctx_zone_add(resolver->context, DOMAIN1,
"static");
1278 ub_ctx_data_add(resolver->context,
records[i].zone_entry);
1355 static const char *DOMAIN1 =
"taco.bananas";
1356 static const char *DOMAIN1_SRV =
"taco.bananas 12345 IN SRV 10 20 5060 sip.taco.bananas";
1361 info->name =
"resolve_srv";
1362 info->category =
"/res/res_resolver_unbound/";
1363 info->summary =
"Test synchronous SRV resolution using libunbound";
1364 info->description =
"This test performs the following:\n"
1365 "\t* Set one SRV record on one domain\n"
1366 "\t* Perform an SRV lookup on the domain\n"
1367 "\t* Ensure that the SRV record returned matches the expected value";
1374 resolver =
ao2_bump(cfg->global->state->resolver);
1376 ub_ctx_zone_add(resolver->context, DOMAIN1,
"static");
1377 ub_ctx_data_add(resolver->context, DOMAIN1_SRV);
1411 ub_ctx_data_remove(resolver->context, DOMAIN1_SRV);
1412 ub_ctx_zone_remove(resolver->context, DOMAIN1);
1446 if (!
global->nameservers) {
1448 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)