]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-in-addr-util.c
769cb8f083b686b9a781dfc93bcbbeb687a6943a
[thirdparty/systemd.git] / src / test / test-in-addr-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <fnmatch.h>
4 #include <netinet/in.h>
5
6 #include "in-addr-util.h"
7 #include "strv.h"
8 #include "tests.h"
9
10 static void test_in_addr_prefix_from_string_one(
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
19 union in_addr_union q;
20 unsigned char l;
21 int f, r;
22
23 r = in_addr_prefix_from_string(p, family, &q, &l);
24 assert_se(r == ret);
25
26 if (r < 0)
27 return;
28
29 assert_se(in_addr_equal(family, &q, u));
30 assert_se(l == prefixlen);
31
32 r = in_addr_prefix_from_string_auto(p, &f, &q, &l);
33 assert_se(r >= 0);
34
35 assert_se(f == family);
36 assert_se(in_addr_equal(family, &q, u));
37 assert_se(l == prefixlen);
38
39 r = in_addr_prefix_from_string_auto_full(p, PREFIXLEN_REFUSE, &f, &q, &l);
40 assert_se(r == ret_refuse);
41
42 if (r >= 0) {
43 assert_se(f == family);
44 assert_se(in_addr_equal(family, &q, u));
45 assert_se(l == prefixlen_refuse);
46 }
47 }
48
49 TEST(in_addr_prefix_from_string) {
50 test_in_addr_prefix_from_string_one("", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0);
51 test_in_addr_prefix_from_string_one("/", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0);
52 test_in_addr_prefix_from_string_one("/8", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0);
53 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);
54 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);
55 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);
56 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);
57 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);
58 test_in_addr_prefix_from_string_one("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0);
59 test_in_addr_prefix_from_string_one("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0);
60 test_in_addr_prefix_from_string_one("::1", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0);
61
62 test_in_addr_prefix_from_string_one("", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0);
63 test_in_addr_prefix_from_string_one("/", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0);
64 test_in_addr_prefix_from_string_one("/8", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0);
65 test_in_addr_prefix_from_string_one("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, -ENOANO, 0);
66 test_in_addr_prefix_from_string_one("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, 0, 0);
67 test_in_addr_prefix_from_string_one("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, 0, 1);
68 test_in_addr_prefix_from_string_one("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, 0, 2);
69 test_in_addr_prefix_from_string_one("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, 0, 32);
70 test_in_addr_prefix_from_string_one("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, 0, 33);
71 test_in_addr_prefix_from_string_one("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, 0, 64);
72 test_in_addr_prefix_from_string_one("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, 0, 128);
73 test_in_addr_prefix_from_string_one("::1/129", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0);
74 test_in_addr_prefix_from_string_one("::1/-1", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0);
75 }
76
77 static void test_in_addr_prefix_to_string_valid(int family, const char *p) {
78 union in_addr_union u;
79 unsigned char l;
80
81 log_info("%s: %s", __func__, p);
82
83 assert_se(in_addr_prefix_from_string(p, family, &u, &l) >= 0);
84 ASSERT_STREQ(p, IN_ADDR_PREFIX_TO_STRING(family, &u, l));
85 }
86
87 static void test_in_addr_prefix_to_string_unoptimized(int family, const char *p) {
88 union in_addr_union u1, u2;
89 unsigned char len1, len2;
90
91 log_info("%s: %s", __func__, p);
92
93 assert_se(in_addr_prefix_from_string(p, family, &u1, &len1) >= 0);
94 const char *str1 = IN_ADDR_PREFIX_TO_STRING(family, &u1, len1);
95 assert_se(str1);
96 assert_se(in_addr_prefix_from_string(str1, family, &u2, &len2) >= 0);
97 const char *str2 = IN_ADDR_PREFIX_TO_STRING(family, &u2, len2);
98 assert_se(str2);
99
100 ASSERT_STREQ(str1, str2);
101 assert_se(len1 == len2);
102 assert_se(in_addr_equal(family, &u1, &u2) > 0);
103 }
104
105 TEST(in_addr_prefix_to_string) {
106 test_in_addr_prefix_to_string_valid(AF_INET, "0.0.0.0/32");
107 test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/0");
108 test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/24");
109 test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/32");
110 test_in_addr_prefix_to_string_valid(AF_INET, "255.255.255.255/32");
111
112 test_in_addr_prefix_to_string_valid(AF_INET6, "::1/128");
113 test_in_addr_prefix_to_string_valid(AF_INET6, "fd00:abcd::1/64");
114 test_in_addr_prefix_to_string_valid(AF_INET6, "fd00:abcd::1234:1/64");
115 test_in_addr_prefix_to_string_valid(AF_INET6, "1111:2222:3333:4444:5555:6666:7777:8888/128");
116
117 test_in_addr_prefix_to_string_unoptimized(AF_INET, "0.0.0.0");
118 test_in_addr_prefix_to_string_unoptimized(AF_INET, "192.168.0.1");
119
120 test_in_addr_prefix_to_string_unoptimized(AF_INET6, "fd00:0000:0000:0000:0000:0000:0000:0001/64");
121 test_in_addr_prefix_to_string_unoptimized(AF_INET6, "fd00:1111::0000:2222:3333:4444:0001/64");
122 }
123
124 TEST(in_addr_random_prefix) {
125 _cleanup_free_ char *str = NULL;
126 union in_addr_union a;
127
128 assert_se(in_addr_from_string(AF_INET, "192.168.10.1", &a) >= 0);
129
130 assert_se(in_addr_random_prefix(AF_INET, &a, 31, 32) >= 0);
131 assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
132 assert_se(STR_IN_SET(str, "192.168.10.0", "192.168.10.1"));
133 str = mfree(str);
134
135 assert_se(in_addr_random_prefix(AF_INET, &a, 24, 26) >= 0);
136 assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
137 assert_se(startswith(str, "192.168.10."));
138 str = mfree(str);
139
140 assert_se(in_addr_random_prefix(AF_INET, &a, 16, 24) >= 0);
141 assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
142 assert_se(fnmatch("192.168.[0-9]*.0", str, 0) == 0);
143 str = mfree(str);
144
145 assert_se(in_addr_random_prefix(AF_INET, &a, 8, 24) >= 0);
146 assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
147 assert_se(fnmatch("192.[0-9]*.[0-9]*.0", str, 0) == 0);
148 str = mfree(str);
149
150 assert_se(in_addr_random_prefix(AF_INET, &a, 8, 16) >= 0);
151 assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
152 assert_se(fnmatch("192.[0-9]*.0.0", str, 0) == 0);
153 str = mfree(str);
154
155 assert_se(in_addr_from_string(AF_INET6, "fd00::1", &a) >= 0);
156
157 assert_se(in_addr_random_prefix(AF_INET6, &a, 16, 64) >= 0);
158 assert_se(in_addr_to_string(AF_INET6, &a, &str) >= 0);
159 assert_se(startswith(str, "fd00:"));
160 str = mfree(str);
161
162 assert_se(in_addr_random_prefix(AF_INET6, &a, 8, 16) >= 0);
163 assert_se(in_addr_to_string(AF_INET6, &a, &str) >= 0);
164 assert_se(fnmatch("fd??::", str, 0) == 0);
165 str = mfree(str);
166 }
167
168 TEST(in_addr_is_null) {
169 union in_addr_union i = {};
170
171 assert_se(in_addr_is_null(AF_INET, &i) == true);
172 assert_se(in_addr_is_null(AF_INET6, &i) == true);
173
174 i.in.s_addr = 0x1000000;
175 assert_se(in_addr_is_null(AF_INET, &i) == false);
176 assert_se(in_addr_is_null(AF_INET6, &i) == false);
177
178 assert_se(in_addr_is_null(-1, &i) == -EAFNOSUPPORT);
179 }
180
181 static void test_in_addr_prefix_intersect_one(unsigned f, const char *a, unsigned apl, const char *b, unsigned bpl, int result) {
182 union in_addr_union ua, ub;
183
184 assert_se(in_addr_from_string(f, a, &ua) >= 0);
185 assert_se(in_addr_from_string(f, b, &ub) >= 0);
186
187 assert_se(in_addr_prefix_intersect(f, &ua, apl, &ub, bpl) == result);
188 }
189
190 TEST(in_addr_prefix_intersect) {
191 test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 32, "255.255.255.254", 32, 0);
192 test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 0, "255.255.255.255", 32, 1);
193 test_in_addr_prefix_intersect_one(AF_INET, "0.0.0.0", 0, "47.11.8.15", 32, 1);
194
195 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.1", 24, 1);
196 test_in_addr_prefix_intersect_one(AF_INET, "2.2.2.2", 24, "1.1.1.1", 24, 0);
197
198 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 25, 1);
199 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 26, 1);
200 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.127", 25, 1);
201 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.255", 25, 0);
202
203 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);
204 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);
205 test_in_addr_prefix_intersect_one(AF_INET6, "::", 0, "beef:beef:beef:beef:beef:beef:beef:beef", 128, 1);
206
207 test_in_addr_prefix_intersect_one(AF_INET6, "1::2", 64, "1::2", 64, 1);
208 test_in_addr_prefix_intersect_one(AF_INET6, "2::2", 64, "1::2", 64, 0);
209
210 test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 121, 1);
211 test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 122, 1);
212 test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::007f", 121, 1);
213 test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::00ff", 121, 0);
214 }
215
216 static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) {
217 union in_addr_union ubefore, uafter, t;
218
219 log_debug("/* %s(%s, prefixlen=%u) */", __func__, before, pl);
220
221 assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
222
223 t = ubefore;
224 assert_se((in_addr_prefix_next(f, &t, pl) >= 0) == !!after);
225
226 if (after) {
227 assert_se(in_addr_from_string(f, after, &uafter) >= 0);
228 assert_se(in_addr_equal(f, &t, &uafter) > 0);
229 }
230 }
231
232 TEST(in_addr_prefix_next) {
233 test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0");
234 test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0");
235 test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0");
236
237 test_in_addr_prefix_next_one(AF_INET, "0.0.0.0", 32, "0.0.0.1");
238 test_in_addr_prefix_next_one(AF_INET, "255.255.255.254", 32, "255.255.255.255");
239 test_in_addr_prefix_next_one(AF_INET, "255.255.255.255", 32, NULL);
240 test_in_addr_prefix_next_one(AF_INET, "255.255.255.0", 24, NULL);
241
242 test_in_addr_prefix_next_one(AF_INET6, "4400::", 128, "4400::0001");
243 test_in_addr_prefix_next_one(AF_INET6, "4400::", 120, "4400::0100");
244 test_in_addr_prefix_next_one(AF_INET6, "4400::", 127, "4400::0002");
245 test_in_addr_prefix_next_one(AF_INET6, "4400::", 8, "4500::");
246 test_in_addr_prefix_next_one(AF_INET6, "4400::", 7, "4600::");
247
248 test_in_addr_prefix_next_one(AF_INET6, "::", 128, "::1");
249
250 test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, NULL);
251 test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00", 120, NULL);
252 }
253
254 static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned pl, uint64_t nth, const char *after) {
255 union in_addr_union ubefore, uafter, t;
256
257 log_debug("/* %s(%s, prefixlen=%u, nth=%"PRIu64") */", __func__, before, pl, nth);
258
259 assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
260
261 t = ubefore;
262 assert_se((in_addr_prefix_nth(f, &t, pl, nth) >= 0) == !!after);
263
264 if (after) {
265 assert_se(in_addr_from_string(f, after, &uafter) >= 0);
266 assert_se(in_addr_equal(f, &t, &uafter) > 0);
267 }
268 }
269
270 TEST(in_addr_prefix_nth) {
271 test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 0, "192.168.0.0");
272 test_in_addr_prefix_nth_one(AF_INET, "192.168.0.123", 24, 0, "192.168.0.0");
273 test_in_addr_prefix_nth_one(AF_INET, "192.168.0.123", 24, 1, "192.168.1.0");
274 test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 4, "192.168.4.0");
275 test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 25, 1, "192.168.0.128");
276 test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 25, 1, "192.168.255.128");
277 test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 24, 0, "192.168.255.0");
278 test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 32, 1, NULL);
279 test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 0, 1, NULL);
280
281 test_in_addr_prefix_nth_one(AF_INET6, "4400::", 8, 1, "4500::");
282 test_in_addr_prefix_nth_one(AF_INET6, "4400::", 7, 1, "4600::");
283 test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 1, "4400:0:0:1::");
284 test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 2, "4400:0:0:2::");
285 test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 0xbad, "4400:0:0:0bad::");
286 test_in_addr_prefix_nth_one(AF_INET6, "4400:0:0:ffff::", 64, 1, "4400:0:1::");
287 test_in_addr_prefix_nth_one(AF_INET6, "4400::", 56, ((uint64_t)1<<48) -1, "44ff:ffff:ffff:ff00::");
288 test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 255, "ff00::");
289 test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 256, NULL);
290 test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1, NULL);
291 test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, 1, NULL);
292 test_in_addr_prefix_nth_one(AF_INET6, "1234:5678:90ab:cdef:1234:5678:90ab:cdef", 12, 1, "1240::");
293 }
294
295 static void test_in_addr_prefix_range_one(
296 int family,
297 const char *in,
298 unsigned prefixlen,
299 const char *expected_start,
300 const char *expected_end) {
301
302 union in_addr_union a, s, e;
303
304 log_debug("/* %s(%s, prefixlen=%u) */", __func__, in, prefixlen);
305
306 assert_se(in_addr_from_string(family, in, &a) >= 0);
307 assert_se((in_addr_prefix_range(family, &a, prefixlen, &s, &e) >= 0) == !!expected_start);
308
309 if (expected_start) {
310 union in_addr_union es;
311
312 assert_se(in_addr_from_string(family, expected_start, &es) >= 0);
313 assert_se(in_addr_equal(family, &s, &es) > 0);
314 }
315 if (expected_end) {
316 union in_addr_union ee;
317
318 assert_se(in_addr_from_string(family, expected_end, &ee) >= 0);
319 assert_se(in_addr_equal(family, &e, &ee) > 0);
320 }
321 }
322
323 TEST(in_addr_prefix_range) {
324 test_in_addr_prefix_range_one(AF_INET, "192.168.123.123", 24, "192.168.123.0", "192.168.124.0");
325 test_in_addr_prefix_range_one(AF_INET, "192.168.123.123", 16, "192.168.0.0", "192.169.0.0");
326
327 test_in_addr_prefix_range_one(AF_INET6, "dead:beef::", 64, "dead:beef::", "dead:beef:0:1::");
328 test_in_addr_prefix_range_one(AF_INET6, "dead:0:0:beef::", 64, "dead:0:0:beef::", "dead:0:0:bef0::");
329 test_in_addr_prefix_range_one(AF_INET6, "2001::", 48, "2001::", "2001:0:1::");
330 test_in_addr_prefix_range_one(AF_INET6, "2001::", 56, "2001::", "2001:0:0:0100::");
331 test_in_addr_prefix_range_one(AF_INET6, "2001::", 65, "2001::", "2001::8000:0:0:0");
332 test_in_addr_prefix_range_one(AF_INET6, "2001::", 66, "2001::", "2001::4000:0:0:0");
333 test_in_addr_prefix_range_one(AF_INET6, "2001::", 127, "2001::", "2001::2");
334 }
335
336 static void test_in_addr_to_string_one(int f, const char *addr) {
337 union in_addr_union ua;
338 _cleanup_free_ char *r;
339
340 assert_se(in_addr_from_string(f, addr, &ua) >= 0);
341 assert_se(in_addr_to_string(f, &ua, &r) >= 0);
342 printf("%s: %s == %s\n", __func__, addr, r);
343 ASSERT_STREQ(addr, r);
344
345 ASSERT_STREQ(r, IN_ADDR_TO_STRING(f, &ua));
346 }
347
348 TEST(in_addr_to_string) {
349 test_in_addr_to_string_one(AF_INET, "192.168.0.1");
350 test_in_addr_to_string_one(AF_INET, "10.11.12.13");
351 test_in_addr_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
352 test_in_addr_to_string_one(AF_INET6, "::1");
353 test_in_addr_to_string_one(AF_INET6, "fe80::");
354 }
355
356 TEST(in_addr_prefixlen_to_netmask) {
357 union in_addr_union addr;
358 static const char *const ipv4_netmasks[] = {
359 "0.0.0.0", "128.0.0.0", "192.0.0.0", "224.0.0.0", "240.0.0.0",
360 "248.0.0.0", "252.0.0.0", "254.0.0.0", "255.0.0.0",
361 "255.128.0.0", "255.192.0.0", "255.224.0.0", "255.240.0.0",
362 "255.248.0.0", "255.252.0.0", "255.254.0.0", "255.255.0.0",
363 "255.255.128.0", "255.255.192.0", "255.255.224.0", "255.255.240.0",
364 "255.255.248.0", "255.255.252.0", "255.255.254.0", "255.255.255.0",
365 "255.255.255.128", "255.255.255.192", "255.255.255.224", "255.255.255.240",
366 "255.255.255.248", "255.255.255.252", "255.255.255.254", "255.255.255.255",
367 };
368
369 static const char *const ipv6_netmasks[] = {
370 [0] = "::",
371 [1] = "8000::",
372 [2] = "c000::",
373 [7] = "fe00::",
374 [8] = "ff00::",
375 [9] = "ff80::",
376 [16] = "ffff::",
377 [17] = "ffff:8000::",
378 [32] = "ffff:ffff::",
379 [33] = "ffff:ffff:8000::",
380 [64] = "ffff:ffff:ffff:ffff::",
381 [65] = "ffff:ffff:ffff:ffff:8000::",
382 [96] = "ffff:ffff:ffff:ffff:ffff:ffff::",
383 [97] = "ffff:ffff:ffff:ffff:ffff:ffff:8000:0",
384 [127] = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe",
385 [128] = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
386 };
387
388 for (unsigned char prefixlen = 0; prefixlen <= 32; prefixlen++) {
389 _cleanup_free_ char *result = NULL;
390
391 assert_se(in_addr_prefixlen_to_netmask(AF_INET, &addr, prefixlen) >= 0);
392 assert_se(in_addr_to_string(AF_INET, &addr, &result) >= 0);
393 printf("test_in_addr_prefixlen_to_netmask: %s == %s\n", ipv4_netmasks[prefixlen], result);
394 ASSERT_STREQ(ipv4_netmasks[prefixlen], result);
395 }
396
397 for (unsigned char prefixlen = 0; prefixlen <= 128; prefixlen++) {
398 _cleanup_free_ char *result = NULL;
399
400 assert_se(in_addr_prefixlen_to_netmask(AF_INET6, &addr, prefixlen) >= 0);
401 assert_se(in_addr_to_string(AF_INET6, &addr, &result) >= 0);
402 printf("test_in_addr_prefixlen_to_netmask: %s\n", result);
403 if (ipv6_netmasks[prefixlen])
404 ASSERT_STREQ(ipv6_netmasks[prefixlen], result);
405 }
406 }
407
408 static void in_addr_prefix_covers_full_one(const char *prefix, const char *address, int expected) {
409 union in_addr_union p, a;
410 unsigned char plen, alen;
411 int family, r;
412
413 assert_se(in_addr_prefix_from_string_auto(prefix, &family, &p, &plen) >= 0);
414 assert_se(in_addr_prefix_from_string(address, family, &a, &alen) >= 0);
415 r = in_addr_prefix_covers_full(family, &p, plen, &a, alen);
416 if (r != expected)
417 log_error("in_addr_prefix_covers_full(%s, %s)=%i (expected=%i)", prefix, address, r, expected);
418 assert_se(r == expected);
419 }
420
421 TEST(in_addr_prefix_covers_full) {
422 /* From issue #32715. */
423 in_addr_prefix_covers_full_one("192.168.235.129/32", "192.168.0.128/32", 0);
424 in_addr_prefix_covers_full_one("192.168.235.130/32", "192.168.0.128/32", 0);
425 in_addr_prefix_covers_full_one("169.254.0.0/17", "192.168.0.128/32", 0);
426 in_addr_prefix_covers_full_one("169.254.128.0/17", "192.168.0.128/32", 0);
427 in_addr_prefix_covers_full_one("0.0.0.0/1", "192.168.0.128/32", 0);
428 in_addr_prefix_covers_full_one("128.0.0.0/1", "192.168.0.128/32", 1);
429 in_addr_prefix_covers_full_one("0.0.0.0/0", "192.168.0.128/32", 1);
430
431 for (unsigned i = 0; i <= 32; i++) {
432 _cleanup_free_ char *prefix = NULL;
433
434 assert_se(asprintf(&prefix, "192.168.0.128/%u", i) >= 0);
435
436 for (unsigned j = 0; j <= 32; j++) {
437 _cleanup_free_ char *address = NULL;
438
439 assert_se(asprintf(&address, "192.168.0.128/%u", j) >= 0);
440 in_addr_prefix_covers_full_one(prefix, address, i <= j);
441 }
442 }
443
444 for (unsigned i = 0; i <= 32; i++) {
445 _cleanup_free_ char *prefix = NULL;
446
447 assert_se(asprintf(&prefix, "192.168.235.129/%u", i) >= 0);
448 in_addr_prefix_covers_full_one(prefix, "192.168.0.128/32", i <= 16);
449 }
450
451 for (unsigned i = 0; i <= 128; i++) {
452 _cleanup_free_ char *prefix = NULL;
453
454 assert_se(asprintf(&prefix, "dead:beef::/%u", i) >= 0);
455 in_addr_prefix_covers_full_one(prefix, "dead:0:beef::1/128", i <= 16);
456 }
457 }
458
459 DEFINE_TEST_MAIN(LOG_DEBUG);