]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-socket-netlink.c
Merge pull request #17549 from yuwata/tiny-fixes
[thirdparty/systemd.git] / src / test / test-socket-netlink.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "alloc-util.h"
4 #include "missing_network.h"
5 #include "tests.h"
6 #include "socket-netlink.h"
7 #include "string-util.h"
8
9 static void test_socket_address_parse_one(const char *in, int ret, int family, const char *expected) {
10 SocketAddress a;
11 _cleanup_free_ char *out = NULL;
12 int r;
13
14 r = socket_address_parse(&a, in);
15 if (r >= 0) {
16 r = socket_address_print(&a, &out);
17 if (r < 0)
18 log_error_errno(r, "Printing failed for \"%s\": %m", in);
19 assert(r >= 0);
20 assert_se(a.type == 0);
21 }
22
23 log_info("\"%s\" → %s %d → \"%s\" (expect %d / \"%s\")",
24 in,
25 r >= 0 ? "✓" : "✗", r,
26 empty_to_dash(out),
27 ret,
28 ret >= 0 ? expected ?: in : "-");
29 assert_se(r == ret);
30 if (r >= 0) {
31 assert_se(a.sockaddr.sa.sa_family == family);
32 assert_se(streq(out, expected ?: in));
33 }
34 }
35
36 static void test_socket_address_parse(void) {
37 log_info("/* %s */", __func__);
38
39 test_socket_address_parse_one("junk", -EINVAL, 0, NULL);
40 test_socket_address_parse_one("192.168.1.1", -EINVAL, 0, NULL);
41 test_socket_address_parse_one(".168.1.1", -EINVAL, 0, NULL);
42 test_socket_address_parse_one("989.168.1.1", -EINVAL, 0, NULL);
43 test_socket_address_parse_one("192.168.1.1:65536", -ERANGE, 0, NULL);
44 test_socket_address_parse_one("192.168.1.1:0", -EINVAL, 0, NULL);
45 test_socket_address_parse_one("0", -EINVAL, 0, NULL);
46 test_socket_address_parse_one("65536", -ERANGE, 0, NULL);
47
48 const int default_family = socket_ipv6_is_supported() ? AF_INET6 : AF_INET;
49
50 test_socket_address_parse_one("65535", 0, default_family, "[::]:65535");
51
52 /* The checks below will pass even if ipv6 is disabled in
53 * kernel. The underlying glibc's inet_pton() is just a string
54 * parser and doesn't make any syscalls. */
55
56 test_socket_address_parse_one("[::1]", -EINVAL, 0, NULL);
57 test_socket_address_parse_one("[::1]8888", -EINVAL, 0, NULL);
58 test_socket_address_parse_one("::1", -EINVAL, 0, NULL);
59 test_socket_address_parse_one("[::1]:0", -EINVAL, 0, NULL);
60 test_socket_address_parse_one("[::1]:65536", -ERANGE, 0, NULL);
61 test_socket_address_parse_one("[a:b:1]:8888", -EINVAL, 0, NULL);
62 test_socket_address_parse_one("[::1]%lo:1234", -EINVAL, 0, NULL);
63 test_socket_address_parse_one("[::1]%lo:0", -EINVAL, 0, NULL);
64 test_socket_address_parse_one("[::1]%lo", -EINVAL, 0, NULL);
65 test_socket_address_parse_one("[::1]%lo%lo:1234", -EINVAL, 0, NULL);
66 test_socket_address_parse_one("[::1]% lo:1234", -EINVAL, 0, NULL);
67
68 test_socket_address_parse_one("8888", 0, default_family, "[::]:8888");
69 test_socket_address_parse_one("[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8888", 0, AF_INET6,
70 "[2001:db8:0:85a3::ac1f:8001]:8888");
71 test_socket_address_parse_one("[::1]:8888", 0, AF_INET6, NULL);
72 test_socket_address_parse_one("[::1]:1234%lo", 0, AF_INET6, NULL);
73 test_socket_address_parse_one("[::1]:0%lo", -EINVAL, 0, NULL);
74 test_socket_address_parse_one("[::1]%lo", -EINVAL, 0, NULL);
75 test_socket_address_parse_one("[::1]:1234%lo%lo", -ENODEV, 0, NULL);
76 test_socket_address_parse_one("[::1]:1234%xxxxasdf", -ENODEV, 0, NULL);
77 test_socket_address_parse_one("192.168.1.254:8888", 0, AF_INET, NULL);
78 test_socket_address_parse_one("/foo/bar", 0, AF_UNIX, NULL);
79 test_socket_address_parse_one("/", -EINVAL, 0, NULL);
80 test_socket_address_parse_one("@abstract", 0, AF_UNIX, NULL);
81
82 {
83 char aaa[SUN_PATH_LEN + 1] = "@";
84
85 memset(aaa + 1, 'a', SUN_PATH_LEN - 1);
86 char_array_0(aaa);
87
88 test_socket_address_parse_one(aaa, -EINVAL, 0, NULL);
89
90 aaa[SUN_PATH_LEN - 1] = '\0';
91 test_socket_address_parse_one(aaa, 0, AF_UNIX, NULL);
92 }
93
94 test_socket_address_parse_one("vsock:2:1234", 0, AF_VSOCK, NULL);
95 test_socket_address_parse_one("vsock::1234", 0, AF_VSOCK, NULL);
96 test_socket_address_parse_one("vsock:2:1234x", -EINVAL, 0, NULL);
97 test_socket_address_parse_one("vsock:2x:1234", -EINVAL, 0, NULL);
98 test_socket_address_parse_one("vsock:2", -EINVAL, 0, NULL);
99 }
100
101 static void test_socket_address_parse_netlink(void) {
102 SocketAddress a;
103
104 log_info("/* %s */", __func__);
105
106 assert_se(socket_address_parse_netlink(&a, "junk") < 0);
107 assert_se(socket_address_parse_netlink(&a, "") < 0);
108
109 assert_se(socket_address_parse_netlink(&a, "route") >= 0);
110 assert_se(a.sockaddr.nl.nl_family == AF_NETLINK);
111 assert_se(a.sockaddr.nl.nl_groups == 0);
112 assert_se(a.protocol == NETLINK_ROUTE);
113 assert_se(socket_address_parse_netlink(&a, "route") >= 0);
114 assert_se(socket_address_parse_netlink(&a, "route 10") >= 0);
115 assert_se(a.sockaddr.nl.nl_family == AF_NETLINK);
116 assert_se(a.sockaddr.nl.nl_groups == 10);
117 assert_se(a.protocol == NETLINK_ROUTE);
118
119 /* With spaces and tabs */
120 assert_se(socket_address_parse_netlink(&a, " kobject-uevent ") >= 0);
121 assert_se(a.sockaddr.nl.nl_family == AF_NETLINK);
122 assert_se(a.sockaddr.nl.nl_groups == 0);
123 assert_se(a.protocol == NETLINK_KOBJECT_UEVENT);
124 assert_se(socket_address_parse_netlink(&a, " \t kobject-uevent \t 10") >= 0);
125 assert_se(a.sockaddr.nl.nl_family == AF_NETLINK);
126 assert_se(a.sockaddr.nl.nl_groups == 10);
127 assert_se(a.protocol == NETLINK_KOBJECT_UEVENT);
128 assert_se(socket_address_parse_netlink(&a, "kobject-uevent\t10") >= 0);
129 assert_se(a.sockaddr.nl.nl_family == AF_NETLINK);
130 assert_se(a.sockaddr.nl.nl_groups == 10);
131 assert_se(a.protocol == NETLINK_KOBJECT_UEVENT);
132
133 /* trailing space is not supported */
134 assert_se(socket_address_parse_netlink(&a, "kobject-uevent\t10 ") < 0);
135
136 /* Group must be unsigned */
137 assert_se(socket_address_parse_netlink(&a, "kobject-uevent -1") < 0);
138
139 /* oss-fuzz #6884 */
140 assert_se(socket_address_parse_netlink(&a, "\xff") < 0);
141 }
142
143 static void test_socket_address_equal(void) {
144 SocketAddress a, b;
145
146 log_info("/* %s */", __func__);
147
148 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
149 assert_se(socket_address_parse(&b, "192.168.1.1:888") >= 0);
150 assert_se(!socket_address_equal(&a, &b));
151
152 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
153 assert_se(socket_address_parse(&b, "192.16.1.1:8888") >= 0);
154 assert_se(!socket_address_equal(&a, &b));
155
156 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
157 assert_se(socket_address_parse(&b, "8888") >= 0);
158 assert_se(!socket_address_equal(&a, &b));
159
160 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
161 assert_se(socket_address_parse(&b, "/foo/bar/") >= 0);
162 assert_se(!socket_address_equal(&a, &b));
163
164 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
165 assert_se(socket_address_parse(&b, "192.168.1.1:8888") >= 0);
166 assert_se(socket_address_equal(&a, &b));
167
168 assert_se(socket_address_parse(&a, "/foo/bar") >= 0);
169 assert_se(socket_address_parse(&b, "/foo/bar") >= 0);
170 assert_se(socket_address_equal(&a, &b));
171
172 assert_se(socket_address_parse(&a, "[::1]:8888") >= 0);
173 assert_se(socket_address_parse(&b, "[::1]:8888") >= 0);
174 assert_se(socket_address_equal(&a, &b));
175
176 assert_se(socket_address_parse(&a, "@abstract") >= 0);
177 assert_se(socket_address_parse(&b, "@abstract") >= 0);
178 assert_se(socket_address_equal(&a, &b));
179
180 assert_se(socket_address_parse_netlink(&a, "firewall") >= 0);
181 assert_se(socket_address_parse_netlink(&b, "firewall") >= 0);
182 assert_se(socket_address_equal(&a, &b));
183
184 assert_se(socket_address_parse(&a, "vsock:2:1234") >= 0);
185 assert_se(socket_address_parse(&b, "vsock:2:1234") >= 0);
186 assert_se(socket_address_equal(&a, &b));
187 assert_se(socket_address_parse(&b, "vsock:2:1235") >= 0);
188 assert_se(!socket_address_equal(&a, &b));
189 assert_se(socket_address_parse(&b, "vsock:3:1234") >= 0);
190 assert_se(!socket_address_equal(&a, &b));
191 }
192
193 static void test_socket_address_get_path(void) {
194 SocketAddress a;
195
196 log_info("/* %s */", __func__);
197
198 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
199 assert_se(!socket_address_get_path(&a));
200
201 assert_se(socket_address_parse(&a, "@abstract") >= 0);
202 assert_se(!socket_address_get_path(&a));
203
204 assert_se(socket_address_parse(&a, "[::1]:8888") >= 0);
205 assert_se(!socket_address_get_path(&a));
206
207 assert_se(socket_address_parse(&a, "/foo/bar") >= 0);
208 assert_se(streq(socket_address_get_path(&a), "/foo/bar"));
209
210 assert_se(socket_address_parse(&a, "vsock:2:1234") >= 0);
211 assert_se(!socket_address_get_path(&a));
212 }
213
214 static void test_socket_address_is(void) {
215 SocketAddress a;
216
217 log_info("/* %s */", __func__);
218
219 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
220 assert_se( socket_address_is(&a, "192.168.1.1:8888", 0 /* unspecified yet */));
221 assert_se(!socket_address_is(&a, "route", 0));
222 assert_se(!socket_address_is(&a, "route", SOCK_STREAM));
223 assert_se(!socket_address_is(&a, "192.168.1.1:8888", SOCK_RAW));
224 assert_se(!socket_address_is(&a, "192.168.1.1:8888", SOCK_STREAM));
225 a.type = SOCK_STREAM;
226 assert_se( socket_address_is(&a, "192.168.1.1:8888", SOCK_STREAM));
227 }
228
229 static void test_socket_address_is_netlink(void) {
230 SocketAddress a;
231
232 log_info("/* %s */", __func__);
233
234 assert_se(socket_address_parse_netlink(&a, "route 10") >= 0);
235 assert_se( socket_address_is_netlink(&a, "route 10"));
236 assert_se(!socket_address_is_netlink(&a, "192.168.1.1:8888"));
237 assert_se(!socket_address_is_netlink(&a, "route 1"));
238 }
239
240 static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) {
241 _cleanup_free_ char *r = NULL;
242 union in_addr_union ua, uuaa;
243 int ff, ifindex2;
244
245 assert_se(in_addr_from_string(f, a, &ua) >= 0);
246 assert_se(in_addr_ifindex_to_string(f, &ua, ifindex, &r) >= 0);
247 printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b, r);
248 assert_se(streq(b, r));
249
250 assert_se(in_addr_ifindex_from_string_auto(b, &ff, &uuaa, &ifindex2) >= 0);
251 assert_se(ff == f);
252 assert_se(in_addr_equal(f, &ua, &uuaa));
253 assert_se(ifindex2 == ifindex || ifindex2 == 0);
254 }
255
256 static void test_in_addr_ifindex_to_string(void) {
257 log_info("/* %s */", __func__);
258
259 test_in_addr_ifindex_to_string_one(AF_INET, "192.168.0.1", 7, "192.168.0.1");
260 test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13");
261 test_in_addr_ifindex_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
262 test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1");
263 test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 12, "fe80::%12");
264 test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 0, "fe80::");
265 test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 12, "fe80::14%12");
266 test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::15", -7, "fe80::15");
267 test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::16", LOOPBACK_IFINDEX, "fe80::16%1");
268 }
269
270 static void test_in_addr_ifindex_from_string_auto(void) {
271 int family, ifindex;
272 union in_addr_union ua;
273
274 log_info("/* %s */", __func__);
275 /* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */
276
277 assert_se(in_addr_ifindex_from_string_auto("fe80::17", &family, &ua, &ifindex) >= 0);
278 assert_se(family == AF_INET6);
279 assert_se(ifindex == 0);
280
281 assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family, &ua, &ifindex) >= 0);
282 assert_se(family == AF_INET6);
283 assert_se(ifindex == 19);
284
285 assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family, &ua, &ifindex) >= 0);
286 assert_se(family == AF_INET6);
287 assert_se(ifindex == LOOPBACK_IFINDEX);
288
289 assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV);
290 }
291
292 static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const char *expected) {
293 int family, ifindex;
294 union in_addr_union ua;
295 _cleanup_free_ char *server_name = NULL;
296
297 assert_se(in_addr_ifindex_name_from_string_auto(a, &family, &ua, &ifindex, &server_name) >= 0);
298 assert_se(streq_ptr(server_name, expected));
299 }
300
301 static void test_in_addr_ifindex_name_from_string_auto(void) {
302 log_info("/* %s */", __func__);
303
304 test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL);
305 test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com");
306 test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL);
307 test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com");
308 }
309
310 static void test_in_addr_port_ifindex_name_from_string_auto_one(const char *str, int family, uint16_t port, int ifindex,
311 const char *server_name, const char *str_repr) {
312 union in_addr_union a;
313 uint16_t p;
314 int f, i;
315 char *fake;
316
317 log_info("%s: %s", __func__, str);
318
319 {
320 _cleanup_free_ char *name = NULL, *x = NULL;
321 assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, &i, &name) == 0);
322 assert_se(family == f);
323 assert_se(port == p);
324 assert_se(ifindex == i);
325 assert_se(streq_ptr(server_name, name));
326 assert_se(in_addr_port_ifindex_name_to_string(f, &a, p, i, name, &x) >= 0);
327 assert_se(streq(str_repr ?: str, x));
328 }
329
330 if (port > 0)
331 assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, NULL, &i, &fake) == -EINVAL);
332 else {
333 _cleanup_free_ char *name = NULL, *x = NULL;
334 assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, NULL, &i, &name) == 0);
335 assert_se(family == f);
336 assert_se(ifindex == i);
337 assert_se(streq_ptr(server_name, name));
338 assert_se(in_addr_port_ifindex_name_to_string(f, &a, 0, i, name, &x) >= 0);
339 assert_se(streq(str_repr ?: str, x));
340 }
341
342 if (ifindex > 0)
343 assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, NULL, &fake) == -EINVAL);
344 else {
345 _cleanup_free_ char *name = NULL, *x = NULL;
346 assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, NULL, &name) == 0);
347 assert_se(family == f);
348 assert_se(port == p);
349 assert_se(streq_ptr(server_name, name));
350 assert_se(in_addr_port_ifindex_name_to_string(f, &a, p, 0, name, &x) >= 0);
351 assert_se(streq(str_repr ?: str, x));
352 }
353
354 if (server_name)
355 assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, &i, NULL) == -EINVAL);
356 else {
357 _cleanup_free_ char *x = NULL;
358 assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, &i, NULL) == 0);
359 assert_se(family == f);
360 assert_se(port == p);
361 assert_se(ifindex == i);
362 assert_se(in_addr_port_ifindex_name_to_string(f, &a, p, i, NULL, &x) >= 0);
363 assert_se(streq(str_repr ?: str, x));
364 }
365 }
366
367 static void test_in_addr_port_ifindex_name_from_string_auto(void) {
368 log_info("/* %s */", __func__);
369
370 test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1", AF_INET, 0, 0, NULL, NULL);
371 test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1#test.com", AF_INET, 0, 0, "test.com", NULL);
372 test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53", AF_INET, 53, 0, NULL, NULL);
373 test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53#example.com", AF_INET, 53, 0, "example.com", NULL);
374 test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18", AF_INET6, 0, 0, NULL, NULL);
375 test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18#hoge.com", AF_INET6, 0, 0, "hoge.com", NULL);
376 test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19", AF_INET6, 0, 19, NULL, NULL);
377 test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%lo", AF_INET6, 0, 1, NULL, "fe80::18%1");
378 test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53", AF_INET6, 53, 0, NULL, NULL);
379 test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19", AF_INET6, 53, 19, NULL, NULL);
380 test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%lo", AF_INET6, 53, 1, NULL, "[fe80::18]:53%1");
381 test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19#hoge.com", AF_INET6, 0, 19, "hoge.com", NULL);
382 test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53#hoge.com", AF_INET6, 53, 0, "hoge.com", NULL);
383 test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19", AF_INET6, 53, 19, NULL, NULL);
384 test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19#hoge.com", AF_INET6, 53, 19, "hoge.com", NULL);
385 test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%lo", AF_INET6, 53, 1, NULL, "[fe80::18]:53%1");
386 test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%lo#hoge.com", AF_INET6, 53, 1, "hoge.com", "[fe80::18]:53%1#hoge.com");
387 }
388
389 int main(int argc, char *argv[]) {
390 test_setup_logging(LOG_DEBUG);
391
392 test_socket_address_parse();
393 test_socket_address_parse_netlink();
394 test_socket_address_equal();
395 test_socket_address_get_path();
396 test_socket_address_is();
397 test_socket_address_is_netlink();
398
399 test_in_addr_ifindex_to_string();
400 test_in_addr_ifindex_from_string_auto();
401 test_in_addr_ifindex_name_from_string_auto();
402 test_in_addr_port_ifindex_name_from_string_auto();
403
404 return 0;
405 }