27 #include <arpa/nameser.h>
34 #include "asterisk/dns_test.h"
41 unsigned int ignore_priority;
42 unsigned int ignore_weight;
43 unsigned int ignore_port;
44 unsigned int ignore_host;
47 static int generate_srv_record(
void *dns_record,
char *buf)
50 uint16_t priority = htons(record->priority);
51 uint16_t weight = htons(record->weight);
52 uint16_t port = htons(record->port);
55 if (!record->ignore_priority) {
56 memcpy(ptr, &priority,
sizeof(priority));
57 ptr +=
sizeof(priority);
60 if (!record->ignore_weight) {
61 memcpy(ptr, &weight,
sizeof(weight));
62 ptr +=
sizeof(weight);
65 if (!record->ignore_port) {
66 memcpy(ptr, &port,
sizeof(port));
70 if (!record->ignore_host) {
71 ptr += ast_dns_test_write_domain(record->host, ptr);
78 static int num_test_records;
79 static char ans_buffer[1024];
81 static void *srv_thread(
void *dns_query)
87 ans_size = ast_dns_test_generate_result(query, test_records, num_test_records,
88 sizeof(
struct srv_record), generate_srv_record, ans_buffer);
92 for (i = 0; i < num_test_records; ++i) {
96 srv_size = generate_srv_record(&test_records[i], record);
110 return ast_pthread_create_detached(&thread, NULL, srv_thread,
ao2_bump(query));
121 .resolve = srv_resolve,
122 .cancel = srv_cancel,
125 static enum ast_test_result_state nominal_test(
struct ast_test *
test,
struct srv_record *records,
126 int *srv_record_order,
int num_records)
130 enum ast_test_result_state res = AST_TEST_PASS;
133 test_records = records;
134 num_test_records = num_records;
135 memset(ans_buffer, 0,
sizeof(ans_buffer));
140 ast_test_status_update(test,
"DNS resolution failed\n");
146 ast_test_status_update(test,
"DNS resolution returned no result\n");
154 ast_test_status_update(test,
"Unexpected priority in returned SRV record\n");
158 ast_test_status_update(test,
"Unexpected weight in returned SRV record\n");
162 ast_test_status_update(test,
"Unexpected port in returned SRV record\n");
166 ast_test_status_update(test,
"Unexpected host in returned SRV record\n");
172 if (i != num_records) {
173 ast_test_status_update(test,
"Unexpected number of records returned in SRV lookup\n");
182 num_test_records = 0;
183 memset(ans_buffer, 0,
sizeof(ans_buffer));
191 { 10, 10, 5060,
"goose.down" },
194 int srv_record_order[] = { 0, };
198 info->name =
"srv_resolve_single_record";
199 info->category =
"/main/dns/srv/";
200 info->summary =
"Test an SRV lookup which returns a single record";
201 info->description =
"This test defines a single SRV record and performs a\n"
202 "resolution of the domain to which they belong. The test ensures that all\n"
203 "fields of the SRV record are parsed correctly";
204 return AST_TEST_NOT_RUN;
209 return nominal_test(test, records, srv_record_order, ARRAY_LEN(records));
215 { 20, 10, 5060,
"tacos" },
216 { 10, 10, 5060,
"goose.down" },
218 int srv_record_order[] = { 1, 0};
222 info->name =
"srv_resolve_sort_priority";
223 info->category =
"/main/dns/srv/";
224 info->summary =
"Test an SRV lookup which returns two records with differing priorities";
225 info->description =
"This test defines two SRV records with differing priorities and\n"
226 "performs a resolution of the domain to which they belong. The test ensures that\n"
227 "the two records are sorted according to priority and that all fields of the SRV\n"
228 "records are parsed correctly";
229 return AST_TEST_NOT_RUN;
234 return nominal_test(test, records, srv_record_order, ARRAY_LEN(records));
240 { 10, 0, 5060,
"tacos" },
241 { 10, 10, 5060,
"goose.down" },
243 int srv_record_order[] = { 1, 0};
247 info->name =
"srv_resolve_same_priority_zero_weight";
248 info->category =
"/main/dns/srv/";
249 info->summary =
"Test an SRV lookup which returns two records with same priority but different weights";
250 info->description =
"This test defines two SRV records with same priority but different weights and\n"
251 "performs a resolution of the domain to which they belong. The test ensures that\n"
252 "the record with zero weight comes last and that all fields of the SRV\n"
253 "records are parsed correctly";
254 return AST_TEST_NOT_RUN;
259 return nominal_test(test, records, srv_record_order, ARRAY_LEN(records));
265 { 10, 10, 5060,
"tacos" },
266 { 10, 20, 5060,
"goose.down" },
269 int srv_record_occurence[2] = { 0, };
270 enum ast_test_result_state res = AST_TEST_PASS;
275 info->name =
"srv_resolve_same_priority_different_weights";
276 info->category =
"/main/dns/srv/";
277 info->summary =
"Test an SRV lookup which returns two records with same priority but different weights";
278 info->description =
"This test defines two SRV records with same priority but different weights and\n"
279 "performs a resolution of the domain to which they belong. The test ensures that\n"
280 "the record with higher weight occurs more often than the one of lesser weight";
281 return AST_TEST_NOT_RUN;
286 test_records = records;
287 num_test_records = ARRAY_LEN(records);
291 for (count = 0; count < 100; count++) {
296 memset(ans_buffer, 0,
sizeof(ans_buffer));
299 ast_test_status_update(test,
"DNS resolution failed\n");
305 ast_test_status_update(test,
"DNS resolution returned no result\n");
311 for (i = 0; i < ARRAY_LEN(records); i++) {
325 srv_record_occurence[i]++;
332 if (srv_record_occurence[0] > srv_record_occurence[1]) {
333 ast_test_status_update(test,
"SRV sorting resulted in lesser weight being returned more often\n");
342 num_test_records = 0;
343 memset(ans_buffer, 0,
sizeof(ans_buffer));
351 { 10, 10, 5060,
"tacos" },
352 { 10, 20, 5060,
"goose.down" },
353 { 5, 80, 5060,
"moo" },
354 { 5, 10, 5060,
"Canada" },
357 int srv_record_priority[4] = { 5, 5, 10, 10 };
358 int srv_record_occurence[4] = { 0, };
359 enum ast_test_result_state res = AST_TEST_PASS;
364 info->name =
"srv_resolve_different_priorities_different_weights";
365 info->category =
"/main/dns/srv/";
366 info->summary =
"Test an SRV lookup which returns four records with different priority and different weights";
367 info->description =
"This test defines four SRV records, two with one priority and two with another priority,\n"
368 "and different weights and performs a resolution of the domain to which they belong.\n"
369 "The test ensures that the priorities are sorted properly and that the records with higher weight\n"
370 "occur more often than the ones of less weight.";
371 return AST_TEST_NOT_RUN;
376 test_records = records;
377 num_test_records = ARRAY_LEN(records);
381 for (count = 0; count < 100; count++) {
386 memset(ans_buffer, 0,
sizeof(ans_buffer));
389 ast_test_status_update(test,
"DNS resolution failed\n");
395 ast_test_status_update(test,
"DNS resolution returned no result\n");
403 ast_test_status_update(test,
"Unexpected priority in returned SRV record\n");
410 for (i = 0; i < ARRAY_LEN(records); i++) {
424 srv_record_occurence[i]++;
431 if (srv_record_occurence[0] > srv_record_occurence[1]) {
432 ast_test_status_update(test,
"SRV sorting resulted in lesser weight being returned more often for priority 10\n");
436 if (srv_record_occurence[3] > srv_record_occurence[2]) {
437 ast_test_status_update(test,
"SRV sorting resulted in lesser weight being returned more often for priority 5\n");
446 num_test_records = 0;
447 memset(ans_buffer, 0,
sizeof(ans_buffer));
452 static enum ast_test_result_state invalid_record_test(
struct ast_test *test,
struct srv_record *records,
457 enum ast_test_result_state res = AST_TEST_PASS;
459 test_records = records;
460 num_test_records = num_records;
461 memset(ans_buffer, 0,
sizeof(ans_buffer));
466 ast_test_status_update(test,
"DNS resolution failed\n");
472 ast_test_status_update(test,
"DNS resolution returned no result\n");
479 ast_test_status_update(test,
"Unexpected record returned from SRV query\n");
488 num_test_records = 0;
489 memset(ans_buffer, 0,
sizeof(ans_buffer));
497 { 10, 10, 5060,
"tacos.com", 0, 1, 1, 1 },
502 info->name =
"srv_resolve_record_missing_weight_port_host";
503 info->category =
"/main/dns/srv/";
504 info->summary =
"Test an SRV lookup which returns a single invalid record";
505 info->description =
"This test defines a single SRV record and performs a\n"
506 "resolution of the domain to which they belong. The test ensures that the\n"
507 "record is determined to be corrupt as it contains only a priority";
508 return AST_TEST_NOT_RUN;
513 return invalid_record_test(test, records, ARRAY_LEN(records));
519 { 10, 10, 5060,
"tacos.com", 0, 0, 1, 1 },
524 info->name =
"srv_resolve_record_missing_port_host";
525 info->category =
"/main/dns/srv/";
526 info->summary =
"Test an SRV lookup which returns a single invalid record";
527 info->description =
"This test defines a single SRV record and performs a\n"
528 "resolution of the domain to which they belong. The test ensures that the\n"
529 "record is determined to be corrupt as it contains only a priority and weight";
530 return AST_TEST_NOT_RUN;
535 return invalid_record_test(test, records, ARRAY_LEN(records));
541 { 10, 10, 5060,
"tacos.com", 0, 0, 0, 1 },
546 info->name =
"srv_resolve_record_missing_host";
547 info->category =
"/main/dns/srv/";
548 info->summary =
"Test an SRV lookup which returns a single invalid record";
549 info->description =
"This test defines a single SRV record and performs a\n"
550 "resolution of the domain to which they belong. The test ensures that the\n"
551 "record is determined to be corrupt as it contains only a priority, weight,\n"
553 return AST_TEST_NOT_RUN;
558 return invalid_record_test(test, records, ARRAY_LEN(records));
561 static int unload_module(
void)
563 AST_TEST_UNREGISTER(srv_resolve_single_record);
564 AST_TEST_UNREGISTER(srv_resolve_sort_priority);
565 AST_TEST_UNREGISTER(srv_resolve_same_priority_zero_weight);
566 AST_TEST_UNREGISTER(srv_resolve_same_priority_different_weights);
567 AST_TEST_UNREGISTER(srv_resolve_different_priorities_different_weights);
568 AST_TEST_UNREGISTER(srv_resolve_record_missing_weight_port_host);
569 AST_TEST_UNREGISTER(srv_resolve_record_missing_port_host);
570 AST_TEST_UNREGISTER(srv_resolve_record_missing_host);
575 static int load_module(
void)
577 AST_TEST_REGISTER(srv_resolve_single_record);
578 AST_TEST_REGISTER(srv_resolve_sort_priority);
579 AST_TEST_REGISTER(srv_resolve_same_priority_zero_weight);
580 AST_TEST_REGISTER(srv_resolve_same_priority_different_weights);
581 AST_TEST_REGISTER(srv_resolve_different_priorities_different_weights);
582 AST_TEST_REGISTER(srv_resolve_record_missing_weight_port_host);
583 AST_TEST_REGISTER(srv_resolve_record_missing_port_host);
584 AST_TEST_REGISTER(srv_resolve_record_missing_host);
unsigned short ast_dns_srv_get_priority(const struct ast_dns_record *record)
Get the priority from an SRV record.
const struct ast_dns_record * ast_dns_record_get_next(const struct ast_dns_record *record)
Get the next DNS record.
Asterisk main include file. File version handling, generic pbx functions.
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.
void ast_dns_resolver_unregister(struct ast_dns_resolver *resolver)
Unregister a DNS resolver.
const char * name
The name of the resolver implementation.
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.
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.
static void cleanup(void)
Clean up any old apps that we don't need any more.
#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.
The result of a DNS query.
void ast_dns_resolver_completed(struct ast_dns_query *query)
Mark a DNS query as having been completed.
DNS resolver implementation.
const struct ast_dns_record * ast_dns_result_get_records(const struct ast_dns_result *result)
Get the first record of a DNS Result.
#define AST_TEST_DEFINE(hdr)
DNS SRV Record Parsing API.
#define ASTERISK_GPL_KEY
The text the key() function should return.
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.