]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-socket-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd
5 Copyright 2014 Ronny Chevalier
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <sys/types.h>
25 #include "alloc-util.h"
28 #include "in-addr-util.h"
31 #include "process-util.h"
32 #include "socket-util.h"
33 #include "string-util.h"
36 static void test_ifname_valid(void) {
37 assert(ifname_valid("foo"));
38 assert(ifname_valid("eth0"));
40 assert(!ifname_valid("0"));
41 assert(!ifname_valid("99"));
42 assert(ifname_valid("a99"));
43 assert(ifname_valid("99a"));
45 assert(!ifname_valid(NULL
));
46 assert(!ifname_valid(""));
47 assert(!ifname_valid(" "));
48 assert(!ifname_valid(" foo"));
49 assert(!ifname_valid("bar\n"));
50 assert(!ifname_valid("."));
51 assert(!ifname_valid(".."));
52 assert(ifname_valid("foo.bar"));
53 assert(!ifname_valid("x:y"));
55 assert(ifname_valid("xxxxxxxxxxxxxxx"));
56 assert(!ifname_valid("xxxxxxxxxxxxxxxx"));
59 static void test_socket_address_parse(void) {
62 assert_se(socket_address_parse(&a
, "junk") < 0);
63 assert_se(socket_address_parse(&a
, "192.168.1.1") < 0);
64 assert_se(socket_address_parse(&a
, ".168.1.1") < 0);
65 assert_se(socket_address_parse(&a
, "989.168.1.1") < 0);
66 assert_se(socket_address_parse(&a
, "192.168.1.1:65536") < 0);
67 assert_se(socket_address_parse(&a
, "192.168.1.1:0") < 0);
68 assert_se(socket_address_parse(&a
, "0") < 0);
69 assert_se(socket_address_parse(&a
, "65536") < 0);
71 assert_se(socket_address_parse(&a
, "65535") >= 0);
73 /* The checks below will pass even if ipv6 is disabled in
74 * kernel. The underlying glibc's inet_pton() is just a string
75 * parser and doesn't make any syscalls. */
77 assert_se(socket_address_parse(&a
, "[::1]") < 0);
78 assert_se(socket_address_parse(&a
, "[::1]8888") < 0);
79 assert_se(socket_address_parse(&a
, "::1") < 0);
80 assert_se(socket_address_parse(&a
, "[::1]:0") < 0);
81 assert_se(socket_address_parse(&a
, "[::1]:65536") < 0);
82 assert_se(socket_address_parse(&a
, "[a:b:1]:8888") < 0);
84 assert_se(socket_address_parse(&a
, "8888") >= 0);
85 assert_se(a
.sockaddr
.sa
.sa_family
== (socket_ipv6_is_supported() ? AF_INET6
: AF_INET
));
87 assert_se(socket_address_parse(&a
, "[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8888") >= 0);
88 assert_se(a
.sockaddr
.sa
.sa_family
== AF_INET6
);
90 assert_se(socket_address_parse(&a
, "[::1]:8888") >= 0);
91 assert_se(a
.sockaddr
.sa
.sa_family
== AF_INET6
);
93 assert_se(socket_address_parse(&a
, "192.168.1.254:8888") >= 0);
94 assert_se(a
.sockaddr
.sa
.sa_family
== AF_INET
);
96 assert_se(socket_address_parse(&a
, "/foo/bar") >= 0);
97 assert_se(a
.sockaddr
.sa
.sa_family
== AF_UNIX
);
99 assert_se(socket_address_parse(&a
, "@abstract") >= 0);
100 assert_se(a
.sockaddr
.sa
.sa_family
== AF_UNIX
);
102 assert_se(socket_address_parse(&a
, "vsock::1234") >= 0);
103 assert_se(a
.sockaddr
.sa
.sa_family
== AF_VSOCK
);
104 assert_se(socket_address_parse(&a
, "vsock:2:1234") >= 0);
105 assert_se(a
.sockaddr
.sa
.sa_family
== AF_VSOCK
);
106 assert_se(socket_address_parse(&a
, "vsock:2:1234x") < 0);
107 assert_se(socket_address_parse(&a
, "vsock:2x:1234") < 0);
108 assert_se(socket_address_parse(&a
, "vsock:2") < 0);
111 static void test_socket_address_parse_netlink(void) {
114 assert_se(socket_address_parse_netlink(&a
, "junk") < 0);
115 assert_se(socket_address_parse_netlink(&a
, "") < 0);
117 assert_se(socket_address_parse_netlink(&a
, "route") >= 0);
118 assert_se(socket_address_parse_netlink(&a
, "route 10") >= 0);
119 assert_se(a
.sockaddr
.sa
.sa_family
== AF_NETLINK
);
120 assert_se(a
.protocol
== NETLINK_ROUTE
);
123 static void test_socket_address_equal(void) {
127 assert_se(socket_address_parse(&a
, "192.168.1.1:8888") >= 0);
128 assert_se(socket_address_parse(&b
, "192.168.1.1:888") >= 0);
129 assert_se(!socket_address_equal(&a
, &b
));
131 assert_se(socket_address_parse(&a
, "192.168.1.1:8888") >= 0);
132 assert_se(socket_address_parse(&b
, "192.16.1.1:8888") >= 0);
133 assert_se(!socket_address_equal(&a
, &b
));
135 assert_se(socket_address_parse(&a
, "192.168.1.1:8888") >= 0);
136 assert_se(socket_address_parse(&b
, "8888") >= 0);
137 assert_se(!socket_address_equal(&a
, &b
));
139 assert_se(socket_address_parse(&a
, "192.168.1.1:8888") >= 0);
140 assert_se(socket_address_parse(&b
, "/foo/bar/") >= 0);
141 assert_se(!socket_address_equal(&a
, &b
));
143 assert_se(socket_address_parse(&a
, "192.168.1.1:8888") >= 0);
144 assert_se(socket_address_parse(&b
, "192.168.1.1:8888") >= 0);
145 assert_se(socket_address_equal(&a
, &b
));
147 assert_se(socket_address_parse(&a
, "/foo/bar") >= 0);
148 assert_se(socket_address_parse(&b
, "/foo/bar") >= 0);
149 assert_se(socket_address_equal(&a
, &b
));
151 assert_se(socket_address_parse(&a
, "[::1]:8888") >= 0);
152 assert_se(socket_address_parse(&b
, "[::1]:8888") >= 0);
153 assert_se(socket_address_equal(&a
, &b
));
155 assert_se(socket_address_parse(&a
, "@abstract") >= 0);
156 assert_se(socket_address_parse(&b
, "@abstract") >= 0);
157 assert_se(socket_address_equal(&a
, &b
));
159 assert_se(socket_address_parse_netlink(&a
, "firewall") >= 0);
160 assert_se(socket_address_parse_netlink(&b
, "firewall") >= 0);
161 assert_se(socket_address_equal(&a
, &b
));
163 assert_se(socket_address_parse(&a
, "vsock:2:1234") >= 0);
164 assert_se(socket_address_parse(&b
, "vsock:2:1234") >= 0);
165 assert_se(socket_address_equal(&a
, &b
));
166 assert_se(socket_address_parse(&b
, "vsock:2:1235") >= 0);
167 assert_se(!socket_address_equal(&a
, &b
));
168 assert_se(socket_address_parse(&b
, "vsock:3:1234") >= 0);
169 assert_se(!socket_address_equal(&a
, &b
));
172 static void test_socket_address_get_path(void) {
175 assert_se(socket_address_parse(&a
, "192.168.1.1:8888") >= 0);
176 assert_se(!socket_address_get_path(&a
));
178 assert_se(socket_address_parse(&a
, "@abstract") >= 0);
179 assert_se(!socket_address_get_path(&a
));
181 assert_se(socket_address_parse(&a
, "[::1]:8888") >= 0);
182 assert_se(!socket_address_get_path(&a
));
184 assert_se(socket_address_parse(&a
, "/foo/bar") >= 0);
185 assert_se(streq(socket_address_get_path(&a
), "/foo/bar"));
187 assert_se(socket_address_parse(&a
, "vsock:2:1234") >= 0);
188 assert_se(!socket_address_get_path(&a
));
191 static void test_socket_address_is(void) {
194 assert_se(socket_address_parse(&a
, "192.168.1.1:8888") >= 0);
195 assert_se(socket_address_is(&a
, "192.168.1.1:8888", SOCK_STREAM
));
196 assert_se(!socket_address_is(&a
, "route", SOCK_STREAM
));
197 assert_se(!socket_address_is(&a
, "192.168.1.1:8888", SOCK_RAW
));
200 static void test_socket_address_is_netlink(void) {
203 assert_se(socket_address_parse_netlink(&a
, "route 10") >= 0);
204 assert_se(socket_address_is_netlink(&a
, "route 10"));
205 assert_se(!socket_address_is_netlink(&a
, "192.168.1.1:8888"));
206 assert_se(!socket_address_is_netlink(&a
, "route 1"));
209 static void test_in_addr_is_null(void) {
211 union in_addr_union i
= {};
213 assert_se(in_addr_is_null(AF_INET
, &i
) == true);
214 assert_se(in_addr_is_null(AF_INET6
, &i
) == true);
216 i
.in
.s_addr
= 0x1000000;
217 assert_se(in_addr_is_null(AF_INET
, &i
) == false);
218 assert_se(in_addr_is_null(AF_INET6
, &i
) == false);
220 assert_se(in_addr_is_null(-1, &i
) == -EAFNOSUPPORT
);
223 static void test_in_addr_prefix_intersect_one(unsigned f
, const char *a
, unsigned apl
, const char *b
, unsigned bpl
, int result
) {
224 union in_addr_union ua
, ub
;
226 assert_se(in_addr_from_string(f
, a
, &ua
) >= 0);
227 assert_se(in_addr_from_string(f
, b
, &ub
) >= 0);
229 assert_se(in_addr_prefix_intersect(f
, &ua
, apl
, &ub
, bpl
) == result
);
232 static void test_in_addr_prefix_intersect(void) {
234 test_in_addr_prefix_intersect_one(AF_INET
, "255.255.255.255", 32, "255.255.255.254", 32, 0);
235 test_in_addr_prefix_intersect_one(AF_INET
, "255.255.255.255", 0, "255.255.255.255", 32, 1);
236 test_in_addr_prefix_intersect_one(AF_INET
, "0.0.0.0", 0, "47.11.8.15", 32, 1);
238 test_in_addr_prefix_intersect_one(AF_INET
, "1.1.1.1", 24, "1.1.1.1", 24, 1);
239 test_in_addr_prefix_intersect_one(AF_INET
, "2.2.2.2", 24, "1.1.1.1", 24, 0);
241 test_in_addr_prefix_intersect_one(AF_INET
, "1.1.1.1", 24, "1.1.1.127", 25, 1);
242 test_in_addr_prefix_intersect_one(AF_INET
, "1.1.1.1", 24, "1.1.1.127", 26, 1);
243 test_in_addr_prefix_intersect_one(AF_INET
, "1.1.1.1", 25, "1.1.1.127", 25, 1);
244 test_in_addr_prefix_intersect_one(AF_INET
, "1.1.1.1", 25, "1.1.1.255", 25, 0);
246 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);
247 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);
248 test_in_addr_prefix_intersect_one(AF_INET6
, "::", 0, "beef:beef:beef:beef:beef:beef:beef:beef", 128, 1);
250 test_in_addr_prefix_intersect_one(AF_INET6
, "1::2", 64, "1::2", 64, 1);
251 test_in_addr_prefix_intersect_one(AF_INET6
, "2::2", 64, "1::2", 64, 0);
253 test_in_addr_prefix_intersect_one(AF_INET6
, "1::1", 120, "1::007f", 121, 1);
254 test_in_addr_prefix_intersect_one(AF_INET6
, "1::1", 120, "1::007f", 122, 1);
255 test_in_addr_prefix_intersect_one(AF_INET6
, "1::1", 121, "1::007f", 121, 1);
256 test_in_addr_prefix_intersect_one(AF_INET6
, "1::1", 121, "1::00ff", 121, 0);
259 static void test_in_addr_prefix_next_one(unsigned f
, const char *before
, unsigned pl
, const char *after
) {
260 union in_addr_union ubefore
, uafter
, t
;
262 assert_se(in_addr_from_string(f
, before
, &ubefore
) >= 0);
265 assert_se((in_addr_prefix_next(f
, &t
, pl
) > 0) == !!after
);
268 assert_se(in_addr_from_string(f
, after
, &uafter
) >= 0);
269 assert_se(in_addr_equal(f
, &t
, &uafter
) > 0);
273 static void test_in_addr_prefix_next(void) {
275 test_in_addr_prefix_next_one(AF_INET
, "192.168.0.0", 24, "192.168.1.0");
276 test_in_addr_prefix_next_one(AF_INET
, "192.168.0.0", 16, "192.169.0.0");
277 test_in_addr_prefix_next_one(AF_INET
, "192.168.0.0", 20, "192.168.16.0");
279 test_in_addr_prefix_next_one(AF_INET
, "0.0.0.0", 32, "0.0.0.1");
280 test_in_addr_prefix_next_one(AF_INET
, "255.255.255.255", 32, NULL
);
281 test_in_addr_prefix_next_one(AF_INET
, "255.255.255.0", 24, NULL
);
283 test_in_addr_prefix_next_one(AF_INET6
, "4400::", 128, "4400::0001");
284 test_in_addr_prefix_next_one(AF_INET6
, "4400::", 120, "4400::0100");
285 test_in_addr_prefix_next_one(AF_INET6
, "4400::", 127, "4400::0002");
286 test_in_addr_prefix_next_one(AF_INET6
, "4400::", 8, "4500::");
287 test_in_addr_prefix_next_one(AF_INET6
, "4400::", 7, "4600::");
289 test_in_addr_prefix_next_one(AF_INET6
, "::", 128, "::1");
291 test_in_addr_prefix_next_one(AF_INET6
, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, NULL
);
292 test_in_addr_prefix_next_one(AF_INET6
, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00", 120, NULL
);
296 static void test_in_addr_to_string_one(int f
, const char *addr
) {
297 union in_addr_union ua
;
298 _cleanup_free_
char *r
= NULL
;
300 assert_se(in_addr_from_string(f
, addr
, &ua
) >= 0);
301 assert_se(in_addr_to_string(f
, &ua
, &r
) >= 0);
302 printf("test_in_addr_to_string_one: %s == %s\n", addr
, r
);
303 assert_se(streq(addr
, r
));
306 static void test_in_addr_to_string(void) {
307 test_in_addr_to_string_one(AF_INET
, "192.168.0.1");
308 test_in_addr_to_string_one(AF_INET
, "10.11.12.13");
309 test_in_addr_to_string_one(AF_INET6
, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
310 test_in_addr_to_string_one(AF_INET6
, "::1");
311 test_in_addr_to_string_one(AF_INET6
, "fe80::");
314 static void test_in_addr_ifindex_to_string_one(int f
, const char *a
, int ifindex
, const char *b
) {
315 _cleanup_free_
char *r
= NULL
;
316 union in_addr_union ua
, uuaa
;
319 assert_se(in_addr_from_string(f
, a
, &ua
) >= 0);
320 assert_se(in_addr_ifindex_to_string(f
, &ua
, ifindex
, &r
) >= 0);
321 printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b
, r
);
322 assert_se(streq(b
, r
));
324 assert_se(in_addr_ifindex_from_string_auto(b
, &ff
, &uuaa
, &ifindex2
) >= 0);
326 assert_se(in_addr_equal(f
, &ua
, &uuaa
));
327 assert_se(ifindex2
== ifindex
|| ifindex2
== 0);
330 static void test_in_addr_ifindex_to_string(void) {
331 test_in_addr_ifindex_to_string_one(AF_INET
, "192.168.0.1", 7, "192.168.0.1");
332 test_in_addr_ifindex_to_string_one(AF_INET
, "10.11.12.13", 9, "10.11.12.13");
333 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");
334 test_in_addr_ifindex_to_string_one(AF_INET6
, "::1", 11, "::1");
335 test_in_addr_ifindex_to_string_one(AF_INET6
, "fe80::", 12, "fe80::%12");
336 test_in_addr_ifindex_to_string_one(AF_INET6
, "fe80::", 0, "fe80::");
337 test_in_addr_ifindex_to_string_one(AF_INET6
, "fe80::14", 12, "fe80::14%12");
338 test_in_addr_ifindex_to_string_one(AF_INET6
, "fe80::15", -7, "fe80::15");
339 test_in_addr_ifindex_to_string_one(AF_INET6
, "fe80::16", LOOPBACK_IFINDEX
, "fe80::16%1");
342 static void test_in_addr_ifindex_from_string_auto(void) {
344 union in_addr_union ua
;
346 /* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */
348 assert_se(in_addr_ifindex_from_string_auto("fe80::17", &family
, &ua
, &ifindex
) >= 0);
349 assert_se(family
== AF_INET6
);
350 assert_se(ifindex
== 0);
352 assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family
, &ua
, &ifindex
) >= 0);
353 assert_se(family
== AF_INET6
);
354 assert_se(ifindex
== 19);
356 assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family
, &ua
, &ifindex
) >= 0);
357 assert_se(family
== AF_INET6
);
358 assert_se(ifindex
== LOOPBACK_IFINDEX
);
360 assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family
, &ua
, &ifindex
) == -ENODEV
);
363 static void test_sockaddr_equal(void) {
364 union sockaddr_union a
= {
365 .in
.sin_family
= AF_INET
,
367 .in
.sin_addr
.s_addr
= htobe32(INADDR_ANY
),
369 union sockaddr_union b
= {
370 .in
.sin_family
= AF_INET
,
372 .in
.sin_addr
.s_addr
= htobe32(INADDR_ANY
),
374 union sockaddr_union c
= {
375 .in
.sin_family
= AF_INET
,
377 .in
.sin_addr
.s_addr
= htobe32(1234),
379 union sockaddr_union d
= {
380 .in6
.sin6_family
= AF_INET6
,
382 .in6
.sin6_addr
= IN6ADDR_ANY_INIT
,
384 union sockaddr_union e
= {
385 .vm
.svm_family
= AF_VSOCK
,
387 .vm
.svm_cid
= VMADDR_CID_ANY
,
389 assert_se(sockaddr_equal(&a
, &a
));
390 assert_se(sockaddr_equal(&a
, &b
));
391 assert_se(sockaddr_equal(&d
, &d
));
392 assert_se(sockaddr_equal(&e
, &e
));
393 assert_se(!sockaddr_equal(&a
, &c
));
394 assert_se(!sockaddr_equal(&b
, &c
));
395 assert_se(!sockaddr_equal(&a
, &e
));
398 static void test_sockaddr_un_len(void) {
399 static const struct sockaddr_un fs
= {
400 .sun_family
= AF_UNIX
,
401 .sun_path
= "/foo/bar/waldo",
404 static const struct sockaddr_un abstract
= {
405 .sun_family
= AF_UNIX
,
406 .sun_path
= "\0foobar",
409 assert_se(SOCKADDR_UN_LEN(fs
) == offsetof(struct sockaddr_un
, sun_path
) + strlen(fs
.sun_path
));
410 assert_se(SOCKADDR_UN_LEN(abstract
) == offsetof(struct sockaddr_un
, sun_path
) + 1 + strlen(abstract
.sun_path
+ 1));
413 static void test_in_addr_is_multicast(void) {
414 union in_addr_union a
, b
;
417 assert_se(in_addr_from_string_auto("192.168.3.11", &f
, &a
) >= 0);
418 assert_se(in_addr_is_multicast(f
, &a
) == 0);
420 assert_se(in_addr_from_string_auto("224.0.0.1", &f
, &a
) >= 0);
421 assert_se(in_addr_is_multicast(f
, &a
) == 1);
423 assert_se(in_addr_from_string_auto("FF01:0:0:0:0:0:0:1", &f
, &b
) >= 0);
424 assert_se(in_addr_is_multicast(f
, &b
) == 1);
426 assert_se(in_addr_from_string_auto("2001:db8::c:69b:aeff:fe53:743e", &f
, &b
) >= 0);
427 assert_se(in_addr_is_multicast(f
, &b
) == 0);
430 static void test_getpeercred_getpeergroups(void) {
433 r
= safe_fork("(getpeercred)", FORK_DEATHSIG
|FORK_LOG
|FORK_WAIT
, NULL
);
437 static const gid_t gids
[] = { 3, 4, 5, 6, 7 };
439 _cleanup_free_ gid_t
*peer_groups
= NULL
;
446 if (geteuid() == 0) {
449 test_gids
= (gid_t
*) gids
;
450 n_test_gids
= ELEMENTSOF(gids
);
452 assert_se(setgroups(n_test_gids
, test_gids
) >= 0);
453 assert_se(setresgid(test_gid
, test_gid
, test_gid
) >= 0);
454 assert_se(setresuid(test_uid
, test_uid
, test_uid
) >= 0);
462 ngroups_max
= sysconf(_SC_NGROUPS_MAX
);
463 assert(ngroups_max
> 0);
465 test_gids
= newa(gid_t
, ngroups_max
);
467 r
= getgroups(ngroups_max
, test_gids
);
469 n_test_gids
= (size_t) r
;
472 assert_se(socketpair(AF_UNIX
, SOCK_STREAM
, 0, pair
) >= 0);
474 assert_se(getpeercred(pair
[0], &ucred
) >= 0);
476 assert_se(ucred
.uid
== test_uid
);
477 assert_se(ucred
.gid
== test_gid
);
478 assert_se(ucred
.pid
== getpid_cached());
480 r
= getpeergroups(pair
[0], &peer_groups
);
481 assert_se(r
>= 0 || IN_SET(r
, -EOPNOTSUPP
, -ENOPROTOOPT
));
484 assert_se((size_t) r
== n_test_gids
);
485 assert_se(memcmp(peer_groups
, test_gids
, sizeof(gid_t
) * n_test_gids
) == 0);
488 safe_close_pair(pair
);
492 int main(int argc
, char *argv
[]) {
494 log_set_max_level(LOG_DEBUG
);
498 test_socket_address_parse();
499 test_socket_address_parse_netlink();
500 test_socket_address_equal();
501 test_socket_address_get_path();
502 test_socket_address_is();
503 test_socket_address_is_netlink();
505 test_in_addr_is_null();
506 test_in_addr_prefix_intersect();
507 test_in_addr_prefix_next();
508 test_in_addr_to_string();
509 test_in_addr_ifindex_to_string();
510 test_in_addr_ifindex_from_string_auto();
512 test_sockaddr_equal();
514 test_sockaddr_un_len();
516 test_in_addr_is_multicast();
518 test_getpeercred_getpeergroups();