mirror of https://github.com/asterisk/asterisk
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@434154 65c4cc65-6c06-0410-ace0-fbb531ad65f3changes/42/42/1
parent
87d7c90e4e
commit
fc314cb43f
@ -0,0 +1,715 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2015, Mark Michelson
|
||||
*
|
||||
* 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_naptr.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,
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Generate a DNS header and write it to a buffer
|
||||
*
|
||||
* The DNS header is the first part of a DNS request or response. In our
|
||||
* case, the only part of the header that a test can affect is the number
|
||||
* of answers. The rest of the DNS header is based on hard-coded values.
|
||||
*
|
||||
* There is no buffer size passed to this function since we provide
|
||||
* the data ourselves and have sized the buffer to be way larger
|
||||
* than necessary for the tests.
|
||||
*
|
||||
* \param num_records The number of DNS records in this DNS response
|
||||
* \param buf The buffer to write the header into
|
||||
* \retval The number of bytes written to the buffer
|
||||
*/
|
||||
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,
|
||||
/* NAPTR type */
|
||||
0x00, 0x23,
|
||||
/* IN class */
|
||||
0x00, 0x01,
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Generate a DNS question and write it to a buffer
|
||||
*
|
||||
* The DNS question is the second part of a DNS request or response.
|
||||
* All DNS questions in this file are for the same domain and thus
|
||||
* the DNS question is a hard-coded value.
|
||||
*
|
||||
* There is no buffer size passed to this function since we provide
|
||||
* the data ourselves and have sized the buffer to be way larger
|
||||
* than necessary for the tests.
|
||||
*
|
||||
* \param buf The buffer to write the question into
|
||||
* \retval The number of bytes written to the buffer
|
||||
*/
|
||||
static int generate_dns_question(char *buf)
|
||||
{
|
||||
memcpy(buf, DNS_QUESTION, ARRAY_LEN(DNS_QUESTION));
|
||||
return ARRAY_LEN(DNS_QUESTION);
|
||||
}
|
||||
|
||||
const char NAPTR_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,
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Generate a DNS answer and write it to a buffer
|
||||
*
|
||||
* The DNS answer is the third (and in our case final) part of a
|
||||
* DNS response. The DNS answer generated here is only partial.
|
||||
* The record-specific data is generated by a separate function.
|
||||
* DNS answers in our tests may have variable TTLs, but the rest
|
||||
* is hard-coded.
|
||||
*
|
||||
* There is no buffer size passed to this function since we provide
|
||||
* the data ourselves and have sized the buffer to be way larger
|
||||
* than necessary for the tests.
|
||||
*
|
||||
* \param buf The buffer to write the answer into
|
||||
* \retval The number of bytes written to the buffer
|
||||
*/
|
||||
static int generate_dns_answer(int ttl, char *buf)
|
||||
{
|
||||
int net_ttl = htonl(ttl);
|
||||
|
||||
memcpy(buf, NAPTR_ANSWER, ARRAY_LEN(NAPTR_ANSWER));
|
||||
/* Overwrite TTL if one is provided */
|
||||
if (ttl) {
|
||||
memcpy(&buf[6], &net_ttl, sizeof(int));
|
||||
}
|
||||
|
||||
return ARRAY_LEN(NAPTR_ANSWER);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Representation of a string in DNS
|
||||
*
|
||||
* In DNS, a string has a byte to indicate the length,
|
||||
* followed by a series of bytes representing the string.
|
||||
* DNS does not NULL-terminate its strings.
|
||||
*/
|
||||
struct dns_string {
|
||||
uint8_t len;
|
||||
const char *val;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Write a DNS string to a buffer
|
||||
*
|
||||
* This writes the DNS string to the buffer and returns the total
|
||||
* number of bytes written to the buffer.
|
||||
*
|
||||
* There is no buffer size passed to this function since we provide
|
||||
* the data ourselves and have sized the buffer to be way larger
|
||||
* than necessary for the tests.
|
||||
*
|
||||
* \param string The string to write
|
||||
* \param buf The buffer to write the string into
|
||||
* \return The number of bytes written to the buffer
|
||||
*/
|
||||
static int write_dns_string(const struct dns_string *string, char *buf)
|
||||
{
|
||||
uint8_t len = string->len;
|
||||
buf[0] = len;
|
||||
/*
|
||||
* We use the actual length of the string instead of
|
||||
* the stated value since sometimes we're going to lie about
|
||||
* the length of the string
|
||||
*/
|
||||
if (strlen(string->val)) {
|
||||
memcpy(&buf[1], string->val, strlen(string->val));
|
||||
}
|
||||
|
||||
return strlen(string->val) + 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Write a DNS domain to a buffer
|
||||
*
|
||||
* A DNS domain consists of a series of labels separated
|
||||
* by dots. Each of these labels gets written as a DNS
|
||||
* string. A DNS domain ends with a NULL label, which is
|
||||
* essentially a zero-length DNS string.
|
||||
*
|
||||
*
|
||||
* There is no buffer size passed to this function since we provide
|
||||
* the data ourselves and have sized the buffer to be way larger
|
||||
* than necessary for the tests.
|
||||
*
|
||||
* \param string The DNS domain to write
|
||||
* \param buf The buffer to write the domain into
|
||||
* \return The number of bytes written to the buffer
|
||||
*/
|
||||
static int write_dns_domain(const char *string, char *buf)
|
||||
{
|
||||
char *copy = ast_strdupa(string);
|
||||
char *part;
|
||||
char *ptr = buf;
|
||||
static const struct dns_string null_label = {
|
||||
.len = 0,
|
||||
.val = "",
|
||||
};
|
||||
|
||||
while (1) {
|
||||
struct dns_string dns_str;
|
||||
part = strsep(©, ".");
|
||||
if (ast_strlen_zero(part)) {
|
||||
break;
|
||||
}
|
||||
dns_str.len = strlen(part);
|
||||
dns_str.val = part;
|
||||
|
||||
ptr += write_dns_string(&dns_str, ptr);
|
||||
}
|
||||
ptr += write_dns_string(&null_label, ptr);
|
||||
|
||||
return ptr - buf;
|
||||
}
|
||||
|
||||
struct naptr_record {
|
||||
uint16_t order;
|
||||
uint16_t preference;
|
||||
struct dns_string flags;
|
||||
struct dns_string services;
|
||||
struct dns_string regexp;
|
||||
const char * replacement;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Given a NAPTR record, generate a binary form, as would appear in DNS RDATA
|
||||
*
|
||||
* This is part of a DNS answer, specific to NAPTR. It consists of all parts of
|
||||
* the NAPTR record, encoded as it should be in a DNS record.
|
||||
*
|
||||
* There is no buffer size passed to this function since we provide
|
||||
* the data ourselves and have sized the buffer to be way larger
|
||||
* than necessary for the tests.
|
||||
*
|
||||
* \param string The NAPTR record to encode
|
||||
* \param buf The buffer to write the record into
|
||||
* \return The number of bytes written to the buffer
|
||||
*/
|
||||
static int generate_naptr_record(struct naptr_record *record, char *buf)
|
||||
{
|
||||
uint16_t net_order = htons(record->order);
|
||||
uint16_t net_preference = htons(record->preference);
|
||||
char *ptr = buf;
|
||||
|
||||
memcpy(ptr, &net_order, sizeof(net_order));
|
||||
ptr += sizeof(net_order);
|
||||
|
||||
memcpy(ptr, &net_preference, sizeof(net_preference));
|
||||
ptr += sizeof(net_preference);
|
||||
|
||||
ptr += write_dns_string(&record->flags, ptr);
|
||||
ptr += write_dns_string(&record->services, ptr);
|
||||
ptr += write_dns_string(&record->regexp, ptr);
|
||||
ptr += write_dns_domain(record->replacement, ptr);
|
||||
|
||||
return ptr - buf;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief A pointer to an array of records for a test
|
||||
*
|
||||
* Each test is expected to set this pointer to its local
|
||||
* array of records and then re-set tis pointer to NULL
|
||||
* at the end of the test
|
||||
*/
|
||||
static struct naptr_record *test_records;
|
||||
/*!
|
||||
* \brief The number of records in the test_records array.
|
||||
*
|
||||
* Each test must set this to the appropriate value at the
|
||||
* beginning of the test and must set this back to zero at
|
||||
* the end of the test.
|
||||
*/
|
||||
static int num_test_records;
|
||||
/*!
|
||||
* \brief A buffer to place raw DNS records into.
|
||||
*
|
||||
* This buffer is way larger than any DNS records we actually
|
||||
* wish to create during any of the tests, but that's fine.
|
||||
*/
|
||||
static char ans_buffer[1024];
|
||||
|
||||
/*!
|
||||
* \brief Asynchronous NAPTR resolution thread.
|
||||
*
|
||||
* This builds an appropriate DNS response based on the NAPTR
|
||||
* records for a given test. Once the records have been created,
|
||||
* the records are added to the DNS result
|
||||
*/
|
||||
static void *naptr_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_naptr_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_naptr_record(&test_records[i], ptr);
|
||||
ast_dns_resolver_add_record(query, ns_t_naptr, ns_c_in, 12345, record, ptr - record);
|
||||
}
|
||||
|
||||
ast_dns_resolver_completed(query);
|
||||
|
||||
ao2_ref(query, -1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Mock NAPTR resolution method.
|
||||
*
|
||||
* This spawns a thread to handle generation of the necessary NAPTR records
|
||||
*/
|
||||
static int naptr_resolve(struct ast_dns_query *query)
|
||||
{
|
||||
pthread_t thread;
|
||||
|
||||
return ast_pthread_create_detached(&thread, NULL, naptr_thread, ao2_bump(query));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief A STUB
|
||||
*/
|
||||
static int naptr_cancel(struct ast_dns_query *query)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Mock NAPTR resolver
|
||||
*/
|
||||
static struct ast_dns_resolver naptr_resolver = {
|
||||
.name = "naptr_test",
|
||||
.priority = 0,
|
||||
.resolve = naptr_resolve,
|
||||
.cancel = naptr_cancel,
|
||||
};
|
||||
|
||||
AST_TEST_DEFINE(naptr_resolve_nominal)
|
||||
{
|
||||
RAII_VAR(struct ast_dns_result *, result, NULL, ast_dns_result_free);
|
||||
const struct ast_dns_record *record;
|
||||
struct naptr_record records[] = {
|
||||
/* Incredibly plain record */
|
||||
{ 200, 100, {1, "A"}, {4, "BLAH"}, {0, ""}, "goose.down" },
|
||||
/* Records with valid but unusual flags */
|
||||
{ 300, 8, {0, ""}, {4, "BLAH"}, {0, ""}, "goose.down" },
|
||||
{ 300, 6, {1, "3"}, {4, "BLAH"}, {0, ""}, "goose.down" },
|
||||
{ 100, 2, {2, "32"}, {4, "BLAH"}, {0, ""}, "goose.down" },
|
||||
{ 400, 100, {3, "A32"}, {4, "BLAH"}, {0, ""}, "goose.down" },
|
||||
/* Records with valid but unusual services */
|
||||
{ 100, 700, {0, ""}, {0, ""}, {0, ""}, "goose.down" },
|
||||
//{ 500, 100, {1, "A"}, {42, "A+B12+C+D+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"}, {0, ""}, "goose.down" },
|
||||
{ 500, 100, {1, "A"}, {14, "A+B12+C+D+EEEE"}, {0, ""}, "goose.down" },
|
||||
/* Records with valid regexes (regexes are always unusual) */
|
||||
{ 500, 101, {1, "A"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, "" },
|
||||
{ 500, 99, {1, "A"}, {4, "BLAH"}, {15, "0.*0horse.mane0"}, "" },
|
||||
{ 10, 100, {1, "A"}, {4, "BLAH"}, {11, "!.*!\\!\\!\\!!"}, "" },
|
||||
{ 700, 999, {1, "A"}, {4, "BLAH"}, {30, "!(.)(.)(.)(.)!\\1.m.\\2.n\\3.o\\4!"}, "" },
|
||||
};
|
||||
|
||||
int naptr_record_order[] = { 9, 3, 5, 0, 2, 1, 4, 8, 6, 7, 10};
|
||||
enum ast_test_result_state res = AST_TEST_PASS;
|
||||
int i;
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = "naptr_resolve";
|
||||
info->category = "/main/dns/naptr/";
|
||||
info->summary = "Test nominal resolution of NAPTR records";
|
||||
info->description = "This test defines four valid NAPTR records and\n"
|
||||
"performs a resolution of the domain to which they belong. The test\n"
|
||||
"ensures that all fields of the NAPTR records are parsed correctly\n"
|
||||
"and that the records are returned in sorted order\n";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
test_records = records;
|
||||
num_test_records = ARRAY_LEN(records);
|
||||
memset(ans_buffer, 0, sizeof(ans_buffer));
|
||||
|
||||
ast_dns_resolver_register(&naptr_resolver);
|
||||
|
||||
if (ast_dns_resolve("goose.feathers", ns_t_naptr, 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_naptr_get_order(record) != records[naptr_record_order[i]].order) {
|
||||
ast_test_status_update(test, "Expected order %hu, got order %hu from NAPTR record\n",
|
||||
records[naptr_record_order[i]].order, ast_dns_naptr_get_order(record));
|
||||
res = AST_TEST_FAIL;
|
||||
}
|
||||
if (ast_dns_naptr_get_preference(record) != records[naptr_record_order[i]].preference) {
|
||||
ast_test_status_update(test, "Expected preference %hu, got preference %hu from NAPTR record\n",
|
||||
records[naptr_record_order[i]].preference, ast_dns_naptr_get_preference(record));
|
||||
res = AST_TEST_FAIL;
|
||||
}
|
||||
if (strcmp(ast_dns_naptr_get_flags(record), records[naptr_record_order[i]].flags.val)) {
|
||||
ast_test_status_update(test, "Expected flags %s, got flags %s from NAPTR record\n",
|
||||
records[naptr_record_order[i]].flags.val, ast_dns_naptr_get_flags(record));
|
||||
res = AST_TEST_FAIL;
|
||||
}
|
||||
if (strcmp(ast_dns_naptr_get_service(record), records[naptr_record_order[i]].services.val)) {
|
||||
ast_test_status_update(test, "Expected services %s, got services %s from NAPTR record\n",
|
||||
records[naptr_record_order[i]].services.val, ast_dns_naptr_get_service(record));
|
||||
res = AST_TEST_FAIL;
|
||||
}
|
||||
if (strcmp(ast_dns_naptr_get_regexp(record), records[naptr_record_order[i]].regexp.val)) {
|
||||
ast_test_status_update(test, "Expected regexp %s, got regexp %s from NAPTR record\n",
|
||||
records[naptr_record_order[i]].regexp.val, ast_dns_naptr_get_regexp(record));
|
||||
res = AST_TEST_FAIL;
|
||||
}
|
||||
if (strcmp(ast_dns_naptr_get_replacement(record), records[naptr_record_order[i]].replacement)) {
|
||||
ast_test_status_update(test, "Expected replacement %s, got replacement %s from NAPTR record\n",
|
||||
records[naptr_record_order[i]].replacement, ast_dns_naptr_get_replacement(record));
|
||||
res = AST_TEST_FAIL;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
if (i != ARRAY_LEN(records)) {
|
||||
ast_test_status_update(test, "Unexpected number of records returned in NAPTR lookup\n");
|
||||
res = AST_TEST_FAIL;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
ast_dns_resolver_unregister(&naptr_resolver);
|
||||
|
||||
test_records = NULL;
|
||||
num_test_records = 0;
|
||||
memset(ans_buffer, 0, sizeof(ans_buffer));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static enum ast_test_result_state off_nominal_test(struct ast_test *test, struct naptr_record *records, int num_records)
|
||||
{
|
||||
RAII_VAR(struct ast_dns_result *, result, NULL, ast_dns_result_free);
|
||||
enum ast_test_result_state res = AST_TEST_PASS;
|
||||
const struct ast_dns_record *record;
|
||||
|
||||
test_records = records;
|
||||
num_test_records = num_records;
|
||||
memset(ans_buffer, 0, sizeof(ans_buffer));
|
||||
|
||||
ast_dns_resolver_register(&naptr_resolver);
|
||||
|
||||
if (ast_dns_resolve("goose.feathers", ns_t_naptr, ns_c_in, &result)) {
|
||||
ast_test_status_update(test, "Failed to perform DNS resolution, despite using valid inputs\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
ast_test_status_update(test, "Synchronous DNS resolution failed to set a result\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
record = ast_dns_result_get_records(result);
|
||||
if (record) {
|
||||
ast_test_status_update(test, "DNS resolution returned records when it was not expected to\n");
|
||||
res = AST_TEST_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
ast_dns_resolver_unregister(&naptr_resolver);
|
||||
|
||||
test_records = NULL;
|
||||
num_test_records = 0;
|
||||
memset(ans_buffer, 0, sizeof(ans_buffer));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
AST_TEST_DEFINE(naptr_resolve_off_nominal_length)
|
||||
{
|
||||
struct naptr_record records[] = {
|
||||
{ 100, 100, {255, "A"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, "" },
|
||||
{ 100, 100, {0, "A"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, "" },
|
||||
{ 100, 100, {1, "A"}, {255, "BLAH"}, {15, "!.*!horse.mane!"}, "" },
|
||||
{ 100, 100, {1, "A"}, {2, "BLAH"}, {15, "!.*!horse.mane!"}, "" },
|
||||
{ 100, 100, {1, "A"}, {4, "BLAH"}, {255, "!.*!horse.mane!"}, "" },
|
||||
{ 100, 100, {1, "A"}, {4, "BLAH"}, {3, "!.*!horse.mane!"}, "" },
|
||||
{ 100, 100, {255, "A"}, {255, "BLAH"}, {255, "!.*!horse.mane!"}, "" },
|
||||
{ 100, 100, {0, "A"}, {2, "BLAH"}, {3, "!.*!horse.mane!"}, "" },
|
||||
};
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = "naptr_resolve_off_nominal_length";
|
||||
info->category = "/main/dns/naptr/";
|
||||
info->summary = "Test resolution of NAPTR records with off-nominal lengths";
|
||||
info->description = "This test defines a set of records where the strings provided\n"
|
||||
"within the record are valid, but the lengths of the strings in the record are\n"
|
||||
"invalid, either too large or too small. The goal of this test is to ensure that\n"
|
||||
"these invalid lengths result in resolution failures\n";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
return off_nominal_test(test, records, ARRAY_LEN(records));
|
||||
}
|
||||
|
||||
AST_TEST_DEFINE(naptr_resolve_off_nominal_flags)
|
||||
{
|
||||
struct naptr_record records[] = {
|
||||
/* Non-alphanumeric flag */
|
||||
{ 100, 100, {1, "!"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
/* Mix of valid and non-alphanumeric */
|
||||
{ 100, 100, {2, "A!"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {2, "!A"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
/* Invalid combinations of flags */
|
||||
{ 100, 100, {2, "sa"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {2, "su"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {2, "sp"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {2, "as"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {2, "au"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {2, "ap"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {2, "ua"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {2, "us"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {2, "up"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {2, "pa"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {2, "ps"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {2, "pu"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
};
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = "naptr_resolve_off_nominal_flags";
|
||||
info->category = "/main/dns/naptr/";
|
||||
info->summary = "Ensure that NAPTR records with invalid flags are not presented in results";
|
||||
info->description = "This test defines a set of records where the flags provided are\n"
|
||||
"invalid in some way. This may be due to providing non-alphanumeric characters or\n"
|
||||
"by providing clashing flags. The result should be that none of the defined records\n"
|
||||
"are returned by the resolver\n";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
return off_nominal_test(test, records, ARRAY_LEN(records));
|
||||
}
|
||||
|
||||
AST_TEST_DEFINE(naptr_resolve_off_nominal_services)
|
||||
{
|
||||
struct naptr_record records[] = {
|
||||
{ 100, 100, {1, "A"}, {5, "BLAH!"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {1, "A"}, {5, "BL!AH"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {1, "A"}, {8, "1SIP+D2U"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {1, "A"}, {8, "SIP+1D2U"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {1, "A"}, {4, "+D2U"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {1, "A"}, {4, "SIP+"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {1, "A"}, {8, "SIP++D2U"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {1, "A"}, {37, "SIPSIPSIPSIPSIPSIPSIPSIPSIPSIPSIP+D2U"}, {15, "!.*!horse.mane!"}, ""},
|
||||
{ 100, 100, {1, "A"}, {37, "SIP+D2UD2UD2UD2UD2UD2UD2UD2UD2UD2UD2U"}, {15, "!.*!horse.mane!"}, ""},
|
||||
};
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = "naptr_resolve_off_nominal_services";
|
||||
info->category = "/main/dns/naptr/";
|
||||
info->summary = "Ensure that NAPTR records with invalid services are not presented in results";
|
||||
info->description = "This test defines a set of records where the services provided are\n"
|
||||
"invalid in some way. This may be due to providing non-alphanumeric characters, providing\n"
|
||||
"protocols or resolution services that start with a non-alphabetic character, or\n"
|
||||
"providing fields that are too long.\n";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
return off_nominal_test(test, records, ARRAY_LEN(records));
|
||||
}
|
||||
|
||||
AST_TEST_DEFINE(naptr_resolve_off_nominal_regexp)
|
||||
{
|
||||
struct naptr_record records[] = {
|
||||
/* Invalid delim-char */
|
||||
{ 100, 100, {1, "A"}, {4, "BLAH"}, {15, "1.*1horse.mane1"}, ""},
|
||||
/* Not enough delim-chars */
|
||||
{ 100, 100, {1, "A"}, {4, "BLAH"}, {14, "!.*!horse.mane"}, ""},
|
||||
/* Not enough delim-chars, part 2 */
|
||||
{ 100, 100, {1, "A"}, {4, "BLAH"}, {16, "!.*!horse.mane\\!"}, ""},
|
||||
/* Too many delim-chars */
|
||||
{ 100, 100, {1, "A"}, {4, "BLAH"}, {15, "!.*!horse!mane!"}, ""},
|
||||
/* Invalid regex flag */
|
||||
{ 100, 100, {1, "A"}, {4, "BLAH"}, {16, "!.*!horse.mane!o"}, ""},
|
||||
/* Invalid backreference */
|
||||
{ 100, 100, {1, "A"}, {4, "BLAH"}, {13, "!.*!horse.\\0!"}, ""},
|
||||
/* Invalid regex */
|
||||
{ 100, 100, {1, "A"}, {4, "BLAH"}, {16, "!(.*!horse.mane!"}, ""},
|
||||
};
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = "naptr_resolve_off_nominal_regexp";
|
||||
info->category = "/main/dns/naptr/";
|
||||
info->summary = "Ensure that NAPTR records with invalid regexps are not presented in results";
|
||||
info->description = "This test defines a set of records where the regexps provided are\n"
|
||||
"invalid in some way. The test ensures that none of the invalid records are returned\n"
|
||||
"when performing a NAPTR lookup\n";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
return off_nominal_test(test, records, ARRAY_LEN(records));
|
||||
}
|
||||
|
||||
AST_TEST_DEFINE(naptr_resolve_off_nominal_interactions)
|
||||
{
|
||||
struct naptr_record records[] = {
|
||||
/* Both regexp and replacement are specified */
|
||||
{ 100, 100, {1, "A"}, {4, "BLAH"}, {15, "!.*!horse.mane!"}, "goose.down"},
|
||||
/* XXX RFC 2915 says that a service MUST be present if terminal flags are
|
||||
* specified. However, RFCs 3401-3404 do not specify this behavior, so
|
||||
* I am not putting in a test for it
|
||||
*/
|
||||
};
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = "naptr_resolve_off_nominal_interactions";
|
||||
info->category = "/main/dns/naptr/";
|
||||
info->summary = "Ensure that NAPTR records with invalid interactions are not presented in results";
|
||||
info->description = "This test defines a set of records where all parts are individually valid,\n"
|
||||
"but when combined do not make sense and are thus invalid.\n";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
return off_nominal_test(test, records, ARRAY_LEN(records));
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
AST_TEST_UNREGISTER(naptr_resolve_nominal);
|
||||
AST_TEST_UNREGISTER(naptr_resolve_off_nominal_length);
|
||||
AST_TEST_UNREGISTER(naptr_resolve_off_nominal_flags);
|
||||
AST_TEST_UNREGISTER(naptr_resolve_off_nominal_services);
|
||||
AST_TEST_UNREGISTER(naptr_resolve_off_nominal_regexp);
|
||||
AST_TEST_UNREGISTER(naptr_resolve_off_nominal_interactions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
{
|
||||
AST_TEST_REGISTER(naptr_resolve_nominal);
|
||||
AST_TEST_REGISTER(naptr_resolve_off_nominal_length);
|
||||
AST_TEST_REGISTER(naptr_resolve_off_nominal_flags);
|
||||
AST_TEST_REGISTER(naptr_resolve_off_nominal_services);
|
||||
AST_TEST_REGISTER(naptr_resolve_off_nominal_regexp);
|
||||
AST_TEST_REGISTER(naptr_resolve_off_nominal_interactions);
|
||||
|
||||
return AST_MODULE_LOAD_SUCCESS;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "DNS API Tests");
|
Loading…
Reference in new issue