]> git.proxmox.com Git - systemd.git/blame - src/test/test-socket-util.c
New upstream version 240
[systemd.git] / src / test / test-socket-util.c
CommitLineData
52ad194e 1/* SPDX-License-Identifier: LGPL-2.1+ */
e842803a 2
1d42b86d
MB
3#include <sys/types.h>
4#include <unistd.h>
5#include <grp.h>
6
db2df898
MP
7#include "alloc-util.h"
8#include "async.h"
6e866b33
MB
9#include "escape.h"
10#include "exit-status.h"
db2df898 11#include "fd-util.h"
5eef597e 12#include "in-addr-util.h"
6e866b33 13#include "io-util.h"
e842803a 14#include "log.h"
db2df898 15#include "macro.h"
6e866b33 16#include "missing_network.h"
1d42b86d 17#include "process-util.h"
db2df898
MP
18#include "socket-util.h"
19#include "string-util.h"
6e866b33
MB
20#include "tests.h"
21#include "tmpfile-util.h"
db2df898 22#include "util.h"
e842803a 23
aa27b158 24static void test_ifname_valid(void) {
6e866b33
MB
25 log_info("/* %s */", __func__);
26
aa27b158
MP
27 assert(ifname_valid("foo"));
28 assert(ifname_valid("eth0"));
29
30 assert(!ifname_valid("0"));
31 assert(!ifname_valid("99"));
32 assert(ifname_valid("a99"));
33 assert(ifname_valid("99a"));
34
35 assert(!ifname_valid(NULL));
36 assert(!ifname_valid(""));
37 assert(!ifname_valid(" "));
38 assert(!ifname_valid(" foo"));
39 assert(!ifname_valid("bar\n"));
40 assert(!ifname_valid("."));
41 assert(!ifname_valid(".."));
42 assert(ifname_valid("foo.bar"));
43 assert(!ifname_valid("x:y"));
44
45 assert(ifname_valid("xxxxxxxxxxxxxxx"));
46 assert(!ifname_valid("xxxxxxxxxxxxxxxx"));
47}
48
6e866b33 49static void test_socket_address_parse_one(const char *in, int ret, int family, const char *expected) {
e842803a 50 SocketAddress a;
6e866b33
MB
51 _cleanup_free_ char *out = NULL;
52 int r;
53
54 r = socket_address_parse(&a, in);
55 if (r >= 0)
56 assert_se(socket_address_print(&a, &out) >= 0);
57
58 log_info("\"%s\" → %s → \"%s\" (expect \"%s\")", in,
59 r >= 0 ? "✓" : "✗", empty_to_dash(out), r >= 0 ? expected ?: in : "-");
60 assert_se(r == ret);
61 if (r >= 0) {
62 assert_se(a.sockaddr.sa.sa_family == family);
63 assert_se(streq(out, expected ?: in));
64 }
65}
66
67#define SUN_PATH_LEN (sizeof(((struct sockaddr_un){}).sun_path))
68assert_cc(sizeof(((struct sockaddr_un){}).sun_path) == 108);
e842803a 69
6e866b33
MB
70static void test_socket_address_parse(void) {
71 log_info("/* %s */", __func__);
72
73 test_socket_address_parse_one("junk", -EINVAL, 0, NULL);
74 test_socket_address_parse_one("192.168.1.1", -EINVAL, 0, NULL);
75 test_socket_address_parse_one(".168.1.1", -EINVAL, 0, NULL);
76 test_socket_address_parse_one("989.168.1.1", -EINVAL, 0, NULL);
77 test_socket_address_parse_one("192.168.1.1:65536", -ERANGE, 0, NULL);
78 test_socket_address_parse_one("192.168.1.1:0", -EINVAL, 0, NULL);
79 test_socket_address_parse_one("0", -EINVAL, 0, NULL);
80 test_socket_address_parse_one("65536", -ERANGE, 0, NULL);
e842803a 81
6e866b33
MB
82 const int default_family = socket_ipv6_is_supported() ? AF_INET6 : AF_INET;
83
84 test_socket_address_parse_one("65535", 0, default_family, "[::]:65535");
e842803a 85
db2df898
MP
86 /* The checks below will pass even if ipv6 is disabled in
87 * kernel. The underlying glibc's inet_pton() is just a string
88 * parser and doesn't make any syscalls. */
e842803a 89
6e866b33
MB
90 test_socket_address_parse_one("[::1]", -EINVAL, 0, NULL);
91 test_socket_address_parse_one("[::1]8888", -EINVAL, 0, NULL);
92 test_socket_address_parse_one("::1", -EINVAL, 0, NULL);
93 test_socket_address_parse_one("[::1]:0", -EINVAL, 0, NULL);
94 test_socket_address_parse_one("[::1]:65536", -ERANGE, 0, NULL);
95 test_socket_address_parse_one("[a:b:1]:8888", -EINVAL, 0, NULL);
e842803a 96
6e866b33
MB
97 test_socket_address_parse_one("8888", 0, default_family, "[::]:8888");
98 test_socket_address_parse_one("[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8888", 0, AF_INET6,
99 "[2001:db8:0:85a3::ac1f:8001]:8888");
100 test_socket_address_parse_one("[::1]:8888", 0, AF_INET6, NULL);
101 test_socket_address_parse_one("192.168.1.254:8888", 0, AF_INET, NULL);
102 test_socket_address_parse_one("/foo/bar", 0, AF_UNIX, NULL);
103 test_socket_address_parse_one("/", 0, AF_UNIX, NULL);
104 test_socket_address_parse_one("@abstract", 0, AF_UNIX, NULL);
e842803a 105
6e866b33
MB
106 {
107 char aaa[SUN_PATH_LEN + 1] = "@";
e842803a 108
6e866b33
MB
109 memset(aaa + 1, 'a', SUN_PATH_LEN - 1);
110 char_array_0(aaa);
e842803a 111
6e866b33 112 test_socket_address_parse_one(aaa, -EINVAL, 0, NULL);
e842803a 113
6e866b33
MB
114 aaa[SUN_PATH_LEN - 1] = '\0';
115 test_socket_address_parse_one(aaa, 0, AF_UNIX, NULL);
116 }
e842803a 117
6e866b33
MB
118 test_socket_address_parse_one("vsock:2:1234", 0, AF_VSOCK, NULL);
119 test_socket_address_parse_one("vsock::1234", 0, AF_VSOCK, NULL);
120 test_socket_address_parse_one("vsock:2:1234x", -EINVAL, 0, NULL);
121 test_socket_address_parse_one("vsock:2x:1234", -EINVAL, 0, NULL);
122 test_socket_address_parse_one("vsock:2", -EINVAL, 0, NULL);
123}
2897b343 124
6e866b33
MB
125static void test_socket_print_unix_one(const char *in, size_t len_in, const char *expected) {
126 _cleanup_free_ char *out = NULL, *c = NULL;
127
128 SocketAddress a = { .sockaddr = { .un = { .sun_family = AF_UNIX } },
129 .size = offsetof(struct sockaddr_un, sun_path) + len_in,
130 .type = SOCK_STREAM,
131 };
132 memcpy(a.sockaddr.un.sun_path, in, len_in);
133
134 assert_se(socket_address_print(&a, &out) >= 0);
135 assert_se(c = cescape(in));
136 log_info("\"%s\" → \"%s\" (expect \"%s\")", in, out, expected);
137 assert_se(streq(out, expected));
138}
139
140static void test_socket_print_unix(void) {
141 log_info("/* %s */", __func__);
142
143 /* Some additional tests for abstract addresses which we don't parse */
144
145 test_socket_print_unix_one("\0\0\0\0", 4, "@\\000\\000\\000");
146 test_socket_print_unix_one("@abs", 5, "@abs");
147 test_socket_print_unix_one("\n", 2, "\\n");
148 test_socket_print_unix_one("", 1, "<unnamed>");
149 test_socket_print_unix_one("\0", 1, "<unnamed>");
150 test_socket_print_unix_one("\0_________________________there's 108 characters in this string_____________________________________________", 108,
151 "@_________________________there\\'s 108 characters in this string_____________________________________________");
152 test_socket_print_unix_one("////////////////////////////////////////////////////////////////////////////////////////////////////////////", 108,
153 "////////////////////////////////////////////////////////////////////////////////////////////////////////////");
154 test_socket_print_unix_one("////////////////////////////////////////////////////////////////////////////////////////////////////////////", 109,
155 "////////////////////////////////////////////////////////////////////////////////////////////////////////////");
156 test_socket_print_unix_one("\0\a\b\n\255", 6, "@\\a\\b\\n\\255\\000");
e842803a
MB
157}
158
159static void test_socket_address_parse_netlink(void) {
160 SocketAddress a;
161
6e866b33
MB
162 log_info("/* %s */", __func__);
163
e842803a
MB
164 assert_se(socket_address_parse_netlink(&a, "junk") < 0);
165 assert_se(socket_address_parse_netlink(&a, "") < 0);
166
167 assert_se(socket_address_parse_netlink(&a, "route") >= 0);
168 assert_se(socket_address_parse_netlink(&a, "route 10") >= 0);
169 assert_se(a.sockaddr.sa.sa_family == AF_NETLINK);
170 assert_se(a.protocol == NETLINK_ROUTE);
b012e921
MB
171
172 /* With spaces and tabs */
173 assert_se(socket_address_parse_netlink(&a, " kobject-uevent ") >= 0);
174 assert_se(socket_address_parse_netlink(&a, " \t kobject-uevent \t 10 \t") >= 0);
175 assert_se(a.sockaddr.sa.sa_family == AF_NETLINK);
176 assert_se(a.protocol == NETLINK_KOBJECT_UEVENT);
177
178 assert_se(socket_address_parse_netlink(&a, "kobject-uevent\t10") >= 0);
179 assert_se(a.sockaddr.sa.sa_family == AF_NETLINK);
180 assert_se(a.protocol == NETLINK_KOBJECT_UEVENT);
181
182 /* oss-fuzz #6884 */
183 assert_se(socket_address_parse_netlink(&a, "\xff") < 0);
e842803a
MB
184}
185
186static void test_socket_address_equal(void) {
6e866b33
MB
187 SocketAddress a, b;
188
189 log_info("/* %s */", __func__);
e842803a
MB
190
191 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
192 assert_se(socket_address_parse(&b, "192.168.1.1:888") >= 0);
193 assert_se(!socket_address_equal(&a, &b));
194
195 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
196 assert_se(socket_address_parse(&b, "192.16.1.1:8888") >= 0);
197 assert_se(!socket_address_equal(&a, &b));
198
199 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
200 assert_se(socket_address_parse(&b, "8888") >= 0);
201 assert_se(!socket_address_equal(&a, &b));
202
203 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
204 assert_se(socket_address_parse(&b, "/foo/bar/") >= 0);
205 assert_se(!socket_address_equal(&a, &b));
206
207 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
208 assert_se(socket_address_parse(&b, "192.168.1.1:8888") >= 0);
209 assert_se(socket_address_equal(&a, &b));
210
211 assert_se(socket_address_parse(&a, "/foo/bar") >= 0);
212 assert_se(socket_address_parse(&b, "/foo/bar") >= 0);
213 assert_se(socket_address_equal(&a, &b));
214
215 assert_se(socket_address_parse(&a, "[::1]:8888") >= 0);
216 assert_se(socket_address_parse(&b, "[::1]:8888") >= 0);
217 assert_se(socket_address_equal(&a, &b));
218
219 assert_se(socket_address_parse(&a, "@abstract") >= 0);
220 assert_se(socket_address_parse(&b, "@abstract") >= 0);
221 assert_se(socket_address_equal(&a, &b));
222
223 assert_se(socket_address_parse_netlink(&a, "firewall") >= 0);
224 assert_se(socket_address_parse_netlink(&b, "firewall") >= 0);
225 assert_se(socket_address_equal(&a, &b));
2897b343
MP
226
227 assert_se(socket_address_parse(&a, "vsock:2:1234") >= 0);
228 assert_se(socket_address_parse(&b, "vsock:2:1234") >= 0);
229 assert_se(socket_address_equal(&a, &b));
230 assert_se(socket_address_parse(&b, "vsock:2:1235") >= 0);
231 assert_se(!socket_address_equal(&a, &b));
232 assert_se(socket_address_parse(&b, "vsock:3:1234") >= 0);
233 assert_se(!socket_address_equal(&a, &b));
e842803a
MB
234}
235
236static void test_socket_address_get_path(void) {
237 SocketAddress a;
238
6e866b33
MB
239 log_info("/* %s */", __func__);
240
e842803a
MB
241 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
242 assert_se(!socket_address_get_path(&a));
243
244 assert_se(socket_address_parse(&a, "@abstract") >= 0);
245 assert_se(!socket_address_get_path(&a));
246
247 assert_se(socket_address_parse(&a, "[::1]:8888") >= 0);
248 assert_se(!socket_address_get_path(&a));
249
250 assert_se(socket_address_parse(&a, "/foo/bar") >= 0);
251 assert_se(streq(socket_address_get_path(&a), "/foo/bar"));
2897b343
MP
252
253 assert_se(socket_address_parse(&a, "vsock:2:1234") >= 0);
254 assert_se(!socket_address_get_path(&a));
e842803a
MB
255}
256
5eef597e
MP
257static void test_socket_address_is(void) {
258 SocketAddress a;
259
6e866b33
MB
260 log_info("/* %s */", __func__);
261
5eef597e
MP
262 assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0);
263 assert_se(socket_address_is(&a, "192.168.1.1:8888", SOCK_STREAM));
264 assert_se(!socket_address_is(&a, "route", SOCK_STREAM));
265 assert_se(!socket_address_is(&a, "192.168.1.1:8888", SOCK_RAW));
266}
267
268static void test_socket_address_is_netlink(void) {
269 SocketAddress a;
270
6e866b33
MB
271 log_info("/* %s */", __func__);
272
5eef597e
MP
273 assert_se(socket_address_parse_netlink(&a, "route 10") >= 0);
274 assert_se(socket_address_is_netlink(&a, "route 10"));
275 assert_se(!socket_address_is_netlink(&a, "192.168.1.1:8888"));
276 assert_se(!socket_address_is_netlink(&a, "route 1"));
277}
278
13d276d0 279static void test_in_addr_is_null(void) {
13d276d0
MP
280 union in_addr_union i = {};
281
6e866b33
MB
282 log_info("/* %s */", __func__);
283
13d276d0
MP
284 assert_se(in_addr_is_null(AF_INET, &i) == true);
285 assert_se(in_addr_is_null(AF_INET6, &i) == true);
286
287 i.in.s_addr = 0x1000000;
288 assert_se(in_addr_is_null(AF_INET, &i) == false);
289 assert_se(in_addr_is_null(AF_INET6, &i) == false);
290
291 assert_se(in_addr_is_null(-1, &i) == -EAFNOSUPPORT);
292}
293
e842803a
MB
294static void test_in_addr_prefix_intersect_one(unsigned f, const char *a, unsigned apl, const char *b, unsigned bpl, int result) {
295 union in_addr_union ua, ub;
296
297 assert_se(in_addr_from_string(f, a, &ua) >= 0);
298 assert_se(in_addr_from_string(f, b, &ub) >= 0);
299
300 assert_se(in_addr_prefix_intersect(f, &ua, apl, &ub, bpl) == result);
301}
302
303static void test_in_addr_prefix_intersect(void) {
6e866b33 304 log_info("/* %s */", __func__);
e842803a
MB
305
306 test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 32, "255.255.255.254", 32, 0);
307 test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 0, "255.255.255.255", 32, 1);
308 test_in_addr_prefix_intersect_one(AF_INET, "0.0.0.0", 0, "47.11.8.15", 32, 1);
309
310 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.1", 24, 1);
311 test_in_addr_prefix_intersect_one(AF_INET, "2.2.2.2", 24, "1.1.1.1", 24, 0);
312
313 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 25, 1);
314 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 26, 1);
315 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.127", 25, 1);
316 test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.255", 25, 0);
317
318 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);
319 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);
320 test_in_addr_prefix_intersect_one(AF_INET6, "::", 0, "beef:beef:beef:beef:beef:beef:beef:beef", 128, 1);
321
322 test_in_addr_prefix_intersect_one(AF_INET6, "1::2", 64, "1::2", 64, 1);
323 test_in_addr_prefix_intersect_one(AF_INET6, "2::2", 64, "1::2", 64, 0);
324
325 test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 121, 1);
326 test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 122, 1);
327 test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::007f", 121, 1);
328 test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::00ff", 121, 0);
329}
330
331static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) {
332 union in_addr_union ubefore, uafter, t;
333
334 assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
335
336 t = ubefore;
337 assert_se((in_addr_prefix_next(f, &t, pl) > 0) == !!after);
338
339 if (after) {
340 assert_se(in_addr_from_string(f, after, &uafter) >= 0);
341 assert_se(in_addr_equal(f, &t, &uafter) > 0);
342 }
343}
344
345static void test_in_addr_prefix_next(void) {
6e866b33 346 log_info("/* %s */", __func__);
e842803a
MB
347
348 test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0");
349 test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0");
350 test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0");
351
352 test_in_addr_prefix_next_one(AF_INET, "0.0.0.0", 32, "0.0.0.1");
353 test_in_addr_prefix_next_one(AF_INET, "255.255.255.255", 32, NULL);
354 test_in_addr_prefix_next_one(AF_INET, "255.255.255.0", 24, NULL);
355
356 test_in_addr_prefix_next_one(AF_INET6, "4400::", 128, "4400::0001");
357 test_in_addr_prefix_next_one(AF_INET6, "4400::", 120, "4400::0100");
358 test_in_addr_prefix_next_one(AF_INET6, "4400::", 127, "4400::0002");
359 test_in_addr_prefix_next_one(AF_INET6, "4400::", 8, "4500::");
360 test_in_addr_prefix_next_one(AF_INET6, "4400::", 7, "4600::");
361
362 test_in_addr_prefix_next_one(AF_INET6, "::", 128, "::1");
363
364 test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, NULL);
365 test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00", 120, NULL);
e842803a
MB
366}
367
e3bff60a
MP
368static void test_in_addr_to_string_one(int f, const char *addr) {
369 union in_addr_union ua;
370 _cleanup_free_ char *r = NULL;
371
372 assert_se(in_addr_from_string(f, addr, &ua) >= 0);
373 assert_se(in_addr_to_string(f, &ua, &r) >= 0);
374 printf("test_in_addr_to_string_one: %s == %s\n", addr, r);
375 assert_se(streq(addr, r));
376}
377
378static void test_in_addr_to_string(void) {
6e866b33
MB
379 log_info("/* %s */", __func__);
380
e3bff60a
MP
381 test_in_addr_to_string_one(AF_INET, "192.168.0.1");
382 test_in_addr_to_string_one(AF_INET, "10.11.12.13");
383 test_in_addr_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
384 test_in_addr_to_string_one(AF_INET6, "::1");
385 test_in_addr_to_string_one(AF_INET6, "fe80::");
386}
387
5a920b42
MP
388static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) {
389 _cleanup_free_ char *r = NULL;
390 union in_addr_union ua, uuaa;
391 int ff, ifindex2;
392
393 assert_se(in_addr_from_string(f, a, &ua) >= 0);
394 assert_se(in_addr_ifindex_to_string(f, &ua, ifindex, &r) >= 0);
395 printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b, r);
396 assert_se(streq(b, r));
397
398 assert_se(in_addr_ifindex_from_string_auto(b, &ff, &uuaa, &ifindex2) >= 0);
399 assert_se(ff == f);
400 assert_se(in_addr_equal(f, &ua, &uuaa));
401 assert_se(ifindex2 == ifindex || ifindex2 == 0);
402}
403
404static void test_in_addr_ifindex_to_string(void) {
6e866b33
MB
405 log_info("/* %s */", __func__);
406
5a920b42
MP
407 test_in_addr_ifindex_to_string_one(AF_INET, "192.168.0.1", 7, "192.168.0.1");
408 test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13");
409 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");
410 test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1");
411 test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 12, "fe80::%12");
412 test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 0, "fe80::");
413 test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 12, "fe80::14%12");
414 test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::15", -7, "fe80::15");
415 test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::16", LOOPBACK_IFINDEX, "fe80::16%1");
416}
417
418static void test_in_addr_ifindex_from_string_auto(void) {
419 int family, ifindex;
420 union in_addr_union ua;
421
6e866b33 422 log_info("/* %s */", __func__);
5a920b42
MP
423 /* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */
424
425 assert_se(in_addr_ifindex_from_string_auto("fe80::17", &family, &ua, &ifindex) >= 0);
426 assert_se(family == AF_INET6);
427 assert_se(ifindex == 0);
428
429 assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family, &ua, &ifindex) >= 0);
430 assert_se(family == AF_INET6);
431 assert_se(ifindex == 19);
432
433 assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family, &ua, &ifindex) >= 0);
434 assert_se(family == AF_INET6);
435 assert_se(ifindex == LOOPBACK_IFINDEX);
436
437 assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV);
438}
439
5eef597e
MP
440static void test_sockaddr_equal(void) {
441 union sockaddr_union a = {
442 .in.sin_family = AF_INET,
443 .in.sin_port = 0,
5a920b42 444 .in.sin_addr.s_addr = htobe32(INADDR_ANY),
5eef597e
MP
445 };
446 union sockaddr_union b = {
447 .in.sin_family = AF_INET,
448 .in.sin_port = 0,
5a920b42 449 .in.sin_addr.s_addr = htobe32(INADDR_ANY),
5eef597e
MP
450 };
451 union sockaddr_union c = {
452 .in.sin_family = AF_INET,
453 .in.sin_port = 0,
5a920b42 454 .in.sin_addr.s_addr = htobe32(1234),
5eef597e
MP
455 };
456 union sockaddr_union d = {
457 .in6.sin6_family = AF_INET6,
458 .in6.sin6_port = 0,
459 .in6.sin6_addr = IN6ADDR_ANY_INIT,
460 };
2897b343
MP
461 union sockaddr_union e = {
462 .vm.svm_family = AF_VSOCK,
463 .vm.svm_port = 0,
464 .vm.svm_cid = VMADDR_CID_ANY,
465 };
6e866b33
MB
466
467 log_info("/* %s */", __func__);
468
5eef597e
MP
469 assert_se(sockaddr_equal(&a, &a));
470 assert_se(sockaddr_equal(&a, &b));
471 assert_se(sockaddr_equal(&d, &d));
2897b343 472 assert_se(sockaddr_equal(&e, &e));
5eef597e
MP
473 assert_se(!sockaddr_equal(&a, &c));
474 assert_se(!sockaddr_equal(&b, &c));
2897b343 475 assert_se(!sockaddr_equal(&a, &e));
5eef597e
MP
476}
477
aa27b158 478static void test_sockaddr_un_len(void) {
6e866b33
MB
479 log_info("/* %s */", __func__);
480
aa27b158
MP
481 static const struct sockaddr_un fs = {
482 .sun_family = AF_UNIX,
483 .sun_path = "/foo/bar/waldo",
484 };
485
486 static const struct sockaddr_un abstract = {
487 .sun_family = AF_UNIX,
488 .sun_path = "\0foobar",
489 };
490
6e866b33 491 assert_se(SOCKADDR_UN_LEN(fs) == offsetof(struct sockaddr_un, sun_path) + strlen(fs.sun_path) + 1);
aa27b158
MP
492 assert_se(SOCKADDR_UN_LEN(abstract) == offsetof(struct sockaddr_un, sun_path) + 1 + strlen(abstract.sun_path + 1));
493}
494
2897b343
MP
495static void test_in_addr_is_multicast(void) {
496 union in_addr_union a, b;
497 int f;
498
6e866b33
MB
499 log_info("/* %s */", __func__);
500
2897b343
MP
501 assert_se(in_addr_from_string_auto("192.168.3.11", &f, &a) >= 0);
502 assert_se(in_addr_is_multicast(f, &a) == 0);
503
504 assert_se(in_addr_from_string_auto("224.0.0.1", &f, &a) >= 0);
505 assert_se(in_addr_is_multicast(f, &a) == 1);
506
507 assert_se(in_addr_from_string_auto("FF01:0:0:0:0:0:0:1", &f, &b) >= 0);
508 assert_se(in_addr_is_multicast(f, &b) == 1);
509
510 assert_se(in_addr_from_string_auto("2001:db8::c:69b:aeff:fe53:743e", &f, &b) >= 0);
511 assert_se(in_addr_is_multicast(f, &b) == 0);
512}
513
1d42b86d
MB
514static void test_getpeercred_getpeergroups(void) {
515 int r;
516
6e866b33
MB
517 log_info("/* %s */", __func__);
518
1d42b86d
MB
519 r = safe_fork("(getpeercred)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
520 assert_se(r >= 0);
521
522 if (r == 0) {
523 static const gid_t gids[] = { 3, 4, 5, 6, 7 };
524 gid_t *test_gids;
1d42b86d
MB
525 size_t n_test_gids;
526 uid_t test_uid;
527 gid_t test_gid;
528 struct ucred ucred;
529 int pair[2];
530
531 if (geteuid() == 0) {
532 test_uid = 1;
533 test_gid = 2;
534 test_gids = (gid_t*) gids;
535 n_test_gids = ELEMENTSOF(gids);
536
537 assert_se(setgroups(n_test_gids, test_gids) >= 0);
538 assert_se(setresgid(test_gid, test_gid, test_gid) >= 0);
539 assert_se(setresuid(test_uid, test_uid, test_uid) >= 0);
540
541 } else {
542 long ngroups_max;
543
544 test_uid = getuid();
545 test_gid = getgid();
546
547 ngroups_max = sysconf(_SC_NGROUPS_MAX);
548 assert(ngroups_max > 0);
549
550 test_gids = newa(gid_t, ngroups_max);
551
552 r = getgroups(ngroups_max, test_gids);
553 assert_se(r >= 0);
554 n_test_gids = (size_t) r;
555 }
556
557 assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0);
558
559 assert_se(getpeercred(pair[0], &ucred) >= 0);
560
561 assert_se(ucred.uid == test_uid);
562 assert_se(ucred.gid == test_gid);
563 assert_se(ucred.pid == getpid_cached());
564
6e866b33
MB
565 {
566 _cleanup_free_ gid_t *peer_groups = NULL;
1d42b86d 567
6e866b33
MB
568 r = getpeergroups(pair[0], &peer_groups);
569 assert_se(r >= 0 || IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT));
570
571 if (r >= 0) {
572 assert_se((size_t) r == n_test_gids);
573 assert_se(memcmp(peer_groups, test_gids, sizeof(gid_t) * n_test_gids) == 0);
574 }
1d42b86d
MB
575 }
576
577 safe_close_pair(pair);
6e866b33 578 _exit(EXIT_SUCCESS);
1d42b86d
MB
579 }
580}
581
6e866b33
MB
582static void test_passfd_read(void) {
583 static const char file_contents[] = "test contents for passfd";
584 _cleanup_close_pair_ int pair[2] = { -1, -1 };
585 int r;
586
587 log_info("/* %s */", __func__);
588
589 assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
590
591 r = safe_fork("(passfd_read)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
592 assert_se(r >= 0);
593
594 if (r == 0) {
595 /* Child */
596 char tmpfile[] = "/tmp/test-socket-util-passfd-read-XXXXXX";
597 _cleanup_close_ int tmpfd = -1;
598
599 pair[0] = safe_close(pair[0]);
600
601 tmpfd = mkostemp_safe(tmpfile);
602 assert_se(tmpfd >= 0);
603 assert_se(write(tmpfd, file_contents, strlen(file_contents)) == (ssize_t) strlen(file_contents));
604 tmpfd = safe_close(tmpfd);
605
606 tmpfd = open(tmpfile, O_RDONLY);
607 assert_se(tmpfd >= 0);
608 assert_se(unlink(tmpfile) == 0);
609
610 assert_se(send_one_fd(pair[1], tmpfd, MSG_DONTWAIT) == 0);
611 _exit(EXIT_SUCCESS);
612 }
613
614 /* Parent */
615 char buf[64];
616 struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1);
617 _cleanup_close_ int fd = -1;
618
619 pair[1] = safe_close(pair[1]);
620
621 assert_se(receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd) == 0);
622
623 assert_se(fd >= 0);
624 r = read(fd, buf, sizeof(buf)-1);
625 assert_se(r >= 0);
626 buf[r] = 0;
627 assert_se(streq(buf, file_contents));
628}
629
630static void test_passfd_contents_read(void) {
631 _cleanup_close_pair_ int pair[2] = { -1, -1 };
632 static const char file_contents[] = "test contents in the file";
633 static const char wire_contents[] = "test contents on the wire";
634 int r;
635
636 log_info("/* %s */", __func__);
637
638 assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
639
640 r = safe_fork("(passfd_contents_read)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
641 assert_se(r >= 0);
642
643 if (r == 0) {
644 /* Child */
645 struct iovec iov = IOVEC_INIT_STRING(wire_contents);
646 char tmpfile[] = "/tmp/test-socket-util-passfd-contents-read-XXXXXX";
647 _cleanup_close_ int tmpfd = -1;
648
649 pair[0] = safe_close(pair[0]);
650
651 tmpfd = mkostemp_safe(tmpfile);
652 assert_se(tmpfd >= 0);
653 assert_se(write(tmpfd, file_contents, strlen(file_contents)) == (ssize_t) strlen(file_contents));
654 tmpfd = safe_close(tmpfd);
655
656 tmpfd = open(tmpfile, O_RDONLY);
657 assert_se(tmpfd >= 0);
658 assert_se(unlink(tmpfile) == 0);
659
660 assert_se(send_one_fd_iov(pair[1], tmpfd, &iov, 1, MSG_DONTWAIT) > 0);
661 _exit(EXIT_SUCCESS);
662 }
663
664 /* Parent */
665 char buf[64];
666 struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1);
667 _cleanup_close_ int fd = -1;
668 ssize_t k;
669
670 pair[1] = safe_close(pair[1]);
671
672 k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd);
673 assert_se(k > 0);
674 buf[k] = 0;
675 assert_se(streq(buf, wire_contents));
676
677 assert_se(fd >= 0);
678 r = read(fd, buf, sizeof(buf)-1);
679 assert_se(r >= 0);
680 buf[r] = 0;
681 assert_se(streq(buf, file_contents));
682}
683
684static void test_receive_nopassfd(void) {
685 _cleanup_close_pair_ int pair[2] = { -1, -1 };
686 static const char wire_contents[] = "no fd passed here";
687 int r;
688
689 log_info("/* %s */", __func__);
690
691 assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
692
693 r = safe_fork("(receive_nopassfd)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
694 assert_se(r >= 0);
695
696 if (r == 0) {
697 /* Child */
698 struct iovec iov = IOVEC_INIT_STRING(wire_contents);
699
700 pair[0] = safe_close(pair[0]);
701
702 assert_se(send_one_fd_iov(pair[1], -1, &iov, 1, MSG_DONTWAIT) > 0);
703 _exit(EXIT_SUCCESS);
704 }
705
706 /* Parent */
707 char buf[64];
708 struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1);
709 int fd = -999;
710 ssize_t k;
711
712 pair[1] = safe_close(pair[1]);
713
714 k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd);
715 assert_se(k > 0);
716 buf[k] = 0;
717 assert_se(streq(buf, wire_contents));
718
719 /* no fd passed here, confirm it was reset */
720 assert_se(fd == -1);
721}
722
723static void test_send_nodata_nofd(void) {
724 _cleanup_close_pair_ int pair[2] = { -1, -1 };
725 int r;
e842803a 726
6e866b33
MB
727 log_info("/* %s */", __func__);
728
729 assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
730
731 r = safe_fork("(send_nodata_nofd)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
732 assert_se(r >= 0);
733
734 if (r == 0) {
735 /* Child */
736 pair[0] = safe_close(pair[0]);
737
738 assert_se(send_one_fd_iov(pair[1], -1, NULL, 0, MSG_DONTWAIT) == -EINVAL);
739 _exit(EXIT_SUCCESS);
740 }
741
742 /* Parent */
743 char buf[64];
744 struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1);
745 int fd = -999;
746 ssize_t k;
747
748 pair[1] = safe_close(pair[1]);
749
750 k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd);
751 /* recvmsg() will return errno EAGAIN if nothing was sent */
752 assert_se(k == -EAGAIN);
753
754 /* receive_one_fd_iov returned error, so confirm &fd wasn't touched */
755 assert_se(fd == -999);
756}
757
758static void test_send_emptydata(void) {
759 _cleanup_close_pair_ int pair[2] = { -1, -1 };
760 int r;
761
762 log_info("/* %s */", __func__);
763
764 assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
765
766 r = safe_fork("(send_emptydata)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
767 assert_se(r >= 0);
768
769 if (r == 0) {
770 /* Child */
771 struct iovec iov = IOVEC_INIT_STRING(""); /* zero-length iov */
772 assert_se(iov.iov_len == 0);
773
774 pair[0] = safe_close(pair[0]);
775
776 /* This will succeed, since iov is set. */
777 assert_se(send_one_fd_iov(pair[1], -1, &iov, 1, MSG_DONTWAIT) == 0);
778 _exit(EXIT_SUCCESS);
779 }
780
781 /* Parent */
782 char buf[64];
783 struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1);
784 int fd = -999;
785 ssize_t k;
786
787 pair[1] = safe_close(pair[1]);
788
789 k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd);
790 /* receive_one_fd_iov() returns -EIO if an fd is not found and no data was returned. */
791 assert_se(k == -EIO);
792
793 /* receive_one_fd_iov returned error, so confirm &fd wasn't touched */
794 assert_se(fd == -999);
795}
796
797int main(int argc, char *argv[]) {
798 test_setup_logging(LOG_DEBUG);
e842803a 799
aa27b158
MP
800 test_ifname_valid();
801
e842803a 802 test_socket_address_parse();
6e866b33 803 test_socket_print_unix();
e842803a
MB
804 test_socket_address_parse_netlink();
805 test_socket_address_equal();
806 test_socket_address_get_path();
5eef597e
MP
807 test_socket_address_is();
808 test_socket_address_is_netlink();
e842803a 809
13d276d0 810 test_in_addr_is_null();
e842803a
MB
811 test_in_addr_prefix_intersect();
812 test_in_addr_prefix_next();
e3bff60a 813 test_in_addr_to_string();
5a920b42
MP
814 test_in_addr_ifindex_to_string();
815 test_in_addr_ifindex_from_string_auto();
e842803a 816
5eef597e
MP
817 test_sockaddr_equal();
818
aa27b158
MP
819 test_sockaddr_un_len();
820
2897b343
MP
821 test_in_addr_is_multicast();
822
1d42b86d
MB
823 test_getpeercred_getpeergroups();
824
6e866b33
MB
825 test_passfd_read();
826 test_passfd_contents_read();
827 test_receive_nopassfd();
828 test_send_nodata_nofd();
829 test_send_emptydata();
830
e842803a
MB
831 return 0;
832}