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