Author: mmichelson Date: Mon Apr 6 14:42:33 2015 New Revision: 434135 URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=434135 Log: Move common DNS test code to its own file.
Currently there is an issue where the test modules will not load properly because of an unresolved symbol. Added: team/group/dns/include/asterisk/dns_test.h (with props) team/group/dns/main/dns_test.c (with props) Modified: team/group/dns/tests/test_dns_srv.c Added: team/group/dns/include/asterisk/dns_test.h URL: http://svnview.digium.com/svn/asterisk/team/group/dns/include/asterisk/dns_test.h?view=auto&rev=434135 ============================================================================== --- team/group/dns/include/asterisk/dns_test.h (added) +++ team/group/dns/include/asterisk/dns_test.h Mon Apr 6 14:42:33 2015 @@ -1,0 +1,109 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2015, Digium, Inc. + * + * Mark Michelson <mmichel...@digium.com> + * + * Includes code and algorithms from the Zapata library. + * + * 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. + */ + +#ifndef DNS_TEST_H +#define DNS_TEST_H + +/*! + * \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. However, the + * string stored in this structure is expected to be NULL- + * terminated. + */ +struct ast_dns_test_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. Tests are expected to + * use a buffer that is sufficiently large for their 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 + */ +int ast_dns_test_write_string(const struct ast_dns_test_string *string, char *buf); + +/*! + * \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. Tests are expected to + * use a buffer that is sufficiently large for their 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 + */ +int ast_dns_test_write_domain(const char *string, char *buf); + +/*! + * \brief Callback to write specific DNS record to an answer + * + * When generating a DNS result, the type of DNS record being generated + * will need to be performed by individual test cases. This is a callback + * that tests can define to write a specific type of DNS record to the + * provided buffer. + * + * There is no buffer size passed to this function. Tests are expected to + * use a buffer that is sufficiently large for their tests. + * + * \param record Pointer to test-specific DNS record data + * \param buf The buffer into which to write the DNS record + * \return The number of bytes written to the buffer + */ +typedef int (*record_fn)(void *record, char *buf); + +/*! + * \brief Generate a full DNS response for the given DNS records. + * + * This function takes care of generating the DNS header, question, and + * answer sections of a DNS response. In order to place test-specific + * record data into the DNS answers, a callback is provided as a parameter + * to this function so that the necessary records can be encoded properly + * by the tests. + * + * There is no buffer size passed to this function. Tests are expected to + * use a buffer that is sufficiently large for their tests. + * + * \param query The DNS query that is being processed + * \param records An array of test-specific representations of DNS records + * \param num_records The number of elements in the records array + * \param record_size The size of each element in the records array + * \param generate The test-specific encoder for DNS records + * \param buffer The buffer into which to write the DNS response + */ +int ast_dns_test_generate_result(struct ast_dns_query *query, void *records, size_t num_records, + size_t record_size, record_fn generate, char *buffer); + +#endif /* DNS_TEST_H */ Propchange: team/group/dns/include/asterisk/dns_test.h ------------------------------------------------------------------------------ svn:eol-style = native Propchange: team/group/dns/include/asterisk/dns_test.h ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Propchange: team/group/dns/include/asterisk/dns_test.h ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: team/group/dns/main/dns_test.c URL: http://svnview.digium.com/svn/asterisk/team/group/dns/main/dns_test.c?view=auto&rev=434135 ============================================================================== --- team/group/dns/main/dns_test.c (added) +++ team/group/dns/main/dns_test.c Mon Apr 6 14:42:33 2015 @@ -1,0 +1,246 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2015, Digium, Inc. + * + * Mark Michelson <mmichel...@digium.com> + * + * Includes code and algorithms from the Zapata library. + * + * 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 + <support_level>core</support_level> + ***/ + +#ifdef TEST_FRAMEWORK + +#include "asterisk.h" +#include "asterisk/dns_core.h" +#include "asterisk/dns_test.h" +#include "asterisk/utils.h" + +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 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 + */ +int ast_dns_test_write_string(const struct ast_dns_test_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 + */ +int ast_dns_test_write_domain(const char *string, char *buf) +{ + char *copy = ast_strdupa(string); + char *part; + char *ptr = buf; + static const struct ast_dns_test_string null_label = { + .len = 0, + .val = "", + }; + + while (1) { + struct ast_dns_test_string dns_str; + part = strsep(©, "."); + if (ast_strlen_zero(part)) { + break; + } + dns_str.len = strlen(part); + dns_str.val = part; + + ptr += ast_dns_test_write_string(&dns_str, ptr); + } + ptr += ast_dns_test_write_string(&null_label, ptr); + + return ptr - buf; +} + +int ast_dns_test_generate_result(struct ast_dns_query *query, void *records, size_t num_records, + size_t record_size, record_fn generate, char *buffer) +{ + char *ptr = buffer; + char *record_iter; + + ptr += generate_dns_header(num_records, ptr); + ptr += generate_dns_question(ptr); + + for (record_iter = records; record_iter < (char *) records + num_records * record_size; record_iter += record_size) { + unsigned short rdlength; + unsigned short net_rdlength; + + /* XXX Do we even want to override TTL? */ + ptr += generate_dns_answer(0, ptr); + rdlength = generate(record_iter, ptr + 2); + net_rdlength = htons(rdlength); + memcpy(ptr, &net_rdlength, 2); + ptr += 2; + ptr += rdlength; + } + + return ptr - buffer; +} + +#endif /* TEST_FRAMEWORK */ Propchange: team/group/dns/main/dns_test.c ------------------------------------------------------------------------------ svn:eol-style = native Propchange: team/group/dns/main/dns_test.c ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Propchange: team/group/dns/main/dns_test.c ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: team/group/dns/tests/test_dns_srv.c URL: http://svnview.digium.com/svn/asterisk/team/group/dns/tests/test_dns_srv.c?view=diff&rev=434135&r1=434134&r2=434135 ============================================================================== --- team/group/dns/tests/test_dns_srv.c (original) +++ team/group/dns/tests/test_dns_srv.c Mon Apr 6 14:42:33 2015 @@ -31,104 +31,7 @@ #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(©, "."))) { - ptr += write_dns_string(part, ptr); - } - ptr += write_dns_string("", ptr); - - return ptr - buf; -} +#include "asterisk/dns_test.h" struct srv_record { uint16_t priority; @@ -141,8 +44,9 @@ unsigned int ignore_host; }; -static int generate_srv_record(struct srv_record *record, char *buf) -{ +static int generate_srv_record(void *dns_record, char *buf) +{ + struct srv_record *record = dns_record; uint16_t priority = htons(record->priority); uint16_t weight = htons(record->weight); uint16_t port = htons(record->port); @@ -164,7 +68,7 @@ } if (!record->ignore_host) { - ptr += write_dns_domain(record->host, ptr); + ptr += ast_dns_test_write_domain(record->host, ptr); } return ptr - buf; @@ -178,31 +82,19 @@ { 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); + int ans_size; + + ans_size = ast_dns_test_generate_result(query, test_records, num_test_records, + sizeof(struct srv_record), generate_srv_record, ans_buffer); + + ast_dns_resolver_set_result(query, 0, 0, ns_r_noerror, "goose.feathers", ans_buffer, ans_size); 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); + int srv_size; + + srv_size = generate_srv_record(&test_records[i], record); + ast_dns_resolver_add_record(query, ns_t_srv, ns_c_in, 12345, record, srv_size); } ast_dns_resolver_completed(query); -- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- svn-commits mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/svn-commits