1 /*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2 
3     This program is free software: you can redistribute it and/or modify
4     it under the terms of the GNU General Public License as published by
5     the Free Software Foundation, either version 3 of the License, or
6     (at your option) any later version.
7 
8     This program is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11     GNU General Public License for more details.
12 
13     You should have received a copy of the GNU General Public License
14     along with this program.  If not, see <https://www.gnu.org/licenses/>.
15  */
16 
17 #include <assert.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <tap/basic.h>
21 
22 #include "libknot/dname.h"
23 
24 /* Test dname_parse_from_wire */
test_fw(size_t l,const char * w)25 static int test_fw(size_t l, const char *w) {
26 	const uint8_t *np = NULL;
27 	if (w != NULL) {
28 		np = (const uint8_t *)w + l;
29 	}
30 	return knot_dname_wire_check((const uint8_t *)w, np, NULL) > 0;
31 }
32 
33 /* Test dname to/from string operations */
test_str(const char * in_str,const char * in_bin,size_t bin_len)34 static void test_str(const char *in_str, const char *in_bin, size_t bin_len)
35 {
36 	knot_dname_storage_t d1;
37 	knot_dname_txt_storage_t s1;
38 	knot_dname_t *d2 = NULL, *aux_d = NULL;
39 	char         *s2 = NULL, *aux_s = NULL;
40 	int          ret = 0;
41 
42 	/* dname_from_str */
43 	aux_d = knot_dname_from_str(d1, in_str, sizeof(d1));
44 	ok(aux_d != NULL, "dname_from_str: %s", in_str);
45 	if (aux_d == NULL) {
46 		skip_block(10, "dname_from_str: %s", in_str);
47 		return;
48 	}
49 
50 	/* dname_wire_check */
51 	ret = knot_dname_wire_check(d1, d1 + sizeof(d1), NULL);
52 	ok(ret == bin_len, "dname_wire_check: %s", in_str);
53 
54 	/* dname compare */
55 	ok(memcmp(d1, in_bin, bin_len) == 0, "dname compare: %s", in_str);
56 
57 	/* dname_to_str */
58 	aux_s = knot_dname_to_str(s1, d1, sizeof(s1));
59 	ok(aux_s != NULL, "dname_to_str: %s", in_str);
60 	if (aux_s == NULL) {
61 		skip_block(7, "dname_to_str: %s", in_str);
62 		return;
63 	}
64 
65 	/* dname_from_str_alloc */
66 	d2 = knot_dname_from_str_alloc(s1);
67 	ok(d2 != NULL, "dname_from_str_alloc: %s", s1);
68 	if (d2 == NULL) {
69 		skip_block(6, "dname_from_str_alloc: %s", s1);
70 		return;
71 	}
72 
73 	/* dname_wire_check */
74 	ret = knot_dname_wire_check(d2, d2 + bin_len, NULL);
75 	ok(ret == bin_len, "dname_wire_check: %s", s1);
76 
77 	/* dname compare */
78 	ok(d2 && memcmp(d2, in_bin, bin_len) == 0, "dname compare: %s", s1);
79 
80 	/* dname_to_str_alloc */
81 	s2 = knot_dname_to_str_alloc(d2);
82 	knot_dname_free(d2, NULL);
83 	ok(s2 != NULL, "dname_to_str_alloc: %s", s1);
84 	if (s2 == NULL) {
85 		skip_block(3, "dname_to_str_alloc: %s", s1);
86 		return;
87 	}
88 
89 	/* As the string representation is ambiguous, the following steps
90 	 * are just for comparison in wire form.
91 	 */
92 	d2 = knot_dname_from_str_alloc(s2);
93 	ok(d2 != NULL, "dname_from_str_alloc: %s", s2);
94 	if (aux_d == NULL) {
95 		skip_block(2, "dname_from_str_alloc: %s", s2);
96 		free(s2);
97 		return;
98 	}
99 
100 	/* dname_wire_check */
101 	ret = knot_dname_wire_check(d2, d2 + bin_len, NULL);
102 	ok(ret == bin_len, "dname_wire_check: %s", s2);
103 
104 	/* dname compare */
105 	ok(d2 && memcmp(d2, in_bin, bin_len) == 0, "dname compare: %s", s2);
106 
107 	knot_dname_free(d2, NULL);
108 	free(s2);
109 }
110 
test_dname_lf(void)111 static void test_dname_lf(void)
112 {
113 	knot_dname_storage_t storage;
114 
115 	/* Maximal DNAME length */
116 	const knot_dname_t *in = (uint8_t *)
117 		"\x3f""iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"
118 		"\x3f""hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
119 		"\x3f""ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"
120 		"\x1f""fffffffffffffffffffffffffffffff"
121 		"\x0f""eeeeeeeeeeeeeee"
122 		"\x07""ddddddd"
123 		"\x03""ccc"
124 		"\x01""b"
125 		"\x00";
126 	const uint8_t *ref = (uint8_t *)
127 		"\xFE"
128 		"b""\x00"
129 		"ccc""\00"
130 		"ddddddd""\x00"
131 		"eeeeeeeeeeeeeee""\x00"
132 		"fffffffffffffffffffffffffffffff""\x00"
133 		"ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg""\x00"
134 		"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh""\x00"
135 		"iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii""\x00";
136 	assert(strlen((const char *)in) == KNOT_DNAME_MAXLEN - 1);
137 	uint8_t *out = knot_dname_lf(in, storage);
138 	ok(out != NULL && memcmp(ref, out, KNOT_DNAME_MAXLEN) == 0,
139 	   "knot_dname_lf: max-length DNAME converted");
140 
141 	/* Zero label DNAME*/
142 	in = (uint8_t *) "\x00";
143 	out = knot_dname_lf(in, storage);
144 	ok(out != NULL && out[0] == '\x00', "knot_dname_lf: zero-label DNAME converted");
145 }
146 
test_dname_storage(void)147 static void test_dname_storage(void)
148 {
149 	const knot_dname_t *dname = (uint8_t *)"\x04""test";
150 	size_t dname_len = knot_dname_size(dname);
151 
152 	knot_dname_storage_t storage;
153 	size_t store_len = knot_dname_store(storage, dname);
154 	size_t storage_len = knot_dname_size(storage);
155 
156 	ok(store_len == dname_len && storage_len == dname_len &&
157 	   memcmp(storage, dname, dname_len) == 0,
158 	   "knot_dname_storage: valid name");
159 }
160 
main(int argc,char * argv[])161 int main(int argc, char *argv[])
162 {
163 	plan_lazy();
164 
165 	knot_dname_t *d = NULL, *d2 = NULL;
166 	const char *w = NULL, *t = NULL;
167 	char *s = NULL;
168 
169 	/* DNAME WIRE CHECKS */
170 
171 	/* NULL wire */
172 	ok(!test_fw(0, NULL), "parsing NULL dname");
173 
174 	/* empty label */
175 	ok(test_fw(1, ""), "parsing empty dname");
176 
177 	/* incomplete dname */
178 	ok(!test_fw(5, "\x08" "dddd"), "parsing incomplete wire");
179 
180 	/* non-fqdn */
181 	ok(!test_fw(3, "\x02" "ab"), "parsing non-fqdn name");
182 
183 	/* label length == 63 */
184 	w = "\x3f" "123456789012345678901234567890123456789012345678901234567890123";
185 	ok(test_fw(1 + 63 + 1, w), "parsing label length == 63");
186 
187 	/* label length > 63 */
188 	w = "\x40" "1234567890123456789012345678901234567890123456789012345678901234";
189 	ok(!test_fw(1 + 64 + 1, w), "parsing label length > 63");
190 
191 	/* label count == 127 (also maximal dname length) */
192 	w = "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
193 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
194 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
195 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
196 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
197 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
198 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
199 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
200 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
201 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
202 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
203 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
204 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64";
205 	ok(test_fw(127 * 2 + 1, w), "parsing label count == 127");
206 
207 	/* label count > 127 */
208 	w = "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
209 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
210 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
211 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
212 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
213 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
214 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
215 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
216 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
217 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
218 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
219 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
220 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64";
221 	ok(!test_fw(128 * 2 + 1, w), "parsing label count > 127");
222 
223 	/* dname length > 255 */
224 	w = "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
225 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
226 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
227 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
228 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
229 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
230 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
231 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
232 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
233 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
234 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
235 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
236 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x02\x64\x64";
237 	ok(!test_fw(126 * 2 + 3 + 1, w), "parsing dname len > 255");
238 
239 	/* DNAME STRING CHECKS */
240 
241 	/* root dname */
242 	test_str(".", "\x00", 1);
243 
244 	/* 1-char dname */
245 	test_str("a.", "\x01""a", 2 + 1);
246 
247 	/* 1-char dname - non-fqdn */
248 	test_str("a", "\x01""a", 2 + 1);
249 
250 	/* wildcard and asterisks */
251 	test_str("*.*a.a*a.**.",
252 	         "\x01" "*" "\x02" "*a" "\x03" "a*a" "\x02" "**",
253 	         2 + 3 + 4 + 3 + 1);
254 
255 	/* special label */
256 	test_str("\\000\\0320\\ \\\\\\\"\\.\\@\\*.",
257 	         "\x09" "\x00\x20\x30\x20\x5c\x22.@*",
258 	         10 + 1);
259 
260 	/* unescaped special characters */
261 	test_str("_a.b-c./d.",
262 	         "\x02" "_a" "\x03" "b-c" "\x02" "/d",
263 	         3 + 4 + 3 + 1);
264 
265 	/* all possible characters */
266 	test_str("\\000\\001\\002\\003\\004\\005\\006\\007\\008\\009\\010\\011\\012\\013\\014\\015\\016\\017\\018\\019",
267 	         "\x14" "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13",
268 	         22);
269 	test_str("\\020\\021\\022\\023\\024\\025\\026\\027\\028\\029\\030\\031\\032\\033\\034\\035\\036\\037\\038\\039",
270 	         "\x14" "\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27",
271 	         22);
272 	test_str("\\040\\041\\042\\043\\044\\045\\046\\047\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\\058\\059",
273 	         "\x14" "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b",
274 	         22);
275 	test_str("\\060\\061\\062\\063\\064\\065\\066\\067\\068\\069\\070\\071\\072\\073\\074\\075\\076\\077\\078\\079",
276 	         "\x14" "\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
277 	         22);
278 	test_str("\\080\\081\\082\\083\\084\\085\\086\\087\\088\\089\\090\\091\\092\\093\\094\\095\\096\\097\\098\\099",
279 	         "\x14" "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63",
280 	         22);
281 	test_str("\\100\\101\\102\\103\\104\\105\\106\\107\\108\\109\\110\\111\\112\\113\\114\\115\\116\\117\\118\\119",
282 	         "\x14" "\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77",
283 	         22);
284 	test_str("\\120\\121\\122\\123\\124\\125\\126\\127\\128\\129\\130\\131\\132\\133\\134\\135\\136\\137\\138\\139",
285 	         "\x14" "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b",
286 	         22);
287 	test_str("\\140\\141\\142\\143\\144\\145\\146\\147\\148\\149\\150\\151\\152\\153\\154\\155\\156\\157\\158\\159",
288 	         "\x14" "\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f",
289 	         22);
290 	test_str("\\160\\161\\162\\163\\164\\165\\166\\167\\168\\169\\170\\171\\172\\173\\174\\175\\176\\177\\178\\179",
291 	         "\x14" "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3",
292 	         22);
293 	test_str("\\180\\181\\182\\183\\184\\185\\186\\187\\188\\189\\190\\191\\192\\193\\194\\195\\196\\197\\198\\199",
294 	         "\x14" "\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
295 	         22);
296 	test_str("\\200\\201\\202\\203\\204\\205\\206\\207\\208\\209\\210\\211\\212\\213\\214\\215\\216\\217\\218\\219",
297 	         "\x14" "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb",
298 	         22);
299 	test_str("\\220\\221\\222\\223\\224\\225\\226\\227\\228\\229\\230\\231\\232\\233\\234\\235\\236\\237\\238\\239",
300 	         "\x14" "\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef",
301 	         22);
302 	test_str("\\240\\241\\242\\243\\244\\245\\246\\247\\248\\249\\250\\251\\252\\253\\254\\255",
303 	         "\x10" "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
304 	         18);
305 
306 	/* maximal dname label length */
307 	test_str("12345678901234567890123456789012345678901234567890123456789012\\063",
308 		 "\x3f" "12345678901234567890123456789012345678901234567890123456789012?",
309 		 65);
310 
311 	/* maximal dname length */
312 	test_str("1234567890123456789012345678901234567890123456789."
313 	         "1234567890123456789012345678901234567890123456789."
314 	         "1234567890123456789012345678901234567890123456789."
315 	         "1234567890123456789012345678901234567890123456789."
316 	         "\\#234567890123456789012345678901234567890123456789012\\063",
317 	         "\x31" "1234567890123456789012345678901234567890123456789"
318 	         "\x31" "1234567890123456789012345678901234567890123456789"
319 	         "\x31" "1234567890123456789012345678901234567890123456789"
320 	         "\x31" "1234567890123456789012345678901234567890123456789"
321 	         "\x35" "#234567890123456789012345678901234567890123456789012?",
322 	         255);
323 
324 	/* NULL output, positive maxlen */
325 	w = "\x02" "aa";
326 	s = knot_dname_to_str(NULL, (const uint8_t *)w, 1);
327 	ok(s != NULL, "dname_to_str: null dname");
328 	if (s != NULL) {
329 		ok(memcmp(s, "aa.", 4) == 0, "dname_to_str: null dname compare");
330 		free(s);
331 	} else {
332 		skip("dname_to_str: null dname");
333 	}
334 
335 	/* non-NULL output, zero maxlen */
336 	char s_small[2];
337 	s = knot_dname_to_str(s_small, (const uint8_t *)w, 0);
338 	ok(s == NULL, "dname_to_str: non-NULL output, zero maxlen");
339 
340 	/* small buffer */
341 	s = knot_dname_to_str(s_small, (const uint8_t *)w, 1);
342 	ok(s == NULL, "dname_to_str: small buffer");
343 
344 	/* NULL dname */
345 	s = knot_dname_to_str_alloc(NULL);
346 	ok(s == NULL, "dname_to_str: null dname");
347 
348 	/* empty dname is considered as a root dname */
349 	w = "";
350 	s = knot_dname_to_str_alloc((const uint8_t *)w);
351 	ok(s != NULL, "dname_to_str: empty dname");
352 	if (s != NULL) {
353 		ok(memcmp(s, ".", 1) == 0, "dname_to_str: empty dname is root dname");
354 		free(s);
355 	} else {
356 		skip("dname_to_str: empty dname");
357 	}
358 
359 	/* incomplete dname */
360 	/* ASAN: global-buffer-overflow
361 	w = "\x08" "dddd";
362 	s = knot_dname_to_str_alloc((const uint8_t *)w);
363 	ok(s != NULL, "dname_to_str: incomplete dname");
364 	free(s);
365 	*/
366 
367 	/* non-fqdn */
368 	w = "\x02" "ab";
369 	s = knot_dname_to_str_alloc((const uint8_t *)w);
370 	ok(s != NULL, "dname_to_str: non-fqdn");
371 	free(s);
372 
373 	/* label length > 63 */
374 	w = "\x40" "1234567890123456789012345678901234567890123456789012345678901234";
375 	s = knot_dname_to_str_alloc((const uint8_t *)w);
376 	ok(s != NULL, "dname_to_str: label length > 63");
377 	free(s);
378 
379 	/* label count > 127 */
380 	w = "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
381 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
382 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
383 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
384 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
385 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
386 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
387 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
388 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
389 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
390 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
391 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
392 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64";
393 	s = knot_dname_to_str_alloc((const uint8_t *)w);
394 	ok(s != NULL, "dname_to_str: label count > 127");
395 	free(s);
396 
397 	/* dname length > 255 */
398 	w = "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
399 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
400 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
401 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
402 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
403 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
404 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
405 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
406 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
407 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
408 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
409 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64"
410 	    "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x02\x64\x64";
411 	s = knot_dname_to_str_alloc((const uint8_t *)w);
412 	ok(s != NULL, "dname_to_str: dname length > 255");
413 	free(s);
414 
415 	/* output overflow sanity check */
416 	uint8_t in[4] = "\x02""\x00\x00""\x00";
417 	for (uint16_t i = 0; i < UINT16_MAX; i++) {
418 		memcpy(in + 1, &i, sizeof(i));
419 		for (int j = 3; j < 8; j++) {
420 			char tmp[j];
421 			char *out_static = knot_dname_to_str(tmp, in, sizeof(tmp));
422 			char *out_dynamic = knot_dname_to_str_alloc(in);
423 			if (out_dynamic == NULL) {
424 				ok(out_dynamic != NULL, "dname_to_str_alloc: invalid input");
425 			} else if (strlen(out_dynamic) < sizeof(tmp) - 1 &&
426 				   out_static == NULL) {
427 				ok(out_static != NULL, "dname_to_str: invalid input");
428 			}
429 			free(out_dynamic);
430 		}
431 	}
432 
433 	/* NULL output, positive maxlen */
434 	s = "aa.";
435 	d = knot_dname_from_str(NULL, s, 1);
436 	ok(s != NULL, "dname_from_str: null name");
437 	if (s != NULL) {
438 		ok(memcmp(d, "\x02" "aa", 4) == 0, "dname_from_str: null name compare");
439 		free(d);
440 	} else {
441 		skip("dname_from_str: null name");
442 	}
443 
444 	/* non-NULL output, zero maxlen */
445 	uint8_t d_small[2];
446 	d = knot_dname_from_str(d_small, s, 0);
447 	ok(d == NULL, "dname_from_str: non-NULL output, zero maxlen");
448 
449 	/* small buffer */
450 	d = knot_dname_from_str(d_small, s, 1);
451 	ok(d == NULL, "dname_from_str: small buffer");
452 
453 	/* NULL string */
454 	d = knot_dname_from_str_alloc(NULL);
455 	ok(d == NULL, "dname_from_str: null string");
456 
457 	/* empty string */
458 	t = "";
459 	d = knot_dname_from_str_alloc(t);
460 	ok(d == NULL, "dname_from_str: empty string");
461 
462 	/* empty label */
463 	t = "..";
464 	d = knot_dname_from_str_alloc(t);
465 	ok(d == NULL, "dname_from_str: empty label");
466 
467 	/* leading dot */
468 	t = ".a";
469 	d = knot_dname_from_str_alloc(t);
470 	ok(d == NULL, "dname_from_str: leading dot");
471 
472 	/* incomplete decimal notation I */
473 	t = "\\1";
474 	d = knot_dname_from_str_alloc(t);
475 	ok(d == NULL, "dname_from_str: incomplete decimal I");
476 
477 	/* incomplete decimal notation II */
478 	t = "\\12";
479 	d = knot_dname_from_str_alloc(t);
480 	ok(d == NULL, "dname_from_str: incomplete decimal II");
481 
482 	/* invalid decimal notation I */
483 	t = "\\256";
484 	d = knot_dname_from_str_alloc(t);
485 	ok(d == NULL, "dname_from_str: invalid decimal I");
486 
487 	/* invalid decimal notation II */
488 	t = "\\2x6";
489 	d = knot_dname_from_str_alloc(t);
490 	ok(d == NULL, "dname_from_str: invalid decimal II");
491 
492 	/* invalid escape notation */
493 	t = "\\2";
494 	d = knot_dname_from_str_alloc(t);
495 	ok(d == NULL, "dname_from_str: invalid escape");
496 
497 	/* label length > 63 I */
498 	t = "1234567890123456789012345678901234567890123456789012345678901234";
499 	d = knot_dname_from_str_alloc(t);
500 	ok(d == NULL, "dname_from_str: label length > 63 I");
501 
502 	/* label length > 63 II */
503 	t = "123456789012345678901234567890123456789012345678901234567890123\\?";
504 	d = knot_dname_from_str_alloc(t);
505 	ok(d == NULL, "dname_from_str: label length > 63 II");
506 
507 	/* label length > 63 III */
508 	t = "123456789012345678901234567890123456789012345678901234567890123\\063";
509 	d = knot_dname_from_str_alloc(t);
510 	ok(d == NULL, "dname_from_str: label length > 63 III");
511 
512 	/* dname length > 255 */
513 	t = "1234567890123456789012345678901234567890123456789."
514 	    "1234567890123456789012345678901234567890123456789."
515 	    "1234567890123456789012345678901234567890123456789."
516 	    "1234567890123456789012345678901234567890123456789."
517 	    "123456789012345678901234567890123456789012345678901234.",
518 	d = knot_dname_from_str_alloc(t);
519 	ok(d == NULL, "dname_from_str: dname length > 255");
520 
521 	/* DNAME SUBDOMAIN CHECKS */
522 
523 	/* equal name is subdomain */
524 	t = "ab.cd.ef";
525 	d2 = knot_dname_from_str_alloc(t);
526 	t = "ab.cd.ef";
527 	d = knot_dname_from_str_alloc(t);
528 	ok(knot_dname_in_bailiwick(d, d2) == 0, "dname_subdomain: equal name");
529 	knot_dname_free(d, NULL);
530 
531 	/* true subdomain */
532 	t = "0.ab.cd.ef";
533 	d = knot_dname_from_str_alloc(t);
534 	ok(knot_dname_in_bailiwick(d, d2) == 1, "dname_subdomain: true subdomain");
535 	knot_dname_free(d, NULL);
536 
537 	/* not subdomain */
538 	t = "cd.ef";
539 	d = knot_dname_from_str_alloc(t);
540 	ok(knot_dname_in_bailiwick(d, d2) < 0, "dname_subdomain: not subdomain");
541 	knot_dname_free(d, NULL);
542 
543 	/* root subdomain */
544 	t = ".";
545 	d = knot_dname_from_str_alloc(t);
546 	ok(knot_dname_in_bailiwick(d2, d) == 3, "dname_subdomain: root subdomain");
547 	knot_dname_free(d, NULL);
548 	knot_dname_free(d2, NULL);
549 
550 	/* DNAME EQUALITY CHECKS */
551 
552 	t = "ab.cd.ef";
553 	d = knot_dname_from_str_alloc(t);
554 	ok(knot_dname_is_equal(d, d), "dname_is_equal: equal names");
555 
556 	t = "ab.cd.fe";
557 	d2 = knot_dname_from_str_alloc(t);
558 	ok(!knot_dname_is_equal(d, d2), "dname_is_equal: same label count");
559 	knot_dname_free(d2, NULL);
560 
561 	t = "ab.cd";
562 	d2 = knot_dname_from_str_alloc(t);
563 	ok(!knot_dname_is_equal(d, d2), "dname_is_equal: len(d1) < len(d2)");
564 	knot_dname_free(d2, NULL);
565 
566 	t = "ab.cd.ef.gh";
567 	d2 = knot_dname_from_str_alloc(t);
568 	ok(!knot_dname_is_equal(d, d2), "dname_is_equal: len(d1) > len(d2)");
569 	knot_dname_free(d2, NULL);
570 
571 	t = "ab.cd.efe";
572 	d2 = knot_dname_from_str_alloc(t);
573 	ok(!knot_dname_is_equal(d, d2), "dname_is_equal: last label longer");
574 	knot_dname_free(d2, NULL);
575 
576 	t = "ab.cd.e";
577 	d2 = knot_dname_from_str_alloc(t);
578 	ok(!knot_dname_is_equal(d, d2), "dname_is_equal: last label shorter");
579 	knot_dname_free(d2, NULL);
580 
581 	knot_dname_free(d, NULL);
582 
583 	/* DNAME EQUALITY CHECKS IGNORING CASE */
584 
585 	t = "aB.cd.ef";
586 	d = knot_dname_from_str_alloc(t);
587 	ok(knot_dname_is_case_equal(d, d), "dname_is_case_equal: equal case");
588 
589 	t = "aB.cD.ef";
590 	d2 = knot_dname_from_str_alloc(t);
591 	ok(knot_dname_is_case_equal(d, d2), "dname_is_case_equal: different case");
592 	knot_dname_free(d2, NULL);
593 
594 	t = "aB.dc.ef";
595 	d2 = knot_dname_from_str_alloc(t);
596 	ok(!knot_dname_is_case_equal(d, d2), "dname_is_case_equal: different name");
597 	knot_dname_free(d2, NULL);
598 
599 	t = "aB.cd";
600 	d2 = knot_dname_from_str_alloc(t);
601 	ok(!knot_dname_is_case_equal(d, d2), "dname_is_case_equal: different length");
602 	knot_dname_free(d2, NULL);
603 
604 	t = "aB.cdx.ef";
605 	d2 = knot_dname_from_str_alloc(t);
606 	ok(!knot_dname_is_case_equal(d, d2), "dname_is_case_equal: different label");
607 	knot_dname_free(d2, NULL);
608 
609 	knot_dname_free(d, NULL);
610 
611 	/* OTHER CHECKS */
612 
613 	test_dname_lf();
614 
615 	test_dname_storage();
616 
617 	return 0;
618 }
619