]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-dns-domain.c
Merge pull request #2007 from poettering/resolve-srv
[thirdparty/systemd.git] / src / test / test-dns-domain.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "alloc-util.h"
23 #include "dns-domain.h"
24 #include "macro.h"
25 #include "string-util.h"
26
27 static void test_dns_label_unescape_one(const char *what, const char *expect, size_t buffer_sz, int ret) {
28 char buffer[buffer_sz];
29 int r;
30
31 r = dns_label_unescape(&what, buffer, buffer_sz);
32 assert_se(r == ret);
33
34 if (r < 0)
35 return;
36
37 assert_se(streq(buffer, expect));
38 }
39
40 static void test_dns_label_unescape(void) {
41 test_dns_label_unescape_one("hallo", "hallo", 6, 5);
42 test_dns_label_unescape_one("hallo", "hallo", 4, -ENOSPC);
43 test_dns_label_unescape_one("", "", 10, 0);
44 test_dns_label_unescape_one("hallo\\.foobar", "hallo.foobar", 20, 12);
45 test_dns_label_unescape_one("hallo.foobar", "hallo", 10, 5);
46 test_dns_label_unescape_one("hallo\n.foobar", "hallo", 20, -EINVAL);
47 test_dns_label_unescape_one("hallo\\", "hallo", 20, -EINVAL);
48 test_dns_label_unescape_one("hallo\\032 ", "hallo ", 20, 7);
49 test_dns_label_unescape_one(".", "", 20, 0);
50 test_dns_label_unescape_one("..", "", 20, -EINVAL);
51 test_dns_label_unescape_one(".foobar", "", 20, -EINVAL);
52 test_dns_label_unescape_one("foobar.", "foobar", 20, 6);
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);
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 const char out1[] = { 3, 'f', 'o', 'o', 0 };
70 const char out2[] = { 5, 'h', 'a', 'l', 'l', 'o', 3, 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
71 const char out3[] = { 4, ' ', 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
72
73 test_dns_name_to_wire_format_one("", NULL, 0, -EINVAL);
74
75 test_dns_name_to_wire_format_one("foo", out1, sizeof(out1), sizeof(out1));
76 test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) + 1, sizeof(out1));
77 test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) - 1, -ENOBUFS);
78
79 test_dns_name_to_wire_format_one("hallo.foo.bar", out2, sizeof(out2), sizeof(out2));
80 test_dns_name_to_wire_format_one("hallo.foo..bar", NULL, 32, -EINVAL);
81
82 test_dns_name_to_wire_format_one("\\032foo.bar", out3, sizeof(out3), sizeof(out3));
83 }
84
85 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) {
86 char buffer[buffer_sz];
87 const char *label;
88 int r;
89
90 label = what + strlen(what);
91
92 r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz);
93 assert_se(r == ret1);
94 if (r >= 0)
95 assert_se(streq(buffer, expect1));
96
97 r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz);
98 assert_se(r == ret2);
99 if (r >= 0)
100 assert_se(streq(buffer, expect2));
101 }
102
103 static void test_dns_label_unescape_suffix(void) {
104 test_dns_label_unescape_suffix_one("hallo", "hallo", "", 6, 5, 0);
105 test_dns_label_unescape_suffix_one("hallo", "hallo", "", 4, -ENOSPC, -ENOSPC);
106 test_dns_label_unescape_suffix_one("", "", "", 10, 0, 0);
107 test_dns_label_unescape_suffix_one("hallo\\.foobar", "hallo.foobar", "", 20, 12, 0);
108 test_dns_label_unescape_suffix_one("hallo.foobar", "foobar", "hallo", 10, 6, 5);
109 test_dns_label_unescape_suffix_one("hallo.foobar\n", "foobar", "foobar", 20, -EINVAL, -EINVAL);
110 test_dns_label_unescape_suffix_one("hallo\\", "hallo", "hallo", 20, -EINVAL, -EINVAL);
111 test_dns_label_unescape_suffix_one("hallo\\032 ", "hallo ", "", 20, 7, 0);
112 test_dns_label_unescape_suffix_one(".", "", "", 20, 0, 0);
113 test_dns_label_unescape_suffix_one("..", "", "", 20, 0, 0);
114 test_dns_label_unescape_suffix_one(".foobar", "foobar", "", 20, 6, -EINVAL);
115 test_dns_label_unescape_suffix_one("foobar.", "", "foobar", 20, 0, 6);
116 test_dns_label_unescape_suffix_one("foo\\\\bar", "foo\\bar", "", 20, 7, 0);
117 test_dns_label_unescape_suffix_one("foo.bar", "bar", "foo", 20, 3, 3);
118 test_dns_label_unescape_suffix_one("foo..bar", "bar", "", 20, 3, -EINVAL);
119 test_dns_label_unescape_suffix_one("foo...bar", "bar", "", 20, 3, -EINVAL);
120 test_dns_label_unescape_suffix_one("foo\\.bar", "foo.bar", "", 20, 7, 0);
121 test_dns_label_unescape_suffix_one("foo\\\\.bar", "bar", "foo\\", 20, 3, 4);
122 test_dns_label_unescape_suffix_one("foo\\\\\\.bar", "foo\\.bar", "", 20, 8, 0);
123 }
124
125 static void test_dns_label_escape_one(const char *what, size_t l, const char *expect, int ret) {
126 _cleanup_free_ char *t = NULL;
127 int r;
128
129 r = dns_label_escape(what, l, &t);
130 assert_se(r == ret);
131
132 if (r < 0)
133 return;
134
135 assert_se(streq_ptr(expect, t));
136 }
137
138 static void test_dns_label_escape(void) {
139 test_dns_label_escape_one("", 0, "", 0);
140 test_dns_label_escape_one("hallo", 5, "hallo", 5);
141 test_dns_label_escape_one("hallo", 6, NULL, -EINVAL);
142 test_dns_label_escape_one("hallo hallo.foobar,waldi", 24, "hallo\\032hallo\\.foobar\\044waldi", 31);
143 }
144
145 static void test_dns_name_normalize_one(const char *what, const char *expect, int ret) {
146 _cleanup_free_ char *t = NULL;
147 int r;
148
149 r = dns_name_normalize(what, &t);
150 assert_se(r == ret);
151
152 if (r < 0)
153 return;
154
155 assert_se(streq_ptr(expect, t));
156 }
157
158 static void test_dns_name_normalize(void) {
159 test_dns_name_normalize_one("", "", 0);
160 test_dns_name_normalize_one("f", "f", 0);
161 test_dns_name_normalize_one("f.waldi", "f.waldi", 0);
162 test_dns_name_normalize_one("f \\032.waldi", "f\\032\\032.waldi", 0);
163 test_dns_name_normalize_one("\\000", NULL, -EINVAL);
164 test_dns_name_normalize_one("..", NULL, -EINVAL);
165 test_dns_name_normalize_one(".foobar", NULL, -EINVAL);
166 test_dns_name_normalize_one("foobar.", "foobar", 0);
167 test_dns_name_normalize_one(".", "", 0);
168 }
169
170 static void test_dns_name_equal_one(const char *a, const char *b, int ret) {
171 int r;
172
173 r = dns_name_equal(a, b);
174 assert_se(r == ret);
175
176 r = dns_name_equal(b, a);
177 assert_se(r == ret);
178 }
179
180 static void test_dns_name_equal(void) {
181 test_dns_name_equal_one("", "", true);
182 test_dns_name_equal_one("x", "x", true);
183 test_dns_name_equal_one("x", "x.", true);
184 test_dns_name_equal_one("abc.def", "abc.def", true);
185 test_dns_name_equal_one("abc.def", "ABC.def", true);
186 test_dns_name_equal_one("abc.def", "CBA.def", false);
187 test_dns_name_equal_one("", "xxx", false);
188 test_dns_name_equal_one("ab", "a", false);
189 test_dns_name_equal_one("\\000", "xxxx", -EINVAL);
190 test_dns_name_equal_one(".", "", true);
191 test_dns_name_equal_one(".", ".", true);
192 test_dns_name_equal_one("..", "..", -EINVAL);
193 }
194
195 static void test_dns_name_between_one(const char *a, const char *b, const char *c, int ret) {
196 int r;
197
198 r = dns_name_between(a, b, c);
199 assert_se(r == ret);
200
201 r = dns_name_between(c, b, a);
202 if (ret >= 0)
203 assert_se(r == 0);
204 else
205 assert_se(r == ret);
206 }
207
208 static void test_dns_name_between(void) {
209 /* see https://tools.ietf.org/html/rfc4034#section-6.1
210 Note that we use "\033.z.example" in stead of "\001.z.example" as we
211 consider the latter invalid */
212 test_dns_name_between_one("example", "a.example", "yljkjljk.a.example", true);
213 test_dns_name_between_one("a.example", "yljkjljk.a.example", "Z.a.example", true);
214 test_dns_name_between_one("yljkjljk.a.example", "Z.a.example", "zABC.a.EXAMPLE", true);
215 test_dns_name_between_one("Z.a.example", "zABC.a.EXAMPLE", "z.example", true);
216 test_dns_name_between_one("zABC.a.EXAMPLE", "z.example", "\\033.z.example", true);
217 test_dns_name_between_one("z.example", "\\033.z.example", "*.z.example", true);
218 test_dns_name_between_one("\\033.z.example", "*.z.example", "\\200.z.example", true);
219 test_dns_name_between_one("*.z.example", "\\200.z.example", "example", true);
220 test_dns_name_between_one("\\200.z.example", "example", "a.example", true);
221
222 test_dns_name_between_one("example", "a.example", "example", -EINVAL);
223 test_dns_name_between_one("example", "example", "yljkjljk.a.example", false);
224 test_dns_name_between_one("example", "yljkjljk.a.example", "yljkjljk.a.example", false);
225 }
226
227 static void test_dns_name_endswith_one(const char *a, const char *b, int ret) {
228 assert_se(dns_name_endswith(a, b) == ret);
229 }
230
231 static void test_dns_name_endswith(void) {
232 test_dns_name_endswith_one("", "", true);
233 test_dns_name_endswith_one("", "xxx", false);
234 test_dns_name_endswith_one("xxx", "", true);
235 test_dns_name_endswith_one("x", "x", true);
236 test_dns_name_endswith_one("x", "y", false);
237 test_dns_name_endswith_one("x.y", "y", true);
238 test_dns_name_endswith_one("x.y", "Y", true);
239 test_dns_name_endswith_one("x.y", "x", false);
240 test_dns_name_endswith_one("x.y.z", "Z", true);
241 test_dns_name_endswith_one("x.y.z", "y.Z", true);
242 test_dns_name_endswith_one("x.y.z", "x.y.Z", true);
243 test_dns_name_endswith_one("x.y.z", "waldo", false);
244 test_dns_name_endswith_one("x.y.z.u.v.w", "y.z", false);
245 test_dns_name_endswith_one("x.y.z.u.v.w", "u.v.w", true);
246 test_dns_name_endswith_one("x.y\001.z", "waldo", -EINVAL);
247 }
248
249 static void test_dns_name_root(void) {
250 assert_se(dns_name_root("") == true);
251 assert_se(dns_name_root(".") == true);
252 assert_se(dns_name_root("xxx") == false);
253 assert_se(dns_name_root("xxx.") == false);
254 assert_se(dns_name_root("..") == -EINVAL);
255 }
256
257 static void test_dns_name_single_label(void) {
258 assert_se(dns_name_single_label("") == false);
259 assert_se(dns_name_single_label(".") == false);
260 assert_se(dns_name_single_label("..") == -EINVAL);
261 assert_se(dns_name_single_label("x") == true);
262 assert_se(dns_name_single_label("x.") == true);
263 assert_se(dns_name_single_label("xx.yy") == false);
264 }
265
266 static void test_dns_name_reverse_one(const char *address, const char *name) {
267 _cleanup_free_ char *p = NULL;
268 union in_addr_union a, b = {};
269 int familya, familyb;
270
271 assert_se(in_addr_from_string_auto(address, &familya, &a) >= 0);
272 assert_se(dns_name_reverse(familya, &a, &p) >= 0);
273 assert_se(streq(p, name));
274 assert_se(dns_name_address(p, &familyb, &b) > 0);
275 assert_se(familya == familyb);
276 assert_se(in_addr_equal(familya, &a, &b));
277 }
278
279 static void test_dns_name_reverse(void) {
280 test_dns_name_reverse_one("47.11.8.15", "15.8.11.47.in-addr.arpa");
281 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");
282 test_dns_name_reverse_one("127.0.0.1", "1.0.0.127.in-addr.arpa");
283 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");
284 }
285
286 static void test_dns_name_concat_one(const char *a, const char *b, int r, const char *result) {
287 _cleanup_free_ char *p = NULL;
288
289 assert_se(dns_name_concat(a, b, &p) == r);
290 assert_se(streq_ptr(p, result));
291 }
292
293 static void test_dns_name_concat(void) {
294 test_dns_name_concat_one("foo", "bar", 0, "foo.bar");
295 test_dns_name_concat_one("foo.foo", "bar.bar", 0, "foo.foo.bar.bar");
296 test_dns_name_concat_one("foo", NULL, 0, "foo");
297 test_dns_name_concat_one("foo.", "bar.", 0, "foo.bar");
298 }
299
300 static void test_dns_name_is_valid_one(const char *s, int ret) {
301 assert_se(dns_name_is_valid(s) == ret);
302 }
303
304 static void test_dns_name_is_valid(void) {
305 test_dns_name_is_valid_one("foo", 1);
306 test_dns_name_is_valid_one("foo.", 1);
307 test_dns_name_is_valid_one("Foo", 1);
308 test_dns_name_is_valid_one("foo.bar", 1);
309 test_dns_name_is_valid_one("foo.bar.baz", 1);
310 test_dns_name_is_valid_one("", 1);
311 test_dns_name_is_valid_one("foo..bar", 0);
312 test_dns_name_is_valid_one(".foo.bar", 0);
313 test_dns_name_is_valid_one("foo.bar.", 1);
314 test_dns_name_is_valid_one("\\zbar", 0);
315 test_dns_name_is_valid_one("ä", 1);
316 test_dns_name_is_valid_one("\n", 0);
317 }
318
319 static void test_dns_service_name_is_valid(void) {
320 assert_se(dns_service_name_is_valid("Lennart's Compüter"));
321 assert_se(dns_service_name_is_valid("piff.paff"));
322
323 assert_se(!dns_service_name_is_valid(NULL));
324 assert_se(!dns_service_name_is_valid(""));
325 assert_se(!dns_service_name_is_valid("foo\nbar"));
326 assert_se(!dns_service_name_is_valid("foo\201bar"));
327 assert_se(!dns_service_name_is_valid("this is an overly long string that is certainly longer than 63 characters"));
328 }
329
330 static void test_dns_srv_type_verify(void) {
331
332 assert_se(dns_srv_type_verify("_http._tcp") > 0);
333 assert_se(dns_srv_type_verify("_foo-bar._tcp") > 0);
334 assert_se(dns_srv_type_verify("_w._udp") > 0);
335 assert_se(dns_srv_type_verify("_a800._tcp") > 0);
336 assert_se(dns_srv_type_verify("_a-800._tcp") > 0);
337
338 assert_se(dns_srv_type_verify(NULL) == 0);
339 assert_se(dns_srv_type_verify("") == 0);
340 assert_se(dns_srv_type_verify("x") == 0);
341 assert_se(dns_srv_type_verify("_foo") == 0);
342 assert_se(dns_srv_type_verify("_tcp") == 0);
343 assert_se(dns_srv_type_verify("_") == 0);
344 assert_se(dns_srv_type_verify("_foo.") == 0);
345 assert_se(dns_srv_type_verify("_föo._tcp") == 0);
346 assert_se(dns_srv_type_verify("_f\no._tcp") == 0);
347 assert_se(dns_srv_type_verify("_800._tcp") == 0);
348 assert_se(dns_srv_type_verify("_-800._tcp") == 0);
349 assert_se(dns_srv_type_verify("_-foo._tcp") == 0);
350 assert_se(dns_srv_type_verify("_piep._foo._udp") == 0);
351 }
352
353 static void test_dns_service_join_one(const char *a, const char *b, const char *c, int r, const char *d) {
354 _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL;
355
356 assert_se(dns_service_join(a, b, c, &t) == r);
357 assert_se(streq_ptr(t, d));
358
359 if (r < 0)
360 return;
361
362 assert_se(dns_service_split(t, &x, &y, &z) >= 0);
363 assert_se(streq_ptr(a, x));
364 assert_se(streq_ptr(b, y));
365 assert_se(streq_ptr(c, z));
366 }
367
368 static void test_dns_service_join(void) {
369 test_dns_service_join_one("", "", "", -EINVAL, NULL);
370 test_dns_service_join_one("", "_http._tcp", "", -EINVAL, NULL);
371 test_dns_service_join_one("", "_http._tcp", "foo", -EINVAL, NULL);
372 test_dns_service_join_one("foo", "", "foo", -EINVAL, NULL);
373 test_dns_service_join_one("foo", "foo", "foo", -EINVAL, NULL);
374
375 test_dns_service_join_one("foo", "_http._tcp", "", 0, "foo._http._tcp");
376 test_dns_service_join_one(NULL, "_http._tcp", "", 0, "_http._tcp");
377 test_dns_service_join_one("foo", "_http._tcp", "foo", 0, "foo._http._tcp.foo");
378 test_dns_service_join_one(NULL, "_http._tcp", "foo", 0, "_http._tcp.foo");
379 test_dns_service_join_one("Lennart's PC", "_pc._tcp", "foo.bar.com", 0, "Lennart\\039s\\032PC._pc._tcp.foo.bar.com");
380 test_dns_service_join_one(NULL, "_pc._tcp", "foo.bar.com", 0, "_pc._tcp.foo.bar.com");
381 }
382
383 static void test_dns_service_split_one(const char *joined, const char *a, const char *b, const char *c, int r) {
384 _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL;
385
386 assert_se(dns_service_split(joined, &x, &y, &z) == r);
387 assert_se(streq_ptr(x, a));
388 assert_se(streq_ptr(y, b));
389 assert_se(streq_ptr(z, c));
390
391 if (r < 0)
392 return;
393
394 if (y) {
395 assert_se(dns_service_join(x, y, z, &t) == 0);
396 assert_se(streq_ptr(joined, t));
397 } else
398 assert_se(!x && streq_ptr(z, joined));
399 }
400
401 static void test_dns_service_split(void) {
402 test_dns_service_split_one("", NULL, NULL, "", 0);
403 test_dns_service_split_one("foo", NULL, NULL, "foo", 0);
404 test_dns_service_split_one("foo.bar", NULL, NULL, "foo.bar", 0);
405 test_dns_service_split_one("_foo.bar", NULL, NULL, "_foo.bar", 0);
406 test_dns_service_split_one("_foo._bar", NULL, "_foo._bar", "", 0);
407 test_dns_service_split_one("_meh._foo._bar", "_meh", "_foo._bar", "", 0);
408 test_dns_service_split_one("Wuff\\032Wuff._foo._bar.waldo.com", "Wuff Wuff", "_foo._bar", "waldo.com", 0);
409 }
410
411 int main(int argc, char *argv[]) {
412
413 test_dns_label_unescape();
414 test_dns_label_unescape_suffix();
415 test_dns_label_escape();
416 test_dns_name_normalize();
417 test_dns_name_equal();
418 test_dns_name_endswith();
419 test_dns_name_between();
420 test_dns_name_root();
421 test_dns_name_single_label();
422 test_dns_name_reverse();
423 test_dns_name_concat();
424 test_dns_name_is_valid();
425 test_dns_name_to_wire_format();
426 test_dns_service_name_is_valid();
427 test_dns_srv_type_verify();
428 test_dns_service_join();
429 test_dns_service_split();
430
431 return 0;
432 }