123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- /*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2015, Digium, Inc.
- *
- * Mark Michelson <mmichelson@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>
- ***/
- #include "asterisk.h"
- #include "asterisk/dns_core.h"
- #include "asterisk/dns_test.h"
- #include "asterisk/utils.h"
- #ifdef TEST_FRAMEWORK
- 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;
- size_t actual_len = strlen(string->val);
- 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 (actual_len) {
- memcpy(&buf[1], string->val, strlen(string->val));
- }
- return actual_len + 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;
- }
- #else /* TEST_FRAMEWORK */
- int ast_dns_test_write_string(const struct ast_dns_test_string *string, char *buf)
- {
- return 0;
- }
- int ast_dns_test_write_domain(const char *string, char *buf)
- {
- return 0;
- }
- 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)
- {
- return 0;
- }
- #endif
|