]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/test-ndisc-rs.c
Merge pull request #10813 from poettering/cgroup-exec-start-pre
[thirdparty/systemd.git] / src / libsystemd-network / test-ndisc-rs.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
f20a35cc 2/***
810adae9 3 Copyright © 2014 Intel Corporation. All rights reserved.
f20a35cc
PF
4***/
5
6#include <netinet/icmp6.h>
1e7a0e21 7#include <arpa/inet.h>
f20a35cc 8
07630cea 9#include "sd-ndisc.h"
f20a35cc 10
1e7a0e21
LP
11#include "alloc-util.h"
12#include "hexdecoct.h"
940367a0 13#include "icmp6-util.h"
07630cea 14#include "socket-util.h"
1e7a0e21 15#include "strv.h"
5a67ed24 16#include "ndisc-internal.h"
6d7c4033 17#include "tests.h"
f20a35cc
PF
18
19static struct ether_addr mac_addr = {
20 .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
21};
22
23static bool verbose = false;
24static sd_event_source *test_hangcheck;
25static int test_fd[2];
5a67ed24 26static sd_ndisc *test_timeout_nd;
f20a35cc 27
99af546d
PF
28typedef int (*send_ra_t)(uint8_t flags);
29static send_ra_t send_ra_function;
30
1e7a0e21
LP
31static void router_dump(sd_ndisc_router *rt) {
32 struct in6_addr addr;
33 char buf[FORMAT_TIMESTAMP_MAX];
34 uint8_t hop_limit;
35 uint64_t t, flags;
36 uint32_t mtu;
37 uint16_t lifetime;
38 unsigned preference;
39 int r;
40
41 assert_se(rt);
42
43 log_info("--");
44 assert_se(sd_ndisc_router_get_address(rt, &addr) == -ENODATA);
45
46 assert_se(sd_ndisc_router_get_timestamp(rt, CLOCK_REALTIME, &t) >= 0);
47 log_info("Timestamp: %s", format_timestamp(buf, sizeof(buf), t));
48
49 assert_se(sd_ndisc_router_get_timestamp(rt, CLOCK_MONOTONIC, &t) >= 0);
50 log_info("Monotonic: %" PRIu64, t);
51
52 if (sd_ndisc_router_get_hop_limit(rt, &hop_limit) < 0)
53 log_info("No hop limit set");
54 else
55 log_info("Hop limit: %u", hop_limit);
56
57 assert_se(sd_ndisc_router_get_flags(rt, &flags) >= 0);
58 log_info("Flags: <%s|%s>",
59 flags & ND_RA_FLAG_OTHER ? "OTHER" : "",
60 flags & ND_RA_FLAG_MANAGED ? "MANAGED" : "");
61
62 assert_se(sd_ndisc_router_get_preference(rt, &preference) >= 0);
63 log_info("Preference: %s",
64 preference == SD_NDISC_PREFERENCE_LOW ? "low" :
65 preference == SD_NDISC_PREFERENCE_HIGH ? "high" : "medium");
66
67 assert_se(sd_ndisc_router_get_lifetime(rt, &lifetime) >= 0);
68 log_info("Lifetime: %" PRIu16, lifetime);
69
70 if (sd_ndisc_router_get_mtu(rt, &mtu) < 0)
71 log_info("No MTU set");
72 else
73 log_info("MTU: %" PRIu32, mtu);
74
75 r = sd_ndisc_router_option_rewind(rt);
76 for (;;) {
77 uint8_t type;
78
79 assert_se(r >= 0);
80
81 if (r == 0)
82 break;
83
84 assert_se(sd_ndisc_router_option_get_type(rt, &type) >= 0);
85
86 log_info(">> Option %u", type);
87
88 switch (type) {
89
90 case SD_NDISC_OPTION_SOURCE_LL_ADDRESS:
91 case SD_NDISC_OPTION_TARGET_LL_ADDRESS: {
92 _cleanup_free_ char *c = NULL;
93 const void *p;
94 size_t n;
95
96 assert_se(sd_ndisc_router_option_get_raw(rt, &p, &n) >= 0);
97 assert_se(n > 2);
98 assert_se(c = hexmem((uint8_t*) p + 2, n - 2));
99
100 log_info("Address: %s", c);
101 break;
102 }
103
104 case SD_NDISC_OPTION_PREFIX_INFORMATION: {
105 uint32_t lifetime_valid, lifetime_preferred;
106 unsigned prefix_len;
107 uint8_t pfl;
108 struct in6_addr a;
109 char buff[INET6_ADDRSTRLEN];
110
111 assert_se(sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid) >= 0);
112 log_info("Valid Lifetime: %" PRIu32, lifetime_valid);
113
114 assert_se(sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred) >= 0);
115 log_info("Preferred Lifetime: %" PRIu32, lifetime_preferred);
116
117 assert_se(sd_ndisc_router_prefix_get_flags(rt, &pfl) >= 0);
118 log_info("Flags: <%s|%s>",
119 pfl & ND_OPT_PI_FLAG_ONLINK ? "ONLINK" : "",
120 pfl & ND_OPT_PI_FLAG_AUTO ? "AUTO" : "");
121
122 assert_se(sd_ndisc_router_prefix_get_prefixlen(rt, &prefix_len) >= 0);
123 log_info("Prefix Length: %u", prefix_len);
124
125 assert_se(sd_ndisc_router_prefix_get_address(rt, &a) >= 0);
126 log_info("Prefix: %s", inet_ntop(AF_INET6, &a, buff, sizeof(buff)));
127
128 break;
129 }
130
131 case SD_NDISC_OPTION_RDNSS: {
132 const struct in6_addr *a;
133 uint32_t lt;
134 int n, i;
135
136 n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
137 assert_se(n > 0);
138
139 for (i = 0; i < n; i++) {
140 char buff[INET6_ADDRSTRLEN];
141 log_info("DNS: %s", inet_ntop(AF_INET6, a + i, buff, sizeof(buff)));
142 }
143
144 assert_se(sd_ndisc_router_rdnss_get_lifetime(rt, &lt) >= 0);
145 log_info("Lifetime: %" PRIu32, lt);
146 break;
147 }
148
149 case SD_NDISC_OPTION_DNSSL: {
150 _cleanup_strv_free_ char **l = NULL;
151 uint32_t lt;
152 int n, i;
153
154 n = sd_ndisc_router_dnssl_get_domains(rt, &l);
155 assert_se(n > 0);
156
157 for (i = 0; i < n; i++)
158 log_info("Domain: %s", l[i]);
159
160 assert_se(sd_ndisc_router_dnssl_get_lifetime(rt, &lt) >= 0);
161 log_info("Lifetime: %" PRIu32, lt);
162 break;
163 }}
164
165 r = sd_ndisc_router_option_next(rt);
166 }
167}
168
f20a35cc
PF
169static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
170 void *userdata) {
787784c4 171 assert_se(false);
f20a35cc
PF
172
173 return 0;
174}
175
940367a0 176int icmp6_bind_router_solicitation(int index) {
787784c4 177 assert_se(index == 42);
f20a35cc 178
3e29b889 179 if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
f20a35cc
PF
180 return -errno;
181
182 return test_fd[0];
183}
184
6142bb37
PF
185int icmp6_bind_router_advertisement(int index) {
186
187 return -ENOSYS;
188}
189
88d5a3db
PF
190int icmp6_receive(int fd, void *iov_base, size_t iov_len,
191 struct in6_addr *dst, triple_timestamp *timestamp) {
19500112 192 assert_se(read (fd, iov_base, iov_len) == (ssize_t)iov_len);
88d5a3db
PF
193
194 if (timestamp)
195 triple_timestamp_get(timestamp);
196
197 return 0;
198}
199
f20a35cc
PF
200static int send_ra(uint8_t flags) {
201 uint8_t advertisement[] = {
202 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
205 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
206 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
209 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
211 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
212 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
213 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
215 };
216
217 advertisement[5] = flags;
218
787784c4 219 assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
f20a35cc
PF
220 sizeof(advertisement));
221
222 if (verbose)
223 printf(" sent RA with flag 0x%02x\n", flags);
224
225 return 0;
226}
227
940367a0 228int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
5a67ed24
PF
229 if (!send_ra_function)
230 return 0;
231
99af546d 232 return send_ra_function(0);
f20a35cc
PF
233}
234
1e7a0e21 235static void test_callback(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata) {
f20a35cc 236 sd_event *e = userdata;
cb53894d 237 static unsigned idx = 0;
1e7a0e21 238 uint64_t flags_array[] = {
9d96e6c3
TG
239 0,
240 0,
241 0,
242 ND_RA_FLAG_OTHER,
243 ND_RA_FLAG_MANAGED
f20a35cc 244 };
1e7a0e21 245 uint64_t flags;
8d7f2c6a
PF
246 uint32_t mtu;
247
787784c4 248 assert_se(nd);
f20a35cc 249
1e7a0e21
LP
250 if (event != SD_NDISC_EVENT_ROUTER)
251 return;
252
253 router_dump(rt);
254
255 assert_se(sd_ndisc_router_get_flags(rt, &flags) >= 0);
9d96e6c3 256 assert_se(flags == flags_array[idx]);
f20a35cc
PF
257 idx++;
258
259 if (verbose)
1e7a0e21 260 printf(" got event 0x%02" PRIx64 "\n", flags);
f20a35cc 261
9d96e6c3
TG
262 if (idx < ELEMENTSOF(flags_array)) {
263 send_ra(flags_array[idx]);
8d7f2c6a
PF
264 return;
265 }
266
1e7a0e21 267 assert_se(sd_ndisc_get_mtu(nd, &mtu) == -ENODATA);
8d7f2c6a
PF
268
269 sd_event_exit(e, 0);
f20a35cc
PF
270}
271
99af546d
PF
272static void test_rs(void) {
273 sd_event *e;
4d7b83da 274 sd_ndisc *nd;
99af546d 275 usec_t time_now = now(clock_boottime_or_monotonic());
f20a35cc
PF
276
277 if (verbose)
278 printf("* %s\n", __FUNCTION__);
279
99af546d
PF
280 send_ra_function = send_ra;
281
282 assert_se(sd_event_new(&e) >= 0);
283
4d7b83da 284 assert_se(sd_ndisc_new(&nd) >= 0);
787784c4 285 assert_se(nd);
f20a35cc 286
4d7b83da 287 assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0);
f20a35cc 288
2f8e7633 289 assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0);
4d7b83da 290 assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
1e7a0e21 291 assert_se(sd_ndisc_set_callback(nd, test_callback, e) >= 0);
f20a35cc 292
787784c4 293 assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
f20a35cc
PF
294 time_now + 2 *USEC_PER_SEC, 0,
295 test_rs_hangcheck, NULL) >= 0);
296
4d7b83da 297 assert_se(sd_ndisc_stop(nd) >= 0);
1e7a0e21 298 assert_se(sd_ndisc_start(nd) >= 0);
4d7b83da 299 assert_se(sd_ndisc_stop(nd) >= 0);
836cf090 300
1e7a0e21 301 assert_se(sd_ndisc_start(nd) >= 0);
f20a35cc
PF
302
303 sd_event_loop(e);
304
305 test_hangcheck = sd_event_source_unref(test_hangcheck);
306
4d7b83da 307 nd = sd_ndisc_unref(nd);
787784c4 308 assert_se(!nd);
f20a35cc 309
f20a35cc 310 close(test_fd[1]);
99af546d
PF
311
312 sd_event_unref(e);
f20a35cc
PF
313}
314
5a67ed24
PF
315static int test_timeout_value(uint8_t flags) {
316 static int count = 0;
317 static usec_t last = 0;
318 sd_ndisc *nd = test_timeout_nd;
319 usec_t min, max;
320 char time_string_min[FORMAT_TIMESPAN_MAX];
321 char time_string_nd[FORMAT_TIMESPAN_MAX];
322 char time_string_max[FORMAT_TIMESPAN_MAX];
323
324 assert_se(nd);
325 assert_se(nd->event);
326
327 if (++count >= 20)
328 sd_event_exit(nd->event, 0);
329
330 if (last == 0) {
331 /* initial RT = IRT + RAND*IRT */
332 min = NDISC_ROUTER_SOLICITATION_INTERVAL -
333 NDISC_ROUTER_SOLICITATION_INTERVAL / 10;
334 max = NDISC_ROUTER_SOLICITATION_INTERVAL +
335 NDISC_ROUTER_SOLICITATION_INTERVAL / 10;
336 } else {
337 /* next RT = 2*RTprev + RAND*RTprev */
338 min = 2 * last - last / 10;
339 max = 2 * last + last / 10;
340 }
341
342 /* final RT > MRT */
343 if (last * 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL) {
344 min = NDISC_MAX_ROUTER_SOLICITATION_INTERVAL -
345 NDISC_MAX_ROUTER_SOLICITATION_INTERVAL / 10;
346 max = NDISC_MAX_ROUTER_SOLICITATION_INTERVAL +
347 NDISC_MAX_ROUTER_SOLICITATION_INTERVAL / 10;
348 }
349
350 format_timespan(time_string_min, FORMAT_TIMESPAN_MAX,
351 min, USEC_PER_MSEC);
352 format_timespan(time_string_nd, FORMAT_TIMESPAN_MAX,
353 nd->retransmit_time, USEC_PER_MSEC);
354 format_timespan(time_string_max, FORMAT_TIMESPAN_MAX,
355 max, USEC_PER_MSEC);
356
357 log_info("backoff timeout interval %2d %s%s <= %s <= %s",
358 count,
359 (last * 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL)? "(max) ": "",
360 time_string_min, time_string_nd, time_string_max);
361
362 assert_se(min <= nd->retransmit_time);
363 assert_se(max >= nd->retransmit_time);
364
365 last = nd->retransmit_time;
366
367 assert_se(sd_event_source_set_time(nd->timeout_event_source, 0) >= 0);
368
369 return 0;
370}
371
372static void test_timeout(void) {
373 sd_event *e;
374 sd_ndisc *nd;
375 usec_t time_now = now(clock_boottime_or_monotonic());
376
377 if (verbose)
378 printf("* %s\n", __FUNCTION__);
379
380 send_ra_function = test_timeout_value;
381
382 assert_se(sd_event_new(&e) >= 0);
383
384 assert_se(sd_ndisc_new(&nd) >= 0);
385 assert_se(nd);
386
387 test_timeout_nd = nd;
388
389 assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0);
390
391 assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0);
392 assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
393
394 assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
395 time_now + 2U * USEC_PER_SEC, 0,
396 test_rs_hangcheck, NULL) >= 0);
397
398 assert_se(sd_ndisc_start(nd) >= 0);
399
400 sd_event_loop(e);
401
402 test_hangcheck = sd_event_source_unref(test_hangcheck);
403
404 nd = sd_ndisc_unref(nd);
405
406 sd_event_unref(e);
407}
408
f20a35cc 409int main(int argc, char *argv[]) {
f20a35cc 410
6d7c4033 411 test_setup_logging(LOG_DEBUG);
f20a35cc 412
99af546d 413 test_rs();
5a67ed24 414 test_timeout();
f20a35cc
PF
415
416 return 0;
417}