]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-in-addr-util.c
license: LGPL-2.1+ -> LGPL-2.1-or-later
[thirdparty/systemd.git] / src / test / test-in-addr-util.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
f4912f3a 2
e762ea74 3#include <fnmatch.h>
f4912f3a
LP
4#include <netinet/in.h>
5
9e0fdc21 6#include "log.h"
e762ea74 7#include "strv.h"
f4912f3a
LP
8#include "in-addr-util.h"
9
146cf7f0 10static void test_in_addr_prefix_from_string_one(
9e0fdc21
YW
11 const char *p,
12 int family,
13 int ret,
14 const union in_addr_union *u,
15 unsigned char prefixlen,
16 int ret_refuse,
17 unsigned char prefixlen_refuse,
18 int ret_legacy,
19 unsigned char prefixlen_legacy) {
20
f4912f3a
LP
21 union in_addr_union q;
22 unsigned char l;
9e0fdc21 23 int f, r;
f4912f3a 24
9e0fdc21 25 r = in_addr_prefix_from_string(p, family, &q, &l);
f4912f3a
LP
26 assert_se(r == ret);
27
9e0fdc21
YW
28 if (r < 0)
29 return;
30
31 assert_se(in_addr_equal(family, &q, u));
32 assert_se(l == prefixlen);
33
34 r = in_addr_prefix_from_string_auto(p, &f, &q, &l);
35 assert_se(r >= 0);
36
37 assert_se(f == family);
38 assert_se(in_addr_equal(family, &q, u));
39 assert_se(l == prefixlen);
40
41 r = in_addr_prefix_from_string_auto_internal(p, PREFIXLEN_REFUSE, &f, &q, &l);
42 assert_se(r == ret_refuse);
f4912f3a 43
9e0fdc21
YW
44 if (r >= 0) {
45 assert_se(f == family);
f4912f3a 46 assert_se(in_addr_equal(family, &q, u));
9e0fdc21
YW
47 assert_se(l == prefixlen_refuse);
48 }
f4912f3a 49
9e0fdc21
YW
50 r = in_addr_prefix_from_string_auto_internal(p, PREFIXLEN_LEGACY, &f, &q, &l);
51 assert_se(r == ret_legacy);
f4912f3a 52
9e0fdc21 53 if (r >= 0) {
f4912f3a
LP
54 assert_se(f == family);
55 assert_se(in_addr_equal(family, &q, u));
9e0fdc21 56 assert_se(l == prefixlen_legacy);
f4912f3a
LP
57 }
58}
59
146cf7f0 60static void test_in_addr_prefix_from_string(void) {
38c30b35
ZJS
61 log_info("/* %s */", __func__);
62
146cf7f0
YW
63 test_in_addr_prefix_from_string_one("", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
64 test_in_addr_prefix_from_string_one("/", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
65 test_in_addr_prefix_from_string_one("/8", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
66 test_in_addr_prefix_from_string_one("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, -ENOANO, 0, 0, 8);
67 test_in_addr_prefix_from_string_one("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0, 0, 0, 0, 0);
68 test_in_addr_prefix_from_string_one("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1, 0, 1, 0, 1);
69 test_in_addr_prefix_from_string_one("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2, 0, 2, 0, 2);
70 test_in_addr_prefix_from_string_one("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, 0, 32, 0, 32);
71 test_in_addr_prefix_from_string_one("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
72 test_in_addr_prefix_from_string_one("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
73 test_in_addr_prefix_from_string_one("::1", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
74
75 test_in_addr_prefix_from_string_one("", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
76 test_in_addr_prefix_from_string_one("/", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
77 test_in_addr_prefix_from_string_one("/8", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
78 test_in_addr_prefix_from_string_one("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, -ENOANO, 0, 0, 0);
79 test_in_addr_prefix_from_string_one("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, 0, 0, 0, 0);
80 test_in_addr_prefix_from_string_one("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, 0, 1, 0, 1);
81 test_in_addr_prefix_from_string_one("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, 0, 2, 0, 2);
82 test_in_addr_prefix_from_string_one("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, 0, 32, 0, 32);
83 test_in_addr_prefix_from_string_one("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, 0, 33, 0, 33);
84 test_in_addr_prefix_from_string_one("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, 0, 64, 0, 64);
85 test_in_addr_prefix_from_string_one("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, 0, 128, 0, 128);
86 test_in_addr_prefix_from_string_one("::1/129", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
87 test_in_addr_prefix_from_string_one("::1/-1", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
88}
89
9201eea1
YW
90static void test_in_addr_prefix_to_string_valid(int family, const char *p) {
91 _cleanup_free_ char *str = NULL;
92 union in_addr_union u;
93 unsigned char l;
94
38c30b35 95 log_info("%s: %s", __func__, p);
9201eea1
YW
96
97 assert_se(in_addr_prefix_from_string(p, family, &u, &l) >= 0);
98 assert_se(in_addr_prefix_to_string(family, &u, l, &str) >= 0);
99 assert_se(streq(str, p));
100}
101
102static void test_in_addr_prefix_to_string_unoptimized(int family, const char *p) {
103 _cleanup_free_ char *str1 = NULL, *str2 = NULL;
104 union in_addr_union u1, u2;
105 unsigned char len1, len2;
106
38c30b35 107 log_info("%s: %s", __func__, p);
9201eea1
YW
108
109 assert_se(in_addr_prefix_from_string(p, family, &u1, &len1) >= 0);
110 assert_se(in_addr_prefix_to_string(family, &u1, len1, &str1) >= 0);
111 assert_se(in_addr_prefix_from_string(str1, family, &u2, &len2) >= 0);
112 assert_se(in_addr_prefix_to_string(family, &u2, len2, &str2) >= 0);
113
114 assert_se(streq(str1, str2));
115 assert_se(len1 == len2);
116 assert_se(in_addr_equal(family, &u1, &u2) > 0);
117}
118
119static void test_in_addr_prefix_to_string(void) {
38c30b35
ZJS
120 log_info("/* %s */", __func__);
121
9201eea1
YW
122 test_in_addr_prefix_to_string_valid(AF_INET, "0.0.0.0/32");
123 test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/0");
124 test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/24");
125 test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/32");
126 test_in_addr_prefix_to_string_valid(AF_INET, "255.255.255.255/32");
127
128 test_in_addr_prefix_to_string_valid(AF_INET6, "::1/128");
129 test_in_addr_prefix_to_string_valid(AF_INET6, "fd00:abcd::1/64");
130 test_in_addr_prefix_to_string_valid(AF_INET6, "fd00:abcd::1234:1/64");
131 test_in_addr_prefix_to_string_valid(AF_INET6, "1111:2222:3333:4444:5555:6666:7777:8888/128");
132
133 test_in_addr_prefix_to_string_unoptimized(AF_INET, "0.0.0.0");
134 test_in_addr_prefix_to_string_unoptimized(AF_INET, "192.168.0.1");
135
136 test_in_addr_prefix_to_string_unoptimized(AF_INET6, "fd00:0000:0000:0000:0000:0000:0000:0001/64");
137 test_in_addr_prefix_to_string_unoptimized(AF_INET6, "fd00:1111::0000:2222:3333:4444:0001/64");
138}
139
e762ea74
YW
140static void test_in_addr_random_prefix(void) {
141 _cleanup_free_ char *str = NULL;
142 union in_addr_union a;
143
38c30b35
ZJS
144 log_info("/* %s */", __func__);
145
e762ea74
YW
146 assert_se(in_addr_from_string(AF_INET, "192.168.10.1", &a) >= 0);
147
148 assert_se(in_addr_random_prefix(AF_INET, &a, 31, 32) >= 0);
149 assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
150 assert_se(STR_IN_SET(str, "192.168.10.0", "192.168.10.1"));
151 str = mfree(str);
152
153 assert_se(in_addr_random_prefix(AF_INET, &a, 24, 26) >= 0);
154 assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
155 assert_se(startswith(str, "192.168.10."));
156 str = mfree(str);
157
158 assert_se(in_addr_random_prefix(AF_INET, &a, 16, 24) >= 0);
159 assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
160 assert_se(fnmatch("192.168.[0-9]*.0", str, 0) == 0);
161 str = mfree(str);
162
163 assert_se(in_addr_random_prefix(AF_INET, &a, 8, 24) >= 0);
164 assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
165 assert_se(fnmatch("192.[0-9]*.[0-9]*.0", str, 0) == 0);
166 str = mfree(str);
167
168 assert_se(in_addr_random_prefix(AF_INET, &a, 8, 16) >= 0);
169 assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
170 assert_se(fnmatch("192.[0-9]*.0.0", str, 0) == 0);
171 str = mfree(str);
172
173 assert_se(in_addr_from_string(AF_INET6, "fd00::1", &a) >= 0);
174
175 assert_se(in_addr_random_prefix(AF_INET6, &a, 16, 64) >= 0);
176 assert_se(in_addr_to_string(AF_INET6, &a, &str) >= 0);
177 assert_se(startswith(str, "fd00:"));
178 str = mfree(str);
179
180 assert_se(in_addr_random_prefix(AF_INET6, &a, 8, 16) >= 0);
181 assert_se(in_addr_to_string(AF_INET6, &a, &str) >= 0);
182 assert_se(fnmatch("fd??::", str, 0) == 0);
183 str = mfree(str);
184}
185
23c5aeaa
YW
186static void test_in_addr_is_null(void) {
187 union in_addr_union i = {};
188
189 log_info("/* %s */", __func__);
190
191 assert_se(in_addr_is_null(AF_INET, &i) == true);
192 assert_se(in_addr_is_null(AF_INET6, &i) == true);
193
194 i.in.s_addr = 0x1000000;
195 assert_se(in_addr_is_null(AF_INET, &i) == false);
196 assert_se(in_addr_is_null(AF_INET6, &i) == false);
197
198 assert_se(in_addr_is_null(-1, &i) == -EAFNOSUPPORT);
199}
200
201static void test_in_addr_prefix_intersect_one(unsigned f, const char *a, unsigned apl, const char *b, unsigned bpl, int result) {
202 union in_addr_union ua, ub;
203
204 assert_se(in_addr_from_string(f, a, &ua) >= 0);
205 assert_se(in_addr_from_string(f, b, &ub) >= 0);
206
207 assert_se(in_addr_prefix_intersect(f, &ua, apl, &ub, bpl) == result);
208}
209
210static void test_in_addr_prefix_intersect(void) {
211 log_info("/* %s */", __func__);
212
213 test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 32, "255.255.255.254", 32, 0);
214 test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 0, "255.255.255.255", 32, 1);
215 test_in_addr_prefix_intersect_one(AF_INET, "0.0.0.0", 0, "47.11.8.15", 32, 1);
216
217 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.1", 24, 1);
218 test_in_addr_prefix_intersect_one(AF_INET, "2.2.2.2", 24, "1.1.1.1", 24, 0);
219
220 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 25, 1);
221 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 26, 1);
222 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.127", 25, 1);
223 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.255", 25, 0);
224
225 test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", 128, 0);
226 test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1);
227 test_in_addr_prefix_intersect_one(AF_INET6, "::", 0, "beef:beef:beef:beef:beef:beef:beef:beef", 128, 1);
228
229 test_in_addr_prefix_intersect_one(AF_INET6, "1::2", 64, "1::2", 64, 1);
230 test_in_addr_prefix_intersect_one(AF_INET6, "2::2", 64, "1::2", 64, 0);
231
232 test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 121, 1);
233 test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 122, 1);
234 test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::007f", 121, 1);
235 test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::00ff", 121, 0);
236}
237
238static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) {
239 union in_addr_union ubefore, uafter, t;
240
241 assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
242
243 t = ubefore;
244 assert_se((in_addr_prefix_next(f, &t, pl) > 0) == !!after);
245
246 if (after) {
247 assert_se(in_addr_from_string(f, after, &uafter) >= 0);
248 assert_se(in_addr_equal(f, &t, &uafter) > 0);
249 }
250}
251
252static void test_in_addr_prefix_next(void) {
253 log_info("/* %s */", __func__);
254
255 test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0");
256 test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0");
257 test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0");
258
259 test_in_addr_prefix_next_one(AF_INET, "0.0.0.0", 32, "0.0.0.1");
260 test_in_addr_prefix_next_one(AF_INET, "255.255.255.255", 32, NULL);
261 test_in_addr_prefix_next_one(AF_INET, "255.255.255.0", 24, NULL);
262
263 test_in_addr_prefix_next_one(AF_INET6, "4400::", 128, "4400::0001");
264 test_in_addr_prefix_next_one(AF_INET6, "4400::", 120, "4400::0100");
265 test_in_addr_prefix_next_one(AF_INET6, "4400::", 127, "4400::0002");
266 test_in_addr_prefix_next_one(AF_INET6, "4400::", 8, "4500::");
267 test_in_addr_prefix_next_one(AF_INET6, "4400::", 7, "4600::");
268
269 test_in_addr_prefix_next_one(AF_INET6, "::", 128, "::1");
270
271 test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, NULL);
272 test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00", 120, NULL);
273}
274
275static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned pl, uint64_t nth, const char *after) {
276 union in_addr_union ubefore, uafter, t;
277
278 assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
279
280 t = ubefore;
281 assert_se((in_addr_prefix_nth(f, &t, pl, nth) > 0) == !!after);
282
283 if (after) {
284 assert_se(in_addr_from_string(f, after, &uafter) >= 0);
285 assert_se(in_addr_equal(f, &t, &uafter) > 0);
286 }
287}
288
289static void test_in_addr_prefix_nth(void) {
290 log_info("/* %s */", __func__);
291
292 test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 0, "192.168.0.0");
293 test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 1, "192.168.1.0");
294 test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 4, "192.168.4.0");
295 test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 25, 1, "192.168.0.128");
296 test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 25, 1, "192.168.255.128");
297 test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 24, 0, "192.168.255.0");
298 test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 32, 1, NULL);
299 test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 0, 1, NULL);
300
301 test_in_addr_prefix_nth_one(AF_INET6, "4400::", 8, 1, "4500::");
302 test_in_addr_prefix_nth_one(AF_INET6, "4400::", 7, 1, "4600::");
303 test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 1, "4400:0:0:1::");
304 test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 2, "4400:0:0:2::");
305 test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 0xbad, "4400:0:0:0bad::");
306 test_in_addr_prefix_nth_one(AF_INET6, "4400:0:0:ffff::", 64, 1, "4400:0:1::");
307 test_in_addr_prefix_nth_one(AF_INET6, "4400::", 56, ((uint64_t)1<<48) -1, "44ff:ffff:ffff:ff00::");
308 test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 255, "ff00::");
309 test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 256, NULL);
310 test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1, NULL);
311 test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, 1, NULL);
312}
313
314static void test_in_addr_to_string_one(int f, const char *addr) {
315 union in_addr_union ua;
316 _cleanup_free_ char *r = NULL;
317
318 assert_se(in_addr_from_string(f, addr, &ua) >= 0);
319 assert_se(in_addr_to_string(f, &ua, &r) >= 0);
320 printf("test_in_addr_to_string_one: %s == %s\n", addr, r);
321 assert_se(streq(addr, r));
322}
323
324static void test_in_addr_to_string(void) {
325 log_info("/* %s */", __func__);
326
327 test_in_addr_to_string_one(AF_INET, "192.168.0.1");
328 test_in_addr_to_string_one(AF_INET, "10.11.12.13");
329 test_in_addr_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
330 test_in_addr_to_string_one(AF_INET6, "::1");
331 test_in_addr_to_string_one(AF_INET6, "fe80::");
332}
333
f4912f3a 334int main(int argc, char *argv[]) {
146cf7f0 335 test_in_addr_prefix_from_string();
e762ea74 336 test_in_addr_random_prefix();
9201eea1 337 test_in_addr_prefix_to_string();
23c5aeaa
YW
338 test_in_addr_is_null();
339 test_in_addr_prefix_intersect();
340 test_in_addr_prefix_next();
341 test_in_addr_prefix_nth();
342 test_in_addr_to_string();
e762ea74 343
f4912f3a
LP
344 return 0;
345}