summaryrefslogtreecommitdiff
path: root/tests/test_dns_srv.c
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2015-04-01 16:27:48 +0000
committerJoshua Colp <jcolp@digium.com>2015-04-01 16:27:48 +0000
commit39824e3d013287d8860d620454d230278b0fba69 (patch)
treeff7380c85bde86fe7138f0b79cf4071594bedb18 /tests/test_dns_srv.c
parentda13d15425e2dfefaf1b656d8aa6462d967b77ad (diff)
dns: Add support for SRV record parsing and sorting.
This change adds support for parsing SRV records and consuming their values in an easy fashion. It also adds automatic sorting of SRV records according to RFC 2782. Tests have also been included which cover parsing, sorting, and off-nominal cases where the record is corrupted. ASTERISK-24931 #close Reported by: Joshua Colp Review: https://reviewboard.asterisk.org/r/4528/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@433889 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'tests/test_dns_srv.c')
-rw-r--r--tests/test_dns_srv.c697
1 files changed, 697 insertions, 0 deletions
diff --git a/tests/test_dns_srv.c b/tests/test_dns_srv.c
new file mode 100644
index 000000000..de79be1d9
--- /dev/null
+++ b/tests/test_dns_srv.c
@@ -0,0 +1,697 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2015, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ * Mark Michelson <mmichelson@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*** MODULEINFO
+ <depend>TEST_FRAMEWORK</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+#include <arpa/nameser.h>
+
+#include "asterisk/test.h"
+#include "asterisk/module.h"
+#include "asterisk/dns_core.h"
+#include "asterisk/dns_resolver.h"
+#include "asterisk/dns_srv.h"
+
+#define DNS_HEADER_SIZE 96
+
+const char DNS_HEADER[] = {
+ /* ID == 0 */
+ 0x00, 0x00,
+ /* QR == 1, Opcode == 0, AA == 1, TC == 0, RD == 1 */
+ 0x85,
+ /* RA == 1, Z == 0, RCODE == 0 */
+ 0x80,
+ /* QDCOUNT == 1 */
+ 0x00, 0x01,
+ /* ANCOUNT == 1 */
+ 0x00, 0x00,
+ /* NSCOUNT == 0 */
+ 0x00, 0x00,
+ /* ARCOUNT == 0 */
+ 0x00, 0x00,
+};
+
+static int generate_dns_header(unsigned short num_records, char *buf)
+{
+ unsigned short net_num_records = htons(num_records);
+
+ memcpy(buf, DNS_HEADER, ARRAY_LEN(DNS_HEADER));
+ /* Overwrite the ANCOUNT with the actual number of answers */
+ memcpy(&buf[6], &net_num_records, sizeof(num_records));
+
+ return ARRAY_LEN(DNS_HEADER);
+}
+
+const char DNS_QUESTION [] = {
+ /* goose */
+ 0x05, 0x67, 0x6f, 0x6f, 0x73, 0x65,
+ /* feathers */
+ 0x08, 0x66, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x73,
+ /* end label */
+ 0x00,
+ /* SRV type */
+ 0x00, 0x23,
+ /* IN class */
+ 0x00, 0x01,
+};
+
+static int generate_dns_question(char *buf)
+{
+ memcpy(buf, DNS_QUESTION, ARRAY_LEN(DNS_QUESTION));
+ return ARRAY_LEN(DNS_QUESTION);
+}
+
+const char SRV_ANSWER [] = {
+ /* Domain points to name from question */
+ 0xc0, 0x0c,
+ /* NAPTR type */
+ 0x00, 0x23,
+ /* IN Class */
+ 0x00, 0x01,
+ /* TTL (12345 by default) */
+ 0x00, 0x00, 0x30, 0x39,
+};
+
+static int generate_dns_answer(int ttl, char *buf)
+{
+ int net_ttl = htonl(ttl);
+
+ memcpy(buf, SRV_ANSWER, ARRAY_LEN(SRV_ANSWER));
+ /* Overwrite TTL if one is provided */
+ if (ttl) {
+ memcpy(&buf[6], &net_ttl, sizeof(int));
+ }
+
+ return ARRAY_LEN(SRV_ANSWER);
+}
+
+static int write_dns_string(const char *string, char *buf)
+{
+ uint8_t len = strlen(string);
+ buf[0] = len;
+ if (len) {
+ memcpy(&buf[1], string, len);
+ }
+
+ return len + 1;
+}
+
+static int write_dns_domain(const char *string, char *buf)
+{
+ char *copy = ast_strdupa(string);
+ char *part;
+ char *ptr = buf;
+
+ while ((part = strsep(&copy, "."))) {
+ ptr += write_dns_string(part, ptr);
+ }
+ ptr += write_dns_string("", ptr);
+
+ return ptr - buf;
+}
+
+struct srv_record {
+ uint16_t priority;
+ uint16_t weight;
+ uint16_t port;
+ const char *host;
+ unsigned int ignore_priority;
+ unsigned int ignore_weight;
+ unsigned int ignore_port;
+ unsigned int ignore_host;
+};
+
+static int generate_srv_record(struct srv_record *record, char *buf)
+{
+ uint16_t priority = htons(record->priority);
+ uint16_t weight = htons(record->weight);
+ uint16_t port = htons(record->port);
+ char *ptr = buf;
+
+ if (!record->ignore_priority) {
+ memcpy(ptr, &priority, sizeof(priority));
+ ptr += sizeof(priority);
+ }
+
+ if (!record->ignore_weight) {
+ memcpy(ptr, &weight, sizeof(weight));
+ ptr += sizeof(weight);
+ }
+
+ if (!record->ignore_port) {
+ memcpy(ptr, &port, sizeof(port));
+ ptr += sizeof(port);
+ }
+
+ if (!record->ignore_host) {
+ ptr += write_dns_domain(record->host, ptr);
+ }
+
+ return ptr - buf;
+}
+
+static struct srv_record *test_records;
+static int num_test_records;
+static char ans_buffer[1024];
+
+static void *srv_thread(void *dns_query)
+{
+ struct ast_dns_query *query = dns_query;
+ int i;
+ char *ptr = ans_buffer;
+
+ ptr += generate_dns_header(num_test_records, ptr);
+ ptr += generate_dns_question(ptr);
+
+ for (i = 0; i < num_test_records; ++i) {
+ unsigned short rdlength;
+ unsigned short net_rdlength;
+
+ ptr += generate_dns_answer(0, ptr);
+ rdlength = generate_srv_record(&test_records[i], ptr + 2);
+ net_rdlength = htons(rdlength);
+ memcpy(ptr, &net_rdlength, 2);
+ ptr += 2;
+ ptr += rdlength;
+ }
+
+ ast_dns_resolver_set_result(query, 0, 0, ns_r_noerror, "goose.feathers", ans_buffer, ptr - ans_buffer);
+
+ for (i = 0; i < num_test_records; ++i) {
+ char record[128];
+ ptr = record;
+
+ ptr += generate_srv_record(&test_records[i], ptr);
+ ast_dns_resolver_add_record(query, ns_t_srv, ns_c_in, 12345, record, ptr - record);
+ }
+
+ ast_dns_resolver_completed(query);
+
+ ao2_ref(query, -1);
+ return NULL;
+}
+
+static int srv_resolve(struct ast_dns_query *query)
+{
+ pthread_t thread;
+
+ return ast_pthread_create_detached(&thread, NULL, srv_thread, ao2_bump(query));
+}
+
+static int srv_cancel(struct ast_dns_query *query)
+{
+ return -1;
+}
+
+static struct ast_dns_resolver srv_resolver = {
+ .name = "srv_test",
+ .priority = 0,
+ .resolve = srv_resolve,
+ .cancel = srv_cancel,
+};
+
+static enum ast_test_result_state nominal_test(struct ast_test *test, struct srv_record *records,
+ int *srv_record_order, int num_records)
+{
+ RAII_VAR(struct ast_dns_result *, result, NULL, ast_dns_result_free);
+ const struct ast_dns_record *record;
+ enum ast_test_result_state res = AST_TEST_PASS;
+ int i;
+
+ test_records = records;
+ num_test_records = num_records;
+ memset(ans_buffer, 0, sizeof(ans_buffer));
+
+ ast_dns_resolver_register(&srv_resolver);
+
+ if (ast_dns_resolve("goose.feathers", ns_t_srv, ns_c_in, &result)) {
+ ast_test_status_update(test, "DNS resolution failed\n");
+ res = AST_TEST_FAIL;
+ goto cleanup;
+ }
+
+ if (!result) {
+ ast_test_status_update(test, "DNS resolution returned no result\n");
+ res = AST_TEST_FAIL;
+ goto cleanup;
+ }
+
+ i = 0;
+ for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) {
+ if (ast_dns_srv_get_priority(record) != records[srv_record_order[i]].priority) {
+ ast_test_status_update(test, "Unexpected priority in returned SRV record\n");
+ res = AST_TEST_FAIL;
+ }
+ if (ast_dns_srv_get_weight(record) != records[srv_record_order[i]].weight) {
+ ast_test_status_update(test, "Unexpected weight in returned SRV record\n");
+ res = AST_TEST_FAIL;
+ }
+ if (ast_dns_srv_get_port(record) != records[srv_record_order[i]].port) {
+ ast_test_status_update(test, "Unexpected port in returned SRV record\n");
+ res = AST_TEST_FAIL;
+ }
+ if (strcmp(ast_dns_srv_get_host(record), records[srv_record_order[i]].host)) {
+ ast_test_status_update(test, "Unexpected host in returned SRV record\n");
+ res = AST_TEST_FAIL;
+ }
+ ++i;
+ }
+
+ if (i != num_records) {
+ ast_test_status_update(test, "Unexpected number of records returned in SRV lookup\n");
+ res = AST_TEST_FAIL;
+ }
+
+cleanup:
+
+ ast_dns_resolver_unregister(&srv_resolver);
+
+ test_records = NULL;
+ num_test_records = 0;
+ memset(ans_buffer, 0, sizeof(ans_buffer));
+
+ return res;
+}
+
+AST_TEST_DEFINE(srv_resolve_single_record)
+{
+ struct srv_record records[] = {
+ { 10, 10, 5060, "goose.down" },
+ };
+
+ int srv_record_order[] = { 0, };
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "srv_resolve_single_record";
+ info->category = "/main/dns/srv/";
+ info->summary = "Test an SRV lookup which returns a single record";
+ info->description = "This test defines a single SRV record and performs a\n"
+ "resolution of the domain to which they belong. The test ensures that all\n"
+ "fields of the SRV record are parsed correctly\n";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ return nominal_test(test, records, srv_record_order, ARRAY_LEN(records));
+}
+
+AST_TEST_DEFINE(srv_resolve_sort_priority)
+{
+ struct srv_record records[] = {
+ { 20, 10, 5060, "tacos" },
+ { 10, 10, 5060, "goose.down" },
+ };
+ int srv_record_order[] = { 1, 0};
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "srv_resolve_sort_priority";
+ info->category = "/main/dns/srv/";
+ info->summary = "Test an SRV lookup which returns two records with differing priorities";
+ info->description = "This test defines two SRV records with differing priorities and\n"
+ "performs a resolution of the domain to which they belong. The test ensures that\n"
+ "the two records are sorted according to priority and that all fields of the SRV\n"
+ "records are parsed correctly\n";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ return nominal_test(test, records, srv_record_order, ARRAY_LEN(records));
+}
+
+AST_TEST_DEFINE(srv_resolve_same_priority_zero_weight)
+{
+ struct srv_record records[] = {
+ { 10, 0, 5060, "tacos" },
+ { 10, 10, 5060, "goose.down" },
+ };
+ int srv_record_order[] = { 1, 0};
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "srv_resolve_same_priority_zero_weight";
+ info->category = "/main/dns/srv/";
+ info->summary = "Test an SRV lookup which returns two records with same priority but different weights";
+ info->description = "This test defines two SRV records with same priority but different weights and\n"
+ "performs a resolution of the domain to which they belong. The test ensures that\n"
+ "the record with zero weight comes last and that all fields of the SRV\n"
+ "records are parsed correctly\n";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ return nominal_test(test, records, srv_record_order, ARRAY_LEN(records));
+}
+
+AST_TEST_DEFINE(srv_resolve_same_priority_different_weights)
+{
+ struct srv_record records[] = {
+ { 10, 10, 5060, "tacos" },
+ { 10, 20, 5060, "goose.down" },
+ };
+
+ int srv_record_occurence[2] = { 0, };
+ enum ast_test_result_state res = AST_TEST_PASS;
+ int count = 0;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "srv_resolve_same_priority_different_weights";
+ info->category = "/main/dns/srv/";
+ info->summary = "Test an SRV lookup which returns two records with same priority but different weights";
+ info->description = "This test defines two SRV records with same priority but different weights and\n"
+ "performs a resolution of the domain to which they belong. The test ensures that\n"
+ "the record with higher weight occurs more often than the one of lesser weight\n";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ test_records = records;
+ num_test_records = ARRAY_LEN(records);
+
+ ast_dns_resolver_register(&srv_resolver);
+
+ for (count = 0; count < 100; count++) {
+ struct ast_dns_result *result;
+ const struct ast_dns_record *record;
+ int i;
+
+ memset(ans_buffer, 0, sizeof(ans_buffer));
+
+ if (ast_dns_resolve("goose.feathers", ns_t_srv, ns_c_in, &result)) {
+ ast_test_status_update(test, "DNS resolution failed\n");
+ res = AST_TEST_FAIL;
+ goto cleanup;
+ }
+
+ if (!result) {
+ ast_test_status_update(test, "DNS resolution returned no result\n");
+ res = AST_TEST_FAIL;
+ goto cleanup;
+ }
+
+ record = ast_dns_result_get_records(result);
+ for (i = 0; i < ARRAY_LEN(records); i++) {
+ if (ast_dns_srv_get_priority(record) != records[i].priority) {
+ continue;
+ }
+ if (ast_dns_srv_get_weight(record) != records[i].weight) {
+ continue;
+ }
+ if (ast_dns_srv_get_port(record) != records[i].port) {
+ continue;
+ }
+ if (strcmp(ast_dns_srv_get_host(record), records[i].host)) {
+ continue;
+ }
+
+ srv_record_occurence[i]++;
+ break;
+ }
+
+ ast_dns_result_free(result);
+ }
+
+ if (srv_record_occurence[0] > srv_record_occurence[1]) {
+ ast_test_status_update(test, "SRV sorting resulted in lesser weight being returned more often\n");
+ res = AST_TEST_FAIL;
+ }
+
+cleanup:
+
+ ast_dns_resolver_unregister(&srv_resolver);
+
+ test_records = NULL;
+ num_test_records = 0;
+ memset(ans_buffer, 0, sizeof(ans_buffer));
+
+ return res;
+}
+
+AST_TEST_DEFINE(srv_resolve_different_priorities_different_weights)
+{
+ struct srv_record records[] = {
+ { 10, 10, 5060, "tacos" },
+ { 10, 20, 5060, "goose.down" },
+ { 5, 80, 5060, "moo" },
+ { 5, 10, 5060, "Canada" },
+ };
+
+ int srv_record_priority[4] = { 5, 5, 10, 10 };
+ int srv_record_occurence[4] = { 0, };
+ enum ast_test_result_state res = AST_TEST_PASS;
+ int count = 0;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "srv_resolve_different_priorities_different_weights";
+ info->category = "/main/dns/srv/";
+ info->summary = "Test an SRV lookup which returns four records with different priority and different weights";
+ info->description = "This test defines four SRV records, two with one priority and two with another priority,\n"
+ "and different weights and performs a resolution of the domain to which they belong.\n"
+ "The test ensures that the priorities are sorted properly and that the records with higher weight\n"
+ "occur more often than the ones of less weight.\n";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ test_records = records;
+ num_test_records = ARRAY_LEN(records);
+
+ ast_dns_resolver_register(&srv_resolver);
+
+ for (count = 0; count < 100; count++) {
+ struct ast_dns_result *result;
+ const struct ast_dns_record *record;
+ int i;
+
+ memset(ans_buffer, 0, sizeof(ans_buffer));
+
+ if (ast_dns_resolve("goose.feathers", ns_t_srv, ns_c_in, &result)) {
+ ast_test_status_update(test, "DNS resolution failed\n");
+ res = AST_TEST_FAIL;
+ goto cleanup;
+ }
+
+ if (!result) {
+ ast_test_status_update(test, "DNS resolution returned no result\n");
+ res = AST_TEST_FAIL;
+ goto cleanup;
+ }
+
+ i = 0;
+ for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) {
+ if (ast_dns_srv_get_priority(record) != srv_record_priority[i]) {
+ ast_test_status_update(test, "Unexpected priority in returned SRV record\n");
+ res = AST_TEST_FAIL;
+ }
+ i++;
+ }
+
+ record = ast_dns_result_get_records(result);
+ for (i = 0; i < ARRAY_LEN(records); i++) {
+ if (ast_dns_srv_get_priority(record) != records[i].priority) {
+ continue;
+ }
+ if (ast_dns_srv_get_weight(record) != records[i].weight) {
+ continue;
+ }
+ if (ast_dns_srv_get_port(record) != records[i].port) {
+ continue;
+ }
+ if (strcmp(ast_dns_srv_get_host(record), records[i].host)) {
+ continue;
+ }
+
+ srv_record_occurence[i]++;
+ break;
+ }
+
+ ast_dns_result_free(result);
+ }
+
+ if (srv_record_occurence[0] > srv_record_occurence[1]) {
+ ast_test_status_update(test, "SRV sorting resulted in lesser weight being returned more often for priority 10\n");
+ res = AST_TEST_FAIL;
+ }
+
+ if (srv_record_occurence[3] > srv_record_occurence[2]) {
+ ast_test_status_update(test, "SRV sorting resulted in lesser weight being returned more often for priority 5\n");
+ res = AST_TEST_FAIL;
+ }
+
+cleanup:
+
+ ast_dns_resolver_unregister(&srv_resolver);
+
+ test_records = NULL;
+ num_test_records = 0;
+ memset(ans_buffer, 0, sizeof(ans_buffer));
+
+ return res;
+}
+
+static enum ast_test_result_state invalid_record_test(struct ast_test *test, struct srv_record *records,
+ int num_records)
+{
+ RAII_VAR(struct ast_dns_result *, result, NULL, ast_dns_result_free);
+ const struct ast_dns_record *record;
+ enum ast_test_result_state res = AST_TEST_PASS;
+
+ test_records = records;
+ num_test_records = num_records;
+ memset(ans_buffer, 0, sizeof(ans_buffer));
+
+ ast_dns_resolver_register(&srv_resolver);
+
+ if (ast_dns_resolve("goose.feathers", ns_t_srv, ns_c_in, &result)) {
+ ast_test_status_update(test, "DNS resolution failed\n");
+ res = AST_TEST_FAIL;
+ goto cleanup;
+ }
+
+ if (!result) {
+ ast_test_status_update(test, "DNS resolution returned no result\n");
+ res = AST_TEST_FAIL;
+ goto cleanup;
+ }
+
+ record = ast_dns_result_get_records(result);
+ if (record) {
+ ast_test_status_update(test, "Unexpected record returned from SRV query\n");
+ res = AST_TEST_FAIL;
+ }
+
+cleanup:
+
+ ast_dns_resolver_unregister(&srv_resolver);
+
+ test_records = NULL;
+ num_test_records = 0;
+ memset(ans_buffer, 0, sizeof(ans_buffer));
+
+ return res;
+}
+
+AST_TEST_DEFINE(srv_resolve_record_missing_weight_port_host)
+{
+ struct srv_record records[] = {
+ { 10, 10, 5060, "tacos.com", 0, 1, 1, 1 },
+ };
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "srv_resolve_record_missing_weight_port_host";
+ info->category = "/main/dns/srv/";
+ info->summary = "Test an SRV lookup which returns a single invalid record";
+ info->description = "This test defines a single SRV record and performs a\n"
+ "resolution of the domain to which they belong. The test ensures that the\n"
+ "record is determined to be corrupt as it contains only a priority\n";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ return invalid_record_test(test, records, ARRAY_LEN(records));
+}
+
+AST_TEST_DEFINE(srv_resolve_record_missing_port_host)
+{
+ struct srv_record records[] = {
+ { 10, 10, 5060, "tacos.com", 0, 0, 1, 1 },
+ };
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "srv_resolve_record_missing_port_host";
+ info->category = "/main/dns/srv/";
+ info->summary = "Test an SRV lookup which returns a single invalid record";
+ info->description = "This test defines a single SRV record and performs a\n"
+ "resolution of the domain to which they belong. The test ensures that the\n"
+ "record is determined to be corrupt as it contains only a priority and weight\n";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ return invalid_record_test(test, records, ARRAY_LEN(records));
+}
+
+AST_TEST_DEFINE(srv_resolve_record_missing_host)
+{
+ struct srv_record records[] = {
+ { 10, 10, 5060, "tacos.com", 0, 0, 0, 1 },
+ };
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "srv_resolve_record_missing_host";
+ info->category = "/main/dns/srv/";
+ info->summary = "Test an SRV lookup which returns a single invalid record";
+ info->description = "This test defines a single SRV record and performs a\n"
+ "resolution of the domain to which they belong. The test ensures that the\n"
+ "record is determined to be corrupt as it contains only a priority, weight,\n"
+ "and port\n";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ return invalid_record_test(test, records, ARRAY_LEN(records));
+}
+
+static int unload_module(void)
+{
+ AST_TEST_UNREGISTER(srv_resolve_single_record);
+ AST_TEST_UNREGISTER(srv_resolve_sort_priority);
+ AST_TEST_UNREGISTER(srv_resolve_same_priority_zero_weight);
+ AST_TEST_UNREGISTER(srv_resolve_same_priority_different_weights);
+ AST_TEST_UNREGISTER(srv_resolve_different_priorities_different_weights);
+ AST_TEST_UNREGISTER(srv_resolve_record_missing_weight_port_host);
+ AST_TEST_UNREGISTER(srv_resolve_record_missing_port_host);
+ AST_TEST_UNREGISTER(srv_resolve_record_missing_host);
+
+ return 0;
+}
+
+static int load_module(void)
+{
+ AST_TEST_REGISTER(srv_resolve_single_record);
+ AST_TEST_REGISTER(srv_resolve_sort_priority);
+ AST_TEST_REGISTER(srv_resolve_same_priority_zero_weight);
+ AST_TEST_REGISTER(srv_resolve_same_priority_different_weights);
+ AST_TEST_REGISTER(srv_resolve_different_priorities_different_weights);
+ AST_TEST_REGISTER(srv_resolve_record_missing_weight_port_host);
+ AST_TEST_REGISTER(srv_resolve_record_missing_port_host);
+ AST_TEST_REGISTER(srv_resolve_record_missing_host);
+
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "DNS SRV Tests");