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