]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-dns-domain.c
dns-domain: add helper that checks whether domain is dot suffixed
[thirdparty/systemd.git] / src / test / test-dns-domain.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include "alloc-util.h"
4 #include "dns-domain.h"
5 #include "macro.h"
6 #include "string-util.h"
7 #include "tests.h"
8
9 static void test_dns_label_unescape_one(const char *what, const char *expect, size_t buffer_sz, int ret, int ret_ldh) {
10 char buffer[buffer_sz];
11 int r;
12 const char *w = what;
13
14 log_info("%s, %s, %zu, →%d/%d", what, expect, buffer_sz, ret, ret_ldh);
15
16 r = dns_label_unescape(&w, buffer, buffer_sz, 0);
17 assert_se(r == ret);
18 if (r >= 0)
19 assert_se(streq(buffer, expect));
20
21 w = what;
22 r = dns_label_unescape(&w, buffer, buffer_sz, DNS_LABEL_LDH);
23 assert_se(r == ret_ldh);
24 if (r >= 0)
25 assert_se(streq(buffer, expect));
26
27 w = what;
28 r = dns_label_unescape(&w, buffer, buffer_sz, DNS_LABEL_NO_ESCAPES);
29 const int ret_noe = strchr(what, '\\') ? -EINVAL : ret;
30 assert_se(r == ret_noe);
31 if (r >= 0)
32 assert_se(streq(buffer, expect));
33 }
34
35 static void test_dns_label_unescape(void) {
36 log_info("/* %s */", __func__);
37
38 test_dns_label_unescape_one("hallo", "hallo", 6, 5, 5);
39 test_dns_label_unescape_one("hallo", "hallo", 4, -ENOBUFS, -ENOBUFS);
40 test_dns_label_unescape_one("", "", 10, 0, 0);
41 test_dns_label_unescape_one("hallo\\.foobar", "hallo.foobar", 20, 12, -EINVAL);
42 test_dns_label_unescape_one("hallo.foobar", "hallo", 10, 5, 5);
43 test_dns_label_unescape_one("hallo\n.foobar", "hallo", 20, -EINVAL, -EINVAL);
44 test_dns_label_unescape_one("hallo\\", "hallo", 20, -EINVAL, -EINVAL);
45 test_dns_label_unescape_one("hallo\\032 ", "hallo ", 20, 7, -EINVAL);
46 test_dns_label_unescape_one(".", "", 20, 0, 0);
47 test_dns_label_unescape_one("..", "", 20, -EINVAL, -EINVAL);
48 test_dns_label_unescape_one(".foobar", "", 20, -EINVAL, -EINVAL);
49 test_dns_label_unescape_one("foobar.", "foobar", 20, 6, 6);
50 test_dns_label_unescape_one("foobar..", "foobar", 20, -EINVAL, -EINVAL);
51 test_dns_label_unescape_one("foo-bar", "foo-bar", 20, 7, 7);
52 test_dns_label_unescape_one("foo-", "foo-", 20, 4, -EINVAL);
53 test_dns_label_unescape_one("-foo", "-foo", 20, 4, -EINVAL);
54 test_dns_label_unescape_one("-foo-", "-foo-", 20, 5, -EINVAL);
55 test_dns_label_unescape_one("foo-.", "foo-", 20, 4, -EINVAL);
56 test_dns_label_unescape_one("foo.-", "foo", 20, 3, 3);
57 test_dns_label_unescape_one("foo\\032", "foo ", 20, 4, -EINVAL);
58 test_dns_label_unescape_one("foo\\045", "foo-", 20, 4, -EINVAL);
59 test_dns_label_unescape_one("głąb", "głąb", 20, 6, -EINVAL);
60 }
61
62 static void test_dns_name_to_wire_format_one(const char *what, const char *expect, size_t buffer_sz, int ret) {
63 uint8_t buffer[buffer_sz];
64 int r;
65
66 log_info("%s, %s, %zu, →%d", what, expect, buffer_sz, ret);
67
68 r = dns_name_to_wire_format(what, buffer, buffer_sz, false);
69 assert_se(r == ret);
70
71 if (r < 0)
72 return;
73
74 assert_se(!memcmp(buffer, expect, r));
75 }
76
77 static void test_dns_name_to_wire_format(void) {
78 static const char out0[] = { 0 };
79 static const char out1[] = { 3, 'f', 'o', 'o', 0 };
80 static const char out2[] = { 5, 'h', 'a', 'l', 'l', 'o', 3, 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
81 static const char out3[] = { 4, ' ', 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
82 static const char out4[] = { 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
83 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
84 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
85 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
86 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
87 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
88 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
89 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
90 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
91 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
92 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
93 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
94 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
95 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
96 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
97 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
98 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
99 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
100 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
101 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
102 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
103 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
104 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
105 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
106 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8',
107 3, 'a', '1', '2', 0 };
108
109 log_info("/* %s */", __func__);
110
111 test_dns_name_to_wire_format_one("", out0, sizeof(out0), sizeof(out0));
112
113 test_dns_name_to_wire_format_one("foo", out1, sizeof(out1), sizeof(out1));
114 test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) + 1, sizeof(out1));
115 test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) - 1, -ENOBUFS);
116
117 test_dns_name_to_wire_format_one("hallo.foo.bar", out2, sizeof(out2), sizeof(out2));
118 test_dns_name_to_wire_format_one("hallo.foo..bar", NULL, 32, -EINVAL);
119
120 test_dns_name_to_wire_format_one("\\032foo.bar", out3, sizeof(out3), sizeof(out3));
121
122 test_dns_name_to_wire_format_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a123", NULL, 500, -EINVAL);
123 test_dns_name_to_wire_format_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12", out4, sizeof(out4), sizeof(out4));
124 }
125
126 static void test_dns_label_unescape_suffix_one(const char *what, const char *expect1, const char *expect2, size_t buffer_sz, int ret1, int ret2) {
127 char buffer[buffer_sz];
128 const char *label;
129 int r;
130
131 log_info("%s, %s, %s, %zu, %d, %d", what, expect1, expect2, buffer_sz, ret1, ret2);
132
133 label = what + strlen(what);
134
135 r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz);
136 assert_se(r == ret1);
137 if (r >= 0)
138 assert_se(streq(buffer, expect1));
139
140 r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz);
141 assert_se(r == ret2);
142 if (r >= 0)
143 assert_se(streq(buffer, expect2));
144 }
145
146 static void test_dns_label_unescape_suffix(void) {
147 log_info("/* %s */", __func__);
148
149 test_dns_label_unescape_suffix_one("hallo", "hallo", "", 6, 5, 0);
150 test_dns_label_unescape_suffix_one("hallo", "hallo", "", 4, -ENOBUFS, -ENOBUFS);
151 test_dns_label_unescape_suffix_one("", "", "", 10, 0, 0);
152 test_dns_label_unescape_suffix_one("hallo\\.foobar", "hallo.foobar", "", 20, 12, 0);
153 test_dns_label_unescape_suffix_one("hallo.foobar", "foobar", "hallo", 10, 6, 5);
154 test_dns_label_unescape_suffix_one("hallo.foobar\n", "foobar", "foobar", 20, -EINVAL, -EINVAL);
155 test_dns_label_unescape_suffix_one("hallo\\", "hallo", "hallo", 20, -EINVAL, -EINVAL);
156 test_dns_label_unescape_suffix_one("hallo\\032 ", "hallo ", "", 20, 7, 0);
157 test_dns_label_unescape_suffix_one(".", "", "", 20, 0, 0);
158 test_dns_label_unescape_suffix_one("..", "", "", 20, 0, -EINVAL);
159 test_dns_label_unescape_suffix_one(".foobar", "foobar", "", 20, 6, -EINVAL);
160 test_dns_label_unescape_suffix_one("foobar.", "foobar", "", 20, 6, 0);
161 test_dns_label_unescape_suffix_one("foo\\\\bar", "foo\\bar", "", 20, 7, 0);
162 test_dns_label_unescape_suffix_one("foo.bar", "bar", "foo", 20, 3, 3);
163 test_dns_label_unescape_suffix_one("foo..bar", "bar", "", 20, 3, -EINVAL);
164 test_dns_label_unescape_suffix_one("foo...bar", "bar", "", 20, 3, -EINVAL);
165 test_dns_label_unescape_suffix_one("foo\\.bar", "foo.bar", "", 20, 7, 0);
166 test_dns_label_unescape_suffix_one("foo\\\\.bar", "bar", "foo\\", 20, 3, 4);
167 test_dns_label_unescape_suffix_one("foo\\\\\\.bar", "foo\\.bar", "", 20, 8, 0);
168 }
169
170 static void test_dns_label_escape_one(const char *what, size_t l, const char *expect, int ret) {
171 _cleanup_free_ char *t = NULL;
172 int r;
173
174 log_info("%s, %zu, %s, →%d", what, l, expect, ret);
175
176 r = dns_label_escape_new(what, l, &t);
177 assert_se(r == ret);
178
179 if (r < 0)
180 return;
181
182 assert_se(streq_ptr(expect, t));
183 }
184
185 static void test_dns_label_escape(void) {
186 log_info("/* %s */", __func__);
187
188 test_dns_label_escape_one("", 0, NULL, -EINVAL);
189 test_dns_label_escape_one("hallo", 5, "hallo", 5);
190 test_dns_label_escape_one("hallo", 6, "hallo\\000", 9);
191 test_dns_label_escape_one("hallo hallo.foobar,waldi", 24, "hallo\\032hallo\\.foobar\\044waldi", 31);
192 }
193
194 static void test_dns_name_normalize_one(const char *what, const char *expect, int ret) {
195 _cleanup_free_ char *t = NULL;
196 int r;
197
198 r = dns_name_normalize(what, 0, &t);
199 assert_se(r == ret);
200
201 if (r < 0)
202 return;
203
204 assert_se(streq_ptr(expect, t));
205 }
206
207 static void test_dns_name_normalize(void) {
208 test_dns_name_normalize_one("", ".", 0);
209 test_dns_name_normalize_one("f", "f", 0);
210 test_dns_name_normalize_one("f.waldi", "f.waldi", 0);
211 test_dns_name_normalize_one("f \\032.waldi", "f\\032\\032.waldi", 0);
212 test_dns_name_normalize_one("\\000", "\\000", 0);
213 test_dns_name_normalize_one("..", NULL, -EINVAL);
214 test_dns_name_normalize_one(".foobar", NULL, -EINVAL);
215 test_dns_name_normalize_one("foobar.", "foobar", 0);
216 test_dns_name_normalize_one(".", ".", 0);
217 }
218
219 static void test_dns_name_equal_one(const char *a, const char *b, int ret) {
220 int r;
221
222 r = dns_name_equal(a, b);
223 assert_se(r == ret);
224
225 r = dns_name_equal(b, a);
226 assert_se(r == ret);
227 }
228
229 static void test_dns_name_equal(void) {
230 test_dns_name_equal_one("", "", true);
231 test_dns_name_equal_one("x", "x", true);
232 test_dns_name_equal_one("x", "x.", true);
233 test_dns_name_equal_one("abc.def", "abc.def", true);
234 test_dns_name_equal_one("abc.def", "ABC.def", true);
235 test_dns_name_equal_one("abc.def", "CBA.def", false);
236 test_dns_name_equal_one("", "xxx", false);
237 test_dns_name_equal_one("ab", "a", false);
238 test_dns_name_equal_one("\\000", "\\000", true);
239 test_dns_name_equal_one(".", "", true);
240 test_dns_name_equal_one(".", ".", true);
241 test_dns_name_equal_one("..", "..", -EINVAL);
242 }
243
244 static void test_dns_name_between_one(const char *a, const char *b, const char *c, int ret) {
245 int r;
246
247 r = dns_name_between(a, b, c);
248 assert_se(r == ret);
249
250 r = dns_name_between(c, b, a);
251 if (ret >= 0)
252 assert_se(r == 0 || dns_name_equal(a, c) > 0);
253 else
254 assert_se(r == ret);
255 }
256
257 static void test_dns_name_between(void) {
258 /* see https://tools.ietf.org/html/rfc4034#section-6.1
259 Note that we use "\033.z.example" in stead of "\001.z.example" as we
260 consider the latter invalid */
261 test_dns_name_between_one("example", "a.example", "yljkjljk.a.example", true);
262 test_dns_name_between_one("a.example", "yljkjljk.a.example", "Z.a.example", true);
263 test_dns_name_between_one("yljkjljk.a.example", "Z.a.example", "zABC.a.EXAMPLE", true);
264 test_dns_name_between_one("Z.a.example", "zABC.a.EXAMPLE", "z.example", true);
265 test_dns_name_between_one("zABC.a.EXAMPLE", "z.example", "\\033.z.example", true);
266 test_dns_name_between_one("z.example", "\\033.z.example", "*.z.example", true);
267 test_dns_name_between_one("\\033.z.example", "*.z.example", "\\200.z.example", true);
268 test_dns_name_between_one("*.z.example", "\\200.z.example", "example", true);
269 test_dns_name_between_one("\\200.z.example", "example", "a.example", true);
270
271 test_dns_name_between_one("example", "a.example", "example", true);
272 test_dns_name_between_one("example", "example", "example", false);
273 test_dns_name_between_one("example", "example", "yljkjljk.a.example", false);
274 test_dns_name_between_one("example", "yljkjljk.a.example", "yljkjljk.a.example", false);
275 test_dns_name_between_one("hkps.pool.sks-keyservers.net", "_pgpkey-https._tcp.hkps.pool.sks-keyservers.net", "ipv4.pool.sks-keyservers.net", true);
276 }
277
278 static void test_dns_name_endswith_one(const char *a, const char *b, int ret) {
279 assert_se(dns_name_endswith(a, b) == ret);
280 }
281
282 static void test_dns_name_endswith(void) {
283 test_dns_name_endswith_one("", "", true);
284 test_dns_name_endswith_one("", "xxx", false);
285 test_dns_name_endswith_one("xxx", "", true);
286 test_dns_name_endswith_one("x", "x", true);
287 test_dns_name_endswith_one("x", "y", false);
288 test_dns_name_endswith_one("x.y", "y", true);
289 test_dns_name_endswith_one("x.y", "Y", true);
290 test_dns_name_endswith_one("x.y", "x", false);
291 test_dns_name_endswith_one("x.y.z", "Z", true);
292 test_dns_name_endswith_one("x.y.z", "y.Z", true);
293 test_dns_name_endswith_one("x.y.z", "x.y.Z", true);
294 test_dns_name_endswith_one("x.y.z", "waldo", false);
295 test_dns_name_endswith_one("x.y.z.u.v.w", "y.z", false);
296 test_dns_name_endswith_one("x.y.z.u.v.w", "u.v.w", true);
297 test_dns_name_endswith_one("x.y\001.z", "waldo", -EINVAL);
298 }
299
300 static void test_dns_name_startswith_one(const char *a, const char *b, int ret) {
301 assert_se(dns_name_startswith(a, b) == ret);
302 }
303
304 static void test_dns_name_startswith(void) {
305 test_dns_name_startswith_one("", "", true);
306 test_dns_name_startswith_one("", "xxx", false);
307 test_dns_name_startswith_one("xxx", "", true);
308 test_dns_name_startswith_one("x", "x", true);
309 test_dns_name_startswith_one("x", "y", false);
310 test_dns_name_startswith_one("x.y", "x.y", true);
311 test_dns_name_startswith_one("x.y", "y.x", false);
312 test_dns_name_startswith_one("x.y", "x", true);
313 test_dns_name_startswith_one("x.y", "X", true);
314 test_dns_name_startswith_one("x.y", "y", false);
315 test_dns_name_startswith_one("x.y", "", true);
316 test_dns_name_startswith_one("x.y", "X", true);
317 }
318
319 static void test_dns_name_is_root(void) {
320 assert_se(dns_name_is_root(""));
321 assert_se(dns_name_is_root("."));
322 assert_se(!dns_name_is_root("xxx"));
323 assert_se(!dns_name_is_root("xxx."));
324 assert_se(!dns_name_is_root(".."));
325 }
326
327 static void test_dns_name_is_single_label(void) {
328 assert_se(!dns_name_is_single_label(""));
329 assert_se(!dns_name_is_single_label("."));
330 assert_se(!dns_name_is_single_label(".."));
331 assert_se(dns_name_is_single_label("x"));
332 assert_se(dns_name_is_single_label("x."));
333 assert_se(!dns_name_is_single_label("xx.yy"));
334 }
335
336 static void test_dns_name_reverse_one(const char *address, const char *name) {
337 _cleanup_free_ char *p = NULL;
338 union in_addr_union a, b = {};
339 int familya, familyb;
340
341 assert_se(in_addr_from_string_auto(address, &familya, &a) >= 0);
342 assert_se(dns_name_reverse(familya, &a, &p) >= 0);
343 assert_se(streq(p, name));
344 assert_se(dns_name_address(p, &familyb, &b) > 0);
345 assert_se(familya == familyb);
346 assert_se(in_addr_equal(familya, &a, &b));
347 }
348
349 static void test_dns_name_reverse(void) {
350 test_dns_name_reverse_one("47.11.8.15", "15.8.11.47.in-addr.arpa");
351 test_dns_name_reverse_one("fe80::47", "7.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa");
352 test_dns_name_reverse_one("127.0.0.1", "1.0.0.127.in-addr.arpa");
353 test_dns_name_reverse_one("::1", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa");
354 }
355
356 static void test_dns_name_concat_one(const char *a, const char *b, int r, const char *result) {
357 _cleanup_free_ char *p = NULL;
358
359 assert_se(dns_name_concat(a, b, 0, &p) == r);
360 assert_se(streq_ptr(p, result));
361 }
362
363 static void test_dns_name_concat(void) {
364 test_dns_name_concat_one("", "", 0, ".");
365 test_dns_name_concat_one(".", "", 0, ".");
366 test_dns_name_concat_one("", ".", 0, ".");
367 test_dns_name_concat_one(".", ".", 0, ".");
368 test_dns_name_concat_one("foo", "bar", 0, "foo.bar");
369 test_dns_name_concat_one("foo.foo", "bar.bar", 0, "foo.foo.bar.bar");
370 test_dns_name_concat_one("foo", NULL, 0, "foo");
371 test_dns_name_concat_one("foo", ".", 0, "foo");
372 test_dns_name_concat_one("foo.", "bar.", 0, "foo.bar");
373 test_dns_name_concat_one(NULL, NULL, 0, ".");
374 test_dns_name_concat_one(NULL, ".", 0, ".");
375 test_dns_name_concat_one(NULL, "foo", 0, "foo");
376 }
377
378 static void test_dns_name_is_valid_one(const char *s, int ret, int ret_ldh) {
379 log_info("%s, →%d", s, ret);
380
381 assert_se(dns_name_is_valid(s) == ret);
382 assert_se(dns_name_is_valid_ldh(s) == ret_ldh);
383 }
384
385 static void test_dns_name_is_valid(void) {
386 log_info("/* %s */", __func__);
387
388 test_dns_name_is_valid_one("foo", 1, 1);
389 test_dns_name_is_valid_one("foo.", 1, 1);
390 test_dns_name_is_valid_one("foo..", 0, 0);
391 test_dns_name_is_valid_one("Foo", 1, 1);
392 test_dns_name_is_valid_one("foo.bar", 1, 1);
393 test_dns_name_is_valid_one("foo.bar.baz", 1, 1);
394 test_dns_name_is_valid_one("", 1, 1);
395 test_dns_name_is_valid_one("foo..bar", 0, 0);
396 test_dns_name_is_valid_one(".foo.bar", 0, 0);
397 test_dns_name_is_valid_one("foo.bar.", 1, 1);
398 test_dns_name_is_valid_one("foo.bar..", 0, 0);
399 test_dns_name_is_valid_one("\\zbar", 0, 0);
400 test_dns_name_is_valid_one("ä", 1, 0);
401 test_dns_name_is_valid_one("\n", 0, 0);
402
403 test_dns_name_is_valid_one("dash-", 1, 0);
404 test_dns_name_is_valid_one("-dash", 1, 0);
405 test_dns_name_is_valid_one("dash-dash", 1, 1);
406 test_dns_name_is_valid_one("foo.dash-", 1, 0);
407 test_dns_name_is_valid_one("foo.-dash", 1, 0);
408 test_dns_name_is_valid_one("foo.dash-dash", 1, 1);
409 test_dns_name_is_valid_one("foo.dash-.bar", 1, 0);
410 test_dns_name_is_valid_one("foo.-dash.bar", 1, 0);
411 test_dns_name_is_valid_one("foo.dash-dash.bar", 1, 1);
412 test_dns_name_is_valid_one("dash-.bar", 1, 0);
413 test_dns_name_is_valid_one("-dash.bar", 1, 0);
414 test_dns_name_is_valid_one("dash-dash.bar", 1, 1);
415 test_dns_name_is_valid_one("-.bar", 1, 0);
416 test_dns_name_is_valid_one("foo.-", 1, 0);
417
418 /* 256 characters */
419 test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345", 0, 0);
420
421 /* 255 characters */
422 test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a1234", 0, 0);
423
424 /* 254 characters */
425 test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a123", 0, 0);
426
427 /* 253 characters */
428 test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12", 1, 1);
429
430 /* label of 64 chars length */
431 test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a123", 0, 0);
432
433 /* label of 63 chars length */
434 test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a12", 1, 1);
435 }
436
437 static void test_dns_service_name_is_valid(void) {
438 log_info("/* %s */", __func__);
439
440 assert_se(dns_service_name_is_valid("Lennart's Compüter"));
441 assert_se(dns_service_name_is_valid("piff.paff"));
442
443 assert_se(!dns_service_name_is_valid(NULL));
444 assert_se(!dns_service_name_is_valid(""));
445 assert_se(!dns_service_name_is_valid("foo\nbar"));
446 assert_se(!dns_service_name_is_valid("foo\201bar"));
447 assert_se(!dns_service_name_is_valid("this is an overly long string that is certainly longer than 63 characters"));
448 }
449
450 static void test_dns_srv_type_is_valid(void) {
451 log_info("/* %s */", __func__);
452
453 assert_se(dns_srv_type_is_valid("_http._tcp"));
454 assert_se(dns_srv_type_is_valid("_foo-bar._tcp"));
455 assert_se(dns_srv_type_is_valid("_w._udp"));
456 assert_se(dns_srv_type_is_valid("_a800._tcp"));
457 assert_se(dns_srv_type_is_valid("_a-800._tcp"));
458
459 assert_se(!dns_srv_type_is_valid(NULL));
460 assert_se(!dns_srv_type_is_valid(""));
461 assert_se(!dns_srv_type_is_valid("x"));
462 assert_se(!dns_srv_type_is_valid("_foo"));
463 assert_se(!dns_srv_type_is_valid("_tcp"));
464 assert_se(!dns_srv_type_is_valid("_"));
465 assert_se(!dns_srv_type_is_valid("_foo."));
466 assert_se(!dns_srv_type_is_valid("_föo._tcp"));
467 assert_se(!dns_srv_type_is_valid("_f\no._tcp"));
468 assert_se(!dns_srv_type_is_valid("_800._tcp"));
469 assert_se(!dns_srv_type_is_valid("_-800._tcp"));
470 assert_se(!dns_srv_type_is_valid("_-foo._tcp"));
471 assert_se(!dns_srv_type_is_valid("_piep._foo._udp"));
472 }
473
474 static void test_dnssd_srv_type_is_valid(void) {
475 log_info("/* %s */", __func__);
476
477 assert_se(dnssd_srv_type_is_valid("_http._tcp"));
478 assert_se(dnssd_srv_type_is_valid("_foo-bar._tcp"));
479 assert_se(dnssd_srv_type_is_valid("_w._udp"));
480 assert_se(dnssd_srv_type_is_valid("_a800._tcp"));
481 assert_se(dnssd_srv_type_is_valid("_a-800._tcp"));
482
483 assert_se(!dnssd_srv_type_is_valid(NULL));
484 assert_se(!dnssd_srv_type_is_valid(""));
485 assert_se(!dnssd_srv_type_is_valid("x"));
486 assert_se(!dnssd_srv_type_is_valid("_foo"));
487 assert_se(!dnssd_srv_type_is_valid("_tcp"));
488 assert_se(!dnssd_srv_type_is_valid("_"));
489 assert_se(!dnssd_srv_type_is_valid("_foo."));
490 assert_se(!dnssd_srv_type_is_valid("_föo._tcp"));
491 assert_se(!dnssd_srv_type_is_valid("_f\no._tcp"));
492 assert_se(!dnssd_srv_type_is_valid("_800._tcp"));
493 assert_se(!dnssd_srv_type_is_valid("_-800._tcp"));
494 assert_se(!dnssd_srv_type_is_valid("_-foo._tcp"));
495 assert_se(!dnssd_srv_type_is_valid("_piep._foo._udp"));
496 assert_se(!dnssd_srv_type_is_valid("_foo._unknown"));
497 }
498
499 static void test_dns_service_join_one(const char *a, const char *b, const char *c, int r, const char *d) {
500 _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL;
501
502 log_info("%s, %s, %s, →%d, %s", a, b, c, r, d);
503
504 assert_se(dns_service_join(a, b, c, &t) == r);
505 assert_se(streq_ptr(t, d));
506
507 if (r < 0)
508 return;
509
510 assert_se(dns_service_split(t, &x, &y, &z) >= 0);
511 assert_se(streq_ptr(a, x));
512 assert_se(streq_ptr(b, y));
513 assert_se(dns_name_equal(c, z) > 0);
514 }
515
516 static void test_dns_service_join(void) {
517 log_info("/* %s */", __func__);
518
519 test_dns_service_join_one("", "", "", -EINVAL, NULL);
520 test_dns_service_join_one("", "_http._tcp", "", -EINVAL, NULL);
521 test_dns_service_join_one("", "_http._tcp", "foo", -EINVAL, NULL);
522 test_dns_service_join_one("foo", "", "foo", -EINVAL, NULL);
523 test_dns_service_join_one("foo", "foo", "foo", -EINVAL, NULL);
524
525 test_dns_service_join_one("foo", "_http._tcp", "", 0, "foo._http._tcp");
526 test_dns_service_join_one(NULL, "_http._tcp", "", 0, "_http._tcp");
527 test_dns_service_join_one("foo", "_http._tcp", "foo", 0, "foo._http._tcp.foo");
528 test_dns_service_join_one(NULL, "_http._tcp", "foo", 0, "_http._tcp.foo");
529 test_dns_service_join_one("Lennart's PC", "_pc._tcp", "foo.bar.com", 0, "Lennart\\039s\\032PC._pc._tcp.foo.bar.com");
530 test_dns_service_join_one(NULL, "_pc._tcp", "foo.bar.com", 0, "_pc._tcp.foo.bar.com");
531 }
532
533 static void test_dns_service_split_one(const char *joined, const char *a, const char *b, const char *c, int r) {
534 _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL;
535
536 log_info("%s, %s, %s, %s, →%d", joined, a, b, c, r);
537
538 assert_se(dns_service_split(joined, &x, &y, &z) == r);
539 assert_se(streq_ptr(x, a));
540 assert_se(streq_ptr(y, b));
541 assert_se(streq_ptr(z, c));
542
543 if (r < 0)
544 return;
545
546 if (y) {
547 assert_se(dns_service_join(x, y, z, &t) == 0);
548 assert_se(dns_name_equal(joined, t) > 0);
549 } else
550 assert_se(!x && dns_name_equal(z, joined) > 0);
551 }
552
553 static void test_dns_service_split(void) {
554 log_info("/* %s */", __func__);
555
556 test_dns_service_split_one("", NULL, NULL, ".", 0);
557 test_dns_service_split_one("foo", NULL, NULL, "foo", 0);
558 test_dns_service_split_one("foo.bar", NULL, NULL, "foo.bar", 0);
559 test_dns_service_split_one("_foo.bar", NULL, NULL, "_foo.bar", 0);
560 test_dns_service_split_one("_foo._bar", NULL, "_foo._bar", ".", 0);
561 test_dns_service_split_one("_meh._foo._bar", "_meh", "_foo._bar", ".", 0);
562 test_dns_service_split_one("Wuff\\032Wuff._foo._bar.waldo.com", "Wuff Wuff", "_foo._bar", "waldo.com", 0);
563 }
564
565 static void test_dns_name_change_suffix_one(const char *name, const char *old_suffix, const char *new_suffix, int r, const char *result) {
566 _cleanup_free_ char *s = NULL;
567
568 log_info("%s, %s, %s, →%s", name, old_suffix, new_suffix, result);
569
570 assert_se(dns_name_change_suffix(name, old_suffix, new_suffix, &s) == r);
571 assert_se(streq_ptr(s, result));
572 }
573
574 static void test_dns_name_change_suffix(void) {
575 log_info("/* %s */", __func__);
576
577 test_dns_name_change_suffix_one("foo.bar", "bar", "waldo", 1, "foo.waldo");
578 test_dns_name_change_suffix_one("foo.bar.waldi.quux", "foo.bar.waldi.quux", "piff.paff", 1, "piff.paff");
579 test_dns_name_change_suffix_one("foo.bar.waldi.quux", "bar.waldi.quux", "piff.paff", 1, "foo.piff.paff");
580 test_dns_name_change_suffix_one("foo.bar.waldi.quux", "waldi.quux", "piff.paff", 1, "foo.bar.piff.paff");
581 test_dns_name_change_suffix_one("foo.bar.waldi.quux", "quux", "piff.paff", 1, "foo.bar.waldi.piff.paff");
582 test_dns_name_change_suffix_one("foo.bar.waldi.quux", "", "piff.paff", 1, "foo.bar.waldi.quux.piff.paff");
583 test_dns_name_change_suffix_one("", "", "piff.paff", 1, "piff.paff");
584 test_dns_name_change_suffix_one("", "", "", 1, ".");
585 test_dns_name_change_suffix_one("a", "b", "c", 0, NULL);
586 }
587
588 static void test_dns_name_suffix_one(const char *name, unsigned n_labels, const char *result, int ret) {
589 const char *p = NULL;
590
591 log_info("%s, %d, →%s, %d", name, n_labels, result, ret);
592
593 assert_se(ret == dns_name_suffix(name, n_labels, &p));
594 assert_se(streq_ptr(p, result));
595 }
596
597 static void test_dns_name_suffix(void) {
598 log_info("/* %s */", __func__);
599
600 test_dns_name_suffix_one("foo.bar", 2, "foo.bar", 0);
601 test_dns_name_suffix_one("foo.bar", 1, "bar", 1);
602 test_dns_name_suffix_one("foo.bar", 0, "", 2);
603 test_dns_name_suffix_one("foo.bar", 3, NULL, -EINVAL);
604 test_dns_name_suffix_one("foo.bar", 4, NULL, -EINVAL);
605
606 test_dns_name_suffix_one("bar", 1, "bar", 0);
607 test_dns_name_suffix_one("bar", 0, "", 1);
608 test_dns_name_suffix_one("bar", 2, NULL, -EINVAL);
609 test_dns_name_suffix_one("bar", 3, NULL, -EINVAL);
610
611 test_dns_name_suffix_one("", 0, "", 0);
612 test_dns_name_suffix_one("", 1, NULL, -EINVAL);
613 test_dns_name_suffix_one("", 2, NULL, -EINVAL);
614 }
615
616 static void test_dns_name_count_labels_one(const char *name, int n) {
617 log_info("%s, →%d", name, n);
618
619 assert_se(dns_name_count_labels(name) == n);
620 }
621
622 static void test_dns_name_count_labels(void) {
623 log_info("/* %s */", __func__);
624
625 test_dns_name_count_labels_one("foo.bar.quux.", 3);
626 test_dns_name_count_labels_one("foo.bar.quux", 3);
627 test_dns_name_count_labels_one("foo.bar.", 2);
628 test_dns_name_count_labels_one("foo.bar", 2);
629 test_dns_name_count_labels_one("foo.", 1);
630 test_dns_name_count_labels_one("foo", 1);
631 test_dns_name_count_labels_one("", 0);
632 test_dns_name_count_labels_one(".", 0);
633 test_dns_name_count_labels_one("..", -EINVAL);
634 }
635
636 static void test_dns_name_equal_skip_one(const char *a, unsigned n_labels, const char *b, int ret) {
637 log_info("%s, %u, %s, →%d", a, n_labels, b, ret);
638
639 assert_se(dns_name_equal_skip(a, n_labels, b) == ret);
640 }
641
642 static void test_dns_name_equal_skip(void) {
643 log_info("/* %s */", __func__);
644
645 test_dns_name_equal_skip_one("foo", 0, "bar", 0);
646 test_dns_name_equal_skip_one("foo", 0, "foo", 1);
647 test_dns_name_equal_skip_one("foo", 1, "foo", 0);
648 test_dns_name_equal_skip_one("foo", 2, "foo", 0);
649
650 test_dns_name_equal_skip_one("foo.bar", 0, "foo.bar", 1);
651 test_dns_name_equal_skip_one("foo.bar", 1, "foo.bar", 0);
652 test_dns_name_equal_skip_one("foo.bar", 2, "foo.bar", 0);
653 test_dns_name_equal_skip_one("foo.bar", 3, "foo.bar", 0);
654
655 test_dns_name_equal_skip_one("foo.bar", 0, "bar", 0);
656 test_dns_name_equal_skip_one("foo.bar", 1, "bar", 1);
657 test_dns_name_equal_skip_one("foo.bar", 2, "bar", 0);
658 test_dns_name_equal_skip_one("foo.bar", 3, "bar", 0);
659
660 test_dns_name_equal_skip_one("foo.bar", 0, "", 0);
661 test_dns_name_equal_skip_one("foo.bar", 1, "", 0);
662 test_dns_name_equal_skip_one("foo.bar", 2, "", 1);
663 test_dns_name_equal_skip_one("foo.bar", 3, "", 0);
664
665 test_dns_name_equal_skip_one("", 0, "", 1);
666 test_dns_name_equal_skip_one("", 1, "", 0);
667 test_dns_name_equal_skip_one("", 1, "foo", 0);
668 test_dns_name_equal_skip_one("", 2, "foo", 0);
669 }
670
671 static void test_dns_name_compare_func(void) {
672 log_info("/* %s */", __func__);
673
674 assert_se(dns_name_compare_func("", "") == 0);
675 assert_se(dns_name_compare_func("", ".") == 0);
676 assert_se(dns_name_compare_func(".", "") == 0);
677 assert_se(dns_name_compare_func("foo", "foo.") == 0);
678 assert_se(dns_name_compare_func("foo.", "foo") == 0);
679 assert_se(dns_name_compare_func("foo", "foo") == 0);
680 assert_se(dns_name_compare_func("foo.", "foo.") == 0);
681 assert_se(dns_name_compare_func("heise.de", "HEISE.DE.") == 0);
682
683 assert_se(dns_name_compare_func("de.", "heise.de") != 0);
684 }
685
686 static void test_dns_name_common_suffix_one(const char *a, const char *b, const char *result) {
687 const char *c;
688
689 log_info("%s, %s, →%s", a, b, result);
690
691 assert_se(dns_name_common_suffix(a, b, &c) >= 0);
692 assert_se(streq(c, result));
693 }
694
695 static void test_dns_name_common_suffix(void) {
696 log_info("/* %s */", __func__);
697
698 test_dns_name_common_suffix_one("", "", "");
699 test_dns_name_common_suffix_one("foo", "", "");
700 test_dns_name_common_suffix_one("", "foo", "");
701 test_dns_name_common_suffix_one("foo", "bar", "");
702 test_dns_name_common_suffix_one("bar", "foo", "");
703 test_dns_name_common_suffix_one("foo", "foo", "foo");
704 test_dns_name_common_suffix_one("quux.foo", "foo", "foo");
705 test_dns_name_common_suffix_one("foo", "quux.foo", "foo");
706 test_dns_name_common_suffix_one("this.is.a.short.sentence", "this.is.another.short.sentence", "short.sentence");
707 test_dns_name_common_suffix_one("FOO.BAR", "tEST.bAR", "BAR");
708 }
709
710 static void test_dns_name_apply_idna_one(const char *s, int expected, const char *result) {
711 _cleanup_free_ char *buf = NULL;
712 int r;
713
714 r = dns_name_apply_idna(s, &buf);
715 log_debug("dns_name_apply_idna: \"%s\" → %d/\"%s\" (expected %d/\"%s\")",
716 s, r, strnull(buf), expected, strnull(result));
717
718 /* Different libidn2 versions are more and less accepting
719 * of underscore-prefixed names. So let's list the lowest
720 * expected return value. */
721 assert_se(r >= expected);
722 if (expected == 1)
723 assert_se(dns_name_equal(buf, result) == 1);
724 }
725
726 static void test_dns_name_apply_idna(void) {
727 #if HAVE_LIBIDN2 || HAVE_LIBIDN
728 const int ret = 1;
729 #else
730 const int ret = 0;
731 #endif
732 log_info("/* %s */", __func__);
733
734 /* IDNA2008 forbids names with hyphens in third and fourth positions
735 * (https://tools.ietf.org/html/rfc5891#section-4.2.3.1).
736 * IDNA2003 does not have this restriction
737 * (https://tools.ietf.org/html/rfc3490#section-5).
738 * This means that when using libidn we will transform and test more
739 * labels. If registrars follow IDNA2008 we'll just be performing a
740 * useless lookup.
741 */
742 #if HAVE_LIBIDN
743 const int ret2 = 1;
744 #else
745 const int ret2 = 0;
746 #endif
747
748 test_dns_name_apply_idna_one("", ret, "");
749 test_dns_name_apply_idna_one("foo", ret, "foo");
750 test_dns_name_apply_idna_one("foo.", ret, "foo");
751 test_dns_name_apply_idna_one("foo.bar", ret, "foo.bar");
752 test_dns_name_apply_idna_one("foo.bar.", ret, "foo.bar");
753 test_dns_name_apply_idna_one("föö", ret, "xn--f-1gaa");
754 test_dns_name_apply_idna_one("föö.", ret, "xn--f-1gaa");
755 test_dns_name_apply_idna_one("föö.bär", ret, "xn--f-1gaa.xn--br-via");
756 test_dns_name_apply_idna_one("föö.bär.", ret, "xn--f-1gaa.xn--br-via");
757 test_dns_name_apply_idna_one("xn--f-1gaa.xn--br-via", ret, "xn--f-1gaa.xn--br-via");
758
759 test_dns_name_apply_idna_one("_443._tcp.fedoraproject.org", ret2,
760 "_443._tcp.fedoraproject.org");
761 test_dns_name_apply_idna_one("_443", ret2, "_443");
762 test_dns_name_apply_idna_one("gateway", ret, "gateway");
763 test_dns_name_apply_idna_one("_gateway", ret2, "_gateway");
764
765 test_dns_name_apply_idna_one("r3---sn-ab5l6ne7.googlevideo.com", ret2,
766 ret2 ? "r3---sn-ab5l6ne7.googlevideo.com" : "");
767 }
768
769 static void test_dns_name_is_valid_or_address(void) {
770 log_info("/* %s */", __func__);
771
772 assert_se(dns_name_is_valid_or_address(NULL) == 0);
773 assert_se(dns_name_is_valid_or_address("") == 0);
774 assert_se(dns_name_is_valid_or_address("foobar") > 0);
775 assert_se(dns_name_is_valid_or_address("foobar.com") > 0);
776 assert_se(dns_name_is_valid_or_address("foobar..com") == 0);
777 assert_se(dns_name_is_valid_or_address("foobar.com.") > 0);
778 assert_se(dns_name_is_valid_or_address("127.0.0.1") > 0);
779 assert_se(dns_name_is_valid_or_address("::") > 0);
780 assert_se(dns_name_is_valid_or_address("::1") > 0);
781 }
782
783 static void test_dns_name_dot_suffixed(void) {
784 log_info("/* %s */", __func__);
785
786 assert_se(dns_name_dot_suffixed("") == 0);
787 assert_se(dns_name_dot_suffixed(".") > 0);
788 assert_se(dns_name_dot_suffixed("foo") == 0);
789 assert_se(dns_name_dot_suffixed("foo.") > 0);
790 assert_se(dns_name_dot_suffixed("foo\\..") > 0);
791 assert_se(dns_name_dot_suffixed("foo\\.") == 0);
792 assert_se(dns_name_dot_suffixed("foo.bar.") > 0);
793 assert_se(dns_name_dot_suffixed("foo.bar\\.\\.\\..") > 0);
794 assert_se(dns_name_dot_suffixed("foo.bar\\.\\.\\.\\.") == 0);
795 }
796
797 int main(int argc, char *argv[]) {
798 test_setup_logging(LOG_DEBUG);
799
800 test_dns_label_unescape();
801 test_dns_label_unescape_suffix();
802 test_dns_label_escape();
803 test_dns_name_normalize();
804 test_dns_name_equal();
805 test_dns_name_endswith();
806 test_dns_name_startswith();
807 test_dns_name_between();
808 test_dns_name_is_root();
809 test_dns_name_is_single_label();
810 test_dns_name_reverse();
811 test_dns_name_concat();
812 test_dns_name_is_valid();
813 test_dns_name_to_wire_format();
814 test_dns_service_name_is_valid();
815 test_dns_srv_type_is_valid();
816 test_dnssd_srv_type_is_valid();
817 test_dns_service_join();
818 test_dns_service_split();
819 test_dns_name_change_suffix();
820 test_dns_name_suffix();
821 test_dns_name_count_labels();
822 test_dns_name_equal_skip();
823 test_dns_name_compare_func();
824 test_dns_name_common_suffix();
825 test_dns_name_apply_idna();
826 test_dns_name_is_valid_or_address();
827 test_dns_name_dot_suffixed();
828
829 return 0;
830 }