2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2015, Digium, Inc.
6 * Mark Michelson <mmichelson@digium.com>
8 * Includes code and algorithms from the Zapata library.
10 * See http://www.asterisk.org for more information about
11 * the Asterisk project. Please do not directly contact
12 * any of the maintainers of this project for assistance;
13 * the project provides a web site, mailing lists and IRC
14 * channels for your use.
16 * This program is free software, distributed under the terms of
17 * the GNU General Public License Version 2. See the LICENSE file
18 * at the top of the source tree.
22 <support_level>core</support_level>
26 #include "asterisk/dns_core.h"
27 #include "asterisk/dns_test.h"
28 #include "asterisk/utils.h"
32 const char DNS_HEADER[] = {
35 /* QR == 1, Opcode == 0, AA == 1, TC == 0, RD == 1 */
37 /* RA == 1, Z == 0, RCODE == 0 */
50 * \brief Generate a DNS header and write it to a buffer
52 * The DNS header is the first part of a DNS request or response. In our
53 * case, the only part of the header that a test can affect is the number
54 * of answers. The rest of the DNS header is based on hard-coded values.
56 * There is no buffer size passed to this function since we provide
57 * the data ourselves and have sized the buffer to be way larger
58 * than necessary for the tests.
60 * \param num_records The number of DNS records in this DNS response
61 * \param buf The buffer to write the header into
62 * \retval The number of bytes written to the buffer
64 static int generate_dns_header(unsigned short num_records, char *buf)
66 unsigned short net_num_records = htons(num_records);
68 memcpy(buf, DNS_HEADER, ARRAY_LEN(DNS_HEADER));
69 /* Overwrite the ANCOUNT with the actual number of answers */
70 memcpy(&buf[6], &net_num_records, sizeof(num_records));
72 return ARRAY_LEN(DNS_HEADER);
75 const char DNS_QUESTION [] = {
77 0x05, 0x67, 0x6f, 0x6f, 0x73, 0x65,
79 0x08, 0x66, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x73,
89 * \brief Generate a DNS question and write it to a buffer
91 * The DNS question is the second part of a DNS request or response.
92 * All DNS questions in this file are for the same domain and thus
93 * the DNS question is a hard-coded value.
95 * There is no buffer size passed to this function since we provide
96 * the data ourselves and have sized the buffer to be way larger
97 * than necessary for the tests.
99 * \param buf The buffer to write the question into
100 * \retval The number of bytes written to the buffer
102 static int generate_dns_question(char *buf)
104 memcpy(buf, DNS_QUESTION, ARRAY_LEN(DNS_QUESTION));
105 return ARRAY_LEN(DNS_QUESTION);
108 const char NAPTR_ANSWER [] = {
109 /* Domain points to name from question */
115 /* TTL (12345 by default) */
116 0x00, 0x00, 0x30, 0x39,
120 * \brief Generate a DNS answer and write it to a buffer
122 * The DNS answer is the third (and in our case final) part of a
123 * DNS response. The DNS answer generated here is only partial.
124 * The record-specific data is generated by a separate function.
125 * DNS answers in our tests may have variable TTLs, but the rest
128 * There is no buffer size passed to this function since we provide
129 * the data ourselves and have sized the buffer to be way larger
130 * than necessary for the tests.
132 * \param buf The buffer to write the answer into
133 * \retval The number of bytes written to the buffer
135 static int generate_dns_answer(int ttl, char *buf)
137 int net_ttl = htonl(ttl);
139 memcpy(buf, NAPTR_ANSWER, ARRAY_LEN(NAPTR_ANSWER));
140 /* Overwrite TTL if one is provided */
142 memcpy(&buf[6], &net_ttl, sizeof(int));
145 return ARRAY_LEN(NAPTR_ANSWER);
149 * \brief Write a DNS string to a buffer
151 * This writes the DNS string to the buffer and returns the total
152 * number of bytes written to the buffer.
154 * There is no buffer size passed to this function since we provide
155 * the data ourselves and have sized the buffer to be way larger
156 * than necessary for the tests.
158 * \param string The string to write
159 * \param buf The buffer to write the string into
160 * \return The number of bytes written to the buffer
162 int ast_dns_test_write_string(const struct ast_dns_test_string *string, char *buf)
164 uint8_t len = string->len;
165 size_t actual_len = strlen(string->val);
168 * We use the actual length of the string instead of
169 * the stated value since sometimes we're going to lie about
170 * the length of the string
173 memcpy(&buf[1], string->val, strlen(string->val));
176 return actual_len + 1;
180 * \brief Write a DNS domain to a buffer
182 * A DNS domain consists of a series of labels separated
183 * by dots. Each of these labels gets written as a DNS
184 * string. A DNS domain ends with a NULL label, which is
185 * essentially a zero-length DNS string.
188 * There is no buffer size passed to this function since we provide
189 * the data ourselves and have sized the buffer to be way larger
190 * than necessary for the tests.
192 * \param string The DNS domain to write
193 * \param buf The buffer to write the domain into
194 * \return The number of bytes written to the buffer
196 int ast_dns_test_write_domain(const char *string, char *buf)
198 char *copy = ast_strdupa(string);
201 static const struct ast_dns_test_string null_label = {
207 struct ast_dns_test_string dns_str;
208 part = strsep(©, ".");
209 if (ast_strlen_zero(part)) {
212 dns_str.len = strlen(part);
215 ptr += ast_dns_test_write_string(&dns_str, ptr);
217 ptr += ast_dns_test_write_string(&null_label, ptr);
222 int ast_dns_test_generate_result(struct ast_dns_query *query, void *records, size_t num_records,
223 size_t record_size, record_fn generate, char *buffer)
228 ptr += generate_dns_header(num_records, ptr);
229 ptr += generate_dns_question(ptr);
231 for (record_iter = records; record_iter < (char *) records + num_records * record_size; record_iter += record_size) {
232 unsigned short rdlength;
233 unsigned short net_rdlength;
235 /* XXX Do we even want to override TTL? */
236 ptr += generate_dns_answer(0, ptr);
237 rdlength = generate(record_iter, ptr + 2);
238 net_rdlength = htons(rdlength);
239 memcpy(ptr, &net_rdlength, 2);
247 #else /* TEST_FRAMEWORK */
249 int ast_dns_test_write_string(struct ast_dns_test_string *string, char *buf)
254 int ast_dns_test_write_domain(const char *string, char *buf)
259 int ast_dns_test_generate_result(struct ast_dns_query *query, void *records, size_t num_records,
260 size_t record_size, record_fn generate, char *buffer)