dns_test.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2015, Digium, Inc.
00005  *
00006  * Mark Michelson <mmichelson@digium.com>
00007  *
00008  * Includes code and algorithms from the Zapata library.
00009  *
00010  * See http://www.asterisk.org for more information about
00011  * the Asterisk project. Please do not directly contact
00012  * any of the maintainers of this project for assistance;
00013  * the project provides a web site, mailing lists and IRC
00014  * channels for your use.
00015  *
00016  * This program is free software, distributed under the terms of
00017  * the GNU General Public License Version 2. See the LICENSE file
00018  * at the top of the source tree.
00019  */
00020 
00021 /*** MODULEINFO
00022    <support_level>core</support_level>
00023  ***/
00024 
00025 #include "asterisk.h"
00026 #include "asterisk/dns_core.h"
00027 #include "asterisk/dns_test.h"
00028 #include "asterisk/utils.h"
00029 
00030 #ifdef TEST_FRAMEWORK
00031 
00032 const char DNS_HEADER[] = {
00033    /* ID  == 0 */
00034    0x00, 0x00,
00035    /* QR == 1, Opcode == 0, AA == 1, TC == 0, RD == 1 */
00036    0x85,
00037    /* RA == 1, Z == 0, RCODE == 0 */
00038    0x80,
00039    /* QDCOUNT == 1 */
00040    0x00, 0x01,
00041    /* ANCOUNT == 1 */
00042    0x00, 0x00,
00043    /* NSCOUNT == 0 */
00044    0x00, 0x00,
00045    /* ARCOUNT == 0 */
00046    0x00, 0x00,
00047 };
00048 
00049 /*!
00050  * \brief Generate a DNS header and write it to a buffer
00051  *
00052  * The DNS header is the first part of a DNS request or response. In our
00053  * case, the only part of the header that a test can affect is the number
00054  * of answers. The rest of the DNS header is based on hard-coded values.
00055  *
00056  * There is no buffer size passed to this function since we provide
00057  * the data ourselves and have sized the buffer to be way larger
00058  * than necessary for the tests.
00059  *
00060  * \param num_records The number of DNS records in this DNS response
00061  * \param buf The buffer to write the header into
00062  * \retval The number of bytes written to the buffer
00063  */
00064 static int generate_dns_header(unsigned short num_records, char *buf)
00065 {
00066    unsigned short net_num_records = htons(num_records);
00067 
00068    memcpy(buf, DNS_HEADER, ARRAY_LEN(DNS_HEADER));
00069    /* Overwrite the ANCOUNT with the actual number of answers */
00070    memcpy(&buf[6], &net_num_records, sizeof(num_records));
00071 
00072    return ARRAY_LEN(DNS_HEADER);
00073 }
00074 
00075 const char DNS_QUESTION [] = {
00076    /* goose */
00077    0x05, 0x67, 0x6f, 0x6f, 0x73, 0x65,
00078    /* feathers */
00079    0x08, 0x66, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x73,
00080    /* end label */
00081    0x00,
00082    /* NAPTR type */
00083    0x00, 0x23,
00084    /* IN class */
00085    0x00, 0x01,
00086 };
00087 
00088 /*!
00089  * \brief Generate a DNS question and write it to a buffer
00090  *
00091  * The DNS question is the second part of a DNS request or response.
00092  * All DNS questions in this file are for the same domain and thus
00093  * the DNS question is a hard-coded value.
00094  *
00095  * There is no buffer size passed to this function since we provide
00096  * the data ourselves and have sized the buffer to be way larger
00097  * than necessary for the tests.
00098  *
00099  * \param buf The buffer to write the question into
00100  * \retval The number of bytes written to the buffer
00101  */
00102 static int generate_dns_question(char *buf)
00103 {
00104    memcpy(buf, DNS_QUESTION, ARRAY_LEN(DNS_QUESTION));
00105    return ARRAY_LEN(DNS_QUESTION);
00106 }
00107 
00108 const char NAPTR_ANSWER [] = {
00109    /* Domain points to name from question */
00110    0xc0, 0x0c,
00111    /* NAPTR type */
00112    0x00, 0x23,
00113    /* IN Class */
00114    0x00, 0x01,
00115    /* TTL (12345 by default) */
00116    0x00, 0x00, 0x30, 0x39,
00117 };
00118 
00119 /*!
00120  * \brief Generate a DNS answer and write it to a buffer
00121  *
00122  * The DNS answer is the third (and in our case final) part of a
00123  * DNS response. The DNS answer generated here is only partial.
00124  * The record-specific data is generated by a separate function.
00125  * DNS answers in our tests may have variable TTLs, but the rest
00126  * is hard-coded.
00127  *
00128  * There is no buffer size passed to this function since we provide
00129  * the data ourselves and have sized the buffer to be way larger
00130  * than necessary for the tests.
00131  *
00132  * \param buf The buffer to write the answer into
00133  * \retval The number of bytes written to the buffer
00134  */
00135 static int generate_dns_answer(int ttl, char *buf)
00136 {
00137    int net_ttl = htonl(ttl);
00138 
00139    memcpy(buf, NAPTR_ANSWER, ARRAY_LEN(NAPTR_ANSWER));
00140    /* Overwrite TTL if one is provided */
00141    if (ttl) {
00142       memcpy(&buf[6], &net_ttl, sizeof(int));
00143    }
00144 
00145    return ARRAY_LEN(NAPTR_ANSWER);
00146 }
00147 
00148 /*!
00149  * \brief Write a DNS string to a buffer
00150  *
00151  * This writes the DNS string to the buffer and returns the total
00152  * number of bytes written to the buffer.
00153  *
00154  * There is no buffer size passed to this function since we provide
00155  * the data ourselves and have sized the buffer to be way larger
00156  * than necessary for the tests.
00157  *
00158  * \param string The string to write
00159  * \param buf The buffer to write the string into
00160  * \return The number of bytes written to the buffer
00161  */
00162 int ast_dns_test_write_string(const struct ast_dns_test_string *string, char *buf)
00163 {
00164    uint8_t len = string->len;
00165    size_t actual_len = strlen(string->val);
00166    buf[0] = len;
00167    /*
00168     * We use the actual length of the string instead of
00169     * the stated value since sometimes we're going to lie about
00170     * the length of the string
00171     */
00172    if (actual_len) {
00173       memcpy(&buf[1], string->val, strlen(string->val));
00174    }
00175 
00176    return actual_len + 1;
00177 }
00178 
00179 /*!
00180  * \brief Write a DNS domain to a buffer
00181  *
00182  * A DNS domain consists of a series of labels separated
00183  * by dots. Each of these labels gets written as a DNS
00184  * string. A DNS domain ends with a NULL label, which is
00185  * essentially a zero-length DNS string.
00186  *
00187  *
00188  * There is no buffer size passed to this function since we provide
00189  * the data ourselves and have sized the buffer to be way larger
00190  * than necessary for the tests.
00191  *
00192  * \param string The DNS domain to write
00193  * \param buf The buffer to write the domain into
00194  * \return The number of bytes written to the buffer
00195  */
00196 int ast_dns_test_write_domain(const char *string, char *buf)
00197 {
00198    char *copy = ast_strdupa(string);
00199    char *part;
00200    char *ptr = buf;
00201    static const struct ast_dns_test_string null_label = {
00202       .len = 0,
00203       .val = "",
00204    };
00205 
00206    while (1) {
00207       struct ast_dns_test_string dns_str;
00208       part = strsep(&copy, ".");
00209       if (ast_strlen_zero(part)) {
00210          break;
00211       }
00212       dns_str.len = strlen(part);
00213       dns_str.val = part;
00214 
00215       ptr += ast_dns_test_write_string(&dns_str, ptr);
00216    }
00217    ptr += ast_dns_test_write_string(&null_label, ptr);
00218 
00219    return ptr - buf;
00220 }
00221 
00222 int ast_dns_test_generate_result(struct ast_dns_query *query, void *records, size_t num_records,
00223       size_t record_size, record_fn generate, char *buffer)
00224 {
00225    char *ptr = buffer;
00226    char *record_iter;
00227 
00228    ptr += generate_dns_header(num_records, ptr);
00229    ptr += generate_dns_question(ptr);
00230 
00231    for (record_iter = records; record_iter < (char *) records + num_records * record_size; record_iter += record_size) {
00232       unsigned short rdlength;
00233       unsigned short net_rdlength;
00234 
00235       /* XXX Do we even want to override TTL? */
00236       ptr += generate_dns_answer(0, ptr);
00237       rdlength = generate(record_iter, ptr + 2);
00238       net_rdlength = htons(rdlength);
00239       memcpy(ptr, &net_rdlength, 2);
00240       ptr += 2;
00241       ptr += rdlength;
00242    }
00243 
00244    return ptr - buffer;
00245 }
00246 
00247 #else /* TEST_FRAMEWORK */
00248 
00249 int ast_dns_test_write_string(const struct ast_dns_test_string *string, char *buf)
00250 {
00251    return 0;
00252 }
00253 
00254 int ast_dns_test_write_domain(const char *string, char *buf)
00255 {
00256    return 0;
00257 }
00258 
00259 int ast_dns_test_generate_result(struct ast_dns_query *query, void *records, size_t num_records,
00260       size_t record_size, record_fn generate, char *buffer)
00261 {
00262    return 0;
00263 }
00264 
00265 #endif

Generated on Thu Apr 16 06:27:33 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6