28 #include <arpa/nameser.h>
127 static void *unbound_config_alloc(
void);
135 .category =
"general",
140 static struct aco_file resolver_unbound_conf = {
141 .
filename =
"resolver_unbound.conf",
152 static int unbound_config_preapply_callback(
void);
156 .files = ACO_FILES(&resolver_unbound_conf),
157 .pre_apply_config = unbound_config_preapply_callback,
161 static void unbound_resolver_destroy(
void *obj)
166 ub_ctx_delete(resolver->
context);
180 resolver->
thread = AST_PTHREADT_NULL;
182 resolver->
context = ub_ctx_create();
189 ub_ctx_async(resolver->
context, 1);
195 static void *unbound_resolver_thread(
void *data)
199 ast_debug(1,
"Starting processing for unbound resolver\n");
201 while (resolver->
thread != AST_PTHREADT_STOP) {
203 ast_wait_for_input(ub_fd(resolver->
context), -1);
209 ast_debug(1,
"Terminating processing for unbound resolver\n");
221 if (resolver->
thread != AST_PTHREADT_NULL) {
225 ast_debug(1,
"Starting thread for unbound resolver\n");
227 res = ast_pthread_create(&resolver->
thread, NULL, unbound_resolver_thread,
ao2_bump(resolver));
229 ast_debug(1,
"Could not start thread for unbound resolver\n");
241 if (resolver->
thread == AST_PTHREADT_NULL) {
245 ast_debug(1,
"Stopping processing thread for unbound resolver\n");
247 thread = resolver->
thread;
248 resolver->
thread = AST_PTHREADT_STOP;
249 pthread_kill(thread, SIGURG);
250 pthread_join(thread, NULL);
252 ast_debug(1,
"Stopped processing thread for unbound resolver\n");
256 static void unbound_resolver_callback(
void *data,
int err,
struct ub_result *ub_result)
265 for (i = 0; (result_data = ub_result->data[i]); i++) {
267 result_data, ub_result->len[i])) {
275 ub_resolve_free(ub_result);
278 static void unbound_resolver_data_dtor(
void *vdoomed)
285 static int unbound_resolver_resolve(
struct ast_dns_query *query)
291 data = ao2_alloc_options(
sizeof(*data), unbound_resolver_data_dtor,
294 ast_log(LOG_ERROR,
"Failed to allocate resolver data for resolution of '%s'\n",
303 ao2_bump(query), unbound_resolver_callback, &data->
id);
306 ast_log(LOG_ERROR,
"Failed to perform async DNS resolution of '%s'\n",
316 static int unbound_resolver_cancel(
struct ast_dns_query *query)
335 .resolve = unbound_resolver_resolve,
336 .cancel = unbound_resolver_cancel,
339 static void unbound_config_destructor(
void *obj)
343 ao2_cleanup(cfg->global);
346 static void unbound_global_config_destructor(
void *obj)
352 ao2_cleanup(global->
state);
355 static void unbound_config_state_destructor(
void *obj)
360 unbound_resolver_stop(state->
resolver);
365 static void *unbound_config_alloc(
void)
375 cfg->global = ao2_alloc_options(
sizeof(*cfg->global), unbound_global_config_destructor,
395 cfg->global->
state = ao2_alloc_options(
sizeof(*cfg->global->
state), unbound_config_state_destructor,
397 if (!cfg->global->
state) {
398 ast_log(LOG_ERROR,
"Could not allocate unbound resolver state structure\n");
404 ast_log(LOG_ERROR,
"Could not create an unbound resolver\n");
410 if (!strcmp(cfg->global->
hosts,
"system")) {
412 }
else if (!ast_strlen_zero(cfg->global->
hosts)) {
417 ast_log(LOG_ERROR,
"Failed to set hosts file to '%s' in unbound resolver: %s\n",
418 cfg->global->
hosts, ub_strerror(res));
427 while (!res && (nameserver = ao2_iterator_next(&it_nameservers))) {
431 ast_log(LOG_ERROR,
"Failed to add nameserver '%s' to unbound resolver: %s\n",
432 nameserver, ub_strerror(res));
442 if (!strcmp(cfg->global->
resolv,
"system")) {
444 }
else if (!ast_strlen_zero(cfg->global->
resolv)) {
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));
454 if (!ast_strlen_zero(cfg->global->
ta_file)) {
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));
465 ast_log(LOG_ERROR,
"Could not start unbound resolver thread\n");
472 static int unbound_config_apply_default(
void)
476 cfg = unbound_config_alloc();
478 ast_log(LOG_ERROR,
"Could not create default configuration for unbound resolver\n");
484 if (unbound_config_preapply(cfg)) {
489 ast_verb(1,
"Starting unbound resolver using default configuration\n");
497 static int unbound_config_preapply_callback(
void)
502 #ifdef TEST_FRAMEWORK
511 const char *as_string;
523 const size_t bufsize;
545 typedef int (*resolve_fn)(
struct ast_test *
test,
const char *domain,
int rr_type,
546 int rr_class,
struct dns_record *records,
size_t num_records);
551 static int nominal_sync_run(
struct ast_test *test,
const char *domain,
int rr_type,
552 int rr_class,
struct dns_record *records,
size_t num_records)
559 for (i = 0; i < num_records; ++i) {
560 records[i].visited = 0;
563 ast_test_status_update(test,
"Performing DNS query '%s', type %d\n", domain, rr_type);
566 ast_test_status_update(test,
"Failed to perform synchronous resolution of domain %s\n", domain);
571 ast_test_status_update(test,
"Successful synchronous resolution of domain %s gave NULL result\n", domain);
579 for (i = 0; i < num_records; ++i) {
585 records[i].visited = 1;
591 ast_test_status_update(test,
"Unknown DNS record returned from domain %s\n", domain);
604 struct dns_record *records;
615 static void async_data_destructor(
void *obj)
617 struct async_data *adata = obj;
619 ast_mutex_destroy(&adata->lock);
620 ast_cond_destroy(&adata->cond);
623 static struct async_data *async_data_alloc(
struct dns_record *records,
size_t num_records)
625 struct async_data *adata;
627 adata = ao2_alloc(
sizeof(*adata), async_data_destructor);
632 ast_mutex_init(&adata->lock);
633 ast_cond_init(&adata->cond, NULL);
634 adata->records = records;
635 adata->num_records = num_records;
649 static void async_callback(
const struct ast_dns_query *query)
665 for (i = 0; i < adata->num_records; ++i) {
671 adata->records[i].visited = 1;
683 ast_mutex_lock(&adata->lock);
685 ast_cond_signal(&adata->cond);
686 ast_mutex_unlock(&adata->lock);
695 static int nominal_async_run(
struct ast_test *test,
const char *domain,
int rr_type,
696 int rr_class,
struct dns_record *records,
size_t num_records)
699 RAII_VAR(
struct async_data *, adata, NULL, ao2_cleanup);
702 adata = async_data_alloc(records, num_records);
704 ast_test_status_update(test,
"Unable to allocate data for async query\n");
709 for (i = 0; i < num_records; ++i) {
710 records[i].visited = 0;
713 ast_test_status_update(test,
"Performing DNS query '%s', type %d\n", domain, rr_type);
717 ast_test_status_update(test,
"Failed to perform asynchronous resolution of domain %s\n", domain);
721 ast_mutex_lock(&adata->lock);
722 while (!adata->complete) {
723 ast_cond_wait(&adata->cond, &adata->lock);
725 ast_mutex_unlock(&adata->lock);
728 ast_test_status_update(test,
"Unknown DNS record returned from domain %s\n", domain);
730 return adata->failed;
743 static enum ast_test_result_state nominal_test(
struct ast_test *test, resolve_fn runner)
745 RAII_VAR(
struct unbound_resolver *, resolver, NULL, ao2_cleanup);
748 static const size_t V4_SIZE =
sizeof(
struct in_addr);
749 static const size_t V6_SIZE =
sizeof(
struct in6_addr);
751 static const char *DOMAIN1 =
"goose.feathers";
752 static const char *DOMAIN2 =
"duck.feathers";
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";
759 char addr1_buf[V4_SIZE];
760 char addr2_buf[V4_SIZE];
761 char addr3_buf[V6_SIZE];
762 char addr4_buf[V4_SIZE];
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 },
775 int visited[ARRAY_LEN(records)];
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 } },
783 enum ast_test_result_state res = AST_TEST_PASS;
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);
793 ub_ctx_zone_add(resolver->
context, DOMAIN1,
"static");
794 ub_ctx_zone_add(resolver->
context, DOMAIN2,
"static");
796 for (i = 0; i < ARRAY_LEN(records); ++i) {
797 ub_ctx_data_add(resolver->
context, records[i].as_string);
800 for (i = 0; i < ARRAY_LEN(runs); ++i) {
803 if (runner(test, runs[i].domain, runs[i].rr_type, runs[i].rr_class, records, ARRAY_LEN(records))) {
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");
818 for (i = 0; i < ARRAY_LEN(records); ++i) {
819 ub_ctx_data_remove(resolver->
context, records[i].as_string);
821 ub_ctx_zone_remove(resolver->
context, DOMAIN1);
822 ub_ctx_zone_remove(resolver->
context, DOMAIN2);
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;
849 return nominal_test(test, nominal_sync_run);
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;
873 return nominal_test(test, nominal_async_run);
876 typedef int (*off_nominal_resolve_fn)(
struct ast_test *test,
const char *domain,
int rr_type,
877 int rr_class,
int expected_rcode);
879 static int off_nominal_sync_run(
struct ast_test *test,
const char *domain,
int rr_type,
880 int rr_class,
int expected_rcode)
886 ast_test_status_update(test,
"Failed to perform resolution :(\n");
891 ast_test_status_update(test,
"Resolution returned no result\n");
896 ast_test_status_update(test,
"Unexpected rcode from DNS resolution\n");
901 ast_test_status_update(test,
"DNS resolution returned records unexpectedly\n");
912 struct off_nominal_async_data {
923 static void off_nominal_async_data_destructor(
void *obj)
925 struct off_nominal_async_data *adata = obj;
927 ast_mutex_destroy(&adata->lock);
928 ast_cond_destroy(&adata->cond);
931 static struct off_nominal_async_data *off_nominal_async_data_alloc(
int expected_rcode)
933 struct off_nominal_async_data *adata;
935 adata = ao2_alloc(
sizeof(*adata), off_nominal_async_data_destructor);
940 ast_mutex_init(&adata->lock);
941 ast_cond_init(&adata->cond, NULL);
943 adata->expected_rcode = expected_rcode;
958 static void off_nominal_async_callback(
const struct ast_dns_query *query)
977 ast_mutex_lock(&adata->lock);
979 ast_cond_signal(&adata->cond);
980 ast_mutex_unlock(&adata->lock);
983 static int off_nominal_async_run(
struct ast_test *test,
const char *domain,
int rr_type,
984 int rr_class,
int expected_rcode)
987 RAII_VAR(
struct off_nominal_async_data *, adata, NULL, ao2_cleanup);
989 adata = off_nominal_async_data_alloc(expected_rcode);
991 ast_test_status_update(test,
"Unable to allocate data for async query\n");
995 ast_test_status_update(test,
"Performing DNS query '%s', type %d\n", domain, rr_type);
999 ast_test_status_update(test,
"Failed to perform asynchronous resolution of domain %s\n", domain);
1003 ast_mutex_lock(&adata->lock);
1004 while (!adata->complete) {
1005 ast_cond_wait(&adata->cond, &adata->lock);
1007 ast_mutex_unlock(&adata->lock);
1009 if (adata->failed) {
1010 ast_test_status_update(test,
"Asynchronous resolution failure %s\n", domain);
1012 return adata->failed;
1015 static enum ast_test_result_state off_nominal_test(
struct ast_test *test,
1016 off_nominal_resolve_fn runner)
1018 RAII_VAR(
struct unbound_resolver *, resolver, NULL, ao2_cleanup);
1021 static const size_t V4_SIZE =
sizeof(
struct in_addr);
1023 static const char *DOMAIN1 =
"goose.feathers";
1024 static const char *DOMAIN2 =
"duck.feathers";
1026 static const char *ADDR1 =
"127.0.0.2";
1028 char addr1_buf[V4_SIZE];
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, },
1035 enum ast_test_result_state res = AST_TEST_PASS;
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 },
1048 inet_pton(AF_INET, ADDR1, addr1_buf);
1053 ub_ctx_zone_add(resolver->
context, DOMAIN1,
"static");
1054 ub_ctx_zone_add(resolver->
context, DOMAIN2,
"static");
1056 for (i = 0; i < ARRAY_LEN(records); ++i) {
1057 ub_ctx_data_add(resolver->
context, records[i].as_string);
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;
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;
1085 return off_nominal_test(test, off_nominal_sync_run);
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;
1104 return off_nominal_test(test, off_nominal_async_run);
1110 struct async_minimal_data {
1116 static void async_minimal_data_destructor(
void *obj)
1118 struct async_minimal_data *adata = obj;
1120 ast_mutex_destroy(&adata->lock);
1121 ast_cond_destroy(&adata->cond);
1124 static struct async_minimal_data *async_minimal_data_alloc(
void)
1126 struct async_minimal_data *adata;
1128 adata = ao2_alloc(
sizeof(*adata), async_minimal_data_destructor);
1133 ast_mutex_init(&adata->lock);
1134 ast_cond_init(&adata->cond, NULL);
1144 static void minimal_callback(
const struct ast_dns_query *query)
1148 ast_mutex_lock(&adata->lock);
1149 adata->complete = 1;
1150 ast_cond_signal(&adata->cond);
1151 ast_mutex_unlock(&adata->lock);
1157 RAII_VAR(
struct async_minimal_data *, adata, NULL, ao2_cleanup);
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;
1172 adata = async_minimal_data_alloc();
1174 ast_test_status_update(test,
"Failed to allocate necessary data for test\n");
1175 return AST_TEST_FAIL;
1180 ast_test_status_update(test,
"Failed to perform asynchronous query\n");
1181 return AST_TEST_FAIL;
1185 ast_mutex_lock(&adata->lock);
1186 while (!adata->complete) {
1187 ast_cond_wait(&adata->cond, &adata->lock);
1189 ast_mutex_unlock(&adata->lock);
1192 ast_test_status_update(test,
"Successfully canceled completed query\n");
1193 return AST_TEST_FAIL;
1196 return AST_TEST_PASS;
1201 RAII_VAR(
struct unbound_resolver *, resolver, NULL, ao2_cleanup);
1207 static char * DOMAIN1 =
"goose.feathers";
1209 enum ast_test_result_state res = AST_TEST_PASS;
1212 const char *zone_entry;
1214 uint16_t preference;
1216 const char *services;
1218 const char *replacement;
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},
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;
1242 ub_ctx_zone_add(resolver->
context, DOMAIN1,
"static");
1244 for (i = 0; i < ARRAY_LEN(records); ++i) {
1245 ub_ctx_data_add(resolver->
context, records[i].zone_entry);
1249 ast_test_status_update(test,
"Failed to resolve domain\n");
1250 return AST_TEST_FAIL;
1254 ast_test_status_update(test,
"Successful resolution set a NULL result\n");
1255 return AST_TEST_FAIL;
1260 ast_test_status_update(test,
"Failed to get any DNS records from the result\n");
1261 return AST_TEST_FAIL;
1267 ast_test_status_update(test,
"Expected order %hu, got order %hu from NAPTR record\n",
1269 res = AST_TEST_FAIL;
1272 ast_test_status_update(test,
"Expected preference %hu, got preference %hu from NAPTR record\n",
1274 res = AST_TEST_FAIL;
1277 ast_test_status_update(test,
"Expected flags %s, got flags %s from NAPTR record\n",
1279 res = AST_TEST_FAIL;
1282 ast_test_status_update(test,
"Expected services %s, got services %s from NAPTR record\n",
1284 res = AST_TEST_FAIL;
1287 ast_test_status_update(test,
"Expected regexp %s, got regexp %s from NAPTR record\n",
1289 res = AST_TEST_FAIL;
1292 ast_test_status_update(test,
"Expected replacement %s, got replacement %s from NAPTR record\n",
1294 res = AST_TEST_FAIL;
1296 records[i].visited = 1;
1300 if (i != ARRAY_LEN(records)) {
1301 ast_test_status_update(test,
"Unexpected number of records visited\n");
1302 res = AST_TEST_FAIL;
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;
1318 RAII_VAR(
struct unbound_resolver *, resolver, NULL, ao2_cleanup);
1322 static const char *DOMAIN1 =
"taco.bananas";
1323 static const char *DOMAIN1_SRV =
"taco.bananas 12345 IN SRV 10 20 5060 sip.taco.bananas";
1324 enum ast_test_result_state res = AST_TEST_PASS;
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;
1343 ub_ctx_zone_add(resolver->
context, DOMAIN1,
"static");
1344 ub_ctx_data_add(resolver->
context, DOMAIN1_SRV);
1347 ast_test_status_update(test,
"Failed to synchronously resolve SRV for domain '%s'\n", DOMAIN1);
1348 res = AST_TEST_FAIL;
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;
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;
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;
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;
1378 ub_ctx_data_remove(resolver->
context, DOMAIN1_SRV);
1379 ub_ctx_zone_remove(resolver->
context, DOMAIN1);
1385 static int reload_module(
void)
1394 static int unload_module(
void)
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);
1423 static int load_module(
void)
1441 if (unbound_config_apply_default()) {
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);
1468 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"Unbound DNS Resolver Support",
1469 .support_level = AST_MODULE_SUPPORT_CORE,
1470 .load = load_module,
1471 .unload = unload_module,
1472 .reload = reload_module,
unsigned short ast_dns_srv_get_priority(const struct ast_dns_record *record)
Get the priority from an SRV 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.
const ast_string_field hosts
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_dns_record_get_data(const struct ast_dns_record *record)
Retrieve the raw 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.
void ast_dns_result_free(struct ast_dns_result *result)
Free the DNS result information.
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.
const char * ast_dns_query_get_name(const struct ast_dns_query *query)
Get the name queried in a DNS query.
int ast_dns_query_get_rr_class(const struct ast_dns_query *query)
Get the record resource class of a DNS query.
A container for config related information.
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
Unbound configuration state information.
const ast_string_field resolv
const ast_string_field ta_file
static int debug
Global debug status.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
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.
Structure for variables, used for configurations and for channel variables.
const char * ast_dns_naptr_get_regexp(const struct ast_dns_record *record)
Get the regular expression from a NAPTR record.
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 ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
struct unbound_resolver * resolver
The configured resolver.
unsigned short ast_dns_naptr_get_preference(const struct ast_dns_record *record)
Get the preference from a NAPTR record.
struct unbound_config_state * state
State information.
The representation of a single configuration file to be processed.
const char * ast_dns_naptr_get_service(const struct ast_dns_record *record)
Get the service from a NAPTR record.
void * ast_dns_resolver_get_data(const struct ast_dns_query *query)
Retrieve resolver specific data.
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
unsigned short ast_dns_srv_get_port(const struct ast_dns_record *record)
Get the port from an SRV record.
const char * ast_dns_srv_get_host(const struct ast_dns_record *record)
Get the hostname from an SRV record.
Structure for query resolver data.
unsigned short ast_dns_srv_get_weight(const struct ast_dns_record *record)
Get the weight from an SRV record.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Configuration File Parser.
A structure to hold global configuration-related options.
static void cleanup(void)
Clean up any old apps that we don't need any more.
#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.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
pthread_t thread
Thread handling the resolver.
void * aco_pending_config(struct aco_info *info)
Get pending config changes.
struct ao2_container * ast_str_container_alloc_options(enum ao2_alloc_opts opts, int buckets)
Allocates a hash container for bare strings.
Type for default option handler for unsigned integers.
void * ast_dns_query_get_data(const struct ast_dns_query *query)
Get the user specific data of a DNS query.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
#define AST_STRING_FIELD(name)
Declare a string field.
A set of macros to manage forward-linked lists.
#define ast_debug(level,...)
Log a DEBUG message.
Their was an error and no changes were applied.
The result of a DNS query.
void ast_dns_resolver_completed(struct ast_dns_query *query)
Mark a DNS query as having been completed.
Configuration option-handling.
const char * ast_dns_naptr_get_flags(const struct ast_dns_record *record)
Get the flags from a NAPTR record.
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
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_resolver_set_data(struct ast_dns_query *query, void *data)
Set resolver specific data on a query.
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
DNS resolver implementation.
int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
Set all default options of obj.
#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.
const struct ast_dns_record * ast_dns_result_get_records(const struct ast_dns_result *result)
Get the first record of a DNS Result.
static struct aco_type global_option
An aco_type structure to link the "general" category to the skel_global_config type.
Structure used to handle boolean flags.
struct ub_ctx * context
Resolver context itself.
int id
ID for the specific query.
struct ao2_container * nameservers
List of nameservers (in order) to use for queries.
int ast_dns_query_get_rr_type(const struct ast_dns_query *query)
Get the record resource type of a DNS query.
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
DNS NAPTR Record Parsing API.
unsigned short ast_dns_naptr_get_order(const struct ast_dns_record *record)
Get the order from a NAPTR record.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Type information about a category-level configurable object.
int ast_dns_resolve_cancel(struct ast_dns_query_active *active)
Cancel an asynchronous DNS resolution.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Structure for an unbound resolver.
#define AST_TEST_DEFINE(hdr)
const char * ast_dns_naptr_get_replacement(const struct ast_dns_record *record)
Get the replacement value from a NAPTR record.
Type for default option handler for stringfields.
DNS SRV Record Parsing API.
int ast_dns_record_get_rr_class(const struct ast_dns_record *record)
Get the resource record class of a DNS record.
struct unbound_resolver * resolver
The resolver in use for the query.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
int ast_dns_record_get_rr_type(const struct ast_dns_record *record)
Get the resource record type of a DNS record.
#define AO2_GLOBAL_OBJ_STATIC(name)
Define a global object holder to be used to hold an ao2 object, statically initialized.
#define ASTERISK_GPL_KEY
The text the key() function should return.
unsigned int debug
Debug level for the resolver.
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.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
#define CONFIG_INFO_STANDARD(name, arr, alloc,...)
Declare an aco_info struct with default module and preload values.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
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.
unsigned int ast_dns_result_get_rcode(const struct ast_dns_result *result)
Get the error rcode of a DN result.
Structure for mutex and tracking information.