]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-dns-domain.c
dns-domain: add dns_name_to_wire_format()
[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 int main(int argc, char *argv[]) {
320
321 test_dns_label_unescape();
322 test_dns_label_unescape_suffix();
323 test_dns_label_escape();
324 test_dns_name_normalize();
325 test_dns_name_equal();
326 test_dns_name_endswith();
327 test_dns_name_between();
328 test_dns_name_root();
329 test_dns_name_single_label();
330 test_dns_name_reverse();
331 test_dns_name_concat();
332 test_dns_name_is_valid();
333 test_dns_name_to_wire_format();
334
335 return 0;
336 }