Asterisk - The Open Source Telephony Project GIT-master-f36a736
dns_test.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2015, Digium, Inc.
5 *
6 * Mark Michelson <mmichelson@digium.com>
7 *
8 * Includes code and algorithms from the Zapata library.
9 *
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.
15 *
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.
19 */
20
21/*** MODULEINFO
22 <support_level>core</support_level>
23 ***/
24
25#include "asterisk.h"
26#include "asterisk/dns_core.h"
27#include "asterisk/dns_test.h"
28#include "asterisk/utils.h"
29
30#ifdef TEST_FRAMEWORK
31
32const char DNS_HEADER[] = {
33 /* ID == 0 */
34 0x00, 0x00,
35 /* QR == 1, Opcode == 0, AA == 1, TC == 0, RD == 1 */
36 0x85,
37 /* RA == 1, Z == 0, RCODE == 0 */
38 0x80,
39 /* QDCOUNT == 1 */
40 0x00, 0x01,
41 /* ANCOUNT == 1 */
42 0x00, 0x00,
43 /* NSCOUNT == 0 */
44 0x00, 0x00,
45 /* ARCOUNT == 0 */
46 0x00, 0x00,
47};
48
49/*!
50 * \brief Generate a DNS header and write it to a buffer
51 *
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.
55 *
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.
59 *
60 * \param num_records The number of DNS records in this DNS response
61 * \param buf The buffer to write the header into
62 * \return The number of bytes written to the buffer
63 */
64static int generate_dns_header(unsigned short num_records, char *buf)
65{
66 unsigned short net_num_records = htons(num_records);
67
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));
71
72 return ARRAY_LEN(DNS_HEADER);
73}
74
75const char DNS_QUESTION [] = {
76 /* goose */
77 0x05, 0x67, 0x6f, 0x6f, 0x73, 0x65,
78 /* feathers */
79 0x08, 0x66, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x73,
80 /* end label */
81 0x00,
82 /* NAPTR type */
83 0x00, 0x23,
84 /* IN class */
85 0x00, 0x01,
86};
87
88/*!
89 * \brief Generate a DNS question and write it to a buffer
90 *
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.
94 *
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.
98 *
99 * \param buf The buffer to write the question into
100 * \return The number of bytes written to the buffer
101 */
102static int generate_dns_question(char *buf)
103{
104 memcpy(buf, DNS_QUESTION, ARRAY_LEN(DNS_QUESTION));
105 return ARRAY_LEN(DNS_QUESTION);
106}
107
108const char NAPTR_ANSWER [] = {
109 /* Domain points to name from question */
110 0xc0, 0x0c,
111 /* NAPTR type */
112 0x00, 0x23,
113 /* IN Class */
114 0x00, 0x01,
115 /* TTL (12345 by default) */
116 0x00, 0x00, 0x30, 0x39,
117};
118
119/*!
120 * \brief Generate a DNS answer and write it to a buffer
121 *
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
126 * is hard-coded.
127 *
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.
131 *
132 * \param ttl Time to live
133 * \param buf The buffer to write the answer into
134 * \return The number of bytes written to the buffer
135 */
136static int generate_dns_answer(int ttl, char *buf)
137{
138 int net_ttl = htonl(ttl);
139
140 memcpy(buf, NAPTR_ANSWER, ARRAY_LEN(NAPTR_ANSWER));
141 /* Overwrite TTL if one is provided */
142 if (ttl) {
143 memcpy(&buf[6], &net_ttl, sizeof(int));
144 }
145
146 return ARRAY_LEN(NAPTR_ANSWER);
147}
148
149int ast_dns_test_write_string(const struct ast_dns_test_string *string, char *buf)
150{
151 uint8_t len = string->len;
152 size_t actual_len = strlen(string->val);
153 buf[0] = len;
154 /*
155 * We use the actual length of the string instead of
156 * the stated value since sometimes we're going to lie about
157 * the length of the string
158 */
159 if (actual_len) {
160 memcpy(&buf[1], string->val, strlen(string->val));
161 }
162
163 return actual_len + 1;
164}
165
166int ast_dns_test_write_domain(const char *string, char *buf)
167{
168 char *copy = ast_strdupa(string);
169 char *part;
170 char *ptr = buf;
171 static const struct ast_dns_test_string null_label = {
172 .len = 0,
173 .val = "",
174 };
175
176 while (1) {
177 struct ast_dns_test_string dns_str;
178 part = strsep(&copy, ".");
179 if (ast_strlen_zero(part)) {
180 break;
181 }
182 dns_str.len = strlen(part);
183 dns_str.val = part;
184
185 ptr += ast_dns_test_write_string(&dns_str, ptr);
186 }
187 ptr += ast_dns_test_write_string(&null_label, ptr);
188
189 return ptr - buf;
190}
191
192int ast_dns_test_generate_result(struct ast_dns_query *query, void *records, size_t num_records,
193 size_t record_size, record_fn generate, char *buffer)
194{
195 char *ptr = buffer;
196 char *record_iter;
197
198 ptr += generate_dns_header(num_records, ptr);
199 ptr += generate_dns_question(ptr);
200
201 for (record_iter = records; record_iter < (char *) records + num_records * record_size; record_iter += record_size) {
202 unsigned short rdlength;
203 unsigned short net_rdlength;
204
205 /* XXX Do we even want to override TTL? */
206 ptr += generate_dns_answer(0, ptr);
207 rdlength = generate(record_iter, ptr + 2);
208 net_rdlength = htons(rdlength);
209 memcpy(ptr, &net_rdlength, 2);
210 ptr += 2;
211 ptr += rdlength;
212 }
213
214 return ptr - buffer;
215}
216
217#else /* TEST_FRAMEWORK */
218
219int ast_dns_test_write_string(const struct ast_dns_test_string *string, char *buf)
220{
221 return 0;
222}
223
224int ast_dns_test_write_domain(const char *string, char *buf)
225{
226 return 0;
227}
228
229int ast_dns_test_generate_result(struct ast_dns_query *query, void *records, size_t num_records,
230 size_t record_size, record_fn generate, char *buffer)
231{
232 return 0;
233}
234
235#endif
static int copy(char *infile, char *outfile)
Utility function to copy a file.
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
static int records
Definition: cdr_pgsql.c:78
Core DNS API.
int ast_dns_test_write_domain(const char *string, char *buf)
Write a DNS domain to a buffer.
Definition: dns_test.c:224
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)
Generate a full DNS response for the given DNS records.
Definition: dns_test.c:229
int ast_dns_test_write_string(const struct ast_dns_test_string *string, char *buf)
Write a DNS string to a buffer.
Definition: dns_test.c:219
int(* record_fn)(void *record, char *buf)
Callback to write specific DNS record to an answer.
Definition: dns_test.h:85
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * strsep(char **str, const char *delims)
const char * string
Definition: presencestate.c:71
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
A DNS query.
Definition: dns_internal.h:137
Representation of a string in DNS.
Definition: dns_test.h:33
Utility functions.
#define ARRAY_LEN(a)
Definition: utils.h:666