1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <inttypes.h>
5 #include <ctype.h>
6
7 #include "test-common.h"
8
9 #include <libmy/ubuf.h>
10 #include <wdns.h>
11
12 #define NAME "test-rdata_to_str"
13
14 struct test {
15 const void *input;
16 size_t input_len;
17 uint16_t rrtype;
18 uint16_t rrclass;
19 const char *expected;
20 };
21
22 struct test tdata[] = {
23 { "\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xde\xad\xbe\xef", 17, WDNS_TYPE_A6, WDNS_CLASS_IN, "0 2000::dead:beef" },
24 { "\x01\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xde\xad\xbe\xef\x03""fsi\x02io\x00", 25, WDNS_TYPE_A6, WDNS_CLASS_IN, "1 2000::dead:beef fsi.io." },
25 { "\x80\x03""fsi\x02io\x00", 9, WDNS_TYPE_A6, WDNS_CLASS_IN, "128 fsi.io." },
26 { "\x80", 1, WDNS_TYPE_A6, WDNS_CLASS_IN, "128" },
27
28 {
29 .input = "\x00\x0a" "\x00\x01" "ftp://ftp1.example.com/public",
30 .input_len = 2 + 2 + 29,
31 .rrtype = WDNS_TYPE_URI,
32 .rrclass = WDNS_CLASS_IN,
33 .expected = "10 1 \"ftp://ftp1.example.com/public\"",
34 },
35
36 {
37 .input = "\x00\x0a" "\x00\x01"
38 "https://www.isc.org/HolyCowThisSureIsAVeryLongURIRecordIDontEvenKnowWhatSomeoneWouldEverWantWithSuchAThingButTheSpecificationRequiresThatWesupportItSoHereWeGoTestingItLaLaLaLaLaLaLaSeriouslyThoughWhyWouldYouEvenConsiderUsingAURIThisLongItSeemsLikeASillyIdeaButEnhWhatAreYouGonnaDo/",
39 .input_len = 2 + 2 + 281,
40 .rrtype = WDNS_TYPE_URI,
41 .rrclass = WDNS_CLASS_IN,
42 .expected = "10 1 " "\"" "https://www.isc.org/HolyCowThisSureIsAVeryLongURIRecordIDontEvenKnowWhatSomeoneWouldEverWantWithSuchAThingButTheSpecificationRequiresThatWesupportItSoHereWeGoTestingItLaLaLaLaLaLaLaSeriouslyThoughWhyWouldYouEvenConsiderUsingAURIThisLongItSeemsLikeASillyIdeaButEnhWhatAreYouGonnaDo/" "\"",
43 },
44
45 {
46 .input = "\x04" "some" "\x04" "text",
47 .input_len = 1 + 4 + 1 + 4,
48 .rrtype = WDNS_TYPE_TXT,
49 .rrclass = WDNS_CLASS_IN,
50 .expected = "\"some\" \"text\"",
51 },
52
53 /* TXT test for: a string beginning with a " and ending with a " */
54 {
55 .input = "\x08" "\x22" "quoted" "\x22",
56 .input_len = 1 + 1 + 6 + 1,
57 .rrtype = WDNS_TYPE_TXT,
58 .rrclass = WDNS_CLASS_IN,
59 .expected = "\"\\\"quoted\\\"\"",
60 },
61
62 /* TXT test for: one quote sent over the wire */
63 {
64 .input = "\x03" "one" "\x05" "quote" "\x01" "\"" "\x04" "sent" "\x04" "over" "\x03" "the" "\x04" "wire",
65 .input_len = 1 + 3 + 1 + 5 + 1 + 1 + 1 + 4 + 1 + 4 + 1 + 3 + 1 + 4,
66 .rrtype = WDNS_TYPE_TXT,
67 .rrclass = WDNS_CLASS_IN,
68 .expected = "\"one\" \"quote\" \"\\\"\" \"sent\" \"over\" \"the\" \"wire\"",
69 },
70
71 /* TXT test for: 256 characters in length (including the length
72 octet) */
73 {
74 .input = "\xff" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
75 .input_len = 1 + 255,
76 .rrtype = WDNS_TYPE_TXT,
77 .rrclass = WDNS_CLASS_IN,
78 .expected = "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"",
79 },
80
81 /* TXT test for: single character string with multiple spaces */
82 {
83 .input = "\x19" "one string multiple words",
84 .input_len = 1 + 25,
85 .rrtype = WDNS_TYPE_TXT,
86 .rrclass = WDNS_CLASS_IN,
87 .expected = "\"one string multiple words\"",
88 },
89
90 /* TXT test for: multiple character strings with spaces */
91 {
92 .input = "\x10" "multiple strings" "\x02" "of" "\x0e" "multiple words",
93 .input_len = 1 + 16 + 1 + 2 + 1+ 14,
94 .rrtype = WDNS_TYPE_TXT,
95 .rrclass = WDNS_CLASS_IN,
96 .expected = "\"multiple strings\" \"of\" \"multiple words\"",
97 },
98
99 /* TXT test for: multiple long character strings */
100 {
101 .input = "\xff" "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" "\xff" "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" "\xff" "ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
102 .input_len = 1 + 255 + 1 + 255 + 1 + 255,
103 .rrtype = WDNS_TYPE_TXT,
104 .rrclass = WDNS_CLASS_IN,
105 .expected = "\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\" \"ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\" \"ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\"",
106 },
107
108 /* TXT test for: real world example of DKIM use.
109 The total length was 411 charcters broke up into
110 multiple character-strings. */
111 {
112 .input = "\xfe" "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2UMfREvlgajdSp3jv1tJ9nLpi/mRYnGyKC3inEQ9a7zqUjLq/yXukgpXs9AEHlvBvioxlgAVCPQQsuc1xp9+KXQGgJ8jTsn5OtKm8u+YBCt6OfvpeCpvt0l9JXMMHBNYV4c0XiPE5RHX2ltI0Av20CfEy+vMecpFtVDg4rMngjLws/ro6qT63S20A4zyVs/V" "\x9c" "19WW5F2Lulgv+l+EJzz9XummIJHOlU5n5ChcWU3Rw5RVGTtNjTZnFUaNXly3fW0ahKcG5Qc3e0Rhztp57JJQTl3OmHiMR5cHsCnrl1VnBi3kaOoQBYsSuBm+KRhMIw/X9wkLY67VLdkrwlX3xxsp6wIDAQAB",
113 .input_len = 1 + 254 + 1 + 156,
114 .rrtype = WDNS_TYPE_TXT,
115 .rrclass = WDNS_CLASS_IN,
116 /* NOTE: the semicolons are not escaped as they would be with dig output */
117 .expected = "\"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2UMfREvlgajdSp3jv1tJ9nLpi/mRYnGyKC3inEQ9a7zqUjLq/yXukgpXs9AEHlvBvioxlgAVCPQQsuc1xp9+KXQGgJ8jTsn5OtKm8u+YBCt6OfvpeCpvt0l9JXMMHBNYV4c0XiPE5RHX2ltI0Av20CfEy+vMecpFtVDg4rMngjLws/ro6qT63S20A4zyVs/V\" \"19WW5F2Lulgv+l+EJzz9XummIJHOlU5n5ChcWU3Rw5RVGTtNjTZnFUaNXly3fW0ahKcG5Qc3e0Rhztp57JJQTl3OmHiMR5cHsCnrl1VnBi3kaOoQBYsSuBm+KRhMIw/X9wkLY67VLdkrwlX3xxsp6wIDAQAB\"",
118 },
119
120 /* TXT test from RFC 7208 section 3.3:
121 concatenated together without adding spaces. */
122 {
123 .input = "\x11" "v=spf1 .... first" "\x10" "second string...",
124 .input_len = 1 + 17 + 1 + 16,
125 .rrtype = WDNS_TYPE_TXT,
126 .rrclass = WDNS_CLASS_IN,
127 .expected = "\"v=spf1 .... first\" \"second string...\"",
128 },
129
130 /* SPF test using real world example, all as one string */
131 {
132 .input = "\x63" "v=spf1 a mx ip4:204.152.184.0/21 ip4:149.20.0.0/16 ip6:2001:04F8::0/32 ip6:2001:500:60::65/128 ~all",
133 .input_len = 1 + 99,
134 .rrtype = WDNS_TYPE_SPF,
135 .rrclass = WDNS_CLASS_IN,
136 .expected = "\"v=spf1 a mx ip4:204.152.184.0/21 ip4:149.20.0.0/16 ip6:2001:04F8::0/32 ip6:2001:500:60::65/128 ~all\"",
137 },
138
139 {
140 .input =
141 "\x1a" "Please stop asking for ANY"
142 "\x1f" "See draft-ietf-dnsop-refuse-any"
143 ,
144 .input_len = 1 + 0x1a + 1 + 0x1f,
145 .rrtype = WDNS_TYPE_HINFO,
146 .rrclass = WDNS_CLASS_IN,
147 .expected = "\"Please stop asking for ANY\" \"See draft-ietf-dnsop-refuse-any\"",
148 },
149
150 {
151 .input =
152 "\x00\x00\x00\x42"
153 "\x00\x03"
154 "\x00\x04\x60\x00\x00\x08"
155 ,
156 .input_len = 4 + 2 + 6,
157 .rrtype = WDNS_TYPE_CSYNC,
158 .rrclass = WDNS_CLASS_IN,
159 .expected = "66 3 A NS AAAA",
160 },
161
162 {
163 .input = "\xAB\xCD\xEF\x01\x02\x03",
164 .input_len = 6,
165 .rrtype = WDNS_TYPE_EUI48,
166 .rrclass = WDNS_CLASS_IN,
167 .expected = "ab-cd-ef-01-02-03",
168 },
169
170 {
171 .input = "\xAB\xCD\xEF\x01\x02\x03\x04\x05",
172 .input_len = 8,
173 .rrtype = WDNS_TYPE_EUI64,
174 .rrclass = WDNS_CLASS_IN,
175 .expected = "ab-cd-ef-01-02-03-04-05",
176 },
177
178 {
179 .input = "\x01\x02\x03\x04\x05\x06\x07\x08",
180 .input_len = 8,
181 .rrtype = WDNS_TYPE_OPENPGPKEY,
182 .rrclass = WDNS_CLASS_IN,
183 .expected = "AQIDBAUGBwg=",
184 },
185
186 {
187 .input =
188 "\x01\x00" "\x03" "\x05"
189 "\x01\x03\xd2\x2a\x6c\xa7\x7f\x35\xb8\x93\x20\x6f\xd3\x5e\x4c\x50"
190 "\x6d\x83\x78\x84\x37\x09\xb9\x7e\x04\x16\x47\xe1\xbf\xf4\x3d\x8d"
191 "\x64\xc6\x49\xaf\x1e\x37\x19\x73\xc9\xe8\x91\xfc\xe3\xdf\x51\x9a"
192 "\x8c\x84\x0a\x63\xee\x42\xa6\xd2\xeb\xdd\xbb\x97\x03\x5d\x21\x5a"
193 "\xa4\xe4\x17\xb1\xfa\x45\xfa\x11\xa9\x74\x1e\xa2\x09\x8c\x1d\xfa"
194 "\x5f\xb5\xfe\xb3\x32\xfd\x4b\xc8\x15\x20\x89\xae\xf3\x6b\xa6\x44"
195 "\xcc\xe2\x41\x3b\x3b\x72\xbe\x18\xcb\xef\x8d\xa2\x53\xf4\xe9\x3d"
196 "\x21\x03\x86\x6d\x92\x34\xa2\xe2\x8d\xf5\x29\xa6\x7d\x54\x68\xdb"
197 "\xef\xe3",
198 .input_len = 2 + 1 + 1 + 130,
199 .rrtype = WDNS_TYPE_CDNSKEY,
200 .rrclass = WDNS_CLASS_IN,
201 .expected =
202 "256 3 5 "
203 "AQPSKmynfzW4kyBv015MUG2DeIQ3Cbl+BBZH4b/0PY1kxkmvHjcZc8no "
204 "kfzj31GajIQKY+5CptLr3buXA10hWqTkF7H6RfoRqXQeogmMHfpftf6z "
205 "Mv1LyBUgia7za6ZEzOJBOztyvhjL742iU/TpPSEDhm2SNKLijfUppn1U "
206 "aNvv4w==",
207 },
208
209 {
210 .input =
211 "\x01\x00" "\x03" "\x05"
212 "\x01\x03\xd2\x2a\x6c\xa7\x7f\x35\xb8\x93\x20\x6f\xd3\x5e\x4c\x50"
213 "\x6d\x83\x78\x84\x37\x09\xb9\x7e\x04\x16\x47\xe1\xbf\xf4\x3d\x8d"
214 "\x64\xc6\x49\xaf\x1e\x37\x19\x73\xc9\xe8\x91\xfc\xe3\xdf\x51\x9a"
215 "\x8c\x84\x0a\x63\xee\x42\xa6\xd2\xeb\xdd\xbb\x97\x03\x5d\x21\x5a"
216 "\xa4\xe4\x17\xb1\xfa\x45\xfa\x11\xa9\x74\x1e\xa2\x09\x8c\x1d\xfa"
217 "\x5f\xb5\xfe\xb3\x32\xfd\x4b\xc8\x15\x20\x89\xae\xf3\x6b\xa6\x44"
218 "\xcc\xe2\x41\x3b\x3b\x72\xbe\x18\xcb\xef\x8d\xa2\x53\xf4\xe9\x3d"
219 "\x21\x03\x86\x6d\x92\x34\xa2\xe2\x8d\xf5\x29\xa6\x7d\x54\x68\xdb"
220 "\xef\xe3",
221 .input_len = 2 + 1 + 1 + 130,
222 .rrtype = WDNS_TYPE_DNSKEY,
223 .rrclass = WDNS_CLASS_IN,
224 .expected =
225 "256 3 5 "
226 "AQPSKmynfzW4kyBv015MUG2DeIQ3Cbl+BBZH4b/0PY1kxkmvHjcZc8no "
227 "kfzj31GajIQKY+5CptLr3buXA10hWqTkF7H6RfoRqXQeogmMHfpftf6z "
228 "Mv1LyBUgia7za6ZEzOJBOztyvhjL742iU/TpPSEDhm2SNKLijfUppn1U "
229 "aNvv4w==",
230 },
231
232 {
233 .input =
234 "\xec\x45" "\x05" "\x01"
235 "\x2b\xb1\x83\xaf\x5f\x22\x58\x81\x79\xa5\x3b\x0a\x98\x63\x1f\xad\x1a\x29\x21\x18",
236 .input_len = 2 + 1 + 1 + 20,
237 .rrtype = WDNS_TYPE_DS,
238 .rrclass = WDNS_CLASS_IN,
239 .expected = "60485 5 1 2BB183AF5F22588179A53B0A98631FAD1A292118",
240 },
241
242 {
243 .input =
244 "\xec\x45" "\x05" "\x01"
245 "\x2b\xb1\x83\xaf\x5f\x22\x58\x81\x79\xa5\x3b\x0a\x98\x63\x1f\xad\x1a\x29\x21\x18",
246 .input_len = 2 + 1 + 1 + 20,
247 .rrtype = WDNS_TYPE_CDS,
248 .rrclass = WDNS_CLASS_IN,
249 .expected = "60485 5 1 2BB183AF5F22588179A53B0A98631FAD1A292118",
250 },
251
252 {
253 .input =
254 "\x00" "\x00" "\x01"
255 "\xd2\xab\xde\x24\x0d\x7c\xd3\xee\x6b\x4b\x28\xc5\x4d\xf0\x34\xb9"
256 "\x79\x83\xa1\xd1\x6e\x8a\x41\x0e\x45\x61\xcb\x10\x66\x18\xe9\x71",
257 .input_len = 1 + 1 + 1 + 32,
258 .rrtype = WDNS_TYPE_TLSA,
259 .rrclass = WDNS_CLASS_IN,
260 .expected =
261 "0 0 1 "
262 "D2ABDE240D7CD3EE6B4B28C54DF034B9"
263 "7983A1D16E8A410E4561CB106618E971",
264 },
265
266 /* rrtype bitmap test for rrtypes > 255 */
267 {
268 .input =
269 "\x03""fsi\x02io\x00"
270 "\x00\x01" "\x40"
271 "\x01\x01" "\x40"
272 "\x80\x01" "\x40",
273 .input_len = 8 + 3 + 3 + 3,
274 .rrtype = WDNS_TYPE_NSEC,
275 .rrclass = WDNS_CLASS_IN,
276 .expected = "fsi.io. A CAA DLV",
277 },
278
279 { 0 }
280 };
281
282
283 static size_t
test_rdata_to_str(void)284 test_rdata_to_str(void) {
285 ubuf *u;
286 struct test *cur;
287 size_t failures = 0;
288
289 u = ubuf_init(256);
290
291 for(cur = tdata; cur->input != NULL; cur++) {
292 char * actual = NULL;
293
294 ubuf_reset(u);
295
296 actual = wdns_rdata_to_str(cur->input, cur->input_len, cur->rrtype, cur->rrclass);
297
298 if (strcmp(actual, cur->expected)) {
299 ubuf_add_fmt(u, "FAIL %" PRIu64 ": input=", cur-tdata);
300 escape(u, cur->input, cur->input_len);
301
302 ubuf_add_fmt(u, " %s %s",
303 wdns_rrclass_to_str(cur->rrclass),
304 wdns_rrtype_to_str(cur->rrtype));
305
306 ubuf_add_cstr(u, " value=");
307 escape(u, (const uint8_t*)actual, strlen(actual));
308 ubuf_add_cstr(u, " != ");
309 escape(u, (const uint8_t*)cur->expected, strlen(cur->expected));
310
311 failures++;
312 } else {
313 ubuf_add_fmt(u, "PASS %" PRIu64 ": input=", cur-tdata);
314 escape(u, cur->input, cur->input_len);
315 ubuf_add_fmt(u, " %s %s",
316 wdns_rrclass_to_str(cur->rrclass),
317 wdns_rrtype_to_str(cur->rrtype));
318
319 ubuf_add_cstr(u, " value=");
320 escape(u, (const uint8_t*)actual, strlen(actual));
321 }
322
323 fprintf (stderr, "%s\n", ubuf_cstr(u));
324 if (actual != NULL) {
325 free(actual);
326 actual = NULL;
327 }
328 }
329
330 ubuf_destroy(&u);
331 return failures;
332 }
333
main(void)334 int main (void) {
335 int ret = 0;
336
337 ret |= check(test_rdata_to_str(), "test_rdata_to_str", NAME);
338
339 if (ret)
340 return (EXIT_FAILURE);
341 return (EXIT_SUCCESS);
342 }
343