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-name_to_str"
13 
14 struct test {
15 	const void *input;
16 	size_t ilen;
17 	const char *expected;
18 	const char *expected_lcase;
19 	const char *expected_rev;
20 	size_t skip_len;
21 };
22 
23 struct test tdata[] = {
24 	{
25 		.input = "\x03" "fsi" "\x02" "io",
26 		.ilen = 1 + 3 + 1 + 2 + 1,
27 		.expected = "fsi.io.",
28 		.expected_lcase = "fsi.io.",
29 		.expected_rev = "io.fsi.",
30 		.skip_len = 1 + 3 + 1 + 2 + 1,
31 	},
32 	{
33 		.input = "\x04" "abcd" "\x03" "fsi" "\x02" "IO",
34 		.ilen = 1 + 4 + 1 + 3 + 1 + 2 + 1,
35 		.expected = "abcd.fsi.IO.",
36 		.expected_lcase = "abcd.fsi.io.",
37 		.expected_rev = "IO.fsi.abcd.",
38 		.skip_len = 1 + 4 + 1 + 3 + 1 + 2 + 1,
39 	},
40 	{
41 		.input = "\x05" "Mixed" "\x03" "fsi" "\x02" "IO",
42 		.ilen = 1 + 5 + 1 + 3 + 1 + 2 + 1,
43 		.expected = "Mixed.fsi.IO.",
44 		.expected_lcase = "mixed.fsi.io.",
45 		.expected_rev = "IO.fsi.Mixed.",
46 		.skip_len = 1 + 5 + 1 + 3 + 1 + 2 + 1,
47 	},
48 	{
49 		.input = "\x07" "testing" "\x08" "trailing" "\x04" "data" "\x03" "fsi" "\x02" "io" "\x00" "\x04" "abcd",
50 		.ilen = 1 + 7 + 1 + 8 + 1 + 4 + 1 + 3 + 1 + 2 + 1     + 1 + 4 + 1,
51 		.expected = "testing.trailing.data.fsi.io.",
52 		.expected_lcase = "testing.trailing.data.fsi.io.",
53 		// It's really unclear how this function should behave when presented
54 		// with trailing data. This topic demands further discussion.
55 		// Ref: https://github.com/farsightsec/wdns/issues/25
56 //		.expected_rev = "io.fsi.data.trailing.testing.",
57 		.expected_rev = ".",
58 		.skip_len = 1 + 7 + 1 + 8 + 1 + 4 + 1 + 3 + 1 + 2 + 1,
59 	},
60 	{
61 		0
62 	}
63 };
64 
65 
66 static size_t
test_name_to_str(void)67 test_name_to_str(void)
68 {
69 	char dstr[1024];
70 	ubuf *u;
71 	struct test *cur;
72 	size_t failures = 0;
73 
74 	u = ubuf_init(256);
75 
76 	for(cur = tdata; cur->input != NULL; cur++) {
77 		wdns_name_t name;
78 		wdns_res res;
79 		int err = 0;
80 
81 		ubuf_reset(u);
82 		memset(&name, 0, sizeof(name));
83 		memset(dstr, 0, sizeof(dstr));
84 
85 		// Don't check result of wdns_domain_to_str() here or elsewhere,
86 		// because if it's wrong, subsequent string comparisons necessarily fail.
87 		wdns_domain_to_str(cur->input, cur->ilen, dstr);
88 
89 		if (strcmp(dstr, cur->expected)) {
90 			ubuf_add_fmt(u, "FAIL %" PRIu64 ": input=", cur-tdata);
91 			escape(u, (uint8_t*)cur->input, strlen(cur->input));
92 			ubuf_add_fmt(u, " name %s != %s", dstr, cur->expected);
93 			err = 1;
94 		}
95 
96 		if (!err) {
97 			name.data = malloc(cur->ilen);
98 			memcpy(name.data, cur->input, cur->ilen);
99 			name.len = cur->ilen;
100 			wdns_downcase_name(&name);
101 
102 			memset(dstr, 0, sizeof(dstr));
103 			wdns_domain_to_str(name.data, name.len, dstr);
104 
105 			if (strcmp(dstr, cur->expected_lcase)) {
106 				ubuf_add_fmt(u, "FAIL %" PRIu64 ": input=", cur-tdata);
107 				escape(u, (uint8_t*)cur->input, strlen(cur->input));
108 				ubuf_add_fmt(u, " lowercase name %s != %s", dstr, cur->expected_lcase);
109 				err = 1;
110 			}
111 
112 		}
113 
114 		if (!err) {
115 			memset(name.data, 0, name.len);
116 
117 			if (wdns_reverse_name(cur->input, cur->ilen, name.data) != wdns_res_success) {
118 				ubuf_add_fmt(u, "FAIL %" PRIu64 ": input=", cur-tdata);
119 				escape(u, (uint8_t*)cur->input, strlen(cur->input));
120 				ubuf_add_fmt(u, " reverse name failure");
121 				err = 1;
122 			} else {
123 				memset(dstr, 0, sizeof(dstr));
124 				wdns_domain_to_str(name.data, name.len, dstr);
125 
126 				if (strcmp(dstr, cur->expected_rev)) {
127 					ubuf_add_fmt(u, "FAIL %" PRIu64 ": input=", cur-tdata);
128 					escape(u, (uint8_t*)cur->input, strlen(cur->input));
129 					ubuf_add_fmt(u, " reverse name %s != %s", dstr, cur->expected_rev);
130 					err = 1;
131 				}
132 
133 			}
134 
135 		}
136 
137 		if (!err) {
138 			const uint8_t *sptr = cur->input;
139 
140 			res = wdns_skip_name(&sptr, (((const uint8_t *)cur->input) + cur->ilen));
141 
142 			if (res != cur->skip_len) {
143 				ubuf_add_fmt(u, "FAIL %" PRIu64 ": input=", cur-tdata);
144 				escape(u, (uint8_t*)cur->input, strlen(cur->input));
145 				ubuf_add_fmt(u, " skip len %zu != %zu", res, cur->skip_len);
146 				err = 1;
147 			}
148 
149 		}
150 
151 		if (!err) {
152 			ubuf_add_fmt(u, "PASS %" PRIu64 ": input=", cur-tdata);
153 			escape(u, (uint8_t*)cur->input, cur->ilen);
154 		} else {
155 			failures++;
156 		}
157 
158 		fprintf (stderr, "%s\n", ubuf_cstr(u));
159 		if (name.data != NULL) {
160 			free(name.data);
161 			name.data = NULL;
162 		}
163 	}
164 
165 	ubuf_destroy(&u);
166 	return failures;
167 }
168 
main(void)169 int main (void)
170 {
171 	int ret = 0;
172 
173 	ret |= check(test_name_to_str(), "test-name_to_str", NAME);
174 
175 	if (ret)
176 		return (EXIT_FAILURE);
177 	return (EXIT_SUCCESS);
178 }
179