]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-socket-netlink.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "alloc-util.h"
4 #include "missing_network.h"
6 #include "socket-netlink.h"
7 #include "string-util.h"
9 static void test_socket_address_parse_one(const char *in
, int ret
, int family
, const char *expected
) {
11 _cleanup_free_
char *out
= NULL
;
14 r
= socket_address_parse(&a
, in
);
16 r
= socket_address_print(&a
, &out
);
18 log_error_errno(r
, "Printing failed for \"%s\": %m", in
);
20 assert_se(a
.type
== 0);
23 log_info("\"%s\" → %s %d → \"%s\" (expect %d / \"%s\")",
25 r
>= 0 ? "✓" : "✗", r
,
28 ret
>= 0 ? expected
?: in
: "-");
31 assert_se(a
.sockaddr
.sa
.sa_family
== family
);
32 assert_se(streq(out
, expected
?: in
));
36 static void test_socket_address_parse(void) {
37 log_info("/* %s */", __func__
);
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
);
48 const int default_family
= socket_ipv6_is_supported() ? AF_INET6
: AF_INET
;
50 test_socket_address_parse_one("65535", 0, default_family
, "[::]:65535");
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. */
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
);
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
);
83 char aaa
[SUN_PATH_LEN
+ 1] = "@";
85 memset(aaa
+ 1, 'a', SUN_PATH_LEN
- 1);
88 test_socket_address_parse_one(aaa
, -EINVAL
, 0, NULL
);
90 aaa
[SUN_PATH_LEN
- 1] = '\0';
91 test_socket_address_parse_one(aaa
, 0, AF_UNIX
, NULL
);
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
);
101 static void test_socket_address_parse_netlink(void) {
104 log_info("/* %s */", __func__
);
106 assert_se(socket_address_parse_netlink(&a
, "junk") < 0);
107 assert_se(socket_address_parse_netlink(&a
, "") < 0);
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
);
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
);
133 /* trailing space is not supported */
134 assert_se(socket_address_parse_netlink(&a
, "kobject-uevent\t10 ") < 0);
136 /* Group must be unsigned */
137 assert_se(socket_address_parse_netlink(&a
, "kobject-uevent -1") < 0);
140 assert_se(socket_address_parse_netlink(&a
, "\xff") < 0);
143 static void test_socket_address_equal(void) {
146 log_info("/* %s */", __func__
);
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
193 static void test_socket_address_get_path(void) {
196 log_info("/* %s */", __func__
);
198 assert_se(socket_address_parse(&a
, "192.168.1.1:8888") >= 0);
199 assert_se(!socket_address_get_path(&a
));
201 assert_se(socket_address_parse(&a
, "@abstract") >= 0);
202 assert_se(!socket_address_get_path(&a
));
204 assert_se(socket_address_parse(&a
, "[::1]:8888") >= 0);
205 assert_se(!socket_address_get_path(&a
));
207 assert_se(socket_address_parse(&a
, "/foo/bar") >= 0);
208 assert_se(streq(socket_address_get_path(&a
), "/foo/bar"));
210 assert_se(socket_address_parse(&a
, "vsock:2:1234") >= 0);
211 assert_se(!socket_address_get_path(&a
));
214 static void test_socket_address_is(void) {
217 log_info("/* %s */", __func__
);
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
));
229 static void test_socket_address_is_netlink(void) {
232 log_info("/* %s */", __func__
);
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"));
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
;
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
));
250 assert_se(in_addr_ifindex_from_string_auto(b
, &ff
, &uuaa
, &ifindex2
) >= 0);
252 assert_se(in_addr_equal(f
, &ua
, &uuaa
));
253 assert_se(ifindex2
== ifindex
|| ifindex2
== 0);
256 static void test_in_addr_ifindex_to_string(void) {
257 log_info("/* %s */", __func__
);
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");
270 static void test_in_addr_ifindex_from_string_auto(void) {
272 union in_addr_union ua
;
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 */
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);
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);
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
);
289 assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family
, &ua
, &ifindex
) == -ENODEV
);
292 static void test_in_addr_ifindex_name_from_string_auto_one(const char *a
, const char *expected
) {
294 union in_addr_union ua
;
295 _cleanup_free_
char *server_name
= NULL
;
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
));
301 static void test_in_addr_ifindex_name_from_string_auto(void) {
302 log_info("/* %s */", __func__
);
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");
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
;
317 log_info("%s: %s", __func__
, str
);
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
));
331 assert_se(in_addr_port_ifindex_name_from_string_auto(str
, &f
, &a
, NULL
, &i
, &fake
) == -EINVAL
);
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
));
343 assert_se(in_addr_port_ifindex_name_from_string_auto(str
, &f
, &a
, &p
, NULL
, &fake
) == -EINVAL
);
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
));
355 assert_se(in_addr_port_ifindex_name_from_string_auto(str
, &f
, &a
, &p
, &i
, NULL
) == -EINVAL
);
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
));
367 static void test_in_addr_port_ifindex_name_from_string_auto(void) {
368 log_info("/* %s */", __func__
);
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");
389 int main(int argc
, char *argv
[]) {
390 test_setup_logging(LOG_DEBUG
);
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();
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();