]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/test-ndisc-ra.c
76f4d7ba3f2d230188988a159c19b6363673bb40
[thirdparty/systemd.git] / src / libsystemd-network / test-ndisc-ra.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3 Copyright © 2017 Intel Corporation. All rights reserved.
4 ***/
5
6 #include <netinet/icmp6.h>
7 #include <arpa/inet.h>
8 #include <unistd.h>
9
10 #include "sd-radv.h"
11
12 #include "alloc-util.h"
13 #include "hexdecoct.h"
14 #include "icmp6-util-unix.h"
15 #include "socket-util.h"
16 #include "strv.h"
17 #include "tests.h"
18
19 static struct ether_addr mac_addr = {
20 .ether_addr_octet = { 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53 }
21 };
22
23 static bool test_stopped;
24 static struct {
25 struct in6_addr address;
26 unsigned char prefixlen;
27 uint32_t valid;
28 uint32_t preferred;
29 bool successful;
30 } prefix[] = {
31 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 64,
33 500, 440, true },
34 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 64,
36 /* indicate default valid and preferred lifetimes for the test code */
37 0, 0, true },
38 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 58,
40 0, 0,
41 /* indicate that this prefix already exists */
42 false },
43 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 120,
45 0, 0,
46 /* indicate that this prefix already exists */
47 false },
48 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 12,
50 0, 0,
51 /* indicate that this prefix already exists */
52 false },
53 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad,
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 48,
55 0, 0, true },
56 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 60,
58 0, 0,
59 /* indicate that this prefix already exists */
60 false },
61 };
62
63 static const struct in6_addr test_rdnss = { { { 0x20, 0x01, 0x0d, 0xb8,
64 0xde, 0xad, 0xbe, 0xef,
65 0x00, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x01 } } };
67 static const char *test_dnssl[] = { "lab.intra",
68 NULL };
69
70 TEST(radv_prefix) {
71 sd_radv_prefix *p;
72
73 assert_se(sd_radv_prefix_new(&p) >= 0);
74
75 ASSERT_RETURN_EXPECTED_SE(sd_radv_prefix_set_onlink(NULL, true) < 0);
76 assert_se(sd_radv_prefix_set_onlink(p, true) >= 0);
77 assert_se(sd_radv_prefix_set_onlink(p, false) >= 0);
78
79 ASSERT_RETURN_EXPECTED_SE(sd_radv_prefix_set_address_autoconfiguration(NULL, true) < 0);
80 assert_se(sd_radv_prefix_set_address_autoconfiguration(p, true) >= 0);
81 assert_se(sd_radv_prefix_set_address_autoconfiguration(p, false) >= 0);
82
83 ASSERT_RETURN_EXPECTED_SE(sd_radv_prefix_set_valid_lifetime(NULL, 1, 1) < 0);
84 assert_se(sd_radv_prefix_set_valid_lifetime(p, 0, 0) >= 0);
85 assert_se(sd_radv_prefix_set_valid_lifetime(p, 300 * USEC_PER_SEC, USEC_INFINITY) >= 0);
86 assert_se(sd_radv_prefix_set_valid_lifetime(p, 300 * USEC_PER_SEC, USEC_PER_YEAR) >= 0);
87
88 ASSERT_RETURN_EXPECTED_SE(sd_radv_prefix_set_preferred_lifetime(NULL, 1, 1) < 0);
89 assert_se(sd_radv_prefix_set_preferred_lifetime(p, 0, 0) >= 0);
90 assert_se(sd_radv_prefix_set_preferred_lifetime(p, 300 * USEC_PER_SEC, USEC_INFINITY) >= 0);
91 assert_se(sd_radv_prefix_set_preferred_lifetime(p, 300 * USEC_PER_SEC, USEC_PER_YEAR) >= 0);
92
93 ASSERT_RETURN_EXPECTED_SE(sd_radv_prefix_set_prefix(NULL, NULL, 0) < 0);
94 ASSERT_RETURN_EXPECTED_SE(sd_radv_prefix_set_prefix(p, NULL, 0) < 0);
95
96 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 64) >= 0);
97 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 0) < 0);
98 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 1) < 0);
99 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 2) < 0);
100 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 3) >= 0);
101 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 125) >= 0);
102 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 128) >= 0);
103 ASSERT_RETURN_EXPECTED_SE(sd_radv_prefix_set_prefix(p, &prefix[0].address, 129) < 0);
104 ASSERT_RETURN_EXPECTED_SE(sd_radv_prefix_set_prefix(p, &prefix[0].address, 255) < 0);
105
106 assert_se(!sd_radv_prefix_unref(p));
107 }
108
109 TEST(radv_route_prefix) {
110 sd_radv_route_prefix *p;
111
112 assert_se(sd_radv_route_prefix_new(&p) >= 0);
113
114 ASSERT_RETURN_EXPECTED_SE(sd_radv_route_prefix_set_lifetime(NULL, 1, 1) < 0);
115 assert_se(sd_radv_route_prefix_set_lifetime(p, 0, 0) >= 0);
116 assert_se(sd_radv_route_prefix_set_lifetime(p, 300 * USEC_PER_SEC, USEC_INFINITY) >= 0);
117 assert_se(sd_radv_route_prefix_set_lifetime(p, 300 * USEC_PER_SEC, USEC_PER_YEAR) >= 0);
118
119 ASSERT_RETURN_EXPECTED_SE(sd_radv_route_prefix_set_prefix(NULL, NULL, 0) < 0);
120 ASSERT_RETURN_EXPECTED_SE(sd_radv_route_prefix_set_prefix(p, NULL, 0) < 0);
121
122 assert_se(sd_radv_route_prefix_set_prefix(p, &prefix[0].address, 64) >= 0);
123 assert_se(sd_radv_route_prefix_set_prefix(p, &prefix[0].address, 0) >= 0);
124 assert_se(sd_radv_route_prefix_set_prefix(p, &prefix[0].address, 1) >= 0);
125 assert_se(sd_radv_route_prefix_set_prefix(p, &prefix[0].address, 2) >= 0);
126 assert_se(sd_radv_route_prefix_set_prefix(p, &prefix[0].address, 3) >= 0);
127 assert_se(sd_radv_route_prefix_set_prefix(p, &prefix[0].address, 125) >= 0);
128 assert_se(sd_radv_route_prefix_set_prefix(p, &prefix[0].address, 128) >= 0);
129 ASSERT_RETURN_EXPECTED_SE(sd_radv_route_prefix_set_prefix(p, &prefix[0].address, 129) < 0);
130 ASSERT_RETURN_EXPECTED_SE(sd_radv_route_prefix_set_prefix(p, &prefix[0].address, 255) < 0);
131
132 assert_se(!sd_radv_route_prefix_unref(p));
133 }
134
135 TEST(radv_pref64_prefix) {
136 sd_radv_pref64_prefix *p;
137
138 assert_se(sd_radv_pref64_prefix_new(&p) >= 0);
139
140 ASSERT_RETURN_EXPECTED_SE(sd_radv_pref64_prefix_set_prefix(NULL, NULL, 0, 0) < 0);
141 ASSERT_RETURN_EXPECTED_SE(sd_radv_pref64_prefix_set_prefix(p, NULL, 0, 0) < 0);
142
143 assert_se(sd_radv_pref64_prefix_set_prefix(p, &prefix[0].address, 32, 300 * USEC_PER_SEC) >= 0);
144 assert_se(sd_radv_pref64_prefix_set_prefix(p, &prefix[0].address, 40, 300 * USEC_PER_SEC) >= 0);
145 assert_se(sd_radv_pref64_prefix_set_prefix(p, &prefix[0].address, 48, 300 * USEC_PER_SEC) >= 0);
146 assert_se(sd_radv_pref64_prefix_set_prefix(p, &prefix[0].address, 56, 300 * USEC_PER_SEC) >= 0);
147 assert_se(sd_radv_pref64_prefix_set_prefix(p, &prefix[0].address, 64, 300 * USEC_PER_SEC) >= 0);
148 assert_se(sd_radv_pref64_prefix_set_prefix(p, &prefix[0].address, 96, 300 * USEC_PER_SEC) >= 0);
149
150 assert_se(sd_radv_pref64_prefix_set_prefix(p, &prefix[0].address, 80, 300 * USEC_PER_SEC) < 0);
151 assert_se(sd_radv_pref64_prefix_set_prefix(p, &prefix[0].address, 80, USEC_PER_DAY) < 0);
152
153 assert_se(!sd_radv_pref64_prefix_unref(p));
154 }
155
156 TEST(radv) {
157 sd_radv *ra;
158
159 assert_se(sd_radv_new(&ra) >= 0);
160 assert_se(ra);
161
162 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_ifindex(NULL, 0) < 0);
163 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_ifindex(ra, 0) < 0);
164 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_ifindex(ra, -1) < 0);
165 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_ifindex(ra, -2) < 0);
166 assert_se(sd_radv_set_ifindex(ra, 42) >= 0);
167
168 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_mac(NULL, NULL) < 0);
169 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_mac(ra, NULL) >= 0);
170 assert_se(sd_radv_set_mac(ra, &mac_addr) >= 0);
171
172 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_mtu(NULL, 0) < 0);
173 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_mtu(ra, 0) < 0);
174 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_mtu(ra, 1279) < 0);
175 assert_se(sd_radv_set_mtu(ra, 1280) >= 0);
176 assert_se(sd_radv_set_mtu(ra, ~0) >= 0);
177
178 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_hop_limit(NULL, 0) < 0);
179 assert_se(sd_radv_set_hop_limit(ra, 0) >= 0);
180 assert_se(sd_radv_set_hop_limit(ra, ~0) >= 0);
181
182 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_router_lifetime(NULL, 0) < 0);
183 assert_se(sd_radv_set_router_lifetime(ra, 0) >= 0);
184 assert_se(sd_radv_set_router_lifetime(ra, USEC_INFINITY) < 0);
185 assert_se(sd_radv_set_router_lifetime(ra, USEC_PER_YEAR) < 0);
186 assert_se(sd_radv_set_router_lifetime(ra, 300 * USEC_PER_SEC) >= 0);
187
188 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_preference(NULL, 0) < 0);
189 assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_LOW) >= 0);
190 assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_MEDIUM) >= 0);
191 assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_HIGH) >= 0);
192 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_preference(ra, ~0) < 0);
193
194 assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_HIGH) >= 0);
195 assert_se(sd_radv_set_router_lifetime(ra, 300 * USEC_PER_SEC) >= 0);
196 assert_se(sd_radv_set_router_lifetime(ra, 0) < 0);
197 assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_MEDIUM) >= 0);
198 assert_se(sd_radv_set_router_lifetime(ra, 0) >= 0);
199
200 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_managed_information(NULL, true) < 0);
201 assert_se(sd_radv_set_managed_information(ra, true) >= 0);
202 assert_se(sd_radv_set_managed_information(ra, false) >= 0);
203
204 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_other_information(NULL, true) < 0);
205 assert_se(sd_radv_set_other_information(ra, true) >= 0);
206 assert_se(sd_radv_set_other_information(ra, false) >= 0);
207
208 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_retransmit(NULL, 10 * USEC_PER_MSEC) < 0);
209 assert_se(sd_radv_set_retransmit(ra, 10 * USEC_PER_MSEC) >= 0);
210 assert_se(sd_radv_set_retransmit(ra, 0) >= 0);
211 assert_se(sd_radv_set_retransmit(ra, usec_add(UINT32_MAX * USEC_PER_MSEC, USEC_PER_MSEC)) < 0);
212
213 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_rdnss(NULL, 0, NULL, 0) < 0);
214 assert_se(sd_radv_set_rdnss(ra, 0, NULL, 0) >= 0);
215 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_rdnss(ra, 0, NULL, 128) < 0);
216 assert_se(sd_radv_set_rdnss(ra, 600 * USEC_PER_SEC, &test_rdnss, 0) >= 0);
217 assert_se(sd_radv_set_rdnss(ra, 600 * USEC_PER_SEC, &test_rdnss, 1) >= 0);
218 assert_se(sd_radv_set_rdnss(ra, 0, &test_rdnss, 1) >= 0);
219 assert_se(sd_radv_set_rdnss(ra, 0, NULL, 0) >= 0);
220
221 assert_se(sd_radv_set_dnssl(ra, 0, NULL) >= 0);
222 assert_se(sd_radv_set_dnssl(ra, 600 * USEC_PER_SEC, NULL) >= 0);
223 assert_se(sd_radv_set_dnssl(ra, 0, (char **)test_dnssl) >= 0);
224 assert_se(sd_radv_set_dnssl(ra, 600 * USEC_PER_SEC, (char **)test_dnssl) >= 0);
225
226 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_home_agent_information(NULL, true) < 0);
227 assert_se(sd_radv_set_home_agent_information(ra, true) >= 0);
228 assert_se(sd_radv_set_home_agent_information(ra, false) >= 0);
229
230 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_home_agent_preference(NULL, 10) < 0);
231 assert_se(sd_radv_set_home_agent_preference(ra, 10) >= 0);
232 assert_se(sd_radv_set_home_agent_preference(ra, 0) >= 0);
233
234 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_home_agent_lifetime(NULL, 300 * USEC_PER_SEC) < 0);
235 assert_se(sd_radv_set_home_agent_lifetime(ra, 300 * USEC_PER_SEC) >= 0);
236 assert_se(sd_radv_set_home_agent_lifetime(ra, 0) >= 0);
237 assert_se(sd_radv_set_home_agent_lifetime(ra, USEC_PER_DAY) < 0);
238
239 ra = sd_radv_unref(ra);
240 assert_se(!ra);
241 }
242
243 static void dump_message(const uint8_t *buf, size_t len) {
244 assert(len >= sizeof(struct nd_router_advert));
245
246 printf("Received Router Advertisement with lifetime %i sec\n",
247 (buf[6] << 8) + buf[7]);
248
249 for (size_t i = 0; i < len; i++) {
250 if (!(i % 8))
251 printf("%3zu: ", i);
252
253 printf("0x%02x", buf[i]);
254
255 if ((i + 1) % 8)
256 printf(", ");
257 else
258 printf("\n");
259 }
260 }
261
262 static void verify_message(const uint8_t *buf, size_t len) {
263 static const uint8_t advertisement[] = {
264 /* ICMPv6 Router Advertisement, no checksum */
265 0x86, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x00, 0xb4,
266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267 /* Source Link Layer Address Option */
268 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
269 /* Prefix Information Option */
270 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
271 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
272 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274 /* Prefix Information Option */
275 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x0e, 0x10,
276 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00,
277 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
279 /* Prefix Information Option */
280 0x03, 0x04, 0x30, 0xc0, 0x00, 0x00, 0x0e, 0x10,
281 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00,
282 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad,
283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 /* Recursive DNS Server Option */
285 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
286 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
288 /* DNS Search List Option */
289 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
290 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
291 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
292 };
293
294 /* verify only up to known options, rest is not yet implemented */
295 for (size_t i = 0, m = MIN(len, sizeof(advertisement)); i < m; i++) {
296 if (test_stopped)
297 /* on stop, many header fields are zero */
298 switch (i) {
299 case 4: /* hop limit */
300 case 5: /* flags */
301 case 6 ... 7: /* router lifetime */
302 case 8 ... 11: /* reachable time */
303 case 12 ... 15: /* retrans timer */
304 assert_se(buf[i] == 0);
305 continue;
306 }
307
308 assert_se(buf[i] == advertisement[i]);
309 }
310 }
311
312 static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
313 sd_radv *ra = ASSERT_PTR(userdata);
314 _cleanup_free_ uint8_t *buf = NULL;
315 ssize_t buflen;
316
317 buflen = next_datagram_size_fd(fd);
318 assert_se(buflen >= 0);
319 assert_se(buf = new0(uint8_t, buflen));
320
321 assert_se(read(fd, buf, buflen) == buflen);
322
323 dump_message(buf, buflen);
324 verify_message(buf, buflen);
325
326 if (test_stopped) {
327 assert_se(sd_event_exit(sd_radv_get_event(ra), 0) >= 0);
328 return 0;
329 }
330
331 assert_se(sd_radv_stop(ra) >= 0);
332 test_stopped = true;
333 return 0;
334 }
335
336 TEST(ra) {
337 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
338 _cleanup_(sd_event_source_unrefp) sd_event_source *recv_router_advertisement = NULL;
339 _cleanup_(sd_radv_unrefp) sd_radv *ra = NULL;
340
341 assert_se(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) >= 0);
342
343 assert_se(sd_event_new(&e) >= 0);
344
345 assert_se(sd_radv_new(&ra) >= 0);
346 assert_se(ra);
347
348 assert_se(sd_radv_attach_event(ra, e, 0) >= 0);
349
350 assert_se(sd_radv_set_ifindex(ra, 42) >= 0);
351 assert_se(sd_radv_set_mac(ra, &mac_addr) >= 0);
352 assert_se(sd_radv_set_router_lifetime(ra, 180 * USEC_PER_SEC) >= 0);
353 assert_se(sd_radv_set_hop_limit(ra, 64) >= 0);
354 assert_se(sd_radv_set_managed_information(ra, true) >= 0);
355 assert_se(sd_radv_set_other_information(ra, true) >= 0);
356 assert_se(sd_radv_set_rdnss(ra, 60 * USEC_PER_SEC, &test_rdnss, 1) >= 0);
357 assert_se(sd_radv_set_dnssl(ra, 60 * USEC_PER_SEC, (char **)test_dnssl) >= 0);
358
359 for (unsigned i = 0; i < ELEMENTSOF(prefix); i++) {
360 sd_radv_prefix *p;
361
362 printf("Test prefix %u\n", i);
363 assert_se(sd_radv_prefix_new(&p) >= 0);
364
365 assert_se(sd_radv_prefix_set_prefix(p, &prefix[i].address,
366 prefix[i].prefixlen) >= 0);
367 if (prefix[i].valid > 0)
368 assert_se(sd_radv_prefix_set_valid_lifetime(p, prefix[i].valid * USEC_PER_SEC, USEC_INFINITY) >= 0);
369 if (prefix[i].preferred > 0)
370 assert_se(sd_radv_prefix_set_preferred_lifetime(p, prefix[i].preferred * USEC_PER_SEC, USEC_INFINITY) >= 0);
371
372 assert_se((sd_radv_add_prefix(ra, p) >= 0) == prefix[i].successful);
373 /* If the previous sd_radv_add_prefix() succeeds, then also the second call should also succeed. */
374 assert_se((sd_radv_add_prefix(ra, p) >= 0) == prefix[i].successful);
375
376 p = sd_radv_prefix_unref(p);
377 assert_se(!p);
378 }
379
380 assert_se(sd_event_add_io(e, &recv_router_advertisement, test_fd[0], EPOLLIN, radv_recv, ra) >= 0);
381 assert_se(sd_event_source_set_io_fd_own(recv_router_advertisement, true) >= 0);
382
383 assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
384 2 * USEC_PER_SEC, 0,
385 NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
386
387 assert_se(sd_radv_start(ra) >= 0);
388
389 assert_se(sd_event_loop(e) >= 0);
390 }
391
392 DEFINE_TEST_MAIN(LOG_DEBUG);