1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2014 Intel Corporation. All rights reserved.
6 #include <netinet/icmp6.h>
11 #include "alloc-util.h"
13 #include "hexdecoct.h"
14 #include "icmp6-packet.h"
15 #include "icmp6-test-util.h"
16 #include "in-addr-util.h"
17 #include "ndisc-internal.h"
21 static struct ether_addr mac_addr
= {
22 .ether_addr_octet
= {'A', 'B', 'C', '1', '2', '3'}
25 static bool verbose
= false;
27 static void router_dump(sd_ndisc_router
*rt
) {
30 usec_t t
, lifetime
, retrans_time
;
39 assert_se(sd_ndisc_router_get_sender_address(rt
, &addr
) >= 0);
40 log_info("Sender: %s", IN6_ADDR_TO_STRING(&addr
));
42 assert_se(sd_ndisc_router_get_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
43 log_info("Timestamp: %s", FORMAT_TIMESTAMP(t
));
45 assert_se(sd_ndisc_router_get_timestamp(rt
, CLOCK_MONOTONIC
, &t
) >= 0);
46 log_info("Monotonic: %" PRIu64
, t
);
48 if (sd_ndisc_router_get_hop_limit(rt
, &hop_limit
) < 0)
49 log_info("No hop limit set");
51 log_info("Hop limit: %u", hop_limit
);
53 assert_se(sd_ndisc_router_get_flags(rt
, &flags
) >= 0);
54 log_info("Flags: <%s|%s>",
55 flags
& ND_RA_FLAG_OTHER
? "OTHER" : "",
56 flags
& ND_RA_FLAG_MANAGED
? "MANAGED" : "");
58 assert_se(sd_ndisc_router_get_preference(rt
, &preference
) >= 0);
59 log_info("Preference: %s",
60 preference
== SD_NDISC_PREFERENCE_LOW
? "low" :
61 preference
== SD_NDISC_PREFERENCE_HIGH
? "high" : "medium");
63 assert_se(sd_ndisc_router_get_lifetime(rt
, &lifetime
) >= 0);
64 assert_se(sd_ndisc_router_get_lifetime_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
65 log_info("Lifetime: %s (%s)", FORMAT_TIMESPAN(lifetime
, USEC_PER_SEC
), FORMAT_TIMESTAMP(t
));
67 assert_se(sd_ndisc_router_get_retransmission_time(rt
, &retrans_time
) >= 0);
68 log_info("Retransmission Time: %s", FORMAT_TIMESPAN(retrans_time
, USEC_PER_SEC
));
70 if (sd_ndisc_router_get_mtu(rt
, &mtu
) < 0)
71 log_info("No MTU set");
73 log_info("MTU: %" PRIu32
, mtu
);
75 r
= sd_ndisc_router_option_rewind(rt
);
84 assert_se(sd_ndisc_router_option_get_type(rt
, &type
) >= 0);
86 log_info(">> Option %u", type
);
90 case SD_NDISC_OPTION_SOURCE_LL_ADDRESS
:
91 case SD_NDISC_OPTION_TARGET_LL_ADDRESS
: {
92 _cleanup_free_
char *c
= NULL
;
96 assert_se(sd_ndisc_router_option_get_raw(rt
, &p
, &n
) >= 0);
98 assert_se(c
= hexmem(p
+ 2, n
- 2));
100 log_info("Address: %s", c
);
104 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
105 uint8_t prefix_len
, pfl
;
108 assert_se(sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime
) >= 0);
109 assert_se(sd_ndisc_router_prefix_get_valid_lifetime_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
110 log_info("Valid Lifetime: %s (%s)", FORMAT_TIMESPAN(lifetime
, USEC_PER_SEC
), FORMAT_TIMESTAMP(t
));
112 assert_se(sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime
) >= 0);
113 assert_se(sd_ndisc_router_prefix_get_preferred_lifetime_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
114 log_info("Preferred Lifetime: %s (%s)", FORMAT_TIMESPAN(lifetime
, USEC_PER_SEC
), FORMAT_TIMESTAMP(t
));
116 assert_se(sd_ndisc_router_prefix_get_flags(rt
, &pfl
) >= 0);
117 log_info("Flags: <%s|%s>",
118 pfl
& ND_OPT_PI_FLAG_ONLINK
? "ONLINK" : "",
119 pfl
& ND_OPT_PI_FLAG_AUTO
? "AUTO" : "");
121 assert_se(sd_ndisc_router_prefix_get_prefixlen(rt
, &prefix_len
) >= 0);
122 log_info("Prefix Length: %u", prefix_len
);
124 assert_se(sd_ndisc_router_prefix_get_address(rt
, &a
) >= 0);
125 log_info("Prefix: %s", IN6_ADDR_TO_STRING(&a
));
130 case SD_NDISC_OPTION_RDNSS
: {
131 const struct in6_addr
*a
;
134 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
137 for (i
= 0; i
< n
; i
++)
138 log_info("DNS: %s", IN6_ADDR_TO_STRING(a
+ i
));
140 assert_se(sd_ndisc_router_rdnss_get_lifetime(rt
, &lifetime
) >= 0);
141 assert_se(sd_ndisc_router_rdnss_get_lifetime_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
142 log_info("Lifetime: %s (%s)", FORMAT_TIMESPAN(lifetime
, USEC_PER_SEC
), FORMAT_TIMESTAMP(t
));
146 case SD_NDISC_OPTION_DNSSL
: {
149 assert_se(sd_ndisc_router_dnssl_get_domains(rt
, &l
) >= 0);
152 log_info("Domain: %s", *s
);
154 assert_se(sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
) >= 0);
155 assert_se(sd_ndisc_router_dnssl_get_lifetime_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
156 log_info("Lifetime: %s (%s)", FORMAT_TIMESPAN(lifetime
, USEC_PER_SEC
), FORMAT_TIMESTAMP(t
));
160 r
= sd_ndisc_router_option_next(rt
);
164 static int send_ra(uint8_t flags
) {
165 uint8_t advertisement
[] = {
166 /* struct nd_router_advert */
167 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 /* type = 0x03 (SD_NDISC_OPTION_PREFIX_INFORMATION), length = 32 */
170 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
171 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
172 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174 /* type = 0x19 (SD_NDISC_OPTION_RDNSS), length = 24 */
175 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
176 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
178 /* type = 0x1f (SD_NDISC_OPTION_DNSSL), length = 24 */
179 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
180 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
181 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182 /* type = 0x01 (SD_NDISC_OPTION_SOURCE_LL_ADDRESS), length = 8 */
183 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
186 advertisement
[5] = flags
;
188 assert_se(write(test_fd
[1], advertisement
, sizeof(advertisement
)) ==
189 sizeof(advertisement
));
192 printf(" sent RA with flag 0x%02x\n", flags
);
197 static void test_callback_ra(sd_ndisc
*nd
, sd_ndisc_event_t event
, void *message
, void *userdata
) {
198 sd_event
*e
= userdata
;
199 static unsigned idx
= 0;
200 uint64_t flags_array
[] = {
211 if (event
!= SD_NDISC_EVENT_ROUTER
)
214 sd_ndisc_router
*rt
= ASSERT_PTR(message
);
218 assert_se(sd_ndisc_router_get_flags(rt
, &flags
) >= 0);
219 assert_se(flags
== flags_array
[idx
]);
223 printf(" got event 0x%02" PRIx64
"\n", flags
);
225 if (idx
< ELEMENTSOF(flags_array
)) {
226 send_ra(flags_array
[idx
]);
234 static int on_recv_rs(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
235 _cleanup_(icmp6_packet_unrefp
) ICMP6Packet
*packet
= NULL
;
236 assert_se(icmp6_packet_receive(fd
, &packet
) >= 0);
242 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
243 _cleanup_(sd_event_source_unrefp
) sd_event_source
*s
= NULL
;
244 _cleanup_(sd_ndisc_unrefp
) sd_ndisc
*nd
= NULL
;
246 assert_se(sd_event_new(&e
) >= 0);
248 assert_se(sd_ndisc_new(&nd
) >= 0);
251 assert_se(sd_ndisc_attach_event(nd
, e
, 0) >= 0);
253 assert_se(sd_ndisc_set_ifindex(nd
, 42) >= 0);
254 assert_se(sd_ndisc_set_mac(nd
, &mac_addr
) >= 0);
255 assert_se(sd_ndisc_set_callback(nd
, test_callback_ra
, e
) >= 0);
257 assert_se(sd_event_add_time_relative(e
, NULL
, CLOCK_BOOTTIME
,
258 30 * USEC_PER_SEC
, 0,
259 NULL
, INT_TO_PTR(-ETIMEDOUT
)) >= 0);
261 assert_se(sd_ndisc_stop(nd
) >= 0);
262 assert_se(sd_ndisc_start(nd
) >= 0);
263 assert_se(sd_ndisc_start(nd
) >= 0);
264 assert_se(sd_ndisc_stop(nd
) >= 0);
265 test_fd
[1] = safe_close(test_fd
[1]);
267 assert_se(sd_ndisc_start(nd
) >= 0);
269 assert_se(sd_event_add_io(e
, &s
, test_fd
[1], EPOLLIN
, on_recv_rs
, nd
) >= 0);
270 assert_se(sd_event_source_set_io_fd_own(s
, true) >= 0);
272 assert_se(sd_event_loop(e
) >= 0);
277 static int send_ra_invalid_domain(uint8_t flags
) {
278 uint8_t advertisement
[] = {
279 /* struct nd_router_advert */
280 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
282 /* type = 0x03 (SD_NDISC_OPTION_PREFIX_INFORMATION), length = 32 */
283 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
284 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
285 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 /* type = 0x19 (SD_NDISC_OPTION_RDNSS), length = 24 */
288 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
289 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
291 /* type = 0x1f (SD_NDISC_OPTION_DNSSL), length = 112 */
292 0x1f, 0x0e, 0xee, 0x68, 0xb0, 0xf4, 0x36, 0x39,
293 0x2c, 0xbc, 0x0b, 0xbc, 0xa9, 0x97, 0x71, 0x37,
294 0xad, 0x86, 0x80, 0x14, 0x2e, 0x58, 0xaa, 0x8a,
295 0xb7, 0xa1, 0xbe, 0x91, 0x59, 0x00, 0xc4, 0xe8,
296 0xdd, 0xd8, 0x6d, 0xe5, 0x4a, 0x7a, 0x71, 0x42,
297 0x74, 0x45, 0x9e, 0x2e, 0xfd, 0x9d, 0x71, 0x1d,
298 0xd0, 0xc0, 0x54, 0x0c, 0x4d, 0x1f, 0xbf, 0x90,
299 0xd9, 0x79, 0x58, 0xc0, 0x1d, 0xa3, 0x39, 0xcf,
300 0xb8, 0xec, 0xd2, 0xe4, 0xcd, 0xb6, 0x13, 0x2f,
301 0xc0, 0x46, 0xe8, 0x07, 0x3f, 0xaa, 0x28, 0xa5,
302 0x23, 0xf1, 0xf0, 0xca, 0xd3, 0x19, 0x3f, 0xfa,
303 0x6c, 0x7c, 0xec, 0x1b, 0xcf, 0x71, 0xeb, 0xba,
304 0x68, 0x1b, 0x8e, 0x7d, 0x93, 0x7e, 0x0b, 0x9f,
305 0xdb, 0x12, 0x9c, 0x75, 0x22, 0x5f, 0x12, 0x00,
306 /* type = 0x01 (SD_NDISC_OPTION_SOURCE_LL_ADDRESS), length = 8 */
307 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
310 advertisement
[5] = flags
;
312 printf("sizeof(nd_router_advert)=%zu\n", sizeof(struct nd_router_advert
));
314 assert_se(write(test_fd
[1], advertisement
, sizeof(advertisement
)) ==
315 sizeof(advertisement
));
318 printf(" sent RA with flag 0x%02x\n", flags
);
323 static int on_recv_rs_invalid_domain(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
324 _cleanup_(icmp6_packet_unrefp
) ICMP6Packet
*packet
= NULL
;
325 assert_se(icmp6_packet_receive(fd
, &packet
) >= 0);
327 return send_ra_invalid_domain(0);
330 TEST(invalid_domain
) {
331 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
332 _cleanup_(sd_event_source_unrefp
) sd_event_source
*s
= NULL
;
333 _cleanup_(sd_ndisc_unrefp
) sd_ndisc
*nd
= NULL
;
335 assert_se(sd_event_new(&e
) >= 0);
337 assert_se(sd_ndisc_new(&nd
) >= 0);
340 assert_se(sd_ndisc_attach_event(nd
, e
, 0) >= 0);
342 assert_se(sd_ndisc_set_ifindex(nd
, 42) >= 0);
343 assert_se(sd_ndisc_set_mac(nd
, &mac_addr
) >= 0);
344 assert_se(sd_ndisc_set_callback(nd
, test_callback_ra
, e
) >= 0);
346 assert_se(sd_event_add_time_relative(e
, NULL
, CLOCK_BOOTTIME
,
347 30 * USEC_PER_SEC
, 0,
348 NULL
, INT_TO_PTR(-ETIMEDOUT
)) >= 0);
350 assert_se(sd_ndisc_start(nd
) >= 0);
352 assert_se(sd_event_add_io(e
, &s
, test_fd
[1], EPOLLIN
, on_recv_rs_invalid_domain
, nd
) >= 0);
353 assert_se(sd_event_source_set_io_fd_own(s
, true) >= 0);
355 assert_se(sd_event_loop(e
) >= 0);
360 static void neighbor_dump(sd_ndisc_neighbor
*na
) {
361 struct in6_addr addr
;
367 assert_se(sd_ndisc_neighbor_get_sender_address(na
, &addr
) >= 0);
368 log_info("Sender: %s", IN6_ADDR_TO_STRING(&addr
));
370 assert_se(sd_ndisc_neighbor_get_flags(na
, &flags
) >= 0);
371 log_info("Flags: Router:%s, Solicited:%s, Override: %s",
372 yes_no(flags
& ND_NA_FLAG_ROUTER
),
373 yes_no(flags
& ND_NA_FLAG_SOLICITED
),
374 yes_no(flags
& ND_NA_FLAG_OVERRIDE
));
376 assert_se(sd_ndisc_neighbor_is_router(na
) == FLAGS_SET(flags
, ND_NA_FLAG_ROUTER
));
377 assert_se(sd_ndisc_neighbor_is_solicited(na
) == FLAGS_SET(flags
, ND_NA_FLAG_SOLICITED
));
378 assert_se(sd_ndisc_neighbor_is_override(na
) == FLAGS_SET(flags
, ND_NA_FLAG_OVERRIDE
));
381 static int send_na(uint32_t flags
) {
382 uint8_t advertisement
[] = {
383 /* struct nd_neighbor_advert */
384 0x88, 0x00, 0xde, 0x83, 0x00, 0x00, 0x00, 0x00,
385 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
386 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
387 /* type = 0x02 (SD_NDISC_OPTION_TARGET_LL_ADDRESS), length = 8 */
388 0x01, 0x01, 'A', 'B', 'C', '1', '2', '3',
391 ((struct nd_neighbor_advert
*) advertisement
)->nd_na_flags_reserved
= flags
;
393 assert_se(write(test_fd
[1], advertisement
, sizeof(advertisement
)) == sizeof(advertisement
));
395 printf(" sent NA with flag 0x%02x\n", flags
);
400 static void test_callback_na(sd_ndisc
*nd
, sd_ndisc_event_t event
, void *message
, void *userdata
) {
401 sd_event
*e
= userdata
;
402 static unsigned idx
= 0;
403 uint32_t flags_array
[] = {
407 ND_NA_FLAG_SOLICITED
,
408 ND_NA_FLAG_SOLICITED
| ND_NA_FLAG_OVERRIDE
,
414 if (event
!= SD_NDISC_EVENT_NEIGHBOR
)
417 sd_ndisc_neighbor
*rt
= ASSERT_PTR(message
);
421 assert_se(sd_ndisc_neighbor_get_flags(rt
, &flags
) >= 0);
422 assert_se(flags
== flags_array
[idx
]);
426 printf(" got event 0x%02" PRIx32
"\n", flags
);
428 if (idx
< ELEMENTSOF(flags_array
)) {
429 send_na(flags_array
[idx
]);
437 static int on_recv_rs_na(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
438 _cleanup_(icmp6_packet_unrefp
) ICMP6Packet
*packet
= NULL
;
439 assert_se(icmp6_packet_receive(fd
, &packet
) >= 0);
445 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
446 _cleanup_(sd_event_source_unrefp
) sd_event_source
*s
= NULL
;
447 _cleanup_(sd_ndisc_unrefp
) sd_ndisc
*nd
= NULL
;
449 assert_se(sd_event_new(&e
) >= 0);
451 assert_se(sd_ndisc_new(&nd
) >= 0);
454 assert_se(sd_ndisc_attach_event(nd
, e
, 0) >= 0);
456 assert_se(sd_ndisc_set_ifindex(nd
, 42) >= 0);
457 assert_se(sd_ndisc_set_mac(nd
, &mac_addr
) >= 0);
458 assert_se(sd_ndisc_set_callback(nd
, test_callback_na
, e
) >= 0);
460 assert_se(sd_event_add_time_relative(e
, NULL
, CLOCK_BOOTTIME
,
461 30 * USEC_PER_SEC
, 0,
462 NULL
, INT_TO_PTR(-ETIMEDOUT
)) >= 0);
464 assert_se(sd_ndisc_start(nd
) >= 0);
466 assert_se(sd_event_add_io(e
, &s
, test_fd
[1], EPOLLIN
, on_recv_rs_na
, nd
) >= 0);
467 assert_se(sd_event_source_set_io_fd_own(s
, true) >= 0);
469 assert_se(sd_event_loop(e
) >= 0);
474 static int on_recv_rs_timeout(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
475 _cleanup_(icmp6_packet_unrefp
) ICMP6Packet
*packet
= NULL
;
476 sd_ndisc
*nd
= ASSERT_PTR(userdata
);
477 static int count
= 0;
478 static usec_t last
= 0;
481 assert_se(icmp6_packet_receive(fd
, &packet
) >= 0);
484 sd_event_exit(nd
->event
, 0);
487 /* initial RT = IRT + RAND*IRT */
488 min
= NDISC_ROUTER_SOLICITATION_INTERVAL
-
489 NDISC_ROUTER_SOLICITATION_INTERVAL
/ 10;
490 max
= NDISC_ROUTER_SOLICITATION_INTERVAL
+
491 NDISC_ROUTER_SOLICITATION_INTERVAL
/ 10;
493 /* next RT = 2*RTprev + RAND*RTprev */
494 min
= 2 * last
- last
/ 10;
495 max
= 2 * last
+ last
/ 10;
499 if (last
* 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
) {
500 min
= NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
-
501 NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
/ 10;
502 max
= NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
+
503 NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
/ 10;
506 log_info("backoff timeout interval %2d %s%s <= %s <= %s",
508 last
* 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
? "(max) ": "",
509 FORMAT_TIMESPAN(min
, USEC_PER_MSEC
),
510 FORMAT_TIMESPAN(nd
->retransmit_time
, USEC_PER_MSEC
),
511 FORMAT_TIMESPAN(max
, USEC_PER_MSEC
));
513 assert_se(min
<= nd
->retransmit_time
);
514 assert_se(max
>= nd
->retransmit_time
);
516 last
= nd
->retransmit_time
;
518 assert_se(sd_event_source_set_time(nd
->timeout_event_source
, 0) >= 0);
524 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
525 _cleanup_(sd_event_source_unrefp
) sd_event_source
*s
= NULL
;
526 _cleanup_(sd_ndisc_unrefp
) sd_ndisc
*nd
= NULL
;
528 assert_se(sd_event_new(&e
) >= 0);
530 assert_se(sd_ndisc_new(&nd
) >= 0);
533 assert_se(sd_ndisc_attach_event(nd
, e
, 0) >= 0);
535 assert_se(sd_ndisc_set_ifindex(nd
, 42) >= 0);
536 assert_se(sd_ndisc_set_mac(nd
, &mac_addr
) >= 0);
538 assert_se(sd_event_add_time_relative(e
, NULL
, CLOCK_BOOTTIME
,
539 30 * USEC_PER_SEC
, 0,
540 NULL
, INT_TO_PTR(-ETIMEDOUT
)) >= 0);
542 assert_se(sd_ndisc_start(nd
) >= 0);
544 assert_se(sd_event_add_io(e
, &s
, test_fd
[1], EPOLLIN
, on_recv_rs_timeout
, nd
) >= 0);
545 assert_se(sd_event_source_set_io_fd_own(s
, true) >= 0);
547 assert_se(sd_event_loop(e
) >= 0);
552 DEFINE_TEST_MAIN(LOG_DEBUG
);