]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
c182135d | 2 | |
ca78ad1d ZJS |
3 | #include <fcntl.h> |
4 | #include <grp.h> | |
dfa2b389 | 5 | #include <net/if_arp.h> |
ca78ad1d | 6 | #include <sys/stat.h> |
43f2c88d LP |
7 | #include <sys/types.h> |
8 | #include <unistd.h> | |
43f2c88d | 9 | |
b5efdb8a | 10 | #include "alloc-util.h" |
07630cea | 11 | #include "async.h" |
15dca371 | 12 | #include "escape.h" |
8a3386ab | 13 | #include "exit-status.h" |
3ffd4af2 | 14 | #include "fd-util.h" |
dfa2b389 | 15 | #include "fs-util.h" |
3b653205 | 16 | #include "in-addr-util.h" |
8a3386ab | 17 | #include "io-util.h" |
059f6c42 | 18 | #include "log.h" |
07630cea | 19 | #include "macro.h" |
dfa2b389 | 20 | #include "path-util.h" |
dccca82b | 21 | #include "process-util.h" |
dfa2b389 LP |
22 | #include "random-util.h" |
23 | #include "rm-rf.h" | |
07630cea LP |
24 | #include "socket-util.h" |
25 | #include "string-util.h" | |
6d7c4033 | 26 | #include "tests.h" |
e4de7287 | 27 | #include "tmpfile-util.h" |
c182135d | 28 | |
5c3fa98d ZJS |
29 | assert_cc(SUN_PATH_LEN == 108); |
30 | ||
4f7452a8 | 31 | TEST(ifname_valid) { |
f21b863e YW |
32 | assert_se( ifname_valid("foo")); |
33 | assert_se( ifname_valid("eth0")); | |
34 | ||
35 | assert_se(!ifname_valid("0")); | |
36 | assert_se(!ifname_valid("99")); | |
37 | assert_se( ifname_valid("a99")); | |
38 | assert_se( ifname_valid("99a")); | |
39 | ||
40 | assert_se(!ifname_valid(NULL)); | |
41 | assert_se(!ifname_valid("")); | |
42 | assert_se(!ifname_valid(" ")); | |
43 | assert_se(!ifname_valid(" foo")); | |
44 | assert_se(!ifname_valid("bar\n")); | |
45 | assert_se(!ifname_valid(".")); | |
46 | assert_se(!ifname_valid("..")); | |
47 | assert_se(ifname_valid("foo.bar")); | |
48 | assert_se(!ifname_valid("x:y")); | |
49 | ||
50 | assert_se( ifname_valid_full("xxxxxxxxxxxxxxx", 0)); | |
51 | assert_se(!ifname_valid_full("xxxxxxxxxxxxxxxx", 0)); | |
52 | assert_se( ifname_valid_full("xxxxxxxxxxxxxxxx", IFNAME_VALID_ALTERNATIVE)); | |
53 | assert_se( ifname_valid_full("xxxxxxxxxxxxxxxx", IFNAME_VALID_ALTERNATIVE)); | |
54 | assert_se(!ifname_valid_full("999", IFNAME_VALID_ALTERNATIVE)); | |
55 | assert_se( ifname_valid_full("999", IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC)); | |
56 | assert_se(!ifname_valid_full("0", IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC)); | |
ef76dff2 LP |
57 | } |
58 | ||
15dca371 ZJS |
59 | static void test_socket_print_unix_one(const char *in, size_t len_in, const char *expected) { |
60 | _cleanup_free_ char *out = NULL, *c = NULL; | |
61 | ||
f21b863e | 62 | assert_se(len_in <= SUN_PATH_LEN); |
15dca371 ZJS |
63 | SocketAddress a = { .sockaddr = { .un = { .sun_family = AF_UNIX } }, |
64 | .size = offsetof(struct sockaddr_un, sun_path) + len_in, | |
65 | .type = SOCK_STREAM, | |
66 | }; | |
67 | memcpy(a.sockaddr.un.sun_path, in, len_in); | |
68 | ||
69 | assert_se(socket_address_print(&a, &out) >= 0); | |
70 | assert_se(c = cescape(in)); | |
71 | log_info("\"%s\" → \"%s\" (expect \"%s\")", in, out, expected); | |
72 | assert_se(streq(out, expected)); | |
73 | } | |
74 | ||
4f7452a8 | 75 | TEST(socket_print_unix) { |
15dca371 ZJS |
76 | /* Some additional tests for abstract addresses which we don't parse */ |
77 | ||
78 | test_socket_print_unix_one("\0\0\0\0", 4, "@\\000\\000\\000"); | |
79 | test_socket_print_unix_one("@abs", 5, "@abs"); | |
80 | test_socket_print_unix_one("\n", 2, "\\n"); | |
81 | test_socket_print_unix_one("", 1, "<unnamed>"); | |
82 | test_socket_print_unix_one("\0", 1, "<unnamed>"); | |
83 | test_socket_print_unix_one("\0_________________________there's 108 characters in this string_____________________________________________", 108, | |
84 | "@_________________________there\\'s 108 characters in this string_____________________________________________"); | |
85 | test_socket_print_unix_one("////////////////////////////////////////////////////////////////////////////////////////////////////////////", 108, | |
86 | "////////////////////////////////////////////////////////////////////////////////////////////////////////////"); | |
15dca371 ZJS |
87 | test_socket_print_unix_one("\0\a\b\n\255", 6, "@\\a\\b\\n\\255\\000"); |
88 | } | |
89 | ||
4f7452a8 | 90 | TEST(sockaddr_equal) { |
43dc0043 RC |
91 | union sockaddr_union a = { |
92 | .in.sin_family = AF_INET, | |
93 | .in.sin_port = 0, | |
8e38570e | 94 | .in.sin_addr.s_addr = htobe32(INADDR_ANY), |
43dc0043 RC |
95 | }; |
96 | union sockaddr_union b = { | |
97 | .in.sin_family = AF_INET, | |
98 | .in.sin_port = 0, | |
8e38570e | 99 | .in.sin_addr.s_addr = htobe32(INADDR_ANY), |
43dc0043 RC |
100 | }; |
101 | union sockaddr_union c = { | |
102 | .in.sin_family = AF_INET, | |
103 | .in.sin_port = 0, | |
8e38570e | 104 | .in.sin_addr.s_addr = htobe32(1234), |
43dc0043 RC |
105 | }; |
106 | union sockaddr_union d = { | |
107 | .in6.sin6_family = AF_INET6, | |
108 | .in6.sin6_port = 0, | |
109 | .in6.sin6_addr = IN6ADDR_ANY_INIT, | |
110 | }; | |
0fc0f14b SH |
111 | union sockaddr_union e = { |
112 | .vm.svm_family = AF_VSOCK, | |
113 | .vm.svm_port = 0, | |
114 | .vm.svm_cid = VMADDR_CID_ANY, | |
115 | }; | |
041103a6 | 116 | |
43dc0043 RC |
117 | assert_se(sockaddr_equal(&a, &a)); |
118 | assert_se(sockaddr_equal(&a, &b)); | |
119 | assert_se(sockaddr_equal(&d, &d)); | |
0fc0f14b | 120 | assert_se(sockaddr_equal(&e, &e)); |
43dc0043 RC |
121 | assert_se(!sockaddr_equal(&a, &c)); |
122 | assert_se(!sockaddr_equal(&b, &c)); | |
0fc0f14b | 123 | assert_se(!sockaddr_equal(&a, &e)); |
43dc0043 RC |
124 | } |
125 | ||
4f7452a8 | 126 | TEST(sockaddr_un_len) { |
fc2fffe7 LP |
127 | static const struct sockaddr_un fs = { |
128 | .sun_family = AF_UNIX, | |
129 | .sun_path = "/foo/bar/waldo", | |
130 | }; | |
131 | ||
132 | static const struct sockaddr_un abstract = { | |
133 | .sun_family = AF_UNIX, | |
134 | .sun_path = "\0foobar", | |
135 | }; | |
136 | ||
69995bff | 137 | assert_se(SOCKADDR_UN_LEN(fs) == offsetof(struct sockaddr_un, sun_path) + strlen(fs.sun_path) + 1); |
fc2fffe7 LP |
138 | assert_se(SOCKADDR_UN_LEN(abstract) == offsetof(struct sockaddr_un, sun_path) + 1 + strlen(abstract.sun_path + 1)); |
139 | } | |
140 | ||
4f7452a8 | 141 | TEST(in_addr_is_multicast) { |
1703b203 SS |
142 | union in_addr_union a, b; |
143 | int f; | |
144 | ||
145 | assert_se(in_addr_from_string_auto("192.168.3.11", &f, &a) >= 0); | |
146 | assert_se(in_addr_is_multicast(f, &a) == 0); | |
147 | ||
148 | assert_se(in_addr_from_string_auto("224.0.0.1", &f, &a) >= 0); | |
149 | assert_se(in_addr_is_multicast(f, &a) == 1); | |
150 | ||
151 | assert_se(in_addr_from_string_auto("FF01:0:0:0:0:0:0:1", &f, &b) >= 0); | |
152 | assert_se(in_addr_is_multicast(f, &b) == 1); | |
153 | ||
154 | assert_se(in_addr_from_string_auto("2001:db8::c:69b:aeff:fe53:743e", &f, &b) >= 0); | |
155 | assert_se(in_addr_is_multicast(f, &b) == 0); | |
156 | } | |
157 | ||
4f7452a8 | 158 | TEST(getpeercred_getpeergroups) { |
43f2c88d LP |
159 | int r; |
160 | ||
161 | r = safe_fork("(getpeercred)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); | |
162 | assert_se(r >= 0); | |
163 | ||
164 | if (r == 0) { | |
165 | static const gid_t gids[] = { 3, 4, 5, 6, 7 }; | |
166 | gid_t *test_gids; | |
43f2c88d LP |
167 | size_t n_test_gids; |
168 | uid_t test_uid; | |
169 | gid_t test_gid; | |
170 | struct ucred ucred; | |
171 | int pair[2]; | |
172 | ||
173 | if (geteuid() == 0) { | |
174 | test_uid = 1; | |
175 | test_gid = 2; | |
176 | test_gids = (gid_t*) gids; | |
177 | n_test_gids = ELEMENTSOF(gids); | |
178 | ||
179 | assert_se(setgroups(n_test_gids, test_gids) >= 0); | |
180 | assert_se(setresgid(test_gid, test_gid, test_gid) >= 0); | |
181 | assert_se(setresuid(test_uid, test_uid, test_uid) >= 0); | |
182 | ||
183 | } else { | |
184 | long ngroups_max; | |
185 | ||
186 | test_uid = getuid(); | |
187 | test_gid = getgid(); | |
188 | ||
189 | ngroups_max = sysconf(_SC_NGROUPS_MAX); | |
f21b863e | 190 | assert_se(ngroups_max > 0); |
43f2c88d LP |
191 | |
192 | test_gids = newa(gid_t, ngroups_max); | |
193 | ||
194 | r = getgroups(ngroups_max, test_gids); | |
195 | assert_se(r >= 0); | |
196 | n_test_gids = (size_t) r; | |
197 | } | |
198 | ||
199 | assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0); | |
200 | ||
201 | assert_se(getpeercred(pair[0], &ucred) >= 0); | |
202 | ||
203 | assert_se(ucred.uid == test_uid); | |
204 | assert_se(ucred.gid == test_gid); | |
205 | assert_se(ucred.pid == getpid_cached()); | |
206 | ||
181c4ba7 ZJS |
207 | { |
208 | _cleanup_free_ gid_t *peer_groups = NULL; | |
43f2c88d | 209 | |
181c4ba7 ZJS |
210 | r = getpeergroups(pair[0], &peer_groups); |
211 | assert_se(r >= 0 || IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT)); | |
212 | ||
213 | if (r >= 0) { | |
214 | assert_se((size_t) r == n_test_gids); | |
215 | assert_se(memcmp(peer_groups, test_gids, sizeof(gid_t) * n_test_gids) == 0); | |
216 | } | |
43f2c88d LP |
217 | } |
218 | ||
219 | safe_close_pair(pair); | |
8a3386ab | 220 | _exit(EXIT_SUCCESS); |
43f2c88d LP |
221 | } |
222 | } | |
223 | ||
4f7452a8 | 224 | TEST(passfd_read) { |
8a3386ab FB |
225 | static const char file_contents[] = "test contents for passfd"; |
226 | _cleanup_close_pair_ int pair[2] = { -1, -1 }; | |
227 | int r; | |
228 | ||
229 | assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0); | |
230 | ||
231 | r = safe_fork("(passfd_read)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); | |
232 | assert_se(r >= 0); | |
233 | ||
234 | if (r == 0) { | |
235 | /* Child */ | |
8a3386ab FB |
236 | pair[0] = safe_close(pair[0]); |
237 | ||
367c47c8 ZJS |
238 | char tmpfile[] = "/tmp/test-socket-util-passfd-read-XXXXXX"; |
239 | assert_se(write_tmpfile(tmpfile, file_contents) == 0); | |
8a3386ab | 240 | |
367c47c8 | 241 | _cleanup_close_ int tmpfd = open(tmpfile, O_RDONLY); |
8a3386ab FB |
242 | assert_se(tmpfd >= 0); |
243 | assert_se(unlink(tmpfile) == 0); | |
244 | ||
245 | assert_se(send_one_fd(pair[1], tmpfd, MSG_DONTWAIT) == 0); | |
246 | _exit(EXIT_SUCCESS); | |
247 | } | |
248 | ||
249 | /* Parent */ | |
250 | char buf[64]; | |
251 | struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1); | |
254d1313 | 252 | _cleanup_close_ int fd; |
8a3386ab FB |
253 | |
254 | pair[1] = safe_close(pair[1]); | |
255 | ||
256 | assert_se(receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd) == 0); | |
257 | ||
258 | assert_se(fd >= 0); | |
259 | r = read(fd, buf, sizeof(buf)-1); | |
260 | assert_se(r >= 0); | |
261 | buf[r] = 0; | |
262 | assert_se(streq(buf, file_contents)); | |
263 | } | |
264 | ||
4f7452a8 | 265 | TEST(passfd_contents_read) { |
8a3386ab FB |
266 | _cleanup_close_pair_ int pair[2] = { -1, -1 }; |
267 | static const char file_contents[] = "test contents in the file"; | |
268 | static const char wire_contents[] = "test contents on the wire"; | |
269 | int r; | |
270 | ||
271 | assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0); | |
272 | ||
273 | r = safe_fork("(passfd_contents_read)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); | |
274 | assert_se(r >= 0); | |
275 | ||
276 | if (r == 0) { | |
277 | /* Child */ | |
278 | struct iovec iov = IOVEC_INIT_STRING(wire_contents); | |
279 | char tmpfile[] = "/tmp/test-socket-util-passfd-contents-read-XXXXXX"; | |
8a3386ab FB |
280 | |
281 | pair[0] = safe_close(pair[0]); | |
282 | ||
367c47c8 | 283 | assert_se(write_tmpfile(tmpfile, file_contents) == 0); |
8a3386ab | 284 | |
367c47c8 | 285 | _cleanup_close_ int tmpfd = open(tmpfile, O_RDONLY); |
8a3386ab FB |
286 | assert_se(tmpfd >= 0); |
287 | assert_se(unlink(tmpfile) == 0); | |
288 | ||
289 | assert_se(send_one_fd_iov(pair[1], tmpfd, &iov, 1, MSG_DONTWAIT) > 0); | |
290 | _exit(EXIT_SUCCESS); | |
291 | } | |
292 | ||
293 | /* Parent */ | |
294 | char buf[64]; | |
295 | struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1); | |
254d1313 | 296 | _cleanup_close_ int fd; |
8a3386ab FB |
297 | ssize_t k; |
298 | ||
299 | pair[1] = safe_close(pair[1]); | |
300 | ||
301 | k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd); | |
302 | assert_se(k > 0); | |
303 | buf[k] = 0; | |
304 | assert_se(streq(buf, wire_contents)); | |
305 | ||
306 | assert_se(fd >= 0); | |
307 | r = read(fd, buf, sizeof(buf)-1); | |
308 | assert_se(r >= 0); | |
309 | buf[r] = 0; | |
310 | assert_se(streq(buf, file_contents)); | |
311 | } | |
312 | ||
4f7452a8 | 313 | TEST(receive_nopassfd) { |
8a3386ab FB |
314 | _cleanup_close_pair_ int pair[2] = { -1, -1 }; |
315 | static const char wire_contents[] = "no fd passed here"; | |
316 | int r; | |
317 | ||
318 | assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0); | |
319 | ||
320 | r = safe_fork("(receive_nopassfd)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); | |
321 | assert_se(r >= 0); | |
322 | ||
323 | if (r == 0) { | |
324 | /* Child */ | |
325 | struct iovec iov = IOVEC_INIT_STRING(wire_contents); | |
326 | ||
327 | pair[0] = safe_close(pair[0]); | |
328 | ||
329 | assert_se(send_one_fd_iov(pair[1], -1, &iov, 1, MSG_DONTWAIT) > 0); | |
330 | _exit(EXIT_SUCCESS); | |
331 | } | |
332 | ||
333 | /* Parent */ | |
334 | char buf[64]; | |
335 | struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1); | |
336 | int fd = -999; | |
337 | ssize_t k; | |
338 | ||
339 | pair[1] = safe_close(pair[1]); | |
340 | ||
341 | k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd); | |
342 | assert_se(k > 0); | |
343 | buf[k] = 0; | |
344 | assert_se(streq(buf, wire_contents)); | |
345 | ||
346 | /* no fd passed here, confirm it was reset */ | |
254d1313 | 347 | assert_se(fd == -EBADF); |
8a3386ab FB |
348 | } |
349 | ||
4f7452a8 | 350 | TEST(send_nodata_nofd) { |
8a3386ab FB |
351 | _cleanup_close_pair_ int pair[2] = { -1, -1 }; |
352 | int r; | |
353 | ||
354 | assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0); | |
355 | ||
356 | r = safe_fork("(send_nodata_nofd)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); | |
357 | assert_se(r >= 0); | |
358 | ||
359 | if (r == 0) { | |
360 | /* Child */ | |
361 | pair[0] = safe_close(pair[0]); | |
362 | ||
363 | assert_se(send_one_fd_iov(pair[1], -1, NULL, 0, MSG_DONTWAIT) == -EINVAL); | |
364 | _exit(EXIT_SUCCESS); | |
365 | } | |
366 | ||
367 | /* Parent */ | |
368 | char buf[64]; | |
369 | struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1); | |
370 | int fd = -999; | |
371 | ssize_t k; | |
372 | ||
373 | pair[1] = safe_close(pair[1]); | |
374 | ||
375 | k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd); | |
376 | /* recvmsg() will return errno EAGAIN if nothing was sent */ | |
377 | assert_se(k == -EAGAIN); | |
378 | ||
379 | /* receive_one_fd_iov returned error, so confirm &fd wasn't touched */ | |
380 | assert_se(fd == -999); | |
381 | } | |
382 | ||
4f7452a8 | 383 | TEST(send_emptydata) { |
8a3386ab FB |
384 | _cleanup_close_pair_ int pair[2] = { -1, -1 }; |
385 | int r; | |
386 | ||
387 | assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0); | |
388 | ||
389 | r = safe_fork("(send_emptydata)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); | |
390 | assert_se(r >= 0); | |
391 | ||
392 | if (r == 0) { | |
393 | /* Child */ | |
394 | struct iovec iov = IOVEC_INIT_STRING(""); /* zero-length iov */ | |
395 | assert_se(iov.iov_len == 0); | |
396 | ||
397 | pair[0] = safe_close(pair[0]); | |
398 | ||
399 | /* This will succeed, since iov is set. */ | |
400 | assert_se(send_one_fd_iov(pair[1], -1, &iov, 1, MSG_DONTWAIT) == 0); | |
401 | _exit(EXIT_SUCCESS); | |
402 | } | |
403 | ||
404 | /* Parent */ | |
405 | char buf[64]; | |
406 | struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1); | |
407 | int fd = -999; | |
408 | ssize_t k; | |
409 | ||
410 | pair[1] = safe_close(pair[1]); | |
411 | ||
412 | k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd); | |
413 | /* receive_one_fd_iov() returns -EIO if an fd is not found and no data was returned. */ | |
414 | assert_se(k == -EIO); | |
415 | ||
416 | /* receive_one_fd_iov returned error, so confirm &fd wasn't touched */ | |
417 | assert_se(fd == -999); | |
418 | } | |
419 | ||
4f7452a8 | 420 | TEST(flush_accept) { |
254d1313 | 421 | _cleanup_close_ int listen_stream, listen_dgram, listen_seqpacket, connect_stream, connect_dgram, connect_seqpacket; |
5b116c37 LP |
422 | static const union sockaddr_union sa = { .un.sun_family = AF_UNIX }; |
423 | union sockaddr_union lsa; | |
424 | socklen_t l; | |
425 | ||
426 | listen_stream = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); | |
427 | assert_se(listen_stream >= 0); | |
428 | ||
429 | listen_dgram = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); | |
430 | assert_se(listen_dgram >= 0); | |
431 | ||
432 | listen_seqpacket = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); | |
433 | assert_se(listen_seqpacket >= 0); | |
434 | ||
435 | assert_se(flush_accept(listen_stream) < 0); | |
436 | assert_se(flush_accept(listen_dgram) < 0); | |
437 | assert_se(flush_accept(listen_seqpacket) < 0); | |
438 | ||
439 | assert_se(bind(listen_stream, &sa.sa, sizeof(sa_family_t)) >= 0); | |
440 | assert_se(bind(listen_dgram, &sa.sa, sizeof(sa_family_t)) >= 0); | |
441 | assert_se(bind(listen_seqpacket, &sa.sa, sizeof(sa_family_t)) >= 0); | |
442 | ||
443 | assert_se(flush_accept(listen_stream) < 0); | |
444 | assert_se(flush_accept(listen_dgram) < 0); | |
445 | assert_se(flush_accept(listen_seqpacket) < 0); | |
446 | ||
447 | assert_se(listen(listen_stream, SOMAXCONN) >= 0); | |
448 | assert_se(listen(listen_dgram, SOMAXCONN) < 0); | |
449 | assert_se(listen(listen_seqpacket, SOMAXCONN) >= 0); | |
450 | ||
451 | assert_se(flush_accept(listen_stream) >= 0); | |
452 | assert_se(flush_accept(listen_dgram) < 0); | |
453 | assert_se(flush_accept(listen_seqpacket) >= 0); | |
454 | ||
455 | connect_stream = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); | |
456 | assert_se(connect_stream >= 0); | |
457 | ||
458 | connect_dgram = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); | |
459 | assert_se(connect_dgram >= 0); | |
460 | ||
461 | connect_seqpacket = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); | |
462 | assert_se(connect_seqpacket >= 0); | |
463 | ||
464 | l = sizeof(lsa); | |
465 | assert_se(getsockname(listen_stream, &lsa.sa, &l) >= 0); | |
466 | assert_se(connect(connect_stream, &lsa.sa, l) >= 0); | |
467 | ||
468 | l = sizeof(lsa); | |
469 | assert_se(getsockname(listen_dgram, &lsa.sa, &l) >= 0); | |
470 | assert_se(connect(connect_dgram, &lsa.sa, l) >= 0); | |
471 | ||
472 | l = sizeof(lsa); | |
473 | assert_se(getsockname(listen_seqpacket, &lsa.sa, &l) >= 0); | |
474 | assert_se(connect(connect_seqpacket, &lsa.sa, l) >= 0); | |
475 | ||
476 | assert_se(flush_accept(listen_stream) >= 0); | |
477 | assert_se(flush_accept(listen_dgram) < 0); | |
478 | assert_se(flush_accept(listen_seqpacket) >= 0); | |
479 | } | |
480 | ||
4f7452a8 | 481 | TEST(ipv6_enabled) { |
83e03c4f LP |
482 | log_info("IPv6 supported: %s", yes_no(socket_ipv6_is_supported())); |
483 | log_info("IPv6 enabled: %s", yes_no(socket_ipv6_is_enabled())); | |
484 | } | |
485 | ||
dfa2b389 LP |
486 | TEST(sockaddr_un_set_path) { |
487 | _cleanup_(rm_rf_physical_and_freep) char *t = NULL; | |
488 | _cleanup_(unlink_and_freep) char *sh = NULL; | |
489 | _cleanup_free_ char *j = NULL; | |
490 | union sockaddr_union sa; | |
254d1313 | 491 | _cleanup_close_ int fd1, fd2, fd3; |
dfa2b389 LP |
492 | |
493 | assert_se(mkdtemp_malloc("/tmp/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaXXXXXX", &t) >= 0); | |
494 | assert_se(strlen(t) > SUN_PATH_LEN); | |
495 | ||
496 | assert_se(j = path_join(t, "sock")); | |
497 | assert_se(sockaddr_un_set_path(&sa.un, j) == -ENAMETOOLONG); /* too long for AF_UNIX socket */ | |
498 | ||
499 | assert_se(asprintf(&sh, "/tmp/%" PRIx64, random_u64()) >= 0); | |
500 | assert_se(symlink(t, sh) >= 0); /* create temporary symlink, to access it anyway */ | |
501 | ||
502 | free(j); | |
503 | assert_se(j = path_join(sh, "sock")); | |
504 | assert_se(sockaddr_un_set_path(&sa.un, j) >= 0); | |
505 | ||
506 | fd1 = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); | |
507 | assert_se(fd1 >= 0); | |
508 | assert_se(bind(fd1, &sa.sa, SOCKADDR_LEN(sa)) >= 0); | |
509 | assert_se(listen(fd1, 1) >= 0); | |
510 | ||
511 | sh = unlink_and_free(sh); /* remove temporary symlink */ | |
512 | ||
513 | fd2 = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); | |
514 | assert_se(fd2 >= 0); | |
515 | assert_se(connect(fd2, &sa.sa, SOCKADDR_LEN(sa)) < 0); | |
516 | assert_se(errno == ENOENT); /* we removed the symlink, must fail */ | |
517 | ||
518 | free(j); | |
519 | assert_se(j = path_join(t, "sock")); | |
520 | ||
521 | fd3 = open(j, O_CLOEXEC|O_PATH|O_NOFOLLOW); | |
522 | assert_se(fd3 > 0); | |
523 | assert_se(sockaddr_un_set_path(&sa.un, FORMAT_PROC_FD_PATH(fd3)) >= 0); /* connect via O_PATH instead, circumventing 108ch limit */ | |
524 | ||
525 | assert_se(connect(fd2, &sa.sa, SOCKADDR_LEN(sa)) >= 0); | |
526 | } | |
527 | ||
4f7452a8 | 528 | DEFINE_TEST_MAIN(LOG_DEBUG); |