Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Typedefs | Functions | Variables
res_resolver_unbound.c File Reference
#include "asterisk.h"
#include <signal.h>
#include <unbound.h>
#include <arpa/nameser.h>
#include "asterisk/module.h"
#include "asterisk/linkedlists.h"
#include "asterisk/dns_core.h"
#include "asterisk/dns_resolver.h"
#include "asterisk/config.h"
#include "asterisk/config_options.h"
#include "asterisk/test.h"
#include "asterisk/dns_srv.h"
#include "asterisk/dns_naptr.h"
Include dependency graph for res_resolver_unbound.c:

Go to the source code of this file.

Data Structures

struct  async_data
 Data required for an asynchronous callback. More...
 
struct  async_minimal_data
 Minimal data required to signal the completion of an async resolve. More...
 
struct  dns_record
 A DNS record to be used during a test. More...
 
struct  off_nominal_async_data
 User data for off-nominal async resolution test. More...
 
struct  unbound_config
 A container for config related information. More...
 
struct  unbound_config_state
 Unbound configuration state information. More...
 
struct  unbound_global_config
 A structure to hold global configuration-related options. More...
 
struct  unbound_resolver
 Structure for an unbound resolver. More...
 
struct  unbound_resolver_data
 Structure for query resolver data. More...
 

Typedefs

typedef int(* off_nominal_resolve_fn) (struct ast_test *test, const char *domain, int rr_type, int rr_class, int expected_rcode)
 
typedef int(* resolve_fn) (struct ast_test *test, const char *domain, int rr_type, int rr_class, struct dns_record *records, size_t num_records)
 Resolution function for tests. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static AO2_GLOBAL_OBJ_STATIC (globals)
 A global object container that will contain the global_config that gets swapped out on reloads. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (resolve_sync)
 
 AST_TEST_DEFINE (resolve_async)
 
 AST_TEST_DEFINE (resolve_sync_off_nominal)
 
 AST_TEST_DEFINE (resolve_async_off_nominal)
 
 AST_TEST_DEFINE (resolve_cancel_off_nominal)
 
 AST_TEST_DEFINE (resolve_naptr)
 
 AST_TEST_DEFINE (resolve_srv)
 
static void async_callback (const struct ast_dns_query *query)
 Callback for asynchronous queries. More...
 
static struct async_dataasync_data_alloc (struct dns_record *records, size_t num_records)
 
static void async_data_destructor (void *obj)
 
static struct async_minimal_dataasync_minimal_data_alloc (void)
 
static void async_minimal_data_destructor (void *obj)
 
 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. More...
 
static int custom_nameserver_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 
static int load_module (void)
 
static void minimal_callback (const struct ast_dns_query *query)
 Async callback for off-nominal cancellation test. More...
 
static int nominal_async_run (struct ast_test *test, const char *domain, int rr_type, int rr_class, struct dns_record *records, size_t num_records)
 Pluggable function for performing an asynchronous query during a test. More...
 
static int nominal_sync_run (struct ast_test *test, const char *domain, int rr_type, int rr_class, struct dns_record *records, size_t num_records)
 Pluggable function for running a synchronous query and checking its results. More...
 
static enum ast_test_result_state nominal_test (struct ast_test *test, resolve_fn runner)
 Framework for running a nominal DNS test. More...
 
static void off_nominal_async_callback (const struct ast_dns_query *query)
 Async callback for off-nominal async test. More...
 
static struct off_nominal_async_dataoff_nominal_async_data_alloc (int expected_rcode)
 
static void off_nominal_async_data_destructor (void *obj)
 
static int off_nominal_async_run (struct ast_test *test, const char *domain, int rr_type, int rr_class, int expected_rcode)
 
static int off_nominal_sync_run (struct ast_test *test, const char *domain, int rr_type, int rr_class, int expected_rcode)
 
static enum ast_test_result_state off_nominal_test (struct ast_test *test, off_nominal_resolve_fn runner)
 
static int reload_module (void)
 
static void * unbound_config_alloc (void)
 Allocate a unbound_config to hold a snapshot of the complete results of parsing a config. More...
 
static int unbound_config_apply_default (void)
 
static void unbound_config_destructor (void *obj)
 
static int unbound_config_preapply (struct unbound_config *cfg)
 
static int unbound_config_preapply_callback (void)
 Finish initializing new configuration. More...
 
static void unbound_config_state_destructor (void *obj)
 
static void unbound_global_config_destructor (void *obj)
 
static struct unbound_resolverunbound_resolver_alloc (void)
 Allocator for unbound resolver. More...
 
static void unbound_resolver_callback (void *data, int err, struct ub_result *ub_result)
 Callback invoked when resolution completes on a query. More...
 
static int unbound_resolver_cancel (struct ast_dns_query *query)
 
static void unbound_resolver_data_dtor (void *vdoomed)
 
static void unbound_resolver_destroy (void *obj)
 Destructor for unbound resolver. More...
 
static int unbound_resolver_resolve (struct ast_dns_query *query)
 
static int unbound_resolver_start (struct unbound_resolver *resolver)
 Start function for the unbound resolver. More...
 
static void unbound_resolver_stop (struct unbound_resolver *resolver)
 Stop function for the unbound resolver. More...
 
static void * unbound_resolver_thread (void *data)
 Resolver thread which waits and handles results. More...
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Unbound DNS Resolver Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND - 4, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct aco_type global_option
 An aco_type structure to link the "general" category to the unbound_global_config type. More...
 
static struct aco_typeglobal_options [] = ACO_TYPES(&global_option)
 
static struct aco_file resolver_unbound_conf
 
struct ast_dns_resolver unbound_resolver
 

Typedef Documentation

◆ off_nominal_resolve_fn

typedef int(* off_nominal_resolve_fn) (struct ast_test *test, const char *domain, int rr_type, int rr_class, int expected_rcode)

Definition at line 876 of file res_resolver_unbound.c.

◆ resolve_fn

typedef int(* resolve_fn) (struct ast_test *test, const char *domain, int rr_type, int rr_class, struct dns_record *records, size_t num_records)

Resolution function for tests.

Several tests will have similar setups but will want to make use of a different means of actually making queries and checking their results. This pluggable function pointer allows for similar tests to be operated in different ways.

Parameters
testThe test being run
domainThe domain to look up
rr_typeThe record type to look up
rr_classThe class of record to look up
recordsAll records that exist for the test.
num_recordsNumber of records in the records array.
Return values
0The test has passed thus far.
-1The test has failed.

Definition at line 545 of file res_resolver_unbound.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1474 of file res_resolver_unbound.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1474 of file res_resolver_unbound.c.

◆ AO2_GLOBAL_OBJ_STATIC()

static AO2_GLOBAL_OBJ_STATIC ( globals  )
static

A global object container that will contain the global_config that gets swapped out on reloads.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1474 of file res_resolver_unbound.c.

◆ AST_TEST_DEFINE() [1/7]

AST_TEST_DEFINE ( resolve_sync  )

Definition at line 827 of file res_resolver_unbound.c.

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), nominal_sync_run(), nominal_test(), TEST_EXECUTE, and TEST_INIT.

828 {
829 
830  switch (cmd) {
831  case TEST_INIT:
832  info->name = "resolve_sync";
833  info->category = "/res/res_resolver_unbound/";
834  info->summary = "Test nominal synchronous resolution using libunbound";
835  info->description = "This test performs the following:\n"
836  "\t* Set two static A records and one static AAAA record on one domain\n"
837  "\t* Set an A record for a second domain\n"
838  "\t* Perform an A record lookup on the first domain\n"
839  "\t* Ensure that both A records are returned and no AAAA record is returned\n"
840  "\t* Perform an AAAA record lookup on the first domain\n"
841  "\t* Ensure that the AAAA record is returned and no A record is returned\n"
842  "\t* Perform an A record lookup on the second domain\n"
843  "\t* Ensure that the A record from the second domain is returned";
844  return AST_TEST_NOT_RUN;
845  case TEST_EXECUTE:
846  break;
847  }
848 
850 }
static enum ast_test_result_state nominal_test(struct ast_test *test, resolve_fn runner)
Framework for running a nominal DNS test.
static int nominal_sync_run(struct ast_test *test, const char *domain, int rr_type, int rr_class, struct dns_record *records, size_t num_records)
Pluggable function for running a synchronous query and checking its results.
def info(msg)

◆ AST_TEST_DEFINE() [2/7]

AST_TEST_DEFINE ( resolve_async  )

Definition at line 852 of file res_resolver_unbound.c.

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), nominal_async_run(), nominal_test(), TEST_EXECUTE, and TEST_INIT.

853 {
854  switch (cmd) {
855  case TEST_INIT:
856  info->name = "resolve_async";
857  info->category = "/res/res_resolver_unbound/";
858  info->summary = "Test nominal asynchronous resolution using libunbound";
859  info->description = "This test performs the following:\n"
860  "\t* Set two static A records and one static AAAA record on one domain\n"
861  "\t* Set an A record for a second domain\n"
862  "\t* Perform an A record lookup on the first domain\n"
863  "\t* Ensure that both A records are returned and no AAAA record is returned\n"
864  "\t* Perform an AAAA record lookup on the first domain\n"
865  "\t* Ensure that the AAAA record is returned and no A record is returned\n"
866  "\t* Perform an A record lookup on the second domain\n"
867  "\t* Ensure that the A record from the second domain is returned";
868  return AST_TEST_NOT_RUN;
869  case TEST_EXECUTE:
870  break;
871  }
872 
874 }
static enum ast_test_result_state nominal_test(struct ast_test *test, resolve_fn runner)
Framework for running a nominal DNS test.
static int nominal_async_run(struct ast_test *test, const char *domain, int rr_type, int rr_class, struct dns_record *records, size_t num_records)
Pluggable function for performing an asynchronous query during a test.
def info(msg)

◆ AST_TEST_DEFINE() [3/7]

AST_TEST_DEFINE ( resolve_sync_off_nominal  )

Definition at line 1069 of file res_resolver_unbound.c.

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), off_nominal_sync_run(), off_nominal_test(), TEST_EXECUTE, and TEST_INIT.

1070 {
1071  switch (cmd) {
1072  case TEST_INIT:
1073  info->name = "resolve_sync_off_nominal";
1074  info->category = "/res/res_resolver_unbound/";
1075  info->summary = "Test off-nominal synchronous resolution using libunbound";
1076  info->description = "This test performs the following:\n"
1077  "\t* Attempt a lookup of a non-existent domain\n"
1078  "\t* Attempt a lookup of a AAAA record on a domain that contains only A records\n"
1079  "\t* Attempt a lookup of an A record on Chaos-net";
1080  return AST_TEST_NOT_RUN;
1081  case TEST_EXECUTE:
1082  break;
1083  }
1084 
1086 }
def info(msg)
static int off_nominal_sync_run(struct ast_test *test, const char *domain, int rr_type, int rr_class, int expected_rcode)
static enum ast_test_result_state off_nominal_test(struct ast_test *test, off_nominal_resolve_fn runner)

◆ AST_TEST_DEFINE() [4/7]

AST_TEST_DEFINE ( resolve_async_off_nominal  )

Definition at line 1088 of file res_resolver_unbound.c.

References AST_TEST_NOT_RUN, sip_to_pjsip::info(), off_nominal_async_run(), off_nominal_test(), TEST_EXECUTE, and TEST_INIT.

1089 {
1090  switch (cmd) {
1091  case TEST_INIT:
1092  info->name = "resolve_async_off_nominal";
1093  info->category = "/res/res_resolver_unbound/";
1094  info->summary = "Test off-nominal synchronous resolution using libunbound";
1095  info->description = "This test performs the following:\n"
1096  "\t* Attempt a lookup of a non-existent domain\n"
1097  "\t* Attempt a lookup of a AAAA record on a domain that contains only A records\n"
1098  "\t* Attempt a lookup of an A record on Chaos-net";
1099  return AST_TEST_NOT_RUN;
1100  case TEST_EXECUTE:
1101  break;
1102  }
1103 
1105 }
static int off_nominal_async_run(struct ast_test *test, const char *domain, int rr_type, int rr_class, int expected_rcode)
def info(msg)
static enum ast_test_result_state off_nominal_test(struct ast_test *test, off_nominal_resolve_fn runner)

◆ AST_TEST_DEFINE() [5/7]

AST_TEST_DEFINE ( resolve_cancel_off_nominal  )

Definition at line 1154 of file res_resolver_unbound.c.

References ao2_cleanup, ast_cond_wait, ast_dns_resolve_async(), ast_dns_resolve_cancel(), ast_mutex_lock, ast_mutex_unlock, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, async_minimal_data_alloc(), sip_to_pjsip::info(), minimal_callback(), NULL, RAII_VAR, TEST_EXECUTE, and TEST_INIT.

1155 {
1156  RAII_VAR(struct ast_dns_query_active *, active, NULL, ao2_cleanup);
1157  RAII_VAR(struct async_minimal_data *, adata, NULL, ao2_cleanup);
1158 
1159  switch (cmd) {
1160  case TEST_INIT:
1161  info->name = "resolve_cancel_off_nominal";
1162  info->category = "/res/res_resolver_unbound/";
1163  info->summary = "Off nominal cancellation test using libunbound";
1164  info->description = "This test does the following:\n"
1165  "\t* Perform an asynchronous query\n"
1166  "\t* Once the query has completed, attempt to cancel it";
1167  return AST_TEST_NOT_RUN;
1168  case TEST_EXECUTE:
1169  break;
1170  }
1171 
1172  adata = async_minimal_data_alloc();
1173  if (!adata) {
1174  ast_test_status_update(test, "Failed to allocate necessary data for test\n");
1175  return AST_TEST_FAIL;
1176  }
1177 
1178  active = ast_dns_resolve_async("crunchy.peanut.butter", ns_t_a, ns_c_in, minimal_callback, adata);
1179  if (!active) {
1180  ast_test_status_update(test, "Failed to perform asynchronous query\n");
1181  return AST_TEST_FAIL;
1182  }
1183 
1184  /* Wait for async query to complete */
1185  ast_mutex_lock(&adata->lock);
1186  while (!adata->complete) {
1187  ast_cond_wait(&adata->cond, &adata->lock);
1188  }
1189  ast_mutex_unlock(&adata->lock);
1190 
1191  if (!ast_dns_resolve_cancel(active)) {
1192  ast_test_status_update(test, "Successfully canceled completed query\n");
1193  return AST_TEST_FAIL;
1194  }
1195 
1196  return AST_TEST_PASS;
1197 }
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
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#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
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
An active DNS query.
Definition: dns_internal.h:201
def info(msg)
Minimal data required to signal the completion of an async resolve.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int ast_dns_resolve_cancel(struct ast_dns_query_active *active)
Cancel an asynchronous DNS resolution.
Definition: dns_core.c:272
static void minimal_callback(const struct ast_dns_query *query)
Async callback for off-nominal cancellation test.
static struct async_minimal_data * async_minimal_data_alloc(void)
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ AST_TEST_DEFINE() [6/7]

AST_TEST_DEFINE ( resolve_naptr  )

Definition at line 1199 of file res_resolver_unbound.c.

References ao2_bump, ao2_cleanup, ao2_global_obj_ref, ARRAY_LEN, 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_record_get_next(), ast_dns_resolve(), ast_dns_result_free(), ast_dns_result_get_records(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, globals, sip_to_pjsip::info(), NULL, order, RAII_VAR, result, TEST_EXECUTE, TEST_INIT, and dns_record::visited.

1200 {
1201  RAII_VAR(struct unbound_resolver *, resolver, NULL, ao2_cleanup);
1202  RAII_VAR(struct unbound_config *, cfg, NULL, ao2_cleanup);
1204 
1205  const struct ast_dns_record *record;
1206 
1207  static char * DOMAIN1 = "goose.feathers";
1208  int i;
1210 
1211  struct naptr_record {
1212  const char *zone_entry;
1213  uint16_t order;
1214  uint16_t preference;
1215  const char *flags;
1216  const char *services;
1217  const char *regexp;
1218  const char *replacement;
1219  int visited;
1220  } records [] = {
1221  { "goose.feathers 12345 IN NAPTR 100 100 A SIP+D2U \"\" goose.down", 100, 100, "A", "SIP+D2U", "", "goose.down", 0},
1222  { "goose.feathers 12345 IN NAPTR 100 200 A SIP+D2T \"\" duck.down", 100, 200, "A", "SIP+D2T", "", "duck.down", 0},
1223  { "goose.feathers 12345 IN NAPTR 200 100 A SIPS+D2U \"\" pheasant.down", 200, 100, "A", "SIPS+D2U", "", "pheasant.down", 0},
1224  { "goose.feathers 12345 IN NAPTR 200 200 A SIPS+D2T \"\" platypus.fur", 200, 200, "A", "SIPS+D2T", "", "platypus.fur", 0},
1225  };
1226 
1227  switch (cmd) {
1228  case TEST_INIT:
1229  info->name = "resolve_naptr";
1230  info->category = "/res/res_resolver_unbound/";
1231  info->summary = "Attempt resolution of NAPTR record";
1232  info->description = "This test performs a NAPTR lookup and ensures that\n"
1233  "the returned record has the appropriate values set";
1234  return AST_TEST_NOT_RUN;
1235  case TEST_EXECUTE:
1236  break;
1237  }
1238 
1239  cfg = ao2_global_obj_ref(globals);
1240  resolver = ao2_bump(cfg->global->state->resolver);
1241 
1242  ub_ctx_zone_add(resolver->context, DOMAIN1, "static");
1243 
1244  for (i = 0; i < ARRAY_LEN(records); ++i) {
1245  ub_ctx_data_add(resolver->context, records[i].zone_entry);
1246  }
1247 
1248  if (ast_dns_resolve(DOMAIN1, ns_t_naptr, ns_c_in, &result)) {
1249  ast_test_status_update(test, "Failed to resolve domain\n");
1250  return AST_TEST_FAIL;
1251  }
1252 
1253  if (!result) {
1254  ast_test_status_update(test, "Successful resolution set a NULL result\n");
1255  return AST_TEST_FAIL;
1256  }
1257 
1259  if (!record) {
1260  ast_test_status_update(test, "Failed to get any DNS records from the result\n");
1261  return AST_TEST_FAIL;
1262  }
1263 
1264  i = 0;
1265  for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) {
1266  if (ast_dns_naptr_get_order(record) != records[i].order) {
1267  ast_test_status_update(test, "Expected order %hu, got order %hu from NAPTR record\n",
1268  records[i].order, ast_dns_naptr_get_order(record));
1269  res = AST_TEST_FAIL;
1270  }
1271  if (ast_dns_naptr_get_preference(record) != records[i].preference) {
1272  ast_test_status_update(test, "Expected preference %hu, got preference %hu from NAPTR record\n",
1273  records[i].preference, ast_dns_naptr_get_preference(record));
1274  res = AST_TEST_FAIL;
1275  }
1276  if (strcmp(ast_dns_naptr_get_flags(record), records[i].flags)) {
1277  ast_test_status_update(test, "Expected flags %s, got flags %s from NAPTR record\n",
1278  records[i].flags, ast_dns_naptr_get_flags(record));
1279  res = AST_TEST_FAIL;
1280  }
1281  if (strcmp(ast_dns_naptr_get_service(record), records[i].services)) {
1282  ast_test_status_update(test, "Expected services %s, got services %s from NAPTR record\n",
1283  records[i].services, ast_dns_naptr_get_service(record));
1284  res = AST_TEST_FAIL;
1285  }
1286  if (strcmp(ast_dns_naptr_get_regexp(record), records[i].regexp)) {
1287  ast_test_status_update(test, "Expected regexp %s, got regexp %s from NAPTR record\n",
1288  records[i].regexp, ast_dns_naptr_get_regexp(record));
1289  res = AST_TEST_FAIL;
1290  }
1291  if (strcmp(ast_dns_naptr_get_replacement(record), records[i].replacement)) {
1292  ast_test_status_update(test, "Expected replacement %s, got replacement %s from NAPTR record\n",
1293  records[i].replacement, ast_dns_naptr_get_replacement(record));
1294  res = AST_TEST_FAIL;
1295  }
1296  records[i].visited = 1;
1297  ++i;
1298  }
1299 
1300  if (i != ARRAY_LEN(records)) {
1301  ast_test_status_update(test, "Unexpected number of records visited\n");
1302  res = AST_TEST_FAIL;
1303  }
1304 
1305  for (i = 0; i < ARRAY_LEN(records); ++i) {
1306  if (!records[i].visited) {
1307  ast_test_status_update(test, "Did not visit all expected NAPTR records\n");
1308  res = AST_TEST_FAIL;
1309  }
1310  }
1311 
1312  return res;
1313 
1314 }
static int records
Definition: cdr_mysql.c:84
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_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
Synchronously resolve a DNS query.
Definition: dns_core.c:314
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
void ast_dns_result_free(struct ast_dns_result *result)
Free the DNS result information.
Definition: dns_core.c:130
A container for config related information.
struct ast_dns_test_string flags
uint16_t preference
For AST_LIST.
Definition: dns_internal.h:39
const char * ast_dns_naptr_get_regexp(const struct ast_dns_record *record)
Get the regular expression from a NAPTR record.
Definition: dns_naptr.c:616
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
unsigned short ast_dns_naptr_get_preference(const struct ast_dns_record *record)
Get the preference from a NAPTR record.
Definition: dns_naptr.c:640
#define NULL
Definition: resample.c:96
const char * ast_dns_naptr_get_service(const struct ast_dns_record *record)
Get the service from a NAPTR record.
Definition: dns_naptr.c:608
#define ao2_bump(obj)
Definition: astobj2.h:491
#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
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
static struct console_pvt globals
struct ast_dns_test_string services
The result of a DNS query.
Definition: dns_internal.h:117
const char * ast_dns_naptr_get_flags(const struct ast_dns_record *record)
Get the flags from a NAPTR record.
Definition: dns_naptr.c:600
def info(msg)
const char * replacement
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
unsigned short ast_dns_naptr_get_order(const struct ast_dns_record *record)
Get the order from a NAPTR record.
Definition: dns_naptr.c:632
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static PGresult * result
Definition: cel_pgsql.c:88
Structure for an unbound resolver.
const char * ast_dns_naptr_get_replacement(const struct ast_dns_record *record)
Get the replacement value from a NAPTR record.
Definition: dns_naptr.c:624
uint16_t order
struct ast_dns_test_string regexp
ast_test_result_state
Definition: test.h:200

◆ AST_TEST_DEFINE() [7/7]

AST_TEST_DEFINE ( resolve_srv  )

Definition at line 1316 of file res_resolver_unbound.c.

References ao2_bump, ao2_cleanup, ao2_global_obj_ref, ast_dns_resolve(), ast_dns_result_free(), ast_dns_result_get_records(), ast_dns_srv_get_host(), ast_dns_srv_get_port(), ast_dns_srv_get_priority(), ast_dns_srv_get_weight(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, cleanup(), globals, sip_to_pjsip::info(), NULL, RAII_VAR, result, TEST_EXECUTE, and TEST_INIT.

1317 {
1318  RAII_VAR(struct unbound_resolver *, resolver, NULL, ao2_cleanup);
1319  RAII_VAR(struct unbound_config *, cfg, NULL, ao2_cleanup);
1321  const struct ast_dns_record *record;
1322  static const char *DOMAIN1 = "taco.bananas";
1323  static const char *DOMAIN1_SRV = "taco.bananas 12345 IN SRV 10 20 5060 sip.taco.bananas";
1325 
1326  switch (cmd) {
1327  case TEST_INIT:
1328  info->name = "resolve_srv";
1329  info->category = "/res/res_resolver_unbound/";
1330  info->summary = "Test synchronous SRV resolution using libunbound";
1331  info->description = "This test performs the following:\n"
1332  "\t* Set one SRV record on one domain\n"
1333  "\t* Perform an SRV lookup on the domain\n"
1334  "\t* Ensure that the SRV record returned matches the expected value";
1335  return AST_TEST_NOT_RUN;
1336  case TEST_EXECUTE:
1337  break;
1338  }
1339 
1340  cfg = ao2_global_obj_ref(globals);
1341  resolver = ao2_bump(cfg->global->state->resolver);
1342 
1343  ub_ctx_zone_add(resolver->context, DOMAIN1, "static");
1344  ub_ctx_data_add(resolver->context, DOMAIN1_SRV);
1345 
1346  if (ast_dns_resolve(DOMAIN1, ns_t_srv, ns_c_in, &result)) {
1347  ast_test_status_update(test, "Failed to synchronously resolve SRV for domain '%s'\n", DOMAIN1);
1348  res = AST_TEST_FAIL;
1349  goto cleanup;
1350  }
1351 
1353  if (ast_dns_srv_get_priority(record) != 10) {
1354  ast_test_status_update(test, "SRV Record returned priority '%d' when we expected 10\n", ast_dns_srv_get_priority(record));
1355  res = AST_TEST_FAIL;
1356  goto cleanup;
1357  }
1358 
1359  if (ast_dns_srv_get_weight(record) != 20) {
1360  ast_test_status_update(test, "SRV Record returned weight '%d' when we expected 20\n", ast_dns_srv_get_weight(record));
1361  res = AST_TEST_FAIL;
1362  goto cleanup;
1363  }
1364 
1365  if (ast_dns_srv_get_port(record) != 5060) {
1366  ast_test_status_update(test, "SRV Record returned port '%d' when we expected 5060\n", ast_dns_srv_get_port(record));
1367  res = AST_TEST_FAIL;
1368  goto cleanup;
1369  }
1370 
1371  if (strcmp(ast_dns_srv_get_host(record), "sip.taco.bananas")) {
1372  ast_test_status_update(test, "SRV Record returned host '%s' when we expected sip.taco.bananas\n", ast_dns_srv_get_host(record));
1373  res = AST_TEST_FAIL;
1374  goto cleanup;
1375  }
1376 
1377 cleanup:
1378  ub_ctx_data_remove(resolver->context, DOMAIN1_SRV);
1379  ub_ctx_zone_remove(resolver->context, DOMAIN1);
1380 
1381  return res;
1382 }
unsigned short ast_dns_srv_get_priority(const struct ast_dns_record *record)
Get the priority from an SRV record.
Definition: dns_srv.c:196
int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
Synchronously resolve a DNS query.
Definition: dns_core.c:314
void ast_dns_result_free(struct ast_dns_result *result)
Free the DNS result information.
Definition: dns_core.c:130
A container for config related information.
For AST_LIST.
Definition: dns_internal.h:39
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define NULL
Definition: resample.c:96
unsigned short ast_dns_srv_get_port(const struct ast_dns_record *record)
Get the port from an SRV record.
Definition: dns_srv.c:212
const char * ast_dns_srv_get_host(const struct ast_dns_record *record)
Get the hostname from an SRV record.
Definition: dns_srv.c:188
unsigned short ast_dns_srv_get_weight(const struct ast_dns_record *record)
Get the weight from an SRV record.
Definition: dns_srv.c:204
#define ao2_bump(obj)
Definition: astobj2.h:491
#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
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
static struct console_pvt globals
The result of a DNS query.
Definition: dns_internal.h:117
def info(msg)
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
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static PGresult * result
Definition: cel_pgsql.c:88
Structure for an unbound resolver.
ast_test_result_state
Definition: test.h:200

◆ async_callback()

static void async_callback ( const struct ast_dns_query query)
static

Callback for asynchronous queries.

This query will check that the records in the DNS result match records that the test has created. The success or failure of the query is indicated through the async_data failed field.

Parameters
queryThe DNS query that has been resolved

Definition at line 649 of file res_resolver_unbound.c.

References ast_cond_signal, ast_dns_query_get_data(), ast_dns_query_get_result(), ast_dns_record_get_data(), ast_dns_record_get_next(), ast_dns_record_get_rr_class(), ast_dns_record_get_rr_type(), ast_dns_record_get_ttl(), ast_dns_result_get_records(), ast_mutex_lock, ast_mutex_unlock, dns_record::buf, dns_record::bufsize, async_data::complete, async_data::cond, end, async_data::failed, async_data::lock, match(), async_data::num_records, async_data::records, result, dns_record::rr_class, dns_record::rr_type, dns_record::ttl, and dns_record::visited.

Referenced by nominal_async_run().

650 {
651  struct async_data *adata = ast_dns_query_get_data(query);
653  const struct ast_dns_record *record;
654  int i;
655 
656  if (!result) {
657  adata->failed = -1;
658  goto end;
659  }
660 
661  for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) {
662  int match = 0;
663 
664  /* Let's make sure this matches one of our known records */
665  for (i = 0; i < adata->num_records; ++i) {
666  if (ast_dns_record_get_rr_type(record) == adata->records[i].rr_type &&
667  ast_dns_record_get_rr_class(record) == adata->records[i].rr_class &&
668  ast_dns_record_get_ttl(record) == adata->records[i].ttl &&
669  !memcmp(ast_dns_record_get_data(record), adata->records[i].buf, adata->records[i].bufsize)) {
670  match = 1;
671  adata->records[i].visited = 1;
672  break;
673  }
674  }
675 
676  if (!match) {
677  adata->failed = -1;
678  goto end;
679  }
680  }
681 
682 end:
683  ast_mutex_lock(&adata->lock);
684  adata->complete = 1;
685  ast_cond_signal(&adata->cond);
686  ast_mutex_unlock(&adata->lock);
687 }
int ast_dns_record_get_ttl(const struct ast_dns_record *record)
Get the TTL of a DNS record.
Definition: dns_core.c:155
Data required for an asynchronous callback.
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
const char * ast_dns_record_get_data(const struct ast_dns_record *record)
Retrieve the raw DNS record.
Definition: dns_core.c:160
ast_mutex_t lock
const size_t bufsize
For AST_LIST.
Definition: dns_internal.h:39
#define ast_mutex_lock(a)
Definition: lock.h:187
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2315
char * end
Definition: eagi_proxy.c:73
#define ast_cond_signal(cond)
Definition: lock.h:201
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
The result of a DNS query.
Definition: dns_internal.h:117
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
struct dns_record * 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.
Definition: dns_core.c:102
const char * buf
static PGresult * result
Definition: cel_pgsql.c:88
int ast_dns_record_get_rr_class(const struct ast_dns_record *record)
Get the resource record class of a DNS record.
Definition: dns_core.c:150
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
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ async_data_alloc()

static struct async_data* async_data_alloc ( struct dns_record records,
size_t  num_records 
)
static

Definition at line 623 of file res_resolver_unbound.c.

References ao2_alloc, ast_cond_init, ast_mutex_init, async_data_destructor(), async_data::cond, async_data::lock, NULL, async_data::num_records, records, and async_data::records.

Referenced by nominal_async_run().

624 {
625  struct async_data *adata;
626 
627  adata = ao2_alloc(sizeof(*adata), async_data_destructor);
628  if (!adata) {
629  return NULL;
630  }
631 
632  ast_mutex_init(&adata->lock);
633  ast_cond_init(&adata->cond, NULL);
634  adata->records = records;
635  adata->num_records = num_records;
636 
637  return adata;
638 }
Data required for an asynchronous callback.
static int records
Definition: cdr_mysql.c:84
ast_mutex_t lock
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define NULL
Definition: resample.c:96
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct dns_record * records
static void async_data_destructor(void *obj)
#define ast_mutex_init(pmutex)
Definition: lock.h:184

◆ async_data_destructor()

static void async_data_destructor ( void *  obj)
static

Definition at line 615 of file res_resolver_unbound.c.

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

Referenced by async_data_alloc().

616 {
617  struct async_data *adata = obj;
618 
619  ast_mutex_destroy(&adata->lock);
620  ast_cond_destroy(&adata->cond);
621 }
Data required for an asynchronous callback.
ast_mutex_t lock
#define ast_cond_destroy(cond)
Definition: lock.h:200
#define ast_mutex_destroy(a)
Definition: lock.h:186

◆ async_minimal_data_alloc()

static struct async_minimal_data* async_minimal_data_alloc ( void  )
static

Definition at line 1124 of file res_resolver_unbound.c.

References ao2_alloc, ast_cond_init, ast_mutex_init, async_minimal_data_destructor(), async_minimal_data::cond, async_minimal_data::lock, and NULL.

Referenced by AST_TEST_DEFINE().

1125 {
1126  struct async_minimal_data *adata;
1127 
1128  adata = ao2_alloc(sizeof(*adata), async_minimal_data_destructor);
1129  if (!adata) {
1130  return NULL;
1131  }
1132 
1133  ast_mutex_init(&adata->lock);
1134  ast_cond_init(&adata->cond, NULL);
1135 
1136  return adata;
1137 }
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define NULL
Definition: resample.c:96
static void async_minimal_data_destructor(void *obj)
Minimal data required to signal the completion of an async resolve.
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define ast_mutex_init(pmutex)
Definition: lock.h:184

◆ async_minimal_data_destructor()

static void async_minimal_data_destructor ( void *  obj)
static

Definition at line 1116 of file res_resolver_unbound.c.

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

Referenced by async_minimal_data_alloc().

1117 {
1118  struct async_minimal_data *adata = obj;
1119 
1120  ast_mutex_destroy(&adata->lock);
1121  ast_cond_destroy(&adata->cond);
1122 }
#define ast_cond_destroy(cond)
Definition: lock.h:200
Minimal data required to signal the completion of an async resolve.
#define ast_mutex_destroy(a)
Definition: lock.h:186

◆ CONFIG_INFO_STANDARD()

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.

◆ custom_nameserver_handler()

static int custom_nameserver_handler ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
)
static

Definition at line 1409 of file res_resolver_unbound.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ast_str_container_add(), ast_str_container_alloc_options(), global, unbound_global_config::nameservers, and ast_variable::value.

Referenced by load_module().

1410 {
1411  struct unbound_global_config *global = obj;
1412 
1413  if (!global->nameservers) {
1415  if (!global->nameservers) {
1416  return -1;
1417  }
1418  }
1419 
1420  return ast_str_container_add(global->nameservers, var->value);
1421 }
static struct aco_type global
Definition: test_config.c:1445
A structure to hold global configuration-related options.
struct ao2_container * ast_str_container_alloc_options(enum ao2_alloc_opts opts, int buckets)
Allocates a hash container for bare strings.
Definition: strings.c:201
struct ao2_container * nameservers
List of nameservers (in order) to use for queries.
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.
Definition: strings.c:206

◆ load_module()

static int load_module ( void  )
static

Definition at line 1423 of file res_resolver_unbound.c.

References ACO_EXACT, aco_info_init(), aco_option_register, aco_option_register_custom, aco_process_config(), ACO_PROCESS_ERROR, ast_config_destroy(), ast_config_load, ast_dns_resolver_register(), AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CHANNEL_DEPEND, AST_MODULE_INFO(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_module_shutdown_ref, AST_MODULE_SUPPORT_CORE, AST_TEST_REGISTER, ASTERISK_GPL_KEY, custom_nameserver_handler(), debug, aco_file::filename, FLDSET, OPT_STRINGFIELD_T, OPT_UINT_T, reload(), reload_module(), ast_module_info::self, STRFLDSET, unbound_config_apply_default(), and unload_module().

1424 {
1425  struct ast_config *cfg;
1426  struct ast_flags cfg_flags = { 0, };
1427 
1428  if (aco_info_init(&cfg_info)) {
1429  return AST_MODULE_LOAD_DECLINE;
1430  }
1431 
1432  aco_option_register(&cfg_info, "hosts", ACO_EXACT, global_options, "system", OPT_STRINGFIELD_T, 0, STRFLDSET(struct unbound_global_config, hosts));
1433  aco_option_register(&cfg_info, "resolv", ACO_EXACT, global_options, "system", OPT_STRINGFIELD_T, 0, STRFLDSET(struct unbound_global_config, resolv));
1435  aco_option_register(&cfg_info, "debug", ACO_EXACT, global_options, "0", OPT_UINT_T, 0, FLDSET(struct unbound_global_config, debug));
1436  aco_option_register(&cfg_info, "ta_file", ACO_EXACT, global_options, "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct unbound_global_config, ta_file));
1437 
1438  /* This purposely checks for a configuration file so we don't output an error message in ACO if one is not present */
1440  if (!cfg) {
1442  unload_module();
1443  return AST_MODULE_LOAD_DECLINE;
1444  }
1445  } else {
1446  ast_config_destroy(cfg);
1447  if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
1448  unload_module();
1449  return AST_MODULE_LOAD_DECLINE;
1450  }
1451  }
1452 
1454 
1456 
1457  AST_TEST_REGISTER(resolve_sync);
1458  AST_TEST_REGISTER(resolve_async);
1459  AST_TEST_REGISTER(resolve_sync_off_nominal);
1460  AST_TEST_REGISTER(resolve_async_off_nominal);
1461  AST_TEST_REGISTER(resolve_cancel_off_nominal);
1462  AST_TEST_REGISTER(resolve_naptr);
1463  AST_TEST_REGISTER(resolve_srv);
1464 
1465  return AST_MODULE_LOAD_SUCCESS;
1466 }
static int unload_module(void)
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
static int debug
Global debug status.
Definition: res_xmpp.c:435
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
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.
static int custom_nameserver_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
A structure to hold global configuration-related options.
#define ast_config_load(filename, flags)
Load a config file.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
struct ast_module * self
Definition: module.h:342
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
Type for default option handler for unsigned integers.
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
Definition: dns_core.c:630
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
Their was an error and no changes were applied.
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
Definition: module.h:464
static int unbound_config_apply_default(void)
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
Structure used to handle boolean flags.
Definition: utils.h:199
const char * filename
Structure for an unbound resolver.
static struct aco_type * global_options[]
Type for default option handler for stringfields.
static struct aco_file resolver_unbound_conf

◆ minimal_callback()

static void minimal_callback ( const struct ast_dns_query query)
static

Async callback for off-nominal cancellation test.

This simply signals the testing thread that the query completed

Definition at line 1144 of file res_resolver_unbound.c.

References ast_cond_signal, ast_dns_query_get_data(), ast_mutex_lock, ast_mutex_unlock, async_minimal_data::complete, async_minimal_data::cond, and async_minimal_data::lock.

Referenced by AST_TEST_DEFINE().

1145 {
1146  struct async_minimal_data *adata = ast_dns_query_get_data(query);
1147 
1148  ast_mutex_lock(&adata->lock);
1149  adata->complete = 1;
1150  ast_cond_signal(&adata->cond);
1151  ast_mutex_unlock(&adata->lock);
1152 }
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_cond_signal(cond)
Definition: lock.h:201
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
Minimal data required to signal the completion of an async resolve.
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ nominal_async_run()

static int nominal_async_run ( struct ast_test test,
const char *  domain,
int  rr_type,
int  rr_class,
struct dns_record records,
size_t  num_records 
)
static

Pluggable function for performing an asynchronous query during a test.

Unlike the synchronous version, this does not check the records, instead leaving that to be done in the asynchronous callback.

Definition at line 695 of file res_resolver_unbound.c.

References ao2_cleanup, ast_cond_wait, ast_dns_resolve_async(), ast_mutex_lock, ast_mutex_unlock, ast_test_status_update, async_callback(), async_data_alloc(), NULL, RAII_VAR, and dns_record::visited.

Referenced by AST_TEST_DEFINE().

697 {
698  RAII_VAR(struct ast_dns_query_active *, active, NULL, ao2_cleanup);
699  RAII_VAR(struct async_data *, adata, NULL, ao2_cleanup);
700  int i;
701 
702  adata = async_data_alloc(records, num_records);
703  if (!adata) {
704  ast_test_status_update(test, "Unable to allocate data for async query\n");
705  return -1;
706  }
707 
708  /* Start by making sure no records have been visited */
709  for (i = 0; i < num_records; ++i) {
710  records[i].visited = 0;
711  }
712 
713  ast_test_status_update(test, "Performing DNS query '%s', type %d\n", domain, rr_type);
714 
715  active = ast_dns_resolve_async(domain, rr_type, rr_class, async_callback, adata);
716  if (!active) {
717  ast_test_status_update(test, "Failed to perform asynchronous resolution of domain %s\n", domain);
718  return -1;
719  }
720 
721  ast_mutex_lock(&adata->lock);
722  while (!adata->complete) {
723  ast_cond_wait(&adata->cond, &adata->lock);
724  }
725  ast_mutex_unlock(&adata->lock);
726 
727  if (adata->failed) {
728  ast_test_status_update(test, "Unknown DNS record returned from domain %s\n", domain);
729  }
730  return adata->failed;
731 }
Data required for an asynchronous callback.
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
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
Domain data structure.
Definition: sip.h:888
#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
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
static void async_callback(const struct ast_dns_query *query)
Callback for asynchronous queries.
An active DNS query.
Definition: dns_internal.h:201
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct async_data * async_data_alloc(struct dns_record *records, size_t num_records)
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ nominal_sync_run()

static int nominal_sync_run ( struct ast_test test,
const char *  domain,
int  rr_type,
int  rr_class,
struct dns_record records,
size_t  num_records 
)
static

Pluggable function for running a synchronous query and checking its results.

Definition at line 551 of file res_resolver_unbound.c.

References ast_dns_record_get_data(), ast_dns_record_get_next(), ast_dns_record_get_rr_class(), ast_dns_record_get_rr_type(), ast_dns_record_get_ttl(), ast_dns_resolve(), ast_dns_result_free(), ast_dns_result_get_records(), ast_test_status_update, buf, match(), NULL, RAII_VAR, result, dns_record::rr_class, dns_record::rr_type, dns_record::ttl, and dns_record::visited.

Referenced by AST_TEST_DEFINE().

553 {
555  const struct ast_dns_record *record;
556  int i;
557 
558  /* Start by making sure no records have been visited */
559  for (i = 0; i < num_records; ++i) {
560  records[i].visited = 0;
561  }
562 
563  ast_test_status_update(test, "Performing DNS query '%s', type %d\n", domain, rr_type);
564 
566  ast_test_status_update(test, "Failed to perform synchronous resolution of domain %s\n", domain);
567  return -1;
568  }
569 
570  if (!result) {
571  ast_test_status_update(test, "Successful synchronous resolution of domain %s gave NULL result\n", domain);
572  return -1;
573  }
574 
575  for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) {
576  int match = 0;
577 
578  /* Let's make sure this matches one of our known records */
579  for (i = 0; i < num_records; ++i) {
580  if (ast_dns_record_get_rr_type(record) == records[i].rr_type &&
581  ast_dns_record_get_rr_class(record) == records[i].rr_class &&
582  ast_dns_record_get_ttl(record) == records[i].ttl &&
583  !memcmp(ast_dns_record_get_data(record), records[i].buf, records[i].bufsize)) {
584  match = 1;
585  records[i].visited = 1;
586  break;
587  }
588  }
589 
590  if (!match) {
591  ast_test_status_update(test, "Unknown DNS record returned from domain %s\n", domain);
592  return -1;
593  }
594  }
595 
596  return 0;
597 }
int ast_dns_record_get_ttl(const struct ast_dns_record *record)
Get the TTL of a DNS record.
Definition: dns_core.c:155
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
const char * ast_dns_record_get_data(const struct ast_dns_record *record)
Retrieve the raw DNS record.
Definition: dns_core.c:160
int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
Synchronously resolve a DNS query.
Definition: dns_core.c:314
void ast_dns_result_free(struct ast_dns_result *result)
Free the DNS result information.
Definition: dns_core.c:130
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
For AST_LIST.
Definition: dns_internal.h:39
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2315
#define NULL
Definition: resample.c:96
Domain data structure.
Definition: sip.h:888
#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
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
The result of a DNS query.
Definition: dns_internal.h:117
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
static PGresult * result
Definition: cel_pgsql.c:88
int ast_dns_record_get_rr_class(const struct ast_dns_record *record)
Get the resource record class of a DNS record.
Definition: dns_core.c:150
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
int rr_type
Resource record type.
Definition: dns_internal.h:41
int rr_class
Resource record class.
Definition: dns_internal.h:43

◆ nominal_test()

static enum ast_test_result_state nominal_test ( struct ast_test test,
resolve_fn  runner 
)
static

Framework for running a nominal DNS test.

Synchronous and asynchronous tests mostly have the same setup, so this function serves as a common way to set up both types of tests by accepting a pluggable function to determine which type of lookup is used

Parameters
testThe test being run
runnerThe method for resolving queries on this test

Definition at line 743 of file res_resolver_unbound.c.

References ao2_bump, ao2_cleanup, ao2_global_obj_ref, ARRAY_LEN, dns_record::as_string, AST_TEST_FAIL, AST_TEST_PASS, ast_test_status_update, cleanup(), globals, NULL, and RAII_VAR.

Referenced by AST_TEST_DEFINE().

744 {
745  RAII_VAR(struct unbound_resolver *, resolver, NULL, ao2_cleanup);
746  RAII_VAR(struct unbound_config *, cfg, NULL, ao2_cleanup);
747 
748  static const size_t V4_SIZE = sizeof(struct in_addr);
749  static const size_t V6_SIZE = sizeof(struct in6_addr);
750 
751  static const char *DOMAIN1 = "goose.feathers";
752  static const char *DOMAIN2 = "duck.feathers";
753 
754  static const char *ADDR1 = "127.0.0.2";
755  static const char *ADDR2 = "127.0.0.3";
756  static const char *ADDR3 = "::1";
757  static const char *ADDR4 = "127.0.0.4";
758 
759  char addr1_buf[V4_SIZE];
760  char addr2_buf[V4_SIZE];
761  char addr3_buf[V6_SIZE];
762  char addr4_buf[V4_SIZE];
763 
764  struct dns_record records [] = {
765  { "goose.feathers 12345 IN A 127.0.0.2", DOMAIN1, ns_t_a, ns_c_in, 12345, addr1_buf, V4_SIZE, 0 },
766  { "goose.feathers 12345 IN A 127.0.0.3", DOMAIN1, ns_t_a, ns_c_in, 12345, addr2_buf, V4_SIZE, 0 },
767  { "goose.feathers 12345 IN AAAA ::1", DOMAIN1, ns_t_aaaa, ns_c_in, 12345, addr3_buf, V6_SIZE, 0 },
768  { "duck.feathers 12345 IN A 127.0.0.4", DOMAIN2, ns_t_a, ns_c_in, 12345, addr4_buf, V4_SIZE, 0 },
769  };
770 
771  struct {
772  const char *domain;
773  int rr_type;
774  int rr_class;
775  int visited[ARRAY_LEN(records)];
776  } runs [] = {
777  { DOMAIN1, ns_t_a, ns_c_in, { 1, 1, 0, 0 } },
778  { DOMAIN1, ns_t_aaaa, ns_c_in, { 0, 0, 1, 0 } },
779  { DOMAIN2, ns_t_a, ns_c_in, { 0, 0, 0, 1 } },
780  };
781 
782  int i;
784 
785  inet_pton(AF_INET, ADDR1, addr1_buf);
786  inet_pton(AF_INET, ADDR2, addr2_buf);
787  inet_pton(AF_INET6, ADDR3, addr3_buf);
788  inet_pton(AF_INET, ADDR4, addr4_buf);
789 
791  resolver = ao2_bump(cfg->global->state->resolver);
792 
793  ub_ctx_zone_add(resolver->context, DOMAIN1, "static");
794  ub_ctx_zone_add(resolver->context, DOMAIN2, "static");
795 
796  for (i = 0; i < ARRAY_LEN(records); ++i) {
797  ub_ctx_data_add(resolver->context, records[i].as_string);
798  }
799 
800  for (i = 0; i < ARRAY_LEN(runs); ++i) {
801  int j;
802 
803  if (runner(test, runs[i].domain, runs[i].rr_type, runs[i].rr_class, records, ARRAY_LEN(records))) {
804  res = AST_TEST_FAIL;
805  goto cleanup;
806  }
807 
808  for (j = 0; j < ARRAY_LEN(records); ++j) {
809  if (records[j].visited != runs[i].visited[j]) {
810  ast_test_status_update(test, "DNS results match unexpected records\n");
811  res = AST_TEST_FAIL;
812  goto cleanup;
813  }
814  }
815  }
816 
817 cleanup:
818  for (i = 0; i < ARRAY_LEN(records); ++i) {
819  ub_ctx_data_remove(resolver->context, records[i].as_string);
820  }
821  ub_ctx_zone_remove(resolver->context, DOMAIN1);
822  ub_ctx_zone_remove(resolver->context, DOMAIN2);
823 
824  return res;
825 }
static int records
Definition: cdr_mysql.c:84
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
A container for config related information.
A DNS record to be used during a test.
const char * as_string
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define NULL
Definition: resample.c:96
const char * domain
Domain data structure.
Definition: sip.h:888
#define ao2_bump(obj)
Definition: astobj2.h:491
#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
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
static struct console_pvt globals
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Structure for an unbound resolver.
ast_test_result_state
Definition: test.h:200

◆ off_nominal_async_callback()

static void off_nominal_async_callback ( const struct ast_dns_query query)
static

Async callback for off-nominal async test.

This test ensures that there is a result present on the query, then it checks that the rcode on the result is the expected value and that there are no records on the result.

Once completed, the testing thread is signaled that the async query has completed.

Definition at line 958 of file res_resolver_unbound.c.

References ast_cond_signal, ast_dns_query_get_data(), ast_dns_query_get_result(), ast_dns_result_get_rcode(), ast_dns_result_get_records(), ast_mutex_lock, ast_mutex_unlock, off_nominal_async_data::complete, off_nominal_async_data::cond, end, off_nominal_async_data::expected_rcode, off_nominal_async_data::failed, off_nominal_async_data::lock, and result.

Referenced by off_nominal_async_run().

959 {
960  struct off_nominal_async_data *adata = ast_dns_query_get_data(query);
962 
963  if (!result) {
964  adata->failed = -1;
965  goto end;
966  }
967 
968  if (ast_dns_result_get_rcode(result) != adata->expected_rcode) {
969  adata->failed = -1;
970  }
971 
972  if (ast_dns_result_get_records(result)) {
973  adata->failed = -1;
974  }
975 
976 end:
977  ast_mutex_lock(&adata->lock);
978  adata->complete = 1;
979  ast_cond_signal(&adata->cond);
980  ast_mutex_unlock(&adata->lock);
981 }
#define ast_mutex_lock(a)
Definition: lock.h:187
char * end
Definition: eagi_proxy.c:73
#define ast_cond_signal(cond)
Definition: lock.h:201
User data for off-nominal async resolution test.
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
The result of a DNS query.
Definition: dns_internal.h:117
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
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
static PGresult * result
Definition: cel_pgsql.c:88
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
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ off_nominal_async_data_alloc()

static struct off_nominal_async_data* off_nominal_async_data_alloc ( int  expected_rcode)
static

Definition at line 931 of file res_resolver_unbound.c.

References ao2_alloc, ast_cond_init, ast_mutex_init, off_nominal_async_data::cond, off_nominal_async_data::expected_rcode, off_nominal_async_data::lock, NULL, and off_nominal_async_data_destructor().

Referenced by off_nominal_async_run().

932 {
933  struct off_nominal_async_data *adata;
934 
935  adata = ao2_alloc(sizeof(*adata), off_nominal_async_data_destructor);
936  if (!adata) {
937  return NULL;
938  }
939 
940  ast_mutex_init(&adata->lock);
941  ast_cond_init(&adata->cond, NULL);
942 
944 
945  return adata;
946 }
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define NULL
Definition: resample.c:96
static void off_nominal_async_data_destructor(void *obj)
User data for off-nominal async resolution test.
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define ast_mutex_init(pmutex)
Definition: lock.h:184

◆ off_nominal_async_data_destructor()

static void off_nominal_async_data_destructor ( void *  obj)
static

Definition at line 923 of file res_resolver_unbound.c.

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

Referenced by off_nominal_async_data_alloc().

924 {
925  struct off_nominal_async_data *adata = obj;
926 
927  ast_mutex_destroy(&adata->lock);
928  ast_cond_destroy(&adata->cond);
929 }
User data for off-nominal async resolution test.
#define ast_cond_destroy(cond)
Definition: lock.h:200
#define ast_mutex_destroy(a)
Definition: lock.h:186

◆ off_nominal_async_run()

static int off_nominal_async_run ( struct ast_test test,
const char *  domain,
int  rr_type,
int  rr_class,
int  expected_rcode 
)
static

Definition at line 983 of file res_resolver_unbound.c.

References ao2_cleanup, ast_cond_wait, ast_dns_resolve_async(), ast_mutex_lock, ast_mutex_unlock, ast_test_status_update, NULL, off_nominal_async_callback(), off_nominal_async_data_alloc(), and RAII_VAR.

Referenced by AST_TEST_DEFINE().

985 {
986  RAII_VAR(struct ast_dns_query_active *, active, NULL, ao2_cleanup);
987  RAII_VAR(struct off_nominal_async_data *, adata, NULL, ao2_cleanup);
988 
990  if (!adata) {
991  ast_test_status_update(test, "Unable to allocate data for async query\n");
992  return -1;
993  }
994 
995  ast_test_status_update(test, "Performing DNS query '%s', type %d\n", domain, rr_type);
996 
997  active = ast_dns_resolve_async(domain, rr_type, rr_class, off_nominal_async_callback, adata);
998  if (!active) {
999  ast_test_status_update(test, "Failed to perform asynchronous resolution of domain %s\n", domain);
1000  return -1;
1001  }
1002 
1003  ast_mutex_lock(&adata->lock);
1004  while (!adata->complete) {
1005  ast_cond_wait(&adata->cond, &adata->lock);
1006  }
1007  ast_mutex_unlock(&adata->lock);
1008 
1009  if (adata->failed) {
1010  ast_test_status_update(test, "Asynchronous resolution failure %s\n", domain);
1011  }
1012  return adata->failed;
1013 }
static struct off_nominal_async_data * off_nominal_async_data_alloc(int expected_rcode)
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
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
Domain data structure.
Definition: sip.h:888
User data for off-nominal async resolution test.
#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
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
An active DNS query.
Definition: dns_internal.h:201
static void off_nominal_async_callback(const struct ast_dns_query *query)
Async callback for off-nominal async test.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ off_nominal_sync_run()

static int off_nominal_sync_run ( struct ast_test test,
const char *  domain,
int  rr_type,
int  rr_class,
int  expected_rcode 
)
static

Definition at line 879 of file res_resolver_unbound.c.

References ast_dns_resolve(), ast_dns_result_free(), ast_dns_result_get_rcode(), ast_dns_result_get_records(), ast_test_status_update, and result.

Referenced by AST_TEST_DEFINE().

881 {
882  struct ast_dns_result *result;
883  int res = 0;
884 
885  if (ast_dns_resolve(domain, rr_type, rr_class, &result)) {
886  ast_test_status_update(test, "Failed to perform resolution :(\n");
887  return -1;
888  }
889 
890  if (!result) {
891  ast_test_status_update(test, "Resolution returned no result\n");
892  return -1;
893  }
894 
895  if (ast_dns_result_get_rcode(result) != expected_rcode) {
896  ast_test_status_update(test, "Unexpected rcode from DNS resolution\n");
897  res = -1;
898  }
899 
900  if (ast_dns_result_get_records(result)) {
901  ast_test_status_update(test, "DNS resolution returned records unexpectedly\n");
902  res = -1;
903  }
904 
905  ast_dns_result_free(result);
906  return res;
907 }
int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
Synchronously resolve a DNS query.
Definition: dns_core.c:314
void ast_dns_result_free(struct ast_dns_result *result)
Free the DNS result information.
Definition: dns_core.c:130
Domain data structure.
Definition: sip.h:888
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
The result of a DNS query.
Definition: dns_internal.h:117
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
static PGresult * result
Definition: cel_pgsql.c:88
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

◆ off_nominal_test()

static enum ast_test_result_state off_nominal_test ( struct ast_test test,
off_nominal_resolve_fn  runner 
)
static

Definition at line 1015 of file res_resolver_unbound.c.

References ao2_bump, ao2_cleanup, ao2_global_obj_ref, ARRAY_LEN, dns_record::as_string, AST_TEST_FAIL, AST_TEST_PASS, globals, NULL, and RAII_VAR.

Referenced by AST_TEST_DEFINE().

1017 {
1018  RAII_VAR(struct unbound_resolver *, resolver, NULL, ao2_cleanup);
1019  RAII_VAR(struct unbound_config *, cfg, NULL, ao2_cleanup);
1020 
1021  static const size_t V4_SIZE = sizeof(struct in_addr);
1022 
1023  static const char *DOMAIN1 = "goose.feathers";
1024  static const char *DOMAIN2 = "duck.feathers";
1025 
1026  static const char *ADDR1 = "127.0.0.2";
1027 
1028  char addr1_buf[V4_SIZE];
1029 
1030  struct dns_record records [] = {
1031  { "goose.feathers 12345 IN A 127.0.0.2", DOMAIN1, ns_t_a, ns_c_in, 12345, addr1_buf, V4_SIZE, 0, },
1032  };
1033 
1034  int i;
1036 
1037  struct {
1038  const char *domain;
1039  int rr_type;
1040  int rr_class;
1041  int rcode;
1042  } runs [] = {
1043  { DOMAIN2, ns_t_a, ns_c_in, ns_r_nxdomain },
1044  { DOMAIN1, ns_t_aaaa, ns_c_in, ns_r_noerror },
1045  { DOMAIN1, ns_t_a, ns_c_chaos, ns_r_refused },
1046  };
1047 
1048  inet_pton(AF_INET, ADDR1, addr1_buf);
1049 
1050  cfg = ao2_global_obj_ref(globals);
1051  resolver = ao2_bump(cfg->global->state->resolver);
1052 
1053  ub_ctx_zone_add(resolver->context, DOMAIN1, "static");
1054  ub_ctx_zone_add(resolver->context, DOMAIN2, "static");
1055 
1056  for (i = 0; i < ARRAY_LEN(records); ++i) {
1057  ub_ctx_data_add(resolver->context, records[i].as_string);
1058  }
1059 
1060  for (i = 0; i < ARRAY_LEN(runs); ++i) {
1061  if (runner(test, runs[i].domain, runs[i].rr_type, runs[i].rr_class, runs[i].rcode)) {
1062  res = AST_TEST_FAIL;
1063  }
1064  }
1065 
1066  return res;
1067 }
static int records
Definition: cdr_mysql.c:84
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
A container for config related information.
A DNS record to be used during a test.
const char * as_string
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define NULL
Definition: resample.c:96
const char * domain
Domain data structure.
Definition: sip.h:888
#define ao2_bump(obj)
Definition: astobj2.h:491
#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
static struct console_pvt globals
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Structure for an unbound resolver.
ast_test_result_state
Definition: test.h:200

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 1385 of file res_resolver_unbound.c.

References aco_process_config(), ACO_PROCESS_ERROR, and AST_MODULE_RELOAD_ERROR.

Referenced by load_module().

1386 {
1387  if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
1388  return AST_MODULE_RELOAD_ERROR;
1389  }
1390 
1391  return 0;
1392 }
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.
Their was an error and no changes were applied.

◆ unbound_config_alloc()

static void * unbound_config_alloc ( void  )
static

Allocate a unbound_config to hold a snapshot of the complete results of parsing a config.

Definition at line 365 of file res_resolver_unbound.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, ast_string_field_init, error(), unbound_config::global, NULL, unbound_config_destructor(), and unbound_global_config_destructor().

Referenced by unbound_config_apply_default().

366 {
367  struct unbound_config *cfg;
368 
370  if (!cfg) {
371  return NULL;
372  }
373 
374  /* Allocate/initialize memory */
377  if (!cfg->global) {
378  goto error;
379  }
380 
381  if (ast_string_field_init(cfg->global, 128)) {
382  goto error;
383  }
384 
385  return cfg;
386 error:
387  ao2_ref(cfg, -1);
388  return NULL;
389 }
A container for config related information.
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
struct unbound_global_config * global
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void unbound_global_config_destructor(void *obj)
static void unbound_config_destructor(void *obj)
int error(const char *format,...)
Definition: utils/frame.c:999

◆ unbound_config_apply_default()

static int unbound_config_apply_default ( void  )
static

Definition at line 472 of file res_resolver_unbound.c.

References aco_set_defaults(), ao2_global_obj_replace_unref, ao2_ref, ast_log, ast_verb, unbound_config::global, globals, LOG_ERROR, unbound_config_alloc(), and unbound_config_preapply().

Referenced by load_module().

473 {
474  struct unbound_config *cfg;
475 
476  cfg = unbound_config_alloc();
477  if (!cfg) {
478  ast_log(LOG_ERROR, "Could not create default configuration for unbound resolver\n");
479  return -1;
480  }
481 
482  aco_set_defaults(&global_option, "general", cfg->global);
483 
484  if (unbound_config_preapply(cfg)) {
485  ao2_ref(cfg, -1);
486  return -1;
487  }
488 
489  ast_verb(1, "Starting unbound resolver using default configuration\n");
490 
492  ao2_ref(cfg, -1);
493 
494  return 0;
495 }
static void * unbound_config_alloc(void)
Allocate a unbound_config to hold a snapshot of the complete results of parsing a config...
A container for config related information.
struct unbound_global_config * global
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct console_pvt globals
#define LOG_ERROR
Definition: logger.h:285
static int unbound_config_preapply(struct unbound_config *cfg)
int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
Set all default options of obj.
#define ao2_global_obj_replace_unref(holder, obj)
Definition: astobj2.h:908
static struct aco_type global_option
An aco_type structure to link the "general" category to the unbound_global_config type...

◆ unbound_config_destructor()

static void unbound_config_destructor ( void *  obj)
static

Definition at line 339 of file res_resolver_unbound.c.

References ao2_cleanup, and unbound_config::global.

Referenced by unbound_config_alloc().

340 {
341  struct unbound_config *cfg = obj;
342 
343  ao2_cleanup(cfg->global);
344 }
A container for config related information.
struct unbound_global_config * global
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ unbound_config_preapply()

static int unbound_config_preapply ( struct unbound_config cfg)
static

Definition at line 391 of file res_resolver_unbound.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_log, ast_strlen_zero, unbound_resolver::context, unbound_global_config::debug, unbound_config::global, unbound_global_config::hosts, LOG_ERROR, unbound_global_config::nameservers, NULL, unbound_global_config::resolv, unbound_config_state::resolver, unbound_global_config::state, unbound_global_config::ta_file, unbound_config_state_destructor(), unbound_resolver_alloc(), and unbound_resolver_start().

Referenced by unbound_config_apply_default(), and unbound_config_preapply_callback().

392 {
393  int res = 0;
394 
397  if (!cfg->global->state) {
398  ast_log(LOG_ERROR, "Could not allocate unbound resolver state structure\n");
399  return -1;
400  }
401 
403  if (!cfg->global->state->resolver) {
404  ast_log(LOG_ERROR, "Could not create an unbound resolver\n");
405  return -1;
406  }
407 
408  ub_ctx_debuglevel(cfg->global->state->resolver->context, cfg->global->debug);
409 
410  if (!strcmp(cfg->global->hosts, "system")) {
411  res = ub_ctx_hosts(cfg->global->state->resolver->context, NULL);
412  } else if (!ast_strlen_zero(cfg->global->hosts)) {
413  res = ub_ctx_hosts(cfg->global->state->resolver->context, cfg->global->hosts);
414  }
415 
416  if (res) {
417  ast_log(LOG_ERROR, "Failed to set hosts file to '%s' in unbound resolver: %s\n",
418  cfg->global->hosts, ub_strerror(res));
419  return -1;
420  }
421 
422  if (cfg->global->nameservers) {
423  struct ao2_iterator it_nameservers;
424  char *nameserver;
425 
426  it_nameservers = ao2_iterator_init(cfg->global->nameservers, 0);
427  while (!res && (nameserver = ao2_iterator_next(&it_nameservers))) {
428  res = ub_ctx_set_fwd(cfg->global->state->resolver->context, nameserver);
429 
430  if (res) {
431  ast_log(LOG_ERROR, "Failed to add nameserver '%s' to unbound resolver: %s\n",
432  nameserver, ub_strerror(res));
433  }
434  ao2_ref(nameserver, -1);
435  }
436  ao2_iterator_destroy(&it_nameservers);
437  if (res) {
438  return -1;
439  }
440  }
441 
442  if (!strcmp(cfg->global->resolv, "system")) {
443  res = ub_ctx_resolvconf(cfg->global->state->resolver->context, NULL);
444  } else if (!ast_strlen_zero(cfg->global->resolv)) {
445  res = ub_ctx_resolvconf(cfg->global->state->resolver->context, cfg->global->resolv);
446  }
447 
448  if (res) {
449  ast_log(LOG_ERROR, "Failed to set resolv.conf file to '%s' in unbound resolver: %s\n",
450  cfg->global->resolv, ub_strerror(res));
451  return -1;
452  }
453 
454  if (!ast_strlen_zero(cfg->global->ta_file)) {
455  res = ub_ctx_add_ta_file(cfg->global->state->resolver->context, cfg->global->ta_file);
456 
457  if (res) {
458  ast_log(LOG_ERROR, "Failed to set trusted anchor file to '%s' in unbound resolver: %s\n",
459  cfg->global->ta_file, ub_strerror(res));
460  return -1;
461  }
462  }
463 
465  ast_log(LOG_ERROR, "Could not start unbound resolver thread\n");
466  return -1;
467  }
468 
469  return 0;
470 }
const ast_string_field hosts
const ast_string_field resolv
const ast_string_field ta_file
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct unbound_resolver * resolver
The configured resolver.
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
struct unbound_config_state * state
State information.
struct unbound_global_config * global
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void unbound_config_state_destructor(void *obj)
#define LOG_ERROR
Definition: logger.h:285
static struct unbound_resolver * unbound_resolver_alloc(void)
Allocator for unbound resolver.
static int unbound_resolver_start(struct unbound_resolver *resolver)
Start function for the unbound resolver.
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
struct ub_ctx * context
Resolver context itself.
struct ao2_container * nameservers
List of nameservers (in order) to use for queries.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
unsigned int debug
Debug level for the resolver.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ unbound_config_preapply_callback()

static int unbound_config_preapply_callback ( void  )
static

Finish initializing new configuration.

Definition at line 497 of file res_resolver_unbound.c.

References aco_pending_config(), and unbound_config_preapply().

498 {
499  return unbound_config_preapply(aco_pending_config(&cfg_info));
500 }
void * aco_pending_config(struct aco_info *info)
Get pending config changes.
static int unbound_config_preapply(struct unbound_config *cfg)

◆ unbound_config_state_destructor()

static void unbound_config_state_destructor ( void *  obj)
static

Definition at line 355 of file res_resolver_unbound.c.

References ao2_ref, unbound_config_state::resolver, and unbound_resolver_stop().

Referenced by unbound_config_preapply().

356 {
357  struct unbound_config_state *state = obj;
358 
359  if (state->resolver) {
361  ao2_ref(state->resolver, -1);
362  }
363 }
Unbound configuration state information.
struct unbound_resolver * resolver
The configured resolver.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void unbound_resolver_stop(struct unbound_resolver *resolver)
Stop function for the unbound resolver.

◆ unbound_global_config_destructor()

static void unbound_global_config_destructor ( void *  obj)
static

Definition at line 346 of file res_resolver_unbound.c.

References ao2_cleanup, ast_string_field_free_memory, global, unbound_global_config::nameservers, and unbound_global_config::state.

Referenced by unbound_config_alloc().

347 {
348  struct unbound_global_config *global = obj;
349 
351  ao2_cleanup(global->nameservers);
352  ao2_cleanup(global->state);
353 }
static struct aco_type global
Definition: test_config.c:1445
struct unbound_config_state * state
State information.
A structure to hold global configuration-related options.
struct ao2_container * nameservers
List of nameservers (in order) to use for queries.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ unbound_resolver_alloc()

static struct unbound_resolver* unbound_resolver_alloc ( void  )
static

Allocator for unbound resolver.

Definition at line 171 of file res_resolver_unbound.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, AST_PTHREADT_NULL, unbound_resolver::context, NULL, unbound_resolver::thread, and unbound_resolver_destroy().

Referenced by unbound_config_preapply().

172 {
173  struct unbound_resolver *resolver;
174 
176  if (!resolver) {
177  return NULL;
178  }
179 
180  resolver->thread = AST_PTHREADT_NULL;
181 
182  resolver->context = ub_ctx_create();
183  if (!resolver->context) {
184  ao2_ref(resolver, -1);
185  return NULL;
186  }
187 
188  /* Each async result should be invoked in a separate thread so others are not blocked */
189  ub_ctx_async(resolver->context, 1);
190 
191  return resolver;
192 }
static void unbound_resolver_destroy(void *obj)
Destructor for unbound resolver.
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
pthread_t thread
Thread handling the resolver.
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ub_ctx * context
Resolver context itself.
Structure for an unbound resolver.

◆ unbound_resolver_callback()

static void unbound_resolver_callback ( void *  data,
int  err,
struct ub_result *  ub_result 
)
static

Callback invoked when resolution completes on a query.

Definition at line 256 of file res_resolver_unbound.c.

References ao2_ref, ast_dns_query_get_name(), ast_dns_resolver_add_record(), ast_dns_resolver_completed(), ast_dns_resolver_set_result(), and S_OR.

Referenced by unbound_resolver_resolve().

257 {
258  struct ast_dns_query *query = data;
259 
260  if (!ast_dns_resolver_set_result(query, ub_result->secure, ub_result->bogus, ub_result->rcode,
261  S_OR(ub_result->canonname, ast_dns_query_get_name(query)), ub_result->answer_packet, ub_result->answer_len)) {
262  int i;
263  char *result_data;
264 
265  for (i = 0; (result_data = ub_result->data[i]); i++) {
266  if (ast_dns_resolver_add_record(query, ub_result->qtype, ub_result->qclass, ub_result->ttl,
267  result_data, ub_result->len[i])) {
268  break;
269  }
270  }
271  }
272 
274  ao2_ref(query, -1);
275  ub_resolve_free(ub_result);
276 }
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.
Definition: dns_core.c:535
const char * ast_dns_query_get_name(const struct ast_dns_query *query)
Get the name queried in a DNS query.
Definition: dns_core.c:57
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_dns_resolver_completed(struct ast_dns_query *query)
Mark a DNS query as having been completed.
Definition: dns_core.c:599
A DNS query.
Definition: dns_internal.h:137
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
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.
Definition: dns_core.c:456

◆ unbound_resolver_cancel()

static int unbound_resolver_cancel ( struct ast_dns_query query)
static

Definition at line 316 of file res_resolver_unbound.c.

References ao2_ref, ast_dns_resolver_get_data(), unbound_resolver::context, unbound_resolver_data::id, and unbound_resolver_data::resolver.

317 {
318  struct unbound_resolver_data *data = ast_dns_resolver_get_data(query);
319  int res;
320 
321  res = ub_cancel(data->resolver->context, data->id);
322  if (!res) {
323  /* When this query was started we bumped the ref, now that it has been cancelled we have ownership and
324  * need to drop it
325  */
326  ao2_ref(query, -1);
327  }
328 
329  return res;
330 }
void * ast_dns_resolver_get_data(const struct ast_dns_query *query)
Retrieve resolver specific data.
Definition: dns_core.c:451
Structure for query resolver data.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ub_ctx * context
Resolver context itself.
int id
ID for the specific query.
struct unbound_resolver * resolver
The resolver in use for the query.

◆ unbound_resolver_data_dtor()

static void unbound_resolver_data_dtor ( void *  vdoomed)
static

Definition at line 278 of file res_resolver_unbound.c.

References ao2_cleanup, and unbound_resolver_data::resolver.

Referenced by unbound_resolver_resolve().

279 {
280  struct unbound_resolver_data *doomed = vdoomed;
281 
282  ao2_cleanup(doomed->resolver);
283 }
Structure for query resolver data.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct unbound_resolver * resolver
The resolver in use for the query.

◆ unbound_resolver_destroy()

static void unbound_resolver_destroy ( void *  obj)
static

Destructor for unbound resolver.

Definition at line 161 of file res_resolver_unbound.c.

References unbound_resolver::context.

Referenced by unbound_resolver_alloc().

162 {
163  struct unbound_resolver *resolver = obj;
164 
165  if (resolver->context) {
166  ub_ctx_delete(resolver->context);
167  }
168 }
struct ub_ctx * context
Resolver context itself.
Structure for an unbound resolver.

◆ unbound_resolver_resolve()

static int unbound_resolver_resolve ( struct ast_dns_query query)
static

Definition at line 285 of file res_resolver_unbound.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_bump, ao2_global_obj_ref, ao2_ref, ast_dns_query_get_name(), ast_dns_query_get_rr_class(), ast_dns_query_get_rr_type(), ast_dns_resolver_set_data(), ast_log, unbound_resolver::context, unbound_config::global, globals, unbound_resolver_data::id, LOG_ERROR, unbound_resolver_data::resolver, unbound_config_state::resolver, unbound_global_config::state, unbound_resolver_callback(), and unbound_resolver_data_dtor().

286 {
288  struct unbound_resolver_data *data;
289  int res;
290 
291  data = ao2_alloc_options(sizeof(*data), unbound_resolver_data_dtor,
293  if (!data) {
294  ast_log(LOG_ERROR, "Failed to allocate resolver data for resolution of '%s'\n",
295  ast_dns_query_get_name(query));
296  return -1;
297  }
298  data->resolver = ao2_bump(cfg->global->state->resolver);
299  ast_dns_resolver_set_data(query, data);
300 
301  res = ub_resolve_async(data->resolver->context, ast_dns_query_get_name(query),
303  ao2_bump(query), unbound_resolver_callback, &data->id);
304 
305  if (res) {
306  ast_log(LOG_ERROR, "Failed to perform async DNS resolution of '%s'\n",
307  ast_dns_query_get_name(query));
308  ao2_ref(query, -1);
309  }
310 
311  ao2_ref(data, -1);
312  ao2_ref(cfg, -1);
313  return res;
314 }
const char * ast_dns_query_get_name(const struct ast_dns_query *query)
Get the name queried in a DNS query.
Definition: dns_core.c:57
static void unbound_resolver_data_dtor(void *vdoomed)
int ast_dns_query_get_rr_class(const struct ast_dns_query *query)
Get the record resource class of a DNS query.
Definition: dns_core.c:67
A container for config related information.
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
struct unbound_resolver * resolver
The configured resolver.
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
struct unbound_config_state * state
State information.
struct unbound_global_config * global
Structure for query resolver data.
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void unbound_resolver_callback(void *data, int err, struct ub_result *ub_result)
Callback invoked when resolution completes on a query.
static struct console_pvt globals
#define LOG_ERROR
Definition: logger.h:285
int ast_dns_resolver_set_data(struct ast_dns_query *query, void *data)
Set resolver specific data on a query.
Definition: dns_core.c:440
struct ub_ctx * context
Resolver context itself.
int id
ID for the specific query.
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
struct unbound_resolver * resolver
The resolver in use for the query.

◆ unbound_resolver_start()

static int unbound_resolver_start ( struct unbound_resolver resolver)
static

Start function for the unbound resolver.

Definition at line 217 of file res_resolver_unbound.c.

References ao2_bump, ao2_ref, ast_debug, ast_pthread_create, AST_PTHREADT_NULL, NULL, unbound_resolver::thread, and unbound_resolver_thread().

Referenced by unbound_config_preapply().

218 {
219  int res;
220 
221  if (resolver->thread != AST_PTHREADT_NULL) {
222  return 0;
223  }
224 
225  ast_debug(1, "Starting thread for unbound resolver\n");
226 
227  res = ast_pthread_create(&resolver->thread, NULL, unbound_resolver_thread, ao2_bump(resolver));
228  if (res) {
229  ast_debug(1, "Could not start thread for unbound resolver\n");
230  ao2_ref(resolver, -1);
231  }
232 
233  return res;
234 }
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
pthread_t thread
Thread handling the resolver.
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void * unbound_resolver_thread(void *data)
Resolver thread which waits and handles results.
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:559

◆ unbound_resolver_stop()

static void unbound_resolver_stop ( struct unbound_resolver resolver)
static

Stop function for the unbound resolver.

Definition at line 237 of file res_resolver_unbound.c.

References ast_debug, AST_PTHREADT_NULL, AST_PTHREADT_STOP, NULL, and unbound_resolver::thread.

Referenced by unbound_config_state_destructor().

238 {
239  pthread_t thread;
240 
241  if (resolver->thread == AST_PTHREADT_NULL) {
242  return;
243  }
244 
245  ast_debug(1, "Stopping processing thread for unbound resolver\n");
246 
247  thread = resolver->thread;
248  resolver->thread = AST_PTHREADT_STOP;
249  pthread_kill(thread, SIGURG);
250  pthread_join(thread, NULL);
251 
252  ast_debug(1, "Stopped processing thread for unbound resolver\n");
253 }
pthread_t thread
Definition: app_meetme.c:1089
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
pthread_t thread
Thread handling the resolver.
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define AST_PTHREADT_STOP
Definition: lock.h:67

◆ unbound_resolver_thread()

static void* unbound_resolver_thread ( void *  data)
static

Resolver thread which waits and handles results.

Definition at line 195 of file res_resolver_unbound.c.

References ao2_ref, ast_debug, AST_PTHREADT_STOP, ast_wait_for_input(), unbound_resolver::context, NULL, and unbound_resolver::thread.

Referenced by unbound_resolver_start().

196 {
197  struct unbound_resolver *resolver = data;
198 
199  ast_debug(1, "Starting processing for unbound resolver\n");
200 
201  while (resolver->thread != AST_PTHREADT_STOP) {
202  /* Wait for any results to come in */
203  ast_wait_for_input(ub_fd(resolver->context), -1);
204 
205  /* Finally process any results */
206  ub_process(resolver->context);
207  }
208 
209  ast_debug(1, "Terminating processing for unbound resolver\n");
210 
211  ao2_ref(resolver, -1);
212 
213  return NULL;
214 }
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
pthread_t thread
Thread handling the resolver.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ub_ctx * context
Resolver context itself.
#define AST_PTHREADT_STOP
Definition: lock.h:67
Structure for an unbound resolver.
int ast_wait_for_input(int fd, int ms)
Definition: main/utils.c:1519

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1394 of file res_resolver_unbound.c.

References aco_info_destroy(), ao2_global_obj_release, AST_TEST_UNREGISTER, and globals.

Referenced by load_module().

1395 {
1396  aco_info_destroy(&cfg_info);
1398 
1399  AST_TEST_UNREGISTER(resolve_sync);
1400  AST_TEST_UNREGISTER(resolve_async);
1401  AST_TEST_UNREGISTER(resolve_sync_off_nominal);
1402  AST_TEST_UNREGISTER(resolve_sync_off_nominal);
1403  AST_TEST_UNREGISTER(resolve_cancel_off_nominal);
1404  AST_TEST_UNREGISTER(resolve_naptr);
1405  AST_TEST_UNREGISTER(resolve_srv);
1406  return 0;
1407 }
static struct console_pvt globals
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
#define ao2_global_obj_release(holder)
Definition: astobj2.h:865

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Unbound DNS Resolver Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND - 4, }
static

Definition at line 1474 of file res_resolver_unbound.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1474 of file res_resolver_unbound.c.

◆ global_option

struct aco_type global_option
static

An aco_type structure to link the "general" category to the unbound_global_config type.

Definition at line 130 of file res_resolver_unbound.c.

◆ global_options

struct aco_type* global_options[] = ACO_TYPES(&global_option)
static

Definition at line 138 of file res_resolver_unbound.c.

◆ resolver_unbound_conf

struct aco_file resolver_unbound_conf
static
Initial value:
= {
.filename = "resolver_unbound.conf",
}
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
static struct aco_type global_option
An aco_type structure to link the "general" category to the unbound_global_config type...

Definition at line 140 of file res_resolver_unbound.c.

◆ unbound_resolver

Definition at line 332 of file res_resolver_unbound.c.